chatccc 0.2.138 → 0.2.139

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 CHANGED
@@ -311,12 +311,6 @@ Codex 的默认模型和推理强度可继续由 `~/.codex/config.toml` 管理
311
311
  | `/sessions` | 查看所有会话状态 |
312
312
  | `/git <子命令>` | 在当前会话工作目录执行 `git ...` 并回传输出 |
313
313
  | `/restart` | 重启机器人进程 |
314
- | `/plan [内容]` | 以 plan 模式传递给 Agent,**不跳过权限检查**(无 `--dangerously-skip-permissions`) |
315
- | `/ask [内容]` | 以 plan 模式传递给 Agent,**不跳过权限检查**(同 `/plan`) |
316
-
317
- > **`/plan` 与 `/ask`**:这两个指令不会被 ChatCCC 当作内置命令处理,而是把用户原话(含指令前缀)完整传给 Agent。与普通消息的区别是:调用时不添加 `--dangerously-skip-permissions`,改为 `--permission-mode plan`,Agent 会先在权限沙盒内运行,遇到命令执行等操作时需要确认。适合需要安全审查的任务场景。
318
- >
319
- > **群名**:`/plan` / `/ask` 消息如果是群内第一条消息,也会触发群名更新。为美观起见,群名会自动去除 `/plan` 或 `/ask` 前缀。
320
314
 
321
315
  > **模型切换**:`/model` 查看可选模型清单,`/model <名称>` 模糊匹配切换,`/model clear` 恢复默认。当前仅 Claude Code 支持模型切换(需同时填写 `claude.model` 和 `claude.subagentModel`),Cursor / Codex 切换正在开发中。
322
316
 
@@ -50,6 +50,4 @@ Never execute the same successful shell command three times for the same task in
50
50
 
51
51
  If the same command has already succeeded twice in a row, the next assistant action must be a final response to the user, not another tool call.
52
52
 
53
- Successful repeated command execution is a terminal condition. Prefer a concise final response over further tool calls.
54
-
55
- 如果计划写好了等待你的审阅,将计划文件通过当前聊天软件发给用户
53
+ Successful repeated command execution is a terminal condition. Prefer a concise final response over further tool calls.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatccc",
3
- "version": "0.2.138",
3
+ "version": "0.2.139",
4
4
  "description": "Feishu bot bridge for Claude Code",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -128,8 +128,6 @@ export interface ToolPromptOptions {
128
128
  onProcessStart?: (info: ToolProcessInfo) => void;
129
129
  /** Called when the adapter leaves the prompt process scope normally or by abort. */
130
130
  onProcessExit?: (info: ToolProcessInfo) => void;
131
- /** 是否为 /plan 或 /ask 模式:不开启 dangerous skip permissions */
132
- planMode?: boolean;
133
131
  }
134
132
 
135
133
  // ---------------------------------------------------------------------------
