larkin 0.5.17 → 0.5.18
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 +4 -0
- package/README.md +11 -0
- package/dist/agent/config-cli-contract.cjs +3 -1
- package/dist/agent/config-cli-contract.mjs +3 -1
- package/dist/app/agent-cli.mjs +18 -1
- package/dist/app/agent-config.mjs +33 -4
- package/dist/app/cli.mjs +1 -0
- package/dist/dashboard/dashboard-config-controller.mjs +11 -0
- package/dist/dashboard/web/assets/dashboard.js +15 -15
- package/dist/feishu/host-shell.cjs +11 -1
- package/dist/feishu/host-shell.mjs +12 -2
- package/dist/platform/config.cjs +85 -2
- package/dist/platform/config.mjs +83 -2
- package/package.json +1 -1
|
@@ -509,6 +509,15 @@ 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
|
+
};
|
|
512
521
|
const onFeishuMessage = async (agent, event, options) => {
|
|
513
522
|
const wake = options?.wake !== false;
|
|
514
523
|
const eventKey = `${agent.agentId}:${event.event_id || event.message_id || ""}`;
|
|
@@ -599,7 +608,8 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
|
|
|
599
608
|
excerpt: (0, host_business_state_js_1.safeConversationExcerpt)(event.content, 180),
|
|
600
609
|
at: new Date().toISOString(),
|
|
601
610
|
}, 30);
|
|
602
|
-
if (inboxEnvelope.sender_type === "human" || inboxEnvelope.sender_type === "agent")
|
|
611
|
+
if ((inboxEnvelope.sender_type === "human" || inboxEnvelope.sender_type === "agent")
|
|
612
|
+
&& processingEyeEnabled(agent)) {
|
|
603
613
|
processingEyes.add(agent, String(inboxEnvelope.message_id || ""), {
|
|
604
614
|
replyInThread: String(inboxEnvelope.target || "").startsWith("thread:"),
|
|
605
615
|
target: String(inboxEnvelope.target || ""),
|
|
@@ -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 } from "../platform/config.mjs";
|
|
23
|
+
import { loadConfig, resolveInboxAuditSchedule, resolveMentionPolicy, resolveProcessingEye } 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,6 +468,15 @@ 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
|
+
};
|
|
471
480
|
const onFeishuMessage = async (agent, event, options) => {
|
|
472
481
|
const wake = options?.wake !== false;
|
|
473
482
|
const eventKey = `${agent.agentId}:${event.event_id || event.message_id || ""}`;
|
|
@@ -558,7 +567,8 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
558
567
|
excerpt: safeConversationExcerpt(event.content, 180),
|
|
559
568
|
at: new Date().toISOString(),
|
|
560
569
|
}, 30);
|
|
561
|
-
if (inboxEnvelope.sender_type === "human" || inboxEnvelope.sender_type === "agent")
|
|
570
|
+
if ((inboxEnvelope.sender_type === "human" || inboxEnvelope.sender_type === "agent")
|
|
571
|
+
&& processingEyeEnabled(agent)) {
|
|
562
572
|
processingEyes.add(agent, String(inboxEnvelope.message_id || ""), {
|
|
563
573
|
replyInThread: String(inboxEnvelope.target || "").startsWith("thread:"),
|
|
564
574
|
target: String(inboxEnvelope.target || ""),
|
package/dist/platform/config.cjs
CHANGED
|
@@ -46,6 +46,7 @@ exports.assertInboxAuditInterval = assertInboxAuditInterval;
|
|
|
46
46
|
exports.parseInboxAuditInterval = parseInboxAuditInterval;
|
|
47
47
|
exports.formatInboxAuditInterval = formatInboxAuditInterval;
|
|
48
48
|
exports.inboxAuditMutationFromCli = inboxAuditMutationFromCli;
|
|
49
|
+
exports.processingEyeMutationFromCli = processingEyeMutationFromCli;
|
|
49
50
|
exports.hydrateAgent = hydrateAgent;
|
|
50
51
|
exports.normalizeConfig = normalizeConfig;
|
|
51
52
|
exports.assertPrivateConfigMetadata = assertPrivateConfigMetadata;
|
|
@@ -55,6 +56,7 @@ exports.toStored = toStored;
|
|
|
55
56
|
exports.resolveMentionPolicy = resolveMentionPolicy;
|
|
56
57
|
exports.resolveAgentGlobalMentionPolicy = resolveAgentGlobalMentionPolicy;
|
|
57
58
|
exports.resolveInboxAuditSchedule = resolveInboxAuditSchedule;
|
|
59
|
+
exports.resolveProcessingEye = resolveProcessingEye;
|
|
58
60
|
exports.runtimeConfigSignature = runtimeConfigSignature;
|
|
59
61
|
exports.configApplyState = configApplyState;
|
|
60
62
|
exports.markConfigApplied = markConfigApplied;
|
|
@@ -86,11 +88,12 @@ exports.MIN_INBOX_AUDIT_INTERVAL_MS = 60_000;
|
|
|
86
88
|
exports.MAX_INBOX_AUDIT_INTERVAL_MS = 24 * 60 * 60_000;
|
|
87
89
|
const TOP_FIELDS_V3 = new Set(["version", "serverId", "activeAgent", "agents"]);
|
|
88
90
|
const TOP_FIELDS_V4 = new Set(["version", "serverId", "mentionPolicy", "activeAgent", "agents"]);
|
|
89
|
-
const OPTIONAL_TOP_FIELDS_V4 = new Set(["inboxAudit"]);
|
|
91
|
+
const OPTIONAL_TOP_FIELDS_V4 = new Set(["inboxAudit", "processingEye"]);
|
|
90
92
|
const AGENT_FIELDS_V3 = new Set(["runtime", "model", "effort", "noMentionChats", "createdAt"]);
|
|
91
|
-
const AGENT_FIELDS_V4 = new Set(["runtime", "model", "effort", "mentionPolicy", "chatMentionPolicies", "inboxAudit", "createdAt"]);
|
|
93
|
+
const AGENT_FIELDS_V4 = new Set(["runtime", "model", "effort", "mentionPolicy", "chatMentionPolicies", "inboxAudit", "processingEye", "createdAt"]);
|
|
92
94
|
const LEGACY_AGENT_FIELDS = new Set(["piDistribution", "runtimeOption"]);
|
|
93
95
|
const INBOX_AUDIT_FIELDS = new Set(["enabled", "intervalMs"]);
|
|
96
|
+
const PROCESSING_EYE_FIELDS = new Set(["enabled"]);
|
|
94
97
|
const APP_ID = /^cli_[A-Za-z0-9]+$/;
|
|
95
98
|
const CHAT_ID = /^oc_[A-Za-z0-9_-]+$/;
|
|
96
99
|
const PI_EFFORTS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
@@ -203,6 +206,22 @@ function resolvedInboxAudit(settings) {
|
|
|
203
206
|
intervalMs: settings?.intervalMs ?? exports.DEFAULT_INBOX_AUDIT_INTERVAL_MS,
|
|
204
207
|
};
|
|
205
208
|
}
|
|
209
|
+
function parseStoredProcessingEye(value, label) {
|
|
210
|
+
if (!isPlainObject(value))
|
|
211
|
+
throw new Error(`${label} 必须是普通 object`);
|
|
212
|
+
assertAllowedFields(value, PROCESSING_EYE_FIELDS, label);
|
|
213
|
+
const settings = {};
|
|
214
|
+
if (Object.hasOwn(value, "enabled")) {
|
|
215
|
+
if (typeof value.enabled !== "boolean")
|
|
216
|
+
throw new Error(`${label}.enabled 必须是 boolean`);
|
|
217
|
+
settings.enabled = value.enabled;
|
|
218
|
+
}
|
|
219
|
+
return settings;
|
|
220
|
+
}
|
|
221
|
+
function resolvedProcessingEye(settings) {
|
|
222
|
+
// 缺 key 视为关闭。升级后不再保留旧的自动 OnIt 行为,除非用户显式开启。
|
|
223
|
+
return { enabled: settings?.enabled ?? false };
|
|
224
|
+
}
|
|
206
225
|
function inboxAuditMutationFromCli(input) {
|
|
207
226
|
if (input.scope === "global") {
|
|
208
227
|
if (input.enabled !== "on" && input.enabled !== "off") {
|
|
@@ -233,6 +252,25 @@ function inboxAuditMutationFromCli(input) {
|
|
|
233
252
|
}
|
|
234
253
|
throw new Error("inbox-audit scope 只支持 global/agent");
|
|
235
254
|
}
|
|
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
|
+
}
|
|
236
274
|
function assertModel(runtime, model) {
|
|
237
275
|
if (model === "default")
|
|
238
276
|
return;
|
|
@@ -302,6 +340,8 @@ function validateStoredAgent(key, agent, version) {
|
|
|
302
340
|
assertPolicy(agent.mentionPolicy, `Agent ${key}.mentionPolicy`);
|
|
303
341
|
if (version === 4 && Object.hasOwn(agent, "inboxAudit"))
|
|
304
342
|
parseStoredInboxAudit(agent.inboxAudit, `Agent ${key}.inboxAudit`);
|
|
343
|
+
if (version === 4 && Object.hasOwn(agent, "processingEye"))
|
|
344
|
+
parseStoredProcessingEye(agent.processingEye, `Agent ${key}.processingEye`);
|
|
305
345
|
if (version === 4 && Object.hasOwn(agent, "chatMentionPolicies")) {
|
|
306
346
|
if (!isPlainObject(agent.chatMentionPolicies))
|
|
307
347
|
throw new Error(`Agent ${key}.chatMentionPolicies 必须是普通 object`);
|
|
@@ -331,6 +371,7 @@ function hydratedStoredAgent(key, agent, version) {
|
|
|
331
371
|
...(typeof agent.effort === "string" ? { effort: agent.effort } : {}),
|
|
332
372
|
...(version === 4 && (agent.mentionPolicy === "require" || agent.mentionPolicy === "free") ? { mentionPolicy: agent.mentionPolicy } : {}),
|
|
333
373
|
...(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`) } : {}),
|
|
334
375
|
...(Object.keys(chatMentionPolicies).length ? { chatMentionPolicies, noMentionChats: Object.entries(chatMentionPolicies).filter(([, policy]) => policy === "free").map(([chatId]) => chatId) } : {}),
|
|
335
376
|
...(typeof agent.createdAt === "string" ? { createdAt: agent.createdAt } : {}),
|
|
336
377
|
};
|
|
@@ -345,6 +386,7 @@ function hydrateAgent(key, agent, configDir) {
|
|
|
345
386
|
...(agent.effort ? { effort: agent.effort } : {}),
|
|
346
387
|
...(agent.mentionPolicy ? { mentionPolicy: agent.mentionPolicy } : {}),
|
|
347
388
|
...(agent.inboxAudit ? { inboxAudit: { ...agent.inboxAudit } } : {}),
|
|
389
|
+
...(agent.processingEye ? { processingEye: { ...agent.processingEye } } : {}),
|
|
348
390
|
...(agent.chatMentionPolicies ? { chatMentionPolicies: { ...agent.chatMentionPolicies } } : {}),
|
|
349
391
|
...(agent.noMentionChats ? { noMentionChats: [...agent.noMentionChats] } : {}),
|
|
350
392
|
...(agent.createdAt ? { createdAt: agent.createdAt } : {}),
|
|
@@ -385,9 +427,13 @@ function normalizeConfig(raw, configDir, { mint } = {}) {
|
|
|
385
427
|
const inboxAudit = version === 4 && Object.hasOwn(raw, "inboxAudit")
|
|
386
428
|
? resolvedInboxAudit(parseStoredInboxAudit(raw.inboxAudit, "config.inboxAudit"))
|
|
387
429
|
: undefined;
|
|
430
|
+
const processingEye = version === 4 && Object.hasOwn(raw, "processingEye")
|
|
431
|
+
? resolvedProcessingEye(parseStoredProcessingEye(raw.processingEye, "config.processingEye"))
|
|
432
|
+
: undefined;
|
|
388
433
|
return {
|
|
389
434
|
version: 4, serverId: raw.serverId, mentionPolicy: version === 4 ? raw.mentionPolicy : "require",
|
|
390
435
|
...(inboxAudit ? { inboxAudit } : {}),
|
|
436
|
+
...(processingEye ? { processingEye } : {}),
|
|
391
437
|
configDir: layout.configDir, larkinHome: layout.larkinHome, larkConfigDir: resolveLarkConfigDir({}, layout.root), activeAgent: raw.activeAgent, agents,
|
|
392
438
|
};
|
|
393
439
|
}
|
|
@@ -618,6 +664,8 @@ function toStored(config) {
|
|
|
618
664
|
};
|
|
619
665
|
if (config.inboxAudit)
|
|
620
666
|
out.inboxAudit = { enabled: config.inboxAudit.enabled, intervalMs: config.inboxAudit.intervalMs };
|
|
667
|
+
if (config.processingEye)
|
|
668
|
+
out.processingEye = { enabled: config.processingEye.enabled };
|
|
621
669
|
for (const [key, agent] of Object.entries(config.agents || {})) {
|
|
622
670
|
const stored = { runtime: agent.runtime, model: agent.model };
|
|
623
671
|
if (typeof agent.effort === "string" && agent.effort)
|
|
@@ -629,6 +677,9 @@ function toStored(config) {
|
|
|
629
677
|
if (agent.inboxAudit && (agent.inboxAudit.enabled !== undefined || agent.inboxAudit.intervalMs !== undefined)) {
|
|
630
678
|
stored.inboxAudit = { ...agent.inboxAudit };
|
|
631
679
|
}
|
|
680
|
+
if (agent.processingEye && agent.processingEye.enabled !== undefined) {
|
|
681
|
+
stored.processingEye = { enabled: agent.processingEye.enabled };
|
|
682
|
+
}
|
|
632
683
|
if (typeof agent.createdAt === "string" && agent.createdAt)
|
|
633
684
|
stored.createdAt = agent.createdAt;
|
|
634
685
|
out.agents[key] = stored;
|
|
@@ -669,6 +720,16 @@ function resolveInboxAuditSchedule(config, agentId) {
|
|
|
669
720
|
intervalSource: agent.inboxAudit?.intervalMs !== undefined ? "agent" : config.inboxAudit?.intervalMs !== undefined ? "global" : "default",
|
|
670
721
|
};
|
|
671
722
|
}
|
|
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
|
+
}
|
|
672
733
|
function revision(bytes) {
|
|
673
734
|
return `sha256:${crypto.createHash("sha256").update(bytes).digest("hex")}`;
|
|
674
735
|
}
|
|
@@ -682,6 +743,7 @@ function agentSignature(config, agentId) {
|
|
|
682
743
|
runtime: agent.runtime, model: agent.model, effort: agent.effort ?? null,
|
|
683
744
|
globalMentionPolicy: config.mentionPolicy, agentMentionPolicy: agent.mentionPolicy ?? null, chatMentionPolicies: chats,
|
|
684
745
|
globalInboxAudit: config.inboxAudit ?? null, agentInboxAudit: agent.inboxAudit ?? null,
|
|
746
|
+
globalProcessingEye: config.processingEye ?? null, agentProcessingEye: agent.processingEye ?? null,
|
|
685
747
|
}));
|
|
686
748
|
}
|
|
687
749
|
function runtimeConfigSignature(config, agentId) {
|
|
@@ -832,6 +894,10 @@ function applyMutation(config, mutation) {
|
|
|
832
894
|
config.inboxAudit = current;
|
|
833
895
|
return { scope: "global", runtimeChange: false, affectedAgentIds: Object.keys(config.agents) };
|
|
834
896
|
}
|
|
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
|
+
}
|
|
835
901
|
if (!APP_ID.test(mutation.agentId) || !config.agents[mutation.agentId])
|
|
836
902
|
throw new Error(`Agent 不存在:${mutation.agentId}`);
|
|
837
903
|
const agent = config.agents[mutation.agentId];
|
|
@@ -864,6 +930,13 @@ function applyMutation(config, mutation) {
|
|
|
864
930
|
agent.inboxAudit = current;
|
|
865
931
|
return { scope: "agent", agentId: mutation.agentId, runtimeChange: false, affectedAgentIds: [mutation.agentId] };
|
|
866
932
|
}
|
|
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
|
+
}
|
|
867
940
|
if (mutation.kind === "set-chat-mention") {
|
|
868
941
|
if (!CHAT_ID.test(mutation.chatId))
|
|
869
942
|
throw new Error(`群 ID 格式无效:${mutation.chatId}`);
|
|
@@ -1361,13 +1434,23 @@ function safeConfigView(config, onlyAgentId, chatId, applyState) {
|
|
|
1361
1434
|
source: { enabled: resolved.enabledSource, intervalMs: resolved.intervalSource },
|
|
1362
1435
|
};
|
|
1363
1436
|
})(),
|
|
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
|
+
})(),
|
|
1364
1445
|
chatMentionPolicies: { ...(agent.chatMentionPolicies || {}) },
|
|
1365
1446
|
apply: applyState?.agents?.[agentId] ?? { applyState: "unknown" },
|
|
1366
1447
|
}));
|
|
1367
1448
|
const inboxAudit = resolvedInboxAudit(config.inboxAudit);
|
|
1449
|
+
const processingEye = resolvedProcessingEye(config.processingEye);
|
|
1368
1450
|
return {
|
|
1369
1451
|
version: 4, mentionPolicy: config.mentionPolicy,
|
|
1370
1452
|
inboxAudit: { enabled: inboxAudit.enabled, intervalMs: inboxAudit.intervalMs },
|
|
1453
|
+
processingEye: { enabled: processingEye.enabled },
|
|
1371
1454
|
persistedRevision: applyState?.persistedRevision ?? "unknown", agents,
|
|
1372
1455
|
};
|
|
1373
1456
|
}
|
package/dist/platform/config.mjs
CHANGED
|
@@ -13,11 +13,12 @@ export const MIN_INBOX_AUDIT_INTERVAL_MS = 60_000;
|
|
|
13
13
|
export const MAX_INBOX_AUDIT_INTERVAL_MS = 24 * 60 * 60_000;
|
|
14
14
|
const TOP_FIELDS_V3 = new Set(["version", "serverId", "activeAgent", "agents"]);
|
|
15
15
|
const TOP_FIELDS_V4 = new Set(["version", "serverId", "mentionPolicy", "activeAgent", "agents"]);
|
|
16
|
-
const OPTIONAL_TOP_FIELDS_V4 = new Set(["inboxAudit"]);
|
|
16
|
+
const OPTIONAL_TOP_FIELDS_V4 = new Set(["inboxAudit", "processingEye"]);
|
|
17
17
|
const AGENT_FIELDS_V3 = new Set(["runtime", "model", "effort", "noMentionChats", "createdAt"]);
|
|
18
|
-
const AGENT_FIELDS_V4 = new Set(["runtime", "model", "effort", "mentionPolicy", "chatMentionPolicies", "inboxAudit", "createdAt"]);
|
|
18
|
+
const AGENT_FIELDS_V4 = new Set(["runtime", "model", "effort", "mentionPolicy", "chatMentionPolicies", "inboxAudit", "processingEye", "createdAt"]);
|
|
19
19
|
const LEGACY_AGENT_FIELDS = new Set(["piDistribution", "runtimeOption"]);
|
|
20
20
|
const INBOX_AUDIT_FIELDS = new Set(["enabled", "intervalMs"]);
|
|
21
|
+
const PROCESSING_EYE_FIELDS = new Set(["enabled"]);
|
|
21
22
|
const APP_ID = /^cli_[A-Za-z0-9]+$/;
|
|
22
23
|
const CHAT_ID = /^oc_[A-Za-z0-9_-]+$/;
|
|
23
24
|
const PI_EFFORTS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
@@ -130,6 +131,22 @@ function resolvedInboxAudit(settings) {
|
|
|
130
131
|
intervalMs: settings?.intervalMs ?? DEFAULT_INBOX_AUDIT_INTERVAL_MS,
|
|
131
132
|
};
|
|
132
133
|
}
|
|
134
|
+
function parseStoredProcessingEye(value, label) {
|
|
135
|
+
if (!isPlainObject(value))
|
|
136
|
+
throw new Error(`${label} 必须是普通 object`);
|
|
137
|
+
assertAllowedFields(value, PROCESSING_EYE_FIELDS, label);
|
|
138
|
+
const settings = {};
|
|
139
|
+
if (Object.hasOwn(value, "enabled")) {
|
|
140
|
+
if (typeof value.enabled !== "boolean")
|
|
141
|
+
throw new Error(`${label}.enabled 必须是 boolean`);
|
|
142
|
+
settings.enabled = value.enabled;
|
|
143
|
+
}
|
|
144
|
+
return settings;
|
|
145
|
+
}
|
|
146
|
+
function resolvedProcessingEye(settings) {
|
|
147
|
+
// 缺 key 视为关闭。升级后不再保留旧的自动 OnIt 行为,除非用户显式开启。
|
|
148
|
+
return { enabled: settings?.enabled ?? false };
|
|
149
|
+
}
|
|
133
150
|
export function inboxAuditMutationFromCli(input) {
|
|
134
151
|
if (input.scope === "global") {
|
|
135
152
|
if (input.enabled !== "on" && input.enabled !== "off") {
|
|
@@ -160,6 +177,25 @@ export function inboxAuditMutationFromCli(input) {
|
|
|
160
177
|
}
|
|
161
178
|
throw new Error("inbox-audit scope 只支持 global/agent");
|
|
162
179
|
}
|
|
180
|
+
export function processingEyeMutationFromCli(input) {
|
|
181
|
+
if (input.scope === "global") {
|
|
182
|
+
if (input.enabled !== "on" && input.enabled !== "off") {
|
|
183
|
+
throw new Error("用法: larkin config processing-eye global <on|off>");
|
|
184
|
+
}
|
|
185
|
+
return { kind: "set-global-processing-eye", enabled: input.enabled === "on" };
|
|
186
|
+
}
|
|
187
|
+
if (input.scope === "agent") {
|
|
188
|
+
if (input.enabled !== "on" && input.enabled !== "off" && input.enabled !== "inherit") {
|
|
189
|
+
throw new Error("用法: larkin config processing-eye agent <inherit|on|off> [--agent <App ID>]");
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
kind: "set-agent-processing-eye",
|
|
193
|
+
agentId: input.agentId,
|
|
194
|
+
enabled: input.enabled === "inherit" ? "inherit" : input.enabled === "on",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
throw new Error("processing-eye scope 只支持 global/agent");
|
|
198
|
+
}
|
|
163
199
|
function assertModel(runtime, model) {
|
|
164
200
|
if (model === "default")
|
|
165
201
|
return;
|
|
@@ -229,6 +265,8 @@ function validateStoredAgent(key, agent, version) {
|
|
|
229
265
|
assertPolicy(agent.mentionPolicy, `Agent ${key}.mentionPolicy`);
|
|
230
266
|
if (version === 4 && Object.hasOwn(agent, "inboxAudit"))
|
|
231
267
|
parseStoredInboxAudit(agent.inboxAudit, `Agent ${key}.inboxAudit`);
|
|
268
|
+
if (version === 4 && Object.hasOwn(agent, "processingEye"))
|
|
269
|
+
parseStoredProcessingEye(agent.processingEye, `Agent ${key}.processingEye`);
|
|
232
270
|
if (version === 4 && Object.hasOwn(agent, "chatMentionPolicies")) {
|
|
233
271
|
if (!isPlainObject(agent.chatMentionPolicies))
|
|
234
272
|
throw new Error(`Agent ${key}.chatMentionPolicies 必须是普通 object`);
|
|
@@ -258,6 +296,7 @@ function hydratedStoredAgent(key, agent, version) {
|
|
|
258
296
|
...(typeof agent.effort === "string" ? { effort: agent.effort } : {}),
|
|
259
297
|
...(version === 4 && (agent.mentionPolicy === "require" || agent.mentionPolicy === "free") ? { mentionPolicy: agent.mentionPolicy } : {}),
|
|
260
298
|
...(version === 4 && Object.hasOwn(agent, "inboxAudit") ? { inboxAudit: parseStoredInboxAudit(agent.inboxAudit, `Agent ${key}.inboxAudit`) } : {}),
|
|
299
|
+
...(version === 4 && Object.hasOwn(agent, "processingEye") ? { processingEye: parseStoredProcessingEye(agent.processingEye, `Agent ${key}.processingEye`) } : {}),
|
|
261
300
|
...(Object.keys(chatMentionPolicies).length ? { chatMentionPolicies, noMentionChats: Object.entries(chatMentionPolicies).filter(([, policy]) => policy === "free").map(([chatId]) => chatId) } : {}),
|
|
262
301
|
...(typeof agent.createdAt === "string" ? { createdAt: agent.createdAt } : {}),
|
|
263
302
|
};
|
|
@@ -272,6 +311,7 @@ export function hydrateAgent(key, agent, configDir) {
|
|
|
272
311
|
...(agent.effort ? { effort: agent.effort } : {}),
|
|
273
312
|
...(agent.mentionPolicy ? { mentionPolicy: agent.mentionPolicy } : {}),
|
|
274
313
|
...(agent.inboxAudit ? { inboxAudit: { ...agent.inboxAudit } } : {}),
|
|
314
|
+
...(agent.processingEye ? { processingEye: { ...agent.processingEye } } : {}),
|
|
275
315
|
...(agent.chatMentionPolicies ? { chatMentionPolicies: { ...agent.chatMentionPolicies } } : {}),
|
|
276
316
|
...(agent.noMentionChats ? { noMentionChats: [...agent.noMentionChats] } : {}),
|
|
277
317
|
...(agent.createdAt ? { createdAt: agent.createdAt } : {}),
|
|
@@ -312,9 +352,13 @@ export function normalizeConfig(raw, configDir, { mint } = {}) {
|
|
|
312
352
|
const inboxAudit = version === 4 && Object.hasOwn(raw, "inboxAudit")
|
|
313
353
|
? resolvedInboxAudit(parseStoredInboxAudit(raw.inboxAudit, "config.inboxAudit"))
|
|
314
354
|
: undefined;
|
|
355
|
+
const processingEye = version === 4 && Object.hasOwn(raw, "processingEye")
|
|
356
|
+
? resolvedProcessingEye(parseStoredProcessingEye(raw.processingEye, "config.processingEye"))
|
|
357
|
+
: undefined;
|
|
315
358
|
return {
|
|
316
359
|
version: 4, serverId: raw.serverId, mentionPolicy: version === 4 ? raw.mentionPolicy : "require",
|
|
317
360
|
...(inboxAudit ? { inboxAudit } : {}),
|
|
361
|
+
...(processingEye ? { processingEye } : {}),
|
|
318
362
|
configDir: layout.configDir, larkinHome: layout.larkinHome, larkConfigDir: resolveLarkConfigDir({}, layout.root), activeAgent: raw.activeAgent, agents,
|
|
319
363
|
};
|
|
320
364
|
}
|
|
@@ -545,6 +589,8 @@ export function toStored(config) {
|
|
|
545
589
|
};
|
|
546
590
|
if (config.inboxAudit)
|
|
547
591
|
out.inboxAudit = { enabled: config.inboxAudit.enabled, intervalMs: config.inboxAudit.intervalMs };
|
|
592
|
+
if (config.processingEye)
|
|
593
|
+
out.processingEye = { enabled: config.processingEye.enabled };
|
|
548
594
|
for (const [key, agent] of Object.entries(config.agents || {})) {
|
|
549
595
|
const stored = { runtime: agent.runtime, model: agent.model };
|
|
550
596
|
if (typeof agent.effort === "string" && agent.effort)
|
|
@@ -556,6 +602,9 @@ export function toStored(config) {
|
|
|
556
602
|
if (agent.inboxAudit && (agent.inboxAudit.enabled !== undefined || agent.inboxAudit.intervalMs !== undefined)) {
|
|
557
603
|
stored.inboxAudit = { ...agent.inboxAudit };
|
|
558
604
|
}
|
|
605
|
+
if (agent.processingEye && agent.processingEye.enabled !== undefined) {
|
|
606
|
+
stored.processingEye = { enabled: agent.processingEye.enabled };
|
|
607
|
+
}
|
|
559
608
|
if (typeof agent.createdAt === "string" && agent.createdAt)
|
|
560
609
|
stored.createdAt = agent.createdAt;
|
|
561
610
|
out.agents[key] = stored;
|
|
@@ -596,6 +645,16 @@ export function resolveInboxAuditSchedule(config, agentId) {
|
|
|
596
645
|
intervalSource: agent.inboxAudit?.intervalMs !== undefined ? "agent" : config.inboxAudit?.intervalMs !== undefined ? "global" : "default",
|
|
597
646
|
};
|
|
598
647
|
}
|
|
648
|
+
export function resolveProcessingEye(config, agentId) {
|
|
649
|
+
const agent = config.agents[agentId];
|
|
650
|
+
if (!agent)
|
|
651
|
+
throw new Error(`Agent 不存在:${agentId}`);
|
|
652
|
+
const enabled = agent.processingEye?.enabled ?? config.processingEye?.enabled ?? false;
|
|
653
|
+
return {
|
|
654
|
+
enabled,
|
|
655
|
+
enabledSource: agent.processingEye?.enabled !== undefined ? "agent" : config.processingEye ? "global" : "default",
|
|
656
|
+
};
|
|
657
|
+
}
|
|
599
658
|
function revision(bytes) {
|
|
600
659
|
return `sha256:${crypto.createHash("sha256").update(bytes).digest("hex")}`;
|
|
601
660
|
}
|
|
@@ -609,6 +668,7 @@ function agentSignature(config, agentId) {
|
|
|
609
668
|
runtime: agent.runtime, model: agent.model, effort: agent.effort ?? null,
|
|
610
669
|
globalMentionPolicy: config.mentionPolicy, agentMentionPolicy: agent.mentionPolicy ?? null, chatMentionPolicies: chats,
|
|
611
670
|
globalInboxAudit: config.inboxAudit ?? null, agentInboxAudit: agent.inboxAudit ?? null,
|
|
671
|
+
globalProcessingEye: config.processingEye ?? null, agentProcessingEye: agent.processingEye ?? null,
|
|
612
672
|
}));
|
|
613
673
|
}
|
|
614
674
|
export function runtimeConfigSignature(config, agentId) {
|
|
@@ -759,6 +819,10 @@ function applyMutation(config, mutation) {
|
|
|
759
819
|
config.inboxAudit = current;
|
|
760
820
|
return { scope: "global", runtimeChange: false, affectedAgentIds: Object.keys(config.agents) };
|
|
761
821
|
}
|
|
822
|
+
if (mutation.kind === "set-global-processing-eye") {
|
|
823
|
+
config.processingEye = { enabled: mutation.enabled };
|
|
824
|
+
return { scope: "global", runtimeChange: false, affectedAgentIds: Object.keys(config.agents) };
|
|
825
|
+
}
|
|
762
826
|
if (!APP_ID.test(mutation.agentId) || !config.agents[mutation.agentId])
|
|
763
827
|
throw new Error(`Agent 不存在:${mutation.agentId}`);
|
|
764
828
|
const agent = config.agents[mutation.agentId];
|
|
@@ -791,6 +855,13 @@ function applyMutation(config, mutation) {
|
|
|
791
855
|
agent.inboxAudit = current;
|
|
792
856
|
return { scope: "agent", agentId: mutation.agentId, runtimeChange: false, affectedAgentIds: [mutation.agentId] };
|
|
793
857
|
}
|
|
858
|
+
if (mutation.kind === "set-agent-processing-eye") {
|
|
859
|
+
if (mutation.enabled === "inherit")
|
|
860
|
+
delete agent.processingEye;
|
|
861
|
+
else
|
|
862
|
+
agent.processingEye = { enabled: mutation.enabled };
|
|
863
|
+
return { scope: "agent", agentId: mutation.agentId, runtimeChange: false, affectedAgentIds: [mutation.agentId] };
|
|
864
|
+
}
|
|
794
865
|
if (mutation.kind === "set-chat-mention") {
|
|
795
866
|
if (!CHAT_ID.test(mutation.chatId))
|
|
796
867
|
throw new Error(`群 ID 格式无效:${mutation.chatId}`);
|
|
@@ -1288,13 +1359,23 @@ export function safeConfigView(config, onlyAgentId, chatId, applyState) {
|
|
|
1288
1359
|
source: { enabled: resolved.enabledSource, intervalMs: resolved.intervalSource },
|
|
1289
1360
|
};
|
|
1290
1361
|
})(),
|
|
1362
|
+
processingEye: (() => {
|
|
1363
|
+
const resolved = resolveProcessingEye(config, agentId);
|
|
1364
|
+
return {
|
|
1365
|
+
override: { enabled: agent.processingEye?.enabled === undefined ? "inherit" : agent.processingEye.enabled ? "on" : "off" },
|
|
1366
|
+
effective: { enabled: resolved.enabled },
|
|
1367
|
+
source: { enabled: resolved.enabledSource },
|
|
1368
|
+
};
|
|
1369
|
+
})(),
|
|
1291
1370
|
chatMentionPolicies: { ...(agent.chatMentionPolicies || {}) },
|
|
1292
1371
|
apply: applyState?.agents?.[agentId] ?? { applyState: "unknown" },
|
|
1293
1372
|
}));
|
|
1294
1373
|
const inboxAudit = resolvedInboxAudit(config.inboxAudit);
|
|
1374
|
+
const processingEye = resolvedProcessingEye(config.processingEye);
|
|
1295
1375
|
return {
|
|
1296
1376
|
version: 4, mentionPolicy: config.mentionPolicy,
|
|
1297
1377
|
inboxAudit: { enabled: inboxAudit.enabled, intervalMs: inboxAudit.intervalMs },
|
|
1378
|
+
processingEye: { enabled: processingEye.enabled },
|
|
1298
1379
|
persistedRevision: applyState?.persistedRevision ?? "unknown", agents,
|
|
1299
1380
|
};
|
|
1300
1381
|
}
|