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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.18
4
+
5
+ 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.
6
+
3
7
  ## 0.5.8
4
8
 
5
9
  Lark setup now reconciles requested tenant permissions with actual grants and links missing scopes to the same application in the developer console. Required permissions still block setup until granted; optional permissions and event/callback verification are reported separately. Existing-application authorization preserves and checks its App ID before recording any capability state.
package/README.md CHANGED
@@ -114,6 +114,17 @@ 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
+ ### Optional processing eye (OnIt)
118
+
119
+ The Feishu "processing eye" (OnIt reaction on inbound messages while the Agent works) is **off by default**. A missing `processingEye` key is treated as off, so upgrading to this version stops the auto-reaction without a migration prompt. In the Dashboard, use **Global settings → 处理中表情** or the selected Agent's **Configuration → 处理中表情**. The same settings are available through the CLI:
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
+ ```
127
+
117
128
  <details>
118
129
  <summary>Windows support and optional autostart</summary>
119
130
 
@@ -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", "apply"]);
4
+ exports.CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "processing-eye", "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,6 +12,8 @@ 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>]",
15
17
  "larkin config apply [--agent <App ID>]",
16
18
  ]);
17
19
  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", "apply"]);
1
+ export const CONFIG_CLI_OPERATIONS = Object.freeze(["show", "runtime", "model", "effort", "mention", "inbox-audit", "processing-eye", "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,6 +9,8 @@ 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>]",
12
14
  "larkin config apply [--agent <App ID>]",
13
15
  ]);
14
16
  export const CONFIG_CLI_VALUES = Object.freeze({
@@ -256,6 +256,23 @@ 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
+ }
259
276
  else if (operation === "apply") {
260
277
  assertOnlyFlags(["--agent"]);
261
278
  if (options.positionals.length)
@@ -269,7 +286,7 @@ function agentConfigRequest(argv, env, config, agent, dependencies) {
269
286
  }).catch((error) => { throw new Error(`配置已保存但未应用:${error instanceof Error ? error.message : String(error)}`); });
270
287
  }
271
288
  else
272
- throw new Error("config 只支持 show/runtime/model/effort/mention/inbox-audit/apply;运行 larkin config --help");
289
+ throw new Error("config 只支持 show/runtime/model/effort/mention/inbox-audit/processing-eye/apply;运行 larkin config --help");
273
290
  const result = larkinConfig.mutateConfig(env, mutation, authority);
274
291
  return { ok: true, revision: result.revision, persisted: true, applyState: result.applyState, changedScope: result.changedScope };
275
292
  }
@@ -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|apply> | larkin model [<id>] | larkin runtime [<id>] [--model <id>] | larkin effort [<level>|clear] | larkin chats [free|strict <oc_id>]");
55
+ die("用法: larkin agents | larkin config <show|mention|inbox-audit|processing-eye|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,13 +162,23 @@ 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
+ }
165
175
  else if (operation === "apply") {
166
176
  assertOnlyFlags(["--agent"]);
167
177
  if (positionals.length !== 1)
168
178
  die("用法: larkin config apply [--agent <App ID>]");
169
179
  }
170
180
  else {
171
- die("config 只支持 show/mention/inbox-audit/apply;运行 larkin config --help");
181
+ die("config 只支持 show/mention/inbox-audit/processing-eye/apply;运行 larkin config --help");
172
182
  }
173
183
  }
174
184
  const loaded = (() => {
@@ -352,15 +362,20 @@ if (kind === "config") {
352
362
  say(`全局群消息策略=${String(view.mentionPolicy)}(free 会唤醒所有继承它的 Agent)`);
353
363
  const inboxAudit = view.inboxAudit;
354
364
  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)`);
355
367
  for (const item of view.agents) {
356
368
  const mention = item.mention;
357
369
  const agentAudit = item.inboxAudit;
370
+ const agentEye = item.processingEye;
358
371
  const apply = item.apply;
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"}`);
372
+ say(`agent=${item.agentId} runtime=${item.runtime} model=${item.model} effort=${item.effort || "default"} mention=${mention.override} inbox-audit=${agentAudit?.override?.enabled || "inherit"} processing-eye=${agentEye?.override?.enabled || "inherit"} apply=${apply.applyState || "unknown"}`);
360
373
  if (mention.chat)
361
374
  say(` chat=${mention.chat.chatId} override=${mention.chat.override} effective=${mention.chat.effective} source=${mention.chat.source}`);
362
375
  if (agentAudit?.effective)
363
376
  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"}`);
364
379
  }
365
380
  }
366
381
  process.exit(0);
@@ -405,6 +420,20 @@ if (kind === "config") {
405
420
  }
406
421
  process.exit(0);
407
422
  }
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
+ }
408
437
  if (operation === "apply") {
409
438
  const agentId = requireTarget();
410
439
  const expectedSignature = larkinConfig.runtimeConfigSignature(config, agentId);
@@ -424,7 +453,7 @@ if (kind === "config") {
424
453
  }
425
454
  process.exit(0);
426
455
  }
427
- die("config 只支持 show/mention/inbox-audit/apply");
456
+ die("config 只支持 show/mention/inbox-audit/processing-eye/apply");
428
457
  }
429
458
  let key = flagAgent;
430
459
  if (!key && runtimeAgentId)
package/dist/app/cli.mjs CHANGED
@@ -87,6 +87,7 @@ 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
90
91
 
91
92
  Credentials, internal paths, serverId, activeAgent, and raw config are never exposed here.`,
92
93
  session: `Usage: larkin session reset --agent <App ID> --json [--wait-ready <seconds>]
@@ -402,11 +402,17 @@ 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"],
405
406
  };
406
407
  if (!allowed[operation] || Object.keys(value).some((key) => !allowed[operation].includes(key)))
407
408
  throw new Error("unsupported operation");
408
409
  if (operation === "set-global-mention")
409
410
  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
+ }
410
416
  if (operation === "set-global-inbox-audit") {
411
417
  if (value.enabled !== undefined && typeof value.enabled !== "boolean")
412
418
  throw new Error("invalid inbox-audit enabled");
@@ -422,6 +428,11 @@ function dashboardMutation(value) {
422
428
  throw new Error("invalid inbox-audit interval");
423
429
  return { kind: operation, agentId, ...(value.enabled !== undefined ? { enabled: value.enabled } : {}), ...(value.intervalMs !== undefined ? { intervalMs: value.intervalMs } : {}) };
424
430
  }
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
+ }
425
436
  if (operation === "set-agent-mention")
426
437
  return { kind: operation, agentId, value: String(value.value) };
427
438
  if (operation === "set-chat-mention")