Commit Graph

1393 Commits

Author SHA1 Message Date
Jeff Emmett 92629e239e fix(blender,freecad): contain render in element, fix FreeCAD file serving
Blender: add wrapper with height:100%, min-height:0 for flex shrink,
object-fit:contain on img — render stays within shape bounds.

FreeCAD: update assembleFreecadResult to scan all tool results for file
paths (.step, .stl, .png), not just execute_python_script JSON parsing.
Add preview PNG rendering instruction to system prompt. Add subdirectory
file serving routes for /data/files/generated/:subdir/:filename. Add
STEP/STL/SVG/PDF mime types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:40:25 -07:00
Jeff Emmett 8ea537525a fix(rwallet): align timeline inflows/outflows with balance changes
- Use curveStepAfter for the balance river so step transitions happen
  exactly at transaction dates (curveBasis didn't pass through data points,
  causing waterfall shapes to disconnect from the river edges)
- Update hardcoded USD estimates to current CoinGecko prices (2026-03-25)
- Add SAFE, COW, ENS, LDO, BAL to the price estimate table
- Fix BigInt→Number precision for large token balances (>2^53 wei) in
  both price-feed enrichment and transfer value parsing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:36:10 -07:00
Jeff Emmett ff09d49127 fix: bump service worker cache version to v4
Forces all clients to invalidate cached assets and re-fetch,
ensuring mobile zoom button position fix is picked up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:35:15 -07:00
Jeff Emmett f3094f5f88 fix(rwallet): chain filter now updates all displayed data + chain proportion bar
- Stats, balance table, and DeFi positions all filter by selected chain
- Added proportional color bar showing each chain's share of total value
- Chain buttons show USD value + percentage on hover
- Bumped JS cache version to v=21

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:32:02 -07:00
Jeff Emmett 8d4e1fd0ff fix(mi,canvas): filter disabled modules from MI assistant and eliminate app-switcher flash
MI now loads space doc to filter module list, capabilities, and fallback
by enabledModules. Canvas fetches /api/modules and space modules in
parallel via Promise.all, calling setModules once with filtered list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:26:07 -07:00
Jeff Emmett ac028cbe04 fix(blender): use shutil.move for cross-fs copy, disable denoiser
os.rename fails across Docker volume boundaries (different filesystems).
Debian Blender 3.4 lacks OpenImageDenoiser — disable denoising in prompt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:21:53 -07:00
Jeff Emmett 555a51f8a7 fix(blender): add EGL/GL libs and use Cycles CPU renderer
EEVEE needs GPU; Cycles CPU works headless. Added libegl1, libgl1-mesa-dri,
libglx-mesa0 to Dockerfile. Updated Gemini prompt to specify Cycles engine
with 64 samples.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:17:34 -07:00
Jeff Emmett ba56697e23 fix(rcal): show calendar event locations on map in all spaces, not just demo
REST API events use location_lat/location_lng while the map panel
filters on latitude/longitude. Demo events set both, but non-demo
events only had location_lat/location_lng — so the map was always
empty outside demo.

Normalize both REST and Automerge event data to include latitude/
longitude aliases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:10:44 -07:00
Jeff Emmett aa02473d0d fix(shell): evict tab pane from cache on script load failure
When a module script (e.g. canvas-*.js) fails to load (502 during
deploy, network error), the pane stayed in cache with a blank canvas.
Subsequent tab switches showed the broken cached pane instead of
re-fetching. Now script onerror removes the failed tag and evicts
the pane, so the next switchTo does a fresh fetch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:10:23 -07:00
Jeff Emmett 44a69e665e perf(rmaps): preload MapLibre GL, switch CDN from unpkg to jsDelivr
Add <link rel="preload"> hints for MapLibre JS+CSS in the module HTML
so the browser starts fetching them in parallel with the main bundle,
instead of waiting until joinRoom() calls loadMapLibre().

