openclaw-telegram-manager 2.5.1 → 2.5.2

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/dist/setup.js CHANGED
@@ -1,26 +1,1165 @@
1
1
  #!/usr/bin/env node
2
- import * as fs from 'node:fs';
3
- import * as path from 'node:path';
4
- import * as crypto from 'node:crypto';
5
- import { execSync } from 'node:child_process';
6
- import * as readline from 'node:readline';
7
- // ── Constants ──────────────────────────────────────────────────────────
8
- const PLUGIN_NAME = 'openclaw-telegram-manager';
9
- const PLUGIN_VERSION = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8')).version;
10
- const MIN_OPENCLAW_VERSION = '2026.1.0';
11
- const INCLUDE_FILENAME = 'telegram-manager.generated.groups.json5';
12
- const REGISTRY_FILENAME = 'topics.json';
13
- const PLUGIN_FILES = ['openclaw.plugin.json', 'dist/plugin.js', 'skills', 'package.json'];
14
- const REQUIRED_PLUGIN_FILES = ['openclaw.plugin.json', 'dist/plugin.js'];
15
- const MEMORY_FLUSH_MARKER = 'topic folder';
16
- // Keep in sync with CURRENT_REGISTRY_VERSION in src/lib/types.ts
17
- const SETUP_REGISTRY_VERSION = 4;
18
- const MEMORY_FLUSH_INSTRUCTION = 'If you are working on a Telegram topic folder (projects/<slug>/), update its STATUS.md with current "Last done (UTC)" and "Next actions (now)" before this context is compacted.';
19
- // Keep in sync with HEARTBEAT_BLOCK in src/commands/autopilot.ts
20
- const SETUP_MARKER_START = '<!-- TM_AUTOPILOT_START -->';
21
- const SETUP_MARKER_END = '<!-- TM_AUTOPILOT_END -->';
22
- const SETUP_HEARTBEAT_BLOCK = `${SETUP_MARKER_START}
23
- ## Topic Manager Balanced Autopilot
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+
28
+ // node_modules/json5/lib/unicode.js
29
+ var require_unicode = __commonJS({
30
+ "node_modules/json5/lib/unicode.js"(exports, module) {
31
+ module.exports.Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
32
+ module.exports.ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
33
+ module.exports.ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/;
34
+ }
35
+ });
36
+
37
+ // node_modules/json5/lib/util.js
38
+ var require_util = __commonJS({
39
+ "node_modules/json5/lib/util.js"(exports, module) {
40
+ var unicode = require_unicode();
41
+ module.exports = {
42
+ isSpaceSeparator(c2) {
43
+ return typeof c2 === "string" && unicode.Space_Separator.test(c2);
44
+ },
45
+ isIdStartChar(c2) {
46
+ return typeof c2 === "string" && (c2 >= "a" && c2 <= "z" || c2 >= "A" && c2 <= "Z" || c2 === "$" || c2 === "_" || unicode.ID_Start.test(c2));
47
+ },
48
+ isIdContinueChar(c2) {
49
+ return typeof c2 === "string" && (c2 >= "a" && c2 <= "z" || c2 >= "A" && c2 <= "Z" || c2 >= "0" && c2 <= "9" || c2 === "$" || c2 === "_" || c2 === "\u200C" || c2 === "\u200D" || unicode.ID_Continue.test(c2));
50
+ },
51
+ isDigit(c2) {
52
+ return typeof c2 === "string" && /[0-9]/.test(c2);
53
+ },
54
+ isHexDigit(c2) {
55
+ return typeof c2 === "string" && /[0-9A-Fa-f]/.test(c2);
56
+ }
57
+ };
58
+ }
59
+ });
60
+
61
+ // node_modules/json5/lib/parse.js
62
+ var require_parse = __commonJS({
63
+ "node_modules/json5/lib/parse.js"(exports, module) {
64
+ var util = require_util();
65
+ var source;
66
+ var parseState;
67
+ var stack;
68
+ var pos;
69
+ var line;
70
+ var column;
71
+ var token;
72
+ var key;
73
+ var root;
74
+ module.exports = function parse(text, reviver) {
75
+ source = String(text);
76
+ parseState = "start";
77
+ stack = [];
78
+ pos = 0;
79
+ line = 1;
80
+ column = 0;
81
+ token = void 0;
82
+ key = void 0;
83
+ root = void 0;
84
+ do {
85
+ token = lex();
86
+ parseStates[parseState]();
87
+ } while (token.type !== "eof");
88
+ if (typeof reviver === "function") {
89
+ return internalize({ "": root }, "", reviver);
90
+ }
91
+ return root;
92
+ };
93
+ function internalize(holder, name, reviver) {
94
+ const value = holder[name];
95
+ if (value != null && typeof value === "object") {
96
+ if (Array.isArray(value)) {
97
+ for (let i = 0; i < value.length; i++) {
98
+ const key2 = String(i);
99
+ const replacement = internalize(value, key2, reviver);
100
+ if (replacement === void 0) {
101
+ delete value[key2];
102
+ } else {
103
+ Object.defineProperty(value, key2, {
104
+ value: replacement,
105
+ writable: true,
106
+ enumerable: true,
107
+ configurable: true
108
+ });
109
+ }
110
+ }
111
+ } else {
112
+ for (const key2 in value) {
113
+ const replacement = internalize(value, key2, reviver);
114
+ if (replacement === void 0) {
115
+ delete value[key2];
116
+ } else {
117
+ Object.defineProperty(value, key2, {
118
+ value: replacement,
119
+ writable: true,
120
+ enumerable: true,
121
+ configurable: true
122
+ });
123
+ }
124
+ }
125
+ }
126
+ }
127
+ return reviver.call(holder, name, value);
128
+ }
129
+ var lexState;
130
+ var buffer;
131
+ var doubleQuote;
132
+ var sign;
133
+ var c2;
134
+ function lex() {
135
+ lexState = "default";
136
+ buffer = "";
137
+ doubleQuote = false;
138
+ sign = 1;
139
+ for (; ; ) {
140
+ c2 = peek();
141
+ const token2 = lexStates[lexState]();
142
+ if (token2) {
143
+ return token2;
144
+ }
145
+ }
146
+ }
147
+ function peek() {
148
+ if (source[pos]) {
149
+ return String.fromCodePoint(source.codePointAt(pos));
150
+ }
151
+ }
152
+ function read() {
153
+ const c3 = peek();
154
+ if (c3 === "\n") {
155
+ line++;
156
+ column = 0;
157
+ } else if (c3) {
158
+ column += c3.length;
159
+ } else {
160
+ column++;
161
+ }
162
+ if (c3) {
163
+ pos += c3.length;
164
+ }
165
+ return c3;
166
+ }
167
+ var lexStates = {
168
+ default() {
169
+ switch (c2) {
170
+ case " ":
171
+ case "\v":
172
+ case "\f":
173
+ case " ":
174
+ case "\xA0":
175
+ case "\uFEFF":
176
+ case "\n":
177
+ case "\r":
178
+ case "\u2028":
179
+ case "\u2029":
180
+ read();
181
+ return;
182
+ case "/":
183
+ read();
184
+ lexState = "comment";
185
+ return;
186
+ case void 0:
187
+ read();
188
+ return newToken("eof");
189
+ }
190
+ if (util.isSpaceSeparator(c2)) {
191
+ read();
192
+ return;
193
+ }
194
+ return lexStates[parseState]();
195
+ },
196
+ comment() {
197
+ switch (c2) {
198
+ case "*":
199
+ read();
200
+ lexState = "multiLineComment";
201
+ return;
202
+ case "/":
203
+ read();
204
+ lexState = "singleLineComment";
205
+ return;
206
+ }
207
+ throw invalidChar(read());
208
+ },
209
+ multiLineComment() {
210
+ switch (c2) {
211
+ case "*":
212
+ read();
213
+ lexState = "multiLineCommentAsterisk";
214
+ return;
215
+ case void 0:
216
+ throw invalidChar(read());
217
+ }
218
+ read();
219
+ },
220
+ multiLineCommentAsterisk() {
221
+ switch (c2) {
222
+ case "*":
223
+ read();
224
+ return;
225
+ case "/":
226
+ read();
227
+ lexState = "default";
228
+ return;
229
+ case void 0:
230
+ throw invalidChar(read());
231
+ }
232
+ read();
233
+ lexState = "multiLineComment";
234
+ },
235
+ singleLineComment() {
236
+ switch (c2) {
237
+ case "\n":
238
+ case "\r":
239
+ case "\u2028":
240
+ case "\u2029":
241
+ read();
242
+ lexState = "default";
243
+ return;
244
+ case void 0:
245
+ read();
246
+ return newToken("eof");
247
+ }
248
+ read();
249
+ },
250
+ value() {
251
+ switch (c2) {
252
+ case "{":
253
+ case "[":
254
+ return newToken("punctuator", read());
255
+ case "n":
256
+ read();
257
+ literal("ull");
258
+ return newToken("null", null);
259
+ case "t":
260
+ read();
261
+ literal("rue");
262
+ return newToken("boolean", true);
263
+ case "f":
264
+ read();
265
+ literal("alse");
266
+ return newToken("boolean", false);
267
+ case "-":
268
+ case "+":
269
+ if (read() === "-") {
270
+ sign = -1;
271
+ }
272
+ lexState = "sign";
273
+ return;
274
+ case ".":
275
+ buffer = read();
276
+ lexState = "decimalPointLeading";
277
+ return;
278
+ case "0":
279
+ buffer = read();
280
+ lexState = "zero";
281
+ return;
282
+ case "1":
283
+ case "2":
284
+ case "3":
285
+ case "4":
286
+ case "5":
287
+ case "6":
288
+ case "7":
289
+ case "8":
290
+ case "9":
291
+ buffer = read();
292
+ lexState = "decimalInteger";
293
+ return;
294
+ case "I":
295
+ read();
296
+ literal("nfinity");
297
+ return newToken("numeric", Infinity);
298
+ case "N":
299
+ read();
300
+ literal("aN");
301
+ return newToken("numeric", NaN);
302
+ case '"':
303
+ case "'":
304
+ doubleQuote = read() === '"';
305
+ buffer = "";
306
+ lexState = "string";
307
+ return;
308
+ }
309
+ throw invalidChar(read());
310
+ },
311
+ identifierNameStartEscape() {
312
+ if (c2 !== "u") {
313
+ throw invalidChar(read());
314
+ }
315
+ read();
316
+ const u = unicodeEscape();
317
+ switch (u) {
318
+ case "$":
319
+ case "_":
320
+ break;
321
+ default:
322
+ if (!util.isIdStartChar(u)) {
323
+ throw invalidIdentifier();
324
+ }
325
+ break;
326
+ }
327
+ buffer += u;
328
+ lexState = "identifierName";
329
+ },
330
+ identifierName() {
331
+ switch (c2) {
332
+ case "$":
333
+ case "_":
334
+ case "\u200C":
335
+ case "\u200D":
336
+ buffer += read();
337
+ return;
338
+ case "\\":
339
+ read();
340
+ lexState = "identifierNameEscape";
341
+ return;
342
+ }
343
+ if (util.isIdContinueChar(c2)) {
344
+ buffer += read();
345
+ return;
346
+ }
347
+ return newToken("identifier", buffer);
348
+ },
349
+ identifierNameEscape() {
350
+ if (c2 !== "u") {
351
+ throw invalidChar(read());
352
+ }
353
+ read();
354
+ const u = unicodeEscape();
355
+ switch (u) {
356
+ case "$":
357
+ case "_":
358
+ case "\u200C":
359
+ case "\u200D":
360
+ break;
361
+ default:
362
+ if (!util.isIdContinueChar(u)) {
363
+ throw invalidIdentifier();
364
+ }
365
+ break;
366
+ }
367
+ buffer += u;
368
+ lexState = "identifierName";
369
+ },
370
+ sign() {
371
+ switch (c2) {
372
+ case ".":
373
+ buffer = read();
374
+ lexState = "decimalPointLeading";
375
+ return;
376
+ case "0":
377
+ buffer = read();
378
+ lexState = "zero";
379
+ return;
380
+ case "1":
381
+ case "2":
382
+ case "3":
383
+ case "4":
384
+ case "5":
385
+ case "6":
386
+ case "7":
387
+ case "8":
388
+ case "9":
389
+ buffer = read();
390
+ lexState = "decimalInteger";
391
+ return;
392
+ case "I":
393
+ read();
394
+ literal("nfinity");
395
+ return newToken("numeric", sign * Infinity);
396
+ case "N":
397
+ read();
398
+ literal("aN");
399
+ return newToken("numeric", NaN);
400
+ }
401
+ throw invalidChar(read());
402
+ },
403
+ zero() {
404
+ switch (c2) {
405
+ case ".":
406
+ buffer += read();
407
+ lexState = "decimalPoint";
408
+ return;
409
+ case "e":
410
+ case "E":
411
+ buffer += read();
412
+ lexState = "decimalExponent";
413
+ return;
414
+ case "x":
415
+ case "X":
416
+ buffer += read();
417
+ lexState = "hexadecimal";
418
+ return;
419
+ }
420
+ return newToken("numeric", sign * 0);
421
+ },
422
+ decimalInteger() {
423
+ switch (c2) {
424
+ case ".":
425
+ buffer += read();
426
+ lexState = "decimalPoint";
427
+ return;
428
+ case "e":
429
+ case "E":
430
+ buffer += read();
431
+ lexState = "decimalExponent";
432
+ return;
433
+ }
434
+ if (util.isDigit(c2)) {
435
+ buffer += read();
436
+ return;
437
+ }
438
+ return newToken("numeric", sign * Number(buffer));
439
+ },
440
+ decimalPointLeading() {
441
+ if (util.isDigit(c2)) {
442
+ buffer += read();
443
+ lexState = "decimalFraction";
444
+ return;
445
+ }
446
+ throw invalidChar(read());
447
+ },
448
+ decimalPoint() {
449
+ switch (c2) {
450
+ case "e":
451
+ case "E":
452
+ buffer += read();
453
+ lexState = "decimalExponent";
454
+ return;
455
+ }
456
+ if (util.isDigit(c2)) {
457
+ buffer += read();
458
+ lexState = "decimalFraction";
459
+ return;
460
+ }
461
+ return newToken("numeric", sign * Number(buffer));
462
+ },
463
+ decimalFraction() {
464
+ switch (c2) {
465
+ case "e":
466
+ case "E":
467
+ buffer += read();
468
+ lexState = "decimalExponent";
469
+ return;
470
+ }
471
+ if (util.isDigit(c2)) {
472
+ buffer += read();
473
+ return;
474
+ }
475
+ return newToken("numeric", sign * Number(buffer));
476
+ },
477
+ decimalExponent() {
478
+ switch (c2) {
479
+ case "+":
480
+ case "-":
481
+ buffer += read();
482
+ lexState = "decimalExponentSign";
483
+ return;
484
+ }
485
+ if (util.isDigit(c2)) {
486
+ buffer += read();
487
+ lexState = "decimalExponentInteger";
488
+ return;
489
+ }
490
+ throw invalidChar(read());
491
+ },
492
+ decimalExponentSign() {
493
+ if (util.isDigit(c2)) {
494
+ buffer += read();
495
+ lexState = "decimalExponentInteger";
496
+ return;
497
+ }
498
+ throw invalidChar(read());
499
+ },
500
+ decimalExponentInteger() {
501
+ if (util.isDigit(c2)) {
502
+ buffer += read();
503
+ return;
504
+ }
505
+ return newToken("numeric", sign * Number(buffer));
506
+ },
507
+ hexadecimal() {
508
+ if (util.isHexDigit(c2)) {
509
+ buffer += read();
510
+ lexState = "hexadecimalInteger";
511
+ return;
512
+ }
513
+ throw invalidChar(read());
514
+ },
515
+ hexadecimalInteger() {
516
+ if (util.isHexDigit(c2)) {
517
+ buffer += read();
518
+ return;
519
+ }
520
+ return newToken("numeric", sign * Number(buffer));
521
+ },
522
+ string() {
523
+ switch (c2) {
524
+ case "\\":
525
+ read();
526
+ buffer += escape();
527
+ return;
528
+ case '"':
529
+ if (doubleQuote) {
530
+ read();
531
+ return newToken("string", buffer);
532
+ }
533
+ buffer += read();
534
+ return;
535
+ case "'":
536
+ if (!doubleQuote) {
537
+ read();
538
+ return newToken("string", buffer);
539
+ }
540
+ buffer += read();
541
+ return;
542
+ case "\n":
543
+ case "\r":
544
+ throw invalidChar(read());
545
+ case "\u2028":
546
+ case "\u2029":
547
+ separatorChar(c2);
548
+ break;
549
+ case void 0:
550
+ throw invalidChar(read());
551
+ }
552
+ buffer += read();
553
+ },
554
+ start() {
555
+ switch (c2) {
556
+ case "{":
557
+ case "[":
558
+ return newToken("punctuator", read());
559
+ }
560
+ lexState = "value";
561
+ },
562
+ beforePropertyName() {
563
+ switch (c2) {
564
+ case "$":
565
+ case "_":
566
+ buffer = read();
567
+ lexState = "identifierName";
568
+ return;
569
+ case "\\":
570
+ read();
571
+ lexState = "identifierNameStartEscape";
572
+ return;
573
+ case "}":
574
+ return newToken("punctuator", read());
575
+ case '"':
576
+ case "'":
577
+ doubleQuote = read() === '"';
578
+ lexState = "string";
579
+ return;
580
+ }
581
+ if (util.isIdStartChar(c2)) {
582
+ buffer += read();
583
+ lexState = "identifierName";
584
+ return;
585
+ }
586
+ throw invalidChar(read());
587
+ },
588
+ afterPropertyName() {
589
+ if (c2 === ":") {
590
+ return newToken("punctuator", read());
591
+ }
592
+ throw invalidChar(read());
593
+ },
594
+ beforePropertyValue() {
595
+ lexState = "value";
596
+ },
597
+ afterPropertyValue() {
598
+ switch (c2) {
599
+ case ",":
600
+ case "}":
601
+ return newToken("punctuator", read());
602
+ }
603
+ throw invalidChar(read());
604
+ },
605
+ beforeArrayValue() {
606
+ if (c2 === "]") {
607
+ return newToken("punctuator", read());
608
+ }
609
+ lexState = "value";
610
+ },
611
+ afterArrayValue() {
612
+ switch (c2) {
613
+ case ",":
614
+ case "]":
615
+ return newToken("punctuator", read());
616
+ }
617
+ throw invalidChar(read());
618
+ },
619
+ end() {
620
+ throw invalidChar(read());
621
+ }
622
+ };
623
+ function newToken(type, value) {
624
+ return {
625
+ type,
626
+ value,
627
+ line,
628
+ column
629
+ };
630
+ }
631
+ function literal(s) {
632
+ for (const c3 of s) {
633
+ const p = peek();
634
+ if (p !== c3) {
635
+ throw invalidChar(read());
636
+ }
637
+ read();
638
+ }
639
+ }
640
+ function escape() {
641
+ const c3 = peek();
642
+ switch (c3) {
643
+ case "b":
644
+ read();
645
+ return "\b";
646
+ case "f":
647
+ read();
648
+ return "\f";
649
+ case "n":
650
+ read();
651
+ return "\n";
652
+ case "r":
653
+ read();
654
+ return "\r";
655
+ case "t":
656
+ read();
657
+ return " ";
658
+ case "v":
659
+ read();
660
+ return "\v";
661
+ case "0":
662
+ read();
663
+ if (util.isDigit(peek())) {
664
+ throw invalidChar(read());
665
+ }
666
+ return "\0";
667
+ case "x":
668
+ read();
669
+ return hexEscape();
670
+ case "u":
671
+ read();
672
+ return unicodeEscape();
673
+ case "\n":
674
+ case "\u2028":
675
+ case "\u2029":
676
+ read();
677
+ return "";
678
+ case "\r":
679
+ read();
680
+ if (peek() === "\n") {
681
+ read();
682
+ }
683
+ return "";
684
+ case "1":
685
+ case "2":
686
+ case "3":
687
+ case "4":
688
+ case "5":
689
+ case "6":
690
+ case "7":
691
+ case "8":
692
+ case "9":
693
+ throw invalidChar(read());
694
+ case void 0:
695
+ throw invalidChar(read());
696
+ }
697
+ return read();
698
+ }
699
+ function hexEscape() {
700
+ let buffer2 = "";
701
+ let c3 = peek();
702
+ if (!util.isHexDigit(c3)) {
703
+ throw invalidChar(read());
704
+ }
705
+ buffer2 += read();
706
+ c3 = peek();
707
+ if (!util.isHexDigit(c3)) {
708
+ throw invalidChar(read());
709
+ }
710
+ buffer2 += read();
711
+ return String.fromCodePoint(parseInt(buffer2, 16));
712
+ }
713
+ function unicodeEscape() {
714
+ let buffer2 = "";
715
+ let count = 4;
716
+ while (count-- > 0) {
717
+ const c3 = peek();
718
+ if (!util.isHexDigit(c3)) {
719
+ throw invalidChar(read());
720
+ }
721
+ buffer2 += read();
722
+ }
723
+ return String.fromCodePoint(parseInt(buffer2, 16));
724
+ }
725
+ var parseStates = {
726
+ start() {
727
+ if (token.type === "eof") {
728
+ throw invalidEOF();
729
+ }
730
+ push();
731
+ },
732
+ beforePropertyName() {
733
+ switch (token.type) {
734
+ case "identifier":
735
+ case "string":
736
+ key = token.value;
737
+ parseState = "afterPropertyName";
738
+ return;
739
+ case "punctuator":
740
+ pop();
741
+ return;
742
+ case "eof":
743
+ throw invalidEOF();
744
+ }
745
+ },
746
+ afterPropertyName() {
747
+ if (token.type === "eof") {
748
+ throw invalidEOF();
749
+ }
750
+ parseState = "beforePropertyValue";
751
+ },
752
+ beforePropertyValue() {
753
+ if (token.type === "eof") {
754
+ throw invalidEOF();
755
+ }
756
+ push();
757
+ },
758
+ beforeArrayValue() {
759
+ if (token.type === "eof") {
760
+ throw invalidEOF();
761
+ }
762
+ if (token.type === "punctuator" && token.value === "]") {
763
+ pop();
764
+ return;
765
+ }
766
+ push();
767
+ },
768
+ afterPropertyValue() {
769
+ if (token.type === "eof") {
770
+ throw invalidEOF();
771
+ }
772
+ switch (token.value) {
773
+ case ",":
774
+ parseState = "beforePropertyName";
775
+ return;
776
+ case "}":
777
+ pop();
778
+ }
779
+ },
780
+ afterArrayValue() {
781
+ if (token.type === "eof") {
782
+ throw invalidEOF();
783
+ }
784
+ switch (token.value) {
785
+ case ",":
786
+ parseState = "beforeArrayValue";
787
+ return;
788
+ case "]":
789
+ pop();
790
+ }
791
+ },
792
+ end() {
793
+ }
794
+ };
795
+ function push() {
796
+ let value;
797
+ switch (token.type) {
798
+ case "punctuator":
799
+ switch (token.value) {
800
+ case "{":
801
+ value = {};
802
+ break;
803
+ case "[":
804
+ value = [];
805
+ break;
806
+ }
807
+ break;
808
+ case "null":
809
+ case "boolean":
810
+ case "numeric":
811
+ case "string":
812
+ value = token.value;
813
+ break;
814
+ }
815
+ if (root === void 0) {
816
+ root = value;
817
+ } else {
818
+ const parent = stack[stack.length - 1];
819
+ if (Array.isArray(parent)) {
820
+ parent.push(value);
821
+ } else {
822
+ Object.defineProperty(parent, key, {
823
+ value,
824
+ writable: true,
825
+ enumerable: true,
826
+ configurable: true
827
+ });
828
+ }
829
+ }
830
+ if (value !== null && typeof value === "object") {
831
+ stack.push(value);
832
+ if (Array.isArray(value)) {
833
+ parseState = "beforeArrayValue";
834
+ } else {
835
+ parseState = "beforePropertyName";
836
+ }
837
+ } else {
838
+ const current = stack[stack.length - 1];
839
+ if (current == null) {
840
+ parseState = "end";
841
+ } else if (Array.isArray(current)) {
842
+ parseState = "afterArrayValue";
843
+ } else {
844
+ parseState = "afterPropertyValue";
845
+ }
846
+ }
847
+ }
848
+ function pop() {
849
+ stack.pop();
850
+ const current = stack[stack.length - 1];
851
+ if (current == null) {
852
+ parseState = "end";
853
+ } else if (Array.isArray(current)) {
854
+ parseState = "afterArrayValue";
855
+ } else {
856
+ parseState = "afterPropertyValue";
857
+ }
858
+ }
859
+ function invalidChar(c3) {
860
+ if (c3 === void 0) {
861
+ return syntaxError(`JSON5: invalid end of input at ${line}:${column}`);
862
+ }
863
+ return syntaxError(`JSON5: invalid character '${formatChar(c3)}' at ${line}:${column}`);
864
+ }
865
+ function invalidEOF() {
866
+ return syntaxError(`JSON5: invalid end of input at ${line}:${column}`);
867
+ }
868
+ function invalidIdentifier() {
869
+ column -= 5;
870
+ return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`);
871
+ }
872
+ function separatorChar(c3) {
873
+ console.warn(`JSON5: '${formatChar(c3)}' in strings is not valid ECMAScript; consider escaping`);
874
+ }
875
+ function formatChar(c3) {
876
+ const replacements = {
877
+ "'": "\\'",
878
+ '"': '\\"',
879
+ "\\": "\\\\",
880
+ "\b": "\\b",
881
+ "\f": "\\f",
882
+ "\n": "\\n",
883
+ "\r": "\\r",
884
+ " ": "\\t",
885
+ "\v": "\\v",
886
+ "\0": "\\0",
887
+ "\u2028": "\\u2028",
888
+ "\u2029": "\\u2029"
889
+ };
890
+ if (replacements[c3]) {
891
+ return replacements[c3];
892
+ }
893
+ if (c3 < " ") {
894
+ const hexString = c3.charCodeAt(0).toString(16);
895
+ return "\\x" + ("00" + hexString).substring(hexString.length);
896
+ }
897
+ return c3;
898
+ }
899
+ function syntaxError(message) {
900
+ const err = new SyntaxError(message);
901
+ err.lineNumber = line;
902
+ err.columnNumber = column;
903
+ return err;
904
+ }
905
+ }
906
+ });
907
+
908
+ // node_modules/json5/lib/stringify.js
909
+ var require_stringify = __commonJS({
910
+ "node_modules/json5/lib/stringify.js"(exports, module) {
911
+ var util = require_util();
912
+ module.exports = function stringify(value, replacer, space) {
913
+ const stack = [];
914
+ let indent = "";
915
+ let propertyList;
916
+ let replacerFunc;
917
+ let gap = "";
918
+ let quote;
919
+ if (replacer != null && typeof replacer === "object" && !Array.isArray(replacer)) {
920
+ space = replacer.space;
921
+ quote = replacer.quote;
922
+ replacer = replacer.replacer;
923
+ }
924
+ if (typeof replacer === "function") {
925
+ replacerFunc = replacer;
926
+ } else if (Array.isArray(replacer)) {
927
+ propertyList = [];
928
+ for (const v of replacer) {
929
+ let item;
930
+ if (typeof v === "string") {
931
+ item = v;
932
+ } else if (typeof v === "number" || v instanceof String || v instanceof Number) {
933
+ item = String(v);
934
+ }
935
+ if (item !== void 0 && propertyList.indexOf(item) < 0) {
936
+ propertyList.push(item);
937
+ }
938
+ }
939
+ }
940
+ if (space instanceof Number) {
941
+ space = Number(space);
942
+ } else if (space instanceof String) {
943
+ space = String(space);
944
+ }
945
+ if (typeof space === "number") {
946
+ if (space > 0) {
947
+ space = Math.min(10, Math.floor(space));
948
+ gap = " ".substr(0, space);
949
+ }
950
+ } else if (typeof space === "string") {
951
+ gap = space.substr(0, 10);
952
+ }
953
+ return serializeProperty("", { "": value });
954
+ function serializeProperty(key, holder) {
955
+ let value2 = holder[key];
956
+ if (value2 != null) {
957
+ if (typeof value2.toJSON5 === "function") {
958
+ value2 = value2.toJSON5(key);
959
+ } else if (typeof value2.toJSON === "function") {
960
+ value2 = value2.toJSON(key);
961
+ }
962
+ }
963
+ if (replacerFunc) {
964
+ value2 = replacerFunc.call(holder, key, value2);
965
+ }
966
+ if (value2 instanceof Number) {
967
+ value2 = Number(value2);
968
+ } else if (value2 instanceof String) {
969
+ value2 = String(value2);
970
+ } else if (value2 instanceof Boolean) {
971
+ value2 = value2.valueOf();
972
+ }
973
+ switch (value2) {
974
+ case null:
975
+ return "null";
976
+ case true:
977
+ return "true";
978
+ case false:
979
+ return "false";
980
+ }
981
+ if (typeof value2 === "string") {
982
+ return quoteString(value2, false);
983
+ }
984
+ if (typeof value2 === "number") {
985
+ return String(value2);
986
+ }
987
+ if (typeof value2 === "object") {
988
+ return Array.isArray(value2) ? serializeArray(value2) : serializeObject(value2);
989
+ }
990
+ return void 0;
991
+ }
992
+ function quoteString(value2) {
993
+ const quotes = {
994
+ "'": 0.1,
995
+ '"': 0.2
996
+ };
997
+ const replacements = {
998
+ "'": "\\'",
999
+ '"': '\\"',
1000
+ "\\": "\\\\",
1001
+ "\b": "\\b",
1002
+ "\f": "\\f",
1003
+ "\n": "\\n",
1004
+ "\r": "\\r",
1005
+ " ": "\\t",
1006
+ "\v": "\\v",
1007
+ "\0": "\\0",
1008
+ "\u2028": "\\u2028",
1009
+ "\u2029": "\\u2029"
1010
+ };
1011
+ let product = "";
1012
+ for (let i = 0; i < value2.length; i++) {
1013
+ const c2 = value2[i];
1014
+ switch (c2) {
1015
+ case "'":
1016
+ case '"':
1017
+ quotes[c2]++;
1018
+ product += c2;
1019
+ continue;
1020
+ case "\0":
1021
+ if (util.isDigit(value2[i + 1])) {
1022
+ product += "\\x00";
1023
+ continue;
1024
+ }
1025
+ }
1026
+ if (replacements[c2]) {
1027
+ product += replacements[c2];
1028
+ continue;
1029
+ }
1030
+ if (c2 < " ") {
1031
+ let hexString = c2.charCodeAt(0).toString(16);
1032
+ product += "\\x" + ("00" + hexString).substring(hexString.length);
1033
+ continue;
1034
+ }
1035
+ product += c2;
1036
+ }
1037
+ const quoteChar = quote || Object.keys(quotes).reduce((a, b) => quotes[a] < quotes[b] ? a : b);
1038
+ product = product.replace(new RegExp(quoteChar, "g"), replacements[quoteChar]);
1039
+ return quoteChar + product + quoteChar;
1040
+ }
1041
+ function serializeObject(value2) {
1042
+ if (stack.indexOf(value2) >= 0) {
1043
+ throw TypeError("Converting circular structure to JSON5");
1044
+ }
1045
+ stack.push(value2);
1046
+ let stepback = indent;
1047
+ indent = indent + gap;
1048
+ let keys = propertyList || Object.keys(value2);
1049
+ let partial = [];
1050
+ for (const key of keys) {
1051
+ const propertyString = serializeProperty(key, value2);
1052
+ if (propertyString !== void 0) {
1053
+ let member = serializeKey(key) + ":";
1054
+ if (gap !== "") {
1055
+ member += " ";
1056
+ }
1057
+ member += propertyString;
1058
+ partial.push(member);
1059
+ }
1060
+ }
1061
+ let final;
1062
+ if (partial.length === 0) {
1063
+ final = "{}";
1064
+ } else {
1065
+ let properties;
1066
+ if (gap === "") {
1067
+ properties = partial.join(",");
1068
+ final = "{" + properties + "}";
1069
+ } else {
1070
+ let separator = ",\n" + indent;
1071
+ properties = partial.join(separator);
1072
+ final = "{\n" + indent + properties + ",\n" + stepback + "}";
1073
+ }
1074
+ }
1075
+ stack.pop();
1076
+ indent = stepback;
1077
+ return final;
1078
+ }
1079
+ function serializeKey(key) {
1080
+ if (key.length === 0) {
1081
+ return quoteString(key, true);
1082
+ }
1083
+ const firstChar = String.fromCodePoint(key.codePointAt(0));
1084
+ if (!util.isIdStartChar(firstChar)) {
1085
+ return quoteString(key, true);
1086
+ }
1087
+ for (let i = firstChar.length; i < key.length; i++) {
1088
+ if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
1089
+ return quoteString(key, true);
1090
+ }
1091
+ }
1092
+ return key;
1093
+ }
1094
+ function serializeArray(value2) {
1095
+ if (stack.indexOf(value2) >= 0) {
1096
+ throw TypeError("Converting circular structure to JSON5");
1097
+ }
1098
+ stack.push(value2);
1099
+ let stepback = indent;
1100
+ indent = indent + gap;
1101
+ let partial = [];
1102
+ for (let i = 0; i < value2.length; i++) {
1103
+ const propertyString = serializeProperty(String(i), value2);
1104
+ partial.push(propertyString !== void 0 ? propertyString : "null");
1105
+ }
1106
+ let final;
1107
+ if (partial.length === 0) {
1108
+ final = "[]";
1109
+ } else {
1110
+ if (gap === "") {
1111
+ let properties = partial.join(",");
1112
+ final = "[" + properties + "]";
1113
+ } else {
1114
+ let separator = ",\n" + indent;
1115
+ let properties = partial.join(separator);
1116
+ final = "[\n" + indent + properties + ",\n" + stepback + "]";
1117
+ }
1118
+ }
1119
+ stack.pop();
1120
+ indent = stepback;
1121
+ return final;
1122
+ }
1123
+ };
1124
+ }
1125
+ });
1126
+
1127
+ // node_modules/json5/lib/index.js
1128
+ var require_lib = __commonJS({
1129
+ "node_modules/json5/lib/index.js"(exports, module) {
1130
+ var parse = require_parse();
1131
+ var stringify = require_stringify();
1132
+ var JSON52 = {
1133
+ parse,
1134
+ stringify
1135
+ };
1136
+ module.exports = JSON52;
1137
+ }
1138
+ });
1139
+
1140
+ // src/setup.ts
1141
+ var import_json5 = __toESM(require_lib(), 1);
1142
+ import * as fs from "node:fs";
1143
+ import * as path from "node:path";
1144
+ import * as crypto from "node:crypto";
1145
+ import { execSync } from "node:child_process";
1146
+ import * as readline from "node:readline";
1147
+ var PLUGIN_NAME = "openclaw-telegram-manager";
1148
+ var PLUGIN_VERSION = JSON.parse(
1149
+ fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8")
1150
+ ).version;
1151
+ var MIN_OPENCLAW_VERSION = "2026.1.0";
1152
+ var INCLUDE_FILENAME = "telegram-manager.generated.groups.json5";
1153
+ var REGISTRY_FILENAME = "topics.json";
1154
+ var PLUGIN_FILES = ["openclaw.plugin.json", "dist/plugin.js", "skills", "package.json"];
1155
+ var REQUIRED_PLUGIN_FILES = ["openclaw.plugin.json", "dist/plugin.js"];
1156
+ var MEMORY_FLUSH_MARKER = "topic folder";
1157
+ var SETUP_REGISTRY_VERSION = 4;
1158
+ var MEMORY_FLUSH_INSTRUCTION = 'If you are working on a Telegram topic folder (projects/<slug>/), update its STATUS.md with current "Last done (UTC)" and "Next actions (now)" before this context is compacted.';
1159
+ var SETUP_MARKER_START = "<!-- TM_AUTOPILOT_START -->";
1160
+ var SETUP_MARKER_END = "<!-- TM_AUTOPILOT_END -->";
1161
+ var SETUP_HEARTBEAT_BLOCK = `${SETUP_MARKER_START}
1162
+ ## Topic Manager \u2014 Balanced Autopilot
24
1163
 
25
1164
  Execute these steps IN ORDER. Do not skip steps.
26
1165
 
@@ -30,624 +1169,559 @@ Execute these steps IN ORDER. Do not skip steps.
30
1169
  post a brief nudge in that topic asking the user for a status update.
31
1170
  3. If no actions were taken in steps 1-2, do nothing (HEARTBEAT_OK).
32
1171
  ${SETUP_MARKER_END}`;
