Skip to content

refactor: excise legacy chat cluster + retire AgentCenter, rewire Automation to Inbox#232

Merged
luokerenx4 merged 11 commits into
masterfrom
feat/refactor
May 31, 2026
Merged

refactor: excise legacy chat cluster + retire AgentCenter, rewire Automation to Inbox#232
luokerenx4 merged 11 commits into
masterfrom
feat/refactor

Conversation

@luokerenx4
Copy link
Copy Markdown
Contributor

Summary

Rips out the entire pre-Workspace chat cluster and retires the in-process agent-loop layer. ~2600 lines of UI deleted, plus the backend subsystems behind them.

  • Deleted: AgentCenter (in-process AI loop), ConnectorCenter, NotificationsStore, notify_user tool, src/connectors/** (web/telegram/mcp-ask/mock), the /chat SSE + /api/dev + /api/notifications routes, and the 3 legacy UI surfaces (traditional-chat / notifications-legacy / connectors) with their full cascade (ChatPage, useChat, ChannelsContext, api/chat·notifications·channels, live/notifications…).
  • Rewired Automation: AgentWorkRunner now drives GenerateRouter directly and delivers to the Inbox (automation:<source> workspace id) instead of AgentCenter + ConnectorCenter. The model loop now lives in the native workspace CLIs; Alice no longer maintains its own.
  • Heartbeat: scheduler kept, push stubbed (output gate unconditionally skips) — its trigger chain isn't closed in the current Harness architecture. Cron: unchanged behavior, now delivers to Inbox.
  • Extracted: AI-Config test path (testProfile/testWithProfile) → core/ai-config.ts so the provider wizard + Workspace config-push survive AgentCenter's removal.
  • Channel stack removed end-to-end: TitleCtx.channels was only ever read by the legacy chat view's title(); dropping it let ChannelsContext + api/channels go entirely. Survivors untouched: top-nav Chat shortcut (workspace tabs) + Inbox.
  • Migration 0007: strips dead telegram/mcpAsk from connectors.json (keeps web.port), deletes orphan notifications.jsonl. Leaves heartbeat.json + cron/jobs.json alone.

Test plan

  • tsc --noEmit (backend src/) clean
  • tsc -p ui/tsconfig.json (UI) clean
  • vitest run src/ — 1632 pass (4 specs rewritten for the new AgentWork→GenerateRouter+Inbox path; dead specs deleted)
  • vitest run ui/ — 101 pass (store.spec retargeted off the removed chat ViewSpec)
  • Manual smoke needed — large deletion; reviewer should verify app boots, Inbox/Chat/Automation render, no dangling routes

Boundary touch

  • Migrations: adds 0007 (config cleanup).
  • Config schema: connectors slimmed to { web } — telegram/mcpAsk removed.
  • No trading / auth / broker-credential paths touched.

🤖 Generated with Claude Code

Ame and others added 11 commits May 31, 2026 18:12
…end)

Rip out the pre-Workspace chat cluster and the in-process agent-loop
layer; rewire Automation onto GenerateRouter + the Inbox. Backend src/
typechecks clean; spec rewrites + migration + UI removal follow.

Deleted:
- AgentCenter (core/agent-center.ts) — the in-process AI loop. The model
  loop now runs inside the native workspace CLIs; Alice no longer keeps
  its own loop.
- ConnectorCenter, NotificationsStore, notify_user tool, session tool.
- src/connectors/** (web, telegram, mcp-ask, mock).
- /chat SSE route, /api/dev, /api/notifications routes + dead specs.

Rewired:
- AgentWorkRunner drives GenerateRouter directly and delivers to the
  InboxStore under a synthetic `automation:<source>` workspace id
  (deps {agentCenter,connectorCenter} -> {router,inboxStore}).
- Heartbeat keeps its scheduler but STUBS the push (output gate is an
  unconditional skip) — its trigger chain isn't closed in the current
  Harness architecture. Cron keeps deliver-all, now to the Inbox.
- AI-Config test path (testProfile/testWithProfile) extracted to
  core/ai-config.ts so the provider wizard + Workspace config-push keep
  working without AgentCenter.
- createMediaRoutes + SSEClient relocated out of the deleted chat route.
- NotificationSource union re-homed to agent-event.ts as AgentWorkSource.
- EngineContext: dropped agentCenter/connectorCenter/notificationsStore,
  added router.
- connectors config schema slimmed to { web } (telegram/mcpAsk removed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite the four specs whose substrate (AgentCenter + ConnectorCenter +
NotificationsStore) was torn out:

- agent-work.spec.ts (37): runner driven by a mock GenerateRouter
  (provider yields a ProviderEvent stream) + memory InboxStore; delivery
  asserted via inbox entries (comments + automation:<source> workspace
  id). notify_user gate suite reframed as a generic tool-inspecting gate.
- agent-work-listener.spec.ts (17): same runner swap, kept the real
  eventLog+registry end-to-end coverage (metadata threading,
  buildDone/ErrorMetadata, multi-source, errors).
- cron/listener.spec.ts (8): cron.fire → agent.work.requested translation
  + delivery to automation:cron inbox.
- heartbeat.spec.ts (16): heartbeat behavior CHANGED — push is stubbed.
  Dropped dedup/notify_user/delivery/STATUS suites (those behaviors are
  gone), added stub-gate coverage (AI runs, gate always skips 'stubbed',
  inbox stays empty), kept active-hours / enable-disable / lifecycle /
  isWithinActiveHours.

Deleted dead specs for removed modules: agent-center, connector-center,
notifications-store, chat-streaming, tool/session, core/__tests__/pipeline.

Full repo `tsc --noEmit` clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migration 0007 cleans up config left dangling by the legacy chat cluster
removal:

- connectors.json: strip dead `telegram` + `mcpAsk` blocks, KEEP `web`
  (web.port is load-bearing — the server binds to it). Config-scoped via
  ctx helpers; idempotent (no rewrite when already clean).
- data/sessions/notifications.jsonl: delete the orphaned NotificationsStore
  log via raw fs (outside config scope, 0004 pattern), ENOENT-tolerant.

Deliberately untouched: heartbeat.json (scheduler survives) and
data/cron/jobs.json (a CronJob has no action/tool field — there is no
structural notify_user job to strip; payloads are generic prompts whose
replies now land in the Inbox).

registry.ts appended; INDEX.md regenerated. Spec: 6 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tors surfaces

Excise the three legacy ActivityBar surfaces and their cascade now that
the backend chat cluster is gone.

Deleted (legacy-only): ChatPage, NotificationsInboxPage, ConnectorsPage;
TraditionalChatSidebar, NotificationsLegacySidebar, ConnectorsLegacySidebar,
ChatChannelList, ChatInput, ChatMessage, ChannelConfigModal, NewChannelButton;
useChat hook; api/chat, api/notifications, api/channels; ChannelsContext;
live/notifications + live/notifications-read; the chat/channels demo
handlers (notificationsNews → newsList, news-only).

The channel stack came out end-to-end: `TitleCtx.channels` was only ever
read by the legacy chat view's title(), so dropping that view let
ChannelsContext + api/channels go entirely (TabStrip no longer threads
channels). Survivors untouched: the top-nav Chat shortcut
(ChatChannelListContainer → workspace tabs) and the Inbox stack.

Type/registry cleanup: removed ViewSpec kinds `chat` + `notifications-inbox`,
the settings `connectors` category, and ActivitySection members
traditional-chat/notifications-legacy/connectors-legacy. ActivityBar's
Legacy section is gone; UrlAdopter redirects stale /chat + /notifications
URLs to /inbox. store.spec retargeted to a surviving ViewSpec.

ui tsc -b clean; 226 UI tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Minor-version bump (not patch) — this release removes the entire
pre-Workspace chat cluster (traditional chat, connectors, notifications)
and retires the AgentCenter in-process agent-loop layer. Large
deprecation surface, hence 0.21 → 0.30.

Also aligns migration 0007's appVersion to the shipping version.
CI's `pnpm build` (tsc -b, stricter than the local single-project check
I ran) caught inline `{ kind: 'chat', ... }` literals still in the tab
store spec after the legacy-chat ViewSpec was removed. An earlier sed
rename only touched a helper that wasn't actually called; the inline
literals remained. Rewrote the spec to drive tab-store mechanics with a
surviving `market-detail` spec via a `tab(symbol)` helper. Sidebar tests
keep ActivitySection 'chat' (the top-nav Chat shortcut survives).

Verified: pnpm build green (9/9 turbo tasks), ui tsc clean, 24 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The demo handler barrel still imported ./chat, ./channels, and
./notificationsNews after those handlers were removed/renamed — a second
miss the local single-project tsc didn't surface but `pnpm build`
(turbo + tsc -b) did. Dropped the chat/channels imports and pointed the
news-article mock at ./newsList (renamed from notificationsNews, which
also dropped the dead /api/notifications/history mock).

Verified both CI gates locally this time: `pnpm build` 6/6 green,
`pnpm test` 1757 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removing the `chat` + `notifications-inbox` ViewSpec kinds (and the
traditional-chat/notifications-legacy/connectors-legacy ActivitySections)
is a persisted-schema change. A returning user's localStorage
(openalice.workspace.v2 @ v3) can hold a tab with kind:'chat' or a
selectedSidebar of a removed section; on rehydrate TabStrip calls
getView(kind) → undefined → .title()/.toUrl() throws → blank/crashed app.

This is a runtime-only hole that build + unit tests can't catch (no test
exercises real persisted state). Bump version 3 → 4 so the store's
existing loud-fail contract (schema bump clears, no migrate fn) drops the
stale state and reinitializes clean.

Found via manual review of the deletion's runtime blast radius.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The earlier bump commit (46541ca) only landed the migration 0007
appVersion alignment — the package.json edit had errored out (Edit
before Read) and was never committed, leaving package.json at beta.5
while migration 0007 declared beta.30. This commits the actual version
bump so the two agree.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Developer-doc sync for the 0.30 removal (README positioning handled
separately):
- core/ structure comment: drop legacy chat path; note agent-work drives
  GenerateRouter+InboxStore and ai-config holds the test path.
- tool/ comment: drop session + notify-user.
- Remove the src/connectors/** tree block (directory deleted).
- migrations 0001–0006 → 0001–0007.
- Inbox section: Inbox is now the only push surface (cron/task deliver here).
- GenerateRouter scope: governs AgentWork + the ai-config test path.
- Replace "### Legacy chat path" with a one-line tombstone pointing at
  migration 0007 + project_agentcenter_retirement, so a future session
  knows where the removed symbols went.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove stale references to the retired pre-Workspace chat cluster from
the public positioning: AgentCenter / ProviderRouter / ConnectorCenter,
the Telegram + MCP Ask connectors, the Notifications surface, and the
"Two kinds of chat" dual-path section.

- Surfaces / Core / Scheduling architecture prose rewired to the new
  stack (GenerateRouter + AgentWork + Inbox).
- "Two kinds of chat" collapsed to a single "Workspace chat" section —
  the traditional chat path no longer exists.
- Connector Key Concept removed; Inbox is now the single push surface
  (scheduled Automation runs deliver there too).
- Config table: drop the telegram.json row, trim connectors.json desc.

Automation is framed as "being rebuilt" rather than removed — the
scheduler's last mile depends on the Workspace scheduler landing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@luokerenx4 luokerenx4 merged commit 681f8e3 into master May 31, 2026
1 check passed
pull Bot pushed a commit to bhardwajRahul/OpenAlice that referenced this pull request Jun 1, 2026
The pushToolGate test helper in agent-work.spec.ts inline-typed its
probe argument with `media: never[]`, while the real
AgentWorkResultProbe interface has `media: MediaAttachment[]`. Strict
tsc (--noEmit) rejected this at three call sites that pass pushToolGate
as an outputGate (lines 406 / 414 / 424); vitest+esbuild let it slip
through because esbuild doesn't enforce types.

Fix by importing AgentWorkResultProbe from agent-work.ts and using it
directly — eliminates the ad-hoc inline shape so this can't drift
again.

Slipped in via PR TraderAlice#232 (legacy chat cluster excision), the same one
that introduced the rewired agent-work pipeline.

Verified:
- npx tsc --noEmit (root, Alice strict): clean
- pnpm vitest run src/core/agent-work.spec.ts: 37/37 pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pull Bot pushed a commit to bhardwajRahul/OpenAlice that referenced this pull request Jun 1, 2026
…v4→v5

Two coupled fixes.

## 1. News handler shape mismatch (the crash)

PR TraderAlice#232's legacy-chat excision replaced the old notifications/news
handler with a new `newsList.ts` that returns:

  { articles: [...], hasMore: false }

with each article shaped { id, title, source, url, publishedAt,
summary, tickers }.

But the contract per ui/src/api/types.ts is NewsListResponse:

  { items: NewsArticle[], count, lookback }

with each NewsArticle shaped { time, title, content, source, link,
categories }.

NewsPage calls `setArticles(res.items)` — wrong shape gives
`articles = undefined`, then render does `[...articles].reverse()`
which throws "undefined is not iterable" as an unhandled exception.
React error boundary upstream catches it on the page level but the
crash poisons any persisted tab state pointing at the news view.

Rewires the handler to use `demoNewsArticles` (PR-4 Stage 2 fixture,
correct NewsArticle shape, 6 realistic items) and the correct
{ items, count, lookback } wrapper.

## 2. Persist version bump (the recovery)

A user who'd already opened the news tab has `selectedSidebar:'news'`
+ a news tab kind persisted to localStorage `openalice.workspace.v2`.
Reload replays that selection → re-triggers the crash → loop. Bumping
the persist version from 4 to 5 makes zustand drop the poisoned state
on rehydrate (no migrate function — schema bump clears, per this
store's loud-fail contract — matching v4's bump pattern from the
legacy chat excision).

Cost: users with healthy state lose their open-tabs/layout. Necessary
trade-off — they were on the crash path too if they navigated to news.

Verified:
- pnpm -F open-alice-ui exec tsc -b: clean
- pnpm -F open-alice-ui build (prod): main chunk has zero
  `demoNewsArticles` / fixture-string leaks
- pnpm dev:demo + Playwright: /news lists 6 articles correctly,
  expand-article click works, single zustand info log "couldn't be
  migrated since no migrate function was provided" is the expected
  v4→v5 dropping behavior

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant