## Summary The generation activity report could not be relied on when something went wrong: - steps were swallowing the exceptions they produced, with no chance for a user to see them - a step whose call failed usually closed as finished, because the services absorb their failures into a fallback; - several requests behind one step — retries, the narrator's empty-answer loop — showed as a single row; - a step could stay *in progress* indefinitely while a retry loop ran out of sight, and the narrator's own errors were swallowed and re-sent as empty answers. This makes the report readable in full and makes it say why each step failed, request by request, without changing what a turn does. ## Changes **Display** - The timeline is uncapped, read by scrolling the story like the reasoning block. Times are rounded to the nearest second, sit in a fixed column, and are left blank for a step recorded after the fact without a duration (an agent tool call, a cached selection) instead of reading a default `0s`. - The collapsed line wraps instead of being cut, and on a narrow card shares its row with the story time. - The latest turn's timeline opens and the previous one folds; a reader's own choice sticks. Records are no longer hidden when a turn ends, and the session keeps the last 20. - Sending scrolls to the end of the story, and the story view no longer jumps when the streaming card is replaced by the entry. - The sparkle marks the model calls themselves, not the steps that contain them. **Failure reporting** - A failed step carries its reason, worded once by `describeActivityError`: status and provider message for an API error, `Failed after N attempts, with no retries left: <last reason>` for exhausted retries, a lost connection named as such rather than the HTTP plugin's `error decoding response body`. - Services that absorb a failure into a fallback — translation, suggestions, action choices, timeline fill, Tier 3 selection, scene analysis, the background image, the classifier's `_error` — still close the step they serve as failed (`failStep`) and return the same fallback as before. - A failure is told once, on the deepest step that carries it; every step above it is marked with a red ⚠. When the only failures beneath a step are attempts its request got past, the ⚠ is in the text colour. - A turn ends with an outcome (`turnOutcome`); only a halted turn says *Failed* on the collapsed line. A halted turn's record moves to its error entry, which is marked by `metadata.source` rather than recognised by its text, and every other system entry gets edit, delete and regenerate. The "Generation failed" banner above the input is removed: it duplicated the error card. - The error card for a turn without narration reads *The narration could not be generated. Please try again.* — it no longer claims a number of attempts. **Requests and retries** - `activityMiddleware` sits inside `retryOn429Middleware`: a request that needs a second attempt gets a row per attempt (the first backfilled) and a row per wait the retry middleware schedules. The SDK's own retries show as attempts. - The narrator's empty-answer loop reports *passes*, kept apart from the transport attempts inside them. A single pass has no container; it is grouped into `Pass 1` only once a second follows. An empty pass is a failure. - Within a pass, `Waiting for model` gives way to `Generating` as soon as the response starts, so a slow first token and an empty answer are both visible. **Narrator errors** - `streamText` reports a failed request as an `error` part rather than by throwing. The narrator dropped it, so every narrator failure read as an empty answer and was re-sent twice. The part is now rethrown, with a provider's in-stream error object turned into an `Error` with its code and message. - A stream that fails after text has arrived keeps that text as the narration and reports the failure without halting: the request was paid for, and the reader can still regenerate. One that fails before any text is passed again, like an empty answer; a request refused outright is not. **Phases** - `Updating world` and `Saving translation` are steps of their own, so a failed write shows where it happened. `Updating world` reads *partly applied* after a salvaged classification and *fallback bookkeeping only* after a failed one. - Agent Mode's hand-off is a `Handed off · N images queued` step under *Images*: the images finish after the turn, and the record does not follow them. - A phase switched off in settings is not reported; one switched on but missing its profile is struck through with that reason. **Stop** - Once the narration is saved, Stop dims, and a tap explains with a toast that the turn is finishing steps that cannot be interrupted. Nothing after the narration observes the abort, so Stop used to free the input while the turn still held the generation lease: Send was offered and refused, the story could not be left, and the report went on counting. "Generate a different response", which refuses Stop throughout, now explains its disabled Stop the same way. **Tooling** - `scripts/fake-provider.mjs` (`npm run fake-provider`) is an OpenAI-compatible chat and image API whose behaviour is chosen by the requested model name: rate limits, 4xx and 5xx, hangs, empty, malformed and partly valid answers, cut streams. Setup and the model list are in `docs/development/testing.md`. `docs/architecture/overview.md` describes the reporting model, the narrator's passes and the Stop refusal. ## Testing - New unit tests for `describeActivityError`, `turnOutcome`, the recorder (including `groupChildren` and untimed steps), the tree readings (`failuresShownBelow`, `failureMarks`, `stepsAboveLLMSteps`), `trackPhase`, the retry and activity middleware, the narrator's chunk translation, each phase's reporting, and `storyEntries`. - `reportingDoesNotAlterTurn.test.ts` and `absorbedFailures.test.ts` check that reporting changes nothing a turn does and that every absorbed failure still returns its fallback. - Every call a turn makes was run against the fake provider in the desktop app, each in the failures it can meet; the display was also checked on Android. - No test renders a component; the timeline, the collapsed line and the Stop button were checked in the running app. ## Known gaps - The retrieval agent builds its model elsewhere and its retries are not reported. - Stop still cannot cancel work after the narration is saved; this only stops it from claiming to. - On Android a tap on Stop while the narration streams can fail to register; that is separate from this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Generation activity reports now show clearer step summaries, elapsed times, failures, recoveries, and retry attempts. More activity history is retained, and reports are visible by default. * Generation errors include clearer explanations. Narration already produced is preserved if a later step fails, and failed generations can be retried from the story. * The story view scrolls to the latest entry when requested during generation. * Added a fake AI provider for testing successful responses and failure scenarios. * Story creation no longer waits for background-image generation to finish. * **Bug Fixes** * Stop controls now reflect when generation can no longer be interrupted. * Generation and translation failures are more consistently shown in activity reports. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Tony Frazier <16245649+a-frazier@users.noreply.github.com> |
||
|---|---|---|
| .cargo | ||
| .github | ||
| docs | ||
| scripts | ||
| src | ||
| src-tauri | ||
| static | ||
| third-party-licenses | ||
| .gitattributes | ||
| .gitignore | ||
| .nvmrc | ||
| .prettierrc | ||
| CLAUDE.md | ||
| compileApk.sh | ||
| components.json | ||
| eslint.config.js | ||
| lefthook.yml | ||
| LICENSE.md | ||
| logo.png | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| sun4.jpg | ||
| sun17.jpg | ||
| sun2022.png | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.js | ||
| vitest.config.ts | ||
Aventuras
Interactive fiction with an AI that remembers. Play a text adventure or write collaboratively, on desktop and Android, with any LLM provider you like — cloud or running on your own machine.
Aventuras keeps the story straight: chapters are summarized as you play, a lorebook feeds the right entries into the right scene, an agent tidies that lorebook behind you, and the world state — who is present, where you are, what you carry — is tracked turn by turn.
Highlights
- Two modes — Adventure, with multiple-choice actions and world tracking; Creative Writing, freeform with AI suggestions. First/second/third person, past or present tense.
- Any provider — OpenRouter, OpenAI, Anthropic, Google, xAI, Groq, DeepSeek, Mistral, Z.AI, NanoGPT, Chutes, Pollinations, NVIDIA NIM, plus local llama.cpp, LM Studio and Ollama. Streaming, extended thinking, and per-subsystem Agent Profiles so retrieval, classification and narration can each use a different model.
- Memory that scales — automatic chapter summarization, and a retrieval step that goes and finds what the current scene needs from everything that came before.
- Lorebook — characters, locations, items, factions, concepts and events, with aliases, secrets, keyword and relevance-based injection, SillyTavern import, and an autonomous agent that consolidates duplicates and fills gaps.
- The Vault — a cross-story library of reusable characters, lorebooks and scenarios, with a tool-calling assistant that edits them and shows you a diff before anything lands.
- Every prompt is editable — they are Liquid templates, all of them, in an in-app editor.
- Images — inline
<pic>illustrations, scene backgrounds and character portraits, across nine backends including local ComfyUI and A1111. - Writing tools — local grammar checking (Harper/WASM), style analysis for repetition, suggestions that match how you write.
- Yours to keep — SQLite on your machine, full backup/restore,
.avtstory export, LAN sync between devices over QR pairing, and an optional translation layer over the whole app. - 26 themes, adjustable text size, dialogue highlighting.
Install
Pre-built binaries are on the Releases page:
| Platform | Download |
|---|---|
| Windows | Aventuras_vX.Y.Z_x64-setup.exe |
| macOS | Aventuras_vX.Y.Z_x64.dmg / _aarch64.dmg |
| Linux | Aventuras_vX.Y.Z_amd64.deb / .AppImage, or _x86_64.rpm |
| Android | Aventuras_vX.Y.Z.apk |
| iOS | Aventuras_vX.Y.Z_ios-arm64-unsigned.ipa (sideload; unsigned) |
No API keys in config files — providers are set up in the app, under Settings → API Settings.
Build from source
Requires the Node.js version in .nvmrc, the latest stable Rust, (for Android) the
Android SDK, NDK r27d and JDK 21–24, and (for iOS) a Mac with Xcode.
git clone https://github.com/AventurasTeam/Aventuras.git
cd Aventuras
npm install
npx tauri dev
| Script | Does |
|---|---|
npm run dev |
Vite dev server (frontend only) |
npx tauri dev |
full app, with hot reload |
npm run build |
production build |
npm run check |
type checking (svelte-check) |
npm test |
test suite (Vitest) |
npm run lint |
ESLint — lint:fix to fix |
npm run format |
Prettier |
npm run release |
version bump, tag and push |
Desktop builds are npx tauri build; Android and iOS are documented in
docs/development/release.md. iOS produces an unsigned
device .ipa (no Apple certificates or signing secrets — see
docs/development/ios-build-target.md for the full
account of how the target was added and how the unsigned CI pipeline works).
Tech stack
TypeScript (strict) · SvelteKit 2 · Svelte 5 runes · Tauri 2 (Rust) · Tailwind + shadcn-svelte ·
SQLite (tauri-plugin-sql / sqlx) · Vercel AI SDK · LiquidJS · CodeMirror 6 · Zod ·
Harper.js (WASM) · Vitest
Contributing
Start with docs/ — the architecture is documented per area, and
CLAUDE.md has the conventions. CI runs lint, type-check, tests and a build on every
PR against master, develop or dev.
Acknowledgments
Tauri · SvelteKit · OpenRouter · Harper · Lucide
License
AGPL-3.0