Switch from unpkg (slow, no HTTP/2) to jsDelivr (faster edge caching).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:03:21 -07:00
Jeff Emmett 101cc3b848 fix(shell): show rApp info popup once per module, then only via icon
Extract autoShowIfFirstVisit() so it runs both on initial page load
and on SPA tab switches. Uses localStorage rapp_info_seen_{moduleId}
to ensure each rApp's landing popup shows exactly once.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:01:54 -07:00
Jeff Emmett 355d33768a fix(mobile): responsive parity — touch targets, iOS zoom, viewport clamping
rNotes: always-visible add button on touch, 36px toolbar buttons with horizontal
scroll, URL popover as bottom sheet on mobile, improved comment sidebar bottom
panel with drag handle, larger footer buttons, slash menu viewport clamping and
mobile-friendly item sizes, reduced code-textarea/image-preview heights.

rTasks/rFiles: font-size 16px on inputs to prevent iOS Safari auto-zoom.

Shell: .hover-reveal touch utility, 36px min-height on rapp-nav buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:59:04 -07:00
Jeff Emmett 0d7c6d08b3 fix(canvas): mobile touch — first touch moves, long-press selects, extra-long opens context menu
Three-tier touch interaction on mobile canvas:
- Immediate drag on finger movement (8px threshold)
- Long press (500ms) selects shape with haptic feedback
- Extra long press (1000ms) opens context menu
- Cancel timers on movement or two-finger gesture

Skip pointerdown selection for touch events in canvas.html,
handle via touch-select custom event from folk-shape instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:58:11 -07:00
Jeff Emmett c046acf9ce fix(blender): switch from Ollama to Gemini Flash for script generation
Ollama runs CPU-only on Netcup — 7B models take minutes, exceeding
Cloudflare's 100s timeout (524). Gemini 2.0 Flash responds in seconds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:51:35 -07:00
Jeff Emmett 4a75c64a18 feat(rdesign): rich landing page, Scribus canvas tool, icon update
- Replace minimal rDesign landing with full rl-* pattern (hero, features,
  how-it-works, capabilities, open source, data protection, CTA)
- Add Scribus button to Create toolbar group in canvas (folk-design-agent)
- Export FolkDesignAgent from lib/index.ts, register in canvas.html
- Update module icon from 🎯 to 🎨 (matches favicon + MODULE_META)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:51:31 -07:00
Jeff Emmett 6d20a275ff fix(rwallet): show all chains with activity, fix chain filter stats
- Backend: detect chains where Safe has transaction history even if
  current balance is zero (queries all-transactions?limit=1)
- Frontend: stats (Total Value, Tokens) now update when clicking
  chain filter buttons instead of always showing all-chain totals

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:50:20 -07:00
Jeff Emmett d7c1501d4f feat(rnotes): Google Docs-style suggestion mode + comment panel fixes
Rewrite suggestion plugin to use ProseMirror props (handleTextInput,
handleKeyDown, handlePaste) instead of broken filterTransaction approach.
Typed text gets suggestionInsert mark (green underline), deleted text gets
suggestionDelete mark (red strikethrough). Add per-suggestion accept/reject
popover and review bar with Accept All / Reject All.

Fix comment panel text overflow with box-sizing: border-box, add
collapse/minimize toggle button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:48:16 -07:00
Jeff Emmett 0db5addc17 fix(rdesign): switch to StreamableHTTP transport, fix KiCad Python path
SSE transport crashes on concurrent connections (supergateway
single-session limit). StreamableHTTP supports multiple sessions.
Also set KICAD_PYTHON=/usr/bin/python3 for existsSync validation
and install missing requests package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:48:11 -07:00
Jeff Emmett e0e9802bd7 feat(rwallet): use CoinGecko Demo API key for batch token pricing
Reads COINGECKO_API_KEY from env (injected via Infisical) and appends
x_cg_demo_api_key param. Enables batch lookups + spam filtering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:45:45 -07:00
Jeff Emmett 1c338529bf fix(presence): relay presence-leave messages and clean up listener on disconnect
- Server now relays presence-leave alongside presence messages for immediate peer removal
- Overlay properly unsubscribes leave listener on disconnectedCallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:42:49 -07:00
Jeff Emmett 2f8ce08e3c feat: add rDesign module metadata, collab presence-leave cleanup
- Register rDesign in folk-rapp MODULE_META and shell FAVICON_BADGE_MAP
- Handle explicit presence-leave messages for immediate peer cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:35:10 -07:00
Jeff Emmett 6b81f808f5 feat(canvas): mobile toolbar flush, zoom icon toggle, SW update banner
- Mobile toolbar collapsed position now flush with bottom-toolbar (bottom: 8px)
- Toolbar defaults to collapsed on mobile (<768px)
- Zoom expand/minimize uses distinct icons (magnifier +/-) instead of CSS rotation
- SW update banner on all pages: "New version available — Tap to update"
  - Detects controllerchange + updatefound events
  - Purple gradient bar, dismissible, reloads on tap
  - Added to both shell.ts (module pages) and canvas.html (standalone)
