chatccc 0.2.122 → 0.2.124

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.
@@ -19,8 +19,6 @@ import {
19
19
  CONFIG_FILE,
20
20
  GIT_TIMEOUT_MS,
21
21
  PROJECT_ROOT,
22
- AGENT_MODE_COMMANDS,
23
- AGENT_TOOLS,
24
22
  anthropicConfigDisplay,
25
23
  config,
26
24
  fileLog,
@@ -127,85 +125,6 @@ function isNonWechatP2p(platform: PlatformAdapter, chatType: string): boolean {
127
125
  return chatType === "p2p" && platform.kind !== "wechat";
128
126
  }
129
127
 
130
- /** 根据 Agent 类型构建欢迎卡片中的指令说明 */
131
- function buildWelcomeCommands(tool: string): string {
132
- const lines = [
133
- "发送 **/cd** 切换新建会话的默认目录。",
134
- "发送 **/model** 查看或切换当前会话的模型。",
135
- "发送 **/new** 创建新会话,**/newh** 重置当前会话(沿用工作目录)。",
136
- "发送 **/sessions** 查看所有会话状态。",
137
- ];
138
- const modeCmds = AGENT_MODE_COMMANDS[tool as AgentTool] ?? [];
139
- for (const mc of modeCmds) {
140
- lines.push(`发送 **${mc.command} <消息>** ${mc.description}。`);
141
- }
142
- return lines.join("\n");
143
- }
144
-
145
- /** 根据指令名从 AGENT_MODE_COMMANDS 查找对应的 mode 和支持的 agent 列表 */
146
- function resolveModeCommand(cmd: string): { mode: "plan" | "ask"; supportedTools: string[] } | null {
147
- const supportedTools: string[] = [];
148
- let mode: "plan" | "ask" | null = null;
149
- for (const tool of AGENT_TOOLS) {
150
- for (const mc of AGENT_MODE_COMMANDS[tool]) {
151
- if (mc.command === cmd) {
152
- supportedTools.push(tool);
153
- mode = mc.mode;
154
- break;
155
- }
156
- }
157
- }
158
- return mode ? { mode, supportedTools } : null;
159
- }
160
-
161
- /** 如果当前群名是未命名会话("新会话" 或 "新会话-xxx"),用消息内容前缀重命名 */
162
- async function renameUntitledSession(
163
- platform: PlatformAdapter,
164
- chatId: string,
165
- chatType: string,
166
- sessionId: string,
167
- tool: string,
168
- namePrefix: string,
169
- description: string | undefined,
170
- chatInfo: { name: string } | undefined,
171
- ): Promise<void> {
172
- const MAX_PREFIX = 10;
173
- const prefix = namePrefix.slice(0, MAX_PREFIX);
174
-
175
- if (chatType !== "p2p" && chatInfo && isUntitledSessionChatName(chatInfo.name)) {
176
- const adapter = getAdapterForTool(tool, sessionId);
177
- const info = await adapter.getSessionInfo(sessionId).catch(() => undefined);
178
- const sessionCwd = info?.cwd ?? (await getDefaultCwd(chatId));
179
- const newName = sessionChatName(prefix, sessionCwd);
180
- try {
181
- await platform.updateChatInfo(chatId, newName, description!);
182
- console.log(`[${ts()}] [RENAME] First message → group renamed to "${newName}"`);
183
- await recordSessionRegistry({ chatId, sessionId, tool, chatName: newName }).catch(() => {});
184
- await saveSessionTool(sessionId, tool, newName).catch(() => {});
185
- } catch (err) {
186
- console.error(`[${ts()}] [RENAME] Failed: ${(err as Error).message}`);
187
- }
188
- }
189
-
190
- if (chatType === "p2p" && platform.kind === "wechat") {
191
- try {
192
- const reg = await loadSessionRegistryForBinding();
193
- const rec = reg[chatId];
194
- if (rec && rec.sessionId === sessionId && isUntitledSessionChatName(rec.chatName ?? "")) {
195
- const adapter = getAdapterForTool(tool, sessionId);
196
- const info = await adapter.getSessionInfo(sessionId).catch(() => undefined);
197
- const sessionCwd = info?.cwd ?? (await getDefaultCwd(chatId));
198
- const newName2 = sessionChatName(prefix, sessionCwd);
199
- await recordSessionRegistry({ chatId, sessionId, tool, chatName: newName2 }).catch(() => {});
200
- await saveSessionTool(sessionId, tool, newName2).catch(() => {});
201
- console.log(`[${ts()}] [RENAME] WeChat P2P → "${newName2}"`);
202
- }
203
- } catch (err) {
204
- console.error(`[${ts()}] [RENAME] WeChat P2P failed: ${(err as Error).message}`);
205
- }
206
- }
207
- }
208
-
209
128
  async function cleanupNonWechatP2pBinding(
210
129
  platform: PlatformAdapter,
211
130
  chatId: string,
@@ -510,7 +429,11 @@ export async function handleCommand(
510
429
  `**Session ID:** ${sessionId}\n` +
511
430
  `**工作目录:** \`${cwd}\`\n\n` +
512
431
  `直接在这里发消息即可与 ${toolLabel} 对话。\n\n` +
513
- buildWelcomeCommands(tool),
432
+ `发送 **/cd** 切换新建会话的默认目录。\n` +
433
+ `发送 **/model** 查看或切换当前会话的模型。\n` +
434
+ `发送 **/new** 创建新会话,**/newh** 重置当前会话(沿用工作目录)。\n` +
435
+ `发送 **/sessions** 查看所有会话状态。\n` +
436
+ `发送 \`/git <子命令>\` 在本会话工作目录执行 git,例如 \`/git status\`、\`/git log --oneline -n 5\`。`,
514
437
  "green",
515
438
  );
516
439
  console.log(
@@ -592,7 +515,11 @@ export async function handleCommand(
592
515
  `**Session ID:** ${sessionId}\n` +
593
516
  `**工作目录:** \`${cwd}\`\n\n` +
594
517
  `直接在这里发消息即可与 ${toolLabel} 对话。\n\n` +
595
- buildWelcomeCommands(tool),
518
+ `发送 **/cd** 切换新建会话的默认目录。\n` +
519
+ `发送 **/model** 查看或切换当前会话的模型。\n` +
520
+ `发送 **/new** 创建新会话,**/newh** 重置当前会话(沿用工作目录)。\n` +
521
+ `发送 **/sessions** 查看所有会话状态。\n` +
522
+ `发送 \`/git <子命令>\` 在本会话工作目录执行 git,例如 \`/git status\`、\`/git log --oneline -n 5\`。`,
596
523
  "green",
597
524
  );
598
525
 
@@ -950,8 +877,9 @@ export async function handleCommand(
950
877
  `会话已重置为新的 **${toolLabel}** 会话。\n\n` +
951
878
  `**Session ID:** ${newSessionId}\n` +
952
879
  `**工作目录:** \`${cwd}\`(沿用当前会话目录)\n\n` +
953
- `直接在这里发消息即可继续对话。\n\n` +
954
- buildWelcomeCommands(descriptionTool),
880
+ `直接在这里发消息即可继续对话。\n` +
881
+ `发送 **/cd** 可切换新建会话的默认目录。\n` +
882
+ `发送 **/model** 查看或切换当前会话的模型。`,
955
883
  "green",
956
884
  );
957
885
 
@@ -1253,134 +1181,6 @@ export async function handleCommand(
1253
1181
  return;
1254
1182
  }
1255
1183
 
1256
- // /plan <message> — 只读/规划模式
1257
- if (textLower.startsWith("/plan ")) {
1258
- const planText = text.slice(6).trim();
1259
- const resolved = resolveModeCommand("/plan");
1260
- if (!planText) {
1261
- await platform.sendText(chatId, "用法:`/plan <消息>` — 在只读/规划模式下提问。").catch(() => {});
1262
- logTrace(tid, "DONE", { outcome: "plan_no_message" });
1263
- return;
1264
- }
1265
- if (resolved?.supportedTools.includes(descriptionTool) === true) {
1266
- logTrace(tid, "BRANCH", { cmd: "/plan", sessionId, tool: descriptionTool });
1267
-
1268
- await renameUntitledSession(
1269
- platform, chatId, chatType, sessionId, descriptionTool,
1270
- planText, description, chatInfo,
1271
- );
1272
-
1273
- if (isSessionRunning(sessionId)) {
1274
- const queued = enqueueMessage(sessionId, {
1275
- text, chatId, openId, msgTimestamp, chatType, traceId: tid,
1276
- });
1277
- if (queued) {
1278
- logTrace(tid, "QUEUED", { sessionId, mode: "plan" });
1279
- if (platform.kind === "wechat") {
1280
- await platform.sendText(chatId, "当前会话正在生成中,你的消息已进入缓存队列,生成完成后会立即处理。发送 /cancel 可取消缓存。").catch(() => {});
1281
- } else {
1282
- await platform.sendRawCard(chatId, buildQueuedCard(planText)).catch(() => {});
1283
- }
1284
- } else {
1285
- logTrace(tid, "QUEUE_FULL", { sessionId });
1286
- if (platform.kind === "wechat") {
1287
- await platform.sendText(chatId, "当前缓存队列中已有消息等待处理,请等待或发送 /stop(停止生成)或 /cancel(取消缓存)。").catch(() => {});
1288
- } else {
1289
- await platform.sendRawCard(chatId, buildQueueFullCard()).catch(() => {});
1290
- }
1291
- }
1292
- return;
1293
- }
1294
-
1295
- if (shouldSendWechatProcessingAck(platform, planText.toLowerCase(), chatType)) {
1296
- await platform.sendText(chatId, "生成中...").catch(() => {});
1297
- }
1298
-
1299
- try {
1300
- logTrace(tid, "RESUME", { sessionId, tool: descriptionTool, mode: "plan" });
1301
- await resumeAndPrompt(
1302
- sessionId, planText, platform, chatId, msgTimestamp,
1303
- descriptionTool, tid, "plan",
1304
- );
1305
- logTrace(tid, "DONE", { outcome: "plan_done", sessionId });
1306
- } catch (err) {
1307
- logTrace(tid, "DONE", { outcome: "plan_fail", error: (err as Error).message });
1308
- await platform.sendCard(
1309
- chatId, "Error",
1310
- `Failed to run plan mode:\n${(err as Error).message}`,
1311
- "red",
1312
- );
1313
- }
1314
- return;
1315
- }
1316
-
1317
- logTrace(tid, "BRANCH", { cmd: "/plan", sessionId, tool: descriptionTool, fallback: "raw_message" });
1318
- }
1319
-
1320
- // /ask <message> — 只读/问答模式
1321
- if (textLower.startsWith("/ask ")) {
1322
- const askText = text.slice(5).trim();
1323
- const resolved = resolveModeCommand("/ask");
1324
- if (!askText) {
1325
- await platform.sendText(chatId, "用法:`/ask <消息>` — 在只读/问答模式下提问。").catch(() => {});
1326
- logTrace(tid, "DONE", { outcome: "ask_no_message" });
1327
- return;
1328
- }
1329
- if (resolved?.supportedTools.includes(descriptionTool) === true) {
1330
- logTrace(tid, "BRANCH", { cmd: "/ask", sessionId, tool: descriptionTool });
1331
-
1332
- await renameUntitledSession(
1333
- platform, chatId, chatType, sessionId, descriptionTool,
1334
- askText, description, chatInfo,
1335
- );
1336
-
1337
- if (isSessionRunning(sessionId)) {
1338
- const queued = enqueueMessage(sessionId, {
1339
- text, chatId, openId, msgTimestamp, chatType, traceId: tid,
1340
- });
1341
- if (queued) {
1342
- logTrace(tid, "QUEUED", { sessionId, mode: "ask" });
1343
- if (platform.kind === "wechat") {
1344
- await platform.sendText(chatId, "当前会话正在生成中,你的消息已进入缓存队列,生成完成后会立即处理。发送 /cancel 可取消缓存。").catch(() => {});
1345
- } else {
1346
- await platform.sendRawCard(chatId, buildQueuedCard(askText)).catch(() => {});
1347
- }
1348
- } else {
1349
- logTrace(tid, "QUEUE_FULL", { sessionId });
1350
- if (platform.kind === "wechat") {
1351
- await platform.sendText(chatId, "当前缓存队列中已有消息等待处理,请等待或发送 /stop(停止生成)或 /cancel(取消缓存)。").catch(() => {});
1352
- } else {
1353
- await platform.sendRawCard(chatId, buildQueueFullCard()).catch(() => {});
1354
- }
1355
- }
1356
- return;
1357
- }
1358
-
1359
- if (shouldSendWechatProcessingAck(platform, askText.toLowerCase(), chatType)) {
1360
- await platform.sendText(chatId, "生成中...").catch(() => {});
1361
- }
1362
-
1363
- try {
1364
- logTrace(tid, "RESUME", { sessionId, tool: descriptionTool, mode: "ask" });
1365
- await resumeAndPrompt(
1366
- sessionId, askText, platform, chatId, msgTimestamp,
1367
- descriptionTool, tid, "ask",
1368
- );
1369
- logTrace(tid, "DONE", { outcome: "ask_done", sessionId });
1370
- } catch (err) {
1371
- logTrace(tid, "DONE", { outcome: "ask_fail", error: (err as Error).message });
1372
- await platform.sendCard(
1373
- chatId, "Error",
1374
- `Failed to run ask mode:\n${(err as Error).message}`,
1375
- "red",
1376
- );
1377
- }
1378
- return;
1379
- }
1380
-
1381
- logTrace(tid, "BRANCH", { cmd: "/ask", sessionId, tool: descriptionTool, fallback: "raw_message" });
1382
- }
1383
-
1384
1184
  const lastTs = lastMsgTimestamps.get(chatId);
1385
1185
  if (lastTs !== undefined && msgTimestamp <= lastTs) {
1386
1186
  logTrace(tid, "DONE", {
@@ -1619,7 +1419,8 @@ export async function handleCommand(
1619
1419
  `**Session ID:** ${sessionId}\n` +
1620
1420
  `**工作目录:** \`${cwd}\`\n\n` +
1621
1421
  `下面会自动把你的私聊消息作为第一句话发送给 ${toolLabel}。\n\n` +
1622
- buildWelcomeCommands(tool),
1422
+ `发送 **/model** 查看或切换当前会话的模型。\n` +
1423
+ `发送 **/new** 创建新会话,**/newh** 重置当前会话(沿用工作目录)。`,
1623
1424
  "green",
1624
1425
  );
1625
1426
  platform.setChatAvatar(newChatId, tool, "new").catch(() => {});
package/src/session.ts CHANGED
@@ -832,9 +832,8 @@ export async function resumeAndPrompt(
832
832
  msgTimestamp: number,
833
833
  tool: string,
834
834
  traceId?: string,
835
- permissionMode?: "plan" | "ask",
836
835
  ): Promise<void> {
837
- return runAgentSession(sessionId, userText, platform, chatId, msgTimestamp, tool, traceId, permissionMode);
836
+ return runAgentSession(sessionId, userText, platform, chatId, msgTimestamp, tool, traceId);
838
837
  }
839
838
 
840
839
  // ---------------------------------------------------------------------------
@@ -849,7 +848,6 @@ export async function runAgentSession(
849
848
  msgTimestamp: number,
850
849
  tool: string,
851
850
  traceId?: string,
852
- permissionMode?: "plan" | "ask",
853
851
  ): Promise<void> {
854
852
  const tid = traceId ?? "";
855
853
 
@@ -1108,7 +1106,6 @@ export async function runAgentSession(
1108
1106
  clearPromptProcessMonitor(sessionId);
1109
1107
  if (exitInfo.pid !== undefined) unregisterProcess(exitInfo.pid);
1110
1108
  },
1111
- permissionMode,
1112
1109
  })) {
1113
1110
  for (const block of unifiedMsg.blocks) {
1114
1111
  accumulateBlockContent(block, state, toolCallMap);