Jaspers Hub

jaspers / agents

pluginOfficialReviewed★ 0↓ 1

Research Agents: Agents you define that answer research chats from SEC filings, your documents, and the web, citing every passage.

1.5 KB
1import type { Definition, Root, RootContent } from 'mdast'
2import { fromMarkdown } from 'mdast-util-from-markdown'
3import { gfmFromMarkdown } from 'mdast-util-gfm'
4import { gfm } from 'micromark-extension-gfm'
5
6// An answer's Markdown read into a tree, which the chat draws as React elements, never as HTML, the
7// way the markdown plugin draws a document: GitHub-flavored, links https only, HTML as its text
8// except <br>. Pure, so the reading can be checked in a test.
9
10/** A <br> models put in a table cell, or anywhere, for a line break. */
11const LINE_BREAK = /^<br\s*\/?>$/i
12
13export function parseMarkdown(source: string): Root {
14 return fromMarkdown(source, { extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()] })
15}
16
17/** The address a link opens, or null: main opens https links only, so nothing else is a link here. */
18export function linkHref(url: string): string | null {
19 try {
20 return new URL(url).protocol === 'https:' ? url : null
21 } catch {
22 return null
23 }
24}
25
26export function isLineBreak(html: string): boolean {
27 return LINE_BREAK.test(html)
28}
29
30/** The definitions reference links point at, by the label mdast gives both, wherever they sit. */
31export function definitionsOf(tree: Root): Map<string, Definition> {
32 const found = new Map<string, Definition>()
33 const visit = (nodes: RootContent[]): void => {
34 for (const node of nodes) {
35 if (node.type === 'definition') {
36 if (!found.has(node.identifier)) found.set(node.identifier, node)
37 } else if ('children' in node) visit(node.children)
38 }
39 }
40 visit(tree.children)
41 return found
42}