10 Commits
Author SHA1 Message Date
bot-hermes 9a0c67081e fix: wire plan-gate activation and add express.json to steer/plan-gate routes
- Wire planGateRuntime.activate() into session creation path when planGate is true
  (Bug 1: sessions map stayed empty, plan/status always returned none)
- Add express.json({ limit: '1mb' }) to session-steer and plan-gate POST routes
  (Bug 2: req.body was undefined, POST with JSON body returned 400)
- Pass planGateRuntime dependency to createOpenChamberSessionService
- Add route-level and integration tests for both fixes
2026-09-07 23:41:36 +00:00
bot-hermes 05d8e953ca feat: agent-to-agent integrations — activity stream, steer channel, plan gate
Three fork-side integrations that turn OpenChamber from a fire-and-forget
coder into a visible, steerable, plan-gated agent:

1. Activity stream (GET /api/openchamber/agent-activity SSE)
   - agent-activity/runtime.js: subscribes to global hub, normalizes
     message.updated parts into structured activity events (tool-call,
     file-edit, text-part), rate-limited coalescing for tool calls
   - Broadcasts openchamber:agent-activity and session-completed events
   - SSE endpoint with heartbeat (25s), same shape as /api/openchamber/events

2. Steer channel (POST /api/openchamber/session/:id/steer)
   - session-steer/runtime.js: interrupt mode (interrupt → inject
     system-level directive → resume) and queue mode (deliver on next idle)
   - Follows message-queue precedent for interrupt-safe dispatch
   - Broadcasts openchamber:steer-delivered on queued delivery

3. Plan-first gate (plan-gate/runtime.js + approve/reject/status routes)
   - State machine per session: pending → approved | rejected | timed_out
   - Injects plan-gate reminder via openchamber-sessions create prompt
   - Agent emits ## Plan, runtime detects and emits openchamber:plan-ready
   - Approve sends 'Proceed' prompt, reject sends revision prompt
   - Configurable timeout (default 5 min), auto-approve on timeout

4. P1 shared plumbing
   - cardID accepted in session create payload, stored in session metadata
   - All new events carry cardID when known

Files added:
- packages/web/server/lib/agent-activity/runtime.js + runtime.test.js
- packages/web/server/lib/session-steer/runtime.js + runtime.test.js
- packages/web/server/lib/plan-gate/runtime.js + runtime.test.js

Files modified:
- packages/web/server/lib/openchamber-sessions/routes.js (cardID, planGate)
- packages/web/server/lib/opencode/feature-routes-runtime.js (route wiring)
- packages/web/server/index.js (runtime creation, SSE_PATH_PREFIXES)
- packages/web/server/lib/ui-auth/ui-auth.js (auth allowlist)
- packages/web/server/lib/realtime-proxy.js (SSE allowlist)

28 new tests passing. All pre-existing tests unaffected.
2026-09-07 22:34:56 +00:00
bot-hermes 4b95b327dd fix: forward agent/model/variant to session creation
createSession() only sent { directory, title } to the OpenCode server,
dropping the agent field. The create() function read payload.agent but
never forwarded it, so every session was created with the OpenCode
default (build) and the agent was only applied later at prompt time.

Now forwards agent/model/variant in the session create POST body so the
session is created with the requested agent from the start.
2026-09-06 17:25:40 +00:00
Iuliia Ivashko 0ef189f3c8 perf(sessions): archive a worktree's sessions through one server batch
Removing a worktree archived its sessions one SDK call at a time and
then re-rendered the whole sidebar once per streamed session.updated
echo. On a worktree with 121 sessions that meant 14.8s of main-thread
work, 121 requests, and 328 localStorage writes.

- Add POST /api/openchamber/sessions/archive: validates a batch (max
  500 ids, per-request archivedAt), archives sequentially, and reports
  partial failures instead of dropping the batch. VS Code serves no
  such route and answers 501; the shared UI then falls back to the
  per-session path.
- Plan batches from the sessions this client actually holds, live
  directory stores first, so worktree-only sessions still batch.
- Claim (id, archivedAt) pairs before the request and consume the
  matching session.updated echoes, so the server's own confirmations
  no longer fan out into 121 store publications. Runtime-scoped, TTL
  30s, released on response or fallback; non-matching updates pass.
- Make the managed-chats persistence a real trailing debounce instead
  of a 50ms throttle, so a burst of publications coalesces into one
  localStorage write.

