@hienlh/ppm 0.9.52 → 0.9.54
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 +24 -0
- package/dist/web/assets/{chat-tab-DvNEQYEe.js → chat-tab-C7LUU8uc.js} +1 -1
- package/dist/web/assets/{code-editor-CoT017Ah.js → code-editor-D8qEQfSv.js} +1 -1
- package/dist/web/assets/{database-viewer-C3wK7cDk.js → database-viewer-Duryc3Y0.js} +1 -1
- package/dist/web/assets/{diff-viewer-D0tuen4I.js → diff-viewer-UGOYufsF.js} +1 -1
- package/dist/web/assets/{extension-webview-Ba5aeo9r.js → extension-webview-fljR76zl.js} +1 -1
- package/dist/web/assets/{git-graph-BnJrVPxJ.js → git-graph-Ccyey8cC.js} +1 -1
- package/dist/web/assets/{index-DUQgLj0D.js → index-CgvhdpCl.js} +4 -4
- package/dist/web/assets/{index-BEfMoc_W.css → index-DVuSY0BZ.css} +1 -1
- package/dist/web/assets/keybindings-store-CGXc_Nqv.js +1 -0
- package/dist/web/assets/{markdown-renderer-BuGSrE3y.js → markdown-renderer-Fm0AKs27.js} +1 -1
- package/dist/web/assets/{port-forwarding-tab-DsbrWNUP.js → port-forwarding-tab-9XP7jh5d.js} +1 -1
- package/dist/web/assets/{postgres-viewer-Bh6YmZPq.js → postgres-viewer-BU2c67YN.js} +1 -1
- package/dist/web/assets/{settings-tab-BnzFtexC.js → settings-tab-kSrv-eTK.js} +1 -1
- package/dist/web/assets/sqlite-viewer-Ctlu51c-.js +1 -0
- package/dist/web/assets/{terminal-tab-fnZvscaH.js → terminal-tab-Cx6Wl0GQ.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-BdcKAZ69.js → use-monaco-theme-DQ-JnmSE.js} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/docs/codebase-summary.md +52 -13
- package/docs/project-changelog.md +75 -1
- package/docs/project-roadmap.md +8 -7
- package/docs/system-architecture.md +193 -13
- package/package.json +1 -1
- package/src/cli/commands/bot-cmd.ts +144 -240
- package/src/cli/commands/restart.ts +29 -0
- package/src/cli/commands/stop.ts +67 -6
- package/src/index.ts +10 -1
- package/src/server/index.ts +131 -19
- package/src/server/routes/database.ts +31 -0
- package/src/server/routes/settings.ts +13 -0
- package/src/server/routes/sqlite.ts +14 -0
- package/src/services/autostart-generator.ts +8 -6
- package/src/services/database/postgres-adapter.ts +8 -0
- package/src/services/database/sqlite-adapter.ts +5 -0
- package/src/services/db.service.ts +109 -1
- package/src/services/postgres.service.ts +12 -0
- package/src/services/ppmbot/ppmbot-delegation.ts +112 -0
- package/src/services/ppmbot/ppmbot-service.ts +194 -369
- package/src/services/ppmbot/ppmbot-session.ts +85 -108
- package/src/services/ppmbot/ppmbot-telegram.ts +5 -16
- package/src/services/sqlite.service.ts +10 -0
- package/src/services/supervisor-state.ts +100 -0
- package/src/services/supervisor-stopped-page.ts +73 -0
- package/src/services/supervisor.ts +144 -50
- package/src/types/config.ts +1 -3
- package/src/types/database.ts +3 -0
- package/src/types/ppmbot.ts +21 -0
- package/src/web/components/settings/ppmbot-settings-section.tsx +87 -26
- package/src/web/components/sqlite/sqlite-data-grid.tsx +55 -8
- package/src/web/components/sqlite/sqlite-viewer.tsx +1 -0
- package/src/web/components/sqlite/use-sqlite.ts +16 -1
- package/dist/web/assets/keybindings-store-CkGFjxkX.js +0 -1
- package/dist/web/assets/sqlite-viewer-Cu3_hf07.js +0 -1
- package/docs/streaming-input-guide.md +0 -267
- package/snapshot-state.md +0 -1526
- package/test-session-ops.mjs +0 -444
- package/test-tokens.mjs +0 -212
|
@@ -193,14 +193,21 @@ Tab IDs are deterministic: `{type}:{identifier}` (e.g., `editor:src/index.ts`, `
|
|
|
193
193
|
| **AccountService** | Account CRUD, token encryption/decryption | getAccounts, createAccount, updateAccount, deleteAccount |
|
|
194
194
|
| **AccountSelectorService** | Select active account based on config | getActiveAccount, setActiveAccount, selectByProject |
|
|
195
195
|
| **UpgradeService** | Version checking, installation, self-replace signaling | checkForUpdate, applyUpgrade, getInstallMethod, compareSemver |
|
|
196
|
-
| **
|
|
197
|
-
| **
|
|
198
|
-
| **
|
|
199
|
-
| **
|
|
200
|
-
| **
|
|
201
|
-
| **
|
|
202
|
-
|
|
203
|
-
**
|
|
196
|
+
| **PPMBotService** | Coordinator orchestrator (team leader, delegation mgmt) | start, stop, handleUpdate, checkPendingTasks |
|
|
197
|
+
| **PPMBotSessionManager** | Coordinator session per chat, project resolver | getCoordinatorSession, rotateCoordinatorSession, resolveProject |
|
|
198
|
+
| **PPMBotTelegramService** | Telegram long-polling, message ops | getUpdates, sendMessage, editMessage, setTyping, handleCommands |
|
|
199
|
+
| **PPMBotMemoryService** | SQLite project memory persistence | saveMemory, recallMemories, searchByProject |
|
|
200
|
+
| **executeDelegation()** | Task execution in isolated session, result capture | (async function, manages ChatService + result storage) |
|
|
201
|
+
| **PPMBotFormatterService** | Markdown → Telegram HTML + chunking | formatMarkdown, chunkMessage |
|
|
202
|
+
| **PPMBotStreamerService** | ChatEvent → progressive Telegram edits | streamMessageEdits |
|
|
203
|
+
| **ClawBotService** | LEGACY Telegram bot (deprecated v0.9.11) | (direct-chat model, replaced by coordinator) |
|
|
204
|
+
| **ClawBotTelegramService** | LEGACY Telegram API | (deprecated v0.9.11) |
|
|
205
|
+
| **ClawBotSessionService** | LEGACY chatID mapping | (deprecated v0.9.11) |
|
|
206
|
+
| **ClawBotMemoryService** | LEGACY FTS5 memory | (deprecated v0.9.11) |
|
|
207
|
+
| **ClawBotFormatterService** | LEGACY formatter | (deprecated v0.9.11) |
|
|
208
|
+
| **ClawBotStreamerService** | LEGACY streamer | (deprecated v0.9.11) |
|
|
209
|
+
|
|
210
|
+
**Key Files:** `src/services/*.service.ts`, `src/services/ppmbot/*.ts`, `src/cli/commands/bot-cmd.ts`
|
|
204
211
|
|
|
205
212
|
---
|
|
206
213
|
|
|
@@ -269,7 +276,112 @@ PPM supports multiple AI providers through a generic `AIProvider` interface and
|
|
|
269
276
|
|
|
270
277
|
---
|
|
271
278
|
|
|
272
|
-
###
|
|
279
|
+
### PPMBot Coordinator Service Layer (Telegram-based Team Leader)
|
|
280
|
+
**Component:** PPMBot coordinator orchestrator + delegation executor
|
|
281
|
+
|
|
282
|
+
**Responsibilities:**
|
|
283
|
+
- Manage single persistent coordinator session per Telegram chat in `~/.ppm/bot/` workspace
|
|
284
|
+
- Route incoming Telegram messages to coordinator (ask/answer) or delegation tracking
|
|
285
|
+
- Decide when to answer directly vs. delegate to subagents (based on project context)
|
|
286
|
+
- Execute delegated tasks in isolated project sessions
|
|
287
|
+
- Track task status and report results back to Telegram
|
|
288
|
+
- Format responses as Telegram HTML with progressive message editing
|
|
289
|
+
|
|
290
|
+
**Architecture:**
|
|
291
|
+
```
|
|
292
|
+
Telegram → PPMBotTelegramService (polling) → PPMBotService (orchestrator)
|
|
293
|
+
↓
|
|
294
|
+
PPMBotSessionManager (coordinator session per chat)
|
|
295
|
+
coordinatorSession.id → chatService.sendMessage()
|
|
296
|
+
Task Poller (5s interval)
|
|
297
|
+
↓
|
|
298
|
+
executeDelegation(taskId, telegram, providerId)
|
|
299
|
+
├─ getBotTask(taskId) → prompt
|
|
300
|
+
├─ chatService.createSession(providerId, projectPath)
|
|
301
|
+
├─ run async generator (abort, 900s timeout)
|
|
302
|
+
└─ updateBotTaskStatus(taskId, "completed", {result})
|
|
303
|
+
↓
|
|
304
|
+
telegram.sendMessage(chatId, result summary)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Services (src/services/ppmbot/):**
|
|
308
|
+
- **PPMBotService** — Lifecycle (start/stop), message queue, Telegram polling loop, task poller loop
|
|
309
|
+
- **PPMBotSessionManager** — Coordinator session cache per chatID, project resolver (case-insensitive, prefix match)
|
|
310
|
+
- **PPMBotTelegramService** — Telegram Bot API (getUpdates polling, sendMessage, editMessage, setTyping)
|
|
311
|
+
- **PPMBotMemoryService** — SQLite project memories, contextual recall
|
|
312
|
+
- **executeDelegation()** — Task execution in isolated session, result capture, timeout/abort handling
|
|
313
|
+
- **PPMBotFormatterService** — Markdown → Telegram HTML, 4096-char chunking
|
|
314
|
+
- **PPMBotStreamerService** — ChatEvent → progressive Telegram message edits (1s throttle)
|
|
315
|
+
|
|
316
|
+
**Coordinator Identity (Persistent Cross-Provider):**
|
|
317
|
+
- Location: `~/.ppm/bot/coordinator.md` (loaded on startup, cached in `coordinatorIdentity`)
|
|
318
|
+
- Role definition: Team leader, project coordinator, decision-maker
|
|
319
|
+
- Decision framework: Answer directly (no project context) vs. Delegate (file access needed)
|
|
320
|
+
- Coordination tools: Bash-safe CLI commands (`ppm bot delegate`, `ppm bot task-status`, etc.)
|
|
321
|
+
- Cross-provider: Identity text injected as XML context block, works with Claude SDK + CLI providers
|
|
322
|
+
|
|
323
|
+
**Delegation Flow:**
|
|
324
|
+
1. User asks task in Telegram
|
|
325
|
+
2. Coordinator decides: delegate? → yes
|
|
326
|
+
3. Coordinator calls bash: `ppm bot delegate --chat <chatId> --project <name> --prompt "<enriched>"`
|
|
327
|
+
4. CLI creates `bot_tasks` row, returns taskId
|
|
328
|
+
5. Service tells user: "Working on it, I'll notify you when done"
|
|
329
|
+
6. Background poller (5s) detects pending task
|
|
330
|
+
7. Executes: `chatService.createSession()` in target project
|
|
331
|
+
8. Streams response, captures summary + full output
|
|
332
|
+
9. Updates task status → "completed"
|
|
333
|
+
10. Sends Telegram notification with result
|
|
334
|
+
|
|
335
|
+
**Task Execution (Isolation & Safety):**
|
|
336
|
+
- Each task = fresh isolated session (no shared context)
|
|
337
|
+
- Timeout: 900s default (configurable per task)
|
|
338
|
+
- Abort: AbortController on timeout, can be canceled mid-execution
|
|
339
|
+
- Result capture: Both summary (for notification) and full text (for detailed review)
|
|
340
|
+
- Error handling: Task status → "failed", error message stored, user notified
|
|
341
|
+
|
|
342
|
+
**Database Schema (v14):**
|
|
343
|
+
- `bot_tasks` — id (UUID), chatId, projectName, projectPath, prompt, status, resultSummary, resultFull, sessionId, error, reported, timeoutMs, createdAt, startedAt, completedAt
|
|
344
|
+
- Indexes: `idx_bot_tasks_status` (fast poller lookup), `idx_bot_tasks_chat` (history queries)
|
|
345
|
+
|
|
346
|
+
**Key Design Decisions:**
|
|
347
|
+
1. **Single coordinator session** — Per chat, persistent, one identity (vs. per-task sessions in ClawBot)
|
|
348
|
+
2. **Delegation via CLI** — Coordinator calls bash commands (safer than direct DB writes, auditable)
|
|
349
|
+
3. **Isolated task execution** — Each delegated task spawns fresh session (no context bleed)
|
|
350
|
+
4. **Background polling** — Task execution decoupled from message handler (non-blocking)
|
|
351
|
+
5. **Result summary + full** — Notification shows short summary; user can fetch full output via CLI
|
|
352
|
+
6. **Cross-provider identity** — Single `coordinator.md` works with any AI provider
|
|
353
|
+
7. **Bash-safe tools only** — Coordinator restricted to Bash, Read, Write, Edit, Glob, Grep (safe delegation)
|
|
354
|
+
|
|
355
|
+
**CLI Expansion (ppm bot commands):**
|
|
356
|
+
```
|
|
357
|
+
ppm bot delegate --chat <id> --project <name> --prompt "<text>" # Create task
|
|
358
|
+
ppm bot task-status <id> # Check status
|
|
359
|
+
ppm bot task-result <id> # Get full output
|
|
360
|
+
ppm bot tasks [--chat <id>] # List recent
|
|
361
|
+
ppm bot project list # Available projects
|
|
362
|
+
ppm bot project current # Active project
|
|
363
|
+
ppm bot project switch <name> # Switch project
|
|
364
|
+
ppm bot session new <title> # Create session
|
|
365
|
+
ppm bot session list # List sessions
|
|
366
|
+
ppm bot session resume <id> # Resume session
|
|
367
|
+
ppm bot session stop <id> # Stop session
|
|
368
|
+
ppm bot status # Bot health
|
|
369
|
+
ppm bot version # PPM version
|
|
370
|
+
ppm bot restart # Restart service
|
|
371
|
+
ppm bot help # Help
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Settings UI (ppmbot-settings-section.tsx):**
|
|
375
|
+
- Enable/disable PPMBot
|
|
376
|
+
- Paired Telegram chats (approval management)
|
|
377
|
+
- Default project selection
|
|
378
|
+
- System prompt customization
|
|
379
|
+
- Task auto-refresh (poll interval, max history)
|
|
380
|
+
- Delegated tasks panel (status, result preview, delete)
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
### ClawBot Service Layer (Telegram Bot Integration) — LEGACY (v0.9.10)
|
|
273
385
|
**Component:** Telegram bot service + subsidiary services
|
|
274
386
|
|
|
275
387
|
**Responsibilities:**
|
|
@@ -1628,13 +1740,81 @@ $ ppm upgrade
|
|
|
1628
1740
|
→ Works in headless environments (no OS autostart dependency)
|
|
1629
1741
|
|
|
1630
1742
|
$ ppm stop
|
|
1631
|
-
→
|
|
1632
|
-
→
|
|
1633
|
-
→
|
|
1743
|
+
→ SOFT STOP: kills server only, supervisor stays alive with Cloud WS + tunnel
|
|
1744
|
+
→ Supervisor transitions to "stopped" state
|
|
1745
|
+
→ Minimal HTML page served on port (503 status on /api/health)
|
|
1746
|
+
→ Tunnel and Cloud connectivity remain active
|
|
1747
|
+
→ `ppm start` resumes without restarting supervisor process
|
|
1748
|
+
|
|
1749
|
+
$ ppm stop --kill OR ppm down
|
|
1750
|
+
→ FULL SHUTDOWN: kills everything (supervisor + server + tunnel)
|
|
1751
|
+
→ Supervisor transitions to "upgrading" then terminates
|
|
1634
1752
|
→ Cleans up status.json and ppm.pid
|
|
1635
|
-
→ Graceful
|
|
1753
|
+
→ Graceful cleanup (close WS, cleanup PTY, stop tunnel)
|
|
1754
|
+
```
|
|
1755
|
+
|
|
1756
|
+
### Supervisor Architecture (v0.9.11+)
|
|
1757
|
+
|
|
1758
|
+
The supervisor is a long-lived parent process that manages server + tunnel children with resilience and state management.
|
|
1759
|
+
|
|
1760
|
+
**Architecture:**
|
|
1761
|
+
```
|
|
1762
|
+
Supervisor Process (parent)
|
|
1763
|
+
├── Server Child (Hono HTTP server)
|
|
1764
|
+
│ ├── Health checks every 30s (/api/health)
|
|
1765
|
+
│ ├── Auto-restart on crash (exponential backoff, max 10 restarts)
|
|
1766
|
+
│ └── If in "stopped" state, serves minimal 503 page instead of restarting
|
|
1767
|
+
│
|
|
1768
|
+
├── Tunnel Child (Cloudflare Quick Tunnel, if --share)
|
|
1769
|
+
│ ├── URL probe every 2min
|
|
1770
|
+
│ ├── Auto-reconnect on failure
|
|
1771
|
+
│ └── URL persisted to status.json
|
|
1772
|
+
│
|
|
1773
|
+
├── State Machine: "running" | "paused" | "stopped" | "upgrading"
|
|
1774
|
+
│ ├── running — Server spawned, tunnel optional, serving requests
|
|
1775
|
+
│ ├── paused — Supervisor paused (resume via signal)
|
|
1776
|
+
│ ├── stopped — Server stopped (soft stop), tunnel alive, Cloud WS active
|
|
1777
|
+
│ └── upgrading — Self-replace in progress
|
|
1778
|
+
│
|
|
1779
|
+
├── Upgrade Check (every 15min)
|
|
1780
|
+
│ └── npm registry poll → availableVersion written to status.json
|
|
1781
|
+
│
|
|
1782
|
+
├── Stopped Page Server
|
|
1783
|
+
│ ├── Lightweight HTTP handler on same port as server
|
|
1784
|
+
│ ├── Returns 503 on /api/health
|
|
1785
|
+
│ └── Tunnels Cloud WS calls through to PPM Cloud
|
|
1786
|
+
│
|
|
1787
|
+
└── Error Resilience
|
|
1788
|
+
├── uncaughtException → log + exit gracefully
|
|
1789
|
+
├── unhandledRejection → log + continue
|
|
1790
|
+
└── Signal handlers: SIGTERM (full shutdown), SIGUSR1 (self-replace), SIGUSR2 (restart skip backoff)
|
|
1636
1791
|
```
|
|
1637
1792
|
|
|
1793
|
+
**Soft Stop vs Full Shutdown:**
|
|
1794
|
+
| Command | Server | Supervisor | Tunnel | Use Case |
|
|
1795
|
+
|---------|--------|------------|--------|----------|
|
|
1796
|
+
| `ppm stop` | Killed | Stays alive | Stays alive | Restart later with `ppm start` |
|
|
1797
|
+
| `ppm stop --kill` | Killed | Killed | Killed | Full cleanup, exit |
|
|
1798
|
+
| `ppm down` | Killed | Killed | Killed | Full cleanup, exit |
|
|
1799
|
+
|
|
1800
|
+
**State Persistence:**
|
|
1801
|
+
- Status file: `~/.ppm/status.json` — PID, port, host, shareUrl, supervisorPid, availableVersion, state
|
|
1802
|
+
- Lock file: `~/.ppm/.start-lock` — Prevent concurrent starts
|
|
1803
|
+
- Command file: `~/.ppm/.supervisor-cmd` — IPC for soft_stop, resume, self_replace
|
|
1804
|
+
|
|
1805
|
+
**Stopped Page Implementation:**
|
|
1806
|
+
- Minimal HTTP server on same port as main server
|
|
1807
|
+
- Serves `503 Service Unavailable` on /api/health
|
|
1808
|
+
- Proxies Cloud WS calls to PPM Cloud (if tunnel configured)
|
|
1809
|
+
- Allows `ppm start` to resume without supervisor restart
|
|
1810
|
+
|
|
1811
|
+
**Files (Modular Design):**
|
|
1812
|
+
- `src/services/supervisor.ts` — Main orchestrator (spawn, health checks, upgrade checks)
|
|
1813
|
+
- `src/services/supervisor-state.ts` — State machine, IPC command handling, signal routing
|
|
1814
|
+
- `src/services/supervisor-stopped-page.ts` — Minimal 503 page + Cloud WS proxy
|
|
1815
|
+
|
|
1816
|
+
---
|
|
1817
|
+
|
|
1638
1818
|
### Future: Multi-Machine (Not in v2)
|
|
1639
1819
|
Would require:
|
|
1640
1820
|
- Central state server (Redis/Postgres)
|