sema-core 2.0.0 → 2.0.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 (184) hide show
  1. package/dist/core/Conversation.d.ts.map +1 -1
  2. package/dist/core/Conversation.js +22 -22
  3. package/dist/core/Conversation.js.map +1 -1
  4. package/dist/core/RunTools.d.ts.map +1 -1
  5. package/dist/core/RunTools.js +6 -6
  6. package/dist/core/RunTools.js.map +1 -1
  7. package/dist/core/SemaCore.d.ts +20 -24
  8. package/dist/core/SemaCore.d.ts.map +1 -1
  9. package/dist/core/SemaCore.js +50 -40
  10. package/dist/core/SemaCore.js.map +1 -1
  11. package/dist/core/SemaEngine.d.ts +25 -16
  12. package/dist/core/SemaEngine.d.ts.map +1 -1
  13. package/dist/core/SemaEngine.js +118 -206
  14. package/dist/core/SemaEngine.js.map +1 -1
  15. package/dist/core/SemaSession.d.ts +43 -0
  16. package/dist/core/SemaSession.d.ts.map +1 -0
  17. package/dist/core/SemaSession.js +72 -0
  18. package/dist/core/SemaSession.js.map +1 -0
  19. package/dist/core/SessionPool.d.ts +32 -0
  20. package/dist/core/SessionPool.d.ts.map +1 -0
  21. package/dist/core/SessionPool.js +89 -0
  22. package/dist/core/SessionPool.js.map +1 -0
  23. package/dist/events/EventSystem.d.ts +40 -12
  24. package/dist/events/EventSystem.d.ts.map +1 -1
  25. package/dist/events/EventSystem.js +83 -25
  26. package/dist/events/EventSystem.js.map +1 -1
  27. package/dist/events/types.d.ts +16 -9
  28. package/dist/events/types.d.ts.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/manager/CronManager.d.ts +16 -5
  34. package/dist/manager/CronManager.d.ts.map +1 -1
  35. package/dist/manager/CronManager.js +46 -19
  36. package/dist/manager/CronManager.js.map +1 -1
  37. package/dist/manager/PermissionManager.d.ts +2 -2
  38. package/dist/manager/PermissionManager.d.ts.map +1 -1
  39. package/dist/manager/PermissionManager.js +211 -20
  40. package/dist/manager/PermissionManager.js.map +1 -1
  41. package/dist/manager/StateManager.d.ts +74 -134
  42. package/dist/manager/StateManager.d.ts.map +1 -1
  43. package/dist/manager/StateManager.js +164 -209
  44. package/dist/manager/StateManager.js.map +1 -1
  45. package/dist/manager/TaskManager.d.ts +28 -10
  46. package/dist/manager/TaskManager.d.ts.map +1 -1
  47. package/dist/manager/TaskManager.js +100 -39
  48. package/dist/manager/TaskManager.js.map +1 -1
  49. package/dist/prompt/design/design.d.ts.map +1 -1
  50. package/dist/prompt/design/design.js +15 -9
  51. package/dist/prompt/design/design.js.map +1 -1
  52. package/dist/prompt/permission.d.ts +3 -0
  53. package/dist/prompt/permission.d.ts.map +1 -0
  54. package/dist/prompt/permission.js +58 -0
  55. package/dist/prompt/permission.js.map +1 -0
  56. package/dist/prompt/system.d.ts +1 -1
  57. package/dist/prompt/system.d.ts.map +1 -1
  58. package/dist/prompt/system.js +5 -2
  59. package/dist/prompt/system.js.map +1 -1
  60. package/dist/services/agents/genSystemPrompt.d.ts +1 -1
  61. package/dist/services/agents/genSystemPrompt.js +1 -1
  62. package/dist/services/api/adapt/anthropic.d.ts +1 -1
  63. package/dist/services/api/adapt/anthropic.d.ts.map +1 -1
  64. package/dist/services/api/adapt/anthropic.js +7 -7
  65. package/dist/services/api/adapt/anthropic.js.map +1 -1
  66. package/dist/services/api/adapt/openai.d.ts +1 -1
  67. package/dist/services/api/adapt/openai.d.ts.map +1 -1
  68. package/dist/services/api/adapt/openai.js +7 -7
  69. package/dist/services/api/adapt/openai.js.map +1 -1
  70. package/dist/services/api/adapt/util.d.ts +2 -2
  71. package/dist/services/api/adapt/util.d.ts.map +1 -1
  72. package/dist/services/api/adapt/util.js +4 -4
  73. package/dist/services/api/adapt/util.js.map +1 -1
  74. package/dist/services/api/cache.d.ts +1 -1
  75. package/dist/services/api/cache.d.ts.map +1 -1
  76. package/dist/services/api/cache.js +7 -7
  77. package/dist/services/api/cache.js.map +1 -1
  78. package/dist/services/api/queryLLM.d.ts +16 -2
  79. package/dist/services/api/queryLLM.d.ts.map +1 -1
  80. package/dist/services/api/queryLLM.js +19 -18
  81. package/dist/services/api/queryLLM.js.map +1 -1
  82. package/dist/services/commands/runCommand.d.ts +1 -1
  83. package/dist/services/commands/runCommand.d.ts.map +1 -1
  84. package/dist/services/commands/runCommand.js +26 -26
  85. package/dist/services/commands/runCommand.js.map +1 -1
  86. package/dist/tools/CreateCron.d.ts +1 -1
  87. package/dist/tools/CreateCron.d.ts.map +1 -1
  88. package/dist/tools/CreateCron.js +2 -2
  89. package/dist/tools/CreateCron.js.map +1 -1
  90. package/dist/tools/CreateTodo.js +1 -1
  91. package/dist/tools/CreateTodo.js.map +1 -1
  92. package/dist/tools/EditNotebook.js +2 -2
  93. package/dist/tools/EditNotebook.js.map +1 -1
  94. package/dist/tools/FetchUrl.js +1 -1
  95. package/dist/tools/FetchUrl.js.map +1 -1
  96. package/dist/tools/GetTodo.js +1 -1
  97. package/dist/tools/GetTodo.js.map +1 -1
  98. package/dist/tools/ListTodos.js +1 -1
  99. package/dist/tools/ListTodos.js.map +1 -1
  100. package/dist/tools/PatchFile.js +2 -2
  101. package/dist/tools/PatchFile.js.map +1 -1
  102. package/dist/tools/PeekBgJob.d.ts.map +1 -1
  103. package/dist/tools/PeekBgJob.js +4 -3
  104. package/dist/tools/PeekBgJob.js.map +1 -1
  105. package/dist/tools/PickOption.js +3 -3
  106. package/dist/tools/PickOption.js.map +1 -1
  107. package/dist/tools/PlanToAgent.d.ts.map +1 -1
  108. package/dist/tools/PlanToAgent.js +10 -11
  109. package/dist/tools/PlanToAgent.js.map +1 -1
  110. package/dist/tools/RunShell.js +1 -1
  111. package/dist/tools/RunShell.js.map +1 -1
  112. package/dist/tools/SubAgent.d.ts.map +1 -1
  113. package/dist/tools/SubAgent.js +20 -17
  114. package/dist/tools/SubAgent.js.map +1 -1
  115. package/dist/tools/UpdateTodo.js +1 -1
  116. package/dist/tools/UpdateTodo.js.map +1 -1
  117. package/dist/tools/ViewFile.js +1 -1
  118. package/dist/tools/ViewFile.js.map +1 -1
  119. package/dist/tools/WriteFile.js +2 -2
  120. package/dist/tools/WriteFile.js.map +1 -1
  121. package/dist/tools/base/tools.d.ts +2 -2
  122. package/dist/tools/base/tools.d.ts.map +1 -1
  123. package/dist/tools/base/tools.js +10 -4
  124. package/dist/tools/base/tools.js.map +1 -1
  125. package/dist/types/agent.d.ts +2 -0
  126. package/dist/types/agent.d.ts.map +1 -1
  127. package/dist/types/cron.d.ts +1 -0
  128. package/dist/types/cron.d.ts.map +1 -1
  129. package/dist/types/index.d.ts +3 -0
  130. package/dist/types/index.d.ts.map +1 -1
  131. package/dist/types/index.js.map +1 -1
  132. package/dist/types/session.d.ts +20 -0
  133. package/dist/types/session.d.ts.map +1 -0
  134. package/dist/types/session.js +3 -0
  135. package/dist/types/session.js.map +1 -0
  136. package/dist/types/task.d.ts +2 -0
  137. package/dist/types/task.d.ts.map +1 -1
  138. package/dist/util/commands.d.ts +4 -1
  139. package/dist/util/commands.d.ts.map +1 -1
  140. package/dist/util/commands.js +126 -9
  141. package/dist/util/commands.js.map +1 -1
  142. package/dist/util/compact.d.ts +2 -2
  143. package/dist/util/compact.d.ts.map +1 -1
  144. package/dist/util/compact.js +6 -7
  145. package/dist/util/compact.js.map +1 -1
  146. package/dist/util/file.d.ts +2 -0
  147. package/dist/util/file.d.ts.map +1 -1
  148. package/dist/util/file.js +11 -0
  149. package/dist/util/file.js.map +1 -1
  150. package/dist/util/fileReference.d.ts.map +1 -1
  151. package/dist/util/fileReference.js +4 -0
  152. package/dist/util/fileReference.js.map +1 -1
  153. package/dist/util/logLLM.d.ts +3 -3
  154. package/dist/util/logLLM.d.ts.map +1 -1
  155. package/dist/util/logLLM.js +10 -15
  156. package/dist/util/logLLM.js.map +1 -1
  157. package/dist/util/message.d.ts +1 -1
  158. package/dist/util/message.d.ts.map +1 -1
  159. package/dist/util/message.js +6 -6
  160. package/dist/util/message.js.map +1 -1
  161. package/dist/util/notifyRegistry.d.ts +18 -0
  162. package/dist/util/notifyRegistry.d.ts.map +1 -0
  163. package/dist/util/notifyRegistry.js +28 -0
  164. package/dist/util/notifyRegistry.js.map +1 -0
  165. package/dist/util/process.d.ts.map +1 -1
  166. package/dist/util/process.js +3 -4
  167. package/dist/util/process.js.map +1 -1
  168. package/dist/util/quickchat.d.ts +1 -1
  169. package/dist/util/quickchat.d.ts.map +1 -1
  170. package/dist/util/quickchat.js +12 -10
  171. package/dist/util/quickchat.js.map +1 -1
  172. package/dist/util/session.d.ts +4 -0
  173. package/dist/util/session.d.ts.map +1 -1
  174. package/dist/util/session.js +8 -1
  175. package/dist/util/session.js.map +1 -1
  176. package/dist/util/shell.d.ts +2 -0
  177. package/dist/util/shell.d.ts.map +1 -1
  178. package/dist/util/shell.js +20 -1
  179. package/dist/util/shell.js.map +1 -1
  180. package/dist/util/topic.d.ts +2 -2
  181. package/dist/util/topic.d.ts.map +1 -1
  182. package/dist/util/topic.js +4 -3
  183. package/dist/util/topic.js.map +1 -1
  184. package/package.json +1 -1
