openclaw-telegram-manager 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/dist/commands/archive.d.ts +4 -0
  4. package/dist/commands/archive.d.ts.map +1 -0
  5. package/dist/commands/archive.js +71 -0
  6. package/dist/commands/archive.js.map +1 -0
  7. package/dist/commands/doctor-all.d.ts +3 -0
  8. package/dist/commands/doctor-all.d.ts.map +1 -0
  9. package/dist/commands/doctor-all.js +193 -0
  10. package/dist/commands/doctor-all.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +3 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +74 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/help.d.ts +4 -0
  16. package/dist/commands/help.d.ts.map +1 -0
  17. package/dist/commands/help.js +8 -0
  18. package/dist/commands/help.js.map +1 -0
  19. package/dist/commands/init.d.ts +17 -0
  20. package/dist/commands/init.d.ts.map +1 -0
  21. package/dist/commands/init.js +304 -0
  22. package/dist/commands/init.js.map +1 -0
  23. package/dist/commands/list.d.ts +3 -0
  24. package/dist/commands/list.d.ts.map +1 -0
  25. package/dist/commands/list.js +22 -0
  26. package/dist/commands/list.js.map +1 -0
  27. package/dist/commands/rename.d.ts +3 -0
  28. package/dist/commands/rename.d.ts.map +1 -0
  29. package/dist/commands/rename.js +115 -0
  30. package/dist/commands/rename.js.map +1 -0
  31. package/dist/commands/snooze.d.ts +3 -0
  32. package/dist/commands/snooze.d.ts.map +1 -0
  33. package/dist/commands/snooze.js +52 -0
  34. package/dist/commands/snooze.js.map +1 -0
  35. package/dist/commands/status.d.ts +3 -0
  36. package/dist/commands/status.d.ts.map +1 -0
  37. package/dist/commands/status.js +48 -0
  38. package/dist/commands/status.js.map +1 -0
  39. package/dist/commands/sync.d.ts +3 -0
  40. package/dist/commands/sync.d.ts.map +1 -0
  41. package/dist/commands/sync.js +38 -0
  42. package/dist/commands/sync.js.map +1 -0
  43. package/dist/commands/upgrade.d.ts +3 -0
  44. package/dist/commands/upgrade.d.ts.map +1 -0
  45. package/dist/commands/upgrade.js +52 -0
  46. package/dist/commands/upgrade.js.map +1 -0
  47. package/dist/index.d.ts +25 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +30 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/lib/audit.d.ts +12 -0
  52. package/dist/lib/audit.d.ts.map +1 -0
  53. package/dist/lib/audit.js +35 -0
  54. package/dist/lib/audit.js.map +1 -0
  55. package/dist/lib/auth.d.ts +26 -0
  56. package/dist/lib/auth.d.ts.map +1 -0
  57. package/dist/lib/auth.js +73 -0
  58. package/dist/lib/auth.js.map +1 -0
  59. package/dist/lib/capsule.d.ts +27 -0
  60. package/dist/lib/capsule.d.ts.map +1 -0
  61. package/dist/lib/capsule.js +130 -0
  62. package/dist/lib/capsule.js.map +1 -0
  63. package/dist/lib/config-restart.d.ts +23 -0
  64. package/dist/lib/config-restart.d.ts.map +1 -0
  65. package/dist/lib/config-restart.js +129 -0
  66. package/dist/lib/config-restart.js.map +1 -0
  67. package/dist/lib/doctor-checks.d.ts +50 -0
  68. package/dist/lib/doctor-checks.d.ts.map +1 -0
  69. package/dist/lib/doctor-checks.js +421 -0
  70. package/dist/lib/doctor-checks.js.map +1 -0
  71. package/dist/lib/include-generator.d.ts +35 -0
  72. package/dist/lib/include-generator.d.ts.map +1 -0
  73. package/dist/lib/include-generator.js +140 -0
  74. package/dist/lib/include-generator.js.map +1 -0
  75. package/dist/lib/registry.d.ts +27 -0
  76. package/dist/lib/registry.d.ts.map +1 -0
  77. package/dist/lib/registry.js +154 -0
  78. package/dist/lib/registry.js.map +1 -0
  79. package/dist/lib/security.d.ts +57 -0
  80. package/dist/lib/security.d.ts.map +1 -0
  81. package/dist/lib/security.js +133 -0
  82. package/dist/lib/security.js.map +1 -0
  83. package/dist/lib/telegram.d.ts +55 -0
  84. package/dist/lib/telegram.d.ts.map +1 -0
  85. package/dist/lib/telegram.js +254 -0
  86. package/dist/lib/telegram.js.map +1 -0
  87. package/dist/lib/types.d.ts +120 -0
  88. package/dist/lib/types.d.ts.map +1 -0
  89. package/dist/lib/types.js +85 -0
  90. package/dist/lib/types.js.map +1 -0
  91. package/dist/setup.d.ts +3 -0
  92. package/dist/setup.d.ts.map +1 -0
  93. package/dist/setup.js +333 -0
  94. package/dist/setup.js.map +1 -0
  95. package/dist/tool.d.ts +15 -0
  96. package/dist/tool.d.ts.map +1 -0
  97. package/dist/tool.js +201 -0
  98. package/dist/tool.js.map +1 -0
  99. package/openclaw.plugin.json +9 -0
  100. package/package.json +48 -0
  101. package/skills/topic/SKILL.md +35 -0
  102. package/src/commands/archive.ts +89 -0
  103. package/src/commands/doctor-all.ts +243 -0
  104. package/src/commands/doctor.ts +100 -0
  105. package/src/commands/help.ts +11 -0
  106. package/src/commands/init.ts +376 -0
  107. package/src/commands/list.ts +28 -0
  108. package/src/commands/rename.ts +140 -0
  109. package/src/commands/snooze.ts +69 -0
  110. package/src/commands/status.ts +59 -0
  111. package/src/commands/sync.ts +46 -0
  112. package/src/commands/upgrade.ts +64 -0
  113. package/src/index.ts +54 -0
  114. package/src/lib/audit.ts +44 -0
  115. package/src/lib/auth.ts +96 -0
  116. package/src/lib/capsule.ts +206 -0
  117. package/src/lib/config-restart.ts +167 -0
  118. package/src/lib/doctor-checks.ts +639 -0
  119. package/src/lib/include-generator.ts +174 -0
  120. package/src/lib/registry.ts +197 -0
  121. package/src/lib/security.ts +174 -0
  122. package/src/lib/telegram.ts +311 -0
  123. package/src/lib/types.ts +172 -0
  124. package/src/setup.ts +402 -0
  125. package/src/templates/base/COMMANDS.md +3 -0
  126. package/src/templates/base/CRON.md +3 -0
  127. package/src/templates/base/LINKS.md +3 -0
  128. package/src/templates/base/NOTES.md +3 -0
  129. package/src/templates/base/README.md +3 -0
  130. package/src/templates/base/STATUS.md +13 -0
  131. package/src/templates/base/TODO.md +11 -0
  132. package/src/templates/overlays/coding/ARCHITECTURE.md +3 -0
  133. package/src/templates/overlays/coding/DEPLOY.md +3 -0
  134. package/src/templates/overlays/marketing/CAMPAIGNS.md +3 -0
  135. package/src/templates/overlays/marketing/METRICS.md +3 -0
  136. package/src/templates/overlays/research/FINDINGS.md +3 -0
  137. package/src/templates/overlays/research/SOURCES.md +3 -0
  138. package/src/tool.ts +282 -0
