larkway 0.3.19 → 0.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  You @ the bot in a Feishu thread. It runs on your machine — reading your real codebase, executing commands, opening MRs — and posts the result back. You define what the agent knows and what it can do. Larkway just carries the messages.
10
10
 
11
- **Current release: v0.3.19**
11
+ **Current release: v0.3.20**
12
12
 
13
13
  ---
14
14
 
package/README.zh.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  你在飞书话题里 @ bot,它在你的机器上运行——读真实代码库、执行命令、开 MR——把结果贴回飞书。你定义 agent 知道什么、能做什么。Larkway 只负责传递消息。
10
10
 
11
- **当前版本:v0.3.19**
11
+ **当前版本:v0.3.20**
12
12
 
13
13
  ---
14
14
 
package/dist/cli/index.js CHANGED
@@ -123677,12 +123677,13 @@ import path from "node:path";
123677
123677
  var NonEmptyString = external_exports.string().trim().min(1);
123678
123678
  function defaultResponseSurfacePrototypeConfig() {
123679
123679
  return {
123680
- enabled: false,
123680
+ enabled: true,
123681
123681
  allowed_chats: [],
123682
123682
  allowed_threads: [],
123683
123683
  lazy_card_creation: false,
123684
123684
  kill_switch: false,
123685
- post_outbound_enabled: false,
123685
+ post_outbound_enabled: true,
123686
+ allow_agent_mentions: true,
123686
123687
  allowed_mention_open_ids: [],
123687
123688
  max_posts_per_turn: 1,
123688
123689
  max_posts_per_window: 4,
@@ -123693,12 +123694,13 @@ function defaultResponseSurfacePrototypeConfig() {
123693
123694
  }
123694
123695
  var DEFAULT_RESPONSE_SURFACE_PROTOTYPE = defaultResponseSurfacePrototypeConfig();
123695
123696
  var responseSurfacePrototypeConfigDefaults = () => ({
123696
- enabled: false,
123697
+ enabled: true,
123697
123698
  allowed_chats: [],
123698
123699
  allowed_threads: [],
123699
123700
  lazy_card_creation: false,
123700
123701
  kill_switch: false,
123701
- post_outbound_enabled: false,
123702
+ post_outbound_enabled: true,
123703
+ allow_agent_mentions: true,
123702
123704
  allowed_mention_open_ids: [],
123703
123705
  max_posts_per_turn: 1,
123704
123706
  max_posts_per_window: 4,
@@ -123747,17 +123749,18 @@ var ResponseSurfaceStateSchema = external_exports.preprocess((value) => {
123747
123749
  }, StrictResponseSurfaceStateSchema.optional());
123748
123750
  var ResponseSurfacePrototypeConfigSchema = external_exports.object({
123749
123751
  /**
123750
- * Master gate. Default false keeps the legacy card-only response path.
123752
+ * Master gate. Default true makes response surfaces available unless the
123753
+ * runtime kill switch disables them.
123751
123754
  */
123752
- enabled: external_exports.boolean().default(false),
123755
+ enabled: external_exports.boolean().default(true),
123753
123756
  /**
123754
- * Optional chat allowlist for dark-launch experiments. Empty means no chat
123755
- * is allowlisted by this gate.
123757
+ * Optional chat allowlist for staged rollout. Empty means all chats are
123758
+ * allowed by this gate.
123756
123759
  */
123757
123760
  allowed_chats: external_exports.array(external_exports.string().min(1)).default([]),
123758
123761
  /**
123759
- * Optional Larkway session/thread allowlist for narrow dogfood topics.
123760
- * Empty means no thread is allowlisted by this gate.
123762
+ * Optional Larkway session/thread allowlist for staged rollout. Empty means
123763
+ * all threads are allowed by this gate.
123761
123764
  */
123762
123765
  allowed_threads: external_exports.array(external_exports.string().min(1)).default([]),
123763
123766
  /**
@@ -123769,18 +123772,23 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
123769
123772
  /**
123770
123773
  * Runtime kill switch for emergency rollback. When true, every response
123771
123774
  * surface post path is treated as disabled even if enabled/allowlists are
123772
- * otherwise configured. Default false preserves current default-off behavior.
123775
+ * otherwise configured.
123773
123776
  */
123774
123777
  kill_switch: external_exports.boolean().default(false),
123775
123778
  /**
123776
- * PR3 dark-launch gate for real post outbound. This must stay false by
123777
- * default. PR4's dispatcher also requires this gate before any post path.
123779
+ * Gate for real post outbound. Defaults on, but the runtime still requires
123780
+ * an injected post client and all safety gates before any post path.
123778
123781
  */
123779
- post_outbound_enabled: external_exports.boolean().default(false),
123782
+ post_outbound_enabled: external_exports.boolean().default(true),
123780
123783
  /**
123781
- * Explicit target allowlist for future real post @ mentions. Empty means no
123782
- * mention target is authorized. Keep real IDs in private bot config, never
123783
- * in public docs/tests.
123784
+ * Allows Agent-authored post mentions. This powers handoff to peer bots.
123785
+ * Keep this false only when the operator wants to suppress every real @.
123786
+ */
123787
+ allow_agent_mentions: external_exports.boolean().default(true),
123788
+ /**
123789
+ * Optional target allowlist for real post @ mentions. Empty means the Agent
123790
+ * may choose mention targets; non-empty narrows mentions to this exact set.
123791
+ * Keep real IDs in private bot config, never in public docs/tests.
123784
123792
  */
123785
123793
  allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([]),
123786
123794
  /**
package/dist/main.js CHANGED
@@ -118256,12 +118256,13 @@ import path6 from "node:path";
118256
118256
  var NonEmptyString = external_exports.string().trim().min(1);
118257
118257
  function defaultResponseSurfacePrototypeConfig() {
118258
118258
  return {
118259
- enabled: false,
118259
+ enabled: true,
118260
118260
  allowed_chats: [],
118261
118261
  allowed_threads: [],
118262
118262
  lazy_card_creation: false,
118263
118263
  kill_switch: false,
118264
- post_outbound_enabled: false,
118264
+ post_outbound_enabled: true,
118265
+ allow_agent_mentions: true,
118265
118266
  allowed_mention_open_ids: [],
118266
118267
  max_posts_per_turn: 1,
118267
118268
  max_posts_per_window: 4,
@@ -118272,12 +118273,13 @@ function defaultResponseSurfacePrototypeConfig() {
118272
118273
  }
118273
118274
  var DEFAULT_RESPONSE_SURFACE_PROTOTYPE = defaultResponseSurfacePrototypeConfig();
118274
118275
  var responseSurfacePrototypeConfigDefaults = () => ({
118275
- enabled: false,
118276
+ enabled: true,
118276
118277
  allowed_chats: [],
118277
118278
  allowed_threads: [],
118278
118279
  lazy_card_creation: false,
118279
118280
  kill_switch: false,
118280
- post_outbound_enabled: false,
118281
+ post_outbound_enabled: true,
118282
+ allow_agent_mentions: true,
118281
118283
  allowed_mention_open_ids: [],
118282
118284
  max_posts_per_turn: 1,
118283
118285
  max_posts_per_window: 4,
@@ -118326,17 +118328,18 @@ var ResponseSurfaceStateSchema = external_exports.preprocess((value) => {
118326
118328
  }, StrictResponseSurfaceStateSchema.optional());
118327
118329
  var ResponseSurfacePrototypeConfigSchema = external_exports.object({
118328
118330
  /**
118329
- * Master gate. Default false keeps the legacy card-only response path.
118331
+ * Master gate. Default true makes response surfaces available unless the
118332
+ * runtime kill switch disables them.
118330
118333
  */
118331
- enabled: external_exports.boolean().default(false),
118334
+ enabled: external_exports.boolean().default(true),
118332
118335
  /**
118333
- * Optional chat allowlist for dark-launch experiments. Empty means no chat
118334
- * is allowlisted by this gate.
118336
+ * Optional chat allowlist for staged rollout. Empty means all chats are
118337
+ * allowed by this gate.
118335
118338
  */
118336
118339
  allowed_chats: external_exports.array(external_exports.string().min(1)).default([]),
118337
118340
  /**
118338
- * Optional Larkway session/thread allowlist for narrow dogfood topics.
118339
- * Empty means no thread is allowlisted by this gate.
118341
+ * Optional Larkway session/thread allowlist for staged rollout. Empty means
118342
+ * all threads are allowed by this gate.
118340
118343
  */
118341
118344
  allowed_threads: external_exports.array(external_exports.string().min(1)).default([]),
118342
118345
  /**
@@ -118348,18 +118351,23 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
118348
118351
  /**
118349
118352
  * Runtime kill switch for emergency rollback. When true, every response
118350
118353
  * surface post path is treated as disabled even if enabled/allowlists are
118351
- * otherwise configured. Default false preserves current default-off behavior.
118354
+ * otherwise configured.
118352
118355
  */
118353
118356
  kill_switch: external_exports.boolean().default(false),
118354
118357
  /**
118355
- * PR3 dark-launch gate for real post outbound. This must stay false by
118356
- * default. PR4's dispatcher also requires this gate before any post path.
118358
+ * Gate for real post outbound. Defaults on, but the runtime still requires
118359
+ * an injected post client and all safety gates before any post path.
118357
118360
  */
118358
- post_outbound_enabled: external_exports.boolean().default(false),
118361
+ post_outbound_enabled: external_exports.boolean().default(true),
118359
118362
  /**
118360
- * Explicit target allowlist for future real post @ mentions. Empty means no
118361
- * mention target is authorized. Keep real IDs in private bot config, never
118362
- * in public docs/tests.
118363
+ * Allows Agent-authored post mentions. This powers handoff to peer bots.
118364
+ * Keep this false only when the operator wants to suppress every real @.
118365
+ */
118366
+ allow_agent_mentions: external_exports.boolean().default(true),
118367
+ /**
118368
+ * Optional target allowlist for real post @ mentions. Empty means the Agent
118369
+ * may choose mention targets; non-empty narrows mentions to this exact set.
118370
+ * Keep real IDs in private bot config, never in public docs/tests.
118363
118371
  */
118364
118372
  allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([]),
118365
118373
  /**
@@ -118391,12 +118399,21 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
118391
118399
  function isResponseSurfacePrototypeAllowlisted(config, facts) {
118392
118400
  if (!config?.enabled) return false;
118393
118401
  if (config.kill_switch) return false;
118402
+ const hasScopedAllowlist = config.allowed_chats.length > 0 || config.allowed_threads.length > 0;
118403
+ if (!hasScopedAllowlist) return true;
118394
118404
  const chatAllowed = config.allowed_chats.length > 0 && config.allowed_chats.includes(facts.chatId);
118395
118405
  const threadAllowed = config.allowed_threads.length > 0 && config.allowed_threads.includes(facts.threadId);
118396
118406
  return chatAllowed || threadAllowed;
118397
118407
  }
118408
+ function isResponseSurfaceMentionAllowed(config, userId) {
118409
+ if (!config?.allow_agent_mentions) return false;
118410
+ const normalized = userId.trim().toLowerCase();
118411
+ if (normalized === "all" || normalized === "@all") return false;
118412
+ if (config.allowed_mention_open_ids.length === 0) return true;
118413
+ return config.allowed_mention_open_ids.includes(userId);
118414
+ }
118398
118415
  function shouldProvideResponseSurfacePostClient(config) {
118399
- return !!(config?.enabled && !config.kill_switch && config.post_outbound_enabled && config.max_posts_per_turn >= 1 && config.max_posts_per_window >= 1 && (config.allowed_chats.length > 0 || config.allowed_threads.length > 0));
118416
+ return !!(config?.enabled && !config.kill_switch && config.post_outbound_enabled && config.max_posts_per_turn >= 1 && config.max_posts_per_window >= 1);
118400
118417
  }
118401
118418
  function isResponseSurfacePostOutboundAvailable(config, facts, opts) {
118402
118419
  return !!(opts.postClientAvailable && shouldProvideResponseSurfacePostClient(config) && isResponseSurfacePrototypeAllowlisted(config, facts));
@@ -119228,7 +119245,7 @@ function policyBlockedCard(input) {
119228
119245
  return {
119229
119246
  ...input.baseCard,
119230
119247
  success: false,
119231
- failureReason: "response_surface post mention target is not in allowed_mention_open_ids; visible card fallback used"
119248
+ failureReason: "response_surface post mention target is blocked by policy; visible card fallback used"
119232
119249
  };
119233
119250
  }
119234
119251
  function postText(input) {
@@ -119347,7 +119364,7 @@ async function dispatchResponseSurfaceInner(input) {
119347
119364
  }
119348
119365
  const mentions = surface.post?.mentions ?? [];
119349
119366
  const blockedMention = mentions.find(
119350
- (mention) => !cfg.allowed_mention_open_ids.includes(mention.user_id)
119367
+ (mention) => !isResponseSurfaceMentionAllowed(cfg, mention.user_id)
119351
119368
  );
119352
119369
  const text = postText(input);
119353
119370
  const policyDigest = digestPostContent(text);
@@ -119363,7 +119380,7 @@ async function dispatchResponseSurfaceInner(input) {
119363
119380
  });
119364
119381
  const now = input.now?.() ?? (/* @__PURE__ */ new Date()).toISOString();
119365
119382
  if (blockedMention) {
119366
- const policyError = `mention target is not allowed: ${blockedMention.user_id}`;
119383
+ const policyError = `mention target is not allowed by response surface policy: ${blockedMention.user_id}`;
119367
119384
  await writeLedger(
119368
119385
  input,
119369
119386
  newLedgerEntry({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larkway",
3
- "version": "0.3.19",
3
+ "version": "0.3.20",
4
4
  "description": "Thin bridge: Feishu thread to local Claude Code CLI",
5
5
  "license": "MIT",
6
6
  "author": "Chuck Wu (chuckwu0)",