@hanhnd/agent-kit 1.0.41 → 1.0.43

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.
package/dist/server.js CHANGED
@@ -36479,19 +36479,19 @@ function adfToMarkdown(adf) {
36479
36479
  if (!adf || typeof adf !== "object") return "No description";
36480
36480
  const content = adf.content;
36481
36481
  if (!content || !Array.isArray(content)) return "No description";
36482
- function renderNodes(nodes, listDepth = 0, parentType) {
36482
+ function renderNodes2(nodes, listDepth = 0, parentType) {
36483
36483
  let result = "";
36484
36484
  if (!nodes || !Array.isArray(nodes)) return result;
36485
36485
  for (const node of nodes) {
36486
36486
  switch (node.type) {
36487
36487
  case "paragraph": {
36488
- const text = renderNodes(node.content, listDepth, node.type);
36488
+ const text = renderNodes2(node.content, listDepth, node.type);
36489
36489
  result += parentType === "listItem" ? text : text + "\n\n";
36490
36490
  break;
36491
36491
  }
36492
36492
  case "heading": {
36493
36493
  const level = node.attrs?.level || 1;
36494
- result += "#".repeat(level) + " " + renderNodes(node.content, listDepth, node.type) + "\n\n";
36494
+ result += "#".repeat(level) + " " + renderNodes2(node.content, listDepth, node.type) + "\n\n";
36495
36495
  break;
36496
36496
  }
36497
36497
  case "text": {
@@ -36522,23 +36522,23 @@ function adfToMarkdown(adf) {
36522
36522
  }
36523
36523
  case "bulletList":
36524
36524
  case "orderedList":
36525
- result += renderNodes(node.content, listDepth + 1, node.type);
36525
+ result += renderNodes2(node.content, listDepth + 1, node.type);
36526
36526
  if (listDepth === 0) result += "\n";
36527
36527
  break;
36528
36528
  case "listItem": {
36529
36529
  const indent = " ".repeat(Math.max(0, listDepth - 1));
36530
36530
  const bullet = parentType === "orderedList" ? "1." : "-";
36531
- const text = renderNodes(node.content, listDepth, node.type).trim();
36531
+ const text = renderNodes2(node.content, listDepth, node.type).trim();
36532
36532
  result += `${indent}${bullet} ${text}
36533
36533
  `;
36534
36534
  break;
36535
36535
  }
36536
36536
  case "blockquote":
36537
- result += "> " + renderNodes(node.content, listDepth, node.type).trim().replace(/\n/g, "\n> ") + "\n\n";
36537
+ result += "> " + renderNodes2(node.content, listDepth, node.type).trim().replace(/\n/g, "\n> ") + "\n\n";
36538
36538
  break;
36539
36539
  case "codeBlock":
36540
36540
  result += `\`\`\`${node.attrs?.language || ""}
36541
- ${renderNodes(node.content, listDepth, node.type).trim()}
36541
+ ${renderNodes2(node.content, listDepth, node.type).trim()}
36542
36542
  \`\`\`
36543
36543
 
36544
36544
  `;
@@ -36550,7 +36550,7 @@ ${renderNodes(node.content, listDepth, node.type).trim()}
36550
36550
  result += "\n";
36551
36551
  break;
36552
36552
  case "table":
36553
- result += renderTable(node.content);
36553
+ result += renderTable2(node.content);
36554
36554
  break;
36555
36555
  case "mention":
36556
36556
  result += `@${node.attrs?.text || node.attrs?.displayName || "user"}`;
@@ -36570,21 +36570,21 @@ ${renderNodes(node.content, listDepth, node.type).trim()}
36570
36570
  break;
36571
36571
  default:
36572
36572
  if (node.content) {
36573
- result += renderNodes(node.content, listDepth, node.type);
36573
+ result += renderNodes2(node.content, listDepth, node.type);
36574
36574
  }
36575
36575
  break;
36576
36576
  }
36577
36577
  }
36578
36578
  return result;
36579
36579
  }
36580
- function renderTable(rows) {
36580
+ function renderTable2(rows) {
36581
36581
  if (!rows || !Array.isArray(rows)) return "";
36582
36582
  let result = "\n";
36583
36583
  let isFirstRow = true;
36584
36584
  for (const row of rows) {
36585
36585
  if (row.type !== "tableRow") continue;
36586
36586
  const cells = row.content || [];
36587
- const rendered = cells.map((c) => renderNodes(c.content).trim().replace(/\n+/g, " ").replace(/\|/g, "\\|"));
36587
+ const rendered = cells.map((c) => renderNodes2(c.content).trim().replace(/\n+/g, " ").replace(/\|/g, "\\|"));
36588
36588
  result += "| " + rendered.join(" | ") + " |\n";
36589
36589
  if (isFirstRow) {
36590
36590
  result += "| " + cells.map(() => "---").join(" | ") + " |\n";
@@ -36593,10 +36593,474 @@ ${renderNodes(node.content, listDepth, node.type).trim()}
36593
36593
  }
36594
36594
  return result + "\n";
36595
36595
  }
36596
- return renderNodes(content).trim() || "No description";
36596
+ return renderNodes2(content).trim() || "No description";
36597
+ }
36598
+
36599
+ // src/services/integration/parser/storage.ts
36600
+ var MAX_STORAGE_DEPTH = 100;
36601
+ var DEPTH_TRUNCATION_MARKER = "[content nested too deeply - truncated]";
36602
+ var VOID_TAGS = /* @__PURE__ */ new Set([
36603
+ "br",
36604
+ "hr",
36605
+ "img",
36606
+ "col",
36607
+ "input",
36608
+ "meta",
36609
+ "link",
36610
+ "ri:page",
36611
+ "ri:attachment",
36612
+ "ri:url",
36613
+ "ri:user",
36614
+ "ri:space",
36615
+ "ri:blog-post",
36616
+ "ac:emoticon"
36617
+ ]);
36618
+ var NAMED_ENTITIES = {
36619
+ // XML predefined
36620
+ nbsp: "\xA0",
36621
+ amp: "&",
36622
+ lt: "<",
36623
+ gt: ">",
36624
+ quot: '"',
36625
+ apos: "'",
36626
+ // dashes & punctuation
36627
+ ndash: "\u2013",
36628
+ mdash: "\u2014",
36629
+ hellip: "\u2026",
36630
+ middot: "\xB7",
36631
+ bull: "\u2022",
36632
+ dagger: "\u2020",
36633
+ Dagger: "\u2021",
36634
+ sect: "\xA7",
36635
+ para: "\xB6",
36636
+ // smart quotes
36637
+ lsquo: "\u2018",
36638
+ rsquo: "\u2019",
36639
+ sbquo: "\u201A",
36640
+ ldquo: "\u201C",
36641
+ rdquo: "\u201D",
36642
+ bdquo: "\u201E",
36643
+ laquo: "\xAB",
36644
+ raquo: "\xBB",
36645
+ prime: "\u2032",
36646
+ Prime: "\u2033",
36647
+ // arrows
36648
+ larr: "\u2190",
36649
+ rarr: "\u2192",
36650
+ uarr: "\u2191",
36651
+ darr: "\u2193",
36652
+ harr: "\u2194",
36653
+ // symbols & math
36654
+ copy: "\xA9",
36655
+ reg: "\xAE",
36656
+ trade: "\u2122",
36657
+ deg: "\xB0",
36658
+ plusmn: "\xB1",
36659
+ times: "\xD7",
36660
+ divide: "\xF7",
36661
+ micro: "\xB5",
36662
+ frac12: "\xBD",
36663
+ frac14: "\xBC",
36664
+ frac34: "\xBE",
36665
+ ne: "\u2260",
36666
+ le: "\u2264",
36667
+ ge: "\u2265",
36668
+ infin: "\u221E",
36669
+ // currency
36670
+ euro: "\u20AC",
36671
+ pound: "\xA3",
36672
+ yen: "\xA5",
36673
+ cent: "\xA2"
36674
+ };
36675
+ var PANEL_MACROS = /* @__PURE__ */ new Set(["info", "note", "warning", "tip", "panel"]);
36676
+ var PLACEHOLDER_MACROS = /* @__PURE__ */ new Set(["toc", "children", "excerpt-include"]);
36677
+ var ATTRIBUTE_PATTERN = /([A-Za-z_:][-A-Za-z0-9_:.]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g;
36678
+ function codePointOrLiteral(code, literal2) {
36679
+ if (!Number.isInteger(code) || code < 1 || code > 1114111) return literal2;
36680
+ try {
36681
+ return String.fromCodePoint(code);
36682
+ } catch {
36683
+ return literal2;
36684
+ }
36685
+ }
36686
+ function decodeEntities(text) {
36687
+ if (!text.includes("&")) return text;
36688
+ return text.replace(/&(#[Xx][0-9A-Fa-f]+|#\d+|[A-Za-z][A-Za-z0-9]*);/g, (literal2, body) => {
36689
+ if (body[0] === "#") {
36690
+ const isHex = body[1] === "x" || body[1] === "X";
36691
+ const code = Number.parseInt(isHex ? body.slice(2) : body.slice(1), isHex ? 16 : 10);
36692
+ return codePointOrLiteral(code, literal2);
36693
+ }
36694
+ return NAMED_ENTITIES[body] ?? literal2;
36695
+ });
36696
+ }
36697
+ function parseAttributes(source) {
36698
+ const attrs = {};
36699
+ ATTRIBUTE_PATTERN.lastIndex = 0;
36700
+ let match;
36701
+ while ((match = ATTRIBUTE_PATTERN.exec(source)) !== null) {
36702
+ const raw = match[2] ?? match[3] ?? match[4] ?? "";
36703
+ attrs[match[1].toLowerCase()] = decodeEntities(raw);
36704
+ }
36705
+ return attrs;
36706
+ }
36707
+ function tokenize(input) {
36708
+ const tokens = [];
36709
+ let cursor = 0;
36710
+ let textStart = 0;
36711
+ const flushText = (end) => {
36712
+ if (end > textStart) tokens.push({ kind: "text", value: input.slice(textStart, end) });
36713
+ };
36714
+ while (cursor < input.length) {
36715
+ const lt = input.indexOf("<", cursor);
36716
+ if (lt === -1) break;
36717
+ if (input.startsWith("<![CDATA[", lt)) {
36718
+ const end = input.indexOf("]]>", lt + 9);
36719
+ if (end === -1) break;
36720
+ flushText(lt);
36721
+ tokens.push({ kind: "cdata", value: input.slice(lt + 9, end) });
36722
+ cursor = end + 3;
36723
+ textStart = cursor;
36724
+ continue;
36725
+ }
36726
+ if (input.startsWith("<!--", lt)) {
36727
+ const end = input.indexOf("-->", lt + 4);
36728
+ if (end === -1) break;
36729
+ flushText(lt);
36730
+ tokens.push({ kind: "comment" });
36731
+ cursor = end + 3;
36732
+ textStart = cursor;
36733
+ continue;
36734
+ }
36735
+ const gt = input.indexOf(">", lt + 1);
36736
+ if (gt === -1) break;
36737
+ const raw = input.slice(lt + 1, gt);
36738
+ if (!/^\/?[A-Za-z]/.test(raw)) {
36739
+ cursor = lt + 1;
36740
+ continue;
36741
+ }
36742
+ flushText(lt);
36743
+ if (raw[0] === "/") {
36744
+ tokens.push({ kind: "close", name: raw.slice(1).trim().toLowerCase() });
36745
+ } else {
36746
+ const selfClosing = raw.endsWith("/");
36747
+ const inner = selfClosing ? raw.slice(0, -1) : raw;
36748
+ const nameEnd = inner.search(/[\s/]/);
36749
+ const name = (nameEnd === -1 ? inner : inner.slice(0, nameEnd)).toLowerCase();
36750
+ const attrs = parseAttributes(nameEnd === -1 ? "" : inner.slice(nameEnd));
36751
+ tokens.push({ kind: selfClosing ? "selfclose" : "open", name, attrs });
36752
+ }
36753
+ cursor = gt + 1;
36754
+ textStart = cursor;
36755
+ }
36756
+ flushText(input.length);
36757
+ return tokens;
36758
+ }
36759
+ function buildTree(tokens) {
36760
+ const root = [];
36761
+ const stack = [];
36762
+ let suppressDepth = 0;
36763
+ const sink = () => stack.length > 0 ? stack[stack.length - 1].children : root;
36764
+ for (const token of tokens) {
36765
+ switch (token.kind) {
36766
+ case "comment":
36767
+ break;
36768
+ case "text":
36769
+ case "cdata":
36770
+ if (suppressDepth === 0) sink().push(token);
36771
+ break;
36772
+ case "open":
36773
+ case "selfclose": {
36774
+ const overDepth = stack.length >= MAX_STORAGE_DEPTH;
36775
+ if (suppressDepth === 0 && overDepth) {
36776
+ sink().push({ kind: "text", value: DEPTH_TRUNCATION_MARKER });
36777
+ }
36778
+ const suppressing = suppressDepth > 0 || overDepth;
36779
+ const isLeaf = token.kind === "selfclose" || VOID_TAGS.has(token.name);
36780
+ if (suppressing) {
36781
+ if (!isLeaf) {
36782
+ stack.push({ name: token.name, children: [], suppressing: true });
36783
+ suppressDepth++;
36784
+ }
36785
+ break;
36786
+ }
36787
+ const element = { kind: "element", name: token.name, attrs: token.attrs, children: [] };
36788
+ sink().push(element);
36789
+ if (!isLeaf) stack.push({ name: token.name, children: element.children, suppressing: false });
36790
+ break;
36791
+ }
36792
+ case "close": {
36793
+ let target = -1;
36794
+ for (let i = stack.length - 1; i >= 0; i--) {
36795
+ if (stack[i].name === token.name) {
36796
+ target = i;
36797
+ break;
36798
+ }
36799
+ }
36800
+ if (target === -1) break;
36801
+ while (stack.length > target) {
36802
+ const frame = stack.pop();
36803
+ if (frame?.suppressing) suppressDepth--;
36804
+ }
36805
+ break;
36806
+ }
36807
+ }
36808
+ }
36809
+ return root;
36810
+ }
36811
+ function isElement(node, name) {
36812
+ return node.kind === "element" && (name === void 0 || node.name === name);
36813
+ }
36814
+ function findChild(element, name) {
36815
+ return element.children.find((child) => isElement(child, name));
36816
+ }
36817
+ function rawText(nodes) {
36818
+ let result = "";
36819
+ for (const node of nodes) {
36820
+ if (node.kind === "element") result += rawText(node.children);
36821
+ else result += node.value;
36822
+ }
36823
+ return result;
36824
+ }
36825
+ function macroParameters(element) {
36826
+ const params = {};
36827
+ for (const child of element.children) {
36828
+ if (!isElement(child, "ac:parameter")) continue;
36829
+ const key = child.attrs["ac:name"];
36830
+ if (key) params[key] = rawText(child.children).trim();
36831
+ }
36832
+ return params;
36833
+ }
36834
+ function collectRows(nodes) {
36835
+ const rows = [];
36836
+ for (const node of nodes) {
36837
+ if (!isElement(node)) continue;
36838
+ if (node.name === "tr") rows.push(node);
36839
+ else if (node.name === "thead" || node.name === "tbody" || node.name === "tfoot") {
36840
+ rows.push(...collectRows(node.children));
36841
+ }
36842
+ }
36843
+ return rows;
36844
+ }
36845
+ function renderTable(nodes) {
36846
+ const rows = collectRows(nodes);
36847
+ if (rows.length === 0) return "";
36848
+ let result = "\n";
36849
+ let isFirstRow = true;
36850
+ for (const row of rows) {
36851
+ const cells = row.children.filter(
36852
+ (child) => isElement(child, "th") || isElement(child, "td")
36853
+ );
36854
+ const rendered = cells.map((cell) => renderNodes(cell.children).trim().replace(/\n+/g, " ").replace(/\|/g, "\\|"));
36855
+ result += "| " + rendered.join(" | ") + " |\n";
36856
+ if (isFirstRow) {
36857
+ result += "| " + cells.map(() => "---").join(" | ") + " |\n";
36858
+ isFirstRow = false;
36859
+ }
36860
+ }
36861
+ return result + "\n";
36862
+ }
36863
+ function renderMacro(element, listDepth) {
36864
+ const name = element.attrs["ac:name"] || "";
36865
+ const params = macroParameters(element);
36866
+ const richBody = findChild(element, "ac:rich-text-body");
36867
+ if (name === "code") {
36868
+ const plainBody = findChild(element, "ac:plain-text-body");
36869
+ const code = plainBody ? rawText(plainBody.children) : rawText(element.children);
36870
+ return `\`\`\`${params.language || ""}
36871
+ ${code.replace(/^\n+|\n+$/g, "")}
36872
+ \`\`\`
36873
+
36874
+ `;
36875
+ }
36876
+ if (PANEL_MACROS.has(name)) {
36877
+ const body = richBody ? renderNodes(richBody.children, listDepth, name).trim() : "";
36878
+ const block = `**${name.toUpperCase()}**${body ? `
36879
+ ${body}` : ""}`;
36880
+ return "> " + block.replace(/\n/g, "\n> ") + "\n\n";
36881
+ }
36882
+ if (name === "expand") {
36883
+ const body = richBody ? renderNodes(richBody.children, listDepth, name).trim() : "";
36884
+ return `**${params.title || "Details"}**
36885
+
36886
+ ${body ? `${body}
36887
+
36888
+ ` : ""}`;
36889
+ }
36890
+ if (name === "jira") {
36891
+ return params.key ? `\`${params.key}\`` : "[macro: jira]";
36892
+ }
36893
+ if (PLACEHOLDER_MACROS.has(name)) return `[macro: ${name}]`;
36894
+ return `[macro: ${name || "unknown"}]`;
36895
+ }
36896
+ function renderLink(element, listDepth) {
36897
+ const bodyElement = findChild(element, "ac:plain-text-link-body") ?? findChild(element, "ac:link-body");
36898
+ const bodyText = bodyElement ? renderNodes(bodyElement.children, listDepth, element.name).trim() : "";
36899
+ const page = findChild(element, "ri:page");
36900
+ if (page) return `[[${bodyText || page.attrs["ri:content-title"] || "page"}]]`;
36901
+ const attachment = findChild(element, "ri:attachment");
36902
+ if (attachment) return `[attachment: ${attachment.attrs["ri:filename"] || "unknown"}]`;
36903
+ const externalUrl = findChild(element, "ri:url");
36904
+ if (externalUrl) {
36905
+ const href = externalUrl.attrs["ri:value"] || "";
36906
+ return `[${bodyText || href}](${href})`;
36907
+ }
36908
+ if (findChild(element, "ri:user")) return "@user";
36909
+ return bodyText;
36910
+ }
36911
+ function renderTaskList(element, listDepth) {
36912
+ let result = "";
36913
+ for (const task of element.children) {
36914
+ if (!isElement(task, "ac:task")) continue;
36915
+ const status = findChild(task, "ac:task-status");
36916
+ const body = findChild(task, "ac:task-body");
36917
+ const marker = rawText(status?.children ?? []).trim() === "complete" ? "[x]" : "[ ]";
36918
+ const text = body ? renderNodes(body.children, listDepth, "ac:task").trim() : "";
36919
+ result += `- ${marker} ${text}
36920
+ `;
36921
+ }
36922
+ return result ? result + "\n" : "";
36923
+ }
36924
+ function renderNodes(nodes, listDepth = 0, parentType) {
36925
+ let result = "";
36926
+ for (const node of nodes) {
36927
+ if (node.kind === "cdata") {
36928
+ result += node.value;
36929
+ continue;
36930
+ }
36931
+ if (node.kind === "text") {
36932
+ result += decodeEntities(node.value);
36933
+ continue;
36934
+ }
36935
+ const children = node.children;
36936
+ switch (node.name) {
36937
+ case "h1":
36938
+ case "h2":
36939
+ case "h3":
36940
+ case "h4":
36941
+ case "h5":
36942
+ case "h6":
36943
+ result += "#".repeat(Number(node.name[1])) + " " + renderNodes(children, listDepth, node.name).trim() + "\n\n";
36944
+ break;
36945
+ case "p": {
36946
+ const text = renderNodes(children, listDepth, node.name);
36947
+ result += parentType === "li" ? text + "\n" : text + "\n\n";
36948
+ break;
36949
+ }
36950
+ case "strong":
36951
+ case "b":
36952
+ result += `**${renderNodes(children, listDepth, node.name)}**`;
36953
+ break;
36954
+ case "em":
36955
+ case "i":
36956
+ result += `*${renderNodes(children, listDepth, node.name)}*`;
36957
+ break;
36958
+ case "code":
36959
+ result += `\`${renderNodes(children, listDepth, node.name)}\``;
36960
+ break;
36961
+ case "s":
36962
+ case "strike":
36963
+ case "del":
36964
+ result += `~~${renderNodes(children, listDepth, node.name)}~~`;
36965
+ break;
36966
+ case "sup":
36967
+ result += `^${renderNodes(children, listDepth, node.name)}^`;
36968
+ break;
36969
+ case "sub":
36970
+ result += `~${renderNodes(children, listDepth, node.name)}~`;
36971
+ break;
36972
+ case "pre":
36973
+ result += `\`\`\`
36974
+ ${renderNodes(children, listDepth, node.name).trim()}
36975
+ \`\`\`
36976
+
36977
+ `;
36978
+ break;
36979
+ case "blockquote":
36980
+ result += "> " + renderNodes(children, listDepth, node.name).trim().replace(/\n/g, "\n> ") + "\n\n";
36981
+ break;
36982
+ case "hr":
36983
+ result += "---\n\n";
36984
+ break;
36985
+ case "br":
36986
+ result += "\n";
36987
+ break;
36988
+ case "a": {
36989
+ const text = renderNodes(children, listDepth, node.name);
36990
+ const href = node.attrs.href ?? "";
36991
+ result += href ? `[${text}](${href})` : text;
36992
+ break;
36993
+ }
36994
+ case "ul":
36995
+ case "ol": {
36996
+ const inner = renderNodes(children, listDepth + 1, node.name);
36997
+ if (parentType === "li") {
36998
+ if (result.length > 0 && !result.endsWith("\n")) result += "\n";
36999
+ result += inner;
37000
+ } else {
37001
+ result += inner;
37002
+ if (listDepth === 0) result += "\n";
37003
+ }
37004
+ break;
37005
+ }
37006
+ case "li": {
37007
+ const indent = " ".repeat(Math.max(0, listDepth - 1));
37008
+ const bullet = parentType === "ol" ? "1." : "-";
37009
+ result += `${indent}${bullet} ${renderNodes(children, listDepth, "li").trim()}
37010
+ `;
37011
+ break;
37012
+ }
37013
+ case "table":
37014
+ result += renderTable(children);
37015
+ break;
37016
+ case "ac:structured-macro":
37017
+ result += renderMacro(node, listDepth);
37018
+ break;
37019
+ case "ac:link":
37020
+ result += renderLink(node, listDepth);
37021
+ break;
37022
+ case "ac:image": {
37023
+ const attachment = findChild(node, "ri:attachment");
37024
+ const externalUrl = findChild(node, "ri:url");
37025
+ const label = attachment?.attrs["ri:filename"] ?? externalUrl?.attrs["ri:value"] ?? "unknown";
37026
+ const marker = `[image: ${label}]`;
37027
+ if (parentType === "p") {
37028
+ result += marker;
37029
+ } else {
37030
+ if (result.length > 0 && !result.endsWith("\n")) result += "\n";
37031
+ result += `${marker}
37032
+
37033
+ `;
37034
+ }
37035
+ break;
37036
+ }
37037
+ case "ac:task-list":
37038
+ result += renderTaskList(node, listDepth);
37039
+ break;
37040
+ case "ac:emoticon":
37041
+ result += `:${node.attrs["ac:name"] || "emoticon"}:`;
37042
+ break;
37043
+ default:
37044
+ result += renderNodes(children, listDepth, node.name);
37045
+ break;
37046
+ }
37047
+ }
37048
+ return result;
37049
+ }
37050
+ function extractPlainText(xhtml) {
37051
+ return decodeEntities(xhtml.replace(/<[^>]*>/g, " ")).replace(/\s+/g, " ").trim();
37052
+ }
37053
+ function storageToMarkdown(xhtml) {
37054
+ if (typeof xhtml !== "string" || xhtml.length === 0) return "";
37055
+ try {
37056
+ return renderNodes(buildTree(tokenize(xhtml))).trim();
37057
+ } catch {
37058
+ return extractPlainText(xhtml);
37059
+ }
36597
37060
  }
36598
37061
 
36599
37062
  // src/mcp/integration.ts
37063
+ var LARGE_PAYLOAD_THRESHOLD = 5e4;
36600
37064
  var BitbucketPrSchema = external_exports.object({
36601
37065
  id: external_exports.number(),
36602
37066
  title: external_exports.string(),
@@ -36634,19 +37098,143 @@ var JiraTicketSchema = external_exports.object({
36634
37098
  errorMessages: external_exports.array(external_exports.string()).optional(),
36635
37099
  fields: JiraFieldsSchema
36636
37100
  });
37101
+ var ConfluencePageSchema = external_exports.object({
37102
+ id: external_exports.string(),
37103
+ title: external_exports.string(),
37104
+ status: external_exports.string().optional(),
37105
+ spaceId: external_exports.string().optional(),
37106
+ version: external_exports.object({
37107
+ number: external_exports.number().optional(),
37108
+ createdAt: external_exports.string().optional(),
37109
+ message: external_exports.string().optional(),
37110
+ minorEdit: external_exports.boolean().optional(),
37111
+ authorId: external_exports.string().optional()
37112
+ }).optional(),
37113
+ body: external_exports.object({
37114
+ storage: external_exports.object({ value: external_exports.string().optional() }).passthrough().optional()
37115
+ }).passthrough().optional(),
37116
+ labels: external_exports.object({ results: external_exports.array(external_exports.object({ name: external_exports.string() }).passthrough()).optional() }).passthrough().optional(),
37117
+ _links: external_exports.object({ base: external_exports.string().optional(), webui: external_exports.string().optional() }).passthrough().optional()
37118
+ });
36637
37119
  function buildBasicAuth(emailVar, tokenVar) {
36638
37120
  const email2 = getCredential(emailVar);
36639
37121
  const token = getCredential(tokenVar);
36640
37122
  if (!email2 || !token) throw new Error(`Missing ${emailVar} or ${tokenVar}`);
36641
37123
  return "Basic " + Buffer.from(`${email2}:${token}`).toString("base64");
36642
37124
  }
37125
+ var PRODUCT_TOKEN_KEY = {
37126
+ jira: "JIRA_API_TOKEN",
37127
+ confluence: "CONFLUENCE_API_TOKEN"
37128
+ };
37129
+ function buildAtlassianContext(product) {
37130
+ const cloudId = getCredential("ATLASSIAN_CLOUD_ID");
37131
+ if (!cloudId) throw new Error("Missing ATLASSIAN_CLOUD_ID");
37132
+ return { auth: buildBasicAuth("ATLASSIAN_USER_EMAIL", PRODUCT_TOKEN_KEY[product]), cloudId };
37133
+ }
36643
37134
  async function callRestApi(url, auth, accept = "application/json") {
36644
37135
  const resp = await fetch(url, { headers: { Authorization: auth, Accept: accept } });
36645
37136
  if (resp.status === 401) throw new Error(`\u274C Auth failed (401): ${url}`);
37137
+ if (resp.status === 403)
37138
+ throw new Error(`\u274C Access denied (403): ${url}
37139
+
37140
+ You lack permission for this resource, or it is restricted.`);
36646
37141
  if (resp.status === 404) throw new Error(`\u274C Not found: ${url}`);
36647
37142
  if (!resp.ok) throw new Error(`\u274C API error ${resp.status}: ${await resp.text()}`);
36648
37143
  return accept === "text/plain" ? resp.text() : resp.json();
36649
37144
  }
37145
+ var CONFLUENCE_INPUT_FORMS = [
37146
+ "Accepted input forms:",
37147
+ " \u2022 https://<site>.atlassian.net/wiki/spaces/<SPACEKEY>/pages/<pageId>/<Title>",
37148
+ " \u2022 https://<site>.atlassian.net/pages/viewpage.action?pageId=<pageId>",
37149
+ " \u2022 a bare numeric page ID (e.g. 123456789)"
37150
+ ].join("\n");
37151
+ function resolveConfluencePageId(input) {
37152
+ const trimmed = input.trim();
37153
+ if (!trimmed) return { kind: "unknown" };
37154
+ if (/\/blog(?:posts?)?\//.test(trimmed)) return { kind: "blog" };
37155
+ if (/\/wiki\/x\/[A-Za-z0-9]+/.test(trimmed)) return { kind: "tiny" };
37156
+ const spacesPageMatch = trimmed.match(/\/wiki\/spaces\/[^/]+\/pages\/(\d+)(?:[/?#]|$)/);
37157
+ if (spacesPageMatch) return { kind: "id", pageId: spacesPageMatch[1] };
37158
+ const queryMatch = trimmed.match(/[?&]pageId=(\d+)(?:[&#]|$)/);
37159
+ if (queryMatch) return { kind: "id", pageId: queryMatch[1] };
37160
+ if (/^\d+$/.test(trimmed)) return { kind: "id", pageId: trimmed };
37161
+ return { kind: "unknown" };
37162
+ }
37163
+ function buildConfluenceHeader(page, absoluteUrl) {
37164
+ const webui = page._links?.webui ?? "";
37165
+ const spaceKey = webui.match(/\/spaces\/([^/]+)\//)?.[1];
37166
+ const lines = [`## \u{1F4C4} ${page.title}`, "", `**Status:** ${page.status || "Unknown"}`];
37167
+ if (spaceKey) lines.push(`**Space:** ${spaceKey}`);
37168
+ lines.push(`**Version:** ${page.version?.number ?? "Unknown"}`);
37169
+ lines.push(`**Last updated:** ${page.version?.createdAt || "Unknown"}`);
37170
+ lines.push(`**URL:** ${absoluteUrl || "Unknown"}`);
37171
+ return lines.join("\n");
37172
+ }
37173
+ async function handleConfluenceGetPage(args) {
37174
+ try {
37175
+ const resolution = resolveConfluencePageId(args.input);
37176
+ if (resolution.kind === "tiny") {
37177
+ return mcpText(
37178
+ `\u274C Confluence tiny links cannot be resolved without following a redirect.
37179
+
37180
+ Open the link in a browser and pass the full page URL instead.
37181
+
37182
+ ${CONFLUENCE_INPUT_FORMS}`
37183
+ );
37184
+ }
37185
+ if (resolution.kind === "blog") {
37186
+ return mcpText(
37187
+ `\u274C Confluence blog posts are not supported \u2014 they live on a different endpoint than pages.
37188
+
37189
+ ${CONFLUENCE_INPUT_FORMS}`
37190
+ );
37191
+ }
37192
+ if (resolution.kind === "unknown") {
37193
+ return mcpText(`\u274C Could not extract a Confluence page ID from: ${args.input}
37194
+
37195
+ ${CONFLUENCE_INPUT_FORMS}`);
37196
+ }
37197
+ const { auth, cloudId } = buildAtlassianContext("confluence");
37198
+ const url = `https://api.atlassian.com/ex/confluence/${cloudId}/wiki/api/v2/pages/${resolution.pageId}?body-format=storage&include-labels=true&include-version=true`;
37199
+ const jsonData = await callRestApi(url, auth);
37200
+ const parseResult = ConfluencePageSchema.safeParse(jsonData);
37201
+ if (!parseResult.success) {
37202
+ return mcpText(`\u274C Invalid Confluence response format: ${parseResult.error.message}`);
37203
+ }
37204
+ const page = parseResult.data;
37205
+ const base = page._links?.base ?? "";
37206
+ const webui = page._links?.webui ?? "";
37207
+ const absoluteUrl = base && webui ? `${base}${webui}` : base || webui;
37208
+ const markdown = storageToMarkdown(page.body?.storage?.value);
37209
+ let contentSection;
37210
+ if (!markdown.trim()) {
37211
+ contentSection = `\u26A0\uFE0F Confluence returned no readable body for this page (status: ${page.status || "Unknown"}). Open ${absoluteUrl || "the page in Confluence"} to view it directly.`;
37212
+ } else if (markdown.length >= LARGE_PAYLOAD_THRESHOLD) {
37213
+ const filePath = `/tmp/kit-confluence-${resolution.pageId}-${Date.now()}.md`;
37214
+ try {
37215
+ writeFileSync4(filePath, sanitizeOutput(markdown), "utf8");
37216
+ contentSection = `Content is large (${markdown.length} chars). Full markdown written to: \`${filePath}\`. Read this file before proceeding.`;
37217
+ } catch {
37218
+ contentSection = `\u26A0\uFE0F Could not write page content to a temp file. Showing inline (may be very large).
37219
+
37220
+ ${markdown}`;
37221
+ }
37222
+ } else {
37223
+ contentSection = markdown;
37224
+ }
37225
+ const labels = page.labels?.results?.map((label) => label.name).filter((name) => name.length > 0) ?? [];
37226
+ const output = `${buildConfluenceHeader(page, absoluteUrl)}
37227
+
37228
+ ### Content
37229
+ ${contentSection}
37230
+
37231
+ ### Labels
37232
+ ${labels.length > 0 ? labels.join(", ") : "None"}`;
37233
+ return mcpText(sanitizeOutput(output));
37234
+ } catch (error2) {
37235
+ return mcpText(`Error: ${error2 instanceof Error ? error2.message : String(error2)}`);
37236
+ }
37237
+ }
36650
37238
  function registerIntegrationTools(server2) {
36651
37239
  server2.registerTool(
36652
37240
  "kit_get_bitbucket_pr",
@@ -36703,8 +37291,7 @@ ${pr.description || "No description"}`;
36703
37291
  if (includeDiff) {
36704
37292
  const diffUrl = `https://api.bitbucket.org/2.0/repositories/${safeWs}/${safeRepo}/pullrequests/${prId}/diff`;
36705
37293
  const diff = await callRestApi(diffUrl, auth, "text/plain");
36706
- const DIFF_FILE_THRESHOLD = 5e4;
36707
- if (diff.length < DIFF_FILE_THRESHOLD) {
37294
+ if (diff.length < LARGE_PAYLOAD_THRESHOLD) {
36708
37295
  output += `
36709
37296
 
36710
37297
  ### Diff
@@ -36754,9 +37341,7 @@ ${diff}
36754
37341
 
36755
37342
  Expected format: PROJ-123`);
36756
37343
  }
36757
- const cloudId = getCredential("ATLASSIAN_CLOUD_ID");
36758
- if (!cloudId) throw new Error("Missing ATLASSIAN_CLOUD_ID");
36759
- const auth = buildBasicAuth("ATLASSIAN_USER_EMAIL", "ATLASSIAN_API_TOKEN");
37344
+ const { auth, cloudId } = buildAtlassianContext("jira");
36760
37345
  const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${safeTicketId}`;
36761
37346
  const jsonData = await callRestApi(url, auth);
36762
37347
  const parseResult = JiraTicketSchema.safeParse(jsonData);
@@ -36788,6 +37373,18 @@ ${ticket.fields.labels?.join(", ") || "None"}`;
36788
37373
  }
36789
37374
  }
36790
37375
  );
37376
+ server2.registerTool(
37377
+ "kit_confluence_get_page",
37378
+ {
37379
+ title: "Get Confluence Page",
37380
+ description: "Get a Confluence page as markdown using the Atlassian REST API. Accepts a full Confluence page URL or a numeric page ID.",
37381
+ inputSchema: {
37382
+ input: external_exports.string().describe("Confluence page URL or numeric page ID")
37383
+ },
37384
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true }
37385
+ },
37386
+ async ({ input }) => handleConfluenceGetPage({ input })
37387
+ );
36791
37388
  }
36792
37389
 
36793
37390
  // src/mcp/memory.ts
@@ -37811,26 +38408,26 @@ var DigestModelRegistryError = class extends Error {
37811
38408
  var DIGEST_MODEL_REGISTRY = {
37812
38409
  ["tiny" /* TINY */]: {
37813
38410
  id: "tiny" /* TINY */,
37814
- ggufUri: "hf:bartowski/Qwen2.5-0.5B-Instruct-GGUF/Qwen2.5-0.5B-Instruct-Q4_K_M.gguf",
37815
- approxSizeBytes: 4e8,
38411
+ ggufUri: "hf:lmstudio-community/Qwen3.5-0.8B-GGUF/Qwen3.5-0.8B-Q4_K_M.gguf",
38412
+ approxSizeBytes: 528e6,
37816
38413
  license: "Apache-2.0",
37817
- sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-0.5B-Instruct-GGUF",
38414
+ sourceUrl: "https://huggingface.co/lmstudio-community/Qwen3.5-0.8B-GGUF",
37818
38415
  enabled: true
37819
38416
  },
37820
38417
  ["base" /* BASE */]: {
37821
38418
  id: "base" /* BASE */,
37822
- ggufUri: "hf:bartowski/Qwen2.5-1.5B-Instruct-GGUF/Qwen2.5-1.5B-Instruct-Q4_K_M.gguf",
37823
- approxSizeBytes: 1e9,
38419
+ ggufUri: "hf:lmstudio-community/Qwen3.5-2B-GGUF/Qwen3.5-2B-Q4_K_M.gguf",
38420
+ approxSizeBytes: 127e7,
37824
38421
  license: "Apache-2.0",
37825
- sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-1.5B-Instruct-GGUF",
38422
+ sourceUrl: "https://huggingface.co/lmstudio-community/Qwen3.5-2B-GGUF",
37826
38423
  enabled: true
37827
38424
  },
37828
38425
  ["large" /* LARGE */]: {
37829
38426
  id: "large" /* LARGE */,
37830
- ggufUri: "hf:bartowski/Qwen2.5-3B-Instruct-GGUF/Qwen2.5-3B-Instruct-Q4_K_M.gguf",
37831
- approxSizeBytes: 19e8,
38427
+ ggufUri: "hf:lmstudio-community/Qwen3.5-4B-GGUF/Qwen3.5-4B-Q4_K_M.gguf",
38428
+ approxSizeBytes: 271e7,
37832
38429
  license: "Apache-2.0",
37833
- sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-3B-Instruct-GGUF",
38430
+ sourceUrl: "https://huggingface.co/lmstudio-community/Qwen3.5-4B-GGUF",
37834
38431
  enabled: true
37835
38432
  }
37836
38433
  };
@@ -37948,7 +38545,8 @@ async function createLlamaLocalDigestProvider(modelId) {
37948
38545
  const response = await withTimeout(
37949
38546
  session.prompt(userContent, {
37950
38547
  maxTokens: LLAMA_MAX_GENERATED_TOKENS,
37951
- temperature: LLAMA_TEMPERATURE
38548
+ temperature: LLAMA_TEMPERATURE,
38549
+ budgets: { thoughtTokens: 0 }
37952
38550
  }),
37953
38551
  options.timeoutMs,
37954
38552
  () => new LlamaLocalDigestProviderError(`Llama provider timed out after ${options.timeoutMs}ms`)