- rename task to convert-audio, support mp3/flac/wav/ogg/aac/opus targets
- add options input type with selectable pill buttons in UI
- extend seed script parser to handle YAML list properties (options)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- fetch task input definitions from API and render configurable inputs
- boolean inputs render as No/Yes toggle (e.g. delete_source)
- auto-filled inputs (file_path) are hidden from the form
- wrap script output in dark pre/code block with copy button
- fix ffmpeg -nostdin for batch directory processing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tasks now live in the database (mode: script or agentic). Script-mode tasks
bypass the agent entirely — the implementation is materialized to a temp file
and executed directly, with stdout/stderr streamed to the UI via WebSocket.
Includes convert-to-mp3 as the first native script task.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sandbox now mounts global content at short /officer/* paths to avoid
bwrap intermediate directory traversal issues. Pi uses NODE_PATH for
extension dependency resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Capture HOST_HOME before user-instance overrides process.env.HOME so
Super Admin spawns claude in /home/pastilhas. Generate separate MCP
configs for sandbox (sandbox paths) and host (real filesystem paths),
pick based on role at spawn time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move claude and pi from sudo global installs to ~/.local. Claude
binary is copied to /usr/local/bin for sandbox visibility, pi runs
via node from ~/.local/lib (ro-mounted). Fix bwrap intermediate dir
traversal by setting 0755 perms on auto-created HOME dirs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- extract buildSandboxPrefix/buildRunuserSuffix into shared sandbox.ts
- super admin bypasses bwrap for full host access (claude, pi, terminal)
- member pi processes now use bwrap instead of sudo -u
- member terminals now use bwrap instead of sudo -u
- mount /run for systemd-resolved DNS inside sandbox
- pass role through claude spawn params and channel types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces prompt injection workaround with a proper MCP server that dynamically
discovers marketplace tools and exposes them as callable tools to Claude Code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add agent-agnostic tool registry (tool-registry.ts) that discovers tools from disk
- Embed tool-loader extension as platform infrastructure (ensure-tool-loader.ts)
- Inject tool context into Claude prompts on first message
- Add marketplace tool sync (sync-marketplace.ts)
- Fix model selector defaulting to claude-code when no model explicitly selected
- Exclude tool-loader-source.ts from tsconfig (Pi-specific deps)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The PUT endpoint was re-merging old DB messages (which already included
previous merges) with disk messages on every turn, causing duplication.
Now the client passes resumedMessageCount so the server always slices
only the original pre-resume messages before concatenating.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add saved_sessions table and CRUD endpoints (save, list, resume, update, delete)
- Save is instant (no LLM summarization), stores exact conversation with tool calls
- Resume loads full message history into chat UI, sends transcript to agent on first message
- Auto-save updates DB after every agent response once a session is saved
- Delete old filesystem-based session/group management (sessions router, useChatSessions, useChatGroups)
- Clean up ChatHeader, SessionList, ChatDetailPanel for saved sessions flow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace JSON file storage with DB tables for dashboard layouts,
screens, projects, and terminal defaults. Fresh drizzle migration
with dashboardDefaults table and new columns on screens/projects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
replaces the single hardcoded systemd VNC service with a dynamic
sidecar that manages per-user VNC sessions on demand. any authenticated
user can now access their own desktop, not just Super Admin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flips the connection model so sidecars register themselves with the API
server via WebSocket at /api/sidecar/register, enabling dynamic discovery,
location independence, and automatic reconnection from either side.
- Add registration protocol types and PTY command/event types
- Create sidecar-registry.ts (replaces sidecar-client.ts) as passive registry
- Create sidecar connector (connect.ts) with exponential backoff reconnect
- Convert process sidecar from WS server to WS client
- Convert PTY sidecar from WS server to multiplexed WS client
- Simplify terminal bridge to thin adapter using registry
- Add PTY sidecar as PM2-managed process
- Update all consumer imports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewired EmailList sync button to call /email/accounts/:id/sync instead
of the old gmail-sync job. Shows sync button for connected and synced
accounts. Allow manual incremental sync for synced accounts.
Added duration logging to queue runner: start/complete/fail markers
with elapsed time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sidecar/queue runner no longer needs job-specific context. API server
resolves account details, IMAP auth, and user email at enqueue time —
all persisted in the job file. Handler reads directly from job meta.
Removed "Load account" step. Sync step auto-reconnects up to 10 times
when Gmail drops the connection, resuming from saved UIDs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Bun routes option matched "/" before fetch could handle the
WebSocket upgrade, so the API server could never connect. Moved
route handling into fetch after the upgrade check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
[Google Mail] locale variant was not matched by hardcoded [Gmail] paths,
so Sent/Starred/Important/Drafts were never labeled. All Mail was skipped
entirely, losing ~9k archived emails. Now normalizes the prefix, imports
everything with proper labels, and processes All Mail last so specific
folder labels take priority.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a separate Bun process (port 5100) that owns all spawned
processes and long-running work, so the API server can restart freely
without disrupting active sessions.
The sidecar owns:
- Anthropic proxy (port 5051) with persisted secret across restarts
- Claude Code process spawning and session tracking (--resume support)
- Pi agent spawning and RPC lifecycle (prompt/abort/thinking)
- Job queue engine (lane processing, retries, notifications)
The API server becomes a thin client that forwards commands over a
single WebSocket connection with auto-reconnect. send-claude-code.ts
goes from 550 lines of spawn logic to 73 lines of sidecar delegation.
State persisted to data/sidecar/state.json every 30s and on shutdown.
Lockfile prevents duplicate instances. See SIDECAR.md for full docs
and manual testing procedures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Local HTTP proxy on 127.0.0.1:5051 intercepts Claude Code API requests
from sandboxed member users, injects the real OAuth token server-side,
and forwards to Anthropic. Users only see a proxy secret, never the
real credentials.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- chown user dirs to pastilhas:<username> instead of pastilhas:officerdev
so users cannot access each other's data
- chmod 2770 (setgid) gives only the owning user terminal access
- setup.sh: ensure home dir is traversable (o+x) for provisioned users
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- provision linux users with pastilhas:officerdev ownership so server
can always read/write, terminal users get group access
- add officerdev shared group setup to setup.sh
- move go install to ~/.local/go with GOPATH at ~/.local/go-path
- add upload file/folder items to file browser context menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- add isync to setup.sh
- ask for gmail address alongside app password in integrations
- add PermanentError to job queue (skips retries for non-recoverable failures)
- use PermanentError for missing credentials, missing executable, auth failures
- auto-add /email to dock after successful gmail sync
- invalidate dock cache on sync completion for seamless UI update
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two-tier model policy: system policy (admin, allowedModels) controls
member access, per-user hiddenModels controls personal visibility.
All model selectors now use useUserVisibleModels. Moved providers
and model visibility out of system settings, AI models out of profile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
770 (rwxrwx---) is more secure - only owner and group can access, excluding 'others'.
The service user can still access because it's added to the user's group via:
usermod -aG shellUsername serviceUser
The real fix was wrapping chmodSync in try/catch in email-db.ts so it doesn't
crash when trying to chmod files owned by other users.
Consistency fix with src/servers/api/users/provision.ts which was updated to use:
- chmod 775 (rwxrwxr-x) instead of 770 (rwxrwx---)
- Recursive chmod to fix all subdirectories
This allows the service user (in the user's group) to read/write files
for background jobs like email sync.
Also added helpful comment explaining the permission choice.
Issues:
1. User directories created with chmod 770 (too restrictive)
- Prevents service user from reading/writing even though in group
- Changed to chmod 775 (recursive) to allow group access
2. openEmailDb tries to chmod file it may not own
- If file owned by different user (e.g., andrepadez), chmod fails
- Wrapped chmodSync in try/catch to gracefully skip
Changes:
- src/servers/api/users/provision.ts:
* Changed chmod 770 → 775 (owner/group rwx, others rx)
* Applied recursively to all subdirectories
* Added chmod after seeding files to ensure consistency
- src/servers/api/email/email-db.ts:
* Wrapped chmodSync in try/catch
* Logs silently skip if file not owned by current process
* Database still works even if chmod fails
Fixes /email endpoint 500 errors for users with email data.
- Mask sleep.target, suspend.target, hibernate.target, hybrid-sleep.target
- Configure systemd-logind to:
- Ignore lid switch events
- Ignore power key presses
- Disable idle action
- Set runtime directory size
- Restart systemd-logind to apply changes
Servers running Officer shouldn't go to sleep when idle.
This prevents unexpected suspends during setup or normal operation.
- Set npm prefix to /usr/local (system location) instead of user-specific ~/.npm-global
- Ensures all users can access installed npm packages
- Fixes issue where packages installed to one user's home directory
- All npm global packages now available system-wide to all users
This ensures that after running setup.sh:
- pi, claude, and other tools are at /usr/local/bin/
- Accessible to all users (pastilhas, andrepadez, etc.)
- New users automatically get access too
- When installing global npm packages, explicitly use /usr/bin/npm
- Falls back to $(which npm) if system npm not found
- Ensures packages go to system location, not nvm location
- Works around nvm PATH interference during setup
- setup.sh now automatically installs Node 22 via NodeSource if not found
- No more separate manual Node installation step required
- Simplified to single command: bash scripts/setup.sh
- Works for apt/pacman/brew systems
- Updated SETUP_GUIDE.md with simplified instructions
- Better logging during Node installation process
Users can now simply run:
bash scripts/setup.sh
And everything (including Node 22) will be installed automatically.
- Added detailed error logging to detect snap node compatibility issues
- When Pi process exits with code 1, log helpful diagnostic info including node path
- Add hint to check for snap node and reinstall via apt/nvm
- Create SNAP_NODE_COMPATIBILITY.md with full troubleshooting guide
- Document root cause: snap node has file descriptor incompatibility with Bun.spawn stdin pipes
- Provide clear installation instructions for NodeSource and nvm alternatives
- add claude-code as virtual model in channel messaging (telegram/discord/whatsapp)
- new send-claude-code.ts: docker exec claude -p with session resumption
- route claude-code model in sendAndAwait before Pi pipeline
- append claude-code to listPiModels output
- fix container .claude mount (rw for sub-mounts), hooks format (matcher-based)
- pre-seed hasTrustDialogAccepted and bypassPermissions in container settings
- git init in entrypoint to skip workspace trust prompt
- fix ~/~ double-tilde in CommandTerminalWrapper cwd resolution
- remove --continue from claude-code panel command
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- respect charset from Content-Type when decoding body and headers
- detect inline attachments with filenames (not just disposition: attachment)
- fix broken decodeQuotedPrintable reference in parseAttachments
- white background for email iframe (emails designed for light bg)
- sticky header in email list, scrollable message area
- arrow key navigation between emails with scroll-into-view
- /email/:id routing for deep linking to specific emails
- empty folder shows "No emails in this folder" instead of losing header
- fix attachment viewer header overlap with dialog close button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- OVERQUOTA from Gmail now continues to import step instead of retrying
- partial sync completion email tells user to try again in a few hours
- engine syncs handler meta to job on completion for richer notifications
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- rewrite gmail-sync handler: mbsync downloads to local Maildir, then import to sqlite
- add app password field to google integration config and API
- gmail sync section independent from oauth in settings UI
- live mbsync progress streaming to job status
- recoverable failure email with instructions for overquota/auth errors
- sync meta persisted to job on failure for richer notifications
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>