# AI Chat Architecture

ZoneGaze Chat adds a local-first AI chat system to the existing installable
`zonegaze-chat` Matrix plugin. The implementation is modular so the UI library,
provider, storage adapter, and agent runtime can be replaced later without changing
the Matrix shell contract.

## Containers

- Chat UI: React components in `plugins/chat/apps/web/src/`.
- UI runtime adapter: `zonegaze-chat-assistant-runtime.tsx` uses `@assistant-ui/react`
  while preserving ZoneGaze's custom Signal-styled layout.
- Runtime API: tRPC procedures under `runtime.*` in `flow/runtime/src/trpc/`.
- Runtime service: `flow/runtime/src/chat/chat-service.ts`.
- Persistence: `flow/runtime/src/chat/chat-store.ts` writes workspace-local `chat.json`
  through locked atomic JSON storage.
- Provider config: `flow/runtime/src/chat/chat-provider-config.ts`.
- Cline boundary: `flow/runtime/src/chat/chat-cline-sdk-runtime.ts` builds the
  Chat request using `@zonegaze/cline-sdk/chat-sdk-boundary` types, then adapts
  it into the existing `flow/runtime/src/cline-sdk/` session boundary with
  Chat-specific locked-down options.
- Streaming: `RuntimeStateHub` broadcasts chat deltas over the existing workspace
  websocket.

## Runtime API

The browser uses tRPC methods instead of raw REST routes:

- `runtime.listChatConversations`
- `runtime.createChatConversation`
- `runtime.getChatConversation`
- `runtime.updateChatConversation`
- `runtime.deleteChatConversation`
- `runtime.archiveChatConversation`
- `runtime.listChatMessages`
- `runtime.sendChatMessage`
- `runtime.stopChatGeneration`
- `runtime.regenerateChatResponse`
- `runtime.getChatSettings`
- `runtime.saveChatSettings`
- `runtime.resetChatSettings`
- `runtime.listChatModels`
- `runtime.getChatAiHealth`
- `runtime.resolveChatToolApproval`

Streaming messages are contract-defined as:

- `chat_conversation_updated`
- `chat_message`
- `chat_generation_status`
- `chat_tool_approval_updated`

## Persistence

Each workspace gets a `chat.json` file in the same state directory used by the rest
of the runtime. The store records:

- conversations and archive/delete flags
- messages and metadata
- active and completed generation records
- provider/model/settings snapshots
- pending and resolved tool approval records
- schema version for future migrations

No SQLite or hosted database is required for this version because ZoneGaze already
has durable workspace JSON storage and no multi-user database/auth model.

## Provider Configuration

Environment defaults are merged with workspace Chat settings:

```sh
ZONEGAZE_CHAT_AI_PROVIDER=ollama
ZONEGAZE_CHAT_AI_MODEL=llama3.1
ZONEGAZE_CHAT_AI_BASE_URL=http://localhost:11434/v1
ZONEGAZE_CHAT_AI_TEMPERATURE=0.2
ZONEGAZE_CHAT_AI_ENABLE_TOOLS=false
ZONEGAZE_CHAT_AI_ENABLE_SHELL=false
ZONEGAZE_CHAT_AI_ENABLE_FILE_WRITE=false
ZONEGAZE_CHAT_AI_ENABLE_BROWSER=false
ZONEGAZE_CHAT_AI_ENABLE_MCP=false
```

The default provider is a local OpenAI-compatible Ollama endpoint. Paid providers
are optional explicit configuration only.

## Agent Runtime

Chat imports upstream SDK request types through the shared
`@zonegaze/cline-sdk/chat-sdk-boundary` adapter. The runtime Chat adapter derives
its request shape from that package boundary, pins Chat defaults to the local
provider settings, and disables shell, file write, browser, MCP, agent teams, and
checkpoints unless the Chat settings explicitly allow a capability.

The adapter currently passes its normalized request into the existing
`flow/runtime/src/cline-sdk/` task-session boundary. This keeps the broader task
agent behavior stable while giving Chat a dedicated upstream SDK integration point.
The boundary check allows direct Cline imports only in `packages/cline-sdk` and
focused tests.

Installed SDK license audit:

| Package | Version | License metadata | Notes |
| --- | --- | --- | --- |
| `@cline/sdk` | `0.0.56` | Apache-2.0 | User-facing upstream SDK package |
| `@cline/core` | `0.0.56` | No npm license field | Same upstream Cline repo, Apache-2.0 |
| `@cline/llms` | `0.0.56` | No npm license field | Same upstream Cline repo, Apache-2.0 |
| `@cline/shared` | `0.0.56` | No npm license field | Same upstream Cline repo, Apache-2.0 |
| `@cline/agents` | `0.0.56` | Apache-2.0 | Cline SDK dependency |
| `@jerome-benoit/sap-ai-provider` | `4.6.9` | Apache-2.0 | Transitive optional provider support |
| `@sap-ai-sdk/foundation-models` | `2.12.0` | Apache-2.0 | Transitive SAP provider support |
| `@sap-ai-sdk/orchestration` | `2.12.0` | Apache-2.0 | Transitive SAP provider support |

The Cline internal packages that omit npm license fields are accepted here because
they resolve to the official Cline repository, which is Apache-2.0. Any future
non-Cline unknown or forbidden license should block the dependency update.

## Tool Approval

Tool execution is disabled by default:

- `enableTools=false`
- `enableShell=false`
- `enableFileWrite=false`
- `enableBrowser=false`
- `enableMcp=false`
- `disableMcpSettingsTools=true`

When tools are enabled, risky requests become stored approval records. The UI can
approve or reject each request once. Pending approvals time out and resolve as
rejected. Payloads expose only user-readable action, tool name, and sanitized target
details such as path, command, or URL when safe.

## Security Notes

- Chat is scoped by workspace. It is auth-ready, but local mode does not provide
  true multi-user isolation.
- The default local endpoint uses loopback Ollama and requires no API key.
- Secrets, `.env` contents, and arbitrary files are not automatically added to model
  context.
- Shell, file write, browser automation, and MCP surfaces require explicit settings
  and approval flow support.
- User-visible errors are separated from developer diagnostics.

## Verification

Focused automated checks cover provider settings and storage migrations. Runtime and
web typechecks cover the contract, tRPC, websocket, and Matrix surface integration.
Manual browser QA should use `http://127.0.0.1:4217/demo-website`.