@@ -1,21 +1,25 @@
1
- import { EventBus } from '../events/EventSystem';
2
- import type { AgentMode } from '../types';
1
+ import { SessionEventBus } from '../events/EventSystem';
2
+ import type { AgentMode, PermissionLevel } from '../types';
3
+ import type { CreateSessionOptions } from '../types/session';
3
4
  /**
4
- * Sema 引擎 - 处理核心业务逻辑
5
+ * Sema 引擎 - 单个会话的核心业务逻辑
6
+ * 每个会话一个实例,绑定固定的 sessionId
5
7
  */
6
8
  export declare class SemaEngine {
7
- private pendingSession;
9
+ readonly sessionId: string;
10
+ private readonly bus;
11
+ /** 当前正在执行的 processQuery Promise(用于 dispose 时等待) */
8
12
  private currentProcessingPromise;
9
- private eventBus;
13
+ private readonly runtime;
10
14
  emit: <T>(event: string, data: T) => boolean;
11
- on: <T>(event: string, listener: (data: T) => void) => EventBus;
12
- once: <T>(event: string, listener: (data: T) => void) => EventBus;
13
- off: <T>(event: string, listener: (data: T) => void) => EventBus;
14
- constructor();
15
+ on: <T>(event: string, listener: (data: T) => void) => SessionEventBus;
16
+ once: <T>(event: string, listener: (data: T) => void) => SessionEventBus;
17
+ off: <T>(event: string, listener: (data: T) => void) => SessionEventBus;
18
+ constructor(sessionId: string, bus: SessionEventBus);
15
19
  /**
16
- * 创建会话
20
+ * 初始化会话:加载历史、发送 session:ready
17
21
  */
18
- createSession(sessionId?: string): Promise<void>;
22
+ createSession(opts?: CreateSessionOptions): Promise<void>;
19
23
  /**
20
24
  * 处理用户输入
21
25
  * 如果当前正在处理中,将输入加入队列等待
@@ -31,22 +35,27 @@ export declare class SemaEngine {
31
35
  private processQuery;
32
36
  /**
33
37
  * 中止当前正在进行的请求(仅处理 AbortController)
34
- * 不更新状态,用于内部调用
35
38
  */
36
39
  private abortCurrentRequest;
37
40
  /**
38
41
  * 中断当前会话
39
- * 仅中断当前正在执行的请求,队列中的待处理输入不受影响
40
- * 由 processQuery 的 finally 决定是否继续消费队列或设为 idle
41
42
  */
42
43
  interruptSession(): void;
43
44
  /**
44
- * 更新 Agent 模式
45
+ * 更新 Agent 模式(会话级)
45
46
  */
46
47
  updateAgentMode(mode: AgentMode): void;
48
+ /**
49
+ * 更新权限自由度档位(会话级)
50
+ */
51
+ updatePermissionLevel(level: PermissionLevel): void;
47
52
  private initialize;
48
53
  /**
49
- * 清理资源和停止所有活动
54
+ * 等待当前处理结束(最多 timeoutMs 毫秒)
55
+ */
56
+ waitForIdle(timeoutMs?: number): Promise<void>;
57
+ /**
58
+ * 清理本会话资源(会话级,不触碰全局单例)
50
59
  */
51
60
  dispose(): void;
52
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SemaEngine.d.ts","sourceRoot":"","sources":["../../src/core/SemaEngine.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAWjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C;;GAEG;AACH,qBAAa,UAAU;IAErB,OAAO,CAAC,cAAc,CAAsB;IAE5C,OAAO,CAAC,wBAAwB,CAA6B;IAG7D,OAAO,CAAC,QAAQ,CAA0B;IAC1C,IAAI,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,MAAM,CAAC,aAA4D;IAC7F,EAAE,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,cAAuC;IAC1F,IAAI,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,cAAyC;IAC9F,GAAG,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,cAAwC;;IAc5F;;OAEG;IACG,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8FtD;;;OAGG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAgD/E;;OAEG;IACH,OAAO,CAAC,UAAU;IAyClB;;OAEG;YACW,YAAY;IAuK1B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;;;OAIG;IACH,gBAAgB,IAAI,IAAI;IAMxB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;YAuBxB,UAAU;IAwCxB;;OAEG;IACH,OAAO,IAAI,IAAI;CAiBhB"}
1
+ {"version":3,"file":"SemaEngine.d.ts","sourceRoot":"","sources":["../../src/core/SemaEngine.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAYxD,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D;;;GAGG;AACH,qBAAa,UAAU;aAaH,SAAS,EAAE,MAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAbtB,mDAAmD;IACnD,OAAO,CAAC,wBAAwB,CAA6B;IAE7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IAGzC,IAAI,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,MAAM,CAAC,aAAgC;IACjE,EAAE,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,qBAAkC;IACrF,IAAI,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,qBAAoC;IACzF,GAAG,GAAI,CAAC,EAAE,OAAO,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,qBAAmC;gBAGrE,SAAS,EAAE,MAAM,EAChB,GAAG,EAAE,eAAe;IAevC;;OAEG;IACG,aAAa,CAAC,IAAI,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDnE;;;OAGG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IA+C/E;;OAEG;IACH,OAAO,CAAC,UAAU;IAqClB;;OAEG;YACW,YAAY;IAwJ1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAetC;;OAEG;IACH,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;YAKrC,UAAU;IA8BxB;;OAEG;IACG,WAAW,CAAC,SAAS,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnD;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB"}
@@ -1,42 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.SemaEngine = void 0;
37
- const crypto = __importStar(require("crypto"));
38
4
  const log_1 = require("../util/log");
39
- const session_1 = require("../util/session");
40
5
  const tokens_1 = require("../util/tokens");
41
6
  const history_1 = require("../util/history");
42
7
  const topic_1 = require("../util/topic");
@@ -47,138 +12,105 @@ const inputQueue_1 = require("../util/inputQueue");
47
12
  const genSystemPrompt_1 = require("../services/agents/genSystemPrompt");
48
13
  const ConfManager_1 = require("../manager/ConfManager");
49
14
  const ModelManager_1 = require("../manager/ModelManager");
50
- const EventSystem_1 = require("../events/EventSystem");
51
15
  const errors_1 = require("../types/errors");
52
16
  const Conversation_1 = require("./Conversation");
53
17
  const StateManager_1 = require("../manager/StateManager");
18
+ const session_1 = require("../util/session");
54
19
  const runCommand_1 = require("../services/commands/runCommand");
55
20
  const TaskManager_1 = require("../manager/TaskManager");
56
21
  const CronManager_1 = require("../manager/CronManager");
57
22
  const quickchat_1 = require("../util/quickchat");
58
23
  const tool_1 = require("../prompt/tool");
59
24
  /**
60
- * Sema 引擎 - 处理核心业务逻辑
25
+ * Sema 引擎 - 单个会话的核心业务逻辑
26
+ * 每个会话一个实例,绑定固定的 sessionId
61
27
  */
62
28
  class SemaEngine {
63
- constructor() {
64
- // 待处理的会话ID(只保留最新的一个)
65
- this.pendingSession = null;
66
- // 当前正在执行的 processQuery Promise(用于等待旧会话结束)
29
+ constructor(sessionId, bus) {
30
+ this.sessionId = sessionId;
31
+ this.bus = bus;
32
+ /** 当前正在执行的 processQuery Promise(用于 dispose 时等待) */
67
33
  this.currentProcessingPromise = null;
68
- // 公共事件接口
69
- this.eventBus = EventSystem_1.EventBus.getInstance();
70
- this.emit = (event, data) => this.eventBus.emit(event, data);
71
- this.on = (event, listener) => this.eventBus.on(event, listener);
72
- this.once = (event, listener) => this.eventBus.once(event, listener);
73
- this.off = (event, listener) => this.eventBus.off(event, listener);
74
- // 注入后台任务通知回调:任务完成后将通知注入用户输入队列
75
- (0, TaskManager_1.getTaskManager)().setNotifyCallback((msg) => {
34
+ // 公共事件接口(会话级,自动按 sessionId 路由)
35
+ this.emit = (event, data) => this.bus.emit(event, data);
36
+ this.on = (event, listener) => this.bus.on(event, listener);
37
+ this.once = (event, listener) => this.bus.once(event, listener);
38
+ this.off = (event, listener) => this.bus.off(event, listener);
39
+ this.runtime = (0, StateManager_1.getStateManager)().session(sessionId);
40
+ // 注入后台任务通知回调:完成后将通知注入本会话输入队列
41
+ (0, TaskManager_1.getTaskManager)().setNotifyCallback(sessionId, (msg) => {
76
42
  this.processUserInput(msg, undefined, true);
77
43
  });
78
44
  // 注入 Cron 定时任务通知回调
79
- (0, CronManager_1.getCronManager)().setNotifyCallback((msg) => {
45
+ (0, CronManager_1.getCronManager)().setNotifyCallback(sessionId, (msg) => {
80
46
  this.processUserInput(msg, undefined, true);
81
47
  });
82
48
  }
83
49
  /**
84
- * 创建会话
50
+ * 初始化会话:加载历史、发送 session:ready
85
51
  */
86
- async createSession(sessionId) {
87
- const finalSessionId = sessionId || (0, session_1.generateSessionId)();
88
- const stateManager = (0, StateManager_1.getStateManager)();
89
- const mainAgentState = stateManager.forAgent(StateManager_1.MAIN_AGENT_ID);
90
- // 如果当前正在处理,中断并等待旧会话结束,然后 fall through 到下方统一创建新会话
91
- if (mainAgentState.getCurrentState() === 'processing') {
92
- this.pendingSession = finalSessionId; // 直接覆盖,只保留最新的会话
93
- this.abortCurrentRequest();
94
- (0, log_1.logInfo)(`会话正在处理中,中断并等待: ${finalSessionId}`);
95
- // 等待旧会话处理完成(最多等待10秒)
96
- if (this.currentProcessingPromise) {
97
- const waitTimeoutSecond = 10;
98
- (0, log_1.logInfo)(`等待旧会话结束...`);
99
- try {
100
- await Promise.race([
101
- this.currentProcessingPromise,
102
- new Promise((_, reject) => setTimeout(() => reject(new Error('等待超时')), 1000 * waitTimeoutSecond))
103
- ]);
104
- (0, log_1.logInfo)(`旧会话已结束`);
105
- }
106
- catch (error) {
107
- (0, log_1.logWarn)(`等待旧会话结束时出错: ${error instanceof Error ? error.message : String(error)}`);
108
- }
109
- }
110
- // 被更新的 createSession 调用覆盖(快速连续新建场景),放弃当前创建
111
- if (this.pendingSession !== finalSessionId) {
112
- (0, log_1.logInfo)(`会话创建被覆盖,放弃: ${finalSessionId}`);
113
- return;
114
- }
115
- }
116
- // 创建新会话,清空所有待处理状态
117
- this.abortCurrentRequest();
118
- stateManager.clearPendingUserInputs(); // 清空输入队列,因为这些输入属于旧会话
119
- this.pendingSession = null;
120
- // 关闭所有后台进程
121
- (0, TaskManager_1.getTaskManager)().dispose();
122
- // 清空所有状态
123
- stateManager.clearAllState();
124
- // 初始化新会话
125
- await this.initialize(finalSessionId);
126
- // 清空非持久化的定时任务,持久化任务保留
127
- (0, CronManager_1.getCronManager)().clearNonDurableTasks();
52
+ async createSession(opts = {}) {
53
+ // 初始化系统配置与模型检查
54
+ await this.initialize();
55
+ // 会话级配置:Agent 模式
128
56
  const coreConfig = (0, ConfManager_1.getConfManager)().getCoreConfig();
57
+ this.runtime.agentMode = opts.agentMode || coreConfig?.agentMode || 'Agent';
58
+ // 会话级配置:权限自由度档位
59
+ this.runtime.setPermissionLevel(opts.permissionLevel || 'Ask');
60
+ // 构建会话级系统提示快照:整个会话不再变化(env/gitStatus 取会话创建时的快照)
61
+ this.runtime.setSystemPromptContent(await (0, genSystemPrompt_1.formatSystemPrompt)());
62
+ const mainAgentState = this.runtime.forAgent(StateManager_1.MAIN_AGENT_ID);
129
63
  const workingDir = coreConfig?.workingDir;
130
- (0, log_1.logInfo)(`[DEBUG] loadHistory - workingDir: ${workingDir}, coreConfig: ${JSON.stringify(coreConfig)}`);
131
- const historyData = await (0, history_1.loadHistory)(sessionId, workingDir);
132
- (0, log_1.logInfo)(`会话CoreConfig: ${JSON.stringify(coreConfig, null, 2)}`);
64
+ const historyId = opts.sessionId;
65
+ const historyData = await (0, history_1.loadHistory)(historyId, workingDir);
133
66
  // 将加载的消息历史、todos 和 readFileTimestamps 设置到主代理状态
134
67
  // 初始化时跳过自动保存,避免把刚读取的数据重复写回文件
135
68
  mainAgentState.setMessageHistory(historyData.messages, true);
136
69
  mainAgentState.setTodos(historyData.todos);
137
70
  if (historyData.todoTasks && historyData.todoTasks.length > 0) {
138
- // 新格式:直接恢复完整 TodoTask 数据
139
- stateManager.restoreTodoTasks(historyData.todoTasks);
71
+ this.runtime.restoreTodoTasks(historyData.todoTasks);
140
72
  }
141
73
  else if (historyData.todos && historyData.todos.length > 0) {
142
- // 旧格式兼容:将 TodoItem 转换为 TodoTask
143
- stateManager.restoreTodoTasksFromLegacy(historyData.todos);
74
+ this.runtime.restoreTodoTasksFromLegacy(historyData.todos);
144
75
  }
145
76
  if (historyData.readFileTimestamps) {
146
77
  mainAgentState.setReadFileTimestamps(historyData.readFileTimestamps);
147
78
  }
148
- // 使用全局配置获取工作路径
149
79
  const projectConfig = (0, ConfManager_1.getConfManager)().getProjectConfig();
150
80
  const projectInputHistory = projectConfig?.history || [];
151
- // 获取tokens
152
81
  const usage = (0, tokens_1.getTokens)(mainAgentState.getMessageHistory());
153
82
  const sessionData = {
154
83
  pid: process.pid,
155
84
  workingDir: coreConfig?.workingDir,
156
- sessionId: stateManager.getSessionId(),
157
- historyLoaded: !!sessionId,
85
+ sessionId: this.sessionId,
86
+ historyLoaded: !!historyId,
158
87
  projectInputHistory: projectInputHistory,
159
88
  usage: usage,
160
89
  todos: mainAgentState.getTodos(),
161
90
  readFileTimestamps: historyData.readFileTimestamps || {}
162
91
  };
163
- (0, log_1.logInfo)(`新会话创建完成,sessionId: ${stateManager.getSessionId()}`);
164
- this.emit('session:ready', sessionData);
165
- mainAgentState.updateState('idle');
92
+ (0, log_1.logInfo)(`新会话创建完成,sessionId: ${this.sessionId}`);
93
+ // 延迟一拍发送 session:ready:调用方需先拿到 createSession 返回的 SemaSession
94
+ // 并在其上注册监听器,再收到首个事件
95
+ setImmediate(() => {
96
+ this.emit('session:ready', sessionData);
97
+ mainAgentState.updateState('idle');
98
+ });
166
99
  }
167
100
  /**
168
101
  * 处理用户输入
169
102
  * 如果当前正在处理中,将输入加入队列等待
170
103
  */
171
104
  processUserInput(input, originalInput, silent) {
172
- const stateManager = (0, StateManager_1.getStateManager)();
173
- const mainAgentState = stateManager.forAgent(StateManager_1.MAIN_AGENT_ID);
174
- const inputId = crypto.randomUUID().replace(/-/g, '').substring(0, 8);
105
+ const mainAgentState = this.runtime.forAgent(StateManager_1.MAIN_AGENT_ID);
106
+ const inputId = (0, session_1.generateShortId)();
175
107
  const trimmedInput = input.trim();
176
108
  // quickchat 旁路:不影响状态和队列,异步处理后直接返回
177
109
  if (trimmedInput === '/quickchat' || trimmedInput.startsWith('/quickchat ')) {
178
- const question = trimmedInput.startsWith('/quickchat ') ? trimmedInput.slice(5).trim() : '';
110
+ const question = trimmedInput.startsWith('/quickchat ') ? trimmedInput.slice('/quickchat '.length).trim() : '';
179
111
  (0, ConfManager_1.getConfManager)().saveUserInputToHistory(originalInput || trimmedInput);
180
112
  if (question) {
181
- (0, quickchat_1.handlequickchat)(question).catch(err => (0, log_1.logWarn)(`[quickchat] 未捕获异常: ${err instanceof Error ? err.message : String(err)}`));
113
+ (0, quickchat_1.handlequickchat)(question, this.sessionId).catch(err => (0, log_1.logWarn)(`[quickchat] 未捕获异常: ${err instanceof Error ? err.message : String(err)}`));
182
114
  }
183
115
  else {
184
116
  this.emit('quickchat:response', { question: '', content: '' });
@@ -187,8 +119,8 @@ class SemaEngine {
187
119
  }
188
120
  if (mainAgentState.getCurrentState() === 'processing') {
189
121
  const type = trimmedInput.startsWith('/') ? 'command' : 'inject';
190
- stateManager.addPendingUserInput({ inputId, input: trimmedInput, originalInput, silent, type });
191
- (0, log_1.logInfo)(`输入已入队(${type}),队列长度: ${stateManager.getPendingUserInputsLength()}`);
122
+ this.runtime.addPendingUserInput({ inputId, input: trimmedInput, originalInput, silent, type });
123
+ (0, log_1.logInfo)(`输入已入队(${type}),队列长度: ${this.runtime.getPendingUserInputsLength()}`);
192
124
  if (!silent) {
193
125
  this.emit('input:received', {
194
126
  inputId,
@@ -196,7 +128,7 @@ class SemaEngine {
196
128
  originalInput,
197
129
  queued: true,
198
130
  inject: type === 'inject',
199
- queueLength: stateManager.getPendingUserInputsLength(),
131
+ queueLength: this.runtime.getPendingUserInputsLength(),
200
132
  });
201
133
  }
202
134
  return;
@@ -217,21 +149,19 @@ class SemaEngine {
217
149
  * 启动一次查询(构建上下文并调用 processQuery)
218
150
  */
219
151
  startQuery(inputs) {
220
- const stateManager = (0, StateManager_1.getStateManager)();
221
- const mainAgentState = stateManager.forAgent(StateManager_1.MAIN_AGENT_ID);
152
+ const mainAgentState = this.runtime.forAgent(StateManager_1.MAIN_AGENT_ID);
222
153
  mainAgentState.updateState('processing');
223
154
  (0, log_1.logInfo)(`用户输入(${inputs.length}条): ${inputs.map(i => i.input).join(' | ')}`);
224
155
  // 创建新的 AbortController 用于此次处理
225
- stateManager.currentAbortController = new AbortController();
226
- // 获取核心配置
227
- const coreConfig = (0, ConfManager_1.getConfManager)().getCoreConfig();
228
- const agentMode = coreConfig?.agentMode || 'Agent';
229
- // 获取工具集
156
+ this.runtime.currentAbortController = new AbortController();
157
+ const agentMode = this.runtime.agentMode;
158
+ // 获取工具集(按核心级 useTools 黑名单过滤)
230
159
  const tools = (0, tools_1.getAvailableTools)();
231
160
  // 构建主代理上下文
232
161
  const agentContext = {
162
+ sessionId: this.sessionId,
233
163
  agentId: StateManager_1.MAIN_AGENT_ID,
234
- abortController: stateManager.currentAbortController,
164
+ abortController: this.runtime.currentAbortController,
235
165
  tools,
236
166
  model: 'main',
237
167
  };
@@ -239,14 +169,12 @@ class SemaEngine {
239
169
  this.currentProcessingPromise = this.processQuery(inputs, agentContext, agentMode)
240
170
  .catch(error => {
241
171
  (0, log_1.logWarn)(`processQuery 未捕获异常: ${error instanceof Error ? error.message : String(error)}`);
242
- // 确保清理 AbortController(防止竞态条件)
243
- if (stateManager.currentAbortController === agentContext.abortController) {
244
- stateManager.currentAbortController = null;
172
+ if (this.runtime.currentAbortController === agentContext.abortController) {
173
+ this.runtime.currentAbortController = null;
245
174
  }
246
175
  mainAgentState.updateState('idle');
247
176
  })
248
177
  .finally(() => {
249
- // 清空 Promise 引用
250
178
  this.currentProcessingPromise = null;
251
179
  });
252
180
  }
@@ -254,9 +182,7 @@ class SemaEngine {
254
182
  * 处理查询逻辑
255
183
  */
256
184
  async processQuery(inputs, agentContext, agentMode) {
257
- // 获取状态管理器和主代理状态
258
- const stateManager = (0, StateManager_1.getStateManager)();
259
- const mainAgentState = stateManager.forAgent(StateManager_1.MAIN_AGENT_ID);
185
+ const mainAgentState = this.runtime.forAgent(StateManager_1.MAIN_AGENT_ID);
260
186
  // 为每条输入发送独立的 input:processing 事件(静默输入跳过)
261
187
  for (const item of inputs) {
262
188
  if (!item.silent) {
@@ -274,12 +200,11 @@ class SemaEngine {
274
200
  const allBlocks = [];
275
201
  let combinedProcessedText = '';
276
202
  for (const item of inputs) {
277
- // abort 早期检查:避免会话切换后继续执行无用操作
278
203
  if (agentContext.abortController.signal.aborted) {
279
204
  (0, log_1.logInfo)('processQuery: abort detected during handleCommand loop, skipping remaining');
280
205
  return;
281
206
  }
282
- const commandResult = await (0, runCommand_1.handleCommand)(item.input);
207
+ const commandResult = await (0, runCommand_1.handleCommand)(item.input, this.sessionId);
283
208
  if (commandResult === null) {
284
209
  // 系统命令已处理(如 /compact, /clear),跳过
285
210
  continue;
@@ -287,23 +212,20 @@ class SemaEngine {
287
212
  combinedProcessedText += (combinedProcessedText ? '\n' : '') + commandResult.processedText;
288
213
  allBlocks.push(...commandResult.blocks);
289
214
  }
290
- // 如果所有输入都是系统命令(返回 null),直接结束
291
215
  if (allBlocks.length === 0) {
292
216
  return;
293
217
  }
294
- // abort 早期检查
295
218
  if (agentContext.abortController.signal.aborted) {
296
219
  (0, log_1.logInfo)('processQuery: abort detected after handleCommand, skipping remaining');
297
220
  return;
298
221
  }
299
- // 后台异步执行话题检测,不阻塞主流程(使用所有输入拼接)
300
- // 跳过条件:全部输入均为 silent(来自 cron / 后台任务通知等系统注入),不应改变会话话题
222
+ // 后台异步执行话题检测,不阻塞主流程
301
223
  const allSilent = inputs.every(i => i.silent);
302
224
  const allOriginalTexts = inputs.map(i => i.originalInput || i.input).join('\n');
303
225
  if (!allSilent && !(0, ConfManager_1.getConfManager)().getCoreConfig()?.disableTopicDetection) {
304
- (0, topic_1.detectTopicInBackground)(allOriginalTexts, stateManager.currentAbortController, (result) => this.emit('topic:update', result));
226
+ (0, topic_1.detectTopicInBackground)(allOriginalTexts, this.runtime.currentAbortController, (result) => this.emit('topic:update', result), this.sessionId);
305
227
  }
306
- // 处理文件引用以获取补充信息(使用处理后的文本)
228
+ // 处理文件引用以获取补充信息
307
229
  const fileReferencesResult = await (0, fileReference_1.processFileReferences)(combinedProcessedText, agentContext);
308
230
  (0, log_1.logInfo)(`返回文件引用信息: ${JSON.stringify(fileReferencesResult.supplementaryInfo, null, 2)}`);
309
231
  if (fileReferencesResult.supplementaryInfo.length > 0) {
@@ -311,25 +233,24 @@ class SemaEngine {
311
233
  references: fileReferencesResult.supplementaryInfo
312
234
  });
313
235
  }
314
- // abort 早期检查
315
236
  if (agentContext.abortController.signal.aborted) {
316
237
  (0, log_1.logInfo)('processQuery: abort detected after processFileReferences, skipping remaining');
317
238
  return;
318
239
  }
319
- // 1、构建系统提示(根据是否有代理配置决定)
240
+ // 1、系统提示:复用会话级快照(整会话不变);缺失时兜底构建一次
320
241
  const hasSkillTool = agentContext.tools.some(tool => tool.name === tool_1.TOOL_NAME_SKILL);
321
- const systemPromptContent = await (0, genSystemPrompt_1.formatSystemPrompt)();
242
+ let systemPromptContent = this.runtime.getSystemPromptContent();
243
+ if (!systemPromptContent) {
244
+ systemPromptContent = await (0, genSystemPrompt_1.formatSystemPrompt)();
245
+ this.runtime.setSystemPromptContent(systemPromptContent);
246
+ }
322
247
  // 2、构建用户消息内容
323
- // 2.1 获取消息历史
324
248
  const messageHistory = mainAgentState.getMessageHistory();
325
- // 2.2 当前用户输入
326
- // 构建reminder信息 文件引用 每次输入均添加,首次查询添加 todos\rules,Plan 模式添加 Plan 信息
327
- const additionalReminders = (0, message_1.buildAdditionalReminders)(fileReferencesResult.systemReminders, messageHistory, agentMode, hasSkillTool);
249
+ const additionalReminders = (0, message_1.buildAdditionalReminders)(fileReferencesResult.systemReminders, messageHistory, agentMode, this.sessionId, hasSkillTool);
328
250
  const userMessage = (0, message_1.buildUserMsg)([
329
251
  ...additionalReminders,
330
252
  ...allBlocks
331
253
  ]);
332
- // 2.3 完整消息
333
254
  const messages = [...messageHistory, userMessage];
334
255
  // 调用 query 函数
335
256
  for await (const _message of (0, Conversation_1.ReAct)(messages, systemPromptContent, agentContext)) {
@@ -340,29 +261,20 @@ class SemaEngine {
340
261
  if ((0, errors_1.isInterruptedException)(error)) {
341
262
  (0, log_1.logDebug)('用户中断操作');
342
263
  }
343
- // API 错误已在 emitSessionError 中记录,这里不重复记录
344
264
  }
345
265
  finally {
346
- // 延迟清空 AbortController,确保所有中断逻辑执行完毕(避免竞态条件)
347
- const currentAbortController = stateManager.currentAbortController;
266
+ // 延迟清空 AbortController,确保所有中断逻辑执行完毕
267
+ const currentAbortController = this.runtime.currentAbortController;
348
268
  if (currentAbortController === agentContext.abortController) {
349
- // 使用 setTimeout 0 确保当前执行栈完成后再清空
350
269
  setTimeout(() => {
351
- if (stateManager.currentAbortController === currentAbortController) {
352
- stateManager.currentAbortController = null;
270
+ if (this.runtime.currentAbortController === currentAbortController) {
271
+ this.runtime.currentAbortController = null;
353
272
  }
354
273
  }, 0);
355
274
  }
356
- // 会话切换:仅清空队列,不再递归调 createSession
357
- // createSession 正在等待 currentProcessingPromise,由它接手创建新会话
358
- if (this.pendingSession) {
359
- stateManager.clearPendingUserInputs();
360
- return;
361
- }
362
- // 处理同一会话中的待处理输入队列
363
- const remaining = stateManager.consumeAllPendingInputs();
275
+ // 处理待处理输入队列
276
+ const remaining = this.runtime.consumeAllPendingInputs();
364
277
  if (remaining.length > 0) {
365
- // 转换为 takeNextBatch 所需格式
366
278
  const pending = remaining.map(item => ({
367
279
  inputId: item.inputId,
368
280
  input: item.input,
@@ -374,7 +286,7 @@ class SemaEngine {
374
286
  if (pending.length > 0) {
375
287
  for (const item of pending) {
376
288
  const type = item.input.startsWith('/') ? 'command' : 'inject';
377
- stateManager.addPendingUserInput({ ...item, type });
289
+ this.runtime.addPendingUserInput({ ...item, type });
378
290
  }
379
291
  }
380
292
  (0, log_1.logInfo)(`处理队列中 ${batch.length} 条待处理输入`);
@@ -387,73 +299,62 @@ class SemaEngine {
387
299
  }
388
300
  /**
389
301
  * 中止当前正在进行的请求(仅处理 AbortController)
390
- * 不更新状态,用于内部调用
391
302
  */
392
303
  abortCurrentRequest() {
393
- const stateManager = (0, StateManager_1.getStateManager)();
394
- const abortController = stateManager.currentAbortController;
304
+ const abortController = this.runtime.currentAbortController;
395
305
  if (abortController && !abortController.signal.aborted) {
396
306
  (0, log_1.logInfo)('通过 AbortController 发送中断信号');
397
307
  abortController.abort();
398
308
  }
399
- stateManager.currentAbortController = null;
309
+ this.runtime.currentAbortController = null;
400
310
  }
401
311
  /**
402
312
  * 中断当前会话
403
- * 仅中断当前正在执行的请求,队列中的待处理输入不受影响
404
- * 由 processQuery 的 finally 决定是否继续消费队列或设为 idle
405
313
  */
406
314
  interruptSession() {
407
315
  this.abortCurrentRequest();
408
- // 不直接设 idle,由 processQuery 的 finally 决定
409
- // 若当前未在 processing(如已经 idle),则无需额外操作
410
316
  }
411
317
  /**
412
- * 更新 Agent 模式
318
+ * 更新 Agent 模式(会话级)
413
319
  */
414
320
  updateAgentMode(mode) {
415
- // 若模式值无变化,直接返回
416
- const currentMode = (0, ConfManager_1.getConfManager)().getCoreConfig()?.agentMode || 'Agent';
417
- if (currentMode === mode) {
321
+ if (this.runtime.agentMode === mode) {
418
322
  return;
419
323
  }
420
- // 更新配置
421
- (0, ConfManager_1.getConfManager)().updateAgentMode(mode);
422
- // 切换到 Plan 模式时,重置 Plan 模式信息发送状态
324
+ this.runtime.agentMode = mode;
325
+ (0, log_1.logInfo)(`[${this.sessionId}] Agent 模式已更新: ${mode}`);
423
326
  if (mode === 'Plan') {
424
- (0, StateManager_1.getStateManager)().resetPlanModeInfoSent();
327
+ this.runtime.resetPlanModeInfoSent();
425
328
  }
426
- // 切换到 Design 模式时,重置 Design 模式信息发送状态
427
- // 新会话由前端在切换 UI 时通过 createSession() 自行触发
428
329
  if (mode === 'Design') {
429
- (0, StateManager_1.getStateManager)().resetDesignModeInfoSent();
330
+ this.runtime.resetDesignModeInfoSent();
430
331
  }
431
332
  }
432
- // 初始化系统
433
- async initialize(sessionId) {
333
+ /**
334
+ * 更新权限自由度档位(会话级)
335
+ */
336
+ updatePermissionLevel(level) {
337
+ this.runtime.setPermissionLevel(level);
338
+ }
339
+ // 初始化系统配置与模型检查
340
+ async initialize() {
434
341
  const coreConfig = (0, ConfManager_1.getConfManager)().getCoreConfig();
435
- // 1、设置日志级别
436
342
  (0, log_1.setLogLevel)(coreConfig?.logLevel || 'info');
437
- // 2、设置sessionId(如果为空则生成一个)
438
- const finalSessionId = sessionId || (0, session_1.generateSessionId)();
439
- const stateManager = (0, StateManager_1.getStateManager)();
440
- stateManager.setSessionId(finalSessionId);
441
- // 3、从配置文件加载模型配置 ~/.sema.conf
442
343
  try {
443
344
  const modelManager = (0, ModelManager_1.getModelManager)();
444
345
  const modelProfile = modelManager.getModel('main');
445
- // 检查是否有可用模型
446
346
  if (!modelProfile) {
447
- // 发送无模型配置事件
448
- this.emit('config:no_models', {
449
- message: '未配置任何模型,请先添加模型配置',
450
- suggestion: ''
347
+ // 延迟一拍:等调用方在返回的 SemaSession 上注册监听器
348
+ setImmediate(() => {
349
+ this.emit('config:no_models', {
350
+ message: '未配置任何模型,请先添加模型配置',
351
+ suggestion: ''
352
+ });
451
353
  });
452
354
  }
453
355
  }
454
356
  catch (error) {
455
357
  const errorMessage = error instanceof Error ? error.message : String(error);
456
- // 发送模型配置错误事件
457
358
  this.emit('session:error', {
458
359
  type: 'model_error',
459
360
  error: {
@@ -466,20 +367,31 @@ class SemaEngine {
466
367
  }
467
368
  }
468
369
  /**
469
- * 清理资源和停止所有活动
370
+ * 等待当前处理结束(最多 timeoutMs 毫秒)
371
+ */
372
+ async waitForIdle(timeoutMs = 10000) {
373
+ if (!this.currentProcessingPromise)
374
+ return;
375
+ try {
376
+ await Promise.race([
377
+ this.currentProcessingPromise,
378
+ new Promise((_, reject) => setTimeout(() => reject(new Error('等待超时')), timeoutMs)),
379
+ ]);
380
+ }
381
+ catch (error) {
382
+ (0, log_1.logWarn)(`等待会话处理结束时出错: ${error instanceof Error ? error.message : String(error)}`);
383
+ }
384
+ }
385
+ /**
386
+ * 清理本会话资源(会话级,不触碰全局单例)
470
387
  */
471
388
  dispose() {
472
- (0, log_1.logInfo)('开始清理 SemaEngine 资源...');
473
- // 1. 中止当前正在进行的请求并清空队列
389
+ (0, log_1.logInfo)(`清理 SemaEngine 资源: ${this.sessionId}`);
474
390
  this.abortCurrentRequest();
475
- (0, StateManager_1.getStateManager)().clearPendingUserInputs();
476
- this.pendingSession = null;
477
- // 2. 清空所有状态数据
478
- const stateManager = (0, StateManager_1.getStateManager)();
479
- stateManager.clearAllState();
480
- // 3. 移除所有事件监听器
481
- this.eventBus.removeAllListeners();
482
- (0, log_1.logInfo)('SemaEngine 资源清理完成');
391
+ this.runtime.clearPendingUserInputs();
392
+ // 移除本会话在 Task/Cron 管理器上的通知回调
393
+ (0, TaskManager_1.getTaskManager)().removeNotifyCallback(this.sessionId);
394
+ (0, CronManager_1.getCronManager)().removeNotifyCallback(this.sessionId);
483
395
  }
484
396
  }
485
397
  exports.SemaEngine = SemaEngine;