openclaw-telegram-manager 1.3.0 → 1.3.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/lib/include-generator.d.ts +1 -1
- package/dist/lib/include-generator.d.ts.map +1 -1
- package/dist/lib/include-generator.js +33 -2
- package/dist/lib/include-generator.js.map +1 -1
- package/dist/plugin.js +29 -2
- package/dist/setup.js +33 -15
- package/dist/setup.js.map +1 -1
- package/package.json +2 -3
- package/src/commands/archive.ts +0 -89
- package/src/commands/doctor-all.ts +0 -243
- package/src/commands/doctor.ts +0 -100
- package/src/commands/help.ts +0 -11
- package/src/commands/init.ts +0 -376
- package/src/commands/list.ts +0 -28
- package/src/commands/rename.ts +0 -140
- package/src/commands/snooze.ts +0 -69
- package/src/commands/status.ts +0 -59
- package/src/commands/sync.ts +0 -46
- package/src/commands/upgrade.ts +0 -64
- package/src/index.ts +0 -91
- package/src/lib/audit.ts +0 -44
- package/src/lib/auth.ts +0 -96
- package/src/lib/capsule.ts +0 -206
- package/src/lib/config-restart.ts +0 -167
- package/src/lib/doctor-checks.ts +0 -639
- package/src/lib/include-generator.ts +0 -174
- package/src/lib/registry.ts +0 -197
- package/src/lib/security.ts +0 -174
- package/src/lib/telegram.ts +0 -311
- package/src/lib/types.ts +0 -172
- package/src/setup.ts +0 -475
- package/src/templates/base/COMMANDS.md +0 -3
- package/src/templates/base/CRON.md +0 -3
- package/src/templates/base/LINKS.md +0 -3
- package/src/templates/base/NOTES.md +0 -3
- package/src/templates/base/README.md +0 -3
- package/src/templates/base/TODO.md +0 -11
- package/src/templates/overlays/coding/ARCHITECTURE.md +0 -3
- package/src/templates/overlays/coding/DEPLOY.md +0 -3
- package/src/templates/overlays/marketing/CAMPAIGNS.md +0 -3
- package/src/templates/overlays/marketing/METRICS.md +0 -3
- package/src/templates/overlays/research/FINDINGS.md +0 -3
- package/src/templates/overlays/research/SOURCES.md +0 -3
- package/src/tool.ts +0 -282
package/src/tool.ts
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { readRegistry, withRegistry } from './lib/registry.js';
|
|
2
|
-
import { parseAndVerifyCallback, htmlEscape } from './lib/security.js';
|
|
3
|
-
import { topicKey } from './lib/types.js';
|
|
4
|
-
import { appendAudit, buildAuditEntry } from './lib/audit.js';
|
|
5
|
-
import { handleInitInteractive, handleInitSlugConfirm, handleInitTypeSelect } from './commands/init.js';
|
|
6
|
-
import { handleDoctor } from './commands/doctor.js';
|
|
7
|
-
import { handleDoctorAll } from './commands/doctor-all.js';
|
|
8
|
-
import { handleList } from './commands/list.js';
|
|
9
|
-
import { handleStatus } from './commands/status.js';
|
|
10
|
-
import { handleSync } from './commands/sync.js';
|
|
11
|
-
import { handleRename } from './commands/rename.js';
|
|
12
|
-
import { handleUpgrade } from './commands/upgrade.js';
|
|
13
|
-
import { handleSnooze } from './commands/snooze.js';
|
|
14
|
-
import { handleArchive, handleUnarchive } from './commands/archive.js';
|
|
15
|
-
import { handleHelp } from './commands/help.js';
|
|
16
|
-
import type { CommandContext, CommandResult } from './commands/help.js';
|
|
17
|
-
import type { Logger, RpcInterface } from './lib/config-restart.js';
|
|
18
|
-
|
|
19
|
-
// ── Dependencies ──────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
export interface ToolDeps {
|
|
22
|
-
logger: Logger;
|
|
23
|
-
configDir: string;
|
|
24
|
-
workspaceDir: string;
|
|
25
|
-
rpc?: RpcInterface | null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ── Tool instance ─────────────────────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
export interface TopicManagerTool {
|
|
31
|
-
execute(
|
|
32
|
-
_id: string,
|
|
33
|
-
params: { command: string },
|
|
34
|
-
execContext?: Record<string, unknown>,
|
|
35
|
-
): Promise<CommandResult>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// ── Factory ───────────────────────────────────────────────────────────
|
|
39
|
-
|
|
40
|
-
export function createTopicManagerTool(deps: ToolDeps): TopicManagerTool {
|
|
41
|
-
const { logger, configDir, workspaceDir, rpc } = deps;
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
async execute(
|
|
45
|
-
_id: string,
|
|
46
|
-
params: { command: string },
|
|
47
|
-
execContext?: Record<string, unknown>,
|
|
48
|
-
): Promise<CommandResult> {
|
|
49
|
-
const commandStr = (params.command ?? '').trim();
|
|
50
|
-
|
|
51
|
-
if (!commandStr) {
|
|
52
|
-
return { text: 'No command provided. Try /topic help for available commands.' };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Extract context from execution params
|
|
56
|
-
const ctx = buildContext(deps, execContext);
|
|
57
|
-
|
|
58
|
-
// Handle tm: callback routing
|
|
59
|
-
if (commandStr.startsWith('tm:')) {
|
|
60
|
-
return handleCallback(commandStr, ctx);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Parse sub-command and args
|
|
64
|
-
const { subCommand, args, flags } = parseCommand(commandStr);
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
switch (subCommand) {
|
|
68
|
-
case 'init':
|
|
69
|
-
return await handleInitInteractive(ctx, args);
|
|
70
|
-
|
|
71
|
-
case 'doctor':
|
|
72
|
-
if (flags.has('--all') || flags.has('all')) {
|
|
73
|
-
return await handleDoctorAll(ctx);
|
|
74
|
-
}
|
|
75
|
-
return await handleDoctor(ctx);
|
|
76
|
-
|
|
77
|
-
case 'doctor-all':
|
|
78
|
-
return await handleDoctorAll(ctx);
|
|
79
|
-
|
|
80
|
-
case 'list':
|
|
81
|
-
return await handleList(ctx);
|
|
82
|
-
|
|
83
|
-
case 'status':
|
|
84
|
-
return await handleStatus(ctx);
|
|
85
|
-
|
|
86
|
-
case 'sync':
|
|
87
|
-
return await handleSync(ctx);
|
|
88
|
-
|
|
89
|
-
case 'rename':
|
|
90
|
-
return await handleRename(ctx, args);
|
|
91
|
-
|
|
92
|
-
case 'upgrade':
|
|
93
|
-
return await handleUpgrade(ctx);
|
|
94
|
-
|
|
95
|
-
case 'snooze':
|
|
96
|
-
return await handleSnooze(ctx, args);
|
|
97
|
-
|
|
98
|
-
case 'archive':
|
|
99
|
-
return await handleArchive(ctx);
|
|
100
|
-
|
|
101
|
-
case 'unarchive':
|
|
102
|
-
return await handleUnarchive(ctx);
|
|
103
|
-
|
|
104
|
-
case 'help':
|
|
105
|
-
return await handleHelp(ctx);
|
|
106
|
-
|
|
107
|
-
default:
|
|
108
|
-
return {
|
|
109
|
-
text: `Unknown command: "${htmlEscape(subCommand)}". Try /topic help for available commands.`,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
} catch (err) {
|
|
113
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
114
|
-
logger.error(`[topic_manager] Command "${subCommand}" failed: ${msg}`);
|
|
115
|
-
return {
|
|
116
|
-
text: `Command failed: ${htmlEscape(msg)}`,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ── Command parsing ───────────────────────────────────────────────────
|
|
124
|
-
|
|
125
|
-
interface ParsedCommand {
|
|
126
|
-
subCommand: string;
|
|
127
|
-
args: string;
|
|
128
|
-
flags: Set<string>;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function parseCommand(commandStr: string): ParsedCommand {
|
|
132
|
-
const parts = commandStr.split(/\s+/);
|
|
133
|
-
const subCommand = (parts[0] ?? '').toLowerCase();
|
|
134
|
-
const remaining = parts.slice(1);
|
|
135
|
-
|
|
136
|
-
const flags = new Set<string>();
|
|
137
|
-
const argParts: string[] = [];
|
|
138
|
-
|
|
139
|
-
for (const part of remaining) {
|
|
140
|
-
if (part.startsWith('--')) {
|
|
141
|
-
flags.add(part);
|
|
142
|
-
} else {
|
|
143
|
-
argParts.push(part);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
subCommand,
|
|
149
|
-
args: argParts.join(' '),
|
|
150
|
-
flags,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// ── Context building ────────────────────────────────────────────────
|
|
155
|
-
|
|
156
|
-
function buildContext(deps: ToolDeps, execContext?: Record<string, unknown>): CommandContext {
|
|
157
|
-
// Extract IDs from the execution context provided by the tool framework
|
|
158
|
-
const groupId = extractString(execContext, 'groupId')
|
|
159
|
-
?? extractString(execContext, 'chatId')
|
|
160
|
-
?? extractNestedString(execContext, 'message', 'chat', 'id');
|
|
161
|
-
|
|
162
|
-
const threadId = extractString(execContext, 'threadId')
|
|
163
|
-
?? extractString(execContext, 'messageThreadId')
|
|
164
|
-
?? extractNestedString(execContext, 'message', 'message_thread_id');
|
|
165
|
-
|
|
166
|
-
const userId = extractString(execContext, 'userId')
|
|
167
|
-
?? extractNestedString(execContext, 'message', 'from', 'id');
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
workspaceDir: deps.workspaceDir,
|
|
171
|
-
configDir: deps.configDir,
|
|
172
|
-
rpc: deps.rpc,
|
|
173
|
-
logger: deps.logger,
|
|
174
|
-
groupId: groupId ?? undefined,
|
|
175
|
-
threadId: threadId ?? undefined,
|
|
176
|
-
userId: userId ?? undefined,
|
|
177
|
-
messageContext: execContext,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function extractString(obj: Record<string, unknown> | undefined, key: string): string | null {
|
|
182
|
-
if (!obj) return null;
|
|
183
|
-
const val = obj[key];
|
|
184
|
-
if (val === undefined || val === null) return null;
|
|
185
|
-
return String(val);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function extractNestedString(
|
|
189
|
-
obj: Record<string, unknown> | undefined,
|
|
190
|
-
...keys: string[]
|
|
191
|
-
): string | null {
|
|
192
|
-
if (!obj) return null;
|
|
193
|
-
let current: unknown = obj;
|
|
194
|
-
for (const key of keys) {
|
|
195
|
-
if (current === null || current === undefined || typeof current !== 'object') return null;
|
|
196
|
-
current = (current as Record<string, unknown>)[key];
|
|
197
|
-
}
|
|
198
|
-
if (current === undefined || current === null) return null;
|
|
199
|
-
return String(current);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// ── Callback handling ───────────────────────────────────────────────
|
|
203
|
-
|
|
204
|
-
async function handleCallback(data: string, ctx: CommandContext): Promise<CommandResult> {
|
|
205
|
-
const { workspaceDir, groupId, threadId, userId } = ctx;
|
|
206
|
-
|
|
207
|
-
if (!groupId || !threadId || !userId) {
|
|
208
|
-
return { text: 'Cannot verify callback: missing context.' };
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const registry = readRegistry(workspaceDir);
|
|
212
|
-
const parsed = parseAndVerifyCallback(data, registry.callbackSecret, groupId, threadId);
|
|
213
|
-
|
|
214
|
-
if (!parsed) {
|
|
215
|
-
return { text: 'Invalid or expired callback.' };
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const { action, slug } = parsed;
|
|
219
|
-
|
|
220
|
-
// Init callbacks: topic doesn't exist in registry yet
|
|
221
|
-
const initTypeMap: Record<string, 'coding' | 'research' | 'marketing' | 'custom'> = {
|
|
222
|
-
ic: 'coding',
|
|
223
|
-
ir: 'research',
|
|
224
|
-
im: 'marketing',
|
|
225
|
-
ix: 'custom',
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
if (action === 'is') {
|
|
229
|
-
return handleInitSlugConfirm(ctx, slug);
|
|
230
|
-
}
|
|
231
|
-
if (action in initTypeMap) {
|
|
232
|
-
return handleInitTypeSelect(ctx, slug, initTypeMap[action]!);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Find the topic entry by slug
|
|
236
|
-
const key = topicKey(groupId, threadId);
|
|
237
|
-
const entry = registry.topics[key];
|
|
238
|
-
|
|
239
|
-
if (!entry || entry.slug !== slug) {
|
|
240
|
-
return { text: 'Topic not found or slug mismatch.' };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
switch (action) {
|
|
244
|
-
case 'fix':
|
|
245
|
-
return handleCallbackFix(ctx);
|
|
246
|
-
|
|
247
|
-
case 'snooze7d':
|
|
248
|
-
return handleSnooze(ctx, '7d');
|
|
249
|
-
|
|
250
|
-
case 'snooze30d':
|
|
251
|
-
return handleSnooze(ctx, '30d');
|
|
252
|
-
|
|
253
|
-
case 'archive':
|
|
254
|
-
return handleArchive(ctx);
|
|
255
|
-
|
|
256
|
-
case 'ignore': {
|
|
257
|
-
// Add the most recent failing check to ignoreChecks
|
|
258
|
-
// For simplicity, we acknowledge the action; the user should specify which check
|
|
259
|
-
return {
|
|
260
|
-
text: `To ignore a specific check, use: /topic snooze or contact an admin. The "Ignore" action requires specifying a check ID.`,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
default:
|
|
265
|
-
return { text: `Unknown callback action: ${htmlEscape(action)}` };
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async function handleCallbackFix(ctx: CommandContext): Promise<CommandResult> {
|
|
270
|
-
// "Fix" re-runs doctor, which auto-fixes fixable issues
|
|
271
|
-
// For now, doctor itself identifies fixable issues
|
|
272
|
-
const { userId, workspaceDir } = ctx;
|
|
273
|
-
|
|
274
|
-
if (userId) {
|
|
275
|
-
appendAudit(
|
|
276
|
-
workspaceDir,
|
|
277
|
-
buildAuditEntry(userId, 'doctor fix', 'callback', 'Fix callback triggered'),
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return handleDoctor(ctx);
|
|
282
|
-
}
|