{"id":35234530,"url":"https://github.com/ebullient/quarkus-soloplay","last_synced_at":"2026-05-21T04:34:24.820Z","repository":{"id":328018009,"uuid":"1112439699","full_name":"ebullient/quarkus-soloplay","owner":"ebullient","description":"Generated by code.quarkus.io","archived":false,"fork":false,"pushed_at":"2026-03-06T03:22:16.000Z","size":761,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-29T16:56:54.629Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ebullient.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-08T16:17:34.000Z","updated_at":"2026-03-06T13:53:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ebullient/quarkus-soloplay","commit_stats":null,"previous_names":["ebullient/quarkus-soloplay"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ebullient/quarkus-soloplay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebullient%2Fquarkus-soloplay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebullient%2Fquarkus-soloplay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebullient%2Fquarkus-soloplay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebullient%2Fquarkus-soloplay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ebullient","download_url":"https://codeload.github.com/ebullient/quarkus-soloplay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebullient%2Fquarkus-soloplay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33288848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-21T02:57:32.698Z","status":"ssl_error","status_checked_at":"2026-05-21T02:57:31.990Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-30T03:32:29.240Z","updated_at":"2026-05-21T04:34:24.813Z","avatar_url":"https://github.com/ebullient.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Soloplay\n\nAn AI-powered solo tabletop RPG assistant,\nbuilt as a conference demo for progressive disclosure of LLM and RAG integration concepts.\n\nBuilt with **Quarkus**, **LangChain4j**, **Ollama** (local LLM), and **Neo4j** (graph database + vector storage).\n\n---\n\n## What This Demonstrates\n\nThis application shows four levels of LLM integration, each building on the last:\n\n### Level 1 — Plain Chat (`/chat`)\n\nA single `@RegisterAiService` interface with an inline system prompt. No memory, no tools —\nthe simplest possible LangChain4j integration.\n\n**Key source:**\n\n- [`ChatAssistant`](src/main/java/dev/ebullient/soloplay/ai/ChatAssistant.java) — the AI service interface\n- [`ChatResource`](src/main/java/dev/ebullient/soloplay/api/ChatResource.java) — REST endpoint at `/api/chat`\n\n### Level 2 — Guided Character Creation (`/play/{gameId}`)\n\nSession memory via `@MemoryId`, structured JSON output with guardrails, and a multi-turn\nconversation that extracts character details across several stages.\n\n**Key source:**\n\n- [`ActorCreationAssistant`](src/main/java/dev/ebullient/soloplay/play/ActorCreationAssistant.java) — AI service with session memory and structured extraction\n- [`ActorCreationEngine`](src/main/java/dev/ebullient/soloplay/play/ActorCreationEngine.java) — orchestrates the multi-stage creation flow\n\n### Level 3 — Lore Queries with RAG (`/lore`)\n\nRetrieval-augmented generation: vector similarity search against ingested campaign documents,\nwith AI tools for cross-reference resolution.\n\nThe document ingestion pipeline (`/ingest`) prepares the knowledge base: upload markdown\nwith YAML frontmatter → chunk → embed with nomic-embed-text → store in Neo4j vector index.\n\n**Key source:**\n\n- [`LoreAssistant`](src/main/java/dev/ebullient/soloplay/ai/LoreAssistant.java) — RAG-enabled AI service\n- [`LoreRetriever`](src/main/java/dev/ebullient/soloplay/ai/LoreRetriever.java) — `RetrievalAugmentor` supplier for Neo4j vector search\n- [`LoreTools`](src/main/java/dev/ebullient/soloplay/ai/LoreTools.java) — AI tools: document retrieval and semantic search\n- [`IngestService`](src/main/java/dev/ebullient/soloplay/IngestService.java) — document parsing, chunking, and embedding pipeline\n\n### Level 4 — Full Gameplay (`/play/{gameId}`)\n\nFull orchestration via an `AgentOrchestrator` that coordinates five specialized agents per turn.\nOnly the narration agent maintains session memory and has tool access; the other four are stateless\nand run concurrently via `CompletableFuture`. A WebSocket transport streams results for interactive play.\n\nThe five agents:\n\n| Agent | Purpose | Stateful? |\n| ----- | ------- | --------- |\n| [`NarrationAgent`](src/main/java/dev/ebullient/soloplay/play/agents/NarrationAgent.java) | Storytelling — produces the scene narration | Yes (session memory + tools) |\n| [`DiceAgent`](src/main/java/dev/ebullient/soloplay/play/agents/DiceAgent.java) | Decides if/what dice roll is required | No |\n| [`SuggestionAgent`](src/main/java/dev/ebullient/soloplay/play/agents/SuggestionAgent.java) | Generates 2–3 concrete next-action choices | No |\n| [`CheckpointAgent`](src/main/java/dev/ebullient/soloplay/play/agents/CheckpointAgent.java) | Identifies milestone moments and segment completion | No |\n| [`RecapAgent`](src/main/java/dev/ebullient/soloplay/play/agents/RecapAgent.java) | Produces a 1–2 sentence turn summary | No |\n\n**Key source:**\n\n- [`AgentOrchestrator`](src/main/java/dev/ebullient/soloplay/play/agents/AgentOrchestrator.java) — coordinates agents, assembles the composite `GamePlayResponse`\n- [`GamePlayEngine`](src/main/java/dev/ebullient/soloplay/play/GamePlayEngine.java) — routes turns through scene start, recap, action, and roll resolution\n- [`GameTools`](src/main/java/dev/ebullient/soloplay/play/GameTools.java) — AI tools: story recap, actor lookup, location lookup\n- [`PlayWebSocket`](src/main/java/dev/ebullient/soloplay/play/PlayWebSocket.java) — WebSocket at `/ws/play/{gameId}` for interactive play\n\n---\n\n## Application Routes\n\n| Route | Description |\n| ----- | ----------- |\n| `/` | Landing page — links to all sections |\n| `/chat` | Level 1: Plain chat with the LLM |\n| `/lore` | Level 3: Lore queries with RAG |\n| `/ingest` | Document upload and ingestion management |\n| `/game` | Game list; create new games |\n| `/play/{gameId}` | Levels 2 + 4: Character creation → active gameplay |\n| `/inspect/{gameId}` | View game state and turn history |\n| `/party/{gameId}` | Manage party members |\n\n---\n\n## Running the Demo\n\n### Prerequisites\n\n**Ollama** (local LLM):\n\n```shell\nollama serve\nollama pull llama3.2           # default chat model\nollama pull nomic-embed-text   # embeddings\n```\n\nThe default model (`llama3.2`) works for levels 1 and 2. For tool calling at levels 3 and 4,\na larger model is recommended. Override via `.env` in the project root:\n\n```shell\nQUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_NAME=qwen3:14b\n```\n\n**Neo4j** (graph database + vector store):\n\n```shell\ndocker compose up -d neo4j\n```\n\n### Start the application\n\n```shell\n./mvnw quarkus:dev\n```\n\nOpen [http://localhost:8080](http://localhost:8080).\n\n---\n\n## Frontend: Renarde + Vanilla JS\n\nThe UI is server-rendered with [Renarde](https://docs.quarkiverse.io/quarkus-renarde/dev/index.html)\n(Qute templates, type-safe routing, flash scope) and driven entirely by vanilla JavaScript — no\nfrontend framework, no build step.\n\n**Renarde controllers** handle page routing, form submissions, and redirects:\n\n- [`Game`](src/main/java/dev/ebullient/soloplay/web/Game.java) — CRUD forms with flash-scope feedback\n- [`Play`](src/main/java/dev/ebullient/soloplay/web/Play.java) — serves the play page with a `data-game-id` attribute for JS to pick up\n- [`Lore`](src/main/java/dev/ebullient/soloplay/web/Lore.java) — multipart file upload for document ingestion (CSRF-protected with `{#authenticityToken/}`)\n\n**Vanilla JS modules** add client-side interactivity:\n\n| Module | What it does |\n| ------ | ------------ |\n| [`play-interface.js`](src/main/resources/META-INF/resources/play-interface.js) | WebSocket streaming chat — reconnection, message buffering, choice buttons |\n| [`chat-interface.js`](src/main/resources/META-INF/resources/chat-interface.js) | Simple fetch-based chat for `/chat` and `/lore` |\n| [`game-index.js`](src/main/resources/META-INF/resources/game-index.js) | Game list — info/delete modals via REST calls |\n| [`inspect.js`](src/main/resources/META-INF/resources/inspect.js) | Developer tool: browse game-state JSON from `/api/game` endpoints |\n\nThe REST API under `/api/` ([`GameResource`](src/main/java/dev/ebullient/soloplay/api/GameResource.java),\n[`ChatResource`](src/main/java/dev/ebullient/soloplay/api/ChatResource.java),\n[`LoreResource`](src/main/java/dev/ebullient/soloplay/api/LoreResource.java)) provides\nthe JSON and HTML-fragment responses consumed by these scripts.\n\n---\n\n## Presentations\n\n* [Devnexus 2026 (Erin Schnabel and Jennifer Reif)](https://speakerdeck.com/jmhreif/supercharge-your-applications-with-java-graphs-and-a-touch-of-ai)\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) for architecture details, API reference,\nbuild commands, and contributor guidelines.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Febullient%2Fquarkus-soloplay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Febullient%2Fquarkus-soloplay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Febullient%2Fquarkus-soloplay/lists"}