From 5d043efa525b1d4a16e51d503dc25e48a79ac916 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sun, 18 Oct 2026 12:37:26 +0800 Subject: [PATCH] fix(lark): surface uncaptured private message sources Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- apps/presentation/dashboard/src/data/chat.ts | 3 + .../private-conversation-panel.tsx | 11 + .../app-conversation-and-async-inbox-v0.md | 22 ++ ...p-conversation-and-async-inbox-v0.zh-CN.md | 16 + .../private-steward-scope.mjs | 16 + .../private-ingress/before-desktop.png | Bin 0 -> 108369 bytes .../private-ingress/gap-desktop.png | Bin 0 -> 110395 bytes .../private-ingress/gap-mobile.png | Bin 0 -> 62150 bytes .../private-ingress/unavailable-mobile.png | Bin 0 -> 61019 bytes .../private-ingress/verified-desktop.png | Bin 0 -> 105806 bytes .../lark/goal_topic_runtime_service.py | 27 +- .../lark/private_conversation_api.py | 6 + .../extensions/lark/private_conversations.py | 2 + loopx/extensions/lark/private_ingress.py | 215 +++++++++++ tests/test_lark_private_ingress.py | 334 ++++++++++++++++++ 15 files changed, 650 insertions(+), 2 deletions(-) create mode 100644 examples/personal-workspace-browser/screenshots/private-ingress/before-desktop.png create mode 100644 examples/personal-workspace-browser/screenshots/private-ingress/gap-desktop.png create mode 100644 examples/personal-workspace-browser/screenshots/private-ingress/gap-mobile.png create mode 100644 examples/personal-workspace-browser/screenshots/private-ingress/unavailable-mobile.png create mode 100644 examples/personal-workspace-browser/screenshots/private-ingress/verified-desktop.png create mode 100644 loopx/extensions/lark/private_ingress.py create mode 100644 tests/test_lark_private_ingress.py diff --git a/apps/presentation/dashboard/src/data/chat.ts b/apps/presentation/dashboard/src/data/chat.ts index 9e5717b8d8..e27fec38f3 100644 --- a/apps/presentation/dashboard/src/data/chat.ts +++ b/apps/presentation/dashboard/src/data/chat.ts @@ -2515,6 +2515,9 @@ const privateConversationSchema = z.object({ goal_scope: z.enum(["all_registered", "selected"]).nullable().optional(), audience: z.enum(["owner", "group"]).default("owner"), group_count: z.number().int().default(0), pending_count: z.number().int(), recovery_count: z.number().int(), + ingress: z.object({status: z.enum(["unobserved", "verified", "gap", "unavailable"]), + last_checked_at: z.number().nullable(), last_complete_at: z.number().nullable(), + source_gap_count: z.number().int().nonnegative(), without_reply_count: z.number().int().nonnegative()}).optional(), owner_attention: z.discriminatedUnion("available", [ z.object({available: z.literal(true), enabled: z.boolean(), revision: z.number().int(), last_checked_at: z.number().nullable(), error_code: z.string().nullable(), diff --git a/apps/presentation/dashboard/src/features/personal-workspace/private-conversation-panel.tsx b/apps/presentation/dashboard/src/features/personal-workspace/private-conversation-panel.tsx index 17cb5f20b9..b6e7f68000 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/private-conversation-panel.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/private-conversation-panel.tsx @@ -103,6 +103,17 @@ export function PrivateConversationPanel() { {row.audience === "group" ?

{zh ? `群话题助手 · 已授权 ${row.group_count} 个群 · 独立工作区隔离` : `Group topic assistant · ${row.group_count} authorized groups · Isolated workspace`}

: null}

{row.executor_endpoint_id} · {zh ? "监听状态" : "Listener"}: {listenerLabel(row.listener_status)}

{zh ? `待处理或回复:${row.pending_count}` : `Pending execution or reply: ${row.pending_count}`}

+ {row.ingress ?

+ {row.ingress.status === "gap" + ? (zh ? `${row.ingress.source_gap_count} 条原消息缺少收件记录,需核对;历史任务不会自动重放。` + : `${row.ingress.source_gap_count} source messages lack receipt records and need reconciliation. Historical tasks are not replayed.`) + : row.ingress.status === "unavailable" + ? (zh ? "原消息核对暂不可用;监听就绪不代表完整收件。" : "Source reconciliation is unavailable; a live connection does not prove complete receipt.") + : row.ingress.status === "verified" && row.ingress.last_complete_at !== null + ? (zh ? `原消息已核对 · ${new Date(row.ingress.last_complete_at * 1000).toLocaleTimeString(locale)}` + : `Sources reconciled · ${new Date(row.ingress.last_complete_at * 1000).toLocaleTimeString(locale)}`) + : (zh ? "原消息核对待运行。" : "Source reconciliation has not run yet.")} +

: null} {row.context_kind === "steward" && row.audience === "owner" ?
{row.owner_attention?.available ? <>