MCPcopy Create free account
hub / github.com/experdot/pointer / computeOutline

Function computeOutline

src/renderer/src/services/messagesService.ts:397–501  ·  view source on GitHub ↗
(
  topicGroups: TopicGroup[],
  currentPath: ChatMessage[]
)

Source from the content-addressed store, hash-verified

395 * @returns OutlineNode 结构
396 */
397export function computeOutline(
398 topicGroups: TopicGroup[],
399 currentPath: ChatMessage[]
400): OutlineNode[] {
401 const outline: OutlineNode[] = []
402 let currentTopicNode: OutlineNode | null = null
403
404 // 构建消息 ID 到消息的映射
405 const messageMap = new Map<string, ChatMessage>()
406 for (const msg of currentPath) {
407 messageMap.set(msg.id, msg)
408 }
409
410 // 构建 Topic startMessageId 到 TopicGroup 的映射
411 const topicGroupMap = new Map<string, TopicGroup>()
412 for (const group of topicGroups) {
413 topicGroupMap.set(group.startMessageId, group)
414 }
415
416 // 截取消息内容作为预览
417 const getContentPreview = (content: string, maxLen = 30): string => {
418 const text = content.replace(/\n/g, ' ').trim()
419 return text.length > maxLen ? text.slice(0, maxLen) + '...' : text
420 }
421
422 // 遍历当前路径
423 for (const msg of currentPath) {
424 const topicGroup = topicGroupMap.get(msg.id)
425
426 // 处理 Topic 节点
427 if (topicGroup) {
428 const topicNode: OutlineNode = {
429 id: `topic-${topicGroup.topicId}`,
430 title: topicGroup.name,
431 type: 'topic',
432 messageId: msg.id,
433 topicId: topicGroup.topicId,
434 role: msg.role,
435 children: [],
436 collapsed: topicGroup.collapsed
437 }
438
439 // 所有 Topic 都是顶级节点
440 outline.push(topicNode)
441 currentTopicNode = topicNode
442
443 // Topic 起始消息作为第一个子节点
444 if (msg.title) {
445 const titleNode: OutlineNode = {
446 id: `title-${msg.id}`,
447 title: msg.title,
448 type: 'title',
449 messageId: msg.id,
450 role: msg.role
451 }
452 topicNode.children!.push(titleNode)
453 } else {
454 // 无标题的 Topic 起始消息

Callers

nothing calls this directly

Calls 2

getContentPreviewFunction · 0.85
getMethod · 0.65

Tested by

no test coverage detected