Commit Graph
1095 Commits
Author SHA1 Message Date
ZacharyZhang-NY e6532713b5 Give every agent a distinct procedural pixel identity
Replace the single cloned character with identity-derived sprites: skin
tone, hair style and color, outfit (tee/hoodie/blazer), shirt palette, and
glasses all hash off the agent id, drawn with facing-aware variants, a walk
cycle, and carried-item support for later behaviors. The CEO always wears
the blazer. Appearance determinism and population variety are unit-tested.
2026-07-06 21:44:04 -04:00
ZacharyZhang-NY cab4e4ba33 Rebuild the pixel office as a real floor plan with rooms and lanes
Replace the viewport-derived desk grid with a fixed-world office: a north
band of rooms (CEO office, meeting room, snack bar, restroom) with door
signage opening onto a corridor, and an open desk field that grows by rows
so any head-count fits the world instead of being cut off. Geometry lives in
a pure floor-plan module that also builds an axis-aligned lane graph with
BFS routing, unit-tested for reachability and collision invariants. A camera
transform centers or clamps the view, the first c_suite agent takes the CEO
office, name labels render the full name, and the mock TODO-board text is
gone. Office screenshots join the visual-review capture set.
2026-07-06 21:39:16 -04:00
ZacharyZhang-NY f61046b7a4 Restore thread panel wiring lost in the flat-timeline refactor
The flat-messages refactor left ChatThreadPanel orphaned: ChatPage passed a
no-op onOpenThread and ChatTimeline hardcoded onOpenThread={null}, so threads
(including /escalate board flows) were unreachable from the UI and the
desktop e2e failed on main. Reconnect open/close/reply/board-intervention
wiring around the flat timeline, show reply counts on thread roots, and
clear the lint debt that severed feature left behind.
2026-07-06 21:39:03 -04:00
ZacharyZhang-NY 06fa8fc07f update 2026-07-06 21:07:02 -04:00
ZacharyZhang-NY eb22b597e5 Merge branch 'main' of https://github.com/ZacharyZhang-NY/AgentCompany 2026-07-01 19:38:15 -04:00
ZacharyZhang-NY 93516ca28b update 2026-07-01 11:56:51 -04:00
ZacharyZhang-NY 8b2f94a715 Show all messages flat in channel and fix V8 OOM crash
Chat: removed all thread abstraction. Every message in a channel now
renders inline chronologically as a flat list — no compact rows, no
thread panel, no thread navigation. Just messages, like Slack.

OOM fix: snapshot now limits fast-growing tables (chat_messages: 500,
task_runs: 200, provider_requests: 100) instead of loading unbounded
rows. This prevents the renderer V8 heap from growing past 3.5GB and
crashing. The notifyDataChanged callback is also wrapped in try/catch
to prevent errors when the renderer frame is disposed during agent runs.
2026-06-30 22:56:58 -04:00
ZacharyZhang-NY 016ae25901 Open threads in-place in center pane and fix office crash
Chat: clicking a thread row now replaces the center pane content with
the thread's full messages (back button to return to thread list).
Removed the right-side thread panel entirely — threads navigate in
place like Slack, not as a side panel overlay.

Office: reduced frame rate to 24fps, skip rendering when canvas has
zero dimensions, schedule next frame AFTER draw (not before) to
prevent runaway frame buildup that caused the white screen crash.
2026-06-30 22:49:41 -04:00
ZacharyZhang-NY 82e28111e9 Fix office layout, performance, and crash issues
Layout: agents now arrange in a horizontal grid (3-4 per row based on
viewport width) instead of stacking vertically. Position calculation
uses layoutPositions() which guarantees agents stay within the canvas.

Performance: render loop throttled to 30fps instead of uncapped 60fps.
Removed Math.random() from render path — building window lights now use
a deterministic hash that changes slowly. Canvas dimensions only resize
when clientWidth/clientHeight actually change.

