Skip to content

Lewik/gromozeka

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,610 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gromozeka

Gromozeka Logo

Gromozeka is an experimental Kotlin Multiplatform AI assistant.

It is both an agent UI and a dogfooding environment for building a more durable agent runtime: multi-tab conversations, tool execution, MCP integration, voice input, and typed long-term memory.

The project is currently a local research/development application, not a polished packaged product.

Current Runtime Reality

  • Main dogfooding runtime: OPEN_AI_SUBSCRIPTION.
  • Runtime composition roots: :server for the control/API plane and :worker for execution.
  • UI clients: :presentation JVM Desktop and Wasm web/PWA.
  • Business workflows: :application.
  • Domain contracts and memory models: :domain.
  • AI integrations and tool implementations: :infrastructure-ai.
  • Persistence and search implementations: :infrastructure-db.
  • Active long-term memory backend: PostgreSQL through MemoryStore.

The current development shape is split:

  • :server accepts client commands, persists runtime state, publishes durable work, streams events, and exposes the Ktor remote endpoint.
  • :worker claims durable tasks and executes conversation, LLM, tool, and memory work according to its declared capabilities and affinities.
  • :presentation owns UI code and can run either as a JVM desktop client or as a Wasm web client.
  • The server listens on /ws for remote UI traffic and serves already-built Wasm static files from presentation/build/dist/wasmJs/developmentExecutable by default.

Legacy and auxiliary integrations still exist in the codebase, but the current default development path is the OpenAI subscription runtime plus PostgreSQL-backed typed memory.

What Gromozeka Does

  • Runs Compose chat UI with tabs and project-aware sessions.
  • Supports remote UI clients over WebSocket: JVM desktop locally, Wasm web/PWA in a browser.
  • Calls LLM runtimes through domain-level AiRuntime abstractions.
  • Exposes internal tools for filesystem, shell, web search, code navigation, planning, and inter-agent workflows.
  • Supports MCP configuration for external tools and servers.
  • Provides voice-oriented UI pieces such as push-to-talk and TTS services.
  • Writes and recalls structured project memory automatically during chat.

Typed Memory MVP

The active memory system is not a plain vector database. It stores typed, provenance-aware memory objects:

  • Source: immutable evidence, usually a chat turn or tool output.
  • Entity: canonical project/user/product/concept anchor.
  • Claim: atomic factual memory with predicate, scope, evidence, lifecycle, and temporal fields.
  • Note: rationale, design note, or reusable reasoning chunk.
  • Task: durable follow-up or commitment memory with lifecycle state.
  • Profile: projection built from profile-sync claims.
  • Episode: reusable experience or lesson pattern.
  • MemoryRun: debug/audit trace for memory pipeline execution.

Runtime write path:

  1. Capture the current message as a source.
  2. Route the message with LlmMemoryWriteRouter.
  3. Retrieve relevant existing memory when needed.
  4. Canonicalize entities.
  5. Build/reconcile notes, claims, and tasks.
  6. Materialize changes into MemoryStore.
  7. Update projections such as profiles.

Runtime read path:

  1. Plan whether memory is needed with LlmMemoryReadPlanner.
  2. Verify no-memory decisions with a model-based verifier when needed.
  3. Search typed memory in PostgreSQL.
  4. Select/rerank final memory context.
  5. Inject the retrieved memory into the main LLM call as runtime-only context.

Maintenance flows are explicit/manual durable operations handled asynchronously by a Worker: note consolidation, repair, entity maintenance, retention, and embedding rebuilds.

Useful memory docs:

Prerequisites

  • macOS development machine.
  • JDK 21.
  • Docker, for local PostgreSQL with pgvector and RabbitMQ runtime work queues.
  • OpenAI subscription auth file in Gromozeka home for the current dogfooding runtime.
  • Microphone permissions if you want to use voice input.

Running Locally

PostgreSQL and RabbitMQ are intentionally explicit. The app should fail fast if either runtime dependency is not available.

The server, Worker, and UI clients are separate processes. Start local infrastructure first, then the server, a Worker, and one of the UI clients.

Start local infrastructure:

GROMOZEKA_HOME="$PWD/dev-data/client/.gromozeka" \
docker compose -f "$PWD/server/src/main/resources/docker-compose.yml" up -d postgres rabbitmq

Run the server:

GROMOZEKA_HOME="$PWD/dev-data/client/.gromozeka" \
GROMOZEKA_MODE=dev \
./gradlew :server:run

The server defaults to 127.0.0.1:8765. It prints a line like:

==== Gromozeka server started: ws://127.0.0.1:8765/ws ====

The Server only accepts commands, persists runtime state, publishes work, and streams events. Start the local all-capabilities Worker:

SPRING_CONFIG_ADDITIONAL_LOCATION="file:$PWD/worker/config/dev-worker.yaml" \
GROMOZEKA_HOME="$PWD/dev-data/client/.gromozeka" \
GROMOZEKA_MODE=dev \
./gradlew :worker:run

See worker/README.md for split cloud and project-affine Worker configuration.

The default remote client endpoint is local:

