@ycodium-ai/plugin-im 0.2.2968 → 0.2.2974

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
@@ -35,8 +35,61 @@ they pick their own project:
35
35
  `/repo` switches the project: the old thread is kept (still under that
36
36
  project's `/sessions`), the chat forgets it, and a running turn blocks the
37
37
  switch. The panel has a Pick project button.
38
- - A chat only hears the project it picked: one conclusion per finished turn and
39
- thread failures go to the chats that picked that project; a chat with no
38
+ - On Telegram a forum topic is a chat of its own: its chat id is `chat:topic`
39
+ (`chatIdOf`, only when Telegram marks the message `is_topic_message`; a reply
40
+ chain in an ordinary supergroup also carries `message_thread_id` and stays the
41
+ group), so each topic picks its own project and keeps its own thread. Sends to a
42
+ topic carry `message_thread_id`; edits, reactions and the member count use the
43
+ group id. General is the group itself. An adapter reports the chat a chat hangs
44
+ under as `parentChatId` on the inbound message (a topic's group); a chat with no
45
+ project yet copies the parent's project, model and plan mode on its first message
46
+ (`inheritFromParent` in `inbound.ts`, one `chat-updated` fact) and is on its own
47
+ from then on.
48
+ - On Lark every answer is a reply to the message that caused it. An adapter opts in
49
+ with `quotesReplies`; only then does `inbound.ts` put a reply anchor
50
+ (`ImReplyAnchor`: message id, in a topic or not) on the binding it handles a message
51
+ with, so command replies and the panel card quote the command, and only threads that
52
+ have an anchor are looked up at all. `bindingOf` drops the anchor, since a binding
53
+ built for another chat (`/group`) must not reply into the old one. `turns.ts` records
54
+ the anchor against the user message it dispatches (`replyAnchors.ts`, in memory,
55
+ bounded), and the reply card, approval and question cards, the settled
56
+ attachments and `im_send_file` look it up through the host's own record of which
57
+ user message started the turn (`getThreadExecution`: the turn intent carrying that
58
+ turn id), not through the order of the message list, because a message queued
59
+ behind a running turn is already in that list. The queued-message card replies to
60
+ the queued message itself. A turn continued from the app, or one that outlives a
61
+ restart, has no anchor and is posted with the plain send. `larkApi.ts` calls the reply endpoint and falls back to the
62
+ plain send when Lark rejects the reply (the quoted message was withdrawn, the chat
63
+ does not take topic replies); a network error is not retried, since the message may
64
+ have gone out. `reply_in_thread` is set when the inbound message already sits in a
65
+ topic (`thread_id`) or mentions the bot while the per-bot **Open a topic when
66
+ mentioned** column (`larkTopicOnMention`, on unless set to `off`, read only by the
67
+ Lark adapter) is on.
68
+ - On Lark a topic in a group is a chat of its own, like a Telegram forum topic. Its
69
+ chat id is `chat:rootMessage` (`topicChatIdOf` in `larkAdapter.ts`): the root message
70
+ is known before the topic exists, the platform's own topic id only after the first
71
+ reply. Later messages in the topic carry the topic id, and usually the root; the
72
+ adapter reports the topic id as `chatAlias`, and the core keeps a persisted
73
+ alias-to-chat table (`chat-aliased` facts, first one wins, `chatAliasOf` in
74
+ `chatState.ts`) so a message that carries only the topic id still lands in the same
75
+ chat. The adapter also learns the topic id when a topic reply goes out (the reply
76
+ response, or a read-back of the root message when the response has none) and reports
77
+ it through `noteChatAlias`; every send takes its target from one helper
78
+ (`sendTarget`), so no send path can skip that. A send to a topic chat with nothing to
79
+ quote replies to the topic's root, since Lark cannot address a topic directly. A
80
+ card callback names only the group, so a panel click is matched to the chat that
81
+ opened the card when that chat sits under the clicked group (`handlePanelClick`
82
+ asks the adapter's `parentChatIdOf`; how a chat id is encoded stays in the adapter).
83
+ Private chats are never split by topic. A main-window message that mentions the
84
+ bot does not yet belong to a topic: the adapter reports it under the group with
85
+ `branchChatId`, and `inbound.ts` moves it to that chat only at the point where a
86
+ turn is about to start, after commands, the project picker, pending questions and
87
+ team routing were handled for the group, so `/repo` typed in the group still changes
88
+ the group.
89
+ - A finished turn or a failed thread is reported to the chat that is talking in that
90
+ thread and to nobody else (`notificationTargets.ts`). Only a thread no chat is
91
+ talking in (opened in the app) is reported by project: one conclusion per finished
92
+ turn and thread failures go to the chats that picked that project; a chat with no
40
93
  project hears nothing.
41
94
  - `/group <name>` (Lark only): the bot creates a group, adds the sender as owner
42
95
  and posts the project picker in it. Telegram and WeCom bots cannot create
@@ -88,7 +141,12 @@ An adapter opts in with the optional `turnCards` surface (`src/adapter.ts`).
88
141
  Approval messages are posted for every pending request on platforms with
89
142
  buttons and replaced with a settled notice when the request is answered, here or
90
143
  elsewhere (`thread.request-resolved`); WeCom, which answers by number, posts only
91
- the first and just stops accepting its number. Cards that were still open when the
144
+ the first and just stops accepting its number. On a platform whose `turnCards` set
145
+ `rotatesOnInteraction` (Lark: patching a card does not move it), an approval or
146
+ question that someone answered seals the open reply card as "continues below" and the
147
+ next tick opens a new one under the interaction card (`rotate` in `turnCards.ts`, on
148
+ the same per-thread queue as the ticks), so the settled reply is the last card in the
149
+ chat. Cards that were still open when the
92
150
  plugin restarted are marked interrupted. The pieces are pure and separate:
93
151
  `turnView.ts` (ticks to a view model), `larkCards.ts` (view model to card JSON),
94
152
  `larkMarkdown.ts`, `larkCardStream.ts` (throttle, one update in flight, newest