@kafca/agentdock 0.1.47 → 0.1.49
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 +6 -0
- package/dist/renderer/assets/{Badge-BYREM3t3.js → Badge-DXjx3T4U.js} +1 -1
- package/dist/renderer/assets/{Chat-Dtb5X7sB.js → Chat-BdLcSBda.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-_slLloCh.js → ChatMarkdown-CSc8mfpv.js} +1 -1
- package/dist/renderer/assets/{Config-pHichs7H.js → Config-b5NK6ZGX.js} +2 -2
- package/dist/renderer/assets/{CronList-CJQMeCjz.js → CronList-B4vdtNHN.js} +1 -1
- package/dist/renderer/assets/{Dashboard-CY77Imde.js → Dashboard-BItoWTOa.js} +2 -2
- package/dist/renderer/assets/{EmptyState-DCqmct2y.js → EmptyState-DUDyUsLL.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-DFrxa-pv.js → KnowledgeDetail-WWH6KxiG.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-DL-vAfrH.js → KnowledgeHome-Dn-NmRxu.js} +2 -2
- package/dist/renderer/assets/{Logs-jw9Uv590.js → Logs-4zMv4FvK.js} +1 -1
- package/dist/renderer/assets/{Modal-ChSm7tk6.js → Modal-BYTZpyD2.js} +3 -3
- package/dist/renderer/assets/{MonitorList-DrEwyS71.js → MonitorList-DzcwVuQO.js} +1 -1
- package/dist/renderer/assets/{Page-DhD-zgMU.js → Page-B0lex3w0.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-BVSjpfpL.js → ProjectDetail-zhmSLySm.js} +2 -2
- package/dist/renderer/assets/{ProjectList-CHGbTJjk.js → ProjectList-DZr7agnE.js} +1 -1
- package/dist/renderer/assets/{Select-rHs9CSam.js → Select-CybeCWXZ.js} +1 -1
- package/dist/renderer/assets/SessionChat-DfsXUkfX.js +1 -0
- package/dist/renderer/assets/{SessionList-Mr1uAnRW.js → SessionList-BHzY2T_K.js} +1 -1
- package/dist/renderer/assets/ThreadChat-BB_Y2SLO.js +28 -0
- package/dist/renderer/assets/{Workspace-MRRg8ndJ.js → Workspace-COip3Zy2.js} +1 -1
- package/dist/renderer/assets/{arrow-left-BU2NB2LA.js → arrow-left-SFlZE8SW.js} +1 -1
- package/dist/renderer/assets/{book-open-D-TGvWwa.js → book-open-CENFRKvo.js} +1 -1
- package/dist/renderer/assets/{bot-IYNh8tH5.js → bot-DeqZUVXX.js} +1 -1
- package/dist/renderer/assets/{check-CCZ0JO_S.js → check-BNBksd9W.js} +1 -1
- package/dist/renderer/assets/{chevron-down-00bRZi15.js → chevron-down-BOhwopXd.js} +1 -1
- package/dist/renderer/assets/{circle-CpQ8x4k_.js → circle-BTT_e1ZT.js} +1 -1
- package/dist/renderer/assets/{desktop-D0k2aGSj.js → desktop-D88Gquih.js} +1 -1
- package/dist/renderer/assets/{funnel-UbcrCBCp.js → funnel-Btin4gwi.js} +1 -1
- package/dist/renderer/assets/{heart-DvLsV7tL.js → heart-BCqqkImr.js} +1 -1
- package/dist/renderer/assets/index-CjCuR6DI.css +11 -0
- package/dist/renderer/assets/{index-B2L4G-b_.js → index-DvKeLUQ8.js} +2 -2
- package/dist/renderer/assets/{index-dy-g2Bh4.js → index-on-scaWG.js} +9 -9
- package/dist/renderer/assets/{pencil-qBYOgW5M.js → pencil-BHu_seP7.js} +1 -1
- package/dist/renderer/assets/{play-Dn6b4AGj.js → play-BoIfwVcE.js} +1 -1
- package/dist/renderer/assets/{plus-CaApUwEm.js → plus-_5sDk2H8.js} +1 -1
- package/dist/renderer/assets/projects-BR_Y3Dov.js +1 -0
- package/dist/renderer/assets/{save-CN6yvTfD.js → save-Bn9HUt7T.js} +1 -1
- package/dist/renderer/assets/{search-Dn2MxYiO.js → search-BOU1rpMw.js} +1 -1
- package/dist/renderer/assets/{server-DpcVLHeh.js → server-BKF47usT.js} +1 -1
- package/dist/renderer/assets/{session-utils-DnD2Q_y1.js → session-utils-B4vjXX1q.js} +1 -1
- package/dist/renderer/assets/{sessions-eK5D4FLt.js → sessions-CtFBPvOB.js} +1 -1
- package/dist/renderer/assets/{shield-check-DSSJkacw.js → shield-check-Q1O3wIT4.js} +1 -1
- package/dist/renderer/assets/{trash-2-DmYJlEvO.js → trash-2-CANqI4Db.js} +1 -1
- package/dist/renderer/assets/{user-Cvf_uiyQ.js → user-DTURDktb.js} +1 -1
- package/dist/renderer/assets/{wifi-off-CCTloj-V.js → wifi-off-YfCo8Dbk.js} +1 -1
- package/dist/renderer/index.html +2 -2
- package/dist-electron/packages/core-sdk/src/index.js +4 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +51 -6
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +3 -0
- package/dist-electron/services/local-ai-core/src/acp/store/platform-store.js +13 -5
- package/dist-electron/services/local-ai-core/src/acp/store/schema.js +1 -0
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +3 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +4 -1
- package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +14 -3
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +10 -3
- package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +4 -0
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +3 -0
- package/dist-electron/services/local-ai-core/src/scheduler/channel-execution-policy.js +3 -1
- package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +2 -1
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +10 -1
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +2 -1
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +10 -1
- package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +23 -2
- package/dist-electron/services/local-ai-core/src/thread/thread-slash-command-dispatcher.js +1 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +2 -0
- package/dist-electron/tests/electron/workspace-task-store.test.js +22 -3
- package/dist-electron/tests/integration/local-core-refactor.test.js +253 -0
- package/dist-electron/tests/integration/local-core-routes.test.js +45 -0
- package/package.json +2 -2
- package/dist/renderer/assets/SessionChat-CDc2FNMA.js +0 -1
- package/dist/renderer/assets/ThreadChat-Detu5UfN.js +0 -23
- package/dist/renderer/assets/index-CO4fGqmv.css +0 -11
- package/dist/renderer/assets/projects-BwF5RlNV.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{D as t}from"./index-on-scaWG.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as o}from"./index-on-scaWG.js";const i=s=>o.get(`/projects/${s}/sessions`),c=(s,e,t)=>o.get(`/projects/${s}/sessions/${e}`,{history_limit:String(t)}),r=(s,e,t)=>o.patch(`/projects/${s}/sessions/${e}`,t),a=(s,e)=>o.delete(`/projects/${s}/sessions/${e}`),p=(s,e)=>o.post(`/projects/${s}/sessions/switch`,e),$=(s,e)=>o.post(`/projects/${s}/send`,e);export{$ as a,a as d,c as g,i as l,r,p as s};
|
package/dist/renderer/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>AgentDock</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-on-scaWG.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CjCuR6DI.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body class="bg-[#f5f5f7] dark:bg-[#151516]">
|
|
12
12
|
<div id="root"></div>
|
|
@@ -85,6 +85,7 @@ exports.createThread = createThread;
|
|
|
85
85
|
exports.getThread = getThread;
|
|
86
86
|
exports.renameThread = renameThread;
|
|
87
87
|
exports.updateThreadKnowledgeBases = updateThreadKnowledgeBases;
|
|
88
|
+
exports.updateThreadMode = updateThreadMode;
|
|
88
89
|
exports.deleteThread = deleteThread;
|
|
89
90
|
exports.sendMessage = sendMessage;
|
|
90
91
|
exports.sendAction = sendAction;
|
|
@@ -498,6 +499,9 @@ async function renameThread(threadId, title) {
|
|
|
498
499
|
async function updateThreadKnowledgeBases(threadId, knowledgeBaseIds) {
|
|
499
500
|
return coreRequest('PATCH', `/threads/${encodeURIComponent(threadId)}/knowledge-bases`, { knowledgeBaseIds });
|
|
500
501
|
}
|
|
502
|
+
async function updateThreadMode(threadId, mode) {
|
|
503
|
+
return coreRequest('PATCH', `/threads/${encodeURIComponent(threadId)}/mode`, { mode });
|
|
504
|
+
}
|
|
501
505
|
async function deleteThread(threadId) {
|
|
502
506
|
return coreRequest('DELETE', `/threads/${encodeURIComponent(threadId)}`);
|
|
503
507
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LocalCoreAcpSessionCoordinator = void 0;
|
|
4
4
|
exports.buildAgentPath = buildAgentPath;
|
|
5
5
|
const node_path_1 = require("node:path");
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
6
7
|
const node_os_1 = require("node:os");
|
|
7
8
|
const scheduled_job_route_js_1 = require("../scheduler/scheduled-job-route.js");
|
|
8
9
|
const env_utils_js_1 = require("../runtime/env-utils.js");
|
|
@@ -290,11 +291,14 @@ exports.LocalCoreAcpSessionCoordinator = LocalCoreAcpSessionCoordinator;
|
|
|
290
291
|
function acpSessionCwd(config) {
|
|
291
292
|
return config.sandbox?.enabled ? config.sandbox.workspaceMountPath : config.workDir;
|
|
292
293
|
}
|
|
293
|
-
function buildAgentPath(existingPath, cliBinDir) {
|
|
294
|
+
function buildAgentPath(existingPath, cliBinDir, options = {}) {
|
|
295
|
+
const platform = options.platform || process.platform;
|
|
296
|
+
const pathDelimiter = platform === 'win32' ? ';' : node_path_1.delimiter;
|
|
294
297
|
const entries = [
|
|
295
298
|
cliBinDir,
|
|
296
|
-
...userBinDirs(),
|
|
297
|
-
...
|
|
299
|
+
...userBinDirs(platform),
|
|
300
|
+
...windowsGitBashDirs(existingPath, platform, options.pathExists || node_fs_1.existsSync),
|
|
301
|
+
...String(existingPath || '').split(pathDelimiter),
|
|
298
302
|
];
|
|
299
303
|
const seen = new Set();
|
|
300
304
|
return entries
|
|
@@ -306,12 +310,53 @@ function buildAgentPath(existingPath, cliBinDir) {
|
|
|
306
310
|
seen.add(entry);
|
|
307
311
|
return true;
|
|
308
312
|
})
|
|
309
|
-
.join(
|
|
313
|
+
.join(pathDelimiter);
|
|
310
314
|
}
|
|
311
|
-
function userBinDirs() {
|
|
312
|
-
if (
|
|
315
|
+
function userBinDirs(platform) {
|
|
316
|
+
if (platform === 'win32') {
|
|
313
317
|
return [];
|
|
314
318
|
}
|
|
315
319
|
const home = process.env.HOME || (0, node_os_1.homedir)();
|
|
316
320
|
return home ? [`${home}/.local/bin`, `${home}/bin`] : [];
|
|
317
321
|
}
|
|
322
|
+
function windowsGitBashDirs(existingPath, platform, pathExists) {
|
|
323
|
+
if (platform !== 'win32') {
|
|
324
|
+
return [];
|
|
325
|
+
}
|
|
326
|
+
const pathEntries = String(existingPath || '')
|
|
327
|
+
.split(';')
|
|
328
|
+
.map((entry) => entry.trim())
|
|
329
|
+
.filter(Boolean);
|
|
330
|
+
const gitRoots = new Set();
|
|
331
|
+
for (const entry of pathEntries) {
|
|
332
|
+
const normalized = node_path_1.win32.normalize(entry).replace(/[\\/]+$/, '');
|
|
333
|
+
const base = node_path_1.win32.basename(normalized).toLowerCase();
|
|
334
|
+
const parent = node_path_1.win32.dirname(normalized);
|
|
335
|
+
const parentBase = node_path_1.win32.basename(parent).toLowerCase();
|
|
336
|
+
const grandParent = node_path_1.win32.dirname(parent);
|
|
337
|
+
if (base === 'cmd' && parentBase === 'git') {
|
|
338
|
+
gitRoots.add(parent);
|
|
339
|
+
}
|
|
340
|
+
else if (base === 'bin' && parentBase === 'git') {
|
|
341
|
+
gitRoots.add(parent);
|
|
342
|
+
}
|
|
343
|
+
else if (base === 'bin' && parentBase === 'usr' && node_path_1.win32.basename(grandParent).toLowerCase() === 'git') {
|
|
344
|
+
gitRoots.add(grandParent);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
for (const root of ['C:\\Program Files\\Git', 'C:\\Program Files (x86)\\Git', 'D:\\Program Files\\Git']) {
|
|
348
|
+
gitRoots.add(root);
|
|
349
|
+
}
|
|
350
|
+
const dirs = [];
|
|
351
|
+
for (const root of gitRoots) {
|
|
352
|
+
const binDir = node_path_1.win32.join(root, 'bin');
|
|
353
|
+
if (pathExists(node_path_1.win32.join(binDir, 'bash.exe'))) {
|
|
354
|
+
dirs.push(binDir);
|
|
355
|
+
}
|
|
356
|
+
const usrBinDir = node_path_1.win32.join(root, 'usr', 'bin');
|
|
357
|
+
if (pathExists(node_path_1.win32.join(usrBinDir, 'bash.exe'))) {
|
|
358
|
+
dirs.push(usrBinDir);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return dirs;
|
|
362
|
+
}
|
|
@@ -281,6 +281,9 @@ class LocalCoreAcpStore {
|
|
|
281
281
|
upsertPlatformThreadBinding(input) {
|
|
282
282
|
this.platform.upsertPlatformThreadBinding(input);
|
|
283
283
|
}
|
|
284
|
+
updatePlatformThreadPreferredAgent(workspaceId, chatId, platformUserId, agentType, platform = 'lark') {
|
|
285
|
+
this.platform.updatePlatformThreadPreferredAgent(workspaceId, chatId, platformUserId, agentType, platform);
|
|
286
|
+
}
|
|
284
287
|
updatePlatformThreadMessageId(workspaceId, chatId, platformUserId, messageId, platform = 'lark') {
|
|
285
288
|
this.platform.updatePlatformThreadMessageId(workspaceId, chatId, platformUserId, messageId, platform);
|
|
286
289
|
}
|
|
@@ -107,14 +107,14 @@ class LocalPlatformStore {
|
|
|
107
107
|
}
|
|
108
108
|
getPlatformThreadBinding(workspaceId, chatId, platformUserId, platform = 'lark') {
|
|
109
109
|
return this.db.prepare(`
|
|
110
|
-
SELECT workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, created_at, updated_at
|
|
110
|
+
SELECT workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, preferred_agent_type, created_at, updated_at
|
|
111
111
|
FROM platform_thread_bindings
|
|
112
112
|
WHERE workspace_id = ? AND platform = ? AND chat_id = ? AND platform_user_id = ?
|
|
113
113
|
`).get(workspaceId, platform, chatId, platformUserId);
|
|
114
114
|
}
|
|
115
115
|
getPlatformThreadBindingByThreadId(threadId) {
|
|
116
116
|
return this.db.prepare(`
|
|
117
|
-
SELECT workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, created_at, updated_at
|
|
117
|
+
SELECT workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, preferred_agent_type, created_at, updated_at
|
|
118
118
|
FROM platform_thread_bindings
|
|
119
119
|
WHERE thread_id = ?
|
|
120
120
|
ORDER BY updated_at DESC
|
|
@@ -127,13 +127,21 @@ class LocalPlatformStore {
|
|
|
127
127
|
upsertPlatformThreadBinding(input) {
|
|
128
128
|
this.db.prepare(`
|
|
129
129
|
INSERT INTO platform_thread_bindings
|
|
130
|
-
(workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, created_at, updated_at)
|
|
131
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
130
|
+
(workspace_id, platform, chat_id, platform_user_id, thread_id, last_platform_message_id, preferred_agent_type, created_at, updated_at)
|
|
131
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
132
132
|
ON CONFLICT(workspace_id, platform, chat_id, platform_user_id) DO UPDATE SET
|
|
133
133
|
thread_id = excluded.thread_id,
|
|
134
134
|
last_platform_message_id = COALESCE(excluded.last_platform_message_id, platform_thread_bindings.last_platform_message_id),
|
|
135
|
+
preferred_agent_type = COALESCE(excluded.preferred_agent_type, platform_thread_bindings.preferred_agent_type),
|
|
135
136
|
updated_at = excluded.updated_at
|
|
136
|
-
`).run(input.workspace_id, input.platform || 'lark', input.chat_id, input.platform_user_id, input.thread_id, input.last_platform_message_id, input.created_at, input.updated_at);
|
|
137
|
+
`).run(input.workspace_id, input.platform || 'lark', input.chat_id, input.platform_user_id, input.thread_id, input.last_platform_message_id, input.preferred_agent_type ?? null, input.created_at, input.updated_at);
|
|
138
|
+
}
|
|
139
|
+
updatePlatformThreadPreferredAgent(workspaceId, chatId, platformUserId, agentType, platform = 'lark') {
|
|
140
|
+
this.db.prepare(`
|
|
141
|
+
UPDATE platform_thread_bindings
|
|
142
|
+
SET preferred_agent_type = ?, updated_at = ?
|
|
143
|
+
WHERE workspace_id = ? AND platform = ? AND chat_id = ? AND platform_user_id = ?
|
|
144
|
+
`).run(agentType, new Date().toISOString(), workspaceId, platform, chatId, platformUserId);
|
|
137
145
|
}
|
|
138
146
|
updatePlatformThreadMessageId(workspaceId, chatId, platformUserId, messageId, platform = 'lark') {
|
|
139
147
|
this.db.prepare(`
|
|
@@ -301,6 +301,7 @@ function ensureLocalCoreAcpSchema(db) {
|
|
|
301
301
|
ensureColumn(db, 'messages', 'tool_call_json', 'TEXT');
|
|
302
302
|
ensureColumn(db, 'messages', 'bridge_kind', 'TEXT');
|
|
303
303
|
ensureColumn(db, 'messages', 'bridge_status', 'TEXT');
|
|
304
|
+
ensureColumn(db, 'platform_thread_bindings', 'preferred_agent_type', 'TEXT');
|
|
304
305
|
ensureColumn(db, 'scheduled_jobs', 'execution_mode', "TEXT NOT NULL DEFAULT 'same-thread'");
|
|
305
306
|
ensureColumn(db, 'scheduled_job_runs', 'platform_message_ids_json', 'TEXT');
|
|
306
307
|
ensureColumn(db, 'scheduled_job_runs', 'delivery_mode', 'TEXT');
|
|
@@ -31,6 +31,7 @@ class LocalThreadStore {
|
|
|
31
31
|
runId: undefined,
|
|
32
32
|
bridgeSessionKey: row.bridge_session_key,
|
|
33
33
|
agentType: row.agent_type,
|
|
34
|
+
agentMode: row.agent_mode,
|
|
34
35
|
}));
|
|
35
36
|
}
|
|
36
37
|
count(workspaceId) {
|
|
@@ -57,6 +58,7 @@ class LocalThreadStore {
|
|
|
57
58
|
excerpt: '',
|
|
58
59
|
bridgeSessionKey,
|
|
59
60
|
agentType,
|
|
61
|
+
agentMode: agentMode || 'default',
|
|
60
62
|
messages: [],
|
|
61
63
|
selectedKnowledgeBaseIds: [],
|
|
62
64
|
pendingPermissionRequest: null,
|
|
@@ -84,6 +86,7 @@ class LocalThreadStore {
|
|
|
84
86
|
excerpt: row.excerpt,
|
|
85
87
|
bridgeSessionKey: row.bridge_session_key,
|
|
86
88
|
agentType: row.agent_type,
|
|
89
|
+
agentMode: row.agent_mode,
|
|
87
90
|
messages: messages.map((message) => ({
|
|
88
91
|
id: message.id,
|
|
89
92
|
role: message.role,
|
|
@@ -35,9 +35,12 @@ class BaseChannelGateway extends node_events_1.EventEmitter {
|
|
|
35
35
|
getLatestRunForThread: (threadId) => options.store.getLatestRunForThread(threadId),
|
|
36
36
|
createAuditEvent: (input) => options.store.createAuditEvent(input),
|
|
37
37
|
getAgentTypes: () => options.getWorkspaceRouter().getAgentTypes(),
|
|
38
|
-
setThreadMode: (threadId, mode) =>
|
|
38
|
+
setThreadMode: async (threadId, mode) => {
|
|
39
|
+
await options.getWorkspaceRouter().setThreadMode(threadId, mode);
|
|
40
|
+
},
|
|
39
41
|
closeThreadSession: (threadId) => options.getWorkspaceRouter().closeThreadSession(threadId),
|
|
40
42
|
interruptRun: (runId) => options.getWorkspaceRouter().interruptRun(runId),
|
|
43
|
+
setChannelPreferredAgent: (input) => options.store.updatePlatformThreadPreferredAgent(input.workspaceId, input.chatId, input.platformUserId, input.agentType, input.platform),
|
|
41
44
|
log: options.log,
|
|
42
45
|
},
|
|
43
46
|
});
|
|
@@ -13,6 +13,11 @@ class ChannelSessionCommandRuntime {
|
|
|
13
13
|
content: input.text,
|
|
14
14
|
defaultTitle: input.defaultTitle,
|
|
15
15
|
defaultAgentType: input.defaultAgentType,
|
|
16
|
+
channel: {
|
|
17
|
+
chatId: input.chatId,
|
|
18
|
+
platformUserId: input.platformUserId,
|
|
19
|
+
platform: input.platformKey,
|
|
20
|
+
},
|
|
16
21
|
});
|
|
17
22
|
if (!result.handled) {
|
|
18
23
|
return { handled: false, threadId: input.currentThreadId };
|
|
@@ -20,7 +25,7 @@ class ChannelSessionCommandRuntime {
|
|
|
20
25
|
let activeThreadId = input.currentThreadId;
|
|
21
26
|
for (const effect of result.effects || []) {
|
|
22
27
|
if (effect.type === 'created_thread') {
|
|
23
|
-
this.
|
|
28
|
+
this.inheritAgentState(input, input.currentThreadId, effect.threadId);
|
|
24
29
|
}
|
|
25
30
|
if (effect.type === 'activate_thread') {
|
|
26
31
|
activeThreadId = effect.threadId;
|
|
@@ -30,11 +35,17 @@ class ChannelSessionCommandRuntime {
|
|
|
30
35
|
await this.options.sendResult(input, result);
|
|
31
36
|
return { handled: true, threadId: activeThreadId, result };
|
|
32
37
|
}
|
|
33
|
-
|
|
34
|
-
const
|
|
38
|
+
inheritAgentState(input, sourceThreadId, targetThreadId) {
|
|
39
|
+
const sourceRow = this.options.store.getThreadRow?.(sourceThreadId);
|
|
40
|
+
const inheritedMode = sourceRow?.agent_mode || '';
|
|
35
41
|
if (inheritedMode && inheritedMode !== 'default') {
|
|
36
42
|
this.options.store.updateThreadAgentMode?.(targetThreadId, inheritedMode);
|
|
37
43
|
}
|
|
44
|
+
const binding = this.options.store.getPlatformThreadBinding?.(input.workspaceId, input.chatId, input.platformUserId, input.platformKey);
|
|
45
|
+
const preferredAgent = binding?.preferred_agent_type || sourceRow?.agent_type || '';
|
|
46
|
+
if (preferredAgent) {
|
|
47
|
+
this.options.store.updateThreadAgentType?.(targetThreadId, preferredAgent);
|
|
48
|
+
}
|
|
38
49
|
}
|
|
39
50
|
activateThread(input, threadId) {
|
|
40
51
|
const now = new Date().toISOString();
|
|
@@ -5,6 +5,7 @@ exports.createWorkspaceRouter = createWorkspaceRouter;
|
|
|
5
5
|
const node_fs_1 = require("node:fs");
|
|
6
6
|
const node_child_process_1 = require("node:child_process");
|
|
7
7
|
const local_core_acp_backend_js_1 = require("../acp/local-core-acp-backend.js");
|
|
8
|
+
const local_core_slash_commands_js_1 = require("../acp/local-core-slash-commands.js");
|
|
8
9
|
const workspace_thread_id_js_1 = require("../thread/workspace-thread-id.js");
|
|
9
10
|
const command_risk_js_1 = require("../security/command-risk.js");
|
|
10
11
|
const workspace_route_config_js_1 = require("./workspace-route-config.js");
|
|
@@ -176,9 +177,9 @@ class WorkspaceRouter {
|
|
|
176
177
|
await this.getWorkspaceRoute(workspaceId);
|
|
177
178
|
return this.localCoreAcp.listThreads(workspaceId);
|
|
178
179
|
}
|
|
179
|
-
async createThread(workspaceId, title) {
|
|
180
|
+
async createThread(workspaceId, title, agentType) {
|
|
180
181
|
const route = await this.getWorkspaceRoute(workspaceId);
|
|
181
|
-
return this.withKnowledge(await this.localCoreAcp.createThread(workspaceId, title || `New thread ${new Date().toLocaleTimeString()}`, route.agentType));
|
|
182
|
+
return this.withKnowledge(await this.localCoreAcp.createThread(workspaceId, title || `New thread ${new Date().toLocaleTimeString()}`, agentType || route.agentType));
|
|
182
183
|
}
|
|
183
184
|
async getThread(threadId) {
|
|
184
185
|
const { workspaceId } = (0, workspace_thread_id_js_1.decodeThreadId)(threadId);
|
|
@@ -226,7 +227,13 @@ class WorkspaceRouter {
|
|
|
226
227
|
async setThreadMode(threadId, mode) {
|
|
227
228
|
const { workspaceId } = (0, workspace_thread_id_js_1.decodeThreadId)(threadId);
|
|
228
229
|
await this.getWorkspaceRoute(workspaceId);
|
|
229
|
-
|
|
230
|
+
const normalizedMode = (0, local_core_slash_commands_js_1.normalizeAgentMode)(mode) || (String(mode || '').trim() === '' ? local_core_slash_commands_js_1.DEFAULT_AGENT_MODE : '');
|
|
231
|
+
if (!normalizedMode) {
|
|
232
|
+
throw new Error(`Unknown thread mode: ${mode}`);
|
|
233
|
+
}
|
|
234
|
+
this.store.updateThreadAgentMode(threadId, normalizedMode);
|
|
235
|
+
await this.localCoreAcp.setThreadMode(threadId, normalizedMode);
|
|
236
|
+
return this.getThread(threadId);
|
|
230
237
|
}
|
|
231
238
|
closeThreadSession(threadId) {
|
|
232
239
|
this.localCoreAcp.closeThreadSession(threadId);
|
|
@@ -21,6 +21,10 @@ function registerThreadHandlers(map, workspaceRouter) {
|
|
|
21
21
|
: [];
|
|
22
22
|
(0, server_helpers_js_1.json)(res, 200, await workspaceRouter.updateThreadKnowledgeBases(route.threadId, knowledgeBaseIds));
|
|
23
23
|
});
|
|
24
|
+
map.set('thread.update-mode', async (route, req, res) => {
|
|
25
|
+
const body = await (0, server_helpers_js_1.readJsonBody)(req);
|
|
26
|
+
(0, server_helpers_js_1.json)(res, 200, await workspaceRouter.setThreadMode(route.threadId, String(body.mode || '')));
|
|
27
|
+
});
|
|
24
28
|
map.set('thread.rename', async (route, req, res) => {
|
|
25
29
|
const body = await (0, server_helpers_js_1.readJsonBody)(req);
|
|
26
30
|
(0, server_helpers_js_1.json)(res, 200, await workspaceRouter.renameThread(route.threadId, String(body.title || '')));
|
|
@@ -239,6 +239,9 @@ function parseThreadsRoute(method, segments) {
|
|
|
239
239
|
if (method === 'PATCH' && segments.length === 3 && segments[2] === 'knowledge-bases') {
|
|
240
240
|
return { name: 'thread.update-knowledge-bases', threadId };
|
|
241
241
|
}
|
|
242
|
+
if (method === 'PATCH' && segments.length === 3 && segments[2] === 'mode') {
|
|
243
|
+
return { name: 'thread.update-mode', threadId };
|
|
244
|
+
}
|
|
242
245
|
if (method === 'POST' && segments.length === 3 && segments[2] === 'messages') {
|
|
243
246
|
return { name: 'thread.messages.send', threadId };
|
|
244
247
|
}
|
|
@@ -55,7 +55,9 @@ class SideThreadChannelExecutionPolicy {
|
|
|
55
55
|
]);
|
|
56
56
|
const existing = (await this.options.workspaceRouter.listThreads(job.workspaceId))
|
|
57
57
|
.find((thread) => reusableTitles.has(thread.title));
|
|
58
|
-
const
|
|
58
|
+
const preferredAgent = this.config.preferredAgentType?.(job) || '';
|
|
59
|
+
const threadId = existing?.id
|
|
60
|
+
|| (await this.options.workspaceRouter.createThread(job.workspaceId, title, preferredAgent || undefined)).id;
|
|
59
61
|
return {
|
|
60
62
|
kind: `${this.config.platformBase}:side-thread`,
|
|
61
63
|
threadId,
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createLarkExecutionPolicy = createLarkExecutionPolicy;
|
|
4
4
|
const channel_execution_policy_js_1 = require("./channel-execution-policy.js");
|
|
5
|
-
function createLarkExecutionPolicy(job, options, resolveSameThread) {
|
|
5
|
+
function createLarkExecutionPolicy(job, options, resolveSameThread, preferredAgentType) {
|
|
6
6
|
return (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
|
|
7
7
|
platformBase: 'lark',
|
|
8
8
|
resolveSameThread,
|
|
9
9
|
sideThreadTitle: (nextJob) => `[Scheduled:Lark] ${nextJob.description || nextJob.id}`,
|
|
10
10
|
legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
|
|
11
|
+
preferredAgentType,
|
|
11
12
|
});
|
|
12
13
|
}
|
|
@@ -24,7 +24,7 @@ class LarkScheduleAdapter {
|
|
|
24
24
|
store: this.options.store,
|
|
25
25
|
workspaceRouter: this.options.getWorkspaceRouter(),
|
|
26
26
|
getChannelRuntime: this.options.getChannelRuntime,
|
|
27
|
-
}, (nextJob) => this.resolveThread(nextJob));
|
|
27
|
+
}, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
|
|
28
28
|
const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
|
|
29
29
|
return {
|
|
30
30
|
threadId: execution.threadId,
|
|
@@ -74,5 +74,14 @@ class LarkScheduleAdapter {
|
|
|
74
74
|
return false;
|
|
75
75
|
}
|
|
76
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
|
+
}
|
|
77
86
|
}
|
|
78
87
|
exports.LarkScheduleAdapter = LarkScheduleAdapter;
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createWeixinExecutionPolicy = createWeixinExecutionPolicy;
|
|
4
4
|
const channel_execution_policy_js_1 = require("./channel-execution-policy.js");
|
|
5
|
-
function createWeixinExecutionPolicy(job, options, resolveSameThread) {
|
|
5
|
+
function createWeixinExecutionPolicy(job, options, resolveSameThread, preferredAgentType) {
|
|
6
6
|
return (0, channel_execution_policy_js_1.createChannelExecutionPolicy)(job, options, {
|
|
7
7
|
platformBase: 'weixin',
|
|
8
8
|
resolveSameThread,
|
|
9
9
|
sideThreadTitle: (nextJob) => `[Scheduled:Weixin] ${nextJob.description || nextJob.id}`,
|
|
10
10
|
legacySideThreadTitles: (nextJob) => [`[Scheduled] ${nextJob.description || nextJob.id}`],
|
|
11
|
+
preferredAgentType,
|
|
11
12
|
});
|
|
12
13
|
}
|
|
@@ -24,7 +24,7 @@ class WeixinScheduleAdapter {
|
|
|
24
24
|
store: this.options.store,
|
|
25
25
|
workspaceRouter: this.options.getWorkspaceRouter(),
|
|
26
26
|
getChannelRuntime: this.options.getChannelRuntime,
|
|
27
|
-
}, (nextJob) => this.resolveThread(nextJob));
|
|
27
|
+
}, (nextJob) => this.resolveThread(nextJob), (nextJob) => this.preferredAgentFor(nextJob));
|
|
28
28
|
const execution = await this.executor.execute(job, job.promptTemplate, executionPolicy);
|
|
29
29
|
return {
|
|
30
30
|
threadId: execution.threadId,
|
|
@@ -74,5 +74,14 @@ class WeixinScheduleAdapter {
|
|
|
74
74
|
return false;
|
|
75
75
|
}
|
|
76
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
|
+
}
|
|
77
86
|
}
|
|
78
87
|
exports.WeixinScheduleAdapter = WeixinScheduleAdapter;
|
|
@@ -27,7 +27,7 @@ class ThreadCommandService {
|
|
|
27
27
|
names: ['agent'],
|
|
28
28
|
execute: (command, input) => ({
|
|
29
29
|
handled: true,
|
|
30
|
-
displayText: this.executeAgentCommand(input.threadId, input.workspaceId, command.args, input.defaultAgentType),
|
|
30
|
+
displayText: this.executeAgentCommand(input.threadId, input.workspaceId, command.args, input.defaultAgentType, input.channel),
|
|
31
31
|
}),
|
|
32
32
|
});
|
|
33
33
|
}
|
|
@@ -64,7 +64,7 @@ class ThreadCommandService {
|
|
|
64
64
|
}
|
|
65
65
|
return `已切换到 ${(0, local_core_slash_commands_js_1.formatAgentMode)(mode)} 模式。`;
|
|
66
66
|
}
|
|
67
|
-
executeAgentCommand(threadId, workspaceId, args, defaultAgentType) {
|
|
67
|
+
executeAgentCommand(threadId, workspaceId, args, defaultAgentType, channel) {
|
|
68
68
|
const row = this.options.getThreadRow(threadId);
|
|
69
69
|
const currentAgent = (0, local_core_slash_commands_js_1.normalizeAgentCommandTarget)(row?.agent_type || defaultAgentType);
|
|
70
70
|
const defaultAgent = (0, local_core_slash_commands_js_1.normalizeAgentCommandTarget)(defaultAgentType);
|
|
@@ -84,6 +84,7 @@ class ThreadCommandService {
|
|
|
84
84
|
}
|
|
85
85
|
if (action === 'reset') {
|
|
86
86
|
if (currentAgent === defaultAgent) {
|
|
87
|
+
this.persistChannelPreferredAgent(channel, workspaceId, null);
|
|
87
88
|
return `当前线程已经使用默认 Agent:${defaultAgent}。`;
|
|
88
89
|
}
|
|
89
90
|
const activeRun = this.hasActiveRun(threadId);
|
|
@@ -91,6 +92,7 @@ class ThreadCommandService {
|
|
|
91
92
|
if (!activeRun) {
|
|
92
93
|
this.options.closeThreadSession?.(threadId);
|
|
93
94
|
}
|
|
95
|
+
this.persistChannelPreferredAgent(channel, workspaceId, null);
|
|
94
96
|
this.options.createAuditEvent({
|
|
95
97
|
type: 'agent.changed',
|
|
96
98
|
workspaceId,
|
|
@@ -114,6 +116,7 @@ class ThreadCommandService {
|
|
|
114
116
|
return `Agent "${canonicalAgent}" 当前不可用。\n可用 Agent:${availableAgents.length ? availableAgents.join(', ') : '无'}`;
|
|
115
117
|
}
|
|
116
118
|
if (canonicalAgent === currentAgent) {
|
|
119
|
+
this.persistChannelPreferredAgent(channel, workspaceId, canonicalAgent);
|
|
117
120
|
return `当前线程已经使用 Agent:${canonicalAgent}。`;
|
|
118
121
|
}
|
|
119
122
|
const activeRun = this.hasActiveRun(threadId);
|
|
@@ -121,6 +124,7 @@ class ThreadCommandService {
|
|
|
121
124
|
if (!activeRun) {
|
|
122
125
|
this.options.closeThreadSession?.(threadId);
|
|
123
126
|
}
|
|
127
|
+
this.persistChannelPreferredAgent(channel, workspaceId, canonicalAgent);
|
|
124
128
|
const runningNote = activeRun
|
|
125
129
|
? `\n当前正在运行的任务仍会继续使用 ${currentAgent},下一轮开始生效。`
|
|
126
130
|
: '';
|
|
@@ -133,6 +137,23 @@ class ThreadCommandService {
|
|
|
133
137
|
});
|
|
134
138
|
return `已将当前线程 Agent 切换为 ${canonicalAgent}。\n后续消息将使用 ${canonicalAgent} 处理。${runningNote}`;
|
|
135
139
|
}
|
|
140
|
+
persistChannelPreferredAgent(channel, workspaceId, agentType) {
|
|
141
|
+
if (!channel || !this.options.setChannelPreferredAgent) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
this.options.setChannelPreferredAgent({
|
|
146
|
+
workspaceId,
|
|
147
|
+
chatId: channel.chatId,
|
|
148
|
+
platformUserId: channel.platformUserId,
|
|
149
|
+
platform: channel.platform,
|
|
150
|
+
agentType,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
this.options.log?.(`setChannelPreferredAgent failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
136
157
|
async executeStopCommand(threadId, workspaceId) {
|
|
137
158
|
const latestRun = this.options.getLatestRunForThread(threadId);
|
|
138
159
|
if (!latestRun || !['queued', 'running', 'awaiting_input'].includes(latestRun.status)) {
|
|
@@ -170,6 +170,7 @@ function toChatThreadSummary(project, session) {
|
|
|
170
170
|
updatedAt: session.updated_at,
|
|
171
171
|
excerpt: extractVisibleMessageContent(session.last_message?.content || ''),
|
|
172
172
|
agentType: session.agent_type,
|
|
173
|
+
agentMode: undefined,
|
|
173
174
|
bridgeSessionKey: session.session_key,
|
|
174
175
|
};
|
|
175
176
|
}
|
|
@@ -183,6 +184,7 @@ function toCoreChatThreadSummary(thread) {
|
|
|
183
184
|
updatedAt: thread.updatedAt,
|
|
184
185
|
excerpt: extractVisibleMessageContent(thread.excerpt),
|
|
185
186
|
agentType: thread.agentType,
|
|
187
|
+
agentMode: thread.agentMode,
|
|
186
188
|
bridgeSessionKey: thread.bridgeSessionKey,
|
|
187
189
|
};
|
|
188
190
|
}
|