@voko/lite 0.3.1

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 (62) hide show
  1. package/package.json +32 -0
  2. package/scripts/build-native.js +72 -0
  3. package/src/bankHeadOffices.js +20543 -0
  4. package/src/channels/email.js +35 -0
  5. package/src/channels/feishu.js +31 -0
  6. package/src/channels/qq-email.js +30 -0
  7. package/src/channels/registry.js +279 -0
  8. package/src/channels/telegram.js +28 -0
  9. package/src/channels/voko-email.js +7 -0
  10. package/src/channels/wechat.js +35 -0
  11. package/src/cli.js +120 -0
  12. package/src/context.js +164 -0
  13. package/src/core/access-control-api.js +150 -0
  14. package/src/core/access-control.js +56 -0
  15. package/src/core/agent-registration.js +319 -0
  16. package/src/core/api-signature.js +33 -0
  17. package/src/core/audit.js +133 -0
  18. package/src/core/database.js +1409 -0
  19. package/src/core/did-auth.js +54 -0
  20. package/src/core/hermes-paths.js +57 -0
  21. package/src/core/invitation.js +49 -0
  22. package/src/core/lite-bus.js +16 -0
  23. package/src/core/llm-client.js +1032 -0
  24. package/src/core/messenger.js +456 -0
  25. package/src/core/notifier.js +99 -0
  26. package/src/core/offline-sync.js +150 -0
  27. package/src/core/payment.js +285 -0
  28. package/src/core/publish-agent.js +166 -0
  29. package/src/core/register-capabilities.js +119 -0
  30. package/src/core/search-capabilities.js +136 -0
  31. package/src/core/send-message.js +85 -0
  32. package/src/core/set-agent-status.js +65 -0
  33. package/src/core/update-agent-profile.js +102 -0
  34. package/src/core/worker-manager.js +332 -0
  35. package/src/endpoints.json +21 -0
  36. package/src/index.js +712 -0
  37. package/src/mcp/CLAUDE_TEST.md +82 -0
  38. package/src/mcp/FULL_TEST.md +139 -0
  39. package/src/mcp/TEST.md +124 -0
  40. package/src/mcp/TEST_STEPS.md +75 -0
  41. package/src/mcp/server.js +612 -0
  42. package/src/mcp/tools.js +1367 -0
  43. package/src/mcp/transport/http.js +95 -0
  44. package/src/mcp/transport/stdio.js +20 -0
  45. package/src/preload.js +27 -0
  46. package/src/server/agent-email-api.js +120 -0
  47. package/src/server/agent-manager.js +580 -0
  48. package/src/server/email-handler.js +329 -0
  49. package/src/server/feishu-handler.js +249 -0
  50. package/src/server/hermes-api-client.js +166 -0
  51. package/src/server/hermes-discovery.js +80 -0
  52. package/src/server/hermes-handler.js +287 -0
  53. package/src/server/openclaw-handler-cli.js +131 -0
  54. package/src/server/openclaw-websocket-handler.js +1290 -0
  55. package/src/server/oss.js +186 -0
  56. package/src/server/owner-intervention-notifier.js +320 -0
  57. package/src/server/release-page.html +204 -0
  58. package/src/server/telegram-handler.js +208 -0
  59. package/src/server/voko-email-handler.js +68 -0
  60. package/src/server/wechat-handler.js +439 -0
  61. package/src/workers/agent-worker.js +378 -0
  62. package/src/workers/message-content.js +51 -0
