No description
Find a file
Igor Ryzhkov 68a16f5e7f chat: route reasoning deltas via partID→type map
The previous attempt split text vs reasoning by the
PartDelta.Field value, but opencode flags both with
field='text' — only the partID differs. Result: every
reasoning delta still landed in the main answer area while
streaming, identical to the original bug.

handleRunStream now carries a partID→type map across deltas,
populated from message.part.updated events (and pre-seeded
from the message's existing parts during replay). When a
text delta arrives, the map says whether its partID belongs
to a reasoning part (emit a think event) or a text part
(filter for <think> tags and emit a delta event). Unknown
partIDs fall through to the text path so a delta arriving
before its part.updated event doesn't drop content.

The previous runStreamState is a tiny struct so both the
filter and the map travel together through translateEvent.
2026-06-12 14:26:32 -07:00
cmd chat: auto-title sessions after first assistant reply 2026-06-12 13:51:57 -07:00
internal chat: route reasoning deltas via partID→type map 2026-06-12 14:26:32 -07:00
third_party Add memory_read + step cap; tighten the chat agent surface 2026-06-06 18:00:27 -07:00
.env.example chat: GPU-aware default + drop ollama from dropdown when down 2026-06-11 08:04:57 -07:00
.gitignore Initial commit: SHAI M1 skeleton 2026-06-06 02:34:56 -07:00
DEPLOY.md Production compose env + DEPLOY.md for homelab + Traefik 2026-06-07 17:42:05 -07:00
docker-compose.yml chat: GPU-aware default + drop ollama from dropdown when down 2026-06-11 08:04:57 -07:00
Dockerfile Pin mail-store paths absolute; add WORKDIR /app in Dockerfile 2026-06-08 16:16:49 -07:00
Dockerfile.opencode opencode: set ov display language in entrypoint 2026-06-11 00:45:04 -07:00
go.mod calendar: ICS fetcher with RRULE expansion for dashboard 2026-06-11 01:13:59 -07:00
go.sum calendar: ICS fetcher with RRULE expansion for dashboard 2026-06-11 01:13:59 -07:00
Makefile Add shai-mail: IMAP poll → opencode classify → Discord notify 2026-06-06 19:01:42 -07:00
opencode.json opencode: register Anthropic (Claude) provider 2026-06-11 07:57:41 -07:00
README.md Delete Python sidecar and dead Go packages; rework Docker/Make/docs 2026-06-06 03:18:42 -07:00
ROADMAP.md Delete Python sidecar and dead Go packages; rework Docker/Make/docs 2026-06-06 03:18:42 -07:00

SHAI — Self-Hosted AI

Personal, single-user AI workspace for the homelab. A thin Go web layer over opencode — opencode owns the agent loop, tool use, provider routing, and persistence; SHAI owns the chat UI and (eventually) the integration surfaces (webhooks, REST, MCP server, scheduling) and the OpenViking memory bridge.

Quick start

You need opencode installed locally (brew install anomalyco/tap/opencode or see opencode.ai/docs).

# Terminal 1 — start opencode serve
make opencode

# Terminal 2 — start the SHAI web server
cp .env.example .env
make run
# open http://127.0.0.1:7100

Or in Docker (homelab deploy):

docker compose up -d --build

The opencode.json at the repo root configures the Ollama provider against the homelab proxy. Edit it (or use ~/.config/opencode/opencode.json) to point at a different Ollama instance, add Anthropic/OpenAI, or change the default model. Restart opencode after edits.

Status

M1.5 — opencode cutover. Chat works end-to-end through opencode serve with streaming, rename, delete, and the sidebar menu. The Python sidecar and SHAI's own message/run/event tables have been deleted; opencode owns persistence. No tools yet exposed in the UI, no API surface, no MCP server, no scheduling.

See ROADMAP.md for the full plan.

Architecture

browser ──HTMX+SSE──▶ Go web (cmd/shai)
                       │
                       └── HTTP/SSE ──▶ opencode serve (REST + /event)
                                            │
                                            ├── Drizzle/SQLite (sessions, messages, parts, events)
                                            ├── AI SDK providers (Ollama, Anthropic, OpenAI, …)
                                            └── tool loop (file/bash/MCP)

Layout

cmd/shai/                 main.go (Go entry)
internal/
  config/                 env-driven config
  opencode/               REST/SSE client for opencode serve
  server/                 HTTP handlers, templates, SSE bridge
    web/
      templates/          HTMX templates
      static/             htmx.min.js, marked.min.js, app.css, app.js
opencode.json             opencode provider config (homelab Ollama)
Dockerfile                Go-only image for the web layer
Dockerfile.opencode       opencode serve image
docker-compose.yml        runs both