larkway 0.3.40 → 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 +1 -1
- package/README.zh.md +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/main.js +51 -32
- package/package.json +1 -1
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.
|
|
11
|
+
**Current release: v0.3.42**
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
package/README.zh.md
CHANGED
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
|
@@ -116656,6 +116656,9 @@ function buildTopicDeepLink(chatId, threadId) {
|
|
|
116656
116656
|
const t = encodeURIComponent(threadId);
|
|
116657
116657
|
return `https://applink.feishu.cn/client/thread/open?open_chat_id=${c}&open_thread_id=${t}&openchatid=${c}&openthreadid=${t}&thread_position=-1`;
|
|
116658
116658
|
}
|
|
116659
|
+
function realTopicThreadId(threadId) {
|
|
116660
|
+
return typeof threadId === "string" && threadId.startsWith("omt_") ? threadId : void 0;
|
|
116661
|
+
}
|
|
116659
116662
|
var LOOKUP_TIMEOUT_MS = 5e3;
|
|
116660
116663
|
var CACHE_MAX = 200;
|
|
116661
116664
|
async function withTimeout2(p, ms, label) {
|
|
@@ -116853,6 +116856,7 @@ function channelMsgToLarkEvent(msg) {
|
|
|
116853
116856
|
if (!message_id || !chat_id || !senderOpenId) return null;
|
|
116854
116857
|
const thread_id = m?.["thread_id"] ?? msg.threadId ?? m?.["root_id"] ?? msg.rootId ?? message_id;
|
|
116855
116858
|
const root_id = m?.["root_id"] ?? msg.rootId ?? void 0;
|
|
116859
|
+
const parent_id = m?.["parent_id"] ?? msg.replyToMessageId ?? void 0;
|
|
116856
116860
|
const rawContent = typeof m?.["content"] === "string" ? m["content"] : void 0;
|
|
116857
116861
|
const content = rawContent ?? JSON.stringify({ text: stripAtMarkup(msg.content ?? "") });
|
|
116858
116862
|
return {
|
|
@@ -116861,6 +116865,7 @@ function channelMsgToLarkEvent(msg) {
|
|
|
116861
116865
|
chat_type: m?.["chat_type"] ?? msg.chatType ?? "group",
|
|
116862
116866
|
thread_id,
|
|
116863
116867
|
root_id,
|
|
116868
|
+
parent_id,
|
|
116864
116869
|
sender_id: senderOpenId,
|
|
116865
116870
|
mentions: m?.["mentions"] ?? void 0,
|
|
116866
116871
|
content,
|
|
@@ -122514,8 +122519,10 @@ var BridgeHandler = class {
|
|
|
122514
122519
|
for await (const event of this.deps.client.events()) {
|
|
122515
122520
|
if (this.closed) break;
|
|
122516
122521
|
if (signal?.aborted) break;
|
|
122517
|
-
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;
|
|
122518
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());
|
|
122519
122526
|
const prev = threadQueues.get(key) ?? Promise.resolve();
|
|
122520
122527
|
const next = prev.then(() => acquire()).then(() => this.handleOne(event)).catch((err) => {
|
|
122521
122528
|
console.error(`[bridge.handler] unhandled error on thread ${key}:`, err);
|
|
@@ -122553,10 +122560,39 @@ var BridgeHandler = class {
|
|
|
122553
122560
|
};
|
|
122554
122561
|
try {
|
|
122555
122562
|
const parsed = parseMessage(event);
|
|
122556
|
-
const {
|
|
122563
|
+
const { messageId, senderOpenId } = parsed;
|
|
122564
|
+
let threadId = parsed.threadId;
|
|
122557
122565
|
const botId = this.deps.botConfig?.id;
|
|
122558
122566
|
const eventLogId = messageId;
|
|
122559
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
|
+
}
|
|
122560
122596
|
const turnReceivedAt = this.threadReceivedAt.get(threadId);
|
|
122561
122597
|
const recordEvent = async (patch) => {
|
|
122562
122598
|
if (!this.deps.recordRuntimeEvent) return;
|
|
@@ -122604,31 +122640,9 @@ var BridgeHandler = class {
|
|
|
122604
122640
|
const isTopLevel = !(typeof parsed.raw.root_id === "string" && parsed.raw.root_id);
|
|
122605
122641
|
let replyInThread = isTopLevel;
|
|
122606
122642
|
let replyAnchorId = messageId;
|
|
122607
|
-
|
|
122608
|
-
|
|
122609
|
-
|
|
122610
|
-
const rootId = typeof parsed.raw.root_id === "string" && parsed.raw.root_id ? parsed.raw.root_id : void 0;
|
|
122611
|
-
const rawThreadId = typeof parsed.raw.thread_id === "string" && parsed.raw.thread_id ? parsed.raw.thread_id : void 0;
|
|
122612
|
-
if (rootId && this.deps.messageLookup) {
|
|
122613
|
-
const probe = this.deps.messageLookup.get(rootId).catch(() => void 0);
|
|
122614
|
-
if (rawThreadId) {
|
|
122615
|
-
deferredTaskRootProbe = probe;
|
|
122616
|
-
} else {
|
|
122617
|
-
const info = await probe;
|
|
122618
|
-
if (info?.msgType === "todo" && info.content) {
|
|
122619
|
-
const todo = parseTodoShareContent(info.content);
|
|
122620
|
-
if (todo) {
|
|
122621
|
-
taskRootInfo = {
|
|
122622
|
-
guid: todo.taskGuid,
|
|
122623
|
-
summary: todo.summaryText,
|
|
122624
|
-
topicLink: info.threadId ? buildTopicDeepLink(parsed.chatId, info.threadId) : void 0
|
|
122625
|
-
};
|
|
122626
|
-
replyInThread = true;
|
|
122627
|
-
replyAnchorId = rootId;
|
|
122628
|
-
}
|
|
122629
|
-
}
|
|
122630
|
-
}
|
|
122631
|
-
}
|
|
122643
|
+
if (taskCardAnchorId) {
|
|
122644
|
+
replyInThread = true;
|
|
122645
|
+
replyAnchorId = taskCardAnchorId;
|
|
122632
122646
|
}
|
|
122633
122647
|
const prototypeConfig = this.deps.botConfig?.response_surface_prototype;
|
|
122634
122648
|
const cardKitAvailable = isResponseSurfaceCardKitAvailable(
|
|
@@ -122716,7 +122730,10 @@ var BridgeHandler = class {
|
|
|
122716
122730
|
inputPreview: parsed.text,
|
|
122717
122731
|
target: {
|
|
122718
122732
|
chatId: parsed.chatId,
|
|
122719
|
-
|
|
122733
|
+
// omt_* only (see realTopicThreadId): passing a reply-chain om_*
|
|
122734
|
+
// id as receive_id_type=thread_id anchored the COT bubble onto a
|
|
122735
|
+
// stray thread on the TRIGGER message (2026-07-08 dogfood).
|
|
122736
|
+
threadId: realTopicThreadId(parsed.raw.thread_id),
|
|
122720
122737
|
originMessageId
|
|
122721
122738
|
}
|
|
122722
122739
|
});
|
|
@@ -123077,19 +123094,21 @@ var BridgeHandler = class {
|
|
|
123077
123094
|
if (info?.msgType === "todo" && info.content) {
|
|
123078
123095
|
const todo = parseTodoShareContent(info.content);
|
|
123079
123096
|
if (todo) {
|
|
123080
|
-
const rawThreadId =
|
|
123097
|
+
const rawThreadId = realTopicThreadId(parsed.raw.thread_id);
|
|
123098
|
+
const probeThreadId = realTopicThreadId(info.threadId);
|
|
123081
123099
|
taskRootInfo = {
|
|
123082
123100
|
guid: todo.taskGuid,
|
|
123083
123101
|
summary: todo.summaryText,
|
|
123084
|
-
topicLink: rawThreadId ? buildTopicDeepLink(parsed.chatId, rawThreadId) :
|
|
123102
|
+
topicLink: rawThreadId ? buildTopicDeepLink(parsed.chatId, rawThreadId) : probeThreadId ? buildTopicDeepLink(parsed.chatId, probeThreadId) : void 0
|
|
123085
123103
|
};
|
|
123086
123104
|
}
|
|
123087
123105
|
}
|
|
123088
123106
|
}
|
|
123089
123107
|
if (taskRootInfo && !taskRootInfo.topicLink && replyAnchorId !== messageId && this.deps.messageLookup) {
|
|
123090
123108
|
const refreshed = await this.deps.messageLookup.get(replyAnchorId, { refresh: true }).catch(() => void 0);
|
|
123091
|
-
|
|
123092
|
-
|
|
123109
|
+
const refreshedThreadId = realTopicThreadId(refreshed?.threadId);
|
|
123110
|
+
if (refreshedThreadId) {
|
|
123111
|
+
taskRootInfo.topicLink = buildTopicDeepLink(parsed.chatId, refreshedThreadId);
|
|
123093
123112
|
}
|
|
123094
123113
|
}
|
|
123095
123114
|
const prompt = await renderPrompt({
|