larkin 0.5.18 → 0.5.19
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/CHANGELOG.md +6 -0
- package/README.md +2 -9
- package/dist/agent/config-cli-contract.cjs +1 -3
- package/dist/agent/config-cli-contract.mjs +1 -3
- package/dist/agent/transport-business-context.cjs +3 -0
- package/dist/agent/transport-business-context.mjs +3 -0
- package/dist/app/agent-cli.mjs +1 -18
- package/dist/app/agent-config.mjs +4 -33
- package/dist/app/cli.mjs +0 -1
- package/dist/app/lark-cli.mjs +4 -0
- package/dist/dashboard/dashboard-config-controller.mjs +0 -11
- package/dist/dashboard/web/assets/dashboard.js +15 -15
- package/dist/feishu/host-processing-eye.cjs +54 -1
- package/dist/feishu/host-processing-eye.mjs +48 -0
- package/dist/feishu/host-shell.cjs +23 -14
- package/dist/feishu/host-shell.mjs +25 -16
- package/dist/feishu/message-policy.cjs +1 -0
- package/dist/feishu/message-policy.mjs +1 -0
- package/dist/platform/config.cjs +13 -84
- package/dist/platform/config.mjs +13 -82
- package/package.json +1 -1
|
@@ -1,8 +1,61 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ProcessingEyeOrchestrator = void 0;
|
|
3
|
+
exports.ProcessingEyeOrchestrator = exports.BOT_TOPIC_ROOT_LIMIT = void 0;
|
|
4
|
+
exports.shouldShowProcessingEye = shouldShowProcessingEye;
|
|
5
|
+
exports.listBotTopicRoots = listBotTopicRoots;
|
|
6
|
+
exports.rememberBotTopicRoot = rememberBotTopicRoot;
|
|
7
|
+
exports.persistBotTopicRoot = persistBotTopicRoot;
|
|
8
|
+
exports.isBotStartedTopic = isBotStartedTopic;
|
|
4
9
|
const node_child_process_1 = require("node:child_process");
|
|
5
10
|
const agent_lark_cli_workspace_js_1 = require("../app/agent-lark-cli-workspace.cjs");
|
|
11
|
+
exports.BOT_TOPIC_ROOT_LIMIT = 256;
|
|
12
|
+
const BOT_TOPIC_ID = /^om[t]?_[A-Za-z0-9_-]+$/;
|
|
13
|
+
function isPrivateChat(input) {
|
|
14
|
+
const chatType = String(input.chatType || "").toLowerCase();
|
|
15
|
+
if (chatType === "p2p" || chatType === "dm")
|
|
16
|
+
return true;
|
|
17
|
+
if (String(input.channelType || "").toLowerCase() === "dm")
|
|
18
|
+
return true;
|
|
19
|
+
return String(input.parentChannelType || "").toLowerCase() === "dm";
|
|
20
|
+
}
|
|
21
|
+
/** OnIt 给私聊、入站 @bot(含 @all),或用户在 AI 消息下发起的话题里说话。群未@且非 AI 话题不点。 */
|
|
22
|
+
function shouldShowProcessingEye(input) {
|
|
23
|
+
if (isPrivateChat(input))
|
|
24
|
+
return true;
|
|
25
|
+
if (input.mentionedBot === true)
|
|
26
|
+
return true;
|
|
27
|
+
return input.botStartedTopic === true;
|
|
28
|
+
}
|
|
29
|
+
function listBotTopicRoots(state) {
|
|
30
|
+
if (!Array.isArray(state?.bot_topic_roots))
|
|
31
|
+
return [];
|
|
32
|
+
return state.bot_topic_roots.filter((id) => typeof id === "string" && BOT_TOPIC_ID.test(id));
|
|
33
|
+
}
|
|
34
|
+
function rememberBotTopicRoot(ids, candidate) {
|
|
35
|
+
const id = String(candidate || "");
|
|
36
|
+
if (!BOT_TOPIC_ID.test(id) || ids.includes(id))
|
|
37
|
+
return [...ids];
|
|
38
|
+
return [...ids, id].slice(-exports.BOT_TOPIC_ROOT_LIMIT);
|
|
39
|
+
}
|
|
40
|
+
/** 机器人成功发出的 `om_`/`omt_` 记为话题根,供后续「AI 发起的话题」判定,不做飞书回查。 */
|
|
41
|
+
function persistBotTopicRoot(store, candidate) {
|
|
42
|
+
const id = String(candidate || "");
|
|
43
|
+
if (!BOT_TOPIC_ID.test(id))
|
|
44
|
+
return;
|
|
45
|
+
store.mutateJson("freshnessState", { version: 1, cursors: {} }, (state) => {
|
|
46
|
+
state.bot_topic_roots = rememberBotTopicRoot(listBotTopicRoots(state), id);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function isBotStartedTopic(input) {
|
|
50
|
+
const threadId = String(input.threadId || "");
|
|
51
|
+
if (!threadId)
|
|
52
|
+
return false;
|
|
53
|
+
const owned = new Set(input.ownedIds || []);
|
|
54
|
+
if (owned.has(threadId))
|
|
55
|
+
return true;
|
|
56
|
+
const rootId = String(input.rootId || "");
|
|
57
|
+
return Boolean(rootId) && owned.has(rootId);
|
|
58
|
+
}
|
|
6
59
|
function errorMessage(error) {
|
|
7
60
|
return error instanceof Error ? error.message : String(error || "?");
|
|
8
61
|
}
|
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
import { execFile as nodeExecFile } from "node:child_process";
|
|
2
2
|
import { managedOfficialLarkCli } from "../app/agent-lark-cli-workspace.mjs";
|
|
3
|
+
export const BOT_TOPIC_ROOT_LIMIT = 256;
|
|
4
|
+
const BOT_TOPIC_ID = /^om[t]?_[A-Za-z0-9_-]+$/;
|
|
5
|
+
function isPrivateChat(input) {
|
|
6
|
+
const chatType = String(input.chatType || "").toLowerCase();
|
|
7
|
+
if (chatType === "p2p" || chatType === "dm")
|
|
8
|
+
return true;
|
|
9
|
+
if (String(input.channelType || "").toLowerCase() === "dm")
|
|
10
|
+
return true;
|
|
11
|
+
return String(input.parentChannelType || "").toLowerCase() === "dm";
|
|
12
|
+
}
|
|
13
|
+
/** OnIt 给私聊、入站 @bot(含 @all),或用户在 AI 消息下发起的话题里说话。群未@且非 AI 话题不点。 */
|
|
14
|
+
export function shouldShowProcessingEye(input) {
|
|
15
|
+
if (isPrivateChat(input))
|
|
16
|
+
return true;
|
|
17
|
+
if (input.mentionedBot === true)
|
|
18
|
+
return true;
|
|
19
|
+
return input.botStartedTopic === true;
|
|
20
|
+
}
|
|
21
|
+
export function listBotTopicRoots(state) {
|
|
22
|
+
if (!Array.isArray(state?.bot_topic_roots))
|
|
23
|
+
return [];
|
|
24
|
+
return state.bot_topic_roots.filter((id) => typeof id === "string" && BOT_TOPIC_ID.test(id));
|
|
25
|
+
}
|
|
26
|
+
export function rememberBotTopicRoot(ids, candidate) {
|
|
27
|
+
const id = String(candidate || "");
|
|
28
|
+
if (!BOT_TOPIC_ID.test(id) || ids.includes(id))
|
|
29
|
+
return [...ids];
|
|
30
|
+
return [...ids, id].slice(-BOT_TOPIC_ROOT_LIMIT);
|
|
31
|
+
}
|
|
32
|
+
/** 机器人成功发出的 `om_`/`omt_` 记为话题根,供后续「AI 发起的话题」判定,不做飞书回查。 */
|
|
33
|
+
export function persistBotTopicRoot(store, candidate) {
|
|
34
|
+
const id = String(candidate || "");
|
|
35
|
+
if (!BOT_TOPIC_ID.test(id))
|
|
36
|
+
return;
|
|
37
|
+
store.mutateJson("freshnessState", { version: 1, cursors: {} }, (state) => {
|
|
38
|
+
state.bot_topic_roots = rememberBotTopicRoot(listBotTopicRoots(state), id);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export function isBotStartedTopic(input) {
|
|
42
|
+
const threadId = String(input.threadId || "");
|
|
43
|
+
if (!threadId)
|
|
44
|
+
return false;
|
|
45
|
+
const owned = new Set(input.ownedIds || []);
|
|
46
|
+
if (owned.has(threadId))
|
|
47
|
+
return true;
|
|
48
|
+
const rootId = String(input.rootId || "");
|
|
49
|
+
return Boolean(rootId) && owned.has(rootId);
|
|
50
|
+
}
|
|
3
51
|
function errorMessage(error) {
|
|
4
52
|
return error instanceof Error ? error.message : String(error || "?");
|
|
5
53
|
}
|
|
@@ -509,15 +509,6 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
|
|
|
509
509
|
});
|
|
510
510
|
const seenEventIds = new Set();
|
|
511
511
|
const inFlightEventIds = new Set();
|
|
512
|
-
const processingEyeEnabled = (agent) => {
|
|
513
|
-
// 缺 key / 读配置失败都关闭,避免升级后继续自动点 OnIt。
|
|
514
|
-
try {
|
|
515
|
-
return (0, config_js_1.resolveProcessingEye)((0, config_js_1.loadConfig)(env).config, agent.agentId).enabled;
|
|
516
|
-
}
|
|
517
|
-
catch {
|
|
518
|
-
return false;
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
512
|
const onFeishuMessage = async (agent, event, options) => {
|
|
522
513
|
const wake = options?.wake !== false;
|
|
523
514
|
const eventKey = `${agent.agentId}:${event.event_id || event.message_id || ""}`;
|
|
@@ -608,12 +599,30 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
|
|
|
608
599
|
excerpt: (0, host_business_state_js_1.safeConversationExcerpt)(event.content, 180),
|
|
609
600
|
at: new Date().toISOString(),
|
|
610
601
|
}, 30);
|
|
611
|
-
if (
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
602
|
+
if (inboxEnvelope.sender_type === "human" || inboxEnvelope.sender_type === "agent") {
|
|
603
|
+
// 私聊、入站 @bot,或 inbound root/thread 落在本 bot 已发出的话题根上才点 OnIt。
|
|
604
|
+
const botStartedTopic = (0, host_processing_eye_js_1.isBotStartedTopic)({
|
|
605
|
+
threadId: event.thread_id,
|
|
606
|
+
rootId: event.root_id,
|
|
607
|
+
ownedIds: (0, host_processing_eye_js_1.listBotTopicRoots)(stateStore(agent).readJson("freshnessState", {})),
|
|
616
608
|
});
|
|
609
|
+
if ((0, host_processing_eye_js_1.shouldShowProcessingEye)({
|
|
610
|
+
chatType: event.chat_type,
|
|
611
|
+
channelType: typeof inboxEnvelope.channel_type === "string" ? inboxEnvelope.channel_type : undefined,
|
|
612
|
+
parentChannelType: typeof inboxEnvelope.parent_channel_type === "string" ? inboxEnvelope.parent_channel_type : undefined,
|
|
613
|
+
mentionedBot: event._mentioned_bot === true,
|
|
614
|
+
botStartedTopic,
|
|
615
|
+
})) {
|
|
616
|
+
if (botStartedTopic)
|
|
617
|
+
(0, host_processing_eye_js_1.persistBotTopicRoot)(stateStore(agent), event.thread_id);
|
|
618
|
+
processingEyes.add(agent, String(inboxEnvelope.message_id || ""), {
|
|
619
|
+
replyInThread: String(inboxEnvelope.target || "").startsWith("thread:"),
|
|
620
|
+
target: String(inboxEnvelope.target || ""),
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
log(`👀 跳过群未@且非 AI 话题消息 agent=${agent.name} chat=${event.chat_id}`);
|
|
625
|
+
}
|
|
617
626
|
}
|
|
618
627
|
if (receipt.status === "deferred")
|
|
619
628
|
log(`Runtime 暂缓投递,消息保留在 inbox seq=${inboxEnvelope.seq}: ${receipt.reason}`);
|
|
@@ -8,7 +8,7 @@ import { currentProcessMetadata } from "../platform/process-inspect.cjs";
|
|
|
8
8
|
import { reconcileAgentWorkspace } from "../platform/workspace-service.mjs";
|
|
9
9
|
import { createAgentStateStore } from "../agent/agent-state-store.mjs";
|
|
10
10
|
import { HostEnvelopeProjector, HostStateProjection, SenderIdentityCache, projectActivityStatus, projectSessionStatus, safeConversationExcerpt, shouldPreventiveReconnect, } from "./host-business-state.mjs";
|
|
11
|
-
import { ProcessingEyeOrchestrator } from "./host-processing-eye.mjs";
|
|
11
|
+
import { isBotStartedTopic, listBotTopicRoots, persistBotTopicRoot, ProcessingEyeOrchestrator, shouldShowProcessingEye, } from "./host-processing-eye.mjs";
|
|
12
12
|
import { feishuImTarget, serializeFeishuImTarget } from "./im-freshness-adapter.mjs";
|
|
13
13
|
import { projectInboxEnvelope, targetKeyOfInboxEnvelope } from "../agent/inbox-projection.mjs";
|
|
14
14
|
import { HostReminderOrchestrator } from "../agent/host-reminder-orchestrator.mjs";
|
|
@@ -20,7 +20,7 @@ import { targetFor } from "./message-policy.mjs";
|
|
|
20
20
|
import { authFailureAppliesTo, parsePersistedAuthFailure, providerAuthenticationFailureReadiness, readinessForPersistedAuthFailure, RuntimePrerequisiteError, } from "../runtime/runtime-readiness.mjs";
|
|
21
21
|
import { providerFinishReason, safeProviderDiagnostic } from "../runtime/provider-error-classifier.mjs";
|
|
22
22
|
import { readDocumentCommentSubscription, verifyCallbackProbe } from "../platform/callback-capability.mjs";
|
|
23
|
-
import { loadConfig, resolveInboxAuditSchedule, resolveMentionPolicy
|
|
23
|
+
import { loadConfig, resolveInboxAuditSchedule, resolveMentionPolicy } from "../platform/config.mjs";
|
|
24
24
|
import { processCommandToken } from "../app/internal-command.mjs";
|
|
25
25
|
import { managedOfficialLarkCli } from "../app/agent-lark-cli-workspace.mjs";
|
|
26
26
|
import { isChannelReconnecting, isRuntimeReadinessCurrent, isSessionCurrent } from "../app/agent-readiness.mjs";
|
|
@@ -468,15 +468,6 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
468
468
|
});
|
|
469
469
|
const seenEventIds = new Set();
|
|
470
470
|
const inFlightEventIds = new Set();
|
|
471
|
-
const processingEyeEnabled = (agent) => {
|
|
472
|
-
// 缺 key / 读配置失败都关闭,避免升级后继续自动点 OnIt。
|
|
473
|
-
try {
|
|
474
|
-
return resolveProcessingEye(loadConfig(env).config, agent.agentId).enabled;
|
|
475
|
-
}
|
|
476
|
-
catch {
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
};
|
|
480
471
|
const onFeishuMessage = async (agent, event, options) => {
|
|
481
472
|
const wake = options?.wake !== false;
|
|
482
473
|
const eventKey = `${agent.agentId}:${event.event_id || event.message_id || ""}`;
|
|
@@ -567,12 +558,30 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
567
558
|
excerpt: safeConversationExcerpt(event.content, 180),
|
|
568
559
|
at: new Date().toISOString(),
|
|
569
560
|
}, 30);
|
|
570
|
-
if (
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
561
|
+
if (inboxEnvelope.sender_type === "human" || inboxEnvelope.sender_type === "agent") {
|
|
562
|
+
// 私聊、入站 @bot,或 inbound root/thread 落在本 bot 已发出的话题根上才点 OnIt。
|
|
563
|
+
const botStartedTopic = isBotStartedTopic({
|
|
564
|
+
threadId: event.thread_id,
|
|
565
|
+
rootId: event.root_id,
|
|
566
|
+
ownedIds: listBotTopicRoots(stateStore(agent).readJson("freshnessState", {})),
|
|
575
567
|
});
|
|
568
|
+
if (shouldShowProcessingEye({
|
|
569
|
+
chatType: event.chat_type,
|
|
570
|
+
channelType: typeof inboxEnvelope.channel_type === "string" ? inboxEnvelope.channel_type : undefined,
|
|
571
|
+
parentChannelType: typeof inboxEnvelope.parent_channel_type === "string" ? inboxEnvelope.parent_channel_type : undefined,
|
|
572
|
+
mentionedBot: event._mentioned_bot === true,
|
|
573
|
+
botStartedTopic,
|
|
574
|
+
})) {
|
|
575
|
+
if (botStartedTopic)
|
|
576
|
+
persistBotTopicRoot(stateStore(agent), event.thread_id);
|
|
577
|
+
processingEyes.add(agent, String(inboxEnvelope.message_id || ""), {
|
|
578
|
+
replyInThread: String(inboxEnvelope.target || "").startsWith("thread:"),
|
|
579
|
+
target: String(inboxEnvelope.target || ""),
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
log(`👀 跳过群未@且非 AI 话题消息 agent=${agent.name} chat=${event.chat_id}`);
|
|
584
|
+
}
|
|
576
585
|
}
|
|
577
586
|
if (receipt.status === "deferred")
|
|
578
587
|
log(`Runtime 暂缓投递,消息保留在 inbox seq=${inboxEnvelope.seq}: ${receipt.reason}`);
|
|
@@ -36,6 +36,7 @@ function normalizeChannelMessage(message) {
|
|
|
36
36
|
content: String(message.content || ""),
|
|
37
37
|
create_time: message.createTime,
|
|
38
38
|
thread_id: message.threadId || null,
|
|
39
|
+
root_id: message.rootId || null,
|
|
39
40
|
_mentioned_bot: Boolean(message.mentionedBot || message.mentionAll),
|
|
40
41
|
_mention_all: Boolean(message.mentionAll),
|
|
41
42
|
_sender_is_bot: message.senderIsBot === true,
|
|
@@ -23,6 +23,7 @@ export function normalizeChannelMessage(message) {
|
|
|
23
23
|
content: String(message.content || ""),
|
|
24
24
|
create_time: message.createTime,
|
|
25
25
|
thread_id: message.threadId || null,
|
|
26
|
+
root_id: message.rootId || null,
|
|
26
27
|
_mentioned_bot: Boolean(message.mentionedBot || message.mentionAll),
|
|
27
28
|
_mention_all: Boolean(message.mentionAll),
|
|
28
29
|
_sender_is_bot: message.senderIsBot === true,
|
package/dist/platform/config.cjs
CHANGED
|
@@ -46,7 +46,6 @@ exports.assertInboxAuditInterval = assertInboxAuditInterval;
|
|
|
46
46
|
exports.parseInboxAuditInterval = parseInboxAuditInterval;
|
|
47
47
|
exports.formatInboxAuditInterval = formatInboxAuditInterval;
|
|
48
48
|
exports.inboxAuditMutationFromCli = inboxAuditMutationFromCli;
|
|
49
|
-
exports.processingEyeMutationFromCli = processingEyeMutationFromCli;
|
|
50
49
|
exports.hydrateAgent = hydrateAgent;
|
|
51
50
|
exports.normalizeConfig = normalizeConfig;
|
|
52
51
|
exports.assertPrivateConfigMetadata = assertPrivateConfigMetadata;
|
|
@@ -56,7 +55,6 @@ exports.toStored = toStored;
|
|
|
56
55
|
exports.resolveMentionPolicy = resolveMentionPolicy;
|
|
57
56
|
exports.resolveAgentGlobalMentionPolicy = resolveAgentGlobalMentionPolicy;
|
|
58
57
|
exports.resolveInboxAuditSchedule = resolveInboxAuditSchedule;
|
|
59
|
-
exports.resolveProcessingEye = resolveProcessingEye;
|
|
60
58
|
exports.runtimeConfigSignature = runtimeConfigSignature;
|
|
61
59
|
exports.configApplyState = configApplyState;
|
|
62
60
|
exports.markConfigApplied = markConfigApplied;
|
|
@@ -88,12 +86,11 @@ exports.MIN_INBOX_AUDIT_INTERVAL_MS = 60_000;
|
|
|
88
86
|
exports.MAX_INBOX_AUDIT_INTERVAL_MS = 24 * 60 * 60_000;
|
|
89
87
|
const TOP_FIELDS_V3 = new Set(["version", "serverId", "activeAgent", "agents"]);
|
|
90
88
|
const TOP_FIELDS_V4 = new Set(["version", "serverId", "mentionPolicy", "activeAgent", "agents"]);
|
|
91
|
-
const OPTIONAL_TOP_FIELDS_V4 = new Set(["inboxAudit"
|
|
89
|
+
const OPTIONAL_TOP_FIELDS_V4 = new Set(["inboxAudit"]);
|
|
92
90
|
const AGENT_FIELDS_V3 = new Set(["runtime", "model", "effort", "noMentionChats", "createdAt"]);
|
|
93
|
-
const AGENT_FIELDS_V4 = new Set(["runtime", "model", "effort", "mentionPolicy", "chatMentionPolicies", "inboxAudit", "
|
|
94
|
-
const LEGACY_AGENT_FIELDS = new Set(["piDistribution", "runtimeOption"]);
|
|
91
|
+
const AGENT_FIELDS_V4 = new Set(["runtime", "model", "effort", "mentionPolicy", "chatMentionPolicies", "inboxAudit", "createdAt"]);
|
|
92
|
+
const LEGACY_AGENT_FIELDS = new Set(["piDistribution", "runtimeOption", "processingEye"]);
|
|
95
93
|
const INBOX_AUDIT_FIELDS = new Set(["enabled", "intervalMs"]);
|
|
96
|
-
const PROCESSING_EYE_FIELDS = new Set(["enabled"]);
|
|
97
94
|
const APP_ID = /^cli_[A-Za-z0-9]+$/;
|
|
98
95
|
const CHAT_ID = /^oc_[A-Za-z0-9_-]+$/;
|
|
99
96
|
const PI_EFFORTS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
@@ -206,21 +203,14 @@ function resolvedInboxAudit(settings) {
|
|
|
206
203
|
intervalMs: settings?.intervalMs ?? exports.DEFAULT_INBOX_AUDIT_INTERVAL_MS,
|
|
207
204
|
};
|
|
208
205
|
}
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
throw new Error(`${label}.enabled 必须是 boolean`);
|
|
217
|
-
settings.enabled = value.enabled;
|
|
206
|
+
function dropRetiredProcessingEye(raw) {
|
|
207
|
+
delete raw.processingEye;
|
|
208
|
+
if (!isPlainObject(raw.agents))
|
|
209
|
+
return;
|
|
210
|
+
for (const agent of Object.values(raw.agents)) {
|
|
211
|
+
if (isPlainObject(agent))
|
|
212
|
+
delete agent.processingEye;
|
|
218
213
|
}
|
|
219
|
-
return settings;
|
|
220
|
-
}
|
|
221
|
-
function resolvedProcessingEye(settings) {
|
|
222
|
-
// 缺 key 视为关闭。升级后不再保留旧的自动 OnIt 行为,除非用户显式开启。
|
|
223
|
-
return { enabled: settings?.enabled ?? false };
|
|
224
214
|
}
|
|
225
215
|
function inboxAuditMutationFromCli(input) {
|
|
226
216
|
if (input.scope === "global") {
|
|
@@ -252,25 +242,6 @@ function inboxAuditMutationFromCli(input) {
|
|
|
252
242
|
}
|
|
253
243
|
throw new Error("inbox-audit scope 只支持 global/agent");
|
|
254
244
|
}
|
|
255
|
-
function processingEyeMutationFromCli(input) {
|
|
256
|
-
if (input.scope === "global") {
|
|
257
|
-
if (input.enabled !== "on" && input.enabled !== "off") {
|
|
258
|
-
throw new Error("用法: larkin config processing-eye global <on|off>");
|
|
259
|
-
}
|
|
260
|
-
return { kind: "set-global-processing-eye", enabled: input.enabled === "on" };
|
|
261
|
-
}
|
|
262
|
-
if (input.scope === "agent") {
|
|
263
|
-
if (input.enabled !== "on" && input.enabled !== "off" && input.enabled !== "inherit") {
|
|
264
|
-
throw new Error("用法: larkin config processing-eye agent <inherit|on|off> [--agent <App ID>]");
|
|
265
|
-
}
|
|
266
|
-
return {
|
|
267
|
-
kind: "set-agent-processing-eye",
|
|
268
|
-
agentId: input.agentId,
|
|
269
|
-
enabled: input.enabled === "inherit" ? "inherit" : input.enabled === "on",
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
throw new Error("processing-eye scope 只支持 global/agent");
|
|
273
|
-
}
|
|
274
245
|
function assertModel(runtime, model) {
|
|
275
246
|
if (model === "default")
|
|
276
247
|
return;
|
|
@@ -340,8 +311,6 @@ function validateStoredAgent(key, agent, version) {
|
|
|
340
311
|
assertPolicy(agent.mentionPolicy, `Agent ${key}.mentionPolicy`);
|
|
341
312
|
if (version === 4 && Object.hasOwn(agent, "inboxAudit"))
|
|
342
313
|
parseStoredInboxAudit(agent.inboxAudit, `Agent ${key}.inboxAudit`);
|
|
343
|
-
if (version === 4 && Object.hasOwn(agent, "processingEye"))
|
|
344
|
-
parseStoredProcessingEye(agent.processingEye, `Agent ${key}.processingEye`);
|
|
345
314
|
if (version === 4 && Object.hasOwn(agent, "chatMentionPolicies")) {
|
|
346
315
|
if (!isPlainObject(agent.chatMentionPolicies))
|
|
347
316
|
throw new Error(`Agent ${key}.chatMentionPolicies 必须是普通 object`);
|
|
@@ -371,7 +340,6 @@ function hydratedStoredAgent(key, agent, version) {
|
|
|
371
340
|
...(typeof agent.effort === "string" ? { effort: agent.effort } : {}),
|
|
372
341
|
...(version === 4 && (agent.mentionPolicy === "require" || agent.mentionPolicy === "free") ? { mentionPolicy: agent.mentionPolicy } : {}),
|
|
373
342
|
...(version === 4 && Object.hasOwn(agent, "inboxAudit") ? { inboxAudit: parseStoredInboxAudit(agent.inboxAudit, `Agent ${key}.inboxAudit`) } : {}),
|
|
374
|
-
...(version === 4 && Object.hasOwn(agent, "processingEye") ? { processingEye: parseStoredProcessingEye(agent.processingEye, `Agent ${key}.processingEye`) } : {}),
|
|
375
343
|
...(Object.keys(chatMentionPolicies).length ? { chatMentionPolicies, noMentionChats: Object.entries(chatMentionPolicies).filter(([, policy]) => policy === "free").map(([chatId]) => chatId) } : {}),
|
|
376
344
|
...(typeof agent.createdAt === "string" ? { createdAt: agent.createdAt } : {}),
|
|
377
345
|
};
|
|
@@ -386,7 +354,6 @@ function hydrateAgent(key, agent, configDir) {
|
|
|
386
354
|
...(agent.effort ? { effort: agent.effort } : {}),
|
|
387
355
|
...(agent.mentionPolicy ? { mentionPolicy: agent.mentionPolicy } : {}),
|
|
388
356
|
...(agent.inboxAudit ? { inboxAudit: { ...agent.inboxAudit } } : {}),
|
|
389
|
-
...(agent.processingEye ? { processingEye: { ...agent.processingEye } } : {}),
|
|
390
357
|
...(agent.chatMentionPolicies ? { chatMentionPolicies: { ...agent.chatMentionPolicies } } : {}),
|
|
391
358
|
...(agent.noMentionChats ? { noMentionChats: [...agent.noMentionChats] } : {}),
|
|
392
359
|
...(agent.createdAt ? { createdAt: agent.createdAt } : {}),
|
|
@@ -401,6 +368,7 @@ function normalizeConfig(raw, configDir, { mint } = {}) {
|
|
|
401
368
|
};
|
|
402
369
|
if (!isPlainObject(raw))
|
|
403
370
|
throw new Error("config 必须是普通 object");
|
|
371
|
+
dropRetiredProcessingEye(raw);
|
|
404
372
|
const version = raw.version;
|
|
405
373
|
if (version !== 3 && version !== 4)
|
|
406
374
|
throw new Error("不支持该配置格式:larkin 只接受 version=3/4");
|
|
@@ -427,13 +395,9 @@ function normalizeConfig(raw, configDir, { mint } = {}) {
|
|
|
427
395
|
const inboxAudit = version === 4 && Object.hasOwn(raw, "inboxAudit")
|
|
428
396
|
? resolvedInboxAudit(parseStoredInboxAudit(raw.inboxAudit, "config.inboxAudit"))
|
|
429
397
|
: undefined;
|
|
430
|
-
const processingEye = version === 4 && Object.hasOwn(raw, "processingEye")
|
|
431
|
-
? resolvedProcessingEye(parseStoredProcessingEye(raw.processingEye, "config.processingEye"))
|
|
432
|
-
: undefined;
|
|
433
398
|
return {
|
|
434
399
|
version: 4, serverId: raw.serverId, mentionPolicy: version === 4 ? raw.mentionPolicy : "require",
|
|
435
400
|
...(inboxAudit ? { inboxAudit } : {}),
|
|
436
|
-
...(processingEye ? { processingEye } : {}),
|
|
437
401
|
configDir: layout.configDir, larkinHome: layout.larkinHome, larkConfigDir: resolveLarkConfigDir({}, layout.root), activeAgent: raw.activeAgent, agents,
|
|
438
402
|
};
|
|
439
403
|
}
|
|
@@ -664,8 +628,6 @@ function toStored(config) {
|
|
|
664
628
|
};
|
|
665
629
|
if (config.inboxAudit)
|
|
666
630
|
out.inboxAudit = { enabled: config.inboxAudit.enabled, intervalMs: config.inboxAudit.intervalMs };
|
|
667
|
-
if (config.processingEye)
|
|
668
|
-
out.processingEye = { enabled: config.processingEye.enabled };
|
|
669
631
|
for (const [key, agent] of Object.entries(config.agents || {})) {
|
|
670
632
|
const stored = { runtime: agent.runtime, model: agent.model };
|
|
671
633
|
if (typeof agent.effort === "string" && agent.effort)
|
|
@@ -677,9 +639,6 @@ function toStored(config) {
|
|
|
677
639
|
if (agent.inboxAudit && (agent.inboxAudit.enabled !== undefined || agent.inboxAudit.intervalMs !== undefined)) {
|
|
678
640
|
stored.inboxAudit = { ...agent.inboxAudit };
|
|
679
641
|
}
|
|
680
|
-
if (agent.processingEye && agent.processingEye.enabled !== undefined) {
|
|
681
|
-
stored.processingEye = { enabled: agent.processingEye.enabled };
|
|
682
|
-
}
|
|
683
642
|
if (typeof agent.createdAt === "string" && agent.createdAt)
|
|
684
643
|
stored.createdAt = agent.createdAt;
|
|
685
644
|
out.agents[key] = stored;
|
|
@@ -720,16 +679,6 @@ function resolveInboxAuditSchedule(config, agentId) {
|
|
|
720
679
|
intervalSource: agent.inboxAudit?.intervalMs !== undefined ? "agent" : config.inboxAudit?.intervalMs !== undefined ? "global" : "default",
|
|
721
680
|
};
|
|
722
681
|
}
|
|
723
|
-
function resolveProcessingEye(config, agentId) {
|
|
724
|
-
const agent = config.agents[agentId];
|
|
725
|
-
if (!agent)
|
|
726
|
-
throw new Error(`Agent 不存在:${agentId}`);
|
|
727
|
-
const enabled = agent.processingEye?.enabled ?? config.processingEye?.enabled ?? false;
|
|
728
|
-
return {
|
|
729
|
-
enabled,
|
|
730
|
-
enabledSource: agent.processingEye?.enabled !== undefined ? "agent" : config.processingEye ? "global" : "default",
|
|
731
|
-
};
|
|
732
|
-
}
|
|
733
682
|
function revision(bytes) {
|
|
734
683
|
return `sha256:${crypto.createHash("sha256").update(bytes).digest("hex")}`;
|
|
735
684
|
}
|
|
@@ -743,7 +692,8 @@ function agentSignature(config, agentId) {
|
|
|
743
692
|
runtime: agent.runtime, model: agent.model, effort: agent.effort ?? null,
|
|
744
693
|
globalMentionPolicy: config.mentionPolicy, agentMentionPolicy: agent.mentionPolicy ?? null, chatMentionPolicies: chats,
|
|
745
694
|
globalInboxAudit: config.inboxAudit ?? null, agentInboxAudit: agent.inboxAudit ?? null,
|
|
746
|
-
|
|
695
|
+
// 0.5.19 起不再有 processingEye 开关;固定 null 以免未配过该 key 的 Agent 升级后无意义 pending apply。
|
|
696
|
+
globalProcessingEye: null, agentProcessingEye: null,
|
|
747
697
|
}));
|
|
748
698
|
}
|
|
749
699
|
function runtimeConfigSignature(config, agentId) {
|
|
@@ -894,10 +844,6 @@ function applyMutation(config, mutation) {
|
|
|
894
844
|
config.inboxAudit = current;
|
|
895
845
|
return { scope: "global", runtimeChange: false, affectedAgentIds: Object.keys(config.agents) };
|
|
896
846
|
}
|
|
897
|
-
if (mutation.kind === "set-global-processing-eye") {
|
|
898
|
-
config.processingEye = { enabled: mutation.enabled };
|
|
899
|
-
return { scope: "global", runtimeChange: false, affectedAgentIds: Object.keys(config.agents) };
|
|
900
|
-
}
|
|
901
847
|
if (!APP_ID.test(mutation.agentId) || !config.agents[mutation.agentId])
|
|
902
848
|
throw new Error(`Agent 不存在:${mutation.agentId}`);
|
|
903
849
|
const agent = config.agents[mutation.agentId];
|
|
@@ -930,13 +876,6 @@ function applyMutation(config, mutation) {
|
|
|
930
876
|
agent.inboxAudit = current;
|
|
931
877
|
return { scope: "agent", agentId: mutation.agentId, runtimeChange: false, affectedAgentIds: [mutation.agentId] };
|
|
932
878
|
}
|
|
933
|
-
if (mutation.kind === "set-agent-processing-eye") {
|
|
934
|
-
if (mutation.enabled === "inherit")
|
|
935
|
-
delete agent.processingEye;
|
|
936
|
-
else
|
|
937
|
-
agent.processingEye = { enabled: mutation.enabled };
|
|
938
|
-
return { scope: "agent", agentId: mutation.agentId, runtimeChange: false, affectedAgentIds: [mutation.agentId] };
|
|
939
|
-
}
|
|
940
879
|
if (mutation.kind === "set-chat-mention") {
|
|
941
880
|
if (!CHAT_ID.test(mutation.chatId))
|
|
942
881
|
throw new Error(`群 ID 格式无效:${mutation.chatId}`);
|
|
@@ -1434,23 +1373,13 @@ function safeConfigView(config, onlyAgentId, chatId, applyState) {
|
|
|
1434
1373
|
source: { enabled: resolved.enabledSource, intervalMs: resolved.intervalSource },
|
|
1435
1374
|
};
|
|
1436
1375
|
})(),
|
|
1437
|
-
processingEye: (() => {
|
|
1438
|
-
const resolved = resolveProcessingEye(config, agentId);
|
|
1439
|
-
return {
|
|
1440
|
-
override: { enabled: agent.processingEye?.enabled === undefined ? "inherit" : agent.processingEye.enabled ? "on" : "off" },
|
|
1441
|
-
effective: { enabled: resolved.enabled },
|
|
1442
|
-
source: { enabled: resolved.enabledSource },
|
|
1443
|
-
};
|
|
1444
|
-
})(),
|
|
1445
1376
|
chatMentionPolicies: { ...(agent.chatMentionPolicies || {}) },
|
|
1446
1377
|
apply: applyState?.agents?.[agentId] ?? { applyState: "unknown" },
|
|
1447
1378
|
}));
|
|
1448
1379
|
const inboxAudit = resolvedInboxAudit(config.inboxAudit);
|
|
1449
|
-
const processingEye = resolvedProcessingEye(config.processingEye);
|
|
1450
1380
|
return {
|
|
1451
1381
|
version: 4, mentionPolicy: config.mentionPolicy,
|
|
1452
1382
|
inboxAudit: { enabled: inboxAudit.enabled, intervalMs: inboxAudit.intervalMs },
|
|
1453
|
-
processingEye: { enabled: processingEye.enabled },
|
|
1454
1383
|
persistedRevision: applyState?.persistedRevision ?? "unknown", agents,
|
|
1455
1384
|
};
|
|
1456
1385
|
}
|