File size: 6,937 Bytes
a9876bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fce80d1
 
a9876bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181b8c1
 
 
 
 
a9876bc
 
 
 
 
181b8c1
 
 
 
 
 
 
 
fce80d1
181b8c1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a9876bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# mona-agent Architecture

How the open-source device daemon is built, and how it talks to the
mona.expert cloud.

## Overview

mona-agent is a **headless Node.js daemon** with two jobs:

1. **Execute** β€” run local tools (files, shell, network, system info) on
   behalf of the cloud agent.
2. **Report** β€” stream device metrics and command results back to the cloud
   in real time.

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Device (your machine)              β”‚      β”‚  mona.expert cloud (SaaS)    β”‚
β”‚                                     β”‚      β”‚                              β”‚
β”‚  mona-agent                         β”‚      β”‚  Control plane API           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚      β”‚  /api/v1/agent/verify        β”‚
β”‚  β”‚ ControlChannel│◄─►│ tools/     β”‚  β”‚      β”‚  /api/v1/agent/stats        β”‚
β”‚  β”‚ (HTTPS + WS) β”‚   β”‚  files     β”‚  β”‚      β”‚  /api/v1/agent/chat …        β”‚
β”‚  β”‚              β”‚   β”‚  shell     β”‚  β”‚      β”‚                              β”‚
β”‚  β”‚   metrics   β”‚   β”‚  net       β”‚  β”‚      β”‚  AI engine (the brain)       β”‚
β”‚  β”‚   commands  β”‚   β”‚  sysinfo   β”‚  β”‚      β”‚  Dashboard + device overview β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚      β”‚  Key vault (AES-256)         β”‚
β”‚         β”‚                           β”‚      β”‚  Audit log                   β”‚
β”‚         β–Ό                           β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚  TUI (mona-agent gui)               β”‚
β”‚  headless daemon (mona-agent start) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Modules

| Module | Responsibility |
|---|---|
| `bin/mona-agent.js` | CLI entrypoint β€” `gui`, `start`, `login`, `connect`, `chat`, `exec` |
| `src/config.js` | Credentials, cloud endpoint resolution, platform detection |
| `src/cloud.js` | REST client for the control plane API (Bearer-auth) |
| `src/control.js` | Control channel: registration, command dispatch, metrics streaming |
| `src/api.js` | Local HTTP API + WebSocket (used by the local dashboard / desktop UI) |
| `src/tools/*` | The tool sandbox: `files`, `shell`, `net`, `sysinfo` |
| `src/tui.js` | Terminal dashboard β€” live log, scrollback, status bar |
| `src/log.js` | Structured logging (quiet in daemon mode) |

## Control channel lifecycle

1. **Boot** β€” `config.js` loads `~/.mona-agent/credentials.json` and
   resolves the cloud endpoint (`MONA_CLOUD` or `https://agent.mona.expert`).
2. **Verify** β€” the daemon authenticates with `POST /api/v1/agent/verify`
   (Bearer token). The server returns the agent identity and capabilities.
3. **Metrics** β€” every 10 seconds the daemon POSTs a snapshot to
   `/api/v1/agent/stats`: CPU %, load average, memory, disk, uptime, host
   and platform info.
4. **Commands** β€” on the Sngine control plane the device **polls the cloud
   task queue** every 2 s (`GET /api/v1/agent/tasks`, claim, then report
   via `POST /api/v1/agent/tasks/:id/result`). No inbound port, no
   WebSocket upgrade required. On the Docker platform, commands arrive
   over the WebSocket control channel instead.
5. **Resilience** β€” metrics streaming is independent of the WebSocket
   channel. If the server cannot upgrade to WebSocket (e.g. shared hosting
   behind LiteSpeed), the daemon transparently falls back to HTTPS polling
   and keeps streaming β€” no reconnect storm.

## Agentic execution loop

Every task runs the same loop, wherever it came from (dashboard chat,
CLI, or the cloud queue):

```
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                 mona.expert brain                β”‚
        β”‚  reason  answer in text OR emit one tool call   β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           task (HTTPS) β”‚                       β”‚ tool result
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                   mona-agent                     β”‚
        β”‚  execute tool locally (sysinfo|shell|files|net)  β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

- Up to **8 tool steps per task** β€” the loop ends when the brain answers
  in plain text.
- Tool protocol is provider-agnostic: the brain replies with a single
  JSON object `{"tool":"<name>","args":{...}}` or plain text. No
  provider-specific function-calling plumbing.
- Every step is reported to the cloud (`tool.call` / `tool.result`) and
  appears live in the dashboard activity feed.
- The final answer is stored in the cloud conversation β€” history survives
  restarts and is visible from every client.

## Metrics pipeline (HTTP-first)

The client was designed so that **metrics never depend on a WebSocket
upgrade**:

- Every 10 s: `POST /api/v1/agent/stats` with CPU, memory, disk, load,
  uptime, hostname, platform, arch, version, IP.
- The cloud keeps the latest snapshot plus a rolling 180-point history per
  device; the dashboard polls every 3 s β€” effectively live.
- A device is shown as **online** when its last snapshot is ≀ 20 s old.

## Security model (client side)

- **No AI provider keys on the device.** Only a mona.expert device token is
  stored (`~/.mona-agent/credentials.json`, mode 0600).
- **Guarded shell** β€” commands run through an allowlist; dangerous patterns
  are blocked before execution.
- **Confined files tool** β€” reads/writes are limited to safe, allowed paths.
- **Egress-only** β€” the daemon opens outbound connections only; it listens
  on localhost only (for the local dashboard).

See [SECURITY.md](../SECURITY.md) for the full model and disclosure policy.

## Why HTTPS polling instead of WebSockets?

The control plane runs on shared hosting (LiteSpeed), where WebSocket
proxying is not always available and long-running Node processes are not
possible. The client therefore uses:

- **WebSocket** when the server upgrades it (self-hosted / VPS setups),
- **HTTPS polling + streaming metrics** everywhere else.

One code path, two transports β€” the daemon decides at runtime.