Benchmark (121 sessions, production build, real Chrome): 14785ms ->
~1030ms, long tasks 100 -> 1, global store publications 236 -> 1,
persistence writes 328 -> 3.
2026-09-04 16:50:03 +03:00
fitzgpt d6a5192fba fix(server): percent-encode non-ASCII directory headers to OpenCode 2026-08-24 02:21:35 +03:00
Bohdan Triapitsyn 34e8a24b20 feat(knowledge): rebuild the project notes panel as Project knowledge (#2973)
The panel stored notes, todos and plans inside one shared JSON file that
six unrelated domains also wrote to, synchronised itself through window
CustomEvents, and could only read plans. It is now Project knowledge:
server-owned storage with explicit routes, a store with rollback, a
section sidebar, plans that open and edit in place, and search across
all of it.

Notes and plans the user pins travel with every message sent in that
project. Pinning is project state, not an attachment to one message, so
it holds until unpinned and the work status panel names what is riding
along and can detach it.

Agent memory is added alongside, in two scopes: what is true about the
user, and what is true about this codebase. The split is not cosmetic —
a wrong project fact costs one project and is noticed, while a wrong
global fact quietly shapes every session everywhere and the user has no
code to check it against. It stays separate from notes so an agent
mistake cannot land in what the user wrote. Sessions receive an index of
titles only; bodies are read on demand, because an index carrying full
text grows until it crowds out the conversation.

Deciding what a session must be told, and whether it has been told, now
lives on the server. The client owned it before, which meant sessions
started without a UI — scheduled tasks, sessions the agent dispatches —
received nothing at all, and a tab's record of what it had sent outlived
the conversation: after compaction the agent no longer held the block
while the tab went on believing it did. What was delivered is recorded
in the session's own metadata, and compaction restores it through the
runtime that already restores pinned messages, in the same turn.

Agent memory ships dark behind OPENCHAMBER_MEMORY_ENABLE: unset, there
is no tool, no routes, no session index, no settings row and no panel
tab. Absent rather than switched off, so nothing invites turning on a
feature that has not been announced. Pinned notes and plans are
unaffected and ship as normal.
2026-08-18 02:59:04 +03:00
Bruno Fantauzzi e8caed45c9 fix: wait for worktree bootstrap before prompt dispatch; resolve session directory for send/fork (#2708) 2026-08-06 23:47:30 +03:00
Bohdan Triapitsyn 9d3d5c0852 fix(sessions): stop reporting a dispatched prompt that never landed
`prompt_async` answers 204 as soon as OpenCode forks the run and reports
every later failure only on the session event stream, so an unusable
model, agent, or variant produced a session with no message while the
result still claimed `promptDispatched: true`.

Validate an explicitly requested model, agent, and variant against the
directory's own agent and provider lists before any session, worktree, or
goal is created, and confirm a new user message actually reached the
session before reporting the dispatch. A failed or empty lookup never
turns a valid selection into a rejection.
2026-08-04 11:08:28 +03:00
Bohdan Triapitsyn b0028283fb feat: expand slash-command goals from command templates
Resolves armed slash-command objectives from authoritative templates before dispatch
Applies OpenCode argument expansion for goal metadata in UI and scheduled tasks
Falls back to the raw invocation when command details are unavailable
2026-07-29 00:47:29 +03:00
Bohdan Triapitsyn e908db637b feat: agent and CLI control plane for sessions, worktrees, and scheduled tasks (#2408)
Add a shared OpenChamber control service with two thin adapters — a native
`openchamber` tool injected into managed OpenCode, and new CLI commands — so
users can manage parallel sessions, worktrees, and scheduled tasks
conversationally through agents or from the terminal.

Control plane:
- New openchamber-control service owning a fixed action contract:
  projects.list, models.list, session list/create/send/fork/status/messages,
  and schedule list/create/run/delete/toggle. Session and worktree deletion
  and project registration are deliberately not exposed.
- New openchamber-sessions module owning create/worktree/prompt orchestration,
  Goal Mode dispatch, wait semantics (initial idle never counts as completion;
  timeout and cancellation are failures), and explicit partial-failure results.
- Scheduled-task logic extracted into a service shared by routes, CLI, and the
  agent tool.

Agent tool:
- Managed OpenCode gets a materialized plugin registering one typed tool with
  a loopback-only callback, per-child ephemeral bearer (timing-safe, never
  persisted or logged), and abort propagation into the service.
- The ~1.5k-token schema applies progressive disclosure: short descriptions,
  server-side validation returning actionable usage errors, and intent
  guardrails — created sessions/tasks are user-facing work (not age
  self-delegation); worktree/goal/agent/variant/wait are omit-by-default;
  dispatches produce no completion notification, and later result r
  to session.messages, which now returns the authoritative sessionStatus.
- session.create without a user-named model picks from favorites/re
  send/fork omit the selection and the service reuses the target session's
  last user-message model, agent, and variant before falling back t
- An "Agent control tool" setting (default on, Save + Reload to apply)
  disables plugin injection entirely.

CLI:
- New `openchamber session`, `schedule`, `projects`, and `models` commands
  with automatic instance targeting, --wait/--timeout/--last-assist
  worktree flags, and Goal Mode, preserving interactive, non-TTY, --quiet,
  and --json contracts. The control HTTP timeout derives from the w
  instead of the 4-second default.

UI:
- New built-in "Schedule a Task" starter (/schedule-task) running a
  dialogue that defines a task and offers to create it via the tool after
  explicit confirmation; Craft a Goal and Feature Planning gain the
  handoff offer, and guided starters reserve the question tool for concrete
  option choices. Localized in all 10 locales, migrated into custom
  starter lists, hidden on VS Code.
- Sidebar shows CLI/agent-created sessions live via the control eve
- openchamber tool calls render with per-action titles and metadata.
2026-07-24 21:54:28 +03:00