@wu529778790/open-im 1.6.2 → 1.6.3-beta.2

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.
Files changed (40) hide show
  1. package/dist/adapters/registry.d.ts +1 -1
  2. package/dist/adapters/registry.js +23 -18
  3. package/dist/commands/handler.d.ts +1 -1
  4. package/dist/commands/handler.js +10 -8
  5. package/dist/config-web-page-i18n.d.ts +4 -0
  6. package/dist/config-web-page-i18n.js +4 -0
  7. package/dist/config-web-page-script.js +16 -5
  8. package/dist/config-web-page-template.js +5 -0
  9. package/dist/config-web.d.ts +7 -0
  10. package/dist/config-web.js +60 -2
  11. package/dist/config-web.test.js +9 -1
  12. package/dist/config.d.ts +14 -0
  13. package/dist/config.js +29 -1
  14. package/dist/dingtalk/event-handler.d.ts +1 -1
  15. package/dist/dingtalk/event-handler.js +7 -5
  16. package/dist/feishu/event-handler.d.ts +1 -1
  17. package/dist/feishu/event-handler.js +8 -6
  18. package/dist/hook/permission-server.d.ts +1 -0
  19. package/dist/hook/permission-server.js +13 -7
  20. package/dist/hook/permission-server.test.d.ts +1 -0
  21. package/dist/hook/permission-server.test.js +12 -0
  22. package/dist/index.js +7 -10
  23. package/dist/manager.js +2 -1
  24. package/dist/qq/event-handler.d.ts +1 -1
  25. package/dist/qq/event-handler.js +6 -4
  26. package/dist/qq/event-handler.test.js +7 -0
  27. package/dist/service-control.d.ts +1 -0
  28. package/dist/service-control.js +26 -7
  29. package/dist/service-control.test.d.ts +1 -0
  30. package/dist/service-control.test.js +36 -0
  31. package/dist/shared/ai-task.js +128 -104
  32. package/dist/shared/ai-task.test.d.ts +1 -0
  33. package/dist/shared/ai-task.test.js +69 -0
  34. package/dist/telegram/event-handler.d.ts +1 -1
  35. package/dist/telegram/event-handler.js +8 -6
  36. package/dist/wechat/event-handler.d.ts +1 -1
  37. package/dist/wechat/event-handler.js +8 -6
  38. package/dist/wework/event-handler.d.ts +1 -1
  39. package/dist/wework/event-handler.js +8 -6
  40. package/package.json +1 -1
@@ -0,0 +1,69 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ vi.mock("../permission-mode/session-mode.js", () => ({
3
+ getPermissionMode: vi.fn(() => "ask"),
4
+ }));
5
+ import { runAITask } from "./ai-task.js";
6
+ describe("runAITask", () => {
7
+ beforeEach(() => {
8
+ vi.useFakeTimers();
9
+ });
10
+ it("keeps the codex session on usage limit errors", async () => {
11
+ const clearSessionForConv = vi.fn();
12
+ const clearActiveToolSession = vi.fn();
13
+ const setSessionIdForConv = vi.fn();
14
+ const sessionManager = {
15
+ addTurnsForThread: vi.fn(() => 0),
16
+ addTurns: vi.fn(() => 0),
17
+ setSessionIdForThread: vi.fn(),
18
+ setSessionIdForConv,
19
+ clearSessionForConv,
20
+ clearActiveToolSession,
21
+ getModel: vi.fn(() => undefined),
22
+ };
23
+ const streamUpdate = vi.fn();
24
+ const sendComplete = vi.fn(async () => { });
25
+ const sendError = vi.fn(async () => { });
26
+ const toolAdapter = {
27
+ toolId: "codex",
28
+ run(_prompt, _sessionId, _workDir, callbacks) {
29
+ callbacks.onError("You've hit your usage limit. To get more access now, send a request to your admin or try again at 12:56 PM.");
30
+ return { abort: vi.fn() };
31
+ },
32
+ };
33
+ const taskPromise = runAITask({
34
+ config: {
35
+ aiCommand: "codex",
36
+ defaultPermissionMode: "ask",
37
+ codexTimeoutMs: 600000,
38
+ claudeTimeoutMs: 600000,
39
+ claudeSkipPermissions: false,
40
+ claudeModel: "",
41
+ useSdkMode: true,
42
+ hookPort: 35801,
43
+ codexProxy: "",
44
+ },
45
+ sessionManager: sessionManager,
46
+ }, {
47
+ userId: "u1",
48
+ chatId: "c1",
49
+ workDir: "D:\\coding\\open-im",
50
+ sessionId: "sess-1",
51
+ convId: "conv-1",
52
+ platform: "wework",
53
+ taskKey: "task-1",
54
+ }, "hello", toolAdapter, {
55
+ streamUpdate,
56
+ sendComplete,
57
+ sendError,
58
+ throttleMs: 0,
59
+ onTaskReady: vi.fn(),
60
+ });
61
+ await taskPromise;
62
+ expect(clearSessionForConv).not.toHaveBeenCalled();
63
+ expect(clearActiveToolSession).not.toHaveBeenCalled();
64
+ expect(sendComplete).not.toHaveBeenCalled();
65
+ expect(sendError).toHaveBeenCalledOnce();
66
+ expect(sendError).toHaveBeenCalledWith(expect.stringContaining("usage limit"));
67
+ expect(streamUpdate).not.toHaveBeenCalled();
68
+ });
69
+ });
@@ -1,5 +1,5 @@
1
1
  import type { Telegraf } from "telegraf";