- folk-rapp: filter picker/switcher by enabled modules
- server/shell: react to modules-changed event for runtime module toggling
- collab-presence: minor overlay updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:34:48 -07:00
Jeff Emmett 76a846cc36 fix(rwallet): handle CoinGecko free tier 1-address limit gracefully
Single-token wallets get CoinGecko verification + spam filtering.
Multi-token wallets attempt batch (works with Pro/Demo keys), degrade
gracefully on free tier — Safe API trusted+exclude_spam handles most spam.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:31:44 -07:00
Jeff Emmett 110b733f94 fix(rnotes): Google Docs-like comment sidebar, fix suggestions + duplicate extensions
- Fix duplicate tiptap extension warnings by disabling link/underline in
  StarterKit v3 (which now includes them by default)
- Move comment panel from metaZone (destroyed by renderMeta) to dedicated
  comment sidebar next to the editor, Google Docs style
- Add click-on-highlight to open comment thread in sidebar
- New comment creation shows inline textarea with auto-focus
- Fix suggestion plugin: pass view getter instead of broken state.view access
- Improve comment panel styling: avatars, Google Docs yellow active border,
  cleaner thread layout, Ctrl+Enter to submit, Escape to cancel
- Bump folk-notes-app cache version to v=7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:29:21 -07:00
Jeff Emmett 8ba14a0e15 fix(rwallet): skip spam filter when CoinGecko data unavailable
Revert per-address batching (rate limit cascade). Track cgAvailable flag
in cache — only apply spam filter when CoinGecko successfully returned data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:25:48 -07:00
Jeff Emmett 395623af66 feat(rdesign): deploy KiCad & FreeCAD MCP as Docker sidecars
Switch from broken StdioClientTransport (child process) to
SSEClientTransport (HTTP to sidecar containers via supergateway).
Both sidecars share rspace-files volume so generated CAD files
(STEP, STL, Gerber, SVG) are directly servable without copying.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:25:23 -07:00
Jeff Emmett 95246743c3 fix(rwallet): batch CoinGecko requests to 1 address each (free tier limit)
CoinGecko free tier now limits to 1 contract address per request.
Process in batches of 3 concurrent single-address requests with 1.5s delay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:17:03 -07:00
Jeff Emmett 55b973ebc2 fix(blender): use correct Ollama model (qwen2.5-coder:7b)
qwen2.5:14b doesn't exist on the server, causing silent 404 from
Ollama and 502 to the client. Also added error logging for non-ok
Ollama responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:10:11 -07:00
Jeff Emmett 1a422f06ac feat(canvas): add first-time forgotten shapes explainer tooltip
Shows a one-time onboarding tooltip when users first encounter a faded
(forgotten) shape. Explains right-click to remember/forget permanently,
the Hide Forgotten toggle in profile menu, and highlights the Collective
Memory graph as a prototype feature. Persisted via localStorage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:09:05 -07:00
Jeff Emmett 5f853322b0 fix(rwallet): filter spam tokens via CoinGecko verification
ERC-20 tokens not recognized by CoinGecko and valued < $1 by Safe API
are now stripped from balance responses, removing fake ETH and airdrop spam.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:08:52 -07:00
Jeff Emmett 4d7d2c0108 fix(rsocials): campaign wizard auth — read correct session storage key
Was reading `encryptid-token` (doesn't exist), now reads `encryptid_session`
and extracts `.accessToken` matching the pattern used by all other modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:01:10 -07:00
Jeff Emmett aa23108f5f fix(invites): redirect to invited space, improve invite emails
- Fix invite accept fetch URL in shell.ts (was missing /api/spaces prefix)
- After accepting invite, redirect to the invited space instead of reloading
- Notification actionUrls now point to the space subdomain (https://slug.rspace.online)
- Direct-add email includes inviter name, role, and space description
- Identity invite email includes space name/role context when inviting to a space

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:39:58 -07:00
Jeff Emmett 2f3a4a13dc fix(blender): make RunPod optional, fix script-only generation
RunPod was hard-gated — returned 503 when RUNPOD_API_KEY missing,
blocking even LLM script generation. Now generates script via Ollama
regardless, only attempts RunPod render if key is configured. Health
check returns warnings (non-blocking) vs issues (blocking). Default
model switched to qwen2.5:14b (available on server). Regex also
handles non-python-tagged code blocks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:38:49 -07:00
Jeff Emmett 59d2cc9933 feat(spaces): add visibility/description to settings panel, merge invite sources
- Space Settings section in dropdown with visibility (public/permissioned/private)
  and description fields, matching the full edit space modal
- GET /api/spaces/:slug now includes description field
- listSpaceInvites merges both space_invites and identity_invites tables
  so email invites appear in Pending Invites
- revokeSpaceInvite falls through to identity_invites table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:29:33 -07:00
Jeff Emmett 858457c056 fix(invites): show email invites in space settings pending list
listSpaceInvites now queries both space_invites and identity_invites
tables, merging results so email-based invites (via /invite endpoint)
appear in the Pending Invites section. revokeSpaceInvite also falls
through to identity_invites if not found in space_invites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:24:26 -07:00
Jeff Emmett 4a43ecdee0 fix(rcal): replace event dots with thin colored bars on mobile
Dots were overlapping in small day cells. Now renders full-width 2px
color-coded stripes (solid for confirmed, dashed for tentative). Multi-day
spans also thinner (10px) with hidden text on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:21:15 -07:00
Jeff Emmett 0753b31990 fix(spaces): correct API paths for member/invite operations in settings panel
All fetch calls in rstack-space-settings were missing the /api/spaces prefix,
causing 404s for add-by-username, invite-by-email, change-role, remove-member,
and load-invites. Also add color-scheme: light dark to fix native select
dropdowns rendering in light mode on dark theme.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:15:33 -07:00
Jeff Emmett 28f11242f7 fix(rwallet): consolidate dual tab bars into single shell subnav
Remove internal view-tabs from folk-wallet-viewer — navigation now handled
entirely by shell subnav outputPaths: Budget (default), Token Balances, Flows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:40:14 -07:00
Jeff Emmett a10f8e9507 fix(rwallet): capture ETHEREUM_TRANSACTION inflows, filter airdrop spam tokens
Transfers: handle ETHEREUM_TRANSACTION txType as inflows (was only scanning
tx.transfers), exclude self-transfers from embedded transfers loop.
Balances: hide unpriced ERC-20s (airdrop spam) while keeping native tokens,
CRDT tokens, and CoinGecko-priced tokens. Filter zero balances on single-chain
Safe endpoint. Bump JS cache to v=20.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:37:35 -07:00
Jeff Emmett c7c6b6a13b chore(rwallet): bump JS cache version to v=19
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:04:00 -07:00
Jeff Emmett 2bfd674d0e refactor(rwallet): consolidate tabs — remove Yield, merge viz into Budget + Flows
Simplify rWallet from 5 internal tabs to 3: Token Balances, Budget Visualization
(default), and Flows (Sankey + timeline scrubber with play/pause). Remove Yield
shell-level outputPath and route. Budget view auto-loads transfer data on entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:03:35 -07:00
Jeff Emmett 8071b620e1 fix(auth): throttle session validation, typed auth-change events, misc fixes
- rstack-identity.ts: throttle server session validation to every 5min,
  add reason detail to all auth-change events (signin/signout/revoked/
  refresh/persona-switch), remove redundant location.reload on signout
- shell.ts: skip UI side-effects on token refresh, only redirect home
  on genuine signout/revocation
- server.ts: add PUT to CORS allowMethods
- folk-inbox-client.ts: pass auth token on mailbox API fetch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:21:26 -07:00
Jeff Emmett 32be9d7b94 fix(ui): bump subnav sticky top to avoid header overlap
Increase .rapp-subnav top from 92px to 93px so pill buttons
don't clip under the fixed header + tab-row border.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:54:23 -07:00
Jeff Emmett c2d7e8b238 fix(shell): prevent infinite loop when rapidly switching tabs
Abort previous in-flight fetch when switchTo() is called again, and
guard the shell's fallback navigation against stale callbacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:44:38 -07:00
Jeff Emmett 06a58f1bba fix(ui): theme-adaptive rSocials buttons + device link textbox
- campaign-wizard.css: fix undefined --rs-surface-hover → --rs-bg-hover
- campaign-workflow.css: replace hardcoded blue colors with theme vars
  (--rs-primary-hover, --rs-bg-active, --rs-border, --rs-primary)
- rstack-identity.ts: device link URL input --rs-bg-inset → --rs-input-bg
  (--rs-bg-inset was never defined in theme.css, dark fallback always won)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:39:14 -07:00
Jeff Emmett b3fb51c39a feat(encryptid): known accounts picker + passkey-first for both UIs
- login-button.ts: no-known-accounts state shows passkey-first button
  (unscoped WebAuthn) with email magic link fallback, auto-revealed on
  NotAllowedError. Fix stale usernameInput ref.
- server.ts (auth.rspace.online): add localStorage known accounts system.
  Returning users see their stored usernames as clickable buttons.
  handleAuth() accepts optional username for scoped auth. Saves account
  after successful login. renderSigninAccounts() called on page init.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:29:44 -07:00
Jeff Emmett 423d2612af fix(auth): preserve active tab through login on bare domain
The identity component's inline _getCurrentModule() assumed path-based
routing (/{space}/{moduleId}) for non-subdomain URLs, returning "rspace"
instead of the actual module. On bare domain (rspace.online/rnotes),
this caused login to redirect to the canvas instead of rnotes.

Add _isBareDomain() check so _getCurrentSpace() returns "demo" and
_getCurrentModule() reads parts[0] (the module) on the bare domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:27:30 -07:00
Jeff Emmett 22b5c00a13 fix(routing): prevent domain stacking and remove Try Demo button
- Fix server-side redirect to always use canonical rspace.online as base
  domain instead of deriving from hostClean (prevents demo.rspace.rspace.online)
- Fix bare-domain check to exact match instead of .includes() (prevents
  stacked subdomains from triggering bare-domain routing)
- Fix client-side rspaceNavUrl to guard against reserved subdomain names
  being used as space subdomains (e.g. rspace.rspace.online)
- Fix identity component _navUrl with same canonical domain guards
- Remove "Try Demo" header button from all shell rendering functions
- Remove demo-btn CSS styles
- Fix pre-existing SchemaType error in Gemini tool declarations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:16:46 -07:00
Jeff Emmett dd46905e12 feat(mi): agentic upgrade — multi-turn loop, LiteLLM, media gen, live data
Transform MI from single-shot chat into an agentic system:

- LiteLLM provider with Claude Sonnet/Haiku models via proxy
- Agentic loop (max 5 turns): stream → parse actions → execute server-side → feed results back
- Server-side media generation (fal.ai + Gemini) as first-class MI actions
- Module data queries (rnotes, rtasks, rcal) read directly from Automerge
- System prompt enriched with recent notes, open tasks, and calendar events
- Client handles new NDJSON types (turn, action-start, action-result)
- Extracted shared media helpers, refactored image/video endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:26:56 -07:00
Jeff Emmett a5c7eef466 fix(startup): move space alias provisioning after loadAllDocs
The IIFE raced with doc loading so listCommunities returned empty.
Moved into the .then() callback to ensure all docs are loaded first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:06:06 -07:00