# Standalone desktop companion This directory runs the desktop pet without DeepSeek Harness. It reuses the repository's `public/` renderer and stores imported models and settings in Electron's user-data directory. ## License boundary The standalone source does not distribute Live2D models, `live2dcubismcore.min.js`, Electron binaries, API keys, or third-party character prompts. Supply these items yourself under their respective licenses. ## Setup on Windows 1. Install Node.js 22.12 or later (required by Electron 43.8.3). 2. Obtain `live2dcubismcore.min.js` from Live2D's official distribution and place it in `public/vendor/`. 3. Run `standalone/setup.cmd`, then `standalone/start.cmd`. 4. On first launch, if no model is present, the app shows its model directory and exits. Copy a complete Cubism 4/5 model folder there, then run `standalone/start.cmd` again. `setup.cmd` installs dependencies and then downloads the Electron runtime binary. Electron 42 and later no longer download that binary during `npm install`, so if the download fails on a restricted network, set `ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/` in the same Command Prompt and run `setup.cmd` again. The local server binds to a random `127.0.0.1` port. Mutating browser routes use a random HttpOnly cookie; Codex/OpenCode adapters use a separate per-launch bearer token stored in Electron's user-data directory. ## Codex and OpenCode With the standalone pet running, launch `连接Codex和OpenCode.cmd`, then restart Codex and OpenCode. On first use, follow the installer's instructions to trust the new Codex hooks in `/hooks`. The installer adds lifecycle hooks, the local OpenCode plugin, and a minimal chat-only `live2d-companion` agent. The agent denies tool permissions. Customize its local prompt for the character you use; repeated installs preserve that customized prompt. Advanced users can select another agent with the `L2D_COMPANION_AGENT` environment variable before starting OpenCode. The chat button is enabled only for `?standalone=1`, so existing DSH widget and pet behavior is unchanged. Standalone chat keeps a scrollable history for the current app launch. Each imported model receives a character profile, and one model can have multiple profiles. Open the model panel's **角色** tab to name the character, paste or import a Markdown/TXT persona, import existing diary or memory files, and enable optional auto-save after one minute without another chat reply. Each reply restarts that idle timer; this is not a periodic save during continuous conversation. Profiles live under Electron's user-data directory rather than inside the model folder. Each profile owns its own `persona.md`, indexed `memories/`, and `diaries/` directory, so switching models or profiles does not mix identities or memories. New memories are stored separately, assigned a coarse category, and de-duplicated by a normalized content hash. Existing `memory.md` files remain readable as legacy memory. Manual and automatic diary summaries update one `diary-*.md` file per app launch; imported diary files remain separate. The built-in local memory provider removes common query words, weights longer matches, ranks small chunks against the newest user message, and sends at most four related results (up to 1,200 characters) to OpenCode. Recalled text is explicitly treated as untrusted reference data and is placed before the newest message. The provider boundary is intentionally independent from the OpenCode/Codex adapters so a future plugin or MCP memory backend can be added without making this repository character-specific. Profiles can optionally enable **OpenCode semantic reranking (experimental)**. The bundled OpenCode companion plugin asks the selected OpenCode model to choose up to four items from a bounded local candidate set, then injects only those items into chat. This costs one additional model request when candidates exist. Invalid output, timeouts, disconnection, or plugin errors fall back to the deterministic local result; no third-party memory service is required. Session creation has a five-second deadline and reranking has an eight-second deadline. Cleanup runs separately with bounded requests, so a stalled cleanup cannot delay the fallback. Game commentary, diary summaries, and ordinary chat use separate internal OpenCode sessions. Internal game turns can drive the main thinking state without appearing as extra numbered task lamps. Codex provides status events; OpenCode additionally provides chat, diary/memory summaries and game commentary. Neither connection hosts the DSH web widget, so standalone stays in desktop-pet mode. Games use the local AI; DSH's model-controlled move mode is not available in standalone. ## Troubleshooting - `测试气泡.cmd` checks the authenticated local adapter path. - The model panel can enable CPU rendering when a Windows GPU/driver combination flashes while moving a transparent window. - Keep OpenCode running for chat. Long generations maintain a separate heartbeat while later messages wait in the local queue. Chat generation has a 60-second deadline (diary/memory: 30 seconds; game commentary: 45 seconds). A failed or timed-out turn retires its session and attempts to abort it; subsequent jobs use a new session, and late results are ignored. These are adapter deadlines, separate from the local server's request timeout.