@@ -0,0 +1,95 @@
1
+ /**
2
+ * VOKO MCP — 纯 HTTP JSON-RPC 传输(StreamableHTTP 兼容)
3
+ *
4
+ * 自写 HTTP transport,不自用 SDK 的 server.connect()。
5
+ * 直接解析 JSON-RPC 报文,转发给 McpServer 处理。
6
+ *
7
+ * 端点:
8
+ * POST /mcp — JSON-RPC 工具调用(initialize / tools/list / tools/call / notifications)
9
+ */
10
+
11
+ const { Router } = require('express');
12
+
13
+ const MCP_VERSION = '2025-11-25';
14
+ const SERVER_NAME = 'voko';
15
+
16
+ /**
17
+ * @param {import('@modelcontextprotocol/sdk/server/mcp').McpServer} mcpServer
18
+ * @param {Object} [options]
19
+ * @param {string} [options.version]
20
+ * @returns {Router}
21
+ */
22
+ function createHttpTransport(mcpServer, options = {}) {
23
+ const router = Router();
24
+ const version = options.version || '0.2.14';
25
+
26
+ // ─── POST /mcp — JSON-RPC 请求 ───
27
+ router.post('/', async (req, res) => {
28
+ const msg = req.body;
29
+ if (!msg || !msg.jsonrpc) {
30
+ return res.status(400).json({
31
+ jsonrpc: '2.0',
32
+ error: { code: -32700, message: 'Parse error: invalid JSON-RPC' },
33
+ id: null,
34
+ });
35
+ }
36
+
37
+ // ── initialize ──
38
+ if (msg.method === 'initialize') {
39
+ return res.json({
40
+ jsonrpc: '2.0',
41
+ id: msg.id,
42
+ result: {
43
+ protocolVersion: MCP_VERSION,
44
+ capabilities: {
45
+ tools: {},
46
+ },
47
+ serverInfo: {
48
+ name: SERVER_NAME,
49
+ version,
50
+ },
51
+ },
52
+ });
53
+ }
54
+
55
+ // ── notifications(无 id,不需要回复) ──
56
+ if (!msg.id) {
57
+ return res.status(202).end();
58
+ }
59
+
60
+ // ── tools/list ──
61
+ if (msg.method === 'tools/list') {
62
+ const handler = mcpServer.server._requestHandlers.get('tools/list');
63
+ if (handler) {
64
+ const result = await handler({ method: 'tools/list', params: {} });
65
+ return res.json({ jsonrpc: '2.0', id: msg.id, result });
66
+ }
67
+ return res.json({ jsonrpc: '2.0', error: { code: -32603, message: 'tools/list handler not found' }, id: msg.id });
68
+ }
69
+
70
+ // ── tools/call ──
71
+ if (msg.method === 'tools/call') {
72
+ const handler = mcpServer.server._requestHandlers.get('tools/call');
73
+ if (handler) {
74
+ try {
75
+ const result = await handler({ method: 'tools/call', params: msg.params });
76
+ return res.json({ jsonrpc: '2.0', id: msg.id, result });
77
+ } catch (e) {
78
+ return res.json({ jsonrpc: '2.0', error: { code: -32603, message: e.message }, id: msg.id });
79
+ }
80
+ }
81
+ return res.json({ jsonrpc: '2.0', error: { code: -32603, message: 'tools/call handler not found' }, id: msg.id });
82
+ }
83
+
84
+ // ── 未知 method ──
85
+ return res.json({
86
+ jsonrpc: '2.0',
87
+ error: { code: -32601, message: `Method not found: ${msg.method}` },
88
+ id: msg.id,
89
+ });
90
+ });
91
+
92
+ return router;
93
+ }
94
+
95
+ module.exports = { createHttpTransport };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * VOKO MCP — stdio 传输(可选)
3
+ *
4
+ * 3 行代码接入 SDK 的 StdioServerTransport。
5
+ * 适用于 Claude Code 通过 stdio 模式连接的场景。
6
+ * CLI:node src/mcp/standalone.js --transport stdio
7
+ */
8
+
9
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
10
+
11
+ /**
12
+ * @param {import('@modelcontextprotocol/sdk/server/mcp').McpServer} mcpServer
13
+ */
14
+ async function createStdioTransport(mcpServer) {
15
+ const transport = new StdioServerTransport();
16
+ await mcpServer.connect(transport);
17
+ console.error('[VOKO MCP] stdio transport 已启动');
18
+ }
19
+
20
+ module.exports = { createStdioTransport };
package/src/preload.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Lite 启动预加载 — 确保 better-sqlite3 使用本地编译的版本
3
+ *
4
+ * 在 Electron 下运行时(Desktop),用根目录的 Electron 编译版。
5
+ * 在纯 Node.js 下运行时(Lite CLI/MCP),用 packages/lite 的本地编译版。
6
+ */
7
+ const path = require('path');
8
+ const Module = require('module');
9
+
10
+ // Electron 环境下不需要重定向(根目录的 better-sqlite3 就是 Electron 版)
11
+ const isElectron = process.versions && process.versions.electron;
12
+ if (isElectron) {
13
+ console.error('[Lite] Electron 环境,使用根目录 better-sqlite3');
14
+ } else {
15
+ const liteBetterSqlite3 = path.join(__dirname, '..', 'native', 'better-sqlite3');
16
+ const origResolve = Module._resolveFilename;
17
+ Module._resolveFilename = function (request, parent) {
18
+ if (request === 'better-sqlite3') {
19
+ try {
20
+ return origResolve.call(this, liteBetterSqlite3, parent);
21
+ } catch (_) {
22
+ // 本地未安装 better-sqlite3 时回退默认
23
+ }
24
+ }
25
+ return origResolve.apply(this, arguments);
26
+ };
27
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Agent Email API — 服务端交互邮件 API 客户端
3
+ *
4
+ * 封装两个端点:
5
+ * POST /api/external/v1/email/send — 发信
6
+ * POST /api/external/v1/email/reply/query — 查回复
7
+ *
8
+ * 使用方式:
9
+ * const api = new AgentEmailApi({ apiBaseUrl, getUserAccessToken });
10
+ * const result = await api.send(agentDid, content, { subject, external_id, context });
11
+ * const reply = await api.queryReply({ message_id });
12
+ */
13
+
14
+ class AgentEmailApi {
15
+ /**
16
+ * @param {Object} opts
17
+ * @param {string} opts.apiBaseUrl — VOKO_API_URL
18
+ * @param {Function} opts.getUserAccessToken — () => string | null,返回 User Access Token
19
+ */
20
+ constructor({ apiBaseUrl, getUserAccessToken }) {
21
+ this.apiBaseUrl = (apiBaseUrl || '').replace(/\/+$/, '');
22
+ this.getUserAccessToken = getUserAccessToken || (() => null);
23
+ }
24
+
25
+ /**
26
+ * 发交互邮件
27
+ * @param {string} agentDid — Agent DID
28
+ * @param {string} content — 邮件正文(template_data.CONTENT)
29
+ * @param {Object} [opts]
30
+ * @param {string} [opts.subject] — 邮件标题
31
+ * @param {string} [opts.external_id] — 外部关联 ID
32
+ * @param {Object} [opts.context] — { visitor_id?, session_id?, snippet? }
33
+ * @returns {Promise<{message_id:string, external_id:string}|null>}
34
+ */
35
+ async send(agentDid, content, opts = {}) {
36
+ const token = this.getUserAccessToken();
37
+ if (!token) { console.warn('[AgentEmailApi] send 跳过: 无 User Access Token'); return null; }
38
+ if (!this.apiBaseUrl) { console.warn('[AgentEmailApi] send 跳过: VOKO_API_URL 未配置'); return null; }
39
+ if (!agentDid) { console.warn('[AgentEmailApi] send 跳过: agentDid 为空'); return null; }
40
+ if (!content) { console.warn('[AgentEmailApi] send 跳过: content 为空'); return null; }
41
+
42
+ const body = {
43
+ agentDid,
44
+ template_data: {
45
+ CONTENT: content,
46
+ TITLE: opts.subject || '请处理',
47
+ },
48
+ reply_enabled: true,
49
+ };
50
+
51
+ if (opts.subject) body.subject = opts.subject;
52
+ if (opts.external_id) body.external_id = opts.external_id;
53
+ if (opts.context) body.context = opts.context;
54
+ if (opts.to) body.to = opts.to;
55
+
56
+ try {
57
+ const resp = await fetch(`${this.apiBaseUrl}/api/external/v1/email/send`, {
58
+ method: 'POST',
59
+ headers: {
60
+ 'Content-Type': 'application/json',
61
+ Authorization: `Bearer ${token}`,
62
+ },
63
+ body: JSON.stringify(body),
64
+ });
65
+ const json = await resp.json();
66
+ if (!json.success || !json.data?.message_id) {
67
+ console.warn('[AgentEmailApi] send 失败:', json.message || json.msg || 'unknown');
68
+ return null;
69
+ }
70
+ return {
71
+ message_id: json.data.message_id,
72
+ external_id: json.data.external_id || opts.external_id || null,
73
+ };
74
+ } catch (e) {
75
+ console.warn('[AgentEmailApi] send 异常:', e.message);
76
+ return null;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 查回复
82
+ * @param {Object} opts
83
+ * @param {string} opts.message_id — 发信返回的 message_id
84
+ * @returns {Promise<{has_reply:boolean, raw_text:string, status:string, replied_at:string}|null>}
85
+ */
86
+ async queryReply({ message_id } = {}) {
87
+ const token = this.getUserAccessToken();
88
+ if (!token || !this.apiBaseUrl || !message_id) {
89
+ return null;
90
+ }
91
+
92
+ try {
93
+ const resp = await fetch(`${this.apiBaseUrl}/api/external/v1/email/reply/query`, {
94
+ method: 'POST',
95
+ headers: {
96
+ 'Content-Type': 'application/json',
97
+ Authorization: `Bearer ${token}`,
98
+ },
99
+ body: JSON.stringify({ message_id }),
100
+ });
101
+ const json = await resp.json();
102
+ if (!json.success || !json.data) {
103
+ return null;
104
+ }
105
+ const data = json.data;
106
+ return {
107
+ has_reply: !!data.has_reply,
108
+ raw_text: data.raw_text || null,
109
+ status: data.status || null,
110
+ replied_at: data.replied_at || null,
111
+ actor_email: data.actor_email || null,
112
+ };
113
+ } catch (e) {
114
+ console.warn('[AgentEmailApi] queryReply 异常:', e.message);
115
+ return null;
116
+ }
117
+ }
118
+ }
119
+
120
+ module.exports = { AgentEmailApi };