mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-20 00:22:31 +00:00
chore(release): bundle webui into wheel and prep 0.2.0
This commit is contained in:
parent
0ca0fe2221
commit
c018c3fb6a
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -49,7 +49,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: nanobot Version
|
label: nanobot Version
|
||||||
description: Run `nanobot --version` or `pip show nanobot-ai`
|
description: Run `nanobot --version` or `pip show nanobot-ai`
|
||||||
placeholder: e.g., 0.1.5
|
placeholder: e.g., 0.2.0
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|||||||
16
README.md
16
README.md
@ -214,10 +214,9 @@ nanobot agent
|
|||||||
- Want to run nanobot in chat apps like Telegram, Discord, WeChat or Feishu? See [Chat Apps](./docs/chat-apps.md)
|
- Want to run nanobot in chat apps like Telegram, Discord, WeChat or Feishu? See [Chat Apps](./docs/chat-apps.md)
|
||||||
- Want Docker or Linux service deployment? See [Deployment](./docs/deployment.md)
|
- Want Docker or Linux service deployment? See [Deployment](./docs/deployment.md)
|
||||||
|
|
||||||
## 🧪 WebUI (Development)
|
## 🌐 WebUI
|
||||||
|
|
||||||
> [!NOTE]
|
The WebUI ships **inside the published wheel** — no extra build step. Just enable the WebSocket channel and open it in your browser.
|
||||||
> The WebUI development workflow currently requires a source checkout and is not yet shipped together with the official packaged release. See [WebUI Document](./webui/README.md) for full WebUI development docs and build steps.
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="images/nanobot_webui.png" alt="nanobot webui preview" width="900">
|
<img src="images/nanobot_webui.png" alt="nanobot webui preview" width="900">
|
||||||
@ -235,13 +234,12 @@ nanobot agent
|
|||||||
nanobot gateway
|
nanobot gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
**3. Start the webui dev server**
|
**3. Open the WebUI**
|
||||||
|
|
||||||
```bash
|
Visit [`http://127.0.0.1:8765`](http://127.0.0.1:8765) in your browser. To open it from another device on your LAN, see [WebUI docs → LAN access](./webui/README.md#access-from-another-device-lan).
|
||||||
cd webui
|
|
||||||
bun install
|
> [!TIP]
|
||||||
bun run dev
|
> Working on the WebUI itself? Check out [`webui/README.md`](./webui/README.md) for the Vite dev server (HMR) workflow.
|
||||||
```
|
|
||||||
|
|
||||||
## 🏗️ Architecture
|
## 🏗️ Architecture
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ Start here for setup, everyday usage, and deployment.
|
|||||||
| Agent social network | [`agent-social-network.md`](./agent-social-network.md) | Join external agent communities from nanobot |
|
| Agent social network | [`agent-social-network.md`](./agent-social-network.md) | Join external agent communities from nanobot |
|
||||||
| Configuration | [`configuration.md`](./configuration.md) | Providers, tools, channels, MCP, and runtime settings |
|
| Configuration | [`configuration.md`](./configuration.md) | Providers, tools, channels, MCP, and runtime settings |
|
||||||
| Image generation | [`image-generation.md`](./image-generation.md) | Configure image providers, WebUI image mode, and generated artifacts |
|
| Image generation | [`image-generation.md`](./image-generation.md) | Configure image providers, WebUI image mode, and generated artifacts |
|
||||||
|
| WebUI | [`../webui/README.md`](../webui/README.md) | Open the bundled browser UI; LAN access; Vite dev server for contributors |
|
||||||
| Multiple instances | [`multiple-instances.md`](./multiple-instances.md) | Run isolated bots with separate configs and workspaces |
|
| Multiple instances | [`multiple-instances.md`](./multiple-instances.md) | Run isolated bots with separate configs and workspaces |
|
||||||
| CLI reference | [`cli-reference.md`](./cli-reference.md) | Core CLI commands and common entrypoints |
|
| CLI reference | [`cli-reference.md`](./cli-reference.md) | Core CLI commands and common entrypoints |
|
||||||
| In-chat commands | [`chat-commands.md`](./chat-commands.md) | Slash commands and periodic task behavior |
|
| In-chat commands | [`chat-commands.md`](./chat-commands.md) | Slash commands and periodic task behavior |
|
||||||
|
|||||||
101
hatch_build.py
Normal file
101
hatch_build.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
"""Hatch build hook that bundles the webui (Vite) into nanobot/web/dist.
|
||||||
|
|
||||||
|
Triggered automatically by `python -m build` (and any other hatch-driven build)
|
||||||
|
so published wheels and sdists ship a fresh webui without requiring developers
|
||||||
|
to remember `cd webui && bun run build` beforehand.
|
||||||
|
|
||||||
|
Behaviour:
|
||||||
|
|
||||||
|
- Skips for editable installs (`pip install -e .`). Editable mode is for Python
|
||||||
|
development; webui contributors use `cd webui && bun run dev` (Vite HMR) and
|
||||||
|
do not need a packaged `dist/`.
|
||||||
|
- No-op when `webui/package.json` is absent (e.g. installing from an sdist that
|
||||||
|
already contains a prebuilt `nanobot/web/dist/`).
|
||||||
|
- Skips when `NANOBOT_SKIP_WEBUI_BUILD=1` is set.
|
||||||
|
- Skips when `nanobot/web/dist/index.html` already exists, unless
|
||||||
|
`NANOBOT_FORCE_WEBUI_BUILD=1` is set.
|
||||||
|
- Uses `bun` when available, otherwise falls back to `npm`. The chosen tool
|
||||||
|
performs `install` followed by `run build`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||||
|
|
||||||
|
|
||||||
|
class WebUIBuildHook(BuildHookInterface):
|
||||||
|
PLUGIN_NAME = "webui-build"
|
||||||
|
|
||||||
|
def initialize(self, version: str, build_data: dict) -> None: # noqa: D401
|
||||||
|
root = Path(self.root)
|
||||||
|
webui_dir = root / "webui"
|
||||||
|
package_json = webui_dir / "package.json"
|
||||||
|
dist_dir = root / "nanobot" / "web" / "dist"
|
||||||
|
index_html = dist_dir / "index.html"
|
||||||
|
|
||||||
|
# `pip install -e .` builds an editable wheel; skip the (slow) webui
|
||||||
|
# bundle since editable installs target Python development and webui
|
||||||
|
# work uses `bun run dev` instead.
|
||||||
|
if self.target_name == "wheel" and version == "editable":
|
||||||
|
self.app.display_info(
|
||||||
|
"[webui-build] skipped for editable install "
|
||||||
|
"(use `cd webui && bun run build` to bundle webui manually)"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if os.environ.get("NANOBOT_SKIP_WEBUI_BUILD") == "1":
|
||||||
|
self.app.display_info("[webui-build] skipped via NANOBOT_SKIP_WEBUI_BUILD=1")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not package_json.is_file():
|
||||||
|
self.app.display_info(
|
||||||
|
"[webui-build] no webui/ source tree, assuming prebuilt nanobot/web/dist/"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
force = os.environ.get("NANOBOT_FORCE_WEBUI_BUILD") == "1"
|
||||||
|
if index_html.is_file() and not force:
|
||||||
|
self.app.display_info(
|
||||||
|
f"[webui-build] reusing existing build at {dist_dir} "
|
||||||
|
"(set NANOBOT_FORCE_WEBUI_BUILD=1 to rebuild)"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
runner = self._pick_runner()
|
||||||
|
if runner is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
"[webui-build] neither `bun` nor `npm` is available on PATH; "
|
||||||
|
"install one or set NANOBOT_SKIP_WEBUI_BUILD=1 to bypass."
|
||||||
|
)
|
||||||
|
|
||||||
|
self.app.display_info(f"[webui-build] using {runner} to build webui")
|
||||||
|
self._run([runner, "install"], cwd=webui_dir)
|
||||||
|
self._run([runner, "run", "build"], cwd=webui_dir)
|
||||||
|
|
||||||
|
if not index_html.is_file():
|
||||||
|
raise RuntimeError(
|
||||||
|
f"[webui-build] build finished but {index_html} is missing; "
|
||||||
|
"check webui/vite.config.ts outDir."
|
||||||
|
)
|
||||||
|
self.app.display_info(f"[webui-build] webui ready at {dist_dir}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _pick_runner() -> str | None:
|
||||||
|
for candidate in ("bun", "npm"):
|
||||||
|
if shutil.which(candidate):
|
||||||
|
return candidate
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _run(self, cmd: list[str], *, cwd: Path) -> None:
|
||||||
|
self.app.display_info(f"[webui-build] $ {' '.join(cmd)} (cwd={cwd})")
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd, cwd=cwd, check=True)
|
||||||
|
except subprocess.CalledProcessError as exc:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"[webui-build] command failed ({exc.returncode}): {' '.join(cmd)}"
|
||||||
|
) from exc
|
||||||
@ -21,7 +21,7 @@ def _resolve_version() -> str:
|
|||||||
return _pkg_version("nanobot-ai")
|
return _pkg_version("nanobot-ai")
|
||||||
except PackageNotFoundError:
|
except PackageNotFoundError:
|
||||||
# Source checkouts often import nanobot without installed dist-info.
|
# Source checkouts often import nanobot without installed dist-info.
|
||||||
return _read_pyproject_version() or "0.1.5.post3"
|
return _read_pyproject_version() or "0.2.0"
|
||||||
|
|
||||||
|
|
||||||
__version__ = _resolve_version()
|
__version__ = _resolve_version()
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
"""Embedded web UI assets.
|
"""Embedded web UI assets.
|
||||||
|
|
||||||
The ``dist/`` subdirectory is populated by ``cd webui && bun run build`` and
|
The ``dist/`` subdirectory holds the production WebUI bundle served by the
|
||||||
is shipped in the wheel; it stays empty in source checkouts until that command
|
gateway. It is shipped inside the published wheel and is rebuilt automatically
|
||||||
has been run.
|
by the ``webui-build`` Hatch hook during ``python -m build``. In an editable
|
||||||
|
source checkout it stays empty until you run ``cd webui && bun run build``
|
||||||
|
(or use the Vite dev server at ``cd webui && bun run dev``).
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "nanobot-ai"
|
name = "nanobot-ai"
|
||||||
version = "0.1.5.post3"
|
version = "0.2.0"
|
||||||
description = "A lightweight personal AI assistant framework"
|
description = "A lightweight personal AI assistant framework"
|
||||||
readme = { file = "README.md", content-type = "text/markdown" }
|
readme = { file = "README.md", content-type = "text/markdown" }
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
@ -121,12 +121,22 @@ build-backend = "hatchling.build"
|
|||||||
[tool.hatch.metadata]
|
[tool.hatch.metadata]
|
||||||
allow-direct-references = true
|
allow-direct-references = true
|
||||||
|
|
||||||
|
[tool.hatch.build.hooks.custom]
|
||||||
|
# Implementation lives in the conventional `hatch_build.py` at the repo root.
|
||||||
|
|
||||||
[tool.hatch.build]
|
[tool.hatch.build]
|
||||||
include = [
|
include = [
|
||||||
"nanobot/**/*.py",
|
"nanobot/**/*.py",
|
||||||
"nanobot/templates/**/*.md",
|
"nanobot/templates/**/*.md",
|
||||||
"nanobot/skills/**/*.md",
|
"nanobot/skills/**/*.md",
|
||||||
"nanobot/skills/**/*.sh",
|
"nanobot/skills/**/*.sh",
|
||||||
|
"nanobot/web/dist/**/*",
|
||||||
|
]
|
||||||
|
# nanobot/web/dist/ is produced by `cd webui && bun run build` and is
|
||||||
|
# git-ignored. List it as an artifact so hatch ships it in both wheel and
|
||||||
|
# sdist even though VCS does not track it.
|
||||||
|
artifacts = [
|
||||||
|
"nanobot/web/dist/**/*",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
@ -141,7 +151,9 @@ packages = ["nanobot"]
|
|||||||
[tool.hatch.build.targets.sdist]
|
[tool.hatch.build.targets.sdist]
|
||||||
include = [
|
include = [
|
||||||
"nanobot/",
|
"nanobot/",
|
||||||
|
"nanobot/web/dist/",
|
||||||
"bridge/",
|
"bridge/",
|
||||||
|
"hatch_build.py",
|
||||||
"README.md",
|
"README.md",
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"THIRD_PARTY_NOTICES.md",
|
"THIRD_PARTY_NOTICES.md",
|
||||||
|
|||||||
@ -8,15 +8,11 @@ on the same port.
|
|||||||
For the project overview, install guide, and general docs map, see the root
|
For the project overview, install guide, and general docs map, see the root
|
||||||
[`README.md`](../README.md).
|
[`README.md`](../README.md).
|
||||||
|
|
||||||
## Current status
|
## Just want to use the WebUI?
|
||||||
|
|
||||||
> [!NOTE]
|
If you installed nanobot via `pip install nanobot-ai`, the WebUI is **already bundled** in the wheel. Enable the WebSocket channel in `~/.nanobot/config.json` and run `nanobot gateway` — see the root [`README.md`](../README.md#-webui) for the 3-step setup. You do **not** need anything in this directory.
|
||||||
> The standalone WebUI development workflow currently requires a source
|
|
||||||
> checkout.
|
This `webui/` tree is for people **hacking on the WebUI itself** (UI changes, new components, styling, etc.).
|
||||||
>
|
|
||||||
> WebUI changes in the GitHub repository may land before they are included in
|
|
||||||
> the next packaged release, so source installs and published package versions
|
|
||||||
> are not yet guaranteed to move in lockstep.
|
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
@ -25,7 +21,7 @@ webui/ source tree (this directory)
|
|||||||
nanobot/web/dist/ build output served by the gateway
|
nanobot/web/dist/ build output served by the gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
## Develop from source
|
## Develop the WebUI (Vite HMR)
|
||||||
|
|
||||||
### 1. Install nanobot from source
|
### 1. Install nanobot from source
|
||||||
|
|
||||||
@ -35,6 +31,8 @@ From the repository root:
|
|||||||
pip install -e .
|
pip install -e .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Editable installs intentionally **skip** the WebUI bundle step — Vite HMR is faster than rebuilding `dist/` on every change.
|
||||||
|
|
||||||
### 2. Enable the WebSocket channel
|
### 2. Enable the WebSocket channel
|
||||||
|
|
||||||
In `~/.nanobot/config.json`:
|
In `~/.nanobot/config.json`:
|
||||||
@ -63,8 +61,7 @@ bun run dev
|
|||||||
|
|
||||||
Then open `http://127.0.0.1:5173`.
|
Then open `http://127.0.0.1:5173`.
|
||||||
|
|
||||||
By default, the dev server proxies `/api`, `/webui`, `/auth`, and WebSocket
|
By default the dev server proxies `/api`, `/webui`, `/auth`, and WebSocket traffic to `http://127.0.0.1:8765`.
|
||||||
traffic to `http://127.0.0.1:8765`.
|
|
||||||
|
|
||||||
If your gateway listens on a non-default port, point the dev server at it:
|
If your gateway listens on a non-default port, point the dev server at it:
|
||||||
|
|
||||||
@ -74,7 +71,7 @@ NANOBOT_API_URL=http://127.0.0.1:9000 bun run dev
|
|||||||
|
|
||||||
### Access from another device (LAN)
|
### Access from another device (LAN)
|
||||||
|
|
||||||
To use the webui from another device on the same network, set `host` to `"0.0.0.0"` and configure a `token` or `tokenIssueSecret` in `~/.nanobot/config.json`:
|
To use the WebUI from another device on the same network, set `host` to `"0.0.0.0"` and configure a `token` or `tokenIssueSecret` in `~/.nanobot/config.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -91,20 +88,20 @@ To use the webui from another device on the same network, set `host` to `"0.0.0.
|
|||||||
|
|
||||||
The gateway will refuse to start if `host` is `"0.0.0.0"` and neither `token` nor `tokenIssueSecret` is set.
|
The gateway will refuse to start if `host` is `"0.0.0.0"` and neither `token` nor `tokenIssueSecret` is set.
|
||||||
|
|
||||||
Then open `http://<your-ip>:8765` on the other device. The webui will show an authentication form where you enter the secret. It is saved in your browser so you only need to enter it once.
|
Then open `http://<your-ip>:8765` on the other device. The WebUI will show an authentication form where you enter the secret. It is saved in your browser so you only need to enter it once.
|
||||||
|
|
||||||
## Build for packaged runtime
|
## Build for packaged runtime
|
||||||
|
|
||||||
|
You usually do not need to run this by hand: `python -m build` invokes the WebUI build automatically when packaging the wheel.
|
||||||
|
|
||||||
|
If you want to preview the production bundle locally without rebuilding the wheel:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd webui
|
cd webui
|
||||||
bun run build
|
bun run build # writes to ../nanobot/web/dist
|
||||||
```
|
```
|
||||||
|
|
||||||
This writes the production assets to `../nanobot/web/dist`, which is the
|
The gateway picks up the new bundle on the next restart.
|
||||||
directory served by `nanobot gateway` and bundled into the Python wheel.
|
|
||||||
|
|
||||||
If you are cutting a release, run the build before packaging so the published
|
|
||||||
wheel contains the current WebUI assets.
|
|
||||||
|
|
||||||
## Test
|
## Test
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,11 @@
|
|||||||
"@radix-ui/react-tooltip": "^1.1.6",
|
"@radix-ui/react-tooltip": "^1.1.6",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"i18next": "^26.0.6",
|
||||||
"lucide-react": "^0.469.0",
|
"lucide-react": "^0.469.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-i18next": "^17.0.4",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
"react-syntax-highlighter": "^15.6.1",
|
"react-syntax-highlighter": "^15.6.1",
|
||||||
"rehype-katex": "^7.0.1",
|
"rehype-katex": "^7.0.1",
|
||||||
@ -506,8 +508,12 @@
|
|||||||
|
|
||||||
"highlightjs-vue": ["highlightjs-vue@1.0.0", "", {}, "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="],
|
"highlightjs-vue": ["highlightjs-vue@1.0.0", "", {}, "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="],
|
||||||
|
|
||||||
|
"html-parse-stringify": ["html-parse-stringify@3.0.1", "", { "dependencies": { "void-elements": "3.1.0" } }, "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg=="],
|
||||||
|
|
||||||
"html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
|
"html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
|
||||||
|
|
||||||
|
"i18next": ["i18next@26.2.0", "", { "peerDependencies": { "typescript": "^5 || ^6" }, "optionalPeers": ["typescript"] }, "sha512-zwBHldHdTmwN7r6UNc7lC6GWNN+YYg3DrRSeHR5PRRBf5QnJZcYHrQc0uaU26qZeYxR7iFZD+Y315dPnKP47wA=="],
|
||||||
|
|
||||||
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
|
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
|
||||||
|
|
||||||
"inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
|
"inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
|
||||||
@ -718,6 +724,8 @@
|
|||||||
|
|
||||||
"react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
|
"react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
|
||||||
|
|
||||||
|
"react-i18next": ["react-i18next@17.0.8", "", { "dependencies": { "@babel/runtime": "^7.29.2", "html-parse-stringify": "^3.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "i18next": ">= 26.2.0", "react": ">= 16.8.0", "typescript": "^5 || ^6" }, "optionalPeers": ["typescript"] }, "sha512-0ooKbGLU8JXhe1zwpQUWIeXSgLPOfwJmgheWRIUpcoA0CpyabpGhayjdG+/eA5esC1AQ8h2jWpXjJfzQzeDOCw=="],
|
||||||
|
|
||||||
"react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
"react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||||
|
|
||||||
"react-markdown": ["react-markdown@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw=="],
|
"react-markdown": ["react-markdown@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw=="],
|
||||||
@ -860,6 +868,8 @@
|
|||||||
|
|
||||||
"vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="],
|
"vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="],
|
||||||
|
|
||||||
|
"void-elements": ["void-elements@3.1.0", "", {}, "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="],
|
||||||
|
|
||||||
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
|
||||||
|
|
||||||
"webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
|
"webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import React from "react";
|
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
|
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": ["node"]
|
"types": ["node", "vite/client"]
|
||||||
},
|
},
|
||||||
"exclude": ["src/tests/**"]
|
"exclude": ["src/tests/**"]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user