@sean.holung/minicode 0.2.4 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/src/indexer/code-map.js +2 -1
  2. package/dist/src/indexer/plugins/typescript.js +63 -34
  3. package/dist/src/serve/agent-bridge.js +127 -4
  4. package/dist/src/serve/server.js +101 -3
  5. package/dist/src/session/session-store.js +3 -1
  6. package/dist/src/ui/cli-ink.js +1 -0
  7. package/dist/src/web/app.js +2037 -117
  8. package/dist/src/web/index.html +28 -9
  9. package/dist/src/web/style.css +503 -3
  10. package/dist/tests/benchmark-index.test.js +152 -0
  11. package/dist/tests/indexer.test.js +62 -0
  12. package/dist/tests/serve.integration.test.js +225 -0
  13. package/node_modules/@minicode/agent-sdk/dist/src/agent/agent.d.ts +6 -1
  14. package/node_modules/@minicode/agent-sdk/dist/src/agent/agent.d.ts.map +1 -1
  15. package/node_modules/@minicode/agent-sdk/dist/src/agent/agent.js +35 -20
  16. package/node_modules/@minicode/agent-sdk/dist/src/agent/agent.js.map +1 -1
  17. package/node_modules/@minicode/agent-sdk/dist/src/index.d.ts +2 -1
  18. package/node_modules/@minicode/agent-sdk/dist/src/index.d.ts.map +1 -1
  19. package/node_modules/@minicode/agent-sdk/dist/src/index.js.map +1 -1
  20. package/node_modules/@minicode/agent-sdk/dist/src/indexer/types.d.ts +68 -0
  21. package/node_modules/@minicode/agent-sdk/dist/src/indexer/types.d.ts.map +1 -0
  22. package/node_modules/@minicode/agent-sdk/dist/src/indexer/types.js +2 -0
  23. package/node_modules/@minicode/agent-sdk/dist/src/indexer/types.js.map +1 -0
  24. package/node_modules/@minicode/agent-sdk/dist/src/prompt/system-prompt.d.ts +1 -5
  25. package/node_modules/@minicode/agent-sdk/dist/src/prompt/system-prompt.d.ts.map +1 -1
  26. package/node_modules/@minicode/agent-sdk/dist/src/prompt/system-prompt.js.map +1 -1
  27. package/node_modules/@minicode/agent-sdk/dist/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +7 -4
@@ -1,48 +1,1978 @@
1
- const messagesEl = document.getElementById("messages");
2
- const chatForm = document.getElementById("chat-form");
3
- const chatInput = document.getElementById("chat-input");
4
- const sendBtn = document.getElementById("send-btn");
5
- const cancelBtn = document.getElementById("cancel-btn");
6
- const statusBadge = document.getElementById("status-badge");
7
- const modelInfo = document.getElementById("model-info");
8
- const sessionBtn = document.getElementById("session-btn");
9
- const sessionDropdown = document.getElementById("session-dropdown");
10
- const sessionList = document.getElementById("session-list");
11
- const saveBtn = document.getElementById("save-btn");
12
- const saveLabelInput = document.getElementById("save-label");
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
4
 
