turbo lint fails for all packages due to eslint binary resolution
issues. Fall back to pnpm --filter which handles node_modules/.bin
PATH correctly. Scope matches original CI (web + desktop).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Configure weekly npm and GitHub Actions dependency updates. Groups
dev and production dependencies separately for easier review.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add test task to turbo.json and include it in the build-and-typecheck
job. Turbo handles the dependency graph: builds deps first, then runs
typecheck and test in parallel for each package.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 12-line check_fillable_fields.py was a subset of
extract_form_field_info.py. Add a --check flag to the latter and
remove the standalone script. Update forms.md reference accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split single CI job into parallel lint + build-and-typecheck jobs.
Add turbo cache via actions/cache for faster subsequent runs.
Use single turbo invocation for build+typecheck to optimize task
scheduling. Add concurrency group to cancel stale PR runs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lint tasks don't need dependencies to be linted first. Removing the
^lint dependency lets turbo run all lint tasks in parallel. Also adds
eslint config files to inputs for correct cache invalidation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the shared office/ directory (pack/unpack, validators, schemas,
soffice wrapper) to skills/_shared/office/ and replace the three
identical copies with symlinks. Update skill loader to dereference
symlinks during copy to managed directory, and skip _-prefixed
directories in the bundled skills scan.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Archives ~/.super-multica-dev and ~/Documents/Multica-dev into
~/.super-multica-dev-archives/<timestamp>/ before cleaning, so the
state can be fed to AI for post-mortem analysis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- dev:desktop:reset now cleans both ~/.super-multica and ~/.super-multica-dev
- reset-user-data.sh handles dev directory
- .env.example documents SMC_DATA_DIR
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sets SMC_DATA_DIR=~/.super-multica-dev and
MULTICA_WORKSPACE_DIR=~/Documents/Multica-dev for gateway and
desktop processes in dev:local, preventing dev/prod data mixing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows isolating dev and prod data by setting SMC_DATA_DIR (e.g.
~/.super-multica-dev). Also fixes cron/store.ts which bypassed
DATA_DIR with a hardcoded path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tray menu now shows:
- Agent status (Idle/Running/Streaming)
- Hub connection status
- Gateway URL
- Show Main Window
- Version number
- Check for Updates
- Quit Multica (⌘Q)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shrink asterisk glyph from 22x22 to 14x14 within the 22x22 canvas
(28x28 within 44x44 @2x), adding proper padding to align with
other macOS menu bar icons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace resized app icon with dedicated tray icon matching MulticaIcon
- Remove click-to-toggle behavior, add "Show Main Window" menu item
- Include tray icon PNGs in electron-builder files config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the main window is closed, the app now stays running with a
menu bar tray icon showing agent/hub status. Users can toggle the
window visibility and quit from the tray menu.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
res.statusText is always empty under HTTP/2, causing "Gateway error: "
with no detail. Now reads the JSON response body to surface the
server's actual error message and always includes the status code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add an `active` flag so that message_update/message_end events are
ignored after reset() until the next message_start, preventing stale
accumulated text from being re-emitted as a block.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track .env.development and .env.production for desktop app
- Add MAIN_VITE_API_URL to all env files
- Remove hardcoded GATEWAY_URL from dev scripts (now in .env.development)
- Update .env.example with full documentation of all env vars
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Read API host from import.meta.env.RENDERER_VITE_API_URL instead of
hardcoding it, so staging/dev builds point to the correct backend.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In packaged Electron builds, @multica/core is externalized and .env
files are excluded. Bridge import.meta.env.MAIN_VITE_API_URL (injected
at build time by electron-vite) to process.env.MULTICA_API_URL so that
getApiBaseUrl() reads the correct value in staging/test environments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lazy-read process.env at call time instead of module import time.
This ensures the env bridge in the Electron main process has time to
set process.env.MULTICA_API_URL before the first API request.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The hasToolUse() function was checking for "tool_use" (raw Anthropic format)
but pi-ai normalizes tool call blocks to type "toolCall". This made tool
narration non-functional in the ChannelManager (Desktop/embedded) path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect both "tool_use" (Anthropic) and "toolCall" (Hub) content types
- Re-send typing indicator after sending/editing status message since
Telegram clears typing state on any message send/edit
- Remove debug file logging (appendFileSync to /tmp)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Table cells already containing **bold** markers got double-wrapped,
creating ****text**** which produced overlapping <b><i> tags rejected
by Telegram's HTML parser.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Telegram bot is handled entirely by the Gateway
(apps/gateway/telegram/). The Desktop channel plugin was never
registered (commented out in initChannels) and is dead code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of silently discarding tool narration or spamming separate
messages, send a single editable Telegram message that updates in-place
as the agent works. First tool narration sends a reply; subsequent
narrations edit the same message. The final answer is sent as a new
message.
- Add replyTextEditable/editText to ChannelOutboundAdapter interface
- Implement editFormatted + editable methods in Telegram plugin
- Track statusMessageId in ChannelManager, clear on agent_end/error
- Add sendOrEditStatus to Gateway TelegramService with same behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the agent uses tools (web search, etc.), it generates intermediate
narration text like "Let me search..." before each tool call. These were
being sent as separate Telegram messages, causing message spam. Now we
detect tool_use blocks in the message content and skip sending those
intermediate messages — only the final answer reaches the user.
Applied to both Desktop channel plugin and Gateway Telegram service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Telegram doesn't support HTML tables, so pipe-delimited Markdown tables
were rendered as hard-to-read plain text on mobile. This converts tables
to a vertical "Header: Value" format with bold first column before
sending to Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract useQRToken and useCountdown hooks to qr-hooks.ts so qr-code.tsx
only exports components (fixes react-refresh/only-export-components)
- Remove unused useRef import from connect-step.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cleanupPendingRequests() iterated the service-wide pendingRequests Map
and rejected every entry. Since it was called from connectUser's catch
block (a per-user error path), one user's connection failure would
spuriously reject other users' in-flight verify RPCs.
The call was also redundant: sendVerifyRpc already cleans up its own
entry in all failure paths (timeout, RPC error, route failure).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DeviceConfirmDialog only exists in the main Layout, so verify
requests were timing out during onboarding. Since the user is
actively generating the QR code, auto-approve and show a success
state instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces in-memory Map with file-backed store at
~/.super-multica/gateway/telegram-users.json so user bindings
survive gateway restarts during local development.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add short code store, bot commands (/start, /status, /help), and
POST /telegram/connect-code endpoint for Desktop to create QR codes.
Users scan a QR → Telegram opens → /start {code} → auto-connects.
- ShortCodeStore: in-memory Map with TTL for connection info
- Bot commands registered via setMyCommands
- Refactor handleConnectionLink into shared connectUser method
- Fetch bot username via getMe() for deep link URL
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>