zerochat 7.3.0__tar.gz → 7.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zerochat-7.3.0/zerochat.egg-info → zerochat-7.5.0}/PKG-INFO +6 -4
- {zerochat-7.3.0 → zerochat-7.5.0}/README.md +5 -3
- {zerochat-7.3.0 → zerochat-7.5.0}/pyproject.toml +1 -2
- {zerochat-7.3.0 → zerochat-7.5.0/zerochat.egg-info}/PKG-INFO +6 -4
- zerochat-7.5.0/zerochat.egg-info/SOURCES.txt +9 -0
- zerochat-7.5.0/zerochat.egg-info/top_level.txt +1 -0
- {zerochat-7.3.0 → zerochat-7.5.0}/zerochat.py +74 -100
- zerochat-7.3.0/MANIFEST.in +0 -15
- zerochat-7.3.0/css/base.css +0 -199
- zerochat-7.3.0/css/components/composer.css +0 -1258
- zerochat-7.3.0/css/components/debug.css +0 -777
- zerochat-7.3.0/css/components/header.css +0 -97
- zerochat-7.3.0/css/components/icons.css +0 -39
- zerochat-7.3.0/css/components/markdown.css +0 -685
- zerochat-7.3.0/css/components/messages.css +0 -473
- zerochat-7.3.0/css/components/modals.css +0 -1319
- zerochat-7.3.0/css/components/sidebar.css +0 -622
- zerochat-7.3.0/css/components/tools.css +0 -1223
- zerochat-7.3.0/css/layout.css +0 -171
- zerochat-7.3.0/css/print.css +0 -120
- zerochat-7.3.0/css/styles.css +0 -18
- zerochat-7.3.0/css/theme-overrides.css +0 -555
- zerochat-7.3.0/css/tokens.css +0 -165
- zerochat-7.3.0/help/architecture.html +0 -247
- zerochat-7.3.0/help/composer.html +0 -134
- zerochat-7.3.0/help/conversations.html +0 -105
- zerochat-7.3.0/help/debug.html +0 -108
- zerochat-7.3.0/help/en/architecture.html +0 -247
- zerochat-7.3.0/help/en/composer.html +0 -134
- zerochat-7.3.0/help/en/conversations.html +0 -104
- zerochat-7.3.0/help/en/debug.html +0 -105
- zerochat-7.3.0/help/en/gemini-free.html +0 -39
- zerochat-7.3.0/help/en/index.html +0 -191
- zerochat-7.3.0/help/en/learning.html +0 -71
- zerochat-7.3.0/help/en/mcp.html +0 -143
- zerochat-7.3.0/help/en/openrouter-free.html +0 -39
- zerochat-7.3.0/help/en/profiles.html +0 -173
- zerochat-7.3.0/help/en/rag.html +0 -130
- zerochat-7.3.0/help/en/reasoning-telemetry.html +0 -108
- zerochat-7.3.0/help/en/tools-agent.html +0 -133
- zerochat-7.3.0/help/en/webllm.html +0 -355
- zerochat-7.3.0/help/gemini-free.html +0 -39
- zerochat-7.3.0/help/help.css +0 -604
- zerochat-7.3.0/help/help.js +0 -51
- zerochat-7.3.0/help/index.html +0 -194
- zerochat-7.3.0/help/learning.html +0 -71
- zerochat-7.3.0/help/mcp.html +0 -143
- zerochat-7.3.0/help/openrouter-free.html +0 -39
- zerochat-7.3.0/help/profiles.html +0 -174
- zerochat-7.3.0/help/rag.html +0 -130
- zerochat-7.3.0/help/reasoning-telemetry.html +0 -111
- zerochat-7.3.0/help/tools-agent.html +0 -133
- zerochat-7.3.0/help/webllm.html +0 -359
- zerochat-7.3.0/js/agent-core.js +0 -1553
- zerochat-7.3.0/js/api.js +0 -844
- zerochat-7.3.0/js/app.js +0 -2558
- zerochat-7.3.0/js/attachments.js +0 -220
- zerochat-7.3.0/js/charts.js +0 -338
- zerochat-7.3.0/js/chat-engine.js +0 -566
- zerochat-7.3.0/js/config-store.js +0 -207
- zerochat-7.3.0/js/context-manager.js +0 -584
- zerochat-7.3.0/js/conversation-service.js +0 -484
- zerochat-7.3.0/js/cookies.js +0 -688
- zerochat-7.3.0/js/data-reset-service.js +0 -136
- zerochat-7.3.0/js/debug.js +0 -508
- zerochat-7.3.0/js/defaults.js +0 -16
- zerochat-7.3.0/js/export.js +0 -179
- zerochat-7.3.0/js/file-parser.js +0 -2088
- zerochat-7.3.0/js/generation-controller.js +0 -417
- zerochat-7.3.0/js/i18n.js +0 -1483
- zerochat-7.3.0/js/icons.js +0 -156
- zerochat-7.3.0/js/ingestionEngine.js +0 -436
- zerochat-7.3.0/js/markdown.js +0 -588
- zerochat-7.3.0/js/mcp.js +0 -1271
- zerochat-7.3.0/js/message-turns.js +0 -62
- zerochat-7.3.0/js/profile-backup.js +0 -118
- zerochat-7.3.0/js/profile-export-bundle.js +0 -481
- zerochat-7.3.0/js/profile-repository.js +0 -213
- zerochat-7.3.0/js/providers-webllm.js +0 -486
- zerochat-7.3.0/js/providers.js +0 -1560
- zerochat-7.3.0/js/rag-index.js +0 -295
- zerochat-7.3.0/js/rag-service.js +0 -530
- zerochat-7.3.0/js/rag-ui.js +0 -997
- zerochat-7.3.0/js/ragStorage.js +0 -676
- zerochat-7.3.0/js/sandbox.js +0 -449
- zerochat-7.3.0/js/state.js +0 -704
- zerochat-7.3.0/js/storage-db.js +0 -144
- zerochat-7.3.0/js/tool-cards.js +0 -330
- zerochat-7.3.0/js/tool-security.js +0 -653
- zerochat-7.3.0/js/tools/README.md +0 -50
- zerochat-7.3.0/js/tools/builtin/agent-checkpoint.tool.js +0 -212
- zerochat-7.3.0/js/tools/builtin/download-pdf.tool.js +0 -111
- zerochat-7.3.0/js/tools/builtin/execute-javascript.tool.js +0 -219
- zerochat-7.3.0/js/tools/builtin/fetch-web-page.tool.js +0 -112
- zerochat-7.3.0/js/tools/builtin/list-documents.tool.js +0 -117
- zerochat-7.3.0/js/tools/builtin/read-knowledge-chunk.tool.js +0 -129
- zerochat-7.3.0/js/tools/builtin/read-knowledge-image.tool.js +0 -95
- zerochat-7.3.0/js/tools/builtin/render-chart.tool.js +0 -90
- zerochat-7.3.0/js/tools/builtin/search-knowledge-base.tool.js +0 -124
- zerochat-7.3.0/js/tools/builtin/search-web.tool.js +0 -125
- zerochat-7.3.0/js/tools/tool-manifest.js +0 -53
- zerochat-7.3.0/js/tools/tool-runtime.js +0 -77
- zerochat-7.3.0/js/ui-composer.js +0 -319
- zerochat-7.3.0/js/ui-conversation.js +0 -655
- zerochat-7.3.0/js/ui-dialogs.js +0 -132
- zerochat-7.3.0/js/ui-generation-status.js +0 -119
- zerochat-7.3.0/js/ui-inspector.js +0 -804
- zerochat-7.3.0/js/ui-mcp.js +0 -604
- zerochat-7.3.0/js/ui-profiles.js +0 -824
- zerochat-7.3.0/js/ui-reasoning.js +0 -146
- zerochat-7.3.0/js/ui-settings.js +0 -825
- zerochat-7.3.0/js/ui-shell.js +0 -215
- zerochat-7.3.0/js/ui-sidebar.js +0 -429
- zerochat-7.3.0/js/ui-telemetry.js +0 -404
- zerochat-7.3.0/js/ui-transfer.js +0 -262
- zerochat-7.3.0/js/utils.js +0 -216
- zerochat-7.3.0/js/vendor/orama.browser.js +0 -11
- zerochat-7.3.0/js/web-browser.js +0 -569
- zerochat-7.3.0/js/web-search.js +0 -519
- zerochat-7.3.0/manifest.webmanifest +0 -20
- zerochat-7.3.0/services/dummy_mcp/dummy_mcp_server.py +0 -47
- zerochat-7.3.0/services/dummy_mcp/service.json +0 -22
- zerochat-7.3.0/services/lsp/installer.json +0 -9
- zerochat-7.3.0/services/lsp/service.json +0 -22
- zerochat-7.3.0/services/memory/installer.json +0 -9
- zerochat-7.3.0/services/memory/service.json +0 -24
- zerochat-7.3.0/services/playwright/installer.json +0 -10
- zerochat-7.3.0/services/playwright/service.json +0 -39
- zerochat-7.3.0/setup.py +0 -42
- zerochat-7.3.0/sw.js +0 -164
- zerochat-7.3.0/zerochat.egg-info/SOURCES.txt +0 -134
- zerochat-7.3.0/zerochat.egg-info/top_level.txt +0 -2
- zerochat-7.3.0/zerochat.html +0 -671
- zerochat-7.3.0/zerochat_runtime/__init__.py +0 -1
- {zerochat-7.3.0 → zerochat-7.5.0}/LICENSE +0 -0
- {zerochat-7.3.0 → zerochat-7.5.0}/setup.cfg +0 -0
- {zerochat-7.3.0 → zerochat-7.5.0}/zerochat.egg-info/dependency_links.txt +0 -0
- {zerochat-7.3.0 → zerochat-7.5.0}/zerochat.egg-info/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zerochat
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.5.0
|
|
4
4
|
Summary: Private local web client for AI models, tools and MCP services
|
|
5
5
|
Author: Alberto Balday
|
|
6
6
|
License-Expression: MIT
|
|
@@ -41,13 +41,15 @@ Funciona de forma estática en el navegador (servido por GitHub Pages o directam
|
|
|
41
41
|
```bash
|
|
42
42
|
python3 zerochat.py
|
|
43
43
|
```
|
|
44
|
-
Inicia el asistente local, crea
|
|
44
|
+
Inicia el asistente local, crea `./zerochat/.venv` para los MCP y abre la interfaz web en tu navegador.
|
|
45
45
|
- **Instalación con PyPI**:
|
|
46
46
|
```bash
|
|
47
|
-
|
|
47
|
+
pip install zerochat
|
|
48
48
|
zerochat
|
|
49
49
|
```
|
|
50
|
-
|
|
50
|
+
Es la vía recomendada para instalar el servidor local desde PyPI. Igual que con la descarga directa, crea `./zerochat/` para el estado y los MCP; la interfaz se carga desde GitHub Pages.
|
|
51
|
+
|
|
52
|
+
En ambos modos, `./zerochat/` contiene configuración, token, servicios MCP y sus dependencias Python en `.venv/`. Borrar ese directorio elimina el estado local y los MCP, sin desinstalar el ejecutable de PyPI ni el archivo descargado.
|
|
51
53
|
|
|
52
54
|
Las publicaciones se realizan desde el repositorio oficial mediante GitHub Actions y PyPI Trusted Publishing.
|
|
53
55
|
|
|
@@ -19,13 +19,15 @@ Funciona de forma estática en el navegador (servido por GitHub Pages o directam
|
|
|
19
19
|
```bash
|
|
20
20
|
python3 zerochat.py
|
|
21
21
|
```
|
|
22
|
-
Inicia el asistente local, crea
|
|
22
|
+
Inicia el asistente local, crea `./zerochat/.venv` para los MCP y abre la interfaz web en tu navegador.
|
|
23
23
|
- **Instalación con PyPI**:
|
|
24
24
|
```bash
|
|
25
|
-
|
|
25
|
+
pip install zerochat
|
|
26
26
|
zerochat
|
|
27
27
|
```
|
|
28
|
-
|
|
28
|
+
Es la vía recomendada para instalar el servidor local desde PyPI. Igual que con la descarga directa, crea `./zerochat/` para el estado y los MCP; la interfaz se carga desde GitHub Pages.
|
|
29
|
+
|
|
30
|
+
En ambos modos, `./zerochat/` contiene configuración, token, servicios MCP y sus dependencias Python en `.venv/`. Borrar ese directorio elimina el estado local y los MCP, sin desinstalar el ejecutable de PyPI ni el archivo descargado.
|
|
29
31
|
|
|
30
32
|
Las publicaciones se realizan desde el repositorio oficial mediante GitHub Actions y PyPI Trusted Publishing.
|
|
31
33
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "zerochat"
|
|
7
|
-
version = "7.
|
|
7
|
+
version = "7.5.0"
|
|
8
8
|
description = "Private local web client for AI models, tools and MCP services"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -32,4 +32,3 @@ zerochat = "zerochat:main"
|
|
|
32
32
|
|
|
33
33
|
[tool.setuptools]
|
|
34
34
|
py-modules = ["zerochat"]
|
|
35
|
-
packages = ["zerochat_runtime"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zerochat
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.5.0
|
|
4
4
|
Summary: Private local web client for AI models, tools and MCP services
|
|
5
5
|
Author: Alberto Balday
|
|
6
6
|
License-Expression: MIT
|
|
@@ -41,13 +41,15 @@ Funciona de forma estática en el navegador (servido por GitHub Pages o directam
|
|
|
41
41
|
```bash
|
|
42
42
|
python3 zerochat.py
|
|
43
43
|
```
|
|
44
|
-
Inicia el asistente local, crea
|
|
44
|
+
Inicia el asistente local, crea `./zerochat/.venv` para los MCP y abre la interfaz web en tu navegador.
|
|
45
45
|
- **Instalación con PyPI**:
|
|
46
46
|
```bash
|
|
47
|
-
|
|
47
|
+
pip install zerochat
|
|
48
48
|
zerochat
|
|
49
49
|
```
|
|
50
|
-
|
|
50
|
+
Es la vía recomendada para instalar el servidor local desde PyPI. Igual que con la descarga directa, crea `./zerochat/` para el estado y los MCP; la interfaz se carga desde GitHub Pages.
|
|
51
|
+
|
|
52
|
+
En ambos modos, `./zerochat/` contiene configuración, token, servicios MCP y sus dependencias Python en `.venv/`. Borrar ese directorio elimina el estado local y los MCP, sin desinstalar el ejecutable de PyPI ni el archivo descargado.
|
|
51
53
|
|
|
52
54
|
Las publicaciones se realizan desde el repositorio oficial mediante GitHub Actions y PyPI Trusted Publishing.
|
|
53
55
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
zerochat
|
|
@@ -16,7 +16,6 @@ import atexit
|
|
|
16
16
|
import datetime
|
|
17
17
|
import hmac
|
|
18
18
|
import importlib.metadata
|
|
19
|
-
import importlib.resources
|
|
20
19
|
import json
|
|
21
20
|
import os
|
|
22
21
|
import platform
|
|
@@ -38,6 +37,8 @@ import webbrowser
|
|
|
38
37
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
39
38
|
from pathlib import Path
|
|
40
39
|
|
|
40
|
+
SOURCE_BACKEND_VERSION = "7.5.0"
|
|
41
|
+
|
|
41
42
|
def _read_source_version(filename: str) -> str | None:
|
|
42
43
|
"""Lee la versión de un archivo del repositorio cuando se ejecuta desde fuentes."""
|
|
43
44
|
try:
|
|
@@ -54,10 +55,13 @@ def _read_source_version(filename: str) -> str | None:
|
|
|
54
55
|
|
|
55
56
|
def _read_backend_version() -> str:
|
|
56
57
|
"""Devuelve la versión publicada del backend, sin depender de package.json instalado."""
|
|
58
|
+
source_version = _read_source_version("pyproject.toml")
|
|
59
|
+
if source_version:
|
|
60
|
+
return source_version
|
|
57
61
|
try:
|
|
58
62
|
return importlib.metadata.version("zerochat")
|
|
59
63
|
except importlib.metadata.PackageNotFoundError:
|
|
60
|
-
return
|
|
64
|
+
return SOURCE_BACKEND_VERSION
|
|
61
65
|
|
|
62
66
|
|
|
63
67
|
def _read_ui_version() -> str:
|
|
@@ -85,6 +89,7 @@ DEFAULT_PORT = 6388
|
|
|
85
89
|
DEFAULT_HOST = "127.0.0.1"
|
|
86
90
|
DEFAULT_UI_URL = "https://albalday.github.io/zerochat/zerochat.html"
|
|
87
91
|
REMOTE_VERSION_URL = "https://raw.githubusercontent.com/albalday/zerochat/master/package.json"
|
|
92
|
+
PYPI_VERSION_URL = "https://pypi.org/pypi/zerochat/json"
|
|
88
93
|
REMOTE_SCRIPT_URL = "https://raw.githubusercontent.com/albalday/zerochat/master/zerochat.py"
|
|
89
94
|
CONSOLE_STATUS_IDLE_SECONDS = 8.0
|
|
90
95
|
CONSOLE_CONTROL = None
|
|
@@ -229,18 +234,6 @@ def console_log(message: str, *, flush: bool = True):
|
|
|
229
234
|
else:
|
|
230
235
|
print(message, flush=flush)
|
|
231
236
|
|
|
232
|
-
def get_packaged_assets_root() -> Path | None:
|
|
233
|
-
"""Devuelve los recursos incluidos en la distribución PyPI, si existen."""
|
|
234
|
-
try:
|
|
235
|
-
root = importlib.resources.files("zerochat_runtime").joinpath("assets")
|
|
236
|
-
path = Path(str(root))
|
|
237
|
-
if (path / "zerochat.html").is_file():
|
|
238
|
-
return path
|
|
239
|
-
except (ModuleNotFoundError, TypeError):
|
|
240
|
-
pass
|
|
241
|
-
return None
|
|
242
|
-
|
|
243
|
-
|
|
244
237
|
def get_dev_root() -> Path | None:
|
|
245
238
|
"""
|
|
246
239
|
Detecta si zerochat.py se está ejecutando en el directorio de desarrollo del repositorio.
|
|
@@ -255,34 +248,36 @@ def get_dev_root() -> Path | None:
|
|
|
255
248
|
|
|
256
249
|
|
|
257
250
|
def get_static_root() -> Path | None:
|
|
258
|
-
"""
|
|
259
|
-
return get_dev_root()
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
def is_packaged_runtime() -> bool:
|
|
263
|
-
return get_dev_root() is None and get_packaged_assets_root() is not None
|
|
251
|
+
"""La interfaz local solo se sirve al ejecutar el repositorio de desarrollo."""
|
|
252
|
+
return get_dev_root()
|
|
264
253
|
|
|
265
254
|
|
|
266
|
-
def
|
|
267
|
-
"""
|
|
255
|
+
def is_installed_runtime() -> bool:
|
|
256
|
+
"""Identifica el ejecutable instalado desde PyPI, sin confundirlo con el repositorio."""
|
|
268
257
|
if get_dev_root() is not None:
|
|
269
|
-
return
|
|
258
|
+
return False
|
|
259
|
+
try:
|
|
260
|
+
return importlib.metadata.version("zerochat") == BACKEND_PACKAGE_VERSION
|
|
261
|
+
except importlib.metadata.PackageNotFoundError:
|
|
262
|
+
return False
|
|
263
|
+
|
|
270
264
|
|
|
265
|
+
def get_data_dir() -> Path:
|
|
266
|
+
"""Devuelve el directorio local que concentra el estado y los MCP de ZeroChat."""
|
|
271
267
|
configured = os.environ.get("ZEROCHAT_DATA_DIR", "").strip()
|
|
272
268
|
if configured:
|
|
273
269
|
return Path(configured).expanduser().resolve()
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return (base / "zerochat").resolve()
|
|
270
|
+
return (Path.cwd() / "zerochat").resolve()
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def get_venv_dir() -> Path:
|
|
274
|
+
"""Devuelve el entorno aislado usado exclusivamente por los MCP Python."""
|
|
275
|
+
return get_data_dir() / ".venv"
|
|
281
276
|
|
|
282
277
|
|
|
283
278
|
def get_daily_token() -> str:
|
|
284
279
|
"""Devuelve un token de sesión diario persistido en ./zerochat/config/token.json."""
|
|
285
|
-
config_dir =
|
|
280
|
+
config_dir = get_data_dir() / "config"
|
|
286
281
|
config_dir.mkdir(parents=True, exist_ok=True)
|
|
287
282
|
token_file = config_dir / "token.json"
|
|
288
283
|
today = datetime.date.today().isoformat()
|
|
@@ -320,12 +315,10 @@ def get_venv_python(venv_dir: Path) -> Path:
|
|
|
320
315
|
|
|
321
316
|
def ensure_virtual_environment():
|
|
322
317
|
"""
|
|
323
|
-
|
|
324
|
-
|
|
318
|
+
Crea ./zerochat/.venv para dependencias MCP en ambos modos de distribución.
|
|
319
|
+
El servidor conserva el intérprete con el que fue iniciado; el entorno se usa
|
|
320
|
+
exclusivamente al lanzar procesos MCP Python.
|
|
325
321
|
"""
|
|
326
|
-
if is_packaged_runtime():
|
|
327
|
-
return
|
|
328
|
-
|
|
329
322
|
venv_dir = get_venv_dir()
|
|
330
323
|
venv_py = get_venv_python(venv_dir)
|
|
331
324
|
|
|
@@ -339,19 +332,6 @@ def ensure_virtual_environment():
|
|
|
339
332
|
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Advertencia al crear venv: {err}. Continuando con intérprete actual.", flush=True)
|
|
340
333
|
return
|
|
341
334
|
|
|
342
|
-
# 2. Comprobar si ya estamos ejecutándonos dentro del venv
|
|
343
|
-
try:
|
|
344
|
-
current_py = Path(sys.executable).resolve()
|
|
345
|
-
target_py = venv_py.resolve()
|
|
346
|
-
if current_py != target_py and target_py.exists():
|
|
347
|
-
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Re-ejecutando bajo {venv_py}...", flush=True)
|
|
348
|
-
# Re-ejecutar con los mismos argumentos
|
|
349
|
-
args = [str(target_py), str(Path(__file__).resolve())] + sys.argv[1:]
|
|
350
|
-
os.execv(str(target_py), args)
|
|
351
|
-
except Exception as err:
|
|
352
|
-
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Error en re-ejecución: {err}. Continuando.", flush=True)
|
|
353
|
-
|
|
354
|
-
|
|
355
335
|
def parse_version(ver: str) -> tuple[int, ...]:
|
|
356
336
|
"""Convierte una cadena de versión semántica en tupla de enteros para comparación."""
|
|
357
337
|
parts = []
|
|
@@ -362,29 +342,43 @@ def parse_version(ver: str) -> tuple[int, ...]:
|
|
|
362
342
|
return tuple(parts)
|
|
363
343
|
|
|
364
344
|
|
|
345
|
+
def _read_remote_version(url: str) -> str | None:
|
|
346
|
+
"""Obtiene una versión publicada desde package.json o la API JSON de PyPI."""
|
|
347
|
+
req = urllib.request.Request(url, headers={"User-Agent": f"ZeroChat/{VERSION}"})
|
|
348
|
+
with urllib.request.urlopen(req, timeout=3) as resp:
|
|
349
|
+
content = resp.read(4096).decode("utf-8", errors="ignore")
|
|
350
|
+
try:
|
|
351
|
+
data = json.loads(content)
|
|
352
|
+
if isinstance(data, dict):
|
|
353
|
+
candidate = data.get("version")
|
|
354
|
+
if not isinstance(candidate, str) and isinstance(data.get("info"), dict):
|
|
355
|
+
candidate = data["info"].get("version")
|
|
356
|
+
if isinstance(candidate, str):
|
|
357
|
+
return candidate.strip()
|
|
358
|
+
except (json.JSONDecodeError, TypeError):
|
|
359
|
+
pass
|
|
360
|
+
match = re.search(r'["\']?version["\']?\s*[:=]\s*["\'](\d+\.\d+\.\d+)["\']', content)
|
|
361
|
+
return match.group(1) if match else None
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def has_new_backend_version(remote_version: str, local_version: str = VERSION) -> bool:
|
|
365
|
+
"""Compara solo major.minor: los parches pertenecen a la interfaz web."""
|
|
366
|
+
return parse_version(compatibility_version(remote_version)) > parse_version(compatibility_version(local_version))
|
|
367
|
+
|
|
368
|
+
|
|
365
369
|
def check_version():
|
|
366
|
-
"""
|
|
367
|
-
if get_dev_root() is not None
|
|
370
|
+
"""Informa de actualizaciones del backend, sin avisar por parches web."""
|
|
371
|
+
if get_dev_root() is not None:
|
|
368
372
|
return
|
|
369
373
|
try:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
remote_ver =
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
except Exception:
|
|
379
|
-
pass
|
|
380
|
-
if not remote_ver:
|
|
381
|
-
match = re.search(r'["\']?version["\']?\s*[:=]\s*["\'](\d+\.\d+\.\d+)["\']', content)
|
|
382
|
-
if match:
|
|
383
|
-
remote_ver = match.group(1)
|
|
384
|
-
if remote_ver and re.match(r"^\d+(\.\d+)+", remote_ver):
|
|
385
|
-
if parse_version(remote_ver) > parse_version(VERSION):
|
|
386
|
-
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] ¡Nueva versión disponible! (Local: {VERSION}, Remota: {remote_ver})", flush=True)
|
|
387
|
-
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Actualiza con: curl -sSL {REMOTE_SCRIPT_URL} -o zerochat.py", flush=True)
|
|
374
|
+
installed = is_installed_runtime()
|
|
375
|
+
remote_ver = _read_remote_version(PYPI_VERSION_URL if installed else REMOTE_VERSION_URL)
|
|
376
|
+
if remote_ver and re.match(r"^\d+(\.\d+)+", remote_ver) and has_new_backend_version(remote_ver):
|
|
377
|
+
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Nueva versión del servidor disponible (Local: {VERSION}, Remota: {compatibility_version(remote_ver)})", flush=True)
|
|
378
|
+
if installed:
|
|
379
|
+
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Actualiza cuando quieras con: {sys.executable} -m pip install --upgrade zerochat", flush=True)
|
|
380
|
+
else:
|
|
381
|
+
console_log(f"[{time.strftime('%H:%M:%S')}] [zerochat] Actualiza con: curl -sSL {REMOTE_SCRIPT_URL} -o zerochat.py", flush=True)
|
|
388
382
|
except Exception:
|
|
389
383
|
# Modo offline o timeout ignorado de forma segura
|
|
390
384
|
pass
|
|
@@ -791,11 +785,11 @@ class McpServiceManager:
|
|
|
791
785
|
else:
|
|
792
786
|
candidates = [
|
|
793
787
|
Path.cwd() / "services",
|
|
794
|
-
|
|
788
|
+
get_data_dir() / "services"
|
|
795
789
|
]
|
|
796
790
|
self.services_root = candidates[0] if get_dev_root() is not None and candidates[0].is_dir() else candidates[1]
|
|
797
791
|
self.services_root.mkdir(parents=True, exist_ok=True)
|
|
798
|
-
self.config_file =
|
|
792
|
+
self.config_file = get_data_dir() / "config" / "services.json"
|
|
799
793
|
self.config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
800
794
|
self.clients: dict[str, StdioMcpClient] = {}
|
|
801
795
|
self.states: dict[str, str] = {}
|
|
@@ -805,28 +799,7 @@ class McpServiceManager:
|
|
|
805
799
|
self.services = self._load_services()
|
|
806
800
|
self.preferences = self._load_preferences()
|
|
807
801
|
|
|
808
|
-
def _copy_packaged_service_templates(self):
|
|
809
|
-
"""Inicializa descriptores MCP editables sin copiar dependencias instaladas."""
|
|
810
|
-
assets_root = get_packaged_assets_root()
|
|
811
|
-
if not assets_root:
|
|
812
|
-
return
|
|
813
|
-
templates_root = assets_root / "services"
|
|
814
|
-
if not templates_root.is_dir():
|
|
815
|
-
return
|
|
816
|
-
for source in templates_root.rglob("*"):
|
|
817
|
-
if not source.is_file():
|
|
818
|
-
continue
|
|
819
|
-
relative = source.relative_to(templates_root)
|
|
820
|
-
if any(part in {"node_modules", ".playwright-mcp"} or part.startswith(".") for part in relative.parts):
|
|
821
|
-
continue
|
|
822
|
-
target = self.services_root / relative
|
|
823
|
-
if target.exists():
|
|
824
|
-
continue
|
|
825
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
826
|
-
shutil.copy2(source, target)
|
|
827
|
-
|
|
828
802
|
def _ensure_default_services(self):
|
|
829
|
-
self._copy_packaged_service_templates()
|
|
830
803
|
dummy_dir = self.services_root / "dummy_mcp"
|
|
831
804
|
dummy_dir.mkdir(parents=True, exist_ok=True)
|
|
832
805
|
service_json_file = dummy_dir / "service.json"
|
|
@@ -1138,7 +1111,7 @@ for raw in sys.stdin:
|
|
|
1138
1111
|
|
|
1139
1112
|
return {
|
|
1140
1113
|
"serviceDir": str(service_dir),
|
|
1141
|
-
"pythonExecutable": sys.executable,
|
|
1114
|
+
"pythonExecutable": str(get_venv_python(get_venv_dir())) if get_venv_python(get_venv_dir()).is_file() else sys.executable,
|
|
1142
1115
|
"nodeExecutable": node
|
|
1143
1116
|
}
|
|
1144
1117
|
|
|
@@ -1350,7 +1323,7 @@ class ZeroChatServerHandler(BaseHTTPRequestHandler):
|
|
|
1350
1323
|
console_log(f"[{now}] <-- {status_text} {detail}{err_suffix} ({duration_ms:.1f}ms)", flush=True)
|
|
1351
1324
|
|
|
1352
1325
|
def serve_static_file(self, rel_path: str) -> bool:
|
|
1353
|
-
"""Sirve
|
|
1326
|
+
"""Sirve recursos estáticos solo desde el repositorio de desarrollo."""
|
|
1354
1327
|
static_root = get_static_root()
|
|
1355
1328
|
if not static_root:
|
|
1356
1329
|
return False
|
|
@@ -1890,7 +1863,7 @@ def main():
|
|
|
1890
1863
|
parser.add_argument("--ui-url", default=None, help="URL de la interfaz web a abrir (por defecto: interfaz local en desarrollo o GitHub Pages)")
|
|
1891
1864
|
parser.add_argument("--no-browser", action="store_true", help="No abrir automáticamente el navegador")
|
|
1892
1865
|
parser.add_argument("--no-exit-on-close", action="store_true", help="No detener el servidor automáticamente al cerrar el navegador")
|
|
1893
|
-
parser.add_argument("--no-venv", action="store_true", help="Omitir la comprobación/creación
|
|
1866
|
+
parser.add_argument("--no-venv", action="store_true", help="Omitir la comprobación/creación de ./zerochat/.venv")
|
|
1894
1867
|
parser.add_argument("--test", action="store_true", help="Ejecutar autocomprobación interna de herramientas")
|
|
1895
1868
|
parser.add_argument("--version", action="version", version=f"ZeroChat {VERSION}")
|
|
1896
1869
|
args = parser.parse_args()
|
|
@@ -1902,7 +1875,7 @@ def main():
|
|
|
1902
1875
|
print(f"[{time.strftime('%H:%M:%S')}] TEST all local tools ready.")
|
|
1903
1876
|
return
|
|
1904
1877
|
|
|
1905
|
-
# 1. Asegurar entorno
|
|
1878
|
+
# 1. Asegurar el entorno MCP aislado en ambos modos de distribución.
|
|
1906
1879
|
if not args.no_venv:
|
|
1907
1880
|
ensure_virtual_environment()
|
|
1908
1881
|
|
|
@@ -1910,7 +1883,7 @@ def main():
|
|
|
1910
1883
|
dev_root = get_dev_root()
|
|
1911
1884
|
static_root = get_static_root()
|
|
1912
1885
|
is_dev = dev_root is not None
|
|
1913
|
-
|
|
1886
|
+
is_installed = is_installed_runtime()
|
|
1914
1887
|
|
|
1915
1888
|
# 3. Comprobar versión remota en segundo plano (solo fuera del entorno de desarrollo local)
|
|
1916
1889
|
if not is_dev:
|
|
@@ -1939,11 +1912,12 @@ def main():
|
|
|
1939
1912
|
print("=" * 64)
|
|
1940
1913
|
print(f" ZeroChat Local Server v{VERSION} (UI {UI_VERSION})")
|
|
1941
1914
|
print(f" Directorio de trabajo : {Path.cwd()}")
|
|
1942
|
-
print(f"
|
|
1915
|
+
print(f" Datos y MCP : {get_data_dir()}")
|
|
1916
|
+
print(f" Entorno MCP : {get_venv_dir()}")
|
|
1943
1917
|
if is_dev:
|
|
1944
1918
|
print(f" Modo de ejecución : Desarrollo local ({dev_root})")
|
|
1945
|
-
elif
|
|
1946
|
-
print(" Modo de ejecución : Paquete PyPI (
|
|
1919
|
+
elif is_installed:
|
|
1920
|
+
print(" Modo de ejecución : Paquete PyPI (GitHub Pages)")
|
|
1947
1921
|
else:
|
|
1948
1922
|
print(f" Modo de ejecución : Producción (Web universal)")
|
|
1949
1923
|
print(f" Servidor HTTP/SSE : http://{ACTIVE_HOST}:{ACTIVE_PORT}")
|
zerochat-7.3.0/MANIFEST.in
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
include LICENSE
|
|
2
|
-
include README.md
|
|
3
|
-
include zerochat.html
|
|
4
|
-
include manifest.webmanifest
|
|
5
|
-
include sw.js
|
|
6
|
-
recursive-include js *
|
|
7
|
-
recursive-include css *
|
|
8
|
-
recursive-include help *
|
|
9
|
-
recursive-include services *.json *.py
|
|
10
|
-
prune services/*/node_modules
|
|
11
|
-
prune services/*/.playwright-mcp
|
|
12
|
-
exclude services/*/.installed.json
|
|
13
|
-
exclude services/*/package.json
|
|
14
|
-
exclude services/*/package-lock.json
|
|
15
|
-
exclude services/*/*.jsonl
|
zerochat-7.3.0/css/base.css
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/* ==========================================================================
|
|
2
|
-
ZeroChat Base Styles - Reseteo, Normalización, Animaciones y Accesibilidad
|
|
3
|
-
========================================================================== */
|
|
4
|
-
* {
|
|
5
|
-
box-sizing: border-box;
|
|
6
|
-
margin: 0;
|
|
7
|
-
padding: 0;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
img {
|
|
11
|
-
max-width: 100%;
|
|
12
|
-
height: auto;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
html, body {
|
|
16
|
-
height: 100%;
|
|
17
|
-
height: 100dvh;
|
|
18
|
-
height: var(--app-height, 100dvh);
|
|
19
|
-
min-height: -webkit-fill-available;
|
|
20
|
-
font-family: var(--font-sans);
|
|
21
|
-
background-color: var(--bg-app);
|
|
22
|
-
color: var(--text-main);
|
|
23
|
-
line-height: 1.5;
|
|
24
|
-
-webkit-font-smoothing: antialiased;
|
|
25
|
-
-moz-osx-font-smoothing: grayscale;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
body {
|
|
29
|
-
display: flex;
|
|
30
|
-
flex-direction: row;
|
|
31
|
-
height: 100%;
|
|
32
|
-
height: 100dvh;
|
|
33
|
-
height: var(--app-height, 100dvh);
|
|
34
|
-
width: 100%;
|
|
35
|
-
width: 100vw;
|
|
36
|
-
overflow: hidden;
|
|
37
|
-
position: relative;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* ==========================================================================
|
|
41
|
-
Accesibilidad de Foco (WCAG 2.1 AA)
|
|
42
|
-
========================================================================== */
|
|
43
|
-
:focus-visible {
|
|
44
|
-
outline: 2px solid var(--primary);
|
|
45
|
-
outline-offset: 2px;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
button:focus-visible,
|
|
49
|
-
a:focus-visible,
|
|
50
|
-
summary:focus-visible {
|
|
51
|
-
outline: 2px solid var(--primary);
|
|
52
|
-
outline-offset: 2px;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
input:focus,
|
|
56
|
-
input:focus-visible,
|
|
57
|
-
textarea:focus,
|
|
58
|
-
textarea:focus-visible,
|
|
59
|
-
select:focus,
|
|
60
|
-
select:focus-visible {
|
|
61
|
-
outline: none;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.chat-textarea,
|
|
65
|
-
.chat-textarea:focus,
|
|
66
|
-
.chat-textarea:focus-visible {
|
|
67
|
-
outline: none !important;
|
|
68
|
-
box-shadow: none !important;
|
|
69
|
-
border: none !important;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/* ==========================================================================
|
|
73
|
-
Barras de Desplazamiento (Scrollbars) Sutiles
|
|
74
|
-
========================================================================== */
|
|
75
|
-
::-webkit-scrollbar {
|
|
76
|
-
width: 6px;
|
|
77
|
-
height: 6px;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
::-webkit-scrollbar-track {
|
|
81
|
-
background: transparent;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
::-webkit-scrollbar-thumb {
|
|
85
|
-
background: var(--scrollbar-thumb);
|
|
86
|
-
border-radius: var(--radius-full);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
::-webkit-scrollbar-thumb:hover {
|
|
90
|
-
background: var(--scrollbar-thumb-hover);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/* ==========================================================================
|
|
94
|
-
Animaciones del Sistema
|
|
95
|
-
========================================================================== */
|
|
96
|
-
@keyframes spin {
|
|
97
|
-
from { transform: rotate(0deg); }
|
|
98
|
-
to { transform: rotate(360deg); }
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/* slideUpFadeIn: solo se aplica a mensajes nuevos via .is-new-message (nunca al historial) */
|
|
102
|
-
@keyframes slideUpFadeIn {
|
|
103
|
-
from { opacity: 0; translate: 0 6px; }
|
|
104
|
-
to { opacity: 1; translate: 0 0; }
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/* typingBounce: para el indicador de escritura del asistente */
|
|
108
|
-
@keyframes typingBounce {
|
|
109
|
-
0%, 80%, 100% { transform: scale(1); opacity: 0.4; }
|
|
110
|
-
40% { transform: scale(1.3); opacity: 1; }
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/* pulseStop: mantener para btn-stop-stream */
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
/* La interfaz responde inmediatamente: no se aplican animaciones ni transiciones. */
|
|
117
|
-
*,
|
|
118
|
-
*::before,
|
|
119
|
-
*::after {
|
|
120
|
-
animation: none !important;
|
|
121
|
-
transition: none !important;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/* ==========================================================================
|
|
125
|
-
Utilidades de Accesibilidad (WCAG 2.1 AA)
|
|
126
|
-
========================================================================== */
|
|
127
|
-
.sr-only {
|
|
128
|
-
position: absolute;
|
|
129
|
-
width: 1px;
|
|
130
|
-
height: 1px;
|
|
131
|
-
padding: 0;
|
|
132
|
-
margin: -1px;
|
|
133
|
-
overflow: hidden;
|
|
134
|
-
clip: rect(0, 0, 0, 0);
|
|
135
|
-
white-space: nowrap;
|
|
136
|
-
border-width: 0;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/* ==========================================================================
|
|
140
|
-
Fundación UI y Consolidación de Clases Base
|
|
141
|
-
========================================================================== */
|
|
142
|
-
.btn-primary,
|
|
143
|
-
.btn-secondary,
|
|
144
|
-
.btn-close,
|
|
145
|
-
.btn-attach,
|
|
146
|
-
.btn-send,
|
|
147
|
-
.btn-stop-stream,
|
|
148
|
-
.btn-reasoning,
|
|
149
|
-
.btn-query-server,
|
|
150
|
-
.btn-profile-action,
|
|
151
|
-
.btn-mcp-action,
|
|
152
|
-
.btn-debug-action,
|
|
153
|
-
.btn-danger-outline,
|
|
154
|
-
.modal-btn-action,
|
|
155
|
-
.modal-btn-close,
|
|
156
|
-
.export-card-btn {
|
|
157
|
-
font-family: inherit;
|
|
158
|
-
cursor: pointer;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.btn-primary,
|
|
162
|
-
.btn-secondary,
|
|
163
|
-
.btn-close,
|
|
164
|
-
.btn-query-server,
|
|
165
|
-
.btn-profile-action,
|
|
166
|
-
.btn-mcp-action,
|
|
167
|
-
.btn-danger-outline {
|
|
168
|
-
display: inline-flex;
|
|
169
|
-
align-items: center;
|
|
170
|
-
justify-content: center;
|
|
171
|
-
border-radius: var(--radius-md);
|
|
172
|
-
font-weight: 500;
|
|
173
|
-
transition: all 0.15s ease;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.chat-chart-card,
|
|
177
|
-
.inspector-intro-card,
|
|
178
|
-
.setting-toggle-card,
|
|
179
|
-
.connection-active-card,
|
|
180
|
-
.rag-branch-details-card,
|
|
181
|
-
.rag-active-tip-card,
|
|
182
|
-
.mcp-status-card,
|
|
183
|
-
.mcp-config-card,
|
|
184
|
-
.mcp-instructions-card,
|
|
185
|
-
.mcp-tool-card {
|
|
186
|
-
background-color: var(--bg-surface);
|
|
187
|
-
border: 1px solid var(--border-color);
|
|
188
|
-
border-radius: var(--radius-md);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.chat-chart-card,
|
|
192
|
-
.inspector-intro-card,
|
|
193
|
-
.mcp-status-card,
|
|
194
|
-
.mcp-config-card,
|
|
195
|
-
.mcp-instructions-card {
|
|
196
|
-
border-radius: var(--radius-lg);
|
|
197
|
-
padding: 1rem;
|
|
198
|
-
box-shadow: var(--shadow-sm);
|
|
199
|
-
}
|