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
|
@@ -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:
|
|
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
|
-
|
|
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
|
);
|
package/src/orchestrator.ts
CHANGED
|
@@ -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" &&
|
|
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
|
-
|
|
604
|
+
!textLower.startsWith("/")
|
|
620
605
|
) {
|
|
621
606
|
const MAX_PREFIX = 10;
|
|
622
|
-
const 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
|
-
|
|
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
|
-
|
|
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) &&
|
|
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(
|
|
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
|
-
|
|
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
|
|
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);
|