@@ -0,0 +1,254 @@
1
+ import { htmlEscape, buildCallbackData } from './security.js';
2
+ import { Severity } from './types.js';
3
+ // ── Telegram message limit ─────────────────────────────────────────────
4
+ const TELEGRAM_MSG_LIMIT = 4096;
5
+ export const DEFAULT_RATE_LIMIT = {
6
+ sameGroupDelayMs: 4000,
7
+ crossGroupDelayMs: 1000,
8
+ };
9
+ // ── Builders ───────────────────────────────────────────────────────────
10
+ /**
11
+ * Build an InlineKeyboardMarkup from rows of buttons.
12
+ */
13
+ export function buildInlineKeyboard(rows) {
14
+ return { inline_keyboard: rows };
15
+ }
16
+ /**
17
+ * Build inline keyboard buttons for a doctor report.
18
+ */
19
+ export function buildDoctorButtons(slug, groupId, threadId, secret) {
20
+ const cb = (action) => buildCallbackData(action, slug, groupId, threadId, secret);
21
+ return buildInlineKeyboard([
22
+ [
23
+ { text: 'Fix', callback_data: cb('fix') },
24
+ { text: 'Snooze 7d', callback_data: cb('snooze7d') },
25
+ { text: 'Snooze 30d', callback_data: cb('snooze30d') },
26
+ ],
27
+ [
28
+ { text: 'Archive', callback_data: cb('archive') },
29
+ { text: 'Ignore check', callback_data: cb('ignore') },
30
+ ],
31
+ ]);
32
+ }
33
+ /**
34
+ * Build inline keyboard with a [Confirm] button for slug confirmation (init step 1).
35
+ */
36
+ export function buildInitSlugButtons(slug, groupId, threadId, secret) {
37
+ const cb = (action) => buildCallbackData(action, slug, groupId, threadId, secret);
38
+ return buildInlineKeyboard([
39
+ [{ text: 'Confirm', callback_data: cb('is') }],
40
+ ]);
41
+ }
42
+ /**
43
+ * Build inline keyboard with type picker buttons for init step 2.
44
+ */
45
+ export function buildInitTypeButtons(slug, groupId, threadId, secret) {
46
+ const cb = (action) => buildCallbackData(action, slug, groupId, threadId, secret);
47
+ return buildInlineKeyboard([
48
+ [
49
+ { text: 'Coding', callback_data: cb('ic') },
50
+ { text: 'Research', callback_data: cb('ir') },
51
+ ],
52
+ [
53
+ { text: 'Marketing', callback_data: cb('im') },
54
+ { text: 'Custom', callback_data: cb('ix') },
55
+ ],
56
+ ]);
57
+ }
58
+ /**
59
+ * Build HTML Topic Card displayed after init.
60
+ */
61
+ export function buildTopicCard(slug, type, capsuleVersion) {
62
+ const s = htmlEscape(slug);
63
+ const t = htmlEscape(type);
64
+ const v = htmlEscape(String(capsuleVersion));
65
+ return [
66
+ `<b>Topic: ${s}</b>`,
67
+ `Type: ${t} | Version: ${v}`,
68
+ `Capsule: projects/${s}/`,
69
+ '',
70
+ '<b>Commands:</b>',
71
+ '/topic doctor \u2014 health checks',
72
+ '/topic status \u2014 quick view',
73
+ '/topic sync \u2014 re-apply config',
74
+ '/topic list \u2014 all topics',
75
+ '/topic archive \u2014 archive this topic',
76
+ '/topic help \u2014 command reference',
77
+ ].join('\n');
78
+ }
79
+ /**
80
+ * Build HTML doctor report with severity icons.
81
+ */
82
+ export function buildDoctorReport(slug, results) {
83
+ const s = htmlEscape(slug);
84
+ const lines = [`<b>Doctor: ${s}</b>`, ''];
85
+ if (results.length === 0) {
86
+ lines.push('All checks passed.');
87
+ return lines.join('\n');
88
+ }
89
+ for (const r of results) {
90
+ const icon = severityIcon(r.severity);
91
+ const msg = htmlEscape(r.message);
92
+ const fix = r.fixable ? ' [fixable]' : '';
93
+ lines.push(`${icon} <code>${htmlEscape(r.checkId)}</code>: ${msg}${fix}`);
94
+ }
95
+ lines.push('');
96
+ lines.push('Reply /topic doctor to re-check, or use the buttons below.');
97
+ return truncateMessage(lines.join('\n'));
98
+ }
99
+ function severityIcon(severity) {
100
+ switch (severity) {
101
+ case Severity.ERROR:
102
+ return '\u274c'; // red X
103
+ case Severity.WARN:
104
+ return '\u26a0\ufe0f'; // warning
105
+ case Severity.INFO:
106
+ return '\u2139\ufe0f'; // info
107
+ default:
108
+ return '\u2022';
109
+ }
110
+ }
111
+ /**
112
+ * Build HTML help card with command reference.
113
+ */
114
+ export function buildHelpCard() {
115
+ return [
116
+ '<b>Topic Manager Commands</b>',
117
+ '',
118
+ '/topic init \u2014 register this topic',
119
+ '/topic doctor \u2014 run health checks',
120
+ '/topic doctor --all \u2014 check all topics',
121
+ '/topic status \u2014 quick STATUS.md view',
122
+ '/topic list \u2014 show all topics',
123
+ '/topic sync \u2014 re-apply config',
124
+ '/topic rename &lt;slug&gt; \u2014 rename topic',
125
+ '/topic upgrade \u2014 update capsule template',
126
+ '/topic snooze &lt;Nd&gt; \u2014 snooze doctor (7d, 30d, etc.)',
127
+ '/topic archive \u2014 archive topic',
128
+ '/topic unarchive \u2014 reactivate topic',
129
+ '/topic help \u2014 this message',
130
+ ].join('\n');
131
+ }
132
+ /**
133
+ * Build compact topic list message in HTML.
134
+ * Groups by status: active first, snoozed, then archived.
135
+ */
136
+ export function buildListMessage(topics) {
137
+ if (topics.length === 0) {
138
+ return '<b>Topic Registry</b> (0 topics)\n\nNo topics registered.';
139
+ }
140
+ const sorted = [...topics].sort((a, b) => {
141
+ const order = { active: 0, snoozed: 1, archived: 2 };
142
+ return (order[a.status] ?? 3) - (order[b.status] ?? 3);
143
+ });
144
+ const lines = [`<b>Topic Registry</b> (${topics.length} topics)`, ''];
145
+ let rendered = 0;
146
+ for (const t of sorted) {
147
+ const entry = [
148
+ `<code>${htmlEscape(t.slug)}</code> [${htmlEscape(t.type)}] ${htmlEscape(t.status)}`,
149
+ ` Last active: ${t.lastMessageAt ? relativeTime(t.lastMessageAt) : 'never'}`,
150
+ ` Thread: #${htmlEscape(t.threadId)}`,
151
+ ].join('\n');
152
+ // Check if adding this entry would exceed limit
153
+ const tentative = [...lines, entry, ''].join('\n');
154
+ if (tentative.length > TELEGRAM_MSG_LIMIT - 40) {
155
+ const remaining = sorted.length - rendered;
156
+ lines.push(`... and ${remaining} more`);
157
+ break;
158
+ }
159
+ lines.push(entry);
160
+ lines.push('');
161
+ rendered++;
162
+ }
163
+ return truncateMessage(lines.join('\n'));
164
+ }
165
+ /**
166
+ * Convert an ISO timestamp to a relative time string.
167
+ */
168
+ function relativeTime(iso) {
169
+ const diff = Date.now() - new Date(iso).getTime();
170
+ const mins = Math.floor(diff / 60_000);
171
+ if (mins < 1)
172
+ return 'just now';
173
+ if (mins < 60)
174
+ return `${mins}m ago`;
175
+ const hours = Math.floor(mins / 60);
176
+ if (hours < 24)
177
+ return `${hours}h ago`;
178
+ const days = Math.floor(hours / 24);
179
+ return `${days}d ago`;
180
+ }
181
+ // ── Rate-limited posting helper ────────────────────────────────────────
182
+ /**
183
+ * Helper that wraps a post function with rate limiting delays.
184
+ * Returns a function that posts messages respecting Telegram rate limits.
185
+ *
186
+ * The postFn should handle the actual Telegram API call.
187
+ * If postFn throws with a 429 status, the helper respects retry_after.
188
+ */
189
+ export function createRateLimitedPoster(postFn, config = DEFAULT_RATE_LIMIT) {
190
+ let lastPostTime = 0;
191
+ let lastGroupId = '';
192
+ return async (groupId, threadId, text, keyboard) => {
193
+ const now = Date.now();
194
+ const delay = groupId === lastGroupId
195
+ ? config.sameGroupDelayMs
196
+ : config.crossGroupDelayMs;
197
+ const elapsed = now - lastPostTime;
198
+ if (elapsed < delay) {
199
+ await sleep(delay - elapsed);
200
+ }
201
+ try {
202
+ await postFn(groupId, threadId, text, keyboard);
203
+ }
204
+ catch (err) {
205
+ if (isTooManyRequestsError(err)) {
206
+ const retryAfter = getRetryAfter(err);
207
+ await sleep(retryAfter * 1000);
208
+ await postFn(groupId, threadId, text, keyboard);
209
+ }
210
+ else {
211
+ throw err;
212
+ }
213
+ }
214
+ lastPostTime = Date.now();
215
+ lastGroupId = groupId;
216
+ };
217
+ }
218
+ function sleep(ms) {
219
+ return new Promise((resolve) => setTimeout(resolve, ms));
220
+ }
221
+ function isTooManyRequestsError(err) {
222
+ if (err && typeof err === 'object' && 'status' in err) {
223
+ const status = err['status'];
224
+ return typeof status === 'number' && status === 429;
225
+ }
226
+ return false;
227
+ }
228
+ function getRetryAfter(err) {
229
+ if (err && typeof err === 'object' && 'retryAfter' in err) {
230
+ const val = err.retryAfter;
231
+ if (typeof val === 'number' && val > 0)
232
+ return val;
233
+ }
234
+ // Default to 5 seconds if retry_after is not available
235
+ return 5;
236
+ }
237
+ // ── Message truncation ─────────────────────────────────────────────────
238
+ /**
239
+ * Truncate a message to fit within Telegram's limit.
240
+ * Appends a truncation indicator if the message was cut.
241
+ */
242
+ export function truncateMessage(msg, limit = TELEGRAM_MSG_LIMIT) {
243
+ if (msg.length <= limit)
244
+ return msg;
245
+ const suffix = '\n\n... (truncated)';
246
+ let truncated = msg.slice(0, limit - suffix.length);
247
+ // Strip any incomplete HTML tag at the truncation point
248
+ const lastOpen = truncated.lastIndexOf('<');
249
+ if (lastOpen !== -1 && lastOpen > truncated.lastIndexOf('>')) {
250
+ truncated = truncated.slice(0, lastOpen);
251
+ }
252
+ return truncated + suffix;
253
+ }
254
+ //# sourceMappingURL=telegram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/lib/telegram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { type Static } from '@sinclair/typebox';
2
+ export declare const CURRENT_REGISTRY_VERSION = 1;
3
+ export declare const CAPSULE_VERSION = 1;
4
+ export declare const MAX_EXTRAS_BYTES = 10240;
5
+ export declare const MAX_POST_ERROR_LENGTH = 500;
6
+ export declare const MAX_TOPICS_DEFAULT = 100;
7
+ export declare const DOCTOR_ALL_COOLDOWN_MS: number;
8
+ export declare const DOCTOR_PER_TOPIC_CAP_MS: number;
9
+ export declare const INACTIVE_AFTER_DAYS = 7;
10
+ export declare const SPAM_THRESHOLD = 3;
11
+ export declare const TopicType: {
12
+ readonly Coding: "coding";
13
+ readonly Research: "research";
14
+ readonly Marketing: "marketing";
15
+ readonly Custom: "custom";
16
+ };
17
+ export type TopicType = (typeof TopicType)[keyof typeof TopicType];
18
+ export declare const TopicStatus: {
19
+ readonly Active: "active";
20
+ readonly Snoozed: "snoozed";
21
+ readonly Archived: "archived";
22
+ };
23
+ export type TopicStatus = (typeof TopicStatus)[keyof typeof TopicStatus];
24
+ export declare const Severity: {
25
+ readonly ERROR: "ERROR";
26
+ readonly WARN: "WARN";
27
+ readonly INFO: "INFO";
28
+ };
29
+ export type Severity = (typeof Severity)[keyof typeof Severity];
30
+ export declare const TopicTypeSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"coding">, import("@sinclair/typebox").TLiteral<"research">, import("@sinclair/typebox").TLiteral<"marketing">, import("@sinclair/typebox").TLiteral<"custom">]>;
31
+ export declare const TopicStatusSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"active">, import("@sinclair/typebox").TLiteral<"snoozed">, import("@sinclair/typebox").TLiteral<"archived">]>;
32
+ export declare const TopicEntrySchema: import("@sinclair/typebox").TObject<{
33
+ groupId: import("@sinclair/typebox").TString;
34
+ threadId: import("@sinclair/typebox").TString;
35
+ slug: import("@sinclair/typebox").TString;
36
+ type: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"coding">, import("@sinclair/typebox").TLiteral<"research">, import("@sinclair/typebox").TLiteral<"marketing">, import("@sinclair/typebox").TLiteral<"custom">]>;
37
+ status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"active">, import("@sinclair/typebox").TLiteral<"snoozed">, import("@sinclair/typebox").TLiteral<"archived">]>;
38
+ capsuleVersion: import("@sinclair/typebox").TInteger;
39
+ lastMessageAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
40
+ lastDoctorReportAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
41
+ lastDoctorRunAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
42
+ snoozeUntil: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
43
+ ignoreChecks: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
44
+ consecutiveSilentDoctors: import("@sinclair/typebox").TInteger;
45
+ lastPostError: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
46
+ extras: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
47
+ }>;
48
+ export type TopicEntry = Static<typeof TopicEntrySchema>;
49
+ export declare const RegistrySchema: import("@sinclair/typebox").TObject<{
50
+ version: import("@sinclair/typebox").TInteger;
51
+ topicManagerAdmins: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
52
+ callbackSecret: import("@sinclair/typebox").TString;
53
+ lastDoctorAllRunAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
54
+ maxTopics: import("@sinclair/typebox").TInteger;
55
+ topics: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
56
+ groupId: import("@sinclair/typebox").TString;
57
+ threadId: import("@sinclair/typebox").TString;
58
+ slug: import("@sinclair/typebox").TString;
59
+ type: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"coding">, import("@sinclair/typebox").TLiteral<"research">, import("@sinclair/typebox").TLiteral<"marketing">, import("@sinclair/typebox").TLiteral<"custom">]>;
60
+ status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"active">, import("@sinclair/typebox").TLiteral<"snoozed">, import("@sinclair/typebox").TLiteral<"archived">]>;
61
+ capsuleVersion: import("@sinclair/typebox").TInteger;
62
+ lastMessageAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
63
+ lastDoctorReportAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
64
+ lastDoctorRunAt: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
65
+ snoozeUntil: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
66
+ ignoreChecks: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
67
+ consecutiveSilentDoctors: import("@sinclair/typebox").TInteger;
68
+ lastPostError: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>;
69
+ extras: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
70
+ }>>;
71
+ }>;
72
+ export type Registry = Static<typeof RegistrySchema>;
73
+ export interface DoctorCheckResult {
74
+ severity: Severity;
75
+ checkId: string;
76
+ message: string;
77
+ fixable: boolean;
78
+ }
79
+ export declare const OVERLAY_FILES: Record<TopicType, string[]>;
80
+ export declare const BASE_FILES: readonly ["README.md", "STATUS.md", "TODO.md", "COMMANDS.md", "LINKS.md", "CRON.md", "NOTES.md"];
81
+ export interface AuditEntry {
82
+ ts: string;
83
+ userId: string;
84
+ cmd: string;
85
+ slug: string;
86
+ detail: string;
87
+ }
88
+ export interface InlineKeyboardButton {
89
+ text: string;
90
+ callback_data: string;
91
+ }
92
+ export interface InlineKeyboardMarkup {
93
+ inline_keyboard: InlineKeyboardButton[][];
94
+ }
95
+ export interface RpcInterface {
96
+ call(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
97
+ }
98
+ export interface Logger {
99
+ info(msg: string): void;
100
+ warn(msg: string): void;
101
+ error(msg: string): void;
102
+ }
103
+ export interface CommandContext {
104
+ workspaceDir: string;
105
+ configDir: string;
106
+ rpc?: RpcInterface | null;
107
+ logger: Logger;
108
+ groupId?: string;
109
+ threadId?: string;
110
+ userId?: string;
111
+ messageContext?: Record<string, unknown>;
112
+ }
113
+ export interface CommandResult {
114
+ text: string;
115
+ parseMode?: 'HTML';
116
+ inlineKeyboard?: InlineKeyboardMarkup;
117
+ pin?: boolean;
118
+ }
119
+ export declare function topicKey(groupId: string, threadId: string): string;
120
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ // ── Constants ──────────────────────────────────────────────────────────
3
+ export const CURRENT_REGISTRY_VERSION = 1;
4
+ export const CAPSULE_VERSION = 1;
5
+ export const MAX_EXTRAS_BYTES = 10_240;
6
+ export const MAX_POST_ERROR_LENGTH = 500;
7
+ export const MAX_TOPICS_DEFAULT = 100;
8
+ export const DOCTOR_ALL_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour
9
+ export const DOCTOR_PER_TOPIC_CAP_MS = 24 * 60 * 60 * 1000; // 24 hours
10
+ export const INACTIVE_AFTER_DAYS = 7;
11
+ export const SPAM_THRESHOLD = 3;
12
+ // ── Enums ──────────────────────────────────────────────────────────────
13
+ export const TopicType = {
14
+ Coding: 'coding',
15
+ Research: 'research',
16
+ Marketing: 'marketing',
17
+ Custom: 'custom',
18
+ };
19
+ export const TopicStatus = {
20
+ Active: 'active',
21
+ Snoozed: 'snoozed',
22
+ Archived: 'archived',
23
+ };
24
+ export const Severity = {
25
+ ERROR: 'ERROR',
26
+ WARN: 'WARN',
27
+ INFO: 'INFO',
28
+ };
29
+ // ── Typebox Schemas ────────────────────────────────────────────────────
30
+ export const TopicTypeSchema = Type.Union([
31
+ Type.Literal('coding'),
32
+ Type.Literal('research'),
33
+ Type.Literal('marketing'),
34
+ Type.Literal('custom'),
35
+ ]);
36
+ export const TopicStatusSchema = Type.Union([
37
+ Type.Literal('active'),
38
+ Type.Literal('snoozed'),
39
+ Type.Literal('archived'),
40
+ ]);
41
+ export const TopicEntrySchema = Type.Object({
42
+ groupId: Type.String({ pattern: '^-?\\d+$' }),
43
+ threadId: Type.String({ pattern: '^\\d+$' }),
44
+ slug: Type.String({ pattern: '^[a-z][a-z0-9-]{0,49}$' }),
45
+ type: TopicTypeSchema,
46
+ status: TopicStatusSchema,
47
+ capsuleVersion: Type.Integer({ minimum: 1 }),
48
+ lastMessageAt: Type.Union([Type.String(), Type.Null()]),
49
+ lastDoctorReportAt: Type.Union([Type.String(), Type.Null()]),
50
+ lastDoctorRunAt: Type.Union([Type.String(), Type.Null()]),
51
+ snoozeUntil: Type.Union([Type.String(), Type.Null()]),
52
+ ignoreChecks: Type.Array(Type.String()),
53
+ consecutiveSilentDoctors: Type.Integer({ minimum: 0 }),
54
+ lastPostError: Type.Union([Type.String({ maxLength: MAX_POST_ERROR_LENGTH }), Type.Null()]),
55
+ extras: Type.Record(Type.String(), Type.Unknown()),
56
+ });
57
+ export const RegistrySchema = Type.Object({
58
+ version: Type.Integer({ minimum: 1 }),
59
+ topicManagerAdmins: Type.Array(Type.String()),
60
+ callbackSecret: Type.String(),
61
+ lastDoctorAllRunAt: Type.Union([Type.String(), Type.Null()]),
62
+ maxTopics: Type.Integer({ minimum: 1 }),
63
+ topics: Type.Record(Type.String(), TopicEntrySchema),
64
+ });
65
+ // ── Overlay mappings ───────────────────────────────────────────────────
66
+ export const OVERLAY_FILES = {
67
+ coding: ['ARCHITECTURE.md', 'DEPLOY.md'],
68
+ research: ['SOURCES.md', 'FINDINGS.md'],
69
+ marketing: ['CAMPAIGNS.md', 'METRICS.md'],
70
+ custom: [],
71
+ };
72
+ export const BASE_FILES = [
73
+ 'README.md',
74
+ 'STATUS.md',
75
+ 'TODO.md',
76
+ 'COMMANDS.md',
77
+ 'LINKS.md',
78
+ 'CRON.md',
79
+ 'NOTES.md',
80
+ ];
81
+ // ── Helper to build a topic map key ────────────────────────────────────
82
+ export function topicKey(groupId, threadId) {
83
+ return `${groupId}:${threadId}`;
84
+ }
85
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":""}