@next-open-ai/openbot 0.6.8 → 0.6.16

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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +156 -137
  3. package/apps/desktop/renderer/dist/assets/index-BxqMW-uy.css +10 -0
  4. package/apps/desktop/renderer/dist/assets/index-DJs-wX3R.js +89 -0
  5. package/apps/desktop/renderer/dist/index.html +2 -2
  6. package/dist/core/agent/agent-manager.d.ts +14 -6
  7. package/dist/core/agent/agent-manager.js +63 -23
  8. package/dist/core/agent/proxy/adapters/coze-adapter.d.ts +2 -0
  9. package/dist/core/agent/proxy/adapters/coze-adapter.js +406 -0
  10. package/dist/core/agent/proxy/adapters/local-adapter.d.ts +2 -0
  11. package/dist/core/agent/proxy/adapters/local-adapter.js +93 -0
  12. package/dist/core/agent/proxy/adapters/openclawx-adapter.d.ts +2 -0
  13. package/dist/core/agent/proxy/adapters/openclawx-adapter.js +115 -0
  14. package/dist/core/agent/proxy/adapters/opencode-adapter.d.ts +11 -0
  15. package/dist/core/agent/proxy/adapters/opencode-adapter.js +750 -0
  16. package/dist/core/agent/proxy/adapters/opencode-free-models.d.ts +20 -0
  17. package/dist/core/agent/proxy/adapters/opencode-free-models.js +14 -0
  18. package/dist/core/agent/proxy/adapters/opencode-local-runner.d.ts +5 -0
  19. package/dist/core/agent/proxy/adapters/opencode-local-runner.js +86 -0
  20. package/dist/core/agent/proxy/index.d.ts +3 -0
  21. package/dist/core/agent/proxy/index.js +16 -0
  22. package/dist/core/agent/proxy/registry.d.ts +7 -0
  23. package/dist/core/agent/proxy/registry.js +13 -0
  24. package/dist/core/agent/proxy/run-for-channel.d.ts +3 -0
  25. package/dist/core/agent/proxy/run-for-channel.js +31 -0
  26. package/dist/core/agent/proxy/types.d.ts +30 -0
  27. package/dist/core/agent/proxy/types.js +1 -0
  28. package/dist/core/agent/run.js +1 -1
  29. package/dist/core/config/agent-reload-pending.d.ts +9 -0
  30. package/dist/core/config/agent-reload-pending.js +66 -0
  31. package/dist/core/config/desktop-config.d.ts +111 -3
  32. package/dist/core/config/desktop-config.js +289 -26
  33. package/dist/core/inbound-message-preprocess.d.ts +27 -0
  34. package/dist/core/inbound-message-preprocess.js +96 -0
  35. package/dist/core/mcp/client.d.ts +4 -0
  36. package/dist/core/mcp/client.js +2 -0
  37. package/dist/core/mcp/config.d.ts +14 -3
  38. package/dist/core/mcp/config.js +68 -3
  39. package/dist/core/mcp/index.d.ts +8 -6
  40. package/dist/core/mcp/index.js +6 -3
  41. package/dist/core/mcp/operator.d.ts +17 -2
  42. package/dist/core/mcp/operator.js +97 -30
  43. package/dist/core/mcp/transport/index.d.ts +4 -0
  44. package/dist/core/mcp/transport/index.js +6 -1
  45. package/dist/core/mcp/transport/stdio.d.ts +6 -0
  46. package/dist/core/mcp/transport/stdio.js +22 -1
  47. package/dist/core/mcp/types.d.ts +18 -0
  48. package/dist/core/memory/compaction-extension.d.ts +4 -3
  49. package/dist/core/memory/compaction-extension.js +6 -14
  50. package/dist/core/memory/embedding-types.d.ts +10 -0
  51. package/dist/core/memory/embedding-types.js +5 -0
  52. package/dist/core/memory/embedding.d.ts +2 -1
  53. package/dist/core/memory/embedding.js +38 -6
  54. package/dist/core/memory/index.js +3 -0
  55. package/dist/core/memory/local-embedding-llama.d.ts +13 -0
  56. package/dist/core/memory/local-embedding-llama.js +76 -0
  57. package/dist/core/memory/local-embedding.d.ts +10 -0
  58. package/dist/core/memory/local-embedding.js +29 -0
  59. package/dist/core/memory/persist-compaction-on-close.d.ts +14 -0
  60. package/dist/core/memory/persist-compaction-on-close.js +32 -0
  61. package/dist/core/session-outlet/index.d.ts +19 -0
  62. package/dist/core/session-outlet/index.js +33 -0
  63. package/dist/core/session-outlet/outlet.d.ts +15 -0
  64. package/dist/core/session-outlet/outlet.js +49 -0
  65. package/dist/core/session-outlet/types.d.ts +35 -0
  66. package/dist/core/session-outlet/types.js +5 -0
  67. package/dist/core/tools/bookmark-tool.d.ts +4 -0
  68. package/dist/core/tools/bookmark-tool.js +59 -3
  69. package/dist/core/tools/index.d.ts +2 -1
  70. package/dist/core/tools/index.js +2 -1
  71. package/dist/core/tools/memory-recall-tool.d.ts +6 -0
  72. package/dist/core/tools/memory-recall-tool.js +77 -0
  73. package/dist/gateway/channel/adapters/telegram.js +13 -2
  74. package/dist/gateway/channel/adapters/wechat.d.ts +24 -0
  75. package/dist/gateway/channel/adapters/wechat.js +205 -0
  76. package/dist/gateway/channel/channel-core.d.ts +1 -0
  77. package/dist/gateway/channel/channel-core.js +101 -59
  78. package/dist/gateway/channel/run-agent.d.ts +2 -4
  79. package/dist/gateway/channel/run-agent.js +13 -125
  80. package/dist/gateway/methods/agent-cancel.d.ts +3 -1
  81. package/dist/gateway/methods/agent-cancel.js +16 -2
  82. package/dist/gateway/methods/agent-chat.d.ts +4 -0
  83. package/dist/gateway/methods/agent-chat.js +309 -118
  84. package/dist/gateway/methods/run-scheduled-task.js +7 -7
  85. package/dist/gateway/proxy-run-abort.d.ts +6 -0
  86. package/dist/gateway/proxy-run-abort.js +39 -0
  87. package/dist/gateway/server.js +64 -7
  88. package/dist/server/agent-config/agent-config.controller.d.ts +2 -2
  89. package/dist/server/agent-config/agent-config.controller.js +8 -4
  90. package/dist/server/agent-config/agent-config.module.js +3 -1
  91. package/dist/server/agent-config/agent-config.service.d.ts +67 -6
  92. package/dist/server/agent-config/agent-config.service.js +75 -3
  93. package/dist/server/agents/agents.controller.d.ts +16 -0
  94. package/dist/server/agents/agents.controller.js +62 -1
  95. package/dist/server/agents/agents.service.js +1 -1
  96. package/dist/server/bootstrap.js +9 -2
  97. package/dist/server/config/config.controller.d.ts +31 -2
  98. package/dist/server/config/config.controller.js +14 -0
  99. package/dist/server/config/config.module.js +2 -2
  100. package/dist/server/config/config.service.d.ts +14 -1
  101. package/dist/server/config/config.service.js +1 -0
  102. package/dist/server/workspace/workspace.service.d.ts +7 -0
  103. package/dist/server/workspace/workspace.service.js +16 -0
  104. package/package.json +8 -2
  105. package/presets/preset-agents.json +94 -0
  106. package/presets/preset-config.json +11 -0
  107. package/presets/preset-providers.json +173 -0
  108. package/presets/workspaces/code-assistant/skills/code-review/SKILL.md +19 -0
  109. package/presets/workspaces/code-assistant/skills/code-runner/SKILL.md +21 -0
  110. package/presets/workspaces/code-assistant/skills/git-helper/SKILL.md +29 -0
  111. package/presets/workspaces/creator-assistant/skills/.gitkeep +0 -0
  112. package/presets/workspaces/creator-assistant/skills/creator-tools/SKILL.md +15 -0
  113. package/presets/workspaces/doc-assistant/skills/doc-processor/SKILL.md +21 -0
  114. package/presets/workspaces/download-assistant/skills/downloader/SKILL.md +20 -0
  115. package/presets/workspaces/file-assistant/skills/file-converter/SKILL.md +21 -0
  116. package/presets/workspaces/file-assistant/skills/file-organizer/SKILL.md +17 -0
  117. package/presets/workspaces/file-assistant/skills/file-search/SKILL.md +22 -0
  118. package/presets/workspaces/morning-briefing/skills/news-fetcher/SKILL.md +16 -0
  119. package/presets/workspaces/morning-briefing/skills/web-summarizer/SKILL.md +20 -0
  120. package/presets/workspaces/news-assistant/skills/news-fetcher/SKILL.md +16 -0
  121. package/presets/workspaces/news-assistant/skills/web-summarizer/SKILL.md +20 -0
  122. package/apps/desktop/renderer/dist/assets/index-LCp1YPVA.css +0 -10
  123. package/apps/desktop/renderer/dist/assets/index-l5fpDsHs.js +0 -89
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 会话关闭时将内存中缓存的 compaction summary 写入向量库的纯逻辑,便于单测且与 AgentManager 解耦。
3
+ */
4
+ const COMPOSITE_KEY_SEP = "::";
5
+ /**
6
+ * 将 map 中指定 compositeKey 的 summary 写入 addMemory 并从 map 删除;用于 Session 关闭前。
7
+ * 写入采用 fire-and-forget,不阻塞调用方,避免 agent.chat 等请求被 addMemory/embed 拖住导致无回复。
8
+ */
9
+ export async function persistStoredCompactionForSession(sessionLatestCompactionSummary, compositeKey, addMemory) {
10
+ const summary = sessionLatestCompactionSummary.get(compositeKey);
11
+ sessionLatestCompactionSummary.delete(compositeKey);
12
+ if (summary?.trim()) {
13
+ const sessionId = compositeKey.split(COMPOSITE_KEY_SEP)[0];
14
+ void addMemory(summary.trim(), { infotype: "compaction", sessionId }).catch(() => { });
15
+ }
16
+ }
17
+ /**
18
+ * 将 map 中所有给定 keys(需以 sessionId + "::" 为前缀)的 summary 依次写入 addMemory 并删除;用于按业务 sessionId 关闭时。
19
+ * 写入采用 fire-and-forget,不阻塞调用方。
20
+ */
21
+ export async function persistStoredCompactionForBusinessSession(sessionLatestCompactionSummary, keysToProcess, sessionId, addMemory) {
22
+ const prefix = sessionId + COMPOSITE_KEY_SEP;
23
+ for (const key of keysToProcess) {
24
+ if (!key.startsWith(prefix))
25
+ continue;
26
+ const summary = sessionLatestCompactionSummary.get(key);
27
+ sessionLatestCompactionSummary.delete(key);
28
+ if (summary?.trim()) {
29
+ void addMemory(summary.trim(), { infotype: "compaction", sessionId }).catch(() => { });
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 会话消息统一出口:各模块仅需 sessionId + 消息即可通过统一出口准确送达当前会话对应的 Web/Desktop 或通道。
3
+ */
4
+ import type { SessionMessageInput, ISessionOutlet } from "./types.js";
5
+ export type { SessionMessage, SessionMessageInput, SessionMessageConsumer, ISessionOutlet } from "./types.js";
6
+ export { SessionOutlet } from "./outlet.js";
7
+ /**
8
+ * 获取当前使用的出口实例(Gateway 启动时通过 setSessionOutlet 注入)。
9
+ */
10
+ export declare function getSessionOutlet(): ISessionOutlet | null;
11
+ /**
12
+ * 设置全局出口实例;传 null 可清空(测试用)。
13
+ */
14
+ export declare function setSessionOutlet(outlet: ISessionOutlet | null): void;
15
+ /**
16
+ * 解耦 API:任意模块携带 sessionId 即可发送会话消息,由统一出口路由到正确端。
17
+ * 若未设置出口或 sessionId 为空,则静默忽略。
18
+ */
19
+ export declare function sendSessionMessage(sessionId: string, message: Omit<SessionMessageInput, "sessionId">): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 会话消息统一出口:各模块仅需 sessionId + 消息即可通过统一出口准确送达当前会话对应的 Web/Desktop 或通道。
3
+ */
4
+ export { SessionOutlet } from "./outlet.js";
5
+ let defaultOutlet = null;
6
+ /**
7
+ * 获取当前使用的出口实例(Gateway 启动时通过 setSessionOutlet 注入)。
8
+ */
9
+ export function getSessionOutlet() {
10
+ return defaultOutlet;
11
+ }
12
+ /**
13
+ * 设置全局出口实例;传 null 可清空(测试用)。
14
+ */
15
+ export function setSessionOutlet(outlet) {
16
+ defaultOutlet = outlet;
17
+ }
18
+ /**
19
+ * 解耦 API:任意模块携带 sessionId 即可发送会话消息,由统一出口路由到正确端。
20
+ * 若未设置出口或 sessionId 为空,则静默忽略。
21
+ */
22
+ export function sendSessionMessage(sessionId, message) {
23
+ if (!sessionId || !message)
24
+ return;
25
+ const outlet = getSessionOutlet();
26
+ if (!outlet)
27
+ return;
28
+ outlet.emit(sessionId, {
29
+ type: message.type,
30
+ code: message.code,
31
+ payload: message.payload ?? {},
32
+ });
33
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 会话消息出口实现:按 sessionId 维护消费者集合,emit 时扇出到该会话所有消费者。
3
+ */
4
+ import type { SessionMessage, SessionMessageConsumer } from "./types.js";
5
+ export declare class SessionOutlet {
6
+ private readonly consumersBySession;
7
+ /**
8
+ * 向指定会话注册消费者;返回取消注册函数。
9
+ */
10
+ registerConsumer(sessionId: string, consumer: SessionMessageConsumer): () => void;
11
+ /**
12
+ * 向指定会话发送消息;将 sessionId、timestamp 注入后扇出到该会话所有消费者。
13
+ */
14
+ emit(sessionId: string, message: Omit<SessionMessage, "sessionId" | "timestamp">): void;
15
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 会话消息出口实现:按 sessionId 维护消费者集合,emit 时扇出到该会话所有消费者。
3
+ */
4
+ export class SessionOutlet {
5
+ consumersBySession = new Map();
6
+ /**
7
+ * 向指定会话注册消费者;返回取消注册函数。
8
+ */
9
+ registerConsumer(sessionId, consumer) {
10
+ let set = this.consumersBySession.get(sessionId);
11
+ if (!set) {
12
+ set = new Set();
13
+ this.consumersBySession.set(sessionId, set);
14
+ }
15
+ set.add(consumer);
16
+ return () => {
17
+ const s = this.consumersBySession.get(sessionId);
18
+ if (s) {
19
+ s.delete(consumer);
20
+ if (s.size === 0)
21
+ this.consumersBySession.delete(sessionId);
22
+ }
23
+ };
24
+ }
25
+ /**
26
+ * 向指定会话发送消息;将 sessionId、timestamp 注入后扇出到该会话所有消费者。
27
+ */
28
+ emit(sessionId, message) {
29
+ const full = {
30
+ ...message,
31
+ sessionId,
32
+ timestamp: Date.now(),
33
+ };
34
+ const set = this.consumersBySession.get(sessionId);
35
+ if (!set || set.size === 0)
36
+ return;
37
+ for (const consumer of set) {
38
+ try {
39
+ const result = consumer.send(full);
40
+ if (result && typeof result.catch === "function") {
41
+ result.catch((err) => console.warn("[SessionOutlet] consumer.send rejected:", err));
42
+ }
43
+ }
44
+ catch (err) {
45
+ console.warn("[SessionOutlet] consumer.send threw:", err);
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 会话消息出口:统一消息类型与消费者接口。
3
+ * 所有发给各端(Web/Desktop、通道)的会话消息经此抽象,由出口按 sessionId 路由到已注册的消费者。
4
+ */
5
+ /** 消息类型:对话内容 vs 系统消息(MCP 进度、// 命令结果等) */
6
+ export type SessionMessageType = "chat" | "system";
7
+ /** 系统消息子类型,便于各端区分展示 */
8
+ export type SessionMessageCode = "agent.chunk" | "agent.tool" | "turn_end" | "message_complete" | "agent_end" | "conversation_end" | "mcp.progress" | "command.result";
9
+ /**
10
+ * 统一会话消息:出口只认 sessionId + 本结构,不关心具体传输。
11
+ */
12
+ export interface SessionMessage {
13
+ type: SessionMessageType;
14
+ code?: SessionMessageCode;
15
+ payload: Record<string, unknown>;
16
+ sessionId: string;
17
+ timestamp?: number;
18
+ }
19
+ /** 发送时调用方可不带 sessionId,由出口注入 */
20
+ export type SessionMessageInput = Omit<SessionMessage, "sessionId"> & {
21
+ sessionId?: string;
22
+ };
23
+ /**
24
+ * 消费者接口:各端(Web、通道)注册后,出口将消息推送给 send(message)。
25
+ */
26
+ export interface SessionMessageConsumer {
27
+ send(message: SessionMessage): void | Promise<void>;
28
+ }
29
+ /**
30
+ * 出口接口:支持注册消费者与发送消息,便于注入与测试。
31
+ */
32
+ export interface ISessionOutlet {
33
+ emit(sessionId: string, message: Omit<SessionMessage, "sessionId" | "timestamp">): void;
34
+ registerConsumer(sessionId: string, consumer: SessionMessageConsumer): () => void;
35
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 会话消息出口:统一消息类型与消费者接口。
3
+ * 所有发给各端(Web/Desktop、通道)的会话消息经此抽象,由出口按 sessionId 路由到已注册的消费者。
4
+ */
5
+ export {};
@@ -1,4 +1,8 @@
1
1
  import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
2
+ /**
3
+ * 新增一个收藏标签。当 get_bookmark_tags 返回的列表中缺少用户想要的标签时,可先调用本工具创建该标签,再使用 save_bookmark 保存收藏。
4
+ */
5
+ export declare function createAddBookmarkTagTool(): ToolDefinition;
2
6
  /**
3
7
  * 获取当前系统中已维护的标签列表,供保存 URL 时选择匹配的标签。
4
8
  */
@@ -1,11 +1,14 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import { getBackendBaseUrl } from "../../gateway/backend-url.js";
3
3
  const GetBookmarkTagsSchema = Type.Object({});
4
+ const AddBookmarkTagSchema = Type.Object({
5
+ tagName: Type.String({ description: "要新增的标签名称,如「技术」「待读」「美女」等" }),
6
+ });
4
7
  const SaveBookmarkSchema = Type.Object({
5
8
  url: Type.String({ description: "要收藏的 URL" }),
6
9
  title: Type.Optional(Type.String({ description: "可选标题" })),
7
10
  tagNames: Type.Optional(Type.Array(Type.String(), {
8
- description: "标签名称列表,须与系统中已维护的标签一致。保存前应先用 get_bookmark_tags 获取可用标签。",
11
+ description: "标签名称列表,须与系统中已维护的标签一致。保存前应先用 get_bookmark_tags 获取可用标签;若缺标签可先用 add_bookmark_tag 新增。",
9
12
  })),
10
13
  });
11
14
  async function apiGet(path) {
@@ -39,6 +42,59 @@ async function apiPost(path, body) {
39
42
  }
40
43
  return res.json();
41
44
  }
45
+ /**
46
+ * 新增一个收藏标签。当 get_bookmark_tags 返回的列表中缺少用户想要的标签时,可先调用本工具创建该标签,再使用 save_bookmark 保存收藏。
47
+ */
48
+ export function createAddBookmarkTagTool() {
49
+ return {
50
+ name: "add_bookmark_tag",
51
+ label: "Add Bookmark Tag",
52
+ description: "在系统中新增一个收藏标签。当用户要保存链接到某个尚不存在的标签(如「美女」「技术」「待读」)时,先调用本工具创建该标签,再调用 get_bookmark_tags 获取最新列表并用 save_bookmark 保存。若标签已存在会提示无需重复创建。",
53
+ parameters: AddBookmarkTagSchema,
54
+ execute: async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
55
+ const tagName = (params.tagName ?? "").trim();
56
+ if (!tagName) {
57
+ return {
58
+ content: [{ type: "text", text: "请提供要新增的标签名称。" }],
59
+ details: undefined,
60
+ };
61
+ }
62
+ try {
63
+ const json = await apiPost("/tags", {
64
+ name: tagName,
65
+ });
66
+ const data = json.data;
67
+ return {
68
+ content: [
69
+ {
70
+ type: "text",
71
+ text: `已新增标签「${data?.name ?? tagName}」,可直接用于 save_bookmark 的 tagNames。`,
72
+ },
73
+ ],
74
+ details: data,
75
+ };
76
+ }
77
+ catch (err) {
78
+ const msg = err instanceof Error ? err.message : String(err);
79
+ if (msg.includes("409") || msg.includes("已存在") || msg.includes("Conflict")) {
80
+ return {
81
+ content: [
82
+ {
83
+ type: "text",
84
+ text: `标签「${tagName}」已存在,无需重复创建。可直接在 save_bookmark 的 tagNames 中使用该名称。`,
85
+ },
86
+ ],
87
+ details: undefined,
88
+ };
89
+ }
90
+ return {
91
+ content: [{ type: "text", text: `新增标签失败: ${msg}` }],
92
+ details: undefined,
93
+ };
94
+ }
95
+ },
96
+ };
97
+ }
42
98
  /**
43
99
  * 获取当前系统中已维护的标签列表,供保存 URL 时选择匹配的标签。
44
100
  */
@@ -55,7 +111,7 @@ export function createGetBookmarkTagsTool() {
55
111
  const names = data.map((t) => t.name);
56
112
  const text = names.length > 0
57
113
  ? `当前可用标签:${names.join("、")}。请根据用户意图选择匹配的标签名用于 save_bookmark。`
58
- : "当前暂无标签。请在设置中先添加标签,或使用 save_bookmark 时不传 tagNames。";
114
+ : "当前暂无标签。可使用 add_bookmark_tag 新增标签,或 save_bookmark 时不传 tagNames。";
59
115
  return {
60
116
  content: [{ type: "text", text }],
61
117
  details: { tags: data },
@@ -78,7 +134,7 @@ export function createSaveBookmarkTool() {
78
134
  return {
79
135
  name: "save_bookmark",
80
136
  label: "Save Bookmark",
81
- description: "将用户提供的 URL 保存到收藏库,并可关联一个或多个标签。标签名必须使用 get_bookmark_tags 返回的已有标签;若用户未指定标签,可根据上下文推断或留空。",
137
+ description: "将用户提供的 URL 保存到收藏库,并可关联一个或多个标签。标签名须为系统已有标签(get_bookmark_tags 返回);若缺少某标签可先用 add_bookmark_tag 新增。",
82
138
  parameters: SaveBookmarkSchema,
83
139
  execute: async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
84
140
  const url = (params.url ?? "").trim();
@@ -1,7 +1,8 @@
1
1
  export { createBrowserTool, closeBrowser } from "./browser-tool.js";
2
2
  export { createSaveExperienceTool } from "./save-experience-tool.js";
3
+ export { createMemoryRecallTool } from "./memory-recall-tool.js";
3
4
  export { createInstallSkillTool } from "./install-skill-tool.js";
4
5
  export { createSwitchAgentTool } from "./switch-agent-tool.js";
5
6
  export { createListAgentsTool } from "./list-agents-tool.js";
6
7
  export { createCreateAgentTool } from "./create-agent-tool.js";
7
- export { createGetBookmarkTagsTool, createSaveBookmarkTool } from "./bookmark-tool.js";
8
+ export { createGetBookmarkTagsTool, createSaveBookmarkTool, createAddBookmarkTagTool, } from "./bookmark-tool.js";
@@ -1,7 +1,8 @@
1
1
  export { createBrowserTool, closeBrowser } from "./browser-tool.js";
2
2
  export { createSaveExperienceTool } from "./save-experience-tool.js";
3
+ export { createMemoryRecallTool } from "./memory-recall-tool.js";
3
4
  export { createInstallSkillTool } from "./install-skill-tool.js";
4
5
  export { createSwitchAgentTool } from "./switch-agent-tool.js";
5
6
  export { createListAgentsTool } from "./list-agents-tool.js";
6
7
  export { createCreateAgentTool } from "./create-agent-tool.js";
7
- export { createGetBookmarkTagsTool, createSaveBookmarkTool } from "./bookmark-tool.js";
8
+ export { createGetBookmarkTagsTool, createSaveBookmarkTool, createAddBookmarkTagTool, } from "./bookmark-tool.js";
@@ -0,0 +1,6 @@
1
+ import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
2
+ /**
3
+ * 创建 memory_recall 工具:按需从向量库检索经验与对话摘要,供回答「过往工作、决定、日期、人、偏好、待办、复杂任务、定时任务、历史经验」等问题时使用。
4
+ * @param useLongMemory 当前智能体是否启用长记忆;为 false 时执行空转(不检索,直接返回未启用提示)。
5
+ */
6
+ export declare function createMemoryRecallTool(useLongMemory: boolean): ToolDefinition;
@@ -0,0 +1,77 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { searchMemory } from "../memory/index.js";
3
+ const MemoryRecallSchema = Type.Object({
4
+ query: Type.String({
5
+ description: "语义检索查询,例如:过往决定、用户偏好、某日讨论、待办、历史经验、任务总结等",
6
+ }),
7
+ topK: Type.Optional(Type.Number({
8
+ description: "返回条数,默认 6",
9
+ minimum: 1,
10
+ maximum: 20,
11
+ })),
12
+ });
13
+ /**
14
+ * 创建 memory_recall 工具:按需从向量库检索经验与对话摘要,供回答「过往工作、决定、日期、人、偏好、待办、复杂任务、定时任务、历史经验」等问题时使用。
15
+ * @param useLongMemory 当前智能体是否启用长记忆;为 false 时执行空转(不检索,直接返回未启用提示)。
16
+ */
17
+ export function createMemoryRecallTool(useLongMemory) {
18
+ return {
19
+ name: "memory_recall",
20
+ label: "Memory Recall",
21
+ description: "从长期记忆中语义检索与查询相关的经验总结和对话摘要。在回答与过往工作、决定、日期、人、偏好、待办、复杂任务、定时任务或需要历史经验相关的问题前,应先调用本工具获取相关记忆再作答。",
22
+ parameters: MemoryRecallSchema,
23
+ execute: async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
24
+ if (!useLongMemory) {
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: "当前智能体未启用长记忆(经验),无法检索。",
30
+ },
31
+ ],
32
+ details: undefined,
33
+ };
34
+ }
35
+ const query = (params.query ?? "").trim();
36
+ if (!query) {
37
+ return {
38
+ content: [{ type: "text", text: "请提供检索查询(query)。" }],
39
+ details: undefined,
40
+ };
41
+ }
42
+ const topK = Math.min(20, Math.max(1, params.topK ?? 6));
43
+ try {
44
+ const results = await searchMemory(query, topK);
45
+ if (results.length === 0) {
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: "未找到与查询相关的记忆。",
51
+ },
52
+ ],
53
+ details: { results: [], query, topK },
54
+ };
55
+ }
56
+ const lines = results.map((r, i) => `${i + 1}. [${r.metadata?.infotype ?? "memory"}]\n${(r.document ?? "").trim()}`);
57
+ const text = "以下为检索到的相关记忆:\n\n" + lines.join("\n\n");
58
+ return {
59
+ content: [{ type: "text", text }],
60
+ details: { results: results.length, query, topK },
61
+ };
62
+ }
63
+ catch (err) {
64
+ const msg = err instanceof Error ? err.message : String(err);
65
+ return {
66
+ content: [
67
+ {
68
+ type: "text",
69
+ text: `记忆检索失败: ${msg}`,
70
+ },
71
+ ],
72
+ details: undefined,
73
+ };
74
+ }
75
+ },
76
+ };
77
+ }
@@ -31,11 +31,14 @@ function truncateForTelegram(text) {
31
31
  /**
32
32
  * 入站:长轮询 getUpdates,收到 message/edited_message 后转 UnifiedMessage 并分发。
33
33
  */
34
+ /** 轮询错误日志节流:同一类错误至少间隔此毫秒数再打印,避免刷屏 */
35
+ const TELEGRAM_POLL_ERROR_LOG_INTERVAL_MS = 60_000;
34
36
  class TelegramLongPollInbound {
35
37
  config;
36
38
  messageHandler = null;
37
39
  stopped = false;
38
40
  lastOffset = 0;
41
+ lastPollErrorLogTime = 0;
39
42
  constructor(config) {
40
43
  this.config = config;
41
44
  }
@@ -91,8 +94,16 @@ class TelegramLongPollInbound {
91
94
  }
92
95
  }
93
96
  catch (e) {
94
- if (!this.stopped)
95
- console.error("[Telegram] long poll error:", e);
97
+ if (!this.stopped) {
98
+ const now = Date.now();
99
+ if (now - this.lastPollErrorLogTime >= TELEGRAM_POLL_ERROR_LOG_INTERVAL_MS) {
100
+ this.lastPollErrorLogTime = now;
101
+ const cause = e?.cause?.code === "UND_ERR_CONNECT_TIMEOUT"
102
+ ? " (api.telegram.org 连接超时,可能需代理或网络不可达,将继续重试)"
103
+ : "";
104
+ console.warn("[Telegram] long poll error:", e?.message ?? e, cause);
105
+ }
106
+ }
96
107
  await new Promise((r) => setTimeout(r, 2000));
97
108
  }
98
109
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 微信通道适配器:使用 Wechaty(Web/UOS 协议)接收消息,say() 发送回复。
3
+ * 不支持流式(微信无法编辑已发消息),回复在 agent_end 后一次性发送。
4
+ * 扫码:scan 事件产生二维码 URL,经 qrcode 库生成 base64 供前端展示。
5
+ */
6
+ import type { IChannel } from "../types.js";
7
+ export interface WechatChannelConfig {
8
+ /** Puppet 名称,缺省使用 Wechaty 自带 puppet */
9
+ puppet?: string;
10
+ /** 默认绑定的 agentId */
11
+ defaultAgentId?: string;
12
+ }
13
+ type WechatLoginStatus = "scanning" | "logged_in" | "logged_out";
14
+ /** 供 Gateway API 查询当前二维码(base64 Data URL 或 null) */
15
+ export declare function getWechatQrCode(): string | null;
16
+ /** 供 Gateway API 查询登录状态 */
17
+ export declare function getWechatStatus(): {
18
+ status: WechatLoginStatus;
19
+ userName: string | null;
20
+ };
21
+ /** 重启 Wechaty 以刷新二维码(二维码过期后调用) */
22
+ export declare function refreshWechatQrCode(): Promise<void>;
23
+ export declare function createWechatChannel(config: WechatChannelConfig): IChannel;
24
+ export {};