larkway 0.3.41 → 0.3.42

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.41**
11
+ **Current release: v0.3.42**
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.41**
11
+ **当前版本:v0.3.42**
12
12
 
13
13
  ---
14
14
 
package/dist/cli/index.js CHANGED
@@ -112702,6 +112702,7 @@ function channelMsgToLarkEvent(msg) {
112702
112702
  if (!message_id || !chat_id || !senderOpenId) return null;
112703
112703
  const thread_id = m?.["thread_id"] ?? msg.threadId ?? m?.["root_id"] ?? msg.rootId ?? message_id;
112704
112704
  const root_id = m?.["root_id"] ?? msg.rootId ?? void 0;
112705
+ const parent_id = m?.["parent_id"] ?? msg.replyToMessageId ?? void 0;
112705
112706
  const rawContent = typeof m?.["content"] === "string" ? m["content"] : void 0;
112706
112707
  const content = rawContent ?? JSON.stringify({ text: stripAtMarkup(msg.content ?? "") });
112707
112708
  return {
@@ -112710,6 +112711,7 @@ function channelMsgToLarkEvent(msg) {
112710
112711
  chat_type: m?.["chat_type"] ?? msg.chatType ?? "group",
112711
112712
  thread_id,
112712
112713
  root_id,
112714
+ parent_id,
112713
112715
  sender_id: senderOpenId,
112714
112716
  mentions: m?.["mentions"] ?? void 0,
112715
112717
  content,
package/dist/main.js CHANGED
@@ -116856,6 +116856,7 @@ function channelMsgToLarkEvent(msg) {
116856
116856
  if (!message_id || !chat_id || !senderOpenId) return null;
116857
116857
  const thread_id = m?.["thread_id"] ?? msg.threadId ?? m?.["root_id"] ?? msg.rootId ?? message_id;
116858
116858
  const root_id = m?.["root_id"] ?? msg.rootId ?? void 0;
116859
+ const parent_id = m?.["parent_id"] ?? msg.replyToMessageId ?? void 0;
116859
116860
  const rawContent = typeof m?.["content"] === "string" ? m["content"] : void 0;
116860
116861
  const content = rawContent ?? JSON.stringify({ text: stripAtMarkup(msg.content ?? "") });
116861
116862
  return {
@@ -116864,6 +116865,7 @@ function channelMsgToLarkEvent(msg) {
116864
116865
  chat_type: m?.["chat_type"] ?? msg.chatType ?? "group",
116865
116866
  thread_id,
116866
116867
  root_id,
116868
+ parent_id,
116867
116869
  sender_id: senderOpenId,
116868
116870
  mentions: m?.["mentions"] ?? void 0,
116869
116871
  content,
@@ -122517,8 +122519,10 @@ var BridgeHandler = class {
122517
122519
  for await (const event of this.deps.client.events()) {
122518
122520
  if (this.closed) break;
122519
122521
  if (signal?.aborted) break;
122520
- const key = typeof event.root_id === "string" && event.root_id ? event.root_id : event.message_id;
122522
+ const key = typeof event.root_id === "string" && event.root_id ? event.root_id : typeof event.parent_id === "string" && event.parent_id ? event.parent_id : event.message_id;
122521
122523
  this.threadReceivedAt.set(key, Date.now());
122524
+ const legacySessionKey = typeof event.root_id === "string" && event.root_id ? event.root_id : event.message_id;
122525
+ if (legacySessionKey !== key) this.threadReceivedAt.set(legacySessionKey, Date.now());
122522
122526
  const prev = threadQueues.get(key) ?? Promise.resolve();
122523
122527
  const next = prev.then(() => acquire()).then(() => this.handleOne(event)).catch((err) => {
122524
122528
  console.error(`[bridge.handler] unhandled error on thread ${key}:`, err);
@@ -122556,10 +122560,39 @@ var BridgeHandler = class {
122556
122560
  };
122557
122561
  try {
122558
122562
  const parsed = parseMessage(event);
122559
- const { threadId, messageId, senderOpenId } = parsed;
122563
+ const { messageId, senderOpenId } = parsed;
122564
+ let threadId = parsed.threadId;
122560
122565
  const botId = this.deps.botConfig?.id;
122561
122566
  const eventLogId = messageId;
122562
122567
  const eventStartedAt = Date.now();
122568
+ let taskRootInfo;
122569
+ let taskCardAnchorId;
122570
+ let deferredTaskRootProbe;
122571
+ {
122572
+ const realTopic = realTopicThreadId(parsed.raw.thread_id);
122573
+ const rootCandidate = (typeof parsed.raw.root_id === "string" && parsed.raw.root_id ? parsed.raw.root_id : void 0) ?? (typeof parsed.raw.parent_id === "string" && parsed.raw.parent_id ? parsed.raw.parent_id : void 0);
122574
+ if (rootCandidate && this.deps.messageLookup) {
122575
+ const probe = this.deps.messageLookup.get(rootCandidate).catch(() => void 0);
122576
+ if (realTopic) {
122577
+ deferredTaskRootProbe = probe;
122578
+ } else {
122579
+ const info = await probe;
122580
+ if (info?.msgType === "todo" && info.content) {
122581
+ const todo = parseTodoShareContent(info.content);
122582
+ if (todo) {
122583
+ const probeThreadId = realTopicThreadId(info.threadId);
122584
+ taskRootInfo = {
122585
+ guid: todo.taskGuid,
122586
+ summary: todo.summaryText,
122587
+ topicLink: probeThreadId ? buildTopicDeepLink(parsed.chatId, probeThreadId) : void 0
122588
+ };
122589
+ taskCardAnchorId = rootCandidate;
122590
+ threadId = rootCandidate;
122591
+ }
122592
+ }
122593
+ }
122594
+ }
122595
+ }
122563
122596
  const turnReceivedAt = this.threadReceivedAt.get(threadId);
122564
122597
  const recordEvent = async (patch) => {
122565
122598
  if (!this.deps.recordRuntimeEvent) return;
@@ -122607,32 +122640,9 @@ var BridgeHandler = class {
122607
122640
  const isTopLevel = !(typeof parsed.raw.root_id === "string" && parsed.raw.root_id);
122608
122641
  let replyInThread = isTopLevel;
122609
122642
  let replyAnchorId = messageId;
122610
- let taskRootInfo;
122611
- let deferredTaskRootProbe;
122612
- {
122613
- const rootId = typeof parsed.raw.root_id === "string" && parsed.raw.root_id ? parsed.raw.root_id : void 0;
122614
- const rawThreadId = realTopicThreadId(parsed.raw.thread_id);
122615
- if (rootId && this.deps.messageLookup) {
122616
- const probe = this.deps.messageLookup.get(rootId).catch(() => void 0);
122617
- if (rawThreadId) {
122618
- deferredTaskRootProbe = probe;
122619
- } else {
122620
- const info = await probe;
122621
- if (info?.msgType === "todo" && info.content) {
122622
- const todo = parseTodoShareContent(info.content);
122623
- if (todo) {
122624
- const probeThreadId = realTopicThreadId(info.threadId);
122625
- taskRootInfo = {
122626
- guid: todo.taskGuid,
122627
- summary: todo.summaryText,
122628
- topicLink: probeThreadId ? buildTopicDeepLink(parsed.chatId, probeThreadId) : void 0
122629
- };
122630
- replyInThread = true;
122631
- replyAnchorId = rootId;
122632
- }
122633
- }
122634
- }
122635
- }
122643
+ if (taskCardAnchorId) {
122644
+ replyInThread = true;
122645
+ replyAnchorId = taskCardAnchorId;
122636
122646
  }
122637
122647
  const prototypeConfig = this.deps.botConfig?.response_surface_prototype;
122638
122648
  const cardKitAvailable = isResponseSurfaceCardKitAvailable(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larkway",
3
- "version": "0.3.41",
3
+ "version": "0.3.42",
4
4
  "description": "Thin bridge: Feishu thread to local Claude Code CLI",
5
5
  "license": "MIT",
6
6
  "author": "Chuck Wu (chuckwu0)",