import type { Message } from "@langchain/langgraph-sdk"; import type { AgentThread, AgentThreadContext } from "./types"; export type ChannelThreadSource = { type: "im_channel"; provider: string; label: string; }; type ThreadRouteTarget = | string | { thread_id: string; context?: Pick | null; metadata?: Record | null; }; export function pathOfThread( thread: ThreadRouteTarget, context?: Pick | null, ) { const threadId = typeof thread === "string" ? thread : thread.thread_id; let agentName: string | undefined; if (typeof thread === "string") { agentName = context?.agent_name; } else { agentName = thread.context?.agent_name; if (!agentName) { const metaAgent = thread.metadata?.agent_name; if (typeof metaAgent === "string") { agentName = metaAgent; } } } return agentName ? `/workspace/agents/${encodeURIComponent(agentName)}/chats/${threadId}` : `/workspace/chats/${threadId}`; } export function textOfMessage(message: Message) { if (typeof message.content === "string") { return message.content; } else if (Array.isArray(message.content)) { for (const part of message.content) { if (part.type === "text") { return part.text; } } } return null; } export function titleOfThread(thread: AgentThread) { return thread.values?.title ?? "Untitled"; } const CHANNEL_PROVIDER_LABELS: Record = { dingtalk: "DingTalk", discord: "Discord", feishu: "Feishu", slack: "Slack", telegram: "Telegram", wechat: "WeChat", wecom: "WeCom", }; function labelOfChannelProvider(provider: string) { return CHANNEL_PROVIDER_LABELS[provider] ?? provider; } export function channelSourceOfThread( thread: Pick, ): ChannelThreadSource | null { const source = thread.metadata?.channel_source; if (!source || typeof source !== "object" || Array.isArray(source)) { return null; } if (Reflect.get(source, "type") !== "im_channel") { return null; } const provider = Reflect.get(source, "provider"); if (typeof provider !== "string" || provider.trim().length === 0) { return null; } const normalizedProvider = provider.trim().toLowerCase(); return { type: "im_channel", provider: normalizedProvider, label: labelOfChannelProvider(normalizedProvider), }; }