Skip to content

feat(cloud-agent): add Cloud Agent SDK#1395

Open
eshurakov wants to merge 1 commit intomainfrom
eshurakov/cloud-agent-sdk
Open

feat(cloud-agent): add Cloud Agent SDK#1395
eshurakov wants to merge 1 commit intomainfrom
eshurakov/cloud-agent-sdk

Conversation

@eshurakov
Copy link
Contributor

Summary

Self-contained Cloud Agent SDK at src/lib/cloud-agent-sdk/ — a pure library replacing the callback-based event-processor with a structured, testable architecture.

  • Normalizer: Raw wire events → typed ChatEvent | ServiceEvent discriminated union with strict validation
  • Reducer: ChatEvent → StorageMutation[] pure mapping
  • Storage adapters: In-memory (memory.ts) and Jotai-backed (jotai.ts) implementations of SessionStorage interface
  • Service state: Manages session activity, agent status, questions, permissions, autocommit, and cloud status from ServiceEvent stream
  • Transport layer: base-connection.ts (generic WebSocket lifecycle with reconnect/backoff), connection.ts (Cloud Agent-specific), cli-live-transport.ts, cli-historical-transport.ts, cloud-agent-transport.ts
  • Session: Orchestrator wiring ChatProcessor + ServiceState + Transport with phase tracking (connecting | streaming | idle | stopped | retrying)
  • Session manager: Multi-session coordinator with Jotai atoms for React integration, session switching, and lifecycle management
  • Type trimming: opencode.gen.ts reduced from 5,449 → 576 lines (only directly-used types retained)

400+ tests across 15 test files covering normalizer, reducer, storage, connection, session phases, transports, and fixture-based integration.

This is PR 1 of 5 in a stacked series. Independent — no dependencies on other PRs.

Verification

  • pnpm test -- src/lib/cloud-agent-sdk — 400+ tests passing
  • SDK tests are self-contained (no external service dependencies)

Visual Changes

N/A

Reviewer Notes

  • The normalizer is the single as cast boundary — all downstream code is properly typed
  • Storage uses frozen snapshot caching for useSyncExternalStore reference stability
  • SessionPhase state machine replaces 4 overlapping lifecycle callbacks with a single discriminated union
  • Key design decision: chat events (messages/parts) and service events (lifecycle/status) flow through separate pipelines to support future separate transport channels

@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Mar 23, 2026

Code Review Summary

Status: 12 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 12
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
src/lib/cloud-agent-sdk/session-manager.ts 618 canInterrupt is too broad for the fallback path.
src/lib/cloud-agent-sdk/session.ts 352 Stop requests during CLI resolution still reconnect.
src/lib/cloud-agent-sdk/base-connection.ts 63 Auth refresh failures permanently stop reconnecting.
src/lib/cloud-agent-sdk/session-manager.ts 481 Loading can stay stuck if no root session.created arrives.
src/lib/cloud-agent-sdk/session-manager.ts 566 Fallback session swap leaves stale per-session UI state behind.
src/lib/cloud-agent-sdk/session-manager.ts 565 Fallback reset drops the request-id mapping for restored questions.

Fix these issues in Kilo Cloud

Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
src/lib/cloud-agent-sdk/session-manager.ts N/A CLI sessions are never actually interrupted here.
src/lib/cloud-agent-sdk/session.ts N/A Repeated connect() calls can attach a stale transport.
src/lib/cloud-agent-sdk/connection.ts N/A 1006 is not specific to auth failures.
src/lib/cloud-agent-sdk/cloud-agent-transport.ts N/A Snapshot replay plus replay=false can drop in-flight events.
src/lib/cloud-agent-sdk/schemas.ts N/A Optional permission fields now block the entire prompt.
src/lib/cloud-agent-sdk/normalizer.ts N/A session.created/session.updated no longer validate that info.id is a string.
Files Reviewed (1 files)
  • packages/trpc/dist/index.d.ts - no new issues

Reviewed by gpt-5.4-20260305 · 298,417 tokens

@eshurakov eshurakov force-pushed the eshurakov/cloud-agent-sdk branch from 3c374e4 to f6588e5 Compare March 24, 2026 08:52
@eshurakov eshurakov force-pushed the eshurakov/cloud-agent-sdk branch from d7193d8 to e57695d Compare March 24, 2026 11:37
if (!store.get(isLoadingAtom)) return;
// Fallback: clear loading state when events start flowing even if
// no root session.created was replayed (e.g. CLI snapshot failure).
store.set(sessionConfigAtom, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Fallback session swap leaves stale per-session UI state behind

This branch swaps in jotaiStorage without the clearAllAtoms() reset used by the root onSessionCreated path. If the previous session had a standalone question/permission, request-id maps, or failedPromptAtom populated, those values survive into the new session whenever session.created never arrives, so the UI can keep showing prompts from the old session.

// no root session.created was replayed (e.g. CLI snapshot failure).
// Reset all per-session atoms first, same as the onSessionCreated
// path, so stale UI state from the previous session doesn't leak.
clearAllAtoms();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Fallback reset drops the request-id mapping for restored questions

processConnected() repopulates questionRequestIdsAtom before the first service-state notification so resumed tool questions can still be answered. Calling clearAllAtoms() inside that first notification wipes the map again, while this callback only restores questionAtom from state. In the snapshot-failure fallback, the question card still renders but QuestionToolCard can no longer resolve toolPart.callID to a request id, so submitting the answer fails.

@eshurakov eshurakov force-pushed the eshurakov/cloud-agent-sdk branch from b291379 to 5ad284d Compare March 25, 2026 12:13
@eshurakov eshurakov force-pushed the eshurakov/cloud-agent-sdk branch from 5ad284d to fbe887f Compare March 25, 2026 12:43
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.

2 participants