@kafca/agentdock 0.1.42 → 0.1.43
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 +4 -0
- package/dist/renderer/assets/{Badge-D-WU4kUV.js → Badge-CbG6yRSm.js} +1 -1
- package/dist/renderer/assets/{Chat-BGkC5tAe.js → Chat-BvNNWGGX.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-CfbC1jRd.js → ChatMarkdown-Ct-PvJB8.js} +1 -1
- package/dist/renderer/assets/{Config-qQb4bX5D.js → Config-lQX2qVVV.js} +2 -2
- package/dist/renderer/assets/CronList-Dj_3muVG.js +1 -0
- package/dist/renderer/assets/{Dashboard-xn6cUy_n.js → Dashboard-eh_RhGYb.js} +2 -2
- package/dist/renderer/assets/{EmptyState-BdKBBUpr.js → EmptyState-Bn2Qh14U.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-Duk8IQP3.js → KnowledgeDetail-Bsz6Ou41.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BfjX_4Sv.js → KnowledgeHome-Cgj4XFXn.js} +2 -2
- package/dist/renderer/assets/{Logs-Bfq61QMn.js → Logs-Dp-NF6GN.js} +1 -1
- package/dist/renderer/assets/{Modal-B3vlBmBr.js → Modal-B6YPPBN6.js} +1 -1
- package/dist/renderer/assets/MonitorList-xEZWg460.js +1 -0
- package/dist/renderer/assets/{Page-CPsLOP3z.js → Page-Bn7RjGOS.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-D-g46wyF.js → ProjectDetail-Cv_jIE61.js} +2 -2
- package/dist/renderer/assets/{ProjectList-BrQEKDQ8.js → ProjectList-BDk5_gqY.js} +1 -1
- package/dist/renderer/assets/{Select-C4CFMQmF.js → Select-xshfMIEQ.js} +1 -1
- package/dist/renderer/assets/SessionChat-BkHy90z3.js +1 -0
- package/dist/renderer/assets/{SessionList-DPWIUbOg.js → SessionList-BZyXT92L.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-BjtU-j9q.js → ThreadChat-DUOIyXrS.js} +7 -7
- package/dist/renderer/assets/{Workspace-BcNmHuJx.js → Workspace-Dl80fNEC.js} +1 -1
- package/dist/renderer/assets/{arrow-left-DPzSmidS.js → arrow-left-C54ZI-AS.js} +1 -1
- package/dist/renderer/assets/{book-open-B0xhoRqZ.js → book-open-Dl7GO0zn.js} +1 -1
- package/dist/renderer/assets/{check-BTJTyd0C.js → check-CiqgtrOL.js} +1 -1
- package/dist/renderer/assets/{chevron-down-B6jJXlhi.js → chevron-down-DTL2OuVh.js} +1 -1
- package/dist/renderer/assets/{circle-qRhJR9qR.js → circle-DaVKfa3P.js} +1 -1
- package/dist/renderer/assets/desktop-C6q6wBae.js +5 -0
- package/dist/renderer/assets/desktop-jaAiayNB.js +1 -0
- package/dist/renderer/assets/en-D2SkCrhG.js +1 -0
- package/dist/renderer/assets/{funnel-CbYKGTn8.js → funnel-CrmnLMJI.js} +1 -1
- package/dist/renderer/assets/{heart-DjwWJfkz.js → heart-BMfQI7y_.js} +1 -1
- package/dist/renderer/assets/{index-BWmHJRhe.js → index-HPNb1zfx.js} +39 -34
- package/dist/renderer/assets/{index-CyZs_2NJ.js → index-nreiKY1f.js} +3 -3
- package/dist/renderer/assets/{pencil-1dfAivmj.js → pencil-wTQ4l465.js} +1 -1
- package/dist/renderer/assets/{play-CB3w1G6S.js → play-BK--MXmw.js} +1 -1
- package/dist/renderer/assets/{plug-Bvep5o3r.js → plug-BIx9fjip.js} +1 -1
- package/dist/renderer/assets/{plus-DJVg9m09.js → plus-Dn7JFWQ8.js} +1 -1
- package/dist/renderer/assets/projects-brJZgwEJ.js +1 -0
- package/dist/renderer/assets/{save-xjJn3qf2.js → save-CC3zOSWb.js} +1 -1
- package/dist/renderer/assets/{search-BK3UrQxM.js → search-CDTy9Czu.js} +1 -1
- package/dist/renderer/assets/{server-Dyd2eXJu.js → server-DtQk3t2a.js} +1 -1
- package/dist/renderer/assets/{session-utils-eXC0020s.js → session-utils-4ep5D66T.js} +1 -1
- package/dist/renderer/assets/{sessions-WLYpkyUt.js → sessions-Dor1LteH.js} +1 -1
- package/dist/renderer/assets/{shield-check-C0N6aWzF.js → shield-check-Cz2LpU6r.js} +1 -1
- package/dist/renderer/assets/{trash-2-BGMTNJA6.js → trash-2-C2EmWFZV.js} +1 -1
- package/dist/renderer/assets/{user-BcGMLyhu.js → user-I8B-cs5A.js} +1 -1
- package/dist/renderer/assets/{wifi-off-FhcQx0HK.js → wifi-off-CPevTQJn.js} +1 -1
- package/dist/renderer/assets/zh-DIcdHycM.js +1 -0
- package/dist/renderer/index.html +1 -1
- package/dist-electron/packages/contracts/src/local-core.js +28 -0
- package/dist-electron/packages/core-sdk/src/index.js +32 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +51 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +4 -1364
- package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +166 -0
- package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +231 -0
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +263 -0
- package/dist-electron/services/local-ai-core/src/acp/store/platform-store.js +186 -0
- package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +201 -0
- package/dist-electron/services/local-ai-core/src/acp/store/schema.js +275 -0
- package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +266 -0
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +232 -0
- package/dist-electron/services/local-ai-core/src/acp/store/utils.js +47 -0
- package/dist-electron/services/local-ai-core/src/acp/store/workspace-registry-store.js +109 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +136 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-repository.js +56 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +359 -0
- package/dist-electron/services/local-ai-core/src/automation/condition-evaluator.js +77 -0
- package/dist-electron/services/local-ai-core/src/automation/mock-stock-provider.js +40 -0
- package/dist-electron/services/local-ai-core/src/automation/monitor-id.js +10 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +55 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +101 -29
- package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +53 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +51 -33
- package/dist-electron/services/local-ai-core/src/cli/lac.js +196 -0
- package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +37 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +43 -0
- package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +12 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/monitor-stock-plugin.js +30 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +41 -0
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +31 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +36 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-bridge-session.js +25 -11
- package/dist-electron/services/local-ai-core/src/thread/session-command-service.js +275 -0
- package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +27 -0
- package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +15 -15
- package/dist-electron/shared/desktop.js +21 -1
- package/dist-electron/tests/contracts/local-core-contracts.test.js +9 -0
- package/dist-electron/tests/electron/automation-monitor.test.js +38 -0
- package/dist-electron/tests/electron/lac-cli.test.js +146 -0
- package/dist-electron/tests/integration/local-core-refactor.test.js +194 -0
- package/package.json +1 -1
- package/dist/renderer/assets/CronList-CKhggzYk.js +0 -1
- package/dist/renderer/assets/SessionChat-06Jny5_G.js +0 -1
- package/dist/renderer/assets/desktop-DXmXjjUR.js +0 -1
- package/dist/renderer/assets/desktop-O8_6ZCVZ.js +0 -4
- package/dist/renderer/assets/en-CKhCF6St.js +0 -1
- package/dist/renderer/assets/projects-xnW0fTtq.js +0 -1
- package/dist/renderer/assets/zh-Dz5FLTBV.js +0 -1
|
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.buildInteractiveCard = buildInteractiveCard;
|
|
4
4
|
exports.renderPermissionCard = renderPermissionCard;
|
|
5
5
|
exports.renderPendingPairingCard = renderPendingPairingCard;
|
|
6
|
+
exports.buildSessionCommandCard = buildSessionCommandCard;
|
|
6
7
|
exports.extractCardActionMessageId = extractCardActionMessageId;
|
|
7
8
|
exports.extractCardActionValue = extractCardActionValue;
|
|
9
|
+
exports.extractSessionCommandActionValue = extractSessionCommandActionValue;
|
|
8
10
|
exports.formatPermissionButtonLabel = formatPermissionButtonLabel;
|
|
9
11
|
exports.formatPermissionResponseLabel = formatPermissionResponseLabel;
|
|
10
12
|
const desktop_js_1 = require("../../../../../shared/desktop.js");
|
|
@@ -80,6 +82,37 @@ function renderPendingPairingCard(code) {
|
|
|
80
82
|
}
|
|
81
83
|
return lines.join('\n\n');
|
|
82
84
|
}
|
|
85
|
+
function buildSessionCommandCard(text, actionRows = [], sessionKey, threadId) {
|
|
86
|
+
const elements = [];
|
|
87
|
+
if (text) {
|
|
88
|
+
elements.push({ tag: 'markdown', content: text });
|
|
89
|
+
}
|
|
90
|
+
for (const row of actionRows) {
|
|
91
|
+
const actions = row
|
|
92
|
+
.filter((button) => button.label && button.command)
|
|
93
|
+
.map((button) => ({
|
|
94
|
+
tag: 'button',
|
|
95
|
+
text: {
|
|
96
|
+
tag: 'plain_text',
|
|
97
|
+
content: button.label,
|
|
98
|
+
},
|
|
99
|
+
type: button.type || 'default',
|
|
100
|
+
value: {
|
|
101
|
+
action: 'session_command',
|
|
102
|
+
command: button.command,
|
|
103
|
+
session_key: sessionKey || '',
|
|
104
|
+
thread_id: threadId || '',
|
|
105
|
+
},
|
|
106
|
+
}));
|
|
107
|
+
if (actions.length) {
|
|
108
|
+
elements.push({ tag: 'action', actions });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
config: { wide_screen_mode: true },
|
|
113
|
+
elements,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
83
116
|
function extractCardActionMessageId(...payloads) {
|
|
84
117
|
for (const payload of payloads) {
|
|
85
118
|
const messageId = extractKnownCardActionMessageId(payload);
|
|
@@ -117,6 +150,28 @@ function extractCardActionValue(payload) {
|
|
|
117
150
|
sessionKey,
|
|
118
151
|
};
|
|
119
152
|
}
|
|
153
|
+
function extractSessionCommandActionValue(payload) {
|
|
154
|
+
const event = (payload?.event && typeof payload.event === 'object')
|
|
155
|
+
? payload.event
|
|
156
|
+
: payload;
|
|
157
|
+
const value = event?.action?.value;
|
|
158
|
+
if (!value || value.action !== 'session_command') {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const command = String(value.command || '').trim();
|
|
162
|
+
const threadId = String(value.thread_id || '').trim();
|
|
163
|
+
const sessionKey = String(value.session_key || '').trim();
|
|
164
|
+
if (!command || !threadId) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
event,
|
|
169
|
+
value: value,
|
|
170
|
+
command,
|
|
171
|
+
threadId,
|
|
172
|
+
sessionKey,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
120
175
|
function formatPermissionButtonLabel(button) {
|
|
121
176
|
return formatPermissionResponseLabel(button.data || button.text);
|
|
122
177
|
}
|
|
@@ -41,11 +41,13 @@ const node_path_1 = require("node:path");
|
|
|
41
41
|
const desktop_js_1 = require("../../../../../shared/desktop.js");
|
|
42
42
|
const content_js_1 = require("../shared/content.js");
|
|
43
43
|
const file_utils_js_1 = require("../shared/file-utils.js");
|
|
44
|
+
const session_command_runtime_js_1 = require("../shared/session-command-runtime.js");
|
|
44
45
|
const cards_js_1 = require("./cards.js");
|
|
45
46
|
const config_js_1 = require("./config.js");
|
|
46
47
|
const registration_js_1 = require("./registration.js");
|
|
47
48
|
const messages_js_1 = require("./rendering/messages.js");
|
|
48
49
|
const runtime_state_js_1 = require("./runtime-state.js");
|
|
50
|
+
const session_command_service_js_1 = require("../../thread/session-command-service.js");
|
|
49
51
|
const PAIRING_EXPIRY_MS = 10 * 60 * 1000;
|
|
50
52
|
const LARK_MAX_UPLOAD_FILE_SIZE = 30 * 1024 * 1024;
|
|
51
53
|
const LARK_FINAL_PATCH_INTERVAL_MS = 900;
|
|
@@ -62,12 +64,37 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
|
|
|
62
64
|
outboundEventChains = new Map();
|
|
63
65
|
outboundTurns = new Map();
|
|
64
66
|
mutedThreadBridgeCounts = new Map();
|
|
67
|
+
sessionCommandRuntime;
|
|
65
68
|
larkModulePromise = null;
|
|
66
69
|
platform = 'lark';
|
|
67
70
|
routeType = 'channel.chat';
|
|
68
71
|
constructor(options) {
|
|
69
72
|
super();
|
|
70
73
|
this.options = options;
|
|
74
|
+
const sessionCommandService = new session_command_service_js_1.SessionCommandService({
|
|
75
|
+
listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
|
|
76
|
+
getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
|
|
77
|
+
createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
|
|
78
|
+
renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
|
|
79
|
+
deleteThread: (threadId) => this.options.getWorkspaceRouter().deleteThread(threadId),
|
|
80
|
+
});
|
|
81
|
+
this.sessionCommandRuntime = new session_command_runtime_js_1.ChannelSessionCommandRuntime({
|
|
82
|
+
service: sessionCommandService,
|
|
83
|
+
store: this.options.store,
|
|
84
|
+
getThreadSessionKey: (threadId) => this.options.getWorkspaceRouter().getThreadSessionKey(threadId),
|
|
85
|
+
setThreadRoute: (sessionKey, route) => {
|
|
86
|
+
this.threadRouting.set(sessionKey, route);
|
|
87
|
+
},
|
|
88
|
+
createRoute: (input, threadId) => ({
|
|
89
|
+
workspaceId: input.workspaceId,
|
|
90
|
+
instanceId: input.instanceId,
|
|
91
|
+
platformKey: input.platformKey,
|
|
92
|
+
platformUserId: input.platformUserId,
|
|
93
|
+
chatId: input.chatId,
|
|
94
|
+
threadId,
|
|
95
|
+
}),
|
|
96
|
+
sendResult: (input, result) => this.sendSessionCommandResult(input, result),
|
|
97
|
+
});
|
|
71
98
|
}
|
|
72
99
|
async refreshBindings() {
|
|
73
100
|
const config = await this.options.readConfig();
|
|
@@ -204,6 +231,17 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
|
|
|
204
231
|
}
|
|
205
232
|
};
|
|
206
233
|
}
|
|
234
|
+
async executeSessionCommand(input) {
|
|
235
|
+
return this.sessionCommandRuntime.execute(input);
|
|
236
|
+
}
|
|
237
|
+
async sendSessionCommandResult(input, result) {
|
|
238
|
+
const state = this.resolveRuntimeState(input.workspaceId, input.instanceId).state;
|
|
239
|
+
if (state?.client && state.connected && result.card?.actions?.length && state.cardActionsEnabled) {
|
|
240
|
+
await this.sendSessionCommandCard(state, input.chatId, result.displayText, result.card.actions, this.options.getWorkspaceRouter().getThreadSessionKey(input.currentThreadId), input.currentThreadId);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
await this.sendImmediateCard(input.workspaceId, input.chatId, result.displayText, input.instanceId);
|
|
244
|
+
}
|
|
207
245
|
async sendOutboundMessage(workspaceId, input) {
|
|
208
246
|
const state = this.resolveRuntimeState(workspaceId, input.route?.instanceId).state;
|
|
209
247
|
if (!state?.client || !state.connected) {
|
|
@@ -659,35 +697,18 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
|
|
|
659
697
|
const acknowledgement = this.createTurnState(effectiveSessionKey, input.messageId);
|
|
660
698
|
await this.addAcknowledgementReaction(input.workspaceId, input.messageId, acknowledgement, instanceId);
|
|
661
699
|
const slashCommand = this.parseSlashCommand(input.text);
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
chat_id: input.chatId,
|
|
675
|
-
platform_user_id: input.platformUserId,
|
|
676
|
-
thread_id: nextThread.id,
|
|
677
|
-
last_platform_message_id: null,
|
|
678
|
-
created_at: now,
|
|
679
|
-
updated_at: now,
|
|
680
|
-
});
|
|
681
|
-
this.threadRouting.set(this.options.getWorkspaceRouter().getThreadSessionKey(nextThread.id), {
|
|
682
|
-
workspaceId: input.workspaceId,
|
|
683
|
-
instanceId,
|
|
684
|
-
platformKey,
|
|
685
|
-
platformUserId: input.platformUserId,
|
|
686
|
-
chatId: input.chatId,
|
|
687
|
-
threadId: nextThread.id,
|
|
688
|
-
});
|
|
689
|
-
await this.sendImmediateCard(input.workspaceId, input.chatId, '**已开始新会话**', instanceId);
|
|
690
|
-
return { paired: true, threadId: nextThread.id };
|
|
700
|
+
const sessionCommand = await this.executeSessionCommand({
|
|
701
|
+
workspaceId: input.workspaceId,
|
|
702
|
+
currentThreadId: threadId,
|
|
703
|
+
text: input.text,
|
|
704
|
+
defaultTitle: `${input.displayName || 'Lark'} ${new Date().toLocaleTimeString()}`,
|
|
705
|
+
chatId: input.chatId,
|
|
706
|
+
platformUserId: input.platformUserId,
|
|
707
|
+
platformKey,
|
|
708
|
+
instanceId,
|
|
709
|
+
});
|
|
710
|
+
if (sessionCommand.handled) {
|
|
711
|
+
return { paired: true, threadId: sessionCommand.threadId || threadId };
|
|
691
712
|
}
|
|
692
713
|
const latestRun = this.options.store.getLatestRunForThread(threadId);
|
|
693
714
|
if ((normalizedText === 'allow' || normalizedText === 'allow all' || normalizedText === 'deny')
|
|
@@ -1157,6 +1178,21 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
|
|
|
1157
1178
|
this.options.log?.(`localcore-lark card create took ${Date.now() - startedAt}ms textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
|
|
1158
1179
|
return String(response?.data?.message_id || '').trim();
|
|
1159
1180
|
}
|
|
1181
|
+
async sendSessionCommandCard(state, chatId, text, actionRows, sessionKey, threadId) {
|
|
1182
|
+
const startedAt = Date.now();
|
|
1183
|
+
const response = await state.client.im.message.create({
|
|
1184
|
+
params: {
|
|
1185
|
+
receive_id_type: this.resolveReceiveIdType(chatId),
|
|
1186
|
+
},
|
|
1187
|
+
data: {
|
|
1188
|
+
receive_id: chatId,
|
|
1189
|
+
msg_type: 'interactive',
|
|
1190
|
+
content: JSON.stringify((0, cards_js_1.buildSessionCommandCard)(text, actionRows, sessionKey, threadId)),
|
|
1191
|
+
},
|
|
1192
|
+
});
|
|
1193
|
+
this.options.log?.(`localcore-lark session card create took ${Date.now() - startedAt}ms textBytes=${Buffer.byteLength(text || '', 'utf8')}`);
|
|
1194
|
+
return String(response?.data?.message_id || '').trim();
|
|
1195
|
+
}
|
|
1160
1196
|
async sendTextAsMessage(state, chatId, text) {
|
|
1161
1197
|
const startedAt = Date.now();
|
|
1162
1198
|
const rendered = (0, messages_js_1.renderLarkTextMessage)(text);
|
|
@@ -1272,6 +1308,27 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
|
|
|
1272
1308
|
const instanceId = legacyCall ? 'default' : instanceIdOrData;
|
|
1273
1309
|
const data = (legacyCall ? instanceIdOrData : maybeData) || {};
|
|
1274
1310
|
try {
|
|
1311
|
+
const sessionAction = (0, cards_js_1.extractSessionCommandActionValue)(data);
|
|
1312
|
+
if (sessionAction) {
|
|
1313
|
+
const route = this.threadRouting.get(sessionAction.sessionKey)
|
|
1314
|
+
|| this.routeFromThreadBinding(sessionAction.threadId, instanceId);
|
|
1315
|
+
if (!route) {
|
|
1316
|
+
this.options.log?.(`localcore-lark session card action ignored without route for thread=${sessionAction.threadId}`);
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
await this.executeSessionCommand({
|
|
1320
|
+
workspaceId,
|
|
1321
|
+
currentThreadId: sessionAction.threadId,
|
|
1322
|
+
text: sessionAction.command,
|
|
1323
|
+
defaultTitle: `Lark ${new Date().toLocaleTimeString()}`,
|
|
1324
|
+
chatId: route.chatId,
|
|
1325
|
+
platformUserId: route.platformUserId,
|
|
1326
|
+
platformKey: route.platformKey,
|
|
1327
|
+
instanceId: route.instanceId,
|
|
1328
|
+
});
|
|
1329
|
+
this.options.log?.(`localcore-lark processed session card action for ${workspaceId}/${instanceId}: ${sessionAction.command}`);
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1275
1332
|
const action = (0, cards_js_1.extractCardActionValue)(data);
|
|
1276
1333
|
if (!action) {
|
|
1277
1334
|
return;
|
|
@@ -1285,6 +1342,21 @@ class LocalCoreLarkGateway extends node_events_1.EventEmitter {
|
|
|
1285
1342
|
this.options.log?.(`localcore-lark card action failed for ${workspaceId}/${instanceId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1286
1343
|
}
|
|
1287
1344
|
}
|
|
1345
|
+
routeFromThreadBinding(threadId, instanceId) {
|
|
1346
|
+
const binding = this.options.store.getPlatformThreadBindingByThreadId(threadId);
|
|
1347
|
+
if (!binding || (binding.platform !== 'lark' && !binding.platform.startsWith('lark:'))) {
|
|
1348
|
+
return undefined;
|
|
1349
|
+
}
|
|
1350
|
+
const bindingInstanceId = getLarkInstanceId(binding.platform) || instanceId || 'default';
|
|
1351
|
+
return {
|
|
1352
|
+
workspaceId: binding.workspace_id,
|
|
1353
|
+
instanceId: bindingInstanceId,
|
|
1354
|
+
platformKey: binding.platform,
|
|
1355
|
+
platformUserId: binding.platform_user_id,
|
|
1356
|
+
chatId: binding.chat_id,
|
|
1357
|
+
threadId: binding.thread_id,
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1288
1360
|
async markPermissionCardActionHandled(workspaceId, instanceId, rootPayload, payload, value, response, threadId) {
|
|
1289
1361
|
const state = this.resolveRuntimeState(workspaceId, instanceId).state;
|
|
1290
1362
|
if (!state?.client) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChannelSessionCommandRuntime = void 0;
|
|
4
|
+
class ChannelSessionCommandRuntime {
|
|
5
|
+
options;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
async execute(input) {
|
|
10
|
+
const result = await this.options.service.execute(input.text, {
|
|
11
|
+
workspaceId: input.workspaceId,
|
|
12
|
+
currentThreadId: input.currentThreadId,
|
|
13
|
+
defaultTitle: input.defaultTitle,
|
|
14
|
+
});
|
|
15
|
+
if (!result.handled) {
|
|
16
|
+
return { handled: false, threadId: input.currentThreadId };
|
|
17
|
+
}
|
|
18
|
+
let activeThreadId = input.currentThreadId;
|
|
19
|
+
for (const effect of result.effects || []) {
|
|
20
|
+
if (effect.type === 'created_thread') {
|
|
21
|
+
this.inheritAgentMode(input.currentThreadId, effect.threadId);
|
|
22
|
+
}
|
|
23
|
+
if (effect.type === 'activate_thread') {
|
|
24
|
+
activeThreadId = effect.threadId;
|
|
25
|
+
this.activateThread(input, effect.threadId);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
await this.options.sendResult(input, result);
|
|
29
|
+
return { handled: true, threadId: activeThreadId, result };
|
|
30
|
+
}
|
|
31
|
+
inheritAgentMode(sourceThreadId, targetThreadId) {
|
|
32
|
+
const inheritedMode = this.options.store.getThreadRow?.(sourceThreadId)?.agent_mode || '';
|
|
33
|
+
if (inheritedMode && inheritedMode !== 'default') {
|
|
34
|
+
this.options.store.updateThreadAgentMode?.(targetThreadId, inheritedMode);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
activateThread(input, threadId) {
|
|
38
|
+
const now = new Date().toISOString();
|
|
39
|
+
this.options.store.updateAuthorizedUserThread(input.workspaceId, input.platformUserId, threadId, input.platformKey);
|
|
40
|
+
this.options.store.upsertPlatformThreadBinding({
|
|
41
|
+
workspace_id: input.workspaceId,
|
|
42
|
+
platform: input.platformKey,
|
|
43
|
+
chat_id: input.chatId,
|
|
44
|
+
platform_user_id: input.platformUserId,
|
|
45
|
+
thread_id: threadId,
|
|
46
|
+
last_platform_message_id: null,
|
|
47
|
+
created_at: now,
|
|
48
|
+
updated_at: now,
|
|
49
|
+
});
|
|
50
|
+
this.options.setThreadRoute(this.options.getThreadSessionKey(threadId), this.options.createRoute(input, threadId));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.ChannelSessionCommandRuntime = ChannelSessionCommandRuntime;
|
package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js
CHANGED
|
@@ -13,6 +13,8 @@ const node_crypto_2 = require("node:crypto");
|
|
|
13
13
|
const desktop_js_1 = require("../../../../../shared/desktop.js");
|
|
14
14
|
const content_js_1 = require("../shared/content.js");
|
|
15
15
|
const file_utils_js_1 = require("../shared/file-utils.js");
|
|
16
|
+
const session_command_runtime_js_1 = require("../shared/session-command-runtime.js");
|
|
17
|
+
const session_command_service_js_1 = require("../../thread/session-command-service.js");
|
|
16
18
|
const config_js_1 = require("./config.js");
|
|
17
19
|
const transport_js_1 = require("./transport.js");
|
|
18
20
|
// ==================== Constants ====================
|
|
@@ -150,11 +152,36 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
|
|
|
150
152
|
outboundTurns = new Map();
|
|
151
153
|
processedInboundMessages = new Map();
|
|
152
154
|
mutedThreadBridgeCounts = new Map();
|
|
155
|
+
sessionCommandRuntime;
|
|
153
156
|
platform = 'weixin';
|
|
154
157
|
routeType = 'channel.chat';
|
|
155
158
|
constructor(options) {
|
|
156
159
|
super();
|
|
157
160
|
this.options = options;
|
|
161
|
+
const sessionCommandService = new session_command_service_js_1.SessionCommandService({
|
|
162
|
+
listThreads: (workspaceId) => this.options.getWorkspaceRouter().listThreads(workspaceId),
|
|
163
|
+
getThread: (threadId) => this.options.getWorkspaceRouter().getThread(threadId),
|
|
164
|
+
createThread: (workspaceId, title) => this.options.getWorkspaceRouter().createThread(workspaceId, title),
|
|
165
|
+
renameThread: (threadId, title) => this.options.getWorkspaceRouter().renameThread(threadId, title),
|
|
166
|
+
deleteThread: (threadId) => this.options.getWorkspaceRouter().deleteThread(threadId),
|
|
167
|
+
});
|
|
168
|
+
this.sessionCommandRuntime = new session_command_runtime_js_1.ChannelSessionCommandRuntime({
|
|
169
|
+
service: sessionCommandService,
|
|
170
|
+
store: this.options.store,
|
|
171
|
+
getThreadSessionKey: (threadId) => this.options.getWorkspaceRouter().getThreadSessionKey(threadId),
|
|
172
|
+
setThreadRoute: (sessionKey, route) => {
|
|
173
|
+
this.threadRouting.set(sessionKey, route);
|
|
174
|
+
},
|
|
175
|
+
createRoute: (input, threadId) => ({
|
|
176
|
+
workspaceId: input.workspaceId,
|
|
177
|
+
instanceId: input.instanceId,
|
|
178
|
+
platformKey: input.platformKey,
|
|
179
|
+
platformUserId: input.platformUserId,
|
|
180
|
+
chatId: input.chatId,
|
|
181
|
+
threadId,
|
|
182
|
+
}),
|
|
183
|
+
sendResult: (input, result) => this.sendSessionCommandResult(input, result),
|
|
184
|
+
});
|
|
158
185
|
}
|
|
159
186
|
// ==================== Lifecycle ====================
|
|
160
187
|
async refreshBindings() {
|
|
@@ -648,7 +675,6 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
|
|
|
648
675
|
updated_at: now,
|
|
649
676
|
});
|
|
650
677
|
}
|
|
651
|
-
const sessionKey = router.getThreadSessionKey(threadId);
|
|
652
678
|
const normalizedText = String(input.text || '').trim().toLowerCase();
|
|
653
679
|
const permissionThreadId = (normalizedText === 'allow' || normalizedText === 'allow all' || normalizedText === 'deny') ? this.findAwaitingPermissionThreadId(input.workspaceId, input.chatId, input.platformUserId, input.platformKey) : '';
|
|
654
680
|
if (permissionThreadId && permissionThreadId !== threadId) {
|
|
@@ -665,38 +691,19 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
|
|
|
665
691
|
});
|
|
666
692
|
// Handle slash commands
|
|
667
693
|
const slashCommand = this.parseSlashCommand(input.text);
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
platform_user_id: input.platformUserId,
|
|
682
|
-
thread_id: nextThread.id,
|
|
683
|
-
last_platform_message_id: null,
|
|
684
|
-
created_at: now,
|
|
685
|
-
updated_at: now,
|
|
686
|
-
});
|
|
687
|
-
this.threadRouting.set(router.getThreadSessionKey(nextThread.id), {
|
|
688
|
-
workspaceId: input.workspaceId,
|
|
689
|
-
instanceId,
|
|
690
|
-
platformKey,
|
|
691
|
-
platformUserId: input.platformUserId,
|
|
692
|
-
chatId: input.chatId,
|
|
693
|
-
threadId: nextThread.id,
|
|
694
|
-
});
|
|
695
|
-
const st = this.runtime.get((0, config_js_1.runtimeKey)(input.workspaceId, instanceId));
|
|
696
|
-
if (st?.connected) {
|
|
697
|
-
await this.sendTextMessage(st, input.chatId, '**已开始新会话**', input.contextToken);
|
|
698
|
-
}
|
|
699
|
-
return { paired: true, threadId: nextThread.id };
|
|
694
|
+
const sessionCommand = await this.executeSessionCommand({
|
|
695
|
+
workspaceId: input.workspaceId,
|
|
696
|
+
currentThreadId: threadId,
|
|
697
|
+
text: input.text,
|
|
698
|
+
defaultTitle: `${input.displayName || 'WeChat'} ${new Date().toLocaleTimeString()}`,
|
|
699
|
+
chatId: input.chatId,
|
|
700
|
+
platformUserId: input.platformUserId,
|
|
701
|
+
platformKey,
|
|
702
|
+
instanceId,
|
|
703
|
+
contextToken: input.contextToken,
|
|
704
|
+
});
|
|
705
|
+
if (sessionCommand.handled) {
|
|
706
|
+
return { paired: true, threadId: sessionCommand.threadId || threadId };
|
|
700
707
|
}
|
|
701
708
|
const latestRun = this.options.store.getLatestRunForThread(threadId);
|
|
702
709
|
if ((normalizedText === 'allow' || normalizedText === 'allow all' || normalizedText === 'deny')
|
|
@@ -711,6 +718,17 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
|
|
|
711
718
|
await router.sendThreadMessage(threadId, (0, content_js_1.createChannelThreadMessageInput)(wrappedText, input.contentParts));
|
|
712
719
|
return { paired: true, threadId };
|
|
713
720
|
}
|
|
721
|
+
async executeSessionCommand(input) {
|
|
722
|
+
return this.sessionCommandRuntime.execute(input);
|
|
723
|
+
}
|
|
724
|
+
async sendSessionCommandResult(input, result) {
|
|
725
|
+
const state = this.resolveRuntimeState(input.workspaceId, input.instanceId).state;
|
|
726
|
+
if (!state?.connected) {
|
|
727
|
+
this.options.log?.(`localcore-weixin session command response skipped: workspace not connected: ${input.workspaceId}`);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
await this.sendTextMessage(state, input.chatId, result.displayText, input.contextToken);
|
|
731
|
+
}
|
|
714
732
|
// ==================== Private: Bindings ====================
|
|
715
733
|
resolveRuntimeState(workspaceId, instanceId) {
|
|
716
734
|
if (instanceId) {
|