33
- // ── Colors (zero dependencies, respects NO_COLOR / non-TTY) ──────────
34
- const useColor = process.stdout.isTTY === true &&
35
- !process.env['NO_COLOR'] &&
36
- process.env['TERM'] !== 'dumb';
37
- const c = {
38
- reset: useColor ? '\x1b[0m' : '',
39
- bold: useColor ? '\x1b[1m' : '',
40
- dim: useColor ? '\x1b[2m' : '',
41
- green: useColor ? '\x1b[32m' : '',
42
- yellow: useColor ? '\x1b[33m' : '',
43
- red: useColor ? '\x1b[31m' : '',
44
- cyan: useColor ? '\x1b[36m' : '',
45
- magenta: useColor ? '\x1b[35m' : '',
1172
+ var useColor = process.stdout.isTTY === true && !process.env["NO_COLOR"] && process.env["TERM"] !== "dumb";
1173
+ var c = {
1174
+ reset: useColor ? "\x1B[0m" : "",
1175
+ bold: useColor ? "\x1B[1m" : "",
1176
+ dim: useColor ? "\x1B[2m" : "",
1177
+ green: useColor ? "\x1B[32m" : "",
1178
+ yellow: useColor ? "\x1B[33m" : "",
1179
+ red: useColor ? "\x1B[31m" : "",
1180
+ cyan: useColor ? "\x1B[36m" : "",
1181
+ magenta: useColor ? "\x1B[35m" : ""
46
1182
  };
47
- // ── Spinner (zero dependencies, TTY-only) ────────────────────────────
48
- let spinnerTimer = null;
1183
+ var spinnerTimer = null;
49
1184
  function startSpinner(msg) {
50
- stopSpinner();
51
- if (!process.stdout.isTTY)
52
- return;
53
- const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
54
- let i = 0;
55
- const render = () => {
56
- process.stdout.write(`\r ${c.cyan}${frames[i++ % frames.length]}${c.reset} ${msg}`);
57
- };
58
- render();
59
- spinnerTimer = setInterval(render, 80);
1185
+ stopSpinner();
1186
+ if (!process.stdout.isTTY) return;
1187
+ const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1188
+ let i = 0;
1189
+ const render = () => {
1190
+ process.stdout.write(`\r ${c.cyan}${frames[i++ % frames.length]}${c.reset} ${msg}`);
1191
+ };
1192
+ render();
1193
+ spinnerTimer = setInterval(render, 80);
60
1194
  }
61
1195
  function stopSpinner() {
62
- if (spinnerTimer) {
63
- clearInterval(spinnerTimer);
64
- spinnerTimer = null;
65
- process.stdout.write('\r\x1b[2K');
66
- }
1196
+ if (spinnerTimer) {
1197
+ clearInterval(spinnerTimer);
1198
+ spinnerTimer = null;
1199
+ process.stdout.write("\r\x1B[2K");
1200
+ }
67
1201
  }
68
- // ── Logging helpers ───────────────────────────────────────────────────
69
1202
  function ok(msg) {
70
- stopSpinner();
71
- console.log(` ${c.green}✓${c.reset} ${msg}`);
1203
+ stopSpinner();
1204
+ console.log(` ${c.green}\u2713${c.reset} ${msg}`);
72
1205
  }
73
1206
  function warn(msg) {
74
- stopSpinner();
75
- console.warn(` ${c.yellow}⚠${c.reset} ${c.yellow}${msg}${c.reset}`);
1207
+ stopSpinner();
1208
+ console.warn(` ${c.yellow}\u26A0${c.reset} ${c.yellow}${msg}${c.reset}`);
76
1209
  }
77
1210
  function fail(msg) {
78
- stopSpinner();
79
- console.error(` ${c.red}✗${c.reset} ${c.red}${msg}${c.reset}`);
1211
+ stopSpinner();
1212
+ console.error(` ${c.red}\u2717${c.reset} ${c.red}${msg}${c.reset}`);
80
1213
  }
81
1214
  function info(msg) {
82
- console.log(` ${c.dim}${msg}${c.reset}`);
1215
+ console.log(` ${c.dim}${msg}${c.reset}`);
83
1216
  }
84
1217
  function banner(title, subtitle) {
85
- console.log('');
86
- console.log(` ${c.cyan}◆${c.reset} ${c.bold}${title}${c.reset}${subtitle ? ` ${c.dim}${subtitle}${c.reset}` : ''}`);
87
- console.log(` ${c.dim}│${c.reset}`);
1218
+ console.log("");
1219
+ console.log(` ${c.cyan}\u25C6${c.reset} ${c.bold}${title}${c.reset}${subtitle ? ` ${c.dim}${subtitle}${c.reset}` : ""}`);
1220
+ console.log(` ${c.dim}\u2502${c.reset}`);
88
1221
  }
89
1222
  function footer(msg) {
90
- console.log(` ${c.dim}│${c.reset}`);
91
- console.log(` ${c.green}◆${c.reset} ${c.bold}${msg}${c.reset}`);
92
- console.log('');
1223
+ console.log(` ${c.dim}\u2502${c.reset}`);
1224
+ console.log(` ${c.green}\u25C6${c.reset} ${c.bold}${msg}${c.reset}`);
1225
+ console.log("");
93
1226
  }
94
1227
  function confirm(question) {
95
- if (!process.stdin.isTTY)
96
- return Promise.resolve(false);
97
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
98
- return new Promise((resolve) => {
99
- rl.question(` ${c.yellow}?${c.reset} ${question} ${c.dim}[y/N]${c.reset} `, (answer) => {
100
- rl.close();
101
- resolve(answer.trim().toLowerCase() === 'y');
102
- });
103
- });
104
- }
105
- // ── Entry point ───────────────────────────────────────────────────────
106
- const command = process.argv[2] ?? 'setup';
107
- if (command === 'setup') {
108
- runSetup().catch((err) => {
109
- stopSpinner();
110
- console.error('Setup failed:', err instanceof Error ? err.message : String(err));
111
- process.exit(1);
112
- });
113
- }
114
- else if (command === 'uninstall') {
115
- runUninstall().catch((err) => {
116
- stopSpinner();
117
- console.error('Uninstall failed:', err instanceof Error ? err.message : String(err));
118
- process.exit(1);
1228
+ if (!process.stdin.isTTY) return Promise.resolve(false);
1229
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1230
+ return new Promise((resolve2) => {
1231
+ rl.question(` ${c.yellow}?${c.reset} ${question} ${c.dim}[y/N]${c.reset} `, (answer) => {
1232
+ rl.close();
1233
+ resolve2(answer.trim().toLowerCase() === "y");
119
1234
  });
1235
+ });
120
1236
  }
121
- else {
122
- console.error(`Unknown command: ${command}`);
123
- console.error(`Usage: ${PLUGIN_NAME} [setup|uninstall [--purge-data]]`);
1237
+ var command = process.argv[2] ?? "setup";
1238
+ if (command === "setup") {
1239
+ runSetup().catch((err) => {
1240
+ stopSpinner();
1241
+ console.error("Setup failed:", err instanceof Error ? err.message : String(err));
1242
+ process.exit(1);
1243
+ });
1244
+ } else if (command === "uninstall") {
1245
+ runUninstall().catch((err) => {
1246
+ stopSpinner();
1247
+ console.error("Uninstall failed:", err instanceof Error ? err.message : String(err));
124
1248
  process.exit(1);
1249
+ });
1250
+ } else {
1251
+ console.error(`Unknown command: ${command}`);
1252
+ console.error(`Usage: ${PLUGIN_NAME} [setup|uninstall [--purge-data]]`);
1253
+ process.exit(1);
125
1254
  }
126
- // ── Setup ─────────────────────────────────────────────────────────────
127
1255
  async function runSetup() {
128
- banner(PLUGIN_NAME, `v${PLUGIN_VERSION}`);
129
- startSpinner('Checking OpenClaw version…');
130
- const version = checkOpenClawVersion();
131
- ok(`OpenClaw ${c.dim}${version}${c.reset}`);
132
- startSpinner('Locating config…');
133
- const configDir = locateConfigDir();
134
- checkDirPermissions(configDir);
135
- ok(`Config ${c.dim}${configDir}${c.reset}`);
136
- startSpinner('Installing plugin…');
137
- installPlugin(configDir);
138
- startSpinner('Patching config…');
139
- const existingGroups = patchConfig(configDir);
140
- startSpinner('Patching memory flush…');
141
- patchMemoryFlush(configDir);
142
- startSpinner('Preparing workspace…');
143
- const projectsDir = path.join(configDir, 'workspace', 'projects');
144
- ensureDir(projectsDir);
145
- initRegistry(projectsDir);
146
- createEmptyInclude(configDir, existingGroups);
147
- ok('Workspace ready');
148
- startSpinner('Enabling autopilot…');
149
- writeHeartbeat(configDir);
150
- ok('Autopilot enabled');
151
- startSpinner('Restarting gateway…');
152
- if (triggerRestart())
153
- ok('Gateway restarted');
154
- footer('Setup complete');
155
- console.log(` ${c.dim}Next steps:${c.reset}`);
156
- console.log(` ${c.dim}1.${c.reset} Open any Telegram forum topic`);
157
- console.log(` ${c.dim}2.${c.reset} Type ${c.cyan}/tm init${c.reset}`);
158
- console.log(` ${c.dim}3.${c.reset} The topic will be set up with persistent memory`);
159
- console.log('');
160
- console.log(` ${c.dim}Autopilot is active health checks and daily reports run automatically.${c.reset}`);
161
- console.log(` ${c.dim}To disable: ${c.reset}${c.cyan}/tm autopilot disable${c.reset}`);
162
- console.log('');
1256
+ banner(PLUGIN_NAME, `v${PLUGIN_VERSION}`);
1257
+ startSpinner("Checking OpenClaw version\u2026");
1258
+ const version = checkOpenClawVersion();
1259
+ ok(`OpenClaw ${c.dim}${version}${c.reset}`);
1260
+ startSpinner("Locating config\u2026");
1261
+ const configDir = locateConfigDir();
1262
+ checkDirPermissions(configDir);
1263
+ ok(`Config ${c.dim}${configDir}${c.reset}`);
1264
+ startSpinner("Installing plugin\u2026");
1265
+ installPlugin(configDir);
1266
+ startSpinner("Patching config\u2026");
1267
+ const existingGroups = patchConfig(configDir);
1268
+ startSpinner("Patching memory flush\u2026");
1269
+ patchMemoryFlush(configDir);
1270
+ startSpinner("Preparing workspace\u2026");
1271
+ const projectsDir = path.join(configDir, "workspace", "projects");
1272
+ ensureDir(projectsDir);
1273
+ initRegistry(projectsDir);
1274
+ createEmptyInclude(configDir, existingGroups);
1275
+ ok("Workspace ready");
1276
+ startSpinner("Enabling autopilot\u2026");
1277
+ writeHeartbeat(configDir);
1278
+ ok("Autopilot enabled");
1279
+ startSpinner("Restarting gateway\u2026");
1280
+ if (triggerRestart()) ok("Gateway restarted");
1281
+ footer("Setup complete");
1282
+ console.log(` ${c.dim}Next steps:${c.reset}`);
1283
+ console.log(` ${c.dim}1.${c.reset} Open any Telegram forum topic`);
1284
+ console.log(` ${c.dim}2.${c.reset} Type ${c.cyan}/tm init${c.reset}`);
1285
+ console.log(` ${c.dim}3.${c.reset} The topic will be set up with persistent memory`);
1286
+ console.log("");
1287
+ console.log(` ${c.dim}Autopilot is active \u2014 health checks and daily reports run automatically.${c.reset}`);
1288
+ console.log(` ${c.dim}To disable: ${c.reset}${c.cyan}/tm autopilot disable${c.reset}`);
1289
+ console.log("");
163
1290
  }
164
- // ── Uninstall ─────────────────────────────────────────────────────────
165
1291
  async function runUninstall() {
166
- banner(PLUGIN_NAME, 'uninstall');
167
- startSpinner('Locating config…');
168
- const configDir = locateConfigDir();
169
- ok(`Config ${c.dim}${configDir}${c.reset}`);
170
- startSpinner('Removing plugin…');
171
- removePluginDir(configDir);
172
- unpatchConfig(configDir);
173
- unpatchMemoryFlush(configDir);
174
- removeFile(path.join(configDir, INCLUDE_FILENAME));
175
- ok('Plugin files removed');
176
- startSpinner('Restarting gateway…');
177
- if (triggerRestart())
178
- ok('Gateway restarted');
179
- const projectsDir = path.join(configDir, 'workspace', 'projects');
180
- if (fs.existsSync(projectsDir)) {
181
- const purge = process.argv.includes('--purge-data')
182
- || await confirm(`Also delete the plugin's stored data at ${projectsDir}? This cannot be undone.`);
183
- if (purge) {
184
- startSpinner('Removing workspace data…');
185
- fs.rmSync(projectsDir, { recursive: true });
186
- ok('Workspace data removed');
187
- }
188
- else {
189
- ok(`Workspace data kept ${c.dim}${projectsDir}${c.reset}`);
190
- info('Run with --purge-data to remove it later.');
191
- }
1292
+ banner(PLUGIN_NAME, "uninstall");
1293
+ startSpinner("Locating config\u2026");
1294
+ const configDir = locateConfigDir();
1295
+ ok(`Config ${c.dim}${configDir}${c.reset}`);
1296
+ startSpinner("Removing plugin\u2026");
1297
+ removePluginDir(configDir);
1298
+ unpatchConfig(configDir);
1299
+ unpatchMemoryFlush(configDir);
1300
+ removeFile(path.join(configDir, INCLUDE_FILENAME));
1301
+ ok("Plugin files removed");
1302
+ startSpinner("Restarting gateway\u2026");
1303
+ if (triggerRestart()) ok("Gateway restarted");
1304
+ const projectsDir = path.join(configDir, "workspace", "projects");
1305
+ if (fs.existsSync(projectsDir)) {
1306
+ const purge = process.argv.includes("--purge-data") || await confirm(`Also delete the plugin's stored data at ${projectsDir}? This cannot be undone.`);
1307
+ if (purge) {
1308
+ startSpinner("Removing workspace data\u2026");
1309
+ fs.rmSync(projectsDir, { recursive: true });
1310
+ ok("Workspace data removed");
1311
+ } else {
1312
+ ok(`Workspace data kept ${c.dim}${projectsDir}${c.reset}`);
1313
+ info("Run with --purge-data to remove it later.");
192
1314
  }
193
- footer('Uninstall complete');
1315
+ }
1316
+ footer("Uninstall complete");
194
1317
  }
195
- // ── Setup step implementations ────────────────────────────────────────
196
1318
  function checkOpenClawVersion() {
197
- let version;
198
- try {
199
- version = execSync('openclaw --version', { encoding: 'utf-8' }).trim();
200
- }
201
- catch {
202
- fail('OpenClaw not found. Install OpenClaw (>=2026.1.0) first.');
203
- process.exit(1);
204
- }
205
- const match = version.match(/(\d+\.\d+\.\d+)/);
206
- if (!match) {
207
- warn(`Could not parse version from "${version}". Proceeding anyway.`);
208
- return version;
209
- }
210
- const versionStr = match[1];
211
- if (compareVersions(versionStr, MIN_OPENCLAW_VERSION) < 0) {
212
- fail(`OpenClaw ${versionStr} found, requires >=${MIN_OPENCLAW_VERSION}. Please upgrade.`);
213
- process.exit(1);
214
- }
215
- return versionStr;
1319
+ let version;
1320
+ try {
1321
+ version = execSync("openclaw --version", { encoding: "utf-8" }).trim();
1322
+ } catch {
1323
+ fail("OpenClaw not found. Install OpenClaw (>=2026.1.0) first.");
1324
+ process.exit(1);
1325
+ }
1326
+ const match = version.match(/(\d+\.\d+\.\d+)/);
1327
+ if (!match) {
1328
+ warn(`Could not parse version from "${version}". Proceeding anyway.`);
1329
+ return version;
1330
+ }
1331
+ const versionStr = match[1];
1332
+ if (compareVersions(versionStr, MIN_OPENCLAW_VERSION) < 0) {
1333
+ fail(`OpenClaw ${versionStr} found, requires >=${MIN_OPENCLAW_VERSION}. Please upgrade.`);
1334
+ process.exit(1);
1335
+ }
1336
+ return versionStr;
216
1337
  }
217
1338
  function locateConfigDir() {
218
- const envDir = process.env['OPENCLAW_CONFIG_DIR'];
219
- if (envDir && fs.existsSync(envDir)) {
220
- return path.resolve(envDir);
221
- }
222
- const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';
223
- const defaultDir = path.join(homeDir, '.openclaw');
224
- if (fs.existsSync(defaultDir)) {
225
- return defaultDir;
226
- }
227
- let dir = process.cwd();
228
- while (dir !== path.dirname(dir)) {
229
- if (fs.existsSync(path.join(dir, 'openclaw.json'))) {
230
- return dir;
231
- }
232
- dir = path.dirname(dir);
1339
+ const envDir = process.env["OPENCLAW_CONFIG_DIR"];
1340
+ if (envDir && fs.existsSync(envDir)) {
1341
+ return path.resolve(envDir);
1342
+ }
1343
+ const homeDir = process.env["HOME"] ?? process.env["USERPROFILE"] ?? "";
1344
+ const defaultDir = path.join(homeDir, ".openclaw");
1345
+ if (fs.existsSync(defaultDir)) {
1346
+ return defaultDir;
1347
+ }
1348
+ let dir = process.cwd();
1349
+ while (dir !== path.dirname(dir)) {
1350
+ if (fs.existsSync(path.join(dir, "openclaw.json"))) {
1351
+ return dir;
233
1352
  }
234
- fail('Could not find OpenClaw config directory. Set $OPENCLAW_CONFIG_DIR or ensure ~/.openclaw/ exists.');
235
- process.exit(1);
1353
+ dir = path.dirname(dir);
1354
+ }
1355
+ fail("Could not find OpenClaw config directory. Set $OPENCLAW_CONFIG_DIR or ensure ~/.openclaw/ exists.");
1356
+ process.exit(1);
236
1357
  }
237
1358
  function checkDirPermissions(dir) {
238
- try {
239
- const stat = fs.statSync(dir);
240
- const mode = stat.mode;
241
- const permissions = (mode & 0o777).toString(8);
242
- if (mode & 0o002) {
243
- warn(`${dir} is world-writable (${permissions}). Consider chmod 700.`);
244
- }
245
- else if (mode & 0o020) {
246
- warn(`${dir} is group-writable (${permissions}). Consider chmod 700.`);
247
- }
248
- }
249
- catch {
250
- warn(`Could not check permissions for ${dir}.`);
1359
+ try {
1360
+ const stat = fs.statSync(dir);
1361
+ const mode = stat.mode;
1362
+ const permissions = (mode & 511).toString(8);
1363
+ if (mode & 2) {
1364
+ warn(`${dir} is world-writable (${permissions}). Consider chmod 700.`);
1365
+ } else if (mode & 16) {
1366
+ warn(`${dir} is group-writable (${permissions}). Consider chmod 700.`);
251
1367
  }
1368
+ } catch {
1369
+ warn(`Could not check permissions for ${dir}.`);
1370
+ }
252
1371
  }
253
1372
  function installPlugin(configDir) {
254
- const extDir = path.join(configDir, 'extensions', PLUGIN_NAME);
255
- const alreadyExists = fs.existsSync(path.join(extDir, 'openclaw.plugin.json'));
256
- const pkgRoot = findPackageRoot();
257
- if (pkgRoot) {
258
- for (const req of REQUIRED_PLUGIN_FILES) {
259
- if (!fs.existsSync(path.join(pkgRoot, req))) {
260
- fail(`Required file missing: ${req}. Was \`npm run build\` run before publishing?`);
261
- process.exit(1);
262
- }
263
- }
264
- fs.mkdirSync(extDir, { recursive: true });
265
- for (const entry of PLUGIN_FILES) {
266
- const src = path.join(pkgRoot, entry);
267
- if (!fs.existsSync(src))
268
- continue;
269
- const dest = path.join(extDir, entry);
270
- fs.mkdirSync(path.dirname(dest), { recursive: true });
271
- copyRecursive(src, dest);
272
- }
273
- ok(alreadyExists ? 'Plugin updated' : 'Plugin installed');
274
- return;
275
- }
276
- if (alreadyExists) {
277
- ok('Plugin already installed');
278
- return;
279
- }
280
- try {
281
- execSync(`openclaw plugins install ${PLUGIN_NAME}`, {
282
- encoding: 'utf-8',
283
- stdio: 'inherit',
284
- });
285
- ok('Plugin installed');
1373
+ const extDir = path.join(configDir, "extensions", PLUGIN_NAME);
1374
+ const alreadyExists = fs.existsSync(path.join(extDir, "openclaw.plugin.json"));
1375
+ const pkgRoot = findPackageRoot();
1376
+ if (pkgRoot) {
1377
+ for (const req of REQUIRED_PLUGIN_FILES) {
1378
+ if (!fs.existsSync(path.join(pkgRoot, req))) {
1379
+ fail(`Required file missing: ${req}. Was \`npm run build\` run before publishing?`);
1380
+ process.exit(1);
1381
+ }
286
1382
  }
287
- catch {
288
- warn('Could not install plugin. You may need to install manually.');
1383
+ fs.mkdirSync(extDir, { recursive: true });
1384
+ for (const entry of PLUGIN_FILES) {
1385
+ const src = path.join(pkgRoot, entry);
1386
+ if (!fs.existsSync(src)) continue;
1387
+ const dest = path.join(extDir, entry);
1388
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
1389
+ copyRecursive(src, dest);
289
1390
  }
1391
+ ok(alreadyExists ? "Plugin updated" : "Plugin installed");
1392
+ return;
1393
+ }
1394
+ if (alreadyExists) {
1395
+ ok("Plugin already installed");
1396
+ return;
1397
+ }
1398
+ try {
1399
+ execSync(`openclaw plugins install ${PLUGIN_NAME}`, {
1400
+ encoding: "utf-8",
1401
+ stdio: "inherit"
1402
+ });
1403
+ ok("Plugin installed");
1404
+ } catch {
1405
+ warn("Could not install plugin. You may need to install manually.");
1406
+ }
290
1407
  }
291
1408
  function patchConfig(configDir) {
292
- const configPath = path.join(configDir, 'openclaw.json');
293
- if (!fs.existsSync(configPath)) {
294
- warn(`${configPath} not found. Skipping config patch.`);
295
- return null;
296
- }
297
- let content;
298
- try {
299
- content = fs.readFileSync(configPath, 'utf-8');
300
- }
301
- catch {
302
- warn(`Could not read ${configPath}. Skipping config patch.`);
303
- return null;
304
- }
305
- let config;
306
- try {
307
- config = JSON.parse(content);
308
- }
309
- catch {
310
- warn('Could not parse openclaw.json. Please manually add the $include reference.');
311
- info(`Add to channels.telegram.groups: { "$include": "./${INCLUDE_FILENAME}" }`);
312
- return null;
313
- }
314
- const hasInclude = content.includes(INCLUDE_FILENAME);
315
- const hasStaleSkillsDir = content.includes(PLUGIN_NAME) && content.includes('extraDirs');
316
- // Clean up stale skills.load.extraDirs from pre-v1.4 installs
317
- if (hasStaleSkillsDir) {
318
- const skills = config['skills'];
319
- const load = skills?.['load'];
320
- if (load && Array.isArray(load['extraDirs'])) {
321
- load['extraDirs'] = load['extraDirs'].filter((d) => !d.includes(PLUGIN_NAME));
322
- if (load['extraDirs'].length === 0)
323
- delete load['extraDirs'];
324
- if (Object.keys(load).length === 0)
325
- delete skills['load'];
326
- if (Object.keys(skills).length === 0)
327
- delete config['skills'];
328
- }
329
- // Write the cleaned config even if $include is already present
330
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
331
- }
332
- if (hasInclude) {
333
- ok(hasStaleSkillsDir ? 'Config patched (removed stale skills entry)' : 'Config already patched');
334
- return null;
1409
+ const configPath = path.join(configDir, "openclaw.json");
1410
+ if (!fs.existsSync(configPath)) {
1411
+ warn(`${configPath} not found. Skipping config patch.`);
1412
+ return null;
1413
+ }
1414
+ let content;
1415
+ try {
1416
+ content = fs.readFileSync(configPath, "utf-8");
1417
+ } catch {
1418
+ warn(`Could not read ${configPath}. Skipping config patch.`);
1419
+ return null;
1420
+ }
1421
+ let config;
1422
+ try {
1423
+ config = JSON.parse(content);
1424
+ } catch {
1425
+ warn("Could not parse openclaw.json. Please manually add the $include reference.");
1426
+ info(`Add to channels.telegram.groups: { "$include": "./${INCLUDE_FILENAME}" }`);
1427
+ return null;
1428
+ }
1429
+ const hasInclude = content.includes(INCLUDE_FILENAME);
1430
+ const hasStaleSkillsDir = content.includes(PLUGIN_NAME) && content.includes("extraDirs");
1431
+ if (hasStaleSkillsDir) {
1432
+ const skills = config["skills"];
1433
+ const load = skills?.["load"];
1434
+ if (load && Array.isArray(load["extraDirs"])) {
1435
+ load["extraDirs"] = load["extraDirs"].filter(
1436
+ (d) => !d.includes(PLUGIN_NAME)
1437
+ );
1438
+ if (load["extraDirs"].length === 0) delete load["extraDirs"];
1439
+ if (Object.keys(load).length === 0) delete skills["load"];
1440
+ if (Object.keys(skills).length === 0) delete config["skills"];
335
1441
  }
336
- // Extract existing inline groups before overwriting
337
- let existingGroups = null;
338
- if (!hasInclude) {
339
- if (!config['channels'])
340
- config['channels'] = {};
341
- const channels = config['channels'];
342
- if (!channels['telegram'])
343
- channels['telegram'] = {};
344
- const telegram = channels['telegram'];
345
- const groups = telegram['groups'];
346
- if (groups && typeof groups === 'object' && !('$include' in groups)) {
347
- existingGroups = groups;
348
- }
349
- telegram['groups'] = { $include: `./${INCLUDE_FILENAME}` };
1442
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
1443
+ }
1444
+ if (hasInclude) {
1445
+ ok(hasStaleSkillsDir ? "Config patched (removed stale skills entry)" : "Config already patched");
1446
+ return null;
1447
+ }
1448
+ let existingGroups = null;
1449
+ if (!hasInclude) {
1450
+ if (!config["channels"]) config["channels"] = {};
1451
+ const channels = config["channels"];
1452
+ if (!channels["telegram"]) channels["telegram"] = {};
1453
+ const telegram = channels["telegram"];
1454
+ const groups = telegram["groups"];
1455
+ if (groups && typeof groups === "object" && !("$include" in groups)) {
1456
+ existingGroups = groups;
350
1457
  }
351
- const bakPath = configPath + '.bak';
352
- fs.copyFileSync(configPath, bakPath);
353
- const newContent = JSON.stringify(config, null, 2) + '\n';
354
- fs.writeFileSync(configPath, newContent, { mode: 0o600 });
355
- ok('Config patched');
356
- return existingGroups;
1458
+ telegram["groups"] = { $include: `./${INCLUDE_FILENAME}` };
1459
+ }
1460
+ const bakPath = configPath + ".bak";
1461
+ fs.copyFileSync(configPath, bakPath);
1462
+ const newContent = JSON.stringify(config, null, 2) + "\n";
1463
+ fs.writeFileSync(configPath, newContent, { mode: 384 });
1464
+ ok("Config patched");
1465
+ return existingGroups;
357
1466
  }
358
1467
  function initRegistry(projectsDir) {
359
- const registryPath = path.join(projectsDir, REGISTRY_FILENAME);
360
- if (fs.existsSync(registryPath)) {
361
- return;
362
- }
363
- const callbackSecret = crypto.randomBytes(32).toString('hex');
364
- const registry = {
365
- version: SETUP_REGISTRY_VERSION,
366
- topicManagerAdmins: [],
367
- callbackSecret,
368
- lastDoctorAllRunAt: null,
369
- autopilotEnabled: true,
370
- maxTopics: 100,
371
- topics: {},
372
- };
373
- fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2) + '\n', {
374
- mode: 0o600,
375
- });
1468
+ const registryPath = path.join(projectsDir, REGISTRY_FILENAME);
1469
+ if (fs.existsSync(registryPath)) {
1470
+ return;
1471
+ }
1472
+ const callbackSecret = crypto.randomBytes(32).toString("hex");
1473
+ const registry = {
1474
+ version: SETUP_REGISTRY_VERSION,
1475
+ topicManagerAdmins: [],
1476
+ callbackSecret,
1477
+ lastDoctorAllRunAt: null,
1478
+ autopilotEnabled: true,
1479
+ maxTopics: 100,
1480
+ topics: {}
1481
+ };
1482
+ fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2) + "\n", {
1483
+ mode: 384
1484
+ });
376
1485
  }
377
1486
  function createEmptyInclude(configDir, seedGroups) {
378
- const includePath = path.join(configDir, INCLUDE_FILENAME);
379
- if (fs.existsSync(includePath)) {
380
- return;
381
- }
382
- const body = seedGroups && Object.keys(seedGroups).length > 0
383
- ? JSON.stringify(seedGroups, null, 2)
384
- : '{}';
385
- const content = [
386
- '// This file is generated by telegram-manager. Do not hand-edit.',
387
- body,
388
- '',
389
- ].join('\n');
390
- fs.writeFileSync(includePath, content, { mode: 0o600 });
1487
+ const includePath = path.join(configDir, INCLUDE_FILENAME);
1488
+ if (fs.existsSync(includePath)) {
1489
+ return;
1490
+ }
1491
+ const body = seedGroups && Object.keys(seedGroups).length > 0 ? JSON.stringify(seedGroups, null, 2) : "{}";
1492
+ const content = [
1493
+ "// This file is generated by telegram-manager. Do not hand-edit.",
1494
+ body,
1495
+ ""
1496
+ ].join("\n");
1497
+ fs.writeFileSync(includePath, content, { mode: 384 });
391
1498
  }
392
1499
  function writeHeartbeat(configDir) {
393
- const heartbeatPath = path.join(configDir, 'workspace', 'HEARTBEAT.md');
394
- // Read existing content if any
395
- let content = '';
396
- try {
397
- if (fs.existsSync(heartbeatPath)) {
398
- content = fs.readFileSync(heartbeatPath, 'utf-8');
399
- }
400
- }
401
- catch {
402
- // File doesn't exist yet — that's fine
1500
+ const heartbeatPath = path.join(configDir, "workspace", "HEARTBEAT.md");
1501
+ let content = "";
1502
+ try {
1503
+ if (fs.existsSync(heartbeatPath)) {
1504
+ content = fs.readFileSync(heartbeatPath, "utf-8");
403
1505
  }
404
- // Idempotent: don't duplicate if marker already present
405
- if (content.includes(SETUP_MARKER_START)) {
406
- return;
407
- }
408
- const newContent = content
409
- ? content.trimEnd() + '\n\n' + SETUP_HEARTBEAT_BLOCK + '\n'
410
- : SETUP_HEARTBEAT_BLOCK + '\n';
411
- // Atomic write: .tmp → rename
412
- const tmpPath = heartbeatPath + '.tmp';
413
- fs.mkdirSync(path.dirname(heartbeatPath), { recursive: true });
414
- fs.writeFileSync(tmpPath, newContent, { mode: 0o640 });
415
- fs.renameSync(tmpPath, heartbeatPath);
1506
+ } catch {
1507
+ }
1508
+ if (content.includes(SETUP_MARKER_START)) {
1509
+ return;
1510
+ }
1511
+ const newContent = content ? content.trimEnd() + "\n\n" + SETUP_HEARTBEAT_BLOCK + "\n" : SETUP_HEARTBEAT_BLOCK + "\n";
1512
+ const tmpPath = heartbeatPath + ".tmp";
1513
+ fs.mkdirSync(path.dirname(heartbeatPath), { recursive: true });
1514
+ fs.writeFileSync(tmpPath, newContent, { mode: 416 });
1515
+ fs.renameSync(tmpPath, heartbeatPath);
416
1516
  }
417
- // ── Uninstall step implementations ────────────────────────────────────
418
1517
  function unpatchConfig(configDir) {
419
- const configPath = path.join(configDir, 'openclaw.json');
420
- const bakPath = configPath + '.bak';
421
- if (!fs.existsSync(configPath)) {
422
- return;
423
- }
424
- let content;
425
- try {
426
- content = fs.readFileSync(configPath, 'utf-8');
427
- }
428
- catch {
429
- warn(`Could not read ${configPath}.`);
430
- return;
431
- }
432
- const hasInclude = content.includes(INCLUDE_FILENAME);
433
- const hasSkillsDir = content.includes(PLUGIN_NAME) && content.includes('extraDirs');
434
- if (!hasInclude && !hasSkillsDir) {
435
- return;
436
- }
437
- let config;
438
- try {
439
- config = JSON.parse(content);
440
- }
441
- catch {
442
- warn('Could not parse openclaw.json. Please manually remove the $include reference.');
443
- return;
444
- }
445
- // Remove the $include reference and restore inline groups
446
- if (hasInclude) {
447
- const channels = config['channels'];
448
- const telegram = channels?.['telegram'];
449
- if (telegram) {
450
- const includePath = path.join(configDir, INCLUDE_FILENAME);
451
- let restoredGroups = null;
452
- if (fs.existsSync(includePath)) {
453
- try {
454
- const raw = fs.readFileSync(includePath, 'utf-8');
455
- const jsonBody = raw.replace(/^\s*\/\/.*$/gm, '').trim();
456
- const parsed = JSON.parse(jsonBody);
457
- if (parsed && typeof parsed === 'object' && Object.keys(parsed).length > 0) {
458
- restoredGroups = parsed;
459
- }
1518
+ const configPath = path.join(configDir, "openclaw.json");
1519
+ const bakPath = configPath + ".bak";
1520
+ if (!fs.existsSync(configPath)) {
1521
+ return;
1522
+ }
1523
+ let content;
1524
+ try {
1525
+ content = fs.readFileSync(configPath, "utf-8");
1526
+ } catch {
1527
+ warn(`Could not read ${configPath}.`);
1528
+ return;
1529
+ }
1530
+ const hasInclude = content.includes(INCLUDE_FILENAME);
1531
+ const hasSkillsDir = content.includes(PLUGIN_NAME) && content.includes("extraDirs");
1532
+ if (!hasInclude && !hasSkillsDir) {
1533
+ return;
1534
+ }
1535
+ let config;
1536
+ try {
1537
+ config = JSON.parse(content);
1538
+ } catch {
1539
+ warn("Could not parse openclaw.json. Please manually remove the $include reference.");
1540
+ return;
1541
+ }
1542
+ if (hasInclude) {
1543
+ const channels = config["channels"];
1544
+ const telegram = channels?.["telegram"];
1545
+ if (telegram) {
1546
+ const includeFilePath = path.join(configDir, INCLUDE_FILENAME);
1547
+ let restoredGroups = null;
1548
+ if (fs.existsSync(includeFilePath)) {
1549
+ try {
1550
+ const raw = fs.readFileSync(includeFilePath, "utf-8");
1551
+ const parsed = import_json5.default.parse(raw);
1552
+ const cleaned = {};
1553
+ for (const [groupId, groupVal] of Object.entries(parsed)) {
1554
+ if (groupVal && typeof groupVal === "object") {
1555
+ const groupSettings = {};
1556
+ for (const [key, val] of Object.entries(groupVal)) {
1557
+ if (key !== "topics") {
1558
+ groupSettings[key] = val;
460
1559
  }
461
- catch { /* fall through – delete key if we can't parse */ }
462
- }
463
- if (restoredGroups) {
464
- telegram['groups'] = restoredGroups;
465
- }
466
- else {
467
- delete telegram['groups'];
1560
+ }
1561
+ if (Object.keys(groupSettings).length > 0) {
1562
+ cleaned[groupId] = groupSettings;
1563
+ }
468
1564
  }
469
- if (Object.keys(telegram).length === 0)
470
- delete channels['telegram'];
471
- if (Object.keys(channels).length === 0)
472
- delete config['channels'];
1565
+ }
1566
+ if (Object.keys(cleaned).length > 0) {
1567
+ restoredGroups = cleaned;
1568
+ }
1569
+ } catch {
473
1570
  }
1571
+ }
1572
+ if (restoredGroups) {
1573
+ telegram["groups"] = restoredGroups;
1574
+ } else {
1575
+ delete telegram["groups"];
1576
+ }
1577
+ if (Object.keys(telegram).length === 0) delete channels["telegram"];
1578
+ if (Object.keys(channels).length === 0) delete config["channels"];
474
1579
  }
475
- // Remove stale skills.load.extraDirs entry from pre-v1.4 installs
476
- if (hasSkillsDir) {
477
- const skills = config['skills'];
478
- const load = skills?.['load'];
479
- if (load && Array.isArray(load['extraDirs'])) {
480
- load['extraDirs'] = load['extraDirs'].filter((d) => !d.includes(PLUGIN_NAME));
481
- if (load['extraDirs'].length === 0)
482
- delete load['extraDirs'];
483
- if (Object.keys(load).length === 0)
484
- delete skills['load'];
485
- if (Object.keys(skills).length === 0)
486
- delete config['skills'];
487
- }
488
- }
489
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
490
- // Clean up stale backup from install time
491
- if (fs.existsSync(bakPath)) {
492
- fs.unlinkSync(bakPath);
1580
+ }
1581
+ if (hasSkillsDir) {
1582
+ const skills = config["skills"];
1583
+ const load = skills?.["load"];
1584
+ if (load && Array.isArray(load["extraDirs"])) {
1585
+ load["extraDirs"] = load["extraDirs"].filter(
1586
+ (d) => !d.includes(PLUGIN_NAME)
1587
+ );
1588
+ if (load["extraDirs"].length === 0) delete load["extraDirs"];
1589
+ if (Object.keys(load).length === 0) delete skills["load"];
1590
+ if (Object.keys(skills).length === 0) delete config["skills"];
493
1591
  }
1592
+ }
1593
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
1594
+ if (fs.existsSync(bakPath)) {
1595
+ fs.unlinkSync(bakPath);
1596
+ }
494
1597
  }
495
1598
  function removeFile(filePath) {
496
- if (fs.existsSync(filePath)) {
497
- fs.unlinkSync(filePath);
498
- }
1599
+ if (fs.existsSync(filePath)) {
1600
+ fs.unlinkSync(filePath);
1601
+ }
499
1602
  }
500
1603
  function removePluginDir(configDir) {
501
- const extDir = path.join(configDir, 'extensions', PLUGIN_NAME);
502
- if (fs.existsSync(extDir)) {
503
- fs.rmSync(extDir, { recursive: true });
504
- }
1604
+ const extDir = path.join(configDir, "extensions", PLUGIN_NAME);
1605
+ if (fs.existsSync(extDir)) {
1606
+ fs.rmSync(extDir, { recursive: true });
1607
+ }
505
1608
  }
506
- // ── Memory flush patching ─────────────────────────────────────────────
507
1609
  function patchMemoryFlush(configDir) {
508
- const configPath = path.join(configDir, 'openclaw.json');
509
- if (!fs.existsSync(configPath)) {
510
- warn('openclaw.json not found. Skipping memoryFlush patch.');
511
- return;
512
- }
513
- let content;
514
- try {
515
- content = fs.readFileSync(configPath, 'utf-8');
516
- }
517
- catch {
518
- warn('Could not read openclaw.json. Skipping memoryFlush patch.');
519
- return;
520
- }
521
- let config;
522
- try {
523
- config = JSON.parse(content);
524
- }
525
- catch {
526
- warn('Could not parse openclaw.json. Skipping memoryFlush patch.');
527
- return;
528
- }
529
- // Navigate to agents.defaults.compaction.memoryFlush.prompt
530
- if (!config['agents'])
531
- config['agents'] = {};
532
- const agents = config['agents'];
533
- if (!agents['defaults'])
534
- agents['defaults'] = {};
535
- const defaults = agents['defaults'];
536
- if (!defaults['compaction'])
537
- defaults['compaction'] = {};
538
- const compaction = defaults['compaction'];
539
- if (!compaction['memoryFlush'])
540
- compaction['memoryFlush'] = {};
541
- const memoryFlush = compaction['memoryFlush'];
542
- const existing = typeof memoryFlush['prompt'] === 'string' ? memoryFlush['prompt'] : '';
543
- // Idempotent: skip if already contains our marker
544
- if (existing.includes(MEMORY_FLUSH_MARKER)) {
545
- ok('Memory flush prompt already patched');
546
- return;
547
- }
548
- memoryFlush['prompt'] = existing
549
- ? existing + '\n' + MEMORY_FLUSH_INSTRUCTION
550
- : MEMORY_FLUSH_INSTRUCTION;
551
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
552
- ok('Memory flush prompt patched');
1610
+ const configPath = path.join(configDir, "openclaw.json");
1611
+ if (!fs.existsSync(configPath)) {
1612
+ warn("openclaw.json not found. Skipping memoryFlush patch.");
1613
+ return;
1614
+ }
1615
+ let content;
1616
+ try {
1617
+ content = fs.readFileSync(configPath, "utf-8");
1618
+ } catch {
1619
+ warn("Could not read openclaw.json. Skipping memoryFlush patch.");
1620
+ return;
1621
+ }
1622
+ let config;
1623
+ try {
1624
+ config = JSON.parse(content);
1625
+ } catch {
1626
+ warn("Could not parse openclaw.json. Skipping memoryFlush patch.");
1627
+ return;
1628
+ }
1629
+ if (!config["agents"]) config["agents"] = {};
1630
+ const agents = config["agents"];
1631
+ if (!agents["defaults"]) agents["defaults"] = {};
1632
+ const defaults = agents["defaults"];
1633
+ if (!defaults["compaction"]) defaults["compaction"] = {};
1634
+ const compaction = defaults["compaction"];
1635
+ if (!compaction["memoryFlush"]) compaction["memoryFlush"] = {};
1636
+ const memoryFlush = compaction["memoryFlush"];
1637
+ const existing = typeof memoryFlush["prompt"] === "string" ? memoryFlush["prompt"] : "";
1638
+ if (existing.includes(MEMORY_FLUSH_MARKER)) {
1639
+ ok("Memory flush prompt already patched");
1640
+ return;
1641
+ }
1642
+ memoryFlush["prompt"] = existing ? existing + "\n" + MEMORY_FLUSH_INSTRUCTION : MEMORY_FLUSH_INSTRUCTION;
1643
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
1644
+ ok("Memory flush prompt patched");
553
1645
  }
554
1646
  function unpatchMemoryFlush(configDir) {
555
- const configPath = path.join(configDir, 'openclaw.json');
556
- if (!fs.existsSync(configPath))
557
- return;
558
- let content;
559
- try {
560
- content = fs.readFileSync(configPath, 'utf-8');
561
- }
562
- catch {
563
- return;
564
- }
565
- if (!content.includes(MEMORY_FLUSH_MARKER))
566
- return;
567
- let config;
568
- try {
569
- config = JSON.parse(content);
570
- }
571
- catch {
572
- return;
573
- }
574
- const agents = config['agents'];
575
- const defaults = agents?.['defaults'];
576
- const compaction = defaults?.['compaction'];
577
- const memoryFlush = compaction?.['memoryFlush'];
578
- if (!memoryFlush || typeof memoryFlush['prompt'] !== 'string')
579
- return;
580
- const prompt = memoryFlush['prompt'];
581
- const cleaned = prompt
582
- .replace(MEMORY_FLUSH_INSTRUCTION, '')
583
- .replace(/\n{2,}/g, '\n')
584
- .trim();
585
- if (cleaned) {
586
- memoryFlush['prompt'] = cleaned;
587
- }
588
- else {
589
- delete memoryFlush['prompt'];
590
- if (Object.keys(memoryFlush).length === 0)
591
- delete compaction['memoryFlush'];
592
- if (Object.keys(compaction).length === 0)
593
- delete defaults['compaction'];
594
- if (Object.keys(defaults).length === 0)
595
- delete agents['defaults'];
596
- if (Object.keys(agents).length === 0)
597
- delete config['agents'];
598
- }
599
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
1647
+ const configPath = path.join(configDir, "openclaw.json");
1648
+ if (!fs.existsSync(configPath)) return;
1649
+ let content;
1650
+ try {
1651
+ content = fs.readFileSync(configPath, "utf-8");
1652
+ } catch {
1653
+ return;
1654
+ }
1655
+ if (!content.includes(MEMORY_FLUSH_MARKER)) return;
1656
+ let config;
1657
+ try {
1658
+ config = JSON.parse(content);
1659
+ } catch {
1660
+ return;
1661
+ }
1662
+ const agents = config["agents"];
1663
+ const defaults = agents?.["defaults"];
1664
+ const compaction = defaults?.["compaction"];
1665
+ const memoryFlush = compaction?.["memoryFlush"];
1666
+ if (!memoryFlush || typeof memoryFlush["prompt"] !== "string") return;
1667
+ const prompt = memoryFlush["prompt"];
1668
+ const cleaned = prompt.replace(MEMORY_FLUSH_INSTRUCTION, "").replace(/\n{2,}/g, "\n").trim();
1669
+ if (cleaned) {
1670
+ memoryFlush["prompt"] = cleaned;
1671
+ } else {
1672
+ delete memoryFlush["prompt"];
1673
+ if (Object.keys(memoryFlush).length === 0) delete compaction["memoryFlush"];
1674
+ if (Object.keys(compaction).length === 0) delete defaults["compaction"];
1675
+ if (Object.keys(defaults).length === 0) delete agents["defaults"];
1676
+ if (Object.keys(agents).length === 0) delete config["agents"];
1677
+ }
1678
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
600
1679
  }
601
- // ── Shared helpers ────────────────────────────────────────────────────
602
1680
  function triggerRestart() {
603
- try {
604
- execSync('openclaw gateway restart', {
605
- encoding: 'utf-8',
606
- timeout: 10_000,
607
- });
608
- return true;
609
- }
610
- catch {
611
- warn('Could not restart gateway. Run `openclaw gateway restart` manually.');
612
- return false;
613
- }
1681
+ try {
1682
+ execSync("openclaw gateway restart", {
1683
+ encoding: "utf-8",
1684
+ timeout: 1e4
1685
+ });
1686
+ return true;
1687
+ } catch {
1688
+ warn("Could not restart gateway. Run `openclaw gateway restart` manually.");
1689
+ return false;
1690
+ }
614
1691
  }
615
1692
  function ensureDir(dir) {
616
- if (!fs.existsSync(dir)) {
617
- fs.mkdirSync(dir, { recursive: true });
618
- }
1693
+ if (!fs.existsSync(dir)) {
1694
+ fs.mkdirSync(dir, { recursive: true });
1695
+ }
619
1696
  }
620
1697
  function compareVersions(a, b) {
621
- const aParts = a.split('.').map(Number);
622
- const bParts = b.split('.').map(Number);
623
- for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
624
- const aVal = aParts[i] ?? 0;
625
- const bVal = bParts[i] ?? 0;
626
- if (aVal !== bVal)
627
- return aVal - bVal;
628
- }
629
- return 0;
1698
+ const aParts = a.split(".").map(Number);
1699
+ const bParts = b.split(".").map(Number);
1700
+ for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
1701
+ const aVal = aParts[i] ?? 0;
1702
+ const bVal = bParts[i] ?? 0;
1703
+ if (aVal !== bVal) return aVal - bVal;
1704
+ }
1705
+ return 0;
630
1706
  }
631
1707
  function findPackageRoot() {
632
- let dir = path.dirname(new URL(import.meta.url).pathname);
633
- for (let i = 0; i < 5; i++) {
634
- if (fs.existsSync(path.join(dir, 'openclaw.plugin.json'))) {
635
- return dir;
636
- }
637
- dir = path.dirname(dir);
1708
+ let dir = path.dirname(new URL(import.meta.url).pathname);
1709
+ for (let i = 0; i < 5; i++) {
1710
+ if (fs.existsSync(path.join(dir, "openclaw.plugin.json"))) {
1711
+ return dir;
638
1712
  }
639
- return null;
1713
+ dir = path.dirname(dir);
1714
+ }
1715
+ return null;
640
1716
  }
641
1717
  function copyRecursive(src, dest) {
642
- const stat = fs.statSync(src);
643
- if (stat.isDirectory()) {
644
- fs.mkdirSync(dest, { recursive: true });
645
- for (const entry of fs.readdirSync(src)) {
646
- copyRecursive(path.join(src, entry), path.join(dest, entry));
647
- }
648
- }
649
- else {
650
- fs.copyFileSync(src, dest);
1718
+ const stat = fs.statSync(src);
1719
+ if (stat.isDirectory()) {
1720
+ fs.mkdirSync(dest, { recursive: true });
1721
+ for (const entry of fs.readdirSync(src)) {
1722
+ copyRecursive(path.join(src, entry), path.join(dest, entry));
651
1723
  }
1724
+ } else {
1725
+ fs.copyFileSync(src, dest);
1726
+ }
652
1727
  }
653
- //# sourceMappingURL=setup.js.map