ws://127.0.0.1:8765/ws

Override it with GROMOZEKA_REMOTE_URL when connecting through LAN, VPN, or Tailscale.

JVM Desktop Client

Run the desktop UI client against the local server:

GROMOZEKA_REMOTE_URL="ws://127.0.0.1:8765/ws" \
GROMOZEKA_CLIENT_HOME="$PWD/dev-data/client/.gromozeka-remote-client" \
./gradlew :presentation:run

Web/PWA Client

Build the Wasm web client:

./gradlew :presentation:wasmJsBrowserDevelopmentExecutableDistribution

Then run the server and open locally:

http://127.0.0.1:8765/

The web client resolves its WebSocket endpoint from the browser URL, so http://127.0.0.1:8765/ uses ws://127.0.0.1:8765/ws.

For raw HTTP testing through LAN/VPN without Tailscale Serve, bind the server to all interfaces:

GROMOZEKA_HOME="$PWD/dev-data/client/.gromozeka" \
GROMOZEKA_MODE=dev \
GROMOZEKA_REMOTE_HOST=0.0.0.0 \
./gradlew :server:run

Then open:

http://<machine-tailscale-or-lan-ip>:8765/

HTTPS Web/PWA through Tailscale

For private phone/laptop access inside a tailnet, use Tailscale Serve instead of exposing Gromozeka publicly. The Wasm client does not need a separate HTTPS build. It resolves /ws from the page URL, so an https:// page uses wss:// automatically.

Build the Wasm web client:

./gradlew :presentation:wasmJsBrowserDevelopmentExecutableDistribution

Run the server:

GROMOZEKA_HOME="$PWD/dev-data/client/.gromozeka" \
GROMOZEKA_MODE=dev \
./gradlew :server:run

Expose the local server through Tailscale Serve:

GROMOZEKA_REMOTE_PORT="${GROMOZEKA_REMOTE_PORT:-8765}"
tailscale serve --bg "http://127.0.0.1:${GROMOZEKA_REMOTE_PORT}"

Then open:

https://<machine>.<tailnet>.ts.net/

If you run the server on a non-default port, rerun the tailscale serve --bg ... command with the same GROMOZEKA_REMOTE_PORT.

Check the current Serve configuration:

tailscale serve status

Stop serving Gromozeka through Tailscale:

tailscale serve reset

If static files need to be served from a custom directory, set:

GROMOZEKA_WEB_STATIC_DIR="/absolute/path/to/web/dist"

Stop local infrastructure:

docker compose -f "$PWD/server/src/main/resources/docker-compose.yml" stop postgres rabbitmq

Verification

Build:

./gradlew :presentation:build -q

Server build:

./gradlew :server:build -q

Web client distribution only:

./gradlew :presentation:wasmJsBrowserDevelopmentExecutableDistribution -q

Application context smoke test:

./gradlew :server:test -q

Memory maintenance unit tests:

./gradlew :application:jvmTest --tests 'com.gromozeka.application.service.memory.MemoryMaintenancePipelineTest' -q

Memory real-model E2E in deterministic replay mode:

./gradlew :server:test \
  --tests 'com.gromozeka.server.MemoryRealModelE2eTest' \
  -Dgromozeka.memory.e2e=true \
  -Dgromozeka.llm.cassette.mode=replay-only \
  -q

Record missing LLM cassettes intentionally:

./gradlew :server:test \
  --tests 'com.gromozeka.server.MemoryRealModelE2eTest' \
  -Dgromozeka.memory.e2e=true \
  -Dgromozeka.llm.cassette.mode=record-missing \
  -q

For gromozeka.memory.e2e=true, cassette mode defaults to replay-only. This prevents accidental live LLM calls during normal verification.

Project Structure

domain/             Domain models, service contracts, tool contracts
application/        Use cases and orchestration pipelines
infrastructure-ai/  LLM runtimes, tools, MCP-related integrations
infrastructure-db/  PostgreSQL persistence, search, repository implementations
server/             Spring/server runtime composition, Ktor remote endpoint, server-owned resources
presentation/       Compose JVM Desktop and Wasm web UI clients
shared/             Shared utilities
agent_memory_handoff/  Memory design handoff and reference architecture
docs/               Architecture notes, diagrams, research, guides

Development Notes

  • Domain contracts should explain what the system must be able to do without forcing a storage or UI implementation.
  • Memory debug quality is judged by traces and E2E artifacts, not only by compilation.
  • The current E2E suite intentionally uses real LLM calls when recording cassettes and deterministic replay afterward.
  • Logs are verbose by design while the memory MVP is still being hardened.
  • Postgres data lives under GROMOZEKA_HOME/postgres when started through the provided compose file.

Philosophy

Gromozeka is an attempt to move beyond "just chat" toward an assistant that can work with code, tools, projects, and its own accumulated context.

The goal is human-AI collaboration where the system remembers useful project knowledge, exposes its traces, and stays debuggable enough that a developer can understand why it did what it did.

License

Custom License - free for non-commercial use, commercial use requires permission. See LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

3 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages