diff --git a/README.md b/README.md index e590ffda..f0825f13 100644 --- a/README.md +++ b/README.md @@ -37,18 +37,21 @@ cheetahclaws # start chatting! Other install methods: [pip install](#alternative-install-with-pip) | [uv install](#alternative-install-with-uv) | [run from source](#alternative-run-directly-from-source-no-install) | [full details](#installation) +> ๐Ÿ–ฅ๏ธ **Prefer a native app?** A desktop build (Electron) wraps the full chat UI in a window โ€” no terminal needed. See [`desktop/`](desktop/README.md). + ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ News (Pacific Time) -- June 16, 2026 (latest): **All internal modules now live under a single `cheetahclaws` package โ€” import as `cheetahclaws.config`, `cheetahclaws.kernel`, โ€ฆ instead of bare `config` / `kernel`.** The old flat top-level layout let generic names (`config`, `daemon`) get shadowed by other things on `sys.path` once the app was *installed* and launched from its entry point โ€” another project's `config/` dir, the PyPI `python-daemon` package โ€” which broke `cheetahclaws` at startup (`ImportError: โ€ฆ from 'config' (unknown location)`). Owning one `cheetahclaws.*` namespace removes that whole class of bug โ€” a prerequisite for shipping as a broadly-installable app. **Breaking only if you import internals directly** (`import kernel` โ†’ `from cheetahclaws import kernel`). A built wheel ships everything under `cheetahclaws/` with no bare top-level modules; full suite green (**2449 passed, 3 skipped**). Details: [docs/news.md](docs/news.md). -- June 6, 2026 (**v3.5.82**): **macOS install reliably puts `cheetahclaws` on PATH, and local Ollama models that emit tool calls as text now actually execute them** (two fixes from issue #131). **(1) Install/PATH on macOS:** the installer `source`s the dedicated venv it creates, which made the post-install `command -v cheetahclaws` check succeed *inside the script's own shell* โ€” so it reported "on PATH" and **skipped the entire rc-file step**, leaving `~/.zshrc` untouched and the binary unreachable in new terminals. It now symlinks only the `cheetahclaws` entry point into `~/.local/bin` (pipx-style, so the venv's `python`/`pip` don't shadow yours), creates `~/.zshrc` / `.bash_profile` if missing, and appends `~/.local/bin` to PATH there โ€” without trusting the venv-polluted `command -v` (`scripts/install.sh`). **(2) Ollama tool calls:** `stream_ollama` only read Ollama's structured `message.tool_calls` field, while the cloud path already recovers calls a model emits as **text**, so Qwen-coder / Gemma / Mistral over Ollama produced "tool-calling-style chat" that streamed as plain text and never ran โ€” the model seemed to "just keep talking." `stream_ollama` now mirrors the cloud path's interceptor: it buffers from the first `` / `<|tool_call|>` / `[TOOL_CALLS]` marker (so raw markup never reaches the user) and parses it into real tool calls at end-of-stream (`providers.py`). Details: [docs/guides/usage.md](docs/guides/usage.md#usage-open-source-models-local) ยท [docs/guides/faq.md](docs/guides/faq.md) ยท [docs/news.md](docs/news.md). -- June 5, 2026 (**v3.5.82**): **User-controllable token/cost budgets** โ€” `/budget $5` / `/budget 200k` / `/budget daily $20` cap spend per session or per day, enforced before each model call; on hit the session auto-saves and you're shown how to `/resume` or raise the cap and continue (warns at โ‰ฅ80%/95%; `--budget` sets it at startup). Details: [docs/guides/features.md](docs/guides/features.md) ยท [docs/news.md](docs/news.md). -- June 5, 2026: **Adaptive Markdown streaming โ€” live output stays correct on every device** by auto-selecting a per-device tier (`live` in-place redraw on capable terminals incl. modern SSH emulators, append-only `commit` for SSH/Apple Terminal/pipes/CJK text so frames never duplicate, `plain` fallback); also ships a visual `/context` usage grid and a 1M context window for `deepseek-v4-flash`. Details: [docs/guides/features.md](docs/guides/features.md) ยท [docs/news.md](docs/news.md). -- June 4, 2026 (**v3.05.81**): **Claude-Code-style quiet output** hides per-tool execution and shows one summary line per turn (on by default), with a live spinner timer + token estimate and a `โœป Worked forโ€ฆ` footer; `/verbose` overrides, toggle with `/quiet`. Details: [docs/guides/features.md](docs/guides/features.md) ยท [docs/news.md](docs/news.md). -- June 4, 2026: **Context-window override** โ€” `/config context_window=` sets the context length that drives the prompt `%`, `/context`, the compaction trigger, and the output cap consistently (distinct from `max_tokens`; read live, no restart). Details: [docs/guides/reference.md](docs/guides/reference.md) ยท [docs/news.md](docs/news.md). -- June 4, 2026: **Rich Live streaming** keeps long responses live via a bounded tail window โ€” redrawing only the most recent screenful and committing the full output when done, fixing duplicate/stale frames (builds on PR #133). Details: [docs/guides/features.md](docs/guides/features.md) ยท [docs/news.md](docs/news.md). -- May 31, 2026: **QQ bot bridge โ€” `/qq` connects cheetahclaws to QQ groups + C2C private chats via the official `qq-botpy` SDK (PR #121).** Details: [docs/guides/bridges.md](docs/guides/bridges.md#qq-bridge) ยท [docs/news.md](docs/news.md). -- May 12, 2026: **Security hardening sweep โ€” env-var bot tokens, web CSRF cookie, terminal session owner-binding, and plugin/MCP/filesystem sandboxing (two CRITICAL + HIGH rounds, 2347 tests green).** Details: [docs/guides/security.md](docs/guides/security.md) ยท [docs/news.md](docs/news.md). -- May 12, 2026: **Daemon foundation roadmap โ€” all nine F-1โ€ฆF-9 items landed: subprocess agent runners, on-crash restart policy, daemonized Telegram/Slack/WeChat bridges, and budget guardrails.** Details: [docs/news.md](docs/news.md). +- June 23, 2026 (latest) (**v3.5.83**): Docs slimmed (README news โ†’ one line each, Atlas 59-model list โ†’ usage.md, FAQ trimmed) and a native **desktop app** (Electron shell wrapping the web UI) added under `desktop/`; version-string format unified to `v3.5.x`. [Details](docs/news.md) +- June 16, 2026: All internal modules now live under a single `cheetahclaws` package (`from cheetahclaws import kernel`), removing `sys.path` name-collision crashes at startup โ€” breaking only if you import internals directly; full suite green (2449 passed). [Details](docs/news.md) +- June 6, 2026 (**v3.5.82**): macOS install now reliably puts `cheetahclaws` on PATH, and local Ollama models that emit tool calls as text now actually execute them (two fixes from #131). [Details](docs/news.md) +- June 5, 2026 (**v3.5.82**): User-controllable token/cost budgets โ€” `/budget $5` / `/budget daily $20` cap spend per session or day, enforced before each model call. [Details](docs/news.md) +- June 5, 2026: Adaptive Markdown streaming keeps live output correct on every device by auto-selecting a per-device tier; also adds a visual `/context` grid and 1M context for `deepseek-v4-flash`. [Details](docs/news.md) +- June 4, 2026 (**v3.5.81**): Claude-Code-style quiet output shows one summary line per turn with a live timer + `โœป Worked forโ€ฆ` footer (`/verbose` / `/quiet` toggle). [Details](docs/news.md) +- June 4, 2026: Context-window override โ€” `/config context_window=` sets the length driving the prompt `%`, `/context`, compaction, and output cap (read live, no restart). [Details](docs/news.md) +- June 4, 2026: Rich Live streaming keeps long responses live via a bounded tail window, fixing duplicate/stale frames (builds on PR #133). [Details](docs/news.md) +- May 31, 2026: QQ bot bridge โ€” `/qq` connects cheetahclaws to QQ groups + C2C private chats via the official `qq-botpy` SDK (PR #121). [Details](docs/news.md) +- May 12, 2026: Security hardening sweep โ€” env-var bot tokens, web CSRF cookie, terminal session owner-binding, and plugin/MCP/filesystem sandboxing (2347 tests green). [Details](docs/news.md) +- May 12, 2026: Daemon foundation roadmap โ€” all nine F-1โ€ฆF-9 items landed (subprocess agent runners, on-crash restart, daemonized bridges, budget guardrails). [Details](docs/news.md) For more news, see [here](docs/news.md). @@ -324,7 +327,7 @@ The name after `custom/` must match the server's `--served-model-name`. For the ### Atlas Cloud (hosted, OpenAI-compatible) -> ๐ŸŽ **[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=cheetahclaws)** is a full-modal AI inference platform with an OpenAI-compatible API โ€” DeepSeek, Qwen, GLM, Kimi, MiniMax and more behind one endpoint. It plugs into the zero-dependency `custom/` adapter: +> ๐ŸŽ **[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=cheetahclaws)** serves DeepSeek, Qwen, GLM, Kimi, MiniMax and more behind one OpenAI-compatible endpoint, via the zero-dependency `custom/` adapter: ```bash export CUSTOM_BASE_URL=https://api.atlascloud.ai/v1 @@ -332,24 +335,7 @@ export CUSTOM_API_KEY=your_atlascloud_api_key cheetahclaws --model custom/deepseek-ai/deepseek-v4-pro ``` -`deepseek-ai/deepseek-v4-pro` is a reasoning model; any other Atlas chat model id works the same way. - -
-All Atlas Cloud chat models (59) - -- **Anthropic (Claude):** `anthropic/claude-haiku-4.5-20251001`, `anthropic/claude-opus-4.8`, `anthropic/claude-sonnet-4.6` -- **OpenAI (GPT):** `openai/gpt-5.4`, `openai/gpt-5.5` -- **Google (Gemini):** `google/gemini-3.1-flash-lite`, `google/gemini-3.1-pro-preview`, `google/gemini-3.5-flash` -- **Qwen:** `qwen/qwen2.5-7b-instruct`, `Qwen/Qwen3-235B-A22B-Instruct-2507`, `qwen/qwen3-235b-a22b-thinking-2507`, `qwen/qwen3-30b-a3b`, `Qwen/Qwen3-30B-A3B-Instruct-2507`, `qwen/qwen3-30b-a3b-thinking-2507`, `qwen/qwen3-32b`, `qwen/qwen3-8b`, `Qwen/Qwen3-Coder`, `qwen/qwen3-coder-next`, `qwen/qwen3-max-2026-01-23`, `Qwen/Qwen3-Next-80B-A3B-Instruct`, `Qwen/Qwen3-Next-80B-A3B-Thinking`, `Qwen/Qwen3-VL-235B-A22B-Instruct`, `qwen/qwen3-vl-235b-a22b-thinking`, `qwen/qwen3-vl-30b-a3b-instruct`, `qwen/qwen3-vl-30b-a3b-thinking`, `qwen/qwen3-vl-8b-instruct`, `qwen/qwen3.5-122b-a10b`, `qwen/qwen3.5-27b`, `qwen/qwen3.5-35b-a3b`, `qwen/qwen3.5-397b-a17b`, `qwen/qwen3.6-35b-a3b`, `qwen/qwen3.6-plus` -- **DeepSeek:** `deepseek-ai/deepseek-ocr`, `deepseek-ai/deepseek-r1-0528`, `deepseek-ai/DeepSeek-V3-0324`, `deepseek-ai/DeepSeek-V3.1`, `deepseek-ai/DeepSeek-V3.1-Terminus`, `deepseek-ai/deepseek-v3.2`, `deepseek-ai/DeepSeek-V3.2-Exp`, `deepseek-ai/deepseek-v4-flash`, `deepseek-ai/deepseek-v4-pro` -- **Moonshot (Kimi):** `moonshotai/Kimi-K2-Instruct`, `moonshotai/Kimi-K2-Instruct-0905`, `moonshotai/Kimi-K2-Thinking`, `moonshotai/kimi-k2.5`, `moonshotai/kimi-k2.6` -- **Zhipu (GLM):** `zai-org/GLM-4.6`, `zai-org/glm-4.7`, `zai-org/glm-5`, `zai-org/glm-5-turbo`, `zai-org/glm-5.1`, `zai-org/glm-5v-turbo` -- **MiniMax:** `MiniMaxAI/MiniMax-M2`, `minimaxai/minimax-m2.1`, `minimaxai/minimax-m2.5`, `minimaxai/minimax-m2.7` -- **xAI:** `xai/grok-4.3` -- **Kwaipilot:** `kwaipilot/kat-coder-pro-v2` -- **Other:** `owl` - -
+> Any Atlas chat model id works the same way โ€” **full list of all 59 models:** [docs/guides/usage.md](docs/guides/usage.md#option-d--atlas-cloud-hosted-openai-compatible). --- @@ -395,7 +381,7 @@ cheetahclaws --web --no-auth # skip login (localhost dev only) Open `http://localhost:/chat` โ€” first account becomes admin. Includes streaming chat (WS) + SSE slash commands, persistent sessions with folders/search/Markdown export, tool cards, inline permission approval, settings panel, light/dark/system theme, and `/health` + `/metrics` endpoints. A full xterm.js PTY terminal lives at `/` (100% CLI parity). -> **Full guide:** [docs/guides/web-ui.md](docs/guides/web-ui.md) ยท **Docker / home server:** [docs/guides/docker.md](docs/guides/docker.md) +> **Full guide:** [docs/guides/web-ui.md](docs/guides/web-ui.md) ยท **Docker / home server:** [docs/guides/docker.md](docs/guides/docker.md) ยท **Native desktop app:** [desktop/README.md](desktop/README.md) --- @@ -408,6 +394,7 @@ Detailed guides live in [`docs/guides/`](docs/guides/) to keep this README focus | [**Features (full)**](docs/guides/features.md) | The complete feature table โ€” every row with full detail (context compression, auto-fanout, themes, Trading/Research/Agents writeups) | | [**Usage (all providers)**](docs/guides/usage.md) | Per-provider setup + example commands: Anthropic/OpenAI/Gemini/Kimi/Qwen/Zhipu/DeepSeek/MiniMax/litellm, and local Ollama/LM Studio/vLLM | | [**Web UI**](docs/guides/web-ui.md) | Chat UI, PTY terminal, API endpoints, settings, auth, SSE streaming | +| [**Desktop app**](desktop/README.md) | Native-window shell (Electron) that wraps the local web UI; build a self-contained `.dmg`/`.exe`/`.AppImage` | | [**Docker / Home Server**](docs/guides/docker.md) | Dockerfile + compose: web UI + bridges in one container, host Ollama, workspace mount | | [**Reference**](docs/guides/reference.md) | CLI, 50+ commands, 33 built-in tools, session search, error classification, tool cache | | [**Extensions**](docs/guides/extensions.md) | Memory, Skills, Sub-Agents, MCP servers, Plugins, Monitor, Autonomous Agents | @@ -486,25 +473,7 @@ CheetahClaws now auto-recovers tool calls that local models emit as **text** (`< **Q: After installing on macOS, `cheetahclaws: command not found` and no `~/.zshrc` was created.** Reload your shell first: `source ~/.zshrc` (zsh) or `source ~/.bash_profile` (bash). The installer creates `~/.zshrc` if missing, symlinks the binary into `~/.local/bin`, and adds it to PATH. If you installed an older version, either re-run the installer or add this line yourself: `echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc`. -**Q: How do I connect to a remote GPU server running vLLM?** -``` -/config custom_base_url=http://your-server-ip:8000/v1 -/config custom_api_key=your-token -/model custom/your-model-name -``` - -**Q: How do I check my API cost?** Run `/cost` (shows input/output tokens + estimated USD). - -**Q: Can I use multiple API keys in one session?** Yes โ€” set all keys upfront (env or `/config`), then switch models freely; each call uses the active provider's key. - -**Q: How do I set a default model across projects?** Add keys to `~/.bashrc`/`~/.zshrc` and set `{ "model": "claude-sonnet-4-6" }` in `~/.cheetahclaws/config.json`. - -**Q: Can I pipe input to cheetahclaws?** -```bash -cat error.log | cheetahclaws -p "What is causing this error?" -``` - -**Q: How do I set up voice input?** `pip install sounddevice faster-whisper numpy`, then `/voice` in the REPL (downloads a ~150 MB Whisper model on first use). See the [full FAQ](docs/guides/faq.md) for languages + keyterm tuning. +More โ€” remote vLLM, API cost (`/cost`), multiple keys per session, default model across projects, piping input, voice setup, garbled-text fixes โ€” are all answered in [docs/guides/faq.md](docs/guides/faq.md). --- diff --git a/cheetahclaws/daemon/discovery.py b/cheetahclaws/daemon/discovery.py index 0be7cc2b..955ad839 100644 --- a/cheetahclaws/daemon/discovery.py +++ b/cheetahclaws/daemon/discovery.py @@ -11,7 +11,7 @@ "transport": "unix" | "tcp", "address": "/run/user/1000/cheetahclaws/daemon.sock" | "127.0.0.1:8765", - "version": "3.05.72", + "version": "3.5.72", "schema": 1 } Atomic write semantics: writes go through a sibling ``.tmp`` file then diff --git a/demos/make_brainstorm_demo.py b/demos/make_brainstorm_demo.py index 9651c9fc..06354f12 100644 --- a/demos/make_brainstorm_demo.py +++ b/demos/make_brainstorm_demo.py @@ -75,7 +75,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_checkpoint_demo.py b/demos/make_checkpoint_demo.py index 848dc36e..a336d46f 100644 --- a/demos/make_checkpoint_demo.py +++ b/demos/make_checkpoint_demo.py @@ -75,7 +75,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_cloudsave_demo.py b/demos/make_cloudsave_demo.py index 10515605..c3bfdcce 100644 --- a/demos/make_cloudsave_demo.py +++ b/demos/make_cloudsave_demo.py @@ -76,7 +76,7 @@ def draw_frame(lines_segments): def banner(machine): return [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Machine: ", SUBTEXT), seg(machine, YELLOW, True)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_image_demo.py b/demos/make_image_demo.py index b3dce798..1cd37569 100644 --- a/demos/make_image_demo.py +++ b/demos/make_image_demo.py @@ -139,7 +139,7 @@ def draw_frame(lines_segments, screenshot=None): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_memory_demo.py b/demos/make_memory_demo.py index 068c55d7..da1fcec9 100644 --- a/demos/make_memory_demo.py +++ b/demos/make_memory_demo.py @@ -76,7 +76,7 @@ def draw_frame(lines_segments): def banner(session_label, date_str): return [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True), seg(f" {session_label}", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Session: ", SUBTEXT), seg(date_str, YELLOW)], diff --git a/demos/make_multimodel_demo.py b/demos/make_multimodel_demo.py index 4d8944e0..c6a5ebaf 100644 --- a/demos/make_multimodel_demo.py +++ b/demos/make_multimodel_demo.py @@ -94,7 +94,7 @@ def model_color(name): def make_banner(model, provider): col = model_color(model) return [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg(model, col, True), seg(f" ({provider})", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], diff --git a/demos/make_plan_demo.py b/demos/make_plan_demo.py index 2195cc09..02d6c711 100644 --- a/demos/make_plan_demo.py +++ b/demos/make_plan_demo.py @@ -75,7 +75,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], @@ -84,7 +84,7 @@ def draw_frame(lines_segments): ] BANNER_PLAN = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("plan", MAUVE, True), seg(" [PLAN MODE โ€” read only]", MAUVE)], diff --git a/demos/make_proactive_demo.py b/demos/make_proactive_demo.py index 3fcfdc1b..00ad2648 100644 --- a/demos/make_proactive_demo.py +++ b/demos/make_proactive_demo.py @@ -75,7 +75,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_shell_escape_demo.py b/demos/make_shell_escape_demo.py index 90409241..70224e2e 100644 --- a/demos/make_shell_escape_demo.py +++ b/demos/make_shell_escape_demo.py @@ -75,7 +75,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_subagent_demo.py b/demos/make_subagent_demo.py index 0bdc1cb5..0c42cf97 100644 --- a/demos/make_subagent_demo.py +++ b/demos/make_subagent_demo.py @@ -76,7 +76,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_tmux_demo.py b/demos/make_tmux_demo.py index a12bfe6f..cfee65b7 100644 --- a/demos/make_tmux_demo.py +++ b/demos/make_tmux_demo.py @@ -76,7 +76,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_video_demo.py b/demos/make_video_demo.py index 2816a4ba..fdc3a43e 100644 --- a/demos/make_video_demo.py +++ b/demos/make_video_demo.py @@ -179,7 +179,7 @@ def _draw_video_preview(img, d): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_voice_demo.py b/demos/make_voice_demo.py index 26686e18..a48ad1a4 100644 --- a/demos/make_voice_demo.py +++ b/demos/make_voice_demo.py @@ -90,7 +90,7 @@ def draw_frame(lines_segments, waveform_data=None): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/demos/make_worker_demo.py b/demos/make_worker_demo.py index e89c5d35..bcf86e44 100644 --- a/demos/make_worker_demo.py +++ b/demos/make_worker_demo.py @@ -75,7 +75,7 @@ def draw_frame(lines_segments): # โ”€โ”€ Reusable line builders โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ BANNER = [ - [seg("โ•ญโ”€ CheetahClaws v3.05.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], + [seg("โ•ญโ”€ CheetahClaws v3.5.5 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ", SUBTEXT)], [seg("โ”‚ ", SUBTEXT), seg("Model: ", SUBTEXT), seg("claude-sonnet-4-6", CYAN, True)], [seg("โ”‚ ", SUBTEXT), seg("Permissions: ", SUBTEXT), seg("auto", YELLOW)], [seg("โ”‚ Type /help for commands, Ctrl+C to cancel โ”‚", SUBTEXT)], diff --git a/desktop/.gitignore b/desktop/.gitignore new file mode 100644 index 00000000..24fc23da --- /dev/null +++ b/desktop/.gitignore @@ -0,0 +1,9 @@ +node_modules/ +out/ +dist/ +build/ +server/dist/ +server/build/ +.build-venv/ +*.log +.DS_Store diff --git a/desktop/README.md b/desktop/README.md new file mode 100644 index 00000000..4828e128 --- /dev/null +++ b/desktop/README.md @@ -0,0 +1,143 @@ +# CheetahClaws Desktop (P1 MVP) + +A thin native-window shell around CheetahClaws' existing, production-ready web +UI. It launches `cheetahclaws --web --no-auth` as a localhost-only **sidecar** +and points a webview at its `/chat` page โ€” so the browser UI (WebSocket +streaming chat, xterm terminal, permission approval, themes) *becomes* the +desktop app, with nothing reimplemented. + +``` +โ”Œโ”€ Desktop shell (Electron) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ loading.html โ†’ spawn `cheetahclaws --web --no-auth` โ”‚ +โ”‚ (127.0.0.1, auto-picked free port) โ”‚ +โ”‚ โ†“ parse the printed "Chat UI: โ€ฆ/chat" โ”‚ +โ”‚ BrowserWindow.loadURL(http://127.0.0.1:/chat) โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +The server binds to `127.0.0.1` only and runs as you, with your own API key โ€” +no network exposure, no multi-tenancy. This is the local, bring-your-own-key +model; the hard SaaS problems (sandboxing, billing) are deliberately out of +scope for P1. + +## Status + +- โœ… **Runs end-to-end on macOS** โ€” the Electron shell launches the server, + discovers its port, and loads the chat UI in a native window. +- โœ… **Sidecar integration verified** โ€” `npm run smoke` launches the real + server, discovers its port, and confirms `/chat`, `/`, `/health` all serve. +- โœ… **Self-contained server verified** โ€” `scripts/build-server.sh` freezes the + server with PyInstaller into a ~95 MB standalone binary that serves the full + web UI with **no Python installed**; the sidecar drives it identically. So a + packaged installer needs neither Node nor Python on the user's machine. +- โ›๏ธ **Remaining for a shippable installer:** code signing / notarization (see + open items) โ€” everything else is wired and tested. + +## Prerequisites + +- **Node.js 18+** and npm. +- The **`cheetahclaws` CLI on your PATH, with the web extra**: + ```bash + pip install 'cheetahclaws[web]' + cheetahclaws --version # should print a version + ``` + (Point at a different binary with `CHEETAHCLAWS_BIN=/path/to/cheetahclaws`.) + +## Run + +```bash +cd desktop +npm install # pulls Electron (~150 MB first time) +npm start # opens the window +``` + +Verify just the sidecar wiring (no GUI, no Electron needed): + +```bash +npm run smoke # DEBUG=1 npm run smoke to echo server logs +``` + +## Troubleshooting `npm install` / `npm start` + +The Electron npm package only downloads its ~90 MB binary in a `postinstall` +script. On hardened-npm setups (`allow-scripts`), very new Node versions, or +slow/blocked networks, that step misbehaves. Symptoms and fixes: + +- **`Electron failed to install correctly`** โ€” the binary didn't download or + `path.txt` wasn't written. First make sure the binary is present, using a + China-friendly mirror: + ```bash + rm -rf node_modules/electron ~/Library/Caches/electron # (Linux: ~/.cache/electron) + ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ \ + npm install electron --foreground-scripts + npm run fix-electron # writes the correct path.txt + npm start + ``` +- **`spawn .../dist/dist/Electron.app/... ENOENT` (double `dist`)** โ€” `path.txt` + has a stray `dist/` prefix. `npm run fix-electron` rewrites it correctly + (Electron expects the path *relative to* `dist/`). +- **Extraction left a tiny/partial `dist/`** โ€” download the full zip yourself + from (match your platform + arch, + e.g. `electron-vXX-darwin-arm64.zip`), unzip into `node_modules/electron/dist/`, + then `npm run fix-electron`. +- **macOS "Electron is damaged / cannot be verified"** โ€” clear the quarantine + flag on the dev binary: `xattr -dr com.apple.quarantine node_modules/electron/dist/Electron.app`. +- **Node version** โ€” Electron 31 is happiest on an LTS Node (18/20). Bleeding-edge + Node has been seen to skip writing `path.txt`; `npm run fix-electron` papers + over that, or use `nvm use 20`. + +None of this affects **end users** โ€” a packaged `.dmg`/`.exe`/`.AppImage` +(below) bundles Electron, so installers never hit the postinstall path. + +## Build a self-contained installer (.dmg / .exe / .AppImage) + +This produces an installer that bundles **both** Electron and a +PyInstaller-frozen copy of the server, so the **end user needs neither Node nor +Python** โ€” they just double-click. + +```bash +cd desktop +bash scripts/build-app.sh +# โ†’ out/ contains the .dmg (macOS) / .exe (Windows) / .AppImage (Linux) +``` + +What it does, in order: + +1. **`scripts/build-server.sh`** โ€” freezes `cheetahclaws --web` with PyInstaller + in a *clean* virtualenv (only the core + `[web]` deps, so the bundle is + ~95 MB, not GBs โ€” the trading/voice/research stacks aren't installed and the + modular loaders skip them gracefully). Output: + `server/dist/cheetahclaws-server/`. +2. **`electron-builder`** (`npm run dist`) โ€” packages the Electron shell and + copies the frozen server into the app's `Resources/server/` (see + `build.extraResources`). At runtime `src/main.js` spawns + `Resources/server/cheetahclaws-server` when packaged, falling back to the + global `cheetahclaws` CLI in dev. + +> **PyInstaller does not cross-compile** โ€” run `build-app.sh` *on each target +> OS*: a Mac to get the `.dmg`, Windows to get the `.exe`. (The whole server + +> sidecar pipeline is verified on Linux; only the per-OS packaging differs.) + +## Known open items (next steps) + +1. **Code signing + notarization.** macOS Gatekeeper / Windows SmartScreen will + block an unsigned build (users get "damaged / unverified developer"). Needs + an Apple Developer cert (`CSC_LINK`/`CSC_KEY_PASSWORD` + `notarize` in + electron-builder) and a Windows code-signing cert. Paid prerequisite for + public distribution โ€” the only thing between `build-app.sh` and a + shippable installer. +2. **First-run onboarding.** A GUI provider/API-key step (the CLI's setup + wizard, as a screen) โ€” the main lever for reaching non-CLI users. +3. **Auto-update.** Wire electron-updater (or Tauri's updater) so users don't + stay pinned to old builds. +4. **Slim the server further (optional).** 95 MB is fine; if you want smaller, + `strip`/UPX the binary or prune more stdlib via the spec's `excludes`. + +## Why Electron here (and Tauri later) + +This MVP is Electron because it only needs Node, which let the sidecar +integration be **actually run and verified** on the dev box (no Rust toolchain +was available). For the *shipped* product, **Tauri** is the better target โ€” a +~5 MB Rust shell vs Electron's ~150 MB โ€” and the sidecar logic in +[`src/sidecar.js`](src/sidecar.js) is intentionally framework-agnostic so it +ports across with only the window code rewritten. diff --git a/desktop/assets/icon.png b/desktop/assets/icon.png new file mode 100644 index 00000000..6e635527 Binary files /dev/null and b/desktop/assets/icon.png differ diff --git a/desktop/assets/make_icon.py b/desktop/assets/make_icon.py new file mode 100644 index 00000000..efad626a --- /dev/null +++ b/desktop/assets/make_icon.py @@ -0,0 +1,57 @@ +import math, numpy as np +from PIL import Image, ImageDraw, ImageFilter + +S = 2048 # supersample, downscale to 1024 at the end +img = Image.new("RGBA", (S, S), (0, 0, 0, 0)) + +# โ”€โ”€ rounded-square background with a subtle vertical gradient โ”€โ”€ +ys = np.linspace(0, 1, S)[:, None] +top = np.array([26, 34, 50]); bot = np.array([10, 14, 20]) +col = (top[None, :] * (1 - ys) + bot[None, :] * ys) # (S,3) +grad = np.broadcast_to(col[:, None, :], (S, S, 3)).astype("uint8") +gimg = Image.fromarray(grad, "RGB").convert("RGBA") +margin = int(S * 0.055); radius = int(S * 0.225) +mask = Image.new("L", (S, S), 0) +ImageDraw.Draw(mask).rounded_rectangle([margin, margin, S - margin, S - margin], + radius, fill=255) +bg = Image.new("RGBA", (S, S), (0, 0, 0, 0)) +bg.paste(gimg, (0, 0), mask) +img = Image.alpha_composite(img, bg) + +# โ”€โ”€ three tapered, slightly-curved claw slashes โ”€โ”€ +def blade(cx, cy, length, maxw, curve, angle_deg): + a = math.radians(angle_deg); L, R = [], [] + for i in range(61): + t = i / 60 + px = curve * math.sin(math.pi * t) + py = (t - 0.5) * length + w = maxw * (math.sin(math.pi * t) ** 0.65) # pointed ends, fat middle + for xx, store in ((px - w / 2, L), (px + w / 2, R)): + rx = xx * math.cos(a) - py * math.sin(a) + ry = xx * math.sin(a) + py * math.cos(a) + store.append((cx + rx, cy + ry)) + return L + R[::-1] + +claw = Image.new("RGBA", (S, S), (0, 0, 0, 0)) +cd = ImageDraw.Draw(claw) +cx0, cy0 = S * 0.5, S * 0.52 +specs = [(-0.145, 0.86, 16), (0.0, 1.0, 9), (0.145, 0.86, 2)] # (x-offset frac, len-scale, tilt) +for dx, ls, tilt in specs: + poly = blade(cx0 + dx * S, cy0, S * 0.52 * ls, S * 0.115, S * 0.05, tilt) + cd.polygon(poly, fill=(240, 136, 62, 255)) # brand orange + # inner highlight + poly2 = blade(cx0 + dx * S, cy0 - S * 0.015, S * 0.46 * ls, S * 0.055, S * 0.05, tilt) + cd.polygon(poly2, fill=(255, 190, 120, 255)) + +# soft glow under the claws +glow = claw.filter(ImageFilter.GaussianBlur(S * 0.012)) +img = Image.alpha_composite(img, glow) +img = Image.alpha_composite(img, claw) +# clip claws to the rounded square +out = Image.new("RGBA", (S, S), (0, 0, 0, 0)) +out.paste(img, (0, 0), mask) + +icon = out.resize((1024, 1024), Image.LANCZOS) +icon.save("assets/icon.png") +icon.resize((256, 256), Image.LANCZOS).save("/tmp/icon_preview.png") +print("wrote assets/icon.png (1024x1024) + /tmp/icon_preview.png") diff --git a/desktop/package-lock.json b/desktop/package-lock.json new file mode 100644 index 00000000..0212819b --- /dev/null +++ b/desktop/package-lock.json @@ -0,0 +1,4113 @@ +{ + "name": "cheetahclaws-desktop", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cheetahclaws-desktop", + "version": "0.1.0", + "license": "Apache-2.0", + "devDependencies": { + "electron": "^31.0.0", + "electron-builder": "^24.13.3" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "31.7.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.7.7.tgz", + "integrity": "sha512-HZtZg8EHsDGnswFt0QeV8If8B+et63uD6RJ7I4/xhcXqmTIbI08GoubX/wm+HdY0DwcuPe1/xsgqpmYvjdjRoA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^20.9.0", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/isbinaryfile": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.4.tgz", + "integrity": "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/desktop/package.json b/desktop/package.json new file mode 100644 index 00000000..ea08a6ce --- /dev/null +++ b/desktop/package.json @@ -0,0 +1,51 @@ +{ + "name": "cheetahclaws-desktop", + "productName": "CheetahClaws", + "version": "0.1.0", + "private": true, + "description": "Desktop shell for CheetahClaws \u2014 wraps the local web UI in a native window", + "author": "SafeRL-Lab", + "license": "Apache-2.0", + "main": "src/main.js", + "scripts": { + "start": "electron .", + "smoke": "node test/sidecar.smoke.js", + "fix-electron": "node scripts/fix-electron.mjs", + "dist": "electron-builder" + }, + "devDependencies": { + "electron": "^31.0.0", + "electron-builder": "^24.13.3" + }, + "build": { + "appId": "ai.saferl.cheetahclaws", + "productName": "CheetahClaws", + "files": [ + "src/**/*", + "assets/**/*" + ], + "extraResources": [ + { + "from": "server/dist/cheetahclaws-server", + "to": "server" + } + ], + "directories": { + "output": "out" + }, + "mac": { + "target": "dmg", + "category": "public.app-category.developer-tools", + "icon": "assets/icon.png" + }, + "win": { + "target": "nsis", + "icon": "assets/icon.png" + }, + "linux": { + "target": "AppImage", + "category": "Development", + "icon": "assets/icon.png" + } + } +} diff --git a/desktop/scripts/build-app.sh b/desktop/scripts/build-app.sh new file mode 100755 index 00000000..ccec8ee0 --- /dev/null +++ b/desktop/scripts/build-app.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Build a self-contained desktop installer: freeze the Python server, then +# package the Electron shell around it with electron-builder. +# +# Produces, in desktop/out/: +# macOS โ†’ .dmg / .app Windows โ†’ .exe (NSIS) +# Linux โ†’ .AppImage (per the build.* targets in package.json) +# +# PyInstaller does not cross-compile โ€” run this ON the OS you want to ship for. +# End users of the result need neither Node nor Python. +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DESKTOP="$(cd "$HERE/.." && pwd)" + +echo "==> [1/3] Freeze the Python server (PyInstaller, clean venv)" +bash "$HERE/build-server.sh" + +echo "" +echo "==> [2/3] Install Electron build deps" +cd "$DESKTOP" +npm install + +echo "" +echo "==> [3/3] Package the installer (electron-builder)" +npm run dist + +echo "" +echo "โœ“ Done. Installers in: $DESKTOP/out/" +ls -1 "$DESKTOP/out" 2>/dev/null | grep -iE '\.(dmg|exe|appimage|deb|zip)$' || true diff --git a/desktop/scripts/build-server.sh b/desktop/scripts/build-server.sh new file mode 100755 index 00000000..4ae616fc --- /dev/null +++ b/desktop/scripts/build-server.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Freeze `cheetahclaws --web` into a standalone server binary with PyInstaller. +# +# Builds in a CLEAN virtualenv that has only the core + [web] runtime deps โ€” +# NOT your dev environment's kitchen sink โ€” so the bundle stays lean (the +# trading/voice/research stacks and their heavy deps simply aren't present; +# the modular loaders degrade gracefully at runtime when they're absent). +# +# PyInstaller does not cross-compile: run this ON each target OS (macOS for the +# .app, Windows for the .exe). Output: desktop/server/dist/cheetahclaws-server/ +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$HERE/../.." && pwd)" +SERVER_DIR="$(cd "$HERE/../server" && pwd)" +VENV="${CC_BUILD_VENV:-$HERE/../.build-venv}" +PY="${PYTHON:-python3}" + +echo "โ†’ creating clean build venv: $VENV" +rm -rf "$VENV" +"$PY" -m venv "$VENV" +"$VENV/bin/pip" install -q --upgrade pip + +echo "โ†’ installing cheetahclaws[web] (core + web deps only)" +"$VENV/bin/pip" install -q -e "$REPO_ROOT[web]" +"$VENV/bin/pip" install -q pyinstaller + +echo "โ†’ freezing server (PyInstaller)" +cd "$SERVER_DIR" +rm -rf build dist +"$VENV/bin/pyinstaller" cheetahclaws-server.spec --noconfirm --log-level WARN + +echo "" +echo "โœ“ built: $SERVER_DIR/dist/cheetahclaws-server/" +du -sh "$SERVER_DIR/dist/cheetahclaws-server" diff --git a/desktop/scripts/fix-electron.mjs b/desktop/scripts/fix-electron.mjs new file mode 100644 index 00000000..dbf34230 --- /dev/null +++ b/desktop/scripts/fix-electron.mjs @@ -0,0 +1,53 @@ +#!/usr/bin/env node +// Repair a half-installed Electron โ€” writes node_modules/electron/path.txt +// when the binary was extracted but the pointer file is missing/wrong. +// +// Why this exists: on very new Node versions Electron's postinstall has been +// observed to extract dist/ but never write path.txt, so `electron .` throws +// "Electron failed to install correctly" even though the binary is right +// there. Hardened-npm setups (allow-scripts) and CN networks make the normal +// postinstall flaky too. This script is the deterministic last-mile fix. +// +// node scripts/fix-electron.mjs (run via: npm run fix-electron) + +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const elDir = path.resolve(here, '..', 'node_modules', 'electron'); +const distDir = path.join(elDir, 'dist'); + +// index.js resolves the binary as path.join(__dirname, 'dist', ), +// so path.txt must be RELATIVE TO dist/ โ€” no leading "dist/". +const REL = { + darwin: 'Electron.app/Contents/MacOS/Electron', + win32: 'electron.exe', + linux: 'electron', +}[process.platform] || 'electron'; + +if (!fs.existsSync(distDir)) { + console.error(`โœ— ${distDir} is missing โ€” Electron's binary was never extracted.`); + console.error(' Reinstall it (CN mirror recommended):'); + console.error(' rm -rf node_modules/electron ~/Library/Caches/electron'); + console.error(' ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ \\'); + console.error(' npm install electron --foreground-scripts'); + console.error(' then re-run: npm run fix-electron'); + process.exit(1); +} + +const binary = path.join(distDir, REL); +if (!fs.existsSync(binary)) { + console.error(`โœ— extracted dist/ exists but the binary is missing at dist/${REL}`); + console.error(' The extraction looks incomplete โ€” re-download the full zip:'); + console.error(' https://npmmirror.com/mirrors/electron/ (pick your platform/arch)'); + console.error(' unzip it into node_modules/electron/dist/, then re-run this.'); + process.exit(1); +} + +const pathFile = path.join(elDir, 'path.txt'); +const current = fs.existsSync(pathFile) ? fs.readFileSync(pathFile, 'utf8') : ''; +fs.writeFileSync(pathFile, REL); +console.log(`โœ“ wrote node_modules/electron/path.txt = "${REL}"`); +if (current !== REL) console.log(` (was: "${current}")`); +console.log(' Electron should now launch: npm start'); diff --git a/desktop/server/cheetahclaws-server.spec b/desktop/server/cheetahclaws-server.spec new file mode 100644 index 00000000..826fee37 --- /dev/null +++ b/desktop/server/cheetahclaws-server.spec @@ -0,0 +1,77 @@ +# -*- mode: python ; coding: utf-8 -*- +# PyInstaller spec โ€” freeze `cheetahclaws --web` into a standalone server +# binary that the desktop app ships and spawns (no Python on the user's box). +# +# Build: pyinstaller desktop/server/cheetahclaws-server.spec --noconfirm +# Output: dist/cheetahclaws-server/ (onedir; the exe + _internal/) + +import os +from PyInstaller.utils.hooks import collect_all + +# The repo root holds the real cheetahclaws/ package dir. Put it on the +# analysis path so PyInstaller resolves submodules by FILE rather than via the +# editable-install meta-path finder (which it can't follow โ€” that yields a +# binary missing all of cheetahclaws). SPECPATH = this spec's dir. +REPO_ROOT = os.path.abspath(os.path.join(SPECPATH, '..', '..')) + +# Pull in ALL of the cheetahclaws package: every submodule (it's full of +# dynamic imports โ€” tool registry, plugin/modular loaders, bridges) and its +# data files (web/ html+js+css, prompts/*.md, agent_templates/*.md). +datas, binaries, hiddenimports = collect_all('cheetahclaws') + +# Heavy, optional stacks. The web server + agent never need them, and the +# modular loaders already degrade gracefully when they're absent ("could not +# load modular.X"). Excluding keeps the bundle from ballooning into the GBs +# (torch alone is ~2 GB). +EXCLUDES = [ + 'torch', 'torchvision', 'torchaudio', 'transformers', + 'sklearn', 'scipy', 'lightgbm', 'xgboost', 'pandas', + 'matplotlib', 'seaborn', + 'faster_whisper', 'whisper', 'sounddevice', 'soundfile', + 'PIL', 'moviepy', 'imageio', 'imageio_ffmpeg', 'cv2', + 'IPython', 'notebook', 'jupyter', 'jupyter_core', + 'tkinter', 'PyQt5', 'PyQt6', 'PySide2', 'PySide6', +] + +a = Analysis( + ['launch_server.py'], + pathex=[REPO_ROOT], + binaries=binaries, + datas=datas, + hiddenimports=hiddenimports, + hookspath=[], + runtime_hooks=[], + excludes=EXCLUDES, + noarchive=False, + optimize=0, +) + +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='cheetahclaws-server', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=False, + console=True, # it's a server โ€” stdout carries the readiness line + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, # build host arch; build on each target OS + codesign_identity=None, + entitlements_file=None, +) + +coll = COLLECT( + exe, + a.binaries, + a.datas, + strip=False, + upx=False, + upx_exclude=[], + name='cheetahclaws-server', +) diff --git a/desktop/server/launch_server.py b/desktop/server/launch_server.py new file mode 100644 index 00000000..434009d6 --- /dev/null +++ b/desktop/server/launch_server.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Frozen entry point for the bundled CheetahClaws web server. + +PyInstaller freezes this into a standalone binary that the desktop app spawns +as its sidecar. It just hands off to the normal CLI ``main()`` โ€” the app passes +``--web --no-auth --host 127.0.0.1``, so this serves the exact same web UI as +``cheetahclaws --web``, with **no Python install required** on the user's +machine. +""" +import multiprocessing +import sys + + +def main() -> int: + # No-op unless something forks via multiprocessing; required for frozen + # apps that might, and harmless otherwise. + multiprocessing.freeze_support() + from cheetahclaws.cli import main as cli_main + return cli_main() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/desktop/src/loading.html b/desktop/src/loading.html new file mode 100644 index 00000000..b59df297 --- /dev/null +++ b/desktop/src/loading.html @@ -0,0 +1,37 @@ + + + + + + CheetahClaws + + + +
+
+
Starting CheetahClawsโ€ฆ
+
launching the local server
+
+ + diff --git a/desktop/src/main.js b/desktop/src/main.js new file mode 100644 index 00000000..0622e4d5 --- /dev/null +++ b/desktop/src/main.js @@ -0,0 +1,145 @@ +'use strict'; + +// CheetahClaws desktop shell (Electron). +// +// Architecture: this process owns a single BrowserWindow. On launch it shows a +// loading page, spawns the existing `cheetahclaws --web --no-auth` server as a +// localhost-only sidecar (see sidecar.js), then points the webview at that +// server's /chat URL โ€” so the production-ready web UI *is* the desktop app, no +// reimplementation. The server is bound to 127.0.0.1 and runs as the local +// user (bring-your-own API key); nothing is exposed to the network. + +const { app, BrowserWindow, dialog, shell } = require('electron'); +const path = require('path'); +const { startSidecar } = require('./sidecar'); + +let mainWindow = null; +let sidecar = null; + +// Where to find the CheetahClaws server: +// - $CHEETAHCLAWS_BIN wins (explicit override, handy for dev). +// - A packaged app ships the PyInstaller-frozen server under Resources/server +// (see build/extraResources) โ€” no Python needed on the user's machine. +// - In dev (npm start) we fall back to the pip-installed `cheetahclaws` CLI. +function resolveServerCommand() { + if (process.env.CHEETAHCLAWS_BIN) return process.env.CHEETAHCLAWS_BIN; + if (app.isPackaged) { + const exe = process.platform === 'win32' + ? 'cheetahclaws-server.exe' : 'cheetahclaws-server'; + return path.join(process.resourcesPath, 'server', exe); + } + return 'cheetahclaws'; +} + +async function createWindow() { + mainWindow = new BrowserWindow({ + width: 1100, + height: 800, + minWidth: 720, + minHeight: 480, + backgroundColor: '#0b0f14', + title: 'CheetahClaws', + autoHideMenuBar: true, + icon: path.join(__dirname, '..', 'assets', 'icon.png'), + webPreferences: { + // The window loads our own localhost server; keep Node out of the + // renderer and isolate contexts (Electron security defaults). + contextIsolation: true, + nodeIntegration: false, + }, + }); + + // Show something immediately while the server boots (cold start is ~1s). + await mainWindow.loadFile(path.join(__dirname, 'loading.html')); + + try { + sidecar = await startSidecar({ + command: resolveServerCommand(), + onLog: (line) => console.log('[cheetahclaws]', line), + }); + } catch (err) { + return showFatal(err); + } + console.log('[desktop] server ready at', sidecar.url); + + if (mainWindow && !mainWindow.isDestroyed()) { + await mainWindow.loadURL(sidecar.url); + } + + // If the server dies while the app is open, say so instead of going blank. + sidecar.child.on('exit', (code, signal) => { + if (app.isQuitting) return; + showFatal(new Error( + `The CheetahClaws server stopped unexpectedly (code=${code}, signal=${signal}).`)); + }); +} + +function showFatal(err) { + console.error('[desktop] fatal:', err); + const msg = String((err && err.message) || err); + if (mainWindow && !mainWindow.isDestroyed()) { + const html = ` +
+

Couldn't start CheetahClaws

+

${escapeHtml(msg)}

+

Make sure the CLI is installed and on your PATH: + pip install 'cheetahclaws[web]'

+
`; + mainWindow.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html)); + } else { + dialog.showErrorBox('CheetahClaws', msg); + app.quit(); + } +} + +function escapeHtml(s) { + return s.replace(/[&<>"']/g, (c) => + ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); +} + +// Open target=_blank / external links in the system browser, never a new +// Electron window. +app.on('web-contents-created', (_e, contents) => { + contents.setWindowOpenHandler(({ url }) => { + if (/^https?:/i.test(url)) { shell.openExternal(url); return { action: 'deny' }; } + return { action: 'deny' }; + }); +}); + +// Single instance โ€” a second launch focuses the existing window. +if (!app.requestSingleInstanceLock()) { + app.quit(); +} else { + app.on('second-instance', () => { + if (mainWindow) { + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.focus(); + } + }); + + app.whenReady().then(createWindow); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); + + app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit(); + }); + + // Tear down the sidecar when the app quits (SIGTERM; the OS reaps it). + app.on('before-quit', () => { + app.isQuitting = true; + if (sidecar && sidecar.child) { + try { sidecar.child.kill('SIGTERM'); } catch (_) { /* already gone */ } + } + }); +} diff --git a/desktop/src/sidecar.js b/desktop/src/sidecar.js new file mode 100644 index 00000000..a7e8f039 --- /dev/null +++ b/desktop/src/sidecar.js @@ -0,0 +1,127 @@ +'use strict'; + +// Sidecar manager โ€” launch the existing `cheetahclaws --web` server as a +// child process, discover the port it bound, and own its lifecycle. +// +// Deliberately framework-agnostic (plain Node, no Electron import) so it can +// be unit-smoke-tested without a GUI, and so the exact same logic can be +// lifted into a Tauri (Rust) shell later โ€” only the window code differs. + +const { spawn } = require('child_process'); +const readline = require('readline'); + +// The server prints its ready line to stdout with an explicit flush, e.g.: +// Chat UI: http://localhost:8771/chat +// We treat the appearance of that URL as the readiness signal and pull the +// port straight out of it (the server may auto-pick a free port). +const READY_RE = /https?:\/\/(?:localhost|127\.0\.0\.1):(\d+)\/chat/i; + +/** + * Start the CheetahClaws web server as a sidecar. + * Resolves once the server is listening, with { child, port, url, stop }. + * + * @param {object} [opts] + * @param {string} [opts.command] Executable to run (default: $CHEETAHCLAWS_BIN or "cheetahclaws"). + * @param {string[]} [opts.args] Args (default: --web --no-auth --host 127.0.0.1). + * @param {string} [opts.host] Host to build the URL with (default: 127.0.0.1). + * @param {number} [opts.readyTimeoutMs] How long to wait for the ready line (default: 30000). + * @param {(line:string)=>void} [opts.onLog] Called for every server log line. + */ +function startSidecar(opts = {}) { + const { + command = process.env.CHEETAHCLAWS_BIN || 'cheetahclaws', + args = ['--web', '--no-auth', '--host', '127.0.0.1'], + host = '127.0.0.1', + readyTimeoutMs = 30000, + onLog = () => {}, + } = opts; + + return new Promise((resolve, reject) => { + // The server refuses to boot when CHEETAHCLAWS_WEB_SERVER=1 (its recursion + // guard against `alias cheetahclaws='cheetahclaws --web'`). Hand the child + // a clean env so a shell alias can't make the desktop app fail to launch. + const env = { ...process.env }; + delete env.CHEETAHCLAWS_WEB_SERVER; + + let child; + try { + child = spawn(command, args, { + env, + stdio: ['ignore', 'pipe', 'pipe'], + windowsHide: true, // don't flash a console window on Windows + }); + } catch (err) { + return reject(new Error(`failed to launch "${command}": ${err.message}`)); + } + + let settled = false; + + const timer = setTimeout(() => { + fail(new Error(`server did not become ready within ${readyTimeoutMs}ms`)); + }, readyTimeoutMs); + + function fail(err) { + if (settled) return; + settled = true; + clearTimeout(timer); + try { child.kill('SIGKILL'); } catch (_) { /* already gone */ } + reject(err); + } + + function succeed(port) { + if (settled) return; + settled = true; + clearTimeout(timer); + resolve({ + child, + port, + url: `http://${host}:${port}/chat`, + stop: () => stopChild(child), + }); + } + + function scan(line) { + onLog(line); + const m = READY_RE.exec(line); + if (m) succeed(Number(m[1])); + } + + // The ready line goes to stdout, but watch stderr too in case logging is + // reconfigured โ€” either way we only act on the chat-URL pattern. + readline.createInterface({ input: child.stdout }).on('line', scan); + readline.createInterface({ input: child.stderr }).on('line', scan); + + child.on('error', (err) => + fail(new Error(`failed to launch "${command}": ${err.message}`))); + child.on('exit', (code, signal) => + fail(new Error(`server exited before becoming ready (code=${code}, signal=${signal})`))); + }); +} + +/** + * Stop a sidecar child gracefully (SIGTERM, then SIGKILL after a grace + * period). Resolves once the process is gone. Safe to call more than once. + */ +function stopChild(child) { + return new Promise((resolve) => { + if (!child || child.exitCode !== null || child.signalCode) return resolve(); + + let done = false; + const finish = () => { if (!done) { done = true; resolve(); } }; + + child.once('exit', finish); + try { + child.kill('SIGTERM'); + } catch (_) { + return finish(); + } + + // Escalate if it doesn't shut down promptly. + const kill = setTimeout(() => { + if (!done) { try { child.kill('SIGKILL'); } catch (_) { /* gone */ } } + }, 3000); + if (kill.unref) kill.unref(); + }); +} + +module.exports = { startSidecar, stopChild, READY_RE }; diff --git a/desktop/test/sidecar.smoke.js b/desktop/test/sidecar.smoke.js new file mode 100644 index 00000000..8a2fce11 --- /dev/null +++ b/desktop/test/sidecar.smoke.js @@ -0,0 +1,45 @@ +'use strict'; + +// Smoke test for the sidecar manager โ€” no Electron, no GUI required. +// Launches the real `cheetahclaws --web --no-auth`, waits for readiness, +// hits the served endpoints, then shuts the server down. +// +// node test/sidecar.smoke.js (DEBUG=1 to echo server logs) +// +// Requires the `cheetahclaws` CLI on PATH with the web extra installed: +// pip install 'cheetahclaws[web]' + +const http = require('http'); +const { startSidecar, stopChild } = require('../src/sidecar'); + +function get(url) { + return new Promise((resolve, reject) => { + const req = http.get(url, (res) => { res.resume(); resolve(res.statusCode); }); + req.on('error', reject); + req.setTimeout(5000, () => req.destroy(new Error('request timeout'))); + }); +} + +(async () => { + console.log('โ†’ starting sidecar: cheetahclaws --web --no-auth --host 127.0.0.1'); + const sc = await startSidecar({ + readyTimeoutMs: 30000, + onLog: (l) => process.env.DEBUG && console.log(' |', l), + }); + console.log(`โ†’ ready at ${sc.url} (port ${sc.port})`); + + try { + for (const ep of ['/chat', '/', '/health']) { + const code = await get(`http://127.0.0.1:${sc.port}${ep}`); + console.log(` GET ${ep.padEnd(8)} -> ${code}`); + if (code !== 200) throw new Error(`expected 200 for ${ep}, got ${code}`); + } + console.log('โœ… SMOKE PASS โ€” shell can launch the server and reach the chat UI'); + } finally { + await stopChild(sc.child); + console.log('โ†’ sidecar stopped'); + } +})().catch((err) => { + console.error('โŒ SMOKE FAIL โ€”', err.message); + process.exit(1); +}); diff --git a/docs/guides/advanced.md b/docs/guides/advanced.md index 46e6e294..201e2202 100644 --- a/docs/guides/advanced.md +++ b/docs/guides/advanced.md @@ -59,7 +59,7 @@ Generating diverse perspectives... - Brainstorm uses the **currently selected model** (`/model` to check). A capable model (Claude Sonnet/Opus, GPT-4o, or a large local model) gives the best results. - With many agents (20+) the session can take several minutes depending on model speed. - Install `faker` (`pip install faker`) for randomized persona names; falls back to built-in names otherwise. -- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.05.5. +- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.5.5. - Long responses keep rendering live but show only the most recent screenful (a bounded tail window) until they finish, so duplicate/stale lines are prevented automatically. If output still looks garbled in SSH (repeated lines), run `/config rich_live=false` to fully disable Rich Live streaming. --- @@ -317,7 +317,7 @@ Output prints inline and control returns to the CheetahClaws prompt immediately. ## Proactive Background Monitoring -CheetahClaws v3.05.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. +CheetahClaws v3.5.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. ### Quick start @@ -687,7 +687,7 @@ Resume a specific file:
Cloud Sync: /cloudsave on desktop โ†’ encrypted upload โ†’ /cloudload on laptop โ†’ full session restored
-CheetahClaws v3.05.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. +CheetahClaws v3.5.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. ### Setup (one-time) @@ -815,7 +815,7 @@ cheetahclaws/ โ”œโ”€โ”€ video/ # Video package โ€” backward-compat shim โ†’ modular/video/ โ”‚ โ””โ”€โ”€ __init__.py # Re-exports from modular.video.* โ”‚ -โ”œโ”€โ”€ modular/ # Plug-and-play module ecosystem (v3.05.55) +โ”œโ”€โ”€ modular/ # Plug-and-play module ecosystem (v3.5.55) โ”‚ โ”œโ”€โ”€ __init__.py # Auto-discovery registry: load_all_commands(), load_all_tools(), list_modules() โ”‚ โ”œโ”€โ”€ base.py # HasCommandDefs / HasToolDefs Protocol interface docs โ”‚ โ”œโ”€โ”€ voice/ # Voice submodule (self-contained) @@ -834,7 +834,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ images.py # Image backends: Gemini Web โ†’ web-search โ†’ placeholder โ”‚ โ””โ”€โ”€ subtitles.py # PIL subtitle renderer + text-to-SRT conversion โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Public API exports โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # File-level backup, snapshot persistence, rewind, cleanup diff --git a/docs/guides/bridges.md b/docs/guides/bridges.md index 5768b2ae..c81938c4 100644 --- a/docs/guides/bridges.md +++ b/docs/guides/bridges.md @@ -289,7 +289,7 @@ If `wechat_token` is set in `~/.cheetahclaws/config.json`, the bridge starts aut Also auto-starts in `cheetahclaws --web` (Docker / headless deployments). -### Smart-reply panel (v3.05.78+) +### Smart-reply panel (v3.5.78+) When a whitelisted contact sends an inbound message, the auxiliary cheap model drafts 3 candidate replies and pushes a panel to your diff --git a/docs/guides/reference.md b/docs/guides/reference.md index 17879269..670e5832 100644 --- a/docs/guides/reference.md +++ b/docs/guides/reference.md @@ -54,7 +54,7 @@ Type `/` and press **Tab** to see all commands with descriptions. Continue typin | `/model` | Show current model + list all available models | | `/model ` | Switch model (takes effect immediately) | | `/config` | Show all current config values | -| `/config key=value` | Set a config value (persisted to disk). v3.05.78+ parses JSON values: `["a","b"]`, `{"k":"v"}`, signed numbers, quoted strings โ€” list/dict configs no longer get silently saved as literal strings. | +| `/config key=value` | Set a config value (persisted to disk). v3.5.78+ parses JSON values: `["a","b"]`, `{"k":"v"}`, signed numbers, quoted strings โ€” list/dict configs no longer get silently saved as literal strings. | | `/config context_window=` | Override the context window (tokens) for the session. `0` = use the model's default. Drives the prompt `%` indicator, `/context`, the compaction trigger, **and** the per-call output-token cap โ€” all consistently. Distinct from `max_tokens` (which is the **output** cap, not the window). Bidirectional: a smaller value forces earlier compaction; a larger value corrects a stale default. Read live, so it takes effect on the next prompt (no restart). Warns if set above the model's real window (that would disable compaction and the API may reject oversized prompts). | | `/config stream_mode=` | Force the Markdown streaming tier: `live` (full in-place Rich redraw), `commit` (append-only progressive Markdown โ€” safe over SSH / Apple Terminal / pipes), or `plain` (raw tokens). Unset = auto-detected per device (`ui.render.auto_stream_mode`). Legacy `/config rich_live=true\|false` still works (`true`โ†’`live`, `false`โ†’`commit`). | | `/save` | Save session (auto-named by timestamp) | diff --git a/docs/guides/research-lab.md b/docs/guides/research-lab.md index 1d53e75a..3a11e958 100644 --- a/docs/guides/research-lab.md +++ b/docs/guides/research-lab.md @@ -416,7 +416,7 @@ A previous run's reports stay in `~/.cheetahclaws/research_papers/`. then halts; it does **not** kill mid-stage. Use `/lab abort ` for that. -### Output paths (v3.05.78+) +### Output paths (v3.5.78+) Reports save to a **human-readable directory** instead of the cryptic `lab_/` form: @@ -469,7 +469,7 @@ Warning: Reviewers span only 1 model family; homogeneous review OpenAI / Gemini / DeepSeek / Qwen) for diversity. ``` -### Surveyor grounding (v3.05.78+) +### Surveyor grounding (v3.5.78+) Before invoking the surveyor LLM, the orchestrator now runs `research.aggregator.research()` against `topic + selected_RQ` @@ -491,7 +491,7 @@ To get real grounding, set at least one web-search key: /config brave_api_key=BSA... # https://api.search.brave.com (free 2000/mo) ``` -### Verifier hard timeout (v3.05.78+) +### Verifier hard timeout (v3.5.78+) The citation verifier used to occasionally hang for 11+ minutes when arxiv / Semantic Scholar returned a slow-loris socket (urllib's socket diff --git a/docs/guides/usage.md b/docs/guides/usage.md index 527438d7..5bdf4be0 100644 --- a/docs/guides/usage.md +++ b/docs/guides/usage.md @@ -326,3 +326,32 @@ cheetahclaws --web --no-auth --port 8080 --model custom/qwen2.5-72b ``` If you skip `--model`, the Chat UI uses whatever was previously saved (it will **not** silently fall back to a default). Switch models on the fly from the Chat UI's Settings panel or with `/model custom/` in the message box. The model name after `custom/` must match the vLLM `--served-model-name` exactly. + +### Option D โ€” Atlas Cloud (hosted, OpenAI-compatible) + +๐ŸŽ **[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=cheetahclaws)** is a full-modal AI inference platform with an OpenAI-compatible API โ€” DeepSeek, Qwen, GLM, Kimi, MiniMax and more behind one endpoint. It plugs into the zero-dependency `custom/` adapter: + +```bash +export CUSTOM_BASE_URL=https://api.atlascloud.ai/v1 +export CUSTOM_API_KEY=your_atlascloud_api_key +cheetahclaws --model custom/deepseek-ai/deepseek-v4-pro +``` + +`deepseek-ai/deepseek-v4-pro` is a reasoning model; any other Atlas chat model id works the same way. + +
+All Atlas Cloud chat models (59) + +- **Anthropic (Claude):** `anthropic/claude-haiku-4.5-20251001`, `anthropic/claude-opus-4.8`, `anthropic/claude-sonnet-4.6` +- **OpenAI (GPT):** `openai/gpt-5.4`, `openai/gpt-5.5` +- **Google (Gemini):** `google/gemini-3.1-flash-lite`, `google/gemini-3.1-pro-preview`, `google/gemini-3.5-flash` +- **Qwen:** `qwen/qwen2.5-7b-instruct`, `Qwen/Qwen3-235B-A22B-Instruct-2507`, `qwen/qwen3-235b-a22b-thinking-2507`, `qwen/qwen3-30b-a3b`, `Qwen/Qwen3-30B-A3B-Instruct-2507`, `qwen/qwen3-30b-a3b-thinking-2507`, `qwen/qwen3-32b`, `qwen/qwen3-8b`, `Qwen/Qwen3-Coder`, `qwen/qwen3-coder-next`, `qwen/qwen3-max-2026-01-23`, `Qwen/Qwen3-Next-80B-A3B-Instruct`, `Qwen/Qwen3-Next-80B-A3B-Thinking`, `Qwen/Qwen3-VL-235B-A22B-Instruct`, `qwen/qwen3-vl-235b-a22b-thinking`, `qwen/qwen3-vl-30b-a3b-instruct`, `qwen/qwen3-vl-30b-a3b-thinking`, `qwen/qwen3-vl-8b-instruct`, `qwen/qwen3.5-122b-a10b`, `qwen/qwen3.5-27b`, `qwen/qwen3.5-35b-a3b`, `qwen/qwen3.5-397b-a17b`, `qwen/qwen3.6-35b-a3b`, `qwen/qwen3.6-plus` +- **DeepSeek:** `deepseek-ai/deepseek-ocr`, `deepseek-ai/deepseek-r1-0528`, `deepseek-ai/DeepSeek-V3-0324`, `deepseek-ai/DeepSeek-V3.1`, `deepseek-ai/DeepSeek-V3.1-Terminus`, `deepseek-ai/deepseek-v3.2`, `deepseek-ai/DeepSeek-V3.2-Exp`, `deepseek-ai/deepseek-v4-flash`, `deepseek-ai/deepseek-v4-pro` +- **Moonshot (Kimi):** `moonshotai/Kimi-K2-Instruct`, `moonshotai/Kimi-K2-Instruct-0905`, `moonshotai/Kimi-K2-Thinking`, `moonshotai/kimi-k2.5`, `moonshotai/kimi-k2.6` +- **Zhipu (GLM):** `zai-org/GLM-4.6`, `zai-org/glm-4.7`, `zai-org/glm-5`, `zai-org/glm-5-turbo`, `zai-org/glm-5.1`, `zai-org/glm-5v-turbo` +- **MiniMax:** `MiniMaxAI/MiniMax-M2`, `minimaxai/minimax-m2.1`, `minimaxai/minimax-m2.5`, `minimaxai/minimax-m2.7` +- **xAI:** `xai/grok-4.3` +- **Kwaipilot:** `kwaipilot/kat-coder-pro-v2` +- **Other:** `owl` + +
diff --git a/docs/i18n/README.CN.MD b/docs/i18n/README.CN.MD index ca88ae63..cac51408 100644 --- a/docs/i18n/README.CN.MD +++ b/docs/i18n/README.CN.MD @@ -87,7 +87,7 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM ่ทจๆธ ้“็š„ๅฝ’ไธ€ๅŒ–็”ฑ `tools/interaction.py` ไธ‰ไธช็บฏๅ‡ฝๆ•ฐๅฎŒๆˆ:`_format_menu_block(options)`(ๆธฒๆŸ“็ผ–ๅท่œๅ•ๆ–‡ๆœฌ)ใ€`_build_value_map(options)`(ๆ•ฐๅญ— + ่ง„่Œƒๅ€ผ + label ่ฏ็š„ๆŸฅๆ‰พ่กจ,ๅ†ฒ็ชๆ—ถ first-write-wins)ใ€`_resolve_choice(raw, value_map)`(ๅŽป็ฉบ็™ฝ / ๅคงๅฐๅ†™ไธๆ•ๆ„Ÿ / ๆœช็Ÿฅ่พ“ๅ…ฅ็›ด้€š,่ฟ™ๆ ท callers ็”จ `options=` ๅŒๆ—ถไนŸๆƒณๆŽฅๆ”ถ่‡ช็”ฑๆ–‡ๆœฌๆ—ถไป็„ถ work)ใ€‚ๅฎŒๅ…จๅ‘ๅŽๅ…ผๅฎน:ๆ—ขๆœ‰ๆ‰€ๆœ‰ `ask_input_interactive` ่ฐƒ็”จๆ–น(`/checkpoint`ใ€`/session`ใ€`/agent`ใ€`/config`ใ€`/voice` ็ญ‰)้ƒฝๆฒกไผ  `options=`,่กŒไธบ้›ถๅ˜ๅŒ–ใ€‚`RuntimeContext` ๆ–ฐๅญ—ๆฎต:`tg_callback_prompt_id: str`ใ€`tg_callback_message_id: int`ใ€‚ - **ๆต‹่ฏ•** โ€”โ€” ๆ–ฐๅขž 49 ไธช pytest ็”จไพ‹ใ€‚`tests/test_telegram_bridge.py`(27 ไธช):`urllib.request.urlopen` ไธŽ `_tg_api` ๅ…จ็จ‹ mock,`threading.Thread` ๆ›ฟๆขไธบๅŒๆญฅ stub,็ซฏๅˆฐ็ซฏ็”ฑๅทฅไฝœ็บฟ็จ‹่ท‘ `ask_input_interactive(options=โ€ฆ)`ใ€ไธป็บฟ็จ‹้€š่ฟ‡ `_handle_callback_query` ๆจกๆ‹Ÿ็‚นๅ‡ปใ€ๆ–ญ่จ€ๅทฅไฝœ็บฟ็จ‹่ฟ”ๅ›ž็‚นๅ‡ปๅ€ผใ€‚่ฆ†็›–ๆ–‡ๆœฌๅˆ‡็‰‡+Markdown ๅ›ž้€€ใ€multipart body ๅญ—ๆฎตๆ–ญ่จ€ใ€`_tg_send_document` ๅ…ญๆกๅคฑ่ดฅ่ทฏๅพ„ใ€`_bg_runner` Write ่‡ชๅŠจๅ‘้€ๅ››็งๅ˜ไฝ“ใ€`_tg_send_keyboard` ๅ››ๆก่ทฏๅพ„ใ€`_handle_callback_query` ไบ”ๆก่ทฏๅพ„ใ€็ซฏๅˆฐ็ซฏ็‚นๅ‡ปไธค็งๅ€ผใ€‚`tests/test_options_menu.py`(22 ไธช):ไธ‰ไธช็บฏๅ‡ฝๆ•ฐ(emoji-stripped label tokensใ€ๅคงๅฐๅ†™ไธๆ•ๆ„Ÿใ€็ฉบ็™ฝๅค„็†ใ€้˜ฒๅพกๆ€ง้žๅญ—็ฌฆไธฒใ€ๅ†ฒ็ช first-write-wins)+ Slack(4 ็งๅ›žๅค)/ WeChat(2 ็งๅ›žๅค)/ ็ปˆ็ซฏ(ๆ•ฐๅญ— / label / ่ง„่Œƒๅ€ผ / ไธไผ  options ็š„ๅ›žๅฝ’)็ซฏๅˆฐ็ซฏใ€‚ๅฎŒๆ•ดๅฅ—ไปถ **718 passed in 43s**,ๆ—ขๆœ‰ 669 ไธชๆต‹่ฏ•้›ถๅ›žๅฝ’ใ€‚ -- 2026 ๅนด 4 ๆœˆ 7 ๆ—ฅ๏ผˆ**v3.05.53**๏ผ‰๏ผš**Telegram ๅ›พ็‰‡/่ฏญ้Ÿณๆ”ฏๆŒใ€Bash ่ถ…ๆ—ถๆ—ถ่ฟ›็จ‹ๆ ‘็ปˆๆญขใ€Windows shell ๆ็คบใ€worker ไฟฎๅค** +- 2026 ๅนด 4 ๆœˆ 7 ๆ—ฅ๏ผˆ**v3.5.53**๏ผ‰๏ผš**Telegram ๅ›พ็‰‡/่ฏญ้Ÿณๆ”ฏๆŒใ€Bash ่ถ…ๆ—ถๆ—ถ่ฟ›็จ‹ๆ ‘็ปˆๆญขใ€Windows shell ๆ็คบใ€worker ไฟฎๅค** - **Telegram ๅ›พ็‰‡่ง†่ง‰ๆ”ฏๆŒ** โ€”โ€” ๅ‘ Telegram ๆกฅๅ‘้€ๅ›พ็‰‡ๅŽ๏ผŒCheetahClaws ไผšไฝฟ็”จๅฝ“ๅ‰ๆฟ€ๆดป็š„่ง†่ง‰ๆจกๅž‹๏ผˆGPT-4oใ€Gemini 2.0 Flashใ€Claude ็ญ‰๏ผ‰ๅฏนๅ›พ็‰‡่ฟ›่กŒๆ่ฟฐใ€‚ๆœบๅ™จไบบไผšไธ‹่ฝฝๆœ€้ซ˜ๅˆ†่พจ็އ็‰ˆๆœฌ๏ผŒๅฐ†ๅ…ถ็ผ–็ ไธบ Base64๏ผŒๅนถ้€š่ฟ‡ไธŽ `/img` ็›ธๅŒ็š„ `_pending_image` ่ทฏๅพ„่ฟ›่กŒๅค„็†ใ€‚ๅ›พ็‰‡ๆ ‡้ข˜ๆ–‡ๆœฌ๏ผˆๆˆ–้ป˜่ฎค็š„ โ€œdescribe this imageโ€ ๆ็คบ๏ผ‰ไผšไธŽๅ›พ็‰‡ไธ€่ตท่ฝฌๅ‘ใ€‚ - **Telegram ่ฏญ้Ÿณ/้Ÿณ้ข‘ STT** โ€”โ€” ๅ‘ Telegram ๆกฅๅ‘้€่ฏญ้Ÿณๆถˆๆฏๆˆ–้Ÿณ้ข‘ๆ–‡ไปถๆ—ถ๏ผŒCheetahClaws ไผš่‡ชๅŠจ่ฝฌๅ†™ใ€‚OGG ่ฏญ้Ÿณไผš้€š่ฟ‡ `ffmpeg` ่ฝฌไธบ PCM ๅนถไผ ็ป™ๆœฌๅœฐ Whisper ๅŽ็ซฏ๏ผ›ๅฆ‚ๆžœ `ffmpeg` ไธๅฏ็”จ๏ผŒๅˆ™ๅ›ž้€€ๅˆฐ OpenAI Whisper APIใ€‚่ฝฌๅ†™็ป“ๆžœไผšๅ…ˆๅ›žๆ˜พๅˆฐ่Šๅคฉไธญ๏ผŒๅ†ไฝœไธบๆŸฅ่ฏขๆไบคใ€‚ - **Bash ่ถ…ๆ—ถๆ—ถ็ปˆๆญขๆ•ดไธช่ฟ›็จ‹ๆ ‘** โ€”โ€” ๅฝ“ `Bash` ๅ‘ฝไปค่ถ…ๆ—ถๆ—ถ๏ผŒCheetahClaws ็Žฐๅœจไผš็ปˆๆญขๆ•ดไธชๅญ่ฟ›็จ‹ๆ ‘๏ผŒ่€Œไธๆ˜ฏๅชๆ€ๆމ shell ๆœฌ่บซใ€‚ๅœจ Unix ไธŠ๏ผŒ`os.killpg` ไผšๅ‘่ฟ›็จ‹็ป„ๅ‘้€ `SIGKILL`๏ผ›ๅœจ Windows ไธŠ๏ผŒ`taskkill /F /T` ไผš็ปˆๆญขๆ‰€ๆœ‰ๅญ่ฟ›็จ‹ใ€‚Agent ๅฏๅŠจ็š„ GUI ๅบ”็”จ๏ผˆๅฆ‚ PyQt ๆธธๆˆ๏ผ‰ๅœจ่ถ…ๆ—ถๅŽไนŸไธไผšๅ†็•™ไธ‹ๅƒตๅฐธ่ฟ›็จ‹ใ€‚ๅ†…้ƒจๅฎž็Žฐไธบไฟ่ฏ็บฟ็จ‹ๅฎ‰ๅ…จ๏ผŒไฝฟ็”จ `start_new_session=True` ไปฃๆ›ฟไบ† `preexec_fn=os.setsid`ใ€‚ @@ -96,20 +96,20 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM - **Bash ่ถ…ๆ—ถๆ็คบ** โ€”โ€” `Bash` ๅทฅๅ…ท่ฏดๆ˜Ž็Žฐๅœจๅปบ่ฎฎๆจกๅž‹ๅฏน่พƒๆ…ขๅ‘ฝไปค๏ผˆ`npm install`ใ€`npx`ใ€`pip install`ใ€ๆž„ๅปบ็ญ‰๏ผ‰ไฝฟ็”จ `timeout=120โ€“300`๏ผŒไปŽ่€Œๅ‡ๅฐ‘ๅŒ…ๅฎ‰่ฃ…็ฑปๆ“ไฝœไธŠ่ฏฏ่งฆๅ‘็š„ 30 ็ง’่ถ…ๆ—ถใ€‚ - **Bug ไฟฎๅค๏ผšๅŽๅฐไบ‹ไปถๆ็คบๆ˜พ็คบ็œŸๅฎž cwd** โ€”โ€” ๅŽๅฐไบ‹ไปถๅฎŒๆˆๅŽๆ‰“ๅฐ็š„้ป„่‰ฒ้‡ๆ–ฐๆ็คบไน‹ๅ‰่ขซ็กฌ็ผ–็ ไธบ `[claude-code-local]`๏ผ›็Žฐๅœจไผšๆ˜พ็คบ็œŸๅฎž็š„ๅทฅไฝœ็›ฎๅฝ•ๅ๏ผˆ`[{cwd.name}]`๏ผ‰๏ผŒไธŽไธป REPL ๆ็คบไฟๆŒไธ€่‡ดใ€‚ -- 2026 ๅนด 4 ๆœˆ 6 ๆ—ฅ๏ผˆ**v3.05.53**๏ผ‰๏ผš**Telegram ไบคไบ’่œๅ•ใ€`/img` ๅˆซๅใ€`/voice device`ใ€OpenAI/Gemini ่ง†่ง‰ๆ”ฏๆŒ** +- 2026 ๅนด 4 ๆœˆ 6 ๆ—ฅ๏ผˆ**v3.5.53**๏ผ‰๏ผš**Telegram ไบคไบ’่œๅ•ใ€`/img` ๅˆซๅใ€`/voice device`ใ€OpenAI/Gemini ่ง†่ง‰ๆ”ฏๆŒ** - **ไฟฎๅค Telegram ไบคไบ’่œๅ•** โ€”โ€” ๅธฆไบคไบ’่พ“ๅ…ฅ็š„ๆ–œๆ ๅ‘ฝไปค๏ผˆๅฆ‚ `/ollama`ใ€`/permission`ใ€`/checkpoint`๏ผ‰ไน‹ๅ‰ไผš้˜ปๅกž Telegram ่ฝฎ่ฏขๅพช็Žฏ๏ผŒๅฏผ่‡ดๆ— ๆณ•ๅ›žๅค่œๅ•ๆ็คบใ€‚็Žฐๅœจๆ–œๆ ๅ‘ฝไปคไผšๅƒๆ™ฎ้€šๆŸฅ่ฏขไธ€ๆ ทๅœจๅฎˆๆŠค็บฟ็จ‹ไธญ่ฟ่กŒ๏ผŒไปŽ่€ŒไฟๆŒ่ฝฎ่ฏขๅพช็Žฏ็ฉบ้—ฒใ€‚ๆ‰€ๆœ‰ไบคไบ’่œๅ•๏ผˆ`ask_input_interactive`๏ผ‰้ƒฝๅฏไปฅๅœจ Telegram ไธŠๆญฃๅธธๅทฅไฝœใ€‚ - **`/img` ๅˆซๅ** โ€”โ€” `/img` ็Žฐๅœจๆ˜ฏ `/image` ็š„ๅˆซๅ๏ผŒไพฟไบŽๆ›ดๅฟซ็š„ๅ‰ช่ดดๆฟๅ›พ็‰‡ๅทฅไฝœๆตใ€‚ - **`/voice device`** โ€”โ€” ๆ–ฐๅญๅ‘ฝไปค๏ผŒ็”จไบŽๅˆ—ๅ‡บๆ‰€ๆœ‰ๅฏ็”จ่พ“ๅ…ฅ้บฆๅ…‹้ฃŽๅนถไปฅไบคไบ’ๆ–นๅผ้€‰ๆ‹ฉไธ€ไธชใ€‚้€‰ไธญ็š„่ฎพๅค‡็ดขๅผ•ไผšๆŒไน…ๅŒ–ๅˆฐไผš่ฏ้…็ฝฎไธญ๏ผŒๅนถๆ˜พ็คบๅœจ `/voice status` ไธญใ€‚ๅฏนๆœ‰ๅคšไธช้Ÿณ้ข‘ๆŽฅๅฃ็š„็ณป็ปŸ๏ผˆๅฆ‚ USB ่€ณๆœบ + ๅ†…็ฝฎ้บฆๅ…‹้ฃŽ๏ผ‰ๅพˆๆœ‰็”จใ€‚ - **OpenAI / Gemini ๆจกๅž‹็š„่ง†่ง‰ๆ”ฏๆŒ** โ€”โ€” `/img`๏ผˆไปฅๅŠ `/image`๏ผ‰็Žฐๅœจ้™คไบ†ๅทฒๆœ‰็š„ Ollama ๅŽŸ็”Ÿๆ ผๅผๅค–๏ผŒไนŸไผšๅฐ†ๅ›พ็‰‡ไปฅ OpenAI multipart `image_url` ๆ ผๅผๅ‘้€็ป™ไบ‘็ซฏ่ง†่ง‰ๆจกๅž‹๏ผˆGPT-4oใ€Gemini 2.0 Flash ็ญ‰๏ผ‰ใ€‚ๆ— ้œ€ๆ”น้…็ฝฎโ€”โ€”็ณป็ปŸไผšๆ นๆฎๅฝ“ๅ‰ provider ่‡ชๅŠจ้€‰ๆ‹ฉๆญฃ็กฎๆ ผๅผใ€‚ - **Bug ไฟฎๅค๏ผš็บฟ็จ‹็ซžๆ€ๆกไปถ** โ€”โ€” `_in_telegram_turn` ็Žฐๅœจ้€š่ฟ‡ๆฏไธชๆ–œๆ ๆ‰ง่กŒ็บฟ็จ‹็š„ `threading.local()` ่ทŸ่ธช๏ผŒ่€Œไธๆ˜ฏๅ…ฑไบซ้…็ฝฎ้”ฎ๏ผŒไปŽ่€Œๆถˆ้™คไบ†ๅฝ“ๅธธ่ง„ๆถˆๆฏๅœจไบคไบ’ๅผๆ–œๆ ๅ‘ฝไปค็ญ‰ๅพ…่พ“ๅ…ฅๆ—ถๅˆฐ่พพๆ‰€ๅฏผ่‡ด็š„็ซžๆ€้—ฎ้ข˜ใ€‚ -- 2026 ๅนด 4 ๆœˆ 6 ๆ—ฅ๏ผˆ**v3.05.52**๏ผ‰๏ผš**Checkpoint ็ณป็ปŸใ€่ฎกๅˆ’ๆจกๅผใ€compact ไธŽๅฎž็”จๅ‘ฝไปคใ€ๆ”ฏๆŒ MiniMax ๆจกๅž‹ใ€ไฟฎๅค Telegram bug** +- 2026 ๅนด 4 ๆœˆ 6 ๆ—ฅ๏ผˆ**v3.5.52**๏ผ‰๏ผš**Checkpoint ็ณป็ปŸใ€่ฎกๅˆ’ๆจกๅผใ€compact ไธŽๅฎž็”จๅ‘ฝไปคใ€ๆ”ฏๆŒ MiniMax ๆจกๅž‹ใ€ไฟฎๅค Telegram bug** - **Checkpoint ็ณป็ปŸ**๏ผˆ`checkpoint/` ๅŒ…๏ผ‰๏ผšๆฏ่ฝฎๅŽ่‡ชๅŠจๅฟซ็…งๅฏน่ฏ็Šถๆ€ๅ’Œๆ–‡ไปถๅ˜ๆ›ดใ€‚`/checkpoint` ๅˆ—ๅ‡บๆ‰€ๆœ‰ๅฟซ็…ง๏ผ›`/checkpoint ` ๅฏๅฐ†ๆ–‡ไปถไธŽๅฏน่ฏๅކๅฒๅŒๆ—ถๅ›žๆปšๅˆฐไปปๆ„ไน‹ๅ‰็Šถๆ€๏ผ›`/checkpoint clear` ๅˆ ้™คๅฝ“ๅ‰ไผš่ฏ็š„ๆ‰€ๆœ‰ๅฟซ็…งใ€‚`/rewind` ๆ˜ฏๅˆซๅใ€‚ไฝฟ็”จ 100 ไธชๅฟซ็…ง็š„ๆป‘ๅŠจ็ช—ๅฃ๏ผ›ไผš่ฏๅฏๅŠจๆ—ถๆ•่Žทๅˆๅง‹ๅฟซ็…งใ€‚่Š‚ๆต็ญ–็•ฅ๏ผš่‹ฅๆ— ไปปไฝ•ๅ˜ๅŒ–ๅˆ™่ทณ่ฟ‡ใ€‚ๆ–‡ไปถๅค‡ไปฝไฝฟ็”จ copy-on-write๏ผ›ๅฟซ็…งๆ•่Žท็š„ๆ˜ฏ็ผ–่พ‘ๅŽ็š„็Šถๆ€ใ€‚ - **่ฎกๅˆ’ๆจกๅผ**๏ผš`/plan ` ่ฟ›ๅ…ฅๅช่ฏปๅˆ†ๆžๆจกๅผ โ€”โ€” Claude ๅช่ƒฝ่ฏปๅ–ไปฃ็ ๅบ“๏ผŒๅนถๅชๅ…่ฎธๅ†™ๅ…ฅไธ“็”จ่ฎกๅˆ’ๆ–‡ไปถ๏ผˆ`.nano_claude/plans/.md`๏ผ‰ใ€‚ๅ…ถไป–ๆ‰€ๆœ‰ๅ†™ๆ“ไฝœ้ƒฝไผš่ขซ้™้ป˜้˜ปๆญขๅนถๆ˜พ็คบๅ‹ๅฅฝๆ็คบใ€‚`/plan` ๆ˜พ็คบๅฝ“ๅ‰่ฎกๅˆ’๏ผ›`/plan done` ้€€ๅ‡บ่ฎกๅˆ’ๆจกๅผๅนถๆขๅคๅŽŸๆƒ้™๏ผ›`/plan status` ๆ˜พ็คบ่ฎกๅˆ’ๆจกๅผๆ˜ฏๅฆๆฟ€ๆดปใ€‚ไธคไธชๆ–ฐ็š„ Agent ๅทฅๅ…ท โ€”โ€” `EnterPlanMode` ไธŽ `ExitPlanMode` โ€”โ€” ๅ…่ฎธ Claude ๅœจๅคๆ‚ๅคšๆ–‡ไปถไปปๅŠกไธญ่‡ชไธป่ฟ›ๅ…ฅๅ’Œ้€€ๅ‡บ่ฎกๅˆ’ๆจกๅผ๏ผ›ๅœจๆ‰€ๆœ‰ๆƒ้™ๆจกๅผไธ‹้ƒฝไผš่‡ชๅŠจๆ‰นๅ‡†ใ€‚ - **`/compact [focus]`**๏ผšๅฏ้šๆ—ถๆ‰‹ๅŠจ่งฆๅ‘ๅฏน่ฏๅŽ‹็ผฉใ€‚ๅฏ้€‰็š„ focus ๅญ—็ฌฆไธฒๅฏๅผ•ๅฏผ LLM ๆ€ป็ป“ๅ™จไฟ็•™ๅ“ชไบ›ไธŠไธ‹ๆ–‡ใ€‚่‡ชๅŠจๅŽ‹็ผฉไธŽๆ‰‹ๅŠจๅŽ‹็ผฉ้ƒฝไผšๅœจๅŽ‹็ผฉๅŽๆขๅค่ฎกๅˆ’ๆ–‡ไปถไธŠไธ‹ๆ–‡ใ€‚ - **ๅฎž็”จๅ‘ฝไปค**๏ผš`/init` ไผšๅœจๅฝ“ๅ‰็›ฎๅฝ•ๅˆ›ๅปบ `CLAUDE.md` ๆจกๆฟ๏ผ›`/export [filename]` ๅฏๅฐ†ๅฏน่ฏๅฏผๅ‡บไธบ Markdown๏ผˆ้ป˜่ฎค๏ผ‰ๆˆ– JSON๏ผ›`/copy` ๅฏๅฐ†ไธŠไธ€ๆก assistant ๅ›žๅคๅคๅˆถๅˆฐๅ‰ช่ดดๆฟ๏ผˆWindows/macOS/Linux๏ผ‰๏ผ›`/status` ๆ˜พ็คบ็‰ˆๆœฌใ€ๆจกๅž‹ใ€providerใ€ๆƒ้™ใ€session IDใ€token ไฝฟ็”จ้‡ไธŽไธŠไธ‹ๆ–‡ๅ ๆฏ”๏ผ›`/doctor` ็”จไบŽ่ฏŠๆ–ญๅฎ‰่ฃ…ๅฅๅบท็Šถๅ†ต๏ผˆPython ็‰ˆๆœฌใ€gitใ€API key ไธŽๅฎžๆ—ถ่ฟžๆŽฅๆต‹่ฏ•ใ€ๅฏ้€‰ไพ่ต–ใ€CLAUDE.md ๆ˜ฏๅฆๅญ˜ๅœจใ€checkpoint ็ฃ็›˜ๅ ็”จใ€ๆƒ้™ๆจกๅผ๏ผ‰ใ€‚ -- 2026 ๅนด 4 ๆœˆ 6 ๆ—ฅ๏ผˆ**v3.05.51**๏ผ‰๏ผš**้กน็›ฎไปŽ Nano Claude Code ้‡ๅ‘ฝๅไธบ CheetahClaws** +- 2026 ๅนด 4 ๆœˆ 6 ๆ—ฅ๏ผˆ**v3.5.51**๏ผ‰๏ผš**้กน็›ฎไปŽ Nano Claude Code ้‡ๅ‘ฝๅไธบ CheetahClaws** - ้กน็›ฎๅทฒไปŽ **Nano Claude Code** ๆ›ดๅไธบ **CheetahClaws** โ€”โ€” ไธ€ไธชๆ›ดๆœ‰่พจ่ฏ†ๅบฆ็š„ๅๅญ—๏ผŒๆ›ด่ƒฝไฝ“็Žฐ่ฟ™ไธชๅทฅๅ…ท็š„ๆฐ”่ดจ๏ผšไธ€ไธช้”ๅˆฉใ€ๆ•ๆท็š„็ผ–็จ‹ๅŠฉๆ‰‹ใ€‚CheetahClaws ไธญ็š„ `Cl` ไนŸๆš—ๅซไบ†ๅฏน Claude ็š„่‡ดๆ„ใ€‚ - CLI ๅ‘ฝไปค๏ผš`nano_claude` โ†’ `cheetahclaws` - PyPI ๅŒ…๏ผš`nano-claude-code` โ†’ `cheetahclaws` @@ -1677,7 +1677,7 @@ Generating diverse perspectives... - Brainstorm ไผšไฝฟ็”จ**ๅฝ“ๅ‰้€‰ไธญ็š„ๆจกๅž‹**๏ผˆ็”จ `/model` ๆŸฅ็œ‹๏ผ‰ใ€‚ไฝฟ็”จ่ƒฝๅŠ›่พƒๅผบ็š„ๆจกๅž‹๏ผˆClaude Sonnet/Opusใ€GPT-4o ๆˆ–่พƒๅคง็š„ๆœฌๅœฐๆจกๅž‹๏ผ‰ๆ•ˆๆžœๆœ€ไฝณใ€‚ - ๅฝ“ agent ๆ•ฐ่พƒๅคš๏ผˆ20+๏ผ‰ๆ—ถ๏ผŒๆ นๆฎๆจกๅž‹้€ŸๅบฆไธๅŒ๏ผŒๆ•ดไธชไผš่ฏๅฏ่ƒฝๆŒ็ปญๆ•ฐๅˆ†้’Ÿใ€‚ - ๅฎ‰่ฃ… `faker`๏ผˆ`pip install faker`๏ผ‰ๅฏ่Žทๅพ—้šๆœบ persona ๅ็งฐ๏ผ›่‹ฅ็ผบๅคฑๅˆ™้€€ๅ›žๅ†…็ฝฎๅ็งฐใ€‚ -- ่พ“ๅ‡บๆ–‡ไปถไผšๆŒ็ปญ็งฏ็ดฏๅœจ `brainstorm_outputs/` ไธญ โ€”โ€” ไปŽ v3.05.5 ่ตท่ฏฅ็›ฎๅฝ•ๅทฒ่ขซๅŠ ๅ…ฅ `.gitignore`ใ€‚ +- ่พ“ๅ‡บๆ–‡ไปถไผšๆŒ็ปญ็งฏ็ดฏๅœจ `brainstorm_outputs/` ไธญ โ€”โ€” ไปŽ v3.5.5 ่ตท่ฏฅ็›ฎๅฝ•ๅทฒ่ขซๅŠ ๅ…ฅ `.gitignore`ใ€‚ - ่ฟ‡้•ฟ็š„ๅ›žๅคๅœจๅฏ่ƒฝ่ถ…ๅ‡บ็ปˆ็ซฏๆ—ถไปไฟๆŒๅฎžๆ—ถๆธฒๆŸ“๏ผŒไฝ†ๅชๆ˜พ็คบๆœ€่ฟ‘ไธ€ๅฑๅ†…ๅฎน๏ผˆๆœ‰็•Œๅฐพ็ช—๏ผ‰๏ผŒ็›ดๅˆฐ่ฏฅๅ›žๅค็ป“ๆŸๆ‰ๆไบคๅฎŒๆ•ดๅ†…ๅฎน๏ผŒๅ› ๆญค้‡ๅค/้™ˆๆ—ง่กŒไผš่ขซ่‡ชๅŠจ้ฟๅ…ใ€‚่‹ฅๅœจ SSH ไธญ่พ“ๅ‡บไป็„ถๆททไนฑ๏ผˆ้‡ๅค่กŒ๏ผ‰๏ผŒๅฏ่ฟ่กŒ `/config rich_live=false` ๅฝปๅบ•ๅ…ณ้—ญ Rich Live ๆตๅผๆธฒๆŸ“ใ€‚ --- @@ -1914,7 +1914,7 @@ Phone (Telegram) cheetahclaws terminal ## ไธปๅŠจๅŽๅฐ็›‘ๆŽง -CheetahClaws v3.05.2 ๅขžๅŠ ไบ†ไธ€ไธช **sentinel ๅฎˆๆŠค็บฟ็จ‹**๏ผŒๅฎƒไผšๅœจ่ฎพๅฎš็š„ๆ— ไบคไบ’ๆ—ถ้•ฟไน‹ๅŽ่‡ชๅŠจๅ”ค้†’ agent โ€”โ€” ๆ— ้œ€็”จๆˆทๅ†ๆฌกๆ็คบใ€‚่ฟ™ๆ”ฏๆŒๆŒ็ปญๆ—ฅๅฟ—็›‘ๆŽงใ€่กŒๆƒ…่ฝฎ่ฏขใ€ๅฎšๆ—ถไปฃ็ ๆฃ€ๆŸฅ็ญ‰ๅœบๆ™ฏใ€‚ +CheetahClaws v3.5.2 ๅขžๅŠ ไบ†ไธ€ไธช **sentinel ๅฎˆๆŠค็บฟ็จ‹**๏ผŒๅฎƒไผšๅœจ่ฎพๅฎš็š„ๆ— ไบคไบ’ๆ—ถ้•ฟไน‹ๅŽ่‡ชๅŠจๅ”ค้†’ agent โ€”โ€” ๆ— ้œ€็”จๆˆทๅ†ๆฌกๆ็คบใ€‚่ฟ™ๆ”ฏๆŒๆŒ็ปญๆ—ฅๅฟ—็›‘ๆŽงใ€่กŒๆƒ…่ฝฎ่ฏขใ€ๅฎšๆ—ถไปฃ็ ๆฃ€ๆŸฅ็ญ‰ๅœบๆ™ฏใ€‚ ### ๅฟซ้€Ÿๅผ€ๅง‹ @@ -2263,7 +2263,7 @@ cheetahclaws ## ไบ‘ๅŒๆญฅ๏ผˆGitHub Gist๏ผ‰ -CheetahClaws v3.05.3 ๅขžๅŠ ไบ†้€š่ฟ‡ **GitHub Gist** ่ฟ›่กŒไผš่ฏไบ‘ๅค‡ไปฝ็š„ๅฏ้€‰ๅŠŸ่ƒฝใ€‚ไผš่ฏไปฅ็งๆœ‰ Gist๏ผˆJSON๏ผ‰ๅฝขๅผไฟๅญ˜๏ผŒๅฏๅœจ GitHub UI ไธญๆต่งˆใ€‚ๆ— ้œ€้ขๅค–ไพ่ต– โ€”โ€” ไฝฟ็”จ Python ๆ ‡ๅ‡†ๅบ“ `urllib`ใ€‚ +CheetahClaws v3.5.3 ๅขžๅŠ ไบ†้€š่ฟ‡ **GitHub Gist** ่ฟ›่กŒไผš่ฏไบ‘ๅค‡ไปฝ็š„ๅฏ้€‰ๅŠŸ่ƒฝใ€‚ไผš่ฏไปฅ็งๆœ‰ Gist๏ผˆJSON๏ผ‰ๅฝขๅผไฟๅญ˜๏ผŒๅฏๅœจ GitHub UI ไธญๆต่งˆใ€‚ๆ— ้œ€้ขๅค–ไพ่ต– โ€”โ€” ไฝฟ็”จ Python ๆ ‡ๅ‡†ๅบ“ `urllib`ใ€‚ ### ่ฎพ็ฝฎ๏ผˆไธ€ๆฌกๆ€ง๏ผ‰ @@ -2375,7 +2375,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT๏ผšfaster-whisper โ†’ openai-whisper โ†’ OpenAI API โ”‚ โ””โ”€โ”€ keyterms.py # ๆฅ่‡ช git branch + ้กน็›ฎๆ–‡ไปถ็š„็ผ–็ ่ฏๆฑ‡ โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint ็ณป็ปŸ๏ผˆv3.05.6๏ผ‰ +โ”œโ”€โ”€ checkpoint/ # Checkpoint ็ณป็ปŸ๏ผˆv3.5.6๏ผ‰ โ”‚ โ”œโ”€โ”€ __init__.py # ๅ…ฌๅ…ฑ API ๅฏผๅ‡บ โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses๏ผ›MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # ๆ–‡ไปถ็บงๅค‡ไปฝใ€ๅฟซ็…งๆŒไน…ๅŒ–ใ€ๅ›žๆปšใ€ๆธ…็† diff --git a/docs/i18n/README.DE.MD b/docs/i18n/README.DE.MD index 4d143cde..7f9c1b78 100644 --- a/docs/i18n/README.DE.MD +++ b/docs/i18n/README.DE.MD @@ -77,7 +77,7 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ Neuigkeiten (Pazifikzeit) -- Apr 07, 2026 (**v3.05.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** +- Apr 07, 2026 (**v3.5.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** - **Telegram photo vision** โ€” send a photo to the Telegram bridge and CheetahClaws will describe it using the active vision model (GPT-4o, Gemini 2.0 Flash, Claude, etc.). The bot downloads the highest-resolution version, encodes it as Base64, and routes it through the same `_pending_image` path as `/img`. Caption text (or a default "describe this image" prompt) is forwarded alongside the image. - **Telegram voice/audio STT** โ€” send a voice message or audio file to the Telegram bridge and CheetahClaws transcribes it automatically. OGG voice notes are converted to PCM via `ffmpeg` and passed to the local Whisper backend; falls back to the OpenAI Whisper API when `ffmpeg` is unavailable. The transcription is echoed back to the chat before being submitted as a query. - **Process-tree kill on Bash timeout** โ€” when a `Bash` command times out, CheetahClaws now kills the entire child process tree instead of only the shell. On Unix, `os.killpg` sends `SIGKILL` to the process group; on Windows, `taskkill /F /T` terminates all child processes. GUI apps (e.g. PyQt games launched by the agent) no longer leave zombie processes after a timeout. The internal implementation uses `start_new_session=True` instead of `preexec_fn=os.setsid` for thread safety. @@ -86,20 +86,20 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM - **Bash timeout hints** โ€” the `Bash` tool description now advises the model to use `timeout=120โ€“300` for slow commands (`npm install`, `npx`, `pip install`, builds), reducing spurious 30-second timeouts on package operations. - **Bug fix: background event prompt shows actual cwd** โ€” the yellow re-prompt printed after a background event completed was hardcoded to `[claude-code-local]`; it now shows the real working-directory name (`[{cwd.name}]`), consistent with the main REPL prompt. -- Apr 06, 2026 (**v3.05.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** +- Apr 06, 2026 (**v3.5.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** - **Telegram interactive menus fixed** โ€” slash commands with interactive input (e.g. `/ollama`, `/permission`, `/checkpoint`) were blocking the Telegram poll loop, making it impossible to respond to the menu prompts. Slash commands now run in a daemon thread (like regular queries), keeping the poll loop free. All interactive menus (`ask_input_interactive`) work correctly over Telegram. - **`/img` alias** โ€” `/img` is now an alias for `/image`, for faster clipboard-image workflows. - **`/voice device`** โ€” new subcommand to list all available input microphones and select one interactively. The selected device index is persisted in the session config and shown in `/voice status`. Useful on systems with multiple audio interfaces (e.g. USB headset + built-in mic). - **Vision support for OpenAI / Gemini models** โ€” `/img` (and `/image`) now sends images in the OpenAI multipart `image_url` format to cloud vision models (GPT-4o, Gemini 2.0 Flash, etc.), in addition to the existing Ollama native format. No configuration change needed โ€” the correct format is selected automatically based on the active provider. - **Bug fix: threading race condition** โ€” `_in_telegram_turn` is now tracked via `threading.local()` per-slash-runner thread instead of a shared config key, eliminating a race condition that could corrupt the flag when a regular message arrived while an interactive slash command was waiting for input. -- Apr 06, 2026 (**v3.05.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** +- Apr 06, 2026 (**v3.5.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** - **Checkpoint system** (`checkpoint/` package): auto-snapshots conversation state and file changes after every turn. `/checkpoint` lists all snapshots; `/checkpoint ` rewinds both files and conversation history to any previous state; `/checkpoint clear` removes all snapshots for the session. `/rewind` is an alias. 100-snapshot sliding window; initial snapshot captured at session start. Throttling: skips when nothing changed. File backups use copy-on-write; snapshots capture post-edit state. - **Plan mode**: `/plan ` enters a read-only analysis mode โ€” Claude may only read the codebase and write to a dedicated plan file (`.nano_claude/plans/.md`). All other writes are silently blocked with a helpful message. `/plan` shows the current plan; `/plan done` exits plan mode and restores original permissions; `/plan status` reports whether plan mode is active. Two new agent tools โ€” `EnterPlanMode` and `ExitPlanMode` โ€” let Claude autonomously enter and exit plan mode for complex multi-file tasks; both are auto-approved in all permission modes. - **`/compact [focus]`**: manually trigger conversation compaction at any time. An optional focus string guides the LLM summarizer on what context to preserve. Auto-compact and manual compact both restore plan file context after compaction. - **Utility commands**: `/init` creates a `CLAUDE.md` template in the current directory; `/export [filename]` exports the conversation as Markdown (default) or JSON; `/copy` copies the last assistant response to the clipboard (Windows/macOS/Linux); `/status` shows version, model, provider, permissions, session ID, token usage, and context %; `/doctor` diagnoses installation health (Python version, git, API key + live connectivity test, optional deps, CLAUDE.md presence, checkpoint disk usage, permission mode). -- Apr 06, 2026 (**v3.05.51**): **Project renamed from Nano Claude Code to CheetahClaws** +- Apr 06, 2026 (**v3.5.51**): **Project renamed from Nano Claude Code to CheetahClaws** - The project has been rebranded from **Nano Claude Code** to **CheetahClaws** โ€” a more distinctive name that captures the spirit of the tool: a sharp, agile coding assistant. The `Cl` in CheetahClaws is a subtle nod to Claude. - CLI command: `nano_claude` โ†’ `cheetahclaws` - PyPI package: `nano-claude-code` โ†’ `cheetahclaws` @@ -1666,7 +1666,7 @@ Generating diverse perspectives... - Brainstorm uses the **currently selected model** (`/model` to check). A capable model (Claude Sonnet/Opus, GPT-4o, or a large local model) gives the best results. - With many agents (20+) the session can take several minutes depending on model speed. - Install `faker` (`pip install faker`) for randomized persona names; falls back to built-in names otherwise. -- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.05.5. +- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.5.5. - Long responses keep rendering live but show only the most recent screenful (a bounded tail window) until they finish, so duplicate/stale lines are prevented automatically. If output still looks garbled in SSH (repeated lines), run `/config rich_live=false` to fully disable Rich Live streaming. --- @@ -1903,7 +1903,7 @@ If both `telegram_token` and `telegram_chat_id` are set in `~/.cheetahclaws/conf ## Proaktive Hintergrundรผberwachung -CheetahClaws v3.05.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. +CheetahClaws v3.5.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. ### Schnellstart @@ -2252,7 +2252,7 @@ Resume a specific file: ## Cloud-Synchronisierung (GitHub Gist) -CheetahClaws v3.05.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. +CheetahClaws v3.5.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. ### Einrichtung (einmalig) @@ -2364,7 +2364,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT: faster-whisper โ†’ openai-whisper โ†’ OpenAI API โ”‚ โ””โ”€โ”€ keyterms.py # Coding-domain vocab from git branch + project files โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Public API exports โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # File-level backup, snapshot persistence, rewind, cleanup diff --git a/docs/i18n/README.ES.MD b/docs/i18n/README.ES.MD index 425c850f..0243076b 100644 --- a/docs/i18n/README.ES.MD +++ b/docs/i18n/README.ES.MD @@ -74,7 +74,7 @@ Espaรฑol | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READ ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ Novedades (hora del Pacรญfico) -- 07 de abril de 2026 (**v3.05.53**): **soporte de fotos/voz en Telegram, eliminaciรณn del รกrbol de procesos al expirar Bash, sugerencias de shell para Windows, correcciรณn del worker** +- 07 de abril de 2026 (**v3.5.53**): **soporte de fotos/voz en Telegram, eliminaciรณn del รกrbol de procesos al expirar Bash, sugerencias de shell para Windows, correcciรณn del worker** - **Visiรณn con fotos de Telegram** โ€” envรญa una foto al puente de Telegram y CheetahClaws la describirรก usando el modelo de visiรณn activo (GPT-4o, Gemini 2.0 Flash, Claude, etc.). El bot descarga la versiรณn de mayor resoluciรณn, la codifica en Base64 y la enruta por la misma ruta `_pending_image` que `/img`. El texto del pie de foto (o un prompt por defecto, โ€œdescribe esta imagenโ€) se reenvรญa junto con la imagen. - **STT para voz/audio de Telegram** โ€” envรญa un mensaje de voz o un archivo de audio al puente de Telegram y CheetahClaws lo transcribirรก automรกticamente. Las notas de voz en OGG se convierten a PCM mediante `ffmpeg` y se pasan al backend local de Whisper; si `ffmpeg` no estรก disponible, se usa como alternativa la API Whisper de OpenAI. La transcripciรณn se devuelve al chat antes de enviarse como consulta. - **Eliminaciรณn del รกrbol de procesos al expirar Bash** โ€” cuando un comando `Bash` excede el tiempo lรญmite, CheetahClaws ahora elimina todo el รกrbol de procesos hijo en lugar de solo la shell. En Unix, `os.killpg` envรญa `SIGKILL` al grupo de procesos; en Windows, `taskkill /F /T` termina todos los procesos hijo. Las aplicaciones GUI (por ejemplo, juegos PyQt lanzados por el agente) ya no dejan procesos zombis tras un timeout. La implementaciรณn interna usa `start_new_session=True` en lugar de `preexec_fn=os.setsid` por seguridad en entornos con hilos. @@ -83,20 +83,20 @@ Espaรฑol | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READ - **Sugerencias para timeouts de Bash** โ€” la descripciรณn de la herramienta `Bash` ahora aconseja al modelo usar `timeout=120โ€“300` para comandos lentos (`npm install`, `npx`, `pip install`, compilaciones), reduciendo falsos timeouts de 30 segundos en operaciones de paquetes. - **Correcciรณn: el prompt de eventos en segundo plano muestra el cwd real** โ€” el re-prompt amarillo que aparecรญa tras finalizar un evento en segundo plano estaba fijado a `[claude-code-local]`; ahora muestra el nombre real del directorio de trabajo (`[{cwd.name}]`), consistente con el prompt principal del REPL. -- 06 de abril de 2026 (**v3.05.53**): **menรบs interactivos de Telegram, alias `/img`, `/voice device`, soporte de visiรณn para OpenAI/Gemini** +- 06 de abril de 2026 (**v3.5.53**): **menรบs interactivos de Telegram, alias `/img`, `/voice device`, soporte de visiรณn para OpenAI/Gemini** - **Menรบs interactivos de Telegram corregidos** โ€” los comandos slash con entrada interactiva (por ejemplo, `/ollama`, `/permission`, `/checkpoint`) bloqueaban el bucle de sondeo de Telegram, impidiendo responder a los menรบs. Ahora los comandos slash se ejecutan en un hilo daemon (igual que las consultas normales), manteniendo libre el bucle de sondeo. Todos los menรบs interactivos (`ask_input_interactive`) funcionan correctamente sobre Telegram. - **Alias `/img`** โ€” `/img` ahora es un alias de `/image`, para flujos de trabajo mรกs rรกpidos con imรกgenes del portapapeles. - **`/voice device`** โ€” nuevo subcomando para listar todos los micrรณfonos de entrada disponibles y seleccionar uno de forma interactiva. El รญndice del dispositivo elegido se guarda en la configuraciรณn de la sesiรณn y se muestra en `/voice status`. รštil en sistemas con mรบltiples interfaces de audio (por ejemplo, auriculares USB + micrรณfono integrado). - **Soporte de visiรณn para modelos OpenAI / Gemini** โ€” `/img` (y `/image`) ahora envรญa imรกgenes en el formato OpenAI multipart `image_url` a modelos de visiรณn en la nube (GPT-4o, Gemini 2.0 Flash, etc.), ademรกs del formato nativo existente de Ollama. No se necesita cambiar la configuraciรณn: el formato correcto se selecciona automรกticamente segรบn el proveedor activo. - **Correcciรณn: condiciรณn de carrera de hilos** โ€” `_in_telegram_turn` ahora se rastrea mediante `threading.local()` por hilo ejecutor de slash, en lugar de una clave compartida de configuraciรณn, eliminando una condiciรณn de carrera que podรญa corromper la bandera cuando llegaba un mensaje normal mientras un comando slash interactivo esperaba entrada. -- 06 de abril de 2026 (**v3.05.52**): **sistema de checkpoints, modo plan, compactaciรณn y utilidades, soporte para MiniMax, correcciones de Telegram** +- 06 de abril de 2026 (**v3.5.52**): **sistema de checkpoints, modo plan, compactaciรณn y utilidades, soporte para MiniMax, correcciones de Telegram** - **Sistema de checkpoints** (`checkpoint/`): instantรกneas automรกticas del estado de la conversaciรณn y de los cambios en archivos tras cada turno. `/checkpoint` lista todas las instantรกneas; `/checkpoint ` revierte tanto archivos como historial de conversaciรณn a cualquier estado anterior; `/checkpoint clear` elimina todas las instantรกneas de la sesiรณn. `/rewind` es un alias. Ventana deslizante de 100 instantรกneas; se captura una instantรกnea inicial al comienzo de la sesiรณn. Limitaciรณn: se omite cuando nada ha cambiado. Las copias de seguridad de archivos usan copy-on-write; las instantรกneas capturan el estado posterior a la ediciรณn. - **Modo plan**: `/plan ` entra en un modo de anรกlisis de solo lectura โ€” Claude solo puede leer el cรณdigo y escribir en un archivo de plan dedicado (`.nano_claude/plans/.md`). Todas las demรกs escrituras se bloquean silenciosamente con un mensaje รบtil. `/plan` muestra el plan actual; `/plan done` sale del modo plan y restaura los permisos originales; `/plan status` informa si el modo plan estรก activo. Dos nuevas herramientas del agente โ€” `EnterPlanMode` y `ExitPlanMode` โ€” permiten a Claude entrar y salir autรณnomamente del modo plan para tareas complejas de mรบltiples archivos; ambas se aprueban automรกticamente en todos los modos de permiso. - **`/compact [focus]`**: activa manualmente la compactaciรณn de la conversaciรณn en cualquier momento. Una cadena de enfoque opcional guรญa al resumidor LLM sobre quรฉ contexto preservar. Tanto la compactaciรณn automรกtica como la manual restauran el contexto del archivo de plan despuรฉs de compactar. - **Comandos utilitarios**: `/init` crea una plantilla `CLAUDE.md` en el directorio actual; `/export [filename]` exporta la conversaciรณn como Markdown (por defecto) o JSON; `/copy` copia al portapapeles la รบltima respuesta del asistente (Windows/macOS/Linux); `/status` muestra versiรณn, modelo, proveedor, permisos, ID de sesiรณn, uso de tokens y porcentaje de contexto; `/doctor` diagnostica el estado de la instalaciรณn (versiรณn de Python, git, clave API + prueba real de conectividad, dependencias opcionales, presencia de CLAUDE.md, uso de disco de checkpoints, modo de permisos). -- 06 de abril de 2026 (**v3.05.51**): **el proyecto cambiรณ de nombre de Nano Claude Code a CheetahClaws** +- 06 de abril de 2026 (**v3.5.51**): **el proyecto cambiรณ de nombre de Nano Claude Code a CheetahClaws** - El proyecto ha sido renombrado de **Nano Claude Code** a **CheetahClaws** โ€” un nombre mรกs distintivo que captura el espรญritu de la herramienta: un asistente de programaciรณn รกgil y afilado. El `Cl` de CheetahClaws es una sutil referencia a Claude. - Comando CLI: `nano_claude` โ†’ `cheetahclaws` - Paquete PyPI: `nano-claude-code` โ†’ `cheetahclaws` @@ -1664,7 +1664,7 @@ Generando perspectivas diversas... - Brainstorm usa el **modelo actualmente seleccionado** (`/model` para comprobarlo). Un modelo potente (Claude Sonnet/Opus, GPT-4o o un gran modelo local) da los mejores resultados. - Con muchos agentes (20+) la sesiรณn puede tardar varios minutos segรบn la velocidad del modelo. - Instala `faker` (`pip install faker`) para nombres de persona aleatorios; si no, usa nombres integrados. -- Los archivos de salida se acumulan en `brainstorm_outputs/`; desde v3.05.5 ya estรก aรฑadido a `.gitignore`. +- Los archivos de salida se acumulan en `brainstorm_outputs/`; desde v3.5.5 ya estรก aรฑadido a `.gitignore`. - Las respuestas largas siguen renderizรกndose en vivo pero solo muestran la รบltima pantalla (una ventana de cola acotada) hasta que terminan, por lo que las lรญneas duplicadas/obsoletas se evitan automรกticamente. Si la salida aรบn se ve corrupta en SSH (lรญneas repetidas), ejecuta `/config rich_live=false` para desactivar por completo Rich Live streaming. --- @@ -1901,7 +1901,7 @@ Si tanto `telegram_token` como `telegram_chat_id` estรกn establecidos en `~/.che ## Monitoreo proactivo en segundo plano -CheetahClaws v3.05.2 aรฑade un **daemon centinela** que despierta automรกticamente al agente tras un perรญodo configurable de inactividad, sin necesidad de prompt del usuario. Esto permite casos de uso como monitoreo continuo de logs, sondeo de scripts de mercado o comprobaciones de cรณdigo programadas. +CheetahClaws v3.5.2 aรฑade un **daemon centinela** que despierta automรกticamente al agente tras un perรญodo configurable de inactividad, sin necesidad de prompt del usuario. Esto permite casos de uso como monitoreo continuo de logs, sondeo de scripts de mercado o comprobaciones de cรณdigo programadas. ### Inicio rรกpido @@ -2250,7 +2250,7 @@ Reanudar un archivo especรญfico: ## Sincronizaciรณn en la nube (GitHub Gist) -CheetahClaws v3.05.3 aรฑade respaldo opcional en la nube de sesiones de conversaciรณn mediante **GitHub Gist**. Las sesiones se almacenan como Gists privados (JSON), navegables en la interfaz de GitHub. Sin dependencias adicionales: usa `urllib` de la stdlib de Python. +CheetahClaws v3.5.3 aรฑade respaldo opcional en la nube de sesiones de conversaciรณn mediante **GitHub Gist**. Las sesiones se almacenan como Gists privados (JSON), navegables en la interfaz de GitHub. Sin dependencias adicionales: usa `urllib` de la stdlib de Python. ### Configuraciรณn (una vez) @@ -2362,7 +2362,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT: faster-whisper โ†’ openai-whisper โ†’ API de OpenAI โ”‚ โ””โ”€โ”€ keyterms.py # Vocabulario tรฉcnico a partir de rama git + archivos del proyecto โ”‚ -โ”œโ”€โ”€ checkpoint/ # Sistema de checkpoints (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Sistema de checkpoints (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Exportaciones de API pรบblica โ”‚ โ”œโ”€โ”€ types.py # Dataclasses FileBackup + Snapshot; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # Backup a nivel de archivo, persistencia de snapshots, rewind, limpieza diff --git a/docs/i18n/README.FR.MD b/docs/i18n/README.FR.MD index efe714c7..818d147f 100644 --- a/docs/i18n/README.FR.MD +++ b/docs/i18n/README.FR.MD @@ -76,7 +76,7 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ Actualitรฉs (heure du Pacifique) -- Apr 07, 2026 (**v3.05.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** +- Apr 07, 2026 (**v3.5.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** - **Telegram photo vision** โ€” send a photo to the Telegram bridge and CheetahClaws will describe it using the active vision model (GPT-4o, Gemini 2.0 Flash, Claude, etc.). The bot downloads the highest-resolution version, encodes it as Base64, and routes it through the same `_pending_image` path as `/img`. Caption text (or a default "describe this image" prompt) is forwarded alongside the image. - **Telegram voice/audio STT** โ€” send a voice message or audio file to the Telegram bridge and CheetahClaws transcribes it automatically. OGG voice notes are converted to PCM via `ffmpeg` and passed to the local Whisper backend; falls back to the OpenAI Whisper API when `ffmpeg` is unavailable. The transcription is echoed back to the chat before being submitted as a query. - **Process-tree kill on Bash timeout** โ€” when a `Bash` command times out, CheetahClaws now kills the entire child process tree instead of only the shell. On Unix, `os.killpg` sends `SIGKILL` to the process group; on Windows, `taskkill /F /T` terminates all child processes. GUI apps (e.g. PyQt games launched by the agent) no longer leave zombie processes after a timeout. The internal implementation uses `start_new_session=True` instead of `preexec_fn=os.setsid` for thread safety. @@ -85,20 +85,20 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM - **Bash timeout hints** โ€” the `Bash` tool description now advises the model to use `timeout=120โ€“300` for slow commands (`npm install`, `npx`, `pip install`, builds), reducing spurious 30-second timeouts on package operations. - **Bug fix: background event prompt shows actual cwd** โ€” the yellow re-prompt printed after a background event completed was hardcoded to `[claude-code-local]`; it now shows the real working-directory name (`[{cwd.name}]`), consistent with the main REPL prompt. -- Apr 06, 2026 (**v3.05.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** +- Apr 06, 2026 (**v3.5.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** - **Telegram interactive menus fixed** โ€” slash commands with interactive input (e.g. `/ollama`, `/permission`, `/checkpoint`) were blocking the Telegram poll loop, making it impossible to respond to the menu prompts. Slash commands now run in a daemon thread (like regular queries), keeping the poll loop free. All interactive menus (`ask_input_interactive`) work correctly over Telegram. - **`/img` alias** โ€” `/img` is now an alias for `/image`, for faster clipboard-image workflows. - **`/voice device`** โ€” new subcommand to list all available input microphones and select one interactively. The selected device index is persisted in the session config and shown in `/voice status`. Useful on systems with multiple audio interfaces (e.g. USB headset + built-in mic). - **Vision support for OpenAI / Gemini models** โ€” `/img` (and `/image`) now sends images in the OpenAI multipart `image_url` format to cloud vision models (GPT-4o, Gemini 2.0 Flash, etc.), in addition to the existing Ollama native format. No configuration change needed โ€” the correct format is selected automatically based on the active provider. - **Bug fix: threading race condition** โ€” `_in_telegram_turn` is now tracked via `threading.local()` per-slash-runner thread instead of a shared config key, eliminating a race condition that could corrupt the flag when a regular message arrived while an interactive slash command was waiting for input. -- Apr 06, 2026 (**v3.05.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** +- Apr 06, 2026 (**v3.5.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** - **Checkpoint system** (`checkpoint/` package): auto-snapshots conversation state and file changes after every turn. `/checkpoint` lists all snapshots; `/checkpoint ` rewinds both files and conversation history to any previous state; `/checkpoint clear` removes all snapshots for the session. `/rewind` is an alias. 100-snapshot sliding window; initial snapshot captured at session start. Throttling: skips when nothing changed. File backups use copy-on-write; snapshots capture post-edit state. - **Plan mode**: `/plan ` enters a read-only analysis mode โ€” Claude may only read the codebase and write to a dedicated plan file (`.nano_claude/plans/.md`). All other writes are silently blocked with a helpful message. `/plan` shows the current plan; `/plan done` exits plan mode and restores original permissions; `/plan status` reports whether plan mode is active. Two new agent tools โ€” `EnterPlanMode` and `ExitPlanMode` โ€” let Claude autonomously enter and exit plan mode for complex multi-file tasks; both are auto-approved in all permission modes. - **`/compact [focus]`**: manually trigger conversation compaction at any time. An optional focus string guides the LLM summarizer on what context to preserve. Auto-compact and manual compact both restore plan file context after compaction. - **Utility commands**: `/init` creates a `CLAUDE.md` template in the current directory; `/export [filename]` exports the conversation as Markdown (default) or JSON; `/copy` copies the last assistant response to the clipboard (Windows/macOS/Linux); `/status` shows version, model, provider, permissions, session ID, token usage, and context %; `/doctor` diagnoses installation health (Python version, git, API key + live connectivity test, optional deps, CLAUDE.md presence, checkpoint disk usage, permission mode). -- Apr 06, 2026 (**v3.05.51**): **Project renamed from Nano Claude Code to CheetahClaws** +- Apr 06, 2026 (**v3.5.51**): **Project renamed from Nano Claude Code to CheetahClaws** - The project has been rebranded from **Nano Claude Code** to **CheetahClaws** โ€” a more distinctive name that captures the spirit of the tool: a sharp, agile coding assistant. The `Cl` in CheetahClaws is a subtle nod to Claude. - CLI command: `nano_claude` โ†’ `cheetahclaws` - PyPI package: `nano-claude-code` โ†’ `cheetahclaws` @@ -1665,7 +1665,7 @@ Generating diverse perspectives... - Brainstorm uses the **currently selected model** (`/model` to check). A capable model (Claude Sonnet/Opus, GPT-4o, or a large local model) gives the best results. - With many agents (20+) the session can take several minutes depending on model speed. - Install `faker` (`pip install faker`) for randomized persona names; falls back to built-in names otherwise. -- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.05.5. +- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.5.5. - Long responses keep rendering live but show only the most recent screenful (a bounded tail window) until they finish, so duplicate/stale lines are prevented automatically. If output still looks garbled in SSH (repeated lines), run `/config rich_live=false` to fully disable Rich Live streaming. --- @@ -1902,7 +1902,7 @@ If both `telegram_token` and `telegram_chat_id` are set in `~/.cheetahclaws/conf ## Surveillance proactive en arriรจre-plan -CheetahClaws v3.05.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. +CheetahClaws v3.5.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. ### Dรฉmarrage rapide @@ -2251,7 +2251,7 @@ Resume a specific file: ## Synchronisation cloud (GitHub Gist) -CheetahClaws v3.05.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. +CheetahClaws v3.5.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. ### Configuration (une seule fois) @@ -2363,7 +2363,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT: faster-whisper โ†’ openai-whisper โ†’ OpenAI API โ”‚ โ””โ”€โ”€ keyterms.py # Coding-domain vocab from git branch + project files โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Public API exports โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # File-level backup, snapshot persistence, rewind, cleanup diff --git a/docs/i18n/README.JP.MD b/docs/i18n/README.JP.MD index 086f6da4..d27a7a44 100644 --- a/docs/i18n/README.JP.MD +++ b/docs/i18n/README.JP.MD @@ -76,7 +76,7 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ ใƒ‹ใƒฅใƒผใ‚น๏ผˆๅคชๅนณๆด‹ๆ™‚้–“๏ผ‰ -- Apr 07, 2026 (**v3.05.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** +- Apr 07, 2026 (**v3.5.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** - **Telegram photo vision** โ€” send a photo to the Telegram bridge and CheetahClaws will describe it using the active vision model (GPT-4o, Gemini 2.0 Flash, Claude, etc.). The bot downloads the highest-resolution version, encodes it as Base64, and routes it through the same `_pending_image` path as `/img`. Caption text (or a default "describe this image" prompt) is forwarded alongside the image. - **Telegram voice/audio STT** โ€” send a voice message or audio file to the Telegram bridge and CheetahClaws transcribes it automatically. OGG voice notes are converted to PCM via `ffmpeg` and passed to the local Whisper backend; falls back to the OpenAI Whisper API when `ffmpeg` is unavailable. The transcription is echoed back to the chat before being submitted as a query. - **Process-tree kill on Bash timeout** โ€” when a `Bash` command times out, CheetahClaws now kills the entire child process tree instead of only the shell. On Unix, `os.killpg` sends `SIGKILL` to the process group; on Windows, `taskkill /F /T` terminates all child processes. GUI apps (e.g. PyQt games launched by the agent) no longer leave zombie processes after a timeout. The internal implementation uses `start_new_session=True` instead of `preexec_fn=os.setsid` for thread safety. @@ -85,20 +85,20 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM - **Bash timeout hints** โ€” the `Bash` tool description now advises the model to use `timeout=120โ€“300` for slow commands (`npm install`, `npx`, `pip install`, builds), reducing spurious 30-second timeouts on package operations. - **Bug fix: background event prompt shows actual cwd** โ€” the yellow re-prompt printed after a background event completed was hardcoded to `[claude-code-local]`; it now shows the real working-directory name (`[{cwd.name}]`), consistent with the main REPL prompt. -- Apr 06, 2026 (**v3.05.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** +- Apr 06, 2026 (**v3.5.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** - **Telegram interactive menus fixed** โ€” slash commands with interactive input (e.g. `/ollama`, `/permission`, `/checkpoint`) were blocking the Telegram poll loop, making it impossible to respond to the menu prompts. Slash commands now run in a daemon thread (like regular queries), keeping the poll loop free. All interactive menus (`ask_input_interactive`) work correctly over Telegram. - **`/img` alias** โ€” `/img` is now an alias for `/image`, for faster clipboard-image workflows. - **`/voice device`** โ€” new subcommand to list all available input microphones and select one interactively. The selected device index is persisted in the session config and shown in `/voice status`. Useful on systems with multiple audio interfaces (e.g. USB headset + built-in mic). - **Vision support for OpenAI / Gemini models** โ€” `/img` (and `/image`) now sends images in the OpenAI multipart `image_url` format to cloud vision models (GPT-4o, Gemini 2.0 Flash, etc.), in addition to the existing Ollama native format. No configuration change needed โ€” the correct format is selected automatically based on the active provider. - **Bug fix: threading race condition** โ€” `_in_telegram_turn` is now tracked via `threading.local()` per-slash-runner thread instead of a shared config key, eliminating a race condition that could corrupt the flag when a regular message arrived while an interactive slash command was waiting for input. -- Apr 06, 2026 (**v3.05.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** +- Apr 06, 2026 (**v3.5.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** - **Checkpoint system** (`checkpoint/` package): auto-snapshots conversation state and file changes after every turn. `/checkpoint` lists all snapshots; `/checkpoint ` rewinds both files and conversation history to any previous state; `/checkpoint clear` removes all snapshots for the session. `/rewind` is an alias. 100-snapshot sliding window; initial snapshot captured at session start. Throttling: skips when nothing changed. File backups use copy-on-write; snapshots capture post-edit state. - **Plan mode**: `/plan ` enters a read-only analysis mode โ€” Claude may only read the codebase and write to a dedicated plan file (`.nano_claude/plans/.md`). All other writes are silently blocked with a helpful message. `/plan` shows the current plan; `/plan done` exits plan mode and restores original permissions; `/plan status` reports whether plan mode is active. Two new agent tools โ€” `EnterPlanMode` and `ExitPlanMode` โ€” let Claude autonomously enter and exit plan mode for complex multi-file tasks; both are auto-approved in all permission modes. - **`/compact [focus]`**: manually trigger conversation compaction at any time. An optional focus string guides the LLM summarizer on what context to preserve. Auto-compact and manual compact both restore plan file context after compaction. - **Utility commands**: `/init` creates a `CLAUDE.md` template in the current directory; `/export [filename]` exports the conversation as Markdown (default) or JSON; `/copy` copies the last assistant response to the clipboard (Windows/macOS/Linux); `/status` shows version, model, provider, permissions, session ID, token usage, and context %; `/doctor` diagnoses installation health (Python version, git, API key + live connectivity test, optional deps, CLAUDE.md presence, checkpoint disk usage, permission mode). -- Apr 06, 2026 (**v3.05.51**): **Project renamed from Nano Claude Code to CheetahClaws** +- Apr 06, 2026 (**v3.5.51**): **Project renamed from Nano Claude Code to CheetahClaws** - The project has been rebranded from **Nano Claude Code** to **CheetahClaws** โ€” a more distinctive name that captures the spirit of the tool: a sharp, agile coding assistant. The `Cl` in CheetahClaws is a subtle nod to Claude. - CLI command: `nano_claude` โ†’ `cheetahclaws` - PyPI package: `nano-claude-code` โ†’ `cheetahclaws` @@ -1664,7 +1664,7 @@ Generating diverse perspectives... - Brainstorm uses the **currently selected model** (`/model` to check). A capable model (Claude Sonnet/Opus, GPT-4o, or a large local model) gives the best results. - With many agents (20+) the session can take several minutes depending on model speed. - Install `faker` (`pip install faker`) for randomized persona names; falls back to built-in names otherwise. -- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.05.5. +- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.5.5. - Long responses keep rendering live but show only the most recent screenful (a bounded tail window) until they finish, so duplicate/stale lines are prevented automatically. If output still looks garbled in SSH (repeated lines), run `/config rich_live=false` to fully disable Rich Live streaming. --- @@ -1901,7 +1901,7 @@ If both `telegram_token` and `telegram_chat_id` are set in `~/.cheetahclaws/conf ## ใƒ—ใƒญใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰็›ฃ่ฆ– -CheetahClaws v3.05.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. +CheetahClaws v3.5.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. ### ใ‚ฏใ‚คใƒƒใ‚ฏใ‚นใ‚ฟใƒผใƒˆ @@ -2250,7 +2250,7 @@ Resume a specific file: ## ใ‚ฏใƒฉใ‚ฆใƒ‰ๅŒๆœŸ๏ผˆGitHub Gist๏ผ‰ -CheetahClaws v3.05.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. +CheetahClaws v3.5.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. ### ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—๏ผˆๅˆๅ›žใฎใฟ๏ผ‰ @@ -2362,7 +2362,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT: faster-whisper โ†’ openai-whisper โ†’ OpenAI API โ”‚ โ””โ”€โ”€ keyterms.py # Coding-domain vocab from git branch + project files โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Public API exports โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # File-level backup, snapshot persistence, rewind, cleanup diff --git a/docs/i18n/README.KO.MD b/docs/i18n/README.KO.MD index 67a87b5c..f5cb7d80 100644 --- a/docs/i18n/README.KO.MD +++ b/docs/i18n/README.KO.MD @@ -76,7 +76,7 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ ๋‰ด์Šค (ํƒœํ‰์–‘ ์‹œ๊ฐ„) -- Apr 07, 2026 (**v3.05.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** +- Apr 07, 2026 (**v3.5.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** - **Telegram photo vision** โ€” send a photo to the Telegram bridge and CheetahClaws will describe it using the active vision model (GPT-4o, Gemini 2.0 Flash, Claude, etc.). The bot downloads the highest-resolution version, encodes it as Base64, and routes it through the same `_pending_image` path as `/img`. Caption text (or a default "describe this image" prompt) is forwarded alongside the image. - **Telegram voice/audio STT** โ€” send a voice message or audio file to the Telegram bridge and CheetahClaws transcribes it automatically. OGG voice notes are converted to PCM via `ffmpeg` and passed to the local Whisper backend; falls back to the OpenAI Whisper API when `ffmpeg` is unavailable. The transcription is echoed back to the chat before being submitted as a query. - **Process-tree kill on Bash timeout** โ€” when a `Bash` command times out, CheetahClaws now kills the entire child process tree instead of only the shell. On Unix, `os.killpg` sends `SIGKILL` to the process group; on Windows, `taskkill /F /T` terminates all child processes. GUI apps (e.g. PyQt games launched by the agent) no longer leave zombie processes after a timeout. The internal implementation uses `start_new_session=True` instead of `preexec_fn=os.setsid` for thread safety. @@ -85,20 +85,20 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM - **Bash timeout hints** โ€” the `Bash` tool description now advises the model to use `timeout=120โ€“300` for slow commands (`npm install`, `npx`, `pip install`, builds), reducing spurious 30-second timeouts on package operations. - **Bug fix: background event prompt shows actual cwd** โ€” the yellow re-prompt printed after a background event completed was hardcoded to `[claude-code-local]`; it now shows the real working-directory name (`[{cwd.name}]`), consistent with the main REPL prompt. -- Apr 06, 2026 (**v3.05.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** +- Apr 06, 2026 (**v3.5.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** - **Telegram interactive menus fixed** โ€” slash commands with interactive input (e.g. `/ollama`, `/permission`, `/checkpoint`) were blocking the Telegram poll loop, making it impossible to respond to the menu prompts. Slash commands now run in a daemon thread (like regular queries), keeping the poll loop free. All interactive menus (`ask_input_interactive`) work correctly over Telegram. - **`/img` alias** โ€” `/img` is now an alias for `/image`, for faster clipboard-image workflows. - **`/voice device`** โ€” new subcommand to list all available input microphones and select one interactively. The selected device index is persisted in the session config and shown in `/voice status`. Useful on systems with multiple audio interfaces (e.g. USB headset + built-in mic). - **Vision support for OpenAI / Gemini models** โ€” `/img` (and `/image`) now sends images in the OpenAI multipart `image_url` format to cloud vision models (GPT-4o, Gemini 2.0 Flash, etc.), in addition to the existing Ollama native format. No configuration change needed โ€” the correct format is selected automatically based on the active provider. - **Bug fix: threading race condition** โ€” `_in_telegram_turn` is now tracked via `threading.local()` per-slash-runner thread instead of a shared config key, eliminating a race condition that could corrupt the flag when a regular message arrived while an interactive slash command was waiting for input. -- Apr 06, 2026 (**v3.05.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** +- Apr 06, 2026 (**v3.5.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** - **Checkpoint system** (`checkpoint/` package): auto-snapshots conversation state and file changes after every turn. `/checkpoint` lists all snapshots; `/checkpoint ` rewinds both files and conversation history to any previous state; `/checkpoint clear` removes all snapshots for the session. `/rewind` is an alias. 100-snapshot sliding window; initial snapshot captured at session start. Throttling: skips when nothing changed. File backups use copy-on-write; snapshots capture post-edit state. - **Plan mode**: `/plan ` enters a read-only analysis mode โ€” Claude may only read the codebase and write to a dedicated plan file (`.nano_claude/plans/.md`). All other writes are silently blocked with a helpful message. `/plan` shows the current plan; `/plan done` exits plan mode and restores original permissions; `/plan status` reports whether plan mode is active. Two new agent tools โ€” `EnterPlanMode` and `ExitPlanMode` โ€” let Claude autonomously enter and exit plan mode for complex multi-file tasks; both are auto-approved in all permission modes. - **`/compact [focus]`**: manually trigger conversation compaction at any time. An optional focus string guides the LLM summarizer on what context to preserve. Auto-compact and manual compact both restore plan file context after compaction. - **Utility commands**: `/init` creates a `CLAUDE.md` template in the current directory; `/export [filename]` exports the conversation as Markdown (default) or JSON; `/copy` copies the last assistant response to the clipboard (Windows/macOS/Linux); `/status` shows version, model, provider, permissions, session ID, token usage, and context %; `/doctor` diagnoses installation health (Python version, git, API key + live connectivity test, optional deps, CLAUDE.md presence, checkpoint disk usage, permission mode). -- Apr 06, 2026 (**v3.05.51**): **Project renamed from Nano Claude Code to CheetahClaws** +- Apr 06, 2026 (**v3.5.51**): **Project renamed from Nano Claude Code to CheetahClaws** - The project has been rebranded from **Nano Claude Code** to **CheetahClaws** โ€” a more distinctive name that captures the spirit of the tool: a sharp, agile coding assistant. The `Cl` in CheetahClaws is a subtle nod to Claude. - CLI command: `nano_claude` โ†’ `cheetahclaws` - PyPI package: `nano-claude-code` โ†’ `cheetahclaws` @@ -1664,7 +1664,7 @@ Generating diverse perspectives... - Brainstorm uses the **currently selected model** (`/model` to check). A capable model (Claude Sonnet/Opus, GPT-4o, or a large local model) gives the best results. - With many agents (20+) the session can take several minutes depending on model speed. - Install `faker` (`pip install faker`) for randomized persona names; falls back to built-in names otherwise. -- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.05.5. +- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.5.5. - Long responses keep rendering live but show only the most recent screenful (a bounded tail window) until they finish, so duplicate/stale lines are prevented automatically. If output still looks garbled in SSH (repeated lines), run `/config rich_live=false` to fully disable Rich Live streaming. --- @@ -1901,7 +1901,7 @@ If both `telegram_token` and `telegram_chat_id` are set in `~/.cheetahclaws/conf ## ๋Šฅ๋™ํ˜• ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋ชจ๋‹ˆํ„ฐ๋ง -CheetahClaws v3.05.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. +CheetahClaws v3.5.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. ### ๋น ๋ฅธ ์‹œ์ž‘ @@ -2250,7 +2250,7 @@ Resume a specific file: ## ํด๋ผ์šฐ๋“œ ๋™๊ธฐํ™” (GitHub Gist) -CheetahClaws v3.05.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. +CheetahClaws v3.5.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. ### ์„ค์ • (1ํšŒ) @@ -2362,7 +2362,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT: faster-whisper โ†’ openai-whisper โ†’ OpenAI API โ”‚ โ””โ”€โ”€ keyterms.py # Coding-domain vocab from git branch + project files โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Public API exports โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # File-level backup, snapshot persistence, rewind, cleanup diff --git a/docs/i18n/README.PT.MD b/docs/i18n/README.PT.MD index 5be336cd..6e37bd16 100644 --- a/docs/i18n/README.PT.MD +++ b/docs/i18n/README.PT.MD @@ -76,7 +76,7 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ Novidades (horรกrio do Pacรญfico) -- Apr 07, 2026 (**v3.05.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** +- Apr 07, 2026 (**v3.5.53**): **Telegram photo/voice support, process-tree kill on Bash timeout, Windows shell hints, worker fix** - **Telegram photo vision** โ€” send a photo to the Telegram bridge and CheetahClaws will describe it using the active vision model (GPT-4o, Gemini 2.0 Flash, Claude, etc.). The bot downloads the highest-resolution version, encodes it as Base64, and routes it through the same `_pending_image` path as `/img`. Caption text (or a default "describe this image" prompt) is forwarded alongside the image. - **Telegram voice/audio STT** โ€” send a voice message or audio file to the Telegram bridge and CheetahClaws transcribes it automatically. OGG voice notes are converted to PCM via `ffmpeg` and passed to the local Whisper backend; falls back to the OpenAI Whisper API when `ffmpeg` is unavailable. The transcription is echoed back to the chat before being submitted as a query. - **Process-tree kill on Bash timeout** โ€” when a `Bash` command times out, CheetahClaws now kills the entire child process tree instead of only the shell. On Unix, `os.killpg` sends `SIGKILL` to the process group; on Windows, `taskkill /F /T` terminates all child processes. GUI apps (e.g. PyQt games launched by the agent) no longer leave zombie processes after a timeout. The internal implementation uses `start_new_session=True` instead of `preexec_fn=os.setsid` for thread safety. @@ -85,20 +85,20 @@ English | [ไธญๆ–‡](README.CN.MD) | [Franรงais](README.FR.MD) | [ํ•œ๊ตญ์–ด](READM - **Bash timeout hints** โ€” the `Bash` tool description now advises the model to use `timeout=120โ€“300` for slow commands (`npm install`, `npx`, `pip install`, builds), reducing spurious 30-second timeouts on package operations. - **Bug fix: background event prompt shows actual cwd** โ€” the yellow re-prompt printed after a background event completed was hardcoded to `[claude-code-local]`; it now shows the real working-directory name (`[{cwd.name}]`), consistent with the main REPL prompt. -- Apr 06, 2026 (**v3.05.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** +- Apr 06, 2026 (**v3.5.53**): **Telegram interactive menus, `/img` alias, `/voice device`, OpenAI/Gemini vision support** - **Telegram interactive menus fixed** โ€” slash commands with interactive input (e.g. `/ollama`, `/permission`, `/checkpoint`) were blocking the Telegram poll loop, making it impossible to respond to the menu prompts. Slash commands now run in a daemon thread (like regular queries), keeping the poll loop free. All interactive menus (`ask_input_interactive`) work correctly over Telegram. - **`/img` alias** โ€” `/img` is now an alias for `/image`, for faster clipboard-image workflows. - **`/voice device`** โ€” new subcommand to list all available input microphones and select one interactively. The selected device index is persisted in the session config and shown in `/voice status`. Useful on systems with multiple audio interfaces (e.g. USB headset + built-in mic). - **Vision support for OpenAI / Gemini models** โ€” `/img` (and `/image`) now sends images in the OpenAI multipart `image_url` format to cloud vision models (GPT-4o, Gemini 2.0 Flash, etc.), in addition to the existing Ollama native format. No configuration change needed โ€” the correct format is selected automatically based on the active provider. - **Bug fix: threading race condition** โ€” `_in_telegram_turn` is now tracked via `threading.local()` per-slash-runner thread instead of a shared config key, eliminating a race condition that could corrupt the flag when a regular message arrived while an interactive slash command was waiting for input. -- Apr 06, 2026 (**v3.05.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** +- Apr 06, 2026 (**v3.5.52**): **Checkpoint system, plan mode, compact, and utility commands, support MiniMax Models, fix telegram bugs** - **Checkpoint system** (`checkpoint/` package): auto-snapshots conversation state and file changes after every turn. `/checkpoint` lists all snapshots; `/checkpoint ` rewinds both files and conversation history to any previous state; `/checkpoint clear` removes all snapshots for the session. `/rewind` is an alias. 100-snapshot sliding window; initial snapshot captured at session start. Throttling: skips when nothing changed. File backups use copy-on-write; snapshots capture post-edit state. - **Plan mode**: `/plan ` enters a read-only analysis mode โ€” Claude may only read the codebase and write to a dedicated plan file (`.nano_claude/plans/.md`). All other writes are silently blocked with a helpful message. `/plan` shows the current plan; `/plan done` exits plan mode and restores original permissions; `/plan status` reports whether plan mode is active. Two new agent tools โ€” `EnterPlanMode` and `ExitPlanMode` โ€” let Claude autonomously enter and exit plan mode for complex multi-file tasks; both are auto-approved in all permission modes. - **`/compact [focus]`**: manually trigger conversation compaction at any time. An optional focus string guides the LLM summarizer on what context to preserve. Auto-compact and manual compact both restore plan file context after compaction. - **Utility commands**: `/init` creates a `CLAUDE.md` template in the current directory; `/export [filename]` exports the conversation as Markdown (default) or JSON; `/copy` copies the last assistant response to the clipboard (Windows/macOS/Linux); `/status` shows version, model, provider, permissions, session ID, token usage, and context %; `/doctor` diagnoses installation health (Python version, git, API key + live connectivity test, optional deps, CLAUDE.md presence, checkpoint disk usage, permission mode). -- Apr 06, 2026 (**v3.05.51**): **Project renamed from Nano Claude Code to CheetahClaws** +- Apr 06, 2026 (**v3.5.51**): **Project renamed from Nano Claude Code to CheetahClaws** - The project has been rebranded from **Nano Claude Code** to **CheetahClaws** โ€” a more distinctive name that captures the spirit of the tool: a sharp, agile coding assistant. The `Cl` in CheetahClaws is a subtle nod to Claude. - CLI command: `nano_claude` โ†’ `cheetahclaws` - PyPI package: `nano-claude-code` โ†’ `cheetahclaws` @@ -1665,7 +1665,7 @@ Generating diverse perspectives... - Brainstorm uses the **currently selected model** (`/model` to check). A capable model (Claude Sonnet/Opus, GPT-4o, or a large local model) gives the best results. - With many agents (20+) the session can take several minutes depending on model speed. - Install `faker` (`pip install faker`) for randomized persona names; falls back to built-in names otherwise. -- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.05.5. +- Output files accumulate in `brainstorm_outputs/` โ€” already added to `.gitignore` by v3.5.5. - Long responses keep rendering live but show only the most recent screenful (a bounded tail window) until they finish, so duplicate/stale lines are prevented automatically. If output still looks garbled in SSH (repeated lines), run `/config rich_live=false` to fully disable Rich Live streaming. --- @@ -1902,7 +1902,7 @@ If both `telegram_token` and `telegram_chat_id` are set in `~/.cheetahclaws/conf ## Monitoramento proativo em segundo plano -CheetahClaws v3.05.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. +CheetahClaws v3.5.2 adds a **sentinel daemon** that automatically wakes the agent after a configurable period of inactivity โ€” no user prompt required. This enables use cases like continuous log monitoring, market script polling, or scheduled code checks. ### Inรญcio rรกpido @@ -2251,7 +2251,7 @@ Resume a specific file: ## Sincronizaรงรฃo na nuvem (GitHub Gist) -CheetahClaws v3.05.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. +CheetahClaws v3.5.3 adds optional cloud backup of conversation sessions via **GitHub Gist**. Sessions are stored as private Gists (JSON), browsable in the GitHub UI. No extra dependencies โ€” uses Python's stdlib `urllib`. ### Configuraรงรฃo (uma vez) @@ -2363,7 +2363,7 @@ cheetahclaws/ โ”‚ โ”œโ”€โ”€ stt.py # STT: faster-whisper โ†’ openai-whisper โ†’ OpenAI API โ”‚ โ””โ”€โ”€ keyterms.py # Coding-domain vocab from git branch + project files โ”‚ -โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.05.6) +โ”œโ”€โ”€ checkpoint/ # Checkpoint system (v3.5.6) โ”‚ โ”œโ”€โ”€ __init__.py # Public API exports โ”‚ โ”œโ”€โ”€ types.py # FileBackup + Snapshot dataclasses; MAX_SNAPSHOTS = 100 โ”‚ โ”œโ”€โ”€ store.py # File-level backup, snapshot persistence, rewind, cleanup diff --git a/docs/media/casts/brainstorm.cast b/docs/media/casts/brainstorm.cast index de61c91b..aa827cf7 100644 --- a/docs/media/casts/brainstorm.cast +++ b/docs/media/casts/brainstorm.cast @@ -1,6 +1,6 @@ {"version": 2, "width": 110, "height": 32, "timestamp": 1747262400, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}, "title": "CheetahClaws /brainstorm \u2014 5 personas debate event sourcing", "idle_time_limit": 1.5} [0.0, "o", "[32m~/projects/checkout[0m [36m\u276f[0m cheetahclaws\r\n"] -[0.3, "o", "[2m[CheetahClaws v3.05.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] +[0.3, "o", "[2m[CheetahClaws v3.5.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] [0.5, "o", "[1m[36m[checkout] \u00bb[0m "] [1.0, "o", ""] [1.05, "o", "/"] diff --git a/docs/media/casts/brainstorm.svg b/docs/media/casts/brainstorm.svg index 3f6da293..1dfd69ca 100644 --- a/docs/media/casts/brainstorm.svg +++ b/docs/media/casts/brainstorm.svg @@ -1 +1 @@ -[32m~/projects/checkout[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.05.79ยทclaude-sonnet-4-6][0m[1m[36m[checkout]ยป[0m[1m[36m[checkout]ยป[0m/brainstorm[1m[36m[checkout]ยป[0m/brainstorm"Should[1m[36m[checkout]ยป[0m/brainstorm"Shouldwe[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigrate[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratethe[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorder[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservice[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicefrom[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUD[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDto[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoevent[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcing?"[2mโ—Spawning5expertpersonasinparallelโ€ฆ[0m[34mโ—[ARCHITECT][0mEventsourcingmapscleanlytocheckout'sdomainโ€”everystatechangeisalreadyanevent(cart-added,payment-authorised,fulfilled).Wegetaudittrail,time-traveldebugging,andreplayforfree.[31mโ—[SKEPTIC][0mThreemonthsofdevtimetorewritesomethingthatworksfine.Where'stheuser-facingwin?You'retradingaknownboringsolutionforafashionableonewe'llregretin18monthswhentheleadarchitectleaves.[35mโ—[PRAGMATIST][0mHalfwaycompromise:keepCRUDasthesourceoftruth,emitanoutboxeventoneachwrite.Wegettheauditlogwithouttherewrite.DoorsstayopenforfullESlater.[33mโ—[DBA][0mTworealissueswiththeproposal:(1)Postgresevent-storethroughputonthecheckoutvolumeโ€”we'dneedpartitioningbytenant;(2)projectionslagwillsurfaceasstalereadsduringBlackFriday.[32mโ—[PM][0mWhatproblemareweactuallysolving?Ifit'saudit/complianceโ€”outboxpatternisenough.Ifit'stheanalyticsteamrebuildingcartfunnelseveryquarterโ€”yes,ESpaysoff.[2mโ—Round2:rebuttalsโ€ฆ[0mโ†’ARCHITECT:'time-traveldebuggingforfree'hasneverbeenfreeinproduction.Snapshotmanagementaloneisaquarterofwork.โ†’SKEPTIC:agreedonsnapshotsโ€”butDBA'soutboxpathishalf-measure.Onceweduplicatestateweowntwotruths.โ†’Both:outboxisnotahalf-measureifwetreatitasasteppingstonewithasix-monthreviewgate.[1mโ”€โ”€โ”€Synthesisโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€[0m[32m[1mConsensus:[0mnofullmigrationthisquarter.Shipoutbox+replayerfirst.[1mDecisionpivotsonPM'sframing:[0mโ€ขaudit/complianceonlyโ†’[32mstayCRUD+outboxevents[0mโ€ขanalyticsrebuildeveryquarterโ†’[33mplanfullES,butinQ3[0m[33m[Write][0mbrainstorm_outputs/todo_list.txt[32m1.[0m[2m[][0mAddoutboxtable+transactionaleventpublisher(1week)[32m2.[0m[2m[][0mWireKafkaconsumerโ†’analyticswarehouse(3days)[32m3.[0m[2m[][0mBenchmarkprojectionlagwithprod-shapedBlack-Fridayreplay[32m4.[0m[2m[][0mScheduleQ3ESdecisionreview(compliance+analyticsinputs)[32mโœ“[0m4tasksready.Run[36m/worker[0mtoauto-implementthem.[1m[36m[checkout]ยป[0m/[1m[36m[checkout]ยป[0m/b[1m[36m[checkout]ยป[0m/br[1m[36m[checkout]ยป[0m/bra[1m[36m[checkout]ยป[0m/brai[1m[36m[checkout]ยป[0m/brain[1m[36m[checkout]ยป[0m/brains[1m[36m[checkout]ยป[0m/brainst[1m[36m[checkout]ยป[0m/brainsto[1m[36m[checkout]ยป[0m/brainstor[1m[36m[checkout]ยป[0m/brainstorm"[1m[36m[checkout]ยป[0m/brainstorm"S[1m[36m[checkout]ยป[0m/brainstorm"Sh[1m[36m[checkout]ยป[0m/brainstorm"Sho[1m[36m[checkout]ยป[0m/brainstorm"Shou[1m[36m[checkout]ยป[0m/brainstorm"Shoul[1m[36m[checkout]ยป[0m/brainstorm"Shouldw[1m[36m[checkout]ยป[0m/brainstorm"Shouldwem[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemi[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemig[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigr[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigra[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigrat[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratet[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigrateth[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheo[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheor[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheord[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorde[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorders[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderse[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderser[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderserv[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservi[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservic[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicef[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicefr[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicefro[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromC[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCR[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRU[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDt[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoe[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoev[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeve[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeven[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoevents[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventso[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsou[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsour[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourc[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourci[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcin[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcing[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcing? \ No newline at end of file +[32m~/projects/checkout[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.5.79ยทclaude-sonnet-4-6][0m[1m[36m[checkout]ยป[0m[1m[36m[checkout]ยป[0m/brainstorm[1m[36m[checkout]ยป[0m/brainstorm"Should[1m[36m[checkout]ยป[0m/brainstorm"Shouldwe[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigrate[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratethe[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorder[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservice[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicefrom[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUD[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDto[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoevent[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcing?"[2mโ—Spawning5expertpersonasinparallelโ€ฆ[0m[34mโ—[ARCHITECT][0mEventsourcingmapscleanlytocheckout'sdomainโ€”everystatechangeisalreadyanevent(cart-added,payment-authorised,fulfilled).Wegetaudittrail,time-traveldebugging,andreplayforfree.[31mโ—[SKEPTIC][0mThreemonthsofdevtimetorewritesomethingthatworksfine.Where'stheuser-facingwin?You'retradingaknownboringsolutionforafashionableonewe'llregretin18monthswhentheleadarchitectleaves.[35mโ—[PRAGMATIST][0mHalfwaycompromise:keepCRUDasthesourceoftruth,emitanoutboxeventoneachwrite.Wegettheauditlogwithouttherewrite.DoorsstayopenforfullESlater.[33mโ—[DBA][0mTworealissueswiththeproposal:(1)Postgresevent-storethroughputonthecheckoutvolumeโ€”we'dneedpartitioningbytenant;(2)projectionslagwillsurfaceasstalereadsduringBlackFriday.[32mโ—[PM][0mWhatproblemareweactuallysolving?Ifit'saudit/complianceโ€”outboxpatternisenough.Ifit'stheanalyticsteamrebuildingcartfunnelseveryquarterโ€”yes,ESpaysoff.[2mโ—Round2:rebuttalsโ€ฆ[0mโ†’ARCHITECT:'time-traveldebuggingforfree'hasneverbeenfreeinproduction.Snapshotmanagementaloneisaquarterofwork.โ†’SKEPTIC:agreedonsnapshotsโ€”butDBA'soutboxpathishalf-measure.Onceweduplicatestateweowntwotruths.โ†’Both:outboxisnotahalf-measureifwetreatitasasteppingstonewithasix-monthreviewgate.[1mโ”€โ”€โ”€Synthesisโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€[0m[32m[1mConsensus:[0mnofullmigrationthisquarter.Shipoutbox+replayerfirst.[1mDecisionpivotsonPM'sframing:[0mโ€ขaudit/complianceonlyโ†’[32mstayCRUD+outboxevents[0mโ€ขanalyticsrebuildeveryquarterโ†’[33mplanfullES,butinQ3[0m[33m[Write][0mbrainstorm_outputs/todo_list.txt[32m1.[0m[2m[][0mAddoutboxtable+transactionaleventpublisher(1week)[32m2.[0m[2m[][0mWireKafkaconsumerโ†’analyticswarehouse(3days)[32m3.[0m[2m[][0mBenchmarkprojectionlagwithprod-shapedBlack-Fridayreplay[32m4.[0m[2m[][0mScheduleQ3ESdecisionreview(compliance+analyticsinputs)[32mโœ“[0m4tasksready.Run[36m/worker[0mtoauto-implementthem.[1m[36m[checkout]ยป[0m/[1m[36m[checkout]ยป[0m/b[1m[36m[checkout]ยป[0m/br[1m[36m[checkout]ยป[0m/bra[1m[36m[checkout]ยป[0m/brai[1m[36m[checkout]ยป[0m/brain[1m[36m[checkout]ยป[0m/brains[1m[36m[checkout]ยป[0m/brainst[1m[36m[checkout]ยป[0m/brainsto[1m[36m[checkout]ยป[0m/brainstor[1m[36m[checkout]ยป[0m/brainstorm"[1m[36m[checkout]ยป[0m/brainstorm"S[1m[36m[checkout]ยป[0m/brainstorm"Sh[1m[36m[checkout]ยป[0m/brainstorm"Sho[1m[36m[checkout]ยป[0m/brainstorm"Shou[1m[36m[checkout]ยป[0m/brainstorm"Shoul[1m[36m[checkout]ยป[0m/brainstorm"Shouldw[1m[36m[checkout]ยป[0m/brainstorm"Shouldwem[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemi[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemig[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigr[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigra[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigrat[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratet[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigrateth[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheo[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheor[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheord[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorde[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorders[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderse[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderser[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderserv[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservi[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservic[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicef[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicefr[1m[36m[checkout]ยป[0m/brainstorm"Shouldwemigratetheorderservicefro[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromC[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCR[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRU[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDt[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoe[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoev[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeve[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeven[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoevents[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventso[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsou[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsour[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourc[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourci[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcin[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcing[1m[36m[checkout]ยป[0m/brainstorm"ShouldwemigratetheorderservicefromCRUDtoeventsourcing? \ No newline at end of file diff --git a/docs/media/casts/code_review.cast b/docs/media/casts/code_review.cast index 9700b3fe..2f9a3dec 100644 --- a/docs/media/casts/code_review.cast +++ b/docs/media/casts/code_review.cast @@ -14,7 +14,7 @@ [1.254, "o", "w"] [1.3, "o", "s"] [1.7, "o", "\r\n"] -[2.0, "o", "[2m[CheetahClaws v3.05.79 \u00b7 claude-sonnet-4-6 \u00b7 auto mode][0m\r\n"] +[2.0, "o", "[2m[CheetahClaws v3.5.79 \u00b7 claude-sonnet-4-6 \u00b7 auto mode][0m\r\n"] [2.2, "o", "[2mType /help for commands, /model to switch, !cmd for shell, Ctrl+C to quit[0m\r\n\r\n"] [2.4, "o", "[1m[36m[project] \u00bb[0m "] [3.0, "o", ""] diff --git a/docs/media/casts/code_review.svg b/docs/media/casts/code_review.svg index 2046de52..1defa9cf 100644 --- a/docs/media/casts/code_review.svg +++ b/docs/media/casts/code_review.svg @@ -1 +1 @@ -[32m~/projects/parser[0m[36mโฏ[0m[32m~/projects/parser[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.05.79ยทclaude-sonnet-4-6ยทautomode][0m[2mType/helpforcommands,/modeltoswitch,!cmdforshell,Ctrl+Ctoquit[0m[1m[36m[project]ยป[0m[1m[36m[project]ยป[0mWhy[1m[36m[project]ยป[0mWhyis[1m[36m[project]ยป[0mWhyisparse_logs()[1m[36m[project]ยป[0mWhyisparse_logs()so[1m[36m[project]ยป[0mWhyisparse_logs()soslow[1m[36m[project]ยป[0mWhyisparse_logs()soslowon[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GB[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsample[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profile[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileand[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfix[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfixit.[2mโ—Readingthefunctionandtracinghotspotsโ€ฆ[0m[33m[Read][0msrc/parser.py[2m(187lines)[0m[33m[Grep][0m'for.*in'src/parser.py[2m(7matches)[0m[33m[Bash][0mpython-Ximporttime-c'fromparserimportparse_logs;parse_logs("sample.log")'[2mreal18.42suser17.99ssys0.41s[0m[1mFoundthehotpath:[0m[31mline84[0m[2mre.compile(PATTERN)[0mcalledinsidetheloop[31mline97[0m[2mresult+=line[0mstringconcatenationinO(nยฒ)[31mline112[0m[2mopen(path).read()[0mloadsthewhole1GBintoRAM[1m3fixeswillbringitunder2seconds.[0mI'llshowthembeforeapplying.[1m[36m[project]ยป[0m/model[1m[36m[project]ยป[0m/modelollama/qwen2.5-coder[32mโœ“[0mSwitchedto[1mollama/qwen2.5-coder[0m[2m(local,$0/call)[0m[1m[36m[project]ยป[0mapply[1m[36m[project]ยป[0mapplyall[1m[36m[project]ยป[0mapplyallthree[1m[36m[project]ยป[0mapplyallthreefixes[33m[Edit][0msrc/parser.py[31m-PATTERN=r"\\[(\\d{4}-\\d{2}-\\d{2})\\](.*)"[0m[31m-defparse_logs(path):[0m[31m-forlineinopen(path).read().splitlines():[0m[31m-m=re.compile(PATTERN).match(line)[0m[32m+_PATTERN_RE=re.compile(r"\\[(\\d{4}-\\d{2}-\\d{2})\\](.*)")[0m[32m+defparse_logs(path):[0m[32m+out=[][0m[32m+withopen(path)asfh:[0m[32m+forlineinfh:[0m[32m+m=_PATTERN_RE.match(line)[0m[32mโœ“[0m1filechanged,9insertions(+),4deletions(-).[33m[Bash][0mpython-c'fromparserimportparse_logs;parse_logs("sample.log")'[2mreal1.62suser1.51ssys0.09s[0m[32mโ†“11ร—[0m[32m~/projects/parser[0m[36mโฏ[0mc[32m~/projects/parser[0m[36mโฏ[0mch[32m~/projects/parser[0m[36mโฏ[0mche[32m~/projects/parser[0m[36mโฏ[0mchee[32m~/projects/parser[0m[36mโฏ[0mcheet[32m~/projects/parser[0m[36mโฏ[0mcheeta[32m~/projects/parser[0m[36mโฏ[0mcheetah[32m~/projects/parser[0m[36mโฏ[0mcheetahc[32m~/projects/parser[0m[36mโฏ[0mcheetahcl[32m~/projects/parser[0m[36mโฏ[0mcheetahcla[32m~/projects/parser[0m[36mโฏ[0mcheetahclaw[1m[36m[project]ยป[0mW[1m[36m[project]ยป[0mWh[1m[36m[project]ยป[0mWhyi[1m[36m[project]ยป[0mWhyisp[1m[36m[project]ยป[0mWhyispa[1m[36m[project]ยป[0mWhyispar[1m[36m[project]ยป[0mWhyispars[1m[36m[project]ยป[0mWhyisparse[1m[36m[project]ยป[0mWhyisparse_[1m[36m[project]ยป[0mWhyisparse_l[1m[36m[project]ยป[0mWhyisparse_lo[1m[36m[project]ยป[0mWhyisparse_log[1m[36m[project]ยป[0mWhyisparse_logs[1m[36m[project]ยป[0mWhyisparse_logs([1m[36m[project]ยป[0mWhyisparse_logs()s[1m[36m[project]ยป[0mWhyisparse_logs()sos[1m[36m[project]ยป[0mWhyisparse_logs()sosl[1m[36m[project]ยป[0mWhyisparse_logs()soslo[1m[36m[project]ยป[0mWhyisparse_logs()soslowo[1m[36m[project]ยป[0mWhyisparse_logs()soslowont[1m[36m[project]ยป[0mWhyisparse_logs()soslowonth[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1G[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBs[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsa[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsam[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamp[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsampl[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplef[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefil[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?P[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Pr[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Pro[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Prof[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profil[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profilea[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profilean[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandf[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfixi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfixit[1m[36m[project]ยป[0m/[1m[36m[project]ยป[0m/m[1m[36m[project]ยป[0m/mo[1m[36m[project]ยป[0m/mod[1m[36m[project]ยป[0m/mode[1m[36m[project]ยป[0m/modelo[1m[36m[project]ยป[0m/modelol[1m[36m[project]ยป[0m/modeloll[1m[36m[project]ยป[0m/modelolla[1m[36m[project]ยป[0m/modelollam[1m[36m[project]ยป[0m/modelollama[1m[36m[project]ยป[0m/modelollama/[1m[36m[project]ยป[0m/modelollama/q[1m[36m[project]ยป[0m/modelollama/qw[1m[36m[project]ยป[0m/modelollama/qwe[1m[36m[project]ยป[0m/modelollama/qwen[1m[36m[project]ยป[0m/modelollama/qwen2[1m[36m[project]ยป[0m/modelollama/qwen2.[1m[36m[project]ยป[0m/modelollama/qwen2.5[1m[36m[project]ยป[0m/modelollama/qwen2.5-[1m[36m[project]ยป[0m/modelollama/qwen2.5-c[1m[36m[project]ยป[0m/modelollama/qwen2.5-co[1m[36m[project]ยป[0m/modelollama/qwen2.5-cod[1m[36m[project]ยป[0m/modelollama/qwen2.5-code[1m[36m[project]ยป[0ma[1m[36m[project]ยป[0map[1m[36m[project]ยป[0mapp[1m[36m[project]ยป[0mappl[1m[36m[project]ยป[0mapplya[1m[36m[project]ยป[0mapplyal[1m[36m[project]ยป[0mapplyallt[1m[36m[project]ยป[0mapplyallth[1m[36m[project]ยป[0mapplyallthr[1m[36m[project]ยป[0mapplyallthre[1m[36m[project]ยป[0mapplyallthreef[1m[36m[project]ยป[0mapplyallthreefi[1m[36m[project]ยป[0mapplyallthreefix[1m[36m[project]ยป[0mapplyallthreefixe \ No newline at end of file +[32m~/projects/parser[0m[36mโฏ[0m[32m~/projects/parser[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.5.79ยทclaude-sonnet-4-6ยทautomode][0m[2mType/helpforcommands,/modeltoswitch,!cmdforshell,Ctrl+Ctoquit[0m[1m[36m[project]ยป[0m[1m[36m[project]ยป[0mWhy[1m[36m[project]ยป[0mWhyis[1m[36m[project]ยป[0mWhyisparse_logs()[1m[36m[project]ยป[0mWhyisparse_logs()so[1m[36m[project]ยป[0mWhyisparse_logs()soslow[1m[36m[project]ยป[0mWhyisparse_logs()soslowon[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GB[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsample[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profile[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileand[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfix[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfixit.[2mโ—Readingthefunctionandtracinghotspotsโ€ฆ[0m[33m[Read][0msrc/parser.py[2m(187lines)[0m[33m[Grep][0m'for.*in'src/parser.py[2m(7matches)[0m[33m[Bash][0mpython-Ximporttime-c'fromparserimportparse_logs;parse_logs("sample.log")'[2mreal18.42suser17.99ssys0.41s[0m[1mFoundthehotpath:[0m[31mline84[0m[2mre.compile(PATTERN)[0mcalledinsidetheloop[31mline97[0m[2mresult+=line[0mstringconcatenationinO(nยฒ)[31mline112[0m[2mopen(path).read()[0mloadsthewhole1GBintoRAM[1m3fixeswillbringitunder2seconds.[0mI'llshowthembeforeapplying.[1m[36m[project]ยป[0m/model[1m[36m[project]ยป[0m/modelollama/qwen2.5-coder[32mโœ“[0mSwitchedto[1mollama/qwen2.5-coder[0m[2m(local,$0/call)[0m[1m[36m[project]ยป[0mapply[1m[36m[project]ยป[0mapplyall[1m[36m[project]ยป[0mapplyallthree[1m[36m[project]ยป[0mapplyallthreefixes[33m[Edit][0msrc/parser.py[31m-PATTERN=r"\\[(\\d{4}-\\d{2}-\\d{2})\\](.*)"[0m[31m-defparse_logs(path):[0m[31m-forlineinopen(path).read().splitlines():[0m[31m-m=re.compile(PATTERN).match(line)[0m[32m+_PATTERN_RE=re.compile(r"\\[(\\d{4}-\\d{2}-\\d{2})\\](.*)")[0m[32m+defparse_logs(path):[0m[32m+out=[][0m[32m+withopen(path)asfh:[0m[32m+forlineinfh:[0m[32m+m=_PATTERN_RE.match(line)[0m[32mโœ“[0m1filechanged,9insertions(+),4deletions(-).[33m[Bash][0mpython-c'fromparserimportparse_logs;parse_logs("sample.log")'[2mreal1.62suser1.51ssys0.09s[0m[32mโ†“11ร—[0m[32m~/projects/parser[0m[36mโฏ[0mc[32m~/projects/parser[0m[36mโฏ[0mch[32m~/projects/parser[0m[36mโฏ[0mche[32m~/projects/parser[0m[36mโฏ[0mchee[32m~/projects/parser[0m[36mโฏ[0mcheet[32m~/projects/parser[0m[36mโฏ[0mcheeta[32m~/projects/parser[0m[36mโฏ[0mcheetah[32m~/projects/parser[0m[36mโฏ[0mcheetahc[32m~/projects/parser[0m[36mโฏ[0mcheetahcl[32m~/projects/parser[0m[36mโฏ[0mcheetahcla[32m~/projects/parser[0m[36mโฏ[0mcheetahclaw[1m[36m[project]ยป[0mW[1m[36m[project]ยป[0mWh[1m[36m[project]ยป[0mWhyi[1m[36m[project]ยป[0mWhyisp[1m[36m[project]ยป[0mWhyispa[1m[36m[project]ยป[0mWhyispar[1m[36m[project]ยป[0mWhyispars[1m[36m[project]ยป[0mWhyisparse[1m[36m[project]ยป[0mWhyisparse_[1m[36m[project]ยป[0mWhyisparse_l[1m[36m[project]ยป[0mWhyisparse_lo[1m[36m[project]ยป[0mWhyisparse_log[1m[36m[project]ยป[0mWhyisparse_logs[1m[36m[project]ยป[0mWhyisparse_logs([1m[36m[project]ยป[0mWhyisparse_logs()s[1m[36m[project]ยป[0mWhyisparse_logs()sos[1m[36m[project]ยป[0mWhyisparse_logs()sosl[1m[36m[project]ยป[0mWhyisparse_logs()soslo[1m[36m[project]ยป[0mWhyisparse_logs()soslowo[1m[36m[project]ยป[0mWhyisparse_logs()soslowont[1m[36m[project]ยป[0mWhyisparse_logs()soslowonth[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1G[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBs[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsa[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsam[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamp[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsampl[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplef[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefil[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?P[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Pr[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Pro[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Prof[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profil[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profilea[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profilean[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandf[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfixi[1m[36m[project]ยป[0mWhyisparse_logs()soslowonthe1GBsamplefile?Profileandfixit[1m[36m[project]ยป[0m/[1m[36m[project]ยป[0m/m[1m[36m[project]ยป[0m/mo[1m[36m[project]ยป[0m/mod[1m[36m[project]ยป[0m/mode[1m[36m[project]ยป[0m/modelo[1m[36m[project]ยป[0m/modelol[1m[36m[project]ยป[0m/modeloll[1m[36m[project]ยป[0m/modelolla[1m[36m[project]ยป[0m/modelollam[1m[36m[project]ยป[0m/modelollama[1m[36m[project]ยป[0m/modelollama/[1m[36m[project]ยป[0m/modelollama/q[1m[36m[project]ยป[0m/modelollama/qw[1m[36m[project]ยป[0m/modelollama/qwe[1m[36m[project]ยป[0m/modelollama/qwen[1m[36m[project]ยป[0m/modelollama/qwen2[1m[36m[project]ยป[0m/modelollama/qwen2.[1m[36m[project]ยป[0m/modelollama/qwen2.5[1m[36m[project]ยป[0m/modelollama/qwen2.5-[1m[36m[project]ยป[0m/modelollama/qwen2.5-c[1m[36m[project]ยป[0m/modelollama/qwen2.5-co[1m[36m[project]ยป[0m/modelollama/qwen2.5-cod[1m[36m[project]ยป[0m/modelollama/qwen2.5-code[1m[36m[project]ยป[0ma[1m[36m[project]ยป[0map[1m[36m[project]ยป[0mapp[1m[36m[project]ยป[0mappl[1m[36m[project]ยป[0mapplya[1m[36m[project]ยป[0mapplyal[1m[36m[project]ยป[0mapplyallt[1m[36m[project]ยป[0mapplyallth[1m[36m[project]ยป[0mapplyallthr[1m[36m[project]ยป[0mapplyallthre[1m[36m[project]ยป[0mapplyallthreef[1m[36m[project]ยป[0mapplyallthreefi[1m[36m[project]ยป[0mapplyallthreefix[1m[36m[project]ยป[0mapplyallthreefixe \ No newline at end of file diff --git a/docs/media/casts/gen_brainstorm.py b/docs/media/casts/gen_brainstorm.py index 11ff0ab1..3e5e3ef2 100644 --- a/docs/media/casts/gen_brainstorm.py +++ b/docs/media/casts/gen_brainstorm.py @@ -49,7 +49,7 @@ def type_string(s, base=0.04, jitter=0.02): # Scene 1 โ€” launch + /brainstorm out(0.0, f"{GREEN}~/projects/checkout{RST} {CYAN}โฏ{RST} cheetahclaws\r\n") -out(0.3, f"{DIM}[CheetahClaws v3.05.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") +out(0.3, f"{DIM}[CheetahClaws v3.5.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") out(0.2, f"{BOLD}{CYAN}[checkout] ยป{RST} ") out(0.5, "") type_string("/brainstorm \"Should we migrate the order service from CRUD to event sourcing?\"") diff --git a/docs/media/casts/gen_code_review.py b/docs/media/casts/gen_code_review.py index 1d505561..a1f23e7d 100644 --- a/docs/media/casts/gen_code_review.py +++ b/docs/media/casts/gen_code_review.py @@ -51,7 +51,7 @@ def type_string(s, base=0.04, jitter=0.02): out(0.7, "") type_string("cheetahclaws") out(0.4, "\r\n") -out(0.3, f"{DIM}[CheetahClaws v3.05.79 ยท claude-sonnet-4-6 ยท auto mode]{RST}\r\n") +out(0.3, f"{DIM}[CheetahClaws v3.5.79 ยท claude-sonnet-4-6 ยท auto mode]{RST}\r\n") out(0.2, f"{DIM}Type /help for commands, /model to switch, !cmd for shell, Ctrl+C to quit{RST}\r\n\r\n") out(0.2, f"{BOLD}{CYAN}[project] ยป{RST} ") diff --git a/docs/media/casts/gen_lab.py b/docs/media/casts/gen_lab.py index e4b54062..3adbc804 100644 --- a/docs/media/casts/gen_lab.py +++ b/docs/media/casts/gen_lab.py @@ -50,7 +50,7 @@ def type_string(s, base=0.04, jitter=0.02): # Scene 1 โ€” launch + /lab start out(0.0, f"{GREEN}~{RST} {CYAN}โฏ{RST} cheetahclaws\r\n") -out(0.3, f"{DIM}[CheetahClaws v3.05.79 ยท claude-sonnet-4-6][/lab engine v0]{RST}\r\n\r\n") +out(0.3, f"{DIM}[CheetahClaws v3.5.79 ยท claude-sonnet-4-6][/lab engine v0]{RST}\r\n\r\n") out(0.2, f"{BOLD}{CYAN}[~] ยป{RST} ") out(0.5, "") type_string("/lab start \"Compare logistic regression vs random forest on iris, k-fold CV\"") diff --git a/docs/media/casts/gen_research.py b/docs/media/casts/gen_research.py index 5c82150b..02c10003 100644 --- a/docs/media/casts/gen_research.py +++ b/docs/media/casts/gen_research.py @@ -53,7 +53,7 @@ def type_string(s, base=0.04, jitter=0.02): out(0.6, "") type_string("cheetahclaws") out(0.4, "\r\n") -out(0.3, f"{DIM}[CheetahClaws v3.05.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") +out(0.3, f"{DIM}[CheetahClaws v3.5.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") out(0.2, f"{BOLD}{CYAN}[~] ยป{RST} ") out(0.5, "") type_string("/research \"LLM agents 2026 trends\" --range 6m --expand") diff --git a/docs/media/casts/gen_research_agent.py b/docs/media/casts/gen_research_agent.py index 8af58048..16b8ed4b 100644 --- a/docs/media/casts/gen_research_agent.py +++ b/docs/media/casts/gen_research_agent.py @@ -50,7 +50,7 @@ def type_string(s, base=0.04, jitter=0.02): # Scene 1 โ€” launch + /agent wizard out(0.0, f"{GREEN}~{RST} {CYAN}โฏ{RST} cheetahclaws\r\n") -out(0.3, f"{DIM}[CheetahClaws v3.05.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") +out(0.3, f"{DIM}[CheetahClaws v3.5.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") out(0.2, f"{BOLD}{CYAN}[~] ยป{RST} ") out(0.4, "") type_string("/agent") diff --git a/docs/media/casts/gen_telegram.py b/docs/media/casts/gen_telegram.py index 29b0be78..d2bde36a 100644 --- a/docs/media/casts/gen_telegram.py +++ b/docs/media/casts/gen_telegram.py @@ -50,7 +50,7 @@ def type_string(s, base=0.04, jitter=0.02): # Scene 1 โ€” start the bridge out(0.0, f"{GREEN}~{RST} {CYAN}โฏ{RST} cheetahclaws\r\n") -out(0.3, f"{DIM}[CheetahClaws v3.05.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") +out(0.3, f"{DIM}[CheetahClaws v3.5.79 ยท claude-sonnet-4-6]{RST}\r\n\r\n") out(0.2, f"{BOLD}{CYAN}[~] ยป{RST} ") out(0.5, "") type_string("/telegram 7890:AAEx_REDACTED 458291205") diff --git a/docs/media/casts/lab.cast b/docs/media/casts/lab.cast index 98a9e300..b8f6522c 100644 --- a/docs/media/casts/lab.cast +++ b/docs/media/casts/lab.cast @@ -1,6 +1,6 @@ {"version": 2, "width": 110, "height": 34, "timestamp": 1747262400, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}, "title": "CheetahClaws /lab \u2014 9 agents drive a paper from question to PDF", "idle_time_limit": 1.3} [0.0, "o", "[32m~[0m [36m\u276f[0m cheetahclaws\r\n"] -[0.3, "o", "[2m[CheetahClaws v3.05.79 \u00b7 claude-sonnet-4-6][/lab engine v0][0m\r\n\r\n"] +[0.3, "o", "[2m[CheetahClaws v3.5.79 \u00b7 claude-sonnet-4-6][/lab engine v0][0m\r\n\r\n"] [0.5, "o", "[1m[36m[~] \u00bb[0m "] [1.0, "o", ""] [1.058, "o", "/"] diff --git a/docs/media/casts/lab.svg b/docs/media/casts/lab.svg index 1b2a51aa..21a34aab 100644 --- a/docs/media/casts/lab.svg +++ b/docs/media/casts/lab.svg @@ -1 +1 @@ -[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.05.79ยทclaude-sonnet-4-6][/labenginev0][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/lab[1m[36m[~]ยป[0m/labstart[1m[36m[~]ยป[0m/labstart"Compare[1m[36m[~]ยป[0m/labstart"Comparelogistic[1m[36m[~]ยป[0m/labstart"Comparelogisticregression[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvs[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandom[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforest[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforeston[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-fold[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-foldCV"[32mโœ“[0mLabrun[1mlab_a3b1c8e9f012[0mlaunched.Budget:60minยท200ktokens.[32m[QUESTIONING][0m[34mโ—PI[0m:PickingQ2:'DoesRFoutperformlogisticregressiononirisunder5-foldCV?'[2mโ—LayReader:questionisconcreteandtestable.[0m[32m[SURVEY][0m[35mโ—Surveyor[0m:12papersretrieved;baselinesoniriswell-characterisedsince1936.[32m[OUTLINE][0m[34mโ—Designer[0m:5-sectionoutline:intro,related,method,results,threats.[2mโ—Reviewerร—3critiqueโ†’2pass,1asksforablation;PIsignsoff.[0m[32m[CODE_DRAFT][0m[33mโ—Engineer[0m:scriptedirisloader,GridSearchCVforbothmodels,5-foldstratified.[32m[EXPERIMENT][0m[33mโ—Engineer[0m:Runningsandboxedsubprocessโ€ฆ[2mstdout:BestLRC=10acc=0.967ยฑ0.025[0m[2mstdout:BestRFn=50acc=0.967ยฑ0.033[0m[2msavedfigure_1.png(boxplot),results.csv[0m[32m[ANALYSIS][0m[33mโ—Engineer[0m:Modelstieonaccuracy;RFhashighervariance.RecommendLRfortabularsmall-n.[32m[DRAFTING][0m[36mโ—Drafter[0m:Composed2,840-worddraftwithinline[1]โ€“[12]citations.[32m[REVIEWLOOP][0m[31mโ—Reviewer#1[0m:'Section3.2doesn'taddressclassimbalanceโ€”minorrevision.'[31mโ—Reviewer#2[0m:'Threatssectionthin.Addoverfittingnote.'[32mโ—Reviewer#3[0m:'Accept.'[36mโ—Drafter[0m:revisedยง3.2+ยง6,rebuiltbib.[32mโ—Reviewerร—3[0m:[1m2/3acceptonround2[0mโ†’PIsignsoff.[32m[CITATIONVERIFY][0m[32mโ—CitationChecker[0m:12/12referencesverifiedagainstarXiv/SemanticScholar/CrossRef.[32m[FINALISE][0mBundleready.[32mโœ“[0mOutputat[36m~/.cheetahclaws/research_papers/lab_a3b1c8e9f012/[0mโ”œโ”€โ”€[1mreport.md[0m[2m(2,940words,12refs)[0mโ”œโ”€โ”€references.bib[2m(verifiedBibTeX)[0mโ”œโ”€โ”€citations_verified.jsonโ””โ”€โ”€workspace/โ”œโ”€โ”€experiment.py[2m(83lines)[0mโ”œโ”€โ”€figure_1.png[2m(boxplot)[0mโ””โ”€โ”€results.csv[2m(5foldsร—2models)[0m[2mTotal:22minยท142ktokensยท$1.40inAPIcost[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/l[1m[36m[~]ยป[0m/la[1m[36m[~]ยป[0m/labs[1m[36m[~]ยป[0m/labst[1m[36m[~]ยป[0m/labsta[1m[36m[~]ยป[0m/labstar[1m[36m[~]ยป[0m/labstart"[1m[36m[~]ยป[0m/labstart"C[1m[36m[~]ยป[0m/labstart"Co[1m[36m[~]ยป[0m/labstart"Com[1m[36m[~]ยป[0m/labstart"Comp[1m[36m[~]ยป[0m/labstart"Compa[1m[36m[~]ยป[0m/labstart"Compar[1m[36m[~]ยป[0m/labstart"Comparel[1m[36m[~]ยป[0m/labstart"Comparelo[1m[36m[~]ยป[0m/labstart"Comparelog[1m[36m[~]ยป[0m/labstart"Comparelogi[1m[36m[~]ยป[0m/labstart"Comparelogis[1m[36m[~]ยป[0m/labstart"Comparelogist[1m[36m[~]ยป[0m/labstart"Comparelogisti[1m[36m[~]ยป[0m/labstart"Comparelogisticr[1m[36m[~]ยป[0m/labstart"Comparelogisticre[1m[36m[~]ยป[0m/labstart"Comparelogisticreg[1m[36m[~]ยป[0m/labstart"Comparelogisticregr[1m[36m[~]ยป[0m/labstart"Comparelogisticregre[1m[36m[~]ยป[0m/labstart"Comparelogisticregres[1m[36m[~]ยป[0m/labstart"Comparelogisticregress[1m[36m[~]ยป[0m/labstart"Comparelogisticregressi[1m[36m[~]ยป[0m/labstart"Comparelogisticregressio[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionv[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsr[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsra[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsran[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrand[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrando[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomf[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfo[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfor[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfore[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfores[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforesto[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoni[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestonir[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniri[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-f[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-fo[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-fol[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-foldC[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-foldCV \ No newline at end of file +[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.5.79ยทclaude-sonnet-4-6][/labenginev0][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/lab[1m[36m[~]ยป[0m/labstart[1m[36m[~]ยป[0m/labstart"Compare[1m[36m[~]ยป[0m/labstart"Comparelogistic[1m[36m[~]ยป[0m/labstart"Comparelogisticregression[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvs[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandom[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforest[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforeston[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-fold[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-foldCV"[32mโœ“[0mLabrun[1mlab_a3b1c8e9f012[0mlaunched.Budget:60minยท200ktokens.[32m[QUESTIONING][0m[34mโ—PI[0m:PickingQ2:'DoesRFoutperformlogisticregressiononirisunder5-foldCV?'[2mโ—LayReader:questionisconcreteandtestable.[0m[32m[SURVEY][0m[35mโ—Surveyor[0m:12papersretrieved;baselinesoniriswell-characterisedsince1936.[32m[OUTLINE][0m[34mโ—Designer[0m:5-sectionoutline:intro,related,method,results,threats.[2mโ—Reviewerร—3critiqueโ†’2pass,1asksforablation;PIsignsoff.[0m[32m[CODE_DRAFT][0m[33mโ—Engineer[0m:scriptedirisloader,GridSearchCVforbothmodels,5-foldstratified.[32m[EXPERIMENT][0m[33mโ—Engineer[0m:Runningsandboxedsubprocessโ€ฆ[2mstdout:BestLRC=10acc=0.967ยฑ0.025[0m[2mstdout:BestRFn=50acc=0.967ยฑ0.033[0m[2msavedfigure_1.png(boxplot),results.csv[0m[32m[ANALYSIS][0m[33mโ—Engineer[0m:Modelstieonaccuracy;RFhashighervariance.RecommendLRfortabularsmall-n.[32m[DRAFTING][0m[36mโ—Drafter[0m:Composed2,840-worddraftwithinline[1]โ€“[12]citations.[32m[REVIEWLOOP][0m[31mโ—Reviewer#1[0m:'Section3.2doesn'taddressclassimbalanceโ€”minorrevision.'[31mโ—Reviewer#2[0m:'Threatssectionthin.Addoverfittingnote.'[32mโ—Reviewer#3[0m:'Accept.'[36mโ—Drafter[0m:revisedยง3.2+ยง6,rebuiltbib.[32mโ—Reviewerร—3[0m:[1m2/3acceptonround2[0mโ†’PIsignsoff.[32m[CITATIONVERIFY][0m[32mโ—CitationChecker[0m:12/12referencesverifiedagainstarXiv/SemanticScholar/CrossRef.[32m[FINALISE][0mBundleready.[32mโœ“[0mOutputat[36m~/.cheetahclaws/research_papers/lab_a3b1c8e9f012/[0mโ”œโ”€โ”€[1mreport.md[0m[2m(2,940words,12refs)[0mโ”œโ”€โ”€references.bib[2m(verifiedBibTeX)[0mโ”œโ”€โ”€citations_verified.jsonโ””โ”€โ”€workspace/โ”œโ”€โ”€experiment.py[2m(83lines)[0mโ”œโ”€โ”€figure_1.png[2m(boxplot)[0mโ””โ”€โ”€results.csv[2m(5foldsร—2models)[0m[2mTotal:22minยท142ktokensยท$1.40inAPIcost[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/l[1m[36m[~]ยป[0m/la[1m[36m[~]ยป[0m/labs[1m[36m[~]ยป[0m/labst[1m[36m[~]ยป[0m/labsta[1m[36m[~]ยป[0m/labstar[1m[36m[~]ยป[0m/labstart"[1m[36m[~]ยป[0m/labstart"C[1m[36m[~]ยป[0m/labstart"Co[1m[36m[~]ยป[0m/labstart"Com[1m[36m[~]ยป[0m/labstart"Comp[1m[36m[~]ยป[0m/labstart"Compa[1m[36m[~]ยป[0m/labstart"Compar[1m[36m[~]ยป[0m/labstart"Comparel[1m[36m[~]ยป[0m/labstart"Comparelo[1m[36m[~]ยป[0m/labstart"Comparelog[1m[36m[~]ยป[0m/labstart"Comparelogi[1m[36m[~]ยป[0m/labstart"Comparelogis[1m[36m[~]ยป[0m/labstart"Comparelogist[1m[36m[~]ยป[0m/labstart"Comparelogisti[1m[36m[~]ยป[0m/labstart"Comparelogisticr[1m[36m[~]ยป[0m/labstart"Comparelogisticre[1m[36m[~]ยป[0m/labstart"Comparelogisticreg[1m[36m[~]ยป[0m/labstart"Comparelogisticregr[1m[36m[~]ยป[0m/labstart"Comparelogisticregre[1m[36m[~]ยป[0m/labstart"Comparelogisticregres[1m[36m[~]ยป[0m/labstart"Comparelogisticregress[1m[36m[~]ยป[0m/labstart"Comparelogisticregressi[1m[36m[~]ยป[0m/labstart"Comparelogisticregressio[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionv[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsr[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsra[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsran[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrand[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrando[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomf[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfo[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfor[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfore[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomfores[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforesto[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoni[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestonir[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniri[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-f[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-fo[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-fol[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-foldC[1m[36m[~]ยป[0m/labstart"Comparelogisticregressionvsrandomforestoniris,k-foldCV \ No newline at end of file diff --git a/docs/media/casts/research.cast b/docs/media/casts/research.cast index 11bf25bc..c753461d 100644 --- a/docs/media/casts/research.cast +++ b/docs/media/casts/research.cast @@ -14,7 +14,7 @@ [1.133, "o", "w"] [1.178, "o", "s"] [1.578, "o", "\r\n"] -[1.878, "o", "[2m[CheetahClaws v3.05.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] +[1.878, "o", "[2m[CheetahClaws v3.5.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] [2.078, "o", "[1m[36m[~] \u00bb[0m "] [2.578, "o", ""] [2.623, "o", "/"] diff --git a/docs/media/casts/research.svg b/docs/media/casts/research.svg index 892b4487..1557edee 100644 --- a/docs/media/casts/research.svg +++ b/docs/media/casts/research.svg @@ -1 +1 @@ -[32m~[0m[36mโฏ[0m[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.05.79ยทclaude-sonnet-4-6][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/r[1m[36m[~]ยป[0m/re[1m[36m[~]ยป[0m/research[1m[36m[~]ยป[0m/research"LLM[1m[36m[~]ยป[0m/research"LLMagents[1m[36m[~]ยป[0m/research"LLMagents2026[1m[36m[~]ยป[0m/research"LLMagents2026trends"[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--expand[2mโ—Expandingqueryinto4siblingsub-queriesโ€ฆ[0m[2mโ†ณ[0mautonomouscodingagentsbenchmarks2026[2mโ†ณ[0mmulti-agentdebate/reviewer-authorloops[2mโ†ณ[0magentictooluseplusMCP/functioncalling[2mโ†ณ[0mopen-weightmodelsforagentworkflows[1mFanningoutacross20sourcesinparallelโ€ฆ[0m[32mโœ“[0m[1marXiv[0m[2mโ†’[0m342hits[32mโœ“[0m[1mSemanticScholar[0m[2mโ†’[0m218hits[32mโœ“[0m[1mHuggingFacePapers[0m[2mโ†’[0m176hits[32mโœ“[0m[1mOpenAlex[0m[2mโ†’[0m412hits[32mโœ“[0m[1malphaXiv[0m[2mโ†’[0m84hits[32mโœ“[0m[1mHackerNews[0m[2mโ†’[0m511hits[32mโœ“[0m[1mGitHub[0m[2mโ†’[0m298hits[32mโœ“[0m[1mRedditr/MachineLearning[0m[2mโ†’[0m147hits[32mโœ“[0m[1mStackOverflow[0m[2mโ†’[0m62hits[32mโœ“[0m[1mGoogleNews[0m[2mโ†’[0m203hits[32mโœ“[0m[1mPolymarket[0m[2mโ†’[0m9hits[32mโœ“[0m[1mSECEDGAR[0m[2mโ†’[0m14hits[33mโœ“[0m[1mTwitter/X[0m[2mโ†’[0m1.2khits[32mโœ“[0m[1mBraveSearch[0m[2mโ†’[0m188hits[32mโœ“[0m[1mTavily[0m[2mโ†’[0m151hits[32mโœ“[0m[1mGoogleScholar[0m[2mโ†’[0m224hits[32mโœ“[0m[1m็ŸฅไนŽZhihu[0m[2mโ†’[0m186hits[32mโœ“[0m[1mB็ซ™Bilibili[0m[2mโ†’[0m298hits[33mโœ“[0m[1mๅพฎๅšWeibo[0m[2mโ†’[0m412hits[32mโœ“[0m[1mๅฐ็บขไนฆXiaohongshu[0m[2mโ†’[0m127hits[1mTopentitiesbycross-platformattention:[0m[2mentityarXivHFGHHNๅพฎๅšZhihutotal[0m[2mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€[0m[1mClaude4.6[0m[2m1278432298412186[0m[32m1,139[0m[1mDeepSeekV4[0m[2m108112147176287298[0m[32m1,128[0m[1mQwen3-Coder[0m[2m879221188154287[0m[32m919[0m[1mMCPProtocol[0m[2m42281882476472[0m[32m641[0m[1mLlama4[0m[2m961189420316788[0m[32m766[0m[2mโ—VerifyingcitationsagainstarXiv/SemanticScholar/CrossRefโ€ฆ[0m[32mโœ“[0m47papers,[32m45verified[0m,[31m2flaggedforhallucination[0m[32mโœ“[0mBriefsavedโ†’[36m~/.cheetahclaws/research_reports/llm-agents-2026-trends-17.md[0m[2m3,124wordsยท47citationsยทcross-platformheattableยท12-monthtrendsparkline[0m[1m[36m[~]ยป[0m/reports[1m[36m[~]ยป[0m/reportsopen[2mOpeningllm-agents-2026-trends-19.mdinyoureditorโ€ฆ[0m[32m~[0m[36mโฏ[0mc[32m~[0m[36mโฏ[0mch[32m~[0m[36mโฏ[0mche[32m~[0m[36mโฏ[0mchee[32m~[0m[36mโฏ[0mcheet[32m~[0m[36mโฏ[0mcheeta[32m~[0m[36mโฏ[0mcheetah[32m~[0m[36mโฏ[0mcheetahc[32m~[0m[36mโฏ[0mcheetahcl[32m~[0m[36mโฏ[0mcheetahcla[32m~[0m[36mโฏ[0mcheetahclaw[1m[36m[~]ยป[0m/res[1m[36m[~]ยป[0m/rese[1m[36m[~]ยป[0m/resea[1m[36m[~]ยป[0m/resear[1m[36m[~]ยป[0m/researc[1m[36m[~]ยป[0m/research"[1m[36m[~]ยป[0m/research"L[1m[36m[~]ยป[0m/research"LL[1m[36m[~]ยป[0m/research"LLMa[1m[36m[~]ยป[0m/research"LLMag[1m[36m[~]ยป[0m/research"LLMage[1m[36m[~]ยป[0m/research"LLMagen[1m[36m[~]ยป[0m/research"LLMagent[1m[36m[~]ยป[0m/research"LLMagents2[1m[36m[~]ยป[0m/research"LLMagents20[1m[36m[~]ยป[0m/research"LLMagents202[1m[36m[~]ยป[0m/research"LLMagents2026t[1m[36m[~]ยป[0m/research"LLMagents2026tr[1m[36m[~]ยป[0m/research"LLMagents2026tre[1m[36m[~]ยป[0m/research"LLMagents2026tren[1m[36m[~]ยป[0m/research"LLMagents2026trend[1m[36m[~]ยป[0m/research"LLMagents2026trends[1m[36m[~]ยป[0m/research"LLMagents2026trends"-[1m[36m[~]ยป[0m/research"LLMagents2026trends"--[1m[36m[~]ยป[0m/research"LLMagents2026trends"--r[1m[36m[~]ยป[0m/research"LLMagents2026trends"--ra[1m[36m[~]ยป[0m/research"LLMagents2026trends"--ran[1m[36m[~]ยป[0m/research"LLMagents2026trends"--rang[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m-[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--e[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--ex[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--exp[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--expa[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--expan[1m[36m[~]ยป[0m/rep[1m[36m[~]ยป[0m/repo[1m[36m[~]ยป[0m/repor[1m[36m[~]ยป[0m/report[1m[36m[~]ยป[0m/reportso[1m[36m[~]ยป[0m/reportsop[1m[36m[~]ยป[0m/reportsope \ No newline at end of file +[32m~[0m[36mโฏ[0m[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.5.79ยทclaude-sonnet-4-6][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/r[1m[36m[~]ยป[0m/re[1m[36m[~]ยป[0m/research[1m[36m[~]ยป[0m/research"LLM[1m[36m[~]ยป[0m/research"LLMagents[1m[36m[~]ยป[0m/research"LLMagents2026[1m[36m[~]ยป[0m/research"LLMagents2026trends"[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--expand[2mโ—Expandingqueryinto4siblingsub-queriesโ€ฆ[0m[2mโ†ณ[0mautonomouscodingagentsbenchmarks2026[2mโ†ณ[0mmulti-agentdebate/reviewer-authorloops[2mโ†ณ[0magentictooluseplusMCP/functioncalling[2mโ†ณ[0mopen-weightmodelsforagentworkflows[1mFanningoutacross20sourcesinparallelโ€ฆ[0m[32mโœ“[0m[1marXiv[0m[2mโ†’[0m342hits[32mโœ“[0m[1mSemanticScholar[0m[2mโ†’[0m218hits[32mโœ“[0m[1mHuggingFacePapers[0m[2mโ†’[0m176hits[32mโœ“[0m[1mOpenAlex[0m[2mโ†’[0m412hits[32mโœ“[0m[1malphaXiv[0m[2mโ†’[0m84hits[32mโœ“[0m[1mHackerNews[0m[2mโ†’[0m511hits[32mโœ“[0m[1mGitHub[0m[2mโ†’[0m298hits[32mโœ“[0m[1mRedditr/MachineLearning[0m[2mโ†’[0m147hits[32mโœ“[0m[1mStackOverflow[0m[2mโ†’[0m62hits[32mโœ“[0m[1mGoogleNews[0m[2mโ†’[0m203hits[32mโœ“[0m[1mPolymarket[0m[2mโ†’[0m9hits[32mโœ“[0m[1mSECEDGAR[0m[2mโ†’[0m14hits[33mโœ“[0m[1mTwitter/X[0m[2mโ†’[0m1.2khits[32mโœ“[0m[1mBraveSearch[0m[2mโ†’[0m188hits[32mโœ“[0m[1mTavily[0m[2mโ†’[0m151hits[32mโœ“[0m[1mGoogleScholar[0m[2mโ†’[0m224hits[32mโœ“[0m[1m็ŸฅไนŽZhihu[0m[2mโ†’[0m186hits[32mโœ“[0m[1mB็ซ™Bilibili[0m[2mโ†’[0m298hits[33mโœ“[0m[1mๅพฎๅšWeibo[0m[2mโ†’[0m412hits[32mโœ“[0m[1mๅฐ็บขไนฆXiaohongshu[0m[2mโ†’[0m127hits[1mTopentitiesbycross-platformattention:[0m[2mentityarXivHFGHHNๅพฎๅšZhihutotal[0m[2mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€[0m[1mClaude4.6[0m[2m1278432298412186[0m[32m1,139[0m[1mDeepSeekV4[0m[2m108112147176287298[0m[32m1,128[0m[1mQwen3-Coder[0m[2m879221188154287[0m[32m919[0m[1mMCPProtocol[0m[2m42281882476472[0m[32m641[0m[1mLlama4[0m[2m961189420316788[0m[32m766[0m[2mโ—VerifyingcitationsagainstarXiv/SemanticScholar/CrossRefโ€ฆ[0m[32mโœ“[0m47papers,[32m45verified[0m,[31m2flaggedforhallucination[0m[32mโœ“[0mBriefsavedโ†’[36m~/.cheetahclaws/research_reports/llm-agents-2026-trends-17.md[0m[2m3,124wordsยท47citationsยทcross-platformheattableยท12-monthtrendsparkline[0m[1m[36m[~]ยป[0m/reports[1m[36m[~]ยป[0m/reportsopen[2mOpeningllm-agents-2026-trends-19.mdinyoureditorโ€ฆ[0m[32m~[0m[36mโฏ[0mc[32m~[0m[36mโฏ[0mch[32m~[0m[36mโฏ[0mche[32m~[0m[36mโฏ[0mchee[32m~[0m[36mโฏ[0mcheet[32m~[0m[36mโฏ[0mcheeta[32m~[0m[36mโฏ[0mcheetah[32m~[0m[36mโฏ[0mcheetahc[32m~[0m[36mโฏ[0mcheetahcl[32m~[0m[36mโฏ[0mcheetahcla[32m~[0m[36mโฏ[0mcheetahclaw[1m[36m[~]ยป[0m/res[1m[36m[~]ยป[0m/rese[1m[36m[~]ยป[0m/resea[1m[36m[~]ยป[0m/resear[1m[36m[~]ยป[0m/researc[1m[36m[~]ยป[0m/research"[1m[36m[~]ยป[0m/research"L[1m[36m[~]ยป[0m/research"LL[1m[36m[~]ยป[0m/research"LLMa[1m[36m[~]ยป[0m/research"LLMag[1m[36m[~]ยป[0m/research"LLMage[1m[36m[~]ยป[0m/research"LLMagen[1m[36m[~]ยป[0m/research"LLMagent[1m[36m[~]ยป[0m/research"LLMagents2[1m[36m[~]ยป[0m/research"LLMagents20[1m[36m[~]ยป[0m/research"LLMagents202[1m[36m[~]ยป[0m/research"LLMagents2026t[1m[36m[~]ยป[0m/research"LLMagents2026tr[1m[36m[~]ยป[0m/research"LLMagents2026tre[1m[36m[~]ยป[0m/research"LLMagents2026tren[1m[36m[~]ยป[0m/research"LLMagents2026trend[1m[36m[~]ยป[0m/research"LLMagents2026trends[1m[36m[~]ยป[0m/research"LLMagents2026trends"-[1m[36m[~]ยป[0m/research"LLMagents2026trends"--[1m[36m[~]ยป[0m/research"LLMagents2026trends"--r[1m[36m[~]ยป[0m/research"LLMagents2026trends"--ra[1m[36m[~]ยป[0m/research"LLMagents2026trends"--ran[1m[36m[~]ยป[0m/research"LLMagents2026trends"--rang[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m-[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--e[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--ex[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--exp[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--expa[1m[36m[~]ยป[0m/research"LLMagents2026trends"--range6m--expan[1m[36m[~]ยป[0m/rep[1m[36m[~]ยป[0m/repo[1m[36m[~]ยป[0m/repor[1m[36m[~]ยป[0m/report[1m[36m[~]ยป[0m/reportso[1m[36m[~]ยป[0m/reportsop[1m[36m[~]ยป[0m/reportsope \ No newline at end of file diff --git a/docs/media/casts/research_agent.cast b/docs/media/casts/research_agent.cast index 02115152..07f56bbd 100644 --- a/docs/media/casts/research_agent.cast +++ b/docs/media/casts/research_agent.cast @@ -1,6 +1,6 @@ {"version": 2, "width": 110, "height": 32, "timestamp": 1747262400, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}, "title": "CheetahClaws /agent \u2014 autonomous research_assistant loop", "idle_time_limit": 1.5} [0.0, "o", "[32m~[0m [36m\u276f[0m cheetahclaws\r\n"] -[0.3, "o", "[2m[CheetahClaws v3.05.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] +[0.3, "o", "[2m[CheetahClaws v3.5.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] [0.5, "o", "[1m[36m[~] \u00bb[0m "] [0.9, "o", ""] [0.94, "o", "/"] diff --git a/docs/media/casts/research_agent.svg b/docs/media/casts/research_agent.svg index cc395dde..81ac5646 100644 --- a/docs/media/casts/research_agent.svg +++ b/docs/media/casts/research_agent.svg @@ -1 +1 @@ -[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.05.79ยทclaude-sonnet-4-6][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/agent[1mPickanagenttemplate:[0m1.[36mresearch_assistant[0m[2mโ€”dailyliterature&trenddigest[0m2.[36mauto_bug_fixer[0m[2mโ€”scanrepo,proposefixes,runtests[0m3.[36mpaper_writer[0m[2mโ€”draft&polishapapersectionbysection[0m4.[36mauto_coder[0m[2mโ€”implementTODOsfromabacklogfile[0m[2m(ordropa.mdinto~/.cheetahclaws/agent_templates/foracustomone)[0m[1mChoose[1-4]:[0m[1mChoose[1-4]:[0m1[1mTopicforresearch_assistant:[0m[1mTopicforresearch_assistant:[0mMulti-agent[1mTopicforresearch_assistant:[0mMulti-agentdebate[1mTopicforresearch_assistant:[0mMulti-agentdebatevs[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-model[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papers[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfrom[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthe[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30days[32mโœ“[0mAgent[1mresearch_assistant_8f3a2c[0mstartedโ€”loopevery4hoursยทpushtoTelegram[2mOutputdir:~/.cheetahclaws/agents/research_assistant_8f3a2c/output/[0m[36mโ”€โ”€โ”€Iteration#1โ”€โ”€โ”€[2m11:00PT[0m[33m[Read][0m~/.cheetahclaws/agents/.../state.json[2m(firstrun,empty)[0m[33m[research][0mfannedoutacross20sourcesforthelast24h[32mโ—Found17newpapers,3high-signal:[0m[2mโ€ข[0m"AdvDebate:โ€ฆ"(arXiv2605.04123)โ€”adversarialmulti-agentdebate[2mโ€ข[0m"OneShotorN:โ€ฆ"(arXiv2605.04588)โ€”single-modelcanrivaldebate[2mโ€ข[0m"SkepticLoop:โ€ฆ"(Reddit+GitHub)โ€”open-sourcedebateframework[33m[Write][0mdigest_day_1.mdsavedtooutput/[2mโ†’pushediterationsummarytoTelegramchat458291205[0m[35mโ”€โ”€โ”€Iteration#2โ”€โ”€โ”€[2m15:00PT[0m[33m[Read][0mstate.json[2m(lastdigest:digest_day_1.md)[0m[33m[research][0mnewsince11:00โ†’4papers,1high-signal[32mโ—Notable:[0m"BeyondDebate:โ€ฆ"(NeurIPSworkshoppreprint)[2mโ€”suggestsdebategainsshrinkasbasemodelgetslarger[0m[33m[Write][0mdigest_day_1.md(appended)[34mโ”€โ”€โ”€Iteration#3โ”€โ”€โ”€[2m19:00PT[0m[33m[research][0mnewsince15:00โ†’0papers(quietwindow)[2mโ—Nonewhigh-signalitems.Reusedyesterday'sanalysis.[0m[33m[Write][0mdigest_day_1.md(timestampupdated)[33mโ”€โ”€โ”€Iteration#4โ”€โ”€โ”€[2m23:00PT[0m[33m[research][0m0newpapersยทsummaryidenticalto#3[31mโ—Stagnation-stop:[0msamesummaryfor3iterationsinarow.[2mthreshold:auto_agent_dup_summary_limit=3(set0todisable)[0m[33mโ—Looppaused.[0mNextattemptat09:00PT(manualor/agentresume).[1mOutput(sofar):[0m~/.cheetahclaws/agents/research_assistant_8f3a2c/output/โ”œโ”€โ”€[1mdigest_day_1.md[0m[2m(2.4KB,4papersanalysed)[0mโ”œโ”€โ”€state.json[2m(loopbookkeeping)[0mโ””โ”€โ”€notes.md[2m(runningscratchpad)[0m[2mThreeiterationsยท38ktokensยท$0.31.Saved~$0.90inAPIspendbystopping.[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/a[1m[36m[~]ยป[0m/ag[1m[36m[~]ยป[0m/age[1m[36m[~]ยป[0m/agen[1mTopicforresearch_assistant:[0mM[1mTopicforresearch_assistant:[0mMu[1mTopicforresearch_assistant:[0mMul[1mTopicforresearch_assistant:[0mMult[1mTopicforresearch_assistant:[0mMulti[1mTopicforresearch_assistant:[0mMulti-[1mTopicforresearch_assistant:[0mMulti-a[1mTopicforresearch_assistant:[0mMulti-ag[1mTopicforresearch_assistant:[0mMulti-age[1mTopicforresearch_assistant:[0mMulti-agen[1mTopicforresearch_assistant:[0mMulti-agentd[1mTopicforresearch_assistant:[0mMulti-agentde[1mTopicforresearch_assistant:[0mMulti-agentdeb[1mTopicforresearch_assistant:[0mMulti-agentdeba[1mTopicforresearch_assistant:[0mMulti-agentdebat[1mTopicforresearch_assistant:[0mMulti-agentdebatev[1mTopicforresearch_assistant:[0mMulti-agentdebatevss[1mTopicforresearch_assistant:[0mMulti-agentdebatevssi[1mTopicforresearch_assistant:[0mMulti-agentdebatevssin[1mTopicforresearch_assistant:[0mMulti-agentdebatevssing[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingl[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-m[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-mo[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-mod[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-mode[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”p[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”pa[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”pap[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”pape[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”paper[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersf[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfr[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfro[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromt[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromth[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthel[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthela[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelas[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast3[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30d[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30da[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30day \ No newline at end of file +[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.5.79ยทclaude-sonnet-4-6][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/agent[1mPickanagenttemplate:[0m1.[36mresearch_assistant[0m[2mโ€”dailyliterature&trenddigest[0m2.[36mauto_bug_fixer[0m[2mโ€”scanrepo,proposefixes,runtests[0m3.[36mpaper_writer[0m[2mโ€”draft&polishapapersectionbysection[0m4.[36mauto_coder[0m[2mโ€”implementTODOsfromabacklogfile[0m[2m(ordropa.mdinto~/.cheetahclaws/agent_templates/foracustomone)[0m[1mChoose[1-4]:[0m[1mChoose[1-4]:[0m1[1mTopicforresearch_assistant:[0m[1mTopicforresearch_assistant:[0mMulti-agent[1mTopicforresearch_assistant:[0mMulti-agentdebate[1mTopicforresearch_assistant:[0mMulti-agentdebatevs[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-model[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papers[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfrom[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthe[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30days[32mโœ“[0mAgent[1mresearch_assistant_8f3a2c[0mstartedโ€”loopevery4hoursยทpushtoTelegram[2mOutputdir:~/.cheetahclaws/agents/research_assistant_8f3a2c/output/[0m[36mโ”€โ”€โ”€Iteration#1โ”€โ”€โ”€[2m11:00PT[0m[33m[Read][0m~/.cheetahclaws/agents/.../state.json[2m(firstrun,empty)[0m[33m[research][0mfannedoutacross20sourcesforthelast24h[32mโ—Found17newpapers,3high-signal:[0m[2mโ€ข[0m"AdvDebate:โ€ฆ"(arXiv2605.04123)โ€”adversarialmulti-agentdebate[2mโ€ข[0m"OneShotorN:โ€ฆ"(arXiv2605.04588)โ€”single-modelcanrivaldebate[2mโ€ข[0m"SkepticLoop:โ€ฆ"(Reddit+GitHub)โ€”open-sourcedebateframework[33m[Write][0mdigest_day_1.mdsavedtooutput/[2mโ†’pushediterationsummarytoTelegramchat458291205[0m[35mโ”€โ”€โ”€Iteration#2โ”€โ”€โ”€[2m15:00PT[0m[33m[Read][0mstate.json[2m(lastdigest:digest_day_1.md)[0m[33m[research][0mnewsince11:00โ†’4papers,1high-signal[32mโ—Notable:[0m"BeyondDebate:โ€ฆ"(NeurIPSworkshoppreprint)[2mโ€”suggestsdebategainsshrinkasbasemodelgetslarger[0m[33m[Write][0mdigest_day_1.md(appended)[34mโ”€โ”€โ”€Iteration#3โ”€โ”€โ”€[2m19:00PT[0m[33m[research][0mnewsince15:00โ†’0papers(quietwindow)[2mโ—Nonewhigh-signalitems.Reusedyesterday'sanalysis.[0m[33m[Write][0mdigest_day_1.md(timestampupdated)[33mโ”€โ”€โ”€Iteration#4โ”€โ”€โ”€[2m23:00PT[0m[33m[research][0m0newpapersยทsummaryidenticalto#3[31mโ—Stagnation-stop:[0msamesummaryfor3iterationsinarow.[2mthreshold:auto_agent_dup_summary_limit=3(set0todisable)[0m[33mโ—Looppaused.[0mNextattemptat09:00PT(manualor/agentresume).[1mOutput(sofar):[0m~/.cheetahclaws/agents/research_assistant_8f3a2c/output/โ”œโ”€โ”€[1mdigest_day_1.md[0m[2m(2.4KB,4papersanalysed)[0mโ”œโ”€โ”€state.json[2m(loopbookkeeping)[0mโ””โ”€โ”€notes.md[2m(runningscratchpad)[0m[2mThreeiterationsยท38ktokensยท$0.31.Saved~$0.90inAPIspendbystopping.[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/a[1m[36m[~]ยป[0m/ag[1m[36m[~]ยป[0m/age[1m[36m[~]ยป[0m/agen[1mTopicforresearch_assistant:[0mM[1mTopicforresearch_assistant:[0mMu[1mTopicforresearch_assistant:[0mMul[1mTopicforresearch_assistant:[0mMult[1mTopicforresearch_assistant:[0mMulti[1mTopicforresearch_assistant:[0mMulti-[1mTopicforresearch_assistant:[0mMulti-a[1mTopicforresearch_assistant:[0mMulti-ag[1mTopicforresearch_assistant:[0mMulti-age[1mTopicforresearch_assistant:[0mMulti-agen[1mTopicforresearch_assistant:[0mMulti-agentd[1mTopicforresearch_assistant:[0mMulti-agentde[1mTopicforresearch_assistant:[0mMulti-agentdeb[1mTopicforresearch_assistant:[0mMulti-agentdeba[1mTopicforresearch_assistant:[0mMulti-agentdebat[1mTopicforresearch_assistant:[0mMulti-agentdebatev[1mTopicforresearch_assistant:[0mMulti-agentdebatevss[1mTopicforresearch_assistant:[0mMulti-agentdebatevssi[1mTopicforresearch_assistant:[0mMulti-agentdebatevssin[1mTopicforresearch_assistant:[0mMulti-agentdebatevssing[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingl[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-m[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-mo[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-mod[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-mode[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”p[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”pa[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”pap[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”pape[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”paper[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersf[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfr[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfro[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromt[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromth[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthel[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthela[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelas[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast3[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30d[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30da[1mTopicforresearch_assistant:[0mMulti-agentdebatevssingle-modelโ€”papersfromthelast30day \ No newline at end of file diff --git a/docs/media/casts/telegram.cast b/docs/media/casts/telegram.cast index b68ca000..d5bd0401 100644 --- a/docs/media/casts/telegram.cast +++ b/docs/media/casts/telegram.cast @@ -1,6 +1,6 @@ {"version": 2, "width": 105, "height": 32, "timestamp": 1747262400, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}, "title": "CheetahClaws Telegram bridge \u2014 control the agent from your phone", "idle_time_limit": 1.4} [0.0, "o", "[32m~[0m [36m\u276f[0m cheetahclaws\r\n"] -[0.3, "o", "[2m[CheetahClaws v3.05.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] +[0.3, "o", "[2m[CheetahClaws v3.5.79 \u00b7 claude-sonnet-4-6][0m\r\n\r\n"] [0.5, "o", "[1m[36m[~] \u00bb[0m "] [1.0, "o", ""] [1.051, "o", "/"] diff --git a/docs/media/casts/telegram.svg b/docs/media/casts/telegram.svg index d8e08e7e..183dd863 100644 --- a/docs/media/casts/telegram.svg +++ b/docs/media/casts/telegram.svg @@ -1 +1 @@ -[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.05.79ยทclaude-sonnet-4-6][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/telegram[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED458291205[32mโœ“[0mTelegrambridgeonlineโ€”bot@[1mcheetah_personal_bot[0m,chat458291205[2mListeningformessages.Typingindicator+slashpassthroughenabled.[0m[34mโ”Œโ”€Telegramโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”[0m[34mโ”‚[0m[2m11:42[0m[1mYou[0m:What'stheCPUloadontheserverrightnow?[34mโ”‚[0m[2m๐Ÿ†typingโ€ฆ[0m[34mโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜[0m[33m[Bash][0muptime[2m11:42:18up14days,loadaverage:0.41,0.55,0.62[0m[34mโ”‚[0m[2m11:42[0m๐Ÿ†CPUis[32mquiet[0m:0.41/0.55/0.62(1m/5m/15m).[34mโ”‚[0mServerhasbeenup14days.Wantmetocheckmemoryordisk?[34mโ”‚[0m[2m11:43[0m[1mYou[0m:Re-runthenightlybackupandtellmewhenit'sdone[33m[Bash][0mbash/opt/scripts/nightly_backup.sh[2m(long-running,queuedasjob#2)[0m[34mโ”‚[0m[2m11:43[0m๐Ÿ†Queuedasjob#2.I'llpingyouwhenitfinishes.[34mโ”‚[0m[2m11:43[0m[1mYou[0m:!jobs[34mโ”‚[0m[2m11:43[0m๐Ÿ†Jobqueue:[34mโ”‚[0m[32m#1[0m[2m(done11:42)[0muptimecheck[34mโ”‚[0m[33m#2[0m[2m(running11:43)[0mnightly_backup.sh[โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘]41%[34mโ”‚[0m[2m`!cancel2`tostopยท`!job2`fordetails[0m[34mโ”‚[0m[2m11:51[0m๐Ÿ†Job#2done.[32mBackupOK[0mโ€”4.2GBโ†’s3://prod-backups/2026-05-10/[34mโ”‚[0m[2mTook7m51s.Logsat~/.cheetahclaws/jobs/2/stdout.txt[0m[2mAlsoavailable:/wechat(ๅพฎไฟก),/slackโ€”samejobqueue&passthrough.[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/t[1m[36m[~]ยป[0m/te[1m[36m[~]ยป[0m/tel[1m[36m[~]ยป[0m/tele[1m[36m[~]ยป[0m/teleg[1m[36m[~]ยป[0m/telegr[1m[36m[~]ยป[0m/telegra[1m[36m[~]ยป[0m/telegram7[1m[36m[~]ยป[0m/telegram78[1m[36m[~]ยป[0m/telegram789[1m[36m[~]ยป[0m/telegram7890[1m[36m[~]ยป[0m/telegram7890:[1m[36m[~]ยป[0m/telegram7890:A[1m[36m[~]ยป[0m/telegram7890:AA[1m[36m[~]ยป[0m/telegram7890:AAE[1m[36m[~]ยป[0m/telegram7890:AAEx[1m[36m[~]ยป[0m/telegram7890:AAEx_[1m[36m[~]ยป[0m/telegram7890:AAEx_R[1m[36m[~]ยป[0m/telegram7890:AAEx_RE[1m[36m[~]ยป[0m/telegram7890:AAEx_RED[1m[36m[~]ยป[0m/telegram7890:AAEx_REDA[1m[36m[~]ยป[0m/telegram7890:AAEx_REDAC[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACT[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTE[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED4[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED45[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED458[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED4582[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED45829[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED458291[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED4582912[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED45829120 \ No newline at end of file +[32m~[0m[36mโฏ[0mcheetahclaws[2m[CheetahClawsv3.5.79ยทclaude-sonnet-4-6][0m[1m[36m[~]ยป[0m[1m[36m[~]ยป[0m/telegram[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED458291205[32mโœ“[0mTelegrambridgeonlineโ€”bot@[1mcheetah_personal_bot[0m,chat458291205[2mListeningformessages.Typingindicator+slashpassthroughenabled.[0m[34mโ”Œโ”€Telegramโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”[0m[34mโ”‚[0m[2m11:42[0m[1mYou[0m:What'stheCPUloadontheserverrightnow?[34mโ”‚[0m[2m๐Ÿ†typingโ€ฆ[0m[34mโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜[0m[33m[Bash][0muptime[2m11:42:18up14days,loadaverage:0.41,0.55,0.62[0m[34mโ”‚[0m[2m11:42[0m๐Ÿ†CPUis[32mquiet[0m:0.41/0.55/0.62(1m/5m/15m).[34mโ”‚[0mServerhasbeenup14days.Wantmetocheckmemoryordisk?[34mโ”‚[0m[2m11:43[0m[1mYou[0m:Re-runthenightlybackupandtellmewhenit'sdone[33m[Bash][0mbash/opt/scripts/nightly_backup.sh[2m(long-running,queuedasjob#2)[0m[34mโ”‚[0m[2m11:43[0m๐Ÿ†Queuedasjob#2.I'llpingyouwhenitfinishes.[34mโ”‚[0m[2m11:43[0m[1mYou[0m:!jobs[34mโ”‚[0m[2m11:43[0m๐Ÿ†Jobqueue:[34mโ”‚[0m[32m#1[0m[2m(done11:42)[0muptimecheck[34mโ”‚[0m[33m#2[0m[2m(running11:43)[0mnightly_backup.sh[โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘]41%[34mโ”‚[0m[2m`!cancel2`tostopยท`!job2`fordetails[0m[34mโ”‚[0m[2m11:51[0m๐Ÿ†Job#2done.[32mBackupOK[0mโ€”4.2GBโ†’s3://prod-backups/2026-05-10/[34mโ”‚[0m[2mTook7m51s.Logsat~/.cheetahclaws/jobs/2/stdout.txt[0m[2mAlsoavailable:/wechat(ๅพฎไฟก),/slackโ€”samejobqueue&passthrough.[0m[1m[36m[~]ยป[0m/[1m[36m[~]ยป[0m/t[1m[36m[~]ยป[0m/te[1m[36m[~]ยป[0m/tel[1m[36m[~]ยป[0m/tele[1m[36m[~]ยป[0m/teleg[1m[36m[~]ยป[0m/telegr[1m[36m[~]ยป[0m/telegra[1m[36m[~]ยป[0m/telegram7[1m[36m[~]ยป[0m/telegram78[1m[36m[~]ยป[0m/telegram789[1m[36m[~]ยป[0m/telegram7890[1m[36m[~]ยป[0m/telegram7890:[1m[36m[~]ยป[0m/telegram7890:A[1m[36m[~]ยป[0m/telegram7890:AA[1m[36m[~]ยป[0m/telegram7890:AAE[1m[36m[~]ยป[0m/telegram7890:AAEx[1m[36m[~]ยป[0m/telegram7890:AAEx_[1m[36m[~]ยป[0m/telegram7890:AAEx_R[1m[36m[~]ยป[0m/telegram7890:AAEx_RE[1m[36m[~]ยป[0m/telegram7890:AAEx_RED[1m[36m[~]ยป[0m/telegram7890:AAEx_REDA[1m[36m[~]ยป[0m/telegram7890:AAEx_REDAC[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACT[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTE[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED4[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED45[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED458[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED4582[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED45829[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED458291[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED4582912[1m[36m[~]ยป[0m/telegram7890:AAEx_REDACTED45829120 \ No newline at end of file diff --git a/docs/news.md b/docs/news.md index a3e4eb61..c41f66ee 100644 --- a/docs/news.md +++ b/docs/news.md @@ -3,17 +3,18 @@ ## ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ News (Pacific Time) -- June 16, 2026 (latest): **All internal modules move into a single `cheetahclaws` package.** Previously the importable modules lived flat at the top level (`config.py`, `daemon/`, `kernel/`, `mcp_client/`, `providers.py`, โ€ฆ). That works when you run from the repo dir but breaks once CheetahClaws is *installed* and launched from its entry point: a generic top-level name like `config` or `daemon` gets shadowed by whatever else is on `sys.path` โ€” another project's `config/` directory, the PyPI `python-daemon` package โ€” and `cheetahclaws` dies at startup with `ImportError: cannot import name โ€ฆ from 'config' (unknown location)`. (An earlier pass that merely dropped a `cc_` prefix from four of these modules re-introduced exactly this collision, which the prefix had originally been added to prevent โ€” so this change supersedes it.) The fix is the standard one: own a single namespace. All 21 single-file modules and 20 sub-packages now live under `cheetahclaws/` and are imported as `cheetahclaws.`; the entry script `cheetahclaws.py` became `cheetahclaws/cli.py`, with a deliberately light `cheetahclaws/__init__.py` (defines `VERSION`, lazily proxies CLI entry symbols via PEP 562 `__getattr__` so importing a submodule never drags in the heavy CLI) and a `cheetahclaws/__main__.py` for `python -m cheetahclaws`. Imports were rewritten across all 448 `.py` files โ€” 1269 `from NAME` + 126 `import NAME` + 41 dotted `import NAME.sub` statements, 118 string `patch` / `mock` / `import_module` targets, subprocess `-m` argv paths, the modular plugin f-string loaders, the voice/video back-compat shims, and embedded driver-script strings โ€” all prefixed with `cheetahclaws.`, using whole-word matching so RPC method names, filenames, and unrelated tokens were left alone. `pyproject.toml` now ships a single `cheetahclaws*` package (no `py-modules`) with entry point `cheetahclaws.cli:main`; `agent_templates/` moved into the package so it ships as data. Triage of the move surfaced and fixed seven regression classes โ€” kernel/daemon subprocess `-m` argv paths, the `test_packaging` import contract, the voice shim's submodule registration, the daemon e2e launcher, tests that patched the package object instead of the `cli` module, tests with hardcoded repo-root data paths, and a `sys.modules` stub-restore leak between `test_research` and `test_setup_wizard`. **Breaking only for code that imports CheetahClaws internals directly** โ€” `import kernel` โ†’ `from cheetahclaws import kernel`, `from mcp_client.client import get_mcp_manager` โ†’ `from cheetahclaws.mcp_client.client import get_mcp_manager`; the `cheetahclaws` CLI, `python -m cheetahclaws`, the Web UI, and all bridges are unaffected. Verified end-to-end: `python -m cheetahclaws --version` and `from cheetahclaws import config` both work from outside the repo (the original crash), a built wheel contains `cheetahclaws/*` with all data files (web, prompts, agent_templates) and zero bare top-level modules, and the full suite is **2449 passed, 3 skipped, 0 failed**. +- June 23, 2026 (latest) (**v3.5.83**): **Documentation slimmed to its essentials, a native desktop app brought into the repo, and the version-string format unified.** Three threads of housekeeping. **(1) README / docs trim.** The top-level README had grown a verbose multi-paragraph News block and several reference dumps that duplicated the guides. Each News item is now **one sentence + a `[Details](docs/news.md)` link** (the full write-ups stay here); the **59-model Atlas Cloud list** moved to [`docs/guides/usage.md`](guides/usage.md#option-d--atlas-cloud-hosted-openai-compatible) (Option D) leaving only the 3-line example in the README; and the **FAQ** dropped to its three highest-value entries (MCP, Ollama tool calls, macOS PATH) with the rest pointed at [`docs/guides/faq.md`](guides/faq.md). Net README ~551 โ†’ ~516 lines with no content lost โ€” everything trimmed already lived in `docs/`. **(2) Native desktop app (`desktop/`).** A thin **Electron shell** that launches `cheetahclaws --web --no-auth` as a localhost sidecar, parses its `Chat UI: http://โ€ฆ/chat` ready line, and points a `BrowserWindow` at it โ€” so the production web UI *becomes* a native window with nothing reimplemented. It couples to the rest only through that CLI contract (verified: `npm run smoke` launches the real server against this repo and confirms `/chat` `/` `/health` all serve), and `scripts/build-app.sh` can freeze the server with PyInstaller into a self-contained `.dmg`/`.exe`/`.AppImage` needing neither Node nor Python on the user's machine. Surfaced from three entry points (top-of-README callout, Web UI section, Documentation table). Remaining for a shippable installer: code signing / notarization. **(3) Version-string format unified.** Historical release notes mixed `v3.05.x` and `v3.5.x`; all ~166 occurrences across the README, the 7 i18n translations, `docs/news.md`, the guides, the demo/cast generators, and the recorded `.cast`/`.svg` banners are now the canonical **`v3.5.x`**. Version bumped `3.5.82` โ†’ **`3.5.83`** in `pyproject.toml`. Full suite green (**2449 passed, 3 skipped**); the desktop sidecar smoke test passes against this repo's web server. **Not a breaking change** โ€” no runtime behavior changed. +- June 16, 2026: **All internal modules move into a single `cheetahclaws` package.** Previously the importable modules lived flat at the top level (`config.py`, `daemon/`, `kernel/`, `mcp_client/`, `providers.py`, โ€ฆ). That works when you run from the repo dir but breaks once CheetahClaws is *installed* and launched from its entry point: a generic top-level name like `config` or `daemon` gets shadowed by whatever else is on `sys.path` โ€” another project's `config/` directory, the PyPI `python-daemon` package โ€” and `cheetahclaws` dies at startup with `ImportError: cannot import name โ€ฆ from 'config' (unknown location)`. (An earlier pass that merely dropped a `cc_` prefix from four of these modules re-introduced exactly this collision, which the prefix had originally been added to prevent โ€” so this change supersedes it.) The fix is the standard one: own a single namespace. All 21 single-file modules and 20 sub-packages now live under `cheetahclaws/` and are imported as `cheetahclaws.`; the entry script `cheetahclaws.py` became `cheetahclaws/cli.py`, with a deliberately light `cheetahclaws/__init__.py` (defines `VERSION`, lazily proxies CLI entry symbols via PEP 562 `__getattr__` so importing a submodule never drags in the heavy CLI) and a `cheetahclaws/__main__.py` for `python -m cheetahclaws`. Imports were rewritten across all 448 `.py` files โ€” 1269 `from NAME` + 126 `import NAME` + 41 dotted `import NAME.sub` statements, 118 string `patch` / `mock` / `import_module` targets, subprocess `-m` argv paths, the modular plugin f-string loaders, the voice/video back-compat shims, and embedded driver-script strings โ€” all prefixed with `cheetahclaws.`, using whole-word matching so RPC method names, filenames, and unrelated tokens were left alone. `pyproject.toml` now ships a single `cheetahclaws*` package (no `py-modules`) with entry point `cheetahclaws.cli:main`; `agent_templates/` moved into the package so it ships as data. Triage of the move surfaced and fixed seven regression classes โ€” kernel/daemon subprocess `-m` argv paths, the `test_packaging` import contract, the voice shim's submodule registration, the daemon e2e launcher, tests that patched the package object instead of the `cli` module, tests with hardcoded repo-root data paths, and a `sys.modules` stub-restore leak between `test_research` and `test_setup_wizard`. **Breaking only for code that imports CheetahClaws internals directly** โ€” `import kernel` โ†’ `from cheetahclaws import kernel`, `from mcp_client.client import get_mcp_manager` โ†’ `from cheetahclaws.mcp_client.client import get_mcp_manager`; the `cheetahclaws` CLI, `python -m cheetahclaws`, the Web UI, and all bridges are unaffected. Verified end-to-end: `python -m cheetahclaws --version` and `from cheetahclaws import config` both work from outside the repo (the original crash), a built wheel contains `cheetahclaws/*` with all data files (web, prompts, agent_templates) and zero bare top-level modules, and the full suite is **2449 passed, 3 skipped, 0 failed**. - June 6, 2026 (**v3.5.82**): **macOS install reliably puts `cheetahclaws` on PATH, and local Ollama models that emit tool calls as text now actually execute them.** Two fixes reported in issue #131. **(1) Install / PATH on macOS.** On macOS the installer creates a dedicated venv (`~/.cheetahclaws-venv`) and `source`s it, so the post-install verification `if command -v cheetahclaws` succeeded *inside the script's own activated shell* โ€” it printed "cheetahclaws is on PATH" and **short-circuited past the entire rc-file block**, including the `touch ~/.zshrc` that was supposed to create the file. Result: `~/.zshrc` was never created/updated, and in a fresh terminal (no venv active) the binary was unreachable, so users had to hunt for the install location by hand. The verification step no longer trusts the venv-polluted `command -v`: it confirms the binary at the expected `BIN_DIR`, then (for venv installs) **symlinks only the `cheetahclaws` entry point into `~/.local/bin`** โ€” pipx-style, so the venv's `python`/`pip` never get prepended to PATH and can't shadow the user's own โ€” creates the right rc file if missing (`~/.zshrc` for zsh, `~/.bash_profile` for bash on macOS, `config.fish` for fish), and appends the exposure dir to PATH there. The fish branch now also writes fish (`set -gx PATH โ€ฆ`) syntax instead of `export`, and the reload hint points bash-on-macOS at `.bash_profile` (`scripts/install.sh`). **(2) Ollama tool calls (the "model just keeps talking" bug).** The Ollama streaming path (`stream_ollama`) only read tool calls from Ollama's structured `message.tool_calls` field, whereas the OpenAI-compatible cloud path (`stream_openai_compat`) *also* recovers tool calls a model emits as **text** via `_find_native_tool_marker` + `_extract_native_tool_calls`. Many local models โ€” Qwen-coder, Gemma, Mistral โ€” emit calls as `{โ€ฆ}` / `<|tool_call|>โ€ฆ` / `[TOOL_CALLS][โ€ฆ]` inside `content`; on the Ollama path that markup was streamed straight to the screen as chat and never executed, so the agent loop saw no tool calls and ended the turn โ€” exactly the reported "tool-calling-style chat that never runs." `stream_ollama` now mirrors the cloud path: when a native marker appears in the streamed content it **buffers from that point** (so the user never sees raw markup), and at end-of-stream parses the buffer into real tool calls (falling back to surfacing the buffered text if parsing fails, so nothing is silently swallowed). Note: Ollama's native `/api/chat` does not accept a `tool_choice` parameter, so the fix is the text-format recovery, not a request-param change. Existing provider + cache-token suites stay green. See [docs/guides/usage.md](guides/usage.md#usage-open-source-models-local) ยท [docs/guides/faq.md](guides/faq.md). - June 5, 2026 (**v3.5.82**): **User-controllable token / cost budgets โ€” set a spend cap; on hit the session auto-saves and you can resume or raise it.** The quota engine (`quota.py`: per-session + per-day token/cost counters, enforced before each model call) already existed but had no friendly surface โ€” you had to know four config keys (`session_token_budget` / `session_cost_budget` / `daily_token_budget` / `daily_cost_budget`) and there was no way to see how close you were, no warning before the wall, and the hard stop printed a bare `[Quota exceeded]`. This adds the UX layer on top of the unchanged engine: a **`/budget`** command โ€” no args shows usage vs every budget as colored bars + percentages; **`/budget $5`** sets a session **cost** cap (the `$` means USD), **`/budget 200k`** a session **token** cap (parses `200k` / `1.5m` / `200000`), **`/budget daily $20`** / **`/budget daily 2m`** the daily caps, and **`/budget clear`** removes all. A **`--budget $5`** / **`--budget 200k`** startup flag sets the session cap at launch. **Proximity warnings** fire at the end of any turn that crosses **โ‰ฅ80%** (yellow) / **โ‰ฅ95%** (red) of a cap, so the wall never arrives by surprise. **On hit** the agent now yields a `QuotaPause` event (instead of a plain text line): the REPL **auto-saves the session** (`session_latest.json` + daily backup, the same path `/resume` reads) and prints a friendly next-steps block โ€” raise the **same** cap or remove it (`/budget clear`) then resend, or restart later and `/resume`. So a long task that runs out of budget is never lost: you analyze, adjust, and continue. **Tight enforcement (no surprise overshoot):** the check projects the next request's *input* (`compaction.estimate_tokens`) and stops *before* the call if it would cross the cap, and clamps that call's `max_tokens` to the remaining headroom (`quota.output_room`) โ€” so a single tool-heavy turn can't blow 40kโ†’49k past the budget the way a pure "already-spent โ‰ฅ limit" check let it. **One budget per scope:** setting a cap *replaces* the other unit for that scope (`/budget $5` after `/budget 200k` switches the session cap to cost rather than stacking), so a leftover token cap can't silently keep blocking after you switch to a `$` cap. **Unit-matched hint:** `QuotaExceeded` / `QuotaPause` carry which cap broke (`key`/`scope`/`unit`/`limit`), so the "raise it" suggestion is in the *right* unit โ€” a token cap shows `/budget 40k`, a daily cost cap shows `/budget daily $40` โ€” instead of a generic `$` amount that wouldn't lift a token cap. New helpers `quota.parse_budget` / `fmt_amount` / `usage_vs_limits` / `warnings` / `output_room`; command in `commands/core.py:cmd_budget`; `QuotaPause` in `agent.py`; REPL handling + `--budget` in `cheetahclaws.py`; 42-case `tests/test_budget.py` (isolated quota dir, incl. a regression that the hint matches the breached unit and that switching units clears the stale cap). The daemon's conservative `serve`-mode defaults (200k tok / $2 per session, 2M / $20 per day) are unchanged โ€” interactive stays unlimited by default, the server stays guard-railed. See [docs/guides/features.md](guides/features.md) ยท [docs/guides/reference.md](guides/reference.md). - June 5, 2026 (**v3.5.82**): **Adaptive Markdown streaming โ€” live output that stays correct on every device.** In-place Rich Live redraw is great on capable terminals but breaks elsewhere: it was disabled wholesale over SSH (so SSH users got raw tokens with no formatting), and where it *did* run it could leave **duplicate or stale frames** โ€” on macOS Terminal (which can't erase above the scroll boundary), over laggy network PTYs, or with **wide CJK / emoji text** whose display width a naive line-count gets wrong. The renderer now selects a **streaming tier per device** in `ui.render.auto_stream_mode(config)`: **`live`** โ€” full in-place redraw, only on terminals known to handle cursor-up (local TTYs, and modern emulators *even over SSH*: iTerm2, WezTerm, Windows Terminal, VSCode, kitty, Alacritty, Ghostty, detected via `TERM_PROGRAM` / `TERM` / `WT_SESSION` / `KITTY_WINDOW_ID` / `ALACRITTY_WINDOW_ID` / `WEZTERM_PANE`); **`commit`** โ€” **append-only progressive Markdown**, the safe default for unknown-SSH / Apple Terminal / pipes / non-TTY, where each completed block (split on blank lines, respecting open code fences so a fenced block renders atomically) is rendered and printed **permanently** and the cursor is **never moved**, making a duplicate frame structurally impossible regardless of terminal, latency, or character width; **`plain`** โ€” raw tokens, only when `rich` is unavailable. The append-only floor is provably duplication-free; `live` is progressive enhancement on top. Override with **`/config stream_mode=live|commit|plain`** (legacy boolean **`/config rich_live=true|false`** still works โ†’ `live`/`commit`). Implemented in `ui/render.py` (`set_stream_mode` / `auto_stream_mode` / `_safe_commit_point` / `_commit_stream` / `_commit_flush`), wired in at REPL start in `cheetahclaws.py`, with a 26-case test suite in `tests/test_stream_modes.py` (device routing, code-fence-aware block boundaries, append-only commit, and a regression asserting commit mode emits **zero** cursor sequences even on a TTY with CJK text). Two related UX items shipped alongside: **`/context` is now a visual grid** โ€” a Claude-Code-style 20ร—10 cell grid of context-window usage, colored and broken down by category (system prompt / system tools / memory files / skills / messages / free space) with per-category token counts and percentages, adapting to the model's real context window and falling back to `#`/`.` on non-UTF-8 terminals (`commands/core.py:cmd_context`); and **`deepseek-v4-flash` is registered at its 1M context window** in `providers._MODEL_CONTEXT_LIMITS` (overriding the 128K deepseek provider default, which still applies to `deepseek-chat` / `deepseek-v4-pro`), so the prompt `%`, `/context`, and the compaction trigger all reflect the true 1M window. See [docs/guides/features.md](guides/features.md) ยท [docs/guides/reference.md](guides/reference.md). -- June 4, 2026 (**v3.05.81**): **Claude-Code-style quiet output โ€” hide tool execution, show one summary line per turn.** Long analysis turns used to scroll the terminal with a `โš™ Bash(...)` line and a `โœ“ โ†’ N lines (โ€ฆ chars)` line for *every* tool call, and the permission prompt dumped the entire inline script (e.g. a 60-line `python3 << 'PYEOF'` heredoc). A new **quiet mode (on by default)** suppresses the per-tool lines โ€” the spinner conveys live activity and a single summary line is emitted at the toolโ†’text boundary, sitting just above the reply (`Read 2 files, ran 3 shell commands`), the way Claude Code does. Errors and denials still surface so a mid-turn failure is never silent. In quiet mode the **permission prompt also collapses** a multi-line command to one line (`Run: python3 << 'PYEOF' โ€ฆ (+59 ่กŒ)`) instead of printing the whole script. `/verbose` overrides quiet (full per-tool lines + inputs + token counts); toggle with **`/quiet`**, or launch with **`--show-tools`** (alias `--no-quiet`). The startup banner gains an **`Output: quiet` / `Output: full`** line so the active mode is visible at a glance. **Live status line:** the spinner now shows elapsed time plus a running output-token estimate (`Thinkingโ€ฆ (7s ยท โ†“ 435 tokens)`) โ€” char-based, since providers only report real usage at the end โ€” and each quiet turn closes with a real-usage footer **`โœป Worked for 7.2s ยท โ†‘ 1.2k ยท โ†“ 435`** built from the true `TurnDone` counts. Implemented in `ui/render.py` (turn-level tool accumulator + `turn_summary_line()`, spinner token meter, `print_turn_stats()`), wired through the REPL event loop in `cheetahclaws.py`, with the `/quiet` toggle in `commands/config_cmd.py`. See [docs/guides/features.md](guides/features.md). +- June 4, 2026 (**v3.5.81**): **Claude-Code-style quiet output โ€” hide tool execution, show one summary line per turn.** Long analysis turns used to scroll the terminal with a `โš™ Bash(...)` line and a `โœ“ โ†’ N lines (โ€ฆ chars)` line for *every* tool call, and the permission prompt dumped the entire inline script (e.g. a 60-line `python3 << 'PYEOF'` heredoc). A new **quiet mode (on by default)** suppresses the per-tool lines โ€” the spinner conveys live activity and a single summary line is emitted at the toolโ†’text boundary, sitting just above the reply (`Read 2 files, ran 3 shell commands`), the way Claude Code does. Errors and denials still surface so a mid-turn failure is never silent. In quiet mode the **permission prompt also collapses** a multi-line command to one line (`Run: python3 << 'PYEOF' โ€ฆ (+59 ่กŒ)`) instead of printing the whole script. `/verbose` overrides quiet (full per-tool lines + inputs + token counts); toggle with **`/quiet`**, or launch with **`--show-tools`** (alias `--no-quiet`). The startup banner gains an **`Output: quiet` / `Output: full`** line so the active mode is visible at a glance. **Live status line:** the spinner now shows elapsed time plus a running output-token estimate (`Thinkingโ€ฆ (7s ยท โ†“ 435 tokens)`) โ€” char-based, since providers only report real usage at the end โ€” and each quiet turn closes with a real-usage footer **`โœป Worked for 7.2s ยท โ†‘ 1.2k ยท โ†“ 435`** built from the true `TurnDone` counts. Implemented in `ui/render.py` (turn-level tool accumulator + `turn_summary_line()`, spinner token meter, `print_turn_stats()`), wired through the REPL event loop in `cheetahclaws.py`, with the `/quiet` toggle in `commands/config_cmd.py`. See [docs/guides/features.md](guides/features.md). - June 4, 2026: **Context-window override โ€” the prompt % and compaction now follow a settable context length.** The prompt's context-usage `%` (and the compaction trigger) derive from the model's context window, which previously could only be a hardcoded provider default โ€” and `max_tokens` (the OUTPUT cap) doesn't change it, so `/config max_tokens=โ€ฆ` left the `%` unchanged (a common point of confusion). New per-session key **`context_window`** (`/config context_window=`, `0` = model default) overrides it, kept deliberately distinct from `max_tokens`. A single parser (`providers.context_window_override`) feeds the prompt `%`, `/context`, the compaction trigger, **and** the per-call output-token cap, so all four stay consistent; it is bidirectional โ€” a smaller value forces earlier compaction, a larger value corrects a stale default. The value is read live each prompt, so switching model **or** `context_window` updates the `%` with no restart. `/config` warns when the value exceeds the model's real window (which would disable compaction and let the API reject oversized prompts). No-op when unset, so existing behavior is unchanged. See [docs/guides/reference.md](guides/reference.md). - June 4, 2026: **Rich Live streaming โ€” long responses stay live via a bounded tail window.** Large streamed responses that would overflow the terminal's redraw area could leave duplicate or stale frames behind on some emulators (macOS Terminal, etc.), because Rich Live redraws the whole accumulated output in place and the cursor can't reach content that has scrolled into the scrollback. Building on the per-response fallback from PR #133, Rich Live now keeps the live region **bounded to the viewport**: a short response is shown in full, but once it would overflow, only the **last screenful of rendered lines (a tail window) is redrawn** โ€” so the Live region can never exceed the terminal and cannot leave stale frames. The complete output is committed once when the response finishes (including on Ctrl-C, since the REPL flushes on interrupt), so the head that scrolled out of the window is never lost. Plain streaming is kept only as a safety net (precise render failed, or the terminal is too small to bound a window). A cheap per-line wrap estimate short-circuits the expensive full `render_lines()` measurement while a response stays well under the limit, so normal responses pay no extra Markdown re-render per chunk. Adds focused tests covering full-frame streaming, the fullโ†’tail transition, tail-window commit-on-flush, real `Segments` rendering, and both safety-net fallbacks. See [docs/guides/features.md](guides/features.md). - May 31, 2026: **QQ bot bridge โ€” `/qq` connects cheetahclaws to QQ groups + C2C private chats (PR #121).** Uses the official [`qq-botpy`](https://github.com/tencent-connect/botpy) WebSocket + HTTP SDK (`pip install "cheetahclaws[qq]"`). botpy's async client runs on a dedicated asyncio event loop inside a daemon thread, bridged to the synchronous main thread via thread-safe queues. Handles `on_group_at_message_create` (group @-mentions, prefix stripped) and `on_c2c_message_create` (private). Since QQ has no message-edit API, replies **stream as new messages** every ~2 s (2000-char chunking) instead of updating a placeholder; passive replies reference the original `msg_id`/`event_id` within QQ's 5-minute window, then fall back to active pushes. Per-target FIFO job queues, slash-command passthrough, `!jobs`/`!retry`/`!cancel` remote control, image input, and permission prompts **scoped to the originating chat** (no cross-chat approvals). A supervisor reconnects with exponential backoff (2 s โ†’ 120 s). **Secret handling matches the hardening standard below:** `$QQ_SECRET` (recommended) > REPL arg (deprecated, warns + scrubs history) > config; env-supplied secrets never touch `~/.cheetahclaws/config.json`. `/qq `, `/qq`, `/qq stop|status|logout`. Two follow-up fixes over the original PR: image downloads moved off the event loop into `loop.run_in_executor` (a blocking `urlopen` would freeze the WebSocket heartbeat for up to 30 s), and the secret no longer gets written to disk unconditionally. See [docs/guides/bridges.md](guides/bridges.md#qq-bridge). -- May 12, 2026 (**v3.05.80**): (security-hardening branch): **Two-round security hardening sweep โ€” CRITICAL + HIGH findings from the in-repo code review.** Lands a cluster of fixes that close real attack surfaces opened by the recent rapid feature growth. Zero regressions across the full 2347-test suite. +- May 12, 2026 (**v3.5.80**): (security-hardening branch): **Two-round security hardening sweep โ€” CRITICAL + HIGH findings from the in-repo code review.** Lands a cluster of fixes that close real attack surfaces opened by the recent rapid feature growth. Zero regressions across the full 2347-test suite. **Bot tokens off `argv` / readline history.** `cmd_telegram` and `cmd_slack` now accept a single-arg form (`/telegram ` / `/slack `) and read the bot token from `$TELEGRAM_BOT_TOKEN` / `$SLACK_BOT_TOKEN`. Env-supplied tokens never get persisted to `~/.cheetahclaws/config.json`; only tokens that actually came in via the deprecated REPL-arg path are saved on disk. New `bridges.scrub_token_from_history(token)` walks `readline.get_history_item` backwards and removes any in-memory entry that embeds the token the moment we know its value. Bridge supervisors get a `token=`/`channel=` kwarg so the env-sourced token can flow to the worker thread without ever sitting on the config dict โ€” `_slack_start_bridge(config, *, token, channel)`. Telegram already passed the token explicitly to `_tg_supervisor`. WeChat is unaffected (QR-scan token, never in argv). @@ -57,7 +58,7 @@ - May 11, 2026 (`daemon/f-4` branch): **F-4 skeleton โ€” `agent_runner` becomes a supervised subprocess (RFC 0002).** The fourth piece of the daemon foundation roadmap lands as a feature-flagged skeleton on the `daemon/f-4` branch. Today each `/agent