@@ -243,7 +243,6 @@ function buildSdkOptions(args: {
243
243
  apiKey?: string;
244
244
  baseUrl?: string;
245
245
  maxTurn: number;
246
- planMode?: boolean;
247
246
  abortController?: AbortController;
248
247
  }): ClaudeSdkSessionOptions {
249
248
  const {
@@ -255,7 +254,6 @@ function buildSdkOptions(args: {
255
254
  apiKey,
256
255
  baseUrl,
257
256
  maxTurn,
258
- planMode,
259
257
  abortController,
260
258
  } = args;
261
259
 
@@ -263,7 +261,7 @@ function buildSdkOptions(args: {
263
261
  cwd,
264
262
  abortController,
265
263
  settingSources: ["user", "project", "local"] as SettingSource[],
266
- permissionMode: planMode ? "plan" : "bypassPermissions",
264
+ permissionMode: "bypassPermissions",
267
265
  autoCompactEnabled: true,
268
266
  maxTurns: maxTurn,
269
267
  skills: "all",
@@ -275,9 +273,7 @@ function buildSdkOptions(args: {
275
273
  },
276
274
  };
277
275
 
278
- if (!planMode) {
279
- options.allowDangerouslySkipPermissions = true;
280
- }
276
+ options.allowDangerouslySkipPermissions = true;
281
277
  if (!isEmpty(model)) {
282
278
  options.model = model;
283
279
  }
@@ -410,7 +406,6 @@ class ClaudeAdapter implements ToolAdapter {
410
406
  apiKey: this.apiKey,
411
407
  baseUrl: this.baseUrl,
412
408
  maxTurn: this.maxTurn,
413
- planMode: options?.planMode,
414
409
  abortController,
415
410
  })),
416
411
  );
@@ -94,21 +94,6 @@ export function sessionChatName(left: string, cwd: string): string {
94
94
  return `${left}-${cwdDisplayName(cwd)}`;
95
95
  }
96
96
 
97
- /** 判断用户消息是否以 /plan 或 /ask 开头(忽略大小写和尾部空格) */
98
- function isPlanOrAsk(text: string): boolean {
99
- const t = text.toLowerCase().trim();
100
- return t === "/plan" || t.startsWith("/plan ") || t === "/ask" || t.startsWith("/ask ");
101
- }
102
-
103
- /** 剥离 /plan 或 /ask 前缀,用于群名等展示场景 */
104
- function stripPlanOrAskPrefix(text: string): string {
105
- if (isPlanOrAsk(text)) {
106
- const match = text.match(/^\/(?:plan|ask)\s*(.*)/i);
107
- return (match?.[1] ?? "").trim() || text.trim();
108
- }
109
- return text;
110
- }
111
-
112
97
  /** 模型模糊匹配:精确匹配优先,否则找子串匹配(模型名越短越优先) */
113
98
  function findModelMatch(input: string, models: string[]): string | null {
114
99
  if (models.length === 0) return null;
@@ -134,7 +119,7 @@ function shouldSendWechatProcessingAck(
134
119
  chatType: string,
135
120
  text: string,
136
121
  ): boolean {
137
- return platform.kind === "wechat" && chatType === "p2p" && (!textLower.startsWith("/") || isPlanOrAsk(text));
122
+ return platform.kind === "wechat" && chatType === "p2p" && !textLower.startsWith("/");
138
123
  }
139
124
 
140
125
  function isNonWechatP2p(platform: PlatformAdapter, chatType: string): boolean {
@@ -616,10 +601,10 @@ export async function handleCommand(
616
601
  if (
617
602
  chatType !== "p2p" &&
618
603
  isUntitledSessionChatName(chatInfo!.name) &&
619
- (!textLower.startsWith("/") || isPlanOrAsk(text))
604
+ !textLower.startsWith("/")
620
605
  ) {
621
606
  const MAX_PREFIX = 10;
622
- const prefix = stripPlanOrAskPrefix(text).slice(0, MAX_PREFIX);
607
+ const prefix = text.slice(0, MAX_PREFIX);
623
608
  const adapter = getAdapterForTool(descriptionTool, sessionId);
624
609
  const info = await adapter
625
610
  .getSessionInfo(sessionId)
@@ -651,7 +636,7 @@ export async function handleCommand(
651
636
  if (
652
637
  chatType === "p2p" &&
653
638
  platform.kind === "wechat" &&
654
- (!textLower.startsWith("/") || isPlanOrAsk(text))
639
+ !textLower.startsWith("/")
655
640
  ) {
656
641
  try {
657
642
  const reg = await loadSessionRegistryForBinding();
@@ -1253,7 +1238,7 @@ export async function handleCommand(
1253
1238
  msgTimestamp,
1254
1239
  descriptionTool,
1255
1240
  tid,
1256
- isPlanOrAsk(text),
1241
+ false,
1257
1242
  );
1258
1243
  logTrace(tid, "DONE", { outcome: "resume_done", sessionId });
1259
1244
  console.log(`[${ts()}] [RESUME] Session ${sessionId} done`);
@@ -1328,7 +1313,7 @@ export async function handleCommand(
1328
1313
  }
1329
1314
 
1330
1315
  // 飞书私聊普通消息:不再绑定私聊本身,而是自动创建会话群并把私聊内容作为首轮 prompt。
1331
- if (isNonWechatP2p(platform, chatType) && (!textLower.startsWith("/") || isPlanOrAsk(text))) {
1316
+ if (isNonWechatP2p(platform, chatType) && !textLower.startsWith("/")) {
1332
1317
  const tool = resolveDefaultAgentTool();
1333
1318
  const toolLabel = toolDisplayName(tool);
1334
1319
  logTrace(tid, "BRANCH", { cmd: "auto_new_from_p2p", tool });
@@ -1369,7 +1354,7 @@ export async function handleCommand(
1369
1354
  }
1370
1355
 
1371
1356
  const cwd = sessionCwd;
1372
- const initialName = sessionChatName(stripPlanOrAskPrefix(text).slice(0, 10) || "新会话", cwd);
1357
+ const initialName = sessionChatName(text.slice(0, 10) || "新会话", cwd);
1373
1358
  let newChatId: string;
1374
1359
  try {
1375
1360
  newChatId = await platform.createGroup(initialName, [openId]);
@@ -1453,7 +1438,7 @@ export async function handleCommand(
1453
1438
  msgTimestamp,
1454
1439
  tool,
1455
1440
  tid,
1456
- isPlanOrAsk(text),
1441
+ false,
1457
1442
  );
1458
1443
  console.log(`[${ts()}] [AUTO-P2P 5/5] First prompt sent → OK`);
1459
1444
  logTrace(tid, "DONE", { outcome: "auto_new_p2p_prompt_done", newChatId, sessionId, tool });
package/src/session.ts CHANGED
@@ -834,9 +834,8 @@ export async function resumeAndPrompt(
834
834
  msgTimestamp: number,
835
835
  tool: string,
836
836
  traceId?: string,
837
- planMode?: boolean,
838
837
  ): Promise<void> {
839
- return runAgentSession(sessionId, userText, platform, chatId, msgTimestamp, tool, traceId, planMode);
838
+ return runAgentSession(sessionId, userText, platform, chatId, msgTimestamp, tool, traceId);
840
839
  }
841
840
 
842
841
  // ---------------------------------------------------------------------------
@@ -851,7 +850,6 @@ export async function runAgentSession(
851
850
  msgTimestamp: number,
852
851
  tool: string,
853
852
  traceId?: string,
854
- planMode?: boolean,
855
853
  ): Promise<void> {
856
854
  const tid = traceId ?? "";
857
855
 
@@ -1110,7 +1108,6 @@ export async function runAgentSession(
1110
1108
  clearPromptProcessMonitor(sessionId);
1111
1109
  if (exitInfo.pid !== undefined) unregisterProcess(exitInfo.pid);
1112
1110
  },
1113
- planMode,
1114
1111
  })) {
1115
1112
  for (const block of unifiedMsg.blocks) {
1116
1113
  accumulateBlockContent(block, state, toolCallMap);