14
- let ws;
15
- let currentAssistantEl = null;
16
- let assistantText = "";
5
+ // node_modules/marked/lib/marked.esm.js
6
+ function M() {
7
+ return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
8
+ }
9
+ var T = M();
10
+ function G(u3) {
11
+ T = u3;
12
+ }
13
+ var _ = { exec: () => null };
14
+ function k(u3, e = "") {
15
+ let t = typeof u3 == "string" ? u3 : u3.source, n = { replace: (r, i) => {
16
+ let s = typeof i == "string" ? i : i.source;
17
+ return s = s.replace(m.caret, "$1"), t = t.replace(r, s), n;
18
+ }, getRegex: () => new RegExp(t, e) };
19
+ return n;
20
+ }
21
+ var be = (() => {
22
+ try {
23
+ return !!new RegExp("(?<=1)(?<!1)");
24
+ } catch {
25
+ return false;
26
+ }
27
+ })();
28
+ var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] +\S/, listReplaceTask: /^\[[ xX]\] +/, listTaskCheckbox: /\[[ xX]\]/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (u3) => new RegExp(`^( {0,3}${u3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`), hrRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), fencesBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}(?:\`\`\`|~~~)`), headingBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}#`), htmlBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}<(?:[a-z].*>|!--)`, "i"), blockquoteBeginRegex: (u3) => new RegExp(`^ {0,${Math.min(3, u3 - 1)}}>`) };
29
+ var Re = /^(?:[ \t]*(?:\n|$))+/;
30
+ var Te = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
31
+ var Oe = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
32
+ var C = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
33
+ var we = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
34
+ var Q = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
35
+ var se = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
36
+ var ie = k(se).replace(/bull/g, Q).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
37
+ var ye = k(se).replace(/bull/g, Q).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
38
+ var j = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
39
+ var Pe = /^[^\n]+/;
40
+ var F = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
41
+ var Se = k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", F).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
42
+ var $e = k(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, Q).getRegex();
43
+ var v = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
44
+ var U = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
45
+ var _e = k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", U).replace("tag", v).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
46
+ var oe = k(j).replace("hr", C).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
47
+ var Le = k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", oe).getRegex();
48
+ var K = { blockquote: Le, code: Te, def: Se, fences: Oe, heading: we, hr: C, html: _e, lheading: ie, list: $e, newline: Re, paragraph: oe, table: _, text: Pe };
49
+ var ne = k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", C).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex();
50
+ var Me = { ...K, lheading: ye, table: ne, paragraph: k(j).replace("hr", C).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", ne).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v).getRegex() };
51
+ var ze = { ...K, html: k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", U).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: _, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: k(j).replace("hr", C).replace("heading", ` *#{1,6} *[^
52
+ ]`).replace("lheading", ie).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
53
+ var Ee = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
54
+ var Ie = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
55
+ var ae = /^( {2,}|\\)\n(?!\s*$)/;
56
+ var Ae = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
57
+ var z = /[\p{P}\p{S}]/u;
58
+ var H = /[\s\p{P}\p{S}]/u;
59
+ var W = /[^\s\p{P}\p{S}]/u;
60
+ var Ce = k(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, H).getRegex();
61
+ var le = /(?!~)[\p{P}\p{S}]/u;
62
+ var Be = /(?!~)[\s\p{P}\p{S}]/u;
63
+ var De = /(?:[^\s\p{P}\p{S}]|~)/u;
64
+ var qe = k(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", be ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
65
+ var ue = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
66
+ var ve = k(ue, "u").replace(/punct/g, z).getRegex();
67
+ var He = k(ue, "u").replace(/punct/g, le).getRegex();
68
+ var pe = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
69
+ var Ze = k(pe, "gu").replace(/notPunctSpace/g, W).replace(/punctSpace/g, H).replace(/punct/g, z).getRegex();
70
+ var Ge = k(pe, "gu").replace(/notPunctSpace/g, De).replace(/punctSpace/g, Be).replace(/punct/g, le).getRegex();
71
+ var Ne = k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, W).replace(/punctSpace/g, H).replace(/punct/g, z).getRegex();
72
+ var Qe = k(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, z).getRegex();
73
+ var je = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
74
+ var Fe = k(je, "gu").replace(/notPunctSpace/g, W).replace(/punctSpace/g, H).replace(/punct/g, z).getRegex();
75
+ var Ue = k(/\\(punct)/, "gu").replace(/punct/g, z).getRegex();
76
+ var Ke = k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
77
+ var We = k(U).replace("(?:-->|$)", "-->").getRegex();
78
+ var Xe = k("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", We).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
79
+ var q = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/;
80
+ var Je = k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", q).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
81
+ var ce = k(/^!?\[(label)\]\[(ref)\]/).replace("label", q).replace("ref", F).getRegex();
82
+ var he = k(/^!?\[(ref)\](?:\[\])?/).replace("ref", F).getRegex();
83
+ var Ve = k("reflink|nolink(?!\\()", "g").replace("reflink", ce).replace("nolink", he).getRegex();
84
+ var re = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
85
+ var X = { _backpedal: _, anyPunctuation: Ue, autolink: Ke, blockSkip: qe, br: ae, code: Ie, del: _, delLDelim: _, delRDelim: _, emStrongLDelim: ve, emStrongRDelimAst: Ze, emStrongRDelimUnd: Ne, escape: Ee, link: Je, nolink: he, punctuation: Ce, reflink: ce, reflinkSearch: Ve, tag: Xe, text: Ae, url: _ };
86
+ var Ye = { ...X, link: k(/^!?\[(label)\]\((.*?)\)/).replace("label", q).getRegex(), reflink: k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", q).getRegex() };
87
+ var N = { ...X, emStrongRDelimAst: Ge, emStrongLDelim: He, delLDelim: Qe, delRDelim: Fe, url: k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", re).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: k(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", re).getRegex() };
88
+ var et = { ...N, br: k(ae).replace("{2,}", "*").getRegex(), text: k(N.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
89
+ var B = { normal: K, gfm: Me, pedantic: ze };
90
+ var E = { normal: X, gfm: N, breaks: et, pedantic: Ye };
91
+ var tt = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
92
+ var ke = (u3) => tt[u3];
93
+ function O(u3, e) {
94
+ if (e) {
95
+ if (m.escapeTest.test(u3)) return u3.replace(m.escapeReplace, ke);
96
+ } else if (m.escapeTestNoEncode.test(u3)) return u3.replace(m.escapeReplaceNoEncode, ke);
97
+ return u3;
98
+ }
99
+ function J(u3) {
100
+ try {
101
+ u3 = encodeURI(u3).replace(m.percentDecode, "%");
102
+ } catch {
103
+ return null;
104
+ }
105
+ return u3;
106
+ }
107
+ function V(u3, e) {
108
+ let t = u3.replace(m.findPipe, (i, s, a) => {
109
+ let o = false, l = s;
110
+ for (; --l >= 0 && a[l] === "\\"; ) o = !o;
111
+ return o ? "|" : " |";
112
+ }), n = t.split(m.splitPipe), r = 0;
113
+ if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
114
+ else for (; n.length < e; ) n.push("");
115
+ for (; r < n.length; r++) n[r] = n[r].trim().replace(m.slashPipe, "|");
116
+ return n;
117
+ }
118
+ function I(u3, e, t) {
119
+ let n = u3.length;
120
+ if (n === 0) return "";
121
+ let r = 0;
122
+ for (; r < n; ) {
123
+ let i = u3.charAt(n - r - 1);
124
+ if (i === e && !t) r++;
125
+ else if (i !== e && t) r++;
126
+ else break;
127
+ }
128
+ return u3.slice(0, n - r);
129
+ }
130
+ function de(u3, e) {
131
+ if (u3.indexOf(e[1]) === -1) return -1;
132
+ let t = 0;
133
+ for (let n = 0; n < u3.length; n++) if (u3[n] === "\\") n++;
134
+ else if (u3[n] === e[0]) t++;
135
+ else if (u3[n] === e[1] && (t--, t < 0)) return n;
136
+ return t > 0 ? -2 : -1;
137
+ }
138
+ function ge(u3, e = 0) {
139
+ let t = e, n = "";
140
+ for (let r of u3) if (r === " ") {
141
+ let i = 4 - t % 4;
142
+ n += " ".repeat(i), t += i;
143
+ } else n += r, t++;
144
+ return n;
145
+ }
146
+ function fe(u3, e, t, n, r) {
147
+ let i = e.href, s = e.title || null, a = u3[1].replace(r.other.outputLinkReplace, "$1");
148
+ n.state.inLink = true;
149
+ let o = { type: u3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: i, title: s, text: a, tokens: n.inlineTokens(a) };
150
+ return n.state.inLink = false, o;
151
+ }
152
+ function nt(u3, e, t) {
153
+ let n = u3.match(t.other.indentCodeCompensation);
154
+ if (n === null) return e;
155
+ let r = n[1];
156
+ return e.split(`
157
+ `).map((i) => {
158
+ let s = i.match(t.other.beginningSpace);
159
+ if (s === null) return i;
160
+ let [a] = s;
161
+ return a.length >= r.length ? i.slice(r.length) : i;
162
+ }).join(`
163
+ `);
164
+ }
165
+ var w = class {
166
+ constructor(e) {
167
+ __publicField(this, "options");
168
+ __publicField(this, "rules");
169
+ __publicField(this, "lexer");
170
+ this.options = e || T;
171
+ }
172
+ space(e) {
173
+ let t = this.rules.block.newline.exec(e);
174
+ if (t && t[0].length > 0) return { type: "space", raw: t[0] };
175
+ }
176
+ code(e) {
177
+ let t = this.rules.block.code.exec(e);
178
+ if (t) {
179
+ let n = t[0].replace(this.rules.other.codeRemoveIndent, "");
180
+ return { type: "code", raw: t[0], codeBlockStyle: "indented", text: this.options.pedantic ? n : I(n, `
181
+ `) };
182
+ }
183
+ }
184
+ fences(e) {
185
+ let t = this.rules.block.fences.exec(e);
186
+ if (t) {
187
+ let n = t[0], r = nt(n, t[3] || "", this.rules);
188
+ return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: r };
189
+ }
190
+ }
191
+ heading(e) {
192
+ let t = this.rules.block.heading.exec(e);
193
+ if (t) {
194
+ let n = t[2].trim();
195
+ if (this.rules.other.endingHash.test(n)) {
196
+ let r = I(n, "#");
197
+ (this.options.pedantic || !r || this.rules.other.endingSpaceChar.test(r)) && (n = r.trim());
198
+ }
199
+ return { type: "heading", raw: t[0], depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
200
+ }
201
+ }
202
+ hr(e) {
203
+ let t = this.rules.block.hr.exec(e);
204
+ if (t) return { type: "hr", raw: I(t[0], `
205
+ `) };
206
+ }
207
+ blockquote(e) {
208
+ let t = this.rules.block.blockquote.exec(e);
209
+ if (t) {
210
+ let n = I(t[0], `
211
+ `).split(`
212
+ `), r = "", i = "", s = [];
213
+ for (; n.length > 0; ) {
214
+ let a = false, o = [], l;
215
+ for (l = 0; l < n.length; l++) if (this.rules.other.blockquoteStart.test(n[l])) o.push(n[l]), a = true;
216
+ else if (!a) o.push(n[l]);
217
+ else break;
218
+ n = n.slice(l);
219
+ let p = o.join(`
220
+ `), c = p.replace(this.rules.other.blockquoteSetextReplace, `
221
+ $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
222
+ r = r ? `${r}
223
+ ${p}` : p, i = i ? `${i}
224
+ ${c}` : c;
225
+ let d = this.lexer.state.top;
226
+ if (this.lexer.state.top = true, this.lexer.blockTokens(c, s, true), this.lexer.state.top = d, n.length === 0) break;
227
+ let h = s.at(-1);
228
+ if (h?.type === "code") break;
229
+ if (h?.type === "blockquote") {
230
+ let R = h, f = R.raw + `
231
+ ` + n.join(`
232
+ `), S = this.blockquote(f);
233
+ s[s.length - 1] = S, r = r.substring(0, r.length - R.raw.length) + S.raw, i = i.substring(0, i.length - R.text.length) + S.text;
234
+ break;
235
+ } else if (h?.type === "list") {
236
+ let R = h, f = R.raw + `
237
+ ` + n.join(`
238
+ `), S = this.list(f);
239
+ s[s.length - 1] = S, r = r.substring(0, r.length - h.raw.length) + S.raw, i = i.substring(0, i.length - R.raw.length) + S.raw, n = f.substring(s.at(-1).raw.length).split(`
240
+ `);
241
+ continue;
242
+ }
243
+ }
244
+ return { type: "blockquote", raw: r, tokens: s, text: i };
245
+ }
246
+ }
247
+ list(e) {
248
+ let t = this.rules.block.list.exec(e);
249
+ if (t) {
250
+ let n = t[1].trim(), r = n.length > 1, i = { type: "list", raw: "", ordered: r, start: r ? +n.slice(0, -1) : "", loose: false, items: [] };
251
+ n = r ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = r ? n : "[*+-]");
252
+ let s = this.rules.other.listItemRegex(n), a = false;
253
+ for (; e; ) {
254
+ let l = false, p = "", c = "";
255
+ if (!(t = s.exec(e)) || this.rules.block.hr.test(e)) break;
256
+ p = t[0], e = e.substring(p.length);
257
+ let d = ge(t[2].split(`
258
+ `, 1)[0], t[1].length), h = e.split(`
259
+ `, 1)[0], R = !d.trim(), f = 0;
260
+ if (this.options.pedantic ? (f = 2, c = d.trimStart()) : R ? f = t[1].length + 1 : (f = d.search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, c = d.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (p += h + `
261
+ `, e = e.substring(h.length + 1), l = true), !l) {
262
+ let S = this.rules.other.nextBulletRegex(f), Y = this.rules.other.hrRegex(f), ee = this.rules.other.fencesBeginRegex(f), te = this.rules.other.headingBeginRegex(f), me = this.rules.other.htmlBeginRegex(f), xe = this.rules.other.blockquoteBeginRegex(f);
263
+ for (; e; ) {
264
+ let Z = e.split(`
265
+ `, 1)[0], A;
266
+ if (h = Z, this.options.pedantic ? (h = h.replace(this.rules.other.listReplaceNesting, " "), A = h) : A = h.replace(this.rules.other.tabCharGlobal, " "), ee.test(h) || te.test(h) || me.test(h) || xe.test(h) || S.test(h) || Y.test(h)) break;
267
+ if (A.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) c += `
268
+ ` + A.slice(f);
269
+ else {
270
+ if (R || d.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ee.test(d) || te.test(d) || Y.test(d)) break;
271
+ c += `
272
+ ` + h;
273
+ }
274
+ R = !h.trim(), p += Z + `
275
+ `, e = e.substring(Z.length + 1), d = A.slice(f);
276
+ }
277
+ }
278
+ i.loose || (a ? i.loose = true : this.rules.other.doubleBlankLine.test(p) && (a = true)), i.items.push({ type: "list_item", raw: p, task: !!this.options.gfm && this.rules.other.listIsTask.test(c), loose: false, text: c, tokens: [] }), i.raw += p;
279
+ }
280
+ let o = i.items.at(-1);
281
+ if (o) o.raw = o.raw.trimEnd(), o.text = o.text.trimEnd();
282
+ else return;
283
+ i.raw = i.raw.trimEnd();
284
+ for (let l of i.items) {
285
+ if (this.lexer.state.top = false, l.tokens = this.lexer.blockTokens(l.text, []), l.task) {
286
+ if (l.text = l.text.replace(this.rules.other.listReplaceTask, ""), l.tokens[0]?.type === "text" || l.tokens[0]?.type === "paragraph") {
287
+ l.tokens[0].raw = l.tokens[0].raw.replace(this.rules.other.listReplaceTask, ""), l.tokens[0].text = l.tokens[0].text.replace(this.rules.other.listReplaceTask, "");
288
+ for (let c = this.lexer.inlineQueue.length - 1; c >= 0; c--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[c].src)) {
289
+ this.lexer.inlineQueue[c].src = this.lexer.inlineQueue[c].src.replace(this.rules.other.listReplaceTask, "");
290
+ break;
291
+ }
292
+ }
293
+ let p = this.rules.other.listTaskCheckbox.exec(l.raw);
294
+ if (p) {
295
+ let c = { type: "checkbox", raw: p[0] + " ", checked: p[0] !== "[ ]" };
296
+ l.checked = c.checked, i.loose ? l.tokens[0] && ["paragraph", "text"].includes(l.tokens[0].type) && "tokens" in l.tokens[0] && l.tokens[0].tokens ? (l.tokens[0].raw = c.raw + l.tokens[0].raw, l.tokens[0].text = c.raw + l.tokens[0].text, l.tokens[0].tokens.unshift(c)) : l.tokens.unshift({ type: "paragraph", raw: c.raw, text: c.raw, tokens: [c] }) : l.tokens.unshift(c);
297
+ }
298
+ }
299
+ if (!i.loose) {
300
+ let p = l.tokens.filter((d) => d.type === "space"), c = p.length > 0 && p.some((d) => this.rules.other.anyLine.test(d.raw));
301
+ i.loose = c;
302
+ }
303
+ }
304
+ if (i.loose) for (let l of i.items) {
305
+ l.loose = true;
306
+ for (let p of l.tokens) p.type === "text" && (p.type = "paragraph");
307
+ }
308
+ return i;
309
+ }
310
+ }
311
+ html(e) {
312
+ let t = this.rules.block.html.exec(e);
313
+ if (t) return { type: "html", block: true, raw: t[0], pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: t[0] };
314
+ }
315
+ def(e) {
316
+ let t = this.rules.block.def.exec(e);
317
+ if (t) {
318
+ let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), r = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", i = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
319
+ return { type: "def", tag: n, raw: t[0], href: r, title: i };
320
+ }
321
+ }
322
+ table(e) {
323
+ let t = this.rules.block.table.exec(e);
324
+ if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
325
+ let n = V(t[1]), r = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), i = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
326
+ `) : [], s = { type: "table", raw: t[0], header: [], align: [], rows: [] };
327
+ if (n.length === r.length) {
328
+ for (let a of r) this.rules.other.tableAlignRight.test(a) ? s.align.push("right") : this.rules.other.tableAlignCenter.test(a) ? s.align.push("center") : this.rules.other.tableAlignLeft.test(a) ? s.align.push("left") : s.align.push(null);
329
+ for (let a = 0; a < n.length; a++) s.header.push({ text: n[a], tokens: this.lexer.inline(n[a]), header: true, align: s.align[a] });
330
+ for (let a of i) s.rows.push(V(a, s.header.length).map((o, l) => ({ text: o, tokens: this.lexer.inline(o), header: false, align: s.align[l] })));
331
+ return s;
332
+ }
333
+ }
334
+ lheading(e) {
335
+ let t = this.rules.block.lheading.exec(e);
336
+ if (t) {
337
+ let n = t[1].trim();
338
+ return { type: "heading", raw: t[0], depth: t[2].charAt(0) === "=" ? 1 : 2, text: n, tokens: this.lexer.inline(n) };
339
+ }
340
+ }
341
+ paragraph(e) {
342
+ let t = this.rules.block.paragraph.exec(e);
343
+ if (t) {
344
+ let n = t[1].charAt(t[1].length - 1) === `
345
+ ` ? t[1].slice(0, -1) : t[1];
346
+ return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
347
+ }
348
+ }
349
+ text(e) {
350
+ let t = this.rules.block.text.exec(e);
351
+ if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
352
+ }
353
+ escape(e) {
354
+ let t = this.rules.inline.escape.exec(e);
355
+ if (t) return { type: "escape", raw: t[0], text: t[1] };
356
+ }
357
+ tag(e) {
358
+ let t = this.rules.inline.tag.exec(e);
359
+ if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
360
+ }
361
+ link(e) {
362
+ let t = this.rules.inline.link.exec(e);
363
+ if (t) {
364
+ let n = t[2].trim();
365
+ if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
366
+ if (!this.rules.other.endAngleBracket.test(n)) return;
367
+ let s = I(n.slice(0, -1), "\\");
368
+ if ((n.length - s.length) % 2 === 0) return;
369
+ } else {
370
+ let s = de(t[2], "()");
371
+ if (s === -2) return;
372
+ if (s > -1) {
373
+ let o = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + s;
374
+ t[2] = t[2].substring(0, s), t[0] = t[0].substring(0, o).trim(), t[3] = "";
375
+ }
376
+ }
377
+ let r = t[2], i = "";
378
+ if (this.options.pedantic) {
379
+ let s = this.rules.other.pedanticHrefTitle.exec(r);
380
+ s && (r = s[1], i = s[3]);
381
+ } else i = t[3] ? t[3].slice(1, -1) : "";
382
+ return r = r.trim(), this.rules.other.startAngleBracket.test(r) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? r = r.slice(1) : r = r.slice(1, -1)), fe(t, { href: r && r.replace(this.rules.inline.anyPunctuation, "$1"), title: i && i.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules);
383
+ }
384
+ }
385
+ reflink(e, t) {
386
+ let n;
387
+ if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
388
+ let r = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), i = t[r.toLowerCase()];
389
+ if (!i) {
390
+ let s = n[0].charAt(0);
391
+ return { type: "text", raw: s, text: s };
392
+ }
393
+ return fe(n, i, n[0], this.lexer, this.rules);
394
+ }
395
+ }
396
+ emStrong(e, t, n = "") {
397
+ let r = this.rules.inline.emStrongLDelim.exec(e);
398
+ if (!r || !r[1] && !r[2] && !r[3] && !r[4] || r[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
399
+ if (!(r[1] || r[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
400
+ let s = [...r[0]].length - 1, a, o, l = s, p = 0, c = r[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
401
+ for (c.lastIndex = 0, t = t.slice(-1 * e.length + s); (r = c.exec(t)) != null; ) {
402
+ if (a = r[1] || r[2] || r[3] || r[4] || r[5] || r[6], !a) continue;
403
+ if (o = [...a].length, r[3] || r[4]) {
404
+ l += o;
405
+ continue;
406
+ } else if ((r[5] || r[6]) && s % 3 && !((s + o) % 3)) {
407
+ p += o;
408
+ continue;
409
+ }
410
+ if (l -= o, l > 0) continue;
411
+ o = Math.min(o, o + l + p);
412
+ let d = [...r[0]][0].length, h = e.slice(0, s + r.index + d + o);
413
+ if (Math.min(s, o) % 2) {
414
+ let f = h.slice(1, -1);
415
+ return { type: "em", raw: h, text: f, tokens: this.lexer.inlineTokens(f) };
416
+ }
417
+ let R = h.slice(2, -2);
418
+ return { type: "strong", raw: h, text: R, tokens: this.lexer.inlineTokens(R) };
419
+ }
420
+ }
421
+ }
422
+ codespan(e) {
423
+ let t = this.rules.inline.code.exec(e);
424
+ if (t) {
425
+ let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), r = this.rules.other.nonSpaceChar.test(n), i = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n);
426
+ return r && i && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
427
+ }
428
+ }
429
+ br(e) {
430
+ let t = this.rules.inline.br.exec(e);
431
+ if (t) return { type: "br", raw: t[0] };
432
+ }
433
+ del(e, t, n = "") {
434
+ let r = this.rules.inline.delLDelim.exec(e);
435
+ if (!r) return;
436
+ if (!(r[1] || "") || !n || this.rules.inline.punctuation.exec(n)) {
437
+ let s = [...r[0]].length - 1, a, o, l = s, p = this.rules.inline.delRDelim;
438
+ for (p.lastIndex = 0, t = t.slice(-1 * e.length + s); (r = p.exec(t)) != null; ) {
439
+ if (a = r[1] || r[2] || r[3] || r[4] || r[5] || r[6], !a || (o = [...a].length, o !== s)) continue;
440
+ if (r[3] || r[4]) {
441
+ l += o;
442
+ continue;
443
+ }
444
+ if (l -= o, l > 0) continue;
445
+ o = Math.min(o, o + l);
446
+ let c = [...r[0]][0].length, d = e.slice(0, s + r.index + c + o), h = d.slice(s, -s);
447
+ return { type: "del", raw: d, text: h, tokens: this.lexer.inlineTokens(h) };
448
+ }
449
+ }
450
+ }
451
+ autolink(e) {
452
+ let t = this.rules.inline.autolink.exec(e);
453
+ if (t) {
454
+ let n, r;
455
+ return t[2] === "@" ? (n = t[1], r = "mailto:" + n) : (n = t[1], r = n), { type: "link", raw: t[0], text: n, href: r, tokens: [{ type: "text", raw: n, text: n }] };
456
+ }
457
+ }
458
+ url(e) {
459
+ let t;
460
+ if (t = this.rules.inline.url.exec(e)) {
461
+ let n, r;
462
+ if (t[2] === "@") n = t[0], r = "mailto:" + n;
463
+ else {
464
+ let i;
465
+ do
466
+ i = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
467
+ while (i !== t[0]);
468
+ n = t[0], t[1] === "www." ? r = "http://" + t[0] : r = t[0];
469
+ }
470
+ return { type: "link", raw: t[0], text: n, href: r, tokens: [{ type: "text", raw: n, text: n }] };
471
+ }
472
+ }
473
+ inlineText(e) {
474
+ let t = this.rules.inline.text.exec(e);
475
+ if (t) {
476
+ let n = this.lexer.state.inRawBlock;
477
+ return { type: "text", raw: t[0], text: t[0], escaped: n };
478
+ }
479
+ }
480
+ };
481
+ var x = class u {
482
+ constructor(e) {
483
+ __publicField(this, "tokens");
484
+ __publicField(this, "options");
485
+ __publicField(this, "state");
486
+ __publicField(this, "inlineQueue");
487
+ __publicField(this, "tokenizer");
488
+ this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || T, this.options.tokenizer = this.options.tokenizer || new w(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true };
489
+ let t = { other: m, block: B.normal, inline: E.normal };
490
+ this.options.pedantic ? (t.block = B.pedantic, t.inline = E.pedantic) : this.options.gfm && (t.block = B.gfm, this.options.breaks ? t.inline = E.breaks : t.inline = E.gfm), this.tokenizer.rules = t;
491
+ }
492
+ static get rules() {
493
+ return { block: B, inline: E };
494
+ }
495
+ static lex(e, t) {
496
+ return new u(t).lex(e);
497
+ }
498
+ static lexInline(e, t) {
499
+ return new u(t).inlineTokens(e);
500
+ }
501
+ lex(e) {
502
+ e = e.replace(m.carriageReturn, `
503
+ `), this.blockTokens(e, this.tokens);
504
+ for (let t = 0; t < this.inlineQueue.length; t++) {
505
+ let n = this.inlineQueue[t];
506
+ this.inlineTokens(n.src, n.tokens);
507
+ }
508
+ return this.inlineQueue = [], this.tokens;
509
+ }
510
+ blockTokens(e, t = [], n = false) {
511
+ for (this.tokenizer.lexer = this, this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, "")); e; ) {
512
+ let r;
513
+ if (this.options.extensions?.block?.some((s) => (r = s.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue;
514
+ if (r = this.tokenizer.space(e)) {
515
+ e = e.substring(r.raw.length);
516
+ let s = t.at(-1);
517
+ r.raw.length === 1 && s !== void 0 ? s.raw += `
518
+ ` : t.push(r);
519
+ continue;
520
+ }
521
+ if (r = this.tokenizer.code(e)) {
522
+ e = e.substring(r.raw.length);
523
+ let s = t.at(-1);
524
+ s?.type === "paragraph" || s?.type === "text" ? (s.raw += (s.raw.endsWith(`
525
+ `) ? "" : `
526
+ `) + r.raw, s.text += `
527
+ ` + r.text, this.inlineQueue.at(-1).src = s.text) : t.push(r);
528
+ continue;
529
+ }
530
+ if (r = this.tokenizer.fences(e)) {
531
+ e = e.substring(r.raw.length), t.push(r);
532
+ continue;
533
+ }
534
+ if (r = this.tokenizer.heading(e)) {
535
+ e = e.substring(r.raw.length), t.push(r);
536
+ continue;
537
+ }
538
+ if (r = this.tokenizer.hr(e)) {
539
+ e = e.substring(r.raw.length), t.push(r);
540
+ continue;
541
+ }
542
+ if (r = this.tokenizer.blockquote(e)) {
543
+ e = e.substring(r.raw.length), t.push(r);
544
+ continue;
545
+ }
546
+ if (r = this.tokenizer.list(e)) {
547
+ e = e.substring(r.raw.length), t.push(r);
548
+ continue;
549
+ }
550
+ if (r = this.tokenizer.html(e)) {
551
+ e = e.substring(r.raw.length), t.push(r);
552
+ continue;
553
+ }
554
+ if (r = this.tokenizer.def(e)) {
555
+ e = e.substring(r.raw.length);
556
+ let s = t.at(-1);
557
+ s?.type === "paragraph" || s?.type === "text" ? (s.raw += (s.raw.endsWith(`
558
+ `) ? "" : `
559
+ `) + r.raw, s.text += `
560
+ ` + r.raw, this.inlineQueue.at(-1).src = s.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r));
561
+ continue;
562
+ }
563
+ if (r = this.tokenizer.table(e)) {
564
+ e = e.substring(r.raw.length), t.push(r);
565
+ continue;
566
+ }
567
+ if (r = this.tokenizer.lheading(e)) {
568
+ e = e.substring(r.raw.length), t.push(r);
569
+ continue;
570
+ }
571
+ let i = e;
572
+ if (this.options.extensions?.startBlock) {
573
+ let s = 1 / 0, a = e.slice(1), o;
574
+ this.options.extensions.startBlock.forEach((l) => {
575
+ o = l.call({ lexer: this }, a), typeof o == "number" && o >= 0 && (s = Math.min(s, o));
576
+ }), s < 1 / 0 && s >= 0 && (i = e.substring(0, s + 1));
577
+ }
578
+ if (this.state.top && (r = this.tokenizer.paragraph(i))) {
579
+ let s = t.at(-1);
580
+ n && s?.type === "paragraph" ? (s.raw += (s.raw.endsWith(`
581
+ `) ? "" : `
582
+ `) + r.raw, s.text += `
583
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = s.text) : t.push(r), n = i.length !== e.length, e = e.substring(r.raw.length);
584
+ continue;
585
+ }
586
+ if (r = this.tokenizer.text(e)) {
587
+ e = e.substring(r.raw.length);
588
+ let s = t.at(-1);
589
+ s?.type === "text" ? (s.raw += (s.raw.endsWith(`
590
+ `) ? "" : `
591
+ `) + r.raw, s.text += `
592
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = s.text) : t.push(r);
593
+ continue;
594
+ }
595
+ if (e) {
596
+ let s = "Infinite loop on byte: " + e.charCodeAt(0);
597
+ if (this.options.silent) {
598
+ console.error(s);
599
+ break;
600
+ } else throw new Error(s);
601
+ }
602
+ }
603
+ return this.state.top = true, t;
604
+ }
605
+ inline(e, t = []) {
606
+ return this.inlineQueue.push({ src: e, tokens: t }), t;
607
+ }
608
+ inlineTokens(e, t = []) {
609
+ this.tokenizer.lexer = this;
610
+ let n = e, r = null;
611
+ if (this.tokens.links) {
612
+ let o = Object.keys(this.tokens.links);
613
+ if (o.length > 0) for (; (r = this.tokenizer.rules.inline.reflinkSearch.exec(n)) != null; ) o.includes(r[0].slice(r[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, r.index) + "[" + "a".repeat(r[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
614
+ }
615
+ for (; (r = this.tokenizer.rules.inline.anyPunctuation.exec(n)) != null; ) n = n.slice(0, r.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
616
+ let i;
617
+ for (; (r = this.tokenizer.rules.inline.blockSkip.exec(n)) != null; ) i = r[2] ? r[2].length : 0, n = n.slice(0, r.index + i) + "[" + "a".repeat(r[0].length - i - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
618
+ n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
619
+ let s = false, a = "";
620
+ for (; e; ) {
621
+ s || (a = ""), s = false;
622
+ let o;
623
+ if (this.options.extensions?.inline?.some((p) => (o = p.call({ lexer: this }, e, t)) ? (e = e.substring(o.raw.length), t.push(o), true) : false)) continue;
624
+ if (o = this.tokenizer.escape(e)) {
625
+ e = e.substring(o.raw.length), t.push(o);
626
+ continue;
627
+ }
628
+ if (o = this.tokenizer.tag(e)) {
629
+ e = e.substring(o.raw.length), t.push(o);
630
+ continue;
631
+ }
632
+ if (o = this.tokenizer.link(e)) {
633
+ e = e.substring(o.raw.length), t.push(o);
634
+ continue;
635
+ }
636
+ if (o = this.tokenizer.reflink(e, this.tokens.links)) {
637
+ e = e.substring(o.raw.length);
638
+ let p = t.at(-1);
639
+ o.type === "text" && p?.type === "text" ? (p.raw += o.raw, p.text += o.text) : t.push(o);
640
+ continue;
641
+ }
642
+ if (o = this.tokenizer.emStrong(e, n, a)) {
643
+ e = e.substring(o.raw.length), t.push(o);
644
+ continue;
645
+ }
646
+ if (o = this.tokenizer.codespan(e)) {
647
+ e = e.substring(o.raw.length), t.push(o);
648
+ continue;
649
+ }
650
+ if (o = this.tokenizer.br(e)) {
651
+ e = e.substring(o.raw.length), t.push(o);
652
+ continue;
653
+ }
654
+ if (o = this.tokenizer.del(e, n, a)) {
655
+ e = e.substring(o.raw.length), t.push(o);
656
+ continue;
657
+ }
658
+ if (o = this.tokenizer.autolink(e)) {
659
+ e = e.substring(o.raw.length), t.push(o);
660
+ continue;
661
+ }
662
+ if (!this.state.inLink && (o = this.tokenizer.url(e))) {
663
+ e = e.substring(o.raw.length), t.push(o);
664
+ continue;
665
+ }
666
+ let l = e;
667
+ if (this.options.extensions?.startInline) {
668
+ let p = 1 / 0, c = e.slice(1), d;
669
+ this.options.extensions.startInline.forEach((h) => {
670
+ d = h.call({ lexer: this }, c), typeof d == "number" && d >= 0 && (p = Math.min(p, d));
671
+ }), p < 1 / 0 && p >= 0 && (l = e.substring(0, p + 1));
672
+ }
673
+ if (o = this.tokenizer.inlineText(l)) {
674
+ e = e.substring(o.raw.length), o.raw.slice(-1) !== "_" && (a = o.raw.slice(-1)), s = true;
675
+ let p = t.at(-1);
676
+ p?.type === "text" ? (p.raw += o.raw, p.text += o.text) : t.push(o);
677
+ continue;
678
+ }
679
+ if (e) {
680
+ let p = "Infinite loop on byte: " + e.charCodeAt(0);
681
+ if (this.options.silent) {
682
+ console.error(p);
683
+ break;
684
+ } else throw new Error(p);
685
+ }
686
+ }
687
+ return t;
688
+ }
689
+ };
690
+ var y = class {
691
+ constructor(e) {
692
+ __publicField(this, "options");
693
+ __publicField(this, "parser");
694
+ this.options = e || T;
695
+ }
696
+ space(e) {
697
+ return "";
698
+ }
699
+ code({ text: e, lang: t, escaped: n }) {
700
+ let r = (t || "").match(m.notSpaceStart)?.[0], i = e.replace(m.endingNewline, "") + `
701
+ `;
702
+ return r ? '<pre><code class="language-' + O(r) + '">' + (n ? i : O(i, true)) + `</code></pre>
703
+ ` : "<pre><code>" + (n ? i : O(i, true)) + `</code></pre>
704
+ `;
705
+ }
706
+ blockquote({ tokens: e }) {
707
+ return `<blockquote>
708
+ ${this.parser.parse(e)}</blockquote>
709
+ `;
710
+ }
711
+ html({ text: e }) {
712
+ return e;
713
+ }
714
+ def(e) {
715
+ return "";
716
+ }
717
+ heading({ tokens: e, depth: t }) {
718
+ return `<h${t}>${this.parser.parseInline(e)}</h${t}>
719
+ `;
720
+ }
721
+ hr(e) {
722
+ return `<hr>
723
+ `;
724
+ }
725
+ list(e) {
726
+ let t = e.ordered, n = e.start, r = "";
727
+ for (let a = 0; a < e.items.length; a++) {
728
+ let o = e.items[a];
729
+ r += this.listitem(o);
730
+ }
731
+ let i = t ? "ol" : "ul", s = t && n !== 1 ? ' start="' + n + '"' : "";
732
+ return "<" + i + s + `>
733
+ ` + r + "</" + i + `>
734
+ `;
735
+ }
736
+ listitem(e) {
737
+ return `<li>${this.parser.parse(e.tokens)}</li>
738
+ `;
739
+ }
740
+ checkbox({ checked: e }) {
741
+ return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox"> ';
742
+ }
743
+ paragraph({ tokens: e }) {
744
+ return `<p>${this.parser.parseInline(e)}</p>
745
+ `;
746
+ }
747
+ table(e) {
748
+ let t = "", n = "";
749
+ for (let i = 0; i < e.header.length; i++) n += this.tablecell(e.header[i]);
750
+ t += this.tablerow({ text: n });
751
+ let r = "";
752
+ for (let i = 0; i < e.rows.length; i++) {
753
+ let s = e.rows[i];
754
+ n = "";
755
+ for (let a = 0; a < s.length; a++) n += this.tablecell(s[a]);
756
+ r += this.tablerow({ text: n });
757
+ }
758
+ return r && (r = `<tbody>${r}</tbody>`), `<table>
759
+ <thead>
760
+ ` + t + `</thead>
761
+ ` + r + `</table>
762
+ `;
763
+ }
764
+ tablerow({ text: e }) {
765
+ return `<tr>
766
+ ${e}</tr>
767
+ `;
768
+ }
769
+ tablecell(e) {
770
+ let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
771
+ return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
772
+ `;
773
+ }
774
+ strong({ tokens: e }) {
775
+ return `<strong>${this.parser.parseInline(e)}</strong>`;
776
+ }
777
+ em({ tokens: e }) {
778
+ return `<em>${this.parser.parseInline(e)}</em>`;
779
+ }
780
+ codespan({ text: e }) {
781
+ return `<code>${O(e, true)}</code>`;
782
+ }
783
+ br(e) {
784
+ return "<br>";
785
+ }
786
+ del({ tokens: e }) {
787
+ return `<del>${this.parser.parseInline(e)}</del>`;
788
+ }
789
+ link({ href: e, title: t, tokens: n }) {
790
+ let r = this.parser.parseInline(n), i = J(e);
791
+ if (i === null) return r;
792
+ e = i;
793
+ let s = '<a href="' + e + '"';
794
+ return t && (s += ' title="' + O(t) + '"'), s += ">" + r + "</a>", s;
795
+ }
796
+ image({ href: e, title: t, text: n, tokens: r }) {
797
+ r && (n = this.parser.parseInline(r, this.parser.textRenderer));
798
+ let i = J(e);
799
+ if (i === null) return O(n);
800
+ e = i;
801
+ let s = `<img src="${e}" alt="${O(n)}"`;
802
+ return t && (s += ` title="${O(t)}"`), s += ">", s;
803
+ }
804
+ text(e) {
805
+ return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : O(e.text);
806
+ }
807
+ };
808
+ var $ = class {
809
+ strong({ text: e }) {
810
+ return e;
811
+ }
812
+ em({ text: e }) {
813
+ return e;
814
+ }
815
+ codespan({ text: e }) {
816
+ return e;
817
+ }
818
+ del({ text: e }) {
819
+ return e;
820
+ }
821
+ html({ text: e }) {
822
+ return e;
823
+ }
824
+ text({ text: e }) {
825
+ return e;
826
+ }
827
+ link({ text: e }) {
828
+ return "" + e;
829
+ }
830
+ image({ text: e }) {
831
+ return "" + e;
832
+ }
833
+ br() {
834
+ return "";
835
+ }
836
+ checkbox({ raw: e }) {
837
+ return e;
838
+ }
839
+ };
840
+ var b = class u2 {
841
+ constructor(e) {
842
+ __publicField(this, "options");
843
+ __publicField(this, "renderer");
844
+ __publicField(this, "textRenderer");
845
+ this.options = e || T, this.options.renderer = this.options.renderer || new y(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new $();
846
+ }
847
+ static parse(e, t) {
848
+ return new u2(t).parse(e);
849
+ }
850
+ static parseInline(e, t) {
851
+ return new u2(t).parseInline(e);
852
+ }
853
+ parse(e) {
854
+ this.renderer.parser = this;
855
+ let t = "";
856
+ for (let n = 0; n < e.length; n++) {
857
+ let r = e[n];
858
+ if (this.options.extensions?.renderers?.[r.type]) {
859
+ let s = r, a = this.options.extensions.renderers[s.type].call({ parser: this }, s);
860
+ if (a !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(s.type)) {
861
+ t += a || "";
862
+ continue;
863
+ }
864
+ }
865
+ let i = r;
866
+ switch (i.type) {
867
+ case "space": {
868
+ t += this.renderer.space(i);
869
+ break;
870
+ }
871
+ case "hr": {
872
+ t += this.renderer.hr(i);
873
+ break;
874
+ }
875
+ case "heading": {
876
+ t += this.renderer.heading(i);
877
+ break;
878
+ }
879
+ case "code": {
880
+ t += this.renderer.code(i);
881
+ break;
882
+ }
883
+ case "table": {
884
+ t += this.renderer.table(i);
885
+ break;
886
+ }
887
+ case "blockquote": {
888
+ t += this.renderer.blockquote(i);
889
+ break;
890
+ }
891
+ case "list": {
892
+ t += this.renderer.list(i);
893
+ break;
894
+ }
895
+ case "checkbox": {
896
+ t += this.renderer.checkbox(i);
897
+ break;
898
+ }
899
+ case "html": {
900
+ t += this.renderer.html(i);
901
+ break;
902
+ }
903
+ case "def": {
904
+ t += this.renderer.def(i);
905
+ break;
906
+ }
907
+ case "paragraph": {
908
+ t += this.renderer.paragraph(i);
909
+ break;
910
+ }
911
+ case "text": {
912
+ t += this.renderer.text(i);
913
+ break;
914
+ }
915
+ default: {
916
+ let s = 'Token with "' + i.type + '" type was not found.';
917
+ if (this.options.silent) return console.error(s), "";
918
+ throw new Error(s);
919
+ }
920
+ }
921
+ }
922
+ return t;
923
+ }
924
+ parseInline(e, t = this.renderer) {
925
+ this.renderer.parser = this;
926
+ let n = "";
927
+ for (let r = 0; r < e.length; r++) {
928
+ let i = e[r];
929
+ if (this.options.extensions?.renderers?.[i.type]) {
930
+ let a = this.options.extensions.renderers[i.type].call({ parser: this }, i);
931
+ if (a !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(i.type)) {
932
+ n += a || "";
933
+ continue;
934
+ }
935
+ }
936
+ let s = i;
937
+ switch (s.type) {
938
+ case "escape": {
939
+ n += t.text(s);
940
+ break;
941
+ }
942
+ case "html": {
943
+ n += t.html(s);
944
+ break;
945
+ }
946
+ case "link": {
947
+ n += t.link(s);
948
+ break;
949
+ }
950
+ case "image": {
951
+ n += t.image(s);
952
+ break;
953
+ }
954
+ case "checkbox": {
955
+ n += t.checkbox(s);
956
+ break;
957
+ }
958
+ case "strong": {
959
+ n += t.strong(s);
960
+ break;
961
+ }
962
+ case "em": {
963
+ n += t.em(s);
964
+ break;
965
+ }
966
+ case "codespan": {
967
+ n += t.codespan(s);
968
+ break;
969
+ }
970
+ case "br": {
971
+ n += t.br(s);
972
+ break;
973
+ }
974
+ case "del": {
975
+ n += t.del(s);
976
+ break;
977
+ }
978
+ case "text": {
979
+ n += t.text(s);
980
+ break;
981
+ }
982
+ default: {
983
+ let a = 'Token with "' + s.type + '" type was not found.';
984
+ if (this.options.silent) return console.error(a), "";
985
+ throw new Error(a);
986
+ }
987
+ }
988
+ }
989
+ return n;
990
+ }
991
+ };
992
+ var _a;
993
+ var P = (_a = class {
994
+ constructor(e) {
995
+ __publicField(this, "options");
996
+ __publicField(this, "block");
997
+ this.options = e || T;
998
+ }
999
+ preprocess(e) {
1000
+ return e;
1001
+ }
1002
+ postprocess(e) {
1003
+ return e;
1004
+ }
1005
+ processAllTokens(e) {
1006
+ return e;
1007
+ }
1008
+ emStrongMask(e) {
1009
+ return e;
1010
+ }
1011
+ provideLexer() {
1012
+ return this.block ? x.lex : x.lexInline;
1013
+ }
1014
+ provideParser() {
1015
+ return this.block ? b.parse : b.parseInline;
1016
+ }
1017
+ }, __publicField(_a, "passThroughHooks", /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"])), __publicField(_a, "passThroughHooksRespectAsync", /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"])), _a);
1018
+ var D = class {
1019
+ constructor(...e) {
1020
+ __publicField(this, "defaults", M());
1021
+ __publicField(this, "options", this.setOptions);
1022
+ __publicField(this, "parse", this.parseMarkdown(true));
1023
+ __publicField(this, "parseInline", this.parseMarkdown(false));
1024
+ __publicField(this, "Parser", b);
1025
+ __publicField(this, "Renderer", y);
1026
+ __publicField(this, "TextRenderer", $);
1027
+ __publicField(this, "Lexer", x);
1028
+ __publicField(this, "Tokenizer", w);
1029
+ __publicField(this, "Hooks", P);
1030
+ this.use(...e);
1031
+ }
1032
+ walkTokens(e, t) {
1033
+ let n = [];
1034
+ for (let r of e) switch (n = n.concat(t.call(this, r)), r.type) {
1035
+ case "table": {
1036
+ let i = r;
1037
+ for (let s of i.header) n = n.concat(this.walkTokens(s.tokens, t));
1038
+ for (let s of i.rows) for (let a of s) n = n.concat(this.walkTokens(a.tokens, t));
1039
+ break;
1040
+ }
1041
+ case "list": {
1042
+ let i = r;
1043
+ n = n.concat(this.walkTokens(i.items, t));
1044
+ break;
1045
+ }
1046
+ default: {
1047
+ let i = r;
1048
+ this.defaults.extensions?.childTokens?.[i.type] ? this.defaults.extensions.childTokens[i.type].forEach((s) => {
1049
+ let a = i[s].flat(1 / 0);
1050
+ n = n.concat(this.walkTokens(a, t));
1051
+ }) : i.tokens && (n = n.concat(this.walkTokens(i.tokens, t)));
1052
+ }
1053
+ }
1054
+ return n;
1055
+ }
1056
+ use(...e) {
1057
+ let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
1058
+ return e.forEach((n) => {
1059
+ let r = { ...n };
1060
+ if (r.async = this.defaults.async || r.async || false, n.extensions && (n.extensions.forEach((i) => {
1061
+ if (!i.name) throw new Error("extension name required");
1062
+ if ("renderer" in i) {
1063
+ let s = t.renderers[i.name];
1064
+ s ? t.renderers[i.name] = function(...a) {
1065
+ let o = i.renderer.apply(this, a);
1066
+ return o === false && (o = s.apply(this, a)), o;
1067
+ } : t.renderers[i.name] = i.renderer;
1068
+ }
1069
+ if ("tokenizer" in i) {
1070
+ if (!i.level || i.level !== "block" && i.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
1071
+ let s = t[i.level];
1072
+ s ? s.unshift(i.tokenizer) : t[i.level] = [i.tokenizer], i.start && (i.level === "block" ? t.startBlock ? t.startBlock.push(i.start) : t.startBlock = [i.start] : i.level === "inline" && (t.startInline ? t.startInline.push(i.start) : t.startInline = [i.start]));
1073
+ }
1074
+ "childTokens" in i && i.childTokens && (t.childTokens[i.name] = i.childTokens);
1075
+ }), r.extensions = t), n.renderer) {
1076
+ let i = this.defaults.renderer || new y(this.defaults);
1077
+ for (let s in n.renderer) {
1078
+ if (!(s in i)) throw new Error(`renderer '${s}' does not exist`);
1079
+ if (["options", "parser"].includes(s)) continue;
1080
+ let a = s, o = n.renderer[a], l = i[a];
1081
+ i[a] = (...p) => {
1082
+ let c = o.apply(i, p);
1083
+ return c === false && (c = l.apply(i, p)), c || "";
1084
+ };
1085
+ }
1086
+ r.renderer = i;
1087
+ }
1088
+ if (n.tokenizer) {
1089
+ let i = this.defaults.tokenizer || new w(this.defaults);
1090
+ for (let s in n.tokenizer) {
1091
+ if (!(s in i)) throw new Error(`tokenizer '${s}' does not exist`);
1092
+ if (["options", "rules", "lexer"].includes(s)) continue;
1093
+ let a = s, o = n.tokenizer[a], l = i[a];
1094
+ i[a] = (...p) => {
1095
+ let c = o.apply(i, p);
1096
+ return c === false && (c = l.apply(i, p)), c;
1097
+ };
1098
+ }
1099
+ r.tokenizer = i;
1100
+ }
1101
+ if (n.hooks) {
1102
+ let i = this.defaults.hooks || new P();
1103
+ for (let s in n.hooks) {
1104
+ if (!(s in i)) throw new Error(`hook '${s}' does not exist`);
1105
+ if (["options", "block"].includes(s)) continue;
1106
+ let a = s, o = n.hooks[a], l = i[a];
1107
+ P.passThroughHooks.has(s) ? i[a] = (p) => {
1108
+ if (this.defaults.async && P.passThroughHooksRespectAsync.has(s)) return (async () => {
1109
+ let d = await o.call(i, p);
1110
+ return l.call(i, d);
1111
+ })();
1112
+ let c = o.call(i, p);
1113
+ return l.call(i, c);
1114
+ } : i[a] = (...p) => {
1115
+ if (this.defaults.async) return (async () => {
1116
+ let d = await o.apply(i, p);
1117
+ return d === false && (d = await l.apply(i, p)), d;
1118
+ })();
1119
+ let c = o.apply(i, p);
1120
+ return c === false && (c = l.apply(i, p)), c;
1121
+ };
1122
+ }
1123
+ r.hooks = i;
1124
+ }
1125
+ if (n.walkTokens) {
1126
+ let i = this.defaults.walkTokens, s = n.walkTokens;
1127
+ r.walkTokens = function(a) {
1128
+ let o = [];
1129
+ return o.push(s.call(this, a)), i && (o = o.concat(i.call(this, a))), o;
1130
+ };
1131
+ }
1132
+ this.defaults = { ...this.defaults, ...r };
1133
+ }), this;
1134
+ }
1135
+ setOptions(e) {
1136
+ return this.defaults = { ...this.defaults, ...e }, this;
1137
+ }
1138
+ lexer(e, t) {
1139
+ return x.lex(e, t ?? this.defaults);
1140
+ }
1141
+ parser(e, t) {
1142
+ return b.parse(e, t ?? this.defaults);
1143
+ }
1144
+ parseMarkdown(e) {
1145
+ return (n, r) => {
1146
+ let i = { ...r }, s = { ...this.defaults, ...i }, a = this.onError(!!s.silent, !!s.async);
1147
+ if (this.defaults.async === true && i.async === false) return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
1148
+ if (typeof n > "u" || n === null) return a(new Error("marked(): input parameter is undefined or null"));
1149
+ if (typeof n != "string") return a(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
1150
+ if (s.hooks && (s.hooks.options = s, s.hooks.block = e), s.async) return (async () => {
1151
+ let o = s.hooks ? await s.hooks.preprocess(n) : n, p = await (s.hooks ? await s.hooks.provideLexer() : e ? x.lex : x.lexInline)(o, s), c = s.hooks ? await s.hooks.processAllTokens(p) : p;
1152
+ s.walkTokens && await Promise.all(this.walkTokens(c, s.walkTokens));
1153
+ let h = await (s.hooks ? await s.hooks.provideParser() : e ? b.parse : b.parseInline)(c, s);
1154
+ return s.hooks ? await s.hooks.postprocess(h) : h;
1155
+ })().catch(a);
1156
+ try {
1157
+ s.hooks && (n = s.hooks.preprocess(n));
1158
+ let l = (s.hooks ? s.hooks.provideLexer() : e ? x.lex : x.lexInline)(n, s);
1159
+ s.hooks && (l = s.hooks.processAllTokens(l)), s.walkTokens && this.walkTokens(l, s.walkTokens);
1160
+ let c = (s.hooks ? s.hooks.provideParser() : e ? b.parse : b.parseInline)(l, s);
1161
+ return s.hooks && (c = s.hooks.postprocess(c)), c;
1162
+ } catch (o) {
1163
+ return a(o);
1164
+ }
1165
+ };
1166
+ }
1167
+ onError(e, t) {
1168
+ return (n) => {
1169
+ if (n.message += `
1170
+ Please report this to https://github.com/markedjs/marked.`, e) {
1171
+ let r = "<p>An error occurred:</p><pre>" + O(n.message + "", true) + "</pre>";
1172
+ return t ? Promise.resolve(r) : r;
1173
+ }
1174
+ if (t) return Promise.reject(n);
1175
+ throw n;
1176
+ };
1177
+ }
1178
+ };
1179
+ var L = new D();
1180
+ function g(u3, e) {
1181
+ return L.parse(u3, e);
1182
+ }
1183
+ g.options = g.setOptions = function(u3) {
1184
+ return L.setOptions(u3), g.defaults = L.defaults, G(g.defaults), g;
1185
+ };
1186
+ g.getDefaults = M;
1187
+ g.defaults = T;
1188
+ g.use = function(...u3) {
1189
+ return L.use(...u3), g.defaults = L.defaults, G(g.defaults), g;
1190
+ };
1191
+ g.walkTokens = function(u3, e) {
1192
+ return L.walkTokens(u3, e);
1193
+ };
1194
+ g.parseInline = L.parseInline;
1195
+ g.Parser = b;
1196
+ g.parser = b.parse;
1197
+ g.Renderer = y;
1198
+ g.TextRenderer = $;
1199
+ g.Lexer = x;
1200
+ g.lexer = x.lex;
1201
+ g.Tokenizer = w;
1202
+ g.Hooks = P;
1203
+ g.parse = g;
1204
+ var Qt = g.options;
1205
+ var jt = g.setOptions;
1206
+ var Ft = g.use;
1207
+ var Ut = g.walkTokens;
1208
+ var Kt = g.parseInline;
1209
+ var Xt = b.parse;
1210
+ var Jt = x.lex;
17
1211
 
18
- // Max chars to show in expanded tool result
19
- const TOOL_RESULT_MAX = 500;
1212
+ // src/web/utils.ts
1213
+ g.setOptions({
1214
+ breaks: true,
1215
+ gfm: true
1216
+ });
1217
+ function escapeHtml(str) {
1218
+ const div = document.createElement("div");
1219
+ div.textContent = str || "";
1220
+ return div.innerHTML;
1221
+ }
1222
+ function renderMarkdown(text) {
1223
+ return g.parse(text, { async: false });
1224
+ }
1225
+ function renderMarkdownInto(el, text) {
1226
+ el.innerHTML = renderMarkdown(text);
1227
+ if (typeof hljs !== "undefined") {
1228
+ el.querySelectorAll("pre code").forEach((block) => {
1229
+ hljs.highlightElement(block);
1230
+ });
1231
+ }
1232
+ }
1233
+
1234
+ // src/web/graph.ts
1235
+ var cy = null;
1236
+ var graphNodes = /* @__PURE__ */ new Map();
1237
+ var graphEdges = [];
1238
+ var edgeIndex = /* @__PURE__ */ new Map();
1239
+ var pinnedNames = /* @__PURE__ */ new Set();
1240
+ var allSymbolNames = [];
1241
+ var initialized = false;
1242
+ var KIND_COLORS = {
1243
+ function: { border: "#7aa2f7", bg: "rgba(122,162,247,0.15)" },
1244
+ class: { border: "#bb9af7", bg: "rgba(187,154,247,0.15)" },
1245
+ interface: { border: "#2ac3de", bg: "rgba(42,195,222,0.15)" },
1246
+ type: { border: "#e0af68", bg: "rgba(224,175,104,0.15)" },
1247
+ variable: { border: "#9ece6a", bg: "rgba(158,206,106,0.15)" },
1248
+ method: { border: "#7dcfff", bg: "rgba(125,207,255,0.15)" }
1249
+ };
1250
+ var EDGE_STYLES = {
1251
+ calls: { lineStyle: "solid", opacity: 0.5, color: "#565f89", width: 1 },
1252
+ imports: { lineStyle: "dashed", opacity: 0.4, color: "#565f89", width: 1 },
1253
+ extends: { lineStyle: "solid", opacity: 0.7, color: "#bb9af7", width: 2 },
1254
+ implements: { lineStyle: "dashed", opacity: 0.6, color: "#2ac3de", width: 1.5 },
1255
+ references: { lineStyle: "dotted", opacity: 0.3, color: "#565f89", width: 1 }
1256
+ };
1257
+ var LAYOUT_OPTIONS = {
1258
+ name: "cose",
1259
+ nodeRepulsion: function() {
1260
+ return 4e3;
1261
+ },
1262
+ idealEdgeLength: function() {
1263
+ return 80;
1264
+ },
1265
+ edgeElasticity: function() {
1266
+ return 100;
1267
+ },
1268
+ animate: true,
1269
+ animationDuration: 300,
1270
+ randomize: false,
1271
+ nodeDimensionsIncludeLabels: true,
1272
+ gravity: 0.5,
1273
+ numIter: 300,
1274
+ fit: true,
1275
+ padding: 50
1276
+ };
1277
+ async function initGraph() {
1278
+ if (initialized) return;
1279
+ initialized = true;
1280
+ const cyEl = document.getElementById("cy");
1281
+ const detailEl = document.getElementById("symbol-detail");
1282
+ try {
1283
+ const [graphRes, symbolsRes, focusRes] = await Promise.all([
1284
+ fetch("/api/graph"),
1285
+ fetch("/api/symbols"),
1286
+ fetch("/api/focus")
1287
+ ]);
1288
+ if (!graphRes.ok || !symbolsRes.ok) {
1289
+ cyEl.innerHTML = '<div class="graph-empty">No index available. Run minicode with a project to generate the code graph.</div>';
1290
+ return;
1291
+ }
1292
+ const graphData = await graphRes.json();
1293
+ const focusData = focusRes.ok ? await focusRes.json() : { pinned: [] };
1294
+ if (!graphData.nodes || graphData.nodes.length === 0) {
1295
+ cyEl.innerHTML = '<div class="graph-empty">No index available. Run minicode with a project to generate the code graph.</div>';
1296
+ return;
1297
+ }
1298
+ for (const node of graphData.nodes) {
1299
+ const id = node.qualifiedName || node.id || node.name || "";
1300
+ graphNodes.set(id, node);
1301
+ }
1302
+ graphEdges = (graphData.edges || []).map((e) => ({
1303
+ source: e.source || e.from || "",
1304
+ target: e.target || e.to || "",
1305
+ kind: (e.kind || e.type || "references").toLowerCase()
1306
+ }));
1307
+ buildEdgeIndex();
1308
+ allSymbolNames = Array.from(graphNodes.keys()).sort();
1309
+ const pinned = focusData.pinned || [];
1310
+ for (const f of pinned) {
1311
+ const name = typeof f === "string" ? f : f.name || f.qualifiedName;
1312
+ if (name) pinnedNames.add(name);
1313
+ }
1314
+ cy = cytoscape({
1315
+ container: cyEl,
1316
+ elements: [],
1317
+ style: buildStylesheet(),
1318
+ minZoom: 0.2,
1319
+ maxZoom: 3
1320
+ });
1321
+ setupInteractions(cy, detailEl);
1322
+ setupToolbar();
1323
+ if (pinnedNames.size > 0) {
1324
+ for (const name of pinnedNames) {
1325
+ addNodeAndNeighbors(name);
1326
+ }
1327
+ runLayout();
1328
+ }
1329
+ } catch (err) {
1330
+ console.error("Graph init failed:", err);
1331
+ const msg = err instanceof Error ? err.message : String(err);
1332
+ cyEl.innerHTML = `<div class="graph-empty">Failed to load graph: ${msg}</div>`;
1333
+ }
1334
+ }
1335
+ function highlightAgentActivity(symbolName) {
1336
+ if (!cy) return;
1337
+ const node = findNode(symbolName);
1338
+ if (node) {
1339
+ node.addClass("agent-pulse");
1340
+ setTimeout(() => node.removeClass("agent-pulse"), 2e3);
1341
+ return;
1342
+ }
1343
+ expandNodeAndLayout(symbolName);
1344
+ const added = findNode(symbolName);
1345
+ if (added) {
1346
+ added.addClass("agent-pulse");
1347
+ setTimeout(() => added.removeClass("agent-pulse"), 2e3);
1348
+ }
1349
+ }
1350
+ function resizeGraph() {
1351
+ if (cy) cy.resize();
1352
+ }
1353
+ function buildEdgeIndex() {
1354
+ edgeIndex.clear();
1355
+ for (const edge of graphEdges) {
1356
+ let srcList = edgeIndex.get(edge.source);
1357
+ if (!srcList) {
1358
+ srcList = [];
1359
+ edgeIndex.set(edge.source, srcList);
1360
+ }
1361
+ srcList.push(edge);
1362
+ let tgtList = edgeIndex.get(edge.target);
1363
+ if (!tgtList) {
1364
+ tgtList = [];
1365
+ edgeIndex.set(edge.target, tgtList);
1366
+ }
1367
+ tgtList.push(edge);
1368
+ }
1369
+ }
1370
+ function addNodeAndNeighbors(symbolId) {
1371
+ addNodeToGraph(symbolId);
1372
+ const edges = edgeIndex.get(symbolId) || [];
1373
+ for (const edge of edges) {
1374
+ const neighbor = edge.source === symbolId ? edge.target : edge.source;
1375
+ addNodeToGraph(neighbor);
1376
+ addEdgeToGraph(edge);
1377
+ }
1378
+ }
1379
+ function expandNodeAndLayout(symbolId) {
1380
+ addNodeAndNeighbors(symbolId);
1381
+ connectExistingNodes();
1382
+ runLayout();
1383
+ }
1384
+ function addNodeToGraph(id) {
1385
+ if (!cy) return;
1386
+ if (cy.getElementById(id).length > 0) return;
1387
+ const nodeData = graphNodes.get(id);
1388
+ if (!nodeData) return;
1389
+ const kind = (nodeData.kind || "function").toLowerCase();
1390
+ const name = nodeData.name || id.split(".").pop() || id;
1391
+ const file = nodeData.filePath || nodeData.file || "";
1392
+ cy.add({
1393
+ data: {
1394
+ id,
1395
+ label: name,
1396
+ name,
1397
+ qualifiedName: id,
1398
+ kind,
1399
+ file,
1400
+ exported: !!nodeData.exported,
1401
+ startLine: nodeData.startLine,
1402
+ endLine: nodeData.endLine
1403
+ },
1404
+ classes: [kind, pinnedNames.has(id) ? "pinned" : ""].filter(Boolean).join(" ")
1405
+ });
1406
+ }
1407
+ function addEdgeToGraph(edge) {
1408
+ if (!cy) return;
1409
+ const edgeId = `${edge.source}->${edge.target}:${edge.kind}`;
1410
+ if (cy.getElementById(edgeId).length > 0) return;
1411
+ if (cy.getElementById(edge.source).length === 0) return;
1412
+ if (cy.getElementById(edge.target).length === 0) return;
1413
+ cy.add({
1414
+ data: {
1415
+ id: edgeId,
1416
+ source: edge.source,
1417
+ target: edge.target,
1418
+ kind: edge.kind
1419
+ },
1420
+ classes: edge.kind
1421
+ });
1422
+ }
1423
+ function runLayout() {
1424
+ if (!cy || cy.nodes().length === 0) return;
1425
+ cy.layout(LAYOUT_OPTIONS).run();
1426
+ }
1427
+ function findNode(name) {
1428
+ if (!cy) return null;
1429
+ const node = cy.getElementById(name);
1430
+ if (node.length > 0) return node;
1431
+ const match = cy.nodes().filter((n) => {
1432
+ const nName = n.data("name") || "";
1433
+ const qName = n.data("qualifiedName") || "";
1434
+ return nName === name || qName.endsWith("." + name);
1435
+ });
1436
+ return match.length > 0 ? match : null;
1437
+ }
1438
+ function buildStylesheet() {
1439
+ const styles = [
1440
+ {
1441
+ selector: "node",
1442
+ style: {
1443
+ "label": "data(label)",
1444
+ "font-size": 11,
1445
+ "color": "#c0caf5",
1446
+ "text-valign": "bottom",
1447
+ "text-halign": "center",
1448
+ "text-margin-y": 5,
1449
+ "width": 20,
1450
+ "height": 20,
1451
+ "shape": "roundrectangle",
1452
+ "border-width": 1.5,
1453
+ "border-color": "#565f89",
1454
+ "background-color": "rgba(34,35,54,0.8)",
1455
+ "font-family": "'JetBrains Mono', monospace",
1456
+ "text-wrap": "none"
1457
+ }
1458
+ },
1459
+ {
1460
+ selector: "edge",
1461
+ style: {
1462
+ "width": 1,
1463
+ "line-color": "#565f89",
1464
+ "target-arrow-color": "#565f89",
1465
+ "target-arrow-shape": "triangle",
1466
+ "arrow-scale": 0.6,
1467
+ "curve-style": "bezier",
1468
+ "opacity": 0.4
1469
+ }
1470
+ }
1471
+ ];
1472
+ for (const [kind, colors] of Object.entries(KIND_COLORS)) {
1473
+ styles.push({
1474
+ selector: `node.${kind}`,
1475
+ style: {
1476
+ "color": colors.border,
1477
+ "border-color": colors.border,
1478
+ "background-color": colors.bg
1479
+ }
1480
+ });
1481
+ }
1482
+ for (const [kind, s] of Object.entries(EDGE_STYLES)) {
1483
+ styles.push({
1484
+ selector: `edge.${kind}`,
1485
+ style: {
1486
+ "line-style": s.lineStyle,
1487
+ "line-color": s.color,
1488
+ "target-arrow-color": s.color,
1489
+ "opacity": s.opacity,
1490
+ "width": s.width
1491
+ }
1492
+ });
1493
+ }
1494
+ styles.push({ selector: "node.pinned", style: { "border-color": "#e0af68", "border-width": 3 } });
1495
+ styles.push({ selector: "node.faded", style: { "opacity": 0.15 } });
1496
+ styles.push({ selector: "edge.faded", style: { "opacity": 0.05 } });
1497
+ styles.push({ selector: "node.highlighted", style: { "border-width": 2.5, "z-index": 10 } });
1498
+ styles.push({ selector: "edge.highlighted", style: { "opacity": 0.9, "width": 2, "z-index": 10 } });
1499
+ styles.push({ selector: "node.agent-pulse", style: { "border-color": "#ff9e64", "border-width": 4, "background-color": "rgba(255,158,100,0.25)" } });
1500
+ styles.push({ selector: "node.search-match", style: { "border-color": "#e0af68", "border-width": 2.5 } });
1501
+ styles.push({ selector: "node.expanded", style: { "border-width": 2.5 } });
1502
+ return styles;
1503
+ }
1504
+ function setupInteractions(cyInst, detailEl) {
1505
+ cyInst.on("tap", "node", function(evt) {
1506
+ const node = evt.target;
1507
+ showDetail(node, detailEl);
1508
+ });
1509
+ cyInst.on("dbltap", "node", function(evt) {
1510
+ const node = evt.target;
1511
+ const id = node.data("qualifiedName") || node.data("id");
1512
+ if (!node.hasClass("expanded")) {
1513
+ node.addClass("expanded");
1514
+ expandNodeAndLayout(id);
1515
+ }
1516
+ });
1517
+ cyInst.on("mouseover", "node", function(evt) {
1518
+ if (!cy) return;
1519
+ const node = evt.target;
1520
+ const neighborhood = node.closedNeighborhood();
1521
+ cy.elements().not(neighborhood).addClass("faded");
1522
+ neighborhood.addClass("highlighted");
1523
+ });
1524
+ cyInst.on("mouseout", "node", function() {
1525
+ if (!cy) return;
1526
+ cy.elements().removeClass("faded highlighted");
1527
+ });
1528
+ cyInst.on("tap", function(evt) {
1529
+ if (evt.target === cyInst) {
1530
+ detailEl.classList.add("hidden");
1531
+ }
1532
+ });
1533
+ }
1534
+ function connectExistingNodes() {
1535
+ if (!cy) return;
1536
+ const nodeIds = new Set(cy.nodes().map((n) => n.id()));
1537
+ const visited = /* @__PURE__ */ new Set();
1538
+ for (const id of nodeIds) {
1539
+ const edges = edgeIndex.get(id) || [];
1540
+ for (const edge of edges) {
1541
+ const edgeId = `${edge.source}->${edge.target}:${edge.kind}`;
1542
+ if (visited.has(edgeId)) continue;
1543
+ visited.add(edgeId);
1544
+ if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
1545
+ addEdgeToGraph(edge);
1546
+ }
1547
+ }
1548
+ }
1549
+ }
1550
+ async function showDetail(node, detailEl) {
1551
+ const data = {
1552
+ label: node.data("label"),
1553
+ qualifiedName: node.data("qualifiedName"),
1554
+ name: node.data("name"),
1555
+ kind: node.data("kind"),
1556
+ file: node.data("file"),
1557
+ startLine: node.data("startLine")
1558
+ };
1559
+ const isPinned = pinnedNames.has(data.qualifiedName);
1560
+ const kind = data.kind || "unknown";
1561
+ const kindColor = KIND_COLORS[kind] ? KIND_COLORS[kind].border : "#565f89";
1562
+ let html = `
1563
+ <div class="detail-header">
1564
+ <span class="detail-name">${escapeHtml(data.label)}</span>
1565
+ <span class="detail-kind-badge" style="background:${kindColor}20;color:${kindColor}">${kind}</span>
1566
+ </div>
1567
+ <div class="detail-file">${escapeHtml(data.file || "unknown")}${data.startLine ? ":" + data.startLine : ""}</div>
1568
+ `;
1569
+ html += `<div class="detail-actions">`;
1570
+ html += `<button class="detail-pin header-btn" data-name="${escapeHtml(data.qualifiedName)}">${isPinned ? "Unpin" : "Pin to focus"}</button>`;
1571
+ html += `<button class="detail-explain-btn header-btn" data-name="${escapeHtml(data.qualifiedName)}">Explain</button>`;
1572
+ html += `</div>`;
1573
+ html += `<div id="detail-source"><div class="detail-section-title">Source</div><pre class="detail-code">Loading...</pre></div>`;
1574
+ html += `<div class="detail-section" id="detail-annotations">`;
1575
+ html += `<div class="detail-section-title">Annotations</div>`;
1576
+ html += `<div class="detail-annotation-list"></div>`;
1577
+ html += `<div class="detail-annotation-input">`;
1578
+ html += `<textarea class="detail-annotation-textarea" placeholder="Add a note..." rows="1"></textarea>`;
1579
+ html += `<button class="dropdown-action detail-annotation-add">Add</button>`;
1580
+ html += `</div></div>`;
1581
+ html += `<div class="detail-section hidden" id="detail-explain"><div class="detail-section-title">Explanation</div><div class="detail-explain-content"></div></div>`;
1582
+ html += '<div class="detail-section" id="detail-deps"><div class="detail-section-title">Dependencies</div><div class="detail-section-list">Loading...</div></div>';
1583
+ html += '<div class="detail-section" id="detail-refs"><div class="detail-section-title">References</div><div class="detail-section-list">Loading...</div></div>';
1584
+ detailEl.innerHTML = '<div class="resize-handle"></div>' + html;
1585
+ detailEl.classList.remove("hidden");
1586
+ const handle = detailEl.querySelector(".resize-handle");
1587
+ handle.addEventListener("mousedown", (e) => {
1588
+ e.preventDefault();
1589
+ handle.classList.add("dragging");
1590
+ const startX = e.clientX;
1591
+ const startWidth = detailEl.offsetWidth;
1592
+ function onMove(ev) {
1593
+ const newWidth = startWidth - (ev.clientX - startX);
1594
+ detailEl.style.width = Math.max(200, newWidth) + "px";
1595
+ }
1596
+ function onUp() {
1597
+ handle.classList.remove("dragging");
1598
+ document.removeEventListener("mousemove", onMove);
1599
+ document.removeEventListener("mouseup", onUp);
1600
+ }
1601
+ document.addEventListener("mousemove", onMove);
1602
+ document.addEventListener("mouseup", onUp);
1603
+ });
1604
+ const pinBtn = detailEl.querySelector(".detail-pin");
1605
+ pinBtn.addEventListener("click", async () => {
1606
+ const name = pinBtn.dataset.name || "";
1607
+ await togglePin(name, node, pinBtn);
1608
+ });
1609
+ const explainBtn = detailEl.querySelector(".detail-explain-btn");
1610
+ explainBtn.addEventListener("click", () => {
1611
+ const name = explainBtn.dataset.name || "";
1612
+ explainSymbol(name, detailEl);
1613
+ });
1614
+ const symName = data.qualifiedName || data.name;
1615
+ const addBtn = detailEl.querySelector(".detail-annotation-add");
1616
+ const textarea = detailEl.querySelector(".detail-annotation-textarea");
1617
+ addBtn.addEventListener("click", async () => {
1618
+ const text = textarea.value.trim();
1619
+ if (!text) return;
1620
+ await addAnnotation(symName, text);
1621
+ textarea.value = "";
1622
+ loadAnnotations(symName, detailEl);
1623
+ });
1624
+ textarea.addEventListener("keydown", (e) => {
1625
+ if (e.key === "Enter" && !e.shiftKey) {
1626
+ e.preventDefault();
1627
+ addBtn.click();
1628
+ }
1629
+ });
1630
+ loadSource(symName, detailEl);
1631
+ loadAnnotations(symName, detailEl);
1632
+ loadDepsAndRefs(symName, detailEl);
1633
+ }
1634
+ async function loadSource(name, detailEl) {
1635
+ const codeEl = detailEl.querySelector("#detail-source .detail-code");
1636
+ if (!codeEl) return;
1637
+ try {
1638
+ const res = await fetch(`/api/symbols/${encodeURIComponent(name)}/source`);
1639
+ if (res.ok) {
1640
+ const data = await res.json();
1641
+ const ext = (data.filePath || "").split(".").pop() || "";
1642
+ const langMap = { ts: "typescript", tsx: "typescript", js: "javascript", jsx: "javascript" };
1643
+ const lang = langMap[ext] || "typescript";
1644
+ codeEl.className = "detail-code language-" + lang;
1645
+ codeEl.textContent = data.source;
1646
+ if (typeof hljs !== "undefined") {
1647
+ hljs.highlightElement(codeEl);
1648
+ }
1649
+ } else {
1650
+ codeEl.textContent = "(source unavailable)";
1651
+ }
1652
+ } catch {
1653
+ codeEl.textContent = "(source unavailable)";
1654
+ }
1655
+ }
1656
+ async function loadDepsAndRefs(name, detailEl) {
1657
+ const encodedName = encodeURIComponent(name);
1658
+ try {
1659
+ const [depsRes, refsRes] = await Promise.all([
1660
+ fetch(`/api/symbols/${encodedName}/dependencies?depth=1`).catch(() => null),
1661
+ fetch(`/api/symbols/${encodedName}/references`).catch(() => null)
1662
+ ]);
1663
+ const depsEl = detailEl.querySelector("#detail-deps .detail-section-list");
1664
+ const refsEl = detailEl.querySelector("#detail-refs .detail-section-list");
1665
+ if (depsRes && depsRes.ok) {
1666
+ const deps = await depsRes.json();
1667
+ const items = deps.dependencies || deps || [];
1668
+ depsEl.innerHTML = items.length ? items.map((d) => {
1669
+ const target = typeof d === "string" ? d : d.qualifiedName || d.name || "";
1670
+ const label = typeof d === "string" ? d : d.name || d.qualifiedName || "";
1671
+ return `<a class="detail-link" data-target="${escapeHtml(target)}">${escapeHtml(label)}</a>`;
1672
+ }).join("") : '<span class="detail-empty">None</span>';
1673
+ } else {
1674
+ depsEl.innerHTML = '<span class="detail-empty">None</span>';
1675
+ }
1676
+ if (refsRes && refsRes.ok) {
1677
+ const refs = await refsRes.json();
1678
+ const items = refs.references || refs || [];
1679
+ refsEl.innerHTML = items.length ? items.map((r) => {
1680
+ const id = typeof r === "string" ? r : r.from || r.qualifiedName || r.name || "";
1681
+ const label = id.split(".").pop() || id;
1682
+ const kind = typeof r === "string" ? "" : r.kind || "";
1683
+ return `<a class="detail-link" data-target="${escapeHtml(id)}">${escapeHtml(label)} <span style="opacity:0.5">${escapeHtml(kind)}</span></a>`;
1684
+ }).join("") : '<span class="detail-empty">None</span>';
1685
+ } else {
1686
+ refsEl.innerHTML = '<span class="detail-empty">None</span>';
1687
+ }
1688
+ detailEl.querySelectorAll(".detail-link").forEach((link) => {
1689
+ link.addEventListener("click", () => {
1690
+ const target = link.dataset.target || "";
1691
+ expandNodeAndLayout(target);
1692
+ if (!cy) return;
1693
+ const targetNode = cy.getElementById(target);
1694
+ if (targetNode.length) {
1695
+ cy.animate({ center: { eles: targetNode }, zoom: 1.5 }, { duration: 300 });
1696
+ targetNode.flashClass("highlighted", 1e3);
1697
+ showDetail(targetNode, detailEl);
1698
+ }
1699
+ });
1700
+ });
1701
+ } catch {
1702
+ }
1703
+ }
1704
+ async function loadAnnotations(name, detailEl) {
1705
+ const listEl = detailEl.querySelector(".detail-annotation-list");
1706
+ if (!listEl) return;
1707
+ try {
1708
+ const res = await fetch(`/api/symbols/${encodeURIComponent(name)}/annotations`);
1709
+ if (!res.ok) {
1710
+ listEl.innerHTML = "";
1711
+ return;
1712
+ }
1713
+ const data = await res.json();
1714
+ const notes = data.annotations || [];
1715
+ if (notes.length === 0) {
1716
+ listEl.innerHTML = '<span class="detail-empty">No annotations</span>';
1717
+ return;
1718
+ }
1719
+ listEl.innerHTML = notes.map(
1720
+ (text, i) => `<div class="detail-annotation-item">
1721
+ <span class="annotation-text">${escapeHtml(text)}</span>
1722
+ <button class="annotation-remove" data-index="${i}" title="Remove">&times;</button>
1723
+ </div>`
1724
+ ).join("");
1725
+ listEl.querySelectorAll(".annotation-remove").forEach((btn) => {
1726
+ btn.addEventListener("click", async () => {
1727
+ const idx = Number(btn.dataset.index);
1728
+ await fetch(`/api/symbols/${encodeURIComponent(name)}/annotations/${idx}`, { method: "DELETE" });
1729
+ loadAnnotations(name, detailEl);
1730
+ });
1731
+ });
1732
+ } catch {
1733
+ listEl.innerHTML = "";
1734
+ }
1735
+ }
1736
+ async function addAnnotation(name, text) {
1737
+ await fetch(`/api/symbols/${encodeURIComponent(name)}/annotations`, {
1738
+ method: "POST",
1739
+ headers: { "Content-Type": "application/json" },
1740
+ body: JSON.stringify({ text })
1741
+ });
1742
+ }
1743
+ async function explainSymbol(name, detailEl) {
1744
+ const section = detailEl.querySelector("#detail-explain");
1745
+ const content = section.querySelector(".detail-explain-content");
1746
+ section.classList.remove("hidden");
1747
+ content.innerHTML = '<span class="explain-status"><span class="explain-spinner"></span> Researching...</span>';
1748
+ let streaming = false;
1749
+ let rawText = "";
1750
+ function showToolStatus(toolName, input) {
1751
+ if (streaming) return;
1752
+ const arg = input.name || input.path || input.symbol || input.query || "";
1753
+ content.innerHTML = `<span class="explain-status"><span class="explain-spinner"></span> ${escapeHtml(toolName)}(${escapeHtml(String(arg))})</span>`;
1754
+ }
1755
+ function startStreaming() {
1756
+ if (streaming) return;
1757
+ streaming = true;
1758
+ rawText = "";
1759
+ content.textContent = "";
1760
+ }
1761
+ function finalize() {
1762
+ if (rawText) {
1763
+ renderMarkdownInto(content, rawText);
1764
+ }
1765
+ }
1766
+ try {
1767
+ const res = await fetch(`/api/symbols/${encodeURIComponent(name)}/explain`);
1768
+ if (!res.ok || !res.body) {
1769
+ content.textContent = "(explain unavailable)";
1770
+ return;
1771
+ }
1772
+ const reader = res.body.getReader();
1773
+ const decoder = new TextDecoder();
1774
+ let buffer = "";
1775
+ while (true) {
1776
+ const { done, value } = await reader.read();
1777
+ if (done) break;
1778
+ buffer += decoder.decode(value, { stream: true });
1779
+ const lines = buffer.split("\n");
1780
+ buffer = lines.pop() || "";
1781
+ for (const line of lines) {
1782
+ if (!line.startsWith("data: ")) continue;
1783
+ const payload = line.slice(6);
1784
+ if (payload === "[DONE]") {
1785
+ finalize();
1786
+ return;
1787
+ }
1788
+ try {
1789
+ const event = JSON.parse(payload);
1790
+ if (event.type === "tool_call_start") {
1791
+ showToolStatus(event.name, event.input || {});
1792
+ } else if (event.type === "streaming_chunk" && event.content) {
1793
+ startStreaming();
1794
+ rawText += event.content;
1795
+ content.textContent = rawText;
1796
+ content.scrollTop = content.scrollHeight;
1797
+ } else if (event.type === "error") {
1798
+ startStreaming();
1799
+ rawText += `
1800
+ [Error: ${event.message}]`;
1801
+ content.textContent = rawText;
1802
+ }
1803
+ } catch {
1804
+ }
1805
+ }
1806
+ }
1807
+ finalize();
1808
+ } catch {
1809
+ if (!streaming) {
1810
+ content.textContent = "(explain failed)";
1811
+ } else {
1812
+ finalize();
1813
+ }
1814
+ }
1815
+ }
1816
+ async function togglePin(name, node, btnEl) {
1817
+ const wasPinned = pinnedNames.has(name);
1818
+ try {
1819
+ await fetch("/api/focus", {
1820
+ method: "POST",
1821
+ headers: { "Content-Type": "application/json" },
1822
+ body: JSON.stringify({
1823
+ action: wasPinned ? "unpin" : "pin",
1824
+ symbol: name
1825
+ })
1826
+ });
1827
+ if (wasPinned) {
1828
+ pinnedNames.delete(name);
1829
+ node.removeClass("pinned");
1830
+ btnEl.textContent = "Pin to focus";
1831
+ } else {
1832
+ pinnedNames.add(name);
1833
+ node.addClass("pinned");
1834
+ btnEl.textContent = "Unpin";
1835
+ }
1836
+ } catch {
1837
+ }
1838
+ }
1839
+ function setupToolbar() {
1840
+ const searchInput = document.getElementById("graph-search");
1841
+ const fitBtn = document.getElementById("graph-fit");
1842
+ const relayoutBtn = document.getElementById("graph-relayout");
1843
+ const clearBtn = document.getElementById("graph-clear");
1844
+ let searchTimeout;
1845
+ const dropdown = document.createElement("div");
1846
+ dropdown.className = "search-dropdown hidden";
1847
+ searchInput.parentNode.style.position = "relative";
1848
+ searchInput.parentNode.appendChild(dropdown);
1849
+ const rankedSymbols = allSymbolNames.slice().sort((a, b2) => {
1850
+ const nodeA = graphNodes.get(a);
1851
+ const nodeB = graphNodes.get(b2);
1852
+ const expA = nodeA ? !!nodeA.exported : false;
1853
+ const expB = nodeB ? !!nodeB.exported : false;
1854
+ if (expA !== expB) return expA ? -1 : 1;
1855
+ const nameA = (a.split(".").pop() || "").toLowerCase();
1856
+ const nameB = (b2.split(".").pop() || "").toLowerCase();
1857
+ return nameA.localeCompare(nameB);
1858
+ });
1859
+ function showDropdownResults(matches) {
1860
+ if (matches.length === 0) {
1861
+ dropdown.classList.add("hidden");
1862
+ return;
1863
+ }
1864
+ dropdown.innerHTML = matches.map((name) => {
1865
+ const node = graphNodes.get(name);
1866
+ const kind = node ? (node.kind || "").toLowerCase() : "";
1867
+ const shortName = name.split(".").pop() || name;
1868
+ const kindColor = KIND_COLORS[kind] ? KIND_COLORS[kind].border : "#565f89";
1869
+ return `<div class="search-result" data-id="${escapeHtml(name)}">
1870
+ <span class="search-result-name">${escapeHtml(shortName)}</span>
1871
+ <span class="search-result-kind" style="color:${kindColor}">${kind}</span>
1872
+ </div>`;
1873
+ }).join("");
1874
+ dropdown.classList.remove("hidden");
1875
+ dropdown.querySelectorAll(".search-result").forEach((el) => {
1876
+ el.addEventListener("click", () => {
1877
+ const id = el.dataset.id || "";
1878
+ expandNodeAndLayout(id);
1879
+ searchInput.value = "";
1880
+ dropdown.classList.add("hidden");
1881
+ if (!cy) return;
1882
+ const targetNode = cy.getElementById(id);
1883
+ if (targetNode.length) {
1884
+ setTimeout(() => {
1885
+ cy.animate({ center: { eles: targetNode }, zoom: 1.2 }, { duration: 300 });
1886
+ targetNode.flashClass("highlighted", 1500);
1887
+ }, 350);
1888
+ }
1889
+ });
1890
+ });
1891
+ }
1892
+ searchInput.addEventListener("focus", () => {
1893
+ if (searchInput.value.trim().length < 2) {
1894
+ showDropdownResults(rankedSymbols.slice(0, 20));
1895
+ }
1896
+ });
1897
+ searchInput.addEventListener("input", () => {
1898
+ clearTimeout(searchTimeout);
1899
+ searchTimeout = setTimeout(() => {
1900
+ const query = searchInput.value.trim().toLowerCase();
1901
+ if (query.length < 2) {
1902
+ showDropdownResults(rankedSymbols.slice(0, 20));
1903
+ return;
1904
+ }
1905
+ const matches = rankedSymbols.filter((name) => {
1906
+ const shortName = (name.split(".").pop() || "").toLowerCase();
1907
+ return shortName.includes(query) || name.toLowerCase().includes(query);
1908
+ }).slice(0, 15);
1909
+ showDropdownResults(matches);
1910
+ }, 150);
1911
+ });
1912
+ searchInput.addEventListener("keydown", (e) => {
1913
+ if (e.key === "Escape") {
1914
+ searchInput.value = "";
1915
+ dropdown.classList.add("hidden");
1916
+ }
1917
+ });
1918
+ document.addEventListener("click", (e) => {
1919
+ if (!searchInput.contains(e.target) && !dropdown.contains(e.target)) {
1920
+ dropdown.classList.add("hidden");
1921
+ }
1922
+ });
1923
+ fitBtn.addEventListener("click", () => {
1924
+ if (cy && cy.nodes().length > 0) {
1925
+ cy.fit(40);
1926
+ }
1927
+ });
1928
+ relayoutBtn.addEventListener("click", () => {
1929
+ runLayout();
1930
+ });
1931
+ clearBtn.addEventListener("click", () => {
1932
+ if (!cy) return;
1933
+ cy.elements().remove();
1934
+ document.getElementById("symbol-detail").classList.add("hidden");
1935
+ });
1936
+ }
20
1937
 
1938
+ // src/web/app.ts
1939
+ var messagesEl = document.getElementById("messages");
1940
+ var chatForm = document.getElementById("chat-form");
1941
+ var chatInput = document.getElementById("chat-input");
1942
+ var sendBtn = document.getElementById("send-btn");
1943
+ var cancelBtn = document.getElementById("cancel-btn");
1944
+ var statusBadge = document.getElementById("status-badge");
1945
+ var modelInfo = document.getElementById("model-info");
1946
+ var sessionBtn = document.getElementById("session-btn");
1947
+ var sessionDropdown = document.getElementById("session-dropdown");
1948
+ var sessionList = document.getElementById("session-list");
1949
+ var saveBtn = document.getElementById("save-btn");
1950
+ var saveLabelInput = document.getElementById("save-label");
1951
+ var ws;
1952
+ var currentAssistantEl = null;
1953
+ var assistantText = "";
1954
+ var hadToolCalls = false;
1955
+ var TOOL_RESULT_MAX = 500;
21
1956
  function connect() {
22
1957
  const protocol = location.protocol === "https:" ? "wss:" : "ws:";
23
1958
  ws = new WebSocket(`${protocol}//${location.host}`);
24
-
25
1959
  ws.onopen = () => {
26
1960
  setStatus("ready");
27
1961
  fetchStatus();
28
1962
  };
29
-
30
1963
  ws.onclose = () => {
31
1964
  setStatus("error");
32
- setTimeout(connect, 2000);
1965
+ setTimeout(connect, 2e3);
33
1966
  };
34
-
35
1967
  ws.onmessage = (event) => {
36
1968
  const msg = JSON.parse(event.data);
37
1969
  handleServerMessage(msg);
38
1970
  };
39
1971
  }
40
-
41
1972
  function setStatus(state) {
42
1973
  statusBadge.textContent = state;
43
1974
  statusBadge.className = `badge ${state}`;
44
1975
  }
45
-
46
1976
  function setBusy(busy) {
47
1977
  sendBtn.disabled = busy;
48
1978
  sendBtn.classList.toggle("hidden", busy);
@@ -53,67 +1983,80 @@ function setBusy(busy) {
53
1983
  setStatus("ready");
54
1984
  }
55
1985
  }
56
-
57
1986
  async function fetchStatus() {
58
1987
  try {
59
1988
  const res = await fetch("/api/status");
60
1989
  const data = await res.json();
61
- modelInfo.textContent = `${data.model} · ${data.provider}`;
1990
+ modelInfo.textContent = `${data.model} \xB7 ${data.provider}`;
62
1991
  } catch {
63
- // ignore
64
1992
  }
65
1993
  }
66
-
67
1994
  function handleServerMessage(msg) {
68
1995
  switch (msg.type) {
69
1996
  case "turn_start":
70
1997
  assistantText = "";
1998
+ hadToolCalls = false;
71
1999
  currentAssistantEl = addMessage("", "assistant");
72
2000
  currentAssistantEl.classList.add("streaming-cursor");
73
2001
  setBusy(true);
74
2002
  break;
75
-
76
2003
  case "streaming_chunk":
77
- assistantText += msg.content;
2004
+ if (hadToolCalls) {
2005
+ if (currentAssistantEl) {
2006
+ currentAssistantEl.classList.remove("streaming-cursor");
2007
+ }
2008
+ assistantText = "";
2009
+ hadToolCalls = false;
2010
+ currentAssistantEl = addMessage("", "assistant");
2011
+ currentAssistantEl.classList.add("streaming-cursor");
2012
+ }
2013
+ assistantText += msg.content || "";
78
2014
  if (currentAssistantEl) {
79
- currentAssistantEl.textContent = assistantText;
2015
+ renderMarkdownInto(currentAssistantEl, assistantText);
80
2016
  scrollToBottom();
81
2017
  }
82
2018
  break;
83
-
84
2019
  case "thinking":
85
- addMessage(msg.content, "thinking");
2020
+ addMessage(msg.content || "", "thinking");
86
2021
  break;
87
-
88
2022
  case "step":
89
- // Intentionally not shown — tool calls provide enough context
90
2023
  break;
91
-
92
2024
  case "tool_call_start":
93
- addToolCall(msg.name, msg.input);
2025
+ hadToolCalls = true;
2026
+ addToolCall(msg.name || "", msg.input || {});
2027
+ {
2028
+ const symbolTools = ["read_symbol", "get_dependencies", "find_references"];
2029
+ if (symbolTools.includes(msg.name || "")) {
2030
+ const symName = msg.input?.name || msg.input?.symbol || msg.input?.qualifiedName;
2031
+ if (symName) highlightAgentActivity(symName);
2032
+ }
2033
+ }
94
2034
  break;
95
-
96
2035
  case "tool_call_end":
97
- finalizeToolCall(msg.name, msg.result, msg.elapsedMs);
2036
+ finalizeToolCall(msg.name || "", msg.result || "", msg.elapsedMs || 0);
98
2037
  break;
99
-
100
2038
  case "turn_end":
101
- if (currentAssistantEl) {
2039
+ if (hadToolCalls && msg.text) {
2040
+ if (currentAssistantEl) {
2041
+ currentAssistantEl.classList.remove("streaming-cursor");
2042
+ }
2043
+ currentAssistantEl = addMessage(msg.text, "assistant", true);
2044
+ } else if (currentAssistantEl) {
102
2045
  currentAssistantEl.classList.remove("streaming-cursor");
103
2046
  if (!assistantText && msg.text) {
104
- currentAssistantEl.textContent = msg.text;
2047
+ renderMarkdownInto(currentAssistantEl, msg.text);
105
2048
  }
106
2049
  }
107
2050
  currentAssistantEl = null;
108
2051
  assistantText = "";
2052
+ hadToolCalls = false;
109
2053
  setBusy(false);
110
2054
  if (msg.usage) {
111
2055
  addUsageInfo(msg.usage);
112
2056
  }
113
2057
  break;
114
-
115
2058
  case "error":
116
- addMessage(`Error: ${msg.message}`, "error");
2059
+ addMessage(`Error: ${msg.message || ""}`, "error");
117
2060
  if (currentAssistantEl) {
118
2061
  currentAssistantEl.classList.remove("streaming-cursor");
119
2062
  }
@@ -121,45 +2064,35 @@ function handleServerMessage(msg) {
121
2064
  assistantText = "";
122
2065
  setBusy(false);
123
2066
  break;
124
-
125
2067
  case "busy":
126
2068
  addMessage("Agent is busy. Please wait for the current turn to finish.", "error");
127
2069
  break;
128
2070
  }
129
2071
  }
130
-
131
- function addMessage(text, type) {
2072
+ function addMessage(text, type, markdown = false) {
132
2073
  const el = document.createElement("div");
133
2074
  el.className = `message ${type}`;
134
- el.textContent = text;
2075
+ if (markdown && type === "assistant") {
2076
+ renderMarkdownInto(el, text);
2077
+ } else {
2078
+ el.textContent = text;
2079
+ }
135
2080
  messagesEl.appendChild(el);
136
2081
  scrollToBottom();
137
2082
  return el;
138
2083
  }
139
-
140
- /**
141
- * Extract the most meaningful short arg from tool input.
142
- * e.g. for read_file → the path, for search → the query, for run_command → the command.
143
- */
144
2084
  function summarizeToolInput(name, input) {
145
- // Priority keys by tool type
146
- const key =
147
- input.path ?? input.file_path ?? input.command ?? input.query ??
148
- input.pattern ?? input.name ?? input.old_string;
149
-
2085
+ const key = input.path ?? input.file_path ?? input.command ?? input.query ?? input.pattern ?? input.name ?? input.old_string;
150
2086
  if (typeof key === "string") {
151
2087
  return key.length > 60 ? key.slice(0, 57) + "..." : key;
152
2088
  }
153
-
154
- // Fallback: first string value, truncated
155
- for (const v of Object.values(input)) {
156
- if (typeof v === "string" && v.length > 0) {
157
- return v.length > 60 ? v.slice(0, 57) + "..." : v;
2089
+ for (const v2 of Object.values(input)) {
2090
+ if (typeof v2 === "string" && v2.length > 0) {
2091
+ return v2.length > 60 ? v2.slice(0, 57) + "..." : v2;
158
2092
  }
159
2093
  }
160
2094
  return "";
161
2095
  }
162
-
163
2096
  function getOrCreateToolGroup() {
164
2097
  const last = messagesEl.lastElementChild;
165
2098
  if (last && last.classList.contains("tool-group")) {
@@ -170,97 +2103,65 @@ function getOrCreateToolGroup() {
170
2103
  messagesEl.appendChild(group);
171
2104
  return group;
172
2105
  }
173
-
174
2106
  function addToolCall(name, input) {
175
2107
  const group = getOrCreateToolGroup();
176
-
177
2108
  const el = document.createElement("div");
178
2109
  el.className = "tool-call";
179
2110
  el.dataset.toolName = name;
180
-
181
2111
  const summary = summarizeToolInput(name, input);
182
2112
  const summaryHtml = summary ? ` <span class="tool-arg">${escapeHtml(summary)}</span>` : "";
183
-
184
- el.innerHTML =
185
- `<span class="tool-header">` +
186
- `<span class="tool-name">${escapeHtml(name)}</span>${summaryHtml}` +
187
- `<span class="tool-time"></span>` +
188
- `</span>` +
189
- `<div class="tool-result"></div>`;
190
-
2113
+ el.innerHTML = `<span class="tool-header"><span class="tool-name">${escapeHtml(name)}</span>${summaryHtml}<span class="tool-time"></span></span><div class="tool-result"></div>`;
191
2114
  el.addEventListener("click", () => el.classList.toggle("expanded"));
192
2115
  group.appendChild(el);
193
2116
  scrollToBottom();
194
2117
  }
195
-
196
2118
  function finalizeToolCall(name, result, elapsedMs) {
197
2119
  const toolEls = messagesEl.querySelectorAll(`.tool-call[data-tool-name="${name}"]`);
198
2120
  const el = toolEls[toolEls.length - 1];
199
2121
  if (!el) return;
200
-
201
2122
  const timeEl = el.querySelector(".tool-time");
202
2123
  if (timeEl) {
203
2124
  timeEl.textContent = `${elapsedMs}ms`;
204
2125
  }
205
-
206
2126
  const resultEl = el.querySelector(".tool-result");
207
2127
  if (resultEl && result) {
208
- const truncated = result.length > TOOL_RESULT_MAX
209
- ? result.slice(0, TOOL_RESULT_MAX) + `\n\n... (${result.length - TOOL_RESULT_MAX} more chars)`
210
- : result;
2128
+ const truncated = result.length > TOOL_RESULT_MAX ? result.slice(0, TOOL_RESULT_MAX) + `
2129
+
2130
+ ... (${result.length - TOOL_RESULT_MAX} more chars)` : result;
211
2131
  resultEl.textContent = truncated;
212
2132
  }
213
2133
  }
214
-
215
2134
  function addUsageInfo(usage) {
216
2135
  const el = document.createElement("div");
217
2136
  el.className = "usage-info";
218
2137
  el.textContent = `${usage.inputTokens} in / ${usage.outputTokens} out`;
219
2138
  messagesEl.appendChild(el);
220
2139
  }
221
-
222
2140
  function scrollToBottom() {
223
2141
  messagesEl.scrollTop = messagesEl.scrollHeight;
224
2142
  }
225
-
226
- function escapeHtml(str) {
227
- const div = document.createElement("div");
228
- div.textContent = str;
229
- return div.innerHTML;
230
- }
231
-
232
- // Form handling
233
2143
  chatForm.addEventListener("submit", (e) => {
234
2144
  e.preventDefault();
235
2145
  const message = chatInput.value.trim();
236
2146
  if (!message) return;
237
-
238
2147
  addMessage(message, "user");
239
2148
  ws.send(JSON.stringify({ type: "chat", message }));
240
2149
  chatInput.value = "";
241
2150
  chatInput.style.height = "auto";
242
2151
  });
243
-
244
2152
  cancelBtn.addEventListener("click", () => {
245
2153
  ws.send(JSON.stringify({ type: "cancel" }));
246
2154
  });
247
-
248
- // Auto-resize textarea
249
2155
  chatInput.addEventListener("input", () => {
250
2156
  chatInput.style.height = "auto";
251
2157
  chatInput.style.height = Math.min(chatInput.scrollHeight, 150) + "px";
252
2158
  });
253
-
254
- // Submit on Enter (Shift+Enter for newline)
255
2159
  chatInput.addEventListener("keydown", (e) => {
256
2160
  if (e.key === "Enter" && !e.shiftKey) {
257
2161
  e.preventDefault();
258
2162
  chatForm.dispatchEvent(new Event("submit"));
259
2163
  }
260
2164
  });
261
-
262
- // ── Session management ──
263
-
264
2165
  sessionBtn.addEventListener("click", (e) => {
265
2166
  e.stopPropagation();
266
2167
  const isOpen = !sessionDropdown.classList.contains("hidden");
@@ -269,21 +2170,18 @@ sessionBtn.addEventListener("click", (e) => {
269
2170
  refreshSessionList();
270
2171
  }
271
2172
  });
272
-
273
- // Close dropdown on outside click
274
2173
  document.addEventListener("click", (e) => {
275
2174
  if (!sessionDropdown.contains(e.target) && e.target !== sessionBtn) {
276
2175
  sessionDropdown.classList.add("hidden");
277
2176
  }
278
2177
  });
279
-
280
2178
  saveBtn.addEventListener("click", async () => {
281
- const label = saveLabelInput.value.trim() || undefined;
2179
+ const label = saveLabelInput.value.trim() || void 0;
282
2180
  try {
283
2181
  const res = await fetch("/api/sessions/save", {
284
2182
  method: "POST",
285
2183
  headers: { "Content-Type": "application/json" },
286
- body: JSON.stringify({ label }),
2184
+ body: JSON.stringify({ label })
287
2185
  });
288
2186
  if (res.ok) {
289
2187
  const data = await res.json();
@@ -292,35 +2190,28 @@ saveBtn.addEventListener("click", async () => {
292
2190
  refreshSessionList();
293
2191
  }
294
2192
  } catch {
295
- // ignore
296
2193
  }
297
2194
  });
298
-
299
2195
  saveLabelInput.addEventListener("keydown", (e) => {
300
2196
  if (e.key === "Enter") {
301
2197
  e.preventDefault();
302
2198
  saveBtn.click();
303
2199
  }
304
2200
  });
305
-
306
2201
  async function refreshSessionList() {
307
2202
  try {
308
2203
  const res = await fetch("/api/sessions");
309
2204
  const data = await res.json();
310
2205
  const sessions = data.sessions;
311
-
312
2206
  if (!sessions || sessions.length === 0) {
313
2207
  sessionList.innerHTML = '<div class="dropdown-empty">No saved sessions</div>';
314
2208
  return;
315
2209
  }
316
-
317
2210
  sessionList.innerHTML = "";
318
2211
  for (const s of sessions) {
319
2212
  const el = document.createElement("div");
320
2213
  el.className = "session-item";
321
- el.innerHTML =
322
- `<span class="session-label">${escapeHtml(s.label)}</span>` +
323
- `<span class="session-meta">${s.messageCount} msgs</span>`;
2214
+ el.innerHTML = `<span class="session-label">${escapeHtml(s.label)}</span><span class="session-meta">${s.messageCount} msgs</span>`;
324
2215
  el.addEventListener("click", () => loadSession(s.label));
325
2216
  sessionList.appendChild(el);
326
2217
  }
@@ -328,13 +2219,12 @@ async function refreshSessionList() {
328
2219
  sessionList.innerHTML = '<div class="dropdown-empty">Failed to load sessions</div>';
329
2220
  }
330
2221
  }
331
-
332
2222
  async function loadSession(label) {
333
2223
  try {
334
2224
  const res = await fetch("/api/sessions/load", {
335
2225
  method: "POST",
336
2226
  headers: { "Content-Type": "application/json" },
337
- body: JSON.stringify({ label }),
2227
+ body: JSON.stringify({ label })
338
2228
  });
339
2229
  if (res.ok) {
340
2230
  sessionDropdown.classList.add("hidden");
@@ -342,9 +2232,39 @@ async function loadSession(label) {
342
2232
  addMessage(`Session "${label}" restored`, "thinking");
343
2233
  }
344
2234
  } catch {
345
- // ignore
346
2235
  }
347
2236
  }
348
-
349
- // Start connection
2237
+ var chatPane = document.getElementById("chat-pane");
2238
+ var divider = document.getElementById("pane-divider");
2239
+ divider.addEventListener("mousedown", (e) => {
2240
+ e.preventDefault();
2241
+ divider.classList.add("dragging");
2242
+ const startX = e.clientX;
2243
+ const startWidth = chatPane.offsetWidth;
2244
+ function onMove(ev) {
2245
+ const newWidth = startWidth + (ev.clientX - startX);
2246
+ const clamped = Math.max(280, Math.min(newWidth, window.innerWidth - 300));
2247
+ chatPane.style.width = clamped + "px";
2248
+ }
2249
+ function onUp() {
2250
+ divider.classList.remove("dragging");
2251
+ document.removeEventListener("mousemove", onMove);
2252
+ document.removeEventListener("mouseup", onUp);
2253
+ resizeGraph();
2254
+ }
2255
+ document.addEventListener("mousemove", onMove);
2256
+ document.addEventListener("mouseup", onUp);
2257
+ });
2258
+ var workspace = document.getElementById("workspace");
2259
+ var graphToggle = document.getElementById("graph-toggle");
2260
+ graphToggle.classList.add("active");
2261
+ graphToggle.addEventListener("click", () => {
2262
+ const isChatOnly = workspace.classList.toggle("chat-only");
2263
+ graphToggle.classList.toggle("active", !isChatOnly);
2264
+ if (!isChatOnly) {
2265
+ chatPane.style.width = "";
2266
+ resizeGraph();
2267
+ }
2268
+ });
350
2269
  connect();
2270
+ initGraph();