clawgram 2.21.0 → 2.22.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/README.md +34 -8
- package/dist/channel.js +290 -57
- package/dist/chat-info.js +28 -22
- package/dist/cli-core.js +109 -20
- package/dist/expiring-map.js +96 -0
- package/dist/gramjs-client.js +104 -29
- package/dist/group-reply-address.js +6 -16
- package/dist/group-visible-reply-guard.js +12 -32
- package/dist/helpers.js +50 -5
- package/dist/history.js +54 -22
- package/dist/html-render.js +44 -1
- package/dist/joins.js +8 -6
- package/dist/manage.js +9 -15
- package/dist/media.js +15 -16
- package/dist/normalize.js +6 -1
- package/dist/proxy-config.js +2 -4
- package/dist/reactions.js +3 -12
- package/dist/secret-refs.js +1 -0
- package/dist/send-scope.js +97 -0
- package/dist/silent-reaction.js +9 -5
- package/dist/state-dir.js +24 -0
- package/dist/system-notice.js +49 -4
- package/dist/update-config.js +139 -33
- package/dist/util.js +36 -0
- package/npm-shrinkwrap.json +4531 -0
- package/openclaw.plugin.json +39 -5
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ Clawgram is a personal-Telegram channel plugin for [OpenClaw](https://github.com
|
|
|
18
18
|
> it can read private and group conversations within its configured scope and send messages that are
|
|
19
19
|
> indistinguishable from ones you typed yourself. Recipients cannot tell an assistant reply from a
|
|
20
20
|
> human one. Treat the account as compromised-if-leaked: `apiHash` and `sessionString` are bearer
|
|
21
|
-
> credentials for everything that account can reach. Scope reads with `readChats`,
|
|
22
|
-
> `allowFrom`, and prefer a dedicated account over your primary one —
|
|
23
|
-
> [Security and privacy](#security-and-privacy).
|
|
21
|
+
> credentials for everything that account can reach. Scope reads with `readChats`, scope sends with
|
|
22
|
+
> `sendChats`, gate senders with `allowFrom`, and prefer a dedicated account over your primary one —
|
|
23
|
+
> see [Security and privacy](#security-and-privacy).
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
## Features
|
|
@@ -184,6 +184,13 @@ openclaw gateway restart
|
|
|
184
184
|
openclaw gateway restart
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
+
**What `--auth` writes is closed, on purpose.** The first config allows only the
|
|
188
|
+
account that authorised (`allowFrom: [<your id>]`), seeds no group entry, and
|
|
189
|
+
writes `readChats: []`. Until 2.21.1 it seeded `allowFrom: ["*"]` with an
|
|
190
|
+
enabled wildcard group, so a freshly authorised account answered any Telegram
|
|
191
|
+
user and read the history of every chat it belonged to. Widen both lists
|
|
192
|
+
deliberately; the flow prints who can reach the agent before it exits.
|
|
193
|
+
|
|
187
194
|
One restart after installation is enough. From 2.17.0 the plugin declares
|
|
188
195
|
`channels.clawgram` as a hot-reloadable prefix, so later edits under it —
|
|
189
196
|
`allowFrom`, `groups`, `readChats`, proxy — are picked up by the Gateway's
|
|
@@ -249,6 +256,7 @@ loud where it does occur.
|
|
|
249
256
|
| `apiHash` | string | required | Telegram API hash |
|
|
250
257
|
| `sessionString` | string | `""` | Authenticated StringSession |
|
|
251
258
|
| `allowFrom` | string[] | `["*"]` | Allowed sender IDs/usernames for direct messages only. Three states: absent means everyone, `[]` denies everyone (a warning is logged at account start), a list allows those senders |
|
|
259
|
+
| `operatorIds` | string[] | — | Who receives core's operational telemetry in a DM (tool-failure warnings, fallback notices). They quote shell commands and secret-store paths, so they go only to these ids. Absent falls back to `allowFrom` when it is a concrete list; a wildcard or an empty list means no operator is identified and the notices are dropped everywhere — they stay in the run diagnostics and the gateway log |
|
|
252
260
|
| `groups` | object | `{}` | Allowed groups map keyed by explicit group id or `*` |
|
|
253
261
|
| `proxy` | object | unset | Optional SOCKS4/SOCKS5 proxy for this account — see [Proxy (SOCKS4/SOCKS5)](#proxy-socks4socks5) |
|
|
254
262
|
| `manageChats` | string[] | unset | Chats the assistant may **manage** — see [Chat management](#chat-management). Absent or empty = management off; `["*"]` = every chat |
|
|
@@ -809,10 +817,27 @@ nothing is not an error — it says which nothing it was:
|
|
|
809
817
|
A reading that fails while the download succeeded still returns `ok: true`, with `readError` beside
|
|
810
818
|
the path: the bytes are already there and can still be forwarded.
|
|
811
819
|
|
|
812
|
-
**Fetched files live
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
820
|
+
**Fetched files live under the OpenClaw state directory** (`$OPENCLAW_STATE_DIR/tmp/clawgram-fetched/`,
|
|
821
|
+
falling back to the system temp directory when that variable is unset), named after the chat and
|
|
822
|
+
message they came from, and are pruned an hour later by the next fetch. The directory is created
|
|
823
|
+
0700 and each file written 0600: these are private-chat images and voice notes, and until 2.21.1
|
|
824
|
+
they sat in a shared `/tmp` at 0644 for a day, readable by every local account on the host. Nothing
|
|
825
|
+
else removes them, and nothing sends them anywhere — putting a fetched file in a chat is an ordinary
|
|
826
|
+
`upload-file`, with whatever confirmation the deployment requires for that.
|
|
827
|
+
|
|
828
|
+
## Dependencies are pinned, and the lock ships
|
|
829
|
+
|
|
830
|
+
`installDependencies: true` tells OpenClaw to run an install in the plugin
|
|
831
|
+
directory, so what lands on the host is whatever the registry serves that day —
|
|
832
|
+
and the MTProto client sees `apiHash`, `sessionString`, the proxy credentials
|
|
833
|
+
and every message. Since 2.21.1 the two runtime dependencies are pinned to
|
|
834
|
+
exact versions and `npm-shrinkwrap.json` is part of the published tarball, so an
|
|
835
|
+
install reproduces the tree the tests ran against rather than resolving a caret
|
|
836
|
+
range. `npm ci --ignore-scripts` verifies it.
|
|
837
|
+
|
|
838
|
+
The transitive `ip-address` is held at 10.7.0 through `overrides`: everything at
|
|
839
|
+
or below 10.3.0 carries three advisories about SSRF and trust-boundary bypass,
|
|
840
|
+
and it sits under the SOCKS proxy path this channel uses.
|
|
816
841
|
|
|
817
842
|
## Security and privacy
|
|
818
843
|
|
|
@@ -825,9 +850,10 @@ that means in practice, and what the code does about it:
|
|
|
825
850
|
| Proxy password | `accounts.*.proxy.password`, or a secret store | Also accepts a SecretRef since 2.2.0. Marked `sensitive` in `uiHints`; diagnostics say `socks4`/`socks5` and nothing more. An invalid proxy fails the account rather than falling back to a direct connection, which would leak the host IP to Telegram |
|
|
826
851
|
| Message bodies | channel logs | **Not logged.** Outbound sends record recipient, ids and `textLength`. Until 2.1.0 the full outbound text was written to the channel log — if you ran 2.0.x, treat those journal entries as containing private correspondence |
|
|
827
852
|
| Read scope | `accounts.*.readChats` | History, membership and attachment fetches are confined to the listed chats. Absent means no restriction; an empty array denies everything. Telegram's own service chat (`777000`, where login codes arrive) is refused unconditionally, including under a wildcard |
|
|
853
|
+
| Send scope | `accounts.*.sendChats` | `send`, `upload-file`, `react` and core's delivery path are confined to the listed chats. Same shape as `readChats`: absent means no restriction, `[]` denies everything, `["*"]` allows every chat. **A phone number is refused whatever the list says** — messaging a raw number starts a conversation with someone who never contacted the account. Without the list, an injected turn can write to strangers from the owner's account or move a work chat's content into a DM one send at a time (2.22.0) |
|
|
828
854
|
| Manage scope | `accounts.*.manageChats` | Creating groups, changing membership, admin rights, ownership and invite links are confined to the listed chats — and **off entirely** when the key is absent or empty (opposite default to `readChats`, because these actions change chats rather than read them) |
|
|
829
855
|
| 2FA password | `accounts.*.twoFaPassword`, or a secret store | Read only by `transferOwnership`, exchanged for an SRP proof in-process. Accepts a SecretRef since 2.12.0; `sensitive` in `uiHints`; on the forbidden-log-keys list the static tests enforce |
|
|
830
|
-
| Who may talk to it | `allowFrom`, `groups.*.groupPolicy` | Direct-message senders and group behaviour are allowlisted; `mention` limits group replies to explicit mentions |
|
|
856
|
+
| Who may talk to it | `allowFrom`, `groups.*.groupPolicy` | Direct-message senders and group behaviour are allowlisted; `mention` limits group replies to explicit mentions. **Write ids, not handles:** an `@username` entry is a claim about a handle, and a released handle can be taken by someone else, after which the entry admits a stranger. The account logs a warning at start-up for every handle entry (2.22.0) |
|
|
831
857
|
|
|
832
858
|
Two static tests (`test/no-secret-logging.test.ts`) fail the build if a message body or a credential
|
|
833
859
|
is ever added back to a log call, or if the auth flow prints the session string unprompted.
|