@kafca/agentdock 0.1.21 → 0.1.23
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/README.md +9 -0
- package/dist/renderer/assets/{Badge-BRmQIqbd.js → Badge-C2K5apfV.js} +1 -1
- package/dist/renderer/assets/{Chat-D94ODABB.js → Chat-DI2YeVKb.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-DqW7OUvV.js → ChatMarkdown-DMAr15Oi.js} +1 -1
- package/dist/renderer/assets/{Config-9lgzpTCp.js → Config-7rP3EuUf.js} +2 -2
- package/dist/renderer/assets/CronList-81QslYE8.js +1 -0
- package/dist/renderer/assets/{Dashboard-COISXbQy.js → Dashboard-Db2T7rSZ.js} +2 -2
- package/dist/renderer/assets/{EmptyState-w5-I9zg7.js → EmptyState-BBJ3cTvB.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-DVxwrTLw.js → KnowledgeDetail-Dz_6flG3.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BKkubcwi.js → KnowledgeHome-DIh046mN.js} +3 -3
- package/dist/renderer/assets/Logs-BXBtHJLf.js +1 -0
- package/dist/renderer/assets/{Modal-Ceu_MP2e.js → Modal-BB2Av_Xs.js} +1 -1
- package/dist/renderer/assets/{Page-CpSczAz8.js → Page-DPSdvMgU.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-FJ_bNXLF.js → ProjectDetail-C6EWGvGg.js} +1 -1
- package/dist/renderer/assets/{ProjectList-DZKL4K9C.js → ProjectList-BBo5ygnS.js} +1 -1
- package/dist/renderer/assets/{Select-BHQk6qCU.js → Select-CNX-Tx_O.js} +2 -7
- package/dist/renderer/assets/SessionChat-BIn46jqZ.js +1 -0
- package/dist/renderer/assets/SessionList-CZt6f1Rd.js +1 -0
- package/dist/renderer/assets/{ThreadChat-D3s4GXGh.js → ThreadChat-BotD0gKQ.js} +7 -7
- package/dist/renderer/assets/Workspace-C_4tdpjX.js +14 -0
- package/dist/renderer/assets/{arrow-left-Dtal-eOi.js → arrow-left-cHr5wkpq.js} +1 -1
- package/dist/renderer/assets/{book-open-q814R_Ov.js → book-open-4nx5C8T-.js} +1 -1
- package/dist/renderer/assets/{check-DjfCdLvw.js → check-exTS-R-x.js} +1 -1
- package/dist/renderer/assets/chevron-down-DSvxXQa0.js +6 -0
- package/dist/renderer/assets/{circle-vfhmyE8v.js → circle-DyvEovdw.js} +1 -1
- package/dist/renderer/assets/desktop-B-KVT10D.js +1 -0
- package/dist/renderer/assets/desktop-CVibRyAw.js +4 -0
- package/dist/renderer/assets/{funnel-CUQibo1I.js → funnel-DA9qVdTy.js} +1 -1
- package/dist/renderer/assets/{heart-DG9_b8P1.js → heart-DuEV0ZRJ.js} +1 -1
- package/dist/renderer/assets/{index-Ds0IN5rP.js → index-BgflqkCN.js} +3 -3
- package/dist/renderer/assets/index-Biz-aexG.js +177 -0
- package/dist/renderer/assets/{index-3CzgyQYB.css → index-DFiJR0vv.css} +1 -1
- package/dist/renderer/assets/{pencil-Dij0LlRY.js → pencil-DBDxeNmO.js} +1 -1
- package/dist/renderer/assets/{play-CPFGjIyJ.js → play-IzlP83_7.js} +1 -1
- package/dist/renderer/assets/{plug-DH3RKQyn.js → plug-CuT-qFnW.js} +1 -1
- package/dist/renderer/assets/{plus-afkK9_Y8.js → plus-DEqgkn63.js} +1 -1
- package/dist/renderer/assets/projects-DDtDN1rc.js +1 -0
- package/dist/renderer/assets/{save-B-cKgWcy.js → save-D4sRo07y.js} +1 -1
- package/dist/renderer/assets/{search-DR6PeYkt.js → search-DbPZLuV8.js} +1 -1
- package/dist/renderer/assets/{server-BM6KOB5a.js → server-D1jUQmwN.js} +1 -1
- package/dist/renderer/assets/{session-utils-BDuThM0a.js → session-utils-Aife8ep2.js} +1 -1
- package/dist/renderer/assets/{sessions-C1yKps4T.js → sessions-DaH3H7gC.js} +1 -1
- package/dist/renderer/assets/{shield-check-BFjMG-r2.js → shield-check-BGwUFWNr.js} +1 -1
- package/dist/renderer/assets/{trash-2-CW1heMCf.js → trash-2-CIFBioBa.js} +1 -1
- package/dist/renderer/assets/{user-r_2sHG7m.js → user-CnKcvHdo.js} +1 -1
- package/dist/renderer/assets/{wifi-off-VMUokMpE.js → wifi-off-ClO53WGa.js} +1 -1
- package/dist/renderer/index.html +2 -2
- package/dist-electron/electron/local-core-refactor.test.js +812 -3
- package/dist-electron/electron/plugin-kernel.test.js +74 -14
- package/dist-electron/packages/core-sdk/src/index.js +40 -20
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +5 -1
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +55 -3
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +210 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/config.js +54 -0
- package/dist-electron/services/local-ai-core/src/{gateway → channel/lark}/local-core-lark-gateway.js +365 -383
- package/dist-electron/services/local-ai-core/src/channel/lark/registration.js +50 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +191 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/types.js +2 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/file-utils.js +33 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/plugin.js +31 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +125 -0
- package/dist-electron/services/local-ai-core/src/{gateway → channel/weixin}/local-core-weixin-gateway.js +262 -258
- package/dist-electron/services/local-ai-core/src/channel/weixin/transport.js +169 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/types.js +2 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +41 -1
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +5 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +19 -40
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +19 -40
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +96 -44
- package/dist-electron/services/local-ai-core/src/runtime/server.js +20 -8
- package/dist-electron/shared/desktop.js +24 -1
- package/package.json +1 -1
- package/dist/renderer/assets/CronList-BYZ-x_bp.js +0 -1
- package/dist/renderer/assets/Logs-D7HxZ8Nb.js +0 -1
- package/dist/renderer/assets/SessionChat-DpgSXF3m.js +0 -1
- package/dist/renderer/assets/SessionList-CU6drQ4N.js +0 -1
- package/dist/renderer/assets/Workspace-B7looTVo.js +0 -14
- package/dist/renderer/assets/desktop-BPIxWbkM.js +0 -1
- package/dist/renderer/assets/desktop-DZHC4PDB.js +0 -3
- package/dist/renderer/assets/index-Bn8ane6_.js +0 -177
- package/dist/renderer/assets/projects-DTDS9SnT.js +0 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.UPLOAD_MEDIA_TYPE_FILE = exports.FILE_ITEM_TYPE = exports.VOICE_ITEM_TYPE = exports.IMAGE_ITEM_TYPE = exports.TEXT_ITEM_TYPE = exports.WEIXIN_ILINK_APP_CLIENT_VERSION = exports.WEIXIN_ILINK_APP_ID = exports.WEIXIN_CHANNEL_VERSION = exports.API_TIMEOUT_MS = void 0;
|
|
7
|
+
exports.createWechatUin = createWechatUin;
|
|
8
|
+
exports.createIlinkHeaders = createIlinkHeaders;
|
|
9
|
+
exports.weixinApiPost = weixinApiPost;
|
|
10
|
+
exports.weixinApiGet = weixinApiGet;
|
|
11
|
+
exports.getWeixinUpdates = getWeixinUpdates;
|
|
12
|
+
exports.sendWeixinTextMessageChunk = sendWeixinTextMessageChunk;
|
|
13
|
+
exports.sendWeixinFileMessage = sendWeixinFileMessage;
|
|
14
|
+
exports.getWeixinUploadUrl = getWeixinUploadUrl;
|
|
15
|
+
exports.uploadEncryptedBufferToWeixinCdn = uploadEncryptedBufferToWeixinCdn;
|
|
16
|
+
exports.isWeixinApiError = isWeixinApiError;
|
|
17
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
18
|
+
exports.API_TIMEOUT_MS = 15_000;
|
|
19
|
+
exports.WEIXIN_CHANNEL_VERSION = '2.1.7';
|
|
20
|
+
exports.WEIXIN_ILINK_APP_ID = 'bot';
|
|
21
|
+
exports.WEIXIN_ILINK_APP_CLIENT_VERSION = '131335';
|
|
22
|
+
exports.TEXT_ITEM_TYPE = 1;
|
|
23
|
+
exports.IMAGE_ITEM_TYPE = 2;
|
|
24
|
+
exports.VOICE_ITEM_TYPE = 3;
|
|
25
|
+
exports.FILE_ITEM_TYPE = 4;
|
|
26
|
+
exports.UPLOAD_MEDIA_TYPE_FILE = 3;
|
|
27
|
+
function createWechatUin() {
|
|
28
|
+
return Buffer.from(String(node_crypto_1.default.randomInt(0, 0xffffffff))).toString('base64');
|
|
29
|
+
}
|
|
30
|
+
function createIlinkHeaders() {
|
|
31
|
+
return {
|
|
32
|
+
'iLink-App-Id': exports.WEIXIN_ILINK_APP_ID,
|
|
33
|
+
'iLink-App-ClientVersion': exports.WEIXIN_ILINK_APP_CLIENT_VERSION,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function weixinApiPost(binding, endpoint, bodyObj, timeoutMs, signal) {
|
|
37
|
+
const url = `${binding.baseUrl.replace(/\/$/, '')}/${endpoint}`;
|
|
38
|
+
const body = JSON.stringify(bodyObj);
|
|
39
|
+
const controller = new AbortController();
|
|
40
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
41
|
+
const onAbort = () => controller.abort();
|
|
42
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
43
|
+
try {
|
|
44
|
+
const headers = {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Content-Length': String(Buffer.byteLength(body, 'utf-8')),
|
|
47
|
+
'X-WECHAT-UIN': createWechatUin(),
|
|
48
|
+
...createIlinkHeaders(),
|
|
49
|
+
};
|
|
50
|
+
if (binding.token) {
|
|
51
|
+
headers.AuthorizationType = 'ilink_bot_token';
|
|
52
|
+
headers.Authorization = `Bearer ${binding.token}`;
|
|
53
|
+
}
|
|
54
|
+
const res = await fetch(url, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers,
|
|
57
|
+
body,
|
|
58
|
+
signal: controller.signal,
|
|
59
|
+
});
|
|
60
|
+
if (!res.ok)
|
|
61
|
+
throw new Error(`HTTP ${res.status}`);
|
|
62
|
+
return (await res.json());
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
signal?.removeEventListener('abort', onAbort);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function weixinApiGet(binding, endpoint, timeoutMs = exports.API_TIMEOUT_MS) {
|
|
70
|
+
const url = `${binding.baseUrl.replace(/\/$/, '')}/${endpoint}`;
|
|
71
|
+
const controller = new AbortController();
|
|
72
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
73
|
+
try {
|
|
74
|
+
const headers = createIlinkHeaders();
|
|
75
|
+
if (binding.token) {
|
|
76
|
+
headers.AuthorizationType = 'ilink_bot_token';
|
|
77
|
+
headers.Authorization = `Bearer ${binding.token}`;
|
|
78
|
+
}
|
|
79
|
+
const res = await fetch(url, {
|
|
80
|
+
method: 'GET',
|
|
81
|
+
headers,
|
|
82
|
+
signal: controller.signal,
|
|
83
|
+
});
|
|
84
|
+
if (!res.ok)
|
|
85
|
+
throw new Error(`HTTP ${res.status}`);
|
|
86
|
+
return (await res.json());
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function getWeixinUpdates(binding, buf, signal) {
|
|
93
|
+
return weixinApiPost(binding, 'ilink/bot/getupdates', { get_updates_buf: buf, base_info: { channel_version: exports.WEIXIN_CHANNEL_VERSION } }, binding.longPollTimeoutMs, signal);
|
|
94
|
+
}
|
|
95
|
+
function sendWeixinTextMessageChunk(binding, toUserId, text, contextToken, options = {}) {
|
|
96
|
+
return weixinApiPost(binding, 'ilink/bot/sendmessage', {
|
|
97
|
+
msg: {
|
|
98
|
+
from_user_id: '',
|
|
99
|
+
to_user_id: toUserId,
|
|
100
|
+
client_id: options.clientId || `openclaw-weixin-${node_crypto_1.default.randomUUID()}`,
|
|
101
|
+
message_type: 2,
|
|
102
|
+
message_state: options.final === false ? 1 : 2,
|
|
103
|
+
item_list: [{ type: exports.TEXT_ITEM_TYPE, text_item: { text } }],
|
|
104
|
+
...(contextToken ? { context_token: contextToken } : {}),
|
|
105
|
+
},
|
|
106
|
+
base_info: { channel_version: exports.WEIXIN_CHANNEL_VERSION },
|
|
107
|
+
}, exports.API_TIMEOUT_MS);
|
|
108
|
+
}
|
|
109
|
+
function sendWeixinFileMessage(binding, toUserId, fileName, uploaded, contextToken, options = {}) {
|
|
110
|
+
return weixinApiPost(binding, 'ilink/bot/sendmessage', {
|
|
111
|
+
msg: {
|
|
112
|
+
from_user_id: '',
|
|
113
|
+
to_user_id: toUserId,
|
|
114
|
+
client_id: options.clientId || `openclaw-weixin-${node_crypto_1.default.randomUUID()}`,
|
|
115
|
+
message_type: 2,
|
|
116
|
+
message_state: 2,
|
|
117
|
+
item_list: [{
|
|
118
|
+
type: exports.FILE_ITEM_TYPE,
|
|
119
|
+
file_item: {
|
|
120
|
+
media: {
|
|
121
|
+
encrypt_query_param: uploaded.encryptedQueryParam,
|
|
122
|
+
aes_key: Buffer.from(uploaded.aesKeyHex).toString('base64'),
|
|
123
|
+
encrypt_type: 1,
|
|
124
|
+
},
|
|
125
|
+
file_name: fileName,
|
|
126
|
+
len: String(uploaded.fileSize),
|
|
127
|
+
},
|
|
128
|
+
}],
|
|
129
|
+
...(contextToken ? { context_token: contextToken } : {}),
|
|
130
|
+
},
|
|
131
|
+
base_info: { channel_version: exports.WEIXIN_CHANNEL_VERSION },
|
|
132
|
+
}, exports.API_TIMEOUT_MS);
|
|
133
|
+
}
|
|
134
|
+
function getWeixinUploadUrl(binding, fileKey, toUserId, plaintextLength, rawMd5, cipherSize, aesKeyHex) {
|
|
135
|
+
return weixinApiPost(binding, 'ilink/bot/getuploadurl', {
|
|
136
|
+
filekey: fileKey,
|
|
137
|
+
media_type: exports.UPLOAD_MEDIA_TYPE_FILE,
|
|
138
|
+
to_user_id: toUserId,
|
|
139
|
+
rawsize: plaintextLength,
|
|
140
|
+
rawfilemd5: rawMd5,
|
|
141
|
+
filesize: cipherSize,
|
|
142
|
+
no_need_thumb: true,
|
|
143
|
+
aeskey: aesKeyHex,
|
|
144
|
+
base_info: { channel_version: exports.WEIXIN_CHANNEL_VERSION },
|
|
145
|
+
}, exports.API_TIMEOUT_MS);
|
|
146
|
+
}
|
|
147
|
+
async function uploadEncryptedBufferToWeixinCdn(binding, plaintext, uploadParam, fileKey, aesKey) {
|
|
148
|
+
const cipher = node_crypto_1.default.createCipheriv('aes-128-ecb', aesKey, null);
|
|
149
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
150
|
+
const url = `${binding.cdnBaseUrl.replace(/\/$/, '')}/upload?encrypted_query_param=${encodeURIComponent(uploadParam)}&filekey=${encodeURIComponent(fileKey)}`;
|
|
151
|
+
const res = await fetch(url, {
|
|
152
|
+
method: 'POST',
|
|
153
|
+
headers: {
|
|
154
|
+
'Content-Type': 'application/octet-stream',
|
|
155
|
+
},
|
|
156
|
+
body: new Uint8Array(ciphertext),
|
|
157
|
+
});
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
throw new Error(`WeChat CDN upload failed: HTTP ${res.status}`);
|
|
160
|
+
}
|
|
161
|
+
const encryptedQueryParam = res.headers.get('x-encrypted-param') || '';
|
|
162
|
+
if (!encryptedQueryParam) {
|
|
163
|
+
throw new Error('WeChat CDN upload response missing x-encrypted-param');
|
|
164
|
+
}
|
|
165
|
+
return encryptedQueryParam;
|
|
166
|
+
}
|
|
167
|
+
function isWeixinApiError(resp) {
|
|
168
|
+
return (resp.ret !== undefined && resp.ret !== 0) || (resp.errcode !== undefined && resp.errcode !== 0);
|
|
169
|
+
}
|
|
@@ -10,11 +10,20 @@ async function runCli(argv, env = node_process_1.default.env, io = node_process_
|
|
|
10
10
|
try {
|
|
11
11
|
const { positionals, flags } = parseArgs(argv);
|
|
12
12
|
const [domain = '', action = '', maybeId = ''] = positionals;
|
|
13
|
+
const json = getBooleanFlag(flags, 'json', false);
|
|
14
|
+
if (domain === 'channel') {
|
|
15
|
+
switch (action) {
|
|
16
|
+
case 'send-file':
|
|
17
|
+
return await handleChannelSendFile(flags, env, io, json);
|
|
18
|
+
default:
|
|
19
|
+
printUsage(io.stderr);
|
|
20
|
+
return 2;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
13
23
|
if (domain !== 'scheduler') {
|
|
14
24
|
printUsage(io.stderr);
|
|
15
25
|
return 2;
|
|
16
26
|
}
|
|
17
|
-
const json = getBooleanFlag(flags, 'json', false);
|
|
18
27
|
switch (action) {
|
|
19
28
|
case 'add':
|
|
20
29
|
return await handleAdd(flags, env, io, json);
|
|
@@ -39,6 +48,36 @@ async function runCli(argv, env = node_process_1.default.env, io = node_process_
|
|
|
39
48
|
return 1;
|
|
40
49
|
}
|
|
41
50
|
}
|
|
51
|
+
async function handleChannelSendFile(flags, env, io, json) {
|
|
52
|
+
const context = resolveContext(flags, env);
|
|
53
|
+
const filePath = getRequiredFlag(flags, 'path');
|
|
54
|
+
const platform = getFlag(flags, 'platform') || context.platform;
|
|
55
|
+
if (!platform) {
|
|
56
|
+
throw new Error('channel send-file requires a platform. Set LOCAL_AI_PLATFORM or pass --platform.');
|
|
57
|
+
}
|
|
58
|
+
if (!context.workspaceId) {
|
|
59
|
+
throw new Error('channel send-file requires a workspace context. Set LOCAL_AI_WORKSPACE_ID or pass --workspace.');
|
|
60
|
+
}
|
|
61
|
+
const target = getFlag(flags, 'target') || getFlag(flags, 'chat-id') || context.chatId;
|
|
62
|
+
if (!target) {
|
|
63
|
+
throw new Error('channel send-file requires a target. Set LOCAL_AI_CHAT_ID or pass --target.');
|
|
64
|
+
}
|
|
65
|
+
const result = await request(context.baseUrl, 'POST', `/platforms/${encodeURIComponent(platform)}/${encodeURIComponent(context.workspaceId)}/messages`, {
|
|
66
|
+
route: {
|
|
67
|
+
type: 'channel.chat',
|
|
68
|
+
channelId: target,
|
|
69
|
+
participantId: getFlag(flags, 'participant-id') || context.platformUserId || undefined,
|
|
70
|
+
},
|
|
71
|
+
parts: [{
|
|
72
|
+
type: 'file',
|
|
73
|
+
path: filePath,
|
|
74
|
+
fileName: getFlag(flags, 'name') || undefined,
|
|
75
|
+
}],
|
|
76
|
+
});
|
|
77
|
+
const file = result.attachments?.[0];
|
|
78
|
+
print(json, io.stdout, result, `Sent file ${file?.fileName || filePath} to ${result.channelId}: ${result.messageIds[0] || ''}`);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
42
81
|
async function handleAdd(flags, env, io, json) {
|
|
43
82
|
const cronExpr = getRequiredFlag(flags, 'cron');
|
|
44
83
|
const promptTemplate = getRequiredFlag(flags, 'message');
|
|
@@ -265,6 +304,7 @@ function printUsage(output) {
|
|
|
265
304
|
' lac scheduler edit <job-id> [--cron "<expr>"] [--message "<text>"] [--desc "<label>"] [--enabled true|false] [--execution-mode same-thread|side-thread] [--json]',
|
|
266
305
|
' lac scheduler del <job-id> [--json]',
|
|
267
306
|
' lac scheduler run <job-id> [--json]',
|
|
307
|
+
' lac channel send-file --path "<file>" [--target <chat-or-user-id>] [--workspace <id>] [--platform lark] [--name <filename>] [--json]',
|
|
268
308
|
].join('\n') + '\n');
|
|
269
309
|
}
|
|
270
310
|
function formatJobLine(job) {
|
|
@@ -220,6 +220,10 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
220
220
|
.map((plugin) => resolveAgentRuntime(plugin, kernel.context).runtime);
|
|
221
221
|
const channelRuntime = resolveChannelRuntime(channelPlugin, kernel.context).channel;
|
|
222
222
|
weixinChannelRuntime = resolveChannelRuntime(weixinChannelPlugin, kernel.context).channel;
|
|
223
|
+
const channelRuntimes = [
|
|
224
|
+
channelRuntime,
|
|
225
|
+
weixinChannelRuntime,
|
|
226
|
+
];
|
|
223
227
|
const knowledgeRuntime = kernel.plugins.isEnabled(knowledgePlugin.manifest.id)
|
|
224
228
|
? resolveKnowledgeRuntime(knowledgePlugin, kernel.context)
|
|
225
229
|
: resolveKnowledgeRuntime((0, knowledge_noop_plugin_js_1.createBuiltinNoopKnowledgePlugin)(), kernel.context);
|
|
@@ -278,6 +282,7 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
278
282
|
state,
|
|
279
283
|
store,
|
|
280
284
|
agentRuntimes,
|
|
285
|
+
channelRuntimes,
|
|
281
286
|
channelRuntime,
|
|
282
287
|
weixinChannelRuntime,
|
|
283
288
|
knowledgeProvider,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createBuiltinLarkChannelPlugin = createBuiltinLarkChannelPlugin;
|
|
4
|
-
const local_core_lark_gateway_js_1 = require("../../
|
|
4
|
+
const local_core_lark_gateway_js_1 = require("../../channel/lark/local-core-lark-gateway.js");
|
|
5
|
+
const plugin_js_1 = require("../../channel/shared/plugin.js");
|
|
5
6
|
function createBuiltinLarkChannelPlugin(options) {
|
|
6
|
-
|
|
7
|
-
let unsubscribeBridgeEvents = null;
|
|
8
|
-
return {
|
|
7
|
+
return (0, plugin_js_1.createBuiltinChannelPlugin)({
|
|
9
8
|
manifest: {
|
|
10
9
|
id: 'builtin.channel-lark',
|
|
11
10
|
kind: 'channel',
|
|
@@ -20,40 +19,20 @@ function createBuiltinLarkChannelPlugin(options) {
|
|
|
20
19
|
],
|
|
21
20
|
},
|
|
22
21
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
40
|
-
eventBus: ctx.bus,
|
|
41
|
-
log: options.log,
|
|
42
|
-
}),
|
|
43
|
-
};
|
|
44
|
-
unsubscribeBridgeEvents = ctx.bus.on('platform.bridge.updated', (event) => {
|
|
45
|
-
void runtime?.channel.onBridgeEvent?.(event);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
return runtime;
|
|
49
|
-
},
|
|
50
|
-
async start() {
|
|
51
|
-
await runtime?.channel.refreshBindings?.();
|
|
52
|
-
},
|
|
53
|
-
async stop() {
|
|
54
|
-
unsubscribeBridgeEvents?.();
|
|
55
|
-
unsubscribeBridgeEvents = null;
|
|
56
|
-
runtime?.channel.close?.();
|
|
57
|
-
},
|
|
58
|
-
};
|
|
22
|
+
channels: [
|
|
23
|
+
{
|
|
24
|
+
id: 'channel.lark',
|
|
25
|
+
platform: 'lark',
|
|
26
|
+
routeType: 'channel.chat',
|
|
27
|
+
displayName: 'LocalCore Lark',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
createChannel: (ctx) => new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
|
|
31
|
+
store: options.store,
|
|
32
|
+
readConfig: options.readConfig,
|
|
33
|
+
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
34
|
+
eventBus: ctx.bus,
|
|
35
|
+
log: options.log,
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
59
38
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createBuiltinWeixinChannelPlugin = createBuiltinWeixinChannelPlugin;
|
|
4
|
-
const local_core_weixin_gateway_js_1 = require("../../
|
|
4
|
+
const local_core_weixin_gateway_js_1 = require("../../channel/weixin/local-core-weixin-gateway.js");
|
|
5
|
+
const plugin_js_1 = require("../../channel/shared/plugin.js");
|
|
5
6
|
function createBuiltinWeixinChannelPlugin(options) {
|
|
6
|
-
|
|
7
|
-
let unsubscribeBridgeEvents = null;
|
|
8
|
-
return {
|
|
7
|
+
return (0, plugin_js_1.createBuiltinChannelPlugin)({
|
|
9
8
|
manifest: {
|
|
10
9
|
id: 'builtin.channel-weixin',
|
|
11
10
|
kind: 'channel',
|
|
@@ -17,40 +16,20 @@ function createBuiltinWeixinChannelPlugin(options) {
|
|
|
17
16
|
fields: [],
|
|
18
17
|
},
|
|
19
18
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
37
|
-
eventBus: ctx.bus,
|
|
38
|
-
log: options.log,
|
|
39
|
-
}),
|
|
40
|
-
};
|
|
41
|
-
unsubscribeBridgeEvents = ctx.bus.on('platform.bridge.updated', (event) => {
|
|
42
|
-
void runtime?.channel.onBridgeEvent?.(event);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return runtime;
|
|
46
|
-
},
|
|
47
|
-
async start() {
|
|
48
|
-
await runtime?.channel.refreshBindings?.();
|
|
49
|
-
},
|
|
50
|
-
async stop() {
|
|
51
|
-
unsubscribeBridgeEvents?.();
|
|
52
|
-
unsubscribeBridgeEvents = null;
|
|
53
|
-
runtime?.channel.close?.();
|
|
54
|
-
},
|
|
55
|
-
};
|
|
19
|
+
channels: [
|
|
20
|
+
{
|
|
21
|
+
id: 'channel.weixin',
|
|
22
|
+
platform: 'weixin',
|
|
23
|
+
routeType: 'channel.chat',
|
|
24
|
+
displayName: 'LocalCore WeChat',
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
createChannel: (ctx) => new local_core_weixin_gateway_js_1.LocalCoreWeixinGateway({
|
|
28
|
+
store: options.store,
|
|
29
|
+
readConfig: options.readConfig,
|
|
30
|
+
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
31
|
+
eventBus: ctx.bus,
|
|
32
|
+
log: options.log,
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
56
35
|
}
|
|
@@ -10,8 +10,7 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
10
10
|
state;
|
|
11
11
|
workspaceRouter;
|
|
12
12
|
knowledgeProvider;
|
|
13
|
-
|
|
14
|
-
weixinChannelRuntime;
|
|
13
|
+
channelRuntimes;
|
|
15
14
|
scheduler;
|
|
16
15
|
kernel;
|
|
17
16
|
runtime;
|
|
@@ -31,8 +30,8 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
31
30
|
this.kernel = this.runtime.kernel;
|
|
32
31
|
this.knowledgeProvider = this.runtime.knowledgeProvider;
|
|
33
32
|
this.workspaceRouter = this.runtime.workspaceRouter;
|
|
34
|
-
this.
|
|
35
|
-
this.
|
|
33
|
+
const runtimeChannels = this.runtime.channelRuntimes || [this.runtime.channelRuntime, this.runtime.weixinChannelRuntime];
|
|
34
|
+
this.channelRuntimes = new Map(runtimeChannels.filter(Boolean).map((runtime) => [runtime.platform, runtime]));
|
|
36
35
|
this.scheduler = this.runtime.scheduler;
|
|
37
36
|
this.runtimeDetection = new runtime_detection_service_js_1.RuntimeDetectionService({
|
|
38
37
|
userDataPath,
|
|
@@ -99,8 +98,7 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
99
98
|
return { status: 'running' };
|
|
100
99
|
}
|
|
101
100
|
async restartService() {
|
|
102
|
-
await this.
|
|
103
|
-
await this.weixinChannelRuntime.refreshBindings?.();
|
|
101
|
+
await this.refreshChannelBindings();
|
|
104
102
|
await this.emitRuntime();
|
|
105
103
|
return { status: 'running' };
|
|
106
104
|
}
|
|
@@ -112,22 +110,19 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
112
110
|
}
|
|
113
111
|
async saveRawConfigFile(raw) {
|
|
114
112
|
const next = await this.state.saveRawConfigFile(raw);
|
|
115
|
-
await this.
|
|
116
|
-
await this.weixinChannelRuntime.refreshBindings?.();
|
|
113
|
+
await this.refreshChannelBindings();
|
|
117
114
|
await this.emitRuntime();
|
|
118
115
|
return next;
|
|
119
116
|
}
|
|
120
117
|
async saveStructuredConfigFile(config) {
|
|
121
118
|
const next = await this.state.saveStructuredConfigFile(config);
|
|
122
|
-
await this.
|
|
123
|
-
await this.weixinChannelRuntime.refreshBindings?.();
|
|
119
|
+
await this.refreshChannelBindings();
|
|
124
120
|
await this.emitRuntime();
|
|
125
121
|
return next;
|
|
126
122
|
}
|
|
127
123
|
async saveSettings(input) {
|
|
128
124
|
const settings = await this.state.saveSettings(input);
|
|
129
|
-
await this.
|
|
130
|
-
await this.weixinChannelRuntime.refreshBindings?.();
|
|
125
|
+
await this.refreshChannelBindings();
|
|
131
126
|
await this.emitRuntime();
|
|
132
127
|
return settings;
|
|
133
128
|
}
|
|
@@ -311,25 +306,22 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
311
306
|
}
|
|
312
307
|
async listChannelGatewayStatuses(platform) {
|
|
313
308
|
if (!platform) {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
this.weixinChannelRuntime.listStatuses(),
|
|
317
|
-
]);
|
|
318
|
-
return [...larkStatuses, ...weixinStatuses];
|
|
309
|
+
const statuses = await Promise.all([...this.channelRuntimes.values()].map((runtime) => runtime.listStatuses()));
|
|
310
|
+
return statuses.flat();
|
|
319
311
|
}
|
|
320
312
|
return this.resolveChannelRuntime(platform).listStatuses();
|
|
321
313
|
}
|
|
322
|
-
async getChannelGatewayStatus(platform, workspaceId) {
|
|
323
|
-
return this.resolveChannelRuntime(platform).getStatus(workspaceId);
|
|
314
|
+
async getChannelGatewayStatus(platform, workspaceId, instanceId) {
|
|
315
|
+
return this.resolveChannelRuntime(platform).getStatus(workspaceId, instanceId);
|
|
324
316
|
}
|
|
325
|
-
async testChannelConnection(platform, workspaceId) {
|
|
326
|
-
return this.resolveChannelRuntime(platform).testConnection(workspaceId);
|
|
317
|
+
async testChannelConnection(platform, workspaceId, instanceId) {
|
|
318
|
+
return this.resolveChannelRuntime(platform).testConnection(workspaceId, instanceId);
|
|
327
319
|
}
|
|
328
|
-
async enableChannelGateway(platform, workspaceId) {
|
|
329
|
-
return this.resolveChannelRuntime(platform).enable(workspaceId);
|
|
320
|
+
async enableChannelGateway(platform, workspaceId, instanceId) {
|
|
321
|
+
return this.resolveChannelRuntime(platform).enable(workspaceId, instanceId);
|
|
330
322
|
}
|
|
331
|
-
async disableChannelGateway(platform, workspaceId) {
|
|
332
|
-
return this.resolveChannelRuntime(platform).disable(workspaceId);
|
|
323
|
+
async disableChannelGateway(platform, workspaceId, instanceId) {
|
|
324
|
+
return this.resolveChannelRuntime(platform).disable(workspaceId, instanceId);
|
|
333
325
|
}
|
|
334
326
|
async listChannelPendingPairings(platform, workspaceId) {
|
|
335
327
|
return this.resolveChannelRuntime(platform).listPendingPairings(workspaceId);
|
|
@@ -343,28 +335,87 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
343
335
|
async listChannelAuthorizedUsers(platform, workspaceId) {
|
|
344
336
|
return this.resolveChannelRuntime(platform).listAuthorizedUsers(workspaceId);
|
|
345
337
|
}
|
|
346
|
-
async
|
|
347
|
-
const runtime = this.
|
|
348
|
-
|
|
338
|
+
async sendChannelFile(platform, workspaceId, input) {
|
|
339
|
+
const runtime = this.resolveChannelRuntime(platform);
|
|
340
|
+
if (runtime.sendOutboundMessage) {
|
|
341
|
+
const result = await runtime.sendOutboundMessage(workspaceId, {
|
|
342
|
+
route: {
|
|
343
|
+
type: 'channel.chat',
|
|
344
|
+
channelId: input.channelId,
|
|
345
|
+
participantId: input.participantId,
|
|
346
|
+
},
|
|
347
|
+
parts: [{
|
|
348
|
+
type: 'file',
|
|
349
|
+
path: input.path,
|
|
350
|
+
fileName: input.fileName,
|
|
351
|
+
}],
|
|
352
|
+
});
|
|
353
|
+
const attachment = result.attachments?.[0];
|
|
354
|
+
return {
|
|
355
|
+
platform: result.platform,
|
|
356
|
+
workspaceId: result.workspaceId,
|
|
357
|
+
channelId: result.channelId,
|
|
358
|
+
messageId: result.messageIds[0] || '',
|
|
359
|
+
messageIds: result.messageIds,
|
|
360
|
+
fileKey: String(attachment?.metadata?.fileKey || attachment?.attachmentId || ''),
|
|
361
|
+
attachmentId: attachment?.attachmentId,
|
|
362
|
+
fileName: attachment?.fileName || input.fileName || '',
|
|
363
|
+
fileSize: attachment?.fileSize || 0,
|
|
364
|
+
metadata: result.metadata,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
if (!runtime.sendFile) {
|
|
368
|
+
throw new Error(`Channel platform does not support sending files: ${platform}`);
|
|
369
|
+
}
|
|
370
|
+
return runtime.sendFile(workspaceId, input);
|
|
371
|
+
}
|
|
372
|
+
async sendChannelMessage(platform, workspaceId, input) {
|
|
373
|
+
const runtime = this.resolveChannelRuntime(platform);
|
|
374
|
+
if (!runtime.sendOutboundMessage) {
|
|
375
|
+
throw new Error(`Channel platform does not support outbound messages: ${platform}`);
|
|
376
|
+
}
|
|
377
|
+
return runtime.sendOutboundMessage(workspaceId, input);
|
|
378
|
+
}
|
|
379
|
+
async getWeixinQrCode(workspaceId, instanceId) {
|
|
380
|
+
return this.getChannelQrCode('weixin', workspaceId, instanceId);
|
|
381
|
+
}
|
|
382
|
+
async checkWeixinQrCodeStatus(workspaceId, ticket, instanceId) {
|
|
383
|
+
return this.checkChannelQrCodeStatus('weixin', workspaceId, ticket, instanceId);
|
|
384
|
+
}
|
|
385
|
+
async getLarkQrCode(workspaceId, instanceId) {
|
|
386
|
+
return this.getChannelQrCode('lark', workspaceId, instanceId);
|
|
349
387
|
}
|
|
350
|
-
async
|
|
351
|
-
|
|
352
|
-
|
|
388
|
+
async checkLarkQrCodeStatus(workspaceId, ticket, instanceId) {
|
|
389
|
+
return this.checkChannelQrCodeStatus('lark', workspaceId, ticket, instanceId);
|
|
390
|
+
}
|
|
391
|
+
async getChannelQrCode(platform, workspaceId, instanceId) {
|
|
392
|
+
const runtime = this.resolveChannelRuntime(platform);
|
|
393
|
+
if (!runtime.getQrCode) {
|
|
394
|
+
throw new Error(`Channel platform does not support QR setup: ${platform}`);
|
|
395
|
+
}
|
|
396
|
+
return runtime.getQrCode(workspaceId, instanceId);
|
|
397
|
+
}
|
|
398
|
+
async checkChannelQrCodeStatus(platform, workspaceId, ticket, instanceId) {
|
|
399
|
+
const runtime = this.resolveChannelRuntime(platform);
|
|
400
|
+
if (!runtime.checkQrCodeStatus) {
|
|
401
|
+
throw new Error(`Channel platform does not support QR setup: ${platform}`);
|
|
402
|
+
}
|
|
403
|
+
return runtime.checkQrCodeStatus(workspaceId, ticket, instanceId);
|
|
353
404
|
}
|
|
354
405
|
async listLarkGatewayStatuses() {
|
|
355
406
|
return this.listChannelGatewayStatuses('lark');
|
|
356
407
|
}
|
|
357
|
-
async getLarkGatewayStatus(workspaceId) {
|
|
358
|
-
return this.getChannelGatewayStatus('lark', workspaceId);
|
|
408
|
+
async getLarkGatewayStatus(workspaceId, instanceId) {
|
|
409
|
+
return this.getChannelGatewayStatus('lark', workspaceId, instanceId);
|
|
359
410
|
}
|
|
360
|
-
async testLarkConnection(workspaceId) {
|
|
361
|
-
return this.testChannelConnection('lark', workspaceId);
|
|
411
|
+
async testLarkConnection(workspaceId, instanceId) {
|
|
412
|
+
return this.testChannelConnection('lark', workspaceId, instanceId);
|
|
362
413
|
}
|
|
363
|
-
async enableLarkGateway(workspaceId) {
|
|
364
|
-
return this.enableChannelGateway('lark', workspaceId);
|
|
414
|
+
async enableLarkGateway(workspaceId, instanceId) {
|
|
415
|
+
return this.enableChannelGateway('lark', workspaceId, instanceId);
|
|
365
416
|
}
|
|
366
|
-
async disableLarkGateway(workspaceId) {
|
|
367
|
-
return this.disableChannelGateway('lark', workspaceId);
|
|
417
|
+
async disableLarkGateway(workspaceId, instanceId) {
|
|
418
|
+
return this.disableChannelGateway('lark', workspaceId, instanceId);
|
|
368
419
|
}
|
|
369
420
|
async listLarkPendingPairings(workspaceId) {
|
|
370
421
|
return this.listChannelPendingPairings('lark', workspaceId);
|
|
@@ -418,12 +469,13 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
418
469
|
this.handlingLog = false;
|
|
419
470
|
}
|
|
420
471
|
}
|
|
472
|
+
async refreshChannelBindings() {
|
|
473
|
+
await Promise.all([...this.channelRuntimes.values()].map((runtime) => runtime.refreshBindings?.()));
|
|
474
|
+
}
|
|
421
475
|
resolveChannelRuntime(platform) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (platform === this.weixinChannelRuntime.platform) {
|
|
426
|
-
return this.weixinChannelRuntime;
|
|
476
|
+
const runtime = this.channelRuntimes.get(platform);
|
|
477
|
+
if (runtime) {
|
|
478
|
+
return runtime;
|
|
427
479
|
}
|
|
428
480
|
throw new Error(`Unsupported channel platform: ${platform}`);
|
|
429
481
|
}
|