imtoagent 0.3.17 → 0.3.18
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/index.ts +14 -1
- package/modules/agent/opencode-adapter.ts +27 -11
- package/modules/core/runtime.ts +1 -0
- package/modules/core/types.ts +4 -0
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -306,6 +306,8 @@ class Bot {
|
|
|
306
306
|
sessions: Map<string, ChatSession> = new Map();
|
|
307
307
|
commands: Map<string, CommandHandler> = new Map();
|
|
308
308
|
adapter: AgentAdapter;
|
|
309
|
+
/** 正在执行的任务的取消信号(chatId → AbortController) */
|
|
310
|
+
activeControllers: Map<string, AbortController> = new Map();
|
|
309
311
|
|
|
310
312
|
constructor(cfg: BotConfig, globalConfig: any) {
|
|
311
313
|
this.id = cfg.id || cfg.name; // 后向兼容:无 id 时用 name
|
|
@@ -466,7 +468,7 @@ class Bot {
|
|
|
466
468
|
let out = '📋 **CC Quick Commands**\n\n';
|
|
467
469
|
out += '/status — Status\n/info — Config\n/stats — Stats\n';
|
|
468
470
|
out += '/model — Model Switch\n/providers — Providers\n';
|
|
469
|
-
out += '/dir — Directory\n/clear — Clear\n';
|
|
471
|
+
out += '/dir — Directory\n/clear — Clear\n/stop — Stop current task\n';
|
|
470
472
|
if (this.backend === 'claude') out += '/mode — Permission\n';
|
|
471
473
|
else if (this.backend === 'codex') out += '/mode — Mode(auto/plan)\n';
|
|
472
474
|
out += '/memory — Overview\n/soul — Soul\n/reload — Reload';
|
|
@@ -495,6 +497,13 @@ class Bot {
|
|
|
495
497
|
return '✅ No active conversation';
|
|
496
498
|
});
|
|
497
499
|
|
|
500
|
+
cmd('/stop', ({ chatId }) => {
|
|
501
|
+
const ctrl = this.activeControllers.get(chatId);
|
|
502
|
+
if (!ctrl) return '✅ 没有正在执行的任务';
|
|
503
|
+
ctrl.abort();
|
|
504
|
+
return '⏹️ 任务已取消';
|
|
505
|
+
});
|
|
506
|
+
|
|
498
507
|
cmd('/model', ({ args }) => {
|
|
499
508
|
const raw = args.trim();
|
|
500
509
|
if (!raw) {
|
|
@@ -678,6 +687,8 @@ class Bot {
|
|
|
678
687
|
// ===== 消息处理 — SDK 完整接入 =====
|
|
679
688
|
async handleMessage(chatId: string, text: string, userId: string, attachments?: MessageAttachment[]) {
|
|
680
689
|
activeRequests++;
|
|
690
|
+
const controller = new AbortController();
|
|
691
|
+
this.activeControllers.set(chatId, controller);
|
|
681
692
|
try {
|
|
682
693
|
// 限流
|
|
683
694
|
const rlResult = checkRateLimit(chatId);
|
|
@@ -715,6 +726,7 @@ class Bot {
|
|
|
715
726
|
sendProgress: async (t: string) => this.sendProgress(chatId, t),
|
|
716
727
|
sendBlocks: async (blocks) => this.sendFormattedReplyDirect(chatId, blocks),
|
|
717
728
|
imCaps: this.im.getCapabilities(),
|
|
729
|
+
cancelSignal: controller.signal,
|
|
718
730
|
}, this.adapter, this.id);
|
|
719
731
|
|
|
720
732
|
// Agent 自主重启信号检测
|
|
@@ -728,6 +740,7 @@ class Bot {
|
|
|
728
740
|
console.error(`[${this.name}] handleMessage error: ${e.message}`);
|
|
729
741
|
await this.reply(chatId, `❌ ${e.message}`);
|
|
730
742
|
} finally {
|
|
743
|
+
this.activeControllers.delete(chatId);
|
|
731
744
|
activeRequests--;
|
|
732
745
|
}
|
|
733
746
|
}
|
|
@@ -64,7 +64,8 @@ async function ocSendPrompt(
|
|
|
64
64
|
initialText: string,
|
|
65
65
|
system: string,
|
|
66
66
|
defaultModel: { providerID: string; modelID: string },
|
|
67
|
-
onTool?: (name: string, args: Record<string, any>) => void
|
|
67
|
+
onTool?: (name: string, args: Record<string, any>) => void,
|
|
68
|
+
cancelSignal?: AbortSignal
|
|
68
69
|
): Promise<{ response: string; toolCalls: Array<{ name: string; summary: string }> }> {
|
|
69
70
|
const MAX_TURNS = 50;
|
|
70
71
|
const TURN_TIMEOUT = 300_000; // 5 min per turn
|
|
@@ -92,15 +93,29 @@ async function ocSendPrompt(
|
|
|
92
93
|
|
|
93
94
|
const ac = new AbortController();
|
|
94
95
|
const timer = setTimeout(() => ac.abort(), TURN_TIMEOUT);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
// 组合外部取消信号(/stop)+ 本层超时
|
|
97
|
+
const signal = cancelSignal ? AbortSignal.any([ac.signal, cancelSignal]) : ac.signal;
|
|
98
|
+
let data: OcMessage;
|
|
99
|
+
try {
|
|
100
|
+
const res = await fetch(`${serverUrl}/session/${sessionId}/message`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: { 'Content-Type': 'application/json' },
|
|
103
|
+
body: JSON.stringify(body),
|
|
104
|
+
signal,
|
|
105
|
+
}).finally(() => clearTimeout(timer));
|
|
106
|
+
if (!res.ok) throw new Error(`oc send prompt (turn ${turn}): ${res.status} ${await res.text()}`);
|
|
107
|
+
data = await res.json();
|
|
108
|
+
} catch (err: any) {
|
|
109
|
+
if (err?.name === 'AbortError') {
|
|
110
|
+
// 外部取消(/stop)优先于超时
|
|
111
|
+
if (cancelSignal?.aborted) {
|
|
112
|
+
console.log('[OpenCodeAdapter] ⏹️ Task cancelled by user (/stop)');
|
|
113
|
+
return { response: '⏹️ 任务已取消', toolCalls: allToolCalls };
|
|
114
|
+
}
|
|
115
|
+
throw err; // 超时等其它 AbortError 继续抛出
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
104
119
|
let hasToolCall = false;
|
|
105
120
|
let hasText = false;
|
|
106
121
|
|
|
@@ -209,7 +224,8 @@ export class OpenCodeAdapter implements AgentAdapter {
|
|
|
209
224
|
// onTool 回调:适配器层不依赖外部 ctx,直接记日志
|
|
210
225
|
(name, args) => {
|
|
211
226
|
// 工具调用日志由 Runtime 层统一格式化
|
|
212
|
-
}
|
|
227
|
+
},
|
|
228
|
+
input.cancelSignal
|
|
213
229
|
);
|
|
214
230
|
|
|
215
231
|
return {
|
package/modules/core/runtime.ts
CHANGED
package/modules/core/types.ts
CHANGED
|
@@ -113,6 +113,8 @@ export interface AgentInput {
|
|
|
113
113
|
workingDir: string;
|
|
114
114
|
systemPrompt?: string;
|
|
115
115
|
model: string;
|
|
116
|
+
/** 外部取消信号(用于 /stop 等中断命令) */
|
|
117
|
+
cancelSignal?: AbortSignal;
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
/** Agent 输出 */
|
|
@@ -165,6 +167,8 @@ export interface MessageContext {
|
|
|
165
167
|
sendBlocks?: (blocks: UnifiedBlock[]) => Promise<void>;
|
|
166
168
|
/** IM 能力声明,用于 parseToBlocks 正确解析 */
|
|
167
169
|
imCaps?: IMCapabilities;
|
|
170
|
+
/** 外部取消信号(用于 /stop 等中断命令) */
|
|
171
|
+
cancelSignal?: AbortSignal;
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
/** Session 管理器 */
|