metame-cli 1.4.18 → 1.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -38
- package/index.js +39 -1
- package/package.json +2 -2
- package/scripts/daemon-admin-commands.js +86 -4
- package/scripts/daemon-agent-commands.js +91 -62
- package/scripts/daemon-agent-tools.js +49 -12
- package/scripts/daemon-bridges.js +26 -6
- package/scripts/daemon-claude-engine.js +111 -32
- package/scripts/daemon-command-router.js +32 -15
- package/scripts/daemon-default.yaml +18 -0
- package/scripts/daemon-exec-commands.js +6 -12
- package/scripts/daemon-file-browser.js +6 -5
- package/scripts/daemon-runtime-lifecycle.js +19 -5
- package/scripts/daemon-session-store.js +176 -41
- package/scripts/daemon-task-scheduler.js +30 -29
- package/scripts/daemon-user-acl.js +399 -0
- package/scripts/daemon.js +43 -6
- package/scripts/distill.js +11 -12
- package/scripts/memory-gc.js +239 -0
- package/scripts/memory-index.js +103 -0
- package/scripts/memory-nightly-reflect.js +299 -0
- package/scripts/memory-write.js +192 -0
- package/scripts/memory.js +144 -6
- package/scripts/schema.js +30 -9
- package/scripts/self-reflect.js +121 -5
- package/scripts/session-analytics.js +9 -10
- package/scripts/task-board.js +9 -3
- package/scripts/telegram-adapter.js +77 -9
|
@@ -18,8 +18,10 @@ function createAgentCommandHandler(deps) {
|
|
|
18
18
|
sessionLabel,
|
|
19
19
|
loadSessionTags,
|
|
20
20
|
sessionRichLabel,
|
|
21
|
+
getSessionRecentContext,
|
|
21
22
|
pendingBinds,
|
|
22
23
|
pendingAgentFlows,
|
|
24
|
+
pendingActivations,
|
|
23
25
|
doBindAgent,
|
|
24
26
|
mergeAgentRole,
|
|
25
27
|
agentTools,
|
|
@@ -28,6 +30,30 @@ function createAgentCommandHandler(deps) {
|
|
|
28
30
|
agentBindTtlMs,
|
|
29
31
|
} = deps;
|
|
30
32
|
|
|
33
|
+
// Pending activations have no TTL — they persist until consumed.
|
|
34
|
+
// The creating chatId is stored to prevent self-activation.
|
|
35
|
+
|
|
36
|
+
function storePendingActivation(agentKey, agentName, cwd, createdByChatId) {
|
|
37
|
+
if (!pendingActivations) return;
|
|
38
|
+
pendingActivations.set(agentKey, {
|
|
39
|
+
agentKey, agentName, cwd,
|
|
40
|
+
createdByChatId: String(createdByChatId),
|
|
41
|
+
createdAt: Date.now(),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Returns the latest pending activation, excluding the creating chat
|
|
46
|
+
function getLatestActivationForChat(chatId) {
|
|
47
|
+
if (!pendingActivations || pendingActivations.size === 0) return null;
|
|
48
|
+
const cid = String(chatId);
|
|
49
|
+
let latest = null;
|
|
50
|
+
for (const rec of pendingActivations.values()) {
|
|
51
|
+
if (rec.createdByChatId === cid) continue; // creating chat cannot self-activate
|
|
52
|
+
if (!latest || rec.createdAt > latest.createdAt) latest = rec;
|
|
53
|
+
}
|
|
54
|
+
return latest;
|
|
55
|
+
}
|
|
56
|
+
|
|
31
57
|
function resolveTtl(valueOrGetter, fallbackMs) {
|
|
32
58
|
const raw = typeof valueOrGetter === 'function' ? valueOrGetter() : valueOrGetter;
|
|
33
59
|
const num = Number(raw);
|
|
@@ -135,9 +161,15 @@ function createAgentCommandHandler(deps) {
|
|
|
135
161
|
return { ok: true, data: legacy };
|
|
136
162
|
}
|
|
137
163
|
|
|
138
|
-
async function createAgentViaUnifiedApi(chatId, name, dir, roleDesc) {
|
|
164
|
+
async function createAgentViaUnifiedApi(chatId, name, dir, roleDesc, opts = {}) {
|
|
165
|
+
// Default: skip binding the creating chat — let the target group activate via /activate
|
|
166
|
+
const { skipChatBinding = true } = opts;
|
|
139
167
|
if (agentTools && typeof agentTools.createNewWorkspaceAgent === 'function') {
|
|
140
|
-
|
|
168
|
+
const res = await agentTools.createNewWorkspaceAgent(name, dir, roleDesc, chatId, { skipChatBinding });
|
|
169
|
+
if (res.ok && skipChatBinding && res.data && res.data.projectKey) {
|
|
170
|
+
storePendingActivation(res.data.projectKey, name, res.data.cwd, chatId);
|
|
171
|
+
}
|
|
172
|
+
return res;
|
|
141
173
|
}
|
|
142
174
|
const bound = await doBindAgent({ sendMessage: async () => {} }, chatId, name, dir);
|
|
143
175
|
if (!bound || bound.ok === false) {
|
|
@@ -249,45 +281,30 @@ function createAgentCommandHandler(deps) {
|
|
|
249
281
|
saveState(state2);
|
|
250
282
|
const name = fullMatch.customTitle;
|
|
251
283
|
const label = name || (fullMatch.summary || fullMatch.firstPrompt || '').slice(0, 40) || sessionId.slice(0, 8);
|
|
252
|
-
await bot.sendMessage(chatId, `Resumed: ${label}\nWorkdir: ${cwd}`);
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
284
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
await bot.sendMessage(chatId, `好的,Agent 名称是「${flow.name}」\n\n请描述这个 Agent 的角色和职责(用自然语言):`);
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
if (flow && flow.step === 'desc' && text && !text.startsWith('/')) {
|
|
267
|
-
pendingAgentFlows.delete(String(chatId));
|
|
268
|
-
const { dir, name } = flow;
|
|
269
|
-
const description = text.trim();
|
|
270
|
-
await bot.sendMessage(chatId, `⏳ 正在配置 Agent「${name}」,稍等...`);
|
|
271
|
-
const created = await createAgentViaUnifiedApi(chatId, name, dir, description);
|
|
272
|
-
if (!created.ok) {
|
|
273
|
-
await bot.sendMessage(chatId, `❌ 创建 Agent 失败: ${created.error}`);
|
|
274
|
-
return true;
|
|
285
|
+
// 读取最近对话片段,帮助确认是否切换到正确的 session
|
|
286
|
+
const recentCtx = getSessionRecentContext ? getSessionRecentContext(sessionId) : null;
|
|
287
|
+
let msg = `✅ 已切换: **${label}**\n📁 ${path.basename(cwd)}`;
|
|
288
|
+
if (recentCtx) {
|
|
289
|
+
if (recentCtx.lastUser) {
|
|
290
|
+
const snippet = recentCtx.lastUser.replace(/\n/g, ' ').slice(0, 80);
|
|
291
|
+
msg += `\n\n💬 上次你说: _${snippet}${recentCtx.lastUser.length > 80 ? '…' : ''}_`;
|
|
275
292
|
}
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const roleInfo = created.data.role || {};
|
|
280
|
-
if (roleInfo.skipped) {
|
|
281
|
-
await bot.sendMessage(chatId, '✅ Agent 创建成功');
|
|
282
|
-
} else if (roleInfo.created) {
|
|
283
|
-
await bot.sendMessage(chatId, '📝 已创建 CLAUDE.md 并写入角色定义');
|
|
284
|
-
} else {
|
|
285
|
-
await bot.sendMessage(chatId, '📝 已将角色定义合并进现有 CLAUDE.md');
|
|
293
|
+
if (recentCtx.lastAssistant) {
|
|
294
|
+
const snippet = recentCtx.lastAssistant.replace(/\n/g, ' ').slice(0, 80);
|
|
295
|
+
msg += `\n🤖 上次回复: ${snippet}${recentCtx.lastAssistant.length > 80 ? '…' : ''}`;
|
|
286
296
|
}
|
|
287
|
-
return true;
|
|
288
297
|
}
|
|
298
|
+
if (bot.sendMarkdown) {
|
|
299
|
+
await bot.sendMarkdown(chatId, msg);
|
|
300
|
+
} else {
|
|
301
|
+
await bot.sendMessage(chatId, msg.replace(/[_*`]/g, ''));
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
289
304
|
}
|
|
290
305
|
|
|
306
|
+
// wizard state machine removed — use natural language to create agents
|
|
307
|
+
|
|
291
308
|
// /agent edit wait-input flow (kept for command compatibility)
|
|
292
309
|
{
|
|
293
310
|
const editFlow = getFreshFlow(String(chatId) + ':edit');
|
|
@@ -336,7 +353,7 @@ function createAgentCommandHandler(deps) {
|
|
|
336
353
|
}
|
|
337
354
|
const agents = res.data.agents || [];
|
|
338
355
|
if (agents.length === 0) {
|
|
339
|
-
await bot.sendMessage(chatId, '暂无已配置的 Agent。\n
|
|
356
|
+
await bot.sendMessage(chatId, '暂无已配置的 Agent。\n用自然语言说"创建一个agent,目录是~/xxx",或 /agent bind <名称> <目录>。');
|
|
340
357
|
return true;
|
|
341
358
|
}
|
|
342
359
|
const lines = ['📋 已配置的 Agent:', ''];
|
|
@@ -354,19 +371,12 @@ function createAgentCommandHandler(deps) {
|
|
|
354
371
|
return true;
|
|
355
372
|
}
|
|
356
373
|
|
|
357
|
-
// /agent new (wizard)
|
|
358
|
-
if (agentSub === 'new') {
|
|
359
|
-
setFlow(String(chatId), { step: 'dir' });
|
|
360
|
-
await sendBrowse(bot, chatId, 'agent-new', HOME, '步骤1/3:选择这个 Agent 的工作目录');
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
374
|
// /agent edit [描述]
|
|
365
375
|
if (agentSub === 'edit') {
|
|
366
376
|
const cfg = loadConfig();
|
|
367
377
|
const { boundProj } = getBoundProject(chatId, cfg);
|
|
368
378
|
if (!boundProj || !boundProj.cwd) {
|
|
369
|
-
await bot.sendMessage(chatId, '❌ 当前群未绑定 Agent
|
|
379
|
+
await bot.sendMessage(chatId, '❌ 当前群未绑定 Agent,请先用自然语言创建 Agent 或 /agent bind <名称> <目录>');
|
|
370
380
|
return true;
|
|
371
381
|
}
|
|
372
382
|
const cwd = normalizeCwd(boundProj.cwd);
|
|
@@ -413,7 +423,7 @@ function createAgentCommandHandler(deps) {
|
|
|
413
423
|
const cfg = loadConfig();
|
|
414
424
|
const { boundProj } = getBoundProject(chatId, cfg);
|
|
415
425
|
if (!boundProj || !boundProj.cwd) {
|
|
416
|
-
await bot.sendMessage(chatId, '❌ 当前群未绑定 Agent
|
|
426
|
+
await bot.sendMessage(chatId, '❌ 当前群未绑定 Agent,请先用自然语言创建 Agent 或 /agent bind <名称> <目录>');
|
|
417
427
|
return true;
|
|
418
428
|
}
|
|
419
429
|
const cwd = normalizeCwd(boundProj.cwd);
|
|
@@ -438,7 +448,7 @@ function createAgentCommandHandler(deps) {
|
|
|
438
448
|
const projects = config.projects || {};
|
|
439
449
|
const entries = Object.entries(projects).filter(([, p]) => p.cwd);
|
|
440
450
|
if (entries.length === 0) {
|
|
441
|
-
await bot.sendMessage(chatId, '暂无已配置的 Agent。\n
|
|
451
|
+
await bot.sendMessage(chatId, '暂无已配置的 Agent。\n用自然语言说"创建一个agent,目录是~/xxx",或 /agent bind <名称> <目录>。');
|
|
442
452
|
return true;
|
|
443
453
|
}
|
|
444
454
|
const currentSession = getSession(chatId);
|
|
@@ -453,6 +463,41 @@ function createAgentCommandHandler(deps) {
|
|
|
453
463
|
}
|
|
454
464
|
}
|
|
455
465
|
|
|
466
|
+
// /activate — bind this unbound chat to the most recently created pending agent
|
|
467
|
+
if (text === '/activate' || text.startsWith('/activate ')) {
|
|
468
|
+
const cfg = loadConfig();
|
|
469
|
+
const { boundKey } = getBoundProject(chatId, cfg);
|
|
470
|
+
if (boundKey) {
|
|
471
|
+
await bot.sendMessage(chatId, `此群已绑定到「${boundKey}」,无需激活。如需更换请先 /agent unbind`);
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
const activation = getLatestActivationForChat(chatId);
|
|
475
|
+
if (!activation) {
|
|
476
|
+
// Check if this chat was the creator (self-activate attempt)
|
|
477
|
+
if (pendingActivations) {
|
|
478
|
+
for (const rec of pendingActivations.values()) {
|
|
479
|
+
if (rec.createdByChatId === String(chatId)) {
|
|
480
|
+
await bot.sendMessage(chatId,
|
|
481
|
+
`❌ 不能在创建来源群激活。\n请在你新建的目标群里发送 \`/activate\`\n\n` +
|
|
482
|
+
`或在任意群用: \`/agent bind ${rec.agentName} ${rec.cwd}\``
|
|
483
|
+
);
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// No pending activation at all — guide to manual bind
|
|
489
|
+
await bot.sendMessage(chatId,
|
|
490
|
+
'没有待激活的 Agent。\n\n如果已创建过 Agent,直接用:\n`/agent bind <名称> <目录>`\n即可绑定,不需要重新创建。'
|
|
491
|
+
);
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
const bindRes = await bindViaUnifiedApi(bot, chatId, activation.agentName, activation.cwd);
|
|
495
|
+
if (bindRes.ok) {
|
|
496
|
+
pendingActivations && pendingActivations.delete(activation.agentKey);
|
|
497
|
+
}
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
|
|
456
501
|
// /agent-bind-dir <path>: internal callback for bind picker
|
|
457
502
|
if (text.startsWith('/agent-bind-dir ')) {
|
|
458
503
|
const dirPath = expandPath(text.slice(16).trim());
|
|
@@ -466,22 +511,6 @@ function createAgentCommandHandler(deps) {
|
|
|
466
511
|
return true;
|
|
467
512
|
}
|
|
468
513
|
|
|
469
|
-
// /agent-dir <path>: internal callback for /agent new wizard
|
|
470
|
-
if (text.startsWith('/agent-dir ')) {
|
|
471
|
-
const dirPath = expandPath(text.slice(11).trim());
|
|
472
|
-
const flow = getFreshFlow(String(chatId));
|
|
473
|
-
if (!flow || flow.step !== 'dir') {
|
|
474
|
-
await bot.sendMessage(chatId, '❌ 没有待完成的 /agent new,请重新发送 /agent new');
|
|
475
|
-
return true;
|
|
476
|
-
}
|
|
477
|
-
flow.dir = dirPath;
|
|
478
|
-
flow.step = 'name';
|
|
479
|
-
setFlow(String(chatId), flow);
|
|
480
|
-
const displayPath = dirPath.replace(HOME, '~');
|
|
481
|
-
await bot.sendMessage(chatId, `✓ 已选择目录:${displayPath}\n\n步骤2/3:给这个 Agent 起个名字?`);
|
|
482
|
-
return true;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
514
|
return false;
|
|
486
515
|
}
|
|
487
516
|
|
|
@@ -37,7 +37,7 @@ function createAgentTools(deps) {
|
|
|
37
37
|
if (!cfg[adapterKey].chat_agent_map) cfg[adapterKey].chat_agent_map = {};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
async function bindAgentToChat(chatId, agentName, workspaceDir) {
|
|
40
|
+
async function bindAgentToChat(chatId, agentName, workspaceDir, { force = false } = {}) {
|
|
41
41
|
try {
|
|
42
42
|
const safeName = sanitizeText(agentName, 120);
|
|
43
43
|
if (!safeName) return { ok: false, error: 'agentName is required' };
|
|
@@ -64,6 +64,16 @@ function createAgentTools(deps) {
|
|
|
64
64
|
return { ok: false, error: `workspaceDir is not a directory: ${resolvedDir}` };
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
// Overwrite protection: reject if chat is already bound to a different agent
|
|
68
|
+
const existingKey = cfg[adapterKey].chat_agent_map[String(chatId)];
|
|
69
|
+
if (existingKey && existingKey !== projectKey && !force) {
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
error: `此群已绑定到 "${existingKey}",如需覆盖请使用 force:true`,
|
|
73
|
+
data: { existingKey },
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
67
77
|
const idVal = typeof chatId === 'number' ? chatId : String(chatId);
|
|
68
78
|
if (!cfg[adapterKey].allowed_chat_ids.includes(idVal)) cfg[adapterKey].allowed_chat_ids.push(idVal);
|
|
69
79
|
|
|
@@ -165,30 +175,57 @@ ${safeDelta}
|
|
|
165
175
|
}
|
|
166
176
|
}
|
|
167
177
|
|
|
168
|
-
async function createNewWorkspaceAgent(agentName, workspaceDir, roleDescription, chatId) {
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
async function createNewWorkspaceAgent(agentName, workspaceDir, roleDescription, chatId, { skipChatBinding = false } = {}) {
|
|
179
|
+
let bindData;
|
|
180
|
+
|
|
181
|
+
if (skipChatBinding) {
|
|
182
|
+
// Create the project entry without touching chat_agent_map
|
|
183
|
+
const safeName = sanitizeText(agentName, 120);
|
|
184
|
+
if (!safeName) return { ok: false, error: 'agentName is required' };
|
|
185
|
+
const resolvedDir = resolveWorkspaceDir(workspaceDir);
|
|
186
|
+
if (!resolvedDir) return { ok: false, error: 'workspaceDir is required' };
|
|
187
|
+
if (!fs.existsSync(resolvedDir) || !fs.statSync(resolvedDir).isDirectory()) {
|
|
188
|
+
return { ok: false, error: `workspaceDir not found or not a directory: ${resolvedDir}` };
|
|
189
|
+
}
|
|
190
|
+
const cfg = loadConfig();
|
|
191
|
+
if (!cfg.projects) cfg.projects = {};
|
|
192
|
+
const projectKey = toProjectKey(safeName, chatId);
|
|
193
|
+
const existed = !!cfg.projects[projectKey];
|
|
194
|
+
if (!existed) {
|
|
195
|
+
cfg.projects[projectKey] = { name: safeName, cwd: resolvedDir, nicknames: [safeName] };
|
|
196
|
+
writeConfigSafe(cfg);
|
|
197
|
+
backupConfig();
|
|
198
|
+
}
|
|
199
|
+
bindData = {
|
|
200
|
+
projectKey,
|
|
201
|
+
cwd: resolvedDir,
|
|
202
|
+
isNewProject: !existed,
|
|
203
|
+
chatId: null, // not bound to any chat
|
|
204
|
+
project: cfg.projects[projectKey],
|
|
205
|
+
};
|
|
206
|
+
} else {
|
|
207
|
+
const bindResult = await bindAgentToChat(chatId, agentName, workspaceDir);
|
|
208
|
+
if (!bindResult.ok) return bindResult;
|
|
209
|
+
bindData = bindResult.data;
|
|
210
|
+
}
|
|
171
211
|
|
|
172
212
|
const roleText = sanitizeText(roleDescription, 1200);
|
|
173
213
|
if (!roleText) {
|
|
174
|
-
return { ok: true, data: { ...
|
|
214
|
+
return { ok: true, data: { ...bindData, role: { skipped: true } } };
|
|
175
215
|
}
|
|
176
216
|
|
|
177
|
-
const roleResult = await editAgentRoleDefinition(
|
|
217
|
+
const roleResult = await editAgentRoleDefinition(bindData.cwd, roleText);
|
|
178
218
|
if (!roleResult.ok) {
|
|
179
219
|
return {
|
|
180
220
|
ok: false,
|
|
181
|
-
error: `agent
|
|
182
|
-
data: { ...
|
|
221
|
+
error: `agent created but role update failed: ${roleResult.error}`,
|
|
222
|
+
data: { ...bindData, roleError: roleResult.error },
|
|
183
223
|
};
|
|
184
224
|
}
|
|
185
225
|
|
|
186
226
|
return {
|
|
187
227
|
ok: true,
|
|
188
|
-
data: {
|
|
189
|
-
...bindResult.data,
|
|
190
|
-
role: roleResult.data,
|
|
191
|
-
},
|
|
228
|
+
data: { ...bindData, role: roleResult.data },
|
|
192
229
|
};
|
|
193
230
|
}
|
|
194
231
|
|
|
@@ -12,8 +12,29 @@ function createBridgeStarter(deps) {
|
|
|
12
12
|
saveState,
|
|
13
13
|
getSession,
|
|
14
14
|
handleCommand,
|
|
15
|
+
pendingActivations, // optional — used to show smart activation hint
|
|
15
16
|
} = deps;
|
|
16
17
|
|
|
18
|
+
// Returns the best pending activation for a given chatId (excludes self-created)
|
|
19
|
+
function getPendingActivationForChat(chatId) {
|
|
20
|
+
if (!pendingActivations || pendingActivations.size === 0) return null;
|
|
21
|
+
const cid = String(chatId);
|
|
22
|
+
let latest = null;
|
|
23
|
+
for (const rec of pendingActivations.values()) {
|
|
24
|
+
if (rec.createdByChatId === cid) continue;
|
|
25
|
+
if (!latest || rec.createdAt > latest.createdAt) latest = rec;
|
|
26
|
+
}
|
|
27
|
+
return latest;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function unauthorizedMsg(chatId, useSend) {
|
|
31
|
+
const pending = getPendingActivationForChat(chatId);
|
|
32
|
+
if (pending) {
|
|
33
|
+
return `⚠️ 此群未授权\n\n发送以下命令激活 Agent「${pending.agentName}」:\n\`/activate\``;
|
|
34
|
+
}
|
|
35
|
+
return '⚠️ 此群未授权\n\n如已创建 Agent,发送 `/activate` 完成绑定。\n否则请先在主群创建 Agent。';
|
|
36
|
+
}
|
|
37
|
+
|
|
17
38
|
async function startTelegramBridge(config, executeTaskByName) {
|
|
18
39
|
if (!config.telegram || !config.telegram.enabled) return null;
|
|
19
40
|
if (!config.telegram.bot_token) {
|
|
@@ -68,13 +89,13 @@ function createBridgeStarter(deps) {
|
|
|
68
89
|
const trimmedText = msg.text && msg.text.trim();
|
|
69
90
|
const isBindCmd = trimmedText && (
|
|
70
91
|
trimmedText.startsWith('/agent bind')
|
|
71
|
-
|| trimmedText.startsWith('/agent new')
|
|
72
92
|
|| trimmedText.startsWith('/agent-bind-dir')
|
|
73
93
|
|| trimmedText.startsWith('/browse bind')
|
|
94
|
+
|| trimmedText === '/activate'
|
|
74
95
|
);
|
|
75
96
|
if (!allowedIds.includes(chatId) && !isBindCmd) {
|
|
76
97
|
log('WARN', `Rejected message from unauthorized chat: ${chatId}`);
|
|
77
|
-
bot.sendMessage(chatId,
|
|
98
|
+
bot.sendMessage(chatId, unauthorizedMsg(chatId)).catch(() => {});
|
|
78
99
|
continue;
|
|
79
100
|
}
|
|
80
101
|
|
|
@@ -157,15 +178,14 @@ function createBridgeStarter(deps) {
|
|
|
157
178
|
const trimmedText = text && text.trim();
|
|
158
179
|
const isBindCmd = trimmedText && (
|
|
159
180
|
trimmedText.startsWith('/agent bind')
|
|
160
|
-
|| trimmedText.startsWith('/agent new')
|
|
161
181
|
|| trimmedText.startsWith('/agent-bind-dir')
|
|
162
182
|
|| trimmedText.startsWith('/browse bind')
|
|
183
|
+
|| trimmedText === '/activate'
|
|
163
184
|
);
|
|
164
185
|
if (!allowedIds.includes(chatId) && !isBindCmd) {
|
|
165
186
|
log('WARN', `Feishu: rejected message from ${chatId}`);
|
|
166
|
-
(
|
|
167
|
-
|
|
168
|
-
: bot.sendMessage(chatId, '⚠️ 此会话未授权\n\n复制发送以下命令注册:\n\n/agent bind personal')).catch(() => {});
|
|
187
|
+
const msg = unauthorizedMsg(chatId);
|
|
188
|
+
(bot.sendMarkdown ? bot.sendMarkdown(chatId, msg) : bot.sendMessage(chatId, msg)).catch(() => {});
|
|
169
189
|
return;
|
|
170
190
|
}
|
|
171
191
|
|