@rozek/nanoclaw 0.0.5 → 0.0.7
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.
- package/container/agent-runner/package-lock.json +1524 -0
- package/dist/cli.js +41 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
- package/.claude/settings.json +0 -1
- package/.claude/skills/add-compact/SKILL.md +0 -135
- package/.claude/skills/add-discord/SKILL.md +0 -203
- package/.claude/skills/add-gmail/SKILL.md +0 -220
- package/.claude/skills/add-image-vision/SKILL.md +0 -94
- package/.claude/skills/add-ollama-tool/SKILL.md +0 -153
- package/.claude/skills/add-parallel/SKILL.md +0 -290
- package/.claude/skills/add-pdf-reader/SKILL.md +0 -104
- package/.claude/skills/add-reactions/SKILL.md +0 -117
- package/.claude/skills/add-slack/SKILL.md +0 -207
- package/.claude/skills/add-telegram/SKILL.md +0 -222
- package/.claude/skills/add-telegram-swarm/SKILL.md +0 -384
- package/.claude/skills/add-voice-transcription/SKILL.md +0 -148
- package/.claude/skills/add-whatsapp/SKILL.md +0 -372
- package/.claude/skills/convert-to-apple-container/SKILL.md +0 -175
- package/.claude/skills/customize/SKILL.md +0 -110
- package/.claude/skills/debug/SKILL.md +0 -349
- package/.claude/skills/get-qodo-rules/SKILL.md +0 -122
- package/.claude/skills/get-qodo-rules/references/output-format.md +0 -41
- package/.claude/skills/get-qodo-rules/references/pagination.md +0 -33
- package/.claude/skills/get-qodo-rules/references/repository-scope.md +0 -26
- package/.claude/skills/qodo-pr-resolver/SKILL.md +0 -326
- package/.claude/skills/qodo-pr-resolver/resources/providers.md +0 -329
- package/.claude/skills/setup/SKILL.md +0 -218
- package/.claude/skills/update-nanoclaw/SKILL.md +0 -235
- package/.claude/skills/update-skills/SKILL.md +0 -130
- package/.claude/skills/use-local-whisper/SKILL.md +0 -152
- package/.claude/skills/x-integration/SKILL.md +0 -417
- package/.claude/skills/x-integration/agent.ts +0 -243
- package/.claude/skills/x-integration/host.ts +0 -159
- package/.claude/skills/x-integration/lib/browser.ts +0 -148
- package/.claude/skills/x-integration/lib/config.ts +0 -62
- package/.claude/skills/x-integration/scripts/like.ts +0 -56
- package/.claude/skills/x-integration/scripts/post.ts +0 -66
- package/.claude/skills/x-integration/scripts/quote.ts +0 -80
- package/.claude/skills/x-integration/scripts/reply.ts +0 -74
- package/.claude/skills/x-integration/scripts/retweet.ts +0 -62
- package/.claude/skills/x-integration/scripts/setup.ts +0 -87
- package/.env.example +0 -1
- package/.github/CODEOWNERS +0 -10
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -14
- package/.github/workflows/bump-version.yml +0 -32
- package/.github/workflows/ci.yml +0 -25
- package/.github/workflows/merge-forward-skills.yml +0 -160
- package/.github/workflows/update-tokens.yml +0 -42
- package/.husky/pre-commit +0 -1
- package/.mcp.json +0 -3
- package/.nvmrc +0 -1
- package/.prettierrc +0 -3
- package/CHANGELOG.md +0 -8
- package/CONTRIBUTING.md +0 -23
- package/CONTRIBUTORS.md +0 -15
- package/NanoClaw_with_Web-Support.md +0 -326
- package/README_zh.md +0 -200
- package/assets/nanoclaw-favicon.png +0 -0
- package/assets/nanoclaw-icon.png +0 -0
- package/assets/nanoclaw-logo-dark.png +0 -0
- package/assets/nanoclaw-logo.png +0 -0
- package/assets/nanoclaw-profile.jpeg +0 -0
- package/assets/nanoclaw-sales.png +0 -0
- package/assets/social-preview.jpg +0 -0
- package/config-examples/mount-allowlist.json +0 -25
- package/docs/APPLE-CONTAINER-NETWORKING.md +0 -90
- package/docs/DEBUG_CHECKLIST.md +0 -143
- package/docs/REQUIREMENTS.md +0 -196
- package/docs/SDK_DEEP_DIVE.md +0 -643
- package/docs/SECURITY.md +0 -122
- package/docs/SPEC.md +0 -785
- package/docs/docker-sandboxes.md +0 -359
- package/docs/nanoclaw-architecture-final.md +0 -1063
- package/docs/nanorepo-architecture.md +0 -168
- package/docs/skills-as-branches.md +0 -662
- package/groups/global/CLAUDE.md +0 -58
- package/groups/main/CLAUDE.md +0 -246
- package/launchd/com.nanoclaw.plist +0 -32
- package/repo-tokens/README.md +0 -113
- package/repo-tokens/action.yml +0 -186
- package/repo-tokens/badge.svg +0 -23
- package/repo-tokens/examples/green.svg +0 -14
- package/repo-tokens/examples/red.svg +0 -14
- package/repo-tokens/examples/yellow-green.svg +0 -14
- package/repo-tokens/examples/yellow.svg +0 -14
- package/scripts/run-migrations.ts +0 -105
- package/setup.sh +0 -161
- package/src/channels/index.ts +0 -15
- package/src/channels/registry.test.ts +0 -42
- package/src/channels/registry.ts +0 -32
- package/src/channels/web.ts +0 -1931
- package/src/cli.ts +0 -254
- package/src/config.ts +0 -73
- package/src/container-runner.test.ts +0 -210
- package/src/container-runner.ts +0 -768
- package/src/container-runtime.test.ts +0 -149
- package/src/container-runtime.ts +0 -127
- package/src/credential-proxy.test.ts +0 -192
- package/src/credential-proxy.ts +0 -125
- package/src/db.test.ts +0 -484
- package/src/db.ts +0 -803
- package/src/env.ts +0 -42
- package/src/formatting.test.ts +0 -256
- package/src/group-folder.test.ts +0 -43
- package/src/group-folder.ts +0 -44
- package/src/group-queue.test.ts +0 -484
- package/src/group-queue.ts +0 -379
- package/src/index.ts +0 -854
- package/src/ipc-auth.test.ts +0 -679
- package/src/ipc.ts +0 -461
- package/src/logger.ts +0 -16
- package/src/mount-security.ts +0 -419
- package/src/remote-control.test.ts +0 -397
- package/src/remote-control.ts +0 -224
- package/src/router.ts +0 -52
- package/src/routing.test.ts +0 -170
- package/src/sender-allowlist.test.ts +0 -216
- package/src/sender-allowlist.ts +0 -128
- package/src/session-commands.test.ts +0 -247
- package/src/session-commands.ts +0 -163
- package/src/task-scheduler.test.ts +0 -129
- package/src/task-scheduler.ts +0 -328
- package/src/timezone.test.ts +0 -29
- package/src/timezone.ts +0 -16
- package/src/types.ts +0 -109
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -7
- package/vitest.skills.config.ts +0 -7
package/CHANGELOG.md
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to NanoClaw will be documented in this file.
|
|
4
|
-
|
|
5
|
-
## [1.2.0](https://github.com/qwibitai/nanoclaw/compare/v1.1.6...v1.2.0)
|
|
6
|
-
|
|
7
|
-
[BREAKING] WhatsApp removed from core, now a skill. Run `/add-whatsapp` to re-add (existing auth/groups preserved).
|
|
8
|
-
- **fix:** Prevent scheduled tasks from executing twice when container runtime exceeds poll interval (#138, #669)
|
package/CONTRIBUTING.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
## Source Code Changes
|
|
4
|
-
|
|
5
|
-
**Accepted:** Bug fixes, security fixes, simplifications, reducing code.
|
|
6
|
-
|
|
7
|
-
**Not accepted:** Features, capabilities, compatibility, enhancements. These should be skills.
|
|
8
|
-
|
|
9
|
-
## Skills
|
|
10
|
-
|
|
11
|
-
A [skill](https://code.claude.com/docs/en/skills) is a markdown file in `.claude/skills/` that teaches Claude Code how to transform a NanoClaw installation.
|
|
12
|
-
|
|
13
|
-
A PR that contributes a skill should not modify any source files.
|
|
14
|
-
|
|
15
|
-
Your skill should contain the **instructions** Claude follows to add the feature—not pre-built code. See `/add-telegram` for a good example.
|
|
16
|
-
|
|
17
|
-
### Why?
|
|
18
|
-
|
|
19
|
-
Every user should have clean and minimal code that does exactly what they need. Skills let users selectively add features to their fork without inheriting code for features they don't want.
|
|
20
|
-
|
|
21
|
-
### Testing
|
|
22
|
-
|
|
23
|
-
Test your skill by running it on a fresh clone before submitting.
|
package/CONTRIBUTORS.md
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Contributors
|
|
2
|
-
|
|
3
|
-
Thanks to everyone who has contributed to NanoClaw!
|
|
4
|
-
|
|
5
|
-
- [Alakazam03](https://github.com/Alakazam03) — Vaibhav Aggarwal
|
|
6
|
-
- [tydev-new](https://github.com/tydev-new)
|
|
7
|
-
- [pottertech](https://github.com/pottertech) — Skip Potter
|
|
8
|
-
- [rgarcia](https://github.com/rgarcia) — Rafael
|
|
9
|
-
- [AmaxGuan](https://github.com/AmaxGuan) — Lingfeng Guan
|
|
10
|
-
- [happydog-intj](https://github.com/happydog-intj) — happy dog
|
|
11
|
-
- [bindoon](https://github.com/bindoon) — 潕量
|
|
12
|
-
- [taslim](https://github.com/taslim) — Taslim
|
|
13
|
-
- [baijunjie](https://github.com/baijunjie) — BaiJunjie
|
|
14
|
-
- [Michaelliv](https://github.com/Michaelliv) — Michael
|
|
15
|
-
- [kk17](https://github.com/kk17) — Kyle Zhike Chen
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
# NanoClaw with Web Support
|
|
2
|
-
|
|
3
|
-
This document describes the changes added in the [rozek/nanoclaw](https://github.com/rozek/nanoclaw) fork of [qwibitai/nanoclaw](https://github.com/qwibitai/nanoclaw). It serves as installation guide, feature reference, and API documentation.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Quick Start (npx)
|
|
8
|
-
|
|
9
|
-
No cloning, no `npm install` — just run:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npx @rozek/nanoclaw
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Then open **http://localhost:3099** in your browser.
|
|
16
|
-
|
|
17
|
-
### Prerequisites
|
|
18
|
-
|
|
19
|
-
| Requirement | How to check | Notes |
|
|
20
|
-
|-------------|-------------|-------|
|
|
21
|
-
| **Node.js ≥ 20** | `node --version` | |
|
|
22
|
-
| **Claude Code** | `claude --version` | `npm install -g @anthropic-ai/claude-code` |
|
|
23
|
-
| **Container runtime** | `docker info` *or* `container --version` | Docker Desktop **or** macOS Sequoia 15+ Apple Container Runtime |
|
|
24
|
-
|
|
25
|
-
> **No API key required** if you have a Claude Pro or Max subscription — NanoClaw uses Claude Code, which is included in those plans.
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Web Channel Features
|
|
30
|
-
|
|
31
|
-
### UI & Design
|
|
32
|
-
|
|
33
|
-
- **Light and dark themes** — with your system theme as default
|
|
34
|
-
- **Full-viewport layout** — always fills the screen
|
|
35
|
-
- **Responsive** — desktop: fixed sidebar; mobile: sidebar as overlay with backdrop
|
|
36
|
-
|
|
37
|
-
### Rich Content Rendering
|
|
38
|
-
|
|
39
|
-
Bot responses are rendered with full Markdown support:
|
|
40
|
-
|
|
41
|
-
| Library | Purpose |
|
|
42
|
-
|---------|---------|
|
|
43
|
-
| [marked.js](https://marked.js.org) | GitHub Flavored Markdown |
|
|
44
|
-
| [KaTeX](https://katex.org) | Inline (`$...$`) and block (`$$...$$`) math formulas |
|
|
45
|
-
| [highlight.js](https://highlightjs.org) | Syntax highlighting (TypeScript, Java, and many more) |
|
|
46
|
-
| [Mermaid](https://mermaid.js.org) | Flowcharts, sequence diagrams, etc. |
|
|
47
|
-
|
|
48
|
-
### Multi-Session Chat
|
|
49
|
-
|
|
50
|
-
- Unlimited parallel chat sessions per browser
|
|
51
|
-
- Sessions are listed in the sidebar, freely sortable by dragging
|
|
52
|
-
- Each session has an editable name (pencil icon ✏; default: date+time)
|
|
53
|
-
- Sessions persist in `localStorage` and SQLite — survive browser reloads and server restarts
|
|
54
|
-
- Sessions from other devices appear automatically in the sidebar (polled every 5 s)
|
|
55
|
-
- Unread message indicators (blue dot) per session, persisted in `localStorage`
|
|
56
|
-
- Sessions can be deleted (removes all messages from DB and `localStorage`)
|
|
57
|
-
|
|
58
|
-
### Session Name Sync
|
|
59
|
-
|
|
60
|
-
Conflict-free name synchronisation across devices:
|
|
61
|
-
|
|
62
|
-
- Every rename carries a `nameUpdatedAt` UNIX timestamp
|
|
63
|
-
- Server-side guard: `UPDATE … WHERE excluded.name_updated_at >= chats.name_updated_at`
|
|
64
|
-
- On SSE connect, the client pushes its local name; if it is newer than the server's name, the server adopts it
|
|
65
|
-
|
|
66
|
-
### Message History
|
|
67
|
-
|
|
68
|
-
- Local `localStorage` cache (`hist:{sid}`) for instant display on load
|
|
69
|
-
- Full conversation history served from SQLite via `GET /history?sid=…`
|
|
70
|
-
- Both user messages and bot replies are persisted and synced across devices
|
|
71
|
-
- Individual messages can be deleted (trash icon; removes from DOM, cache, and DB)
|
|
72
|
-
|
|
73
|
-
### Real-Time Updates (Server-Sent Events)
|
|
74
|
-
|
|
75
|
-
All live updates arrive over a single SSE connection (`GET /events?sid=…`):
|
|
76
|
-
|
|
77
|
-
| Event | Payload | Purpose |
|
|
78
|
-
|-------|---------|---------|
|
|
79
|
-
| `message` | `{"text":"…","id":"…"}` | Append bot reply |
|
|
80
|
-
| `typing` | `"true"` / `"false"` | Show/hide typing indicator |
|
|
81
|
-
| `status` | `{"tool":"…","input":"…"}` or `null` | Display active tool (e.g. "searching…") |
|
|
82
|
-
| `cwd` | path string | Update working-directory display in header |
|
|
83
|
-
|
|
84
|
-
On connect, the server immediately sends the current `typing`, `status`, and `cwd` state so reconnects are seamless. Additionally, the client fetches `GET /pwd?sid=…` in the SSE `open` handler to reliably sync the CWD even if the `cwd` event arrives before the session is fully initialized.
|
|
85
|
-
|
|
86
|
-
### Working Folder (CWD)
|
|
87
|
-
|
|
88
|
-
- Current working folder shown in the header: `NanoClaw — IP:Port — <relative-path>`
|
|
89
|
-
- Set by the agent or user via `switching to folder: <relative-path>` (in any message or response)
|
|
90
|
-
- User shorthand commands available in the chat input:
|
|
91
|
-
- `/cwd <path>` — change the working folder instantly (no agent invocation)
|
|
92
|
-
- `/pwd` — display the current working folder
|
|
93
|
-
- Persisted in `chats.cwd` (SQLite) — survives server restarts
|
|
94
|
-
- Also cached in `localStorage` per session
|
|
95
|
-
- NanoClaw ships with built-in skills (`container/skills/cwd/` and `container/skills/pwd/`) that instruct the AI how to use these commands
|
|
96
|
-
- All CWD values (from agent output, `/cwd` command, or `POST /cwd`) are passed through `sanitizeCwd()` which resolves paths relative to the workspace root and rejects any attempt to escape it (absolute paths outside the workspace are silently clamped to `''`)
|
|
97
|
-
|
|
98
|
-
### File Upload
|
|
99
|
-
|
|
100
|
-
- Drag files into the browser window
|
|
101
|
-
- Files are written to the session's current working directory (or group root if no CWD)
|
|
102
|
-
- Maximum file size: 10 MB
|
|
103
|
-
|
|
104
|
-
### Cancel In-Progress Requests
|
|
105
|
-
|
|
106
|
-
- A **Cancel** button appears while the agent is processing
|
|
107
|
-
- Clicking it immediately kills the container process (SIGTERM) via `POST /cancel?sid=…`
|
|
108
|
-
- The button is disabled while the cancel request is in flight to prevent double-clicks
|
|
109
|
-
|
|
110
|
-
### Cron Jobs Tab
|
|
111
|
-
|
|
112
|
-
- A dedicated **Cron Jobs** tab (`local@web-cron`) shows output from all scheduled tasks
|
|
113
|
-
- The text input is disabled in this tab — it is reserved for task output only
|
|
114
|
-
|
|
115
|
-
### Access Control
|
|
116
|
-
|
|
117
|
-
Token-based authentication is optional but recommended when NanoClaw is reachable from the LAN:
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
npx @rozek/nanoclaw --token mySecretToken
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Clients authenticate via:
|
|
124
|
-
1. `Authorization: Bearer mySecretToken` header
|
|
125
|
-
2. `?token=mySecretToken` URL query parameter (sets an HttpOnly session cookie)
|
|
126
|
-
3. The HttpOnly session cookie set after step 2
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
## Installation & Usage
|
|
131
|
-
|
|
132
|
-
### Simplest start
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
npx @rozek/nanoclaw
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Auto-detects the container runtime (Docker first, then Apple Container). Binds to `127.0.0.1:3099` by default (localhost only).
|
|
139
|
-
|
|
140
|
-
### Common options
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
# Custom port
|
|
144
|
-
npx @rozek/nanoclaw --port 8080
|
|
145
|
-
|
|
146
|
-
# Custom workspace (directory NanoClaw works in)
|
|
147
|
-
npx @rozek/nanoclaw --workspace ~/my-workspace
|
|
148
|
-
|
|
149
|
-
# Token protection — recommended when accessible from the LAN
|
|
150
|
-
npx @rozek/nanoclaw --token mySecretToken
|
|
151
|
-
|
|
152
|
-
# Make accessible from the LAN (bind to all interfaces) — use with a token!
|
|
153
|
-
npx nanoclaw --host 0.0.0.0 --token mySecretToken
|
|
154
|
-
|
|
155
|
-
# Explicit container runtime
|
|
156
|
-
npx @rozek/nanoclaw --sandbox docker
|
|
157
|
-
npx @rozek/nanoclaw --sandbox apple
|
|
158
|
-
|
|
159
|
-
# With an Anthropic API key (for users without Pro/Max)
|
|
160
|
-
npx @rozek/nanoclaw --key sk-ant-...
|
|
161
|
-
|
|
162
|
-
# Combine options
|
|
163
|
-
npx @rozek/nanoclaw --port 8080 --workspace ~/my-workspace --token mySecretToken --sandbox docker
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### All CLI options
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
Options:
|
|
170
|
-
--host <address> Bind address for the web channel (default: 127.0.0.1)
|
|
171
|
-
--port <number> Port for the web channel (default: 3099)
|
|
172
|
-
--workspace <path> Workspace directory (default: current directory)
|
|
173
|
-
--key <api-key> Anthropic API key
|
|
174
|
-
Not required with Claude Pro/Max — NanoClaw uses
|
|
175
|
-
Claude Code, which is included in those plans.
|
|
176
|
-
--token <token> Access token for the web interface (default: no protection)
|
|
177
|
-
Clients supply it via:
|
|
178
|
-
Authorization: Bearer <token>
|
|
179
|
-
?token=<value> query parameter
|
|
180
|
-
or a session cookie
|
|
181
|
-
--sandbox <type> Container runtime: "docker" or "apple"
|
|
182
|
-
Defaults to auto-detect (docker → apple).
|
|
183
|
-
-h, --help Show this help and exit
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Environment variables
|
|
187
|
-
|
|
188
|
-
CLI flags take precedence. Alternatively, set environment variables:
|
|
189
|
-
|
|
190
|
-
```bash
|
|
191
|
-
NANOCLAW_HOST=127.0.0.1
|
|
192
|
-
NANOCLAW_PORT=3099
|
|
193
|
-
NANOCLAW_TOKEN=mySecretToken
|
|
194
|
-
NANOCLAW_KEY=sk-ant-...
|
|
195
|
-
NANOCLAW_WORKSPACE=/path/to/workspace
|
|
196
|
-
NANOCLAW_SANDBOX=docker # or: apple
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## HTTP API Reference
|
|
202
|
-
|
|
203
|
-
| Method | Path | Description |
|
|
204
|
-
|--------|------|-------------|
|
|
205
|
-
| `GET` | `/` | Serves the web UI (HTML) |
|
|
206
|
-
| `GET` | `/events?sid=…` | SSE stream for real-time updates |
|
|
207
|
-
| `GET` | `/sessions` | All web sessions with custom display order (JSON) |
|
|
208
|
-
| `GET` | `/history?sid=…` | Conversation history (JSON) |
|
|
209
|
-
| `GET` | `/favicon.ico` | Favicon (ICO) |
|
|
210
|
-
| `GET` | `/favicon.png` | Favicon (PNG) |
|
|
211
|
-
| `GET` | `/apple-touch-icon.png` | iOS home-screen icon |
|
|
212
|
-
| `POST` | `/message` | Send a chat message |
|
|
213
|
-
| `POST` | `/session-name` | Rename a session |
|
|
214
|
-
| `POST` | `/session-order` | Persist the user-defined session display order (drag-and-drop) |
|
|
215
|
-
| `POST` | `/delete-session` | Delete a session and all its messages |
|
|
216
|
-
| `POST` | `/delete-message` | Delete a single message `{sid, id}` |
|
|
217
|
-
| `GET` | `/pwd?sid=…` | Get the current working folder for a session (JSON: `{cwd}`) |
|
|
218
|
-
| `POST` | `/cwd` | Set the working folder for a session (`{cwd, sessionId}`) |
|
|
219
|
-
| `POST` | `/upload` | Upload a file (Base64-encoded body) |
|
|
220
|
-
| `POST` | `/cancel?sid=…` | Cancel the active request for a session |
|
|
221
|
-
|
|
222
|
-
---
|
|
223
|
-
|
|
224
|
-
## Architecture
|
|
225
|
-
|
|
226
|
-
```
|
|
227
|
-
Browser Server (web.ts) DB (SQLite)
|
|
228
|
-
─────── ─────────────── ───────────
|
|
229
|
-
GET / ←───────────── Embedded HTML/CSS/JS
|
|
230
|
-
GET /events ←── SSE ────── sseClients Map
|
|
231
|
-
POST /message ────────────→ onMessage() → agent run
|
|
232
|
-
agent replies → broadcastToSession()
|
|
233
|
-
GET /sessions ←── poll 5s ─ getAllChats() + sessionCwds chats table
|
|
234
|
-
POST /session-name ────────→ updateChatName() (with guard) chats.name
|
|
235
|
-
POST /session-order ────────→ setWebSessionOrder() router_state
|
|
236
|
-
GET /history ←───────────── getConversation() messages table
|
|
237
|
-
POST /delete-session ──────→ deleteChat() chats + messages
|
|
238
|
-
POST /delete-message ──────→ deleteMessage(id) messages table
|
|
239
|
-
GET /pwd ←───────────── sessionCwds.get(sid)
|
|
240
|
-
POST /cwd ────────────→ updateChatCwd() → broadcast chats.cwd
|
|
241
|
-
POST /upload ────────────→ fs.writeFile() into CWD dir
|
|
242
|
-
POST /cancel ────────────→ onCancelRequest()
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### In-Memory Server State
|
|
246
|
-
|
|
247
|
-
| Variable | Type | Content |
|
|
248
|
-
|----------|------|---------|
|
|
249
|
-
| `sseClients` | `Map<sid, Set<Response>>` | Open SSE connections per session |
|
|
250
|
-
| `sessionCwds` | `Map<sid, string>` | Current CWD per session |
|
|
251
|
-
| `sessionTyping` | `Map<sid, boolean>` | Whether the agent is processing |
|
|
252
|
-
| `sessionStatus` | `Map<sid, string\|null>` | Last tool-status payload |
|
|
253
|
-
| `registeredSessions` | `Set<sid>` | Sessions already registered with NanoClaw |
|
|
254
|
-
|
|
255
|
-
### Database Schema (relevant columns in `chats`)
|
|
256
|
-
|
|
257
|
-
| Column | Type | Purpose |
|
|
258
|
-
|--------|------|---------|
|
|
259
|
-
| `jid` | TEXT PK | `local@web-{sessionId}` |
|
|
260
|
-
| `name` | TEXT | Session display name |
|
|
261
|
-
| `name_updated_at` | INTEGER | UNIX epoch of the last rename |
|
|
262
|
-
| `cwd` | TEXT | Current working directory |
|
|
263
|
-
| `last_message_time` | TEXT | ISO timestamp updated on every message |
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
## Development Workflow
|
|
268
|
-
|
|
269
|
-
If you are running NanoClaw from source (not via `npx`):
|
|
270
|
-
|
|
271
|
-
```bash
|
|
272
|
-
# 1. Install dependencies
|
|
273
|
-
npm install
|
|
274
|
-
|
|
275
|
-
# 2. Build
|
|
276
|
-
npm run build
|
|
277
|
-
|
|
278
|
-
# 3. Run
|
|
279
|
-
node dist/cli.js [options]
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
To apply changes and rebuild in one step:
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
npm run build && node dist/cli.js
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## What's New
|
|
291
|
-
|
|
292
|
-
The following files were added or changed relative to [qwibitai/nanoclaw](https://github.com/qwibitai/nanoclaw) `main`:
|
|
293
|
-
|
|
294
|
-
### New files
|
|
295
|
-
|
|
296
|
-
| File | Purpose |
|
|
297
|
-
|------|---------|
|
|
298
|
-
| `src/cli.ts` | CLI entry point — parses arguments, validates them, starts NanoClaw; enables `npx @rozek/nanoclaw` |
|
|
299
|
-
| `src/channels/web.ts` | Complete HTTP server with embedded browser chat UI (HTML/CSS/JS inline) |
|
|
300
|
-
| `src/mount-security.ts` | Validates additional container mounts against an allowlist stored outside the project root (prevents agents from tampering with security config) |
|
|
301
|
-
| `src/session-commands.ts` | Session management commands (e.g. `/compact` for context compaction) — merged from upstream `skill/compact` branch |
|
|
302
|
-
| `src/session-commands.test.ts` | Unit tests for session commands |
|
|
303
|
-
| `container/skills/cwd/SKILL.md` | Built-in skill: instructs the AI to output `switching to folder: <path>` to update the working folder display |
|
|
304
|
-
| `container/skills/pwd/SKILL.md` | Built-in skill: instructs the AI how to determine and report the current working folder |
|
|
305
|
-
|
|
306
|
-
### Modified files
|
|
307
|
-
|
|
308
|
-
| File | What changed |
|
|
309
|
-
|------|-------------|
|
|
310
|
-
| `package.json` | Added `"bin": {"nanoclaw": "dist/cli.js"}` so the package works as an `npx` command; `setup/` must be included in the TypeScript compilation (`tsconfig.json`) so `dist/setup/index.js` is available at runtime |
|
|
311
|
-
| `src/cli.ts` | Added `runFirstTimeSetup()`: detects first run by checking for `store/messages.db`; if missing, automatically runs the setup steps `environment`, `container`, `mounts --empty`, and `verify` before starting NanoClaw — makes `npx @rozek/nanoclaw` self-configuring on first launch |
|
|
312
|
-
| `src/channels/index.ts` | Exports the new web channel |
|
|
313
|
-
| `src/channels/registry.ts` | Adds `registerGroup` and `onCancelRequest` to `ChannelOpts` so channels can register groups and handle cancel requests |
|
|
314
|
-
| `src/index.ts` | Integrates the web channel and session commands into the orchestrator's main loop; exports `main()` for use by `cli.ts`; adds `formatApiError()` to display Anthropic API errors (401/429/529/500) as user-facing chat messages; uses per-session chat IDs as Claude session keys; adds `statusCallback` to forward live tool-use events to the channel; adds `initWorkspace()` which runs at startup and creates all required workspace directories (`store/`, `groups/main/`, `groups/global/`, `data/ipc/`, `data/sessions/`, `groups/main/Tools/`, `groups/main/Skills/`, `groups/main/MCP-Servers/`, `groups/main/conversations/`) if they don't exist yet |
|
|
315
|
-
| `src/group-queue.ts` | Adds `cancelContainer()` — writes the close sentinel and sends SIGTERM to the container process for immediate cancellation |
|
|
316
|
-
| `src/db.ts` | Adds `name_updated_at` and `cwd` columns to the `chats` table; updates `updateChatName()` with timestamp guard and optional `nameUpdatedAt` argument; extends `getAllChats()` to return the new columns; adds `getWebSessionOrder()`, `setWebSessionOrder()`, `updateChatCwd()`, `getConversation()`, `deleteChat()`, `clearChatMessages()`, `deleteMessage()` |
|
|
317
|
-
| `src/types.ts` | Adds optional `setStatus?(jid, tool, inputSnippet)` to the channel interface so channels can show live tool-use status |
|
|
318
|
-
| `src/container-runner.ts` | Adds status-marker protocol (`---NANOCLAW_STATUS_START---` / `---NANOCLAW_STATUS_END---`) so the agent runner can emit tool-use status events; always syncs agent-runner source from master on container start |
|
|
319
|
-
| `src/task-scheduler.ts` | Routes scheduled task output for web sessions to a dedicated `local@web-cron` session (with task header); each task runs in its own queue slot (`task:<id>`) for parallel execution; uses per-session session IDs; falls back to the first `isMain` group when the task's `group_folder` is not found |
|
|
320
|
-
| `container/agent-runner/src/index.ts` | Updated agent runner: emits status markers for tool use; supports external MCP servers from `MCP-Servers/`; supports context compaction (`/compact`) |
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## License
|
|
325
|
-
|
|
326
|
-
MIT — same as the upstream [qwibitai/nanoclaw](https://github.com/qwibitai/nanoclaw).
|
package/README_zh.md
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="assets/nanoclaw-logo.png" alt="NanoClaw" width="400">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
NanoClaw —— 您的专属 Claude 助手,在容器中安全运行。它轻巧易懂,并能根据您的个人需求灵活定制。
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
<p align="center">
|
|
10
|
-
<a href="https://nanoclaw.dev">nanoclaw.dev</a> •
|
|
11
|
-
<a href="README.md">English</a> •
|
|
12
|
-
<a href="https://discord.gg/VDdww8qS42"><img src="https://img.shields.io/discord/1470188214710046894?label=Discord&logo=discord&v=2" alt="Discord" valign="middle"></a> •
|
|
13
|
-
<a href="repo-tokens"><img src="repo-tokens/badge.svg" alt="34.9k tokens, 17% of context window" valign="middle"></a>
|
|
14
|
-
</p>
|
|
15
|
-
通过 Claude Code,NanoClaw 可以动态重写自身代码,根据您的需求定制功能。
|
|
16
|
-
|
|
17
|
-
**新功能:** 首个支持 [Agent Swarms(智能体集群)](https://code.claude.com/docs/en/agent-teams) 的 AI 助手。可轻松组建智能体团队,在您的聊天中高效协作。
|
|
18
|
-
|
|
19
|
-
## 我为什么创建这个项目
|
|
20
|
-
|
|
21
|
-
[OpenClaw](https://github.com/openclaw/openclaw) 是一个令人印象深刻的项目,但我无法安心使用一个我不了解却能访问我个人隐私的软件。OpenClaw 有近 50 万行代码、53 个配置文件和 70+ 个依赖项。其安全性是应用级别的(通过白名单、配对码实现),而非操作系统级别的隔离。所有东西都在一个共享内存的 Node 进程中运行。
|
|
22
|
-
|
|
23
|
-
NanoClaw 用一个您能快速理解的代码库,为您提供了同样的核心功能。只有一个进程,少数几个文件。智能体(Agent)运行在具有文件系统隔离的真实 Linux 容器中,而不是依赖于权限检查。
|
|
24
|
-
|
|
25
|
-
## 快速开始
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
git clone https://github.com/qwibitai/nanoclaw.git
|
|
29
|
-
cd nanoclaw
|
|
30
|
-
claude
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
然后运行 `/setup`。Claude Code 会处理一切:依赖安装、身份验证、容器设置、服务配置。
|
|
34
|
-
|
|
35
|
-
> **注意:** 以 `/` 开头的命令(如 `/setup`、`/add-whatsapp`)是 [Claude Code 技能](https://code.claude.com/docs/en/skills)。请在 `claude` CLI 提示符中输入,而非在普通终端中。
|
|
36
|
-
|
|
37
|
-
## 设计哲学
|
|
38
|
-
|
|
39
|
-
**小巧易懂:** 单一进程,少量源文件。无微服务、无消息队列、无复杂抽象层。让 Claude Code 引导您轻松上手。
|
|
40
|
-
|
|
41
|
-
**通过隔离保障安全:** 智能体运行在 Linux 容器(在 macOS 上是 Apple Container,或 Docker)中。它们只能看到被明确挂载的内容。即便通过 Bash 访问也十分安全,因为所有命令都在容器内执行,不会直接操作您的宿主机。
|
|
42
|
-
|
|
43
|
-
**为单一用户打造:** 这不是一个框架,是一个完全符合您个人需求的、可工作的软件。您可以 Fork 本项目,然后让 Claude Code 根据您的精确需求进行修改和适配。
|
|
44
|
-
|
|
45
|
-
**定制即代码修改:** 没有繁杂的配置文件。想要不同的行为?直接修改代码。代码库足够小,这样做是安全的。
|
|
46
|
-
|
|
47
|
-
**AI 原生:** 无安装向导(由 Claude Code 指导安装)。无需监控仪表盘,直接询问 Claude 即可了解系统状况。无调试工具(描述问题,Claude 会修复它)。
|
|
48
|
-
|
|
49
|
-
**技能(Skills)优于功能(Features):** 贡献者不应该向代码库添加新功能(例如支持 Telegram)。相反,他们应该贡献像 `/add-telegram` 这样的 [Claude Code 技能](https://code.claude.com/docs/en/skills),这些技能可以改造您的 fork。最终,您得到的是只做您需要事情的整洁代码。
|
|
50
|
-
|
|
51
|
-
**最好的工具套件,最好的模型:** 本项目运行在 Claude Agent SDK 之上,这意味着您直接运行的就是 Claude Code。Claude Code 高度强大,其编码和问题解决能力使其能够修改和扩展 NanoClaw,为每个用户量身定制。
|
|
52
|
-
|
|
53
|
-
## 功能支持
|
|
54
|
-
|
|
55
|
-
- **多渠道消息** - 通过 WhatsApp、Telegram、Discord、Slack 或 Gmail 与您的助手对话。使用 `/add-whatsapp` 或 `/add-telegram` 等技能添加渠道,可同时运行一个或多个。
|
|
56
|
-
- **隔离的群组上下文** - 每个群组都拥有独立的 `CLAUDE.md` 记忆和隔离的文件系统。它们在各自的容器沙箱中运行,且仅挂载所需的文件系统。
|
|
57
|
-
- **主频道** - 您的私有频道(self-chat),用于管理控制;其他所有群组都完全隔离
|
|
58
|
-
- **计划任务** - 运行 Claude 的周期性作业,并可以给您回发消息
|
|
59
|
-
- **网络访问** - 搜索和抓取网页内容
|
|
60
|
-
- **容器隔离** - 智能体在 Apple Container (macOS) 或 Docker (macOS/Linux) 的沙箱中运行
|
|
61
|
-
- **智能体集群(Agent Swarms)** - 启动多个专业智能体团队,协作完成复杂任务(首个支持此功能的个人 AI 助手)
|
|
62
|
-
- **可选集成** - 通过技能添加 Gmail (`/add-gmail`) 等更多功能
|
|
63
|
-
|
|
64
|
-
## 使用方法
|
|
65
|
-
|
|
66
|
-
使用触发词(默认为 `@Andy`)与您的助手对话:
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
@Andy 每周一到周五早上9点,给我发一份销售渠道的概览(需要访问我的 Obsidian vault 文件夹)
|
|
70
|
-
@Andy 每周五回顾过去一周的 git 历史,如果与 README 有出入,就更新它
|
|
71
|
-
@Andy 每周一早上8点,从 Hacker News 和 TechCrunch 收集关于 AI 发展的资讯,然后发给我一份简报
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
在主频道(您的self-chat)中,可以管理群组和任务:
|
|
75
|
-
```
|
|
76
|
-
@Andy 列出所有群组的计划任务
|
|
77
|
-
@Andy 暂停周一简报任务
|
|
78
|
-
@Andy 加入"家庭聊天"群组
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## 定制
|
|
82
|
-
|
|
83
|
-
没有需要学习的配置文件。直接告诉 Claude Code 您想要什么:
|
|
84
|
-
|
|
85
|
-
- "把触发词改成 @Bob"
|
|
86
|
-
- "记住以后回答要更简短直接"
|
|
87
|
-
- "当我说早上好的时候,加一个自定义的问候"
|
|
88
|
-
- "每周存储一次对话摘要"
|
|
89
|
-
|
|
90
|
-
或者运行 `/customize` 进行引导式修改。
|
|
91
|
-
|
|
92
|
-
代码库足够小,Claude 可以安全地修改它。
|
|
93
|
-
|
|
94
|
-
## 贡献
|
|
95
|
-
|
|
96
|
-
**不要添加功能,而是添加技能。**
|
|
97
|
-
|
|
98
|
-
如果您想添加 Telegram 支持,不要创建一个 PR 同时添加 Telegram 和 WhatsApp。而是贡献一个技能文件 (`.claude/skills/add-telegram/SKILL.md`),教 Claude Code 如何改造一个 NanoClaw 安装以使用 Telegram。
|
|
99
|
-
|
|
100
|
-
然后用户在自己的 fork 上运行 `/add-telegram`,就能得到只做他们需要事情的整洁代码,而不是一个试图支持所有用例的臃肿系统。
|
|
101
|
-
|
|
102
|
-
### RFS (技能征集)
|
|
103
|
-
|
|
104
|
-
我们希望看到的技能:
|
|
105
|
-
|
|
106
|
-
**通信渠道**
|
|
107
|
-
- `/add-signal` - 添加 Signal 作为渠道
|
|
108
|
-
|
|
109
|
-
**会话管理**
|
|
110
|
-
- `/clear` - 添加一个 `/clear` 命令,用于压缩会话(在同一会话中总结上下文,同时保留关键信息)。这需要研究如何通过 Claude Agent SDK 以编程方式触发压缩。
|
|
111
|
-
|
|
112
|
-
## 系统要求
|
|
113
|
-
|
|
114
|
-
- macOS 或 Linux
|
|
115
|
-
- Node.js 20+
|
|
116
|
-
- [Claude Code](https://claude.ai/download)
|
|
117
|
-
- [Apple Container](https://github.com/apple/container) (macOS) 或 [Docker](https://docker.com/products/docker-desktop) (macOS/Linux)
|
|
118
|
-
|
|
119
|
-
## 架构
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
渠道 --> SQLite --> 轮询循环 --> 容器 (Claude Agent SDK) --> 响应
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
单一 Node.js 进程。渠道通过技能添加,启动时自注册 — 编排器连接具有凭据的渠道。智能体在具有文件系统隔离的 Linux 容器中执行。每个群组的消息队列带有并发控制。通过文件系统进行 IPC。
|
|
126
|
-
|
|
127
|
-
完整架构详情请见 [docs/SPEC.md](docs/SPEC.md)。
|
|
128
|
-
|
|
129
|
-
关键文件:
|
|
130
|
-
- `src/index.ts` - 编排器:状态管理、消息循环、智能体调用
|
|
131
|
-
- `src/channels/registry.ts` - 渠道注册表(启动时自注册)
|
|
132
|
-
- `src/ipc.ts` - IPC 监听与任务处理
|
|
133
|
-
- `src/router.ts` - 消息格式化与出站路由
|
|
134
|
-
- `src/group-queue.ts` - 带全局并发限制的群组队列
|
|
135
|
-
- `src/container-runner.ts` - 生成流式智能体容器
|
|
136
|
-
- `src/task-scheduler.ts` - 运行计划任务
|
|
137
|
-
- `src/db.ts` - SQLite 操作(消息、群组、会话、状态)
|
|
138
|
-
- `groups/*/CLAUDE.md` - 各群组的记忆
|
|
139
|
-
|
|
140
|
-
## FAQ
|
|
141
|
-
|
|
142
|
-
**为什么是 Docker?**
|
|
143
|
-
|
|
144
|
-
Docker 提供跨平台支持(macOS 和 Linux)和成熟的生态系统。在 macOS 上,您可以选择通过运行 `/convert-to-apple-container` 切换到 Apple Container,以获得更轻量级的原生运行时体验。
|
|
145
|
-
|
|
146
|
-
**我可以在 Linux 上运行吗?**
|
|
147
|
-
|
|
148
|
-
可以。Docker 是默认的容器运行时,在 macOS 和 Linux 上都可以使用。只需运行 `/setup`。
|
|
149
|
-
|
|
150
|
-
**这个项目安全吗?**
|
|
151
|
-
|
|
152
|
-
智能体在容器中运行,而不是在应用级别的权限检查之后。它们只能访问被明确挂载的目录。您仍然应该审查您运行的代码,但这个代码库小到您真的可以做到。完整的安全模型请见 [docs/SECURITY.md](docs/SECURITY.md)。
|
|
153
|
-
|
|
154
|
-
**为什么没有配置文件?**
|
|
155
|
-
|
|
156
|
-
我们不希望配置泛滥。每个用户都应该定制它,让代码完全符合他们的需求,而不是去配置一个通用的系统。如果您喜欢用配置文件,告诉 Claude 让它加上。
|
|
157
|
-
|
|
158
|
-
**我可以使用第三方或开源模型吗?**
|
|
159
|
-
|
|
160
|
-
可以。NanoClaw 支持任何 API 兼容的模型端点。在 `.env` 文件中设置以下环境变量:
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
ANTHROPIC_BASE_URL=https://your-api-endpoint.com
|
|
164
|
-
ANTHROPIC_AUTH_TOKEN=your-token-here
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
这使您能够使用:
|
|
168
|
-
- 通过 [Ollama](https://ollama.ai) 配合 API 代理运行的本地模型
|
|
169
|
-
- 托管在 [Together AI](https://together.ai)、[Fireworks](https://fireworks.ai) 等平台上的开源模型
|
|
170
|
-
- 兼容 Anthropic API 格式的自定义模型部署
|
|
171
|
-
|
|
172
|
-
注意:为获得最佳兼容性,模型需支持 Anthropic API 格式。
|
|
173
|
-
|
|
174
|
-
**我该如何调试问题?**
|
|
175
|
-
|
|
176
|
-
问 Claude Code。"为什么计划任务没有运行?" "最近的日志里有什么?" "为什么这条消息没有得到回应?" 这就是 AI 原生的方法。
|
|
177
|
-
|
|
178
|
-
**为什么我的安装不成功?**
|
|
179
|
-
|
|
180
|
-
如果遇到问题,安装过程中 Claude 会尝试动态修复。如果问题仍然存在,运行 `claude`,然后运行 `/debug`。如果 Claude 发现一个可能影响其他用户的问题,请开一个 PR 来修改 setup SKILL.md。
|
|
181
|
-
|
|
182
|
-
**什么样的代码更改会被接受?**
|
|
183
|
-
|
|
184
|
-
安全修复、bug 修复,以及对基础配置的明确改进。仅此而已。
|
|
185
|
-
|
|
186
|
-
其他一切(新功能、操作系统兼容性、硬件支持、增强功能)都应该作为技能来贡献。
|
|
187
|
-
|
|
188
|
-
这使得基础系统保持最小化,并让每个用户可以定制他们的安装,而无需继承他们不想要的功能。
|
|
189
|
-
|
|
190
|
-
## 社区
|
|
191
|
-
|
|
192
|
-
有任何疑问或建议?欢迎[加入 Discord 社区](https://discord.gg/VDdww8qS42)与我们交流。
|
|
193
|
-
|
|
194
|
-
## 更新日志
|
|
195
|
-
|
|
196
|
-
破坏性变更和迁移说明请见 [CHANGELOG.md](CHANGELOG.md)。
|
|
197
|
-
|
|
198
|
-
## 许可证
|
|
199
|
-
|
|
200
|
-
MIT
|
|
Binary file
|
package/assets/nanoclaw-icon.png
DELETED
|
Binary file
|
|
Binary file
|
package/assets/nanoclaw-logo.png
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"allowedRoots": [
|
|
3
|
-
{
|
|
4
|
-
"path": "~/projects",
|
|
5
|
-
"allowReadWrite": true,
|
|
6
|
-
"description": "Development projects"
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"path": "~/repos",
|
|
10
|
-
"allowReadWrite": true,
|
|
11
|
-
"description": "Git repositories"
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"path": "~/Documents/work",
|
|
15
|
-
"allowReadWrite": false,
|
|
16
|
-
"description": "Work documents (read-only)"
|
|
17
|
-
}
|
|
18
|
-
],
|
|
19
|
-
"blockedPatterns": [
|
|
20
|
-
"password",
|
|
21
|
-
"secret",
|
|
22
|
-
"token"
|
|
23
|
-
],
|
|
24
|
-
"nonMainReadOnly": true
|
|
25
|
-
}
|