2
- import type { Config } from "../config.js";
2
+ import { type Config } from "../config.js";
3
3
  import type { SessionManager } from "../session/session-manager.js";
4
4
  export interface TelegramEventHandlerHandle {
5
5
  stop: () => void;
@@ -1,4 +1,5 @@
1
1
  import { message } from "telegraf/filters";
2
+ import { resolvePlatformAiCommand } from "../config.js";
2
3
  import { AccessControl } from "../access/access-control.js";
3
4
  import { RequestQueue } from "../queue/request-queue.js";
4
5
  import { sendThinkingMessage, updateMessage, sendFinalMessages, sendTextReply, startTypingLoop, sendImageReply, sendModeKeyboard, sendDirectorySelection, } from "./message-sender.js";
@@ -93,16 +94,17 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
93
94
  async function handleAIRequest(userId, chatId, prompt, workDir, convId, _threadCtx, replyToMessageId) {
94
95
  const currentTurns = sessionManager.addTurns(userId, 1);
95
96
  log.info(`User request: total turns = ${currentTurns} for user ${userId}`);
96
- const toolAdapter = getAdapter(config.aiCommand);
97
+ const aiCommand = resolvePlatformAiCommand(config, "telegram");
98
+ const toolAdapter = getAdapter(aiCommand);
97
99
  if (!toolAdapter) {
98
- await sendTextReply(chatId, `未配置 AI 工具: ${config.aiCommand}`);
100
+ await sendTextReply(chatId, `未配置 AI 工具: ${aiCommand}`);
99
101
  return;
100
102
  }
101
103
  const sessionId = convId
102
- ? sessionManager.getSessionIdForConv(userId, convId, config.aiCommand)
104
+ ? sessionManager.getSessionIdForConv(userId, convId, aiCommand)
103
105
  : undefined;
104
- log.info(`Running ${config.aiCommand} for user ${userId}, sessionId=${sessionId ?? "new"}`);
105
- const toolId = config.aiCommand;
106
+ log.info(`Running ${aiCommand} for user ${userId}, sessionId=${sessionId ?? "new"}`);
107
+ const toolId = aiCommand;
106
108
  let msgId;
107
109
  try {
108
110
  msgId = await sendThinkingMessage(chatId, replyToMessageId, toolId);
@@ -271,7 +273,7 @@ export function setupTelegramHandlers(bot, config, sessionManager) {
271
273
  taskInfo.settle();
272
274
  taskInfo.handle.abort();
273
275
  const chatId = String(ctx.chat?.id ?? "");
274
- await updateMessage(chatId, messageId, taskInfo.latestContent || "已停止", "error", "⏹️ 已停止", config.aiCommand);
276
+ await updateMessage(chatId, messageId, taskInfo.latestContent || "已停止", "error", "⏹️ 已停止", taskInfo.toolId);
275
277
  await ctx.answerCbQuery("已停止执行");
276
278
  }
277
279
  else {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WeChat Event Handler - Handle WeChat message events from AGP WebSocket
3
3
  */
4
- import type { Config } from '../config.js';
4
+ import { type Config } from '../config.js';
5
5
  import type { SessionManager } from '../session/session-manager.js';
6
6
  export interface WeChatEventHandlerHandle {
7
7
  stop: () => void;
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * WeChat Event Handler - Handle WeChat message events from AGP WebSocket
3
3
  */
4
+ import { resolvePlatformAiCommand } from '../config.js';
4
5
  import { AccessControl } from '../access/access-control.js';
5
6
  import { RequestQueue } from '../queue/request-queue.js';
6
7
  import { sendThinkingMessage, updateMessage, sendFinalMessages, sendTextReply, sendImageReply, startTypingLoop, sendPermissionCard, sendModeCard, } from './message-sender.js';
@@ -115,17 +116,18 @@ export function setupWeChatHandlers(config, sessionManager) {
115
116
  }
116
117
  async function handleAIRequest(userId, chatId, prompt, workDir, convId, _threadCtx, replyToMessageId) {
117
118
  log.info(`[AI_REQUEST] userId=${userId}, chatId=${chatId}, promptLength=${prompt.length}`);
118
- const toolAdapter = getAdapter(config.aiCommand);
119
+ const aiCommand = resolvePlatformAiCommand(config, 'wechat');
120
+ const toolAdapter = getAdapter(aiCommand);
119
121
  if (!toolAdapter) {
120
- log.error(`[handleAIRequest] No adapter found for: ${config.aiCommand}`);
121
- await sendTextReply(chatId, `AI tool is not configured: ${config.aiCommand}`);
122
+ log.error(`[handleAIRequest] No adapter found for: ${aiCommand}`);
123
+ await sendTextReply(chatId, `AI tool is not configured: ${aiCommand}`);
122
124
  return;
123
125
  }
124
126
  const sessionId = convId
125
- ? sessionManager.getSessionIdForConv(userId, convId, config.aiCommand)
127
+ ? sessionManager.getSessionIdForConv(userId, convId, aiCommand)
126
128
  : undefined;
127
- log.info(`[handleAIRequest] Running ${config.aiCommand} for user ${userId}, sessionId=${sessionId ?? 'new'}`);
128
- const toolId = config.aiCommand;
129
+ log.info(`[handleAIRequest] Running ${aiCommand} for user ${userId}, sessionId=${sessionId ?? 'new'}`);
130
+ const toolId = aiCommand;
129
131
  let msgId;
130
132
  try {
131
133
  msgId = await sendThinkingMessage(chatId, replyToMessageId, toolId);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WeWork Event Handler - Handle WeWork message events
3
3
  */
4
- import type { Config } from '../config.js';
4
+ import { type Config } from '../config.js';
5
5
  import type { SessionManager } from '../session/session-manager.js';
6
6
  import type { WeWorkCallbackMessage } from './types.js';
7
7
  type MediaKind = 'image' | 'file' | 'voice' | 'video';
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * WeWork Event Handler - Handle WeWork message events
3
3
  */
4
+ import { resolvePlatformAiCommand } from '../config.js';
4
5
  import { AccessControl } from '../access/access-control.js';
5
6
  import { RequestQueue } from '../queue/request-queue.js';
6
7
  import { sendThinkingMessage, updateMessage, sendFinalMessages, sendTextReply, sendImageReply, startTypingLoop, sendPermissionCard, sendModeCard, setCurrentReqId, } from './message-sender.js';
@@ -174,17 +175,18 @@ export function setupWeWorkHandlers(config, sessionManager) {
174
175
  if (reqId)
175
176
  setCurrentReqId(reqId);
176
177
  try {
177
- const toolAdapter = getAdapter(config.aiCommand);
178
+ const aiCommand = resolvePlatformAiCommand(config, 'wework');
179
+ const toolAdapter = getAdapter(aiCommand);
178
180
  if (!toolAdapter) {
179
- log.error(`[handleAIRequest] No adapter found for: ${config.aiCommand}`);
180
- await sendTextReply(chatId, `AI tool is not configured: ${config.aiCommand}`, reqId);
181
+ log.error(`[handleAIRequest] No adapter found for: ${aiCommand}`);
182
+ await sendTextReply(chatId, `AI tool is not configured: ${aiCommand}`, reqId);
181
183
  return;
182
184
  }
183
185
  const sessionId = convId
184
- ? sessionManager.getSessionIdForConv(userId, convId, config.aiCommand)
186
+ ? sessionManager.getSessionIdForConv(userId, convId, aiCommand)
185
187
  : undefined;
186
- log.info(`[handleAIRequest] Running ${config.aiCommand} for user ${userId}, sessionId=${sessionId ?? 'new'}`);
187
- const toolId = config.aiCommand;
188
+ log.info(`[handleAIRequest] Running ${aiCommand} for user ${userId}, sessionId=${sessionId ?? 'new'}`);
189
+ const toolId = aiCommand;
188
190
  const msgId = await sendThinkingMessage(chatId, replyToMessageId, toolId, reqId);
189
191
  const stopTyping = startTypingLoop(chatId);
190
192
  const taskKey = `${userId}:${msgId}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.6.2",
3
+ "version": "1.6.3-beta.2",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, Cursor)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",