pelulu-cli 1.0.5 → 1.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,81 @@
1
+ # Changelog
2
+
3
+ All notable changes to **Pelulu CLI** will be documented in this file.
4
+
5
+ ## [1.1.0] - 2026-07-21
6
+
7
+ ### Fixed
8
+ - **MQTT disconnect loop** — `tools/list` response exceeded 8KB broker limit, now optimized to ~4KB
9
+ - **Agent sends prompt before session ready** — `LLMClient` now waits for MCP handshake + session before sending
10
+ - **Double tool execution** — agent loop no longer re-executes tools already handled by MQTT client
11
+ - **Prompt sent multiple times** — agent loop now sends prompt only once per run
12
+ - **AI responses not in log file** — added `llm:text` and `tts:sentence` event logging
13
+ - **Log files accumulate** — old logs deleted on startup, only latest kept
14
+ - **y/N confirmation prompt flashing** — agent tool calls auto-approved (no more UI glitches)
15
+ - **Version mismatch** — version now read from `package.json` (auto-sync)
16
+
17
+ ### Changed
18
+ - **Statusbar redesigned** — clean minimal layout: `🐱 PELULU ● online session:xxx xiaozhi.me`
19
+ - **Tool schema optimization** — `action` enum preserved, first 4 properties sent (under 8KB)
20
+ - **System prompt added to hello message** — tells XiaoZhi to use tools instead of just chatting
21
+
22
+ ## [1.0.5] - 2026-07-20
23
+
24
+ ### Added
25
+ - File logging (`logs/` directory)
26
+ - Char counter on TUI input (70 char limit)
27
+ - Scrollable chat (Shift+Up/Down, PgUp/PgDn)
28
+
29
+ ### Fixed
30
+ - Chat limited to 12 visible lines
31
+ - Progress feedback and timeout handling in agent loop
32
+
33
+ ## [1.0.4] - 2026-07-19
34
+
35
+ ### Changed
36
+ - Update checker uses npm registry instead of GitHub releases
37
+
38
+ ### Fixed
39
+ - Activation code displays directly to console
40
+
41
+ ## [1.0.3] - 2026-07-19
42
+
43
+ ### Fixed
44
+ - Duplicate user messages (Enter key fired onSubmit twice)
45
+ - TTS responses handled as assistant messages
46
+
47
+ ## [1.0.2] - 2026-07-18
48
+
49
+ ### Added
50
+ - Cute ASCII cat banner above CLI header
51
+ - Block CLI when update is available
52
+
53
+ ### Fixed
54
+ - Redirect ALL startup logs into Ink TUI
55
+ - Clean status bar header format
56
+
57
+ ## [1.0.1] - 2026-07-17
58
+
59
+ ### Added
60
+ - OpenHands-style agent system (AgentLoop, AgentController, LLMClient)
61
+ - Auto-completion with Tab key
62
+ - Auto-format for written files
63
+
64
+ ### Changed
65
+ - Replaced readline with Ink React TUI
66
+
67
+ ### Fixed
68
+ - Compact banner text
69
+ - TTY fallback for non-interactive mode
70
+ - Log status as single-line auto-updating text
71
+
72
+ ## [1.0.0] - 2026-07-16
73
+
74
+ ### Added
75
+ - Initial release
76
+ - XiaoZhi AI integration via MQTT
77
+ - MCP tool protocol support
78
+ - 18 built-in tools (file, shell, git, project, network, etc.)
79
+ - Interactive REPL with syntax highlighting
80
+ - Plugin system
81
+ - Workspace detection and context building
package/docs/AGENT.md ADDED
@@ -0,0 +1,237 @@
1
+ # Pelulu-CLI Agent System
2
+
3
+ Pelulu-CLI now includes an OpenHands-style agent system that provides autonomous coding capabilities.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ ┌─────────────────────────────────────────────────────────────┐
9
+ │ Agent Controller │
10
+ │ Orchestrates all agent components │
11
+ └──────────────────────────┬──────────────────────────────────┘
12
+
13
+ ┌─────────────────┼─────────────────┐
14
+ │ │ │
15
+ ▼ ▼ ▼
16
+ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐
17
+ │ Agent Loop │ │ Plan Manager │ │ LLM Client │
18
+ │ (observe→ │ │ (task │ │ (XiaoZhi AI │
19
+ │ think→act)│ │ decomposition│ │ via MQTT) │
20
+ └──────┬──────┘ └──────────────┘ └──────────────┘
21
+
22
+
23
+ ┌─────────────────────────────────────────────────────────────┐
24
+ │ Tool System │
25
+ │ file, shell, git, search, agent, ai, ... │
26
+ └─────────────────────────────────────────────────────────────┘
27
+ ```
28
+
29
+ ## Components
30
+
31
+ ### 1. Agent Loop (`agent-loop.js`)
32
+ The core observe→think→act cycle:
33
+ - **Observe**: Builds context from history, workspace, and plan
34
+ - **Think**: Sends context to LLM for reasoning
35
+ - **Act**: Executes tool calls returned by LLM
36
+ - **Loop**: Repeats until "finish" is called or max iterations reached
37
+
38
+ ### 2. Plan Manager (`plan-manager.js`)
39
+ Task decomposition and tracking:
40
+ - Auto-generates plans for complex tasks
41
+ - Tracks step progress (pending → in_progress → completed/failed)
42
+ - Supports dynamic plan modification during execution
43
+ - Provides visual progress indicators
44
+
45
+ ### 3. LLM Client (`llm-client.js`)
46
+ Wraps XiaoZhi AI into a standard interface:
47
+ - MQTT-based communication
48
+ - Tool call parsing from text responses
49
+ - Token usage tracking
50
+ - Request timeout and abort support
51
+
52
+ ### 4. Context Builder (`context-builder.js`)
53
+ Builds rich workspace context:
54
+ - Git status and history
55
+ - Project type detection
56
+ - File structure analysis
57
+ - Runtime environment info
58
+ - Cached for performance
59
+
60
+ ### 5. History Condenser (`history-condenser.js`)
61
+ Manages long conversations:
62
+ - Automatic condensation when history is too long
63
+ - Preserves important context (files modified, errors)
64
+ - Optional LLM-based summarization
65
+ - Token-aware windowing
66
+
67
+ ### 6. System Prompt (`system-prompt.js`)
68
+ Builds comprehensive prompts:
69
+ - Agent identity and capabilities
70
+ - Tool descriptions with schemas
71
+ - Workspace context
72
+ - Microagents/skills (trigger-based)
73
+ - Plan status
74
+ - Guidelines and constraints
75
+
76
+ ## Usage
77
+
78
+ ### Basic Usage
79
+ The agent system is automatically initialized when you start Pelulu-CLI:
80
+
81
+ ```bash
82
+ pelulu
83
+ ```
84
+
85
+ Then simply describe your task:
86
+ ```
87
+ > Fix the bug in auth.js where login fails with special characters
88
+ ```
89
+
90
+ ### Disable Agent Mode
91
+ If you want to use the legacy direct tool call mode:
92
+
93
+ ```bash
94
+ pelulu --no-agent
95
+ ```
96
+
97
+ ### Debug Mode
98
+ Enable debug logging:
99
+
100
+ ```bash
101
+ pelulu --debug
102
+ ```
103
+
104
+ ## Agent Tool
105
+
106
+ The agent system is exposed as a tool that can be called directly:
107
+
108
+ ```json
109
+ {
110
+ "tool": "agent",
111
+ "action": "run",
112
+ "task": "Implement user authentication with JWT"
113
+ }
114
+ ```
115
+
116
+ ### Actions
117
+
118
+ | Action | Description |
119
+ |--------|-------------|
120
+ | `run` | Execute a task with the agent loop |
121
+ | `plan` | Create, view, or manage plans |
122
+ | `status` | Get agent status and summary |
123
+ | `abort` | Abort the current run |
124
+ | `reset` | Reset agent state |
125
+ | `history` | Get conversation history |
126
+ | `context` | Get workspace context |
127
+
128
+ ## Plan Management
129
+
130
+ ### Auto-Planning
131
+ Complex tasks automatically get plans:
132
+ ```
133
+ > Implement a REST API with user authentication, CRUD operations, and tests
134
+
135
+ 📋 Plan: Implement REST API
136
+ ────────────────────────────
137
+ 🔄 1. Set up Express project structure
138
+ ⬜ 2. Create User model with Mongoose
139
+ ⬜ 3. Implement authentication middleware
140
+ ⬜ 4. Create CRUD routes for users
141
+ ⬜ 5. Add input validation
142
+ ⬜ 6. Write unit tests
143
+ ⬜ 7. Test the API
144
+ ────────────────────────────
145
+ Progress: 14%
146
+ ```
147
+
148
+ ### Manual Planning
149
+ Create plans explicitly:
150
+ ```json
151
+ {
152
+ "tool": "agent",
153
+ "action": "plan",
154
+ "goal": "Refactor auth module",
155
+ "steps": [
156
+ { "description": "Extract auth logic to separate file" },
157
+ { "description": "Add JWT support" },
158
+ { "description": "Update tests" }
159
+ ]
160
+ }
161
+ ```
162
+
163
+ ## Skills/Microagents
164
+
165
+ Pelulu-CLI loads skills from:
166
+ - `.pelulu/skills/*.md`
167
+ - `.openhands/microagents/*.md`
168
+ - `.agents/skills/*.md`
169
+
170
+ ### Skill File Format
171
+ ```markdown
172
+ ---
173
+ triggers:
174
+ - authentication
175
+ - jwt
176
+ - login
177
+ ---
178
+ # Authentication Best Practices
179
+
180
+ When implementing authentication:
181
+ 1. Always hash passwords with bcrypt
182
+ 2. Use JWT with short expiration
183
+ 3. Implement refresh tokens
184
+ 4. Add rate limiting to login endpoints
185
+ ```
186
+
187
+ Skills with triggers are only loaded when the user's message matches the trigger keywords.
188
+
189
+ ## Configuration
190
+
191
+ Add to your `pelulu.config.json`:
192
+
193
+ ```json
194
+ {
195
+ "agent": {
196
+ "name": "Pelulu",
197
+ "max_iterations": 100,
198
+ "max_history": 50,
199
+ "auto_plan": true,
200
+ "max_tokens": 100000
201
+ }
202
+ }
203
+ ```
204
+
205
+ | Option | Default | Description |
206
+ |--------|---------|-------------|
207
+ | `max_iterations` | 100 | Maximum agent loop iterations |
208
+ | `max_history` | 50 | Maximum messages before condensation |
209
+ | `auto_plan` | true | Auto-generate plans for complex tasks |
210
+ | `max_tokens` | 100000 | Token limit for history |
211
+
212
+ ## Differences from OpenHands
213
+
214
+ | Feature | OpenHands | Pelulu-CLI |
215
+ |---------|-----------|------------|
216
+ | LLM | OpenAI/Anthropic/etc | XiaoZhi AI (MQTT) |
217
+ | Runtime | Docker sandbox | Local execution |
218
+ | UI | Web React | Terminal Ink |
219
+ | Planning | Optional | Auto for complex tasks |
220
+ | Skills | Global + repo | Local files |
221
+ | Multi-agent | Yes | Single agent |
222
+
223
+ ## Troubleshooting
224
+
225
+ ### Agent not responding
226
+ 1. Check MQTT connection: `pelulu --debug`
227
+ 2. Verify XiaoZhi is activated
228
+ 3. Check network connectivity
229
+
230
+ ### Plan not generating
231
+ - Ensure `auto_plan: true` in config
232
+ - Task must be complex enough (50+ chars, contain action words)
233
+
234
+ ### History too long
235
+ - The agent auto-condenses history
236
+ - Use `agent.history` with `condensed: true`
237
+ - Adjust `max_history` in config
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "pelulu-cli",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "CLI coding agent powered by XiaoZhi AI — a tiny Chinese LLM that lives in ESP32 chips",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
7
7
  "bin": {
8
- "pelulu": "src/index.js"
8
+ "pelulu-cli": "src/index.js"
9
9
  },
10
10
  "scripts": {
11
11
  "start": "node src/index.js",
12
12
  "start:debug": "node src/index.js --debug",
13
13
  "start:fallback": "node src/index.js --no-ink",
14
+ "start:no-agent": "node src/index.js --no-agent",
14
15
  "tools": "node src/index.js --list-tools",
15
16
  "test": "node src/index.js --test"
16
17
  },
@@ -0,0 +1,46 @@
1
+ # XiaoZhi MQTT Broker Specifications
2
+
3
+ ## MCP Tools/List Response Size Limit
4
+
5
+ - **Limit:** ~8KB (8,192 bytes estimated)
6
+ - **Behavior:** Broker disconnects client immediately after receiving `tools/list` response that exceeds the limit
7
+ - **Tested:**
8
+ - 15,423 bytes → ❌ Disconnected
9
+ - 10,344 bytes → ❌ Disconnected
10
+ - 9,104 bytes → ❌ Disconnected
11
+ - 8,894 bytes → ❌ Disconnected
12
+ - 8,079 bytes → ✅ Connected
13
+ - 7,656 bytes → ✅ Connected
14
+ - 7,928 bytes → ✅ Connected (Pelulu-CLI baseline)
15
+
16
+ ## Content Filtering
17
+
18
+ - **No content filtering detected.** Tool names like `bruteforce`, `exploit`, `sqli`, `injection`, `fuzzer`, `evasion`, `vuln` are accepted as long as response is under 8KB.
19
+
20
+ ## Optimization Techniques (to stay under 8KB)
21
+
22
+ 1. Remove `description` from inputSchema properties
23
+ 2. Remove `action` enum values (keep as plain `{ type: "string" }`)
24
+ 3. Trim tool descriptions to essential keywords only
25
+
26
+ ## MQTT Connection
27
+
28
+ - **Endpoint:** `mqtt.xiaozhi.me:8883` (MQTTS)
29
+ - **Keepalive:** 60s recommended (240s may cause issues)
30
+ - **Protocol:** MQTT v3.1.1 (v5 rejected)
31
+ - **Subscribe topic:** `devices/p2p/#`
32
+ - **Publish topic:** `device-server` (from OTA response)
33
+ - **subscribe_topic from OTA:** Always `"null"` (string, not null)
34
+
35
+ ## Device Activation
36
+
37
+ - **OTA URL:** `https://api.tenclass.net/xiaozhi/ota/`
38
+ - **Activation URL:** `https://xiaozhi.me`
39
+ - **Device name:** Set in `board.name` field of OTA request
40
+ - **Credentials:** Fresh credentials from OTA for each connection (do not cache/reuse)
41
+
42
+ ## Tool Execution Notes
43
+
44
+ - **Port scanning:** Use `nc -z -w1` (netcat) instead of `bash /dev/tcp` for reliable scanning
45
+ - **Timeout:** 15 default ports × 1s timeout = ~15-20s total (within 30s tool timeout)
46
+ - **Shell escaping:** Use semicolons (`;`) not newlines when passing multi-command scripts to `bash -c` via `JSON.stringify`
@@ -0,0 +1,100 @@
1
+ /**
2
+ * AgentController — Orchestrates the agent system
3
+ */
4
+ import { AgentLoop } from './agent-loop.js';
5
+ import { LLMClient } from './llm-client.js';
6
+ import { ContextBuilder } from './context-builder.js';
7
+ import { bus } from '../core/event-bus.js';
8
+ import { debug } from '../core/logger.js';
9
+
10
+ export class AgentController {
11
+ #loop;
12
+ #llm;
13
+ #contextBuilder;
14
+ #registry;
15
+ #sandbox;
16
+ #confirm;
17
+ #config;
18
+ #running = false;
19
+
20
+ constructor({ registry, mqtt, sandbox, confirm, config }) {
21
+ this.#registry = registry;
22
+ this.#sandbox = sandbox;
23
+ this.#confirm = confirm;
24
+ this.#config = config;
25
+ this.#loop = new AgentLoop({ maxIterations: config.agent?.max_iterations || 50 });
26
+ this.#llm = new LLMClient(mqtt);
27
+ this.#contextBuilder = new ContextBuilder();
28
+ }
29
+
30
+ get isRunning() { return this.#running; }
31
+
32
+ get summary() {
33
+ return {
34
+ state: this.#loop.state,
35
+ iteration: this.#loop.iteration,
36
+ history: this.#loop.history.length,
37
+ running: this.#running,
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Run agent for a user prompt
43
+ */
44
+ async run(userPrompt, options = {}) {
45
+ // Validate input length
46
+ const MAX_LEN = 70;
47
+ if (userPrompt.length > MAX_LEN) {
48
+ throw new Error(`Input too long (${userPrompt.length}/${MAX_LEN} chars)`);
49
+ }
50
+
51
+ if (this.#running) {
52
+ this.abort();
53
+ await new Promise(r => setTimeout(r, 300));
54
+ }
55
+
56
+ this.#running = true;
57
+ const start = Date.now();
58
+
59
+ try {
60
+ debug('agent', `Running: ${userPrompt}`);
61
+
62
+ const result = await this.#loop.run(userPrompt, {
63
+ llm: this.#llm,
64
+ tools: this.#registry,
65
+ sandbox: this.#sandbox,
66
+ confirm: this.#confirm,
67
+ });
68
+
69
+ result.duration = Date.now() - start;
70
+ debug('agent', `Done in ${result.duration}ms: ${result.success}`);
71
+ return result;
72
+
73
+ } finally {
74
+ this.#running = false;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Abort current run
80
+ */
81
+ abort() {
82
+ this.#loop.abort();
83
+ this.#running = false;
84
+ debug('agent', 'Aborted');
85
+ }
86
+
87
+ /**
88
+ * Get workspace context
89
+ */
90
+ async getContext() {
91
+ return this.#contextBuilder.build();
92
+ }
93
+
94
+ /**
95
+ * Reset agent state
96
+ */
97
+ reset() {
98
+ this.#running = false;
99
+ }
100
+ }