botmux 2.95.0 → 2.96.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +4 -4
- package/README.md +3 -3
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +6 -10
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/cli/kimi.d.ts +4 -0
- package/dist/adapters/cli/kimi.d.ts.map +1 -0
- package/dist/adapters/cli/kimi.js +54 -0
- package/dist/adapters/cli/kimi.js.map +1 -0
- package/dist/adapters/cli/registry.d.ts +2 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +6 -20
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +1 -1
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-installer.d.ts.map +1 -1
- package/dist/adapters/hook-installer.js +138 -28
- package/dist/adapters/hook-installer.js.map +1 -1
- package/dist/bot-registry.d.ts +61 -4
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +164 -3
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/stdin-encoding.d.ts +21 -0
- package/dist/cli/stdin-encoding.d.ts.map +1 -1
- package/dist/cli/stdin-encoding.js +37 -0
- package/dist/cli/stdin-encoding.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -0
- package/dist/config.js.map +1 -1
- package/dist/core/ask-hook/opencode.d.ts +15 -17
- package/dist/core/ask-hook/opencode.d.ts.map +1 -1
- package/dist/core/ask-hook/opencode.js +17 -19
- package/dist/core/ask-hook/opencode.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +1 -0
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +193 -5
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +2 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +2 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +99 -7
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +16 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +68 -11
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +7 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +7 -1
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/session-cleanup.d.ts +1 -0
- package/dist/dashboard/session-cleanup.d.ts.map +1 -1
- package/dist/dashboard/session-cleanup.js +2 -0
- package/dist/dashboard/session-cleanup.js.map +1 -1
- package/dist/dashboard/settings-write-applier.d.ts +2 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +6 -0
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/trigger-api.d.ts +4 -0
- package/dist/dashboard/trigger-api.d.ts.map +1 -1
- package/dist/dashboard/trigger-api.js +20 -0
- package/dist/dashboard/trigger-api.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +1 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +247 -4
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors.d.ts +11 -0
- package/dist/dashboard/web/connectors.d.ts.map +1 -1
- package/dist/dashboard/web/connectors.js +45 -1
- package/dist/dashboard/web/connectors.js.map +1 -1
- package/dist/dashboard/web/groups.d.ts +7 -0
- package/dist/dashboard/web/groups.d.ts.map +1 -1
- package/dist/dashboard/web/groups.js +62 -15
- package/dist/dashboard/web/groups.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +58 -2
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +149 -5
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings.d.ts.map +1 -1
- package/dist/dashboard/web/settings.js +10 -0
- package/dist/dashboard/web/settings.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts.map +1 -1
- package/dist/dashboard/webhook-routes.js +126 -6
- package/dist/dashboard/webhook-routes.js.map +1 -1
- package/dist/dashboard-web/app.js +827 -751
- package/dist/dashboard-web/style.css +47 -0
- package/dist/dashboard.js +85 -6
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts +4 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +2 -0
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +1 -0
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/client.d.ts +12 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +154 -9
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +13 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +200 -16
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts +11 -0
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +2 -1
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/summary-command.d.ts +19 -0
- package/dist/im/lark/summary-command.d.ts.map +1 -0
- package/dist/im/lark/summary-command.js +276 -0
- package/dist/im/lark/summary-command.js.map +1 -0
- package/dist/mir-local-runtime.d.ts +40 -0
- package/dist/mir-local-runtime.d.ts.map +1 -1
- package/dist/mir-local-runtime.js +246 -52
- package/dist/mir-local-runtime.js.map +1 -1
- package/dist/mir-runner.js +26 -1
- package/dist/mir-runner.js.map +1 -1
- package/dist/services/card-prefs-store.d.ts +2 -2
- package/dist/services/card-prefs-store.d.ts.map +1 -1
- package/dist/services/card-prefs-store.js +5 -5
- package/dist/services/card-prefs-store.js.map +1 -1
- package/dist/services/chat-reply-mode-store.d.ts +6 -4
- package/dist/services/chat-reply-mode-store.d.ts.map +1 -1
- package/dist/services/chat-reply-mode-store.js +6 -4
- package/dist/services/chat-reply-mode-store.js.map +1 -1
- package/dist/services/pi-transcript.d.ts +19 -0
- package/dist/services/pi-transcript.d.ts.map +1 -0
- package/dist/services/pi-transcript.js +222 -0
- package/dist/services/pi-transcript.js.map +1 -0
- package/dist/services/seen-message-store.d.ts +12 -0
- package/dist/services/seen-message-store.d.ts.map +1 -0
- package/dist/services/seen-message-store.js +119 -0
- package/dist/services/seen-message-store.js.map +1 -0
- package/dist/services/summary-range-store.d.ts +21 -0
- package/dist/services/summary-range-store.d.ts.map +1 -0
- package/dist/services/summary-range-store.js +89 -0
- package/dist/services/summary-range-store.js.map +1 -0
- package/dist/services/trigger-types.d.ts +14 -2
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/trigger-types.js +15 -1
- package/dist/services/trigger-types.js.map +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +2 -0
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/types.d.ts +20 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/executable.d.ts +3 -0
- package/dist/utils/executable.d.ts.map +1 -0
- package/dist/utils/executable.js +24 -0
- package/dist/utils/executable.js.map +1 -0
- package/dist/worker.js +75 -6
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +8 -8
- package/dist/workflows/events/payloads.d.ts +10 -10
- package/dist/workflows/events/schema.d.ts +28 -28
- package/package.json +1 -1
|
@@ -18,10 +18,11 @@ import * as observedBotsStore from '../services/observed-bots-store.js';
|
|
|
18
18
|
import { getDeploymentIdentity } from '../services/deployment-identity.js';
|
|
19
19
|
import * as grantPrefsStore from '../services/grant-prefs-store.js';
|
|
20
20
|
import { findConfigField, applyConfigField, coerceConfigValue } from '../services/bot-config-store.js';
|
|
21
|
+
import { summaryRangeFromBotConfig, updateDashboardSummaryRange } from '../services/summary-range-store.js';
|
|
21
22
|
import { config } from '../config.js';
|
|
22
23
|
import { computeSandboxDiff, applySandboxDiff } from '../services/sandbox-land.js';
|
|
23
24
|
import { buildSafeInsightConversation, buildSafeInsightOverview, buildSafeInsightReport, buildSafeInsightTurnDetail } from '../services/insight/report.js';
|
|
24
|
-
import { readRawConfig, findEntryIndex, requireConfigPath } from '../services/config-store.js';
|
|
25
|
+
import { readRawConfig, findEntryIndex, requireConfigPath, rmwBotEntry } from '../services/config-store.js';
|
|
25
26
|
import { setDefaultLocale, localeForBot, t } from '../i18n/index.js';
|
|
26
27
|
import { isLocale } from '../i18n/types.js';
|
|
27
28
|
import { readGlobalConfig } from '../global-config.js';
|
|
@@ -44,6 +45,7 @@ import { deleteRoleProfileEntry, deleteRoleProfileIfEmpty, isValidRoleProfileId,
|
|
|
44
45
|
import { triggerSessionTurn } from './trigger-session.js';
|
|
45
46
|
import { triggerWorkflowFromEnvelope } from '../workflows/trigger-from-envelope.js';
|
|
46
47
|
import { validateTriggerRequest } from '../services/trigger-types.js';
|
|
48
|
+
import { resolveCliSelection, selectionKeyForBot } from '../setup/cli-selection.js';
|
|
47
49
|
// Workflow runner is wired by the daemon (it owns the heavy triggerWorkflowRun
|
|
48
50
|
// deps). Until set, workflow-targeted triggers report not-implemented.
|
|
49
51
|
let workflowRunner = null;
|
|
@@ -209,6 +211,46 @@ ipcRoute('POST', '/api/sessions/:sessionId/restart', (_req, res, params) => {
|
|
|
209
211
|
function findSessionRecord(sessionId) {
|
|
210
212
|
return findActiveBySessionId(sessionId)?.session ?? sessionStore.getSession(sessionId);
|
|
211
213
|
}
|
|
214
|
+
function buildAsyncTriggerLookupResponse(sessionId, triggerId) {
|
|
215
|
+
const ds = findActiveBySessionId(sessionId);
|
|
216
|
+
if (!ds) {
|
|
217
|
+
return { ok: false, errorCode: 'session_not_found', error: `active session not found: ${sessionId}` };
|
|
218
|
+
}
|
|
219
|
+
const resolvedTriggerId = triggerId || ds.latestAsyncTriggerId;
|
|
220
|
+
if (!resolvedTriggerId) {
|
|
221
|
+
return { ok: false, errorCode: 'bad_request', error: 'no async trigger recorded for this session' };
|
|
222
|
+
}
|
|
223
|
+
const state = ds.asyncTriggerResults?.get(resolvedTriggerId);
|
|
224
|
+
if (!state) {
|
|
225
|
+
return { ok: false, errorCode: 'bad_request', error: `async trigger not found for session: ${resolvedTriggerId}` };
|
|
226
|
+
}
|
|
227
|
+
if (state.status === 'completed') {
|
|
228
|
+
return {
|
|
229
|
+
ok: true,
|
|
230
|
+
triggerId: resolvedTriggerId,
|
|
231
|
+
action: 'completed',
|
|
232
|
+
target: { kind: 'turn', sessionId, chatId: ds.chatId },
|
|
233
|
+
output: state.content ? { content: state.content } : undefined,
|
|
234
|
+
async: {
|
|
235
|
+
status: 'completed',
|
|
236
|
+
sessionId,
|
|
237
|
+
completedAt: state.completedAt ? new Date(state.completedAt).toISOString() : undefined,
|
|
238
|
+
},
|
|
239
|
+
message: 'async trigger completed',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
ok: true,
|
|
244
|
+
triggerId: resolvedTriggerId,
|
|
245
|
+
action: 'queued',
|
|
246
|
+
target: { kind: 'turn', sessionId, chatId: ds.chatId },
|
|
247
|
+
async: {
|
|
248
|
+
status: 'pending',
|
|
249
|
+
sessionId,
|
|
250
|
+
},
|
|
251
|
+
message: 'async trigger pending',
|
|
252
|
+
};
|
|
253
|
+
}
|
|
212
254
|
// 看板放置:dashboard 看板视图拖拽卡片后持久化列 + 列内排序位置。
|
|
213
255
|
// 改完广播 session.update,所有打开的 dashboard 实时同步。
|
|
214
256
|
ipcRoute('POST', '/api/sessions/:sessionId/board', async (req, res, params) => {
|
|
@@ -352,6 +394,17 @@ ipcRoute('GET', '/api/sessions/:sessionId/history', async (req, res, params) =>
|
|
|
352
394
|
jsonRes(res, 502, { ok: false, error: String(err?.message ?? err) });
|
|
353
395
|
}
|
|
354
396
|
});
|
|
397
|
+
ipcRoute('GET', '/api/sessions/:sessionId/trigger-result', (req, res, params) => {
|
|
398
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
399
|
+
const triggerId = url.searchParams.get('triggerId') ?? undefined;
|
|
400
|
+
const result = buildAsyncTriggerLookupResponse(params.sessionId, triggerId);
|
|
401
|
+
const status = result.ok
|
|
402
|
+
? 200
|
|
403
|
+
: result.errorCode === 'session_not_found'
|
|
404
|
+
? 404
|
|
405
|
+
: 400;
|
|
406
|
+
jsonRes(res, status, result);
|
|
407
|
+
});
|
|
355
408
|
// 会话 insight:只读解析本会话的 transcript,产出动作 span / 失败聚合 / 规则建议
|
|
356
409
|
// (SafeInsightReport)。底层 services/insight 已做 fail-closed 脱敏投影——raw 命令
|
|
357
410
|
// 与输出永不进结构。detail=summary 只返聚合+建议(/insight 卡片、抽屉概览用);
|
|
@@ -487,6 +540,33 @@ ipcRoute('POST', '/api/sessions/:sessionId/rename', async (req, res, params) =>
|
|
|
487
540
|
});
|
|
488
541
|
jsonRes(res, 200, { ok: true, title });
|
|
489
542
|
});
|
|
543
|
+
// 会话锁定:保护被锁定会话不被 dashboard「清理空闲」批量关闭。锁定是会话元数据,
|
|
544
|
+
// 不影响用户显式点击关闭/批量关闭,避免把会话变成不可管理状态。
|
|
545
|
+
ipcRoute('POST', '/api/sessions/:sessionId/lock', async (req, res, params) => {
|
|
546
|
+
let body;
|
|
547
|
+
try {
|
|
548
|
+
body = await readJsonBody(req);
|
|
549
|
+
}
|
|
550
|
+
catch {
|
|
551
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
552
|
+
}
|
|
553
|
+
if (typeof body.locked !== 'boolean')
|
|
554
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_locked' });
|
|
555
|
+
const session = findSessionRecord(params.sessionId);
|
|
556
|
+
if (!session)
|
|
557
|
+
return jsonRes(res, 404, { ok: false, error: 'session_not_found' });
|
|
558
|
+
if (body.locked)
|
|
559
|
+
session.locked = true;
|
|
560
|
+
else
|
|
561
|
+
delete session.locked;
|
|
562
|
+
sessionStore.updateSession(session);
|
|
563
|
+
const locked = !!session.locked;
|
|
564
|
+
dashboardEventBus.publish({
|
|
565
|
+
type: 'session.update',
|
|
566
|
+
body: { sessionId: params.sessionId, patch: { locked } },
|
|
567
|
+
});
|
|
568
|
+
jsonRes(res, 200, { ok: true, locked });
|
|
569
|
+
});
|
|
490
570
|
/**
|
|
491
571
|
* Mint the WRITABLE web-terminal link for a live session — the dashboard
|
|
492
572
|
* counterpart to the Lark card's "🔑 获取操作链接" button. Returns the URL with
|
|
@@ -863,9 +943,11 @@ ipcRoute('POST', '/api/trigger', async (req, res) => {
|
|
|
863
943
|
? 403
|
|
864
944
|
: result.errorCode === 'session_not_found'
|
|
865
945
|
? 404
|
|
866
|
-
: result.errorCode === '
|
|
867
|
-
?
|
|
868
|
-
:
|
|
946
|
+
: result.errorCode === 'wait_timeout'
|
|
947
|
+
? 504
|
|
948
|
+
: result.errorCode === 'target_required' || result.errorCode === 'bad_request'
|
|
949
|
+
? 400
|
|
950
|
+
: 500;
|
|
869
951
|
return jsonRes(res, status, result);
|
|
870
952
|
}
|
|
871
953
|
catch (e) {
|
|
@@ -1180,6 +1262,18 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
|
|
|
1180
1262
|
p2pMode = 'chat';
|
|
1181
1263
|
}
|
|
1182
1264
|
catch { /* default thread */ }
|
|
1265
|
+
let cliId = '';
|
|
1266
|
+
let wrapperCli = null;
|
|
1267
|
+
let model = null;
|
|
1268
|
+
let agentSelectionKey = '';
|
|
1269
|
+
try {
|
|
1270
|
+
const cfg = getBot(cachedLarkAppId).config;
|
|
1271
|
+
cliId = cfg.cliId;
|
|
1272
|
+
wrapperCli = typeof cfg.wrapperCli === 'string' && cfg.wrapperCli.trim() ? cfg.wrapperCli : null;
|
|
1273
|
+
model = typeof cfg.model === 'string' && cfg.model.trim() ? cfg.model : null;
|
|
1274
|
+
agentSelectionKey = selectionKeyForBot(cliId, wrapperCli ?? undefined);
|
|
1275
|
+
}
|
|
1276
|
+
catch { /* no registered bot */ }
|
|
1183
1277
|
let maxLiveWorkers = null;
|
|
1184
1278
|
try {
|
|
1185
1279
|
const m = getBot(cachedLarkAppId).config.maxLiveWorkers;
|
|
@@ -1218,6 +1312,10 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
|
|
|
1218
1312
|
jsonRes(res, 200, {
|
|
1219
1313
|
larkAppId: cachedLarkAppId,
|
|
1220
1314
|
botName: getBotName(),
|
|
1315
|
+
cliId,
|
|
1316
|
+
wrapperCli,
|
|
1317
|
+
model,
|
|
1318
|
+
agentSelectionKey,
|
|
1221
1319
|
defaultOncall: defaultOncall ?? { enabled: false, workingDir: '', since: 0 },
|
|
1222
1320
|
defaultWorkingDir,
|
|
1223
1321
|
autoboundChatCount: autoboundChats.length,
|
|
@@ -1242,6 +1340,7 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
|
|
|
1242
1340
|
startupCommands,
|
|
1243
1341
|
launchShell: getBot(cachedLarkAppId).config.launchShell ?? '',
|
|
1244
1342
|
env,
|
|
1343
|
+
summaryRange: summaryRangeFromBotConfig(getBot(cachedLarkAppId).config),
|
|
1245
1344
|
skills: getBot(cachedLarkAppId).config.skills ?? null,
|
|
1246
1345
|
});
|
|
1247
1346
|
});
|
|
@@ -1279,7 +1378,7 @@ ipcRoute('PUT', '/api/bot-card-prefs', async (req, res) => {
|
|
|
1279
1378
|
if (m)
|
|
1280
1379
|
patch.regularGroupReplyMode = m;
|
|
1281
1380
|
}
|
|
1282
|
-
if (body.regularGroupMentionMode === 'always' || body.regularGroupMentionMode === 'topic' || body.regularGroupMentionMode === 'never') {
|
|
1381
|
+
if (body.regularGroupMentionMode === 'always' || body.regularGroupMentionMode === 'topic' || body.regularGroupMentionMode === 'never' || body.regularGroupMentionMode === 'ambient') {
|
|
1283
1382
|
patch.regularGroupMentionMode = body.regularGroupMentionMode;
|
|
1284
1383
|
}
|
|
1285
1384
|
if (body.docSubscribeDefaultMode === 'mention-only' || body.docSubscribeDefaultMode === 'all') {
|
|
@@ -1292,6 +1391,41 @@ ipcRoute('PUT', '/api/bot-card-prefs', async (req, res) => {
|
|
|
1292
1391
|
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
1293
1392
|
jsonRes(res, 200, { ok: true, ...r.prefs });
|
|
1294
1393
|
});
|
|
1394
|
+
// Per-bot explicit `/summary` history range. Body `{ limit, sinceHours }`.
|
|
1395
|
+
ipcRoute('PUT', '/api/bot-summary-range', async (req, res) => {
|
|
1396
|
+
if (!cachedLarkAppId)
|
|
1397
|
+
return jsonRes(res, 503, { error: 'larkAppId_not_set' });
|
|
1398
|
+
let raw;
|
|
1399
|
+
try {
|
|
1400
|
+
raw = await readJsonBody(req);
|
|
1401
|
+
}
|
|
1402
|
+
catch {
|
|
1403
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
1404
|
+
}
|
|
1405
|
+
const r = await updateDashboardSummaryRange(cachedLarkAppId, raw);
|
|
1406
|
+
if (!r.ok)
|
|
1407
|
+
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
1408
|
+
jsonRes(res, 200, { ok: true, summaryRange: r.summaryRange });
|
|
1409
|
+
});
|
|
1410
|
+
// Backward-compatible dashboard endpoint from the short-lived keyword-trigger UI.
|
|
1411
|
+
ipcRoute('PUT', '/api/bot-summary-trigger', async (req, res) => {
|
|
1412
|
+
if (!cachedLarkAppId)
|
|
1413
|
+
return jsonRes(res, 503, { error: 'larkAppId_not_set' });
|
|
1414
|
+
let raw;
|
|
1415
|
+
try {
|
|
1416
|
+
raw = await readJsonBody(req);
|
|
1417
|
+
}
|
|
1418
|
+
catch {
|
|
1419
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
1420
|
+
}
|
|
1421
|
+
const body = raw && typeof raw === 'object' && !Array.isArray(raw)
|
|
1422
|
+
? { limit: raw.limit, sinceHours: raw.sinceHours }
|
|
1423
|
+
: raw;
|
|
1424
|
+
const r = await updateDashboardSummaryRange(cachedLarkAppId, body);
|
|
1425
|
+
if (!r.ok)
|
|
1426
|
+
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
1427
|
+
jsonRes(res, 200, { ok: true, summaryRange: r.summaryRange });
|
|
1428
|
+
});
|
|
1295
1429
|
// Per-bot 授权偏好。Body 任意子集:
|
|
1296
1430
|
// • restrictGrantCommands: boolean — 限制被授权人只能纯对话
|
|
1297
1431
|
// • autoGrantRequestCards: boolean — 未授权 @ 被挡住时是否发 grant 申请卡
|
|
@@ -1347,6 +1481,60 @@ ipcRoute('PUT', '/api/bot-brand-label', async (req, res) => {
|
|
|
1347
1481
|
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
1348
1482
|
jsonRes(res, 200, { ok: true, brandLabel: r.brandLabel });
|
|
1349
1483
|
});
|
|
1484
|
+
// Per-bot agent launch settings. Body `{ cliId, model }` where `cliId` is the
|
|
1485
|
+
// dashboard selection key (plain adapter id or a wrapper option such as
|
|
1486
|
+
// `ttadk-x-codex`). Changes affect the next spawned CLI session.
|
|
1487
|
+
ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
|
|
1488
|
+
if (!cachedLarkAppId)
|
|
1489
|
+
return jsonRes(res, 503, { error: 'larkAppId_not_set' });
|
|
1490
|
+
let body;
|
|
1491
|
+
try {
|
|
1492
|
+
body = await readJsonBody(req);
|
|
1493
|
+
}
|
|
1494
|
+
catch {
|
|
1495
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
1496
|
+
}
|
|
1497
|
+
const key = typeof body.cliId === 'string' && body.cliId.trim() ? body.cliId.trim() : '';
|
|
1498
|
+
if (!key)
|
|
1499
|
+
return jsonRes(res, 400, { ok: false, error: 'cli_required' });
|
|
1500
|
+
let selected;
|
|
1501
|
+
try {
|
|
1502
|
+
selected = resolveCliSelection(key);
|
|
1503
|
+
}
|
|
1504
|
+
catch (err) {
|
|
1505
|
+
return jsonRes(res, 400, { ok: false, error: 'invalid_cli', message: err?.message ?? String(err) });
|
|
1506
|
+
}
|
|
1507
|
+
const model = typeof body.model === 'string' ? body.model.trim() : '';
|
|
1508
|
+
const r = await rmwBotEntry(cachedLarkAppId, (entry) => {
|
|
1509
|
+
entry.cliId = selected.cliId;
|
|
1510
|
+
if (selected.wrapperCli)
|
|
1511
|
+
entry.wrapperCli = selected.wrapperCli;
|
|
1512
|
+
else
|
|
1513
|
+
delete entry.wrapperCli;
|
|
1514
|
+
if (model)
|
|
1515
|
+
entry.model = model;
|
|
1516
|
+
else
|
|
1517
|
+
delete entry.model;
|
|
1518
|
+
return { write: true, result: null };
|
|
1519
|
+
});
|
|
1520
|
+
if (!r.ok)
|
|
1521
|
+
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
1522
|
+
const bot = getBot(cachedLarkAppId);
|
|
1523
|
+
bot.config.cliId = selected.cliId;
|
|
1524
|
+
if (selected.wrapperCli)
|
|
1525
|
+
bot.config.wrapperCli = selected.wrapperCli;
|
|
1526
|
+
else
|
|
1527
|
+
bot.config.wrapperCli = undefined;
|
|
1528
|
+
bot.config.model = model || undefined;
|
|
1529
|
+
const selectionKey = selectionKeyForBot(selected.cliId, selected.wrapperCli);
|
|
1530
|
+
jsonRes(res, 200, {
|
|
1531
|
+
ok: true,
|
|
1532
|
+
cliId: selected.cliId,
|
|
1533
|
+
wrapperCli: selected.wrapperCli ?? null,
|
|
1534
|
+
model: model || null,
|
|
1535
|
+
selectionKey,
|
|
1536
|
+
});
|
|
1537
|
+
});
|
|
1350
1538
|
// Per-bot 私聊单聊模式 p2pMode。Body `{ p2pMode: 'chat' | 'thread' }`:
|
|
1351
1539
|
// • 'chat' → 私聊走扁平连续 chat-scope 会话
|
|
1352
1540
|
// • 'thread'(默认) → 清回每条 DM 独立 thread-scope 会话
|