graphNeighborsText renders the local graph (backlinks + related notes) of the node best matching idOrQuery, for @memory neighbors. Free text resolves to the best-matching node, so the model can pass a subject rather than a node id.
(idOrQuery string)
| 228 | // node best matching idOrQuery, for @memory neighbors. Free text resolves to the |
| 229 | // best-matching node, so the model can pass a subject rather than a node id. |
| 230 | func (cli *ChatCLI) graphNeighborsText(idOrQuery string) (string, error) { |
| 231 | g := cli.buildKnowledgeGraph() |
| 232 | |
| 233 | seed, ok := g.Node(idOrQuery) |
| 234 | if !ok { |
| 235 | if hits := g.Search(strings.Fields(idOrQuery), 1); len(hits) > 0 { |
| 236 | seed = hits[0] |
| 237 | } |
| 238 | } |
| 239 | if seed == nil { |
| 240 | return i18n.T("graph.tool.no_node", idOrQuery), nil |
| 241 | } |
| 242 | |
| 243 | hood := g.Neighborhood(seed.ID, graphHoodHops, graphHoodLimit) |
| 244 | var b strings.Builder |
| 245 | fmt.Fprintf(&b, "Local graph of %q (%s):\n", strings.TrimSpace(seed.Title), seed.ID) |
| 246 | if seed.Summary != "" && seed.Summary != seed.Title { |
| 247 | fmt.Fprintf(&b, " · %s\n", truncateForLog(seed.Summary, 200)) |
| 248 | } |
| 249 | if len(hood) == 0 { |
| 250 | b.WriteString(" (no connected notes yet)") |
| 251 | return b.String(), nil |
| 252 | } |
| 253 | b.WriteString("Connected:\n") |
| 254 | for _, n := range hood { |
| 255 | writeGraphNode(&b, n) |
| 256 | } |
| 257 | return strings.TrimRight(b.String(), "\n"), nil |
| 258 | } |
| 259 | |
| 260 | func writeGraphNode(b *strings.Builder, n *knowledge.Node) { |
| 261 | title := strings.TrimSpace(n.Title) |