Crash fix: clearRect at frame start prevents accumulated draw state.
setTransform instead of scale prevents compounding transforms. Animation
cleanup properly cancels requestAnimationFrame on unmount.
2026-06-30 22:45:16 -04:00
ZacharyZhang-NY 2447bfba9c Rebuild office with rich pixel-art rendering inspired by claude-office
Characters now have round heads, headphones, eyes, shirts, pants, and
shoes — proper pixel-art people like claude-office. Desks are detailed
wooden tables with monitors showing task text, keyboards, and coffee
cups. The wall has a city skyline window, analog clock, whiteboard with
TODO items, and an employee-of-the-month painting. Active agents bob
and show speech bubbles with their current task. Floor has tile grid.
2026-06-30 22:34:58 -04:00
ZacharyZhang-NY f60ef60da1 Replace office sidebar with full-page canvas-rendered office
The virtual office is now a dedicated page (nav: Office) with an HTML5
Canvas rendering animated pixel-art characters. Each agent is drawn as
a pixel person with deterministic skin/shirt colors, walking legs, and
a bobbing head when active. Idle agents wander randomly near their desk.
Active agents show a green dot, thinking agents show a question mark.
Departments are labeled zones with desks and monitors. Removed the old
sidebar component entirely.
2026-06-30 22:30:00 -04:00
ZacharyZhang-NY 7a85f73dbb Show threads as compact rows instead of inline full messages
The channel timeline now renders each thread as a single compact row
with sender avatar, message preview (truncated to one line), reply
count with participant avatars, and last reply time. Clicking a row
opens the thread in the right panel where the full conversation lives.
This matches Slack's thread-list pattern instead of dumping every
message body into the channel view.
2026-06-30 22:27:11 -04:00
ZacharyZhang-NY e37faf1a2e Rewrite virtual office with pixel-art characters and compact layout
Replaced generic bot icons with CSS pixel-art people — colored head,
shirt body, and legs, each agent with a stable color derived from their
name. Layout is now compact flex-wrap (42px per agent) instead of one
agent per row. Sidebar narrowed to 172px. Tooltip anchored to right
edge to prevent clipping. Department floors use the app's panel-2
background for a clean integrated look.
2026-06-30 22:20:24 -04:00
ZacharyZhang-NY 7ff8e4becd Update migration version expectation for migrations 043-044 2026-06-30 22:09:57 -04:00
ZacharyZhang-NY 63c760860e Tell agents about available external tools in system prompt
When Composio tools are loaded for an agent run, the system prompt now
mentions their count and purpose so the agent knows it can interact
with external services like GitHub, Slack, and Gmail.
2026-06-30 22:00:56 -04:00
ZacharyZhang-NY 81aae82211 Add resilient error handling for Composio tool execution
Tool execution now returns actionable error messages when a connected
account is missing, directing the admin to set up the connection. Tool
loading is resilient to API failures, falling back to cached tools if
available instead of crashing the agent run.
2026-06-30 21:59:39 -04:00
ZacharyZhang-NY e83f379143 Cache Composio tools and load saved settings in the UI
Tools are now cached per-org with a 5-minute TTL to avoid hitting the
Composio API on every agent run. The ComposioPanel loads the currently
saved API key status and pre-checks enabled toolkits from the snapshot,
so users see their existing configuration when opening Settings > Tools.
2026-06-30 21:58:48 -04:00
ZacharyZhang-NY 3d685e5a4b Add e2e and integration tests for new features
E2e test updated to verify: virtual office sidebar toggle, Composio
Tools settings tab visibility, and @mention with canonical handles.
New integration test verifies that a human reply in a thread wakes
agent participants without requiring explicit @mentions.
2026-06-30 21:55:24 -04:00
ZacharyZhang-NY 7d9995f62c Polish virtual office with building floors and animated workstations
Inspired by claude-office's multi-floor building metaphor but rendered
as a polished UI instead of pixel art. Departments appear as numbered
floors in a building frame. Each workstation has a monitor with animated
screen glow for active agents, a stand, and a status dot. The building
header shows the active/total agent ratio at a glance.
2026-06-30 21:54:05 -04:00
ZacharyZhang-NY bb24a444f4 Wake thread participants when a human replies without @mentions
When a human or board member posts in a thread where agents have
previously participated, those agents are now woken even without
explicit @mentions. This matches the old version's behavior where
any message in a conversation could wake the recipient, enabling
natural back-and-forth between humans and agents.
2026-06-30 21:51:32 -04:00
ZacharyZhang-NY 651e7a69ec Fix Composio API endpoints to match verified v3 contract
Updated getTools to use the validated toolkit_slug parameter and
per-toolkit fetching. Updated executeTool to use the verified path
POST /api/v3/tools/execute/{TOOL_NAME} with entityId and arguments
fields. Updated normalizeToolSchema to use slug and input_parameters
from the actual API response format.
2026-06-30 21:50:35 -04:00
ZacharyZhang-NY 13a235a42d Seed Composio API key and default toolkits for all organizations
New orgs get the Composio API key and default toolkits (github, gmail,
slack, notion, linear, google_calendar) during bootstrap. Existing orgs
without Composio settings are seeded at app startup via the recovery
pass, ensuring every org has external tool access from first boot.
2026-06-30 21:47:00 -04:00
ZacharyZhang-NY 26db40282b Add unit tests for @mention resolution and read_messages tool
Tests verify: canonical handle generation for multi-word names, mention
resolution via canonical handles, read_messages from channel, and
read_messages inbox (agent @mentions across channels).
2026-06-30 21:44:45 -04:00
ZacharyZhang-NY 3a3c5b7ca3 Redesign virtual office with desk workstations and spatial layout
Each agent sits at a workstation with a monitor, status-colored glow for
active agents, and a rich tooltip showing name, role, and current task.
Departments render as labeled rooms with subtle borders. The monitor
lights up when the agent has a running task run, giving a real sense of
who is working and who is idle.
2026-06-30 21:42:50 -04:00
ZacharyZhang-NY 453e47274a Inject inbox context into non-chat task runs
Heartbeat and manual task runs now load the agent's recent @mentions and
include them directly in the task prompt. This gives agents conversational
context even before they call read_messages, ensuring they respond to
teammates who addressed them rather than silently ignoring messages.
2026-06-30 21:41:28 -04:00
ZacharyZhang-NY 59e3b6bf51 Add Composio settings panel for external tool configuration
Settings > Tools tab lets the user enter their Composio API key and
select which toolkits (GitHub, Slack, Gmail, etc.) to enable for agents.
The configuration is saved per-org and loaded at agent run time.
2026-06-30 21:39:56 -04:00
ZacharyZhang-NY 77644121db Record @mention wake failures instead of silently swallowing them
The catch block in wakeAgentMentions now records wake_state on each
mention (woken/failed) instead of silently discarding the error. Failed
mentions render with a strikethrough and muted color so the user sees
which agents could not be reached, with a tooltip on hover. Migration
044 adds the wake_state column to chat_mentions.
2026-06-30 21:38:19 -04:00
ZacharyZhang-NY f6a2659761 Extract read_messages tool to keep agent-tools under 500 lines 2026-06-30 21:35:11 -04:00
ZacharyZhang-NY 07fa105bf3 Add virtual office sidebar showing real-time agent status
A collapsible right sidebar renders agent presence as a visual office
floor plan grouped by department. Each agent shows at their desk with a
status ring (active/thinking/busy/idle) and a tooltip revealing their
current task on hover. Toggle via the Office button in the left nav.
2026-06-30 21:33:42 -04:00
ZacharyZhang-NY 77f191fa25 Integrate Composio for external tool access
Agents can now call external tools (GitHub, Slack, Gmail, etc.) via
Composio's managed API. A thin HTTP client calls the Composio REST API
directly — no heavy SDK dependency. External tools are loaded per-org
from composio_settings and merged with internal tools at run time. The
agent run loop routes composio_* tool calls to the Composio execution
endpoint while internal tools dispatch as before.

