zerochat 9.0.0__tar.gz → 9.2.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.
Potentially problematic release.
This version of zerochat might be problematic. Click here for more details.
- zerochat-9.2.0/PKG-INFO +125 -0
- zerochat-9.2.0/README.md +103 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/pyproject.toml +1 -1
- zerochat-9.2.0/zerochat.egg-info/PKG-INFO +125 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/zerochat.py +120 -112
- zerochat-9.0.0/PKG-INFO +0 -118
- zerochat-9.0.0/README.md +0 -96
- zerochat-9.0.0/zerochat.egg-info/PKG-INFO +0 -118
- {zerochat-9.0.0 → zerochat-9.2.0}/LICENSE +0 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/setup.cfg +0 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/zerochat.egg-info/SOURCES.txt +0 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/zerochat.egg-info/dependency_links.txt +0 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/zerochat.egg-info/entry_points.txt +0 -0
- {zerochat-9.0.0 → zerochat-9.2.0}/zerochat.egg-info/top_level.txt +0 -0
zerochat-9.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zerochat
|
|
3
|
+
Version: 9.2.0
|
|
4
|
+
Summary: Private local web client for AI models, tools and MCP services
|
|
5
|
+
Author: Alberto Alday
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://albalday.github.io/zerochat/
|
|
8
|
+
Project-URL: Repository, https://github.com/albalday/zerochat
|
|
9
|
+
Project-URL: Issues, https://github.com/albalday/zerochat/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# ZeroChat
|
|
24
|
+
|
|
25
|
+
[English](#english) · [Español](#español)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
<a name="english"></a>
|
|
30
|
+
## English
|
|
31
|
+
|
|
32
|
+
ZeroChat is a personal, private web client for chatting with AI models, consulting documents and running tools. This documentation covers the **9.x** series. Free and open source under the MIT licence.
|
|
33
|
+
|
|
34
|
+
The interface runs entirely in the browser as static files: history and settings remain in local browser storage without automatic cloud synchronization.
|
|
35
|
+
|
|
36
|
+
### Key features
|
|
37
|
+
|
|
38
|
+
- **AI Profiles:** OpenAI and compatible chat APIs, Ollama, OpenRouter, Claude and Gemini. Supports reasoning, vision and function calling.
|
|
39
|
+
- **WebLLM:** In-browser WebGPU inference with downloadable models (requires compatible hardware).
|
|
40
|
+
- **Documents & RAG:** Local document attachments and collections with client-side text extraction and Orama lexical search (no external embeddings required).
|
|
41
|
+
- **Agentic Tools:** JavaScript sandbox, web search, page fetching, interactive charts and read-only subagents. The optional local backend adds filesystem access, shell commands, diagnostics and MCP services.
|
|
42
|
+
- **Diagnostics:** Conversation branches, JSON and Markdown export, PDF print, context metrics and request inspector.
|
|
43
|
+
|
|
44
|
+
### Quick start
|
|
45
|
+
|
|
46
|
+
1. **Web (client-only):** Open [ZeroChat on GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), configure a connection profile, and start chatting.
|
|
47
|
+
2. **With local computer tools (Python backend):**
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Via PyPI (Linux, macOS, Windows)
|
|
51
|
+
pip install zerochat
|
|
52
|
+
zerochat
|
|
53
|
+
|
|
54
|
+
# Or download and run directly
|
|
55
|
+
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
56
|
+
python3 zerochat.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Documentation & Help
|
|
60
|
+
|
|
61
|
+
Comprehensive guides covering configuration, supported environments (Linux, Windows, macOS, Android/Termux), MCP services, and security:
|
|
62
|
+
- [ZeroChat 9.x Help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
63
|
+
- [Ayuda de ZeroChat 9.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
64
|
+
|
|
65
|
+
### Development
|
|
66
|
+
|
|
67
|
+
ZeroChat is developed on the `dev` branch:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git checkout dev
|
|
71
|
+
npm install
|
|
72
|
+
npm test
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For development rules, architecture and test suites, see [`AGENTS.md`](./AGENTS.md), [`js/README.md`](./js/README.md), [`py/README.md`](./py/README.md) and [`tests/README.md`](./tests/README.md).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
<a name="español"></a>
|
|
80
|
+
## Español
|
|
81
|
+
|
|
82
|
+
ZeroChat es un cliente web de uso personal para conversar con modelos de IA, consultar documentos y ejecutar herramientas. Esta documentación corresponde a la serie **9.x**. Proyecto de libre uso bajo licencia MIT.
|
|
83
|
+
|
|
84
|
+
La interfaz se ejecuta íntegramente en el navegador como archivos estáticos: el historial y la configuración se conservan en el almacenamiento local del navegador, sin sincronización automática en la nube.
|
|
85
|
+
|
|
86
|
+
### Características principales
|
|
87
|
+
|
|
88
|
+
- **Perfiles de IA:** OpenAI y APIs compatibles, Ollama, OpenRouter, Claude y Gemini. Soporta razonamiento, visión y llamadas a herramientas (*tool calling*).
|
|
89
|
+
- **WebLLM:** Inferencia local en el navegador mediante WebGPU tras descargar el modelo (requiere hardware compatible).
|
|
90
|
+
- **Documentos y RAG:** Adjuntos y colecciones locales con extracción de texto en el cliente y búsqueda léxica mediante Orama (sin requerir *embeddings* externos).
|
|
91
|
+
- **Herramientas agénticas:** Entorno aislado de JavaScript, búsqueda y lectura web, gráficos interactivos y subagentes de solo lectura. El backend local opcional añade acceso al sistema de archivos, ejecución de comandos, diagnósticos y servicios MCP.
|
|
92
|
+
- **Diagnóstico e historial:** Ramas de conversación, exportación a JSON y Markdown, impresión en PDF, métricas de contexto e inspección de peticiones.
|
|
93
|
+
|
|
94
|
+
### Inicio rápido
|
|
95
|
+
|
|
96
|
+
1. **Web directa (solo cliente):** Abre [ZeroChat en GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), configura un perfil de conexión y comienza.
|
|
97
|
+
2. **Con herramientas del equipo (backend Python):**
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Mediante PyPI (Linux, macOS, Windows)
|
|
101
|
+
pip install zerochat
|
|
102
|
+
zerochat
|
|
103
|
+
|
|
104
|
+
# O descarga directa del script
|
|
105
|
+
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
106
|
+
python3 zerochat.py
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Documentación y ayuda
|
|
110
|
+
|
|
111
|
+
Guías completas de configuración, soporte de entornos (Linux, Windows, macOS, Android/Termux), servicios MCP y seguridad:
|
|
112
|
+
- [Ayuda de ZeroChat 9.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
113
|
+
- [ZeroChat 9.x Help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
114
|
+
|
|
115
|
+
### Desarrollo
|
|
116
|
+
|
|
117
|
+
El desarrollo se realiza en la rama `dev`:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
git checkout dev
|
|
121
|
+
npm install
|
|
122
|
+
npm test
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Las normas de desarrollo, arquitectura y suite de pruebas se describen en [`AGENTS.md`](./AGENTS.md), [`js/README.md`](./js/README.md), [`py/README.md`](./py/README.md) y [`tests/README.md`](./tests/README.md).
|
zerochat-9.2.0/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# ZeroChat
|
|
2
|
+
|
|
3
|
+
[English](#english) · [Español](#español)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<a name="english"></a>
|
|
8
|
+
## English
|
|
9
|
+
|
|
10
|
+
ZeroChat is a personal, private web client for chatting with AI models, consulting documents and running tools. This documentation covers the **9.x** series. Free and open source under the MIT licence.
|
|
11
|
+
|
|
12
|
+
The interface runs entirely in the browser as static files: history and settings remain in local browser storage without automatic cloud synchronization.
|
|
13
|
+
|
|
14
|
+
### Key features
|
|
15
|
+
|
|
16
|
+
- **AI Profiles:** OpenAI and compatible chat APIs, Ollama, OpenRouter, Claude and Gemini. Supports reasoning, vision and function calling.
|
|
17
|
+
- **WebLLM:** In-browser WebGPU inference with downloadable models (requires compatible hardware).
|
|
18
|
+
- **Documents & RAG:** Local document attachments and collections with client-side text extraction and Orama lexical search (no external embeddings required).
|
|
19
|
+
- **Agentic Tools:** JavaScript sandbox, web search, page fetching, interactive charts and read-only subagents. The optional local backend adds filesystem access, shell commands, diagnostics and MCP services.
|
|
20
|
+
- **Diagnostics:** Conversation branches, JSON and Markdown export, PDF print, context metrics and request inspector.
|
|
21
|
+
|
|
22
|
+
### Quick start
|
|
23
|
+
|
|
24
|
+
1. **Web (client-only):** Open [ZeroChat on GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), configure a connection profile, and start chatting.
|
|
25
|
+
2. **With local computer tools (Python backend):**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Via PyPI (Linux, macOS, Windows)
|
|
29
|
+
pip install zerochat
|
|
30
|
+
zerochat
|
|
31
|
+
|
|
32
|
+
# Or download and run directly
|
|
33
|
+
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
34
|
+
python3 zerochat.py
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Documentation & Help
|
|
38
|
+
|
|
39
|
+
Comprehensive guides covering configuration, supported environments (Linux, Windows, macOS, Android/Termux), MCP services, and security:
|
|
40
|
+
- [ZeroChat 9.x Help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
41
|
+
- [Ayuda de ZeroChat 9.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
42
|
+
|
|
43
|
+
### Development
|
|
44
|
+
|
|
45
|
+
ZeroChat is developed on the `dev` branch:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git checkout dev
|
|
49
|
+
npm install
|
|
50
|
+
npm test
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For development rules, architecture and test suites, see [`AGENTS.md`](./AGENTS.md), [`js/README.md`](./js/README.md), [`py/README.md`](./py/README.md) and [`tests/README.md`](./tests/README.md).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
<a name="español"></a>
|
|
58
|
+
## Español
|
|
59
|
+
|
|
60
|
+
ZeroChat es un cliente web de uso personal para conversar con modelos de IA, consultar documentos y ejecutar herramientas. Esta documentación corresponde a la serie **9.x**. Proyecto de libre uso bajo licencia MIT.
|
|
61
|
+
|
|
62
|
+
La interfaz se ejecuta íntegramente en el navegador como archivos estáticos: el historial y la configuración se conservan en el almacenamiento local del navegador, sin sincronización automática en la nube.
|
|
63
|
+
|
|
64
|
+
### Características principales
|
|
65
|
+
|
|
66
|
+
- **Perfiles de IA:** OpenAI y APIs compatibles, Ollama, OpenRouter, Claude y Gemini. Soporta razonamiento, visión y llamadas a herramientas (*tool calling*).
|
|
67
|
+
- **WebLLM:** Inferencia local en el navegador mediante WebGPU tras descargar el modelo (requiere hardware compatible).
|
|
68
|
+
- **Documentos y RAG:** Adjuntos y colecciones locales con extracción de texto en el cliente y búsqueda léxica mediante Orama (sin requerir *embeddings* externos).
|
|
69
|
+
- **Herramientas agénticas:** Entorno aislado de JavaScript, búsqueda y lectura web, gráficos interactivos y subagentes de solo lectura. El backend local opcional añade acceso al sistema de archivos, ejecución de comandos, diagnósticos y servicios MCP.
|
|
70
|
+
- **Diagnóstico e historial:** Ramas de conversación, exportación a JSON y Markdown, impresión en PDF, métricas de contexto e inspección de peticiones.
|
|
71
|
+
|
|
72
|
+
### Inicio rápido
|
|
73
|
+
|
|
74
|
+
1. **Web directa (solo cliente):** Abre [ZeroChat en GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), configura un perfil de conexión y comienza.
|
|
75
|
+
2. **Con herramientas del equipo (backend Python):**
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Mediante PyPI (Linux, macOS, Windows)
|
|
79
|
+
pip install zerochat
|
|
80
|
+
zerochat
|
|
81
|
+
|
|
82
|
+
# O descarga directa del script
|
|
83
|
+
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
84
|
+
python3 zerochat.py
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Documentación y ayuda
|
|
88
|
+
|
|
89
|
+
Guías completas de configuración, soporte de entornos (Linux, Windows, macOS, Android/Termux), servicios MCP y seguridad:
|
|
90
|
+
- [Ayuda de ZeroChat 9.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
91
|
+
- [ZeroChat 9.x Help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
92
|
+
|
|
93
|
+
### Desarrollo
|
|
94
|
+
|
|
95
|
+
El desarrollo se realiza en la rama `dev`:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
git checkout dev
|
|
99
|
+
npm install
|
|
100
|
+
npm test
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Las normas de desarrollo, arquitectura y suite de pruebas se describen en [`AGENTS.md`](./AGENTS.md), [`js/README.md`](./js/README.md), [`py/README.md`](./py/README.md) y [`tests/README.md`](./tests/README.md).
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zerochat
|
|
3
|
+
Version: 9.2.0
|
|
4
|
+
Summary: Private local web client for AI models, tools and MCP services
|
|
5
|
+
Author: Alberto Alday
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://albalday.github.io/zerochat/
|
|
8
|
+
Project-URL: Repository, https://github.com/albalday/zerochat
|
|
9
|
+
Project-URL: Issues, https://github.com/albalday/zerochat/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# ZeroChat
|
|
24
|
+
|
|
25
|
+
[English](#english) · [Español](#español)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
<a name="english"></a>
|
|
30
|
+
## English
|
|
31
|
+
|
|
32
|
+
ZeroChat is a personal, private web client for chatting with AI models, consulting documents and running tools. This documentation covers the **9.x** series. Free and open source under the MIT licence.
|
|
33
|
+
|
|
34
|
+
The interface runs entirely in the browser as static files: history and settings remain in local browser storage without automatic cloud synchronization.
|
|
35
|
+
|
|
36
|
+
### Key features
|
|
37
|
+
|
|
38
|
+
- **AI Profiles:** OpenAI and compatible chat APIs, Ollama, OpenRouter, Claude and Gemini. Supports reasoning, vision and function calling.
|
|
39
|
+
- **WebLLM:** In-browser WebGPU inference with downloadable models (requires compatible hardware).
|
|
40
|
+
- **Documents & RAG:** Local document attachments and collections with client-side text extraction and Orama lexical search (no external embeddings required).
|
|
41
|
+
- **Agentic Tools:** JavaScript sandbox, web search, page fetching, interactive charts and read-only subagents. The optional local backend adds filesystem access, shell commands, diagnostics and MCP services.
|
|
42
|
+
- **Diagnostics:** Conversation branches, JSON and Markdown export, PDF print, context metrics and request inspector.
|
|
43
|
+
|
|
44
|
+
### Quick start
|
|
45
|
+
|
|
46
|
+
1. **Web (client-only):** Open [ZeroChat on GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), configure a connection profile, and start chatting.
|
|
47
|
+
2. **With local computer tools (Python backend):**
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Via PyPI (Linux, macOS, Windows)
|
|
51
|
+
pip install zerochat
|
|
52
|
+
zerochat
|
|
53
|
+
|
|
54
|
+
# Or download and run directly
|
|
55
|
+
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
56
|
+
python3 zerochat.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Documentation & Help
|
|
60
|
+
|
|
61
|
+
Comprehensive guides covering configuration, supported environments (Linux, Windows, macOS, Android/Termux), MCP services, and security:
|
|
62
|
+
- [ZeroChat 9.x Help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
63
|
+
- [Ayuda de ZeroChat 9.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
64
|
+
|
|
65
|
+
### Development
|
|
66
|
+
|
|
67
|
+
ZeroChat is developed on the `dev` branch:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git checkout dev
|
|
71
|
+
npm install
|
|
72
|
+
npm test
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For development rules, architecture and test suites, see [`AGENTS.md`](./AGENTS.md), [`js/README.md`](./js/README.md), [`py/README.md`](./py/README.md) and [`tests/README.md`](./tests/README.md).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
<a name="español"></a>
|
|
80
|
+
## Español
|
|
81
|
+
|
|
82
|
+
ZeroChat es un cliente web de uso personal para conversar con modelos de IA, consultar documentos y ejecutar herramientas. Esta documentación corresponde a la serie **9.x**. Proyecto de libre uso bajo licencia MIT.
|
|
83
|
+
|
|
84
|
+
La interfaz se ejecuta íntegramente en el navegador como archivos estáticos: el historial y la configuración se conservan en el almacenamiento local del navegador, sin sincronización automática en la nube.
|
|
85
|
+
|
|
86
|
+
### Características principales
|
|
87
|
+
|
|
88
|
+
- **Perfiles de IA:** OpenAI y APIs compatibles, Ollama, OpenRouter, Claude y Gemini. Soporta razonamiento, visión y llamadas a herramientas (*tool calling*).
|
|
89
|
+
- **WebLLM:** Inferencia local en el navegador mediante WebGPU tras descargar el modelo (requiere hardware compatible).
|
|
90
|
+
- **Documentos y RAG:** Adjuntos y colecciones locales con extracción de texto en el cliente y búsqueda léxica mediante Orama (sin requerir *embeddings* externos).
|
|
91
|
+
- **Herramientas agénticas:** Entorno aislado de JavaScript, búsqueda y lectura web, gráficos interactivos y subagentes de solo lectura. El backend local opcional añade acceso al sistema de archivos, ejecución de comandos, diagnósticos y servicios MCP.
|
|
92
|
+
- **Diagnóstico e historial:** Ramas de conversación, exportación a JSON y Markdown, impresión en PDF, métricas de contexto e inspección de peticiones.
|
|
93
|
+
|
|
94
|
+
### Inicio rápido
|
|
95
|
+
|
|
96
|
+
1. **Web directa (solo cliente):** Abre [ZeroChat en GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), configura un perfil de conexión y comienza.
|
|
97
|
+
2. **Con herramientas del equipo (backend Python):**
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Mediante PyPI (Linux, macOS, Windows)
|
|
101
|
+
pip install zerochat
|
|
102
|
+
zerochat
|
|
103
|
+
|
|
104
|
+
# O descarga directa del script
|
|
105
|
+
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
106
|
+
python3 zerochat.py
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Documentación y ayuda
|
|
110
|
+
|
|
111
|
+
Guías completas de configuración, soporte de entornos (Linux, Windows, macOS, Android/Termux), servicios MCP y seguridad:
|
|
112
|
+
- [Ayuda de ZeroChat 9.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
113
|
+
- [ZeroChat 9.x Help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
114
|
+
|
|
115
|
+
### Desarrollo
|
|
116
|
+
|
|
117
|
+
El desarrollo se realiza en la rama `dev`:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
git checkout dev
|
|
121
|
+
npm install
|
|
122
|
+
npm test
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Las normas de desarrollo, arquitectura y suite de pruebas se describen en [`AGENTS.md`](./AGENTS.md), [`js/README.md`](./js/README.md), [`py/README.md`](./py/README.md) y [`tests/README.md`](./tests/README.md).
|
|
@@ -35,6 +35,7 @@ import tempfile
|
|
|
35
35
|
import threading
|
|
36
36
|
import time
|
|
37
37
|
import traceback
|
|
38
|
+
import urllib.error
|
|
38
39
|
import urllib.request
|
|
39
40
|
from urllib.parse import urlencode
|
|
40
41
|
import venv
|
|
@@ -42,7 +43,7 @@ import webbrowser
|
|
|
42
43
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
43
44
|
from pathlib import Path
|
|
44
45
|
|
|
45
|
-
SOURCE_BACKEND_VERSION = "9.
|
|
46
|
+
SOURCE_BACKEND_VERSION = "9.2.0"
|
|
46
47
|
|
|
47
48
|
def _read_source_version(filename: str) -> str | None:
|
|
48
49
|
"""Lee la versión de un archivo del repositorio cuando se ejecuta desde fuentes."""
|
|
@@ -53,7 +54,7 @@ def _read_source_version(filename: str) -> str | None:
|
|
|
53
54
|
match = re.search(r'version\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)"', content)
|
|
54
55
|
if match:
|
|
55
56
|
return match.group(1)
|
|
56
|
-
except
|
|
57
|
+
except (OSError, re.error):
|
|
57
58
|
pass
|
|
58
59
|
return None
|
|
59
60
|
|
|
@@ -77,7 +78,7 @@ def _read_ui_version() -> str:
|
|
|
77
78
|
data = json.loads(pkg_path.read_text(encoding="utf-8"))
|
|
78
79
|
if isinstance(data.get("version"), str):
|
|
79
80
|
return data["version"].strip()
|
|
80
|
-
except
|
|
81
|
+
except (OSError, json.JSONDecodeError):
|
|
81
82
|
pass
|
|
82
83
|
return BACKEND_PACKAGE_VERSION
|
|
83
84
|
|
|
@@ -294,13 +295,13 @@ def get_daily_token() -> str:
|
|
|
294
295
|
data = json.loads(token_file.read_text(encoding="utf-8"))
|
|
295
296
|
if data.get("date") == today and data.get("token") and isinstance(data["token"], str):
|
|
296
297
|
return data["token"]
|
|
297
|
-
except
|
|
298
|
+
except (OSError, json.JSONDecodeError):
|
|
298
299
|
pass
|
|
299
300
|
token = secrets.token_urlsafe(32)
|
|
300
301
|
try:
|
|
301
302
|
_write_private_text(token_file, json.dumps({"token": token, "date": today}, indent=2))
|
|
302
|
-
except
|
|
303
|
-
|
|
303
|
+
except OSError as err:
|
|
304
|
+
log_event(f"[zerochat] Advertencia: no se pudo guardar el token diario en {token_file}: {err}")
|
|
304
305
|
return token
|
|
305
306
|
|
|
306
307
|
|
|
@@ -402,8 +403,8 @@ def check_version():
|
|
|
402
403
|
else:
|
|
403
404
|
notice += f" Actualiza con: curl -sSL {REMOTE_SCRIPT_URL} -o zerochat.py"
|
|
404
405
|
add_notice(notice)
|
|
405
|
-
except
|
|
406
|
-
# Modo offline o
|
|
406
|
+
except (urllib.error.URLError, TimeoutError, OSError):
|
|
407
|
+
# Modo offline o sin conectividad al comprobar versiones remotas.
|
|
407
408
|
pass
|
|
408
409
|
# ==============================================================================
|
|
409
410
|
# Ejecución de comandos y tareas en segundo plano
|
|
@@ -465,15 +466,18 @@ def _kill_process_tree(proc: subprocess.Popen):
|
|
|
465
466
|
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0)
|
|
466
467
|
)
|
|
467
468
|
if proc.poll() is None:
|
|
468
|
-
|
|
469
|
+
try:
|
|
470
|
+
proc.kill()
|
|
471
|
+
except (ProcessLookupError, OSError, AttributeError):
|
|
472
|
+
pass
|
|
469
473
|
elif hasattr(os, "killpg") and hasattr(os, "getpgid"):
|
|
470
474
|
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
|
|
471
475
|
else:
|
|
472
476
|
proc.kill()
|
|
473
|
-
except
|
|
477
|
+
except (ProcessLookupError, PermissionError, OSError, AttributeError):
|
|
474
478
|
try:
|
|
475
479
|
proc.kill()
|
|
476
|
-
except
|
|
480
|
+
except (ProcessLookupError, OSError, AttributeError):
|
|
477
481
|
pass
|
|
478
482
|
|
|
479
483
|
|
|
@@ -1110,6 +1114,9 @@ def materialize_managed_services(services_root: Path | None = None) -> None:
|
|
|
1110
1114
|
# Herramientas Locales Core
|
|
1111
1115
|
# ==============================================================================
|
|
1112
1116
|
|
|
1117
|
+
MAX_HTTP_BODY_BYTES = 1024 * 1024
|
|
1118
|
+
MAX_PATH_LENGTH = 4096
|
|
1119
|
+
MAX_COMMAND_LENGTH = 16384
|
|
1113
1120
|
BROWSER_ACTIONS = ("navigate", "screenshot", "click", "fill")
|
|
1114
1121
|
|
|
1115
1122
|
|
|
@@ -1126,6 +1133,12 @@ def _atomic_write_text(target: Path, text: str):
|
|
|
1126
1133
|
temp_path.replace(target)
|
|
1127
1134
|
|
|
1128
1135
|
|
|
1136
|
+
IGNORED_WORKSPACE_DIRS = {
|
|
1137
|
+
".git", ".venv", "venv", "node_modules", "__pycache__",
|
|
1138
|
+
".pytest_cache", ".cache", ".gemini", "dist", "build"
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
|
|
1129
1142
|
def list_directory(path: str = ".", recursive: bool = False) -> str:
|
|
1130
1143
|
"""List files and directories in a local directory with safe bounded recursive traversal."""
|
|
1131
1144
|
try:
|
|
@@ -1151,21 +1164,28 @@ def list_directory(path: str = ".", recursive: bool = False) -> str:
|
|
|
1151
1164
|
try:
|
|
1152
1165
|
stat = entry.stat(follow_symlinks=False)
|
|
1153
1166
|
is_dir = entry.is_dir(follow_symlinks=False)
|
|
1167
|
+
try:
|
|
1168
|
+
resolved_path = str(Path(entry.path).resolve())
|
|
1169
|
+
except (OSError, RuntimeError):
|
|
1170
|
+
resolved_path = str(Path(entry.path).absolute())
|
|
1154
1171
|
entry_data = {
|
|
1155
1172
|
"name": entry.name,
|
|
1156
|
-
"path":
|
|
1173
|
+
"path": resolved_path,
|
|
1157
1174
|
"type": "directory" if is_dir else "file",
|
|
1158
1175
|
"size_bytes": None if is_dir else stat.st_size,
|
|
1159
1176
|
"is_symlink": entry.is_symlink()
|
|
1160
1177
|
}
|
|
1161
1178
|
if recursive:
|
|
1162
|
-
|
|
1179
|
+
try:
|
|
1180
|
+
entry_data["relative_path"] = str(Path(entry.path).relative_to(target))
|
|
1181
|
+
except ValueError:
|
|
1182
|
+
entry_data["relative_path"] = entry.name
|
|
1163
1183
|
entries.append(entry_data)
|
|
1164
1184
|
if recursive and is_dir and not entry.is_symlink():
|
|
1165
1185
|
_scan(Path(entry.path), current_depth + 1)
|
|
1166
|
-
except (PermissionError, FileNotFoundError):
|
|
1186
|
+
except (PermissionError, FileNotFoundError, OSError):
|
|
1167
1187
|
continue
|
|
1168
|
-
except (PermissionError, FileNotFoundError):
|
|
1188
|
+
except (PermissionError, FileNotFoundError, OSError):
|
|
1169
1189
|
pass
|
|
1170
1190
|
|
|
1171
1191
|
_scan(target, 1)
|
|
@@ -1196,7 +1216,8 @@ def read_file(path: str, start_line: int = 1, end_line: int = None, max_lines: i
|
|
|
1196
1216
|
|
|
1197
1217
|
if end_line is not None:
|
|
1198
1218
|
safe_end_line = max(safe_start_line, int(end_line))
|
|
1199
|
-
target_line_count = safe_end_line - safe_start_line + 1
|
|
1219
|
+
target_line_count = min(safe_end_line - safe_start_line + 1, 2000)
|
|
1220
|
+
safe_end_line = safe_start_line + target_line_count - 1
|
|
1200
1221
|
else:
|
|
1201
1222
|
safe_end_line = None
|
|
1202
1223
|
target_line_count = max(1, min(int(max_lines), 2000))
|
|
@@ -1232,6 +1253,7 @@ def read_file(path: str, start_line: int = 1, end_line: int = None, max_lines: i
|
|
|
1232
1253
|
selected_lines.append(encoded.decode("utf-8", errors="ignore"))
|
|
1233
1254
|
truncated_bytes = True
|
|
1234
1255
|
reached_end_bound = True
|
|
1256
|
+
break
|
|
1235
1257
|
else:
|
|
1236
1258
|
selected_lines.append(line)
|
|
1237
1259
|
current_bytes += line_bytes
|
|
@@ -1272,8 +1294,8 @@ def write_file(path: str, content: str) -> str:
|
|
|
1272
1294
|
return _tool_error(str(e))
|
|
1273
1295
|
|
|
1274
1296
|
|
|
1275
|
-
def edit_file(path: str, old_str: str, new_str: str) -> str:
|
|
1276
|
-
"""Replace
|
|
1297
|
+
def edit_file(path: str, old_str: str, new_str: str, replace_all: bool = False) -> str:
|
|
1298
|
+
"""Replace old_str with new_str in an existing file: its single occurrence, or all of them with replace_all."""
|
|
1277
1299
|
try:
|
|
1278
1300
|
target = Path(path).expanduser().resolve()
|
|
1279
1301
|
if not target.exists():
|
|
@@ -1284,19 +1306,21 @@ def edit_file(path: str, old_str: str, new_str: str) -> str:
|
|
|
1284
1306
|
with open(target, "r", encoding="utf-8", errors="replace") as f:
|
|
1285
1307
|
file_text = f.read()
|
|
1286
1308
|
|
|
1309
|
+
if not old_str:
|
|
1310
|
+
return _tool_error("old_str is empty. Provide the exact text to replace.")
|
|
1287
1311
|
occurrences = file_text.count(old_str)
|
|
1288
1312
|
if occurrences == 0:
|
|
1289
1313
|
return _tool_error(f"Target text was not found in '{path}'. Check exact file content with read_file.")
|
|
1290
|
-
if occurrences > 1:
|
|
1291
|
-
return _tool_error(f"Found {occurrences} matches for the snippet in '{path}'. Provide more surrounding context in old_str to ensure a unique match.")
|
|
1314
|
+
if occurrences > 1 and not replace_all:
|
|
1315
|
+
return _tool_error(f"Found {occurrences} matches for the snippet in '{path}'. Provide more surrounding context in old_str to ensure a unique match, or set replace_all to replace every match.")
|
|
1292
1316
|
|
|
1293
|
-
updated_text = file_text.replace(old_str, new_str, 1)
|
|
1317
|
+
updated_text = file_text.replace(old_str, new_str) if replace_all else file_text.replace(old_str, new_str, 1)
|
|
1294
1318
|
_atomic_write_text(target, updated_text)
|
|
1295
1319
|
return json.dumps({
|
|
1296
1320
|
"success": True,
|
|
1297
1321
|
"path": str(target),
|
|
1298
1322
|
"bytes_written": len(updated_text.encode("utf-8")),
|
|
1299
|
-
"replacements": 1
|
|
1323
|
+
"replacements": occurrences if replace_all else 1
|
|
1300
1324
|
}, ensure_ascii=False, indent=2)
|
|
1301
1325
|
except Exception as e:
|
|
1302
1326
|
return _tool_error(str(e))
|
|
@@ -1331,14 +1355,18 @@ def search_files(query: str, path: str = ".", file_pattern: str = None, max_resu
|
|
|
1331
1355
|
except re.error:
|
|
1332
1356
|
regex = re.compile(re.escape(query), re.MULTILINE)
|
|
1333
1357
|
|
|
1334
|
-
|
|
1358
|
+
try:
|
|
1359
|
+
safe_max_results = max(1, min(int(max_results), 500))
|
|
1360
|
+
except (TypeError, ValueError):
|
|
1361
|
+
safe_max_results = 100
|
|
1362
|
+
|
|
1335
1363
|
matches = []
|
|
1336
1364
|
files_searched = 0
|
|
1337
1365
|
max_file_size = 2 * 1024 * 1024
|
|
1338
1366
|
truncated = False
|
|
1339
1367
|
|
|
1340
1368
|
for root, dirs, files in os.walk(target):
|
|
1341
|
-
dirs[:] = [d for d in dirs if d not in
|
|
1369
|
+
dirs[:] = [d for d in dirs if d not in IGNORED_WORKSPACE_DIRS and not d.startswith(".")]
|
|
1342
1370
|
|
|
1343
1371
|
for fname in sorted(files):
|
|
1344
1372
|
if file_pattern and not fnmatch.fnmatch(fname, file_pattern):
|
|
@@ -1346,6 +1374,12 @@ def search_files(query: str, path: str = ".", file_pattern: str = None, max_resu
|
|
|
1346
1374
|
|
|
1347
1375
|
fpath = Path(root) / fname
|
|
1348
1376
|
try:
|
|
1377
|
+
if fpath.is_symlink():
|
|
1378
|
+
try:
|
|
1379
|
+
if not fpath.resolve().is_relative_to(target):
|
|
1380
|
+
continue
|
|
1381
|
+
except (OSError, ValueError):
|
|
1382
|
+
continue
|
|
1349
1383
|
stat = fpath.stat()
|
|
1350
1384
|
if stat.st_size > max_file_size:
|
|
1351
1385
|
continue
|
|
@@ -1367,7 +1401,7 @@ def search_files(query: str, path: str = ".", file_pattern: str = None, max_resu
|
|
|
1367
1401
|
"line_number": line_idx,
|
|
1368
1402
|
"content": line.rstrip("\r\n")[:300]
|
|
1369
1403
|
})
|
|
1370
|
-
if len(matches) >=
|
|
1404
|
+
if len(matches) >= safe_max_results:
|
|
1371
1405
|
truncated = True
|
|
1372
1406
|
break
|
|
1373
1407
|
except (PermissionError, OSError):
|
|
@@ -1445,7 +1479,7 @@ def get_diagnostics(path: str | None = None) -> str:
|
|
|
1445
1479
|
"severity": "error",
|
|
1446
1480
|
"message": msg
|
|
1447
1481
|
})
|
|
1448
|
-
except
|
|
1482
|
+
except (subprocess.SubprocessError, OSError):
|
|
1449
1483
|
pass
|
|
1450
1484
|
elif ext == ".json":
|
|
1451
1485
|
try:
|
|
@@ -1465,12 +1499,20 @@ def get_diagnostics(path: str | None = None) -> str:
|
|
|
1465
1499
|
files_checked = 1
|
|
1466
1500
|
diagnostics.extend(check_single_file(target))
|
|
1467
1501
|
else:
|
|
1468
|
-
ignore_dirs = {".git", "node_modules", ".venv", "venv", "dist", "build", "__pycache__", ".gemini", ".cache"}
|
|
1469
1502
|
max_scan = 200
|
|
1470
1503
|
for root, dirs, files in os.walk(target):
|
|
1471
|
-
dirs[:] = [d for d in dirs if d not in
|
|
1504
|
+
dirs[:] = [d for d in dirs if d not in IGNORED_WORKSPACE_DIRS and not d.startswith(".")]
|
|
1472
1505
|
for fname in sorted(files):
|
|
1473
1506
|
fp = Path(root) / fname
|
|
1507
|
+
try:
|
|
1508
|
+
if fp.is_symlink():
|
|
1509
|
+
try:
|
|
1510
|
+
if not fp.resolve().is_relative_to(target):
|
|
1511
|
+
continue
|
|
1512
|
+
except (OSError, ValueError):
|
|
1513
|
+
continue
|
|
1514
|
+
except OSError:
|
|
1515
|
+
continue
|
|
1474
1516
|
if fp.suffix.lower() in (".py", ".js", ".mjs", ".cjs", ".json"):
|
|
1475
1517
|
files_checked += 1
|
|
1476
1518
|
diagnostics.extend(check_single_file(fp))
|
|
@@ -1676,9 +1718,9 @@ try {
|
|
|
1676
1718
|
self._process.stdin.write(json.dumps({"action": "close"}) + "\n")
|
|
1677
1719
|
self._process.stdin.flush()
|
|
1678
1720
|
self._process.wait(timeout=2)
|
|
1679
|
-
except
|
|
1721
|
+
except (OSError, subprocess.SubprocessError):
|
|
1680
1722
|
self._process.kill()
|
|
1681
|
-
except
|
|
1723
|
+
except (OSError, subprocess.SubprocessError):
|
|
1682
1724
|
pass
|
|
1683
1725
|
self._process = None
|
|
1684
1726
|
|
|
@@ -1746,7 +1788,7 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1746
1788
|
"inputSchema": {
|
|
1747
1789
|
"type": "object",
|
|
1748
1790
|
"properties": {
|
|
1749
|
-
"path": {"type": "string", "description": "Relative or absolute directory path (defaults to '.')"},
|
|
1791
|
+
"path": {"type": "string", "maxLength": MAX_PATH_LENGTH, "description": "Relative or absolute directory path (defaults to '.')"},
|
|
1750
1792
|
"recursive": {"type": "boolean", "description": "If true, traverses subdirectories up to depth 3", "default": False}
|
|
1751
1793
|
}
|
|
1752
1794
|
}
|
|
@@ -1757,7 +1799,7 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1757
1799
|
"inputSchema": {
|
|
1758
1800
|
"type": "object",
|
|
1759
1801
|
"properties": {
|
|
1760
|
-
"path": {"type": "string", "description": "File path"},
|
|
1802
|
+
"path": {"type": "string", "maxLength": MAX_PATH_LENGTH, "description": "File path"},
|
|
1761
1803
|
"start_line": {"type": "integer", "description": "First line (1-based)", "default": 1},
|
|
1762
1804
|
"end_line": {"type": "integer", "description": "Last line (inclusive)"},
|
|
1763
1805
|
"max_lines": {"type": "integer", "description": "Line cap if no end_line", "default": 500},
|
|
@@ -1772,21 +1814,26 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1772
1814
|
"inputSchema": {
|
|
1773
1815
|
"type": "object",
|
|
1774
1816
|
"properties": {
|
|
1775
|
-
"path": {"type": "string", "description": "Path to the file to write"},
|
|
1776
|
-
"content": {"type": "string", "description": "Full content of the file"}
|
|
1817
|
+
"path": {"type": "string", "maxLength": MAX_PATH_LENGTH, "description": "Path to the file to write"},
|
|
1818
|
+
"content": {"type": "string", "maxLength": MAX_HTTP_BODY_BYTES, "description": "Full content of the file"}
|
|
1777
1819
|
},
|
|
1778
1820
|
"required": ["path", "content"]
|
|
1779
1821
|
}
|
|
1780
1822
|
},
|
|
1781
1823
|
{
|
|
1782
1824
|
"name": "edit_file",
|
|
1783
|
-
"description":
|
|
1825
|
+
"description": (
|
|
1826
|
+
"Replace old_str with new_str in an existing file. "
|
|
1827
|
+
"For several changes, in this file or in others, emit several edit_file calls in the same response; "
|
|
1828
|
+
"they are applied in order, each one on the result of the previous one."
|
|
1829
|
+
),
|
|
1784
1830
|
"inputSchema": {
|
|
1785
1831
|
"type": "object",
|
|
1786
1832
|
"properties": {
|
|
1787
|
-
"path": {"type": "string", "description": "File path"},
|
|
1788
|
-
"old_str": {"type": "string", "description": "Exact text to replace; must occur once"},
|
|
1789
|
-
"new_str": {"type": "string", "description": "Replacement text"}
|
|
1833
|
+
"path": {"type": "string", "maxLength": MAX_PATH_LENGTH, "description": "File path"},
|
|
1834
|
+
"old_str": {"type": "string", "maxLength": MAX_HTTP_BODY_BYTES, "description": "Exact text to replace; must occur once unless replace_all is true"},
|
|
1835
|
+
"new_str": {"type": "string", "maxLength": MAX_HTTP_BODY_BYTES, "description": "Replacement text"},
|
|
1836
|
+
"replace_all": {"type": "boolean", "description": "Replace every occurrence of old_str (e.g. to rename an identifier)", "default": False}
|
|
1790
1837
|
},
|
|
1791
1838
|
"required": ["path", "old_str", "new_str"]
|
|
1792
1839
|
}
|
|
@@ -1797,9 +1844,10 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1797
1844
|
"inputSchema": {
|
|
1798
1845
|
"type": "object",
|
|
1799
1846
|
"properties": {
|
|
1800
|
-
"query": {"type": "string", "description": "Plain text string or regular expression to search for"},
|
|
1801
|
-
"path": {"type": "string", "description": "Base search directory (defaults to '.')", "default": "."},
|
|
1802
|
-
"file_pattern": {"type": "string", "description": "Optional glob filter (e.g. *.js, *.py)"}
|
|
1847
|
+
"query": {"type": "string", "maxLength": 4096, "description": "Plain text string or regular expression to search for"},
|
|
1848
|
+
"path": {"type": "string", "maxLength": MAX_PATH_LENGTH, "description": "Base search directory (defaults to '.')", "default": "."},
|
|
1849
|
+
"file_pattern": {"type": "string", "maxLength": 256, "description": "Optional glob filter (e.g. *.js, *.py)"},
|
|
1850
|
+
"max_results": {"type": "integer", "description": "Maximum number of matching lines to return (default 100, max 500)", "default": 100}
|
|
1803
1851
|
},
|
|
1804
1852
|
"required": ["query"]
|
|
1805
1853
|
}
|
|
@@ -1825,6 +1873,7 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1825
1873
|
"properties": {
|
|
1826
1874
|
"command": {
|
|
1827
1875
|
"type": "string",
|
|
1876
|
+
"maxLength": MAX_COMMAND_LENGTH,
|
|
1828
1877
|
"description": (
|
|
1829
1878
|
"PowerShell command to run (e.g. git status; npm test)"
|
|
1830
1879
|
if DETECTED_OS == "windows"
|
|
@@ -1856,7 +1905,7 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1856
1905
|
"inputSchema": {
|
|
1857
1906
|
"type": "object",
|
|
1858
1907
|
"properties": {
|
|
1859
|
-
"path": {"type": "string", "description": "Path to the file or directory to inspect (defaults to '.')"}
|
|
1908
|
+
"path": {"type": "string", "maxLength": MAX_PATH_LENGTH, "description": "Path to the file or directory to inspect (defaults to '.')"}
|
|
1860
1909
|
}
|
|
1861
1910
|
}
|
|
1862
1911
|
},
|
|
@@ -1869,11 +1918,12 @@ LOCAL_TOOLS_DEFINITIONS = [
|
|
|
1869
1918
|
"action": {
|
|
1870
1919
|
"type": "string",
|
|
1871
1920
|
"enum": list(BROWSER_ACTIONS),
|
|
1921
|
+
"maxLength": 32,
|
|
1872
1922
|
"description": "Action to perform in the browser"
|
|
1873
1923
|
},
|
|
1874
|
-
"url": {"type": "string", "description": "Target URL for navigate or screenshot"},
|
|
1875
|
-
"selector": {"type": "string", "description": "CSS selector for click or fill actions"},
|
|
1876
|
-
"value": {"type": "string", "description": "Text value to type for fill action"}
|
|
1924
|
+
"url": {"type": "string", "maxLength": 4096, "description": "Target URL for navigate or screenshot"},
|
|
1925
|
+
"selector": {"type": "string", "maxLength": 1024, "description": "CSS selector for click or fill actions"},
|
|
1926
|
+
"value": {"type": "string", "maxLength": MAX_HTTP_BODY_BYTES, "description": "Text value to type for fill action"}
|
|
1877
1927
|
},
|
|
1878
1928
|
"required": ["action"]
|
|
1879
1929
|
}
|
|
@@ -1895,11 +1945,8 @@ LOCAL_TOOL_HANDLERS = {
|
|
|
1895
1945
|
# Servidor HTTP JSON-RPC 2.0 y SSE con Autenticación por Token
|
|
1896
1946
|
# ==============================================================================
|
|
1897
1947
|
|
|
1898
|
-
MAX_HTTP_BODY_BYTES = 1024 * 1024
|
|
1899
1948
|
MAX_RPC_METHOD_LENGTH = 128
|
|
1900
1949
|
MAX_TOOL_NAME_LENGTH = 128
|
|
1901
|
-
MAX_PATH_LENGTH = 4096
|
|
1902
|
-
MAX_COMMAND_LENGTH = 16384
|
|
1903
1950
|
# Un mensaje MCP admite imágenes en base64, pero no puede agotar la memoria del backend.
|
|
1904
1951
|
MAX_MCP_MESSAGE_CHARS = 16 * 1024 * 1024
|
|
1905
1952
|
MAX_MCP_STDERR_LINE_CHARS = 64 * 1024
|
|
@@ -1907,73 +1954,32 @@ DEFAULT_MCP_CALL_TIMEOUT_SECONDS = 30
|
|
|
1907
1954
|
|
|
1908
1955
|
|
|
1909
1956
|
def validate_local_tool_arguments(tool_name: str, arguments: dict) -> str | None:
|
|
1910
|
-
"""Valida tipos y límites de las herramientas locales
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
"path": (str, MAX_PATH_LENGTH),
|
|
1914
|
-
"recursive": (bool, None)
|
|
1915
|
-
},
|
|
1916
|
-
"read_file": {
|
|
1917
|
-
"path": (str, MAX_PATH_LENGTH),
|
|
1918
|
-
"start_line": (int, None),
|
|
1919
|
-
"end_line": (int, None),
|
|
1920
|
-
"max_lines": (int, None),
|
|
1921
|
-
"max_bytes": (int, None)
|
|
1922
|
-
},
|
|
1923
|
-
"write_file": {
|
|
1924
|
-
"path": (str, MAX_PATH_LENGTH),
|
|
1925
|
-
"content": (str, MAX_HTTP_BODY_BYTES)
|
|
1926
|
-
},
|
|
1927
|
-
"edit_file": {
|
|
1928
|
-
"path": (str, MAX_PATH_LENGTH),
|
|
1929
|
-
"old_str": (str, MAX_HTTP_BODY_BYTES),
|
|
1930
|
-
"new_str": (str, MAX_HTTP_BODY_BYTES)
|
|
1931
|
-
},
|
|
1932
|
-
"run_command": {
|
|
1933
|
-
"command": (str, MAX_COMMAND_LENGTH),
|
|
1934
|
-
"timeout_seconds": (int, None),
|
|
1935
|
-
"background": (bool, None)
|
|
1936
|
-
},
|
|
1937
|
-
"check_command": {
|
|
1938
|
-
"job_id": (int, None),
|
|
1939
|
-
"wait_seconds": (int, None),
|
|
1940
|
-
"stop": (bool, None)
|
|
1941
|
-
},
|
|
1942
|
-
"search_files": {
|
|
1943
|
-
"query": (str, 4096),
|
|
1944
|
-
"path": (str, MAX_PATH_LENGTH),
|
|
1945
|
-
"file_pattern": (str, 256)
|
|
1946
|
-
},
|
|
1947
|
-
"get_diagnostics": {
|
|
1948
|
-
"path": (str, MAX_PATH_LENGTH)
|
|
1949
|
-
},
|
|
1950
|
-
"browser_action": {
|
|
1951
|
-
"action": (str, 32),
|
|
1952
|
-
"url": (str, 4096),
|
|
1953
|
-
"selector": (str, 1024),
|
|
1954
|
-
"value": (str, MAX_HTTP_BODY_BYTES)
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
schema = schemas.get(tool_name)
|
|
1958
|
-
if schema is None:
|
|
1957
|
+
"""Valida tipos y límites de las herramientas locales a partir de su definición canónica."""
|
|
1958
|
+
definition = next((item for item in LOCAL_TOOLS_DEFINITIONS if item["name"] == tool_name), None)
|
|
1959
|
+
if definition is None:
|
|
1959
1960
|
return None
|
|
1960
1961
|
|
|
1962
|
+
schema = definition.get("inputSchema", {})
|
|
1963
|
+
properties = schema.get("properties", {})
|
|
1964
|
+
type_map = {"string": str, "integer": int, "boolean": bool}
|
|
1965
|
+
|
|
1961
1966
|
for name, value in arguments.items():
|
|
1962
|
-
|
|
1963
|
-
if
|
|
1967
|
+
prop = properties.get(name)
|
|
1968
|
+
if prop is None:
|
|
1964
1969
|
return f"Argumento no permitido: {name}"
|
|
1965
|
-
|
|
1970
|
+
expected_type_name = prop.get("type")
|
|
1971
|
+
expected_type = type_map.get(expected_type_name)
|
|
1966
1972
|
if expected_type is bool:
|
|
1967
1973
|
if not isinstance(value, bool):
|
|
1968
1974
|
return f"Tipo inválido para '{name}'"
|
|
1969
1975
|
else:
|
|
1970
1976
|
if isinstance(value, bool) or not isinstance(value, expected_type):
|
|
1971
1977
|
return f"Tipo inválido para '{name}'"
|
|
1978
|
+
max_length = prop.get("maxLength")
|
|
1972
1979
|
if max_length is not None and len(value) > max_length:
|
|
1973
1980
|
return f"'{name}' excede el tamaño máximo permitido"
|
|
1974
1981
|
|
|
1975
|
-
|
|
1976
|
-
for name in definition.get("inputSchema", {}).get("required", ()):
|
|
1982
|
+
for name in schema.get("required", ()):
|
|
1977
1983
|
if name not in arguments:
|
|
1978
1984
|
return f"Falta el argumento obligatorio: {name}"
|
|
1979
1985
|
|
|
@@ -2173,7 +2179,7 @@ class StdioMcpClient:
|
|
|
2173
2179
|
continue
|
|
2174
2180
|
try:
|
|
2175
2181
|
msg = json.loads(line)
|
|
2176
|
-
except
|
|
2182
|
+
except json.JSONDecodeError:
|
|
2177
2183
|
continue
|
|
2178
2184
|
req_id = msg.get("id")
|
|
2179
2185
|
if req_id is not None:
|
|
@@ -2247,7 +2253,7 @@ class StdioMcpClient:
|
|
|
2247
2253
|
if self.running():
|
|
2248
2254
|
try:
|
|
2249
2255
|
self._write(json.dumps({"jsonrpc": "2.0", "method": method}) + "\n")
|
|
2250
|
-
except
|
|
2256
|
+
except (OSError, ValueError):
|
|
2251
2257
|
self._alive = False
|
|
2252
2258
|
|
|
2253
2259
|
def _signal_group(self, sig) -> bool:
|
|
@@ -2327,7 +2333,7 @@ class McpServiceManager:
|
|
|
2327
2333
|
server["id"] = server_id
|
|
2328
2334
|
server["_directory"] = directory
|
|
2329
2335
|
servers[server_id] = server
|
|
2330
|
-
except
|
|
2336
|
+
except (OSError, json.JSONDecodeError):
|
|
2331
2337
|
continue
|
|
2332
2338
|
return servers
|
|
2333
2339
|
|
|
@@ -2335,7 +2341,7 @@ class McpServiceManager:
|
|
|
2335
2341
|
if self.config_file.exists():
|
|
2336
2342
|
try:
|
|
2337
2343
|
return json.loads(self.config_file.read_text(encoding="utf-8"))
|
|
2338
|
-
except
|
|
2344
|
+
except (OSError, json.JSONDecodeError):
|
|
2339
2345
|
return {}
|
|
2340
2346
|
return {}
|
|
2341
2347
|
|
|
@@ -2344,8 +2350,8 @@ class McpServiceManager:
|
|
|
2344
2350
|
tmp = self.config_file.with_suffix(".tmp")
|
|
2345
2351
|
tmp.write_text(json.dumps(self.preferences, indent=2), encoding="utf-8")
|
|
2346
2352
|
tmp.replace(self.config_file)
|
|
2347
|
-
except
|
|
2348
|
-
|
|
2353
|
+
except OSError as err:
|
|
2354
|
+
log_event(f"[zerochat] Advertencia al guardar preferencias MCP en {self.config_file}: {err}")
|
|
2349
2355
|
|
|
2350
2356
|
def list_servers(self) -> list[dict]:
|
|
2351
2357
|
self.services = self._load_services()
|
|
@@ -2412,7 +2418,7 @@ class McpServiceManager:
|
|
|
2412
2418
|
installation = json.loads(marker.read_text(encoding="utf-8"))
|
|
2413
2419
|
if installation.get("package") != package or installation.get("version") != version:
|
|
2414
2420
|
needs_install = True
|
|
2415
|
-
except
|
|
2421
|
+
except (OSError, json.JSONDecodeError):
|
|
2416
2422
|
needs_install = True
|
|
2417
2423
|
|
|
2418
2424
|
if needs_install:
|
|
@@ -2596,7 +2602,7 @@ class McpServiceManager:
|
|
|
2596
2602
|
for t in client.tools:
|
|
2597
2603
|
try:
|
|
2598
2604
|
matches = public_tool_name(server_id, t.get("name")) == public_name
|
|
2599
|
-
except
|
|
2605
|
+
except (ValueError, TypeError):
|
|
2600
2606
|
continue
|
|
2601
2607
|
if matches:
|
|
2602
2608
|
target = (client, t["name"])
|
|
@@ -2957,7 +2963,7 @@ class ZeroChatServerHandler(BaseHTTPRequestHandler):
|
|
|
2957
2963
|
if content_len <= MAX_HTTP_BODY_BYTES * 2:
|
|
2958
2964
|
try:
|
|
2959
2965
|
self.rfile.read(content_len)
|
|
2960
|
-
except
|
|
2966
|
+
except (OSError, ValueError):
|
|
2961
2967
|
pass
|
|
2962
2968
|
self.close_connection = True
|
|
2963
2969
|
self._reject(413, {"error": "Request body too large"}, safe_path, t0, "Cuerpo HTTP excede el límite")
|
|
@@ -3090,7 +3096,7 @@ class ZeroChatServerHandler(BaseHTTPRequestHandler):
|
|
|
3090
3096
|
parsed_out = json.loads(tool_output_json)
|
|
3091
3097
|
if isinstance(parsed_out, dict) and parsed_out.get("success") is False:
|
|
3092
3098
|
tool_error_info = str(parsed_out.get("error", "Error en herramienta local"))
|
|
3093
|
-
except
|
|
3099
|
+
except (json.JSONDecodeError, TypeError):
|
|
3094
3100
|
pass
|
|
3095
3101
|
return {"content": [{"type": "text", "text": tool_output_json}], "isError": bool(tool_error_info)}, None, tool_error_info
|
|
3096
3102
|
if method == "zerochat/project/set_directory":
|
|
@@ -3410,6 +3416,8 @@ def main():
|
|
|
3410
3416
|
global TOOL_AUTH_KEY, TOOL_AUTH_SESSION_ID, TOOL_AUTH_NONCES
|
|
3411
3417
|
|
|
3412
3418
|
parser = argparse.ArgumentParser(description=f"ZeroChat Local Server v{VERSION}")
|
|
3419
|
+
# Desde Python 3.14 argparse colorea la ayuda con códigos ANSI; la consola la muestra en texto plano.
|
|
3420
|
+
parser.color = False
|
|
3413
3421
|
parser.add_argument("--port", type=int, default=int(os.environ.get("ZEROCHAT_PORT", DEFAULT_PORT)), help=f"Puerto de escucha (default: {DEFAULT_PORT})")
|
|
3414
3422
|
parser.add_argument("--host", default=os.environ.get("ZEROCHAT_HOST", DEFAULT_HOST), help=f"Host de escucha (default: {DEFAULT_HOST})")
|
|
3415
3423
|
parser.add_argument("--ui-url", default=None, help="URL de la interfaz web a abrir (por defecto: interfaz local en desarrollo o GitHub Pages)")
|
zerochat-9.0.0/PKG-INFO
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: zerochat
|
|
3
|
-
Version: 9.0.0
|
|
4
|
-
Summary: Private local web client for AI models, tools and MCP services
|
|
5
|
-
Author: Alberto Alday
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://albalday.github.io/zerochat/
|
|
8
|
-
Project-URL: Repository, https://github.com/albalday/zerochat
|
|
9
|
-
Project-URL: Issues, https://github.com/albalday/zerochat/issues
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Environment :: Web Environment
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Requires-Python: >=3.10
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
License-File: LICENSE
|
|
21
|
-
Dynamic: license-file
|
|
22
|
-
|
|
23
|
-
# ZeroChat
|
|
24
|
-
|
|
25
|
-
ZeroChat es un cliente web de uso personal para conversar con modelos de IA, consultar documentos y utilizar herramientas. Esta documentación corresponde a la serie **8.x**, que consolida las funcionalidades existentes. El desarrollo de nuevas funcionalidades queda en pausa por el momento.
|
|
26
|
-
|
|
27
|
-
La interfaz se sirve como archivos estáticos: `zerochat.html` necesita sus módulos `js/` y `css/`. El historial y la configuración se guardan en el navegador; no se sincronizan automáticamente entre dispositivos. Los proveedores remotos reciben el contenido incluido en las peticiones, y las herramientas web pueden utilizar servicios intermediarios. Almacenamiento local no significa privacidad absoluta.
|
|
28
|
-
|
|
29
|
-
*English:* ZeroChat is a web client for personal use: chatting with AI models, consulting documents and using tools. This documentation covers the **8.x** series, which consolidates existing features. New feature development is paused for now.
|
|
30
|
-
|
|
31
|
-
The interface is served as static files: `zerochat.html` needs its `js/` and `css/` modules. History and settings are stored in the browser, without automatic cross-device sync. Remote providers receive content included in requests, and web tools may use intermediary services. Local storage does not mean absolute privacy.
|
|
32
|
-
|
|
33
|
-
## Características principales / Main features
|
|
34
|
-
|
|
35
|
-
- **Perfiles:** OpenAI y APIs de chat compatibles, Ollama, OpenRouter, Claude y Gemini. La visión, las herramientas y el razonamiento dependen del modelo y del adaptador.
|
|
36
|
-
- **WebLLM:** inferencia en el navegador con WebGPU, tras descargar un modelo. Necesita hardware compatible y memoria suficiente.
|
|
37
|
-
- **Documentos:** adjuntos y colecciones RAG con extracción local y búsqueda léxica mediante Orama; sin embeddings. Los fragmentos recuperados se envían al modelo elegido. La extracción de PDF tiene límites y no incluye OCR general.
|
|
38
|
-
- **Herramientas:** JavaScript aislado, búsqueda y lectura web, gráficos, planes y puntos de control. El backend opcional añade archivos, comandos, diagnósticos, automatización de navegador y servicios MCP.
|
|
39
|
-
- **Historial y diagnóstico:** ramas de conversación, exportación JSON y Markdown, impresión a PDF, métricas de contexto y revisión de peticiones antes del envío.
|
|
40
|
-
|
|
41
|
-
*English:*
|
|
42
|
-
|
|
43
|
-
- **Profiles:** OpenAI and compatible chat APIs, Ollama, OpenRouter, Claude and Gemini. Vision, tools and reasoning depend on the model and adapter.
|
|
44
|
-
- **WebLLM:** browser inference through WebGPU after downloading a model. Requires compatible hardware and enough memory.
|
|
45
|
-
- **Documents:** attachments and RAG collections with local extraction and Orama lexical search, without embeddings. Retrieved passages are sent to the selected model. PDF extraction has limitations and no general OCR.
|
|
46
|
-
- **Tools:** isolated JavaScript, web search and retrieval, charts, plans and checkpoints. The optional backend adds files, commands, diagnostics, browser automation and MCP services.
|
|
47
|
-
- **History and diagnostics:** conversation branches, JSON and Markdown export, printing to PDF, context metrics and request inspection before sending.
|
|
48
|
-
|
|
49
|
-
## Inicio rápido / Quick start
|
|
50
|
-
|
|
51
|
-
Abre [ZeroChat en GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), crea un perfil, introduce la URL y la clave si corresponde, consulta los modelos con **Query** y guarda. El perfil **Espejo** permite probar la interfaz sin inferencia. Para WebLLM, prepara un modelo del catálogo.
|
|
52
|
-
|
|
53
|
-
*English:* Open [ZeroChat on GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), create a profile, enter the URL and key where required, query models with **Query**, and save. **Mirror** lets you try the interface without inference. For WebLLM, prepare a catalogue model.
|
|
54
|
-
|
|
55
|
-
Para añadir herramientas del equipo, instala y ejecuta el backend con Python. / To add computer tools, install and run the Python backend:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# Linux, macOS, Android (Termux)
|
|
59
|
-
pip install zerochat
|
|
60
|
-
zerochat
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
```powershell
|
|
64
|
-
# Windows (PowerShell o CMD / PowerShell or CMD)
|
|
65
|
-
py -m pip install zerochat
|
|
66
|
-
py -m zerochat
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
También puedes descargar el script y ejecutarlo. / You can also download and run the script:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
# Linux, macOS, Android (Termux)
|
|
73
|
-
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
74
|
-
python3 zerochat.py
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
```powershell
|
|
78
|
-
# Windows (PowerShell o CMD / PowerShell or CMD)
|
|
79
|
-
curl.exe -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
80
|
-
py zerochat.py
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
> **Entornos probados / Tested environments:** Linux (x86_64, ARM), Windows 10/11 (PowerShell, `py -m zerochat`), Android (Termux con `python`; Playwright no se puede usar actualmente en Termux / Playwright cannot currently be used on Termux).
|
|
84
|
-
> **Navegadores / Browsers:** ZeroChat **no es compatible con Safari / does not work on Safari**. En macOS debería funcionar con Firefox o Chromium, pero no se ha probado / On macOS it should work with Firefox or Chromium, but it has not been tested.
|
|
85
|
-
|
|
86
|
-
Fuera del repositorio de desarrollo, ambos modos abren la interfaz de GitHub Pages. Crean `~/zerochat/` para configuración y servicios, con `.venv/` para dependencias MCP Python. Mantén el proceso abierto y usa su enlace de arranque para autenticar la conexión local. Revisa **Ajustes → MCP** y **Permisos** antes de habilitar herramientas: los comandos actúan con los permisos del proceso local y detenerlos no deshace cambios.
|
|
87
|
-
|
|
88
|
-
Borrar `~/zerochat/` elimina ese estado y los MCP gestionados, no el ejecutable, los archivos modificados fuera de esa carpeta ni los datos del navegador. Exporta las conversaciones y perfiles que quieras conservar; sus copias no incluyen las colecciones RAG ni los modelos descargados. El cifrado predeterminado de perfiles utiliza una clave integrada conocida: trata las copias como archivos sensibles.
|
|
89
|
-
|
|
90
|
-
*English:* Outside the development repository, both modes open the GitHub Pages interface. They create `~/zerochat/` for configuration and services, with `.venv/` for Python MCP dependencies. Keep the process running and use its startup link to authenticate the local connection. Review **Settings → MCP** and **Permissions** before enabling tools: commands run with the local process permissions, and stopping them does not undo changes.
|
|
91
|
-
|
|
92
|
-
Deleting `~/zerochat/` removes that state and managed MCP services, not the executable, files changed elsewhere or browser data. Export conversations and profiles you want to keep; these backups do not include RAG collections or downloaded models. Default profile encryption uses a known built-in key: treat backups as sensitive files.
|
|
93
|
-
|
|
94
|
-
## Documentación y ayuda / Documentation and help
|
|
95
|
-
|
|
96
|
-
- [Ayuda de ZeroChat 8.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
97
|
-
- [ZeroChat 8.x help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
98
|
-
|
|
99
|
-
Las guías explican configuración, uso y límites.
|
|
100
|
-
|
|
101
|
-
*English:* The guides explain setup, usage and limits.
|
|
102
|
-
|
|
103
|
-
## Desarrollo / Development
|
|
104
|
-
|
|
105
|
-
Trabaja en `dev`. Para instalar dependencias y ejecutar las pruebas del proyecto: / Work on `dev`. To install dependencies and run the project tests:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
npm install
|
|
109
|
-
npm test
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Dentro del repositorio, `python3 zerochat.py` sirve la interfaz local de desarrollo. Si modificas `py/`, reconstruye `zerochat.py` con `npm run build:backend`. La web carga directamente sus módulos, sin un bundle de aplicación.
|
|
113
|
-
|
|
114
|
-
*English:* Inside the repository, `python3 zerochat.py` serves the local development interface. After changing `py/`, rebuild `zerochat.py` with `npm run build:backend`. The web app loads its modules directly, without an application bundle.
|
|
115
|
-
|
|
116
|
-
Las normas y validaciones se describen en [`AGENTS.md`](./AGENTS.md) y [`tests/README.md`](./tests/README.md).
|
|
117
|
-
|
|
118
|
-
*English:* See those files for the applicable development rules and validation.
|
zerochat-9.0.0/README.md
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# ZeroChat
|
|
2
|
-
|
|
3
|
-
ZeroChat es un cliente web de uso personal para conversar con modelos de IA, consultar documentos y utilizar herramientas. Esta documentación corresponde a la serie **8.x**, que consolida las funcionalidades existentes. El desarrollo de nuevas funcionalidades queda en pausa por el momento.
|
|
4
|
-
|
|
5
|
-
La interfaz se sirve como archivos estáticos: `zerochat.html` necesita sus módulos `js/` y `css/`. El historial y la configuración se guardan en el navegador; no se sincronizan automáticamente entre dispositivos. Los proveedores remotos reciben el contenido incluido en las peticiones, y las herramientas web pueden utilizar servicios intermediarios. Almacenamiento local no significa privacidad absoluta.
|
|
6
|
-
|
|
7
|
-
*English:* ZeroChat is a web client for personal use: chatting with AI models, consulting documents and using tools. This documentation covers the **8.x** series, which consolidates existing features. New feature development is paused for now.
|
|
8
|
-
|
|
9
|
-
The interface is served as static files: `zerochat.html` needs its `js/` and `css/` modules. History and settings are stored in the browser, without automatic cross-device sync. Remote providers receive content included in requests, and web tools may use intermediary services. Local storage does not mean absolute privacy.
|
|
10
|
-
|
|
11
|
-
## Características principales / Main features
|
|
12
|
-
|
|
13
|
-
- **Perfiles:** OpenAI y APIs de chat compatibles, Ollama, OpenRouter, Claude y Gemini. La visión, las herramientas y el razonamiento dependen del modelo y del adaptador.
|
|
14
|
-
- **WebLLM:** inferencia en el navegador con WebGPU, tras descargar un modelo. Necesita hardware compatible y memoria suficiente.
|
|
15
|
-
- **Documentos:** adjuntos y colecciones RAG con extracción local y búsqueda léxica mediante Orama; sin embeddings. Los fragmentos recuperados se envían al modelo elegido. La extracción de PDF tiene límites y no incluye OCR general.
|
|
16
|
-
- **Herramientas:** JavaScript aislado, búsqueda y lectura web, gráficos, planes y puntos de control. El backend opcional añade archivos, comandos, diagnósticos, automatización de navegador y servicios MCP.
|
|
17
|
-
- **Historial y diagnóstico:** ramas de conversación, exportación JSON y Markdown, impresión a PDF, métricas de contexto y revisión de peticiones antes del envío.
|
|
18
|
-
|
|
19
|
-
*English:*
|
|
20
|
-
|
|
21
|
-
- **Profiles:** OpenAI and compatible chat APIs, Ollama, OpenRouter, Claude and Gemini. Vision, tools and reasoning depend on the model and adapter.
|
|
22
|
-
- **WebLLM:** browser inference through WebGPU after downloading a model. Requires compatible hardware and enough memory.
|
|
23
|
-
- **Documents:** attachments and RAG collections with local extraction and Orama lexical search, without embeddings. Retrieved passages are sent to the selected model. PDF extraction has limitations and no general OCR.
|
|
24
|
-
- **Tools:** isolated JavaScript, web search and retrieval, charts, plans and checkpoints. The optional backend adds files, commands, diagnostics, browser automation and MCP services.
|
|
25
|
-
- **History and diagnostics:** conversation branches, JSON and Markdown export, printing to PDF, context metrics and request inspection before sending.
|
|
26
|
-
|
|
27
|
-
## Inicio rápido / Quick start
|
|
28
|
-
|
|
29
|
-
Abre [ZeroChat en GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), crea un perfil, introduce la URL y la clave si corresponde, consulta los modelos con **Query** y guarda. El perfil **Espejo** permite probar la interfaz sin inferencia. Para WebLLM, prepara un modelo del catálogo.
|
|
30
|
-
|
|
31
|
-
*English:* Open [ZeroChat on GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), create a profile, enter the URL and key where required, query models with **Query**, and save. **Mirror** lets you try the interface without inference. For WebLLM, prepare a catalogue model.
|
|
32
|
-
|
|
33
|
-
Para añadir herramientas del equipo, instala y ejecuta el backend con Python. / To add computer tools, install and run the Python backend:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
# Linux, macOS, Android (Termux)
|
|
37
|
-
pip install zerochat
|
|
38
|
-
zerochat
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
```powershell
|
|
42
|
-
# Windows (PowerShell o CMD / PowerShell or CMD)
|
|
43
|
-
py -m pip install zerochat
|
|
44
|
-
py -m zerochat
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
También puedes descargar el script y ejecutarlo. / You can also download and run the script:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# Linux, macOS, Android (Termux)
|
|
51
|
-
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
52
|
-
python3 zerochat.py
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
```powershell
|
|
56
|
-
# Windows (PowerShell o CMD / PowerShell or CMD)
|
|
57
|
-
curl.exe -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
58
|
-
py zerochat.py
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
> **Entornos probados / Tested environments:** Linux (x86_64, ARM), Windows 10/11 (PowerShell, `py -m zerochat`), Android (Termux con `python`; Playwright no se puede usar actualmente en Termux / Playwright cannot currently be used on Termux).
|
|
62
|
-
> **Navegadores / Browsers:** ZeroChat **no es compatible con Safari / does not work on Safari**. En macOS debería funcionar con Firefox o Chromium, pero no se ha probado / On macOS it should work with Firefox or Chromium, but it has not been tested.
|
|
63
|
-
|
|
64
|
-
Fuera del repositorio de desarrollo, ambos modos abren la interfaz de GitHub Pages. Crean `~/zerochat/` para configuración y servicios, con `.venv/` para dependencias MCP Python. Mantén el proceso abierto y usa su enlace de arranque para autenticar la conexión local. Revisa **Ajustes → MCP** y **Permisos** antes de habilitar herramientas: los comandos actúan con los permisos del proceso local y detenerlos no deshace cambios.
|
|
65
|
-
|
|
66
|
-
Borrar `~/zerochat/` elimina ese estado y los MCP gestionados, no el ejecutable, los archivos modificados fuera de esa carpeta ni los datos del navegador. Exporta las conversaciones y perfiles que quieras conservar; sus copias no incluyen las colecciones RAG ni los modelos descargados. El cifrado predeterminado de perfiles utiliza una clave integrada conocida: trata las copias como archivos sensibles.
|
|
67
|
-
|
|
68
|
-
*English:* Outside the development repository, both modes open the GitHub Pages interface. They create `~/zerochat/` for configuration and services, with `.venv/` for Python MCP dependencies. Keep the process running and use its startup link to authenticate the local connection. Review **Settings → MCP** and **Permissions** before enabling tools: commands run with the local process permissions, and stopping them does not undo changes.
|
|
69
|
-
|
|
70
|
-
Deleting `~/zerochat/` removes that state and managed MCP services, not the executable, files changed elsewhere or browser data. Export conversations and profiles you want to keep; these backups do not include RAG collections or downloaded models. Default profile encryption uses a known built-in key: treat backups as sensitive files.
|
|
71
|
-
|
|
72
|
-
## Documentación y ayuda / Documentation and help
|
|
73
|
-
|
|
74
|
-
- [Ayuda de ZeroChat 8.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
75
|
-
- [ZeroChat 8.x help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
76
|
-
|
|
77
|
-
Las guías explican configuración, uso y límites.
|
|
78
|
-
|
|
79
|
-
*English:* The guides explain setup, usage and limits.
|
|
80
|
-
|
|
81
|
-
## Desarrollo / Development
|
|
82
|
-
|
|
83
|
-
Trabaja en `dev`. Para instalar dependencias y ejecutar las pruebas del proyecto: / Work on `dev`. To install dependencies and run the project tests:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
npm install
|
|
87
|
-
npm test
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Dentro del repositorio, `python3 zerochat.py` sirve la interfaz local de desarrollo. Si modificas `py/`, reconstruye `zerochat.py` con `npm run build:backend`. La web carga directamente sus módulos, sin un bundle de aplicación.
|
|
91
|
-
|
|
92
|
-
*English:* Inside the repository, `python3 zerochat.py` serves the local development interface. After changing `py/`, rebuild `zerochat.py` with `npm run build:backend`. The web app loads its modules directly, without an application bundle.
|
|
93
|
-
|
|
94
|
-
Las normas y validaciones se describen en [`AGENTS.md`](./AGENTS.md) y [`tests/README.md`](./tests/README.md).
|
|
95
|
-
|
|
96
|
-
*English:* See those files for the applicable development rules and validation.
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: zerochat
|
|
3
|
-
Version: 9.0.0
|
|
4
|
-
Summary: Private local web client for AI models, tools and MCP services
|
|
5
|
-
Author: Alberto Alday
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://albalday.github.io/zerochat/
|
|
8
|
-
Project-URL: Repository, https://github.com/albalday/zerochat
|
|
9
|
-
Project-URL: Issues, https://github.com/albalday/zerochat/issues
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Environment :: Web Environment
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Requires-Python: >=3.10
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
License-File: LICENSE
|
|
21
|
-
Dynamic: license-file
|
|
22
|
-
|
|
23
|
-
# ZeroChat
|
|
24
|
-
|
|
25
|
-
ZeroChat es un cliente web de uso personal para conversar con modelos de IA, consultar documentos y utilizar herramientas. Esta documentación corresponde a la serie **8.x**, que consolida las funcionalidades existentes. El desarrollo de nuevas funcionalidades queda en pausa por el momento.
|
|
26
|
-
|
|
27
|
-
La interfaz se sirve como archivos estáticos: `zerochat.html` necesita sus módulos `js/` y `css/`. El historial y la configuración se guardan en el navegador; no se sincronizan automáticamente entre dispositivos. Los proveedores remotos reciben el contenido incluido en las peticiones, y las herramientas web pueden utilizar servicios intermediarios. Almacenamiento local no significa privacidad absoluta.
|
|
28
|
-
|
|
29
|
-
*English:* ZeroChat is a web client for personal use: chatting with AI models, consulting documents and using tools. This documentation covers the **8.x** series, which consolidates existing features. New feature development is paused for now.
|
|
30
|
-
|
|
31
|
-
The interface is served as static files: `zerochat.html` needs its `js/` and `css/` modules. History and settings are stored in the browser, without automatic cross-device sync. Remote providers receive content included in requests, and web tools may use intermediary services. Local storage does not mean absolute privacy.
|
|
32
|
-
|
|
33
|
-
## Características principales / Main features
|
|
34
|
-
|
|
35
|
-
- **Perfiles:** OpenAI y APIs de chat compatibles, Ollama, OpenRouter, Claude y Gemini. La visión, las herramientas y el razonamiento dependen del modelo y del adaptador.
|
|
36
|
-
- **WebLLM:** inferencia en el navegador con WebGPU, tras descargar un modelo. Necesita hardware compatible y memoria suficiente.
|
|
37
|
-
- **Documentos:** adjuntos y colecciones RAG con extracción local y búsqueda léxica mediante Orama; sin embeddings. Los fragmentos recuperados se envían al modelo elegido. La extracción de PDF tiene límites y no incluye OCR general.
|
|
38
|
-
- **Herramientas:** JavaScript aislado, búsqueda y lectura web, gráficos, planes y puntos de control. El backend opcional añade archivos, comandos, diagnósticos, automatización de navegador y servicios MCP.
|
|
39
|
-
- **Historial y diagnóstico:** ramas de conversación, exportación JSON y Markdown, impresión a PDF, métricas de contexto y revisión de peticiones antes del envío.
|
|
40
|
-
|
|
41
|
-
*English:*
|
|
42
|
-
|
|
43
|
-
- **Profiles:** OpenAI and compatible chat APIs, Ollama, OpenRouter, Claude and Gemini. Vision, tools and reasoning depend on the model and adapter.
|
|
44
|
-
- **WebLLM:** browser inference through WebGPU after downloading a model. Requires compatible hardware and enough memory.
|
|
45
|
-
- **Documents:** attachments and RAG collections with local extraction and Orama lexical search, without embeddings. Retrieved passages are sent to the selected model. PDF extraction has limitations and no general OCR.
|
|
46
|
-
- **Tools:** isolated JavaScript, web search and retrieval, charts, plans and checkpoints. The optional backend adds files, commands, diagnostics, browser automation and MCP services.
|
|
47
|
-
- **History and diagnostics:** conversation branches, JSON and Markdown export, printing to PDF, context metrics and request inspection before sending.
|
|
48
|
-
|
|
49
|
-
## Inicio rápido / Quick start
|
|
50
|
-
|
|
51
|
-
Abre [ZeroChat en GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), crea un perfil, introduce la URL y la clave si corresponde, consulta los modelos con **Query** y guarda. El perfil **Espejo** permite probar la interfaz sin inferencia. Para WebLLM, prepara un modelo del catálogo.
|
|
52
|
-
|
|
53
|
-
*English:* Open [ZeroChat on GitHub Pages](https://albalday.github.io/zerochat/zerochat.html), create a profile, enter the URL and key where required, query models with **Query**, and save. **Mirror** lets you try the interface without inference. For WebLLM, prepare a catalogue model.
|
|
54
|
-
|
|
55
|
-
Para añadir herramientas del equipo, instala y ejecuta el backend con Python. / To add computer tools, install and run the Python backend:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# Linux, macOS, Android (Termux)
|
|
59
|
-
pip install zerochat
|
|
60
|
-
zerochat
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
```powershell
|
|
64
|
-
# Windows (PowerShell o CMD / PowerShell or CMD)
|
|
65
|
-
py -m pip install zerochat
|
|
66
|
-
py -m zerochat
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
También puedes descargar el script y ejecutarlo. / You can also download and run the script:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
# Linux, macOS, Android (Termux)
|
|
73
|
-
curl -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
74
|
-
python3 zerochat.py
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
```powershell
|
|
78
|
-
# Windows (PowerShell o CMD / PowerShell or CMD)
|
|
79
|
-
curl.exe -fsSL https://albalday.github.io/zerochat/zerochat.py -o zerochat.py
|
|
80
|
-
py zerochat.py
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
> **Entornos probados / Tested environments:** Linux (x86_64, ARM), Windows 10/11 (PowerShell, `py -m zerochat`), Android (Termux con `python`; Playwright no se puede usar actualmente en Termux / Playwright cannot currently be used on Termux).
|
|
84
|
-
> **Navegadores / Browsers:** ZeroChat **no es compatible con Safari / does not work on Safari**. En macOS debería funcionar con Firefox o Chromium, pero no se ha probado / On macOS it should work with Firefox or Chromium, but it has not been tested.
|
|
85
|
-
|
|
86
|
-
Fuera del repositorio de desarrollo, ambos modos abren la interfaz de GitHub Pages. Crean `~/zerochat/` para configuración y servicios, con `.venv/` para dependencias MCP Python. Mantén el proceso abierto y usa su enlace de arranque para autenticar la conexión local. Revisa **Ajustes → MCP** y **Permisos** antes de habilitar herramientas: los comandos actúan con los permisos del proceso local y detenerlos no deshace cambios.
|
|
87
|
-
|
|
88
|
-
Borrar `~/zerochat/` elimina ese estado y los MCP gestionados, no el ejecutable, los archivos modificados fuera de esa carpeta ni los datos del navegador. Exporta las conversaciones y perfiles que quieras conservar; sus copias no incluyen las colecciones RAG ni los modelos descargados. El cifrado predeterminado de perfiles utiliza una clave integrada conocida: trata las copias como archivos sensibles.
|
|
89
|
-
|
|
90
|
-
*English:* Outside the development repository, both modes open the GitHub Pages interface. They create `~/zerochat/` for configuration and services, with `.venv/` for Python MCP dependencies. Keep the process running and use its startup link to authenticate the local connection. Review **Settings → MCP** and **Permissions** before enabling tools: commands run with the local process permissions, and stopping them does not undo changes.
|
|
91
|
-
|
|
92
|
-
Deleting `~/zerochat/` removes that state and managed MCP services, not the executable, files changed elsewhere or browser data. Export conversations and profiles you want to keep; these backups do not include RAG collections or downloaded models. Default profile encryption uses a known built-in key: treat backups as sensitive files.
|
|
93
|
-
|
|
94
|
-
## Documentación y ayuda / Documentation and help
|
|
95
|
-
|
|
96
|
-
- [Ayuda de ZeroChat 8.x — Español](https://albalday.github.io/zerochat/help/index.html)
|
|
97
|
-
- [ZeroChat 8.x help — English](https://albalday.github.io/zerochat/help/en/index.html)
|
|
98
|
-
|
|
99
|
-
Las guías explican configuración, uso y límites.
|
|
100
|
-
|
|
101
|
-
*English:* The guides explain setup, usage and limits.
|
|
102
|
-
|
|
103
|
-
## Desarrollo / Development
|
|
104
|
-
|
|
105
|
-
Trabaja en `dev`. Para instalar dependencias y ejecutar las pruebas del proyecto: / Work on `dev`. To install dependencies and run the project tests:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
npm install
|
|
109
|
-
npm test
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Dentro del repositorio, `python3 zerochat.py` sirve la interfaz local de desarrollo. Si modificas `py/`, reconstruye `zerochat.py` con `npm run build:backend`. La web carga directamente sus módulos, sin un bundle de aplicación.
|
|
113
|
-
|
|
114
|
-
*English:* Inside the repository, `python3 zerochat.py` serves the local development interface. After changing `py/`, rebuild `zerochat.py` with `npm run build:backend`. The web app loads its modules directly, without an application bundle.
|
|
115
|
-
|
|
116
|
-
Las normas y validaciones se describen en [`AGENTS.md`](./AGENTS.md) y [`tests/README.md`](./tests/README.md).
|
|
117
|
-
|
|
118
|
-
*English:* See those files for the applicable development rules and validation.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|