@kafca/agentdock 0.1.56 → 0.1.58
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 +7 -0
- package/dist/renderer/assets/{Badge-DjcoXx2J.js → Badge-BfY1VaHS.js} +1 -1
- package/dist/renderer/assets/Card-DWA_Tww_.js +1 -0
- package/dist/renderer/assets/Config-nHj3g1U5.js +21 -0
- package/dist/renderer/assets/CronList-BwkA_I7v.js +1 -0
- package/dist/renderer/assets/Dashboard-D0_A7k02.js +41 -0
- package/dist/renderer/assets/{EmptyState-DIZLiccW.js → EmptyState-zatDjLj_.js} +1 -1
- package/dist/renderer/assets/HighlightedMarkdown-CsM5n70d.js +12 -0
- package/dist/renderer/assets/Input-R1XdFK1K.js +1 -0
- package/dist/renderer/assets/{KnowledgeDetail-CJ9IYOsa.js → KnowledgeDetail-Co5sxeGd.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BLGPwnBO.js → KnowledgeHome-DwziPw5m.js} +3 -3
- package/dist/renderer/assets/Logs-NwZUtR_G.js +6 -0
- package/dist/renderer/assets/{Modal-CQiUpfl4.js → Modal-CrcIwIFL.js} +3 -3
- package/dist/renderer/assets/MonitorList-CS1uLS5A.js +1 -0
- package/dist/renderer/assets/Page-Dp0obeSw.js +1 -0
- package/dist/renderer/assets/{Select-D6z65IT3.js → Select-6mVQaf84.js} +2 -2
- package/dist/renderer/assets/ThreadChat-BFzbn3L6.js +86 -0
- package/dist/renderer/assets/Workspace-DCmo8BMm.js +19 -0
- package/dist/renderer/assets/{arrow-left-CV5cL3f4.js → arrow-left-9rjg_Hp4.js} +1 -1
- package/dist/renderer/assets/{book-open-DThvB7pj.js → book-open-Bu8GCHnG.js} +1 -1
- package/dist/renderer/assets/channels-BxVbG-6j.js +6 -0
- package/dist/renderer/assets/chevron-down-BE8uQmWM.js +11 -0
- package/dist/renderer/assets/index-B7TeF6Es.js +41 -0
- package/dist/renderer/assets/index-BIKL3fTP.css +11 -0
- package/dist/renderer/assets/index-BkI9POxj.js +167 -0
- package/dist/renderer/assets/knowledge-Kl19SqGS.js +1 -0
- package/dist/renderer/assets/{pencil-Dv5WxhdC.js → pencil-CPB7SK1m.js} +1 -1
- package/dist/renderer/assets/{play-DnCnft83.js → play-DGAO4OCu.js} +1 -1
- package/dist/renderer/assets/{plus-DsxIagzS.js → plus-Bt26z-4q.js} +1 -1
- package/dist/renderer/assets/{save-CST01lIc.js → save-Une7GMxT.js} +1 -1
- package/dist/renderer/assets/{search-B_bqy6Wd.js → search-DE0agJjJ.js} +1 -1
- package/dist/renderer/assets/{shield-check-D6lG5Aoc.js → shield-check-De7xaXZh.js} +1 -1
- package/dist/renderer/assets/threads-BnsNL5ei.js +1 -0
- package/dist/renderer/assets/{trash-2-Cefngb6Q.js → trash-2-6iGF59Ac.js} +1 -1
- package/dist/renderer/index.html +2 -2
- package/dist-electron/packages/contracts/src/automation.js +2 -0
- package/dist-electron/packages/contracts/src/channels.js +2 -0
- package/dist-electron/packages/contracts/src/knowledge.js +2 -0
- package/dist-electron/packages/contracts/src/local-core.js +15 -0
- package/dist-electron/packages/contracts/src/runtime.js +2 -0
- package/dist-electron/packages/contracts/src/scheduler.js +2 -0
- package/dist-electron/packages/contracts/src/threads.js +2 -0
- package/dist-electron/packages/core-sdk/src/automation.js +32 -0
- package/dist-electron/packages/core-sdk/src/channels.js +121 -0
- package/dist-electron/packages/core-sdk/src/client.js +455 -0
- package/dist-electron/packages/core-sdk/src/index.js +43 -607
- package/dist-electron/packages/core-sdk/src/knowledge.js +85 -0
- package/dist-electron/packages/core-sdk/src/request.js +22 -0
- package/dist-electron/packages/core-sdk/src/runtime.js +214 -0
- package/dist-electron/packages/core-sdk/src/scheduler.js +32 -0
- package/dist-electron/packages/core-sdk/src/threads.js +67 -0
- package/dist-electron/packages/plugin-sdk/src/agents.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/automation.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/channels.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/index.js +21 -0
- package/dist-electron/packages/plugin-sdk/src/knowledge.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/runtime.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/scheduler.js +2 -0
- package/dist-electron/packages/plugin-sdk/src/threads.js +2 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +5 -8
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +2 -2
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +3 -3
- package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +5 -5
- package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +12 -12
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +2 -2
- package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +11 -11
- package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +3 -3
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +7 -7
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/claudecode/definition.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/codex/definition.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/localcore-acp/definition.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/localcore-acp/index.js +4 -4
- package/dist-electron/services/local-ai-core/src/agents/opencode/launch.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/pi/definition.js +2 -2
- package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +3 -3
- package/dist-electron/services/local-ai-core/src/agents/pi/provider-materializer.js +1 -1
- package/dist-electron/services/local-ai-core/src/agents/shared/agent-plugin.js +4 -4
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +6 -47
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +2 -5
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +33 -18
- package/dist-electron/services/local-ai-core/src/channel/lark/config.js +2 -2
- package/dist-electron/services/local-ai-core/src/channel/lark/gateway-utils.js +91 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/inbound-handler.js +180 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +58 -539
- package/dist-electron/services/local-ai-core/src/channel/lark/outbound-transport.js +112 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +5 -20
- package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +37 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/bridge-event-helpers.js +23 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/channel-keys.js +6 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/inbound-authorization.js +54 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +2 -2
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-media.js +21 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +167 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +55 -512
- package/dist-electron/services/local-ai-core/src/channel/weixin/runtime-state.js +149 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/text-utils.js +92 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +9 -11
- package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +2 -2
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +28 -70
- package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +8 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +2 -2
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +2 -2
- package/dist-electron/services/local-ai-core/src/router/workspace-bridge-event-stream.js +29 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +5 -5
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +47 -60
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +5 -5
- package/dist-electron/services/local-ai-core/src/runtime/config-migration.js +6 -6
- package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +3 -3
- package/dist-electron/services/local-ai-core/src/runtime/external-service.js +3 -1
- package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +11 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +12 -6
- package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +10 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +18 -6
- package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +7 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +28 -3
- package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +10 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +18 -5
- package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +14 -2
- package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +18 -15
- package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +13 -2
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +35 -8
- package/dist-electron/services/local-ai-core/src/runtime/request-validation.js +79 -0
- package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +9 -9
- package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +10 -1
- package/dist-electron/services/local-ai-core/src/runtime/server.js +2 -1
- package/dist-electron/services/local-ai-core/src/runtime/workspace-project-registry.js +76 -0
- package/dist-electron/services/local-ai-core/src/sandbox/opensandbox-client.js +3 -2
- package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +8 -8
- package/dist-electron/services/local-ai-core/src/scheduler/base-channel-schedule-adapter.js +77 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +13 -79
- package/dist-electron/services/local-ai-core/src/scheduler/local-schedule-adapter.js +2 -10
- package/dist-electron/services/local-ai-core/src/scheduler/run-polling.js +19 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +3 -37
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-route.js +20 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +15 -28
- package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +12 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +13 -79
- package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +75 -0
- package/dist-electron/shared/desktop.js +1 -64
- package/dist-electron/src/components/chat/chat-controller-state.js +60 -0
- package/dist-electron/src/components/chat/chat-event-gate.js +146 -0
- package/dist-electron/src/components/chat/markdown-code-block.js +8 -0
- package/dist-electron/src/pages/Desktop/workspace-model.js +212 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +50 -51
- package/dist-electron/tests/contracts/agent-message-policy.test.js +21 -0
- package/dist-electron/tests/contracts/architecture-docs.test.js +56 -33
- package/dist-electron/tests/contracts/chat-event-gate.test.js +114 -0
- package/dist-electron/tests/contracts/chat-markdown.test.js +16 -0
- package/dist-electron/tests/contracts/thread-task-state.test.js +32 -0
- package/dist-electron/tests/contracts/workspace-identity.test.js +23 -0
- package/dist-electron/tests/electron/core-client.test.js +284 -0
- package/dist-electron/tests/electron/plugin-kernel.test.js +54 -0
- package/dist-electron/tests/electron/renderer-packaging.test.js +9 -0
- package/dist-electron/tests/electron/workspace-task-store.test.js +31 -0
- package/dist-electron/tests/integration/channel-inbound-authorization.test.js +80 -0
- package/dist-electron/tests/integration/lark-gateway-utils.test.js +13 -0
- package/dist-electron/tests/integration/lark-gateway.test.js +4 -4
- package/dist-electron/tests/integration/local-core-refactor.test.js +15 -8
- package/dist-electron/tests/integration/weixin-runtime-state.test.js +32 -0
- package/dist-electron/tests/integration/weixin-text-utils.test.js +15 -0
- package/package.json +9 -4
- package/dist/renderer/assets/Chat-C5Bkm9-M.js +0 -2
- package/dist/renderer/assets/ChatMarkdown-uc36EzyD.js +0 -45
- package/dist/renderer/assets/Config-DHtQuuLy.js +0 -21
- package/dist/renderer/assets/CronList-BYUnhzSC.js +0 -1
- package/dist/renderer/assets/Dashboard-BPnGMDg3.js +0 -26
- package/dist/renderer/assets/Logs-Dyd2Uwlt.js +0 -1
- package/dist/renderer/assets/MonitorList-Byg3E3Gt.js +0 -1
- package/dist/renderer/assets/Page-7DxXvTMm.js +0 -1
- package/dist/renderer/assets/ProjectDetail-Dfr5s0Ja.js +0 -11
- package/dist/renderer/assets/ProjectList-CDDQjAQ_.js +0 -1
- package/dist/renderer/assets/SessionChat-s7CAaCPL.js +0 -1
- package/dist/renderer/assets/SessionList-D-OycKKS.js +0 -1
- package/dist/renderer/assets/ThreadChat-CLdFynB5.js +0 -28
- package/dist/renderer/assets/Workspace-xfT5z4j_.js +0 -19
- package/dist/renderer/assets/bot-CWQ5-ovl.js +0 -6
- package/dist/renderer/assets/check-DKM7zfWG.js +0 -6
- package/dist/renderer/assets/chevron-down-Dfw2KU87.js +0 -6
- package/dist/renderer/assets/circle-CoP4RA4s.js +0 -6
- package/dist/renderer/assets/desktop-CsDYrOOU.js +0 -1
- package/dist/renderer/assets/desktop-JQkhNOF4.js +0 -5
- package/dist/renderer/assets/funnel-DpVLlG3g.js +0 -6
- package/dist/renderer/assets/heart-BMD36ejP.js +0 -6
- package/dist/renderer/assets/index-COxSYBjE.js +0 -182
- package/dist/renderer/assets/index-CTGTI-cm.js +0 -41
- package/dist/renderer/assets/index-CjCuR6DI.css +0 -11
- package/dist/renderer/assets/projects-DgjHcNgt.js +0 -1
- package/dist/renderer/assets/server-ecH4GNwa.js +0 -11
- package/dist/renderer/assets/session-utils-Dd_WKMYW.js +0 -6
- package/dist/renderer/assets/sessions-BQ33Mv4k.js +0 -1
- package/dist/renderer/assets/user-D_8RSH-T.js +0 -6
- package/dist/renderer/assets/wifi-off-DB9D-pOu.js +0 -11
- package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +0 -13
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +0 -13
- package/dist-electron/src/api/client.js +0 -73
- package/dist-electron/src/api/sessions.js +0 -21
- package/dist-electron/src/lib/session-utils.js +0 -51
- package/dist-electron/src/pages/Projects/project-provider-config.js +0 -75
- package/dist-electron/tests/electron/project-provider-config.test.js +0 -71
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseChannelScheduleAdapter = void 0;
|
|
4
|
+
const scheduled_conversation_executor_js_1 = require("./scheduled-conversation-executor.js");
|
|
5
|
+
const scheduled_job_route_js_1 = require("./scheduled-job-route.js");
|
|
6
|
+
const thread_resolution_js_1 = require("./thread-resolution.js");
|
|
7
|
+
class BaseChannelScheduleAdapter {
|
|
8
|
+
options;
|
|
9
|
+
executor;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.options = options;
|
|
12
|
+
this.executor = new scheduled_conversation_executor_js_1.ScheduledConversationExecutor({
|
|
13
|
+
store: options.store,
|
|
14
|
+
getWorkspaceRouter: options.getWorkspaceRouter,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
supports(job) {
|
|
18
|
+
return (0, scheduled_job_route_js_1.platformMatches)(job.platform, this.platformBase) && this.supportedRouteTypes.includes(job.route.type);
|
|
19
|
+
}
|
|
20
|
+
async execute(context) {
|
|
21
|
+
const { job } = context;
|
|
22
|
+
const executionPolicy = this.createPolicy(job, {
|
|
23
|
+
store: this.options.store,
|
|
24
|
+
workspaceRouter: this.options.getWorkspaceRouter(),
|
|
25
|
+
getChannelRuntime: this.options.getChannelRuntime,
|
|
26
|
+
}, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
|
|
27
|
+
const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
|
|
28
|
+
return {
|
|
29
|
+
threadId: execution.threadId,
|
|
30
|
+
runId: execution.runId,
|
|
31
|
+
replyText: execution.replyText,
|
|
32
|
+
deliveryMode: 'bridge-stream',
|
|
33
|
+
deliveryStatus: 'succeeded',
|
|
34
|
+
lastBridgeEventAt: new Date().toISOString(),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async resolveThread(job) {
|
|
38
|
+
const workspaceRouter = this.options.getWorkspaceRouter();
|
|
39
|
+
const route = job.route;
|
|
40
|
+
const channelId = route.channelId;
|
|
41
|
+
const participantId = route.participantId || '';
|
|
42
|
+
const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
|
|
43
|
+
if (binding?.thread_id && await (0, thread_resolution_js_1.threadExists)(workspaceRouter, binding.thread_id)) {
|
|
44
|
+
return binding.thread_id;
|
|
45
|
+
}
|
|
46
|
+
if (route.threadId && await (0, thread_resolution_js_1.threadExists)(workspaceRouter, route.threadId)) {
|
|
47
|
+
return route.threadId;
|
|
48
|
+
}
|
|
49
|
+
const thread = await workspaceRouter.createThread(job.workspaceId, job.description || `Scheduled ${job.platform} task`);
|
|
50
|
+
const now = new Date().toISOString();
|
|
51
|
+
this.options.store.upsertPlatformThreadBinding({
|
|
52
|
+
workspace_id: job.workspaceId,
|
|
53
|
+
platform: job.platform,
|
|
54
|
+
chat_id: channelId,
|
|
55
|
+
platform_user_id: participantId,
|
|
56
|
+
thread_id: thread.id,
|
|
57
|
+
last_platform_message_id: null,
|
|
58
|
+
created_at: now,
|
|
59
|
+
updated_at: now,
|
|
60
|
+
});
|
|
61
|
+
const authorized = this.options.store.getAuthorizedUser(job.workspaceId, participantId, job.platform);
|
|
62
|
+
if (authorized) {
|
|
63
|
+
this.options.store.updateAuthorizedUserThread(job.workspaceId, participantId, thread.id, job.platform);
|
|
64
|
+
}
|
|
65
|
+
return thread.id;
|
|
66
|
+
}
|
|
67
|
+
preferredAgentFor(job) {
|
|
68
|
+
const route = job.route;
|
|
69
|
+
const channelId = route.channelId;
|
|
70
|
+
if (!channelId)
|
|
71
|
+
return '';
|
|
72
|
+
const participantId = route.participantId || '';
|
|
73
|
+
const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
|
|
74
|
+
return binding?.preferred_agent_type || '';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.BaseChannelScheduleAdapter = BaseChannelScheduleAdapter;
|
|
@@ -1,87 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LarkScheduleAdapter = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
executor;
|
|
4
|
+
const channel_execution_policy_js_1 = require("./channel-execution-policy.js");
|
|
5
|
+
const base_channel_schedule_adapter_js_1 = require("./base-channel-schedule-adapter.js");
|
|
6
|
+
class LarkScheduleAdapter extends base_channel_schedule_adapter_js_1.BaseChannelScheduleAdapter {
|
|
7
|
+
platformBase = 'lark';
|
|
8
|
+
supportedRouteTypes = ['channel.chat', 'lark_chat'];
|
|
10
9
|
deliveryTargets = ['lark'];
|
|
11
|
-
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
createPolicy(job, options, resolveSameThread, preferredAgentType) {
|
|
11
|
+
const label = this.platformBase.charAt(0).toUpperCase() + this.platformBase.slice(1);
|
|
12
|
+
return (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
|
|
13
|
+
platformBase: this.platformBase,
|
|
14
|
+
resolveSameThread,
|
|
15
|
+
sideThreadTitle: (nextJob) => `[Scheduled:${label}] ${nextJob.description || nextJob.id}`,
|
|
16
|
+
legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
|
|
17
|
+
preferredAgentType,
|
|
16
18
|
});
|
|
17
19
|
}
|
|
18
|
-
supports(job) {
|
|
19
|
-
return (0, scheduled_job_route_js_1.platformMatches)(job.platform, 'lark') && (job.route.type === 'channel.chat' || job.route.type === 'lark_chat');
|
|
20
|
-
}
|
|
21
|
-
async execute(context) {
|
|
22
|
-
const { job } = context;
|
|
23
|
-
const executionPolicy = (0, lark_execution_policies_js_1.createLarkExecutionPolicy)(job, {
|
|
24
|
-
store: this.options.store,
|
|
25
|
-
workspaceRouter: this.options.getWorkspaceRouter(),
|
|
26
|
-
getChannelRuntime: this.options.getChannelRuntime,
|
|
27
|
-
}, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
|
|
28
|
-
const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
|
|
29
|
-
return {
|
|
30
|
-
threadId: execution.threadId,
|
|
31
|
-
runId: execution.runId,
|
|
32
|
-
replyText: execution.replyText,
|
|
33
|
-
deliveryMode: 'bridge-stream',
|
|
34
|
-
deliveryStatus: 'succeeded',
|
|
35
|
-
lastBridgeEventAt: new Date().toISOString(),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
async resolveThread(job) {
|
|
39
|
-
const workspaceRouter = this.options.getWorkspaceRouter();
|
|
40
|
-
const route = job.route;
|
|
41
|
-
const channelId = route.channelId;
|
|
42
|
-
const participantId = route.participantId || '';
|
|
43
|
-
const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
|
|
44
|
-
if (binding?.thread_id && await this.threadExists(binding.thread_id)) {
|
|
45
|
-
return binding.thread_id;
|
|
46
|
-
}
|
|
47
|
-
if (route.threadId && await this.threadExists(route.threadId)) {
|
|
48
|
-
return route.threadId;
|
|
49
|
-
}
|
|
50
|
-
const thread = await workspaceRouter.createThread(job.workspaceId, job.description || `Scheduled ${job.platform} task`);
|
|
51
|
-
const now = new Date().toISOString();
|
|
52
|
-
this.options.store.upsertPlatformThreadBinding({
|
|
53
|
-
workspace_id: job.workspaceId,
|
|
54
|
-
platform: job.platform,
|
|
55
|
-
chat_id: channelId,
|
|
56
|
-
platform_user_id: participantId,
|
|
57
|
-
thread_id: thread.id,
|
|
58
|
-
last_platform_message_id: null,
|
|
59
|
-
created_at: now,
|
|
60
|
-
updated_at: now,
|
|
61
|
-
});
|
|
62
|
-
const authorized = this.options.store.getAuthorizedUser(job.workspaceId, participantId, job.platform);
|
|
63
|
-
if (authorized) {
|
|
64
|
-
this.options.store.updateAuthorizedUserThread(job.workspaceId, participantId, thread.id, job.platform);
|
|
65
|
-
}
|
|
66
|
-
return thread.id;
|
|
67
|
-
}
|
|
68
|
-
async threadExists(threadId) {
|
|
69
|
-
try {
|
|
70
|
-
await this.options.getWorkspaceRouter().getThread(threadId);
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
preferredAgentFor(job) {
|
|
78
|
-
const route = job.route;
|
|
79
|
-
const channelId = route.channelId;
|
|
80
|
-
if (!channelId)
|
|
81
|
-
return '';
|
|
82
|
-
const participantId = route.participantId || '';
|
|
83
|
-
const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
|
|
84
|
-
return binding?.preferred_agent_type || '';
|
|
85
|
-
}
|
|
86
20
|
}
|
|
87
21
|
exports.LarkScheduleAdapter = LarkScheduleAdapter;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LocalScheduleAdapter = void 0;
|
|
4
4
|
const scheduled_conversation_executor_js_1 = require("./scheduled-conversation-executor.js");
|
|
5
|
+
const thread_resolution_js_1 = require("./thread-resolution.js");
|
|
5
6
|
class LocalScheduleAdapter {
|
|
6
7
|
options;
|
|
7
8
|
executor;
|
|
@@ -40,7 +41,7 @@ class LocalScheduleAdapter {
|
|
|
40
41
|
}
|
|
41
42
|
async resolveThread(job) {
|
|
42
43
|
const workspaceRouter = this.options.getWorkspaceRouter();
|
|
43
|
-
if (job.route.threadId && await
|
|
44
|
+
if (job.route.threadId && await (0, thread_resolution_js_1.threadExists)(workspaceRouter, job.route.threadId)) {
|
|
44
45
|
return job.route.threadId;
|
|
45
46
|
}
|
|
46
47
|
const title = `[Scheduled] ${job.description || job.id}`;
|
|
@@ -52,14 +53,5 @@ class LocalScheduleAdapter {
|
|
|
52
53
|
const created = await workspaceRouter.createThread(job.workspaceId, title);
|
|
53
54
|
return created.id;
|
|
54
55
|
}
|
|
55
|
-
async threadExists(threadId) {
|
|
56
|
-
try {
|
|
57
|
-
await this.options.getWorkspaceRouter().getThread(threadId);
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
56
|
}
|
|
65
57
|
exports.LocalScheduleAdapter = LocalScheduleAdapter;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForRunCompletion = waitForRunCompletion;
|
|
4
|
+
const TERMINAL_RUN_STATES = new Set(['completed', 'failed', 'interrupted']);
|
|
5
|
+
const RUN_POLL_INTERVAL_MS = 300;
|
|
6
|
+
async function waitForRunCompletion(store, runId, timeoutMs, label) {
|
|
7
|
+
const startedAt = Date.now();
|
|
8
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
9
|
+
const run = store.getRun(runId);
|
|
10
|
+
if (run && TERMINAL_RUN_STATES.has(run.status)) {
|
|
11
|
+
if (run.status !== 'completed') {
|
|
12
|
+
throw new Error(`${label} run finished with status ${run.status}`);
|
|
13
|
+
}
|
|
14
|
+
return run;
|
|
15
|
+
}
|
|
16
|
+
await new Promise((resolve) => setTimeout(resolve, RUN_POLL_INTERVAL_MS));
|
|
17
|
+
}
|
|
18
|
+
throw new Error(`Timed out waiting for ${label.toLowerCase()} run ${runId}`);
|
|
19
|
+
}
|
package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ScheduledConversationExecutor = void 0;
|
|
4
4
|
const scheduled_job_route_js_1 = require("./scheduled-job-route.js");
|
|
5
|
-
const
|
|
5
|
+
const run_polling_js_1 = require("./run-polling.js");
|
|
6
6
|
const SCHEDULED_RUN_PERMISSION_MODE = 'bypassPermissions';
|
|
7
7
|
class ScheduledConversationExecutor {
|
|
8
8
|
options;
|
|
@@ -16,9 +16,9 @@ class ScheduledConversationExecutor {
|
|
|
16
16
|
const workspaceRouter = this.options.getWorkspaceRouter();
|
|
17
17
|
const sendResult = await workspaceRouter.sendThreadMessage(target.threadId, prompt, {
|
|
18
18
|
permissionMode: SCHEDULED_RUN_PERMISSION_MODE,
|
|
19
|
-
runtimeEnv:
|
|
19
|
+
runtimeEnv: (0, scheduled_job_route_js_1.buildPlatformRuntimeEnv)(target.platform, target.route),
|
|
20
20
|
});
|
|
21
|
-
await this.
|
|
21
|
+
await (0, run_polling_js_1.waitForRunCompletion)(this.options.store, sendResult.runId, timeoutMs, 'Scheduled');
|
|
22
22
|
const thread = await workspaceRouter.getThread(target.threadId);
|
|
23
23
|
const replyText = [...thread.messages]
|
|
24
24
|
.reverse()
|
|
@@ -34,39 +34,5 @@ class ScheduledConversationExecutor {
|
|
|
34
34
|
await policy.afterExecute?.(target, job);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
buildScheduledRuntimeEnv(target) {
|
|
38
|
-
const route = target.route;
|
|
39
|
-
const basePlatform = (0, scheduled_job_route_js_1.getChannelPlatformBase)(target.platform);
|
|
40
|
-
const env = {};
|
|
41
|
-
if (basePlatform && basePlatform !== 'local') {
|
|
42
|
-
env.LOCAL_AI_PLATFORM = basePlatform;
|
|
43
|
-
env.LOCAL_AI_ROUTE_TYPE = (0, scheduled_job_route_js_1.routeTypeForPlatform)(target.platform);
|
|
44
|
-
}
|
|
45
|
-
const instanceId = route.instanceId || (0, scheduled_job_route_js_1.getChannelPlatformInstanceId)(target.platform);
|
|
46
|
-
if (instanceId) {
|
|
47
|
-
env.LOCAL_AI_PLATFORM_INSTANCE_ID = instanceId;
|
|
48
|
-
}
|
|
49
|
-
if (route.channelId) {
|
|
50
|
-
env.LOCAL_AI_CHAT_ID = route.channelId;
|
|
51
|
-
}
|
|
52
|
-
if (route.participantId) {
|
|
53
|
-
env.LOCAL_AI_PLATFORM_USER_ID = route.participantId;
|
|
54
|
-
}
|
|
55
|
-
return env;
|
|
56
|
-
}
|
|
57
|
-
async waitForRun(runId, timeoutMs) {
|
|
58
|
-
const startedAt = Date.now();
|
|
59
|
-
while (Date.now() - startedAt < timeoutMs) {
|
|
60
|
-
const run = this.options.store.getRun(runId);
|
|
61
|
-
if (run && TERMINAL_RUN_STATES.has(run.status)) {
|
|
62
|
-
if (run.status !== 'completed') {
|
|
63
|
-
throw new Error(`Scheduled run finished with status ${run.status}`);
|
|
64
|
-
}
|
|
65
|
-
return run;
|
|
66
|
-
}
|
|
67
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
68
|
-
}
|
|
69
|
-
throw new Error(`Timed out waiting for scheduled run ${runId}`);
|
|
70
|
-
}
|
|
71
37
|
}
|
|
72
38
|
exports.ScheduledConversationExecutor = ScheduledConversationExecutor;
|
|
@@ -6,6 +6,7 @@ exports.getChannelPlatformInstanceId = getChannelPlatformInstanceId;
|
|
|
6
6
|
exports.platformMatches = platformMatches;
|
|
7
7
|
exports.routeWithPlatformInstance = routeWithPlatformInstance;
|
|
8
8
|
exports.routeTypeForPlatform = routeTypeForPlatform;
|
|
9
|
+
exports.buildPlatformRuntimeEnv = buildPlatformRuntimeEnv;
|
|
9
10
|
exports.routeFromPlatformThreadBinding = routeFromPlatformThreadBinding;
|
|
10
11
|
exports.scheduledJobMatchesPlatformBinding = scheduledJobMatchesPlatformBinding;
|
|
11
12
|
exports.scheduledJobMatchesCliContext = scheduledJobMatchesCliContext;
|
|
@@ -32,6 +33,25 @@ function routeTypeForPlatform(platform) {
|
|
|
32
33
|
const base = getChannelPlatformBase(platform);
|
|
33
34
|
return base === 'lark' || base === 'weixin' ? 'channel.chat' : base;
|
|
34
35
|
}
|
|
36
|
+
function buildPlatformRuntimeEnv(platform, route) {
|
|
37
|
+
const basePlatform = getChannelPlatformBase(platform);
|
|
38
|
+
const env = {};
|
|
39
|
+
if (basePlatform && basePlatform !== 'local') {
|
|
40
|
+
env.LOCAL_AI_PLATFORM = basePlatform;
|
|
41
|
+
env.LOCAL_AI_ROUTE_TYPE = routeTypeForPlatform(platform);
|
|
42
|
+
}
|
|
43
|
+
const instanceId = route.instanceId || getChannelPlatformInstanceId(platform);
|
|
44
|
+
if (instanceId) {
|
|
45
|
+
env.LOCAL_AI_PLATFORM_INSTANCE_ID = instanceId;
|
|
46
|
+
}
|
|
47
|
+
if (route.channelId) {
|
|
48
|
+
env.LOCAL_AI_CHAT_ID = route.channelId;
|
|
49
|
+
}
|
|
50
|
+
if (route.participantId) {
|
|
51
|
+
env.LOCAL_AI_PLATFORM_USER_ID = route.participantId;
|
|
52
|
+
}
|
|
53
|
+
return env;
|
|
54
|
+
}
|
|
35
55
|
function routeFromPlatformThreadBinding(binding) {
|
|
36
56
|
return {
|
|
37
57
|
type: routeTypeForPlatform(binding.platform),
|
|
@@ -16,10 +16,18 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
16
16
|
this.options = options;
|
|
17
17
|
this.runLifecycle = new scheduler_run_lifecycle_js_1.SchedulerRunLifecycle({
|
|
18
18
|
store: options.store,
|
|
19
|
-
emitRun: (run) => this.
|
|
20
|
-
emitJob: (job) => this.
|
|
19
|
+
emitRun: (run) => this.emitRun(run),
|
|
20
|
+
emitJob: (job) => this.emitJob(job),
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
+
emitJob(job) {
|
|
24
|
+
this.emit('job', job);
|
|
25
|
+
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: job });
|
|
26
|
+
}
|
|
27
|
+
emitRun(run) {
|
|
28
|
+
this.emit('run', run);
|
|
29
|
+
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: run });
|
|
30
|
+
}
|
|
23
31
|
async start() {
|
|
24
32
|
await this.tick();
|
|
25
33
|
this.timer = setInterval(() => {
|
|
@@ -41,14 +49,12 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
41
49
|
}
|
|
42
50
|
createJob(input) {
|
|
43
51
|
const job = this.options.store.createScheduledJob(input);
|
|
44
|
-
this.
|
|
45
|
-
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: job });
|
|
52
|
+
this.emitJob(job);
|
|
46
53
|
return job;
|
|
47
54
|
}
|
|
48
55
|
updateJob(jobId, input) {
|
|
49
56
|
const job = this.options.store.updateScheduledJob(this.resolveRequiredJobId(jobId), input);
|
|
50
|
-
this.
|
|
51
|
-
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: job });
|
|
57
|
+
this.emitJob(job);
|
|
52
58
|
return job;
|
|
53
59
|
}
|
|
54
60
|
deleteJob(jobId) {
|
|
@@ -115,39 +121,21 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
115
121
|
}
|
|
116
122
|
async executeJob(job, triggeredAt, manual) {
|
|
117
123
|
if (this.runningJobs.has(job.id)) {
|
|
118
|
-
|
|
119
|
-
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: skipped });
|
|
120
|
-
return skipped;
|
|
124
|
+
return this.runLifecycle.markSkipped(job, triggeredAt, 'Skipped because the previous run is still active.');
|
|
121
125
|
}
|
|
122
126
|
this.runningJobs.add(job.id);
|
|
123
127
|
const run = this.runLifecycle.markQueued(job, triggeredAt);
|
|
124
|
-
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: run });
|
|
125
128
|
try {
|
|
126
129
|
const executor = this.options.executors.find((candidate) => candidate.supports(job));
|
|
127
130
|
if (!executor) {
|
|
128
131
|
throw new Error(`No scheduler executor is available for delivery target "${job.platform}"`);
|
|
129
132
|
}
|
|
130
133
|
this.runLifecycle.markRunning(run.id);
|
|
131
|
-
const running = this.options.store.getScheduledJobRun(run.id);
|
|
132
|
-
if (running) {
|
|
133
|
-
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: running });
|
|
134
|
-
}
|
|
135
134
|
const result = await executor.execute({ job, triggeredAt });
|
|
136
|
-
|
|
137
|
-
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: succeeded });
|
|
138
|
-
const nextJob = this.options.store.getScheduledJob(job.id);
|
|
139
|
-
if (nextJob) {
|
|
140
|
-
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: nextJob });
|
|
141
|
-
}
|
|
142
|
-
return succeeded;
|
|
135
|
+
return this.runLifecycle.markSucceeded(job, run.id, result, !manual && job.triggerType === 'once');
|
|
143
136
|
}
|
|
144
137
|
catch (error) {
|
|
145
138
|
const failed = this.runLifecycle.markFailed(job.id, run.id, error instanceof Error ? error.message : String(error));
|
|
146
|
-
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: failed });
|
|
147
|
-
const nextJob = this.options.store.getScheduledJob(job.id);
|
|
148
|
-
if (nextJob) {
|
|
149
|
-
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: nextJob });
|
|
150
|
-
}
|
|
151
139
|
this.options.log?.(`scheduler job failed ${job.id}: ${failed.error || 'unknown error'}`);
|
|
152
140
|
this.maybeAutoDisableAfterFailure(job.id);
|
|
153
141
|
return failed;
|
|
@@ -173,8 +161,7 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
173
161
|
this.options.store.updateScheduledJobStatus(jobId, { enabled: false });
|
|
174
162
|
const disabled = this.options.store.getScheduledJob(jobId);
|
|
175
163
|
if (disabled) {
|
|
176
|
-
this.
|
|
177
|
-
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: disabled });
|
|
164
|
+
this.emitJob(disabled);
|
|
178
165
|
}
|
|
179
166
|
this.options.log?.(`scheduler auto-disabled job ${jobId} after ${consecutiveFailures} consecutive failures`);
|
|
180
167
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.threadExists = threadExists;
|
|
4
|
+
async function threadExists(router, threadId) {
|
|
5
|
+
try {
|
|
6
|
+
await router.getThread(threadId);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,87 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WeixinScheduleAdapter = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
executor;
|
|
4
|
+
const channel_execution_policy_js_1 = require("./channel-execution-policy.js");
|
|
5
|
+
const base_channel_schedule_adapter_js_1 = require("./base-channel-schedule-adapter.js");
|
|
6
|
+
class WeixinScheduleAdapter extends base_channel_schedule_adapter_js_1.BaseChannelScheduleAdapter {
|
|
7
|
+
platformBase = 'weixin';
|
|
8
|
+
supportedRouteTypes = ['channel.chat', 'weixin_chat'];
|
|
10
9
|
deliveryTargets = ['weixin'];
|
|
11
|
-
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
createPolicy(job, options, resolveSameThread, preferredAgentType) {
|
|
11
|
+
const label = this.platformBase.charAt(0).toUpperCase() + this.platformBase.slice(1);
|
|
12
|
+
return (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
|
|
13
|
+
platformBase: this.platformBase,
|
|
14
|
+
resolveSameThread,
|
|
15
|
+
sideThreadTitle: (nextJob) => `[Scheduled:${label}] ${nextJob.description || nextJob.id}`,
|
|
16
|
+
legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
|
|
17
|
+
preferredAgentType,
|
|
16
18
|
});
|
|
17
19
|
}
|
|
18
|
-
supports(job) {
|
|
19
|
-
return (0, scheduled_job_route_js_1.platformMatches)(job.platform, 'weixin') && (job.route.type === 'channel.chat' || job.route.type === 'weixin_chat');
|
|
20
|
-
}
|
|
21
|
-
async execute(context) {
|
|
22
|
-
const { job } = context;
|
|
23
|
-
const executionPolicy = (0, weixin_execution_policies_js_1.createWeixinExecutionPolicy)(job, {
|
|
24
|
-
store: this.options.store,
|
|
25
|
-
workspaceRouter: this.options.getWorkspaceRouter(),
|
|
26
|
-
getChannelRuntime: this.options.getChannelRuntime,
|
|
27
|
-
}, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
|
|
28
|
-
const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
|
|
29
|
-
return {
|
|
30
|
-
threadId: execution.threadId,
|
|
31
|
-
runId: execution.runId,
|
|
32
|
-
replyText: execution.replyText,
|
|
33
|
-
deliveryMode: 'bridge-stream',
|
|
34
|
-
deliveryStatus: 'succeeded',
|
|
35
|
-
lastBridgeEventAt: new Date().toISOString(),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
async resolveThread(job) {
|
|
39
|
-
const workspaceRouter = this.options.getWorkspaceRouter();
|
|
40
|
-
const route = job.route;
|
|
41
|
-
const channelId = route.channelId;
|
|
42
|
-
const participantId = route.participantId || '';
|
|
43
|
-
const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
|
|
44
|
-
if (binding?.thread_id && await this.threadExists(binding.thread_id)) {
|
|
45
|
-
return binding.thread_id;
|
|
46
|
-
}
|
|
47
|
-
if (route.threadId && await this.threadExists(route.threadId)) {
|
|
48
|
-
return route.threadId;
|
|
49
|
-
}
|
|
50
|
-
const thread = await workspaceRouter.createThread(job.workspaceId, job.description || `Scheduled ${job.platform} task`);
|
|
51
|
-
const now = new Date().toISOString();
|
|
52
|
-
this.options.store.upsertPlatformThreadBinding({
|
|
53
|
-
workspace_id: job.workspaceId,
|
|
54
|
-
platform: 'weixin',
|
|
55
|
-
chat_id: channelId,
|
|
56
|
-
platform_user_id: participantId,
|
|
57
|
-
thread_id: thread.id,
|
|
58
|
-
last_platform_message_id: null,
|
|
59
|
-
created_at: now,
|
|
60
|
-
updated_at: now,
|
|
61
|
-
});
|
|
62
|
-
const authorized = this.options.store.getAuthorizedUser(job.workspaceId, participantId, job.platform);
|
|
63
|
-
if (authorized) {
|
|
64
|
-
this.options.store.updateAuthorizedUserThread(job.workspaceId, participantId, thread.id, job.platform);
|
|
65
|
-
}
|
|
66
|
-
return thread.id;
|
|
67
|
-
}
|
|
68
|
-
async threadExists(threadId) {
|
|
69
|
-
try {
|
|
70
|
-
await this.options.getWorkspaceRouter().getThread(threadId);
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
preferredAgentFor(job) {
|
|
78
|
-
const route = job.route;
|
|
79
|
-
const channelId = route.channelId;
|
|
80
|
-
if (!channelId)
|
|
81
|
-
return '';
|
|
82
|
-
const participantId = route.participantId || '';
|
|
83
|
-
const binding = this.options.store.getPlatformThreadBinding(job.workspaceId, channelId, participantId, job.platform);
|
|
84
|
-
return binding?.preferred_agent_type || '';
|
|
85
|
-
}
|
|
86
20
|
}
|
|
87
21
|
exports.WeixinScheduleAdapter = WeixinScheduleAdapter;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.composeAgentMessage = composeAgentMessage;
|
|
4
|
+
const SCHEDULER_INSTRUCTION = [
|
|
5
|
+
'[Scheduler Tools]',
|
|
6
|
+
'If the user asks to create, view, edit, delete, or manually run a scheduled task for this conversation, use the Bash tool to run the local scheduler CLI.',
|
|
7
|
+
'Use these commands:',
|
|
8
|
+
'lac scheduler add --cron "<5-field cron>" --message "<exact message to send>" --desc "<short label>" [--execution-mode same-thread|side-thread]',
|
|
9
|
+
'lac scheduler list',
|
|
10
|
+
'lac scheduler list --thread',
|
|
11
|
+
'lac scheduler info <short-job-id>',
|
|
12
|
+
'lac scheduler edit <short-job-id> [--cron "<5-field cron>"] [--message "<exact message>"] [--desc "<short label>"] [--enabled true|false] [--execution-mode same-thread|side-thread]',
|
|
13
|
+
'lac scheduler del <short-job-id>',
|
|
14
|
+
'lac scheduler run <short-job-id>',
|
|
15
|
+
'Environment variables LOCAL_AI_WORKSPACE_ID, LOCAL_AI_THREAD_ID, LOCAL_AI_PLATFORM, LOCAL_AI_CHAT_ID, and LOCAL_AI_PLATFORM_USER_ID are already set when available.',
|
|
16
|
+
'Prefer relying on those variables instead of inventing your own route or creating session-only cron jobs.',
|
|
17
|
+
'By default, `lac scheduler list` shows all scheduled tasks in the current workspace. Use `lac scheduler list --thread` to show only the current conversation thread.',
|
|
18
|
+
'Use the short job id shown by `lac scheduler list`; do not add a `job:` prefix or expand it to a full UUID.',
|
|
19
|
+
'Use `--execution-mode same-thread` to reuse the current thread, or `--execution-mode side-thread` to run in a dedicated scheduled thread.',
|
|
20
|
+
'Only use the scheduler CLI when the user explicitly asks for scheduled automation.',
|
|
21
|
+
'[/Scheduler Tools]',
|
|
22
|
+
].join('\n');
|
|
23
|
+
const MONITOR_INSTRUCTION = [
|
|
24
|
+
'[Monitor Tools]',
|
|
25
|
+
'If the user asks to create, view, edit, delete, or manually run an event monitor for this conversation, use the Bash tool to run the local monitor CLI.',
|
|
26
|
+
'Use these commands:',
|
|
27
|
+
'lac monitor add --title "<short title>" --source stock.quote --symbol "<ticker>" --condition "<metric operator value>" --message "<exact analysis prompt>" [--cooldown 15m] [--execution-mode same-thread|side-thread]',
|
|
28
|
+
'lac monitor list',
|
|
29
|
+
'lac monitor list --thread',
|
|
30
|
+
'lac monitor info <short-monitor-id>',
|
|
31
|
+
'lac monitor edit <short-monitor-id> [--title "<title>"] [--condition "<expr>"] [--message "<exact prompt>"] [--enabled true|false] [--cooldown 15m] [--execution-mode same-thread|side-thread]',
|
|
32
|
+
'lac monitor del <short-monitor-id>',
|
|
33
|
+
'lac monitor run <short-monitor-id>',
|
|
34
|
+
'Supported stock metrics include latestPrice, change_percent, changePercent, and abs_change_percent. Example condition: "abs_change_percent >= 3".',
|
|
35
|
+
'Environment variables LOCAL_AI_WORKSPACE_ID, LOCAL_AI_THREAD_ID, LOCAL_AI_PLATFORM, LOCAL_AI_CHAT_ID, and LOCAL_AI_PLATFORM_USER_ID are already set when available.',
|
|
36
|
+
'Prefer relying on those variables instead of inventing your own route.',
|
|
37
|
+
'Use --execution-mode side-thread by default so monitor analysis does not interrupt the current conversation.',
|
|
38
|
+
'Only use the monitor CLI when the user explicitly asks for event monitoring automation.',
|
|
39
|
+
'[/Monitor Tools]',
|
|
40
|
+
].join('\n');
|
|
41
|
+
const CHANNEL_INSTRUCTION = [
|
|
42
|
+
'[Channel Tools]',
|
|
43
|
+
'If the user asks you to send a local file back through the current channel conversation, use the Bash tool to run the local channel CLI.',
|
|
44
|
+
'Use this command:',
|
|
45
|
+
'lac channel send-file --path "<absolute-or-workdir-relative-file-path>" [--target "<channel-chat-or-user-id>"]',
|
|
46
|
+
'By default, the file is sent to the current platform conversation from LOCAL_AI_CHAT_ID.',
|
|
47
|
+
'Use --target only when the user explicitly names a different channel chat or user id.',
|
|
48
|
+
'The CLI accepts absolute paths. Check that the file exists before sending when practical.',
|
|
49
|
+
'Only use the channel CLI when the user explicitly asks to send a file through the channel.',
|
|
50
|
+
'[/Channel Tools]',
|
|
51
|
+
].join('\n');
|
|
52
|
+
function composeAgentMessage(content, knowledgeBases = []) {
|
|
53
|
+
if (content.trim().startsWith('/')) {
|
|
54
|
+
return content;
|
|
55
|
+
}
|
|
56
|
+
const knowledgeBlock = knowledgeBases.length
|
|
57
|
+
? [
|
|
58
|
+
'[Selected Knowledge Bases]',
|
|
59
|
+
...knowledgeBases.map((base) => `- id: ${base.id} | name: ${base.name}`),
|
|
60
|
+
'[/Selected Knowledge Bases]',
|
|
61
|
+
].join('\n')
|
|
62
|
+
: '';
|
|
63
|
+
return [
|
|
64
|
+
SCHEDULER_INSTRUCTION,
|
|
65
|
+
'',
|
|
66
|
+
MONITOR_INSTRUCTION,
|
|
67
|
+
'',
|
|
68
|
+
CHANNEL_INSTRUCTION,
|
|
69
|
+
...(knowledgeBlock ? ['', knowledgeBlock] : []),
|
|
70
|
+
'',
|
|
71
|
+
'[User Message]',
|
|
72
|
+
content,
|
|
73
|
+
'[/User Message]',
|
|
74
|
+
].join('\n');
|
|
75
|
+
}
|