The global webRequest.onHeadersReceived CSP rewrite was attached to
session.defaultSession, which intercepts every Chromium request
(including devtools and network service internals) and crashed the
network service in dev. Drop the global override and rely on the
renderer-level meta tag, widened to allow Vite's localhost HMR
connections.
- Port design tokens, sidebar, topbar, and icons to inline SVG set
- Rewrite each page (Home/Team/Work/Chat/Files/Approvals/Social/Settings)
to drive real snapshot data and match the bento, kanban, three-pane chat,
file tree + pinned cards, approval queue, social schedule + calendar,
and settings sub-nav layouts
- Split Chat and Settings into per-concern subcomponents so every file
stays under 500 lines
- Add schema v4 for pinned files and scheduled posts plus IPC + service
wiring; cover new behavior in unit tests
- Update onboarding labels and Hire form to remove ambiguity for the
expanded e2e suite (all settings tabs + 8 routes at 1280 and 980)
- TeamPage: add SVG connector lines between CEO and subordinate agent cards
- WorkPage: add Board/List view toggle and Filter button matching design topbar
- List view shows all tasks in table format with status/priority/assignee columns
Replaces simple metric cards with the design's rich two-row bento grid:
- Row 1: Today (active tasks), Waiting on you (quick-approve), Monthly budget
- Row 2: In progress work, Team roster, Quarter goal (dark card with progress bar)
Personalized greeting based on time of day. All data bound to real snapshot.
- Add search bar with ⌘K hint between org logo and nav in sidebar
- Move Settings nav item to bottom section above sidebar footer
- Fix minimize button icon from MoreHorizontal to Minus on non-macOS
- Replace work/social nav icons with design-spec custom SVG paths
- Add --r-xl and --shadow-md CSS tokens from design system
- Set letter-spacing -0.005em and font-feature-settings on body
Boss build seeds one Fire Pass key for every agent. Three concurrent
agents -> three concurrent streamSimple calls against the Kimi K2.6
Turbo router -> three HTTP 429s on the overview dashboard.
Add an in-memory async semaphore keyed by (provider, sha1(apiKey)) and
acquire a slot inside `createSafePiStream` before invoking the source.
The slot is released when the stream finishes, errors, or aborts.
`fireworks-firepass` is capped at 1 concurrent call; every other
provider stays uncapped (no fallback layer, no 429 retry — flow control
prevents the burst at the source instead of recovering after).
Same code path applies to public and boss builds: only the seeded key
differs, the gate behaviour is identical.
Both servers expose OpenAI-compatible /v1/chat/completions and /v1/models,
so we route them through pi-ai's `openai-completions` API the same way
Fireworks does — but with a per-installation base URL the user enters
during onboarding instead of a hardcoded one. The shared schemas grow a
`local` credential payload carrying just the baseUrl; the credential
resolver surfaces it on `ResolvedCredential.baseUrl`, the runtime bridge
forwards it through `prepareRun`, and the worker plumbs it into
`resolveModel` so the streamed Model<openai-completions> targets the
user's server. The local-cost path short-circuits to zero in cost-writer
since users bill their own hardware, and the live model list is fetched
from the saved baseUrl by `fetchLocalConnectorModels` (Ollama and LM
Studio both speak the standard OpenAI catalog shape). Onboarding ships
a new LocalProviderCard and the Settings panel a LocalForm; both default
to the catalog's per-connector localhost URL and accept any custom URL.
Fireworks rolled out the kimi-k2p6-turbo router as the new Fire Pass
target; the k2p5-turbo route will start refusing Fire-Pass-only
callers. Bump the router id and display name in connector-catalog,
apikey connector definition, model-resolver, and capability-seed so
the desktop catalog, the renderer's onboarding rail, the capability
matrix, and the runtime model resolver all point at the same model.
agent_message_reads is the per-viewer source of truth for readAt, but
the send path never recorded the author's own receipt. Every message
the board operator or an agent sent therefore counted as unread to
themselves until they happened to re-open the channel — sidebar badge,
inbox panel, and the channel sidebar all derive from the same join
table. Insert a (message_id, from_agent_id, created_at) row in the
same transaction as the message itself; the receipt becomes an
atomic part of the write rather than a deferred maintenance task.
handleRunFinished and releaseCompletedRunWorkspaceLock both run between
receiving run-finished and posting run-completion-ack. If either throws,
the ack is skipped and the worker keeps the agent in its `active` map
forever; every subsequent wake then queues behind an `isAgentBusy` check
that never clears, and manual wakes from the UI silently fail to start.
Wrap the post-finalize work in try/catch so the ack is posted
unconditionally and the worker state machine stays consistent.
Pi-ai ships $0 pricing for github-copilot (25 models), google-gemini-cli
(6 models), zai (13 models), and kimi-coding (2 models). This made cost
tracking produce $0 for every run through these providers, rendering
budget enforcement useless.
Added resolveModelCostFallback() in model-resolver.ts with two strategies:
1. Cross-provider lookup: subscription providers (github-copilot,
google-gemini-cli) use the same models as their API counterparts.
Look up the model in anthropic/openai/google/xai catalogs using
normalized ID matching (dots→hyphens) to find real pricing.
2. Per-provider fallback: API-key providers with no cross-provider
equivalent (zai, kimi-coding) get a static per-provider cost.
CostWriter now calls resolveModelCostFallback after resolveModel, so
all consumers get patched pricing without touching the pi-ai library.