- store.test.ts: use baseDir option instead of mocking paths.js
- session-file-repair.test.ts: remove write-lock mock, assert behavior
- announce-findings.test.ts: use real storage with temp dirs
- sessions-list.test.ts: use real registry with seed helper
- compaction.test.ts: mock only third-party pi-coding-agent, use real
context-window internals
All tests exercise real code paths, improving confidence in actual
behavior per the strict mock policy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AuthStoreOptions with baseDir to auth-profiles/store.ts functions,
add baseDir option to announce.ts readLatestAssistantReply, and add
seedSubagentRunForTests helper to registry.ts. These enable tests to
use real implementations with temp directories instead of mocking
internal modules.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scans test files at startup and warns when vi.mock() targets internal
modules (relative paths or @multica/* packages). Reports file paths
and line numbers for all violations without interfering with test
execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Establish "external-only mock" rule: only third-party dependencies
may be mocked in tests. Internal modules must use real implementations
with temp directories, reset functions, or dependency injection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce a RunLog system that records agent execution events as
structured JSONL to ~/.super-multica/sessions/{id}/run-log.jsonl.
Enable via MULTICA_RUN_LOG=1 env var or AgentOptions.enableRunLog.
Logs: run lifecycle, LLM calls, tool execution timing, context
overflow recovery, auth profile rotation, error classification,
and compaction events.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prefer markdown responses from servers that support Cloudflare's Markdown
for Agents feature, reducing token usage by ~80% when available. Non-supporting
servers fall back to HTML as before.
- Update Accept header to prefer text/markdown in web_fetch requests
- Add text/markdown content-type handling to skip HTML parsing pipeline
- Capture x-markdown-tokens response header in WebFetchResult
- Add extractMarkdownTitle() helper for native markdown title extraction
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix publish repo from "multica" to "super-multica"
- Add zip to mac targets (required for electron-updater auto-updates)
- Enable hardenedRuntime (required for notarization)
- Add notarize config with teamId placeholder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional context parameter to getAuthHeaders() so callers can
provide feature-specific suffixes (e.g. "to use web search") in the
not-logged-in error message, restoring the original behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace duplicated getLocalAuth() + manual header construction in
finance/api.ts and web-search.ts with the shared getAuthHeaders()
and API_BASE_URL from hub/api-client.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract API_BASE_URL and getAuthHeaders() into a reusable module
so that tools don't duplicate base URL and auth header construction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Route all financial data requests through api-dev.copilothub.ai/api/v1/financial
proxy and authenticate via sid/device-id/os-type headers instead of X-API-KEY.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate web_search tool from HMAC-SHA256 reqId signing to
sid/device-id/os-type auth headers, matching the desktop API client
pattern. Update endpoint to /api/v1/web-search.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reads sid and deviceId from ~/.super-multica/auth.json for use by
tools that need authenticated API access.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add common generateEncryptedId() utility in @multica/utils
- All Device IDs now use same encryption algorithm (40 hex chars)
- Web: store encrypted format directly in localStorage
- Desktop: use shared utility, accept encrypted ID from Web
- Hub: use shared utility for hub-id generation
- Telegram: use shared utility for device ID generation
- Gateway hook: use encrypted format for client connections
Algorithm: sha256(sha256(uuid).slice(0,32)).slice(0,8) + sha256(uuid).slice(0,32)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add WebkitAppRegion drag to login page background areas so the window
can be dragged on macOS. Mark the sign-in button as no-drag to keep it
clickable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep LocalChat mounted at the Layout level with CSS visibility toggle
instead of unmounting on route change, preserving messages, streaming
state, and IPC subscriptions when switching sidebar tabs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Turborepo was not passing the API_URL environment variable to the build
process, causing Next.js rewrites to fall back to the default test API
instead of the production API configured in Vercel.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move auth callback listener setup before async operations
- Add unique ID to welcome toast to prevent duplicates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Web stores raw UUID, encrypts when transmitting (consistent with copilot-search)
- Desktop receives encrypted Device ID from Web login callback
- Desktop stores encrypted 40-char format in auth.json
- Update IPC types to include deviceId in auth callback
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add fetch wrapper for desktop renderer to call Multica backend REST API.
Attaches sid, device-id, and os-type headers automatically using
useAuthStore and electronAPI.auth.getDeviceIdHeader().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change from storing raw UUID to storing encrypted format
- Consistent with devv-sdk and Web implementation
- Auto-migrate old UUID format to new encrypted format
- Validate device ID format (40 hex characters)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Server-side redirect to deep link for production builds.
More reliable than client-side window.location.href.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Generate UUID-based Device ID on first launch
- Store deviceId in auth.json (persists across logins/logouts)
- Add double SHA-256 encryption (consistent with Web)
- Expose getDeviceId and getDeviceIdHeader IPC methods
- Fix callback path to only accept /callback (prevent duplicate toasts)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wraps the read tool from pi-coding-agent to automatically downscale
oversized images (>1MB or >2000px) before they enter the session.
Uses macOS sips for resize with no extra dependencies, following the
same pattern as OpenClaw. Falls back gracefully on non-macOS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Session JSONL files were bloated because base64 image data was stored
inline (a real session had 6.7MB of images in a 9.8MB file). Images
are now extracted to per-session media/ directories as binary files,
with compact $ref references stored in the JSONL. Images are restored
transparently on read. Old sessions with inline base64 remain
backward compatible and auto-migrate on next compaction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codex OAuth tokens use the ChatGPT backend API (chatgpt.com), not the
standard OpenAI API (api.openai.com). pi-ai already has a dedicated
openai-codex provider with the correct API format (openai-codex-responses)
and base URL. Remove the alias that was incorrectly mapping openai-codex
to openai, which caused 401 errors due to missing scopes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>