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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.19
|
|
4
|
+
|
|
5
|
+
The Feishu processing-eye OnIt reaction is no longer a config switch. After a successful deliver, Larkin reacts OnIt only for private chats (DM / p2p), when the inbound event already marked the bot as mentioned, or when the user is talking inside a topic the bot started (a Feishu topic whose root is a bot-owned message). Ordinary group messages without @ and outside a bot-started topic never get the reaction, including free-mention chats that still wake the Agent.
|
|
6
|
+
|
|
7
|
+
The 0.5.18 `processingEye.enabled` key, `larkin config processing-eye`, and Dashboard 处理中表情 toggle are removed. Leftover keys in existing configs are ignored on load and dropped on the next config write. There is no on/off flag and no migration prompt.
|
|
8
|
+
|
|
3
9
|
## 0.5.18
|
|
4
10
|
|
|
5
11
|
The Feishu processing-eye OnIt reaction is now off by default. New installs and existing configs that omit `processingEye` no longer auto-react on inbound messages after upgrade; there is no migration prompt. Opt back in with `larkin config processing-eye global on`, a per-Agent `on`/`off`/`inherit` override, or the Dashboard 处理中表情 toggle. Explicit `enabled: false` and a missing key both skip the reactions API.
|
package/README.md
CHANGED
|
@@ -114,16 +114,9 @@ larkin config inbox-audit global off
|
|
|
114
114
|
|
|
115
115
|
When enabled, audit only revisits originally wake-eligible human group/topic work and does not wake a model for an empty work list. Reading an audit list does not complete it: the managed Agent follows the returned inspection instructions and explicitly confirms the receipt after checking. A failed check remains retryable; newer messages cannot be completed by an older receipt. Old audit-index records without proven eligibility or observation identity are ignored; ordinary Inbox messages and conversation history are preserved.
|
|
116
116
|
|
|
117
|
-
###
|
|
117
|
+
### Processing eye (OnIt)
|
|
118
118
|
|
|
119
|
-
The Feishu "processing eye"
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
larkin config processing-eye global on
|
|
123
|
-
larkin config processing-eye agent off --agent <App-ID>
|
|
124
|
-
larkin config processing-eye agent inherit --agent <App-ID>
|
|
125
|
-
larkin config processing-eye global off
|
|
126
|
-
```
|
|
119
|
+
The Feishu "processing eye" is an OnIt reaction on the inbound message while the Agent works. It is automatic and not configurable: Larkin adds it after a successful deliver only for private chats (DM / p2p), when the inbound event marked the bot as mentioned, or when the user is talking inside a topic the bot started. Ordinary group messages without @ and outside a bot-started topic never get the reaction. The 0.5.18 `processingEye` config key, CLI, and Dashboard toggle are removed; leftover keys are ignored.
|
|
127
120
|
|
|
128
121
|
<details>
|
|
129
122
|
<summary>Windows support and optional autostart</summary>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CONFIG_CLI_VALUES = exports.CONFIG_CLI_USAGE = exports.CONFIG_CLI_OPERATIONS = void 0;
|
|
4
|
-
exports.CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "
|
|
4
|
+
exports.CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "apply"]);
|
|
5
5
|
exports.CONFIG_CLI_USAGE = Object.freeze([
|
|
6
6
|
"larkin config show [--agent <App ID>] [--chat <oc_id>] [--json]",
|
|
7
7
|
"larkin config runtime <runtime> [--model <model>] [--agent <App ID>]",
|
|
@@ -12,8 +12,6 @@ exports.CONFIG_CLI_USAGE = Object.freeze([
|
|
|
12
12
|
"larkin config mention chat <oc_id> <inherit|require|free> [--agent <App ID>]",
|
|
13
13
|
"larkin config inbox-audit global <on|off> [--interval <15m|1h>]",
|
|
14
14
|
"larkin config inbox-audit agent <inherit|on|off> [--agent <App ID>] [--interval <15m|inherit>]",
|
|
15
|
-
"larkin config processing-eye global <on|off>",
|
|
16
|
-
"larkin config processing-eye agent <inherit|on|off> [--agent <App ID>]",
|
|
17
15
|
"larkin config apply [--agent <App ID>]",
|
|
18
16
|
]);
|
|
19
17
|
exports.CONFIG_CLI_VALUES = Object.freeze({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "
|
|
1
|
+
export const CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "apply"]);
|
|
2
2
|
export const CONFIG_CLI_USAGE = Object.freeze([
|
|
3
3
|
"larkin config show [--agent <App ID>] [--chat <oc_id>] [--json]",
|
|
4
4
|
"larkin config runtime <runtime> [--model <model>] [--agent <App ID>]",
|
|
@@ -9,8 +9,6 @@ export const CONFIG_CLI_USAGE = Object.freeze([
|
|
|
9
9
|
"larkin config mention chat <oc_id> <inherit|require|free> [--agent <App ID>]",
|
|
10
10
|
"larkin config inbox-audit global <on|off> [--interval <15m|1h>]",
|
|
11
11
|
"larkin config inbox-audit agent <inherit|on|off> [--agent <App ID>] [--interval <15m|inherit>]",
|
|
12
|
-
"larkin config processing-eye global <on|off>",
|
|
13
|
-
"larkin config processing-eye agent <inherit|on|off> [--agent <App ID>]",
|
|
14
12
|
"larkin config apply [--agent <App ID>]",
|
|
15
13
|
]);
|
|
16
14
|
export const CONFIG_CLI_VALUES = Object.freeze({
|
|
@@ -49,6 +49,7 @@ const reminder_routes_js_1 = require("./reminder-routes.cjs");
|
|
|
49
49
|
const reminder_delivery_audit_js_1 = require("./reminder-delivery-audit.cjs");
|
|
50
50
|
const transport_shell_js_1 = require("./transport-shell.cjs");
|
|
51
51
|
const agent_lark_cli_workspace_js_1 = require("../app/agent-lark-cli-workspace.cjs");
|
|
52
|
+
const host_processing_eye_js_1 = require("../feishu/host-processing-eye.cjs");
|
|
52
53
|
function formatFeishuError(error, grantLink = null) {
|
|
53
54
|
if (!error)
|
|
54
55
|
return null;
|
|
@@ -139,6 +140,8 @@ function createTransportBusinessContext(env = process.env) {
|
|
|
139
140
|
const appendConversation = (item) => {
|
|
140
141
|
try {
|
|
141
142
|
fs.appendFileSync(paths.conversation, `${JSON.stringify({ ...item, text: (0, transport_shell_js_1.safeConversationExcerpt)(item.text) })}\n`);
|
|
143
|
+
if (item.direction === "out")
|
|
144
|
+
(0, host_processing_eye_js_1.persistBotTopicRoot)(stateStore, typeof item.messageId === "string" ? item.messageId : null);
|
|
142
145
|
}
|
|
143
146
|
catch (error) {
|
|
144
147
|
log(`conversation 写失败: ${error.message}`);
|
|
@@ -12,6 +12,7 @@ import { createReminderRoutes } from "./reminder-routes.mjs";
|
|
|
12
12
|
import { auditReminderDelivery } from "./reminder-delivery-audit.mjs";
|
|
13
13
|
import { isImageMime, looksLikeMarkdown, resolveMappedChatId, safeConversationExcerpt } from "./transport-shell.mjs";
|
|
14
14
|
import { managedOfficialLarkCli } from "../app/agent-lark-cli-workspace.mjs";
|
|
15
|
+
import { persistBotTopicRoot } from "../feishu/host-processing-eye.mjs";
|
|
15
16
|
export function formatFeishuError(error, grantLink = null) {
|
|
16
17
|
if (!error)
|
|
17
18
|
return null;
|
|
@@ -102,6 +103,8 @@ export function createTransportBusinessContext(env = process.env) {
|
|
|
102
103
|
const appendConversation = (item) => {
|
|
103
104
|
try {
|
|
104
105
|
fs.appendFileSync(paths.conversation, `${JSON.stringify({ ...item, text: safeConversationExcerpt(item.text) })}\n`);
|
|
106
|
+
if (item.direction === "out")
|
|
107
|
+
persistBotTopicRoot(stateStore, typeof item.messageId === "string" ? item.messageId : null);
|
|
105
108
|
}
|
|
106
109
|
catch (error) {
|
|
107
110
|
log(`conversation 写失败: ${error.message}`);
|
package/dist/app/agent-cli.mjs
CHANGED
|
@@ -256,23 +256,6 @@ function agentConfigRequest(argv, env, config, agent, dependencies) {
|
|
|
256
256
|
agentId: targetId,
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
|
-
else if (operation === "processing-eye") {
|
|
260
|
-
const [scope, first] = options.positionals;
|
|
261
|
-
if (scope === "global")
|
|
262
|
-
assertOnlyFlags([]);
|
|
263
|
-
else if (scope === "agent")
|
|
264
|
-
assertOnlyFlags(["--agent"]);
|
|
265
|
-
else
|
|
266
|
-
assertOnlyFlags([]);
|
|
267
|
-
if (options.positionals.length !== 2) {
|
|
268
|
-
throw new Error("用法: larkin config processing-eye global <on|off> | processing-eye agent <inherit|on|off> [--agent <App ID>]");
|
|
269
|
-
}
|
|
270
|
-
mutation = larkinConfig.processingEyeMutationFromCli({
|
|
271
|
-
scope: scope || "",
|
|
272
|
-
enabled: first,
|
|
273
|
-
agentId: targetId,
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
259
|
else if (operation === "apply") {
|
|
277
260
|
assertOnlyFlags(["--agent"]);
|
|
278
261
|
if (options.positionals.length)
|
|
@@ -286,7 +269,7 @@ function agentConfigRequest(argv, env, config, agent, dependencies) {
|
|
|
286
269
|
}).catch((error) => { throw new Error(`配置已保存但未应用:${error instanceof Error ? error.message : String(error)}`); });
|
|
287
270
|
}
|
|
288
271
|
else
|
|
289
|
-
throw new Error("config 只支持 show/runtime/model/effort/mention/inbox-audit/
|
|
272
|
+
throw new Error("config 只支持 show/runtime/model/effort/mention/inbox-audit/apply;运行 larkin config --help");
|
|
290
273
|
const result = larkinConfig.mutateConfig(env, mutation, authority);
|
|
291
274
|
return { ok: true, revision: result.revision, persisted: true, applyState: result.applyState, changedScope: result.changedScope };
|
|
292
275
|
}
|
|
@@ -52,7 +52,7 @@ const die = (message) => {
|
|
|
52
52
|
process.exit(1);
|
|
53
53
|
};
|
|
54
54
|
if (!kind || !["agents", "model", "runtime", "effort", "chats", "config"].includes(kind)) {
|
|
55
|
-
die("用法: larkin agents | larkin config <show|mention|inbox-audit|
|
|
55
|
+
die("用法: larkin agents | larkin config <show|mention|inbox-audit|apply> | larkin model [<id>] | larkin runtime [<id>] [--model <id>] | larkin effort [<level>|clear] | larkin chats [free|strict <oc_id>]");
|
|
56
56
|
}
|
|
57
57
|
const allowedValueFlags = {
|
|
58
58
|
agents: new Set(), model: new Set(["--agent"]), runtime: new Set(["--agent", "--model"]),
|
|
@@ -162,23 +162,13 @@ else if (kind === "config") {
|
|
|
162
162
|
if (positionals.length !== 3)
|
|
163
163
|
die("用法: larkin config inbox-audit agent <inherit|on|off> [--agent <App ID>] [--interval <15m|inherit>]");
|
|
164
164
|
}
|
|
165
|
-
else if (operation === "processing-eye" && scope === "global") {
|
|
166
|
-
assertOnlyFlags([]);
|
|
167
|
-
if (positionals.length !== 3)
|
|
168
|
-
die("用法: larkin config processing-eye global <on|off>");
|
|
169
|
-
}
|
|
170
|
-
else if (operation === "processing-eye" && scope === "agent") {
|
|
171
|
-
assertOnlyFlags(["--agent"]);
|
|
172
|
-
if (positionals.length !== 3)
|
|
173
|
-
die("用法: larkin config processing-eye agent <inherit|on|off> [--agent <App ID>]");
|
|
174
|
-
}
|
|
175
165
|
else if (operation === "apply") {
|
|
176
166
|
assertOnlyFlags(["--agent"]);
|
|
177
167
|
if (positionals.length !== 1)
|
|
178
168
|
die("用法: larkin config apply [--agent <App ID>]");
|
|
179
169
|
}
|
|
180
170
|
else {
|
|
181
|
-
die("config 只支持 show/mention/inbox-audit/
|
|
171
|
+
die("config 只支持 show/mention/inbox-audit/apply;运行 larkin config --help");
|
|
182
172
|
}
|
|
183
173
|
}
|
|
184
174
|
const loaded = (() => {
|
|
@@ -362,20 +352,15 @@ if (kind === "config") {
|
|
|
362
352
|
say(`全局群消息策略=${String(view.mentionPolicy)}(free 会唤醒所有继承它的 Agent)`);
|
|
363
353
|
const inboxAudit = view.inboxAudit;
|
|
364
354
|
say(`全局 Inbox Audit=${inboxAudit?.enabled ? "on" : "off"} interval=${larkinConfig.formatInboxAuditInterval(Number(inboxAudit?.intervalMs || larkinConfig.DEFAULT_INBOX_AUDIT_INTERVAL_MS))}(默认关闭;未 @ 的 require 群消息不会进入审计)`);
|
|
365
|
-
const processingEye = view.processingEye;
|
|
366
|
-
say(`全局处理中表情=${processingEye?.enabled ? "on" : "off"}(默认关闭;缺 key 视为关闭,升级后不再自动点 OnIt)`);
|
|
367
355
|
for (const item of view.agents) {
|
|
368
356
|
const mention = item.mention;
|
|
369
357
|
const agentAudit = item.inboxAudit;
|
|
370
|
-
const agentEye = item.processingEye;
|
|
371
358
|
const apply = item.apply;
|
|
372
|
-
say(`agent=${item.agentId} runtime=${item.runtime} model=${item.model} effort=${item.effort || "default"} mention=${mention.override} inbox-audit=${agentAudit?.override?.enabled || "inherit"}
|
|
359
|
+
say(`agent=${item.agentId} runtime=${item.runtime} model=${item.model} effort=${item.effort || "default"} mention=${mention.override} inbox-audit=${agentAudit?.override?.enabled || "inherit"} apply=${apply.applyState || "unknown"}`);
|
|
373
360
|
if (mention.chat)
|
|
374
361
|
say(` chat=${mention.chat.chatId} override=${mention.chat.override} effective=${mention.chat.effective} source=${mention.chat.source}`);
|
|
375
362
|
if (agentAudit?.effective)
|
|
376
363
|
say(` inbox-audit effective=${agentAudit.effective.enabled ? "on" : "off"} interval=${larkinConfig.formatInboxAuditInterval(Number(agentAudit.effective.intervalMs || larkinConfig.DEFAULT_INBOX_AUDIT_INTERVAL_MS))}`);
|
|
377
|
-
if (agentEye?.effective)
|
|
378
|
-
say(` processing-eye effective=${agentEye.effective.enabled ? "on" : "off"}`);
|
|
379
364
|
}
|
|
380
365
|
}
|
|
381
366
|
process.exit(0);
|
|
@@ -420,20 +405,6 @@ if (kind === "config") {
|
|
|
420
405
|
}
|
|
421
406
|
process.exit(0);
|
|
422
407
|
}
|
|
423
|
-
if (operation === "processing-eye") {
|
|
424
|
-
try {
|
|
425
|
-
const result = larkinConfig.mutateConfig(process.env, larkinConfig.processingEyeMutationFromCli({
|
|
426
|
-
scope: scope || "",
|
|
427
|
-
enabled: first,
|
|
428
|
-
agentId: scope === "agent" ? requireTarget() : (selected || keys[0] || ""),
|
|
429
|
-
}), authority);
|
|
430
|
-
say(JSON.stringify({ ok: true, revision: result.revision, persisted: result.persisted, applyState: result.applyState, changedScope: result.changedScope }, null, 2));
|
|
431
|
-
}
|
|
432
|
-
catch (error) {
|
|
433
|
-
die(error instanceof Error ? error.message : String(error));
|
|
434
|
-
}
|
|
435
|
-
process.exit(0);
|
|
436
|
-
}
|
|
437
408
|
if (operation === "apply") {
|
|
438
409
|
const agentId = requireTarget();
|
|
439
410
|
const expectedSignature = larkinConfig.runtimeConfigSignature(config, agentId);
|
|
@@ -453,7 +424,7 @@ if (kind === "config") {
|
|
|
453
424
|
}
|
|
454
425
|
process.exit(0);
|
|
455
426
|
}
|
|
456
|
-
die("config 只支持 show/mention/inbox-audit/
|
|
427
|
+
die("config 只支持 show/mention/inbox-audit/apply");
|
|
457
428
|
}
|
|
458
429
|
let key = flagAgent;
|
|
459
430
|
if (!key && runtimeAgentId)
|
package/dist/app/cli.mjs
CHANGED
|
@@ -87,7 +87,6 @@ Examples:
|
|
|
87
87
|
larkin config runtime pi --agent cli_x --model default
|
|
88
88
|
larkin config mention chat oc_x free --agent cli_x
|
|
89
89
|
larkin config inbox-audit global on --interval 15m
|
|
90
|
-
larkin config processing-eye global on
|
|
91
90
|
|
|
92
91
|
Credentials, internal paths, serverId, activeAgent, and raw config are never exposed here.`,
|
|
93
92
|
session: `Usage: larkin session reset --agent <App ID> --json [--wait-ready <seconds>]
|
package/dist/app/lark-cli.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import * as larkinConfig from "../platform/config.mjs";
|
|
|
11
11
|
import { resolveOfficialLarkCli } from "./official-lark-cli.mjs";
|
|
12
12
|
import { assertAgentWorkspaceBound, managedLarkCliEnv } from "./agent-lark-cli-workspace.mjs";
|
|
13
13
|
import { parseDocumentCommentTarget } from "../feishu/document-comment.mjs";
|
|
14
|
+
import { persistBotTopicRoot } from "../feishu/host-processing-eye.mjs";
|
|
14
15
|
import { SpanKind } from "@opentelemetry/api";
|
|
15
16
|
import { loadTelemetryConfig } from "../platform/telemetry-config.mjs";
|
|
16
17
|
import { telemetrySingleton } from "../platform/telemetry-tracing.mjs";
|
|
@@ -1294,6 +1295,9 @@ export function runLarkCli(argv, env = process.env, dependencies = {}) {
|
|
|
1294
1295
|
const deliveryAnchor = currentReminder?.deliveryAnchor;
|
|
1295
1296
|
const memo = !write.error && write.status === 0 && writeMessage
|
|
1296
1297
|
? recordImWriteMemo(store, intentKey, writeMessage.message_id, deliveryAnchor) : { duplicate: false };
|
|
1298
|
+
if (!write.error && write.status === 0 && writeMessage?.message_id) {
|
|
1299
|
+
persistBotTopicRoot(store, writeMessage.message_id);
|
|
1300
|
+
}
|
|
1297
1301
|
const duplicateOfEarlierReminder = memo.duplicate && Boolean(currentReminder)
|
|
1298
1302
|
&& memo.priorSourceMessageId !== currentReminder?.deliveryAnchor;
|
|
1299
1303
|
const committedWrite = !write.error && write.status === 0 && !duplicateOfEarlierReminder;
|
|
@@ -402,17 +402,11 @@ function dashboardMutation(value) {
|
|
|
402
402
|
"set-chat-mention": ["operation", "agentId", "chatId", "value"], "set-agent-runtime": ["operation", "agentId", "runtime", "model"],
|
|
403
403
|
"set-agent-model": ["operation", "agentId", "model"], "set-agent-effort": ["operation", "agentId", "effort"],
|
|
404
404
|
"set-global-inbox-audit": ["operation", "enabled", "intervalMs"], "set-agent-inbox-audit": ["operation", "agentId", "enabled", "intervalMs"],
|
|
405
|
-
"set-global-processing-eye": ["operation", "enabled"], "set-agent-processing-eye": ["operation", "agentId", "enabled"],
|
|
406
405
|
};
|
|
407
406
|
if (!allowed[operation] || Object.keys(value).some((key) => !allowed[operation].includes(key)))
|
|
408
407
|
throw new Error("unsupported operation");
|
|
409
408
|
if (operation === "set-global-mention")
|
|
410
409
|
return { kind: operation, value: String(value.value) };
|
|
411
|
-
if (operation === "set-global-processing-eye") {
|
|
412
|
-
if (typeof value.enabled !== "boolean")
|
|
413
|
-
throw new Error("invalid processing-eye enabled");
|
|
414
|
-
return { kind: operation, enabled: value.enabled };
|
|
415
|
-
}
|
|
416
410
|
if (operation === "set-global-inbox-audit") {
|
|
417
411
|
if (value.enabled !== undefined && typeof value.enabled !== "boolean")
|
|
418
412
|
throw new Error("invalid inbox-audit enabled");
|
|
@@ -428,11 +422,6 @@ function dashboardMutation(value) {
|
|
|
428
422
|
throw new Error("invalid inbox-audit interval");
|
|
429
423
|
return { kind: operation, agentId, ...(value.enabled !== undefined ? { enabled: value.enabled } : {}), ...(value.intervalMs !== undefined ? { intervalMs: value.intervalMs } : {}) };
|
|
430
424
|
}
|
|
431
|
-
if (operation === "set-agent-processing-eye") {
|
|
432
|
-
if (value.enabled !== "inherit" && typeof value.enabled !== "boolean")
|
|
433
|
-
throw new Error("invalid processing-eye enabled");
|
|
434
|
-
return { kind: operation, agentId, enabled: value.enabled };
|
|
435
|
-
}
|
|
436
425
|
if (operation === "set-agent-mention")
|
|
437
426
|
return { kind: operation, agentId, value: String(value.value) };
|
|
438
427
|
if (operation === "set-chat-mention")
|