polygram 0.8.0-rc.67 → 0.8.0-rc.68
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/.claude-plugin/plugin.json +1 -1
- package/lib/attachments.js +61 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "polygram",
|
|
4
|
-
"version": "0.8.0-rc.
|
|
4
|
+
"version": "0.8.0-rc.68",
|
|
5
5
|
"description": "Telegram integration for Claude Code that preserves the OpenClaw per-chat session model. Migration target for OpenClaw users. Multi-bot, multi-chat, per-topic isolation; SQLite transcripts; inline-keyboard approvals. Bundles /polygram:status|logs|pair-code|approvals admin commands plus history (transcript queries) and polygram-send (out-of-turn IPC sends with file-upload validation) skills.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"telegram",
|
package/lib/attachments.js
CHANGED
|
@@ -6,6 +6,20 @@
|
|
|
6
6
|
* No count cap: per-file (10 MB) and total-size (20 MB) bound resource
|
|
7
7
|
* usage already; an additional count limit just produces "skipped: max
|
|
8
8
|
* count" surprises on Telegram albums (up to 10 photos in one send).
|
|
9
|
+
*
|
|
10
|
+
* rc.68 — widened scope:
|
|
11
|
+
* - archives (zip + alt zip MIME some Telegram clients send): containers
|
|
12
|
+
* the agent unpacks via Bash + unzip when downstream tools are gated
|
|
13
|
+
* in. Size caps remain the binding control.
|
|
14
|
+
* - markup the agent reads natively but was silently being denied unless
|
|
15
|
+
* the client happened to ship it as text/plain (markdown, html, yaml,
|
|
16
|
+
* xml). Closes the consistency gap.
|
|
17
|
+
* - extension-fallback path for missing/octet-stream MIME. Telegram's
|
|
18
|
+
* server-side detection degrades to octet-stream (or omits MIME) for
|
|
19
|
+
* extensions it doesn't sniff; the fallback trusts the filename when
|
|
20
|
+
* extension is on the same well-known list. Defense-in-depth: explicit
|
|
21
|
+
* denylisted MIME (e.g. application/x-msdownload) still wins over
|
|
22
|
+
* extension — the fallback only kicks in when MIME is unhelpful.
|
|
9
23
|
*/
|
|
10
24
|
|
|
11
25
|
const MAX_FILE_BYTES = 10 * 1024 * 1024;
|
|
@@ -16,12 +30,42 @@ const MIME_ALLOW = [
|
|
|
16
30
|
/^application\/msword$/, /^application\/vnd\.openxmlformats-/,
|
|
17
31
|
/^application\/vnd\.ms-excel$/, /^application\/json$/,
|
|
18
32
|
/^text\/csv$/,
|
|
33
|
+
// rc.68: archives + markup formats Claude reads natively.
|
|
34
|
+
/^application\/zip$/, /^application\/x-zip-compressed$/,
|
|
35
|
+
/^text\/markdown$/,
|
|
36
|
+
/^text\/html$/,
|
|
37
|
+
/^text\/yaml$/, /^application\/yaml$/, /^application\/x-yaml$/,
|
|
38
|
+
/^application\/xml$/, /^text\/xml$/,
|
|
19
39
|
];
|
|
20
40
|
|
|
41
|
+
// rc.68: extensions trusted when MIME is missing or generic
|
|
42
|
+
// (application/octet-stream). Same set the explicit MIME list covers, so
|
|
43
|
+
// the fallback is "trust the filename when MIME is unhelpful" — not "any
|
|
44
|
+
// extension goes." A file named foo.exe with empty MIME stays rejected.
|
|
45
|
+
const EXTENSION_ALLOW = new Set([
|
|
46
|
+
// archives
|
|
47
|
+
'zip',
|
|
48
|
+
// text / structured data
|
|
49
|
+
'txt', 'md', 'csv', 'json', 'yaml', 'yml', 'xml', 'html',
|
|
50
|
+
// documents
|
|
51
|
+
'pdf', 'doc', 'docx', 'xls', 'xlsx',
|
|
52
|
+
]);
|
|
53
|
+
// MIME values that mean "I have no idea what this is" — fall back to
|
|
54
|
+
// extension match for these.
|
|
55
|
+
const FALLBACK_MIMES = new Set(['', 'application/octet-stream']);
|
|
56
|
+
|
|
57
|
+
function extensionOf(name) {
|
|
58
|
+
if (!name) return '';
|
|
59
|
+
const dot = String(name).lastIndexOf('.');
|
|
60
|
+
if (dot < 0 || dot === name.length - 1) return '';
|
|
61
|
+
return name.slice(dot + 1).toLowerCase();
|
|
62
|
+
}
|
|
63
|
+
|
|
21
64
|
function filterAttachments(attachments, opts = {}) {
|
|
22
65
|
const maxFileBytes = opts.maxFileBytes ?? MAX_FILE_BYTES;
|
|
23
66
|
const maxTotalBytes = opts.maxTotalBytes ?? MAX_TOTAL_BYTES;
|
|
24
67
|
const mimeAllow = opts.mimeAllow ?? MIME_ALLOW;
|
|
68
|
+
const extensionAllow = opts.extensionAllow ?? EXTENSION_ALLOW;
|
|
25
69
|
|
|
26
70
|
const accepted = [];
|
|
27
71
|
const rejected = [];
|
|
@@ -29,7 +73,15 @@ function filterAttachments(attachments, opts = {}) {
|
|
|
29
73
|
|
|
30
74
|
for (const a of attachments || []) {
|
|
31
75
|
const mime = a.mime_type || '';
|
|
32
|
-
|
|
76
|
+
const mimeOk = mimeAllow.some((re) => re.test(mime));
|
|
77
|
+
// rc.68: extension fallback only when MIME is unhelpful (empty or
|
|
78
|
+
// octet-stream). An explicit MIME — even one we don't allow — wins
|
|
79
|
+
// over the extension; that keeps malware.zip with mime
|
|
80
|
+
// application/x-msdownload from sneaking through via the .zip suffix.
|
|
81
|
+
const fallbackOk = !mimeOk
|
|
82
|
+
&& FALLBACK_MIMES.has(mime)
|
|
83
|
+
&& extensionAllow.has(extensionOf(a.name));
|
|
84
|
+
if (!mimeOk && !fallbackOk) {
|
|
33
85
|
rejected.push({ att: a, reason: `mime not allowed (${mime || 'unknown'})` });
|
|
34
86
|
continue;
|
|
35
87
|
}
|
|
@@ -55,4 +107,11 @@ function filterAttachments(attachments, opts = {}) {
|
|
|
55
107
|
return { accepted, rejected, totalBytes };
|
|
56
108
|
}
|
|
57
109
|
|
|
58
|
-
module.exports = {
|
|
110
|
+
module.exports = {
|
|
111
|
+
filterAttachments,
|
|
112
|
+
MAX_FILE_BYTES,
|
|
113
|
+
MAX_TOTAL_BYTES,
|
|
114
|
+
MIME_ALLOW,
|
|
115
|
+
EXTENSION_ALLOW,
|
|
116
|
+
FALLBACK_MIMES,
|
|
117
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polygram",
|
|
3
|
-
"version": "0.8.0-rc.
|
|
3
|
+
"version": "0.8.0-rc.68",
|
|
4
4
|
"description": "Telegram daemon for Claude Code that preserves the OpenClaw per-chat session model. Migration path for OpenClaw users moving to Claude Code.",
|
|
5
5
|
"main": "lib/ipc-client.js",
|
|
6
6
|
"bin": {
|