Includes: migration 043 for composio_settings table, IPC handler for
saving Composio API key and toolkit configuration, and the composio
client/bridge modules.
2026-06-30 21:31:04 -04:00
ZacharyZhang-NY 65c5bec9a3 Add read_messages tool and conversational task prompts
Agents now have a read_messages tool to check their inbox and channel
history during runs, enabling them to catch up on conversation before
acting. Task prompts are rewritten to encourage checking messages first
and discussing work with teammates rather than posting status updates.
2026-06-30 21:21:21 -04:00
ZacharyZhang-NY 5bb9aea4f9 Fix @mention resolution for multi-word agent names
MentionTextarea inserted raw agent names (e.g. @Sarah Chen) but the
backend regex captured only the first word (@Sarah), causing mention
resolution to fail silently. Moved canonicalMentionHandle to shared/
so the renderer can produce space-free handles that the backend resolves
correctly.
2026-06-30 21:17:43 -04:00
ZacharyZhang-NY dfa2df3334 Remove visible input placeholders 2026-06-26 19:44:02 -04:00
ZacharyZhang-NY 8923a2bf0a Clarify agent mention reply readiness 2026-06-26 19:41:56 -04:00
ZacharyZhang-NY 91991f7c4a Restrict external browser URLs 2026-06-26 19:37:11 -04:00
ZacharyZhang-NY d148146b91 Split snapshot domain types 2026-06-26 19:34:52 -04:00
ZacharyZhang-NY d85a47c40c Harden custom provider endpoint validation 2026-06-26 19:31:32 -04:00
ZacharyZhang-NY 745c22ec77 Fix agent assignment conversations 2026-06-26 19:27:28 -04:00
ZacharyZhang-NY bd63d42aa7 Extract slash-command routing out of ChatService
ChatService was 542 lines, mixing message delivery with the dispatch of
nine slash commands. Move the command cluster — /board, /approve, /deny,
/agent, /skill, /file, /runbook, /handoff, /escalate — into a
ChatSlashRouter that owns the approval and board-intervention services it
needs. ChatService keeps message delivery and delegates two calls.
Behaviour identical: chat-service 376 lines, router 196, full suite and
e2e green; the slash-routing governance test exercises every branch.
2026-06-26 18:25:14 -04:00
ZacharyZhang-NY 12c8402644 Extract organization seeding into its own module
OrganizationService was 552 lines, over the 500-line ceiling. The
80-line createOrganization routine — seed the org, the Board Chair,
identity/governance/operations/SDLC/policy defaults, starter channels,
the provider catalog — is a self-contained concern. Move it to
organization-seed.ts; the service now delegates and drops the two
service fields (operations, sdlc) only that routine used. Pure
relocation, behaviour identical: 469 lines, full suite and e2e green.
2026-06-26 18:19:05 -04:00
ZacharyZhang-NY 7db777b5d3 Harden main window navigation and permissions (sec #7)
The main window guarded will-navigate but not will-redirect, and left
the default session's permission handler at allow — looser than the
provider sign-in windows. Gate redirects with the same off-origin check
and deny every permission request/check by default. The first-party
renderer requests no web permissions, so denial changes nothing it does
while removing the grant a compromised page would otherwise inherit.
Verified end to end.
2026-06-26 18:11:05 -04:00
ZacharyZhang-NY 23a007d157 Require the OAuth state on the Codex callback (sec #4)
The Codex flow guarded with `result.state && result.state !== state`,
so a callback that simply omitted state skipped CSRF validation while a
sign-in window was open. Match the Anthropic and Google flows: compare
strictly, so a missing or mismatched state is rejected. PKCE already
blocks code injection; this closes the login-CSRF gap.
2026-06-26 18:06:58 -04:00
ZacharyZhang-NY 03c4b5376d Harden the renderer CSP (sec #2)
The policy fell back to default-src for scripts and allowed
'unsafe-inline', so any future injection sink would run with the
renderer's full contextBridge authority. The page has no inline scripts
(one external module), so split the directives: script-src 'self' with
no inline, style-src keeps 'unsafe-inline' for React inline styles, and
add object-src/base-uri/frame-src 'none'. localhost stays only on
script/connect for the dev server. Verified the production build still
loads and renders end to end.
2026-06-26 18:05:58 -04:00
ZacharyZhang-NY 867070f575 Contain workspace file ingestion to the bound folder (sec #3)
writeDeliverable guards against path traversal, but recordWorkspaceFile
resolved and readFileSync'd its path with no containment check — safe
only because today's lone caller hands it the already-sanitized result.
Any future caller passing a raw agent path (../../.ssh/id_rsa) could read
an arbitrary file into the org's file store.

Extract the resolve+reject-".."/absolute guard into one workspace-path
helper and route both the writer and the reader through it, so the
defense lives on the function rather than the caller.
2026-06-26 18:04:13 -04:00
ZacharyZhang-NY 6367512052 Render light markdown in chat messages
Bodies were printed verbatim, so an agent's **bold**, `code`, or
[link](https://...) showed as literal punctuation — the opposite of
people talking. Render the inline markdown agents and humans actually
use in chat into React nodes, composed around the existing @mention
highlighting.

Links are restricted to http(s) and nothing is ever set as raw HTML
(no dangerouslySetInnerHTML), so a message body can never inject markup
or a javascript: URL. A plain message still comes back as one string.
2026-06-26 18:00:10 -04:00
ZacharyZhang-NY 287c072c9f Take the audit log and file checksums out of the chat surface
The thread panel rendered an "Audit" feed — "Chat message sent", "Task
run completed", "Approval requested" rows with monospace timestamps —
a server log sitting inside a conversation. Attachments showed an eight-
character SHA-256 fragment next to the file type. Neither belongs in a
surface a non-technical operator reads as people talking.

Remove the audit replay from the chat thread (and its now-dead
replayEventsForThread/auditPayload plumbing) and drop the checksum from
the attachment card. The audit trail itself is unchanged — it is still
recorded and still shown on the task activity tab. The e2e thread check
now asserts the reply box, not the log.
2026-06-26 17:56:15 -04:00
ZacharyZhang-NY e80c8487f3 Return who is in the room from send_message, not a receipt id
send_message answered the agent with "Posted to #x (message_id=...,
thread_id=...)" — a transaction receipt that gives no sense anyone is
there. An agent posting into that void has no reason to converse.

Now it answers with presence: who was addressed and can reply, who else
is in the channel, and the thread_id to stay in the conversation. The
message_id noise is gone. The tool's own description now frames it as
talking to teammates rather than posting a coordination status.
2026-06-26 17:49:11 -04:00
ZacharyZhang-NY a9049612c5 Frame agent chat runs as a conversation, not a ticket
A woken agent was handed a "Chat reply" ticket whose description was
four source ids and "you were @mentioned... reply", then a closing that
told it to "report progress and completion" and "update the task status"
— so it answered like a status bot.

Now the wake reason names who spoke, in which channel, and quotes what
they said, and asks the agent to reply to that person in their own voice.
When a run carries a thread, buildTaskPrompt ends as a conversation
("reply to the people here... not a status report") and skips the work
closing entirely. The ordinary work closing also drops "reporting your
progress and completion" for "tell the team what you did and what's next,
the way you'd bring a colleague up to speed." The thread_id reply token
is preserved. This is the second half of making the company feel human.
2026-06-26 17:43:41 -04:00
ZacharyZhang-NY 1efd432eea Give each agent a role-shaped persona and a human voice
The system prompt was a single flat role line, so every agent sounded
like the same status bot. Replace it with an identity (name, title,
department, company, "a colleague, not a generic assistant") and a voice
that differs by standing — executive, manager, or individual contributor
— plus an explicit "talk like a person on a team, not a status bot"
directive. The classification is derived from existing fields (top of
org = CEO, has reports = manager), so there is no schema change.

This is the first half of why the old app felt human and the new one
did not: identical model calls now carry a distinct person behind them.
2026-06-26 17:38:06 -04:00
ZacharyZhang-NY fd52dc0861 Gate autonomous task runs on the execution approval
The manual runTask path enforces assertExecutionApproval, but the
autonomous heartbeat path (enqueueHeartbeatRuns -> enqueueRun -> the
queue worker) did not, so a high-risk or filesystem task whose approval
was still pending — the normal state in ai_cofounder mode, or after an
operator declines — was executed unsupervised.

Apply the same gate in enqueueRun. Pending/declined approvals leave the
task unqueued (the heartbeat's existing try/catch skips it) and it is
picked up on the next tick once approved. ai_ceo mode auto-approves at
task creation, so autonomous companies are unaffected.
2026-06-26 17:34:09 -04:00