diff --git a/_pagefind/fragment/en_11642b7.pf_fragment b/_pagefind/fragment/en_11642b7.pf_fragment new file mode 100644 index 00000000..c88360cb Binary files /dev/null and b/_pagefind/fragment/en_11642b7.pf_fragment differ diff --git a/_pagefind/fragment/en_16181a0.pf_fragment b/_pagefind/fragment/en_16181a0.pf_fragment new file mode 100644 index 00000000..9f9e3bf7 Binary files /dev/null and b/_pagefind/fragment/en_16181a0.pf_fragment differ diff --git a/_pagefind/fragment/en_1c9bfe8.pf_fragment b/_pagefind/fragment/en_1c9bfe8.pf_fragment new file mode 100644 index 00000000..c7496c29 Binary files /dev/null and b/_pagefind/fragment/en_1c9bfe8.pf_fragment differ diff --git a/_pagefind/fragment/en_236cc3c.pf_fragment b/_pagefind/fragment/en_236cc3c.pf_fragment new file mode 100644 index 00000000..255c507e Binary files /dev/null and b/_pagefind/fragment/en_236cc3c.pf_fragment differ diff --git a/_pagefind/fragment/en_2c38f2a.pf_fragment b/_pagefind/fragment/en_2c38f2a.pf_fragment new file mode 100644 index 00000000..60ace0c8 Binary files /dev/null and b/_pagefind/fragment/en_2c38f2a.pf_fragment differ diff --git a/_pagefind/fragment/en_2d586b8.pf_fragment b/_pagefind/fragment/en_2d586b8.pf_fragment new file mode 100644 index 00000000..2f879f20 Binary files /dev/null and b/_pagefind/fragment/en_2d586b8.pf_fragment differ diff --git a/_pagefind/fragment/en_3d997be.pf_fragment b/_pagefind/fragment/en_3d997be.pf_fragment new file mode 100644 index 00000000..ebcbfd2b Binary files /dev/null and b/_pagefind/fragment/en_3d997be.pf_fragment differ diff --git a/_pagefind/fragment/en_44458e8.pf_fragment b/_pagefind/fragment/en_44458e8.pf_fragment new file mode 100644 index 00000000..dc0ec666 Binary files /dev/null and b/_pagefind/fragment/en_44458e8.pf_fragment differ diff --git a/_pagefind/fragment/en_5bb96db.pf_fragment b/_pagefind/fragment/en_5bb96db.pf_fragment new file mode 100644 index 00000000..96219559 Binary files /dev/null and b/_pagefind/fragment/en_5bb96db.pf_fragment differ diff --git a/_pagefind/fragment/en_5eb7564.pf_fragment b/_pagefind/fragment/en_5eb7564.pf_fragment new file mode 100644 index 00000000..7c4f37f8 Binary files /dev/null and b/_pagefind/fragment/en_5eb7564.pf_fragment differ diff --git a/_pagefind/fragment/en_6b1fb6d.pf_fragment b/_pagefind/fragment/en_6b1fb6d.pf_fragment new file mode 100644 index 00000000..cdff7042 Binary files /dev/null and b/_pagefind/fragment/en_6b1fb6d.pf_fragment differ diff --git a/_pagefind/fragment/en_80d31f1.pf_fragment b/_pagefind/fragment/en_80d31f1.pf_fragment new file mode 100644 index 00000000..921729f0 Binary files /dev/null and b/_pagefind/fragment/en_80d31f1.pf_fragment differ diff --git a/_pagefind/fragment/en_95479f6.pf_fragment b/_pagefind/fragment/en_95479f6.pf_fragment new file mode 100644 index 00000000..386ad4c4 Binary files /dev/null and b/_pagefind/fragment/en_95479f6.pf_fragment differ diff --git a/_pagefind/fragment/en_bf49bfb.pf_fragment b/_pagefind/fragment/en_bf49bfb.pf_fragment new file mode 100644 index 00000000..cf5420f0 Binary files /dev/null and b/_pagefind/fragment/en_bf49bfb.pf_fragment differ diff --git a/_pagefind/fragment/en_c9220e3.pf_fragment b/_pagefind/fragment/en_c9220e3.pf_fragment new file mode 100644 index 00000000..8e4aef2f Binary files /dev/null and b/_pagefind/fragment/en_c9220e3.pf_fragment differ diff --git a/_pagefind/fragment/en_c927f3f.pf_fragment b/_pagefind/fragment/en_c927f3f.pf_fragment new file mode 100644 index 00000000..9bfe4931 Binary files /dev/null and b/_pagefind/fragment/en_c927f3f.pf_fragment differ diff --git a/_pagefind/fragment/en_d67b2ae.pf_fragment b/_pagefind/fragment/en_d67b2ae.pf_fragment new file mode 100644 index 00000000..87a283d8 Binary files /dev/null and b/_pagefind/fragment/en_d67b2ae.pf_fragment differ diff --git a/_pagefind/fragment/en_e58e25a.pf_fragment b/_pagefind/fragment/en_e58e25a.pf_fragment new file mode 100644 index 00000000..831fded6 Binary files /dev/null and b/_pagefind/fragment/en_e58e25a.pf_fragment differ diff --git a/_pagefind/fragment/en_ea3bc5f.pf_fragment b/_pagefind/fragment/en_ea3bc5f.pf_fragment new file mode 100644 index 00000000..44b8571b Binary files /dev/null and b/_pagefind/fragment/en_ea3bc5f.pf_fragment differ diff --git a/_pagefind/index/en_fa2211e.pf_index b/_pagefind/index/en_fa2211e.pf_index new file mode 100644 index 00000000..2b3f1042 Binary files /dev/null and b/_pagefind/index/en_fa2211e.pf_index differ diff --git a/_pagefind/pagefind-entry.json b/_pagefind/pagefind-entry.json new file mode 100644 index 00000000..5906a762 --- /dev/null +++ b/_pagefind/pagefind-entry.json @@ -0,0 +1 @@ +{"version":"1.4.0","languages":{"en":{"hash":"en_3a80c79c47","wasm":"en","page_count":19}},"include_characters":["_","‿","⁀","⁔","︳","︴","﹍","﹎","﹏","_"]} \ No newline at end of file diff --git a/_pagefind/pagefind-highlight.js b/_pagefind/pagefind-highlight.js new file mode 100644 index 00000000..b8189558 --- /dev/null +++ b/_pagefind/pagefind-highlight.js @@ -0,0 +1,1064 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/mark.js/dist/mark.js +var require_mark = __commonJS({ + "node_modules/mark.js/dist/mark.js"(exports, module) { + (function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.Mark = factory(); + })(exports, (function() { + "use strict"; + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { + return typeof obj; + } : function(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + var classCallCheck = function(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + var createClass = /* @__PURE__ */ (function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + })(); + var _extends = Object.assign || function(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + var DOMIterator = (function() { + function DOMIterator2(ctx) { + var iframes = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true; + var exclude = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : []; + var iframesTimeout = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 5e3; + classCallCheck(this, DOMIterator2); + this.ctx = ctx; + this.iframes = iframes; + this.exclude = exclude; + this.iframesTimeout = iframesTimeout; + } + createClass(DOMIterator2, [{ + key: "getContexts", + value: function getContexts() { + var ctx = void 0, filteredCtx = []; + if (typeof this.ctx === "undefined" || !this.ctx) { + ctx = []; + } else if (NodeList.prototype.isPrototypeOf(this.ctx)) { + ctx = Array.prototype.slice.call(this.ctx); + } else if (Array.isArray(this.ctx)) { + ctx = this.ctx; + } else if (typeof this.ctx === "string") { + ctx = Array.prototype.slice.call(document.querySelectorAll(this.ctx)); + } else { + ctx = [this.ctx]; + } + ctx.forEach(function(ctx2) { + var isDescendant = filteredCtx.filter(function(contexts) { + return contexts.contains(ctx2); + }).length > 0; + if (filteredCtx.indexOf(ctx2) === -1 && !isDescendant) { + filteredCtx.push(ctx2); + } + }); + return filteredCtx; + } + }, { + key: "getIframeContents", + value: function getIframeContents(ifr, successFn) { + var errorFn = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : function() { + }; + var doc = void 0; + try { + var ifrWin = ifr.contentWindow; + doc = ifrWin.document; + if (!ifrWin || !doc) { + throw new Error("iframe inaccessible"); + } + } catch (e) { + errorFn(); + } + if (doc) { + successFn(doc); + } + } + }, { + key: "isIframeBlank", + value: function isIframeBlank(ifr) { + var bl = "about:blank", src = ifr.getAttribute("src").trim(), href = ifr.contentWindow.location.href; + return href === bl && src !== bl && src; + } + }, { + key: "observeIframeLoad", + value: function observeIframeLoad(ifr, successFn, errorFn) { + var _this = this; + var called = false, tout = null; + var listener = function listener2() { + if (called) { + return; + } + called = true; + clearTimeout(tout); + try { + if (!_this.isIframeBlank(ifr)) { + ifr.removeEventListener("load", listener2); + _this.getIframeContents(ifr, successFn, errorFn); + } + } catch (e) { + errorFn(); + } + }; + ifr.addEventListener("load", listener); + tout = setTimeout(listener, this.iframesTimeout); + } + }, { + key: "onIframeReady", + value: function onIframeReady(ifr, successFn, errorFn) { + try { + if (ifr.contentWindow.document.readyState === "complete") { + if (this.isIframeBlank(ifr)) { + this.observeIframeLoad(ifr, successFn, errorFn); + } else { + this.getIframeContents(ifr, successFn, errorFn); + } + } else { + this.observeIframeLoad(ifr, successFn, errorFn); + } + } catch (e) { + errorFn(); + } + } + }, { + key: "waitForIframes", + value: function waitForIframes(ctx, done) { + var _this2 = this; + var eachCalled = 0; + this.forEachIframe(ctx, function() { + return true; + }, function(ifr) { + eachCalled++; + _this2.waitForIframes(ifr.querySelector("html"), function() { + if (!--eachCalled) { + done(); + } + }); + }, function(handled) { + if (!handled) { + done(); + } + }); + } + }, { + key: "forEachIframe", + value: function forEachIframe(ctx, filter, each) { + var _this3 = this; + var end = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : function() { + }; + var ifr = ctx.querySelectorAll("iframe"), open = ifr.length, handled = 0; + ifr = Array.prototype.slice.call(ifr); + var checkEnd = function checkEnd2() { + if (--open <= 0) { + end(handled); + } + }; + if (!open) { + checkEnd(); + } + ifr.forEach(function(ifr2) { + if (DOMIterator2.matches(ifr2, _this3.exclude)) { + checkEnd(); + } else { + _this3.onIframeReady(ifr2, function(con) { + if (filter(ifr2)) { + handled++; + each(con); + } + checkEnd(); + }, checkEnd); + } + }); + } + }, { + key: "createIterator", + value: function createIterator(ctx, whatToShow, filter) { + return document.createNodeIterator(ctx, whatToShow, filter, false); + } + }, { + key: "createInstanceOnIframe", + value: function createInstanceOnIframe(contents) { + return new DOMIterator2(contents.querySelector("html"), this.iframes); + } + }, { + key: "compareNodeIframe", + value: function compareNodeIframe(node, prevNode, ifr) { + var compCurr = node.compareDocumentPosition(ifr), prev = Node.DOCUMENT_POSITION_PRECEDING; + if (compCurr & prev) { + if (prevNode !== null) { + var compPrev = prevNode.compareDocumentPosition(ifr), after = Node.DOCUMENT_POSITION_FOLLOWING; + if (compPrev & after) { + return true; + } + } else { + return true; + } + } + return false; + } + }, { + key: "getIteratorNode", + value: function getIteratorNode(itr) { + var prevNode = itr.previousNode(); + var node = void 0; + if (prevNode === null) { + node = itr.nextNode(); + } else { + node = itr.nextNode() && itr.nextNode(); + } + return { + prevNode, + node + }; + } + }, { + key: "checkIframeFilter", + value: function checkIframeFilter(node, prevNode, currIfr, ifr) { + var key = false, handled = false; + ifr.forEach(function(ifrDict, i) { + if (ifrDict.val === currIfr) { + key = i; + handled = ifrDict.handled; + } + }); + if (this.compareNodeIframe(node, prevNode, currIfr)) { + if (key === false && !handled) { + ifr.push({ + val: currIfr, + handled: true + }); + } else if (key !== false && !handled) { + ifr[key].handled = true; + } + return true; + } + if (key === false) { + ifr.push({ + val: currIfr, + handled: false + }); + } + return false; + } + }, { + key: "handleOpenIframes", + value: function handleOpenIframes(ifr, whatToShow, eCb, fCb) { + var _this4 = this; + ifr.forEach(function(ifrDict) { + if (!ifrDict.handled) { + _this4.getIframeContents(ifrDict.val, function(con) { + _this4.createInstanceOnIframe(con).forEachNode(whatToShow, eCb, fCb); + }); + } + }); + } + }, { + key: "iterateThroughNodes", + value: function iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) { + var _this5 = this; + var itr = this.createIterator(ctx, whatToShow, filterCb); + var ifr = [], elements = [], node = void 0, prevNode = void 0, retrieveNodes = function retrieveNodes2() { + var _getIteratorNode = _this5.getIteratorNode(itr); + prevNode = _getIteratorNode.prevNode; + node = _getIteratorNode.node; + return node; + }; + while (retrieveNodes()) { + if (this.iframes) { + this.forEachIframe(ctx, function(currIfr) { + return _this5.checkIframeFilter(node, prevNode, currIfr, ifr); + }, function(con) { + _this5.createInstanceOnIframe(con).forEachNode(whatToShow, function(ifrNode) { + return elements.push(ifrNode); + }, filterCb); + }); + } + elements.push(node); + } + elements.forEach(function(node2) { + eachCb(node2); + }); + if (this.iframes) { + this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb); + } + doneCb(); + } + }, { + key: "forEachNode", + value: function forEachNode(whatToShow, each, filter) { + var _this6 = this; + var done = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : function() { + }; + var contexts = this.getContexts(); + var open = contexts.length; + if (!open) { + done(); + } + contexts.forEach(function(ctx) { + var ready = function ready2() { + _this6.iterateThroughNodes(whatToShow, ctx, each, filter, function() { + if (--open <= 0) { + done(); + } + }); + }; + if (_this6.iframes) { + _this6.waitForIframes(ctx, ready); + } else { + ready(); + } + }); + } + }], [{ + key: "matches", + value: function matches(element, selector) { + var selectors = typeof selector === "string" ? [selector] : selector, fn = element.matches || element.matchesSelector || element.msMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector; + if (fn) { + var match = false; + selectors.every(function(sel) { + if (fn.call(element, sel)) { + match = true; + return false; + } + return true; + }); + return match; + } else { + return false; + } + } + }]); + return DOMIterator2; + })(); + var Mark$1 = (function() { + function Mark3(ctx) { + classCallCheck(this, Mark3); + this.ctx = ctx; + this.ie = false; + var ua = window.navigator.userAgent; + if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) { + this.ie = true; + } + } + createClass(Mark3, [{ + key: "log", + value: function log(msg) { + var level = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "debug"; + var log2 = this.opt.log; + if (!this.opt.debug) { + return; + } + if ((typeof log2 === "undefined" ? "undefined" : _typeof(log2)) === "object" && typeof log2[level] === "function") { + log2[level]("mark.js: " + msg); + } + } + }, { + key: "escapeStr", + value: function escapeStr(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + }, { + key: "createRegExp", + value: function createRegExp(str) { + if (this.opt.wildcards !== "disabled") { + str = this.setupWildcardsRegExp(str); + } + str = this.escapeStr(str); + if (Object.keys(this.opt.synonyms).length) { + str = this.createSynonymsRegExp(str); + } + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.setupIgnoreJoinersRegExp(str); + } + if (this.opt.diacritics) { + str = this.createDiacriticsRegExp(str); + } + str = this.createMergedBlanksRegExp(str); + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.createJoinersRegExp(str); + } + if (this.opt.wildcards !== "disabled") { + str = this.createWildcardsRegExp(str); + } + str = this.createAccuracyRegExp(str); + return str; + } + }, { + key: "createSynonymsRegExp", + value: function createSynonymsRegExp(str) { + var syn = this.opt.synonyms, sens = this.opt.caseSensitive ? "" : "i", joinerPlaceholder = this.opt.ignoreJoiners || this.opt.ignorePunctuation.length ? "\0" : ""; + for (var index in syn) { + if (syn.hasOwnProperty(index)) { + var value = syn[index], k1 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(index) : this.escapeStr(index), k2 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(value) : this.escapeStr(value); + if (k1 !== "" && k2 !== "") { + str = str.replace(new RegExp("(" + this.escapeStr(k1) + "|" + this.escapeStr(k2) + ")", "gm" + sens), joinerPlaceholder + ("(" + this.processSynomyms(k1) + "|") + (this.processSynomyms(k2) + ")") + joinerPlaceholder); + } + } + } + return str; + } + }, { + key: "processSynomyms", + value: function processSynomyms(str) { + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.setupIgnoreJoinersRegExp(str); + } + return str; + } + }, { + key: "setupWildcardsRegExp", + value: function setupWildcardsRegExp(str) { + str = str.replace(/(?:\\)*\?/g, function(val) { + return val.charAt(0) === "\\" ? "?" : ""; + }); + return str.replace(/(?:\\)*\*/g, function(val) { + return val.charAt(0) === "\\" ? "*" : ""; + }); + } + }, { + key: "createWildcardsRegExp", + value: function createWildcardsRegExp(str) { + var spaces = this.opt.wildcards === "withSpaces"; + return str.replace(/\u0001/g, spaces ? "[\\S\\s]?" : "\\S?").replace(/\u0002/g, spaces ? "[\\S\\s]*?" : "\\S*"); + } + }, { + key: "setupIgnoreJoinersRegExp", + value: function setupIgnoreJoinersRegExp(str) { + return str.replace(/[^(|)\\]/g, function(val, indx, original) { + var nextChar = original.charAt(indx + 1); + if (/[(|)\\]/.test(nextChar) || nextChar === "") { + return val; + } else { + return val + "\0"; + } + }); + } + }, { + key: "createJoinersRegExp", + value: function createJoinersRegExp(str) { + var joiner = []; + var ignorePunctuation = this.opt.ignorePunctuation; + if (Array.isArray(ignorePunctuation) && ignorePunctuation.length) { + joiner.push(this.escapeStr(ignorePunctuation.join(""))); + } + if (this.opt.ignoreJoiners) { + joiner.push("\\u00ad\\u200b\\u200c\\u200d"); + } + return joiner.length ? str.split(/\u0000+/).join("[" + joiner.join("") + "]*") : str; + } + }, { + key: "createDiacriticsRegExp", + value: function createDiacriticsRegExp(str) { + var sens = this.opt.caseSensitive ? "" : "i", dct = this.opt.caseSensitive ? ["a\xE0\xE1\u1EA3\xE3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xE2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xE4\xE5\u0101\u0105", "A\xC0\xC1\u1EA2\xC3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xC2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xC4\xC5\u0100\u0104", "c\xE7\u0107\u010D", "C\xC7\u0106\u010C", "d\u0111\u010F", "D\u0110\u010E", "e\xE8\xE9\u1EBB\u1EBD\u1EB9\xEA\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xEB\u011B\u0113\u0119", "E\xC8\xC9\u1EBA\u1EBC\u1EB8\xCA\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xCB\u011A\u0112\u0118", "i\xEC\xED\u1EC9\u0129\u1ECB\xEE\xEF\u012B", "I\xCC\xCD\u1EC8\u0128\u1ECA\xCE\xCF\u012A", "l\u0142", "L\u0141", "n\xF1\u0148\u0144", "N\xD1\u0147\u0143", "o\xF2\xF3\u1ECF\xF5\u1ECD\xF4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xF6\xF8\u014D", "O\xD2\xD3\u1ECE\xD5\u1ECC\xD4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xD6\xD8\u014C", "r\u0159", "R\u0158", "s\u0161\u015B\u0219\u015F", "S\u0160\u015A\u0218\u015E", "t\u0165\u021B\u0163", "T\u0164\u021A\u0162", "u\xF9\xFA\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xFB\xFC\u016F\u016B", "U\xD9\xDA\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xDB\xDC\u016E\u016A", "y\xFD\u1EF3\u1EF7\u1EF9\u1EF5\xFF", "Y\xDD\u1EF2\u1EF6\u1EF8\u1EF4\u0178", "z\u017E\u017C\u017A", "Z\u017D\u017B\u0179"] : ["a\xE0\xE1\u1EA3\xE3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xE2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xE4\xE5\u0101\u0105A\xC0\xC1\u1EA2\xC3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xC2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xC4\xC5\u0100\u0104", "c\xE7\u0107\u010DC\xC7\u0106\u010C", "d\u0111\u010FD\u0110\u010E", "e\xE8\xE9\u1EBB\u1EBD\u1EB9\xEA\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xEB\u011B\u0113\u0119E\xC8\xC9\u1EBA\u1EBC\u1EB8\xCA\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xCB\u011A\u0112\u0118", "i\xEC\xED\u1EC9\u0129\u1ECB\xEE\xEF\u012BI\xCC\xCD\u1EC8\u0128\u1ECA\xCE\xCF\u012A", "l\u0142L\u0141", "n\xF1\u0148\u0144N\xD1\u0147\u0143", "o\xF2\xF3\u1ECF\xF5\u1ECD\xF4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xF6\xF8\u014DO\xD2\xD3\u1ECE\xD5\u1ECC\xD4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xD6\xD8\u014C", "r\u0159R\u0158", "s\u0161\u015B\u0219\u015FS\u0160\u015A\u0218\u015E", "t\u0165\u021B\u0163T\u0164\u021A\u0162", "u\xF9\xFA\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xFB\xFC\u016F\u016BU\xD9\xDA\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xDB\xDC\u016E\u016A", "y\xFD\u1EF3\u1EF7\u1EF9\u1EF5\xFFY\xDD\u1EF2\u1EF6\u1EF8\u1EF4\u0178", "z\u017E\u017C\u017AZ\u017D\u017B\u0179"]; + var handled = []; + str.split("").forEach(function(ch) { + dct.every(function(dct2) { + if (dct2.indexOf(ch) !== -1) { + if (handled.indexOf(dct2) > -1) { + return false; + } + str = str.replace(new RegExp("[" + dct2 + "]", "gm" + sens), "[" + dct2 + "]"); + handled.push(dct2); + } + return true; + }); + }); + return str; + } + }, { + key: "createMergedBlanksRegExp", + value: function createMergedBlanksRegExp(str) { + return str.replace(/[\s]+/gmi, "[\\s]+"); + } + }, { + key: "createAccuracyRegExp", + value: function createAccuracyRegExp(str) { + var _this = this; + var chars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\xA1\xBF"; + var acc = this.opt.accuracy, val = typeof acc === "string" ? acc : acc.value, ls = typeof acc === "string" ? [] : acc.limiters, lsJoin = ""; + ls.forEach(function(limiter) { + lsJoin += "|" + _this.escapeStr(limiter); + }); + switch (val) { + case "partially": + default: + return "()(" + str + ")"; + case "complementary": + lsJoin = "\\s" + (lsJoin ? lsJoin : this.escapeStr(chars)); + return "()([^" + lsJoin + "]*" + str + "[^" + lsJoin + "]*)"; + case "exactly": + return "(^|\\s" + lsJoin + ")(" + str + ")(?=$|\\s" + lsJoin + ")"; + } + } + }, { + key: "getSeparatedKeywords", + value: function getSeparatedKeywords(sv) { + var _this2 = this; + var stack = []; + sv.forEach(function(kw) { + if (!_this2.opt.separateWordSearch) { + if (kw.trim() && stack.indexOf(kw) === -1) { + stack.push(kw); + } + } else { + kw.split(" ").forEach(function(kwSplitted) { + if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) { + stack.push(kwSplitted); + } + }); + } + }); + return { + "keywords": stack.sort(function(a, b) { + return b.length - a.length; + }), + "length": stack.length + }; + } + }, { + key: "isNumeric", + value: function isNumeric(value) { + return Number(parseFloat(value)) == value; + } + }, { + key: "checkRanges", + value: function checkRanges(array) { + var _this3 = this; + if (!Array.isArray(array) || Object.prototype.toString.call(array[0]) !== "[object Object]") { + this.log("markRanges() will only accept an array of objects"); + this.opt.noMatch(array); + return []; + } + var stack = []; + var last = 0; + array.sort(function(a, b) { + return a.start - b.start; + }).forEach(function(item) { + var _callNoMatchOnInvalid = _this3.callNoMatchOnInvalidRanges(item, last), start = _callNoMatchOnInvalid.start, end = _callNoMatchOnInvalid.end, valid = _callNoMatchOnInvalid.valid; + if (valid) { + item.start = start; + item.length = end - start; + stack.push(item); + last = end; + } + }); + return stack; + } + }, { + key: "callNoMatchOnInvalidRanges", + value: function callNoMatchOnInvalidRanges(range, last) { + var start = void 0, end = void 0, valid = false; + if (range && typeof range.start !== "undefined") { + start = parseInt(range.start, 10); + end = start + parseInt(range.length, 10); + if (this.isNumeric(range.start) && this.isNumeric(range.length) && end - last > 0 && end - start > 0) { + valid = true; + } else { + this.log("Ignoring invalid or overlapping range: " + ("" + JSON.stringify(range))); + this.opt.noMatch(range); + } + } else { + this.log("Ignoring invalid range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } + return { + start, + end, + valid + }; + } + }, { + key: "checkWhitespaceRanges", + value: function checkWhitespaceRanges(range, originalLength, string) { + var end = void 0, valid = true, max = string.length, offset = originalLength - max, start = parseInt(range.start, 10) - offset; + start = start > max ? max : start; + end = start + parseInt(range.length, 10); + if (end > max) { + end = max; + this.log("End range automatically set to the max value of " + max); + } + if (start < 0 || end - start < 0 || start > max || end > max) { + valid = false; + this.log("Invalid range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } else if (string.substring(start, end).replace(/\s+/g, "") === "") { + valid = false; + this.log("Skipping whitespace only range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } + return { + start, + end, + valid + }; + } + }, { + key: "getTextNodes", + value: function getTextNodes(cb) { + var _this4 = this; + var val = "", nodes = []; + this.iterator.forEachNode(NodeFilter.SHOW_TEXT, function(node) { + nodes.push({ + start: val.length, + end: (val += node.textContent).length, + node + }); + }, function(node) { + if (_this4.matchesExclude(node.parentNode)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }, function() { + cb({ + value: val, + nodes + }); + }); + } + }, { + key: "matchesExclude", + value: function matchesExclude(el) { + return DOMIterator.matches(el, this.opt.exclude.concat(["script", "style", "title", "head", "html"])); + } + }, { + key: "wrapRangeInTextNode", + value: function wrapRangeInTextNode(node, start, end) { + var hEl = !this.opt.element ? "mark" : this.opt.element, startNode = node.splitText(start), ret = startNode.splitText(end - start); + var repl = document.createElement(hEl); + repl.setAttribute("data-markjs", "true"); + if (this.opt.className) { + repl.setAttribute("class", this.opt.className); + } + repl.textContent = startNode.textContent; + startNode.parentNode.replaceChild(repl, startNode); + return ret; + } + }, { + key: "wrapRangeInMappedTextNode", + value: function wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) { + var _this5 = this; + dict.nodes.every(function(n, i) { + var sibl = dict.nodes[i + 1]; + if (typeof sibl === "undefined" || sibl.start > start) { + if (!filterCb(n.node)) { + return false; + } + var s = start - n.start, e = (end > n.end ? n.end : end) - n.start, startStr = dict.value.substr(0, n.start), endStr = dict.value.substr(e + n.start); + n.node = _this5.wrapRangeInTextNode(n.node, s, e); + dict.value = startStr + endStr; + dict.nodes.forEach(function(k, j) { + if (j >= i) { + if (dict.nodes[j].start > 0 && j !== i) { + dict.nodes[j].start -= e; + } + dict.nodes[j].end -= e; + } + }); + end -= e; + eachCb(n.node.previousSibling, n.start); + if (end > n.end) { + start = n.end; + } else { + return false; + } + } + return true; + }); + } + }, { + key: "wrapMatches", + value: function wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) { + var _this6 = this; + var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; + this.getTextNodes(function(dict) { + dict.nodes.forEach(function(node) { + node = node.node; + var match = void 0; + while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== "") { + if (!filterCb(match[matchIdx], node)) { + continue; + } + var pos = match.index; + if (matchIdx !== 0) { + for (var i = 1; i < matchIdx; i++) { + pos += match[i].length; + } + } + node = _this6.wrapRangeInTextNode(node, pos, pos + match[matchIdx].length); + eachCb(node.previousSibling); + regex.lastIndex = 0; + } + }); + endCb(); + }); + } + }, { + key: "wrapMatchesAcrossElements", + value: function wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) { + var _this7 = this; + var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; + this.getTextNodes(function(dict) { + var match = void 0; + while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== "") { + var start = match.index; + if (matchIdx !== 0) { + for (var i = 1; i < matchIdx; i++) { + start += match[i].length; + } + } + var end = start + match[matchIdx].length; + _this7.wrapRangeInMappedTextNode(dict, start, end, function(node) { + return filterCb(match[matchIdx], node); + }, function(node, lastIndex) { + regex.lastIndex = lastIndex; + eachCb(node); + }); + } + endCb(); + }); + } + }, { + key: "wrapRangeFromIndex", + value: function wrapRangeFromIndex(ranges, filterCb, eachCb, endCb) { + var _this8 = this; + this.getTextNodes(function(dict) { + var originalLength = dict.value.length; + ranges.forEach(function(range, counter) { + var _checkWhitespaceRange = _this8.checkWhitespaceRanges(range, originalLength, dict.value), start = _checkWhitespaceRange.start, end = _checkWhitespaceRange.end, valid = _checkWhitespaceRange.valid; + if (valid) { + _this8.wrapRangeInMappedTextNode(dict, start, end, function(node) { + return filterCb(node, range, dict.value.substring(start, end), counter); + }, function(node) { + eachCb(node, range); + }); + } + }); + endCb(); + }); + } + }, { + key: "unwrapMatches", + value: function unwrapMatches(node) { + var parent = node.parentNode; + var docFrag = document.createDocumentFragment(); + while (node.firstChild) { + docFrag.appendChild(node.removeChild(node.firstChild)); + } + parent.replaceChild(docFrag, node); + if (!this.ie) { + parent.normalize(); + } else { + this.normalizeTextNode(parent); + } + } + }, { + key: "normalizeTextNode", + value: function normalizeTextNode(node) { + if (!node) { + return; + } + if (node.nodeType === 3) { + while (node.nextSibling && node.nextSibling.nodeType === 3) { + node.nodeValue += node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } else { + this.normalizeTextNode(node.firstChild); + } + this.normalizeTextNode(node.nextSibling); + } + }, { + key: "markRegExp", + value: function markRegExp(regexp, opt) { + var _this9 = this; + this.opt = opt; + this.log('Searching with expression "' + regexp + '"'); + var totalMatches = 0, fn = "wrapMatches"; + var eachCb = function eachCb2(element) { + totalMatches++; + _this9.opt.each(element); + }; + if (this.opt.acrossElements) { + fn = "wrapMatchesAcrossElements"; + } + this[fn](regexp, this.opt.ignoreGroups, function(match, node) { + return _this9.opt.filter(node, match, totalMatches); + }, eachCb, function() { + if (totalMatches === 0) { + _this9.opt.noMatch(regexp); + } + _this9.opt.done(totalMatches); + }); + } + }, { + key: "mark", + value: function mark(sv, opt) { + var _this10 = this; + this.opt = opt; + var totalMatches = 0, fn = "wrapMatches"; + var _getSeparatedKeywords = this.getSeparatedKeywords(typeof sv === "string" ? [sv] : sv), kwArr = _getSeparatedKeywords.keywords, kwArrLen = _getSeparatedKeywords.length, sens = this.opt.caseSensitive ? "" : "i", handler = function handler2(kw) { + var regex = new RegExp(_this10.createRegExp(kw), "gm" + sens), matches = 0; + _this10.log('Searching with expression "' + regex + '"'); + _this10[fn](regex, 1, function(term, node) { + return _this10.opt.filter(node, kw, totalMatches, matches); + }, function(element) { + matches++; + totalMatches++; + _this10.opt.each(element); + }, function() { + if (matches === 0) { + _this10.opt.noMatch(kw); + } + if (kwArr[kwArrLen - 1] === kw) { + _this10.opt.done(totalMatches); + } else { + handler2(kwArr[kwArr.indexOf(kw) + 1]); + } + }); + }; + if (this.opt.acrossElements) { + fn = "wrapMatchesAcrossElements"; + } + if (kwArrLen === 0) { + this.opt.done(totalMatches); + } else { + handler(kwArr[0]); + } + } + }, { + key: "markRanges", + value: function markRanges(rawRanges, opt) { + var _this11 = this; + this.opt = opt; + var totalMatches = 0, ranges = this.checkRanges(rawRanges); + if (ranges && ranges.length) { + this.log("Starting to mark with the following ranges: " + JSON.stringify(ranges)); + this.wrapRangeFromIndex(ranges, function(node, range, match, counter) { + return _this11.opt.filter(node, range, match, counter); + }, function(element, range) { + totalMatches++; + _this11.opt.each(element, range); + }, function() { + _this11.opt.done(totalMatches); + }); + } else { + this.opt.done(totalMatches); + } + } + }, { + key: "unmark", + value: function unmark(opt) { + var _this12 = this; + this.opt = opt; + var sel = this.opt.element ? this.opt.element : "*"; + sel += "[data-markjs]"; + if (this.opt.className) { + sel += "." + this.opt.className; + } + this.log('Removal selector "' + sel + '"'); + this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT, function(node) { + _this12.unwrapMatches(node); + }, function(node) { + var matchesSel = DOMIterator.matches(node, sel), matchesExclude = _this12.matchesExclude(node); + if (!matchesSel || matchesExclude) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }, this.opt.done); + } + }, { + key: "opt", + set: function set$$1(val) { + this._opt = _extends({}, { + "element": "", + "className": "", + "exclude": [], + "iframes": false, + "iframesTimeout": 5e3, + "separateWordSearch": true, + "diacritics": true, + "synonyms": {}, + "accuracy": "partially", + "acrossElements": false, + "caseSensitive": false, + "ignoreJoiners": false, + "ignoreGroups": 0, + "ignorePunctuation": [], + "wildcards": "disabled", + "each": function each() { + }, + "noMatch": function noMatch() { + }, + "filter": function filter() { + return true; + }, + "done": function done() { + }, + "debug": false, + "log": window.console + }, val); + }, + get: function get$$1() { + return this._opt; + } + }, { + key: "iterator", + get: function get$$1() { + return new DOMIterator(this.ctx, this.opt.iframes, this.opt.exclude, this.opt.iframesTimeout); + } + }]); + return Mark3; + })(); + function Mark2(ctx) { + var _this = this; + var instance = new Mark$1(ctx); + this.mark = function(sv, opt) { + instance.mark(sv, opt); + return _this; + }; + this.markRegExp = function(sv, opt) { + instance.markRegExp(sv, opt); + return _this; + }; + this.markRanges = function(sv, opt) { + instance.markRanges(sv, opt); + return _this; + }; + this.unmark = function(opt) { + instance.unmark(opt); + return _this; + }; + return this; + } + return Mark2; + })); + } +}); + +// lib/highlight.ts +var import_mark = __toESM(require_mark(), 1); +var PagefindHighlight = class { + constructor(options = { + markContext: null, + highlightParam: "pagefind-highlight", + markOptions: { + className: "pagefind-highlight", + exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"] + }, + addStyles: true + }) { + var _a, _b; + const { highlightParam, markContext, markOptions, addStyles } = options; + this.highlightParam = highlightParam ?? "pagefind-highlight"; + this.addStyles = addStyles ?? true; + this.markContext = markContext !== void 0 ? markContext : null; + this.markOptions = markOptions !== void 0 ? markOptions : { + className: "pagefind-highlight", + exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"] + }; + (_a = this.markOptions).className ?? (_a.className = "pagefind__highlight"); + (_b = this.markOptions).exclude ?? (_b.exclude = [ + "[data-pagefind-ignore]", + "[data-pagefind-ignore] *" + ]); + this.markOptions.separateWordSearch = false; + this.highlight(); + } + getHighlightParams(paramName) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.getAll(paramName); + } + // Inline styles might be too hard to override + addHighlightStyles(className) { + if (!className) return; + const styleElement = document.createElement("style"); + styleElement.innerText = `:where(.${className}) { background-color: yellow; color: black; }`; + document.head.appendChild(styleElement); + } + createMarkInstance() { + if (this.markContext) { + return new import_mark.default(this.markContext); + } + const pagefindBody = document.querySelectorAll("[data-pagefind-body]"); + if (pagefindBody.length !== 0) { + return new import_mark.default(pagefindBody); + } else { + return new import_mark.default(document.body); + } + } + markText(instance, text) { + instance.mark(text, this.markOptions); + } + highlight() { + const params = this.getHighlightParams(this.highlightParam); + if (!params || params.length === 0) return; + this.addStyles && this.addHighlightStyles(this.markOptions.className); + const markInstance = this.createMarkInstance(); + this.markText(markInstance, params); + } +}; +window.PagefindHighlight = PagefindHighlight; +export { + PagefindHighlight as default +}; +/*! Bundled license information: + +mark.js/dist/mark.js: + (*!*************************************************** + * mark.js v8.11.1 + * https://markjs.io/ + * Copyright (c) 2014–2018, Julian Kühnel + * Released under the MIT license https://git.io/vwTVl + *****************************************************) +*/ diff --git a/_pagefind/pagefind-modular-ui.css b/_pagefind/pagefind-modular-ui.css new file mode 100644 index 00000000..9c6793ed --- /dev/null +++ b/_pagefind/pagefind-modular-ui.css @@ -0,0 +1,214 @@ +:root { + --pagefind-ui-scale: 0.8; + --pagefind-ui-primary: #034AD8; + --pagefind-ui-fade: #707070; + --pagefind-ui-text: #393939; + --pagefind-ui-background: #ffffff; + --pagefind-ui-border: #eeeeee; + --pagefind-ui-tag: #eeeeee; + --pagefind-ui-border-width: 2px; + --pagefind-ui-border-radius: 8px; + --pagefind-ui-image-border-radius: 8px; + --pagefind-ui-image-box-ratio: 3 / 2; + --pagefind-ui-font: system, -apple-system, ".SFNSText-Regular", + "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", + "Lucida Grande", sans-serif; +} + +[data-pfmod-hidden] { + display: none !important; +} + +[data-pfmod-suppressed] { + opacity: 0 !important; + pointer-events: none !important; +} + +[data-pfmod-sr-hidden] { + -webkit-clip: rect(0 0 0 0) !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + height: 1px !important; + overflow: hidden !important; + overflow: clip !important; + position: absolute !important; + white-space: nowrap !important; + width: 1px !important; +} + +[data-pfmod-loading] { + color: var(--pagefind-ui-text); + background-color: var(--pagefind-ui-text); + border-radius: var(--pagefind-ui-border-radius); + opacity: 0.1; + pointer-events: none; +} + +/* Input */ + +.pagefind-modular-input-wrapper { + position: relative; +} + +.pagefind-modular-input-wrapper::before { + background-color: var(--pagefind-ui-text); + width: calc(18px * var(--pagefind-ui-scale)); + height: calc(18px * var(--pagefind-ui-scale)); + top: calc(23px * var(--pagefind-ui-scale)); + left: calc(20px * var(--pagefind-ui-scale)); + content: ""; + position: absolute; + display: block; + opacity: 0.7; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A"); + mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A"); + -webkit-mask-size: 100%; + mask-size: 100%; + z-index: 9; + pointer-events: none; +} + +.pagefind-modular-input { + height: calc(64px * var(--pagefind-ui-scale)); + padding: 0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale)); + background-color: var(--pagefind-ui-background); + border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border); + border-radius: var(--pagefind-ui-border-radius); + font-size: calc(21px * var(--pagefind-ui-scale)); + position: relative; + appearance: none; + -webkit-appearance: none; + display: flex; + width: 100%; + box-sizing: border-box; + font-weight: 700; +} + +.pagefind-modular-input::placeholder { + opacity: 0.2; +} + +.pagefind-modular-input-clear { + position: absolute; + top: calc(2px * var(--pagefind-ui-scale)); + right: calc(2px * var(--pagefind-ui-scale)); + height: calc(60px * var(--pagefind-ui-scale)); + border-radius: var(--pagefind-ui-border-radius); + padding: 0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale)); + color: var(--pagefind-ui-text); + font-size: calc(14px * var(--pagefind-ui-scale)); + cursor: pointer; + background-color: var(--pagefind-ui-background); + border: none; + appearance: none; +} + +/* ResultList */ + +.pagefind-modular-list-result { + list-style-type: none; + display: flex; + align-items: flex-start; + gap: min(calc(40px * var(--pagefind-ui-scale)), 3%); + padding: calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale)); + border-top: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border); +} + +.pagefind-modular-list-result:last-of-type { + border-bottom: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border); +} + +.pagefind-modular-list-thumb { + width: min(30%, + calc((30% - (100px * var(--pagefind-ui-scale))) * 100000)); + max-width: calc(120px * var(--pagefind-ui-scale)); + margin-top: calc(10px * var(--pagefind-ui-scale)); + aspect-ratio: var(--pagefind-ui-image-box-ratio); + position: relative; +} + +.pagefind-modular-list-image { + display: block; + position: absolute; + left: 50%; + transform: translateX(-50%); + font-size: 0; + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + border-radius: var(--pagefind-ui-image-border-radius); +} + +.pagefind-modular-list-inner { + flex: 1; + display: flex; + flex-direction: column; + align-items: flex-start; + margin-top: calc(10px * var(--pagefind-ui-scale)); +} + +.pagefind-modular-list-title { + display: inline-block; + font-weight: 700; + font-size: calc(21px * var(--pagefind-ui-scale)); + margin-top: 0; + margin-bottom: 0; +} + +.pagefind-modular-list-link { + color: var(--pagefind-ui-text); + text-decoration: none; +} + +.pagefind-modular-list-link:hover { + text-decoration: underline; +} + +.pagefind-modular-list-excerpt { + display: inline-block; + font-weight: 400; + font-size: calc(16px * var(--pagefind-ui-scale)); + margin-top: calc(4px * var(--pagefind-ui-scale)); + margin-bottom: 0; + min-width: calc(250px * var(--pagefind-ui-scale)); +} + +/* FilterPills */ + +.pagefind-modular-filter-pills-wrapper { + overflow-x: scroll; + padding: 15px 0; +} + +.pagefind-modular-filter-pills { + display: flex; + gap: 6px; +} + +.pagefind-modular-filter-pill { + display: flex; + justify-content: center; + align-items: center; + border: none; + appearance: none; + padding: 0 calc(24px * var(--pagefind-ui-scale)); + background-color: var(--pagefind-ui-background); + color: var(--pagefind-ui-fade); + border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border); + border-radius: calc(25px * var(--pagefind-ui-scale)); + font-size: calc(18px * var(--pagefind-ui-scale)); + height: calc(50px * var(--pagefind-ui-scale)); + cursor: pointer; + white-space: nowrap; +} + +.pagefind-modular-filter-pill:hover { + border-color: var(--pagefind-ui-primary); +} + +.pagefind-modular-filter-pill[aria-pressed="true"] { + border-color: var(--pagefind-ui-primary); + color: var(--pagefind-ui-primary); +} \ No newline at end of file diff --git a/_pagefind/pagefind-modular-ui.js b/_pagefind/pagefind-modular-ui.js new file mode 100644 index 00000000..6caacd6a --- /dev/null +++ b/_pagefind/pagefind-modular-ui.js @@ -0,0 +1,8 @@ +(()=>{var w=Object.defineProperty;var b=(i,e)=>{for(var t in e)w(i,t,{get:e[t],enumerable:!0})};var f={};b(f,{FilterPills:()=>c,Input:()=>a,Instance:()=>p,ResultList:()=>o,Summary:()=>h});var r=class i{constructor(e){this.element=document.createElement(e)}id(e){return this.element.id=e,this}class(e){return this.element.classList.add(e),this}attrs(e){for(let[t,s]of Object.entries(e))this.element.setAttribute(t,s);return this}text(e){return this.element.innerText=e,this}html(e){return this.element.innerHTML=e,this}handle(e,t){return this.element.addEventListener(e,t),this}addTo(e){return e instanceof i?e.element.appendChild(this.element):e.appendChild(this.element),this.element}};var T=async(i=100)=>new Promise(e=>setTimeout(e,i)),a=class{constructor(e={}){if(this.inputEl=null,this.clearEl=null,this.instance=null,this.searchID=0,this.debounceTimeoutMs=e.debounceTimeoutMs??300,e.inputElement){if(e.containerElement){console.warn("[Pagefind Input component]: inputElement and containerElement both supplied. Ignoring the container option.");return}this.initExisting(e.inputElement)}else if(e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind Input component]: No selector supplied for containerElement or inputElement");return}this.inputEl.addEventListener("input",async t=>{if(this.instance&&typeof t?.target?.value=="string"){this.updateState(t.target.value);let s=++this.searchID;if(await T(this.debounceTimeoutMs),s!==this.searchID)return null;this.instance?.triggerSearch(t.target.value)}}),this.inputEl.addEventListener("keydown",t=>{t.key==="Escape"&&(++this.searchID,this.inputEl.value="",this.instance?.triggerSearch(""),this.updateState("")),t.key==="Enter"&&t.preventDefault()}),this.inputEl.addEventListener("focus",()=>{this.instance?.triggerLoad()})}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Input component]: No container found for ${e} selector`);return}if(t.tagName==="INPUT")console.warn(`[Pagefind Input component]: Encountered input element for ${e} when a container was expected`),console.warn("[Pagefind Input component]: Treating containerElement option as inputElement and proceeding"),this.initExisting(e);else{t.innerHTML="";let s=0;for(;document.querySelector(`#pfmod-input-${s}`);)s+=1;let n=new r("form").class("pagefind-modular-input-wrapper").attrs({role:"search","aria-label":"Search this site",action:"javascript:void(0);"});new r("label").attrs({for:`pfmod-input-${s}`,"data-pfmod-sr-hidden":"true"}).text("Search this site").addTo(n),this.inputEl=new r("input").id(`pfmod-input-${s}`).class("pagefind-modular-input").attrs({autocapitalize:"none",enterkeyhint:"search"}).addTo(n),this.clearEl=new r("button").class("pagefind-modular-input-clear").attrs({"data-pfmod-suppressed":"true"}).text("Clear").handle("click",()=>{this.inputEl.value="",this.instance.triggerSearch(""),this.updateState("")}).addTo(n),n.addTo(t)}}initExisting(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Input component]: No input element found for ${e} selector`);return}if(t.tagName!=="INPUT"){console.error(`[Pagefind Input component]: Expected ${e} to be an element`);return}this.inputEl=t}updateState(e){this.clearEl&&(e&&e?.length?this.clearEl.removeAttribute("data-pfmod-suppressed"):this.clearEl.setAttribute("data-pfmod-suppressed","true"))}register(e){this.instance=e,this.instance.on("search",(t,s)=>{this.inputEl&&document.activeElement!==this.inputEl&&(this.inputEl.value=t,this.updateState(t))})}focus(){this.inputEl&&this.inputEl.focus()}};var g=i=>{if(i instanceof Element)return[i];if(Array.isArray(i)&&i.every(e=>e instanceof Element))return i;if(typeof i=="string"||i instanceof String){let e=document.createElement("div");return e.innerHTML=i,[...e.childNodes]}else return console.error(`[Pagefind ResultList component]: Expected template function to return an HTML element or string, got ${typeof i}`),[]},v=()=>{let i=(e=30)=>". ".repeat(Math.floor(10+Math.random()*e));return`
  • +
    +
    +

    ${i(30)}

    +

    ${i(40)}

    +
    +
  • `},y=(i,e)=>{let t=new r("li").class("pagefind-modular-list-result");if(e){let l=new r("div").class("pagefind-modular-list-thumb").addTo(t);i?.meta?.image&&new r("img").class("pagefind-modular-list-image").attrs({src:i.meta.image,alt:i.meta.image_alt||i.meta.title}).addTo(l)}let s=new r("div").class("pagefind-modular-list-inner").addTo(t),n=new r("p").class("pagefind-modular-list-title").addTo(s);return new r("a").class("pagefind-modular-list-link").text(i.meta?.title).attrs({href:i.meta?.url||i.url}).addTo(n),new r("p").class("pagefind-modular-list-excerpt").html(i.excerpt).addTo(s),t.element},E=i=>{if(!(i instanceof HTMLElement))return null;let e=window.getComputedStyle(i).overflowY;return e!=="visible"&&e!=="hidden"?i:E(i.parentNode)},d=class{constructor(e={}){this.rawResult=e.result,this.placeholderNodes=e.placeholderNodes,this.resultFn=e.resultFn,this.intersectionEl=e.intersectionEl,this.showImages=e.showImages,this.result=null,this.waitForIntersection()}waitForIntersection(){if(!this.placeholderNodes?.length)return;let e={root:this.intersectionEl,rootMargin:"0px",threshold:.01};new IntersectionObserver((s,n)=>{this.result===null&&s?.[0]?.isIntersecting&&(this.load(),n.disconnect())},e).observe(this.placeholderNodes[0])}async load(){if(!this.placeholderNodes?.length)return;this.result=await this.rawResult.data();let e=this.resultFn(this.result,this.showImages),t=g(e);for(;this.placeholderNodes.length>1;)this.placeholderNodes.pop().remove();this.placeholderNodes[0].replaceWith(...t)}},o=class{constructor(e){if(this.intersectionEl=document.body,this.containerEl=null,this.results=[],this.placeholderTemplate=e.placeholderTemplate??v,this.resultTemplate=e.resultTemplate??y,this.showImages=e.showImages??!0,e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind ResultList component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind ResultList component]: No container found for ${e} selector`);return}this.containerEl=t}append(e){for(let t of e)this.containerEl.appendChild(t)}register(e){e.on("results",t=>{this.containerEl&&(this.containerEl.innerHTML="",this.intersectionEl=E(this.containerEl),this.results=t.results.map(s=>{let n=g(this.placeholderTemplate());return this.append(n),new d({result:s,placeholderNodes:n,resultFn:this.resultTemplate,intersectionEl:this.intersectionEl,showImages:this.showImages})}))}),e.on("loading",()=>{this.containerEl&&(this.containerEl.innerHTML="")})}};var h=class{constructor(e={}){if(this.containerEl=null,this.defaultMessage=e.defaultMessage??"",this.term="",e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind Summary component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Summary component]: No container found for ${e} selector`);return}this.containerEl=t,this.containerEl.innerText=this.defaultMessage}register(e){e.on("search",(t,s)=>{this.term=t}),e.on("results",t=>{if(!this.containerEl||!t)return;if(!this.term){this.containerEl.innerText=this.defaultMessage;return}let s=t?.results?.length??0;this.containerEl.innerText=`${s} result${s===1?"":"s"} for ${this.term}`}),e.on("loading",()=>{this.containerEl&&(this.containerEl.innerText=`Searching for ${this.term}...`)})}};var c=class{constructor(e={}){if(this.instance=null,this.wrapper=null,this.pillContainer=null,this.available={},this.selected=["All"],this.total=0,this.filterMemo="",this.filter=e.filter,this.ordering=e.ordering??null,this.alwaysShow=e.alwaysShow??!1,this.selectMultiple=e.selectMultiple??!1,!this.filter?.length){console.error("[Pagefind FilterPills component]: No filter option supplied, nothing to display");return}if(e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind FilterPills component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind FilterPills component]: No container found for ${e} selector`);return}t.innerHTML="";let s=`pagefind_modular_filter_pills_${this.filter}`,n=new r("div").class("pagefind-modular-filter-pills-wrapper").attrs({role:"group","aria-labelledby":s});this.alwaysShow||n.attrs({"data-pfmod-hidden":!0}),new r("div").id(s).class("pagefind-modular-filter-pills-label").attrs({"data-pfmod-sr-hidden":!0}).text(`Filter results by ${this.filter}`).addTo(n),this.pillContainer=new r("div").class("pagefind-modular-filter-pills").addTo(n),this.wrapper=n.addTo(t)}update(){let e=this.available.map(t=>t[0]).join("~");e==this.filterMemo?this.updateExisting():(this.renderNew(),this.filterMemo=e)}pushFilters(){let e=this.selected.filter(t=>t!=="All");this.instance.triggerFilter(this.filter,e)}pillInner(e,t){return this.total?`${e} (${t})`:`${e}`}renderNew(){this.available.forEach(([e,t])=>{new r("button").class("pagefind-modular-filter-pill").html(this.pillInner(e,t)).attrs({"aria-pressed":this.selected.includes(e),type:"button"}).handle("click",()=>{e==="All"?this.selected=["All"]:this.selected.includes(e)?this.selected=this.selected.filter(s=>s!==e):this.selectMultiple?this.selected.push(e):this.selected=[e],this.selected?.length?this.selected?.length>1&&(this.selected=this.selected.filter(s=>s!=="All")):this.selected=["All"],this.update(),this.pushFilters()}).addTo(this.pillContainer)})}updateExisting(){let e=[...this.pillContainer.childNodes];this.available.forEach(([t,s],n)=>{e[n].innerHTML=this.pillInner(t,s),e[n].setAttribute("aria-pressed",this.selected.includes(t))})}register(e){this.instance=e,this.instance.on("filters",t=>{if(!this.pillContainer)return;this.selectMultiple?t=t.available:t=t.total;let s=t[this.filter];if(!s){console.warn(`[Pagefind FilterPills component]: No possible values found for the ${this.filter} filter`);return}this.available=Object.entries(s),Array.isArray(this.ordering)?this.available.sort((n,l)=>{let m=this.ordering.indexOf(n[0]),_=this.ordering.indexOf(l[0]);return(m===-1?1/0:m)-(_===-1?1/0:_)}):this.available.sort((n,l)=>n[0].localeCompare(l[0])),this.available.unshift(["All",this.total]),this.update()}),e.on("results",t=>{this.pillContainer&&(this.total=t?.unfilteredResultCount||0,this.available?.[0]?.[0]==="All"&&(this.available[0][1]=this.total),this.total||this.alwaysShow?this.wrapper.removeAttribute("data-pfmod-hidden"):this.wrapper.setAttribute("data-pfmod-hidden","true"),this.update())})}};var P=async(i=50)=>await new Promise(e=>setTimeout(e,i)),u;try{document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&(u=new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?modular-ui.js.*$/)[1])}catch{u="/pagefind/"}var p=class{constructor(e={}){this.__pagefind__=null,this.__initializing__=null,this.__searchID__=0,this.__hooks__={search:[],filters:[],loading:[],results:[]},this.components=[],this.searchTerm="",this.searchFilters={},this.searchResult={},this.availableFilters=null,this.totalFilters=null,this.options={bundlePath:e.bundlePath??u,mergeIndex:e.mergeIndex??[]},delete e.bundlePath,delete e.resetStyles,delete e.processResult,delete e.processTerm,delete e.debounceTimeoutMs,delete e.mergeIndex,delete e.translations,this.pagefindOptions=e}add(e){e?.register?.(this),this.components.push(e)}on(e,t){if(!this.__hooks__[e]){let s=Object.keys(this.__hooks__).join(", ");console.error(`[Pagefind Composable]: Unknown event type ${e}. Supported events: [${s}]`);return}if(typeof t!="function"){console.error(`[Pagefind Composable]: Expected callback to be a function, received ${typeof t}`);return}this.__hooks__[e].push(t)}triggerLoad(){this.__load__()}triggerSearch(e){this.searchTerm=e,this.__dispatch__("search",e,this.searchFilters),this.__search__(e,this.searchFilters)}triggerSearchWithFilters(e,t){this.searchTerm=e,this.searchFilters=t,this.__dispatch__("search",e,t),this.__search__(e,t)}triggerFilters(e){this.searchFilters=e,this.__dispatch__("search",this.searchTerm,e),this.__search__(this.searchTerm,e)}triggerFilter(e,t){this.searchFilters=this.searchFilters||{},this.searchFilters[e]=t,this.__dispatch__("search",this.searchTerm,this.searchFilters),this.__search__(this.searchTerm,this.searchFilters)}__dispatch__(e,...t){this.__hooks__[e]?.forEach(s=>s?.(...t))}async __clear__(){this.__dispatch__("results",{results:[],unfilteredTotalCount:0}),this.availableFilters=await this.__pagefind__.filters(),this.totalFilters=this.availableFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})}async __search__(e,t){this.__dispatch__("loading"),await this.__load__();let s=++this.__searchID__;if(!e||!e.length)return this.__clear__();let n=await this.__pagefind__.search(e,{filters:t});n&&this.__searchID__===s&&(n.filters&&Object.keys(n.filters)?.length&&(this.availableFilters=n.filters,this.totalFilters=n.totalFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})),this.searchResult=n,this.__dispatch__("results",this.searchResult))}async __load__(){if(this.__initializing__){for(;!this.__pagefind__;)await P(50);return}if(this.__initializing__=!0,!this.__pagefind__){let e;try{e=await import(`${this.options.bundlePath}pagefind.js`)}catch(t){console.error(t),console.error([`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,"You can configure this by passing a bundlePath option to PagefindComposable Instance"].join(` +`)),document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?console.error(`[DEBUG: Loaded from ${document.currentScript?.src??"bad script location"}]`):console.error("no known script location")}await e.options(this.pagefindOptions||{});for(let t of this.options.mergeIndex){if(!t.bundlePath)throw new Error("mergeIndex requires a bundlePath parameter");let s=t.bundlePath;delete t.bundlePath,await e.mergeIndex(s,t)}this.__pagefind__=e}this.availableFilters=await this.__pagefind__.filters(),this.totalFilters=this.availableFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})}};window.PagefindModularUI=f;})(); diff --git a/_pagefind/pagefind-ui.css b/_pagefind/pagefind-ui.css new file mode 100644 index 00000000..d7984a98 --- /dev/null +++ b/_pagefind/pagefind-ui.css @@ -0,0 +1 @@ +.pagefind-ui__result.svelte-j9e30.svelte-j9e30{list-style-type:none;display:flex;align-items:flex-start;gap:min(calc(40px * var(--pagefind-ui-scale)),3%);padding:calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));border-top:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result.svelte-j9e30.svelte-j9e30:last-of-type{border-bottom:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result-thumb.svelte-j9e30.svelte-j9e30{width:min(30%,calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));max-width:calc(120px * var(--pagefind-ui-scale));margin-top:calc(10px * var(--pagefind-ui-scale));aspect-ratio:var(--pagefind-ui-image-box-ratio);position:relative}.pagefind-ui__result-image.svelte-j9e30.svelte-j9e30{display:block;position:absolute;left:50%;transform:translate(-50%);font-size:0;width:auto;height:auto;max-width:100%;max-height:100%;border-radius:var(--pagefind-ui-image-border-radius)}.pagefind-ui__result-inner.svelte-j9e30.svelte-j9e30{flex:1;display:flex;flex-direction:column;align-items:flex-start;margin-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-title.svelte-j9e30.svelte-j9e30{display:inline-block;font-weight:700;font-size:calc(21px * var(--pagefind-ui-scale));margin-top:0;margin-bottom:0}.pagefind-ui__result-title.svelte-j9e30 .pagefind-ui__result-link.svelte-j9e30{color:var(--pagefind-ui-text);text-decoration:none}.pagefind-ui__result-title.svelte-j9e30 .pagefind-ui__result-link.svelte-j9e30:hover{text-decoration:underline}.pagefind-ui__result-excerpt.svelte-j9e30.svelte-j9e30{display:inline-block;font-weight:400;font-size:calc(16px * var(--pagefind-ui-scale));margin-top:calc(4px * var(--pagefind-ui-scale));margin-bottom:0;min-width:calc(250px * var(--pagefind-ui-scale))}.pagefind-ui__loading.svelte-j9e30.svelte-j9e30{color:var(--pagefind-ui-text);background-color:var(--pagefind-ui-text);border-radius:var(--pagefind-ui-border-radius);opacity:.1;pointer-events:none}.pagefind-ui__result-tags.svelte-j9e30.svelte-j9e30{list-style-type:none;padding:0;display:flex;gap:calc(20px * var(--pagefind-ui-scale));flex-wrap:wrap;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-tag.svelte-j9e30.svelte-j9e30{padding:calc(4px * var(--pagefind-ui-scale)) calc(8px * var(--pagefind-ui-scale));font-size:calc(14px * var(--pagefind-ui-scale));border-radius:var(--pagefind-ui-border-radius);background-color:var(--pagefind-ui-tag)}.pagefind-ui__result.svelte-4xnkmf.svelte-4xnkmf{list-style-type:none;display:flex;align-items:flex-start;gap:min(calc(40px * var(--pagefind-ui-scale)),3%);padding:calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));border-top:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result.svelte-4xnkmf.svelte-4xnkmf:last-of-type{border-bottom:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result-nested.svelte-4xnkmf.svelte-4xnkmf{display:flex;flex-direction:column;padding-left:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-nested.svelte-4xnkmf.svelte-4xnkmf:first-of-type{padding-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-nested.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf{font-size:.9em;position:relative}.pagefind-ui__result-nested.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf:before{content:"\2937 ";position:absolute;top:0;right:calc(100% + .1em)}.pagefind-ui__result-thumb.svelte-4xnkmf.svelte-4xnkmf{width:min(30%,calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));max-width:calc(120px * var(--pagefind-ui-scale));margin-top:calc(10px * var(--pagefind-ui-scale));aspect-ratio:var(--pagefind-ui-image-box-ratio);position:relative}.pagefind-ui__result-image.svelte-4xnkmf.svelte-4xnkmf{display:block;position:absolute;left:50%;transform:translate(-50%);font-size:0;width:auto;height:auto;max-width:100%;max-height:100%;border-radius:var(--pagefind-ui-image-border-radius)}.pagefind-ui__result-inner.svelte-4xnkmf.svelte-4xnkmf{flex:1;display:flex;flex-direction:column;align-items:flex-start;margin-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-title.svelte-4xnkmf.svelte-4xnkmf{display:inline-block;font-weight:700;font-size:calc(21px * var(--pagefind-ui-scale));margin-top:0;margin-bottom:0}.pagefind-ui__result-title.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf{color:var(--pagefind-ui-text);text-decoration:none}.pagefind-ui__result-title.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf:hover{text-decoration:underline}.pagefind-ui__result-excerpt.svelte-4xnkmf.svelte-4xnkmf{display:inline-block;font-weight:400;font-size:calc(16px * var(--pagefind-ui-scale));margin-top:calc(4px * var(--pagefind-ui-scale));margin-bottom:0;min-width:calc(250px * var(--pagefind-ui-scale))}.pagefind-ui__loading.svelte-4xnkmf.svelte-4xnkmf{color:var(--pagefind-ui-text);background-color:var(--pagefind-ui-text);border-radius:var(--pagefind-ui-border-radius);opacity:.1;pointer-events:none}.pagefind-ui__result-tags.svelte-4xnkmf.svelte-4xnkmf{list-style-type:none;padding:0;display:flex;gap:calc(20px * var(--pagefind-ui-scale));flex-wrap:wrap;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-tag.svelte-4xnkmf.svelte-4xnkmf{padding:calc(4px * var(--pagefind-ui-scale)) calc(8px * var(--pagefind-ui-scale));font-size:calc(14px * var(--pagefind-ui-scale));border-radius:var(--pagefind-ui-border-radius);background-color:var(--pagefind-ui-tag)}legend.svelte-1v2r7ls.svelte-1v2r7ls{position:absolute;clip:rect(0 0 0 0)}.pagefind-ui__filter-panel.svelte-1v2r7ls.svelte-1v2r7ls{min-width:min(calc(260px * var(--pagefind-ui-scale)),100%);flex:1;display:flex;flex-direction:column;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__filter-group.svelte-1v2r7ls.svelte-1v2r7ls{border:0;padding:0}.pagefind-ui__filter-block.svelte-1v2r7ls.svelte-1v2r7ls{padding:0;display:block;border-bottom:solid calc(2px * var(--pagefind-ui-scale)) var(--pagefind-ui-border);padding:calc(20px * var(--pagefind-ui-scale)) 0}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls{font-size:calc(16px * var(--pagefind-ui-scale));position:relative;display:flex;align-items:center;list-style:none;font-weight:700;cursor:pointer;height:calc(24px * var(--pagefind-ui-scale))}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls::-webkit-details-marker{display:none}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls:after{position:absolute;content:"";right:calc(6px * var(--pagefind-ui-scale));top:50%;width:calc(8px * var(--pagefind-ui-scale));height:calc(8px * var(--pagefind-ui-scale));border:solid calc(2px * var(--pagefind-ui-scale)) currentColor;border-right:0;border-top:0;transform:translateY(-70%) rotate(-45deg)}.pagefind-ui__filter-block[open].svelte-1v2r7ls .pagefind-ui__filter-name.svelte-1v2r7ls:after{transform:translateY(-70%) rotate(-225deg)}.pagefind-ui__filter-group.svelte-1v2r7ls.svelte-1v2r7ls{display:flex;flex-direction:column;gap:calc(20px * var(--pagefind-ui-scale));padding-top:calc(30px * var(--pagefind-ui-scale))}.pagefind-ui__filter-value.svelte-1v2r7ls.svelte-1v2r7ls{position:relative;display:flex;align-items:center;gap:calc(8px * var(--pagefind-ui-scale))}.pagefind-ui__filter-value.svelte-1v2r7ls.svelte-1v2r7ls:before{position:absolute;content:"";top:50%;left:calc(8px * var(--pagefind-ui-scale));width:0px;height:0px;border:solid 1px #fff;opacity:0;transform:translate(calc(4.5px * var(--pagefind-ui-scale) * -1),calc(.8px * var(--pagefind-ui-scale))) skew(-5deg) rotate(-45deg);transform-origin:top left;border-top:0;border-right:0;pointer-events:none}.pagefind-ui__filter-value.pagefind-ui__filter-value--checked.svelte-1v2r7ls.svelte-1v2r7ls:before{opacity:1;width:calc(9px * var(--pagefind-ui-scale));height:calc(4px * var(--pagefind-ui-scale));transition:width .1s ease-out .1s,height .1s ease-in}.pagefind-ui__filter-checkbox.svelte-1v2r7ls.svelte-1v2r7ls{margin:0;width:calc(16px * var(--pagefind-ui-scale));height:calc(16px * var(--pagefind-ui-scale));border:solid 1px var(--pagefind-ui-border);appearance:none;-webkit-appearance:none;border-radius:calc(var(--pagefind-ui-border-radius) / 2);background-color:var(--pagefind-ui-background);cursor:pointer}.pagefind-ui__filter-checkbox.svelte-1v2r7ls.svelte-1v2r7ls:checked{background-color:var(--pagefind-ui-primary);border:solid 1px var(--pagefind-ui-primary)}.pagefind-ui__filter-label.svelte-1v2r7ls.svelte-1v2r7ls{cursor:pointer;font-size:calc(16px * var(--pagefind-ui-scale));font-weight:400}.pagefind-ui--reset *:where(:not(html,iframe,canvas,img,svg,video):not(svg *,symbol *)){all:unset;display:revert;outline:revert}.pagefind-ui--reset *,.pagefind-ui--reset *:before,.pagefind-ui--reset *:after{box-sizing:border-box}.pagefind-ui--reset a,.pagefind-ui--reset button{cursor:revert}.pagefind-ui--reset ol,.pagefind-ui--reset ul,.pagefind-ui--reset menu{list-style:none}.pagefind-ui--reset img{max-width:100%}.pagefind-ui--reset table{border-collapse:collapse}.pagefind-ui--reset input,.pagefind-ui--reset textarea{-webkit-user-select:auto}.pagefind-ui--reset textarea{white-space:revert}.pagefind-ui--reset meter{-webkit-appearance:revert;appearance:revert}.pagefind-ui--reset ::placeholder{color:unset}.pagefind-ui--reset :where([hidden]){display:none}.pagefind-ui--reset :where([contenteditable]:not([contenteditable="false"])){-moz-user-modify:read-write;-webkit-user-modify:read-write;overflow-wrap:break-word;-webkit-line-break:after-white-space;-webkit-user-select:auto}.pagefind-ui--reset :where([draggable="true"]){-webkit-user-drag:element}.pagefind-ui--reset mark{all:revert}:root{--pagefind-ui-scale:.8;--pagefind-ui-primary:#393939;--pagefind-ui-text:#393939;--pagefind-ui-background:#ffffff;--pagefind-ui-border:#eeeeee;--pagefind-ui-tag:#eeeeee;--pagefind-ui-border-width:2px;--pagefind-ui-border-radius:8px;--pagefind-ui-image-border-radius:8px;--pagefind-ui-image-box-ratio:3 / 2;--pagefind-ui-font:system, -apple-system, "BlinkMacSystemFont", ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", "Ubuntu", "arial", sans-serif}.pagefind-ui.svelte-e9gkc3{width:100%;color:var(--pagefind-ui-text);font-family:var(--pagefind-ui-font)}.pagefind-ui__hidden.svelte-e9gkc3{display:none!important}.pagefind-ui__suppressed.svelte-e9gkc3{opacity:0;pointer-events:none}.pagefind-ui__form.svelte-e9gkc3{position:relative}.pagefind-ui__form.svelte-e9gkc3:before{background-color:var(--pagefind-ui-text);width:calc(18px * var(--pagefind-ui-scale));height:calc(18px * var(--pagefind-ui-scale));top:calc(23px * var(--pagefind-ui-scale));left:calc(20px * var(--pagefind-ui-scale));content:"";position:absolute;display:block;opacity:.7;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");mask-image:url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");-webkit-mask-size:100%;mask-size:100%;z-index:9;pointer-events:none}.pagefind-ui__search-input.svelte-e9gkc3{height:calc(64px * var(--pagefind-ui-scale));padding:0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale));background-color:var(--pagefind-ui-background);border:var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);border-radius:var(--pagefind-ui-border-radius);font-size:calc(21px * var(--pagefind-ui-scale));position:relative;appearance:none;-webkit-appearance:none;display:flex;width:100%;box-sizing:border-box;font-weight:700}.pagefind-ui__search-input.svelte-e9gkc3::placeholder{opacity:.2}.pagefind-ui__search-clear.svelte-e9gkc3{position:absolute;top:calc(3px * var(--pagefind-ui-scale));right:calc(3px * var(--pagefind-ui-scale));height:calc(58px * var(--pagefind-ui-scale));padding:0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale));color:var(--pagefind-ui-text);font-size:calc(14px * var(--pagefind-ui-scale));cursor:pointer;background-color:var(--pagefind-ui-background);border-radius:var(--pagefind-ui-border-radius)}.pagefind-ui__drawer.svelte-e9gkc3{gap:calc(60px * var(--pagefind-ui-scale));display:flex;flex-direction:row;flex-wrap:wrap}.pagefind-ui__results-area.svelte-e9gkc3{min-width:min(calc(400px * var(--pagefind-ui-scale)),100%);flex:1000;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__results.svelte-e9gkc3{padding:0}.pagefind-ui__message.svelte-e9gkc3{box-sizing:content-box;font-size:calc(16px * var(--pagefind-ui-scale));height:calc(24px * var(--pagefind-ui-scale));padding:calc(20px * var(--pagefind-ui-scale)) 0;display:flex;align-items:center;font-weight:700;margin-top:0}.pagefind-ui__button.svelte-e9gkc3{margin-top:calc(40px * var(--pagefind-ui-scale));border:var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);border-radius:var(--pagefind-ui-border-radius);height:calc(48px * var(--pagefind-ui-scale));padding:0 calc(12px * var(--pagefind-ui-scale));font-size:calc(16px * var(--pagefind-ui-scale));color:var(--pagefind-ui-primary);background:var(--pagefind-ui-background);width:100%;text-align:center;font-weight:700;cursor:pointer}.pagefind-ui__button.svelte-e9gkc3:hover{border-color:var(--pagefind-ui-primary);color:var(--pagefind-ui-primary);background:var(--pagefind-ui-background)} diff --git a/_pagefind/pagefind-ui.js b/_pagefind/pagefind-ui.js new file mode 100644 index 00000000..44c2d5d2 --- /dev/null +++ b/_pagefind/pagefind-ui.js @@ -0,0 +1,2 @@ +(()=>{var Ur=Object.defineProperty;var A=(n,e)=>{for(var t in e)Ur(n,t,{get:e[t],enumerable:!0})};function U(){}function bt(n){return n()}function yn(){return Object.create(null)}function K(n){n.forEach(bt)}function at(n){return typeof n=="function"}function G(n,e){return n!=n?e==e:n!==e||n&&typeof n=="object"||typeof n=="function"}var lt;function ie(n,e){return lt||(lt=document.createElement("a")),lt.href=e,n===lt.href}function vn(n){return Object.keys(n).length===0}var Hn=typeof window<"u"?window:typeof globalThis<"u"?globalThis:global,de=class{constructor(e){this.options=e,this._listeners="WeakMap"in Hn?new WeakMap:void 0}observe(e,t){return this._listeners.set(e,t),this._getObserver().observe(e,this.options),()=>{this._listeners.delete(e),this._observer.unobserve(e)}}_getObserver(){var e;return(e=this._observer)!==null&&e!==void 0?e:this._observer=new ResizeObserver(t=>{var r;for(let s of t)de.entries.set(s.target,s),(r=this._listeners.get(s.target))===null||r===void 0||r(s)})}};de.entries="WeakMap"in Hn?new WeakMap:void 0;var wn=!1;function Dr(){wn=!0}function Ir(){wn=!1}function R(n,e){n.appendChild(e)}function S(n,e,t){n.insertBefore(e,t||null)}function k(n){n.parentNode&&n.parentNode.removeChild(n)}function Q(n,e){for(let t=0;tn.removeEventListener(e,t,r)}function m(n,e,t){t==null?n.removeAttribute(e):n.getAttribute(e)!==t&&n.setAttribute(e,t)}function Lr(n){return Array.from(n.childNodes)}function z(n,e){e=""+e,n.data!==e&&(n.data=e)}function Tt(n,e){n.value=e??""}function B(n,e,t){n.classList[t?"add":"remove"](e)}var ot=class{constructor(e=!1){this.is_svg=!1,this.is_svg=e,this.e=this.n=null}c(e){this.h(e)}m(e,t,r=null){this.e||(this.is_svg?this.e=Pr(t.nodeName):this.e=C(t.nodeType===11?"TEMPLATE":t.nodeName),this.t=t.tagName!=="TEMPLATE"?t:t.content,this.c(e)),this.i(r)}h(e){this.e.innerHTML=e,this.n=Array.from(this.e.nodeName==="TEMPLATE"?this.e.content.childNodes:this.e.childNodes)}i(e){for(let t=0;tn.indexOf(r)===-1?e.push(r):t.push(r)),t.forEach(r=>r()),se=e}var it=new Set,ee;function ae(){ee={r:0,c:[],p:ee}}function oe(){ee.r||K(ee.c),ee=ee.p}function D(n,e){n&&n.i&&(it.delete(n),n.i(e))}function P(n,e,t,r){if(n&&n.o){if(it.has(n))return;it.add(n),ee.c.push(()=>{it.delete(n),r&&(t&&n.d(1),r())}),n.o(e)}else r&&r()}function On(n,e){P(n,1,1,()=>{e.delete(n.key)})}function jn(n,e,t,r,s,l,i,a,o,f,c,d){let p=n.length,h=l.length,u=p,_={};for(;u--;)_[n[u].key]=u;let E=[],b=new Map,T=new Map,M=[];for(u=h;u--;){let H=d(s,l,u),F=t(H),O=i.get(F);O?r&&M.push(()=>O.p(H,e)):(O=f(F,H),O.c()),b.set(F,E[u]=O),F in _&&T.set(F,Math.abs(u-_[F]))}let y=new Set,X=new Set;function V(H){D(H,1),H.m(a,c),i.set(H.key,H),c=H.first,h--}for(;p&&h;){let H=E[h-1],F=n[p-1],O=H.key,W=F.key;H===F?(c=H.first,p--,h--):b.has(W)?!i.has(O)||y.has(O)?V(H):X.has(W)?p--:T.get(O)>T.get(W)?(X.add(O),V(H)):(y.add(W),p--):(o(F,i),p--)}for(;p--;){let H=n[p];b.has(H.key)||o(H,i)}for(;h;)V(E[h-1]);return K(M),E}var Kr=["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"],Eo=new Set([...Kr]);function Un(n,e,t){let r=n.$$.props[e];r!==void 0&&(n.$$.bound[r]=t,t(n.$$.ctx[r]))}function ut(n){n&&n.c()}function me(n,e,t,r){let{fragment:s,after_update:l}=n.$$;s&&s.m(e,t),r||Rt(()=>{let i=n.$$.on_mount.map(bt).filter(at);n.$$.on_destroy?n.$$.on_destroy.push(...i):K(i),n.$$.on_mount=[]}),l.forEach(Rt)}function ue(n,e){let t=n.$$;t.fragment!==null&&(Wr(t.after_update),K(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Gr(n,e){n.$$.dirty[0]===-1&&(re.push(n),Br(),n.$$.dirty.fill(0)),n.$$.dirty[e/31|0]|=1<{let u=h.length?h[0]:p;return f.ctx&&s(f.ctx[d],f.ctx[d]=u)&&(!f.skip_bound&&f.bound[d]&&f.bound[d](u),c&&Gr(n,d)),p}):[],f.update(),c=!0,K(f.before_update),f.fragment=r?r(f.ctx):!1,e.target){if(e.hydrate){Dr();let d=Lr(e.target);f.fragment&&f.fragment.l(d),d.forEach(k)}else f.fragment&&f.fragment.c();e.intro&&D(n.$$.fragment),me(n,e.target,e.anchor,e.customElement),Ir(),zn()}fe(o)}var Jr;typeof HTMLElement=="function"&&(Jr=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:n}=this.$$;this.$$.on_disconnect=n.map(bt).filter(at);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(n,e,t){this[n]=t}disconnectedCallback(){K(this.$$.on_disconnect)}$destroy(){ue(this,1),this.$destroy=U}$on(n,e){if(!at(e))return U;let t=this.$$.callbacks[n]||(this.$$.callbacks[n]=[]);return t.push(e),()=>{let r=t.indexOf(e);r!==-1&&t.splice(r,1)}}$set(n){this.$$set&&!vn(n)&&(this.$$.skip_bound=!0,this.$$set(n),this.$$.skip_bound=!1)}});var q=class{$destroy(){ue(this,1),this.$destroy=U}$on(e,t){if(!at(t))return U;let r=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return r.push(t),()=>{let s=r.indexOf(t);s!==-1&&r.splice(s,1)}}$set(e){this.$$set&&!vn(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};function I(n){let e=typeof n=="string"?n.charCodeAt(0):n;return e>=97&&e<=122||e>=65&&e<=90}function $(n){let e=typeof n=="string"?n.charCodeAt(0):n;return e>=48&&e<=57}function Z(n){return I(n)||$(n)}var Dn=["art-lojban","cel-gaulish","no-bok","no-nyn","zh-guoyu","zh-hakka","zh-min","zh-min-nan","zh-xiang"];var St={"en-gb-oed":"en-GB-oxendict","i-ami":"ami","i-bnn":"bnn","i-default":null,"i-enochian":null,"i-hak":"hak","i-klingon":"tlh","i-lux":"lb","i-mingo":null,"i-navajo":"nv","i-pwn":"pwn","i-tao":"tao","i-tay":"tay","i-tsu":"tsu","sgn-be-fr":"sfb","sgn-be-nl":"vgt","sgn-ch-de":"sgg","art-lojban":"jbo","cel-gaulish":null,"no-bok":"nb","no-nyn":"nn","zh-guoyu":"cmn","zh-hakka":"hak","zh-min":null,"zh-min-nan":"nan","zh-xiang":"hsn"};var Yr={}.hasOwnProperty;function ct(n,e={}){let t=In(),r=String(n),s=r.toLowerCase(),l=0;if(n==null)throw new Error("Expected string, got `"+n+"`");if(Yr.call(St,s)){let a=St[s];return(e.normalize===void 0||e.normalize===null||e.normalize)&&typeof a=="string"?ct(a):(t[Dn.includes(s)?"regular":"irregular"]=r,t)}for(;I(s.charCodeAt(l))&&l<9;)l++;if(l>1&&l<9){if(t.language=r.slice(0,l),l<4){let a=0;for(;s.charCodeAt(l)===45&&I(s.charCodeAt(l+1))&&I(s.charCodeAt(l+2))&&I(s.charCodeAt(l+3))&&!I(s.charCodeAt(l+4));){if(a>2)return i(l,3,"Too many extended language subtags, expected at most 3 subtags");t.extendedLanguageSubtags.push(r.slice(l+1,l+4)),l+=4,a++}}for(s.charCodeAt(l)===45&&I(s.charCodeAt(l+1))&&I(s.charCodeAt(l+2))&&I(s.charCodeAt(l+3))&&I(s.charCodeAt(l+4))&&!I(s.charCodeAt(l+5))&&(t.script=r.slice(l+1,l+5),l+=5),s.charCodeAt(l)===45&&(I(s.charCodeAt(l+1))&&I(s.charCodeAt(l+2))&&!I(s.charCodeAt(l+3))?(t.region=r.slice(l+1,l+3),l+=3):$(s.charCodeAt(l+1))&&$(s.charCodeAt(l+2))&&$(s.charCodeAt(l+3))&&!$(s.charCodeAt(l+4))&&(t.region=r.slice(l+1,l+4),l+=4));s.charCodeAt(l)===45;){let a=l+1,o=a;for(;Z(s.charCodeAt(o));){if(o-a>7)return i(o,1,"Too long variant, expected at most 8 characters");o++}if(o-a>4||o-a>3&&$(s.charCodeAt(a)))t.variants.push(r.slice(a,o)),l=o;else break}for(;s.charCodeAt(l)===45&&!(s.charCodeAt(l+1)===120||!Z(s.charCodeAt(l+1))||s.charCodeAt(l+2)!==45||!Z(s.charCodeAt(l+3)));){let a=l+2,o=0;for(;s.charCodeAt(a)===45&&Z(s.charCodeAt(a+1))&&Z(s.charCodeAt(a+2));){let f=a+1;for(a=f+2,o++;Z(s.charCodeAt(a));){if(a-f>7)return i(a,2,"Too long extension, expected at most 8 characters");a++}}if(!o)return i(a,4,"Empty extension, extensions must have at least 2 characters of content");t.extensions.push({singleton:r.charAt(l+1),extensions:r.slice(l+3,a).split("-")}),l=a}}else l=0;if(l===0&&s.charCodeAt(l)===120||s.charCodeAt(l)===45&&s.charCodeAt(l+1)===120){l=l?l+2:1;let a=l;for(;s.charCodeAt(a)===45&&Z(s.charCodeAt(a+1));){let o=l+1;for(a=o;Z(s.charCodeAt(a));){if(a-o>7)return i(a,5,"Too long private-use area, expected at most 8 characters");a++}t.privateuse.push(r.slice(l+1,a)),l=a}}if(l!==r.length)return i(l,6,"Found superfluous content after tag");return t;function i(a,o,f){return e.warning&&e.warning(f,o,a),e.forgiving?t:In()}}function In(){return{language:null,extendedLanguageSubtags:[],script:null,region:null,variants:[],extensions:[],privateuse:[],irregular:null,regular:null}}function Pn(n,e,t){let r=n.slice();return r[8]=e[t][0],r[9]=e[t][1],r}function Zr(n){let e,t,r,s,l,i=n[0]&&Ln(n);return{c(){i&&i.c(),e=v(),t=C("div"),r=C("p"),r.textContent=`${n[3](30)}`,s=v(),l=C("p"),l.textContent=`${n[3](40)}`,m(r,"class","pagefind-ui__result-title pagefind-ui__loading svelte-j9e30"),m(l,"class","pagefind-ui__result-excerpt pagefind-ui__loading svelte-j9e30"),m(t,"class","pagefind-ui__result-inner svelte-j9e30")},m(a,o){i&&i.m(a,o),S(a,e,o),S(a,t,o),R(t,r),R(t,s),R(t,l)},p(a,o){a[0]?i||(i=Ln(a),i.c(),i.m(e.parentNode,e)):i&&(i.d(1),i=null)},d(a){i&&i.d(a),a&&k(e),a&&k(t)}}}function Xr(n){let e,t,r,s,l=n[1].meta?.title+"",i,a,o,f,c=n[1].excerpt+"",d,p=n[0]&&qn(n),h=n[2].length&&Vn(n);return{c(){p&&p.c(),e=v(),t=C("div"),r=C("p"),s=C("a"),i=w(l),o=v(),f=C("p"),d=v(),h&&h.c(),m(s,"class","pagefind-ui__result-link svelte-j9e30"),m(s,"href",a=n[1].meta?.url||n[1].url),m(r,"class","pagefind-ui__result-title svelte-j9e30"),m(f,"class","pagefind-ui__result-excerpt svelte-j9e30"),m(t,"class","pagefind-ui__result-inner svelte-j9e30")},m(u,_){p&&p.m(u,_),S(u,e,_),S(u,t,_),R(t,r),R(r,s),R(s,i),R(t,o),R(t,f),f.innerHTML=c,R(t,d),h&&h.m(t,null)},p(u,_){u[0]?p?p.p(u,_):(p=qn(u),p.c(),p.m(e.parentNode,e)):p&&(p.d(1),p=null),_&2&&l!==(l=u[1].meta?.title+"")&&z(i,l),_&2&&a!==(a=u[1].meta?.url||u[1].url)&&m(s,"href",a),_&2&&c!==(c=u[1].excerpt+"")&&(f.innerHTML=c),u[2].length?h?h.p(u,_):(h=Vn(u),h.c(),h.m(t,null)):h&&(h.d(1),h=null)},d(u){p&&p.d(u),u&&k(e),u&&k(t),h&&h.d()}}}function Ln(n){let e;return{c(){e=C("div"),m(e,"class","pagefind-ui__result-thumb pagefind-ui__loading svelte-j9e30")},m(t,r){S(t,e,r)},d(t){t&&k(e)}}}function qn(n){let e,t=n[1].meta.image&&Bn(n);return{c(){e=C("div"),t&&t.c(),m(e,"class","pagefind-ui__result-thumb svelte-j9e30")},m(r,s){S(r,e,s),t&&t.m(e,null)},p(r,s){r[1].meta.image?t?t.p(r,s):(t=Bn(r),t.c(),t.m(e,null)):t&&(t.d(1),t=null)},d(r){r&&k(e),t&&t.d()}}}function Bn(n){let e,t,r;return{c(){e=C("img"),m(e,"class","pagefind-ui__result-image svelte-j9e30"),ie(e.src,t=n[1].meta?.image)||m(e,"src",t),m(e,"alt",r=n[1].meta?.image_alt||n[1].meta?.title)},m(s,l){S(s,e,l)},p(s,l){l&2&&!ie(e.src,t=s[1].meta?.image)&&m(e,"src",t),l&2&&r!==(r=s[1].meta?.image_alt||s[1].meta?.title)&&m(e,"alt",r)},d(s){s&&k(e)}}}function Vn(n){let e,t=n[2],r=[];for(let s=0;sn.toLocaleUpperCase();function xr(n,e,t){let{show_images:r=!0}=e,{process_result:s=null}=e,{result:l={data:async()=>{}}}=e,i=["title","image","image_alt","url"],a,o=[],f=async d=>{t(1,a=await d.data()),t(1,a=s?.(a)??a),t(2,o=Object.entries(a.meta).filter(([p])=>!i.includes(p)))},c=(d=30)=>". ".repeat(Math.floor(10+Math.random()*d));return n.$$set=d=>{"show_images"in d&&t(0,r=d.show_images),"process_result"in d&&t(4,s=d.process_result),"result"in d&&t(5,l=d.result)},n.$$.update=()=>{if(n.$$.dirty&32)e:f(l)},[r,a,o,c,s,l]}var Mt=class extends q{constructor(e){super(),Y(this,e,xr,Qr,G,{show_images:0,process_result:4,result:5})}},Gn=Mt;function Jn(n,e,t){let r=n.slice();return r[11]=e[t][0],r[12]=e[t][1],r}function Yn(n,e,t){let r=n.slice();return r[15]=e[t],r}function $r(n){let e,t,r,s,l,i=n[0]&&Zn(n);return{c(){i&&i.c(),e=v(),t=C("div"),r=C("p"),r.textContent=`${n[5](30)}`,s=v(),l=C("p"),l.textContent=`${n[5](40)}`,m(r,"class","pagefind-ui__result-title pagefind-ui__loading svelte-4xnkmf"),m(l,"class","pagefind-ui__result-excerpt pagefind-ui__loading svelte-4xnkmf"),m(t,"class","pagefind-ui__result-inner svelte-4xnkmf")},m(a,o){i&&i.m(a,o),S(a,e,o),S(a,t,o),R(t,r),R(t,s),R(t,l)},p(a,o){a[0]?i||(i=Zn(a),i.c(),i.m(e.parentNode,e)):i&&(i.d(1),i=null)},d(a){i&&i.d(a),a&&k(e),a&&k(t)}}}function es(n){let e,t,r,s,l=n[1].meta?.title+"",i,a,o,f,c,d=n[0]&&Xn(n),p=n[4]&&xn(n),h=n[3],u=[];for(let E=0;En.toLocaleUpperCase();function ns(n,e,t){let{show_images:r=!0}=e,{process_result:s=null}=e,{result:l={data:async()=>{}}}=e,i=["title","image","image_alt","url"],a,o=[],f=[],c=!1,d=(u,_)=>{if(u.length<=_)return u;let E=[...u].sort((b,T)=>T.locations.length-b.locations.length).slice(0,3).map(b=>b.url);return u.filter(b=>E.includes(b.url))},p=async u=>{t(1,a=await u.data()),t(1,a=s?.(a)??a),t(2,o=Object.entries(a.meta).filter(([_])=>!i.includes(_))),Array.isArray(a.sub_results)&&(t(4,c=a.sub_results?.[0]?.url===(a.meta?.url||a.url)),c?t(3,f=d(a.sub_results.slice(1),3)):t(3,f=d([...a.sub_results],3)))},h=(u=30)=>". ".repeat(Math.floor(10+Math.random()*u));return n.$$set=u=>{"show_images"in u&&t(0,r=u.show_images),"process_result"in u&&t(6,s=u.process_result),"result"in u&&t(7,l=u.result)},n.$$.update=()=>{if(n.$$.dirty&128)e:p(l)},[r,a,o,f,c,h,s,l]}var At=class extends q{constructor(e){super(),Y(this,e,ns,ts,G,{show_images:0,process_result:6,result:7})}},rr=At;function sr(n,e,t){let r=n.slice();return r[10]=e[t][0],r[11]=e[t][1],r[12]=e,r[13]=t,r}function lr(n,e,t){let r=n.slice();return r[14]=e[t][0],r[15]=e[t][1],r[16]=e,r[17]=t,r}function ir(n){let e,t,r=n[4]("filters_label",n[5],n[6])+"",s,l,i=Object.entries(n[1]),a=[];for(let o=0;on.toLocaleUpperCase(),_r=n=>n.toLowerCase();function ss(n,e,t){let{available_filters:r=null}=e,{show_empty_filters:s=!0}=e,{open_filters:l=[]}=e,{translate:i=()=>""}=e,{automatic_translations:a={}}=e,{translations:o={}}=e,{selected_filters:f={}}=e,c=!1,d=!1;function p(h,u){f[`${h}:${u}`]=this.checked,t(0,f)}return n.$$set=h=>{"available_filters"in h&&t(1,r=h.available_filters),"show_empty_filters"in h&&t(2,s=h.show_empty_filters),"open_filters"in h&&t(3,l=h.open_filters),"translate"in h&&t(4,i=h.translate),"automatic_translations"in h&&t(5,a=h.automatic_translations),"translations"in h&&t(6,o=h.translations),"selected_filters"in h&&t(0,f=h.selected_filters)},n.$$.update=()=>{if(n.$$.dirty&258){e:if(r&&!c){t(8,c=!0);let h=Object.entries(r||{});h.length===1&&Object.entries(h[0][1])?.length<=6&&t(7,d=!0)}}},[f,r,s,l,i,a,o,d,c,p]}var yt=class extends q{constructor(e){super(),Y(this,e,ss,rs,G,{available_filters:1,show_empty_filters:2,open_filters:3,translate:4,automatic_translations:5,translations:6,selected_filters:0})}},fr=yt;var vt={};A(vt,{comments:()=>is,default:()=>us,direction:()=>as,strings:()=>os,thanks_to:()=>ls});var ls="Jan Claasen ",is="",as="ltr",os={placeholder:"Soek",clear_search:"Opruim",load_more:"Laai nog resultate",search_label:"Soek hierdie webwerf",filters_label:"Filters",zero_results:"Geen resultate vir [SEARCH_TERM]",many_results:"[COUNT] resultate vir [SEARCH_TERM]",one_result:"[COUNT] resultate vir [SEARCH_TERM]",alt_search:"Geen resultate vir [SEARCH_TERM]. Toon resultate vir [DIFFERENT_TERM] in plaas daarvan",search_suggestion:"Geen resultate vir [SEARCH_TERM]. Probeer eerder een van die volgende terme:",searching:"Soek vir [SEARCH_TERM]"},us={thanks_to:ls,comments:is,direction:as,strings:os};var Ht={};A(Ht,{comments:()=>_s,default:()=>hs,direction:()=>fs,strings:()=>ds,thanks_to:()=>cs});var cs="Jermanuts",_s="",fs="rtl",ds={placeholder:"\u0628\u062D\u062B",clear_search:"\u0627\u0645\u0633\u062D",load_more:"\u062D\u0645\u0651\u0650\u0644 \u0627\u0644\u0645\u0632\u064A\u062F \u0645\u0646 \u0627\u0644\u0646\u062A\u0627\u0626\u062C",search_label:"\u0627\u0628\u062D\u062B \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u0645\u0648\u0642\u0639",filters_label:"\u062A\u0635\u0641\u064A\u0627\u062A",zero_results:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]",many_results:"[COUNT] \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]",one_result:"[COUNT] \u0646\u062A\u064A\u062C\u0629 \u0644 [SEARCH_TERM]",alt_search:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]. \u064A\u0639\u0631\u0636 \u0627\u0644\u0646\u062A\u0627\u0626\u062C \u0644 [DIFFERENT_TERM] \u0628\u062F\u0644\u0627\u064B \u0645\u0646 \u0630\u0644\u0643",search_suggestion:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C \u0644 [SEARCH_TERM]. \u062C\u0631\u0628 \u0623\u062D\u062F \u0639\u0645\u0644\u064A\u0627\u062A \u0627\u0644\u0628\u062D\u062B \u0627\u0644\u062A\u0627\u0644\u064A\u0629:",searching:"\u064A\u0628\u062D\u062B \u0639\u0646 [SEARCH_TERM]..."},hs={thanks_to:cs,comments:_s,direction:fs,strings:ds};var wt={};A(wt,{comments:()=>ps,default:()=>Rs,direction:()=>gs,strings:()=>Es,thanks_to:()=>ms});var ms="Maruf Alom ",ps="",gs="ltr",Es={placeholder:"\u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u0995\u09B0\u09C1\u09A8",clear_search:"\u09AE\u09C1\u099B\u09C7 \u09AB\u09C7\u09B2\u09C1\u09A8",load_more:"\u0986\u09B0\u09CB \u09AB\u09B2\u09BE\u09AB\u09B2 \u09A6\u09C7\u0996\u09C1\u09A8",search_label:"\u098F\u0987 \u0993\u09DF\u09C7\u09AC\u09B8\u09BE\u0987\u099F\u09C7 \u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u0995\u09B0\u09C1\u09A8",filters_label:"\u09AB\u09BF\u09B2\u09CD\u099F\u09BE\u09B0",zero_results:"[SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF",many_results:"[COUNT]-\u099F\u09BF \u09AB\u09B2\u09BE\u09AB\u09B2 \u09AA\u09BE\u0993\u09DF\u09BE \u0997\u09BF\u09DF\u09C7\u099B\u09C7 [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF",one_result:"[COUNT]-\u099F\u09BF \u09AB\u09B2\u09BE\u09AB\u09B2 \u09AA\u09BE\u0993\u09DF\u09BE \u0997\u09BF\u09DF\u09C7\u099B\u09C7 [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF",alt_search:"\u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF. \u09AA\u09B0\u09BF\u09AC\u09B0\u09CD\u09A4\u09C7 [DIFFERENT_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF \u09A6\u09C7\u0996\u09BE\u09A8\u09CB \u09B9\u099A\u09CD\u099B\u09C7",search_suggestion:"\u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF [SEARCH_TERM] \u098F\u09B0 \u09AC\u09BF\u09B7\u09DF\u09C7. \u09A8\u09BF\u09A8\u09CD\u09AE\u09C7\u09B0 \u09AC\u09BF\u09B7\u09DF\u09AC\u09B8\u09CD\u09A4\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09A6\u09C7\u0996\u09C1\u09A8:",searching:"\u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u099A\u09B2\u099B\u09C7 [SEARCH_TERM]..."},Rs={thanks_to:ms,comments:ps,direction:gs,strings:Es};var Ft={};A(Ft,{comments:()=>Ts,default:()=>Ss,direction:()=>Cs,strings:()=>ks,thanks_to:()=>bs});var bs="Pablo Villaverde ",Ts="",Cs="ltr",ks={placeholder:"Cerca",clear_search:"Netejar",load_more:"Veure m\xE9s resultats",search_label:"Cerca en aquest lloc",filters_label:"Filtres",zero_results:"No es van trobar resultats per [SEARCH_TERM]",many_results:"[COUNT] resultats trobats per [SEARCH_TERM]",one_result:"[COUNT] resultat trobat per [SEARCH_TERM]",alt_search:"No es van trobar resultats per [SEARCH_TERM]. Mostrant al seu lloc resultats per [DIFFERENT_TERM]",search_suggestion:"No es van trobar resultats per [SEARCH_TERM]. Proveu una de les cerques seg\xFCents:",searching:"Cercant [SEARCH_TERM]..."},Ss={thanks_to:bs,comments:Ts,direction:Cs,strings:ks};var Nt={};A(Nt,{comments:()=>As,default:()=>Hs,direction:()=>ys,strings:()=>vs,thanks_to:()=>Ms});var Ms="Dalibor Hon ",As="",ys="ltr",vs={placeholder:"Hledat",clear_search:"Smazat",load_more:"Na\u010D\xEDst dal\u0161\xED v\xFDsledky",search_label:"Prohledat tuto str\xE1nku",filters_label:"Filtry",zero_results:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]",many_results:"[COUNT] v\xFDsledk\u016F pro [SEARCH_TERM]",one_result:"[COUNT] v\xFDsledek pro [SEARCH_TERM]",alt_search:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]. Zobrazuj\xED se v\xFDsledky pro [DIFFERENT_TERM]",search_suggestion:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]. Souvisej\xEDc\xED v\xFDsledky hled\xE1n\xED:",searching:"Hled\xE1m [SEARCH_TERM]..."},Hs={thanks_to:Ms,comments:As,direction:ys,strings:vs};var zt={};A(zt,{comments:()=>Fs,default:()=>Os,direction:()=>Ns,strings:()=>zs,thanks_to:()=>ws});var ws="Jonas Smedegaard ",Fs="",Ns="ltr",zs={placeholder:"S\xF8g",clear_search:"Nulstil",load_more:"Indl\xE6s flere resultater",search_label:"S\xF8g p\xE5 dette website",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v et af disse s\xF8geord i stedet:",searching:"S\xF8ger efter [SEARCH_TERM]..."},Os={thanks_to:ws,comments:Fs,direction:Ns,strings:zs};var Ot={};A(Ot,{comments:()=>Us,default:()=>Ps,direction:()=>Ds,strings:()=>Is,thanks_to:()=>js});var js="Jan Claasen ",Us="",Ds="ltr",Is={placeholder:"Suche",clear_search:"L\xF6schen",load_more:"Mehr Ergebnisse laden",search_label:"Suche diese Seite",filters_label:"Filter",zero_results:"Keine Ergebnisse f\xFCr [SEARCH_TERM]",many_results:"[COUNT] Ergebnisse f\xFCr [SEARCH_TERM]",one_result:"[COUNT] Ergebnis f\xFCr [SEARCH_TERM]",alt_search:"Keine Ergebnisse f\xFCr [SEARCH_TERM]. Stattdessen werden Ergebnisse f\xFCr [DIFFERENT_TERM] angezeigt",search_suggestion:"Keine Ergebnisse f\xFCr [SEARCH_TERM]. Versuchen Sie eine der folgenden Suchen:",searching:"Suche f\xFCr [SEARCH_TERM]"},Ps={thanks_to:js,comments:Us,direction:Ds,strings:Is};var jt={};A(jt,{comments:()=>qs,default:()=>Ws,direction:()=>Bs,strings:()=>Vs,thanks_to:()=>Ls});var Ls="Liam Bigelow ",qs="",Bs="ltr",Vs={placeholder:"Search",clear_search:"Clear",load_more:"Load more results",search_label:"Search this site",filters_label:"Filters",zero_results:"No results for [SEARCH_TERM]",many_results:"[COUNT] results for [SEARCH_TERM]",one_result:"[COUNT] result for [SEARCH_TERM]",alt_search:"No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead",search_suggestion:"No results for [SEARCH_TERM]. Try one of the following searches:",searching:"Searching for [SEARCH_TERM]..."},Ws={thanks_to:Ls,comments:qs,direction:Bs,strings:Vs};var Ut={};A(Ut,{comments:()=>Gs,default:()=>Zs,direction:()=>Js,strings:()=>Ys,thanks_to:()=>Ks});var Ks="Pablo Villaverde ",Gs="",Js="ltr",Ys={placeholder:"Buscar",clear_search:"Limpiar",load_more:"Ver m\xE1s resultados",search_label:"Buscar en este sitio",filters_label:"Filtros",zero_results:"No se encontraron resultados para [SEARCH_TERM]",many_results:"[COUNT] resultados encontrados para [SEARCH_TERM]",one_result:"[COUNT] resultado encontrado para [SEARCH_TERM]",alt_search:"No se encontraron resultados para [SEARCH_TERM]. Mostrando en su lugar resultados para [DIFFERENT_TERM]",search_suggestion:"No se encontraron resultados para [SEARCH_TERM]. Prueba una de las siguientes b\xFAsquedas:",searching:"Buscando [SEARCH_TERM]..."},Zs={thanks_to:Ks,comments:Gs,direction:Js,strings:Ys};var Dt={};A(Dt,{comments:()=>Qs,default:()=>el,direction:()=>xs,strings:()=>$s,thanks_to:()=>Xs});var Xs="Mikel Larreategi ",Qs="",xs="ltr",$s={placeholder:"Bilatu",clear_search:"Garbitu",load_more:"Kargatu emaitza gehiagi",search_label:"Bilatu",filters_label:"Iragazkiak",zero_results:"Ez dago emaitzarik [SEARCH_TERM] bilaketarentzat",many_results:"[COUNT] emaitza [SEARCH_TERM] bilaketarentzat",one_result:"Emaitza bat [COUNT] [SEARCH_TERM] bilaketarentzat",alt_search:"Ez dago emaitzarik [SEARCH_TERM] bilaketarentzat. [DIFFERENT_TERM] bilaketaren emaitzak erakusten",search_suggestion:"Ez dago emaitzarik [SEARCH_TERM] bilaketarentzat. Saiatu hauetako beste bateikin:",searching:"[SEARCH_TERM] bilatzen..."},el={thanks_to:Xs,comments:Qs,direction:xs,strings:$s};var It={};A(It,{comments:()=>nl,default:()=>ll,direction:()=>rl,strings:()=>sl,thanks_to:()=>tl});var tl="Ali Khaleqi Yekta ",nl="",rl="rtl",sl={placeholder:"\u062C\u0633\u062A\u062C\u0648",clear_search:"\u067E\u0627\u06A9\u0633\u0627\u0632\u06CC",load_more:"\u0628\u0627\u0631\u06AF\u0630\u0627\u0631\u06CC \u0646\u062A\u0627\u06CC\u062C \u0628\u06CC\u0634\u062A\u0631",search_label:"\u062C\u0633\u062A\u062C\u0648 \u062F\u0631 \u0633\u0627\u06CC\u062A",filters_label:"\u0641\u06CC\u0644\u062A\u0631\u0647\u0627",zero_results:"\u0646\u062A\u06CC\u062C\u0647\u200C\u0627\u06CC \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0646\u0634\u062F",many_results:"[COUNT] \u0646\u062A\u06CC\u062C\u0647 \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0634\u062F",one_result:"[COUNT] \u0646\u062A\u06CC\u062C\u0647 \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0634\u062F",alt_search:"\u0646\u062A\u06CC\u062C\u0647\u200C\u0627\u06CC \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0646\u0634\u062F. \u062F\u0631 \u0639\u0648\u0636 \u0646\u062A\u0627\u06CC\u062C \u0628\u0631\u0627\u06CC [DIFFERENT_TERM] \u0646\u0645\u0627\u06CC\u0634 \u062F\u0627\u062F\u0647 \u0645\u06CC\u200C\u0634\u0648\u062F",search_suggestion:"\u0646\u062A\u06CC\u062C\u0647\u200C\u0627\u06CC \u0628\u0631\u0627\u06CC [SEARCH_TERM] \u06CC\u0627\u0641\u062A \u0646\u0634\u062F. \u06CC\u06A9\u06CC \u0627\u0632 \u062C\u0633\u062A\u062C\u0648\u0647\u0627\u06CC \u0632\u06CC\u0631 \u0631\u0627 \u0627\u0645\u062A\u062D\u0627\u0646 \u06A9\u0646\u06CC\u062F:",searching:"\u062F\u0631 \u062D\u0627\u0644 \u062C\u0633\u062A\u062C\u0648\u06CC [SEARCH_TERM]..."},ll={thanks_to:tl,comments:nl,direction:rl,strings:sl};var Pt={};A(Pt,{comments:()=>al,default:()=>cl,direction:()=>ol,strings:()=>ul,thanks_to:()=>il});var il="Valtteri Laitinen ",al="",ol="ltr",ul={placeholder:"Haku",clear_search:"Tyhjenn\xE4",load_more:"Lataa lis\xE4\xE4 tuloksia",search_label:"Hae t\xE4lt\xE4 sivustolta",filters_label:"Suodattimet",zero_results:"Ei tuloksia haulle [SEARCH_TERM]",many_results:"[COUNT] tulosta haulle [SEARCH_TERM]",one_result:"[COUNT] tulos haulle [SEARCH_TERM]",alt_search:"Ei tuloksia haulle [SEARCH_TERM]. N\xE4ytet\xE4\xE4n tulokset sen sijaan haulle [DIFFERENT_TERM]",search_suggestion:"Ei tuloksia haulle [SEARCH_TERM]. Kokeile jotain seuraavista:",searching:"Haetaan [SEARCH_TERM]..."},cl={thanks_to:il,comments:al,direction:ol,strings:ul};var Lt={};A(Lt,{comments:()=>fl,default:()=>ml,direction:()=>dl,strings:()=>hl,thanks_to:()=>_l});var _l="Nicolas Friedli ",fl="",dl="ltr",hl={placeholder:"Rechercher",clear_search:"Nettoyer",load_more:"Charger plus de r\xE9sultats",search_label:"Recherche sur ce site",filters_label:"Filtres",zero_results:"Pas de r\xE9sultat pour [SEARCH_TERM]",many_results:"[COUNT] r\xE9sultats pour [SEARCH_TERM]",one_result:"[COUNT] r\xE9sultat pour [SEARCH_TERM]",alt_search:"Pas de r\xE9sultat pour [SEARCH_TERM]. Montre les r\xE9sultats pour [DIFFERENT_TERM] \xE0 la place",search_suggestion:"Pas de r\xE9sultat pour [SEARCH_TERM]. Essayer une des recherches suivantes:",searching:"Recherche [SEARCH_TERM]..."},ml={thanks_to:_l,comments:fl,direction:dl,strings:hl};var qt={};A(qt,{comments:()=>gl,default:()=>bl,direction:()=>El,strings:()=>Rl,thanks_to:()=>pl});var pl="Pablo Villaverde ",gl="",El="ltr",Rl={placeholder:"Buscar",clear_search:"Limpar",load_more:"Ver m\xE1is resultados",search_label:"Buscar neste sitio",filters_label:"Filtros",zero_results:"Non se atoparon resultados para [SEARCH_TERM]",many_results:"[COUNT] resultados atopados para [SEARCH_TERM]",one_result:"[COUNT] resultado atopado para [SEARCH_TERM]",alt_search:"Non se atoparon resultados para [SEARCH_TERM]. Amosando no seu lugar resultados para [DIFFERENT_TERM]",search_suggestion:"Non se atoparon resultados para [SEARCH_TERM]. Probe unha das seguintes pesquisas:",searching:"Buscando [SEARCH_TERM]..."},bl={thanks_to:pl,comments:gl,direction:El,strings:Rl};var Bt={};A(Bt,{comments:()=>Cl,default:()=>Ml,direction:()=>kl,strings:()=>Sl,thanks_to:()=>Tl});var Tl="Nir Tamir ",Cl="",kl="rtl",Sl={placeholder:"\u05D7\u05D9\u05E4\u05D5\u05E9",clear_search:"\u05E0\u05D9\u05E7\u05D5\u05D9",load_more:"\u05E2\u05D5\u05D3 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA",search_label:"\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05D0\u05EA\u05E8 \u05D6\u05D4",filters_label:"\u05DE\u05E1\u05E0\u05E0\u05D9\u05DD",zero_results:"\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]",many_results:"\u05E0\u05DE\u05E6\u05D0\u05D5 [COUNT] \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]",one_result:"\u05E0\u05DE\u05E6\u05D0\u05D4 \u05EA\u05D5\u05E6\u05D0\u05D4 \u05D0\u05D7\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]",alt_search:"\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]. \u05DE\u05D5\u05E6\u05D2\u05D5\u05EA \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [DIFFERENT_TERM]",search_suggestion:"\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E2\u05D1\u05D5\u05E8 [SEARCH_TERM]. \u05E0\u05E1\u05D5 \u05D0\u05D7\u05D3 \u05DE\u05D4\u05D7\u05D9\u05E4\u05D5\u05E9\u05D9\u05DD \u05D4\u05D1\u05D0\u05D9\u05DD:",searching:"\u05DE\u05D7\u05E4\u05E9 \u05D0\u05EA [SEARCH_TERM]..."},Ml={thanks_to:Tl,comments:Cl,direction:kl,strings:Sl};var Vt={};A(Vt,{comments:()=>yl,default:()=>wl,direction:()=>vl,strings:()=>Hl,thanks_to:()=>Al});var Al="Amit Yadav ",yl="",vl="ltr",Hl={placeholder:"\u0916\u094B\u091C\u0947\u0902",clear_search:"\u0938\u093E\u092B \u0915\u0930\u0947\u0902",load_more:"\u0914\u0930 \u0905\u0927\u093F\u0915 \u092A\u0930\u093F\u0923\u093E\u092E \u0932\u094B\u0921 \u0915\u0930\u0947\u0902",search_label:"\u0907\u0938 \u0938\u093E\u0907\u091F \u092E\u0947\u0902 \u0916\u094B\u091C\u0947\u0902",filters_label:"\u092B\u093C\u093F\u0932\u094D\u091F\u0930",zero_results:"\u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E",many_results:"[COUNT] \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u092E\u093F\u0932\u0947",one_result:"[COUNT] \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u092E\u093F\u0932\u093E",alt_search:"[SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964 \u0907\u0938\u0915\u0947 \u092C\u091C\u093E\u092F [DIFFERENT_TERM] \u0915\u0947 \u0932\u093F\u090F \u092A\u0930\u093F\u0923\u093E\u092E \u0926\u093F\u0916\u093E \u0930\u0939\u093E \u0939\u0948",search_suggestion:"[SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964 \u0928\u093F\u092E\u094D\u0928\u0932\u093F\u0916\u093F\u0924 \u0916\u094B\u091C\u094B\u0902 \u092E\u0947\u0902 \u0938\u0947 \u0915\u094B\u0908 \u090F\u0915 \u0906\u091C\u093C\u092E\u093E\u090F\u0902:",searching:"[SEARCH_TERM] \u0915\u0940 \u0916\u094B\u091C \u0915\u0940 \u091C\u093E \u0930\u0939\u0940 \u0939\u0948..."},wl={thanks_to:Al,comments:yl,direction:vl,strings:Hl};var Wt={};A(Wt,{comments:()=>Nl,default:()=>jl,direction:()=>zl,strings:()=>Ol,thanks_to:()=>Fl});var Fl="Diomed ",Nl="",zl="ltr",Ol={placeholder:"Tra\u017Ei",clear_search:"O\u010Disti",load_more:"U\u010Ditaj vi\u0161e rezultata",search_label:"Pretra\u017Ei ovu stranicu",filters_label:"Filteri",zero_results:"Nema rezultata za [SEARCH_TERM]",many_results:"[COUNT] rezultata za [SEARCH_TERM]",one_result:"[COUNT] rezultat za [SEARCH_TERM]",alt_search:"Nema rezultata za [SEARCH_TERM]. Prikazujem rezultate za [DIFFERENT_TERM]",search_suggestion:"Nema rezultata za [SEARCH_TERM]. Poku\u0161aj s jednom od ovih pretraga:",searching:"Pretra\u017Eujem [SEARCH_TERM]..."},jl={thanks_to:Fl,comments:Nl,direction:zl,strings:Ol};var Kt={};A(Kt,{comments:()=>Dl,default:()=>Ll,direction:()=>Il,strings:()=>Pl,thanks_to:()=>Ul});var Ul="Adam Laki ",Dl="",Il="ltr",Pl={placeholder:"Keres\xE9s",clear_search:"T\xF6rl\xE9s",load_more:"Tov\xE1bbi tal\xE1latok bet\xF6lt\xE9se",search_label:"Keres\xE9s az oldalon",filters_label:"Sz\u0171r\xE9s",zero_results:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",many_results:"[COUNT] db tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",one_result:"[COUNT] db tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",alt_search:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre. Tal\xE1latok mutat\xE1sa ink\xE1bb a(z) [DIFFERENT_TERM] kifejez\xE9sre",search_suggestion:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre. Pr\xF3b\xE1ld meg a k\xF6vetkez\u0151 keres\xE9sek egyik\xE9t:",searching:"Keres\xE9s a(z) [SEARCH_TERM] kifejez\xE9sre..."},Ll={thanks_to:Ul,comments:Dl,direction:Il,strings:Pl};var Gt={};A(Gt,{comments:()=>Bl,default:()=>Kl,direction:()=>Vl,strings:()=>Wl,thanks_to:()=>ql});var ql="Nixentric",Bl="",Vl="ltr",Wl={placeholder:"Cari",clear_search:"Bersihkan",load_more:"Muat lebih banyak hasil",search_label:"Telusuri situs ini",filters_label:"Filter",zero_results:"[SEARCH_TERM] tidak ditemukan",many_results:"Ditemukan [COUNT] hasil untuk [SEARCH_TERM]",one_result:"Ditemukan [COUNT] hasil untuk [SEARCH_TERM]",alt_search:"[SEARCH_TERM] tidak ditemukan. Menampilkan hasil [DIFFERENT_TERM] sebagai gantinya",search_suggestion:"[SEARCH_TERM] tidak ditemukan. Coba salah satu pencarian berikut ini:",searching:"Mencari [SEARCH_TERM]..."},Kl={thanks_to:ql,comments:Bl,direction:Vl,strings:Wl};var Jt={};A(Jt,{comments:()=>Jl,default:()=>Xl,direction:()=>Yl,strings:()=>Zl,thanks_to:()=>Gl});var Gl="Cosette Bruhns Alonso, Andrew Janco ",Jl="",Yl="ltr",Zl={placeholder:"Cerca",clear_search:"Cancella la cronologia",load_more:"Mostra pi\xF9 risultati",search_label:"Cerca nel sito",filters_label:"Filtri di ricerca",zero_results:"Nessun risultato per [SEARCH_TERM]",many_results:"[COUNT] risultati per [SEARCH_TERM]",one_result:"[COUNT] risultato per [SEARCH_TERM]",alt_search:"Nessun risultato per [SEARCH_TERM]. Mostrando risultati per [DIFFERENT_TERM] come alternativa.",search_suggestion:"Nessun risultato per [SEARCH_TERM]. Prova una delle seguenti ricerche:",searching:"Cercando [SEARCH_TERM]..."},Xl={thanks_to:Gl,comments:Jl,direction:Yl,strings:Zl};var Yt={};A(Yt,{comments:()=>xl,default:()=>ti,direction:()=>$l,strings:()=>ei,thanks_to:()=>Ql});var Ql="Tate",xl="",$l="ltr",ei={placeholder:"\u691C\u7D22",clear_search:"\u30AF\u30EA\u30A2",load_more:"\u6B21\u3092\u8AAD\u307F\u8FBC\u3080",search_label:"\u3053\u306E\u30B5\u30A4\u30C8\u3092\u691C\u7D22",filters_label:"\u30D5\u30A3\u30EB\u30BF",zero_results:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F",many_results:"[SEARCH_TERM]\u306E[COUNT]\u4EF6\u306E\u691C\u7D22\u7D50\u679C",one_result:"[SEARCH_TERM]\u306E[COUNT]\u4EF6\u306E\u691C\u7D22\u7D50\u679C",alt_search:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002[DIFFERENT_TERM]\u306E\u691C\u7D22\u7D50\u679C\u3092\u8868\u793A\u3057\u3066\u3044\u307E\u3059",search_suggestion:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6B21\u306E\u3044\u305A\u308C\u304B\u306E\u691C\u7D22\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044",searching:"[SEARCH_TERM]\u3092\u691C\u7D22\u3057\u3066\u3044\u307E\u3059"},ti={thanks_to:Ql,comments:xl,direction:$l,strings:ei};var Zt={};A(Zt,{comments:()=>ri,default:()=>ii,direction:()=>si,strings:()=>li,thanks_to:()=>ni});var ni="Seokho Son ",ri="",si="ltr",li={placeholder:"\uAC80\uC0C9\uC5B4",clear_search:"\uBE44\uC6B0\uAE30",load_more:"\uAC80\uC0C9 \uACB0\uACFC \uB354 \uBCF4\uAE30",search_label:"\uC0AC\uC774\uD2B8 \uAC80\uC0C9",filters_label:"\uD544\uD130",zero_results:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C",many_results:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC [COUNT]\uAC74",one_result:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC [COUNT]\uAC74",alt_search:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C. [DIFFERENT_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC",search_suggestion:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C. \uCD94\uCC9C \uAC80\uC0C9\uC5B4: ",searching:"[SEARCH_TERM] \uAC80\uC0C9 \uC911..."},ii={thanks_to:ni,comments:ri,direction:si,strings:li};var Xt={};A(Xt,{comments:()=>oi,default:()=>_i,direction:()=>ui,strings:()=>ci,thanks_to:()=>ai});var ai="",oi="",ui="ltr",ci={placeholder:"Rapu",clear_search:"Whakakore",load_more:"Whakauta \u0113tahi otinga k\u0113",search_label:"Rapu",filters_label:"T\u0101tari",zero_results:"Otinga kore ki [SEARCH_TERM]",many_results:"[COUNT] otinga ki [SEARCH_TERM]",one_result:"[COUNT] otinga ki [SEARCH_TERM]",alt_search:"Otinga kore ki [SEARCH_TERM]. Otinga k\u0113 ki [DIFFERENT_TERM]",search_suggestion:"Otinga kore ki [SEARCH_TERM]. whakam\u0101tau ki ng\u0101 mea atu:",searching:"Rapu ki [SEARCH_TERM]..."},_i={thanks_to:ai,comments:oi,direction:ui,strings:ci};var Qt={};A(Qt,{comments:()=>di,default:()=>pi,direction:()=>hi,strings:()=>mi,thanks_to:()=>fi});var fi="Harry Min Khant ",di="",hi="ltr",mi={placeholder:"\u101B\u103E\u102C\u101B\u1014\u103A",clear_search:"\u101B\u103E\u102C\u1016\u103D\u1031\u1019\u103E\u102F\u1000\u102D\u102F \u101B\u103E\u1004\u103A\u1038\u101C\u1004\u103A\u1038\u1015\u102B\u104B",load_more:"\u1014\u1031\u102C\u1000\u103A\u1011\u1015\u103A\u101B\u101C\u1012\u103A\u1019\u103B\u102C\u1038\u1000\u102D\u102F \u1010\u1004\u103A\u1015\u102B\u104B",search_label:"\u1024\u1006\u102D\u102F\u1000\u103A\u1010\u103D\u1004\u103A\u101B\u103E\u102C\u1016\u103D\u1031\u1015\u102B\u104B",filters_label:"\u1005\u1005\u103A\u1011\u102F\u1010\u103A\u1019\u103E\u102F\u1019\u103B\u102C\u1038",zero_results:"[SEARCH_TERM] \u1021\u1010\u103D\u1000\u103A \u101B\u101C\u1012\u103A\u1019\u103B\u102C\u1038 \u1019\u101B\u103E\u102D\u1015\u102B",many_results:"[SEARCH_TERM] \u1021\u1010\u103D\u1000\u103A \u101B\u101C\u1012\u103A [COUNT] \u1001\u102F",one_result:"[SEARCH_TERM] \u1021\u1010\u103D\u1000\u103A \u101B\u101C\u1012\u103A [COUNT]",alt_search:"[SEARCH_TERM] \u1021\u1010\u103D\u1000\u103A \u101B\u101C\u1012\u103A\u1019\u101B\u103E\u102D\u1015\u102B\u104B \u104E\u1004\u103A\u1038\u1021\u1005\u102C\u1038 [DIFFERENT_TERM] \u1021\u1010\u103D\u1000\u103A \u101B\u101C\u1012\u103A\u1019\u103B\u102C\u1038\u1000\u102D\u102F \u1015\u103C\u101E\u101E\u100A\u103A\u104B",search_suggestion:"[SEARCH_TERM] \u1021\u1010\u103D\u1000\u103A \u101B\u101C\u1012\u103A\u1019\u101B\u103E\u102D\u1015\u102B\u104B \u1021\u1031\u102C\u1000\u103A\u1015\u102B\u101B\u103E\u102C\u1016\u103D\u1031\u1019\u103E\u102F\u1019\u103B\u102C\u1038\u1011\u1032\u1019\u103E \u1010\u1005\u103A\u1001\u102F\u1000\u102D\u102F \u1005\u1019\u103A\u1038\u1000\u103C\u100A\u1037\u103A\u1015\u102B:",searching:"[SEARCH_TERM] \u1000\u102D\u102F \u101B\u103E\u102C\u1016\u103D\u1031\u1014\u1031\u101E\u100A\u103A..."},pi={thanks_to:fi,comments:di,direction:hi,strings:mi};var xt={};A(xt,{comments:()=>Ei,default:()=>Ti,direction:()=>Ri,strings:()=>bi,thanks_to:()=>gi});var gi="Eirik Mikkelsen",Ei="",Ri="ltr",bi={placeholder:"S\xF8k",clear_search:"Fjern",load_more:"Last flere resultater",search_label:"S\xF8k p\xE5 denne siden",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v en av disse s\xF8keordene i stedet:",searching:"S\xF8ker etter [SEARCH_TERM]"},Ti={thanks_to:gi,comments:Ei,direction:Ri,strings:bi};var $t={};A($t,{comments:()=>ki,default:()=>Ai,direction:()=>Si,strings:()=>Mi,thanks_to:()=>Ci});var Ci="Paul van Brouwershaven",ki="",Si="ltr",Mi={placeholder:"Zoeken",clear_search:"Reset",load_more:"Meer resultaten laden",search_label:"Doorzoek deze site",filters_label:"Filters",zero_results:"Geen resultaten voor [SEARCH_TERM]",many_results:"[COUNT] resultaten voor [SEARCH_TERM]",one_result:"[COUNT] resultaat voor [SEARCH_TERM]",alt_search:"Geen resultaten voor [SEARCH_TERM]. In plaats daarvan worden resultaten voor [DIFFERENT_TERM] weergegeven",search_suggestion:"Geen resultaten voor [SEARCH_TERM]. Probeer een van de volgende zoekopdrachten:",searching:"Zoeken naar [SEARCH_TERM]..."},Ai={thanks_to:Ci,comments:ki,direction:Si,strings:Mi};var en={};A(en,{comments:()=>vi,default:()=>Fi,direction:()=>Hi,strings:()=>wi,thanks_to:()=>yi});var yi="Eirik Mikkelsen",vi="",Hi="ltr",wi={placeholder:"S\xF8k",clear_search:"Fjern",load_more:"Last fleire resultat",search_label:"S\xF8k p\xE5 denne sida",filters_label:"Filter",zero_results:"Ingen resultat for [SEARCH_TERM]",many_results:"[COUNT] resultat for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultat for [SEARCH_TERM]. Viser resultat for [DIFFERENT_TERM] i staden",search_suggestion:"Ingen resultat for [SEARCH_TERM]. Pr\xF8v eitt av desse s\xF8keorda i staden:",searching:"S\xF8ker etter [SEARCH_TERM]"},Fi={thanks_to:yi,comments:vi,direction:Hi,strings:wi};var tn={};A(tn,{comments:()=>zi,default:()=>Ui,direction:()=>Oi,strings:()=>ji,thanks_to:()=>Ni});var Ni="Christopher Wingate",zi="",Oi="ltr",ji={placeholder:"S\xF8k",clear_search:"Fjern",load_more:"Last flere resultater",search_label:"S\xF8k p\xE5 denne siden",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v en av disse s\xF8keordene i stedet:",searching:"S\xF8ker etter [SEARCH_TERM]"},Ui={thanks_to:Ni,comments:zi,direction:Oi,strings:ji};var nn={};A(nn,{comments:()=>Ii,default:()=>qi,direction:()=>Pi,strings:()=>Li,thanks_to:()=>Di});var Di="",Ii="",Pi="ltr",Li={placeholder:"Szukaj",clear_search:"Wyczy\u015B\u0107",load_more:"Za\u0142aduj wi\u0119cej",search_label:"Przeszukaj t\u0119 stron\u0119",filters_label:"Filtry",zero_results:"Brak wynik\xF3w dla [SEARCH_TERM]",many_results:"[COUNT] wynik\xF3w dla [SEARCH_TERM]",one_result:"[COUNT] wynik dla [SEARCH_TERM]",alt_search:"Brak wynik\xF3w dla [SEARCH_TERM]. Wy\u015Bwietlam wyniki dla [DIFFERENT_TERM]",search_suggestion:"Brak wynik\xF3w dla [SEARCH_TERM]. Pokrewne wyniki wyszukiwania:",searching:"Szukam [SEARCH_TERM]..."},qi={thanks_to:Di,comments:Ii,direction:Pi,strings:Li};var rn={};A(rn,{comments:()=>Vi,default:()=>Gi,direction:()=>Wi,strings:()=>Ki,thanks_to:()=>Bi});var Bi="Jonatah",Vi="",Wi="ltr",Ki={placeholder:"Pesquisar",clear_search:"Limpar",load_more:"Ver mais resultados",search_label:"Pesquisar",filters_label:"Filtros",zero_results:"Nenhum resultado encontrado para [SEARCH_TERM]",many_results:"[COUNT] resultados encontrados para [SEARCH_TERM]",one_result:"[COUNT] resultado encontrado para [SEARCH_TERM]",alt_search:"Nenhum resultado encontrado para [SEARCH_TERM]. Exibindo resultados para [DIFFERENT_TERM]",search_suggestion:"Nenhum resultado encontrado para [SEARCH_TERM]. Tente uma das seguintes pesquisas:",searching:"Pesquisando por [SEARCH_TERM]..."},Gi={thanks_to:Bi,comments:Vi,direction:Wi,strings:Ki};var sn={};A(sn,{comments:()=>Yi,default:()=>Qi,direction:()=>Zi,strings:()=>Xi,thanks_to:()=>Ji});var Ji="Bogdan Mateescu ",Yi="",Zi="ltr",Xi={placeholder:"C\u0103utare",clear_search:"\u015Eterge\u0163i",load_more:"\xCEnc\u0103rca\u021Bi mai multe rezultate",search_label:"C\u0103uta\u021Bi \xEEn acest site",filters_label:"Filtre",zero_results:"Niciun rezultat pentru [SEARCH_TERM]",many_results:"[COUNT] rezultate pentru [SEARCH_TERM]",one_result:"[COUNT] rezultat pentru [SEARCH_TERM]",alt_search:"Niciun rezultat pentru [SEARCH_TERM]. Se afi\u0219eaz\u0103 \xEEn schimb rezultatele pentru [DIFFERENT_TERM]",search_suggestion:"Niciun rezultat pentru [SEARCH_TERM]. \xCEncerca\u021Bi una dintre urm\u0103toarele c\u0103ut\u0103ri:",searching:"Se caut\u0103 dup\u0103: [SEARCH_TERM]..."},Qi={thanks_to:Ji,comments:Yi,direction:Zi,strings:Xi};var ln={};A(ln,{comments:()=>$i,default:()=>na,direction:()=>ea,strings:()=>ta,thanks_to:()=>xi});var xi="Aleksandr Gordeev",$i="",ea="ltr",ta={placeholder:"\u041F\u043E\u0438\u0441\u043A",clear_search:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C \u043F\u043E\u043B\u0435",load_more:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0435\u0449\u0435",search_label:"\u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0441\u0430\u0439\u0442\u0443",filters_label:"\u0424\u0438\u043B\u044C\u0442\u0440\u044B",zero_results:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432 \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",alt_search:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]. \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u044B \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [DIFFERENT_TERM]",search_suggestion:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]. \u041F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0438\u0437 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u043E\u0432",searching:"\u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]"},na={thanks_to:xi,comments:$i,direction:ea,strings:ta};var an={};A(an,{comments:()=>sa,default:()=>aa,direction:()=>la,strings:()=>ia,thanks_to:()=>ra});var ra="Andrija Sagicc",sa="",la="ltr",ia={placeholder:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430",clear_search:"\u0411\u0440\u0438\u0441\u0430\u045A\u0435",load_more:"\u041F\u0440\u0438\u043A\u0430\u0437 \u0432\u0438\u0448\u0435 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430",search_label:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0441\u0430\u0458\u0442\u0430",filters_label:"\u0424\u0438\u043B\u0442\u0435\u0440\u0438",zero_results:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",alt_search:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]. \u041F\u0440\u0438\u043A\u0430\u0437 \u0434\u043E\u0434\u0430\u0442\u043D\u0438\u043A \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [DIFFERENT_TERM]",search_suggestion:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]. \u041F\u043E\u043A\u0443\u0448\u0430\u0458\u0442\u0435 \u0441\u0430 \u043D\u0435\u043A\u043E\u043C \u043E\u0434 \u0441\u043B\u0435\u0434\u0435\u045B\u0438\u0445 \u043F\u0440\u0435\u0442\u0440\u0430\u0433\u0430:",searching:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0442\u0435\u0440\u043C\u0438\u043D\u0430 [SEARCH_TERM]..."},aa={thanks_to:ra,comments:sa,direction:la,strings:ia};var on={};A(on,{comments:()=>ua,default:()=>fa,direction:()=>ca,strings:()=>_a,thanks_to:()=>oa});var oa="Montazar Al-Jaber ",ua="",ca="ltr",_a={placeholder:"S\xF6k",clear_search:"Rensa",load_more:"Visa fler tr\xE4ffar",search_label:"S\xF6k p\xE5 denna sida",filters_label:"Filter",zero_results:"[SEARCH_TERM] gav inga tr\xE4ffar",many_results:"[SEARCH_TERM] gav [COUNT] tr\xE4ffar",one_result:"[SEARCH_TERM] gav [COUNT] tr\xE4ff",alt_search:"[SEARCH_TERM] gav inga tr\xE4ffar. Visar resultat f\xF6r [DIFFERENT_TERM] ist\xE4llet",search_suggestion:"[SEARCH_TERM] gav inga tr\xE4ffar. F\xF6rs\xF6k igen med en av f\xF6ljande s\xF6kord:",searching:"S\xF6ker efter [SEARCH_TERM]..."},fa={thanks_to:oa,comments:ua,direction:ca,strings:_a};var un={};A(un,{comments:()=>ha,default:()=>ga,direction:()=>ma,strings:()=>pa,thanks_to:()=>da});var da="Anonymous",ha="",ma="ltr",pa={placeholder:"Tafuta",clear_search:"Futa",load_more:"Pakia matokeo zaidi",search_label:"Tafuta tovuti hii",filters_label:"Vichujio",zero_results:"Hakuna matokeo ya [SEARCH_TERM]",many_results:"Matokeo [COUNT] ya [SEARCH_TERM]",one_result:"Tokeo [COUNT] la [SEARCH_TERM]",alt_search:"Hakuna mayokeo ya [SEARCH_TERM]. Badala yake, inaonyesha matokeo ya [DIFFERENT_TERM]",search_suggestion:"Hakuna matokeo ya [SEARCH_TERM]. Jaribu mojawapo ya utafutaji ufuatao:",searching:"Kutafuta [SEARCH_TERM]..."},ga={thanks_to:da,comments:ha,direction:ma,strings:pa};var cn={};A(cn,{comments:()=>Ra,default:()=>Ca,direction:()=>ba,strings:()=>Ta,thanks_to:()=>Ea});var Ea="",Ra="",ba="ltr",Ta={placeholder:"\u0BA4\u0BC7\u0B9F\u0BC1\u0B95",clear_search:"\u0B85\u0BB4\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0B95",load_more:"\u0BAE\u0BC7\u0BB2\u0BC1\u0BAE\u0BCD \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BC8\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0B95",search_label:"\u0B87\u0BA8\u0BCD\u0BA4 \u0BA4\u0BB3\u0BA4\u0BCD\u0BA4\u0BBF\u0BB2\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1\u0B95",filters_label:"\u0BB5\u0B9F\u0BBF\u0B95\u0B9F\u0BCD\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",zero_results:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8",many_results:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 [COUNT] \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD",one_result:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1",alt_search:"[SEARCH_TERM] \u0B87\u0BA4\u0BCD\u0BA4\u0BC7\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8, \u0B87\u0BA8\u0BCD\u0BA4 \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B92\u0BA4\u0BCD\u0BA4 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD [DIFFERENT_TERM]",search_suggestion:"[SEARCH_TERM] \u0B87\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8.\u0B87\u0BA4\u0BB1\u0BCD\u0B95\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC0\u0B9F\u0BBE\u0BA9 \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BC8 \u0BA4\u0BC7\u0B9F\u0BC1\u0B95:",searching:"[SEARCH_TERM] \u0BA4\u0BC7\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0B95\u0BBF\u0BA9\u0BCD\u0BB1\u0BA4\u0BC1"},Ca={thanks_to:Ea,comments:Ra,direction:ba,strings:Ta};var _n={};A(_n,{comments:()=>Sa,default:()=>ya,direction:()=>Ma,strings:()=>Aa,thanks_to:()=>ka});var ka="Patiphon Loetsuthakun ",Sa="",Ma="ltr",Aa={placeholder:"\u0E04\u0E49\u0E19\u0E2B\u0E32",clear_search:"\u0E25\u0E49\u0E32\u0E07",load_more:"\u0E42\u0E2B\u0E25\u0E14\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E40\u0E15\u0E34\u0E21",search_label:"\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E1A\u0E19\u0E40\u0E27\u0E47\u0E1A\u0E44\u0E0B\u0E15\u0E4C",filters_label:"\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07",zero_results:"\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C\u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A [SEARCH_TERM]",many_results:"\u0E1E\u0E1A [COUNT] \u0E1C\u0E25\u0E01\u0E32\u0E23\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A [SEARCH_TERM]",one_result:"\u0E1E\u0E1A [COUNT] \u0E1C\u0E25\u0E01\u0E32\u0E23\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A [SEARCH_TERM]",alt_search:"\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C\u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A [SEARCH_TERM] \u0E41\u0E2A\u0E14\u0E07\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C\u0E08\u0E32\u0E01\u0E01\u0E32\u0E23\u0E04\u0E49\u0E19\u0E2B\u0E32 [DIFFERENT_TERM] \u0E41\u0E17\u0E19",search_suggestion:"\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E1C\u0E25\u0E25\u0E31\u0E1E\u0E18\u0E4C\u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A [SEARCH_TERM] \u0E25\u0E2D\u0E07\u0E04\u0E33\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E40\u0E2B\u0E25\u0E48\u0E32\u0E19\u0E35\u0E49\u0E41\u0E17\u0E19:",searching:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E04\u0E49\u0E19\u0E2B\u0E32 [SEARCH_TERM]..."},ya={thanks_to:ka,comments:Sa,direction:Ma,strings:Aa};var fn={};A(fn,{comments:()=>Ha,default:()=>Na,direction:()=>wa,strings:()=>Fa,thanks_to:()=>va});var va="Taylan \xD6zg\xFCr Bildik",Ha="",wa="ltr",Fa={placeholder:"Ara\u015Ft\u0131r",clear_search:"Temizle",load_more:"Daha fazla sonu\xE7",search_label:"Site genelinde arama",filters_label:"Filtreler",zero_results:"[SEARCH_TERM] i\xE7in sonu\xE7 yok",many_results:"[SEARCH_TERM] i\xE7in [COUNT] sonu\xE7 bulundu",one_result:"[SEARCH_TERM] i\xE7in [COUNT] sonu\xE7 bulundu",alt_search:"[SEARCH_TERM] i\xE7in sonu\xE7 yok. Bunun yerine [DIFFERENT_TERM] i\xE7in sonu\xE7lar g\xF6steriliyor",search_suggestion:"[SEARCH_TERM] i\xE7in sonu\xE7 yok. Alternatif olarak a\u015Fa\u011F\u0131daki kelimelerden birini deneyebilirsiniz:",searching:"[SEARCH_TERM] ara\u015Ft\u0131r\u0131l\u0131yor..."},Na={thanks_to:va,comments:Ha,direction:wa,strings:Fa};var dn={};A(dn,{comments:()=>Oa,default:()=>Da,direction:()=>ja,strings:()=>Ua,thanks_to:()=>za});var za="Vladyslav Lyshenko ",Oa="",ja="ltr",Ua={placeholder:"\u041F\u043E\u0448\u0443\u043A",clear_search:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u043F\u043E\u043B\u0435",load_more:"\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0449\u0435",search_label:"\u041F\u043E\u0448\u0443\u043A \u043F\u043E \u0441\u0430\u0439\u0442\u0443",filters_label:"\u0424\u0456\u043B\u044C\u0442\u0440\u0438",zero_results:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0456\u0432 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]",alt_search:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]. \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0438 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [DIFFERENT_TERM]",search_suggestion:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]. \u0421\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0456\u0437 \u0442\u0430\u043A\u0438\u0445 \u0432\u0430\u0440\u0456\u0430\u043D\u0442\u0456\u0432",searching:"\u041F\u043E\u0448\u0443\u043A \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]"},Da={thanks_to:za,comments:Oa,direction:ja,strings:Ua};var hn={};A(hn,{comments:()=>Pa,default:()=>Ba,direction:()=>La,strings:()=>qa,thanks_to:()=>Ia});var Ia="Long Nhat Nguyen",Pa="",La="ltr",qa={placeholder:"T\xECm ki\u1EBFm",clear_search:"X\xF3a",load_more:"Nhi\u1EC1u k\u1EBFt qu\u1EA3 h\u01A1n",search_label:"T\xECm ki\u1EBFm trong trang n\xE0y",filters_label:"B\u1ED9 l\u1ECDc",zero_results:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",many_results:"[COUNT] k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",one_result:"[COUNT] k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",alt_search:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]. Ki\u1EC3m th\u1ECB k\u1EBFt qu\u1EA3 thay th\u1EBF v\u1EDBi [DIFFERENT_TERM]",search_suggestion:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]. Th\u1EED m\u1ED9t trong c\xE1c t\xECm ki\u1EBFm:",searching:"\u0110ang t\xECm ki\u1EBFm cho [SEARCH_TERM]..."},Ba={thanks_to:Ia,comments:Pa,direction:La,strings:qa};var mn={};A(mn,{comments:()=>Wa,default:()=>Ja,direction:()=>Ka,strings:()=>Ga,thanks_to:()=>Va});var Va="Amber Song",Wa="",Ka="ltr",Ga={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F7D\u66F4\u591A\u7ED3\u679C",search_label:"\u7AD9\u5185\u641C\u7D22",filters_label:"\u7B5B\u9009",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",many_results:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",one_result:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u6539\u4E3A\u663E\u793A [DIFFERENT_TERM] \u7684\u76F8\u5173\u7ED3\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u8BF7\u5C1D\u8BD5\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},Ja={thanks_to:Va,comments:Wa,direction:Ka,strings:Ga};var pn={};A(pn,{comments:()=>Za,default:()=>xa,direction:()=>Xa,strings:()=>Qa,thanks_to:()=>Ya});var Ya="Amber Song",Za="",Xa="ltr",Qa={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F09\u66F4\u591A\u7D50\u679C",search_label:"\u7AD9\u5167\u641C\u7D22",filters_label:"\u7BE9\u9078",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",many_results:"\u627E\u5230 [COUNT] \u500B [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",one_result:"\u627E\u5230 [COUNT] \u500B [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C\u3002\u6539\u70BA\u986F\u793A [DIFFERENT_TERM] \u7684\u76F8\u95DC\u7D50\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C\u3002\u8ACB\u5617\u8A66\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},xa={thanks_to:Ya,comments:Za,direction:Xa,strings:Qa};var gn={};A(gn,{comments:()=>eo,default:()=>ro,direction:()=>to,strings:()=>no,thanks_to:()=>$a});var $a="Amber Song",eo="",to="ltr",no={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F7D\u66F4\u591A\u7ED3\u679C",search_label:"\u7AD9\u5185\u641C\u7D22",filters_label:"\u7B5B\u9009",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",many_results:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",one_result:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u6539\u4E3A\u663E\u793A [DIFFERENT_TERM] \u7684\u76F8\u5173\u7ED3\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u8BF7\u5C1D\u8BD5\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},ro={thanks_to:$a,comments:eo,direction:to,strings:no};var so=[vt,Ht,wt,Ft,Nt,zt,Ot,jt,Ut,Dt,It,Pt,Lt,qt,Bt,Vt,Wt,Kt,Gt,Jt,Yt,Zt,Xt,Qt,xt,$t,en,tn,nn,rn,sn,ln,an,on,un,cn,_n,fn,dn,hn,mn,pn,gn],dr=so,hr=["../../translations/af.json","../../translations/ar.json","../../translations/bn.json","../../translations/ca.json","../../translations/cs.json","../../translations/da.json","../../translations/de.json","../../translations/en.json","../../translations/es.json","../../translations/eu.json","../../translations/fa.json","../../translations/fi.json","../../translations/fr.json","../../translations/gl.json","../../translations/he.json","../../translations/hi.json","../../translations/hr.json","../../translations/hu.json","../../translations/id.json","../../translations/it.json","../../translations/ja.json","../../translations/ko.json","../../translations/mi.json","../../translations/my.json","../../translations/nb.json","../../translations/nl.json","../../translations/nn.json","../../translations/no.json","../../translations/pl.json","../../translations/pt.json","../../translations/ro.json","../../translations/ru.json","../../translations/sr.json","../../translations/sv.json","../../translations/sw.json","../../translations/ta.json","../../translations/th.json","../../translations/tr.json","../../translations/uk.json","../../translations/vi.json","../../translations/zh-cn.json","../../translations/zh-tw.json","../../translations/zh.json"];function mr(n,e,t){let r=n.slice();return r[51]=e[t],r}function pr(n){let e,t,r;function s(i){n[37](i)}let l={show_empty_filters:n[5],open_filters:n[6],available_filters:n[18],translate:n[20],automatic_translations:n[19],translations:n[7]};return n[0]!==void 0&&(l.selected_filters=n[0]),e=new fr({props:l}),le.push(()=>Un(e,"selected_filters",s)),{c(){ut(e.$$.fragment)},m(i,a){me(e,i,a),r=!0},p(i,a){let o={};a[0]&32&&(o.show_empty_filters=i[5]),a[0]&64&&(o.open_filters=i[6]),a[0]&262144&&(o.available_filters=i[18]),a[0]&524288&&(o.automatic_translations=i[19]),a[0]&128&&(o.translations=i[7]),!t&&a[0]&1&&(t=!0,o.selected_filters=i[0],Nn(()=>t=!1)),e.$set(o)},i(i){r||(D(e.$$.fragment,i),r=!0)},o(i){P(e.$$.fragment,i),r=!1},d(i){ue(e,i)}}}function gr(n){let e,t,r,s,l=[ao,io],i=[];function a(o,f){return o[14]?0:1}return t=a(n,[-1,-1]),r=i[t]=l[t](n),{c(){e=C("div"),r.c(),m(e,"class","pagefind-ui__results-area svelte-e9gkc3")},m(o,f){S(o,e,f),i[t].m(e,null),s=!0},p(o,f){let c=t;t=a(o,f),t===c?i[t].p(o,f):(ae(),P(i[c],1,1,()=>{i[c]=null}),oe(),r=i[t],r?r.p(o,f):(r=i[t]=l[t](o),r.c()),D(r,1),r.m(e,null))},i(o){s||(D(r),s=!0)},o(o){P(r),s=!1},d(o){o&&k(e),i[t].d()}}}function io(n){let e,t,r,s=[],l=new Map,i,a,o;function f(_,E){return _[13].results.length===0?co:_[13].results.length===1?uo:oo}let c=f(n,[-1,-1]),d=c(n),p=n[13].results.slice(0,n[17]),h=_=>_[51].id;for(let _=0;_n[17]&&Rr(n);return{c(){e=C("p"),d.c(),t=v(),r=C("ol");for(let _=0;__[17]?u?u.p(_,E):(u=Rr(_),u.c(),u.m(a.parentNode,a)):u&&(u.d(1),u=null)},i(_){if(!o){for(let E=0;E{o[p]=null}),oe(),s=o[r],s?s.p(e,d):(s=o[r]=a[r](e),s.c()),D(s,1),s.m(l.parentNode,l))},i(c){i||(D(s),i=!0)},o(c){P(s),i=!1},d(c){c&&k(t),o[r].d(c),c&&k(l)}}}function Rr(n){let e,t=n[20]("load_more",n[19],n[7])+"",r,s,l;return{c(){e=C("button"),r=w(t),m(e,"type","button"),m(e,"class","pagefind-ui__button svelte-e9gkc3")},m(i,a){S(i,e,a),R(e,r),s||(l=J(e,"click",n[22]),s=!0)},p(i,a){a[0]&524416&&t!==(t=i[20]("load_more",i[19],i[7])+"")&&z(r,t)},d(i){i&&k(e),s=!1,l()}}}function br(n){let e,t=n[20]("searching",n[19],n[7]).replace(/\[SEARCH_TERM\]/,n[16])+"",r;return{c(){e=C("p"),r=w(t),m(e,"class","pagefind-ui__message svelte-e9gkc3")},m(s,l){S(s,e,l),R(e,r)},p(s,l){l[0]&589952&&t!==(t=s[20]("searching",s[19],s[7]).replace(/\[SEARCH_TERM\]/,s[16])+"")&&z(r,t)},d(s){s&&k(e)}}}function ho(n){let e,t,r,s,l,i,a,o=n[20]("clear_search",n[19],n[7])+"",f,c,d,p,h,u,_,E,b=n[12]&&pr(n),T=n[15]&&gr(n);return{c(){e=C("div"),t=C("form"),r=C("input"),i=v(),a=C("button"),f=w(o),c=v(),d=C("div"),b&&b.c(),p=v(),T&&T.c(),m(r,"class","pagefind-ui__search-input svelte-e9gkc3"),m(r,"type","text"),m(r,"placeholder",s=n[20]("placeholder",n[19],n[7])),m(r,"title",l=n[20]("placeholder",n[19],n[7])),m(r,"autocapitalize","none"),m(r,"enterkeyhint","search"),r.autofocus=n[8],m(a,"class","pagefind-ui__search-clear svelte-e9gkc3"),B(a,"pagefind-ui__suppressed",!n[9]),m(d,"class","pagefind-ui__drawer svelte-e9gkc3"),B(d,"pagefind-ui__hidden",!n[15]),m(t,"class","pagefind-ui__form svelte-e9gkc3"),m(t,"role","search"),m(t,"aria-label",h=n[20]("search_label",n[19],n[7])),m(t,"action","javascript:void(0);"),m(e,"class","pagefind-ui svelte-e9gkc3"),B(e,"pagefind-ui--reset",n[1])},m(M,y){S(M,e,y),R(e,t),R(t,r),Tt(r,n[9]),n[34](r),R(t,i),R(t,a),R(a,f),n[35](a),R(t,c),R(t,d),b&&b.m(d,null),R(d,p),T&&T.m(d,null),u=!0,n[8]&&r.focus(),_||(E=[J(r,"focus",n[21]),J(r,"keydown",n[32]),J(r,"input",n[33]),J(a,"click",n[36]),J(t,"submit",mo)],_=!0)},p(M,y){(!u||y[0]&524416&&s!==(s=M[20]("placeholder",M[19],M[7])))&&m(r,"placeholder",s),(!u||y[0]&524416&&l!==(l=M[20]("placeholder",M[19],M[7])))&&m(r,"title",l),(!u||y[0]&256)&&(r.autofocus=M[8]),y[0]&512&&r.value!==M[9]&&Tt(r,M[9]),(!u||y[0]&524416)&&o!==(o=M[20]("clear_search",M[19],M[7])+"")&&z(f,o),(!u||y[0]&512)&&B(a,"pagefind-ui__suppressed",!M[9]),M[12]?b?(b.p(M,y),y[0]&4096&&D(b,1)):(b=pr(M),b.c(),D(b,1),b.m(d,p)):b&&(ae(),P(b,1,1,()=>{b=null}),oe()),M[15]?T?(T.p(M,y),y[0]&32768&&D(T,1)):(T=gr(M),T.c(),D(T,1),T.m(d,null)):T&&(ae(),P(T,1,1,()=>{T=null}),oe()),(!u||y[0]&32768)&&B(d,"pagefind-ui__hidden",!M[15]),(!u||y[0]&524416&&h!==(h=M[20]("search_label",M[19],M[7])))&&m(t,"aria-label",h),(!u||y[0]&2)&&B(e,"pagefind-ui--reset",M[1])},i(M){u||(D(b),D(T),u=!0)},o(M){P(b),P(T),u=!1},d(M){M&&k(e),n[34](null),n[35](null),b&&b.d(),T&&T.d(),_=!1,K(E)}}}var mo=n=>n.preventDefault();function po(n,e,t){let r={},s=hr.map(g=>g.match(/([^\/]+)\.json$/)[1]);for(let g=0;gj[g]??N[g]??"";Ct(()=>{let g=document?.querySelector?.("html")?.getAttribute?.("lang")||"en",N=ct(g.toLocaleLowerCase());t(19,Sn=r[`${N.language}-${N.script}-${N.region}`]||r[`${N.language}-${N.region}`]||r[`${N.language}`]||r.en)}),kt(()=>{F?.destroy?.(),F=null});let Mn=async()=>{if(!ft&&(t(12,ft=!0),!F)){let g;try{g=await import(`${l}pagefind.js`)}catch(j){console.error(j),console.error([`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,"You can configure this by passing a bundlePath option to PagefindUI"].join(` +`)),document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?console.error(`[DEBUG: Loaded from ${document.currentScript.src??"bad script location"}]`):console.error("no known script location")}c||t(24,c=f?12:30);let N={...E||{},excerptLength:c};await g.options(N);for(let j of b){if(!j.bundlePath)throw new Error("mergeIndex requires a bundlePath parameter");let L=j.bundlePath;delete j.bundlePath,await g.mergeIndex(L,j)}F=g,Sr()}},Sr=async()=>{F&&(kn=await F.filters(),(!ce||!Object.keys(ce).length)&&t(18,ce=kn))},Mr=g=>{let N={};return Object.entries(g).filter(([,j])=>j).forEach(([j])=>{let[L,te]=j.split(/:(.*)$/);N[L]=N[L]||[],N[L].push(te)}),N},_e,Ar=async(g,N)=>{if(!g){t(15,ht=!1),_e&&clearTimeout(_e);return}let j=Mr(N),L=()=>yr(g,j);_>0&&g?(_e&&clearTimeout(_e),_e=setTimeout(L,_),await An(),F.preload(g,{filters:j})):L(),vr()},An=async()=>{for(;!F;)Mn(),await new Promise(g=>setTimeout(g,50))},yr=async(g,N)=>{t(16,Cn=g||""),typeof p=="function"&&(g=p(g)),t(14,dt=!0),t(15,ht=!0),await An();let j=++Tn,L={filters:N};X&&typeof X=="object"&&(L.sort=X);let te=await F.search(g,L);Tn===j&&(te.filters&&Object.keys(te.filters)?.length&&t(18,ce=te.filters),t(13,bn=te),t(14,dt=!1),t(17,mt=i))},vr=()=>{let g=W.offsetWidth;g!=Cr&&t(10,O.style.paddingRight=`${g+2}px`,O)},Hr=g=>{g?.preventDefault(),t(17,mt+=i)},wr=g=>{g.key==="Escape"&&(t(9,H=""),O.blur()),g.key==="Enter"&&g.preventDefault()};function Fr(){H=this.value,t(9,H),t(23,T)}function Nr(g){le[g?"unshift":"push"](()=>{O=g,t(10,O)})}function zr(g){le[g?"unshift":"push"](()=>{W=g,t(11,W)})}let Or=()=>{t(9,H=""),O.blur()};function jr(g){V=g,t(0,V)}return n.$$set=g=>{"base_path"in g&&t(25,l=g.base_path),"page_size"in g&&t(26,i=g.page_size),"reset_styles"in g&&t(1,a=g.reset_styles),"show_images"in g&&t(2,o=g.show_images),"show_sub_results"in g&&t(3,f=g.show_sub_results),"excerpt_length"in g&&t(24,c=g.excerpt_length),"process_result"in g&&t(4,d=g.process_result),"process_term"in g&&t(27,p=g.process_term),"show_empty_filters"in g&&t(5,h=g.show_empty_filters),"open_filters"in g&&t(6,u=g.open_filters),"debounce_timeout_ms"in g&&t(28,_=g.debounce_timeout_ms),"pagefind_options"in g&&t(29,E=g.pagefind_options),"merge_index"in g&&t(30,b=g.merge_index),"trigger_search_term"in g&&t(23,T=g.trigger_search_term),"translations"in g&&t(7,M=g.translations),"autofocus"in g&&t(8,y=g.autofocus),"sort"in g&&t(31,X=g.sort),"selected_filters"in g&&t(0,V=g.selected_filters)},n.$$.update=()=>{if(n.$$.dirty[0]&8388608)e:T&&(t(9,H=T),t(23,T=""));if(n.$$.dirty[0]&513)e:Ar(H,V)},[V,a,o,f,d,h,u,M,y,H,O,W,ft,bn,dt,ht,Cn,mt,ce,Sn,kr,Mn,Hr,T,c,l,i,p,_,E,b,X,wr,Fr,Nr,zr,Or,jr]}var En=class extends q{constructor(e){super(),Y(this,e,po,ho,G,{base_path:25,page_size:26,reset_styles:1,show_images:2,show_sub_results:3,excerpt_length:24,process_result:4,process_term:27,show_empty_filters:5,open_filters:6,debounce_timeout_ms:28,pagefind_options:29,merge_index:30,trigger_search_term:23,translations:7,autofocus:8,sort:31,selected_filters:0},null,[-1,-1])}},Tr=En;var Rn;try{document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&(Rn=new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?ui.js.*$/)[1])}catch{Rn="/pagefind/"}var _t=class{constructor(e){this._pfs=null;let t=e.element??"[data-pagefind-ui]",r=e.bundlePath??Rn,s=e.pageSize??5,l=e.resetStyles??!0,i=e.showImages??!0,a=e.showSubResults??!1,o=e.excerptLength??0,f=e.processResult??null,c=e.processTerm??null,d=e.showEmptyFilters??!0,p=e.openFilters??[],h=e.debounceTimeoutMs??300,u=e.mergeIndex??[],_=e.translations??[],E=e.autofocus??!1,b=e.sort??null;delete e.element,delete e.bundlePath,delete e.pageSize,delete e.resetStyles,delete e.showImages,delete e.showSubResults,delete e.excerptLength,delete e.processResult,delete e.processTerm,delete e.showEmptyFilters,delete e.openFilters,delete e.debounceTimeoutMs,delete e.mergeIndex,delete e.translations,delete e.autofocus,delete e.sort;let T=t instanceof HTMLElement?t:document.querySelector(t);T?this._pfs=new Tr({target:T,props:{base_path:r,page_size:s,reset_styles:l,show_images:i,show_sub_results:a,excerpt_length:o,process_result:f,process_term:c,show_empty_filters:d,open_filters:p,debounce_timeout_ms:h,merge_index:u,translations:_,autofocus:E,sort:b,pagefind_options:e}}):console.error(`Pagefind UI couldn't find the selector ${t}`)}triggerSearch(e){this._pfs.$$set({trigger_search_term:e})}triggerFilters(e){let t={};for(let[r,s]of Object.entries(e))if(Array.isArray(s))for(let l of s)t[`${r}:${l}`]=!0;else t[`${r}:${s}`]=!0;this._pfs.$$set({selected_filters:t})}destroy(){this._pfs.$destroy()}};window.PagefindUI=_t;})(); diff --git a/_pagefind/pagefind.en_3a80c79c47.pf_meta b/_pagefind/pagefind.en_3a80c79c47.pf_meta new file mode 100644 index 00000000..53fdd066 Binary files /dev/null and b/_pagefind/pagefind.en_3a80c79c47.pf_meta differ diff --git a/_pagefind/pagefind.js b/_pagefind/pagefind.js new file mode 100644 index 00000000..54e2f7cc --- /dev/null +++ b/_pagefind/pagefind.js @@ -0,0 +1,6 @@ +const pagefind_version="1.4.0";let wasm_bindgen;(function(){const __exports={};let script_src;if(typeof document!=='undefined'&&document.currentScript!==null){script_src=new URL("UNHANDLED",location.href).toString()}let wasm=undefined;let WASM_VECTOR_LEN=0;let cachedUint8Memory0=null;function getUint8Memory0(){if(cachedUint8Memory0===null||cachedUint8Memory0.byteLength===0){cachedUint8Memory0=new Uint8Array(wasm.memory.buffer)}return cachedUint8Memory0}const cachedTextEncoder=(typeof TextEncoder!=='undefined'?new TextEncoder('utf-8'):{encode:()=>{throw Error('TextEncoder not available')}});const encodeString=(typeof cachedTextEncoder.encodeInto==='function'?function(arg,view){return cachedTextEncoder.encodeInto(arg,view)}:function(arg,view){const buf=cachedTextEncoder.encode(arg);view.set(buf);return{read:arg.length,written:buf.length}});function passStringToWasm0(arg,malloc,realloc){if(realloc===undefined){const buf=cachedTextEncoder.encode(arg);const ptr=malloc(buf.length,1)>>>0;getUint8Memory0().subarray(ptr,ptr+buf.length).set(buf);WASM_VECTOR_LEN=buf.length;return ptr}let len=arg.length;let ptr=malloc(len,1)>>>0;const mem=getUint8Memory0();let offset=0;for(;offset0x7F)break;mem[ptr+offset]=code}if(offset!==len){if(offset!==0){arg=arg.slice(offset)}ptr=realloc(ptr,len,len=offset+arg.length*3,1)>>>0;const view=getUint8Memory0().subarray(ptr+offset,ptr+len);const ret=encodeString(arg,view);offset+=ret.written;ptr=realloc(ptr,len,offset,1)>>>0}WASM_VECTOR_LEN=offset;return ptr}let cachedInt32Memory0=null;function getInt32Memory0(){if(cachedInt32Memory0===null||cachedInt32Memory0.byteLength===0){cachedInt32Memory0=new Int32Array(wasm.memory.buffer)}return cachedInt32Memory0}const cachedTextDecoder=(typeof TextDecoder!=='undefined'?new TextDecoder('utf-8',{ignoreBOM:true,fatal:true}):{decode:()=>{throw Error('TextDecoder not available')}});if(typeof TextDecoder!=='undefined'){cachedTextDecoder.decode()};function getStringFromWasm0(ptr,len){ptr=ptr>>>0;return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr,ptr+len))}__exports.request_indexes=function(ptr,query){let deferred2_0;let deferred2_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(query,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;wasm.request_indexes(retptr,ptr,ptr0,len0);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred2_0=r0;deferred2_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred2_0,deferred2_1,1)}};__exports.filters=function(ptr){let deferred1_0;let deferred1_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);wasm.filters(retptr,ptr);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred1_0=r0;deferred1_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred1_0,deferred1_1,1)}};__exports.request_filter_indexes=function(ptr,filters){let deferred2_0;let deferred2_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(filters,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;wasm.request_filter_indexes(retptr,ptr,ptr0,len0);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred2_0=r0;deferred2_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred2_0,deferred2_1,1)}};__exports.enter_playground_mode=function(ptr){const ret=wasm.enter_playground_mode(ptr);return ret>>>0};__exports.request_all_filter_indexes=function(ptr){let deferred1_0;let deferred1_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);wasm.request_all_filter_indexes(retptr,ptr);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred1_0=r0;deferred1_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred1_0,deferred1_1,1)}};function passArray8ToWasm0(arg,malloc){const ptr=malloc(arg.length*1,1)>>>0;getUint8Memory0().set(arg,ptr/1);WASM_VECTOR_LEN=arg.length;return ptr}__exports.init_pagefind=function(metadata_bytes){const ptr0=passArray8ToWasm0(metadata_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.init_pagefind(ptr0,len0);return ret>>>0};__exports.search=function(ptr,query,filter,sort,exact){let deferred4_0;let deferred4_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(query,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ptr1=passStringToWasm0(filter,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;const ptr2=passStringToWasm0(sort,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len2=WASM_VECTOR_LEN;wasm.search(retptr,ptr,ptr0,len0,ptr1,len1,ptr2,len2,exact);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred4_0=r0;deferred4_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred4_0,deferred4_1,1)}};__exports.load_index_chunk=function(ptr,chunk_bytes){const ptr0=passArray8ToWasm0(chunk_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.load_index_chunk(ptr,ptr0,len0);return ret>>>0};__exports.add_synthetic_filter=function(ptr,filter){const ptr0=passStringToWasm0(filter,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ret=wasm.add_synthetic_filter(ptr,ptr0,len0);return ret>>>0};__exports.set_ranking_weights=function(ptr,weights){const ptr0=passStringToWasm0(weights,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ret=wasm.set_ranking_weights(ptr,ptr0,len0);return ret>>>0};__exports.load_filter_chunk=function(ptr,chunk_bytes){const ptr0=passArray8ToWasm0(chunk_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.load_filter_chunk(ptr,ptr0,len0);return ret>>>0};async function __wbg_load(module,imports){if(typeof Response==='function'&&module instanceof Response){if(typeof WebAssembly.instantiateStreaming==='function'){try{return await WebAssembly.instantiateStreaming(module,imports)}catch(e){if(module.headers.get('Content-Type')!='application/wasm'){console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",e)}else{throw e}}}const bytes=await module.arrayBuffer();return await WebAssembly.instantiate(bytes,imports)}else{const instance=await WebAssembly.instantiate(module,imports);if(instance instanceof WebAssembly.Instance){return{instance,module}}else{return instance}}}function __wbg_get_imports(){const imports={};imports.wbg={};return imports}function __wbg_init_memory(imports,maybe_memory){}function __wbg_finalize_init(instance,module){wasm=instance.exports;__wbg_init.__wbindgen_wasm_module=module;cachedInt32Memory0=null;cachedUint8Memory0=null;return wasm}function initSync(module){if(wasm!==undefined)return wasm;const imports=__wbg_get_imports();__wbg_init_memory(imports);if(!(module instanceof WebAssembly.Module)){module=new WebAssembly.Module(module)}const instance=new WebAssembly.Instance(module,imports);return __wbg_finalize_init(instance,module)}async function __wbg_init(input){if(wasm!==undefined)return wasm;if(typeof input==='undefined'&&typeof script_src!=='undefined'){input=script_src.replace(/\.js$/,'_bg.wasm')}const imports=__wbg_get_imports();if(typeof input==='string'||(typeof Request==='function'&&input instanceof Request)||(typeof URL==='function'&&input instanceof URL)){input=fetch(input)}__wbg_init_memory(imports);const{instance,module}=await __wbg_load(await input,imports);return __wbg_finalize_init(instance,module)}wasm_bindgen=Object.assign(__wbg_init,{initSync},__exports)})();var u8=Uint8Array;var u16=Uint16Array;var u32=Uint32Array;var fleb=new u8([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]);var fdeb=new u8([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]);var clim=new u8([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);var freb=function(eb,start){var b=new u16(31);for(var i2=0;i2<31;++i2){b[i2]=start+=1<>>1|(i&21845)<<1;x=(x&52428)>>>2|(x&13107)<<2;x=(x&61680)>>>4|(x&3855)<<4;rev[i]=((x&65280)>>>8|(x&255)<<8)>>>1}var x;var i;var hMap=function(cd,mb,r){var s=cd.length;var i2=0;var l=new u16(mb);for(;i2>>rvb]=sv}}}}else{co=new u16(s);for(i2=0;i2>>15-cd[i2]}}}return co};var flt=new u8(288);for(i=0;i<144;++i)flt[i]=8;var i;for(i=144;i<256;++i)flt[i]=9;var i;for(i=256;i<280;++i)flt[i]=7;var i;for(i=280;i<288;++i)flt[i]=8;var i;var fdt=new u8(32);for(i=0;i<32;++i)fdt[i]=5;var i;var flrm=hMap(flt,9,1);var fdrm=hMap(fdt,5,1);var max=function(a){var m=a[0];for(var i2=1;i2m)m=a[i2]}return m};var bits=function(d,p,m){var o=p/8|0;return(d[o]|d[o+1]<<8)>>(p&7)&m};var bits16=function(d,p){var o=p/8|0;return(d[o]|d[o+1]<<8|d[o+2]<<16)>>(p&7)};var shft=function(p){return(p+7)/8|0};var slc=function(v,s,e){if(s==null||s<0)s=0;if(e==null||e>v.length)e=v.length;var n=new(v.BYTES_PER_ELEMENT==2?u16:v.BYTES_PER_ELEMENT==4?u32:u8)(e-s);n.set(v.subarray(s,e));return n};var ec=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"];var err=function(ind,msg,nt){var e=new Error(msg||ec[ind]);e.code=ind;if(Error.captureStackTrace)Error.captureStackTrace(e,err);if(!nt)throw e;return e};var inflt=function(dat,buf,st){var sl=dat.length;if(!sl||st&&st.f&&!st.l)return buf||new u8(0);var noBuf=!buf||st;var noSt=!st||st.i;if(!st)st={};if(!buf)buf=new u8(sl*3);var cbuf=function(l2){var bl=buf.length;if(l2>bl){var nbuf=new u8(Math.max(bl*2,l2));nbuf.set(buf);buf=nbuf}};var final=st.f||0,pos=st.p||0,bt=st.b||0,lm=st.l,dm=st.d,lbt=st.m,dbt=st.n;var tbts=sl*8;do{if(!lm){final=bits(dat,pos,1);var type=bits(dat,pos+1,3);pos+=3;if(!type){var s=shft(pos)+4,l=dat[s-4]|dat[s-3]<<8,t=s+l;if(t>sl){if(noSt)err(0);break}if(noBuf)cbuf(bt+l);buf.set(dat.subarray(s,t),bt);st.b=bt+=l,st.p=pos=t*8,st.f=final;continue}else if(type==1)lm=flrm,dm=fdrm,lbt=9,dbt=5;else if(type==2){var hLit=bits(dat,pos,31)+257,hcLen=bits(dat,pos+10,15)+4;var tl=hLit+bits(dat,pos+5,31)+1;pos+=14;var ldt=new u8(tl);var clt=new u8(19);for(var i2=0;i2>>4;if(s<16){ldt[i2++]=s}else{var c=0,n=0;if(s==16)n=3+bits(dat,pos,3),pos+=2,c=ldt[i2-1];else if(s==17)n=3+bits(dat,pos,7),pos+=3;else if(s==18)n=11+bits(dat,pos,127),pos+=7;while(n--)ldt[i2++]=c}}var lt=ldt.subarray(0,hLit),dt=ldt.subarray(hLit);lbt=max(lt);dbt=max(dt);lm=hMap(lt,lbt,1);dm=hMap(dt,dbt,1)}else err(1);if(pos>tbts){if(noSt)err(0);break}}if(noBuf)cbuf(bt+131072);var lms=(1<>>4;pos+=c&15;if(pos>tbts){if(noSt)err(0);break}if(!c)err(2);if(sym<256)buf[bt++]=sym;else if(sym==256){lpos=pos,lm=null;break}else{var add=sym-254;if(sym>264){var i2=sym-257,b=fleb[i2];add=bits(dat,pos,(1<>>4;if(!d)err(3);pos+=d&15;var dt=fd[dsym];if(dsym>3){var b=fdeb[dsym];dt+=bits16(dat,pos)&(1<tbts){if(noSt)err(0);break}if(noBuf)cbuf(bt+131072);var end=bt+add;for(;bt>3&1)+(flg>>4&1);zs>0;zs-=!d[st++]);return st+(flg&2)};var gzl=function(d){var l=d.length;return(d[l-4]|d[l-3]<<8|d[l-2]<<16|d[l-1]<<24)>>>0};function gunzipSync(data,out){return inflt(data.subarray(gzs(data),-8),out||new u8(gzl(data)))}var td=typeof TextDecoder!="undefined"&&new TextDecoder();var tds=0;try{td.decode(et,{stream:true});tds=1}catch(e){}var gz_default=gunzipSync;var calculate_excerpt_region=(word_positions,excerpt_length)=>{if(word_positions.length===0){return 0}let words=[];for(const word of word_positions){words[word.location]=words[word.location]||0;words[word.location]+=word.balanced_score}if(words.length<=excerpt_length){return 0}let densest=words.slice(0,excerpt_length).reduce((partialSum,a)=>partialSum+a,0);let working_sum=densest;let densest_at=[0];for(let i2=0;i2densest){densest=working_sum;densest_at=[i2]}else if(working_sum===densest&&densest_at[densest_at.length-1]===i2-1){densest_at.push(i2)}}let midpoint=densest_at[Math.floor(densest_at.length/2)];return midpoint};var build_excerpt=(content,start,length,locations,not_before,not_from)=>{let is_zws_delimited=content.includes("\u200B");let fragment_words=[];if(is_zws_delimited){fragment_words=content.split("\u200B")}else{fragment_words=content.split(/[\r\n\s]+/g)}for(let word of locations){if(fragment_words[word]?.startsWith(``)){continue}fragment_words[word]=`${fragment_words[word]}`}let endcap=not_from??fragment_words.length;let startcap=not_before??0;if(endcap-startcapendcap){start=endcap-length}if(start{const anchors=fragment.anchors.filter((a)=>/h\d/i.test(a.element)&&a.text?.length&&/\S/.test(a.text)).sort((a,b)=>a.location-b.location);const results=[];let current_anchor_position=0;let current_anchor={title:fragment.meta["title"],url:fragment.url,weighted_locations:[],locations:[],excerpt:""};const add_result=(end_range)=>{if(current_anchor.locations.length){const relative_weighted_locations=current_anchor.weighted_locations.map((l)=>{return{weight:l.weight,balanced_score:l.balanced_score,location:l.location-current_anchor_position}});const excerpt_start=calculate_excerpt_region(relative_weighted_locations,desired_excerpt_length)+current_anchor_position;const excerpt_length=end_range?Math.min(end_range-excerpt_start,desired_excerpt_length):desired_excerpt_length;current_anchor.excerpt=build_excerpt(fragment.raw_content??"",excerpt_start,excerpt_length,current_anchor.locations,current_anchor_position,end_range);results.push(current_anchor)}};for(let word of fragment.weighted_locations){if(!anchors.length||word.location=anchors[0].location){next_anchor=anchors.shift()}let anchored_url=fragment.url;try{const url_is_fq=/^((https?:)?\/\/)/.test(anchored_url);if(url_is_fq){let fq_url=new URL(anchored_url);fq_url.hash=next_anchor.id;anchored_url=fq_url.toString()}else{if(!/^\//.test(anchored_url)){anchored_url=`/${anchored_url}`}let fq_url=new URL(`https://example.com${anchored_url}`);fq_url.hash=next_anchor.id;anchored_url=fq_url.toString().replace(/^https:\/\/example.com/,"")}}catch(e){console.error(`Pagefind: Couldn't process ${anchored_url} for a search result`)}current_anchor_position=next_anchor.location;current_anchor={title:next_anchor.text,url:anchored_url,anchor:next_anchor,weighted_locations:[word],locations:[word.location],excerpt:""}}}add_result(anchors[0]?.location);return results};var asyncSleep=async(ms=100)=>{return new Promise((r)=>setTimeout(r,ms))};var isBrowser=typeof window!=="undefined"&&typeof document!=="undefined";var PagefindInstance=class{constructor(opts={}){this.version=pagefind_version;this.backend=wasm_bindgen;this.decoder=new TextDecoder("utf-8");this.wasm=null;this.basePath=opts.basePath||"/pagefind/";this.primary=opts.primary||false;if(this.primary&&!opts.basePath){this.initPrimary()}if(/[^\/]$/.test(this.basePath)){this.basePath=`${this.basePath}/`}if(isBrowser&&window?.location?.origin&&this.basePath.startsWith(window.location.origin)){this.basePath=this.basePath.replace(window.location.origin,"")}this.baseUrl=opts.baseUrl||this.defaultBaseUrl();if(!/^(\/|https?:\/\/)/.test(this.baseUrl)){this.baseUrl=`/${this.baseUrl}`}this.indexWeight=opts.indexWeight??1;this.excerptLength=opts.excerptLength??30;this.mergeFilter=opts.mergeFilter??{};this.ranking=opts.ranking;this.highlightParam=opts.highlightParam??null;this.loaded_chunks={};this.loaded_filters={};this.loaded_fragments={};this.raw_ptr=null;this.searchMeta=null;this.languages=null}initPrimary(){if(isBrowser&&typeof import.meta.url!=="undefined"){let derivedBasePath=import.meta.url.match(/^(.*\/)pagefind.js.*$/)?.[1];if(derivedBasePath){this.basePath=derivedBasePath}else{console.warn(["Pagefind couldn't determine the base of the bundle from the import path. Falling back to the default.","Set a basePath option when initialising Pagefind to ignore this message."].join("\n"))}}}defaultBaseUrl(){let default_base=this.basePath.match(/^(.*\/)_?pagefind/)?.[1];return default_base||"/"}async options(options2){const opts=["basePath","baseUrl","indexWeight","excerptLength","mergeFilter","highlightParam","ranking"];for(const[k,v]of Object.entries(options2)){if(k==="mergeFilter"){let filters2=this.stringifyFilters(v);let ptr=await this.getPtr();this.raw_ptr=this.backend.add_synthetic_filter(ptr,filters2)}else if(k==="ranking"){await this.set_ranking(options2.ranking)}else if(opts.includes(k)){if(k==="basePath"&&typeof v==="string")this.basePath=v;if(k==="baseUrl"&&typeof v==="string")this.baseUrl=v;if(k==="indexWeight"&&typeof v==="number")this.indexWeight=v;if(k==="excerptLength"&&typeof v==="number")this.excerptLength=v;if(k==="mergeFilter"&&typeof v==="object")this.mergeFilter=v;if(k==="highlightParam"&&typeof v==="string")this.highlightParam=v}else{console.warn(`Unknown Pagefind option ${k}. Allowed options: [${opts.join(", ")}]`)}}}async enterPlaygroundMode(){let ptr=await this.getPtr();this.raw_ptr=this.backend.enter_playground_mode(ptr)}decompress(data,file="unknown file"){if(this.decoder.decode(data.slice(0,12))==="pagefind_dcd"){return data.slice(12)}data=gz_default(data);if(this.decoder.decode(data.slice(0,12))!=="pagefind_dcd"){console.error(`Decompressing ${file} appears to have failed: Missing signature`);return data}return data.slice(12)}async set_ranking(ranking){if(!ranking)return;let rankingWeights={term_similarity:ranking.termSimilarity??null,page_length:ranking.pageLength??null,term_saturation:ranking.termSaturation??null,term_frequency:ranking.termFrequency??null};let ptr=await this.getPtr();this.raw_ptr=this.backend.set_ranking_weights(ptr,JSON.stringify(rankingWeights))}async init(language,opts){await this.loadEntry();let index=this.findIndex(language);let lang_wasm=index.wasm?index.wasm:"unknown";this.loadedLanguage=language;let resources=[this.loadMeta(index.hash)];if(opts.load_wasm===true){resources.push(this.loadWasm(lang_wasm))}await Promise.all(resources);this.raw_ptr=this.backend.init_pagefind(new Uint8Array(this.searchMeta));if(Object.keys(this.mergeFilter)?.length){let filters2=this.stringifyFilters(this.mergeFilter);let ptr=await this.getPtr();this.raw_ptr=this.backend.add_synthetic_filter(ptr,filters2)}if(this.ranking){await this.set_ranking(this.ranking)}}async loadEntry(){try{let entry_response=await fetch(`${this.basePath}pagefind-entry.json?ts=${Date.now()}`);let entry_json=await entry_response.json();this.languages=entry_json.languages;this.loadedVersion=entry_json.version;this.includeCharacters=entry_json.include_characters??[];if(entry_json.version!==this.version){if(this.primary){console.warn(["Pagefind JS version doesn't match the version in your search index.",`Pagefind JS: ${this.version}. Pagefind index: ${entry_json.version}`,"If you upgraded Pagefind recently, you likely have a cached pagefind.js file.","If you encounter any search errors, try clearing your cache."].join("\n"))}else{console.warn(["Merging a Pagefind index from a different version than the main Pagefind instance.",`Main Pagefind JS: ${this.version}. Merged index (${this.basePath}): ${entry_json.version}`,"If you encounter any search errors, make sure that both sites are running the same version of Pagefind."].join("\n"))}}}catch(e){console.error(`Failed to load Pagefind metadata: +${e?.toString()}`);throw new Error("Failed to load Pagefind metadata")}}findIndex(language){if(this.languages){let index=this.languages[language];if(index)return index;index=this.languages[language.split("-")[0]];if(index)return index;let topLang=Object.values(this.languages).sort((a,b)=>b.page_count-a.page_count);if(topLang[0])return topLang[0]}throw new Error("Pagefind Error: No language indexes found.")}async loadMeta(index){try{let compressed_resp=await fetch(`${this.basePath}pagefind.${index}.pf_meta`);let compressed_meta=await compressed_resp.arrayBuffer();this.searchMeta=this.decompress(new Uint8Array(compressed_meta),"Pagefind metadata")}catch(e){console.error(`Failed to load the meta index: +${e?.toString()}`)}}async loadWasm(language){try{const wasm_url=`${this.basePath}wasm.${language}.pagefind`;let compressed_resp=await fetch(wasm_url);let compressed_wasm=await compressed_resp.arrayBuffer();const final_wasm=this.decompress(new Uint8Array(compressed_wasm),"Pagefind WebAssembly");if(!final_wasm){throw new Error("No WASM after decompression")}this.wasm=await this.backend(final_wasm)}catch(e){console.error(`Failed to load the Pagefind WASM: +${e?.toString()}`);throw new Error(`Failed to load the Pagefind WASM: +${e?.toString()}`)}}async _loadGenericChunk(url,method){try{let compressed_resp=await fetch(url);let compressed_chunk=await compressed_resp.arrayBuffer();let chunk=this.decompress(new Uint8Array(compressed_chunk),url);let ptr=await this.getPtr();this.raw_ptr=this.backend[method](ptr,chunk)}catch(e){console.error(`Failed to load the index chunk ${url}: +${e?.toString()}`)}}async loadChunk(hash){if(!this.loaded_chunks[hash]){const url=`${this.basePath}index/${hash}.pf_index`;this.loaded_chunks[hash]=this._loadGenericChunk(url,"load_index_chunk")}return await this.loaded_chunks[hash]}async loadFilterChunk(hash){if(!this.loaded_filters[hash]){const url=`${this.basePath}filter/${hash}.pf_filter`;this.loaded_filters[hash]=this._loadGenericChunk(url,"load_filter_chunk")}return await this.loaded_filters[hash]}async _loadFragment(hash){let compressed_resp=await fetch(`${this.basePath}fragment/${hash}.pf_fragment`);let compressed_fragment=await compressed_resp.arrayBuffer();let fragment=this.decompress(new Uint8Array(compressed_fragment),`Fragment ${hash}`);return JSON.parse(new TextDecoder().decode(fragment))}async loadFragment(hash,weighted_locations=[],search_term){if(!this.loaded_fragments[hash]){this.loaded_fragments[hash]=this._loadFragment(hash)}let fragment=await this.loaded_fragments[hash];fragment.weighted_locations=weighted_locations;fragment.locations=weighted_locations.map((l)=>l.location);if(!fragment.raw_content){fragment.raw_content=fragment.content.replace(//g,">");fragment.content=fragment.content.replace(/\u200B/g,"")}if(!fragment.raw_url){fragment.raw_url=fragment.url}fragment.url=this.processedUrl(fragment.raw_url,search_term);const excerpt_start=calculate_excerpt_region(weighted_locations,this.excerptLength);fragment.excerpt=build_excerpt(fragment.raw_content,excerpt_start,this.excerptLength,fragment.locations);fragment.sub_results=calculate_sub_results(fragment,this.excerptLength);return fragment}fullUrl(raw){if(/^(https?:)?\/\//.test(raw)){return raw}return`${this.baseUrl}/${raw}`.replace(/\/+/g,"/").replace(/^(https?:\/)/,"$1/")}processedUrl(url,search_term){const normalized=this.fullUrl(url);if(this.highlightParam===null){return normalized}let individual_terms=search_term.split(/\s+/);try{let processed=new URL(normalized);for(const term of individual_terms){processed.searchParams.append(this.highlightParam,term)}return processed.toString()}catch(e){try{let processed=new URL(`https://example.com${normalized}`);for(const term of individual_terms){processed.searchParams.append(this.highlightParam,term)}return processed.toString().replace(/^https:\/\/example\.com/,"")}catch(e2){return normalized}}}async getPtr(){while(this.raw_ptr===null){await asyncSleep(50)}if(!this.raw_ptr){console.error("Pagefind: WASM Error (No pointer)");throw new Error("Pagefind: WASM Error (No pointer)")}return this.raw_ptr}stringifyFilters(obj={}){return JSON.stringify(obj)}stringifySorts(obj={}){let sorts=Object.entries(obj);for(let[sort,direction]of sorts){if(sorts.length>1){console.warn(`Pagefind was provided multiple sort options in this search, but can only operate on one. Using the ${sort} sort.`)}if(direction!=="asc"&&direction!=="desc"){console.warn(`Pagefind was provided a sort with unknown direction ${direction}. Supported: [asc, desc]`)}return`${sort}:${direction}`}return``}async filters(){let ptr=await this.getPtr();let filters2=this.backend.request_all_filter_indexes(ptr);let filter_array=JSON.parse(filters2);if(Array.isArray(filter_array)){let filter_chunks=filter_array.filter((v)=>v).map((chunk)=>this.loadFilterChunk(chunk));await Promise.all([...filter_chunks])}ptr=await this.getPtr();let results=this.backend.filters(ptr);return JSON.parse(results)}async preload(term,options2={}){await this.search(term,{...options2,preload:true})}async search(term,options2={}){options2={verbose:false,filters:{},sort:{},...options2};const log=(str)=>{if(options2.verbose)console.log(str)};log(`Starting search on ${this.basePath}`);let start=Date.now();let ptr=await this.getPtr();let filter_only=term===null;term=term??"";let exact_search=/^\s*".+"\s*$/.test(term);if(exact_search){log(`Running an exact search`)}let trueLanguage=null;try{trueLanguage=Intl.getCanonicalLocales(this.loadedLanguage)[0]}catch(err2){}const term_chunks=[];let segments;if(trueLanguage&&typeof Intl.Segmenter!=="undefined"){const segmenter=new Intl.Segmenter(trueLanguage,{granularity:"grapheme"});segments=[...segmenter.segment(term)].map(({segment})=>segment)}else{segments=[...term]}for(const segment of segments){if(this.includeCharacters?.includes(segment)){term_chunks.push(segment)}else if(!/^\p{Pd}|\p{Pe}|\p{Pf}|\p{Pi}|\p{Po}|\p{Ps}$/u.test(segment)){term_chunks.push(segment.toLocaleLowerCase())}}term=term_chunks.join("").replace(/\s{2,}/g," ").trim();log(`Normalized search term to ${term}`);if(!term?.length&&!filter_only){return{results:[],unfilteredResultCount:0,filters:{},totalFilters:{},timings:{preload:Date.now()-start,search:Date.now()-start,total:Date.now()-start}}}let sort_list=this.stringifySorts(options2.sort);log(`Stringified sort to ${sort_list}`);const filter_list=this.stringifyFilters(options2.filters);log(`Stringified filters to ${filter_list}`);let index_resp=this.backend.request_indexes(ptr,term);let index_array=JSON.parse(index_resp);let filter_resp=this.backend.request_filter_indexes(ptr,filter_list);let filter_array=JSON.parse(filter_resp);let chunks=index_array.filter((v)=>v).map((chunk)=>this.loadChunk(chunk));let filter_chunks=filter_array.filter((v)=>v).map((chunk)=>this.loadFilterChunk(chunk));await Promise.all([...chunks,...filter_chunks]);log(`Loaded necessary chunks to run search`);if(options2.preload){log(`Preload \u2014 bailing out of search operation now.`);return null}ptr=await this.getPtr();let searchStart=Date.now();let result=this.backend.search(ptr,term,filter_list,sort_list,exact_search);log(`Got the raw search result: ${result}`);let{filtered_counts,total_counts,results,unfiltered_total,search_keywords}=JSON.parse(result);let resultsInterface=results.map((result2)=>{let weighted_locations=result2.l.map((l)=>{let loc={weight:l.w/24,balanced_score:l.s,location:l.l};if(l.v){loc.verbose={word_string:l.v.ws,length_bonus:l.v.lb}}return loc});let locations=weighted_locations.map((l)=>l.location);let res={id:result2.p,score:result2.s*this.indexWeight,words:locations,data:async()=>await this.loadFragment(result2.p,weighted_locations,term)};if(result2.params){res.params={document_length:result2.params.dl,average_page_length:result2.params.apl,total_pages:result2.params.tp}}if(result2.scores){res.scores=result2.scores.map((r)=>{return{search_term:r.w,idf:r.idf,saturating_tf:r.b_tf,raw_tf:r.r_tf,pagefind_tf:r.p_tf,score:r.s,params:{weighted_term_frequency:r.params.w_tf,pages_containing_term:r.params.pct,length_bonus:r.params.lb}}})}return res});const searchTime=Date.now()-searchStart;const realTime=Date.now()-start;log(`Found ${results.length} result${results.length == 1 ? "" : "s"} for "${term}" in ${Date.now() - searchStart}ms (${Date.now() - start}ms realtime)`);let response={results:resultsInterface,unfilteredResultCount:unfiltered_total,filters:filtered_counts,totalFilters:total_counts,timings:{preload:realTime-searchTime,search:searchTime,total:realTime}};if(search_keywords){response.search_keywords=search_keywords}return response}};var Pagefind=class{constructor(options2={}){this.backend=wasm_bindgen;this.primaryLanguage="unknown";this.searchID=0;this.primary=new PagefindInstance({...options2,primary:true});this.instances=[this.primary];this.init(options2?.language)}async options(options2){await this.primary.options(options2)}async enterPlaygroundMode(){await this.primary.enterPlaygroundMode()}async init(overrideLanguage){if(isBrowser&&document?.querySelector){const langCode=document.querySelector("html")?.getAttribute("lang")||"unknown";this.primaryLanguage=langCode.toLocaleLowerCase()}await this.primary.init(overrideLanguage?overrideLanguage:this.primaryLanguage,{load_wasm:true})}async mergeIndex(indexPath,options2={}){if(this.primary.basePath.startsWith(indexPath)){console.warn(`Skipping mergeIndex ${indexPath} that appears to be the same as the primary index (${this.primary.basePath})`);return}let newInstance=new PagefindInstance({primary:false,basePath:indexPath});this.instances.push(newInstance);while(this.primary.wasm===null){await asyncSleep(50)}await newInstance.init(options2.language||this.primaryLanguage,{load_wasm:false});delete options2["language"];await newInstance.options(options2)}mergeFilters(filters2){const merged={};for(const searchFilter of filters2){for(const[filterKey,values]of Object.entries(searchFilter)){if(!merged[filterKey]){merged[filterKey]=values;continue}else{const filter=merged[filterKey];for(const[valueKey,count]of Object.entries(values)){filter[valueKey]=(filter[valueKey]||0)+count}}}}return merged}async filters(){let filters2=await Promise.all(this.instances.map((i2)=>i2.filters()));return this.mergeFilters(filters2)}async preload(term,options2={}){await Promise.all(this.instances.map((i2)=>i2.preload(term,options2)))}async debouncedSearch(term,options2,debounceTimeoutMs){const thisSearchID=++this.searchID;this.preload(term,options2);await asyncSleep(debounceTimeoutMs);if(thisSearchID!==this.searchID){return null}const searchResult=await this.search(term,options2);if(thisSearchID!==this.searchID){return null}return searchResult}async search(term,options2={}){let search2=await Promise.all(this.instances.map((i2)=>i2.search(term,options2)));const filters2=this.mergeFilters(search2.map((s)=>s.filters));const totalFilters=this.mergeFilters(search2.map((s)=>s.totalFilters));const results=search2.map((s)=>s.results).flat().sort((a,b)=>b.score-a.score);const timings=search2.map((s)=>s.timings);const unfilteredResultCount=search2.reduce((sum,s)=>sum+s.unfilteredResultCount,0);let response={results,unfilteredResultCount,filters:filters2,totalFilters,timings};if(search2[0].search_keywords){response.search_keywords=search2[0].search_keywords}return response}};var pagefind=void 0;var initial_options=void 0;var init_pagefind=()=>{if(!pagefind){pagefind=new Pagefind(initial_options??{})}};var options=async(new_options)=>{if(pagefind){await pagefind.options(new_options)}else{initial_options=new_options}};var init=async()=>{init_pagefind()};var destroy=async()=>{pagefind=void 0;initial_options=void 0};var mergeIndex=async(indexPath,options2)=>{init_pagefind();return await pagefind.mergeIndex(indexPath,options2)};var search=async(term,options2)=>{init_pagefind();return await pagefind.search(term,options2)};var debouncedSearch=async(term,options2,debounceTimeoutMs=300)=>{init_pagefind();return await pagefind.debouncedSearch(term,options2,debounceTimeoutMs)};var preload=async(term,options2)=>{init_pagefind();return await pagefind.preload(term,options2)};var filters=async()=>{init_pagefind();return await pagefind.filters()};export{debouncedSearch,destroy,filters,init,mergeIndex,options,preload,search} \ No newline at end of file diff --git a/_pagefind/wasm.en.pagefind b/_pagefind/wasm.en.pagefind new file mode 100644 index 00000000..e49ad34d Binary files /dev/null and b/_pagefind/wasm.en.pagefind differ diff --git a/_pagefind/wasm.unknown.pagefind b/_pagefind/wasm.unknown.pagefind new file mode 100644 index 00000000..e3f5520e Binary files /dev/null and b/_pagefind/wasm.unknown.pagefind differ diff --git a/advanced/json-output/index.html b/advanced/json-output/index.html new file mode 100644 index 00000000..05393688 --- /dev/null +++ b/advanced/json-output/index.html @@ -0,0 +1,107 @@ + + + + + +JSON Output | Kit + + + + + + + +
    +

    JSON Output

    +# JSON Output + +Use the `--json` flag to get structured output for scripting and automation: + +```bash +kit "Explain main.go" --json --quiet --no-session +``` + +## Response format + +```json +{ + "response": "Final assistant response text", + "model": "anthropic/claude-haiku-3-5-20241022", + "stop_reason": "end_turn", + "session_id": "a1b2c3d4e5f6", + "usage": { + "input_tokens": 1024, + "output_tokens": 512, + "total_tokens": 1536, + "cache_read_tokens": 0, + "cache_creation_tokens": 0 + }, + "messages": [ + { + "role": "assistant", + "parts": [ + {"type": "text", "data": "..."}, + {"type": "tool_call", "data": {"name": "...", "args": "..."}}, + {"type": "tool_result", "data": {"name": "...", "result": "..."}} + ] + } + ] +} +``` + +## Fields + +### Top-level + +| Field | Type | Description | +|-------|------|-------------| +| `response` | string | The final assistant response text | +| `model` | string | The model that was used | +| `stop_reason` | string | Why the model stopped (e.g., `end_turn`) | +| `session_id` | string | Session identifier (omitted in `--no-session` mode) | +| `usage` | object | Token usage statistics | +| `messages` | array | Full conversation history | + +### Usage + +| Field | Type | Description | +|-------|------|-------------| +| `input_tokens` | int | Tokens sent to the model | +| `output_tokens` | int | Tokens generated by the model | +| `total_tokens` | int | Sum of input and output tokens | +| `cache_read_tokens` | int | Tokens read from prompt cache | +| `cache_creation_tokens` | int | Tokens written to prompt cache | + +### Message parts + +Each message contains a `parts` array with typed entries: + +| Type | Description | +|------|-------------| +| `text` | Assistant text content | +| `tool_call` | Tool invocation with name and args | +| `tool_result` | Tool execution result | +| `reasoning` | Extended thinking content | +| `finish` | End-of-turn marker | + +## Parsing in scripts + +### bash + jq + +```bash +result=$(kit "Count files" --json --quiet --no-session) +response=$(echo "$result" | jq -r '.response') +tokens=$(echo "$result" | jq '.usage.total_tokens') +``` + +### Go SDK + +For Go programs, use the SDK's `PromptResult` method instead of parsing JSON: + +```go +result, err := host.PromptResult(ctx, "Count files") +fmt.Println(result.Response) +fmt.Println(result.Usage.TotalTokens) +```
    + + \ No newline at end of file diff --git a/advanced/subagents/index.html b/advanced/subagents/index.html new file mode 100644 index 00000000..3c820844 --- /dev/null +++ b/advanced/subagents/index.html @@ -0,0 +1,85 @@ + + + + + +Subagents | Kit + + + + + + + +
    +

    Subagents

    +# Subagents + +Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents. + +## Subprocess pattern + +Spawn Kit as a subprocess for isolated agent execution: + +```bash +kit "Analyze codebase" \ + --json \ + --no-session \ + --no-extensions \ + --quiet \ + --model anthropic/claude-haiku-3-5-20241022 +``` + +Key flags for subprocess usage: + +| Flag | Purpose | +|------|---------| +| `--quiet` | Stdout only, no TUI | +| `--no-session` | Ephemeral, no persistence | +| `--no-extensions` | Prevent recursive extension loading | +| `--json` | Machine-readable output | +| `--system-prompt` | Custom system prompt (string or file path) | + +Positional arguments are the prompt. `@file` arguments attach file content as context. + +## Built-in spawn_subagent tool + +Kit includes a built-in `spawn_subagent` tool that the LLM can use to delegate tasks to independent child agents: + +``` +spawn_subagent( + task: "Analyze the test files and summarize coverage", + model: "anthropic/claude-haiku-3-5-20241022", // optional + system_prompt: "You are a test analysis expert.", // optional + timeout_seconds: 300 // optional, max 1800 +) +``` + +Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel. + +## Extension subagents + +Extensions can spawn subagents programmatically: + +```go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Review this code for security issues", + Model: "anthropic/claude-sonnet-4-5-20250929", + SystemPrompt: "You are a security auditor.", +}) +``` + +## Go SDK subagents + +The SDK provides in-process subagent spawning: + +```go +result, err := host.Subagent(ctx, kit.SubagentConfig{ + Task: "Summarize the changes in this PR", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a code reviewer.", + Timeout: 5 * time.Minute, +}) +```
    + + \ No newline at end of file diff --git a/advanced/testing/index.html b/advanced/testing/index.html new file mode 100644 index 00000000..0672d0b2 --- /dev/null +++ b/advanced/testing/index.html @@ -0,0 +1,86 @@ + + + + + +Testing with tmux | Kit + + + + + + + +
    +

    Testing with tmux

    +# Testing with tmux + +Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development. + +## Basic pattern + +```bash +# Start Kit in a detached tmux session +tmux new-session -d -s kittest -x 120 -y 40 \ + "output/kit -e ext.go --no-session 2>kit_stderr.log" + +# Wait for startup +sleep 3 + +# Capture the current screen +tmux capture-pane -t kittest -p + +# Send input +tmux send-keys -t kittest '/command' Enter + +# Wait for response +sleep 2 + +# Capture updated screen +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +``` + +## Testing extensions + +When testing extensions, the pattern is: + +1. Build Kit with your changes +2. Start Kit in tmux with the extension loaded +3. Send slash commands or prompts +4. Capture and verify the screen output +5. Check stderr logs for errors + +```bash +# Build first +go build -o output/kit ./cmd/kit + +# Start with extension +tmux new-session -d -s kittest -x 120 -y 40 \ + "output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log" + +sleep 3 + +# Verify widget appears in screen +tmux capture-pane -t kittest -p | grep "Status" + +# Send a slash command +tmux send-keys -t kittest '/stats' Enter +sleep 1 +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +``` + +## Tips + +- Use `-x` and `-y` to set consistent terminal dimensions +- Redirect stderr to a log file (`2>kit.log`) for debugging +- Use `--no-session` to avoid creating session files during tests +- Add sufficient `sleep` between commands for the TUI to render +- Use `grep` on captured pane output to verify specific content
    + + \ No newline at end of file diff --git a/assets/callbacks-DY5vOJ-1.js b/assets/callbacks-DY5vOJ-1.js new file mode 100644 index 00000000..318f0019 --- /dev/null +++ b/assets/callbacks-DY5vOJ-1.js @@ -0,0 +1,220 @@ +const s={frontmatter:{title:"Callbacks",description:"Monitor tool calls and streaming output with the Kit Go SDK.",hidden:!1,toc:!0,draft:!1},html:`

    Callbacks

    +

    PromptWithCallbacks

    +

    The PromptWithCallbacks method provides real-time visibility into tool calls and streaming output:

    +
    response, err := host.PromptWithCallbacks(
    +    ctx,
    +    "List files in current directory",
    +    func(name, args string) {
    +        // Called when the model invokes a tool
    +        fmt.Println("Calling tool:", name)
    +    },
    +    func(name, args, result string, isError bool) {
    +        // Called when a tool returns its result
    +        if isError {
    +            fmt.Println("Tool failed:", name)
    +        }
    +    },
    +    func(chunk string) {
    +        // Called for each streaming text chunk
    +        fmt.Print(chunk)
    +    },
    +)
    +

    Callback signatures

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    CallbackSignatureWhen
    onToolCallfunc(name, args string)Model requests a tool call
    onToolResultfunc(name, args, result string, isError bool)Tool execution completes
    onStreamingfunc(chunk string)Streaming text chunk received
    +

    Any callback can be nil if you don't need it:

    +
    // Only care about streaming output
    +response, err := host.PromptWithCallbacks(ctx, "Hello", nil, nil, func(chunk string) {
    +    fmt.Print(chunk)
    +})
    +

    Event-based monitoring

    +

    For more granular control, use the event subscription API:

    +
    // Subscribe returns an unsubscribe function
    +unsub := host.OnToolCall(func(event kit.ToolCallEvent) {
    +    fmt.Printf("Tool: %s, Args: %s\\n", event.Name, event.Args)
    +})
    +defer unsub()
    +
    +unsub2 := host.OnToolResult(func(event kit.ToolResultEvent) {
    +    fmt.Printf("Result: %s (error: %v)\\n", event.Name, event.IsError)
    +})
    +defer unsub2()
    +
    +unsub3 := host.OnStreaming(func(event kit.MessageUpdateEvent) {
    +    fmt.Print(event.Chunk)
    +})
    +defer unsub3()
    +
    +unsub4 := host.OnResponse(func(event kit.ResponseEvent) {
    +    fmt.Println("Final response received")
    +})
    +defer unsub4()
    +
    +unsub5 := host.OnTurnStart(func(event kit.TurnStartEvent) {
    +    fmt.Println("Turn started")
    +})
    +defer unsub5()
    +
    +unsub6 := host.OnTurnEnd(func(event kit.TurnEndEvent) {
    +    fmt.Println("Turn ended")
    +})
    +defer unsub6()
    +

    Hook system

    +

    Hooks allow you to intercept and modify behavior. Unlike events, hooks can modify or cancel operations:

    +
    // Intercept tool calls before execution
    +host.OnBeforeToolCall(0, func(ctx context.Context, name string, args string) (string, error) {
    +    if name == "bash" {
    +        log.Println("Bash command:", args)
    +    }
    +    return args, nil // return modified args or error to cancel
    +})
    +
    +// Process results after tool execution
    +host.OnAfterToolResult(0, func(ctx context.Context, name string, result string) (string, error) {
    +    return result, nil
    +})
    +
    +// Before/after each agent turn
    +host.OnBeforeTurn(0, func(ctx context.Context) error {
    +    return nil
    +})
    +
    +host.OnAfterTurn(0, func(ctx context.Context) error {
    +    return nil
    +})
    +

    The first argument is a priority (lower = runs first).

    `,headings:[{depth:2,text:"PromptWithCallbacks",id:"promptwithcallbacks"},{depth:3,text:"Callback signatures",id:"callback-signatures"},{depth:2,text:"Event-based monitoring",id:"event-based-monitoring"},{depth:2,text:"Hook system",id:"hook-system"}],raw:` +# Callbacks + +## PromptWithCallbacks + +The \`PromptWithCallbacks\` method provides real-time visibility into tool calls and streaming output: + +\`\`\`go +response, err := host.PromptWithCallbacks( + ctx, + "List files in current directory", + func(name, args string) { + // Called when the model invokes a tool + fmt.Println("Calling tool:", name) + }, + func(name, args, result string, isError bool) { + // Called when a tool returns its result + if isError { + fmt.Println("Tool failed:", name) + } + }, + func(chunk string) { + // Called for each streaming text chunk + fmt.Print(chunk) + }, +) +\`\`\` + +### Callback signatures + +| Callback | Signature | When | +|----------|-----------|------| +| \`onToolCall\` | \`func(name, args string)\` | Model requests a tool call | +| \`onToolResult\` | \`func(name, args, result string, isError bool)\` | Tool execution completes | +| \`onStreaming\` | \`func(chunk string)\` | Streaming text chunk received | + +Any callback can be \`nil\` if you don't need it: + +\`\`\`go +// Only care about streaming output +response, err := host.PromptWithCallbacks(ctx, "Hello", nil, nil, func(chunk string) { + fmt.Print(chunk) +}) +\`\`\` + +## Event-based monitoring + +For more granular control, use the event subscription API: + +\`\`\`go +// Subscribe returns an unsubscribe function +unsub := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Printf("Tool: %s, Args: %s\\n", event.Name, event.Args) +}) +defer unsub() + +unsub2 := host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Printf("Result: %s (error: %v)\\n", event.Name, event.IsError) +}) +defer unsub2() + +unsub3 := host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +defer unsub3() + +unsub4 := host.OnResponse(func(event kit.ResponseEvent) { + fmt.Println("Final response received") +}) +defer unsub4() + +unsub5 := host.OnTurnStart(func(event kit.TurnStartEvent) { + fmt.Println("Turn started") +}) +defer unsub5() + +unsub6 := host.OnTurnEnd(func(event kit.TurnEndEvent) { + fmt.Println("Turn ended") +}) +defer unsub6() +\`\`\` + +## Hook system + +Hooks allow you to intercept and modify behavior. Unlike events, hooks can modify or cancel operations: + +\`\`\`go +// Intercept tool calls before execution +host.OnBeforeToolCall(0, func(ctx context.Context, name string, args string) (string, error) { + if name == "bash" { + log.Println("Bash command:", args) + } + return args, nil // return modified args or error to cancel +}) + +// Process results after tool execution +host.OnAfterToolResult(0, func(ctx context.Context, name string, result string) (string, error) { + return result, nil +}) + +// Before/after each agent turn +host.OnBeforeTurn(0, func(ctx context.Context) error { + return nil +}) + +host.OnAfterTurn(0, func(ctx context.Context) error { + return nil +}) +\`\`\` + +The first argument is a priority (lower = runs first). +`};export{s as default}; diff --git a/assets/capabilities-hnq2TbFu.js b/assets/capabilities-hnq2TbFu.js new file mode 100644 index 00000000..0ea7a85d --- /dev/null +++ b/assets/capabilities-hnq2TbFu.js @@ -0,0 +1,485 @@ +const s={frontmatter:{title:"Capabilities",description:"All extension capabilities — lifecycle events, tools, commands, widgets, and more.",hidden:!1,toc:!0,draft:!1},html:`

    Extension Capabilities

    +

    Lifecycle events

    +

    Extensions can hook into 18 lifecycle events:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EventDescription
    OnSessionStartSession initialized
    OnSessionShutdownSession ending
    OnBeforeAgentStartBefore the agent loop begins
    OnAgentStartAgent loop started
    OnAgentEndAgent loop completed
    OnToolCallTool call requested by the model
    OnToolExecutionStartTool execution beginning
    OnToolExecutionEndTool execution completed
    OnToolResultTool result returned
    OnInputUser input received
    OnMessageStartAssistant message started
    OnMessageUpdateStreaming text chunk received
    OnMessageEndAssistant message completed
    OnModelChangeModel switched
    OnContextPrepareContext being assembled for the model
    OnBeforeForkBefore forking a conversation branch
    OnBeforeSessionSwitchBefore switching sessions
    OnBeforeCompactBefore conversation compaction
    +

    Example

    +
    api.OnToolCall(func(event ext.ToolCallEvent, ctx ext.Context) {
    +    ctx.PrintInfo("Calling tool: " + event.Name)
    +})
    +
    +api.OnAgentEnd(func(_ ext.AgentEndEvent, ctx ext.Context) {
    +    ctx.PrintInfo("Agent finished")
    +})
    +

    Tools

    +

    Register custom tools that the LLM can invoke:

    +
    api.RegisterTool(ext.ToolDef{
    +    Name:        "weather",
    +    Description: "Get current weather for a location",
    +    Parameters: map[string]ext.ParameterDef{
    +        "city": {Type: "string", Description: "City name", Required: true},
    +    },
    +    Handler: func(ctx ext.Context, params map[string]any) (string, error) {
    +        city := params["city"].(string)
    +        return "Sunny, 72°F in " + city, nil
    +    },
    +})
    +

    Commands

    +

    Register slash commands that users can invoke directly:

    +
    api.RegisterCommand(ext.CommandDef{
    +    Name:        "stats",
    +    Description: "Show context statistics",
    +    Handler: func(ctx ext.Context, args string) {
    +        stats := ctx.GetContextStats()
    +        ctx.PrintInfo(fmt.Sprintf("Tokens: %d", stats.TotalTokens))
    +    },
    +})
    +

    Widgets

    +

    Add persistent status displays above or below the input area:

    +
    ctx.SetWidget(ext.WidgetConfig{
    +    ID:       "token-count",
    +    Position: "bottom",
    +    Content:  ext.WidgetContent{Text: "Tokens: 1,234"},
    +})
    +
    +// Update later
    +ctx.SetWidget(ext.WidgetConfig{
    +    ID:       "token-count",
    +    Position: "bottom",
    +    Content:  ext.WidgetContent{Text: "Tokens: 2,456"},
    +})
    +
    +// Remove
    +ctx.RemoveWidget("token-count")
    +

    Headers and footers

    +

    Persistent content above and below the conversation:

    +
    ctx.SetHeader(ext.HeaderFooterConfig{
    +    Content: ext.WidgetContent{Text: "Project: my-app | Branch: main"},
    +})
    +
    +ctx.SetFooter(ext.HeaderFooterConfig{
    +    Content: ext.WidgetContent{Text: "Plan Mode (read-only)"},
    +})
    +

    Status bar

    +

    Custom status bar entries:

    +
    ctx.SetStatus("mode", "Planning")
    +ctx.RemoveStatus("mode")
    +

    Shortcuts

    +

    Global keyboard shortcuts:

    +
    api.RegisterShortcut(ext.ShortcutDef{
    +    Key:         "ctrl+t",
    +    Description: "Toggle plan mode",
    +}, func(ctx ext.Context) {
    +    // handle shortcut
    +})
    +

    Overlays

    +

    Modal dialogs with markdown content:

    +
    ctx.ShowOverlay(ext.OverlayConfig{
    +    Title:   "Help",
    +    Content: "# Keyboard Shortcuts\\n\\n- **ctrl+t** — Toggle plan mode\\n- **ctrl+s** — Save session",
    +})
    +

    Tool renderers

    +

    Customize how specific tool calls are displayed in the TUI:

    +
    api.RegisterToolRenderer(ext.ToolRenderConfig{
    +    ToolName: "bash",
    +    Render: func(name, args, result string, isError bool) string {
    +        return "$ " + args + "\\n" + result
    +    },
    +})
    +

    Message renderers

    +

    Custom rendering for assistant messages:

    +
    api.RegisterMessageRenderer(ext.MessageRendererConfig{
    +    Name: "custom",
    +    Render: func(content string) string {
    +        return ">> " + content
    +    },
    +})
    +

    Editor interceptors

    +

    Handle key events and wrap the editor's rendering:

    +
    ctx.SetEditor(ext.EditorConfig{
    +    HandleKey: func(key, text string) ext.EditorKeyAction {
    +        if key == "escape" {
    +            return ext.EditorKeyAction{Handled: true}
    +        }
    +        return ext.EditorKeyAction{Handled: false}
    +    },
    +})
    +

    Interactive prompts

    +

    Select, confirm, input, and multi-select dialogs:

    +
    // Single select
    +response := ctx.PromptSelect(ext.PromptSelectConfig{
    +    Title:   "Choose a model",
    +    Options: []string{"claude-sonnet", "gpt-4o", "llama3"},
    +})
    +
    +// Confirm
    +confirmed := ctx.PromptConfirm(ext.PromptConfirmConfig{
    +    Title: "Delete this file?",
    +})
    +
    +// Text input
    +name := ctx.PromptInput(ext.PromptInputConfig{
    +    Title:       "Enter project name",
    +    Placeholder: "my-project",
    +})
    +

    Options

    +

    Register configurable extension options:

    +
    api.RegisterOption(ext.OptionDef{
    +    Name:         "auto-commit",
    +    Description:  "Automatically commit on shutdown",
    +    DefaultValue: "false",
    +})
    +

    Subagents

    +

    Spawn in-process child Kit instances:

    +
    result := ctx.SpawnSubagent(ext.SubagentConfig{
    +    Task:         "Analyze the test files and summarize coverage",
    +    Model:        "anthropic/claude-haiku-3-5-20241022",
    +    SystemPrompt: "You are a test analysis expert.",
    +})
    +

    LLM completion

    +

    Make direct model calls without going through the agent loop:

    +
    response := ctx.Complete(ext.CompleteRequest{
    +    Prompt: "Summarize this in one sentence: " + content,
    +})
    +

    Custom events

    +

    Inter-extension communication:

    +
    // Emit
    +ctx.EmitCustomEvent("my-extension:data-ready", payload)
    +
    +// Listen
    +api.OnCustomEvent("my-extension:data-ready", func(data any, ctx ext.Context) {
    +    // handle event
    +})
    `,headings:[{depth:2,text:"Lifecycle events",id:"lifecycle-events"},{depth:3,text:"Example",id:"example"},{depth:2,text:"Tools",id:"tools"},{depth:2,text:"Commands",id:"commands"},{depth:2,text:"Widgets",id:"widgets"},{depth:2,text:"Headers and footers",id:"headers-and-footers"},{depth:2,text:"Status bar",id:"status-bar"},{depth:2,text:"Shortcuts",id:"shortcuts"},{depth:2,text:"Overlays",id:"overlays"},{depth:2,text:"Tool renderers",id:"tool-renderers"},{depth:2,text:"Message renderers",id:"message-renderers"},{depth:2,text:"Editor interceptors",id:"editor-interceptors"},{depth:2,text:"Interactive prompts",id:"interactive-prompts"},{depth:2,text:"Options",id:"options"},{depth:2,text:"Subagents",id:"subagents"},{depth:2,text:"LLM completion",id:"llm-completion"},{depth:2,text:"Custom events",id:"custom-events"}],raw:` +# Extension Capabilities + +## Lifecycle events + +Extensions can hook into 18 lifecycle events: + +| Event | Description | +|-------|-------------| +| \`OnSessionStart\` | Session initialized | +| \`OnSessionShutdown\` | Session ending | +| \`OnBeforeAgentStart\` | Before the agent loop begins | +| \`OnAgentStart\` | Agent loop started | +| \`OnAgentEnd\` | Agent loop completed | +| \`OnToolCall\` | Tool call requested by the model | +| \`OnToolExecutionStart\` | Tool execution beginning | +| \`OnToolExecutionEnd\` | Tool execution completed | +| \`OnToolResult\` | Tool result returned | +| \`OnInput\` | User input received | +| \`OnMessageStart\` | Assistant message started | +| \`OnMessageUpdate\` | Streaming text chunk received | +| \`OnMessageEnd\` | Assistant message completed | +| \`OnModelChange\` | Model switched | +| \`OnContextPrepare\` | Context being assembled for the model | +| \`OnBeforeFork\` | Before forking a conversation branch | +| \`OnBeforeSessionSwitch\` | Before switching sessions | +| \`OnBeforeCompact\` | Before conversation compaction | + +### Example + +\`\`\`go +api.OnToolCall(func(event ext.ToolCallEvent, ctx ext.Context) { + ctx.PrintInfo("Calling tool: " + event.Name) +}) + +api.OnAgentEnd(func(_ ext.AgentEndEvent, ctx ext.Context) { + ctx.PrintInfo("Agent finished") +}) +\`\`\` + +## Tools + +Register custom tools that the LLM can invoke: + +\`\`\`go +api.RegisterTool(ext.ToolDef{ + Name: "weather", + Description: "Get current weather for a location", + Parameters: map[string]ext.ParameterDef{ + "city": {Type: "string", Description: "City name", Required: true}, + }, + Handler: func(ctx ext.Context, params map[string]any) (string, error) { + city := params["city"].(string) + return "Sunny, 72°F in " + city, nil + }, +}) +\`\`\` + +## Commands + +Register slash commands that users can invoke directly: + +\`\`\`go +api.RegisterCommand(ext.CommandDef{ + Name: "stats", + Description: "Show context statistics", + Handler: func(ctx ext.Context, args string) { + stats := ctx.GetContextStats() + ctx.PrintInfo(fmt.Sprintf("Tokens: %d", stats.TotalTokens)) + }, +}) +\`\`\` + +## Widgets + +Add persistent status displays above or below the input area: + +\`\`\`go +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 1,234"}, +}) + +// Update later +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 2,456"}, +}) + +// Remove +ctx.RemoveWidget("token-count") +\`\`\` + +## Headers and footers + +Persistent content above and below the conversation: + +\`\`\`go +ctx.SetHeader(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Project: my-app | Branch: main"}, +}) + +ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Plan Mode (read-only)"}, +}) +\`\`\` + +## Status bar + +Custom status bar entries: + +\`\`\`go +ctx.SetStatus("mode", "Planning") +ctx.RemoveStatus("mode") +\`\`\` + +## Shortcuts + +Global keyboard shortcuts: + +\`\`\`go +api.RegisterShortcut(ext.ShortcutDef{ + Key: "ctrl+t", + Description: "Toggle plan mode", +}, func(ctx ext.Context) { + // handle shortcut +}) +\`\`\` + +## Overlays + +Modal dialogs with markdown content: + +\`\`\`go +ctx.ShowOverlay(ext.OverlayConfig{ + Title: "Help", + Content: "# Keyboard Shortcuts\\n\\n- **ctrl+t** — Toggle plan mode\\n- **ctrl+s** — Save session", +}) +\`\`\` + +## Tool renderers + +Customize how specific tool calls are displayed in the TUI: + +\`\`\`go +api.RegisterToolRenderer(ext.ToolRenderConfig{ + ToolName: "bash", + Render: func(name, args, result string, isError bool) string { + return "$ " + args + "\\n" + result + }, +}) +\`\`\` + +## Message renderers + +Custom rendering for assistant messages: + +\`\`\`go +api.RegisterMessageRenderer(ext.MessageRendererConfig{ + Name: "custom", + Render: func(content string) string { + return ">> " + content + }, +}) +\`\`\` + +## Editor interceptors + +Handle key events and wrap the editor's rendering: + +\`\`\`go +ctx.SetEditor(ext.EditorConfig{ + HandleKey: func(key, text string) ext.EditorKeyAction { + if key == "escape" { + return ext.EditorKeyAction{Handled: true} + } + return ext.EditorKeyAction{Handled: false} + }, +}) +\`\`\` + +## Interactive prompts + +Select, confirm, input, and multi-select dialogs: + +\`\`\`go +// Single select +response := ctx.PromptSelect(ext.PromptSelectConfig{ + Title: "Choose a model", + Options: []string{"claude-sonnet", "gpt-4o", "llama3"}, +}) + +// Confirm +confirmed := ctx.PromptConfirm(ext.PromptConfirmConfig{ + Title: "Delete this file?", +}) + +// Text input +name := ctx.PromptInput(ext.PromptInputConfig{ + Title: "Enter project name", + Placeholder: "my-project", +}) +\`\`\` + +## Options + +Register configurable extension options: + +\`\`\`go +api.RegisterOption(ext.OptionDef{ + Name: "auto-commit", + Description: "Automatically commit on shutdown", + DefaultValue: "false", +}) +\`\`\` + +## Subagents + +Spawn in-process child Kit instances: + +\`\`\`go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Analyze the test files and summarize coverage", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a test analysis expert.", +}) +\`\`\` + +## LLM completion + +Make direct model calls without going through the agent loop: + +\`\`\`go +response := ctx.Complete(ext.CompleteRequest{ + Prompt: "Summarize this in one sentence: " + content, +}) +\`\`\` + +## Custom events + +Inter-extension communication: + +\`\`\`go +// Emit +ctx.EmitCustomEvent("my-extension:data-ready", payload) + +// Listen +api.OnCustomEvent("my-extension:data-ready", func(data any, ctx ext.Context) { + // handle event +}) +\`\`\` +`};export{s as default}; diff --git a/assets/commands-B2onU7kX.js b/assets/commands-B2onU7kX.js new file mode 100644 index 00000000..0aa772f4 --- /dev/null +++ b/assets/commands-B2onU7kX.js @@ -0,0 +1,95 @@ +const s={frontmatter:{title:"Commands",description:"Complete reference for all Kit CLI subcommands.",hidden:!1,toc:!0,draft:!1},html:`

    Commands

    +

    Authentication

    +

    For OAuth-enabled providers like Anthropic.

    +
    kit auth login [provider]    # Start OAuth flow (e.g., anthropic)
    +kit auth logout [provider]   # Remove credentials for provider
    +kit auth status              # Check authentication status
    +

    Model database

    +

    Manage the local model database that maps provider names to API configurations.

    +
    kit models [provider]        # List available models (optionally filter by provider)
    +kit models --all             # Show all providers (not just Fantasy-compatible)
    +kit update-models [source]   # Update model database
    +

    The update-models command accepts an optional source argument:

    +
      +
    • (none) — update from models.dev
    • +
    • A URL — fetch from a custom endpoint
    • +
    • A file path — load from a local file
    • +
    • embedded — reset to the bundled database
    • +
    +

    Extension management

    +
    kit extensions list          # List discovered extensions
    +kit extensions validate      # Validate extension files
    +kit extensions init          # Generate example extension template
    +

    Installing extensions from git

    +
    kit install <git-url>        # Install extensions from git repositories
    +kit install -l <git-url>     # Install to project-local .kit/git/ directory
    +kit install -u <git-url>     # Update an already-installed package
    +kit install --uninstall <pkg> # Remove an installed package
    +kit install --all            # Install all extensions without prompting
    +

    Skills

    +
    kit skill                    # Install the Kit extensions skill via skills.sh
    +

    ACP server

    +

    Run Kit as an ACP (Agent Client Protocol) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout.

    +
    kit acp                      # Start as ACP agent
    +kit acp --debug              # With debug logging to stderr
    `,headings:[{depth:2,text:"Authentication",id:"authentication"},{depth:2,text:"Model database",id:"model-database"},{depth:2,text:"Extension management",id:"extension-management"},{depth:3,text:"Installing extensions from git",id:"installing-extensions-from-git"},{depth:2,text:"Skills",id:"skills"},{depth:2,text:"ACP server",id:"acp-server"}],raw:` +# Commands + +## Authentication + +For OAuth-enabled providers like Anthropic. + +\`\`\`bash +kit auth login [provider] # Start OAuth flow (e.g., anthropic) +kit auth logout [provider] # Remove credentials for provider +kit auth status # Check authentication status +\`\`\` + +## Model database + +Manage the local model database that maps provider names to API configurations. + +\`\`\`bash +kit models [provider] # List available models (optionally filter by provider) +kit models --all # Show all providers (not just Fantasy-compatible) +kit update-models [source] # Update model database +\`\`\` + +The \`update-models\` command accepts an optional source argument: +- *(none)* — update from [models.dev](https://models.dev) +- A URL — fetch from a custom endpoint +- A file path — load from a local file +- \`embedded\` — reset to the bundled database + +## Extension management + +\`\`\`bash +kit extensions list # List discovered extensions +kit extensions validate # Validate extension files +kit extensions init # Generate example extension template +\`\`\` + +### Installing extensions from git + +\`\`\`bash +kit install # Install extensions from git repositories +kit install -l # Install to project-local .kit/git/ directory +kit install -u # Update an already-installed package +kit install --uninstall # Remove an installed package +kit install --all # Install all extensions without prompting +\`\`\` + +## Skills + +\`\`\`bash +kit skill # Install the Kit extensions skill via skills.sh +\`\`\` + +## ACP server + +Run Kit as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout. + +\`\`\`bash +kit acp # Start as ACP agent +kit acp --debug # With debug logging to stderr +\`\`\` +`};export{s as default}; diff --git a/assets/configuration-BU6tST5r.js b/assets/configuration-BU6tST5r.js new file mode 100644 index 00000000..61af25fe --- /dev/null +++ b/assets/configuration-BU6tST5r.js @@ -0,0 +1,195 @@ +const n={frontmatter:{title:"Configuration",description:"Configure Kit using config files, environment variables, and CLI flags.",hidden:!1,toc:!0,draft:!1},html:`

    Configuration

    +

    Kit looks for configuration in the following locations, in order of priority:

    +
      +
    1. CLI flags
    2. +
    3. Environment variables (with KIT_ prefix)
    4. +
    5. ./.kit.yml / ./.kit.yaml / ./.kit.json (project-local)
    6. +
    7. ~/.kit.yml / ~/.kit.yaml / ~/.kit.json (global)
    8. +
    +

    Basic configuration

    +

    Create ~/.kit.yml:

    +
    model: anthropic/claude-sonnet-4-5-20250929
    +max-tokens: 4096
    +temperature: 0.7
    +stream: true
    +

    All configuration keys

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyTypeDefaultDescription
    modelstringanthropic/claude-sonnet-4-5-20250929Model to use (provider/model format)
    max-tokensint4096Maximum tokens in response
    temperaturefloat0.7Randomness 0.0–1.0
    top-pfloat0.95Nucleus sampling 0.0–1.0
    top-kint40Limit top K tokens
    streambooltrueEnable streaming output
    debugboolfalseEnable debug logging
    compactboolfalseEnable compact output mode
    system-promptstringSystem prompt text or file path
    max-stepsint0Maximum agent steps (0 = unlimited)
    thinking-levelstringoffExtended thinking: off, minimal, low, medium, high
    provider-api-keystringAPI key for the provider
    provider-urlstringBase URL for provider API
    tls-skip-verifyboolfalseSkip TLS certificate verification
    stop-sequenceslistCustom stop sequences
    themestringUI theme
    markdown-themestringMarkdown rendering theme
    +

    Environment variables

    +

    Any configuration key can be set via environment variable with the KIT_ prefix. Hyphens become underscores:

    +
    export KIT_MODEL="openai/gpt-4o"
    +export KIT_MAX_TOKENS="8192"
    +export KIT_TEMPERATURE="0.5"
    +

    Provider API keys use their own environment variables:

    +
    export ANTHROPIC_API_KEY="sk-..."
    +export OPENAI_API_KEY="sk-..."
    +export GOOGLE_API_KEY="..."
    +

    MCP server configuration

    +

    Add external MCP servers to your .kit.yml:

    +
    mcpServers:
    +  filesystem:
    +    type: local
    +    command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
    +    environment:
    +      LOG_LEVEL: "info"
    +    allowedTools: ["read_file", "write_file"]
    +    excludedTools: ["delete_file"]
    +
    +  search:
    +    type: remote
    +    url: "https://mcp.example.com/search"
    +

    MCP server fields

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeDescription
    typestringlocal (stdio) or remote (streamable HTTP)
    commandlistCommand and args for local servers
    environmentmapEnvironment variables for the server process
    urlstringURL for remote servers
    allowedToolslistWhitelist of tool names to expose
    excludedToolslistBlacklist of tool names to hide
    +

    A legacy format with transport, args, env, and headers fields is also supported.

    `,headings:[{depth:2,text:"Basic configuration",id:"basic-configuration"},{depth:2,text:"All configuration keys",id:"all-configuration-keys"},{depth:2,text:"Environment variables",id:"environment-variables"},{depth:2,text:"MCP server configuration",id:"mcp-server-configuration"},{depth:3,text:"MCP server fields",id:"mcp-server-fields"}],raw:'\n# Configuration\n\nKit looks for configuration in the following locations, in order of priority:\n\n1. CLI flags\n2. Environment variables (with `KIT_` prefix)\n3. `./.kit.yml` / `./.kit.yaml` / `./.kit.json` (project-local)\n4. `~/.kit.yml` / `~/.kit.yaml` / `~/.kit.json` (global)\n\n## Basic configuration\n\nCreate `~/.kit.yml`:\n\n```yaml\nmodel: anthropic/claude-sonnet-4-5-20250929\nmax-tokens: 4096\ntemperature: 0.7\nstream: true\n```\n\n## All configuration keys\n\n| Key | Type | Default | Description |\n|-----|------|---------|-------------|\n| `model` | string | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) |\n| `max-tokens` | int | `4096` | Maximum tokens in response |\n| `temperature` | float | `0.7` | Randomness 0.0–1.0 |\n| `top-p` | float | `0.95` | Nucleus sampling 0.0–1.0 |\n| `top-k` | int | `40` | Limit top K tokens |\n| `stream` | bool | `true` | Enable streaming output |\n| `debug` | bool | `false` | Enable debug logging |\n| `compact` | bool | `false` | Enable compact output mode |\n| `system-prompt` | string | — | System prompt text or file path |\n| `max-steps` | int | `0` | Maximum agent steps (0 = unlimited) |\n| `thinking-level` | string | `off` | Extended thinking: off, minimal, low, medium, high |\n| `provider-api-key` | string | — | API key for the provider |\n| `provider-url` | string | — | Base URL for provider API |\n| `tls-skip-verify` | bool | `false` | Skip TLS certificate verification |\n| `stop-sequences` | list | — | Custom stop sequences |\n| `theme` | string | — | UI theme |\n| `markdown-theme` | string | — | Markdown rendering theme |\n\n## Environment variables\n\nAny configuration key can be set via environment variable with the `KIT_` prefix. Hyphens become underscores:\n\n```bash\nexport KIT_MODEL="openai/gpt-4o"\nexport KIT_MAX_TOKENS="8192"\nexport KIT_TEMPERATURE="0.5"\n```\n\nProvider API keys use their own environment variables:\n\n```bash\nexport ANTHROPIC_API_KEY="sk-..."\nexport OPENAI_API_KEY="sk-..."\nexport GOOGLE_API_KEY="..."\n```\n\n## MCP server configuration\n\nAdd external MCP servers to your `.kit.yml`:\n\n```yaml\nmcpServers:\n filesystem:\n type: local\n command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]\n environment:\n LOG_LEVEL: "info"\n allowedTools: ["read_file", "write_file"]\n excludedTools: ["delete_file"]\n\n search:\n type: remote\n url: "https://mcp.example.com/search"\n```\n\n### MCP server fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | string | `local` (stdio) or `remote` (streamable HTTP) |\n| `command` | list | Command and args for local servers |\n| `environment` | map | Environment variables for the server process |\n| `url` | string | URL for remote servers |\n| `allowedTools` | list | Whitelist of tool names to expose |\n| `excludedTools` | list | Blacklist of tool names to hide |\n\nA legacy format with `transport`, `args`, `env`, and `headers` fields is also supported.\n'};export{n as default}; diff --git a/assets/development-BTUHn6x2.js b/assets/development-BTUHn6x2.js new file mode 100644 index 00000000..7cb30624 --- /dev/null +++ b/assets/development-BTUHn6x2.js @@ -0,0 +1,138 @@ +const e={frontmatter:{title:"Development",description:"Build, test, and contribute to Kit.",hidden:!1,toc:!0,draft:!1},html:`

    Development

    +

    Build and test

    +
    # Build
    +go build -o output/kit ./cmd/kit
    +
    +# Run all tests
    +go test -race ./...
    +
    +# Run a specific test
    +go test -race ./cmd -run TestScriptExecution
    +
    +# Lint
    +go vet ./...
    +
    +# Format
    +go fmt ./...
    +

    Project structure

    +
    cmd/kit/             - CLI entry point (main.go)
    +cmd/                 - CLI command implementations (root, auth, models, etc.)
    +pkg/kit/             - Go SDK for embedding Kit
    +internal/app/        - Application orchestrator (agent loop, message store, queue)
    +internal/agent/      - Agent execution and tool dispatch
    +internal/auth/       - OAuth authentication and credential storage
    +internal/acpserver/  - ACP (Agent Client Protocol) server
    +internal/clipboard/  - Cross-platform clipboard operations
    +internal/compaction/ - Conversation compaction and summarization
    +internal/config/     - Configuration management
    +internal/core/       - Built-in tools (bash, read, write, edit, grep, find, ls)
    +internal/extensions/ - Yaegi extension system
    +internal/kitsetup/   - Initial setup wizard
    +internal/message/    - Message content types and structured content blocks
    +internal/models/     - Provider and model management
    +internal/session/    - Session persistence (tree-based JSONL)
    +internal/skills/     - Skill loading and system prompt composition
    +internal/tools/      - MCP tool integration
    +internal/ui/         - Bubble Tea TUI components
    +examples/extensions/ - Example extension files
    +npm/                 - NPM package wrapper for distribution
    +
    +

    Architecture overview

    +

    Kit is built around a few key architectural patterns:

    +

    Multi-provider LLM support

    +

    The llm.Provider interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API.

    +

    MCP client-server model

    +

    External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in .kit.yml.

    +

    Extension system

    +

    Extensions are Go source files interpreted at runtime by Yaegi. The internal/extensions/ package manages loading, symbol export, and lifecycle dispatch. See the Extension System docs for details.

    +

    TUI architecture

    +

    The interactive terminal UI is built with Bubble Tea v2, using a parent-child model where AppModel manages child components (InputComponent, StreamComponent, etc.).

    +

    Decoupling pattern

    +

    cmd/root.go contains converter functions (e.g., widgetProviderForUI()) that bridge internal/extensions/ types to internal/ui/ types. The UI never imports the extensions package directly.

    +

    Contributing

    +

    Contributions are welcome! Please see the contribution guide for guidelines.

    +

    Community

    +`,headings:[{depth:2,text:"Build and test",id:"build-and-test"},{depth:2,text:"Project structure",id:"project-structure"},{depth:2,text:"Architecture overview",id:"architecture-overview"},{depth:3,text:"Multi-provider LLM support",id:"multi-provider-llm-support"},{depth:3,text:"MCP client-server model",id:"mcp-client-server-model"},{depth:3,text:"Extension system",id:"extension-system"},{depth:3,text:"TUI architecture",id:"tui-architecture"},{depth:3,text:"Decoupling pattern",id:"decoupling-pattern"},{depth:2,text:"Contributing",id:"contributing"},{depth:2,text:"Community",id:"community"}],raw:` +# Development + +## Build and test + +\`\`\`bash +# Build +go build -o output/kit ./cmd/kit + +# Run all tests +go test -race ./... + +# Run a specific test +go test -race ./cmd -run TestScriptExecution + +# Lint +go vet ./... + +# Format +go fmt ./... +\`\`\` + +## Project structure + +\`\`\` +cmd/kit/ - CLI entry point (main.go) +cmd/ - CLI command implementations (root, auth, models, etc.) +pkg/kit/ - Go SDK for embedding Kit +internal/app/ - Application orchestrator (agent loop, message store, queue) +internal/agent/ - Agent execution and tool dispatch +internal/auth/ - OAuth authentication and credential storage +internal/acpserver/ - ACP (Agent Client Protocol) server +internal/clipboard/ - Cross-platform clipboard operations +internal/compaction/ - Conversation compaction and summarization +internal/config/ - Configuration management +internal/core/ - Built-in tools (bash, read, write, edit, grep, find, ls) +internal/extensions/ - Yaegi extension system +internal/kitsetup/ - Initial setup wizard +internal/message/ - Message content types and structured content blocks +internal/models/ - Provider and model management +internal/session/ - Session persistence (tree-based JSONL) +internal/skills/ - Skill loading and system prompt composition +internal/tools/ - MCP tool integration +internal/ui/ - Bubble Tea TUI components +examples/extensions/ - Example extension files +npm/ - NPM package wrapper for distribution +\`\`\` + +## Architecture overview + +Kit is built around a few key architectural patterns: + +### Multi-provider LLM support + +The \`llm.Provider\` interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API. + +### MCP client-server model + +External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in \`.kit.yml\`. + +### Extension system + +Extensions are Go source files interpreted at runtime by Yaegi. The \`internal/extensions/\` package manages loading, symbol export, and lifecycle dispatch. See the [Extension System](/extensions/overview) docs for details. + +### TUI architecture + +The interactive terminal UI is built with [Bubble Tea v2](https://github.com/charmbracelet/bubbletea), using a parent-child model where \`AppModel\` manages child components (\`InputComponent\`, \`StreamComponent\`, etc.). + +### Decoupling pattern + +\`cmd/root.go\` contains converter functions (e.g., \`widgetProviderForUI()\`) that bridge \`internal/extensions/\` types to \`internal/ui/\` types. The UI never imports the extensions package directly. + +## Contributing + +Contributions are welcome! Please see the [contribution guide](https://github.com/mark3labs/kit/blob/master/contribute/contribute.md) for guidelines. + +## Community + +- [Discord](https://discord.gg/RqSS2NQVsY) +- [GitHub Issues](https://github.com/mark3labs/kit/issues) +`};export{e as default}; diff --git a/assets/examples-C-0Ua9md.js b/assets/examples-C-0Ua9md.js new file mode 100644 index 00000000..bc7e0a68 --- /dev/null +++ b/assets/examples-C-0Ua9md.js @@ -0,0 +1,273 @@ +const t={frontmatter:{title:"Examples",description:"Catalog of example extensions included with Kit.",hidden:!1,toc:!0,draft:!1},html:`

    Extension Examples

    +

    Kit ships with a rich set of example extensions in the examples/extensions/ directory. These serve as both documentation and starting points for your own extensions.

    +

    UI and display

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ExtensionDescription
    minimal.goClean UI with custom footer
    branded-output.goBranded output rendering
    header-footer-demo.goCustom headers and footers
    widget-status.goPersistent status widgets
    overlay-demo.goModal dialogs
    tool-renderer-demo.goCustom tool call rendering
    custom-editor-demo.goVim-like modal editor
    pirate.goPirate-themed personality
    +

    Workflow and automation

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ExtensionDescription
    auto-commit.goAuto-commit changes on shutdown
    plan-mode.goRead-only planning mode
    permission-gate.goPermission gating for destructive tools
    confirm-destructive.goConfirm destructive operations
    protected-paths.goPath protection for sensitive files
    project-rules.goProject-specific rules injection
    compact-notify.goNotification on conversation compaction
    +

    Interactive features

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ExtensionDescription
    prompt-demo.goInteractive prompts (select/confirm/input)
    bookmark.goBookmark conversations
    inline-bash.goInline bash execution
    interactive-shell.goInteractive shell integration
    notify.goDesktop notifications
    +

    Agent and context

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    ExtensionDescription
    tool-logger.goLog all tool calls
    context-inject.goInject context into conversations
    summarize.goConversation summarization
    lsp-diagnostics.goLSP diagnostic integration
    +

    Multi-agent

    + + + + + + + + + + + + + + + + + + + + + +
    ExtensionDescription
    kit-kit.goKit-in-Kit sub-agent spawning
    subagent-widget.goMulti-agent orchestration with status widget
    subagent-test.goSubagent testing utilities
    +

    Development

    + + + + + + + + + + + + + +
    ExtensionDescription
    dev-reload.goDevelopment live-reload
    +

    Subdirectory extensions

    + + + + + + + + + + + + + + + + + + + + + +
    DirectoryDescription
    kit-kit-agents/Multi-agent orchestration example
    kit-telegram/Telegram bot integration
    status-tools/Status bar tool examples
    `,headings:[{depth:2,text:"UI and display",id:"ui-and-display"},{depth:2,text:"Workflow and automation",id:"workflow-and-automation"},{depth:2,text:"Interactive features",id:"interactive-features"},{depth:2,text:"Agent and context",id:"agent-and-context"},{depth:2,text:"Multi-agent",id:"multi-agent"},{depth:2,text:"Development",id:"development"},{depth:2,text:"Subdirectory extensions",id:"subdirectory-extensions"}],raw:` +# Extension Examples + +Kit ships with a rich set of example extensions in the \`examples/extensions/\` directory. These serve as both documentation and starting points for your own extensions. + +## UI and display + +| Extension | Description | +|-----------|-------------| +| \`minimal.go\` | Clean UI with custom footer | +| \`branded-output.go\` | Branded output rendering | +| \`header-footer-demo.go\` | Custom headers and footers | +| \`widget-status.go\` | Persistent status widgets | +| \`overlay-demo.go\` | Modal dialogs | +| \`tool-renderer-demo.go\` | Custom tool call rendering | +| \`custom-editor-demo.go\` | Vim-like modal editor | +| \`pirate.go\` | Pirate-themed personality | + +## Workflow and automation + +| Extension | Description | +|-----------|-------------| +| \`auto-commit.go\` | Auto-commit changes on shutdown | +| \`plan-mode.go\` | Read-only planning mode | +| \`permission-gate.go\` | Permission gating for destructive tools | +| \`confirm-destructive.go\` | Confirm destructive operations | +| \`protected-paths.go\` | Path protection for sensitive files | +| \`project-rules.go\` | Project-specific rules injection | +| \`compact-notify.go\` | Notification on conversation compaction | + +## Interactive features + +| Extension | Description | +|-----------|-------------| +| \`prompt-demo.go\` | Interactive prompts (select/confirm/input) | +| \`bookmark.go\` | Bookmark conversations | +| \`inline-bash.go\` | Inline bash execution | +| \`interactive-shell.go\` | Interactive shell integration | +| \`notify.go\` | Desktop notifications | + +## Agent and context + +| Extension | Description | +|-----------|-------------| +| \`tool-logger.go\` | Log all tool calls | +| \`context-inject.go\` | Inject context into conversations | +| \`summarize.go\` | Conversation summarization | +| \`lsp-diagnostics.go\` | LSP diagnostic integration | + +## Multi-agent + +| Extension | Description | +|-----------|-------------| +| \`kit-kit.go\` | Kit-in-Kit sub-agent spawning | +| \`subagent-widget.go\` | Multi-agent orchestration with status widget | +| \`subagent-test.go\` | Subagent testing utilities | + +## Development + +| Extension | Description | +|-----------|-------------| +| \`dev-reload.go\` | Development live-reload | + +## Subdirectory extensions + +| Directory | Description | +|-----------|-------------| +| \`kit-kit-agents/\` | Multi-agent orchestration example | +| \`kit-telegram/\` | Telegram bot integration | +| \`status-tools/\` | Status bar tool examples | +`};export{t as default}; diff --git a/assets/flags-CkTF-Pw-.js b/assets/flags-CkTF-Pw-.js new file mode 100644 index 00000000..b1868a4f --- /dev/null +++ b/assets/flags-CkTF-Pw-.js @@ -0,0 +1,237 @@ +const t={frontmatter:{title:"Global Flags",description:"Complete reference for all Kit CLI flags.",hidden:!1,toc:!0,draft:!1},html:`

    Global Flags

    +

    All flags can be passed to the root kit command.

    +

    Model and provider

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlagShortDefaultDescription
    --model-manthropic/claude-sonnet-4-5-20250929Model to use (provider/model format)
    --provider-api-keyAPI key for the provider
    --provider-urlBase URL for provider API
    --tls-skip-verifyfalseSkip TLS certificate verification
    +

    Session management

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlagShortDefaultDescription
    --session-sOpen specific JSONL session file
    --continue-cfalseResume most recent session for current directory
    --resume-rfalseInteractive session picker
    --no-sessionfalseEphemeral mode, no persistence
    +

    Behavior

    +

    These flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlagShortDefaultDescription
    --quietfalseSuppress all output (non-interactive only)
    --jsonfalseOutput response as JSON (non-interactive only)
    --no-exitfalseEnter interactive mode after prompt completes
    --max-steps0Maximum agent steps (0 for unlimited)
    --streamtrueEnable streaming output
    --compactfalseEnable compact output mode
    --auto-compactfalseAuto-compact conversation near context limit
    +

    Extensions

    + + + + + + + + + + + + + + + + + + + + + + + +
    FlagShortDefaultDescription
    --extension-eLoad additional extension file(s) (repeatable)
    --no-extensionsfalseDisable all extensions
    +

    Generation parameters

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlagShortDefaultDescription
    --max-tokens4096Maximum tokens in response
    --temperature0.7Randomness 0.0–1.0
    --top-p0.95Nucleus sampling 0.0–1.0
    --top-k40Limit top K tokens
    --stop-sequencesCustom stop sequences (comma-separated)
    --thinking-leveloffExtended thinking level: off, minimal, low, medium, high
    +

    System

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlagShortDefaultDescription
    --config~/.kit.ymlConfig file path
    --system-promptSystem prompt text or file path
    --debugfalseEnable debug logging
    `,headings:[{depth:2,text:"Model and provider",id:"model-and-provider"},{depth:2,text:"Session management",id:"session-management"},{depth:2,text:"Behavior",id:"behavior"},{depth:2,text:"Extensions",id:"extensions"},{depth:2,text:"Generation parameters",id:"generation-parameters"},{depth:2,text:"System",id:"system"}],raw:"\n# Global Flags\n\nAll flags can be passed to the root `kit` command.\n\n## Model and provider\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--model` | `-m` | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) |\n| `--provider-api-key` | — | — | API key for the provider |\n| `--provider-url` | — | — | Base URL for provider API |\n| `--tls-skip-verify` | — | `false` | Skip TLS certificate verification |\n\n## Session management\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--session` | `-s` | — | Open specific JSONL session file |\n| `--continue` | `-c` | `false` | Resume most recent session for current directory |\n| `--resume` | `-r` | `false` | Interactive session picker |\n| `--no-session` | — | `false` | Ephemeral mode, no persistence |\n\n## Behavior\n\nThese flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode.\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--quiet` | — | `false` | Suppress all output (non-interactive only) |\n| `--json` | — | `false` | Output response as JSON (non-interactive only) |\n| `--no-exit` | — | `false` | Enter interactive mode after prompt completes |\n| `--max-steps` | — | `0` | Maximum agent steps (0 for unlimited) |\n| `--stream` | — | `true` | Enable streaming output |\n| `--compact` | — | `false` | Enable compact output mode |\n| `--auto-compact` | — | `false` | Auto-compact conversation near context limit |\n\n## Extensions\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--extension` | `-e` | — | Load additional extension file(s) (repeatable) |\n| `--no-extensions` | — | `false` | Disable all extensions |\n\n## Generation parameters\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--max-tokens` | — | `4096` | Maximum tokens in response |\n| `--temperature` | — | `0.7` | Randomness 0.0–1.0 |\n| `--top-p` | — | `0.95` | Nucleus sampling 0.0–1.0 |\n| `--top-k` | — | `40` | Limit top K tokens |\n| `--stop-sequences` | — | — | Custom stop sequences (comma-separated) |\n| `--thinking-level` | — | `off` | Extended thinking level: off, minimal, low, medium, high |\n\n## System\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--config` | — | `~/.kit.yml` | Config file path |\n| `--system-prompt` | — | — | System prompt text or file path |\n| `--debug` | — | `false` | Enable debug logging |\n"};export{t as default}; diff --git a/assets/index-BdEV_URu.js b/assets/index-BdEV_URu.js new file mode 100644 index 00000000..91bddd00 --- /dev/null +++ b/assets/index-BdEV_URu.js @@ -0,0 +1,1730 @@ +(function(){const h=document.createElement("link").relList;if(h&&h.supports&&h.supports("modulepreload"))return;for(const v of document.querySelectorAll('link[rel="modulepreload"]'))c(v);new MutationObserver(v=>{for(const E of v)if(E.type==="childList")for(const M of E.addedNodes)M.tagName==="LINK"&&M.rel==="modulepreload"&&c(M)}).observe(document,{childList:!0,subtree:!0});function d(v){const E={};return v.integrity&&(E.integrity=v.integrity),v.referrerPolicy&&(E.referrerPolicy=v.referrerPolicy),v.crossOrigin==="use-credentials"?E.credentials="include":v.crossOrigin==="anonymous"?E.credentials="omit":E.credentials="same-origin",E}function c(v){if(v.ep)return;v.ep=!0;const E=d(v);fetch(v.href,E)}})();function zh(u){return u&&u.__esModule&&Object.prototype.hasOwnProperty.call(u,"default")?u.default:u}var Lu={exports:{}},ii={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Yd;function Ch(){if(Yd)return ii;Yd=1;var u=Symbol.for("react.transitional.element"),h=Symbol.for("react.fragment");function d(c,v,E){var M=null;if(E!==void 0&&(M=""+E),v.key!==void 0&&(M=""+v.key),"key"in v){E={};for(var D in v)D!=="key"&&(E[D]=v[D])}else E=v;return v=E.ref,{$$typeof:u,type:c,key:M,ref:v!==void 0?v:null,props:E}}return ii.Fragment=h,ii.jsx=d,ii.jsxs=d,ii}var Kd;function jh(){return Kd||(Kd=1,Lu.exports=Ch()),Lu.exports}var s=jh(),Gu={exports:{}},ot={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Xd;function Mh(){if(Xd)return ot;Xd=1;var u=Symbol.for("react.transitional.element"),h=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),c=Symbol.for("react.strict_mode"),v=Symbol.for("react.profiler"),E=Symbol.for("react.consumer"),M=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),z=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),G=Symbol.for("react.lazy"),R=Symbol.for("react.activity"),K=Symbol.iterator;function nt(m){return m===null||typeof m!="object"?null:(m=K&&m[K]||m["@@iterator"],typeof m=="function"?m:null)}var bt={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Ot=Object.assign,jt={};function W(m,k,N){this.props=m,this.context=k,this.refs=jt,this.updater=N||bt}W.prototype.isReactComponent={},W.prototype.setState=function(m,k){if(typeof m!="object"&&typeof m!="function"&&m!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,m,k,"setState")},W.prototype.forceUpdate=function(m){this.updater.enqueueForceUpdate(this,m,"forceUpdate")};function I(){}I.prototype=W.prototype;function ct(m,k,N){this.props=m,this.context=k,this.refs=jt,this.updater=N||bt}var Q=ct.prototype=new I;Q.constructor=ct,Ot(Q,W.prototype),Q.isPureReactComponent=!0;var Y=Array.isArray;function H(){}var U={H:null,A:null,T:null,S:null},at=Object.prototype.hasOwnProperty;function lt(m,k,N){var L=N.ref;return{$$typeof:u,type:m,key:k,ref:L!==void 0?L:null,props:N}}function P(m,k){return lt(m.type,k,m.props)}function mt(m){return typeof m=="object"&&m!==null&&m.$$typeof===u}function tt(m){var k={"=":"=0",":":"=2"};return"$"+m.replace(/[=:]/g,function(N){return k[N]})}var Mt=/\/+/g;function $t(m,k){return typeof m=="object"&&m!==null&&m.key!=null?tt(""+m.key):k.toString(36)}function ft(m){switch(m.status){case"fulfilled":return m.value;case"rejected":throw m.reason;default:switch(typeof m.status=="string"?m.then(H,H):(m.status="pending",m.then(function(k){m.status==="pending"&&(m.status="fulfilled",m.value=k)},function(k){m.status==="pending"&&(m.status="rejected",m.reason=k)})),m.status){case"fulfilled":return m.value;case"rejected":throw m.reason}}throw m}function C(m,k,N,L,it){var rt=typeof m;(rt==="undefined"||rt==="boolean")&&(m=null);var Et=!1;if(m===null)Et=!0;else switch(rt){case"bigint":case"string":case"number":Et=!0;break;case"object":switch(m.$$typeof){case u:case h:Et=!0;break;case G:return Et=m._init,C(Et(m._payload),k,N,L,it)}}if(Et)return it=it(m),Et=L===""?"."+$t(m,0):L,Y(it)?(N="",Et!=null&&(N=Et.replace(Mt,"$&/")+"/"),C(it,k,N,"",function(Ze){return Ze})):it!=null&&(mt(it)&&(it=P(it,N+(it.key==null||m&&m.key===it.key?"":(""+it.key).replace(Mt,"$&/")+"/")+Et)),k.push(it)),1;Et=0;var It=L===""?".":L+":";if(Y(m))for(var Ut=0;Ut>>1,Tt=C[J];if(0>>1;Jv(N,Z))Lv(it,N)?(C[J]=it,C[L]=Z,J=L):(C[J]=N,C[k]=Z,J=k);else if(Lv(it,Z))C[J]=it,C[L]=Z,J=L;else break t}}return w}function v(C,w){var Z=C.sortIndex-w.sortIndex;return Z!==0?Z:C.id-w.id}if(u.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var E=performance;u.unstable_now=function(){return E.now()}}else{var M=Date,D=M.now();u.unstable_now=function(){return M.now()-D}}var z=[],y=[],G=1,R=null,K=3,nt=!1,bt=!1,Ot=!1,jt=!1,W=typeof setTimeout=="function"?setTimeout:null,I=typeof clearTimeout=="function"?clearTimeout:null,ct=typeof setImmediate<"u"?setImmediate:null;function Q(C){for(var w=d(y);w!==null;){if(w.callback===null)c(y);else if(w.startTime<=C)c(y),w.sortIndex=w.expirationTime,h(z,w);else break;w=d(y)}}function Y(C){if(Ot=!1,Q(C),!bt)if(d(z)!==null)bt=!0,H||(H=!0,tt());else{var w=d(y);w!==null&&ft(Y,w.startTime-C)}}var H=!1,U=-1,at=5,lt=-1;function P(){return jt?!0:!(u.unstable_now()-ltC&&P());){var J=R.callback;if(typeof J=="function"){R.callback=null,K=R.priorityLevel;var Tt=J(R.expirationTime<=C);if(C=u.unstable_now(),typeof Tt=="function"){R.callback=Tt,Q(C),w=!0;break e}R===d(z)&&c(z),Q(C)}else c(z);R=d(z)}if(R!==null)w=!0;else{var m=d(y);m!==null&&ft(Y,m.startTime-C),w=!1}}break t}finally{R=null,K=Z,nt=!1}w=void 0}}finally{w?tt():H=!1}}}var tt;if(typeof ct=="function")tt=function(){ct(mt)};else if(typeof MessageChannel<"u"){var Mt=new MessageChannel,$t=Mt.port2;Mt.port1.onmessage=mt,tt=function(){$t.postMessage(null)}}else tt=function(){W(mt,0)};function ft(C,w){U=W(function(){C(u.unstable_now())},w)}u.unstable_IdlePriority=5,u.unstable_ImmediatePriority=1,u.unstable_LowPriority=4,u.unstable_NormalPriority=3,u.unstable_Profiling=null,u.unstable_UserBlockingPriority=2,u.unstable_cancelCallback=function(C){C.callback=null},u.unstable_forceFrameRate=function(C){0>C||125J?(C.sortIndex=Z,h(y,C),d(z)===null&&C===d(y)&&(Ot?(I(U),U=-1):Ot=!0,ft(Y,Z-J))):(C.sortIndex=Tt,h(z,C),bt||nt||(bt=!0,H||(H=!0,tt()))),C},u.unstable_shouldYield=P,u.unstable_wrapCallback=function(C){var w=K;return function(){var Z=K;K=w;try{return C.apply(this,arguments)}finally{K=Z}}}})(Xu)),Xu}var Zd;function kh(){return Zd||(Zd=1,Ku.exports=_h()),Ku.exports}var Qu={exports:{}},re={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Jd;function Oh(){if(Jd)return re;Jd=1;var u=$u();function h(z){var y="https://react.dev/errors/"+z;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(u)}catch(h){console.error(h)}}return u(),Qu.exports=Oh(),Qu.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Fd;function Rh(){if(Fd)return oi;Fd=1;var u=kh(),h=$u(),d=Dh();function c(t){var e="https://react.dev/errors/"+t;if(1Tt||(t.current=J[Tt],J[Tt]=null,Tt--)}function N(t,e){Tt++,J[Tt]=t.current,t.current=e}var L=m(null),it=m(null),rt=m(null),Et=m(null);function It(t,e){switch(N(rt,e),N(it,t),N(L,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?fd(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=fd(e),t=dd(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}k(L),N(L,t)}function Ut(){k(L),k(it),k(rt)}function Ze(t){t.memoizedState!==null&&N(Et,t);var e=L.current,n=dd(e,t.type);e!==n&&(N(it,t),N(L,n))}function pa(t){it.current===t&&(k(L),k(it)),Et.current===t&&(k(Et),ei._currentValue=Z)}var ha,rl;function Je(t){if(ha===void 0)try{throw Error()}catch(n){var e=n.stack.trim().match(/\n( *(at )?)/);ha=e&&e[1]||"",rl=-1)":-1l||f[a]!==S[l]){var j=` +`+f[a].replace(" at new "," at ");return t.displayName&&j.includes("")&&(j=j.replace("",t.displayName)),j}while(1<=a&&0<=l);break}}}finally{cl=!1,Error.prepareStackTrace=n}return(n=t?t.displayName||t.name:"")?Je(n):""}function Oo(t,e){switch(t.tag){case 26:case 27:case 5:return Je(t.type);case 16:return Je("Lazy");case 13:return t.child!==e&&e!==null?Je("Suspense Fallback"):Je("Suspense");case 19:return Je("SuspenseList");case 0:case 15:return ga(t.type,!1);case 11:return ga(t.type.render,!1);case 1:return ga(t.type,!0);case 31:return Je("Activity");default:return""}}function We(t){try{var e="",n=null;do e+=Oo(t,n),n=t,t=t.return;while(t);return e}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var Fn=Object.prototype.hasOwnProperty,fl=u.unstable_scheduleCallback,va=u.unstable_cancelCallback,Do=u.unstable_shouldYield,si=u.unstable_requestPaint,se=u.unstable_now,ui=u.unstable_getCurrentPriorityLevel,te=u.unstable_ImmediatePriority,ya=u.unstable_UserBlockingPriority,bn=u.unstable_NormalPriority,Sn=u.unstable_LowPriority,ri=u.unstable_IdlePriority,Pu=u.log,xa=u.unstable_setDisableYieldValue,ye=null,ue=null;function je(t){if(typeof Pu=="function"&&xa(t),ue&&typeof ue.setStrictMode=="function")try{ue.setStrictMode(ye,t)}catch{}}var ee=Math.clz32?Math.clz32:Sa,ci=Math.log,ba=Math.LN2;function Sa(t){return t>>>=0,t===0?32:31-(ci(t)/ba|0)|0}var Fe=256,$e=262144,Ie=4194304;function Pe(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&261888;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function Ta(t,e,n){var a=t.pendingLanes;if(a===0)return 0;var l=0,i=t.suspendedLanes,o=t.pingedLanes;t=t.warmLanes;var r=a&134217727;return r!==0?(a=r&~i,a!==0?l=Pe(a):(o&=r,o!==0?l=Pe(o):n||(n=r&~t,n!==0&&(l=Pe(n))))):(r=a&~i,r!==0?l=Pe(r):o!==0?l=Pe(o):n||(n=a&~t,n!==0&&(l=Pe(n)))),l===0?0:e!==0&&e!==l&&(e&i)===0&&(i=l&-l,n=e&-e,i>=n||i===32&&(n&4194048)!==0)?e:l}function Tn(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function Ne(t,e){switch(t){case 1:case 2:case 4:case 8:case 64:return e+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ea(){var t=Ie;return Ie<<=1,(Ie&62914560)===0&&(Ie=4194304),t}function Aa(t){for(var e=[],n=0;31>n;n++)e.push(t);return e}function En(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function fi(t,e,n,a,l,i){var o=t.pendingLanes;t.pendingLanes=n,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=n,t.entangledLanes&=n,t.errorRecoveryDisabledLanes&=n,t.shellSuspendCounter=0;var r=t.entanglements,f=t.expirationTimes,S=t.hiddenUpdates;for(n=o&~n;0"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var xm=/[\n"\\]/g;function _e(t){return t.replace(xm,function(e){return"\\"+e.charCodeAt(0).toString(16)+" "})}function Bo(t,e,n,a,l,i,o,r){t.name="",o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?t.type=o:t.removeAttribute("type"),e!=null?o==="number"?(e===0&&t.value===""||t.value!=e)&&(t.value=""+Me(e)):t.value!==""+Me(e)&&(t.value=""+Me(e)):o!=="submit"&&o!=="reset"||t.removeAttribute("value"),e!=null?wo(t,o,Me(e)):n!=null?wo(t,o,Me(n)):a!=null&&t.removeAttribute("value"),l==null&&i!=null&&(t.defaultChecked=!!i),l!=null&&(t.checked=l&&typeof l!="function"&&typeof l!="symbol"),r!=null&&typeof r!="function"&&typeof r!="symbol"&&typeof r!="boolean"?t.name=""+Me(r):t.removeAttribute("name")}function lr(t,e,n,a,l,i,o,r){if(i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(t.type=i),e!=null||n!=null){if(!(i!=="submit"&&i!=="reset"||e!=null)){Ro(t);return}n=n!=null?""+Me(n):"",e=e!=null?""+Me(e):n,r||e===t.value||(t.value=e),t.defaultValue=e}a=a??l,a=typeof a!="function"&&typeof a!="symbol"&&!!a,t.checked=r?t.checked:!!a,t.defaultChecked=!!a,o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"&&(t.name=o),Ro(t)}function wo(t,e,n){e==="number"&&vi(t.ownerDocument)===t||t.defaultValue===""+n||(t.defaultValue=""+n)}function _a(t,e,n,a){if(t=t.options,e){e={};for(var l=0;l"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Lo=!1;if(an)try{var xl={};Object.defineProperty(xl,"passive",{get:function(){Lo=!0}}),window.addEventListener("test",xl,xl),window.removeEventListener("test",xl,xl)}catch{Lo=!1}var zn=null,Go=null,xi=null;function fr(){if(xi)return xi;var t,e=Go,n=e.length,a,l="value"in zn?zn.value:zn.textContent,i=l.length;for(t=0;t=Tl),vr=" ",yr=!1;function xr(t,e){switch(t){case"keyup":return Zm.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function br(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Ra=!1;function Wm(t,e){switch(t){case"compositionend":return br(e);case"keypress":return e.which!==32?null:(yr=!0,vr);case"textInput":return t=e.data,t===vr&&yr?null:t;default:return null}}function Fm(t,e){if(Ra)return t==="compositionend"||!Vo&&xr(t,e)?(t=fr(),xi=Go=zn=null,Ra=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1=e)return{node:n,offset:e-t};t=a}t:{for(;n;){if(n.nextSibling){n=n.nextSibling;break t}n=n.parentNode}n=void 0}n=Mr(n)}}function kr(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?kr(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function Or(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=vi(t.document);e instanceof t.HTMLIFrameElement;){try{var n=typeof e.contentWindow.location.href=="string"}catch{n=!1}if(n)t=e.contentWindow;else break;e=vi(t.document)}return e}function Wo(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var lp=an&&"documentMode"in document&&11>=document.documentMode,Ba=null,Fo=null,Cl=null,$o=!1;function Dr(t,e,n){var a=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;$o||Ba==null||Ba!==vi(a)||(a=Ba,"selectionStart"in a&&Wo(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Cl&&zl(Cl,a)||(Cl=a,a=mo(Fo,"onSelect"),0>=o,l-=o,Ke=1<<32-ee(e)+l|n<ut?(vt=V,V=null):vt=V.sibling;var zt=T(g,V,b[ut],_);if(zt===null){V===null&&(V=vt);break}t&&V&&zt.alternate===null&&e(g,V),p=i(zt,p,ut),At===null?F=zt:At.sibling=zt,At=zt,V=vt}if(ut===b.length)return n(g,V),xt&&on(g,ut),F;if(V===null){for(;utut?(vt=V,V=null):vt=V.sibling;var Zn=T(g,V,zt.value,_);if(Zn===null){V===null&&(V=vt);break}t&&V&&Zn.alternate===null&&e(g,V),p=i(Zn,p,ut),At===null?F=Zn:At.sibling=Zn,At=Zn,V=vt}if(zt.done)return n(g,V),xt&&on(g,ut),F;if(V===null){for(;!zt.done;ut++,zt=b.next())zt=O(g,zt.value,_),zt!==null&&(p=i(zt,p,ut),At===null?F=zt:At.sibling=zt,At=zt);return xt&&on(g,ut),F}for(V=a(V);!zt.done;ut++,zt=b.next())zt=A(V,g,ut,zt.value,_),zt!==null&&(t&&zt.alternate!==null&&V.delete(zt.key===null?ut:zt.key),p=i(zt,p,ut),At===null?F=zt:At.sibling=zt,At=zt);return t&&V.forEach(function(Ah){return e(g,Ah)}),xt&&on(g,ut),F}function Bt(g,p,b,_){if(typeof b=="object"&&b!==null&&b.type===Ot&&b.key===null&&(b=b.props.children),typeof b=="object"&&b!==null){switch(b.$$typeof){case nt:t:{for(var F=b.key;p!==null;){if(p.key===F){if(F=b.type,F===Ot){if(p.tag===7){n(g,p.sibling),_=l(p,b.props.children),_.return=g,g=_;break t}}else if(p.elementType===F||typeof F=="object"&&F!==null&&F.$$typeof===at&&sa(F)===p.type){n(g,p.sibling),_=l(p,b.props),Dl(_,b),_.return=g,g=_;break t}n(g,p);break}else e(g,p);p=p.sibling}b.type===Ot?(_=na(b.props.children,g.mode,_,b.key),_.return=g,g=_):(_=_i(b.type,b.key,b.props,null,g.mode,_),Dl(_,b),_.return=g,g=_)}return o(g);case bt:t:{for(F=b.key;p!==null;){if(p.key===F)if(p.tag===4&&p.stateNode.containerInfo===b.containerInfo&&p.stateNode.implementation===b.implementation){n(g,p.sibling),_=l(p,b.children||[]),_.return=g,g=_;break t}else{n(g,p);break}else e(g,p);p=p.sibling}_=ls(b,g.mode,_),_.return=g,g=_}return o(g);case at:return b=sa(b),Bt(g,p,b,_)}if(ft(b))return X(g,p,b,_);if(tt(b)){if(F=tt(b),typeof F!="function")throw Error(c(150));return b=F.call(b),$(g,p,b,_)}if(typeof b.then=="function")return Bt(g,p,Ui(b),_);if(b.$$typeof===ct)return Bt(g,p,Di(g,b),_);Hi(g,b)}return typeof b=="string"&&b!==""||typeof b=="number"||typeof b=="bigint"?(b=""+b,p!==null&&p.tag===6?(n(g,p.sibling),_=l(p,b),_.return=g,g=_):(n(g,p),_=as(b,g.mode,_),_.return=g,g=_),o(g)):n(g,p)}return function(g,p,b,_){try{Ol=0;var F=Bt(g,p,b,_);return Qa=null,F}catch(V){if(V===Xa||V===Bi)throw V;var At=be(29,V,null,g.mode);return At.lanes=_,At.return=g,At}finally{}}}var ra=ec(!0),nc=ec(!1),kn=!1;function gs(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function vs(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function On(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Dn(t,e,n){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(Ct&2)!==0){var l=a.pending;return l===null?e.next=e:(e.next=l.next,l.next=e),a.pending=e,e=Mi(t),qr(t,null,n),e}return ji(t,a,e,n),Mi(t)}function Rl(t,e,n){if(e=e.updateQueue,e!==null&&(e=e.shared,(n&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,n|=a,e.lanes=n,ml(t,n)}}function ys(t,e){var n=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,n===a)){var l=null,i=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};i===null?l=i=o:i=i.next=o,n=n.next}while(n!==null);i===null?l=i=e:i=i.next=e}else l=i=e;n={baseState:a.baseState,firstBaseUpdate:l,lastBaseUpdate:i,shared:a.shared,callbacks:a.callbacks},t.updateQueue=n;return}t=n.lastBaseUpdate,t===null?n.firstBaseUpdate=e:t.next=e,n.lastBaseUpdate=e}var xs=!1;function Bl(){if(xs){var t=Ka;if(t!==null)throw t}}function wl(t,e,n,a){xs=!1;var l=t.updateQueue;kn=!1;var i=l.firstBaseUpdate,o=l.lastBaseUpdate,r=l.shared.pending;if(r!==null){l.shared.pending=null;var f=r,S=f.next;f.next=null,o===null?i=S:o.next=S,o=f;var j=t.alternate;j!==null&&(j=j.updateQueue,r=j.lastBaseUpdate,r!==o&&(r===null?j.firstBaseUpdate=S:r.next=S,j.lastBaseUpdate=f))}if(i!==null){var O=l.baseState;o=0,j=S=f=null,r=i;do{var T=r.lane&-536870913,A=T!==r.lane;if(A?(gt&T)===T:(a&T)===T){T!==0&&T===Ya&&(xs=!0),j!==null&&(j=j.next={lane:0,tag:r.tag,payload:r.payload,callback:null,next:null});t:{var X=t,$=r;T=e;var Bt=n;switch($.tag){case 1:if(X=$.payload,typeof X=="function"){O=X.call(Bt,O,T);break t}O=X;break t;case 3:X.flags=X.flags&-65537|128;case 0:if(X=$.payload,T=typeof X=="function"?X.call(Bt,O,T):X,T==null)break t;O=R({},O,T);break t;case 2:kn=!0}}T=r.callback,T!==null&&(t.flags|=64,A&&(t.flags|=8192),A=l.callbacks,A===null?l.callbacks=[T]:A.push(T))}else A={lane:T,tag:r.tag,payload:r.payload,callback:r.callback,next:null},j===null?(S=j=A,f=O):j=j.next=A,o|=T;if(r=r.next,r===null){if(r=l.shared.pending,r===null)break;A=r,r=A.next,A.next=null,l.lastBaseUpdate=A,l.shared.pending=null}}while(!0);j===null&&(f=O),l.baseState=f,l.firstBaseUpdate=S,l.lastBaseUpdate=j,i===null&&(l.shared.lanes=0),Hn|=o,t.lanes=o,t.memoizedState=O}}function ac(t,e){if(typeof t!="function")throw Error(c(191,t));t.call(e)}function lc(t,e){var n=t.callbacks;if(n!==null)for(t.callbacks=null,t=0;ti?i:8;var o=C.T,r={};C.T=r,Ns(t,!1,e,n);try{var f=l(),S=C.S;if(S!==null&&S(r,f),f!==null&&typeof f=="object"&&typeof f.then=="function"){var j=mp(f,a);Nl(t,e,j,ze(t))}else Nl(t,e,a,ze(t))}catch(O){Nl(t,e,{then:function(){},status:"rejected",reason:O},ze())}finally{w.p=i,o!==null&&r.types!==null&&(o.types=r.types),C.T=o}}function xp(){}function Us(t,e,n,a){if(t.tag!==5)throw Error(c(476));var l=Uc(t).queue;wc(t,l,e,Z,n===null?xp:function(){return Hc(t),n(a)})}function Uc(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:Z,baseState:Z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cn,lastRenderedState:Z},next:null};var n={};return e.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cn,lastRenderedState:n},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function Hc(t){var e=Uc(t);e.next===null&&(e=t.alternate.memoizedState),Nl(t,e.next.queue,{},ze())}function Hs(){return le(ei)}function Nc(){return Kt().memoizedState}function qc(){return Kt().memoizedState}function bp(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var n=ze();t=On(n);var a=Dn(e,t,n);a!==null&&(ve(a,e,n),Rl(a,e,n)),e={cache:ds()},t.payload=e;return}e=e.return}}function Sp(t,e,n){var a=ze();n={lane:a,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Zi(t)?Gc(e,n):(n=es(t,e,n,a),n!==null&&(ve(n,t,a),Yc(n,e,a)))}function Lc(t,e,n){var a=ze();Nl(t,e,n,a)}function Nl(t,e,n,a){var l={lane:a,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Zi(t))Gc(e,l);else{var i=t.alternate;if(t.lanes===0&&(i===null||i.lanes===0)&&(i=e.lastRenderedReducer,i!==null))try{var o=e.lastRenderedState,r=i(o,n);if(l.hasEagerState=!0,l.eagerState=r,xe(r,o))return ji(t,e,l,0),wt===null&&Ci(),!1}catch{}finally{}if(n=es(t,e,l,a),n!==null)return ve(n,t,a),Yc(n,e,a),!0}return!1}function Ns(t,e,n,a){if(a={lane:2,revertLane:gu(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Zi(t)){if(e)throw Error(c(479))}else e=es(t,n,a,2),e!==null&&ve(e,t,2)}function Zi(t){var e=t.alternate;return t===st||e!==null&&e===st}function Gc(t,e){Za=Li=!0;var n=t.pending;n===null?e.next=e:(e.next=n.next,n.next=e),t.pending=e}function Yc(t,e,n){if((n&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,n|=a,e.lanes=n,ml(t,n)}}var ql={readContext:le,use:Ki,useCallback:Lt,useContext:Lt,useEffect:Lt,useImperativeHandle:Lt,useLayoutEffect:Lt,useInsertionEffect:Lt,useMemo:Lt,useReducer:Lt,useRef:Lt,useState:Lt,useDebugValue:Lt,useDeferredValue:Lt,useTransition:Lt,useSyncExternalStore:Lt,useId:Lt,useHostTransitionStatus:Lt,useFormState:Lt,useActionState:Lt,useOptimistic:Lt,useMemoCache:Lt,useCacheRefresh:Lt};ql.useEffectEvent=Lt;var Kc={readContext:le,use:Ki,useCallback:function(t,e){return fe().memoizedState=[t,e===void 0?null:e],t},useContext:le,useEffect:Cc,useImperativeHandle:function(t,e,n){n=n!=null?n.concat([t]):null,Qi(4194308,4,kc.bind(null,e,t),n)},useLayoutEffect:function(t,e){return Qi(4194308,4,t,e)},useInsertionEffect:function(t,e){Qi(4,2,t,e)},useMemo:function(t,e){var n=fe();e=e===void 0?null:e;var a=t();if(ca){je(!0);try{t()}finally{je(!1)}}return n.memoizedState=[a,e],a},useReducer:function(t,e,n){var a=fe();if(n!==void 0){var l=n(e);if(ca){je(!0);try{n(e)}finally{je(!1)}}}else l=e;return a.memoizedState=a.baseState=l,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:l},a.queue=t,t=t.dispatch=Sp.bind(null,st,t),[a.memoizedState,t]},useRef:function(t){var e=fe();return t={current:t},e.memoizedState=t},useState:function(t){t=Os(t);var e=t.queue,n=Lc.bind(null,st,e);return e.dispatch=n,[t.memoizedState,n]},useDebugValue:Bs,useDeferredValue:function(t,e){var n=fe();return ws(n,t,e)},useTransition:function(){var t=Os(!1);return t=wc.bind(null,st,t.queue,!0,!1),fe().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,n){var a=st,l=fe();if(xt){if(n===void 0)throw Error(c(407));n=n()}else{if(n=e(),wt===null)throw Error(c(349));(gt&127)!==0||cc(a,e,n)}l.memoizedState=n;var i={value:n,getSnapshot:e};return l.queue=i,Cc(dc.bind(null,a,i,t),[t]),a.flags|=2048,Wa(9,{destroy:void 0},fc.bind(null,a,i,n,e),null),n},useId:function(){var t=fe(),e=wt.identifierPrefix;if(xt){var n=Xe,a=Ke;n=(a&~(1<<32-ee(a)-1)).toString(32)+n,e="_"+e+"R_"+n,n=Gi++,0<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof a.is=="string"?o.createElement("select",{is:a.is}):o.createElement("select"),a.multiple?i.multiple=!0:a.size&&(i.size=a.size);break;default:i=typeof a.is=="string"?o.createElement(l,{is:a.is}):o.createElement(l)}}i[Qt]=e,i[ne]=a;t:for(o=e.child;o!==null;){if(o.tag===5||o.tag===6)i.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===e)break t;for(;o.sibling===null;){if(o.return===null||o.return===e)break t;o=o.return}o.sibling.return=o.return,o=o.sibling}e.stateNode=i;t:switch(oe(i,l,a),l){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&dn(e)}}return Nt(e),Is(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,n),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&dn(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(c(166));if(t=rt.current,La(e)){if(t=e.stateNode,n=e.memoizedProps,a=null,l=ae,l!==null)switch(l.tag){case 27:case 5:a=l.memoizedProps}t[Qt]=e,t=!!(t.nodeValue===n||a!==null&&a.suppressHydrationWarning===!0||rd(t.nodeValue,n)),t||Mn(e,!0)}else t=po(t).createTextNode(a),t[Qt]=e,e.stateNode=t}return Nt(e),null;case 31:if(n=e.memoizedState,t===null||t.memoizedState!==null){if(a=La(e),n!==null){if(t===null){if(!a)throw Error(c(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(c(557));t[Qt]=e}else aa(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Nt(e),t=!1}else n=us(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=n),t=!0;if(!t)return e.flags&256?(Te(e),e):(Te(e),null);if((e.flags&128)!==0)throw Error(c(558))}return Nt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(l=La(e),a!==null&&a.dehydrated!==null){if(t===null){if(!l)throw Error(c(318));if(l=e.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(c(317));l[Qt]=e}else aa(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Nt(e),l=!1}else l=us(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),l=!0;if(!l)return e.flags&256?(Te(e),e):(Te(e),null)}return Te(e),(e.flags&128)!==0?(e.lanes=n,e):(n=a!==null,t=t!==null&&t.memoizedState!==null,n&&(a=e.child,l=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(l=a.alternate.memoizedState.cachePool.pool),i=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(i=a.memoizedState.cachePool.pool),i!==l&&(a.flags|=2048)),n!==t&&n&&(e.child.flags|=8192),Ii(e,e.updateQueue),Nt(e),null);case 4:return Ut(),t===null&&bu(e.stateNode.containerInfo),Nt(e),null;case 10:return un(e.type),Nt(e),null;case 19:if(k(Yt),a=e.memoizedState,a===null)return Nt(e),null;if(l=(e.flags&128)!==0,i=a.rendering,i===null)if(l)Gl(a,!1);else{if(Gt!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(i=qi(t),i!==null){for(e.flags|=128,Gl(a,!1),t=i.updateQueue,e.updateQueue=t,Ii(e,t),e.subtreeFlags=0,t=n,n=e.child;n!==null;)Lr(n,t),n=n.sibling;return N(Yt,Yt.current&1|2),xt&&on(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&se()>ao&&(e.flags|=128,l=!0,Gl(a,!1),e.lanes=4194304)}else{if(!l)if(t=qi(i),t!==null){if(e.flags|=128,l=!0,t=t.updateQueue,e.updateQueue=t,Ii(e,t),Gl(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!xt)return Nt(e),null}else 2*se()-a.renderingStartTime>ao&&n!==536870912&&(e.flags|=128,l=!0,Gl(a,!1),e.lanes=4194304);a.isBackwards?(i.sibling=e.child,e.child=i):(t=a.last,t!==null?t.sibling=i:e.child=i,a.last=i)}return a.tail!==null?(t=a.tail,a.rendering=t,a.tail=t.sibling,a.renderingStartTime=se(),t.sibling=null,n=Yt.current,N(Yt,l?n&1|2:n&1),xt&&on(e,a.treeForkCount),t):(Nt(e),null);case 22:case 23:return Te(e),Ss(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(n&536870912)!==0&&(e.flags&128)===0&&(Nt(e),e.subtreeFlags&6&&(e.flags|=8192)):Nt(e),n=e.updateQueue,n!==null&&Ii(e,n.retryQueue),n=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(n=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==n&&(e.flags|=2048),t!==null&&k(oa),null;case 24:return n=null,t!==null&&(n=t.memoizedState.cache),e.memoizedState.cache!==n&&(e.flags|=2048),un(Vt),Nt(e),null;case 25:return null;case 30:return null}throw Error(c(156,e.tag))}function Cp(t,e){switch(os(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return un(Vt),Ut(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return pa(e),null;case 31:if(e.memoizedState!==null){if(Te(e),e.alternate===null)throw Error(c(340));aa()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(Te(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(c(340));aa()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return k(Yt),null;case 4:return Ut(),null;case 10:return un(e.type),null;case 22:case 23:return Te(e),Ss(),t!==null&&k(oa),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return un(Vt),null;case 25:return null;default:return null}}function pf(t,e){switch(os(e),e.tag){case 3:un(Vt),Ut();break;case 26:case 27:case 5:pa(e);break;case 4:Ut();break;case 31:e.memoizedState!==null&&Te(e);break;case 13:Te(e);break;case 19:k(Yt);break;case 10:un(e.type);break;case 22:case 23:Te(e),Ss(),t!==null&&k(oa);break;case 24:un(Vt)}}function Yl(t,e){try{var n=e.updateQueue,a=n!==null?n.lastEffect:null;if(a!==null){var l=a.next;n=l;do{if((n.tag&t)===t){a=void 0;var i=n.create,o=n.inst;a=i(),o.destroy=a}n=n.next}while(n!==l)}}catch(r){kt(e,e.return,r)}}function wn(t,e,n){try{var a=e.updateQueue,l=a!==null?a.lastEffect:null;if(l!==null){var i=l.next;a=i;do{if((a.tag&t)===t){var o=a.inst,r=o.destroy;if(r!==void 0){o.destroy=void 0,l=e;var f=n,S=r;try{S()}catch(j){kt(l,f,j)}}}a=a.next}while(a!==i)}}catch(j){kt(e,e.return,j)}}function hf(t){var e=t.updateQueue;if(e!==null){var n=t.stateNode;try{lc(e,n)}catch(a){kt(t,t.return,a)}}}function gf(t,e,n){n.props=fa(t.type,t.memoizedProps),n.state=t.memoizedState;try{n.componentWillUnmount()}catch(a){kt(t,e,a)}}function Kl(t,e){try{var n=t.ref;if(n!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:a=t.stateNode;break;default:a=t.stateNode}typeof n=="function"?t.refCleanup=n(a):n.current=a}}catch(l){kt(t,e,l)}}function Qe(t,e){var n=t.ref,a=t.refCleanup;if(n!==null)if(typeof a=="function")try{a()}catch(l){kt(t,e,l)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof n=="function")try{n(null)}catch(l){kt(t,e,l)}else n.current=null}function vf(t){var e=t.type,n=t.memoizedProps,a=t.stateNode;try{t:switch(e){case"button":case"input":case"select":case"textarea":n.autoFocus&&a.focus();break t;case"img":n.src?a.src=n.src:n.srcSet&&(a.srcset=n.srcSet)}}catch(l){kt(t,t.return,l)}}function Ps(t,e,n){try{var a=t.stateNode;Jp(a,t.type,n,e),a[ne]=e}catch(l){kt(t,t.return,l)}}function yf(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&Yn(t.type)||t.tag===4}function tu(t){t:for(;;){for(;t.sibling===null;){if(t.return===null||yf(t.return))return null;t=t.return}for(t.sibling.return=t.return,t=t.sibling;t.tag!==5&&t.tag!==6&&t.tag!==18;){if(t.tag===27&&Yn(t.type)||t.flags&2||t.child===null||t.tag===4)continue t;t.child.return=t,t=t.child}if(!(t.flags&2))return t.stateNode}}function eu(t,e,n){var a=t.tag;if(a===5||a===6)t=t.stateNode,e?(n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n).insertBefore(t,e):(e=n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n,e.appendChild(t),n=n._reactRootContainer,n!=null||e.onclick!==null||(e.onclick=nn));else if(a!==4&&(a===27&&Yn(t.type)&&(n=t.stateNode,e=null),t=t.child,t!==null))for(eu(t,e,n),t=t.sibling;t!==null;)eu(t,e,n),t=t.sibling}function Pi(t,e,n){var a=t.tag;if(a===5||a===6)t=t.stateNode,e?n.insertBefore(t,e):n.appendChild(t);else if(a!==4&&(a===27&&Yn(t.type)&&(n=t.stateNode),t=t.child,t!==null))for(Pi(t,e,n),t=t.sibling;t!==null;)Pi(t,e,n),t=t.sibling}function xf(t){var e=t.stateNode,n=t.memoizedProps;try{for(var a=t.type,l=e.attributes;l.length;)e.removeAttributeNode(l[0]);oe(e,a,n),e[Qt]=t,e[ne]=n}catch(i){kt(t,t.return,i)}}var mn=!1,Wt=!1,nu=!1,bf=typeof WeakSet=="function"?WeakSet:Set,Pt=null;function jp(t,e){if(t=t.containerInfo,Eu=So,t=Or(t),Wo(t)){if("selectionStart"in t)var n={start:t.selectionStart,end:t.selectionEnd};else t:{n=(n=t.ownerDocument)&&n.defaultView||window;var a=n.getSelection&&n.getSelection();if(a&&a.rangeCount!==0){n=a.anchorNode;var l=a.anchorOffset,i=a.focusNode;a=a.focusOffset;try{n.nodeType,i.nodeType}catch{n=null;break t}var o=0,r=-1,f=-1,S=0,j=0,O=t,T=null;e:for(;;){for(var A;O!==n||l!==0&&O.nodeType!==3||(r=o+l),O!==i||a!==0&&O.nodeType!==3||(f=o+a),O.nodeType===3&&(o+=O.nodeValue.length),(A=O.firstChild)!==null;)T=O,O=A;for(;;){if(O===t)break e;if(T===n&&++S===l&&(r=o),T===i&&++j===a&&(f=o),(A=O.nextSibling)!==null)break;O=T,T=O.parentNode}O=A}n=r===-1||f===-1?null:{start:r,end:f}}else n=null}n=n||{start:0,end:0}}else n=null;for(Au={focusedElem:t,selectionRange:n},So=!1,Pt=e;Pt!==null;)if(e=Pt,t=e.child,(e.subtreeFlags&1028)!==0&&t!==null)t.return=e,Pt=t;else for(;Pt!==null;){switch(e=Pt,i=e.alternate,t=e.flags,e.tag){case 0:if((t&4)!==0&&(t=e.updateQueue,t=t!==null?t.events:null,t!==null))for(n=0;n title"))),oe(i,a,n),i[Qt]=t,yt(i),a=i;break t;case"link":var o=Cd("link","href",l).get(a+(n.href||""));if(o){for(var r=0;rBt&&(o=Bt,Bt=$,$=o);var g=_r(r,$),p=_r(r,Bt);if(g&&p&&(A.rangeCount!==1||A.anchorNode!==g.node||A.anchorOffset!==g.offset||A.focusNode!==p.node||A.focusOffset!==p.offset)){var b=O.createRange();b.setStart(g.node,g.offset),A.removeAllRanges(),$>Bt?(A.addRange(b),A.extend(p.node,p.offset)):(b.setEnd(p.node,p.offset),A.addRange(b))}}}}for(O=[],A=r;A=A.parentNode;)A.nodeType===1&&O.push({element:A,left:A.scrollLeft,top:A.scrollTop});for(typeof r.focus=="function"&&r.focus(),r=0;rn?32:n,C.T=null,n=ru,ru=null;var i=qn,o=yn;if(Ft=0,tl=qn=null,yn=0,(Ct&6)!==0)throw Error(c(331));var r=Ct;if(Ct|=4,Of(i.current),Mf(i,i.current,o,n),Ct=r,Wl(0,!1),ue&&typeof ue.onPostCommitFiberRoot=="function")try{ue.onPostCommitFiberRoot(ye,i)}catch{}return!0}finally{w.p=l,C.T=a,Wf(t,e)}}function $f(t,e,n){e=Oe(n,e),e=Ys(t.stateNode,e,2),t=Dn(t,e,2),t!==null&&(En(t,2),Ve(t))}function kt(t,e,n){if(t.tag===3)$f(t,t,n);else for(;e!==null;){if(e.tag===3){$f(e,t,n);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Nn===null||!Nn.has(a))){t=Oe(n,t),n=$c(2),a=Dn(e,n,2),a!==null&&(Ic(n,a,e,t),En(a,2),Ve(a));break}}e=e.return}}function mu(t,e,n){var a=t.pingCache;if(a===null){a=t.pingCache=new kp;var l=new Set;a.set(e,l)}else l=a.get(e),l===void 0&&(l=new Set,a.set(e,l));l.has(n)||(iu=!0,l.add(n),t=wp.bind(null,t,e,n),e.then(t,t))}function wp(t,e,n){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&n,t.warmLanes&=~n,wt===t&&(gt&n)===n&&(Gt===4||Gt===3&&(gt&62914560)===gt&&300>se()-no?(Ct&2)===0&&el(t,0):ou|=n,Pa===gt&&(Pa=0)),Ve(t)}function If(t,e){e===0&&(e=Ea()),t=ea(t,e),t!==null&&(En(t,e),Ve(t))}function Up(t){var e=t.memoizedState,n=0;e!==null&&(n=e.retryLane),If(t,n)}function Hp(t,e){var n=0;switch(t.tag){case 31:case 13:var a=t.stateNode,l=t.memoizedState;l!==null&&(n=l.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(c(314))}a!==null&&a.delete(e),If(t,n)}function Np(t,e){return fl(t,e)}var ro=null,al=null,pu=!1,co=!1,hu=!1,Gn=0;function Ve(t){t!==al&&t.next===null&&(al===null?ro=al=t:al=al.next=t),co=!0,pu||(pu=!0,Lp())}function Wl(t,e){if(!hu&&co){hu=!0;do for(var n=!1,a=ro;a!==null;){if(t!==0){var l=a.pendingLanes;if(l===0)var i=0;else{var o=a.suspendedLanes,r=a.pingedLanes;i=(1<<31-ee(42|t)+1)-1,i&=l&~(o&~r),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(n=!0,nd(a,i))}else i=gt,i=Ta(a,a===wt?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||Tn(a,i)||(n=!0,nd(a,i));a=a.next}while(n);hu=!1}}function qp(){Pf()}function Pf(){co=pu=!1;var t=0;Gn!==0&&Fp()&&(t=Gn);for(var e=se(),n=null,a=ro;a!==null;){var l=a.next,i=td(a,e);i===0?(a.next=null,n===null?ro=l:n.next=l,l===null&&(al=n)):(n=a,(t!==0||(i&3)!==0)&&(co=!0)),a=l}Ft!==0&&Ft!==5||Wl(t),Gn!==0&&(Gn=0)}function td(t,e){for(var n=t.suspendedLanes,a=t.pingedLanes,l=t.expirationTimes,i=t.pendingLanes&-62914561;0r)break;var j=f.transferSize,O=f.initiatorType;j&&cd(O)&&(f=f.responseEnd,o+=j*(f"u"?null:document;function Td(t,e,n){var a=ll;if(a&&typeof e=="string"&&e){var l=_e(e);l='link[rel="'+t+'"][href="'+l+'"]',typeof n=="string"&&(l+='[crossorigin="'+n+'"]'),Sd.has(l)||(Sd.add(l),t={rel:t,crossOrigin:n,href:e},a.querySelector(l)===null&&(e=a.createElement("link"),oe(e,"link",t),yt(e),a.head.appendChild(e)))}}function ih(t){xn.D(t),Td("dns-prefetch",t,null)}function oh(t,e){xn.C(t,e),Td("preconnect",t,e)}function sh(t,e,n){xn.L(t,e,n);var a=ll;if(a&&t&&e){var l='link[rel="preload"][as="'+_e(e)+'"]';e==="image"&&n&&n.imageSrcSet?(l+='[imagesrcset="'+_e(n.imageSrcSet)+'"]',typeof n.imageSizes=="string"&&(l+='[imagesizes="'+_e(n.imageSizes)+'"]')):l+='[href="'+_e(t)+'"]';var i=l;switch(e){case"style":i=il(t);break;case"script":i=ol(t)}He.has(i)||(t=R({rel:"preload",href:e==="image"&&n&&n.imageSrcSet?void 0:t,as:e},n),He.set(i,t),a.querySelector(l)!==null||e==="style"&&a.querySelector(Pl(i))||e==="script"&&a.querySelector(ti(i))||(e=a.createElement("link"),oe(e,"link",t),yt(e),a.head.appendChild(e)))}}function uh(t,e){xn.m(t,e);var n=ll;if(n&&t){var a=e&&typeof e.as=="string"?e.as:"script",l='link[rel="modulepreload"][as="'+_e(a)+'"][href="'+_e(t)+'"]',i=l;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=ol(t)}if(!He.has(i)&&(t=R({rel:"modulepreload",href:t},e),He.set(i,t),n.querySelector(l)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(n.querySelector(ti(i)))return}a=n.createElement("link"),oe(a,"link",t),yt(a),n.head.appendChild(a)}}}function rh(t,e,n){xn.S(t,e,n);var a=ll;if(a&&t){var l=St(a).hoistableStyles,i=il(t);e=e||"default";var o=l.get(i);if(!o){var r={loading:0,preload:null};if(o=a.querySelector(Pl(i)))r.loading=5;else{t=R({rel:"stylesheet",href:t,"data-precedence":e},n),(n=He.get(i))&&Ou(t,n);var f=o=a.createElement("link");yt(f),oe(f,"link",t),f._p=new Promise(function(S,j){f.onload=S,f.onerror=j}),f.addEventListener("load",function(){r.loading|=1}),f.addEventListener("error",function(){r.loading|=2}),r.loading|=4,go(o,e,a)}o={type:"stylesheet",instance:o,count:1,state:r},l.set(i,o)}}}function ch(t,e){xn.X(t,e);var n=ll;if(n&&t){var a=St(n).hoistableScripts,l=ol(t),i=a.get(l);i||(i=n.querySelector(ti(l)),i||(t=R({src:t,async:!0},e),(e=He.get(l))&&Du(t,e),i=n.createElement("script"),yt(i),oe(i,"link",t),n.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(l,i))}}function fh(t,e){xn.M(t,e);var n=ll;if(n&&t){var a=St(n).hoistableScripts,l=ol(t),i=a.get(l);i||(i=n.querySelector(ti(l)),i||(t=R({src:t,async:!0,type:"module"},e),(e=He.get(l))&&Du(t,e),i=n.createElement("script"),yt(i),oe(i,"link",t),n.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(l,i))}}function Ed(t,e,n,a){var l=(l=rt.current)?ho(l):null;if(!l)throw Error(c(446));switch(t){case"meta":case"title":return null;case"style":return typeof n.precedence=="string"&&typeof n.href=="string"?(e=il(n.href),n=St(l).hoistableStyles,a=n.get(e),a||(a={type:"style",instance:null,count:0,state:null},n.set(e,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(n.rel==="stylesheet"&&typeof n.href=="string"&&typeof n.precedence=="string"){t=il(n.href);var i=St(l).hoistableStyles,o=i.get(t);if(o||(l=l.ownerDocument||l,o={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},i.set(t,o),(i=l.querySelector(Pl(t)))&&!i._p&&(o.instance=i,o.state.loading=5),He.has(t)||(n={rel:"preload",as:"style",href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},He.set(t,n),i||dh(l,t,n,o.state))),e&&a===null)throw Error(c(528,""));return o}if(e&&a!==null)throw Error(c(529,""));return null;case"script":return e=n.async,n=n.src,typeof n=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(e=ol(n),n=St(l).hoistableScripts,a=n.get(e),a||(a={type:"script",instance:null,count:0,state:null},n.set(e,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(c(444,t))}}function il(t){return'href="'+_e(t)+'"'}function Pl(t){return'link[rel="stylesheet"]['+t+"]"}function Ad(t){return R({},t,{"data-precedence":t.precedence,precedence:null})}function dh(t,e,n,a){t.querySelector('link[rel="preload"][as="style"]['+e+"]")?a.loading=1:(e=t.createElement("link"),a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2}),oe(e,"link",n),yt(e),t.head.appendChild(e))}function ol(t){return'[src="'+_e(t)+'"]'}function ti(t){return"script[async]"+t}function zd(t,e,n){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+_e(n.href)+'"]');if(a)return e.instance=a,yt(a),a;var l=R({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),yt(a),oe(a,"style",l),go(a,n.precedence,t),e.instance=a;case"stylesheet":l=il(n.href);var i=t.querySelector(Pl(l));if(i)return e.state.loading|=4,e.instance=i,yt(i),i;a=Ad(n),(l=He.get(l))&&Ou(a,l),i=(t.ownerDocument||t).createElement("link"),yt(i);var o=i;return o._p=new Promise(function(r,f){o.onload=r,o.onerror=f}),oe(i,"link",a),e.state.loading|=4,go(i,n.precedence,t),e.instance=i;case"script":return i=ol(n.src),(l=t.querySelector(ti(i)))?(e.instance=l,yt(l),l):(a=n,(l=He.get(i))&&(a=R({},n),Du(a,l)),t=t.ownerDocument||t,l=t.createElement("script"),yt(l),oe(l,"link",a),t.head.appendChild(l),e.instance=l);case"void":return null;default:throw Error(c(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,go(a,n.precedence,t));return e.instance}function go(t,e,n){for(var a=n.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),l=a.length?a[a.length-1]:null,i=l,o=0;o title"):null)}function mh(t,e,n){if(n===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;switch(e.rel){case"stylesheet":return t=e.disabled,typeof e.precedence=="string"&&t==null;default:return!0}case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function Md(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function ph(t,e,n,a){if(n.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(n.state.loading&4)===0){if(n.instance===null){var l=il(a.href),i=e.querySelector(Pl(l));if(i){e=i._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=yo.bind(t),e.then(t,t)),n.state.loading|=4,n.instance=i,yt(i);return}i=e.ownerDocument||e,a=Ad(a),(l=He.get(l))&&Ou(a,l),i=i.createElement("link"),yt(i);var o=i;o._p=new Promise(function(r,f){o.onload=r,o.onerror=f}),oe(i,"link",a),n.instance=i}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(n,e),(e=n.state.preload)&&(n.state.loading&3)===0&&(t.count++,n=yo.bind(t),e.addEventListener("load",n),e.addEventListener("error",n))}}var Ru=0;function hh(t,e){return t.stylesheets&&t.count===0&&bo(t,t.stylesheets),0Ru?50:800)+e);return t.unsuspend=n,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(l)}}:null}function yo(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)bo(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var xo=null;function bo(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,xo=new Map,e.forEach(gh,t),xo=null,yo.call(t))}function gh(t,e){if(!(e.state.loading&4)){var n=xo.get(t);if(n)var a=n.get(null);else{n=new Map,xo.set(t,n);for(var l=t.querySelectorAll("link[data-precedence],style[data-precedence]"),i=0;i"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(u)}catch(h){console.error(h)}}return u(),Yu.exports=Rh(),Yu.exports}var wh=Bh();const Uh="modulepreload",Hh=function(u){return"/"+u},Id={},Xt=function(h,d,c){let v=Promise.resolve();if(d&&d.length>0){let M=function(y){return Promise.all(y.map(G=>Promise.resolve(G).then(R=>({status:"fulfilled",value:R}),R=>({status:"rejected",reason:R}))))};document.getElementsByTagName("link");const D=document.querySelector("meta[property=csp-nonce]"),z=(D==null?void 0:D.nonce)||(D==null?void 0:D.getAttribute("nonce"));v=M(d.map(y=>{if(y=Hh(y),y in Id)return;Id[y]=!0;const G=y.endsWith(".css"),R=G?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${y}"]${R}`))return;const K=document.createElement("link");if(K.rel=G?"stylesheet":Uh,G||(K.as="script"),K.crossOrigin="",K.href=y,z&&K.setAttribute("nonce",z),document.head.appendChild(K),G)return new Promise((nt,bt)=>{K.addEventListener("load",nt),K.addEventListener("error",()=>bt(new Error(`Unable to preload CSS for ${y}`)))})}))}function E(M){const D=new Event("vite:preloadError",{cancelable:!0});if(D.payload=M,window.dispatchEvent(D),!D.defaultPrevented)throw M}return v.then(M=>{for(const D of M||[])D.status==="rejected"&&E(D.reason);return h().catch(E)})},Mo={amber:{dark:{bg:"#09090b",sf:"#111114",sfH:"#18181c",bd:"#1e1e24",tx:"#e4e4e7",tx2:"#a1a1aa",txM:"#919199",ac:"#e8a845",acD:"rgba(232,168,69,0.12)",acT:"#fbbf24",cdBg:"#0c0c0f",cdTx:"#c4c4cc",sbBg:"#0c0c0e",hdBg:"rgba(9,9,11,0.85)"},light:{bg:"#fafaf9",sf:"#ffffff",sfH:"#f5f5f4",bd:"#e7e5e4",tx:"#1c1917",tx2:"#57534e",txM:"#706b66",ac:"#96640a",acD:"rgba(150,100,10,0.08)",acT:"#7a5208",cdBg:"#f5f3f0",cdTx:"#2c2520",sbBg:"#f5f5f3",hdBg:"rgba(250,250,249,0.85)"},fonts:{heading:"Instrument Serif",body:"DM Sans",code:"JetBrains Mono"}},editorial:{dark:{bg:"#080c1f",sf:"#0e1333",sfH:"#141940",bd:"#1a2050",tx:"#e8e6f0",tx2:"#b5b1c8",txM:"#9490ae",ac:"#ff6b4a",acD:"rgba(255,107,74,0.1)",acT:"#ff8a70",cdBg:"#0a0e27",cdTx:"#b8b4cc",sbBg:"#0a0e27",hdBg:"rgba(8,12,31,0.9)"},light:{bg:"#f6f4f0",sf:"#ffffff",sfH:"#eeece6",bd:"#ddd9d0",tx:"#1a1716",tx2:"#4a443e",txM:"#706960",ac:"#b83d22",acD:"rgba(184,61,34,0.07)",acT:"#9c3019",cdBg:"#edeae4",cdTx:"#3a3530",sbBg:"#f0ede8",hdBg:"rgba(246,244,240,0.92)"},fonts:{heading:"Cormorant Garamond",body:"Bricolage Grotesque",code:"Fira Code"}},cipher:{dark:{bg:"#050508",sf:"#0c0c12",sfH:"#12121a",bd:"#1a1a25",tx:"#d4ff00",tx2:"#8a90a0",txM:"#6a7080",ac:"#6666ff",acD:"rgba(102,102,255,0.10)",acT:"#8080ff",cdBg:"#08080e",cdTx:"#b0c870",sbBg:"#08080d",hdBg:"rgba(5,5,8,0.88)"},light:{bg:"#f0f2f5",sf:"#ffffff",sfH:"#e8eaef",bd:"#d0d4db",tx:"#0f1219",tx2:"#4a5060",txM:"#6a7080",ac:"#2020cc",acD:"rgba(32,32,204,0.08)",acT:"#1a1aa8",cdBg:"#e6e9ef",cdTx:"#2a3520",sbBg:"#ebedf2",hdBg:"rgba(240,242,245,0.90)"},fonts:{heading:"Bodoni Moda",body:"Space Grotesk",code:"Source Code Pro"}},mint:{dark:{bg:"#0d1117",sf:"#161b22",sfH:"#1c2129",bd:"#21262d",tx:"#e6edf3",tx2:"#8b949e",txM:"#6e7681",ac:"#0ea371",acD:"rgba(14,163,113,0.10)",acT:"#2dd4a0",cdBg:"#0a0e14",cdTx:"#adbac7",sbBg:"#0d1117",hdBg:"rgba(13,17,23,0.88)"},light:{bg:"#ffffff",sf:"#f6f8fa",sfH:"#eef1f5",bd:"#d8dee4",tx:"#1f2328",tx2:"#59636e",txM:"#6e7681",ac:"#0a7b53",acD:"rgba(10,123,83,0.07)",acT:"#087a50",cdBg:"#f0f3f6",cdTx:"#24292f",sbBg:"#f6f8fa",hdBg:"rgba(255,255,255,0.90)"},fonts:{heading:"Inter",body:"Inter",code:"Fira Code"}}},Nh=()=>s.jsx("svg",{width:22,height:22,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})}),qh=()=>s.jsx("svg",{width:18,height:18,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("path",{d:"M18 6L6 18M6 6l12 12"})}),Lh=()=>s.jsx("svg",{width:16,height:16,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("path",{d:"M22 2L11 13M22 2l-7 20-4-9-9-4z"})});function um(u){let h="You are a helpful documentation assistant. Answer questions accurately based on the documentation provided below. If the answer isn't in the documentation, say so clearly. Keep answers concise and reference specific sections when possible.";if(u){const d=u.length>1e5?u.slice(0,1e5)+` + +[Documentation truncated...]`:u;h+=` + +Documentation: +${d}`}return h}async function Gh(u,h,d,c){var M,D,z;const v=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${h}`},body:JSON.stringify({model:d,messages:[{role:"system",content:um(c)},...u.map(y=>({role:y.role,content:y.content}))]})});if(!v.ok){const y=await v.text();throw new Error(`OpenAI API error (${v.status}): ${y}`)}return((z=(D=(M=(await v.json()).choices)==null?void 0:M[0])==null?void 0:D.message)==null?void 0:z.content)||"No response."}async function Yh(u,h,d,c){var M,D;const v=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":h,"anthropic-version":"2023-06-01","anthropic-dangerous-direct-browser-access":"true"},body:JSON.stringify({model:d,max_tokens:1024,system:um(c),messages:u.map(z=>({role:z.role,content:z.content}))})});if(!v.ok){const z=await v.text();throw new Error(`Anthropic API error (${v.status}): ${z}`)}return((D=(M=(await v.json()).content)==null?void 0:M[0])==null?void 0:D.text)||"No response."}function Kh(u){return u==="openai"?"gpt-4o-mini":"claude-sonnet-4-20250514"}function Xh({provider:u,model:h,apiKey:d,context:c}){const[v,E]=B.useState(!1),[M,D]=B.useState([]),[z,y]=B.useState(""),[G,R]=B.useState(!1),[K,nt]=B.useState(null),bt=B.useRef(null),Ot=B.useRef(null),jt=d||(typeof window<"u"?window.__TOME_AI_API_KEY__:void 0),W=h||Kh(u);B.useEffect(()=>{var Q;(Q=bt.current)==null||Q.scrollIntoView({behavior:"smooth"})},[M]),B.useEffect(()=>{v&&setTimeout(()=>{var Q;return(Q=Ot.current)==null?void 0:Q.focus()},100)},[v]);const I=B.useCallback(async()=>{const Q=z.trim();if(!Q||G||!jt)return;const Y={role:"user",content:Q},H=[...M,Y];D(H),y(""),R(!0),nt(null);try{let U;u==="openai"?U=await Gh(H,jt,W,c):U=await Yh(H,jt,W,c),D(at=>[...at,{role:"assistant",content:U}])}catch(U){nt(U instanceof Error?U.message:"Failed to get response")}finally{R(!1)}},[z,G,M,u,jt,W,c]),ct=B.useCallback(Q=>{Q.key==="Enter"&&!Q.shiftKey&&(Q.preventDefault(),I())},[I]);return v?s.jsxs("div",{"data-testid":"ai-chat-panel",style:{position:"fixed",bottom:24,right:24,zIndex:900,width:380,maxWidth:"calc(100vw - 48px)",height:520,maxHeight:"calc(100vh - 48px)",background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:12,boxShadow:"0 16px 64px rgba(0,0,0,0.3)",display:"flex",flexDirection:"column",overflow:"hidden",fontFamily:"var(--font-body)"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"12px 16px",borderBottom:"1px solid var(--bd)",flexShrink:0},children:[s.jsx("span",{style:{fontSize:14,fontWeight:600,color:"var(--tx)"},children:"Ask AI"}),s.jsx("button",{"data-testid":"ai-chat-close",onClick:()=>E(!1),"aria-label":"Close AI chat",style:{background:"none",border:"none",color:"var(--txM)",cursor:"pointer",display:"flex",padding:4},children:s.jsx(qh,{})})]}),s.jsxs("div",{style:{flex:1,overflow:"auto",padding:"12px 16px"},children:[!jt&&s.jsxs("div",{"data-testid":"ai-chat-no-key",style:{textAlign:"center",color:"var(--txM)",fontSize:13,padding:"24px 8px",lineHeight:1.6},children:[s.jsx("p",{style:{marginBottom:8,fontWeight:500,color:"var(--tx)"},children:"AI not configured"}),s.jsxs("p",{style:{marginBottom:8},children:["To enable AI chat, set the ",s.jsx("code",{style:{fontFamily:"var(--font-code)",fontSize:"0.88em",background:"var(--cdBg)",padding:"0.15em 0.4em",borderRadius:4},children:"apiKeyEnv"})," in ",s.jsx("code",{style:{fontFamily:"var(--font-code)",fontSize:"0.88em",background:"var(--cdBg)",padding:"0.15em 0.4em",borderRadius:4},children:"tome.config.js"})," and provide the environment variable at build time."]}),s.jsxs("p",{style:{fontSize:11.5,color:"var(--txM)"},children:["Example: ",s.jsx("code",{style:{fontFamily:"var(--font-code)",fontSize:"0.88em",background:"var(--cdBg)",padding:"0.15em 0.4em",borderRadius:4},children:"TOME_AI_KEY=sk-... tome build"})]})]}),M.map((Q,Y)=>s.jsx("div",{"data-testid":`ai-chat-message-${Q.role}`,style:{marginBottom:12,display:"flex",justifyContent:Q.role==="user"?"flex-end":"flex-start"},children:s.jsx("div",{style:{maxWidth:"85%",padding:"8px 12px",borderRadius:10,fontSize:13,lineHeight:1.55,whiteSpace:"pre-wrap",wordBreak:"break-word",background:Q.role==="user"?"var(--ac)":"var(--cdBg)",color:Q.role==="user"?"#fff":"var(--tx)"},children:Q.content})},Y)),G&&s.jsx("div",{"data-testid":"ai-chat-loading",style:{display:"flex",justifyContent:"flex-start",marginBottom:12},children:s.jsx("div",{style:{padding:"8px 12px",borderRadius:10,fontSize:13,background:"var(--cdBg)",color:"var(--txM)"},children:"Thinking..."})}),K&&s.jsx("div",{"data-testid":"ai-chat-error",style:{padding:"8px 12px",borderRadius:8,fontSize:12,background:"rgba(220,50,50,0.1)",color:"#d44",marginBottom:12},children:K}),s.jsx("div",{ref:bt})]}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,padding:"10px 12px",borderTop:"1px solid var(--bd)",flexShrink:0},children:[s.jsx("input",{ref:Ot,"data-testid":"ai-chat-input",value:z,onChange:Q=>y(Q.target.value),onKeyDown:ct,placeholder:jt?"Ask a question...":"API key required",disabled:!jt,style:{flex:1,background:"var(--cdBg)",border:"1px solid var(--bd)",borderRadius:8,padding:"8px 12px",color:"var(--tx)",fontSize:13,fontFamily:"var(--font-body)",outline:"none"}}),s.jsx("button",{"data-testid":"ai-chat-send",onClick:I,disabled:!jt||!z.trim()||G,"aria-label":"Send message",style:{width:34,height:34,borderRadius:8,background:jt&&z.trim()?"var(--ac)":"var(--cdBg)",color:jt&&z.trim()?"#fff":"var(--txM)",border:"none",cursor:jt&&z.trim()?"pointer":"default",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0},children:s.jsx(Lh,{})})]})]}):s.jsx("button",{"data-testid":"ai-chat-button",onClick:()=>E(!0),"aria-label":"Open AI chat",style:{position:"fixed",bottom:24,right:24,zIndex:900,width:48,height:48,borderRadius:"50%",background:"var(--ac)",color:"#fff",border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 16px rgba(0,0,0,0.25)",transition:"transform 0.15s"},children:s.jsx(Nh,{})})}function Qh(u){const h=/^#([0-9a-f]{6})$/i.exec(u.trim());if(!h)return null;const d=parseInt(h[1],16);return[d>>16&255,d>>8&255,d&255]}function Vh(u,h){const d=Qh(u);if(!d)return null;const[c,v,E]=d,M=`rgba(${c},${v},${E},${h?.12:.08})`,D=h?1.15:.85,z=Math.min(255,Math.round(c*D)),y=Math.min(255,Math.round(v*D)),G=Math.min(255,Math.round(E*D)),R=`rgb(${z},${y},${G})`;return{ac:u,acD:M,acT:R}}const Ce=({d:u,size:h=16})=>s.jsx("svg",{width:h,height:h,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("path",{d:u})}),rm=()=>s.jsx(Ce,{d:"M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.3-4.3"}),Pd=()=>s.jsx(Ce,{d:"M9 18l6-6-6-6",size:14}),Vu=()=>s.jsx(Ce,{d:"M6 9l6 6 6-6",size:14}),Zh=()=>s.jsx(Ce,{d:"M3 12h18M3 6h18M3 18h18",size:20}),Jh=()=>s.jsx(Ce,{d:"M18 6L6 18M6 6l12 12",size:18}),tm=()=>s.jsx(Ce,{d:"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"}),em=()=>s.jsx(Ce,{d:"M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm0-4a1 1 0 0 1 1-1v-1a1 1 0 0 1-2 0v1a1 1 0 0 1 1 1Zm0 16a1 1 0 0 1 1 1v1a1 1 0 0 1-2 0v-1a1 1 0 0 1 1-1ZM4 12a1 1 0 0 1-1 1H2a1 1 0 0 1 0-2h1a1 1 0 0 1 1 1Zm18-1h-1a1 1 0 0 1 0 2h1a1 1 0 0 1 0-2ZM6.34 6.34a1 1 0 0 1-1.41 0l-.71-.71a1 1 0 0 1 1.41-1.41l.71.71a1 1 0 0 1 0 1.41Zm12.73-2.12-.71.71a1 1 0 0 1-1.41-1.41l.71-.71a1 1 0 1 1 1.41 1.41ZM6.34 17.66l-.71.71a1 1 0 0 1-1.41-1.41l.71-.71a1 1 0 0 1 1.41 1.41Zm12.73 2.12-.71-.71a1 1 0 0 1 1.41-1.41l.71.71a1 1 0 0 1-1.41 1.41Z"}),nm=()=>s.jsx(Ce,{d:"M19 12H5M12 19l-7-7 7-7",size:14}),am=()=>s.jsx(Ce,{d:"M5 12h14M12 5l7 7-7 7",size:14}),Wh=()=>s.jsx(Ce,{d:"M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z",size:13});function Fh(u){const h=new Date(u),c=new Date().getTime()-h.getTime();if(isNaN(c))return"";const v=Math.floor(c/1e3),E=Math.floor(v/60),M=Math.floor(E/60),D=Math.floor(M/24),z=Math.floor(D/30),y=Math.floor(D/365);return v<60?"just now":E<60?`${E} minute${E===1?"":"s"} ago`:M<24?`${M} hour${M===1?"":"s"} ago`:D<30?`${D} day${D===1?"":"s"} ago`:z<12?`${z} month${z===1?"":"s"} ago`:y>=1?`${y} year${y===1?"":"s"} ago`:h.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}let ul=null;const $h="/_pagefind/pagefind.js";async function Ih(){if(ul)return ul;try{return ul=await import($h),await ul.init(),ul}catch{return null}}let _o=null;function Ph(){return _o||(_o=Xt(()=>import("./theme-BIHI7g3E.js"),[]).catch(()=>null),_o)}function t0({appId:u,apiKey:h,indexName:d,onNavigate:c,onClose:v,basePath:E=""}){const[M,D]=B.useState(null),[z,y]=B.useState(!1);B.useEffect(()=>{Ph().then(R=>{R&&R.DocSearch?D(()=>R.DocSearch):R&&R.default?D(()=>R.default):y(!0)})},[]);const G=B.useCallback(R=>{try{let nt=new URL(R,"http://localhost").pathname;if(E){const bt=E.replace(/\/$/,"");nt.startsWith(bt)&&(nt=nt.slice(bt.length))}return nt.replace(/^\//,"").replace(/\/index\.html$/,"").replace(/\.html$/,"")||"index"}catch{return"index"}},[E]);return z?s.jsx("div",{onClick:v,style:{position:"fixed",inset:0,zIndex:1e3,background:"rgba(0,0,0,0.55)",backdropFilter:"blur(6px)",display:"flex",alignItems:"flex-start",justifyContent:"center",paddingTop:"12vh"},children:s.jsx("div",{onClick:R=>R.stopPropagation(),style:{background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:12,width:"100%",maxWidth:520,boxShadow:"0 24px 80px rgba(0,0,0,0.4)",padding:"32px 18px",textAlign:"center",color:"var(--txM)",fontSize:14},children:"Algolia DocSearch is not available. Install @docsearch/react to enable it."})}):M?s.jsx("div",{"data-testid":"algolia-search-modal",children:s.jsx(M,{appId:u,apiKey:h,indexName:d,navigator:{navigate({itemUrl:R}){const K=G(R);c(K)}},hitComponent:({hit:R,children:K})=>s.jsx("a",{href:R.url,onClick:nt=>{nt.preventDefault();const bt=G(R.url);c(bt)},children:K})})}):s.jsx("div",{onClick:v,style:{position:"fixed",inset:0,zIndex:1e3,background:"rgba(0,0,0,0.55)",backdropFilter:"blur(6px)",display:"flex",alignItems:"flex-start",justifyContent:"center",paddingTop:"12vh"},children:s.jsx("div",{style:{background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:12,width:"100%",maxWidth:520,boxShadow:"0 24px 80px rgba(0,0,0,0.4)",padding:"32px 18px",textAlign:"center",color:"var(--txM)",fontSize:14},children:"Loading search..."})})}const e0=()=>s.jsx(Ce,{d:"M12 8v4l3 3m6-3a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z",size:14}),n0=()=>s.jsx(Ce,{d:"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM3.6 9h16.8M3.6 15h16.8M12 3a15 15 0 0 1 4 9 15 15 0 0 1-4 9 15 15 0 0 1-4-9 15 15 0 0 1 4-9Z",size:14}),a0=()=>s.jsx(Ce,{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3",size:11}),l0={github:"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z",twitter:"M12.6.75h2.454l-5.36 6.142L16 15.25h-4.937l-3.867-5.07-4.425 5.07H.316l5.733-6.57L0 .75h5.063l3.495 4.633L12.601.75Zm-.86 13.028h1.36L4.323 2.145H2.865l8.875 11.633Z",discord:"M13.545 2.907a13.227 13.227 0 00-3.257-1.011.05.05 0 00-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 00-3.658 0 8.258 8.258 0 00-.412-.833.051.051 0 00-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 00-.021.018C.356 6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 003.995 2.02.05.05 0 00.056-.019c.308-.42.582-.863.818-1.329a.05.05 0 00-.028-.07 8.735 8.735 0 01-1.248-.595.05.05 0 01-.005-.083c.084-.063.168-.129.248-.195a.05.05 0 01.051-.007c2.619 1.196 5.454 1.196 8.041 0a.052.052 0 01.053.007c.08.066.164.132.248.195a.051.051 0 01-.004.085c-.399.232-.813.431-1.249.594a.05.05 0 00-.03.07c.24.465.515.909.817 1.329a.05.05 0 00.056.019 13.235 13.235 0 004.001-2.02.049.049 0 00.021-.037c.334-3.451-.559-6.449-2.366-9.106a.034.034 0 00-.02-.019z",linkedin:"M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 01.016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4z",youtube:"M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 011.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 01-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 01-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 010 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 011.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 017.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z",mastodon:"M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765 2.79.765.504 1.783.504 5.253c-.005.995-.01 2.19.013 3.44.075 4.21.56 8.354 3.383 9.386 1.302.476 2.418.576 3.317.507 1.628-.125 2.541-.8 2.541-.8l-.054-1.182s-1.163.366-2.47.322c-1.293-.044-2.658-.138-2.867-1.716a3.23 3.23 0 01-.028-.465s1.27.31 2.879.384c.984.045 1.905-.058 2.842-.17zM13 8.59V5.319c0-.67-.17-1.2-.507-1.592-.348-.4-.806-.605-1.373-.605-.656 0-1.154.252-1.486.756L9.2 4.595l-.434-.717c-.332-.504-.83-.756-1.486-.756-.567 0-1.025.204-1.373.605-.338.392-.507.923-.507 1.592V8.59h1.69V5.468c0-.67.285-1.012.855-1.012.63 0 .946.404.946 1.204V7.11h1.682V5.66c0-.8.316-1.204.946-1.204.57 0 .855.342.855 1.012V8.59H13z",bluesky:"M3.468 1.948C5.303 3.325 7.276 6.118 8 7.616c.724-1.498 2.697-4.29 4.532-5.668C13.855 1.013 16 .638 16 3.14c0 .5-.286 4.2-.454 4.8-.585 2.093-2.716 2.628-4.544 2.305 3.195.564 4.007 2.433 2.25 4.302-3.337 3.548-4.8-1.244-5.252-2.547 0 0-.116-.334-.166-.334h.332C8.166 11.666 8.05 12 8.05 12c-.452 1.303-1.916 6.095-5.252 2.547-1.756-1.869-.946-3.738 2.25-4.302-1.829.323-3.96-.212-4.544-2.305C.336 7.34.05 3.64.05 3.14.05.638 2.195 1.013 3.468 1.948z"},i0=({platform:u,customIcon:h})=>{const d=u==="custom"&&h?h:l0[u];return d?s.jsx("svg",{width:16,height:16,viewBox:"0 0 16 16",fill:"currentColor",children:s.jsx("path",{d})}):null},o0={Added:"#22c55e",Changed:"#3b82f6",Deprecated:"#f59e0b",Removed:"#ef4444",Fixed:"#8b5cf6",Security:"#f97316"};function s0({entries:u}){const[h,d]=B.useState(u.length<=5),c=h?u:u.slice(0,5);return s.jsxs("div",{"data-testid":"changelog-timeline",style:{position:"relative"},children:[s.jsx("div",{style:{position:"absolute",left:15,top:8,bottom:8,width:2,background:"var(--bd)"}}),c.map((v,E)=>s.jsxs("div",{"data-testid":`changelog-entry-${v.version}`,style:{position:"relative",paddingLeft:44,paddingBottom:E{const D=o0[M.type]||"#6b7280";return s.jsxs("div",{style:{marginBottom:16},children:[s.jsxs("div",{style:{display:"inline-flex",alignItems:"center",gap:6,marginBottom:8},children:[s.jsx("span",{style:{display:"inline-block",width:8,height:8,borderRadius:"50%",background:D}}),s.jsx("span",{style:{fontSize:12,fontWeight:600,textTransform:"uppercase",letterSpacing:".06em",color:D,fontFamily:"var(--font-code, monospace)"},children:M.type})]}),s.jsx("ul",{style:{margin:0,paddingLeft:18,listStyleType:"disc",color:"var(--tx2)"},children:M.items.map((z,y)=>s.jsx("li",{style:{fontSize:14,lineHeight:1.7,color:"var(--tx2)",marginBottom:2},children:z},y))})]},M.type)})]},v.version)),!h&&u.length>5&&s.jsx("div",{style:{textAlign:"center",marginTop:24},children:s.jsxs("button",{"data-testid":"changelog-show-more",onClick:()=>d(!0),style:{background:"none",border:"1px solid var(--bd)",borderRadius:2,padding:"8px 20px",color:"var(--tx2)",fontSize:13,fontFamily:"var(--font-body, inherit)",cursor:"pointer"},children:["Show all ",u.length," releases"]})})]})}function u0(u,h,d){if(h==="index")return[];for(const c of u)if(c.pages.find(E=>E.id===h)){const E=[],M=c.pages[0];return E.push({label:c.section,href:M?M.urlPath:null}),E.push({label:d,href:null}),E}return[]}function r0({config:u,navigation:h,currentPageId:d,pageHtml:c,pageComponent:v,mdxComponents:E,pageTitle:M,pageDescription:D,headings:z,tocEnabled:y=!0,editUrl:G,lastUpdated:R,changelogEntries:K,apiManifest:nt,apiBaseUrl:bt,apiPlayground:Ot,apiAuth:jt,ApiReferenceComponent:W,onNavigate:I,allPages:ct,versioning:Q,currentVersion:Y,i18n:H,currentLocale:U,docContext:at,basePath:lt="",isDraft:P,dir:mt,overrides:tt}){var Aa,En,fi,dl,ml,pl,za,Ca,hl,gl,qe,Qt,ne,tn,ja,di,mi,vl,An;const Mt=U||(H==null?void 0:H.defaultLocale)||"en",$t=mt||((Aa=H==null?void 0:H.localeDirs)==null?void 0:Aa[Mt])||"ltr",ft=$t==="rtl",C=((En=u.theme)==null?void 0:En.mode)||"auto",[w,Z]=B.useState(()=>{var x;return C==="dark"?!0:C==="light"?!1:((x=window.matchMedia)==null?void 0:x.call(window,"(prefers-color-scheme: dark)").matches)??!1}),[J,Tt]=B.useState(()=>typeof window<"u"&&window.innerWidth<768),[m,k]=B.useState(()=>typeof window<"u"&&window.innerWidth>=768),[N,L]=B.useState(!1),[it,rt]=B.useState(!1),[Et,It]=B.useState(!1),[Ut,Ze]=B.useState(null),[pa,ha]=B.useState({}),[rl,Je]=B.useState(()=>{var x;if(!((x=u.banner)!=null&&x.text))return!0;try{const q=Array.from(u.banner.text).reduce((et,dt)=>(et<<5)-et+dt.charCodeAt(0)|0,0).toString(36);return localStorage.getItem("tome-banner-dismissed")===q}catch{return!1}}),cl=Q&&Y&&Y!==Q.current,[ga,Oo]=B.useState(h.map(x=>x.section)),We=B.useRef(null),Fn=B.useRef(null),fl=B.useRef(""),[va,Do]=B.useState(()=>typeof window<"u"&&window.innerWidth>1100),si=((fi=u.theme)==null?void 0:fi.preset)||"amber",se=((dl=Mo[si])==null?void 0:dl[w?"dark":"light"])||Mo.amber.dark,ui=(ml=u.theme)!=null&&ml.accent?Vh(u.theme.accent,w):null,te=ui?{...se,...ui}:se,ya=((pl=Mo[si])==null?void 0:pl.fonts)||Mo.amber.fonts,bn={heading:((Ca=(za=u.theme)==null?void 0:za.fonts)==null?void 0:Ca.heading)||ya.heading,body:((gl=(hl=u.theme)==null?void 0:hl.fonts)==null?void 0:gl.body)||ya.body,code:((Qt=(qe=u.theme)==null?void 0:qe.fonts)==null?void 0:Qt.code)||ya.code};B.useEffect(()=>{if(C!=="auto")return;const x=window.matchMedia("(prefers-color-scheme: dark)"),q=et=>Z(et.matches);return x.addEventListener("change",q),()=>x.removeEventListener("change",q)},[C]),B.useEffect(()=>{document.documentElement.classList.toggle("dark",w)},[w]),B.useEffect(()=>{const x=()=>{const q=window.innerWidth;Do(q>1100),Tt(q<768)};return x(),window.addEventListener("resize",x),()=>window.removeEventListener("resize",x)},[]),B.useEffect(()=>{if(J&&m)return document.body.style.overflow="hidden",()=>{document.body.style.overflow=""}},[J,m]),B.useEffect(()=>{var x;(x=We.current)==null||x.scrollTo(0,0)},[d]),B.useEffect(()=>{const x=We.current;if(!x)return;const q=et=>{const dt=et.target;dt.tagName==="IMG"&&dt.closest(".tome-content")&&Ze(dt.src)};return x.addEventListener("click",q),()=>x.removeEventListener("click",q)},[]),B.useEffect(()=>{const x=We.current;if(!x)return;const q=et=>{const dt=et.target.closest("a");if(!dt)return;const St=dt.getAttribute("href");if(!St||St.startsWith("http://")||St.startsWith("https://")||St.startsWith("mailto:")||St.startsWith("tel:")||St.startsWith("//")||St.startsWith("#"))return;et.preventDefault();let yt=St.replace(/^\.\//,"").replace(/^\//,"").replace(/\.mdx?$/,"").replace(/\/$/,"");if(lt){const ce=lt.replace(/^\//,"").replace(/\/$/,"");ce&&yt.startsWith(ce+"/")?yt=yt.slice(ce.length+1):ce&&yt===ce&&(yt="index")}yt||(yt="index"),I(yt)};return x.addEventListener("click",q),()=>x.removeEventListener("click",q)},[I,lt]),B.useEffect(()=>{if(!Ut)return;const x=q=>{q.key==="Escape"&&Ze(null)};return window.addEventListener("keydown",x),()=>window.removeEventListener("keydown",x)},[Ut]);const Sn=u.toc,ri=(Sn==null?void 0:Sn.depth)??3,xa=(Sn==null?void 0:Sn.enabled)!==!1&&y,ye=z.filter(x=>x.depth<=ri),[ue,je]=B.useState("");B.useEffect(()=>{if(!xa||ye.length<2)return;const x=We.current;if(!x)return;const q=setTimeout(()=>{const et=[];for(const St of ye){const yt=x.querySelector(`#${CSS.escape(St.id)}`);yt&&et.push(yt)}if(et.length===0)return;const dt=new IntersectionObserver(St=>{const yt=St.filter(ce=>ce.isIntersecting).sort((ce,pi)=>ce.boundingClientRect.top-pi.boundingClientRect.top);yt.length>0&&je(yt[0].target.id)},{root:x,rootMargin:"0px 0px -80% 0px",threshold:0});for(const St of et)dt.observe(St);ee.current=dt},100);return()=>{var et;clearTimeout(q),(et=ee.current)==null||et.disconnect(),ee.current=null}},[d,xa,ye.map(x=>x.id).join(",")]);const ee=B.useRef(null);B.useEffect(()=>{je("")},[d]),B.useLayoutEffect(()=>{if(!Fn.current||!c)return;const x=c.replace(/]*>[\s\S]*?<\/h1>\s*/,"");Fn.current.innerHTML=x,fl.current=x},[c,d]);const ci=B.useCallback((x,q)=>{x.preventDefault();const et=We.current;if(!et)return;const dt=et.querySelector(`#${CSS.escape(q)}`);dt&&(dt.scrollIntoView({behavior:"smooth",block:"start"}),je(q))},[]);B.useEffect(()=>{const x=q=>{(q.metaKey||q.ctrlKey)&&q.key==="k"&&(q.preventDefault(),L(!0)),q.key==="Escape"&&L(!1)};return window.addEventListener("keydown",x),()=>window.removeEventListener("keydown",x)},[]);const ba=h.flatMap(x=>x.pages),Sa=ba.findIndex(x=>x.id===d),Fe=Sa>0?ba[Sa-1]:null,$e=SaOo(q=>q.includes(x)?q.filter(et=>et!==x):[...q,x]),Ta={"--bg":te.bg,"--sf":te.sf,"--sfH":te.sfH,"--bd":te.bd,"--tx":te.tx,"--tx2":te.tx2,"--txM":te.txM,"--ac":te.ac,"--acD":te.acD,"--acT":te.acT,"--cdBg":te.cdBg,"--cdTx":te.cdTx,"--sbBg":te.sbBg,"--hdBg":te.hdBg,"--font-heading":`"${bn.heading}", serif`,"--font-body":`"${bn.body}", sans-serif`,"--font-code":`"${bn.code}", monospace`},Tn=v,Ne=(ne=u.banner)==null?void 0:ne.link,Ea=Ne?Ne.startsWith("#")||lt&&Ne.startsWith(lt+"/"):!1;return s.jsxs("div",{dir:$t,className:"tome-grain",style:{...Ta,color:"var(--tx)",background:"var(--bg)",fontFamily:"var(--font-body)",height:"100vh",overflow:"clip"},children:[((tn=u.banner)==null?void 0:tn.text)&&!rl&&s.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",gap:12,background:"var(--ac)",color:"#fff",padding:"8px 16px",fontSize:13,fontFamily:"var(--font-body)",fontWeight:500,textAlign:"center",width:"100vw",boxSizing:"border-box"},children:[u.banner.link?s.jsx("a",{href:Ea&&Ne.startsWith("#")?lt+"/"+Ne.slice(1):Ne,...Ea?{}:{target:"_blank",rel:"noopener noreferrer"},style:{color:"#fff",textDecoration:"underline"},onClick:Ea?x=>{x.preventDefault();const q=lt.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),et=Ne.startsWith("#")?Ne.slice(1):Ne.replace(new RegExp("^"+q+"/?"),"");I(et||"index")}:void 0,children:u.banner.text}):s.jsx("span",{children:u.banner.text}),u.banner.dismissible!==!1&&s.jsx("button",{onClick:()=>{Je(!0);try{const x=Array.from(u.banner.text).reduce((q,et)=>(q<<5)-q+et.charCodeAt(0)|0,0).toString(36);localStorage.setItem("tome-banner-dismissed",x)}catch{}},"aria-label":"Dismiss banner",style:{background:"none",border:"none",color:"#fff",cursor:"pointer",fontSize:16,lineHeight:1,padding:0,opacity:.8},children:"×"})]}),N&&((ja=u.search)==null?void 0:ja.provider)==="algolia"&&u.search.appId&&u.search.apiKey&&u.search.indexName?s.jsx(t0,{appId:u.search.appId,apiKey:u.search.apiKey,indexName:u.search.indexName,onNavigate:x=>{I(x),L(!1)},onClose:()=>L(!1),basePath:lt}):N?s.jsx(c0,{allPages:ct,onNavigate:x=>{I(x),L(!1)},onClose:()=>L(!1),mobile:J}):null,s.jsxs("div",{style:{display:"flex",flexDirection:ft?"row-reverse":"row",flex:1,height:(di=u.banner)!=null&&di.text&&!rl?"calc(100vh - 32px)":"100vh"},children:[J&&m&&s.jsx("div",{onClick:()=>k(!1),style:{position:"fixed",inset:0,zIndex:200,background:"rgba(0,0,0,0.4)",backdropFilter:"blur(2px)"}}),tt!=null&&tt.Sidebar?s.jsx(tt.Sidebar,{config:u,navigation:h,currentPageId:d,onNavigate:I,mobile:J,sbOpen:m,setSbOpen:k,versioning:Q,currentVersion:Y}):s.jsxs("aside",{style:{width:m?270:0,minWidth:m?270:0,background:"var(--sbBg)",[ft?"borderLeft":"borderRight"]:"1px solid var(--bd)",display:"flex",flexDirection:"column",transition:"width .2s, min-width .2s",overflow:"hidden",...J?{position:"fixed",top:0,[ft?"right":"left"]:0,bottom:0,zIndex:201}:{}},children:[s.jsxs("a",{href:"/",style:{padding:"18px 20px",display:"flex",alignItems:"baseline",gap:6,borderBottom:"1px solid var(--bd)",textDecoration:"none",color:"inherit"},children:[s.jsx("span",{style:{fontFamily:"var(--font-heading)",fontSize:22,fontWeight:700,fontStyle:"italic"},children:u.name}),s.jsx("span",{style:{width:5,height:5,borderRadius:"50%",background:"var(--ac)",display:"inline-block"}})]}),s.jsx("div",{style:{padding:"12px 14px"},children:s.jsxs("button",{onClick:()=>{L(!0),J&&k(!1)},style:{display:"flex",alignItems:"center",gap:8,width:"100%",background:"var(--cdBg)",border:"1px solid var(--bd)",borderRadius:2,padding:"8px 12px",cursor:"pointer",color:"var(--txM)",fontSize:12.5,fontFamily:"var(--font-body)"},children:[s.jsx(rm,{}),s.jsx("span",{style:{flex:1,textAlign:ft?"right":"left"},children:"Search..."}),s.jsx("kbd",{style:{fontFamily:"var(--font-code)",fontSize:9,background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:2,padding:"2px 6px"},children:"⌘K"})]})}),s.jsx("nav",{style:{flex:1,overflow:"auto",padding:"4px 10px 20px"},children:h.map(x=>s.jsxs("div",{style:{marginBottom:8},children:[s.jsxs("button",{onClick:()=>Pe(x.section),style:{display:"flex",alignItems:"center",gap:6,width:"100%",background:"none",border:"none",padding:"8px 10px",cursor:"pointer",borderRadius:2,color:"var(--txM)",fontSize:10,fontWeight:600,textTransform:"uppercase",letterSpacing:".1em",fontFamily:"var(--font-code)"},children:[ga.includes(x.section)?s.jsx(Vu,{}):s.jsx(Pd,{}),x.section]}),ga.includes(x.section)&&s.jsx("div",{style:{[ft?"marginRight":"marginLeft"]:8,[ft?"borderRight":"borderLeft"]:"1px solid var(--bd)",[ft?"paddingRight":"paddingLeft"]:0},children:x.pages.map(q=>{const et=d===q.id;return s.jsxs("button",{onClick:()=>{I(q.id),J&&k(!1)},style:{display:"flex",alignItems:"center",gap:10,width:"100%",textAlign:ft?"right":"left",background:"none",border:"none",borderRadius:0,[ft?"borderRight":"borderLeft"]:et?"2px solid var(--ac)":"2px solid transparent",padding:"7px 14px",cursor:"pointer",color:et?"var(--ac)":"var(--tx2)",fontSize:13,fontWeight:et?500:400,fontFamily:"var(--font-body)",transition:"all .12s"},children:[q.title,q.badge&&(()=>{const dt={default:{bg:"var(--sf)",text:"var(--tx2)"},info:{bg:"rgba(59,130,246,0.15)",text:"rgb(59,130,246)"},success:{bg:"rgba(34,197,94,0.15)",text:"rgb(34,197,94)"},warning:{bg:"rgba(234,179,8,0.15)",text:"rgb(202,138,4)"},danger:{bg:"rgba(239,68,68,0.15)",text:"rgb(239,68,68)"}},St=dt[q.badge.variant||"default"]||dt.default;return s.jsx("span",{style:{fontSize:10,fontWeight:600,padding:"2px 6px",borderRadius:4,marginLeft:6,whiteSpace:"nowrap",background:St.bg,color:St.text},children:q.badge.text})})()]},q.id)})})]},x.section))}),Q&&J&&s.jsx("div",{style:{padding:"8px 16px",borderTop:"1px solid var(--bd)",display:"flex",gap:6},children:Q.versions.map(x=>s.jsxs("button",{onClick:()=>{const q=x===Q.current?"index":`${x}/index`;I(q)},style:{flex:1,padding:"3px 0",textAlign:"center",background:x===(Y||Q.current)?"var(--acD)":"var(--sf)",border:"1px solid var(--bd)",borderRadius:2,cursor:"pointer",color:x===(Y||Q.current)?"var(--ac)":"var(--tx2)",fontSize:11,fontFamily:"var(--font-code)",fontWeight:x===Q.current?600:400},children:[x,x===Q.current?" (latest)":""]},x))}),s.jsxs("div",{style:{padding:"12px 16px",borderTop:"1px solid var(--bd)",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[C==="auto"?s.jsx("button",{"aria-label":w?"Switch to light mode":"Switch to dark mode",onClick:()=>Z(x=>!x),style:{background:"none",border:"none",color:"var(--txM)",cursor:"pointer",display:"flex"},children:w?s.jsx(em,{}):s.jsx(tm,{})}):s.jsx("div",{}),s.jsxs("span",{style:{fontSize:11,color:"var(--txM)",letterSpacing:.2},children:["Built with ","♡"," by Tome"]}),s.jsx("span",{style:{fontFamily:"var(--font-code)",fontSize:10,color:"var(--txM)"},children:"v0.5.0"})]})]}),s.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",overflow:"hidden"},children:[tt!=null&&tt.Header?s.jsx(tt.Header,{config:u,navigation:h,currentPageId:d,onNavigate:I,mobile:J,sbOpen:m,setSbOpen:k,isDark:w,setDark:Z,versioning:Q,currentVersion:Y,i18n:H,currentLocale:U,onSearchOpen:()=>L(!0),basePath:lt}):s.jsxs("header",{style:{display:"flex",alignItems:"center",gap:J?8:12,padding:J?"8px 12px":"10px 24px",borderBottom:"1px solid var(--bd)",background:"var(--hdBg)",backdropFilter:"blur(12px)",maxWidth:"100vw",overflow:"visible",position:"relative",zIndex:200},children:[s.jsx("button",{"aria-label":m?"Close sidebar":"Open sidebar",onClick:()=>k(!m),style:{background:"none",border:"none",color:"var(--txM)",cursor:"pointer",display:"flex"},children:m?s.jsx(Jh,{}):s.jsx(Zh,{})}),J?s.jsx("span",{style:{fontSize:13,color:"var(--ac)",fontFamily:"var(--font-code)",flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:((mi=h.flatMap(x=>x.pages).find(x=>x.id===d))==null?void 0:mi.title)||""}):s.jsx("div",{style:{display:"flex",alignItems:"center",gap:8,fontFamily:"var(--font-code)",fontSize:11,color:"var(--txM)",letterSpacing:".03em",flex:1},children:h.map(x=>{const q=x.pages.find(et=>et.id===d);return q?s.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[s.jsx("span",{children:x.section}),s.jsx(Pd,{}),s.jsx("span",{style:{color:"var(--ac)"},children:q.title})]},x.section):null})}),u.topNav&&u.topNav.length>0&&!J&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12},children:[u.topNav.map(x=>{const q=x.href.startsWith("#")||lt&&x.href.startsWith(lt+"/"),et=!q;return s.jsxs("a",{href:q&&x.href.startsWith("#")?lt+"/"+x.href.slice(1):x.href,...et?{target:"_blank",rel:"noopener noreferrer"}:{},onClick:q?dt=>{dt.preventDefault();const St=x.href.startsWith("#")?x.href.slice(1):x.href.replace(new RegExp("^"+lt.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"/?"),"");I(St)}:void 0,style:{display:"flex",alignItems:"center",gap:4,color:"var(--txM)",textDecoration:"none",fontSize:12,fontFamily:"var(--font-body)",fontWeight:500,transition:"color .15s"},onMouseOver:dt=>dt.currentTarget.style.color="var(--ac)",onMouseOut:dt=>dt.currentTarget.style.color="var(--txM)",children:[x.label,et&&s.jsx(a0,{})]},x.label)}),s.jsx("span",{style:{width:1,height:16,background:"var(--bd)"}})]}),u.socialLinks&&u.socialLinks.length>0&&!J&&s.jsx("div",{style:{display:"flex",alignItems:"center",gap:8},children:u.socialLinks.map(x=>s.jsx("a",{href:x.url,target:"_blank",rel:"noopener noreferrer","aria-label":x.label||x.platform,"data-testid":`social-link-${x.platform}`,style:{display:"flex",alignItems:"center",justifyContent:"center",color:"var(--tx2)",cursor:"pointer",transition:"color .15s"},onMouseOver:q=>q.currentTarget.style.color="var(--tx)",onMouseOut:q=>q.currentTarget.style.color="var(--tx2)",children:s.jsx(i0,{platform:x.platform,customIcon:x.icon})},x.url))}),J&&C==="auto"&&s.jsx("button",{"aria-label":w?"Switch to light mode":"Switch to dark mode",onClick:()=>Z(x=>!x),style:{background:"none",border:"none",color:"var(--txM)",cursor:"pointer",display:"flex",flexShrink:0},children:w?s.jsx(em,{}):s.jsx(tm,{})}),Q&&!J&&s.jsxs("div",{style:{position:"relative"},children:[s.jsxs("button",{"data-testid":"version-switcher",onClick:()=>rt(x=>!x),style:{display:"flex",alignItems:"center",gap:6,background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:2,padding:"5px 10px",cursor:"pointer",color:"var(--tx2)",fontSize:12,fontFamily:"var(--font-code)"},children:[s.jsx(e0,{}),Y||Q.current,s.jsx(Vu,{})]}),it&&s.jsx("div",{"data-testid":"version-dropdown",style:{position:"absolute",top:"100%",right:0,marginTop:4,background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:2,boxShadow:"0 8px 32px rgba(0,0,0,0.2)",overflow:"hidden",zIndex:100,minWidth:120},children:Q.versions.map(x=>s.jsxs("button",{onClick:()=>{rt(!1);const q=x===Q.current?"index":`${x}/index`;I(q)},style:{display:"block",width:"100%",textAlign:"left",background:x===(Y||Q.current)?"var(--acD)":"none",border:"none",padding:"8px 14px",cursor:"pointer",color:x===(Y||Q.current)?"var(--ac)":"var(--tx2)",fontSize:12,fontFamily:"var(--font-code)",fontWeight:x===Q.current?600:400},children:[x,x===Q.current?" (latest)":""]},x))})]}),H&&H.locales.length>1&&!J&&s.jsxs("div",{style:{position:"relative"},children:[s.jsxs("button",{"data-testid":"language-switcher",onClick:()=>It(x=>!x),style:{display:"flex",alignItems:"center",gap:6,background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:2,padding:"5px 10px",cursor:"pointer",color:"var(--tx2)",fontSize:12,fontFamily:"var(--font-body)"},children:[s.jsx(n0,{}),((vl=H.localeNames)==null?void 0:vl[U||H.defaultLocale])||U||H.defaultLocale,s.jsx(Vu,{})]}),Et&&s.jsx("div",{"data-testid":"language-dropdown",style:{position:"absolute",top:"100%",right:0,marginTop:4,background:"var(--sf)",border:"1px solid var(--bd)",borderRadius:2,boxShadow:"0 8px 32px rgba(0,0,0,0.2)",overflow:"hidden",zIndex:100,minWidth:120},children:H.locales.map(x=>{var ce;const q=x===(U||H.defaultLocale),et=((ce=H.localeNames)==null?void 0:ce[x])||x,dt=U||H.defaultLocale;let St=d;dt!==H.defaultLocale&&d.startsWith(`${dt}/`)&&(St=d.slice(dt.length+1));const yt=x===H.defaultLocale?St:`${x}/${St}`;return s.jsx("button",{onClick:()=>{It(!1),I(yt)},style:{display:"block",width:"100%",textAlign:"left",background:q?"var(--acD)":"none",border:"none",padding:"8px 14px",cursor:"pointer",color:q?"var(--ac)":"var(--tx2)",fontSize:12,fontFamily:"var(--font-body)",fontWeight:q?600:400},children:et},x)})})]})]}),cl&&s.jsxs("div",{"data-testid":"old-version-banner",style:{display:"flex",alignItems:"center",justifyContent:"center",gap:8,background:"var(--acD)",borderBottom:"1px solid var(--bd)",padding:"8px 24px",fontSize:13,color:"var(--tx2)"},children:[s.jsxs("span",{children:["You're viewing docs for ",Y,"."]}),s.jsx("button",{onClick:()=>{I("index")},style:{background:"none",border:"none",color:"var(--ac)",cursor:"pointer",fontWeight:600,fontSize:13,fontFamily:"var(--font-body)",textDecoration:"underline"},children:"Switch to latest."})]}),s.jsxs("div",{ref:We,style:{flex:1,overflow:"auto",display:"flex"},children:[s.jsxs("main",{style:{flex:1,maxWidth:J?"100%":nt?1100:760,padding:J?"24px 16px 60px":"40px 48px 80px",margin:"0 auto",minWidth:0},children:[Ie.length>0&&s.jsx("nav",{"aria-label":"Breadcrumbs","data-testid":"breadcrumbs",style:{display:"flex",alignItems:"center",gap:6,fontSize:13,color:"var(--tx2)",marginBottom:8},children:Ie.map((x,q)=>s.jsxs(sm.Fragment,{children:[q>0&&s.jsx("span",{style:{color:"var(--tx2)",opacity:.5},children:"›"}),q{et.preventDefault();const dt=h.flatMap(St=>St.pages).find(St=>St.urlPath===x.href);dt&&I(dt.id)},style:{color:"var(--tx2)",textDecoration:"none",cursor:"pointer"},children:x.label}):s.jsx("span",{style:q===Ie.length-1?{color:"var(--tx)"}:void 0,children:x.label})]},q))}),s.jsx("h1",{style:{fontFamily:"var(--font-heading)",fontSize:J?26:38,fontWeight:400,fontStyle:"italic",lineHeight:1.15,marginBottom:8},children:M}),P&&s.jsx("div",{"data-testid":"draft-banner",style:{background:"#fef3c7",color:"#92400e",padding:"8px 16px",borderRadius:6,fontSize:13,marginBottom:16},children:"Draft — This page is only visible in development"}),D&&s.jsx("p",{style:{fontSize:16,color:"var(--tx2)",lineHeight:1.6,marginBottom:32},children:D}),s.jsx("div",{style:{borderTop:"1px solid var(--bd)",paddingTop:28},children:nt&&W?s.jsx(W,{manifest:nt,baseUrl:bt,showPlayground:Ot,playgroundAuth:jt}):K&&K.length>0?s.jsx(s0,{entries:K}):Tn?s.jsx("div",{className:"tome-content",children:s.jsx(Tn,{components:E||{}})}):s.jsx("div",{className:"tome-content",ref:Fn},d)}),tt!=null&&tt.PageFooter?s.jsx(tt.PageFooter,{editUrl:G,lastUpdated:R,currentPageId:d,prev:Fe,next:$e,onNavigate:I,mobile:J}):s.jsxs(s.Fragment,{children:[(G||R)&&s.jsxs("div",{style:{marginTop:40,display:"flex",flexDirection:J?"column":"row",alignItems:J?"flex-start":"center",justifyContent:"space-between",gap:J?8:16},children:[G&&s.jsx("div",{"data-testid":"edit-page-link",children:s.jsxs("a",{href:G,target:"_blank",rel:"noopener noreferrer",style:{display:"inline-flex",alignItems:"center",gap:6,color:"var(--txM)",textDecoration:"none",fontSize:13,fontFamily:"var(--font-body)",transition:"color .15s"},onMouseOver:x=>x.currentTarget.style.color="var(--ac)",onMouseOut:x=>x.currentTarget.style.color="var(--txM)",children:[s.jsx(Wh,{})," Edit this page on GitHub"]})}),R&&s.jsxs("div",{"data-testid":"last-updated",style:{fontSize:12,color:"var(--txM)",fontFamily:"var(--font-body)"},children:["Last updated ",Fh(R)]})]}),s.jsx("div",{style:{display:"flex",alignItems:"center",gap:12,marginTop:24,padding:"12px 0"},children:pa[d]?s.jsx("span",{style:{fontSize:13,color:"var(--txM)",fontFamily:"var(--font-body)"},children:"Thanks for your feedback!"}):s.jsxs(s.Fragment,{children:[s.jsx("span",{style:{fontSize:13,color:"var(--txM)",fontFamily:"var(--font-body)"},children:"Was this helpful?"}),s.jsx("button",{onClick:()=>{ha(x=>({...x,[d]:!0}));try{localStorage.setItem(`tome-feedback-${d}`,"up")}catch{}},style:{background:"none",border:"1px solid var(--bd)",borderRadius:2,padding:"4px 10px",cursor:"pointer",fontSize:13,color:"var(--txM)",transition:"border-color .15s"},children:"👍"}),s.jsx("button",{onClick:()=>{ha(x=>({...x,[d]:!0}));try{localStorage.setItem(`tome-feedback-${d}`,"down")}catch{}},style:{background:"none",border:"1px solid var(--bd)",borderRadius:2,padding:"4px 10px",cursor:"pointer",fontSize:13,color:"var(--txM)",transition:"border-color .15s"},children:"👎"})]})}),s.jsxs("div",{style:{display:"flex",flexDirection:J?"column":"row",justifyContent:"space-between",marginTop:16,paddingTop:24,borderTop:"1px solid var(--bd)",gap:J?12:16},children:[Fe?s.jsxs("button",{onClick:()=>I(Fe.id),style:{display:"flex",alignItems:"center",gap:8,background:"none",border:"1px solid var(--bd)",borderRadius:2,padding:"10px 16px",cursor:"pointer",color:"var(--tx2)",fontSize:13,fontFamily:"var(--font-body)",transition:"border-color .15s, color .15s"},children:[ft?s.jsx(am,{}):s.jsx(nm,{})," ",Fe.title]}):s.jsx("div",{}),$e?s.jsxs("button",{onClick:()=>I($e.id),style:{display:"flex",alignItems:"center",gap:8,background:"none",border:"1px solid var(--bd)",borderRadius:2,padding:"10px 16px",cursor:"pointer",color:"var(--tx2)",fontSize:13,fontFamily:"var(--font-body)",transition:"border-color .15s, color .15s"},children:[$e.title," ",ft?s.jsx(nm,{}):s.jsx(am,{})]}):s.jsx("div",{})]})]})]}),tt!=null&&tt.Toc?xa&&ye.length>=2&&va&&s.jsx(tt.Toc,{headings:ye,activeHeadingId:ue,onScrollToHeading:ci}):xa&&ye.length>=2&&va&&s.jsxs("aside",{"data-testid":"toc-sidebar",style:{width:200,padding:ft?"40px 0 40px 16px":"40px 16px 40px 0",position:"sticky",top:0,alignSelf:"flex-start",flexShrink:0},children:[s.jsx("div",{style:{fontSize:10,fontWeight:600,textTransform:"uppercase",letterSpacing:".1em",color:"var(--txM)",marginBottom:12,fontFamily:"var(--font-code)"},children:"On this page"}),s.jsx("nav",{"aria-label":"Table of contents",style:{[ft?"borderRight":"borderLeft"]:"1px solid var(--bd)",[ft?"paddingRight":"paddingLeft"]:0},children:ye.map((x,q)=>{const et=ue===x.id;return s.jsx("a",{href:`#${x.id}`,onClick:dt=>ci(dt,x.id),"data-testid":`toc-link-${x.id}`,style:{display:"block",fontSize:12,color:et?"var(--ac)":"var(--txM)",fontWeight:et?500:400,textDecoration:"none",padding:"4px 12px",[ft?"paddingRight":"paddingLeft"]:12+(x.depth-2)*12,lineHeight:1.4,transition:"color .15s, font-weight .15s",[ft?"borderRight":"borderLeft"]:et?"2px solid var(--ac)":"2px solid transparent",[ft?"marginRight":"marginLeft"]:-1},children:x.text},q)})})]})]})]})]}),(tt==null?void 0:tt.Footer)&&s.jsx(tt.Footer,{config:u,navigation:h,currentPageId:d,onNavigate:I}),((An=u.ai)==null?void 0:An.enabled)&&s.jsx(Xh,{provider:u.ai.provider||"anthropic",model:u.ai.model,apiKey:typeof __TOME_AI_API_KEY__<"u"&&__TOME_AI_API_KEY__?__TOME_AI_API_KEY__:void 0,context:(at==null?void 0:at.map(x=>`## ${x.title} +${x.content}`).join(` + +`))??ct.map(x=>`- ${x.title}${x.description?": "+x.description:""}`).join(` +`)}),Ut&&s.jsx("div",{onClick:()=>Ze(null),style:{position:"fixed",inset:0,zIndex:9999,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.7)",backdropFilter:"blur(8px)",cursor:"zoom-out"},children:s.jsx("img",{src:Ut,alt:"",style:{maxWidth:"90vw",maxHeight:"90vh",objectFit:"contain",borderRadius:4,boxShadow:"0 16px 64px rgba(0,0,0,0.4)"}})})]})}function c0({allPages:u,onNavigate:h,onClose:d,mobile:c}){const[v,E]=B.useState(""),[M,D]=B.useState([]),[z,y]=B.useState(0),[G,R]=B.useState(null),K=B.useRef(null),nt=B.useRef(void 0);B.useEffect(()=>{Ih().then(W=>R(!!W)),setTimeout(()=>{var W;return(W=K.current)==null?void 0:W.focus()},50)},[]);const bt=B.useCallback(W=>{if(!W.trim())return[];const I=W.toLowerCase();return u.filter(ct=>ct.title.toLowerCase().includes(I)||(ct.description||"").toLowerCase().includes(I)).slice(0,8).map(ct=>({id:ct.id,title:ct.title,excerpt:ct.description}))},[u]),Ot=B.useCallback(async W=>{var ct;if(!W.trim()){D([]),y(0);return}const I=ul;if(I)try{const Q=await I.search(W),Y=[];for(const H of Q.results.slice(0,8)){const U=await H.data(),lt=(U.url||"").replace(/^\//,"").replace(/\/index\.html$/,"").replace(/\.html$/,"")||"index";Y.push({id:lt,title:((ct=U.meta)==null?void 0:ct.title)||lt,excerpt:U.excerpt||void 0})}D(Y),y(0);return}catch{}D(bt(W)),y(0)},[bt]);B.useEffect(()=>(nt.current&&clearTimeout(nt.current),nt.current=setTimeout(()=>Ot(v),120),()=>{nt.current&&clearTimeout(nt.current)}),[v,Ot]);const jt=B.useCallback(W=>{W.key==="ArrowDown"?(W.preventDefault(),y(I=>Math.min(I+1,M.length-1))):W.key==="ArrowUp"?(W.preventDefault(),y(I=>Math.max(I-1,0))):W.key==="Enter"&&M.length>0&&(W.preventDefault(),h(M[z].id))},[M,z,h]);return s.jsx("div",{onClick:d,style:{position:"fixed",inset:0,zIndex:1e3,background:"rgba(0,0,0,0.55)",backdropFilter:"blur(6px)",display:"flex",alignItems:c?"stretch":"flex-start",justifyContent:"center",paddingTop:c?0:"12vh"},children:s.jsxs("div",{onClick:W=>W.stopPropagation(),style:{background:"var(--sf)",border:c?"none":"1px solid var(--bd)",borderRadius:c?0:2,width:"100%",maxWidth:c?"100%":520,boxShadow:c?"none":"0 24px 80px rgba(0,0,0,0.4)",overflow:"hidden",display:"flex",flexDirection:"column",...c?{height:"100%"}:{}},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,padding:"14px 18px",borderBottom:"1px solid var(--bd)"},children:[s.jsx(rm,{}),s.jsx("input",{ref:K,value:v,onChange:W=>E(W.target.value),onKeyDown:jt,placeholder:"Search documentation...",style:{flex:1,background:"none",border:"none",outline:"none",color:"var(--tx)",fontSize:15,fontFamily:"var(--font-body)"}}),s.jsx("kbd",{style:{fontFamily:"var(--font-code)",fontSize:10,color:"var(--txM)",background:"var(--cdBg)",padding:"2px 6px",borderRadius:2,border:"1px solid var(--bd)"},children:"ESC"})]}),M.length>0&&s.jsx("div",{style:{padding:6,maxHeight:c?"none":360,overflow:"auto",flex:c?1:void 0},children:M.map((W,I)=>s.jsxs("button",{onClick:()=>h(W.id),style:{display:"block",width:"100%",textAlign:"left",background:I===z?"var(--acD)":"none",border:"none",borderRadius:2,padding:"10px 14px",cursor:"pointer",color:"var(--tx)",fontFamily:"var(--font-body)"},onMouseEnter:()=>y(I),children:[s.jsx("div",{style:{fontWeight:500,fontSize:14,marginBottom:2},children:W.title}),W.excerpt&&s.jsx("div",{style:{fontSize:12,color:"var(--txM)",lineHeight:1.3},dangerouslySetInnerHTML:{__html:W.excerpt}})]},W.id+I))}),v&&!M.length&&s.jsx("div",{style:{padding:"32px 18px",textAlign:"center",color:"var(--txM)",fontSize:14},children:"No results found"}),G===!1&&v&&M.length>0&&s.jsx("div",{style:{padding:"6px 18px 10px",fontSize:11,color:"var(--txM)",textAlign:"center"},children:"Showing title matches. Build your site for full-text search."})]})})}function cm(u,h,d){let c=u;h&&c.startsWith(h)&&(c=c.slice(h.length));const v=c.replace(/^\//,"").replace(/\/index\.html$/,"").replace(/\.html$/,"").replace(/\/$/,"")||"index";return d.find(M=>M.id===v)?v:null}function f0(u,h,d){const c=d.find(v=>v.id===u);return c?h+c.urlPath:h+"/"+u}class d0 extends Error{constructor(h){super(`Page not found: ${h}`),this.code="PAGE_NOT_FOUND",this.name="PageNotFoundError"}}class m0 extends Error{constructor(h,d){super(`Failed to load page: ${h}`),this.code="PAGE_LOAD_ERROR",this.name="PageLoadError",d&&(this.cause=d)}}function p0(u,h){if(!u||!h)return;const{repo:d,branch:c="main",dir:v=""}=u,E=v?`${v.replace(/\/$/,"")}/`:"";return`https://github.com/${d}/edit/${c}/${E}${h}`}function h0(u,h,d,c,v){var D;const E=v(u,c,d);if(E)return E;const M=h.startsWith("#")?h.slice(1):h;return M&&d.some(z=>z.id===M)?M:((D=d[0])==null?void 0:D.id)||"index"}async function fm(u,h,d){const c=h.find(E=>E.id===u);let v;try{v=await d(u)}catch(E){throw new m0(u,E)}if(c!=null&&c.isMdx&&v.meta)return{isMdx:!0,component:v.default,frontmatter:v.meta.frontmatter,headings:v.meta.headings};if(!v.default)throw new d0(u);return v.isApiReference&&v.apiManifest?{isMdx:!1,isApiReference:!0,...v.default,apiManifest:v.apiManifest}:v.isChangelog&&v.changelogEntries?{isMdx:!1,...v.default,changelogEntries:v.changelogEntries}:{isMdx:!1,...v.default}}function g0(u,h){return(u==null?void 0:u.version)||void 0}const Jn={name:"Kit",logo:"/logo.jpg",favicon:"/logo.jpg",baseUrl:"https://go-kit.dev",theme:{preset:"cipher",accent:"#e03030",mode:"dark",fonts:{heading:"Space Grotesk",body:"Space Grotesk",code:"Source Code Pro"}},navigation:[{group:"Getting Started",pages:["index","installation","quick-start"]},{group:"Configuration",pages:["configuration","providers"]},{group:"CLI Reference",pages:["cli/flags","cli/commands"]},{group:"Extensions",pages:["extensions/overview","extensions/capabilities","extensions/examples","extensions/loading"]},{group:"Sessions",pages:["sessions"]},{group:"Go SDK",pages:["sdk/overview","sdk/options","sdk/callbacks","sdk/sessions"]},{group:"Advanced",pages:["advanced/subagents","advanced/json-output","advanced/testing"]},{group:"Development",pages:["development"]}],search:{provider:"local"},toc:{enabled:!0,depth:3},math:!1,strictLinks:!1,lastUpdated:!0,redirects:[],socialLinks:[{platform:"github",url:"https://github.com/mark3labs/kit"},{platform:"discord",url:"https://discord.gg/RqSS2NQVsY"}]},Wn=[{id:"advanced/json-output",filePath:"advanced/json-output.md",urlPath:"/advanced/json-output",frontmatter:{title:"JSON Output",description:"Machine-readable JSON output for scripting and automation.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"advanced/subagents",filePath:"advanced/subagents.md",urlPath:"/advanced/subagents",frontmatter:{title:"Subagents",description:"Multi-agent orchestration with Kit subagents.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"advanced/testing",filePath:"advanced/testing.md",urlPath:"/advanced/testing",frontmatter:{title:"Testing with tmux",description:"Test Kit's TUI non-interactively using tmux.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"cli/commands",filePath:"cli/commands.md",urlPath:"/cli/commands",frontmatter:{title:"Commands",description:"Complete reference for all Kit CLI subcommands.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"cli/flags",filePath:"cli/flags.md",urlPath:"/cli/flags",frontmatter:{title:"Global Flags",description:"Complete reference for all Kit CLI flags.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"configuration",filePath:"configuration.md",urlPath:"/configuration",frontmatter:{title:"Configuration",description:"Configure Kit using config files, environment variables, and CLI flags.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"development",filePath:"development.md",urlPath:"/development",frontmatter:{title:"Development",description:"Build, test, and contribute to Kit.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"extensions/capabilities",filePath:"extensions/capabilities.md",urlPath:"/extensions/capabilities",frontmatter:{title:"Capabilities",description:"All extension capabilities — lifecycle events, tools, commands, widgets, and more.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"extensions/examples",filePath:"extensions/examples.md",urlPath:"/extensions/examples",frontmatter:{title:"Examples",description:"Catalog of example extensions included with Kit.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"extensions/loading",filePath:"extensions/loading.md",urlPath:"/extensions/loading",frontmatter:{title:"Loading Extensions",description:"How Kit discovers and loads extensions.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"extensions/overview",filePath:"extensions/overview.md",urlPath:"/extensions/overview",frontmatter:{title:"Extension System",description:"Overview of Kit's Go-based extension system.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"index",filePath:"index.md",urlPath:"/",frontmatter:{title:"Kit",description:"Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"installation",filePath:"installation.md",urlPath:"/installation",frontmatter:{title:"Installation",description:"Install Kit using npm, Go, or build from source.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"providers",filePath:"providers.md",urlPath:"/providers",frontmatter:{title:"Providers",description:"Supported LLM providers and model configuration.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"quick-start",filePath:"quick-start.md",urlPath:"/quick-start",frontmatter:{title:"Quick Start",description:"Get up and running with Kit in minutes.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"sdk/callbacks",filePath:"sdk/callbacks.md",urlPath:"/sdk/callbacks",frontmatter:{title:"Callbacks",description:"Monitor tool calls and streaming output with the Kit Go SDK.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"sdk/options",filePath:"sdk/options.md",urlPath:"/sdk/options",frontmatter:{title:"SDK Options",description:"Configuration options for the Kit Go SDK.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"sdk/overview",filePath:"sdk/overview.md",urlPath:"/sdk/overview",frontmatter:{title:"Go SDK",description:"Embed Kit in your Go applications.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"sdk/sessions",filePath:"sdk/sessions.md",urlPath:"/sdk/sessions",frontmatter:{title:"SDK Sessions",description:"Session management in the Kit Go SDK.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"},{id:"sessions",filePath:"sessions.md",urlPath:"/sessions",frontmatter:{title:"Session Management",description:"How Kit persists and manages conversation sessions.",hidden:!1,draft:!1},isMdx:!1,lastUpdated:"2026-03-19T16:42:04+03:00"}],v0=[{section:"Getting Started",pages:[{title:"Kit",id:"index",urlPath:"/"},{title:"Installation",id:"installation",urlPath:"/installation"},{title:"Quick Start",id:"quick-start",urlPath:"/quick-start"}]},{section:"Configuration",pages:[{title:"Configuration",id:"configuration",urlPath:"/configuration"},{title:"Providers",id:"providers",urlPath:"/providers"}]},{section:"CLI Reference",pages:[{title:"Global Flags",id:"cli/flags",urlPath:"/cli/flags"},{title:"Commands",id:"cli/commands",urlPath:"/cli/commands"}]},{section:"Extensions",pages:[{title:"Extension System",id:"extensions/overview",urlPath:"/extensions/overview"},{title:"Capabilities",id:"extensions/capabilities",urlPath:"/extensions/capabilities"},{title:"Examples",id:"extensions/examples",urlPath:"/extensions/examples"},{title:"Loading Extensions",id:"extensions/loading",urlPath:"/extensions/loading"}]},{section:"Sessions",pages:[{title:"Session Management",id:"sessions",urlPath:"/sessions"}]},{section:"Go SDK",pages:[{title:"Go SDK",id:"sdk/overview",urlPath:"/sdk/overview"},{title:"SDK Options",id:"sdk/options",urlPath:"/sdk/options"},{title:"Callbacks",id:"sdk/callbacks",urlPath:"/sdk/callbacks"},{title:"SDK Sessions",id:"sdk/sessions",urlPath:"/sdk/sessions"}]},{section:"Advanced",pages:[{title:"Subagents",id:"advanced/subagents",urlPath:"/advanced/subagents"},{title:"JSON Output",id:"advanced/json-output",urlPath:"/advanced/json-output"},{title:"Testing with tmux",id:"advanced/testing",urlPath:"/advanced/testing"}]},{section:"Development",pages:[{title:"Development",id:"development",urlPath:"/development"}]}],Zu=null,y0={"advanced/json-output":()=>Xt(()=>import("./json-output-B1QZabVS.js"),[]),"advanced/subagents":()=>Xt(()=>import("./subagents-ChkZbdDR.js"),[]),"advanced/testing":()=>Xt(()=>import("./testing-COLNxuKj.js"),[]),"cli/commands":()=>Xt(()=>import("./commands-B2onU7kX.js"),[]),"cli/flags":()=>Xt(()=>import("./flags-CkTF-Pw-.js"),[]),configuration:()=>Xt(()=>import("./configuration-BU6tST5r.js"),[]),development:()=>Xt(()=>import("./development-BTUHn6x2.js"),[]),"extensions/capabilities":()=>Xt(()=>import("./capabilities-hnq2TbFu.js"),[]),"extensions/examples":()=>Xt(()=>import("./examples-C-0Ua9md.js"),[]),"extensions/loading":()=>Xt(()=>import("./loading-CfdMbwrl.js"),[]),"extensions/overview":()=>Xt(()=>import("./overview-DNz93_Eg.js"),[]),index:()=>Xt(()=>import("./index-CGDazwHL.js"),[]),installation:()=>Xt(()=>import("./installation-DaBrcZPn.js"),[]),providers:()=>Xt(()=>import("./providers-B05lw6S_.js"),[]),"quick-start":()=>Xt(()=>import("./quick-start-B51YvXk3.js"),[]),"sdk/callbacks":()=>Xt(()=>import("./callbacks-DY5vOJ-1.js"),[]),"sdk/options":()=>Xt(()=>import("./options-DhBmR6ye.js"),[]),"sdk/overview":()=>Xt(()=>import("./overview-DbvqPNef.js"),[]),"sdk/sessions":()=>Xt(()=>import("./sessions-X-l1qojs.js"),[]),sessions:()=>Xt(()=>import("./sessions-BM7WkgkF.js"),[])};function dm(u){const h=y0[u];if(!h)throw new Error("Unknown page: "+u);return h()}const x0=[{id:"advanced/json-output",title:"JSON Output",content:` +# JSON Output + +Use the \`--json\` flag to get structured output for scripting and automation: + +\`\`\`bash +kit "Explain main.go" --json --quiet --no-session +\`\`\` + +## Response format + +\`\`\`json +{ + "response": "Final assistant response text", + "model": "anthropic/claude-haiku-3-5-20241022", + "stop_reason": "end_turn", + "session_id": "a1b2c3d4e5f6", + "usage": { + "input_tokens": 1024, + "output_tokens": 512, + "total_tokens": 1536, + "cache_read_tokens": 0, + "cache_creation_tokens": 0 + }, + "messages": [ + { + "role": "assistant", + "parts": [ + {"type": "text", "data": "..."}, + {"type": "tool_call", "data": {"name": "...", "args": "..."}}, + {"type": "tool_result", "data": {"name": "...", "result": "..."}} + ] + } + ] +} +\`\`\` + +## Fields + +### Top-level + +| Field | Type | Description | +|-------|------|-------------| +| \`response\` | string | The final assistant response text | +| \`model\` | string | The model that was used | +| \`stop_reason\` | string | Why the model stopped (e.g., \`end_turn\`) | +| \`session_id\` | string | Session identifier (omitted in \`--no-session\` mode) | +| \`usage\` | object | Token usage statistics | +| \`messages\` | array | Full conversation history | + +### Usage + +| Field | Type | Description | +|-------|------|-------------| +| \`input_tokens\` | int | Tokens sent to the model | +| \`output_tokens\` | int | Tokens generated by the model | +| \`total_tokens\` | int | Sum of input and output tokens | +| \`cache_read_tokens\` | int | Tokens read from prompt cache | +| \`cache_creation_tokens\` | int | Tokens written to prompt cache | + +### Message parts + +Each message contains a \`parts\` array with typed entries: + +| Type | Description | +|------|-------------| +| \`text\` | Assistant text content | +| \`tool_call\` | Tool invocation with name and args | +| \`tool_result\` | Tool execution result | +| \`reasoning\` | Extended thinking content | +| \`finish\` | End-of-turn marker | + +## Parsing in scripts + +### bash + jq + +\`\`\`bash +result=$(kit "Count files" --json --quiet --no-session) +response=$(echo "$result" | jq -r '.response') +tokens=$(echo "$result" | jq '.usage.total_tokens') +\`\`\` + +### Go SDK + +For Go programs, use the SDK's \`PromptResult\` method instead of parsing JSON: + +\`\`\`go +result, err := host.PromptResult(ctx, "Count files") +fmt.Println(result.Response) +fmt.Println(result.Usage.TotalTokens) +\`\`\` +`},{id:"advanced/subagents",title:"Subagents",content:` +# Subagents + +Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents. + +## Subprocess pattern + +Spawn Kit as a subprocess for isolated agent execution: + +\`\`\`bash +kit "Analyze codebase" \\ + --json \\ + --no-session \\ + --no-extensions \\ + --quiet \\ + --model anthropic/claude-haiku-3-5-20241022 +\`\`\` + +Key flags for subprocess usage: + +| Flag | Purpose | +|------|---------| +| \`--quiet\` | Stdout only, no TUI | +| \`--no-session\` | Ephemeral, no persistence | +| \`--no-extensions\` | Prevent recursive extension loading | +| \`--json\` | Machine-readable output | +| \`--system-prompt\` | Custom system prompt (string or file path) | + +Positional arguments are the prompt. \`@file\` arguments attach file content as context. + +## Built-in spawn_subagent tool + +Kit includes a built-in \`spawn_subagent\` tool that the LLM can use to delegate tasks to independent child agents: + +\`\`\` +spawn_subagent( + task: "Analyze the test files and summarize coverage", + model: "anthropic/claude-haiku-3-5-20241022", // optional + system_prompt: "You are a test analysis expert.", // optional + timeout_seconds: 300 // optional, max 1800 +) +\`\`\` + +Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel. + +## Extension subagents + +Extensions can spawn subagents programmatically: + +\`\`\`go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Review this code for security issues", + Model: "anthropic/claude-sonnet-4-5-20250929", + SystemPrompt: "You are a security auditor.", +}) +\`\`\` + +## Go SDK subagents + +The SDK provides in-process subagent spawning: + +\`\`\`go +result, err := host.Subagent(ctx, kit.SubagentConfig{ + Task: "Summarize the changes in this PR", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a code reviewer.", + Timeout: 5 * time.Minute, +}) +\`\`\` +`},{id:"advanced/testing",title:"Testing with tmux",content:` +# Testing with tmux + +Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development. + +## Basic pattern + +\`\`\`bash +# Start Kit in a detached tmux session +tmux new-session -d -s kittest -x 120 -y 40 \\ + "output/kit -e ext.go --no-session 2>kit_stderr.log" + +# Wait for startup +sleep 3 + +# Capture the current screen +tmux capture-pane -t kittest -p + +# Send input +tmux send-keys -t kittest '/command' Enter + +# Wait for response +sleep 2 + +# Capture updated screen +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +\`\`\` + +## Testing extensions + +When testing extensions, the pattern is: + +1. Build Kit with your changes +2. Start Kit in tmux with the extension loaded +3. Send slash commands or prompts +4. Capture and verify the screen output +5. Check stderr logs for errors + +\`\`\`bash +# Build first +go build -o output/kit ./cmd/kit + +# Start with extension +tmux new-session -d -s kittest -x 120 -y 40 \\ + "output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log" + +sleep 3 + +# Verify widget appears in screen +tmux capture-pane -t kittest -p | grep "Status" + +# Send a slash command +tmux send-keys -t kittest '/stats' Enter +sleep 1 +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +\`\`\` + +## Tips + +- Use \`-x\` and \`-y\` to set consistent terminal dimensions +- Redirect stderr to a log file (\`2>kit.log\`) for debugging +- Use \`--no-session\` to avoid creating session files during tests +- Add sufficient \`sleep\` between commands for the TUI to render +- Use \`grep\` on captured pane output to verify specific content +`},{id:"cli/commands",title:"Commands",content:` +# Commands + +## Authentication + +For OAuth-enabled providers like Anthropic. + +\`\`\`bash +kit auth login [provider] # Start OAuth flow (e.g., anthropic) +kit auth logout [provider] # Remove credentials for provider +kit auth status # Check authentication status +\`\`\` + +## Model database + +Manage the local model database that maps provider names to API configurations. + +\`\`\`bash +kit models [provider] # List available models (optionally filter by provider) +kit models --all # Show all providers (not just Fantasy-compatible) +kit update-models [source] # Update model database +\`\`\` + +The \`update-models\` command accepts an optional source argument: +- *(none)* — update from [models.dev](https://models.dev) +- A URL — fetch from a custom endpoint +- A file path — load from a local file +- \`embedded\` — reset to the bundled database + +## Extension management + +\`\`\`bash +kit extensions list # List discovered extensions +kit extensions validate # Validate extension files +kit extensions init # Generate example extension template +\`\`\` + +### Installing extensions from git + +\`\`\`bash +kit install # Install extensions from git repositories +kit install -l # Install to project-local .kit/git/ directory +kit install -u # Update an already-installed package +kit install --uninstall # Remove an installed package +kit install --all # Install all extensions without prompting +\`\`\` + +## Skills + +\`\`\`bash +kit skill # Install the Kit extensions skill via skills.sh +\`\`\` + +## ACP server + +Run Kit as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout. + +\`\`\`bash +kit acp # Start as ACP agent +kit acp --debug # With debug logging to stderr +\`\`\` +`},{id:"cli/flags",title:"Global Flags",content:"\n# Global Flags\n\nAll flags can be passed to the root `kit` command.\n\n## Model and provider\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--model` | `-m` | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) |\n| `--provider-api-key` | — | — | API key for the provider |\n| `--provider-url` | — | — | Base URL for provider API |\n| `--tls-skip-verify` | — | `false` | Skip TLS certificate verification |\n\n## Session management\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--session` | `-s` | — | Open specific JSONL session file |\n| `--continue` | `-c` | `false` | Resume most recent session for current directory |\n| `--resume` | `-r` | `false` | Interactive session picker |\n| `--no-session` | — | `false` | Ephemeral mode, no persistence |\n\n## Behavior\n\nThese flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode.\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--quiet` | — | `false` | Suppress all output (non-interactive only) |\n| `--json` | — | `false` | Output response as JSON (non-interactive only) |\n| `--no-exit` | — | `false` | Enter interactive mode after prompt completes |\n| `--max-steps` | — | `0` | Maximum agent steps (0 for unlimited) |\n| `--stream` | — | `true` | Enable streaming output |\n| `--compact` | — | `false` | Enable compact output mode |\n| `--auto-compact` | — | `false` | Auto-compact conversation near context limit |\n\n## Extensions\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--extension` | `-e` | — | Load additional extension file(s) (repeatable) |\n| `--no-extensions` | — | `false` | Disable all extensions |\n\n## Generation parameters\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--max-tokens` | — | `4096` | Maximum tokens in response |\n| `--temperature` | — | `0.7` | Randomness 0.0–1.0 |\n| `--top-p` | — | `0.95` | Nucleus sampling 0.0–1.0 |\n| `--top-k` | — | `40` | Limit top K tokens |\n| `--stop-sequences` | — | — | Custom stop sequences (comma-separated) |\n| `--thinking-level` | — | `off` | Extended thinking level: off, minimal, low, medium, high |\n\n## System\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--config` | — | `~/.kit.yml` | Config file path |\n| `--system-prompt` | — | — | System prompt text or file path |\n| `--debug` | — | `false` | Enable debug logging |\n"},{id:"configuration",title:"Configuration",content:'\n# Configuration\n\nKit looks for configuration in the following locations, in order of priority:\n\n1. CLI flags\n2. Environment variables (with `KIT_` prefix)\n3. `./.kit.yml` / `./.kit.yaml` / `./.kit.json` (project-local)\n4. `~/.kit.yml` / `~/.kit.yaml` / `~/.kit.json` (global)\n\n## Basic configuration\n\nCreate `~/.kit.yml`:\n\n```yaml\nmodel: anthropic/claude-sonnet-4-5-20250929\nmax-tokens: 4096\ntemperature: 0.7\nstream: true\n```\n\n## All configuration keys\n\n| Key | Type | Default | Description |\n|-----|------|---------|-------------|\n| `model` | string | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) |\n| `max-tokens` | int | `4096` | Maximum tokens in response |\n| `temperature` | float | `0.7` | Randomness 0.0–1.0 |\n| `top-p` | float | `0.95` | Nucleus sampling 0.0–1.0 |\n| `top-k` | int | `40` | Limit top K tokens |\n| `stream` | bool | `true` | Enable streaming output |\n| `debug` | bool | `false` | Enable debug logging |\n| `compact` | bool | `false` | Enable compact output mode |\n| `system-prompt` | string | — | System prompt text or file path |\n| `max-steps` | int | `0` | Maximum agent steps (0 = unlimited) |\n| `thinking-level` | string | `off` | Extended thinking: off, minimal, low, medium, high |\n| `provider-api-key` | string | — | API key for the provider |\n| `provider-url` | string | — | Base URL for provider API |\n| `tls-skip-verify` | bool | `false` | Skip TLS certificate verification |\n| `stop-sequences` | list | — | Custom stop sequences |\n| `theme` | string | — | UI theme |\n| `markdown-theme` | string | — | Markdown rendering theme |\n\n## Environment variables\n\nAny configuration key can be set via environment variable with the `KIT_` prefix. Hyphens become underscores:\n\n```bash\nexport KIT_MODEL="openai/gpt-4o"\nexport KIT_MAX_TOKENS="8192"\nexport KIT_TEMPERATURE="0.5"\n```\n\nProvider API keys use their own environment variables:\n\n```bash\nexport ANTHROPIC_API_KEY="sk-..."\nexport OPENAI_API_KEY="sk-..."\nexport GOOGLE_API_KEY="..."\n```\n\n## MCP server configuration\n\nAdd external MCP servers to your `.kit.yml`:\n\n```yaml\nmcpServers:\n filesystem:\n type: local\n command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]\n environment:\n LOG_LEVEL: "info"\n allowedTools: ["read_file", "write_file"]\n excludedTools: ["delete_file"]\n\n search:\n type: remote\n url: "https://mcp.example.com/search"\n```\n\n### MCP server fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | string | `local` (stdio) or `remote` (streamable HTTP) |\n| `command` | list | Command and args for local servers |\n| `environment` | map | Environment variables for the server process |\n| `url` | string | URL for remote servers |\n| `allowedTools` | list | Whitelist of tool names to expose |\n| `excludedTools` | list | Blacklist of tool names to hide |\n\nA legacy format with `transport`, `args`, `env`, and `headers` fields is also supported.\n'},{id:"development",title:"Development",content:` +# Development + +## Build and test + +\`\`\`bash +# Build +go build -o output/kit ./cmd/kit + +# Run all tests +go test -race ./... + +# Run a specific test +go test -race ./cmd -run TestScriptExecution + +# Lint +go vet ./... + +# Format +go fmt ./... +\`\`\` + +## Project structure + +\`\`\` +cmd/kit/ - CLI entry point (main.go) +cmd/ - CLI command implementations (root, auth, models, etc.) +pkg/kit/ - Go SDK for embedding Kit +internal/app/ - Application orchestrator (agent loop, message store, queue) +internal/agent/ - Agent execution and tool dispatch +internal/auth/ - OAuth authentication and credential storage +internal/acpserver/ - ACP (Agent Client Protocol) server +internal/clipboard/ - Cross-platform clipboard operations +internal/compaction/ - Conversation compaction and summarization +internal/config/ - Configuration management +internal/core/ - Built-in tools (bash, read, write, edit, grep, find, ls) +internal/extensions/ - Yaegi extension system +internal/kitsetup/ - Initial setup wizard +internal/message/ - Message content types and structured content blocks +internal/models/ - Provider and model management +internal/session/ - Session persistence (tree-based JSONL) +internal/skills/ - Skill loading and system prompt composition +internal/tools/ - MCP tool integration +internal/ui/ - Bubble Tea TUI components +examples/extensions/ - Example extension files +npm/ - NPM package wrapper for distribution +\`\`\` + +## Architecture overview + +Kit is built around a few key architectural patterns: + +### Multi-provider LLM support + +The \`llm.Provider\` interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API. + +### MCP client-server model + +External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in \`.kit.yml\`. + +### Extension system + +Extensions are Go source files interpreted at runtime by Yaegi. The \`internal/extensions/\` package manages loading, symbol export, and lifecycle dispatch. See the [Extension System](/extensions/overview) docs for details. + +### TUI architecture + +The interactive terminal UI is built with [Bubble Tea v2](https://github.com/charmbracelet/bubbletea), using a parent-child model where \`AppModel\` manages child components (\`InputComponent\`, \`StreamComponent\`, etc.). + +### Decoupling pattern + +\`cmd/root.go\` contains converter functions (e.g., \`widgetProviderForUI()\`) that bridge \`internal/extensions/\` types to \`internal/ui/\` types. The UI never imports the extensions package directly. + +## Contributing + +Contributions are welcome! Please see the [contribution guide](https://github.com/mark3labs/kit/blob/master/contribute/contribute.md) for guidelines. + +## Community + +- [Discord](https://discord.gg/RqSS2NQVsY) +- [GitHub Issues](https://github.com/mark3labs/kit/issues) +`},{id:"extensions/capabilities",title:"Capabilities",content:` +# Extension Capabilities + +## Lifecycle events + +Extensions can hook into 18 lifecycle events: + +| Event | Description | +|-------|-------------| +| \`OnSessionStart\` | Session initialized | +| \`OnSessionShutdown\` | Session ending | +| \`OnBeforeAgentStart\` | Before the agent loop begins | +| \`OnAgentStart\` | Agent loop started | +| \`OnAgentEnd\` | Agent loop completed | +| \`OnToolCall\` | Tool call requested by the model | +| \`OnToolExecutionStart\` | Tool execution beginning | +| \`OnToolExecutionEnd\` | Tool execution completed | +| \`OnToolResult\` | Tool result returned | +| \`OnInput\` | User input received | +| \`OnMessageStart\` | Assistant message started | +| \`OnMessageUpdate\` | Streaming text chunk received | +| \`OnMessageEnd\` | Assistant message completed | +| \`OnModelChange\` | Model switched | +| \`OnContextPrepare\` | Context being assembled for the model | +| \`OnBeforeFork\` | Before forking a conversation branch | +| \`OnBeforeSessionSwitch\` | Before switching sessions | +| \`OnBeforeCompact\` | Before conversation compaction | + +### Example + +\`\`\`go +api.OnToolCall(func(event ext.ToolCallEvent, ctx ext.Context) { + ctx.PrintInfo("Calling tool: " + event.Name) +}) + +api.OnAgentEnd(func(_ ext.AgentEndEvent, ctx ext.Context) { + ctx.PrintInfo("Agent finished") +}) +\`\`\` + +## Tools + +Register custom tools that the LLM can invoke: + +\`\`\`go +api.RegisterTool(ext.ToolDef{ + Name: "weather", + Description: "Get current weather for a location", + Parameters: map[string]ext.ParameterDef{ + "city": {Type: "string", Description: "City name", Required: true}, + }, + Handler: func(ctx ext.Context, params map[string]any) (string, error) { + city := params["city"].(string) + return "Sunny, 72°F in " + city, nil + }, +}) +\`\`\` + +## Commands + +Register slash commands that users can invoke directly: + +\`\`\`go +api.RegisterCommand(ext.CommandDef{ + Name: "stats", + Description: "Show context statistics", + Handler: func(ctx ext.Context, args string) { + stats := ctx.GetContextStats() + ctx.PrintInfo(fmt.Sprintf("Tokens: %d", stats.TotalTokens)) + }, +}) +\`\`\` + +## Widgets + +Add persistent status displays above or below the input area: + +\`\`\`go +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 1,234"}, +}) + +// Update later +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 2,456"}, +}) + +// Remove +ctx.RemoveWidget("token-count") +\`\`\` + +## Headers and footers + +Persistent content above and below the conversation: + +\`\`\`go +ctx.SetHeader(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Project: my-app | Branch: main"}, +}) + +ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Plan Mode (read-only)"}, +}) +\`\`\` + +## Status bar + +Custom status bar entries: + +\`\`\`go +ctx.SetStatus("mode", "Planning") +ctx.RemoveStatus("mode") +\`\`\` + +## Shortcuts + +Global keyboard shortcuts: + +\`\`\`go +api.RegisterShortcut(ext.ShortcutDef{ + Key: "ctrl+t", + Description: "Toggle plan mode", +}, func(ctx ext.Context) { + // handle shortcut +}) +\`\`\` + +## Overlays + +Modal dialogs with markdown content: + +\`\`\`go +ctx.ShowOverlay(ext.OverlayConfig{ + Title: "Help", + Content: "# Keyboard Shortcuts\\n\\n- **ctrl+t** — Toggle plan mode\\n- **ctrl+s** — Save session", +}) +\`\`\` + +## Tool renderers + +Customize how specific tool calls are displayed in the TUI: + +\`\`\`go +api.RegisterToolRenderer(ext.ToolRenderConfig{ + ToolName: "bash", + Render: func(name, args, result string, isError bool) string { + return "$ " + args + "\\n" + result + }, +}) +\`\`\` + +## Message renderers + +Custom rendering for assistant messages: + +\`\`\`go +api.RegisterMessageRenderer(ext.MessageRendererConfig{ + Name: "custom", + Render: func(content string) string { + return ">> " + content + }, +}) +\`\`\` + +## Editor interceptors + +Handle key events and wrap the editor's rendering: + +\`\`\`go +ctx.SetEditor(ext.EditorConfig{ + HandleKey: func(key, text string) ext.EditorKeyAction { + if key == "escape" { + return ext.EditorKeyAction{Handled: true} + } + return ext.EditorKeyAction{Handled: false} + }, +}) +\`\`\` + +## Interactive prompts + +Select, confirm, input, and multi-select dialogs: + +\`\`\`go +// Single select +response := ctx.PromptSelect(ext.PromptSelectConfig{ + Title: "Choose a model", + Options: []string{"claude-sonnet", "gpt-4o", "llama3"}, +}) + +// Confirm +confirmed := ctx.PromptConfirm(ext.PromptConfirmConfig{ + Title: "Delete this file?", +}) + +// Text input +name := ctx.PromptInput(ext.PromptInputConfig{ + Title: "Enter project name", + Placeholder: "my-project", +}) +\`\`\` + +## Options + +Register configurable extension options: + +\`\`\`go +api.RegisterOption(ext.OptionDef{ + Name: "auto-commit", + Description: "Automatically commit on shutdown", + DefaultValue: "false", +}) +\`\`\` + +## Subagents + +Spawn in-process child Kit instances: + +\`\`\`go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Analyze the test files and summarize coverage", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a test analysis expert.", +}) +\`\`\` + +## LLM completion + +Make direct model calls without going through the agent loop: + +\`\`\`go +response := ctx.Complete(ext.CompleteRequest{ + Prompt: "Summarize this in one sentence: " + content, +}) +\`\`\` + +## Custom events + +Inter-extension communication: + +\`\`\`go +// Emit +ctx.EmitCustomEvent("my-extension:data-ready", payload) + +// Listen +api.OnCustomEvent("my-extension:data-ready", func(data any, ctx ext.Context) { + // handle event +}) +\`\`\` +`},{id:"extensions/examples",title:"Examples",content:` +# Extension Examples + +Kit ships with a rich set of example extensions in the \`examples/extensions/\` directory. These serve as both documentation and starting points for your own extensions. + +## UI and display + +| Extension | Description | +|-----------|-------------| +| \`minimal.go\` | Clean UI with custom footer | +| \`branded-output.go\` | Branded output rendering | +| \`header-footer-demo.go\` | Custom headers and footers | +| \`widget-status.go\` | Persistent status widgets | +| \`overlay-demo.go\` | Modal dialogs | +| \`tool-renderer-demo.go\` | Custom tool call rendering | +| \`custom-editor-demo.go\` | Vim-like modal editor | +| \`pirate.go\` | Pirate-themed personality | + +## Workflow and automation + +| Extension | Description | +|-----------|-------------| +| \`auto-commit.go\` | Auto-commit changes on shutdown | +| \`plan-mode.go\` | Read-only planning mode | +| \`permission-gate.go\` | Permission gating for destructive tools | +| \`confirm-destructive.go\` | Confirm destructive operations | +| \`protected-paths.go\` | Path protection for sensitive files | +| \`project-rules.go\` | Project-specific rules injection | +| \`compact-notify.go\` | Notification on conversation compaction | + +## Interactive features + +| Extension | Description | +|-----------|-------------| +| \`prompt-demo.go\` | Interactive prompts (select/confirm/input) | +| \`bookmark.go\` | Bookmark conversations | +| \`inline-bash.go\` | Inline bash execution | +| \`interactive-shell.go\` | Interactive shell integration | +| \`notify.go\` | Desktop notifications | + +## Agent and context + +| Extension | Description | +|-----------|-------------| +| \`tool-logger.go\` | Log all tool calls | +| \`context-inject.go\` | Inject context into conversations | +| \`summarize.go\` | Conversation summarization | +| \`lsp-diagnostics.go\` | LSP diagnostic integration | + +## Multi-agent + +| Extension | Description | +|-----------|-------------| +| \`kit-kit.go\` | Kit-in-Kit sub-agent spawning | +| \`subagent-widget.go\` | Multi-agent orchestration with status widget | +| \`subagent-test.go\` | Subagent testing utilities | + +## Development + +| Extension | Description | +|-----------|-------------| +| \`dev-reload.go\` | Development live-reload | + +## Subdirectory extensions + +| Directory | Description | +|-----------|-------------| +| \`kit-kit-agents/\` | Multi-agent orchestration example | +| \`kit-telegram/\` | Telegram bot integration | +| \`status-tools/\` | Status bar tool examples | +`},{id:"extensions/loading",title:"Loading Extensions",content:` +# Loading Extensions + +## Auto-discovery + +Kit automatically discovers and loads extensions from these paths, in order: + +| Path | Scope | +|------|-------| +| \`~/.config/kit/extensions/*.go\` | Global single files | +| \`~/.config/kit/extensions/*/main.go\` | Global subdirectory extensions | +| \`.kit/extensions/*.go\` | Project-local single files | +| \`.kit/extensions/*/main.go\` | Project-local subdirectory extensions | +| \`~/.local/share/kit/git/\` | Global git-installed packages | +| \`.kit/git/\` | Project-local git-installed packages | + +## Explicit loading + +Load extensions by path using the \`-e\` flag: + +\`\`\`bash +kit -e path/to/extension.go +\`\`\` + +Load multiple extensions: + +\`\`\`bash +kit -e ext1.go -e ext2.go +\`\`\` + +## Disabling extensions + +Disable all auto-discovered extensions: + +\`\`\`bash +kit --no-extensions +\`\`\` + +You can combine \`--no-extensions\` with \`-e\` to load only specific extensions: + +\`\`\`bash +kit --no-extensions -e my-extension.go +\`\`\` + +## Installing from git + +Install extensions from git repositories using \`kit install\`: + +\`\`\`bash +# Install globally (to ~/.local/share/kit/git/) +kit install https://github.com/user/my-kit-extension.git + +# Install project-locally (to .kit/git/) +kit install -l https://github.com/user/my-kit-extension.git + +# Update an installed package +kit install -u https://github.com/user/my-kit-extension.git + +# Remove +kit install --uninstall my-kit-extension +\`\`\` + +## Extension structure + +### Single-file extensions + +A single \`.go\` file with an \`Init\` function: + +\`\`\`go +//go:build ignore + +package main + +import "kit/ext" + +func Init(api ext.API) { + // register handlers, tools, commands, etc. +} +\`\`\` + +The \`//go:build ignore\` directive prevents the Go toolchain from trying to compile the file as part of a normal build. + +### Subdirectory extensions + +For more complex extensions, create a directory with a \`main.go\` entry point: + +\`\`\` +.kit/extensions/my-extension/ +├── main.go # Must contain Init(api ext.API) +├── helpers.go # Additional source files +└── config.go +\`\`\` + +### Package-level state + +Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks: + +\`\`\`go +package main + +import "kit/ext" + +var callCount int + +func Init(api ext.API) { + api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) { + callCount++ + ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{ + Text: fmt.Sprintf("Tools called: %d", callCount), + }, + }) + }) +} +\`\`\` +`},{id:"extensions/overview",title:"Extension System",content:'\n# Extension System\n\nExtensions are Go source files interpreted at runtime via [Yaegi](https://github.com/traefik/yaegi). They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit.\n\n## Minimal extension\n\n```go\n//go:build ignore\n\npackage main\n\nimport "kit/ext"\n\nfunc Init(api ext.API) {\n api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {\n ctx.SetFooter(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{Text: "Custom Footer"},\n })\n })\n}\n```\n\nRun it with:\n\n```bash\nkit -e examples/extensions/minimal.go\n```\n\n## How extensions work\n\n1. Kit discovers extension files from [auto-discovery paths](/extensions/loading) or explicit `-e` flags\n2. Each `.go` file is loaded into a Yaegi interpreter with access to the `kit/ext` package\n3. Kit calls the `Init(api ext.API)` function in each extension\n4. The extension registers callbacks, tools, commands, and UI components via the `api` and `ctx` objects\n\n## Key concepts\n\n### The `API` object\n\nPassed to `Init()`, the `API` object is used to register lifecycle event handlers and static components:\n\n- **Lifecycle handlers** — `api.OnSessionStart(...)`, `api.OnToolCall(...)`, etc.\n- **Tools** — `api.RegisterTool(ext.ToolDef{...})`\n- **Commands** — `api.RegisterCommand(ext.CommandDef{...})`\n- **Shortcuts** — `api.RegisterShortcut(ext.ShortcutDef{...}, handler)`\n- **Tool renderers** — `api.RegisterToolRenderer(ext.ToolRenderConfig{...})`\n- **Message renderers** — `api.RegisterMessageRenderer(ext.MessageRendererConfig{...})`\n- **Options** — `api.RegisterOption(ext.OptionDef{...})`\n\n### The `Context` object\n\nPassed to event handlers, the `Context` object provides runtime access to Kit\'s state and UI:\n\n- **Output** — `ctx.Print(...)`, `ctx.PrintInfo(...)`, `ctx.PrintError(...)`\n- **UI components** — `ctx.SetWidget(...)`, `ctx.SetHeader(...)`, `ctx.SetFooter(...)`, `ctx.SetStatus(...)`\n- **Editor** — `ctx.SetEditor(...)`, `ctx.ResetEditor()`\n- **Prompts** — `ctx.PromptSelect(...)`, `ctx.PromptConfirm(...)`, `ctx.PromptInput(...)`\n- **Overlays** — `ctx.ShowOverlay(...)`\n- **Messages** — `ctx.SendMessage(...)`, `ctx.GetMessages()`\n- **Model** — `ctx.SetModel(...)`, `ctx.GetAvailableModels()`\n- **Tools** — `ctx.GetAllTools()`, `ctx.SetActiveTools(...)`\n- **Context stats** — `ctx.GetContextStats()`\n- **Session data** — `ctx.AppendEntry(...)`, `ctx.GetEntries(...)`\n- **Subagents** — `ctx.SpawnSubagent(...)`\n- **LLM completion** — `ctx.Complete(...)`\n- **Custom events** — `ctx.EmitCustomEvent(...)`\n- **App control** — `ctx.Exit()`, `ctx.ReloadExtensions()`\n\nSee [Capabilities](/extensions/capabilities) for full details on each component type.\n'},{id:"index",title:"Kit",content:` +
    + KIT +
    + +A powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system. + +## Features + +- **Multi-Provider LLM Support** — Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more +- **Built-in Core Tools** — bash, read, write, edit, grep, find, ls, spawn_subagent with no MCP overhead +- **MCP Integration** — Connect external MCP servers for expanded capabilities +- **Extension System** — Write custom tools, commands, widgets, and UI modifications in Go +- **Interactive TUI** — Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering +- **Session Management** — Tree-based conversation history with branching support +- **Non-Interactive Mode** — Script-friendly positional args with JSON output +- **ACP Server** — Run Kit as an [Agent Client Protocol](https://agentclientprotocol.com) agent over stdio +- **Go SDK** — Embed Kit in your own applications + +## Quick links + +| Resource | Description | +|----------|-------------| +| [Installation](/installation) | Get Kit up and running | +| [Quick Start](/quick-start) | Your first Kit session | +| [Configuration](/configuration) | Customize Kit for your workflow | +| [Extensions](/extensions/overview) | Build custom tools and UI components | +| [Go SDK](/sdk/overview) | Embed Kit in your applications | +`},{id:"installation",title:"Installation",content:` +# Installation + +## Using npm (recommended) + +\`\`\`bash +npm install -g @mark3labs/kit +\`\`\` + +## Using Go + +\`\`\`bash +go install github.com/mark3labs/kit/cmd/kit@latest +\`\`\` + +## Building from source + +\`\`\`bash +git clone https://github.com/mark3labs/kit.git +cd kit +go build -o kit ./cmd/kit +\`\`\` + +## Verifying the installation + +After installing, verify Kit is available: + +\`\`\`bash +kit --help +\`\`\` + +## Setting up a provider + +Kit needs at least one LLM provider configured. Set an API key for your preferred provider: + +\`\`\`bash +# Anthropic (default provider) +export ANTHROPIC_API_KEY="sk-..." + +# OpenAI +export OPENAI_API_KEY="sk-..." + +# Google Gemini +export GOOGLE_API_KEY="..." +\`\`\` + +For OAuth-enabled providers like Anthropic, you can also authenticate interactively: + +\`\`\`bash +kit auth login anthropic +\`\`\` + +See [Providers](/providers) for the full list of supported providers and their configuration. +`},{id:"providers",title:"Providers",content:` +# Providers + +Kit supports a wide range of LLM providers through a unified \`provider/model\` string format. + +## Supported providers + +| Provider | Prefix | Description | +|----------|--------|-------------| +| **Anthropic** | \`anthropic/\` | Claude models (native, prompt caching, OAuth) | +| **OpenAI** | \`openai/\` | GPT models | +| **Google** | \`google/\` or \`gemini/\` | Gemini models | +| **Ollama** | \`ollama/\` | Local models | +| **Azure OpenAI** | \`azure/\` | Azure-hosted OpenAI | +| **AWS Bedrock** | \`bedrock/\` | Bedrock models | +| **Google Vertex** | \`google-vertex-anthropic/\` | Claude on Vertex AI | +| **OpenRouter** | \`openrouter/\` | Multi-provider router | +| **Vercel AI** | \`vercel/\` | Vercel AI SDK models | +| **Auto-routed** | any | Any provider from the models.dev database | + +## Model string format + +\`\`\`bash +provider/model # Standard format +anthropic/claude-sonnet-4-5-20250929 +openai/gpt-4o +ollama/llama3 +google/gemini-2.0-flash-exp +\`\`\` + +## Model aliases + +Kit provides aliases for commonly used models: + +\`\`\`bash +claude-opus-latest → claude-opus-4-20250514 +claude-sonnet-latest → claude-sonnet-4-5-20250929 +claude-4-opus-latest → claude-opus-4-20250514 +claude-4-sonnet-latest → claude-sonnet-4-5-20250929 +claude-3-7-sonnet-latest → claude-3-7-sonnet-20250219 +claude-3-5-sonnet-latest → claude-3-5-sonnet-20241022 +claude-3-5-haiku-latest → claude-3-5-haiku-20241022 +claude-3-opus-latest → claude-3-opus-20240229 +\`\`\` + +## Specifying a model + +Via CLI flag: + +\`\`\`bash +kit --model openai/gpt-4o +kit -m ollama/llama3 +\`\`\` + +Via config file: + +\`\`\`yaml +model: anthropic/claude-sonnet-4-5-20250929 +\`\`\` + +Via environment variable: + +\`\`\`bash +export KIT_MODEL="google/gemini-2.0-flash-exp" +\`\`\` + +## Authentication + +### API keys + +Set the appropriate environment variable for your provider: + +\`\`\`bash +export ANTHROPIC_API_KEY="sk-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +\`\`\` + +Or pass it directly: + +\`\`\`bash +kit --provider-api-key "sk-..." --model openai/gpt-4o +\`\`\` + +### OAuth + +For providers that support OAuth (e.g., Anthropic): + +\`\`\`bash +kit auth login anthropic # Start OAuth flow +kit auth status # Check authentication status +kit auth logout anthropic # Remove credentials +\`\`\` + +### Custom provider URL + +For self-hosted or proxy endpoints: + +\`\`\`bash +kit --provider-url "https://my-proxy.example.com/v1" --model openai/gpt-4o +\`\`\` + +## Model database + +Kit ships with a local model database that maps provider names to API configurations. You can manage it with: + +\`\`\`bash +kit models # List available models +kit models openai # Filter by provider +kit models --all # Show all providers +kit update-models # Update from models.dev +kit update-models embedded # Reset to bundled database +\`\`\` +`},{id:"quick-start",title:"Quick Start",content:` +# Quick Start + +## Basic usage + +Start an interactive session: + +\`\`\`bash +kit +\`\`\` + +Run a one-off prompt: + +\`\`\`bash +kit "List files in src/" +\`\`\` + +Attach files as context using the \`@\` prefix: + +\`\`\`bash +kit @main.go @test.go "Review these files" +\`\`\` + +Use a specific model: + +\`\`\`bash +kit --model anthropic/claude-sonnet-4-5-20250929 +\`\`\` + +## Non-interactive mode + +Kit can run as a non-interactive tool for scripting and automation. + +Get JSON output: + +\`\`\`bash +kit "Explain main.go" --json +\`\`\` + +Quiet mode (final response only, no TUI): + +\`\`\`bash +kit "Run tests" --quiet +\`\`\` + +Ephemeral mode (no session file created): + +\`\`\`bash +kit "Quick question" --no-session +\`\`\` + +## Resuming sessions + +Continue the most recent session for the current directory: + +\`\`\`bash +kit --continue +# or +kit -c +\`\`\` + +Pick from previous sessions interactively: + +\`\`\`bash +kit --resume +# or +kit -r +\`\`\` + +## ACP server mode + +Kit can run as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server, enabling ACP-compatible clients (such as [OpenCode](https://github.com/sst/opencode)) to drive Kit as a remote coding agent over stdio: + +\`\`\`bash +# Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout) +kit acp + +# With debug logging to stderr +kit acp --debug +\`\`\` + +The ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol. +`},{id:"sdk/callbacks",title:"Callbacks",content:` +# Callbacks + +## PromptWithCallbacks + +The \`PromptWithCallbacks\` method provides real-time visibility into tool calls and streaming output: + +\`\`\`go +response, err := host.PromptWithCallbacks( + ctx, + "List files in current directory", + func(name, args string) { + // Called when the model invokes a tool + fmt.Println("Calling tool:", name) + }, + func(name, args, result string, isError bool) { + // Called when a tool returns its result + if isError { + fmt.Println("Tool failed:", name) + } + }, + func(chunk string) { + // Called for each streaming text chunk + fmt.Print(chunk) + }, +) +\`\`\` + +### Callback signatures + +| Callback | Signature | When | +|----------|-----------|------| +| \`onToolCall\` | \`func(name, args string)\` | Model requests a tool call | +| \`onToolResult\` | \`func(name, args, result string, isError bool)\` | Tool execution completes | +| \`onStreaming\` | \`func(chunk string)\` | Streaming text chunk received | + +Any callback can be \`nil\` if you don't need it: + +\`\`\`go +// Only care about streaming output +response, err := host.PromptWithCallbacks(ctx, "Hello", nil, nil, func(chunk string) { + fmt.Print(chunk) +}) +\`\`\` + +## Event-based monitoring + +For more granular control, use the event subscription API: + +\`\`\`go +// Subscribe returns an unsubscribe function +unsub := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Printf("Tool: %s, Args: %s\\n", event.Name, event.Args) +}) +defer unsub() + +unsub2 := host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Printf("Result: %s (error: %v)\\n", event.Name, event.IsError) +}) +defer unsub2() + +unsub3 := host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +defer unsub3() + +unsub4 := host.OnResponse(func(event kit.ResponseEvent) { + fmt.Println("Final response received") +}) +defer unsub4() + +unsub5 := host.OnTurnStart(func(event kit.TurnStartEvent) { + fmt.Println("Turn started") +}) +defer unsub5() + +unsub6 := host.OnTurnEnd(func(event kit.TurnEndEvent) { + fmt.Println("Turn ended") +}) +defer unsub6() +\`\`\` + +## Hook system + +Hooks allow you to intercept and modify behavior. Unlike events, hooks can modify or cancel operations: + +\`\`\`go +// Intercept tool calls before execution +host.OnBeforeToolCall(0, func(ctx context.Context, name string, args string) (string, error) { + if name == "bash" { + log.Println("Bash command:", args) + } + return args, nil // return modified args or error to cancel +}) + +// Process results after tool execution +host.OnAfterToolResult(0, func(ctx context.Context, name string, result string) (string, error) { + return result, nil +}) + +// Before/after each agent turn +host.OnBeforeTurn(0, func(ctx context.Context) error { + return nil +}) + +host.OnAfterTurn(0, func(ctx context.Context) error { + return nil +}) +\`\`\` + +The first argument is a priority (lower = runs first). +`},{id:"sdk/options",title:"SDK Options",content:'\n# SDK Options\n\nPass an `Options` struct to `kit.New()` to configure the Kit instance.\n\n## Full options reference\n\n```go\nhost, err := kit.New(ctx, &kit.Options{\n // Model\n Model: "ollama/llama3",\n SystemPrompt: "You are a helpful bot",\n ConfigFile: "/path/to/config.yml",\n\n // Behavior\n MaxSteps: 10,\n Streaming: true,\n Quiet: true,\n Debug: true,\n\n // Session\n SessionPath: "./session.jsonl",\n SessionDir: "/custom/sessions/",\n Continue: true,\n NoSession: true,\n\n // Tools\n Tools: []kit.Tool{...}, // Replace default tool set entirely\n ExtraTools: []kit.Tool{...}, // Add tools alongside defaults\n\n // Compaction\n AutoCompact: true,\n\n // Skills\n Skills: []string{"/path/to/skill.md"},\n SkillsDir: "/path/to/skills/",\n})\n```\n\n## Options fields\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `Model` | `string` | config default | Model string (provider/model format) |\n| `SystemPrompt` | `string` | — | System prompt text or file path |\n| `ConfigFile` | `string` | `~/.kit.yml` | Path to config file |\n| `MaxSteps` | `int` | `0` | Max agent steps (0 = unlimited) |\n| `Streaming` | `bool` | `true` | Enable streaming output |\n| `Quiet` | `bool` | `false` | Suppress output |\n| `Debug` | `bool` | `false` | Enable debug logging |\n| `SessionPath` | `string` | — | Open a specific session file |\n| `SessionDir` | `string` | — | Base directory for session discovery |\n| `Continue` | `bool` | `false` | Resume most recent session |\n| `NoSession` | `bool` | `false` | Ephemeral mode (no persistence) |\n| `Tools` | `[]Tool` | — | Replace the entire default tool set |\n| `ExtraTools` | `[]Tool` | — | Additional tools alongside core/MCP/extension tools |\n| `AutoCompact` | `bool` | `false` | Auto-compact when near context limit |\n| `CompactionOptions` | `*CompactionOptions` | — | Configuration for auto-compaction |\n| `Skills` | `[]string` | — | Explicit skill files/dirs to load |\n| `SkillsDir` | `string` | — | Override default skills directory |\n'},{id:"sdk/overview",title:"Go SDK",content:` +# Go SDK + +The \`pkg/kit\` package lets you embed Kit as a library in your Go applications. + +## Installation + +\`\`\`bash +go get github.com/mark3labs/kit/pkg/kit +\`\`\` + +## Basic usage + +\`\`\`go +package main + +import ( + "context" + "log" + + kit "github.com/mark3labs/kit/pkg/kit" +) + +func main() { + ctx := context.Background() + + // Create Kit instance with default configuration + host, err := kit.New(ctx, nil) + if err != nil { + log.Fatal(err) + } + defer host.Close() + + // Send a prompt + response, err := host.Prompt(ctx, "What is 2+2?") + if err != nil { + log.Fatal(err) + } + + println(response) +} +\`\`\` + +## Multi-turn conversations + +Conversations retain context automatically across calls: + +\`\`\`go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +\`\`\` + +## Additional prompt methods + +The SDK provides several prompt variants: + +| Method | Description | +|--------|-------------| +| \`Prompt(ctx, message)\` | Simple prompt, returns response string | +| \`PromptWithCallbacks(ctx, message, ...)\` | With tool call and streaming callbacks | +| \`PromptWithOptions(ctx, message, opts)\` | With per-call options | +| \`PromptResult(ctx, message)\` | Returns full \`TurnResult\` with usage stats | +| \`PromptResultWithFiles(ctx, message, files)\` | Multimodal with file attachments | +| \`Steer(ctx, instruction)\` | System-level steering without user message | +| \`FollowUp(ctx, text)\` | Continue without new user input | + +## Event system + +Subscribe to events for monitoring: + +\`\`\`go +unsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Println("Tool called:", event.Name) +}) +defer unsubscribe() + +host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Println("Tool result:", event.Name) +}) + +host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +\`\`\` + +## Model management + +Switch models at runtime: + +\`\`\`go +host.SetModel(ctx, "openai/gpt-4o") +info := host.GetModelInfo() +models := host.GetAvailableModels() +\`\`\` + +## Context and compaction + +Monitor and manage context usage: + +\`\`\`go +tokens := host.EstimateContextTokens() +stats := host.GetContextStats() + +if host.ShouldCompact() { + result, err := host.Compact(ctx, nil, "") +} +\`\`\` + +See [Options](/sdk/options), [Callbacks](/sdk/callbacks), and [Sessions](/sdk/sessions) for more details. +`},{id:"sdk/sessions",title:"SDK Sessions",content:` +# SDK Sessions + +## Automatic persistence + +By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls: + +\`\`\`go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +\`\`\` + +## Accessing session info + +\`\`\`go +// Get the current session file path +path := host.GetSessionPath() + +// Get the session ID +id := host.GetSessionID() + +// Get the current model string +model := host.GetModelString() +\`\`\` + +## Configuring sessions via Options + +Session behavior is configured at initialization: + +\`\`\`go +// Open a specific session file +host, _ := kit.New(ctx, &kit.Options{ + SessionPath: "./my-session.jsonl", +}) + +// Resume the most recent session for the current directory +host, _ := kit.New(ctx, &kit.Options{ + Continue: true, +}) + +// Ephemeral mode (no file persistence) +host, _ := kit.New(ctx, &kit.Options{ + NoSession: true, +}) + +// Custom session directory +host, _ := kit.New(ctx, &kit.Options{ + SessionDir: "/custom/sessions/", +}) +\`\`\` + +## Clearing history + +Clear the in-memory conversation history (does not delete the session file): + +\`\`\`go +host.ClearSession() +\`\`\` + +## Tree-based sessions + +Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths: + +\`\`\`go +// Access the tree session manager +ts := host.GetTreeSession() + +// Branch from a specific entry +err := host.Branch("entry-id-123") +\`\`\` + +## Listing and managing sessions + +Package-level functions for session discovery: + +\`\`\`go +// List sessions for a specific directory +sessions := kit.ListSessions("/home/user/project") + +// List all sessions across all directories +all := kit.ListAllSessions() + +// Delete a session file +kit.DeleteSession("/path/to/session.jsonl") +\`\`\` +`},{id:"sessions",title:"Session Management",content:` +# Session Management + +Kit uses a tree-based session model that supports branching and forking conversations. + +## Session storage + +Sessions are stored as JSONL (JSON Lines) files: + +\`\`\` +~/.kit/sessions//_.jsonl +\`\`\` + +Path separators in the working directory are replaced with \`--\`. For example, \`/home/user/project\` becomes \`home--user--project\`. + +Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths. + +## Resuming sessions + +### Continue most recent + +Resume the most recent session for the current directory: + +\`\`\`bash +kit --continue +kit -c +\`\`\` + +### Interactive picker + +Choose from previous sessions interactively: + +\`\`\`bash +kit --resume +kit -r +\`\`\` + +### Open a specific session + +\`\`\`bash +kit --session path/to/session.jsonl +kit -s path/to/session.jsonl +\`\`\` + +## Ephemeral mode + +Run without creating a session file: + +\`\`\`bash +kit --no-session +\`\`\` + +This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed. +`}],b0={};function S0(u){return u>=200&&u<300?"#22c55e":u>=400&&u<500?"#f59e0b":u>=500?"#ef4444":"#6b7280"}function T0(u,h,d,c){let v=h;for(const[M,D]of Object.entries(d))v=v.replace(`{${M}}`,encodeURIComponent(D));const E=new URL(v,u);for(const[M,D]of Object.entries(c))D&&E.searchParams.set(M,D);return E.toString()}function E0(u){return u==="bearer"?"Authorization":"X-API-Key"}const Fu={width:"100%",padding:"6px 10px",border:"1px solid var(--bd)",borderRadius:4,background:"var(--bg)",color:"var(--tx)",fontSize:13,fontFamily:"var(--font-code, monospace)",boxSizing:"border-box"};function Ju({param:u,value:h,onChange:d}){return s.jsxs("div",{style:{marginBottom:10},children:[s.jsxs("label",{style:{display:"block",fontSize:12,fontWeight:600,marginBottom:3,color:"var(--tx)"},children:[u.name,u.required&&s.jsx("span",{style:{color:"#ef4444",marginLeft:2},children:"*"}),s.jsxs("span",{style:{fontWeight:400,color:"var(--txM)",marginLeft:6,fontSize:11},children:[u.in," · ",u.type]})]}),s.jsx("input",{"data-testid":`param-input-${u.name}`,style:Fu,placeholder:u.description||u.name,value:h,onChange:c=>d(c.target.value)})]})}function A0({endpoint:u,baseUrl:h,auth:d}){var lt;const[c,v]=B.useState(!1),[E,M]=B.useState({}),[D,z]=B.useState((lt=u.requestBody)!=null&<.schema?JSON.stringify(u.requestBody.schema,null,2):""),[y,G]=B.useState(""),[R,K]=B.useState(!1),[nt,bt]=B.useState(null),[Ot,jt]=B.useState(null),[W,I]=B.useState(!1),ct=(P,mt)=>M(tt=>({...tt,[P]:mt})),Q=u.parameters.filter(P=>P.in==="path"),Y=u.parameters.filter(P=>P.in==="query"),H=u.parameters.filter(P=>P.in==="header"),U=u.requestBody!=null,at=async()=>{K(!0),bt(null),jt(null);const P={};for(const Mt of Q)P[Mt.name]=E[Mt.name]||"";const mt={};for(const Mt of Y)E[Mt.name]&&(mt[Mt.name]=E[Mt.name]);const tt={};for(const Mt of H)E[Mt.name]&&(tt[Mt.name]=E[Mt.name]);if(U&&(tt["Content-Type"]="application/json"),d&&y){const Mt=d.header||E0(d.type);tt[Mt]=d.type==="bearer"?`Bearer ${y}`:y}try{const Mt=T0(h,u.path,P,mt),$t=Date.now(),ft=await fetch(Mt,{method:u.method.toUpperCase(),headers:tt,body:U&&D?D:void 0}),C=Date.now()-$t,w={};ft.headers.forEach((Tt,m)=>{w[m]=Tt});let Z;if((ft.headers.get("content-type")||"").includes("json")){const Tt=await ft.json();Z=JSON.stringify(Tt,null,2)}else Z=await ft.text();bt({status:ft.status,statusText:ft.statusText,headers:w,body:Z,time:C})}catch(Mt){jt(Mt instanceof Error?Mt.message:"Network error")}finally{K(!1)}};return s.jsxs("div",{"data-testid":"api-playground",style:{border:"1px solid var(--bd)",borderRadius:6,overflow:"hidden",marginTop:8},children:[s.jsxs("button",{"data-testid":"playground-toggle",onClick:()=>v(!c),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"10px 14px",background:"var(--sf)",border:"none",cursor:"pointer",fontFamily:"inherit",fontSize:13,fontWeight:600,color:"var(--ac)"},children:[s.jsx("span",{style:{fontSize:14},children:c?"▼":"▶"}),"Try it out"]}),c&&s.jsxs("div",{style:{padding:"14px 16px",borderTop:"1px solid var(--bd)"},children:[d&&s.jsxs("div",{style:{marginBottom:12},children:[s.jsx("label",{style:{display:"block",fontSize:12,fontWeight:600,marginBottom:3,color:"var(--tx)"},children:d.type==="bearer"?"Bearer Token":"API Key"}),s.jsx("input",{"data-testid":"auth-input",type:"password",style:Fu,placeholder:d.type==="bearer"?"Enter bearer token":"Enter API key",value:y,onChange:P=>G(P.target.value)})]}),Q.length>0&&s.jsxs("div",{style:{marginBottom:4},children:[s.jsx("div",{style:{fontSize:11,fontWeight:700,textTransform:"uppercase",color:"var(--txM)",marginBottom:6,letterSpacing:"0.05em"},children:"Path Parameters"}),Q.map(P=>s.jsx(Ju,{param:P,value:E[P.name]||"",onChange:mt=>ct(P.name,mt)},P.name))]}),Y.length>0&&s.jsxs("div",{style:{marginBottom:4},children:[s.jsx("div",{style:{fontSize:11,fontWeight:700,textTransform:"uppercase",color:"var(--txM)",marginBottom:6,letterSpacing:"0.05em"},children:"Query Parameters"}),Y.map(P=>s.jsx(Ju,{param:P,value:E[P.name]||"",onChange:mt=>ct(P.name,mt)},P.name))]}),H.length>0&&s.jsxs("div",{style:{marginBottom:4},children:[s.jsx("div",{style:{fontSize:11,fontWeight:700,textTransform:"uppercase",color:"var(--txM)",marginBottom:6,letterSpacing:"0.05em"},children:"Header Parameters"}),H.map(P=>s.jsx(Ju,{param:P,value:E[P.name]||"",onChange:mt=>ct(P.name,mt)},P.name))]}),U&&s.jsxs("div",{style:{marginBottom:12},children:[s.jsx("label",{style:{display:"block",fontSize:12,fontWeight:600,marginBottom:3,color:"var(--tx)"},children:"Request Body"}),s.jsx("textarea",{"data-testid":"request-body",style:{...Fu,minHeight:100,resize:"vertical",lineHeight:1.5},value:D,onChange:P=>z(P.target.value)})]}),s.jsx("button",{"data-testid":"send-request",onClick:at,disabled:R,style:{padding:"8px 20px",borderRadius:4,border:"none",background:"var(--ac)",color:"#fff",fontWeight:600,fontSize:13,cursor:R?"wait":"pointer",opacity:R?.7:1,fontFamily:"inherit"},children:R?"Sending...":"Send Request"}),Ot&&s.jsx("div",{"data-testid":"playground-error",style:{marginTop:12,padding:"10px 14px",borderRadius:4,background:"#ef444418",border:"1px solid #ef444444",color:"#ef4444",fontSize:13},children:Ot}),nt&&s.jsxs("div",{"data-testid":"playground-response",style:{marginTop:12},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:8},children:[s.jsxs("span",{"data-testid":"response-status",style:{padding:"2px 10px",borderRadius:4,fontSize:13,fontWeight:700,fontFamily:"var(--font-code, monospace)",color:"#fff",background:S0(nt.status)},children:[nt.status," ",nt.statusText]}),s.jsxs("span",{style:{fontSize:12,color:"var(--txM)"},children:[nt.time,"ms"]})]}),s.jsxs("button",{"data-testid":"toggle-headers",onClick:()=>I(!W),style:{display:"flex",alignItems:"center",gap:4,background:"none",border:"none",cursor:"pointer",fontSize:12,color:"var(--txM)",padding:"4px 0",fontFamily:"inherit",marginBottom:4},children:[s.jsx("span",{style:{transform:W?"rotate(90deg)":"rotate(0)",transition:"transform 0.15s"},children:"▶"}),"Response Headers"]}),W&&s.jsx("pre",{style:{background:"var(--sf)",padding:10,borderRadius:4,fontSize:11,fontFamily:"var(--font-code, monospace)",overflow:"auto",lineHeight:1.5,marginBottom:8,color:"var(--tx2)",margin:"0 0 8px 0"},children:Object.entries(nt.headers).map(([P,mt])=>`${P}: ${mt}`).join(` +`)}),s.jsx("pre",{"data-testid":"response-body",style:{background:"var(--cdBg)",color:"var(--cdTx)",padding:14,borderRadius:6,fontSize:12,fontFamily:"var(--font-code, monospace)",overflow:"auto",lineHeight:1.6,margin:0,maxHeight:400},children:nt.body})]})]})]})}function mm({samples:u}){var c;const[h,d]=B.useState(0);return u.length===0?null:s.jsxs("div",{"data-testid":"code-samples",style:{border:"1px solid var(--bd)",borderRadius:8,overflow:"hidden"},children:[s.jsx("div",{style:{display:"flex",borderBottom:"1px solid var(--bd)",background:"var(--sf)",overflowX:"auto",WebkitOverflowScrolling:"touch"},children:u.map((v,E)=>s.jsx("button",{onClick:()=>d(E),style:{padding:"8px 16px",fontSize:13,fontWeight:500,background:E===h?"var(--cdBg)":"transparent",color:E===h?"var(--tx)":"var(--tx2)",border:"none",borderBottom:E===h?"2px solid var(--ac)":"2px solid transparent",cursor:"pointer",fontFamily:"var(--font-body)",whiteSpace:"nowrap"},children:v.label},v.language))}),s.jsx("pre",{style:{margin:0,padding:16,background:"var(--cdBg)",overflow:"auto"},children:s.jsx("code",{style:{fontSize:13,fontFamily:"var(--font-code)"},children:(c=u[h])==null?void 0:c.code})})]})}const pm={get:"#22c55e",post:"#3b82f6",put:"#f59e0b",delete:"#ef4444",patch:"#a78bfa",head:"#6b7280",options:"#6b7280"};function z0({method:u}){const h=pm[u.toLowerCase()]||"#6b7280";return s.jsx("span",{"data-testid":"method-badge",style:{display:"inline-block",padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:700,fontFamily:"var(--font-code, monospace)",textTransform:"uppercase",color:"#fff",background:h,letterSpacing:"0.05em"},children:u.toUpperCase()})}function C0({parameters:u}){return u.length===0?null:s.jsx("div",{style:{overflowX:"auto",marginBottom:16},children:s.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:13,lineHeight:1.5},children:[s.jsx("thead",{children:s.jsxs("tr",{style:{borderBottom:"2px solid var(--bd)",textAlign:"left"},children:[s.jsx("th",{style:{padding:"8px 12px",fontWeight:600,color:"var(--tx)"},children:"Name"}),s.jsx("th",{style:{padding:"8px 12px",fontWeight:600,color:"var(--tx)"},children:"Type"}),s.jsx("th",{style:{padding:"8px 12px",fontWeight:600,color:"var(--tx)"},children:"In"}),s.jsx("th",{style:{padding:"8px 12px",fontWeight:600,color:"var(--tx)"},children:"Required"}),s.jsx("th",{style:{padding:"8px 12px",fontWeight:600,color:"var(--tx)"},children:"Description"})]})}),s.jsx("tbody",{children:u.map((h,d)=>s.jsxs("tr",{style:{borderBottom:"1px solid var(--bd)"},children:[s.jsx("td",{style:{padding:"8px 12px",fontFamily:"var(--font-code, monospace)",fontWeight:500,color:h.in==="path"?"var(--ac)":"var(--tx)"},children:h.name}),s.jsx("td",{style:{padding:"8px 12px",fontFamily:"var(--font-code, monospace)",color:"var(--tx2)"},children:h.type}),s.jsx("td",{style:{padding:"8px 12px",color:"var(--txM)"},children:s.jsx("span",{style:{padding:"1px 6px",borderRadius:3,fontSize:11,background:h.in==="path"?"var(--ac)22":"var(--sf)",color:h.in==="path"?"var(--ac)":"var(--txM)"},children:h.in})}),s.jsx("td",{style:{padding:"8px 12px"},children:h.required?s.jsx("span",{"data-testid":"required-badge",style:{padding:"1px 6px",borderRadius:3,fontSize:11,fontWeight:600,background:"#ef444422",color:"#ef4444"},children:"required"}):s.jsx("span",{style:{color:"var(--txM)",fontSize:12},children:"optional"})}),s.jsx("td",{style:{padding:"8px 12px",color:"var(--tx2)"},children:h.description||"—"})]},`${h.name}-${d}`))})]})})}function j0({requestBody:u}){return s.jsxs("div",{style:{marginBottom:16},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[s.jsx("span",{style:{padding:"2px 8px",borderRadius:4,fontSize:11,fontFamily:"var(--font-code, monospace)",background:"var(--sf)",color:"var(--tx2)"},children:u.contentType}),u.required&&s.jsx("span",{style:{padding:"1px 6px",borderRadius:3,fontSize:11,fontWeight:600,background:"#ef444422",color:"#ef4444"},children:"required"})]}),u.description&&s.jsx("p",{style:{fontSize:13,color:"var(--tx2)",marginBottom:8,marginTop:0},children:u.description}),u.schema&&s.jsx("pre",{style:{background:"var(--cdBg)",color:"var(--cdTx)",padding:16,borderRadius:6,fontSize:12,fontFamily:"var(--font-code, monospace)",overflow:"auto",lineHeight:1.6,margin:0},children:JSON.stringify(u.schema,null,2)})]})}function M0(u){return u.startsWith("2")?"#22c55e":u.startsWith("4")?"#f59e0b":u.startsWith("5")?"#ef4444":"#6b7280"}function _0({responses:u}){return u.length===0?null:s.jsx("div",{style:{marginBottom:16},children:u.map((h,d)=>{const c=M0(h.statusCode);return s.jsxs("div",{style:{border:"1px solid var(--bd)",borderRadius:6,marginBottom:8,overflow:"hidden"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,padding:"10px 14px",background:"var(--sf)"},children:[s.jsx("span",{"data-testid":"status-badge",style:{padding:"2px 8px",borderRadius:4,fontSize:12,fontWeight:700,fontFamily:"var(--font-code, monospace)",color:"#fff",background:c},children:h.statusCode}),s.jsx("span",{style:{fontSize:13,color:"var(--tx2)"},children:h.description})]}),h.schema&&s.jsx("pre",{style:{background:"var(--cdBg)",color:"var(--cdTx)",padding:14,fontSize:12,fontFamily:"var(--font-code, monospace)",overflow:"auto",lineHeight:1.6,margin:0,borderTop:"1px solid var(--bd)"},children:JSON.stringify(h.schema,null,2)})]},`${h.statusCode}-${d}`)})})}function k0(u,h){const d=h+u.path,c=[`curl -X ${u.method.toUpperCase()} "${d}"`],v=u.parameters.filter(E=>E.in==="header");for(const E of v)c.push(` -H "${E.name}: "`);return u.requestBody&&(c.push(` -H "Content-Type: ${u.requestBody.contentType}"`),u.requestBody.schema&&c.push(` -d '${JSON.stringify(u.requestBody.schema,null,2)}'`)),c.join(` \\ +`)}function O0(u,h){var M;const d=h+u.path,c=[];c.push(` method: "${u.method.toUpperCase()}",`);const v={},E=u.parameters.filter(D=>D.in==="header");for(const D of E)v[D.name]="";return u.requestBody&&(v["Content-Type"]=u.requestBody.contentType),Object.keys(v).length>0&&c.push(` headers: ${JSON.stringify(v,null,4).replace(/\n/g,` + `)},`),(M=u.requestBody)!=null&&M.schema&&c.push(` body: JSON.stringify(${JSON.stringify(u.requestBody.schema,null,4).replace(/\n/g,` + `)}),`),`fetch("${d}", { +${c.join(` +`)} +});`}function D0(u,h){var D,z;const d=h+u.path,c=["import requests",""],v={},E=u.parameters.filter(y=>y.in==="header");for(const y of E)v[y.name]="";u.requestBody&&(v["Content-Type"]=u.requestBody.contentType),Object.keys(v).length>0&&(c.push(`headers = ${JSON.stringify(v,null,4)}`),c.push("")),(D=u.requestBody)!=null&&D.schema&&(c.push(`data = ${JSON.stringify(u.requestBody.schema,null,4)}`),c.push(""));const M=[`"${d}"`];return Object.keys(v).length>0&&M.push("headers=headers"),(z=u.requestBody)!=null&&z.schema&&M.push("json=data"),c.push(`response = requests.${u.method}(${M.join(", ")})`),c.push("print(response.json())"),c.join(` +`)}function R0(u,h){var E,M;const d=h+u.path,c=["package main","","import (",' "fmt"',' "net/http"'];(E=u.requestBody)!=null&&E.schema&&c.push(' "bytes"',' "encoding/json"'),c.push(' "io"',")",""),c.push("func main() {"),(M=u.requestBody)!=null&&M.schema?(c.push(` body, _ := json.Marshal(${JSON.stringify(u.requestBody.schema)})`),c.push(` req, _ := http.NewRequest("${u.method.toUpperCase()}", "${d}", bytes.NewBuffer(body))`)):c.push(` req, _ := http.NewRequest("${u.method.toUpperCase()}", "${d}", nil)`);const v=u.parameters.filter(D=>D.in==="header");for(const D of v)c.push(` req.Header.Set("${D.name}", "")`);return u.requestBody&&c.push(` req.Header.Set("Content-Type", "${u.requestBody.contentType}")`),c.push(" resp, _ := http.DefaultClient.Do(req)"),c.push(" defer resp.Body.Close()"),c.push(" data, _ := io.ReadAll(resp.Body)"),c.push(" fmt.Println(string(data))"),c.push("}"),c.join(` +`)}function B0(u,h){var E;const d=h+u.path,c=["import java.net.http.*;","import java.net.URI;","","var client = HttpClient.newHttpClient();"];(E=u.requestBody)!=null&&E.schema?(c.push(`var body = ${JSON.stringify(JSON.stringify(u.requestBody.schema))};`),c.push("var request = HttpRequest.newBuilder()"),c.push(` .uri(URI.create("${d}"))`),c.push(` .method("${u.method.toUpperCase()}", HttpRequest.BodyPublishers.ofString(body))`)):(c.push("var request = HttpRequest.newBuilder()"),c.push(` .uri(URI.create("${d}"))`),c.push(` .method("${u.method.toUpperCase()}", HttpRequest.BodyPublishers.noBody())`));const v=u.parameters.filter(M=>M.in==="header");for(const M of v)c.push(` .header("${M.name}", "")`);return u.requestBody&&c.push(` .header("Content-Type", "${u.requestBody.contentType}")`),c.push(" .build();"),c.push(""),c.push("var response = client.send(request, HttpResponse.BodyHandlers.ofString());"),c.push("System.out.println(response.body());"),c.join(` +`)}function w0(u,h){var E;const d=h+u.path,c=["using var client = new HttpClient();","",`var request = new HttpRequestMessage(HttpMethod.${u.method.charAt(0).toUpperCase()+u.method.slice(1)}, "${d}");`],v=u.parameters.filter(M=>M.in==="header");for(const M of v)c.push(`request.Headers.Add("${M.name}", "");`);return(E=u.requestBody)!=null&&E.schema&&(c.push("request.Content = new StringContent("),c.push(` ${JSON.stringify(JSON.stringify(u.requestBody.schema))},`),c.push(" System.Text.Encoding.UTF8,"),c.push(` "${u.requestBody.contentType}");`)),c.push(""),c.push("var response = await client.SendAsync(request);"),c.push("var body = await response.Content.ReadAsStringAsync();"),c.push("Console.WriteLine(body);"),c.join(` +`)}function U0({endpoint:u,baseUrl:h="https://api.example.com"}){const[d,c]=B.useState(0),v=["cURL","JavaScript","Python","Go","Java","C#"],E=[k0(u,h),O0(u,h),D0(u,h),R0(u,h),B0(u,h),w0(u,h)];return s.jsxs("div",{style:{marginBottom:16},children:[s.jsx("div",{style:{display:"flex",gap:0,borderBottom:"1px solid var(--bd)",overflowX:"auto",WebkitOverflowScrolling:"touch"},children:v.map((M,D)=>s.jsx("button",{onClick:()=>c(D),style:{padding:"6px 14px",background:"none",border:"none",borderBottom:d===D?"2px solid var(--ac)":"2px solid transparent",color:d===D?"var(--ac)":"var(--txM)",fontWeight:d===D?600:400,fontSize:12,cursor:"pointer",fontFamily:"inherit",whiteSpace:"nowrap"},children:M},M))}),s.jsx("pre",{style:{background:"var(--cdBg)",color:"var(--cdTx)",padding:16,borderRadius:"0 0 6px 6px",fontSize:12,fontFamily:"var(--font-code, monospace)",overflow:"auto",lineHeight:1.6,margin:0},children:E[d]})]})}function H0({endpoint:u,baseUrl:h,defaultExpanded:d=!1,showPlayground:c,playgroundAuth:v}){const[E,M]=B.useState(d),D=(u.operationId||`${u.method}-${u.path}`).toLowerCase().replace(/[^a-z0-9]+/g,"-"),z=u.parameters.length>0||u.requestBody!=null||u.responses.length>0;return s.jsxs("div",{id:D,style:{border:"1px solid var(--bd)",borderRadius:8,marginBottom:12,overflow:"hidden",scrollMarginTop:24},children:[s.jsxs("button",{onClick:()=>z&&M(!E),style:{display:"flex",alignItems:"center",gap:10,width:"100%",padding:"14px 18px",background:"var(--sf)",border:"none",cursor:z?"pointer":"default",textAlign:"left",fontFamily:"inherit",color:"var(--tx)"},children:[s.jsx(z0,{method:u.method}),s.jsx("span",{style:{fontFamily:"var(--font-code, monospace)",fontSize:14,fontWeight:500},children:u.path}),u.deprecated&&s.jsx("span",{"data-testid":"deprecated-badge",style:{padding:"1px 6px",borderRadius:3,fontSize:10,fontWeight:700,background:"#f59e0b33",color:"#f59e0b",textTransform:"uppercase",letterSpacing:"0.05em"},children:"Deprecated"}),u.tags.map(y=>s.jsx("span",{style:{padding:"1px 6px",borderRadius:3,fontSize:10,background:"var(--bd)",color:"var(--txM)"},children:y},y)),s.jsx("span",{style:{flex:1}}),u.summary&&s.jsx("span",{style:{fontSize:13,color:"var(--tx2)",marginRight:8},children:u.summary}),z&&s.jsx("span",{style:{transform:E?"rotate(180deg)":"rotate(0)",transition:"transform 0.2s",fontSize:12,color:"var(--txM)"},children:"▾"})]}),E&&s.jsxs("div",{style:{padding:"16px 18px",borderTop:"1px solid var(--bd)"},children:[u.description&&s.jsx("p",{style:{fontSize:14,color:"var(--tx2)",lineHeight:1.65,marginTop:0,marginBottom:16},children:u.description}),u.parameters.length>0&&s.jsxs("div",{style:{marginBottom:16},children:[s.jsx("h4",{style:{fontSize:13,fontWeight:600,marginBottom:8,color:"var(--tx)"},children:"Parameters"}),s.jsx(C0,{parameters:u.parameters})]}),u.requestBody&&s.jsxs("div",{style:{marginBottom:16},children:[s.jsx("h4",{style:{fontSize:13,fontWeight:600,marginBottom:8,color:"var(--tx)"},children:"Request Body"}),s.jsx(j0,{requestBody:u.requestBody})]}),u.responses.length>0&&s.jsxs("div",{style:{marginBottom:16},children:[s.jsx("h4",{style:{fontSize:13,fontWeight:600,marginBottom:8,color:"var(--tx)"},children:"Responses"}),s.jsx(_0,{responses:u.responses})]}),s.jsxs("div",{children:[s.jsx("h4",{style:{fontSize:13,fontWeight:600,marginBottom:8,color:"var(--tx)"},children:"Code Examples"}),u.codeSamples&&u.codeSamples.length>0?s.jsx(mm,{samples:u.codeSamples}):s.jsx(U0,{endpoint:u,baseUrl:h})]}),c&&s.jsx("div",{style:{marginTop:16},children:s.jsx(A0,{endpoint:u,baseUrl:h||"https://api.example.com",auth:v})})]})]})}function N0({manifest:u,baseUrl:h,showPlayground:d,playgroundAuth:c}){const v=h||(u.servers.length>0?u.servers[0].url:"https://api.example.com"),E=new Map;for(const z of u.endpoints){const y=z.tags.length>0?z.tags[0]:"Other";E.has(y)||E.set(y,[]),E.get(y).push(z)}const M=[];for(const z of u.tags)E.has(z.name)&&M.push(z.name);for(const z of E.keys())M.includes(z)||M.push(z);const D=new Map;for(const z of u.tags)D.set(z.name,z.description);return s.jsxs("div",{style:{display:"flex",gap:32},children:[s.jsxs("nav",{"data-testid":"api-toc",style:{width:200,flexShrink:0,position:"sticky",top:24,alignSelf:"flex-start",maxHeight:"calc(100vh - 48px)",overflowY:"auto"},children:[s.jsx("div",{style:{fontSize:11,fontWeight:700,textTransform:"uppercase",color:"var(--txM)",marginBottom:12,letterSpacing:"0.05em"},children:"Endpoints"}),M.map(z=>{const y=z.toLowerCase().replace(/\s+/g,"-");return s.jsxs("div",{style:{marginBottom:14},children:[s.jsx("a",{href:`#${y}`,onClick:G=>{var R;G.preventDefault(),(R=document.getElementById(y))==null||R.scrollIntoView({behavior:"smooth",block:"start"})},style:{display:"block",fontSize:13,fontWeight:600,color:"var(--tx)",textDecoration:"none",marginBottom:4},children:z}),(E.get(z)||[]).map(G=>{const R=(G.operationId||`${G.method}-${G.path}`).toLowerCase().replace(/[^a-z0-9]+/g,"-");return s.jsxs("a",{href:`#${R}`,onClick:K=>{var nt;K.preventDefault(),(nt=document.getElementById(R))==null||nt.scrollIntoView({behavior:"smooth",block:"start"})},style:{display:"flex",alignItems:"center",gap:6,fontSize:12,color:"var(--tx2)",textDecoration:"none",padding:"3px 0"},children:[s.jsx("span",{style:{fontSize:9,fontWeight:700,fontFamily:"var(--font-code, monospace)",color:pm[G.method]||"#6b7280",width:36,textTransform:"uppercase"},children:G.method}),s.jsx("span",{style:{fontFamily:"var(--font-code, monospace)"},children:G.path})]},`${G.method}-${G.path}`)})]},z)})]}),s.jsxs("div",{style:{flex:1,minWidth:0},children:[s.jsxs("div",{style:{marginBottom:32},children:[s.jsx("h1",{style:{fontSize:28,fontWeight:700,marginBottom:4},children:u.title}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[s.jsxs("span",{style:{padding:"2px 8px",borderRadius:4,fontSize:11,fontWeight:600,background:"var(--sf)",color:"var(--txM)"},children:["v",u.version]}),u.servers.length>0&&s.jsx("span",{style:{fontSize:12,fontFamily:"var(--font-code, monospace)",color:"var(--tx2)"},children:u.servers[0].url})]}),u.description&&s.jsx("p",{style:{fontSize:14,color:"var(--tx2)",lineHeight:1.65,marginTop:0},children:u.description})]}),M.map(z=>s.jsxs("section",{id:z.toLowerCase().replace(/\s+/g,"-"),"data-testid":"tag-section",style:{marginBottom:40},children:[s.jsx("h2",{style:{fontSize:20,fontWeight:700,marginBottom:4},children:z}),D.get(z)&&s.jsx("p",{style:{fontSize:14,color:"var(--tx2)",lineHeight:1.65,marginTop:0,marginBottom:16},children:D.get(z)}),(E.get(z)||[]).map(y=>s.jsx(H0,{endpoint:y,baseUrl:v,showPlayground:d,playgroundAuth:c},`${y.method}-${y.path}`))]},z))]})]})}function q0({href:u,title:h,description:d,icon:c,external:v}){const E=v??u.startsWith("http");return s.jsxs("a",{href:u,target:E?"_blank":void 0,rel:E?"noopener noreferrer":void 0,style:{display:"block",padding:"16px 20px",border:"1px solid var(--bd)",borderRadius:8,textDecoration:"none",color:"inherit",background:"var(--sf)",transition:"border-color 0.15s, background 0.15s",cursor:"pointer"},onMouseEnter:M=>{M.currentTarget.style.borderColor="var(--ac)",M.currentTarget.style.background="var(--sfH)"},onMouseLeave:M=>{M.currentTarget.style.borderColor="var(--bd)",M.currentTarget.style.background="var(--sf)"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[c&&s.jsx("span",{style:{fontSize:18},children:c}),s.jsx("span",{style:{fontWeight:600,fontSize:15,color:"var(--tx)"},children:h}),s.jsx("span",{style:{marginLeft:"auto",color:"var(--tx2)",fontSize:14},children:E?"↗":"→"})]}),d&&s.jsx("p",{style:{margin:"6px 0 0",fontSize:13,color:"var(--tx2)",lineHeight:1.5},children:d})]})}function L0({columns:u=2,children:h}){return s.jsx("div",{style:{display:"grid",gridTemplateColumns:`repeat(${u}, 1fr)`,gap:12,marginTop:16,marginBottom:16},children:h})}const G0={Added:"#22c55e",Changed:"#3b82f6",Deprecated:"#f59e0b",Removed:"#ef4444",Fixed:"#8b5cf6",Security:"#f97316"};function lm(u){return G0[u]||"#6b7280"}function Y0({entries:u,initialLimit:h}){const[d,c]=B.useState(!h),v=d?u:u.slice(0,h||u.length);return u.length===0?s.jsx("div",{"data-testid":"changelog-empty",style:{padding:"40px 0",textAlign:"center",color:"var(--txM)",fontSize:14},children:"No changelog entries found."}):s.jsxs("div",{"data-testid":"changelog-timeline",style:{position:"relative"},children:[s.jsx("div",{style:{position:"absolute",left:15,top:8,bottom:8,width:2,background:"var(--bd)"}}),v.map((E,M)=>s.jsxs("div",{"data-testid":`changelog-entry-${E.version}`,style:{position:"relative",paddingLeft:44,paddingBottom:Ms.jsxs("div",{style:{marginBottom:16},children:[s.jsxs("div",{style:{display:"inline-flex",alignItems:"center",gap:6,marginBottom:8},children:[s.jsx("span",{style:{display:"inline-block",width:8,height:8,borderRadius:"50%",background:lm(D.type)}}),s.jsx("span",{style:{fontSize:12,fontWeight:600,textTransform:"uppercase",letterSpacing:".06em",color:lm(D.type),fontFamily:"var(--font-code, monospace)"},children:D.type})]}),s.jsx("ul",{style:{margin:0,paddingLeft:18,listStyleType:"disc",color:"var(--tx2)"},children:D.items.map((z,y)=>s.jsx("li",{style:{fontSize:14,lineHeight:1.7,color:"var(--tx2)",marginBottom:2},children:z},y))})]},D.type))]},E.version)),!d&&u.length>(h||0)&&s.jsx("div",{style:{textAlign:"center",marginTop:24},children:s.jsxs("button",{"data-testid":"changelog-show-more",onClick:()=>c(!0),style:{background:"none",border:"1px solid var(--bd)",borderRadius:2,padding:"8px 20px",color:"var(--tx2)",fontSize:13,fontFamily:"var(--font-body, inherit)",cursor:"pointer",transition:"border-color .15s, color .15s"},children:["Show all ",u.length," releases"]})})]})}const im={info:{color:"#3b82f6",label:"INFO"},warning:{color:"#f59e0b",label:"WARNING"},tip:{color:"var(--ac, #a78bfa)",label:"TIP"},danger:{color:"#ef4444",label:"DANGER"}};function K0({type:u="info",title:h,children:d}){const c=im[u]||im.info;return s.jsxs("div",{style:{borderLeft:`3px solid ${c.color}`,background:`${c.color}11`,borderRadius:"0 2px 2px 0",padding:"14px 18px",marginBottom:20},children:[h?s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:4},children:[s.jsx("span",{style:{fontWeight:700,fontSize:10,letterSpacing:".08em",color:c.color,fontFamily:"var(--font-code, monospace)"},children:c.label}),s.jsx("span",{style:{fontWeight:600,fontSize:13,color:c.color},children:h})]}):s.jsx("div",{style:{marginBottom:4},children:s.jsx("span",{style:{fontWeight:700,fontSize:10,letterSpacing:".08em",color:c.color,fontFamily:"var(--font-code, monospace)"},children:c.label})}),s.jsx("div",{style:{fontSize:14,lineHeight:1.65,color:"var(--tx2)"},children:d})]})}function X0({items:u,children:h}){const[d,c]=B.useState(0);return s.jsxs("div",{style:{marginBottom:20},children:[s.jsx("div",{style:{display:"flex",gap:0,borderBottom:"1px solid var(--bd)"},children:u.map((v,E)=>s.jsx("button",{onClick:()=>c(E),style:{padding:"8px 16px",background:"none",border:"none",borderBottom:d===E?"2px solid var(--ac)":"2px solid transparent",color:d===E?"var(--ac)":"var(--txM)",fontWeight:d===E?600:400,fontSize:13,cursor:"pointer",fontFamily:"inherit"},children:v},E))}),s.jsx("div",{style:{padding:"16px 0"},children:h[d]})]})}function Q0({title:u,icon:h,href:d,children:c}){const v=s.jsxs("div",{style:{border:"1px solid var(--bd)",borderRadius:2,padding:"20px",transition:"border-color 0.15s",cursor:d?"pointer":"default"},children:[h&&s.jsx("span",{style:{fontSize:24,marginBottom:8,display:"block"},children:h}),s.jsx("div",{style:{fontWeight:600,fontSize:14,marginBottom:4},children:u}),c&&s.jsx("div",{style:{fontSize:13,color:"var(--txM)",lineHeight:1.5},children:c})]});return d?s.jsx("a",{href:d,style:{textDecoration:"none",color:"inherit"},children:v}):v}function V0({cols:u=2,children:h}){return s.jsx("div",{style:{display:"grid",gridTemplateColumns:`repeat(${u}, 1fr)`,gap:12,marginBottom:20},children:h})}function Z0({children:u}){return s.jsx("div",{style:{paddingLeft:24,borderLeft:"2px solid var(--bd)",marginBottom:20},children:sm.Children.map(u,(h,d)=>s.jsxs("div",{style:{position:"relative",paddingBottom:20},children:[s.jsx("div",{style:{position:"absolute",left:-33,top:0,width:20,height:20,borderRadius:"50%",background:"var(--ac)",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontSize:11,fontWeight:700},children:d+1}),s.jsx("div",{style:{paddingLeft:8},children:h})]}))})}function J0({title:u,children:h}){const[d,c]=B.useState(!1);return s.jsxs("div",{style:{border:"1px solid var(--bd)",borderRadius:2,marginBottom:8,overflow:"hidden"},children:[s.jsxs("button",{onClick:()=>c(!d),style:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"12px 16px",background:"var(--sf)",border:"none",cursor:"pointer",fontWeight:500,fontSize:14,color:"var(--tx)",fontFamily:"inherit"},children:[u,s.jsx("span",{style:{transform:d?"rotate(180deg)":"rotate(0)",transition:"transform 0.2s"},children:"▾"})]}),d&&s.jsx("div",{style:{padding:"12px 16px",borderTop:"1px solid var(--bd)",fontSize:14,color:"var(--tx2)",lineHeight:1.65},children:h})]})}const W0={install:{npm:"npm install",yarn:"yarn add",pnpm:"pnpm add",bun:"bun add"},"install -D":{npm:"npm install -D",yarn:"yarn add -D",pnpm:"pnpm add -D",bun:"bun add -d"},uninstall:{npm:"npm uninstall",yarn:"yarn remove",pnpm:"pnpm remove",bun:"bun remove"},run:{npm:"npm run",yarn:"yarn",pnpm:"pnpm",bun:"bun run"},exec:{npm:"npx",yarn:"yarn dlx",pnpm:"pnpm dlx",bun:"bunx"},init:{npm:"npm init",yarn:"yarn init",pnpm:"pnpm init",bun:"bun init"},create:{npm:"npm create",yarn:"yarn create",pnpm:"pnpm create",bun:"bun create"}};function F0(u,h){for(const[d,c]of Object.entries(W0))if(u.startsWith(d+" ")||u===d){const v=u.slice(d.length);return(c[h]||d)+v}return`${h} ${u}`}function $0({command:u}){const[h,d]=B.useState(0),[c,v]=B.useState(!1),E=["npm","yarn","pnpm","bun"],M=F0(u,E[h]);return s.jsxs("div",{style:{border:"1px solid var(--bd)",borderRadius:2,marginBottom:16,overflow:"hidden"},children:[s.jsx("div",{style:{display:"flex",borderBottom:"1px solid var(--bd)",background:"var(--sf)",overflowX:"auto"},children:E.map((D,z)=>s.jsx("button",{onClick:()=>{d(z),v(!1)},style:{padding:"8px 14px",background:"none",border:"none",cursor:"pointer",fontSize:12,fontFamily:"var(--font-code)",fontWeight:z===h?600:400,color:z===h?"var(--ac)":"var(--txM)",borderBottom:z===h?"2px solid var(--ac)":"2px solid transparent",whiteSpace:"nowrap"},children:D},D))}),s.jsxs("div",{style:{display:"flex",alignItems:"center",padding:"10px 14px",background:"var(--cdBg)",gap:8},children:[s.jsx("code",{style:{flex:1,fontFamily:"var(--font-code)",fontSize:13,color:"var(--cdTx)",whiteSpace:"pre",overflowX:"auto"},children:M}),s.jsx("button",{onClick:()=>{var D;(D=navigator.clipboard)==null||D.writeText(M),v(!0),setTimeout(()=>v(!1),2e3)},style:{background:"none",border:"none",cursor:"pointer",color:"var(--txM)",fontSize:12,fontFamily:"var(--font-code)",flexShrink:0},children:c?"✓":"Copy"})]})]})}function I0({name:u,fields:h}){return s.jsxs("div",{style:{marginBottom:16},children:[u&&s.jsx("h4",{style:{fontFamily:"var(--font-code)",fontSize:15,marginBottom:8,color:"var(--tx)"},children:u}),s.jsx("div",{style:{overflowX:"auto",WebkitOverflowScrolling:"touch"},children:s.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:13,fontFamily:"var(--font-body)"},children:[s.jsx("thead",{children:s.jsx("tr",{style:{borderBottom:"2px solid var(--bd)"},children:["Property","Type","Required","Default","Description"].map(d=>s.jsx("th",{style:{textAlign:"left",padding:"8px 10px",color:"var(--txM)",fontWeight:600,fontSize:11,textTransform:"uppercase",letterSpacing:".05em",whiteSpace:"nowrap"},children:d},d))})}),s.jsx("tbody",{children:h.map(d=>s.jsxs("tr",{style:{borderBottom:"1px solid var(--bd)"},children:[s.jsx("td",{style:{padding:"8px 10px",fontFamily:"var(--font-code)",fontWeight:500,color:"var(--tx)"},children:d.name}),s.jsx("td",{style:{padding:"8px 10px",fontFamily:"var(--font-code)",fontSize:12,color:"var(--ac)"},children:d.type}),s.jsx("td",{style:{padding:"8px 10px"},children:d.required&&s.jsx("span",{style:{fontSize:10,fontWeight:600,color:"#e04040",background:"rgba(224,64,64,0.1)",padding:"2px 6px",borderRadius:2},children:"required"})}),s.jsx("td",{style:{padding:"8px 10px",fontFamily:"var(--font-code)",fontSize:12,color:"var(--txM)"},children:d.default||"—"}),s.jsx("td",{style:{padding:"8px 10px",color:"var(--tx2)"},children:d.description||""})]},d.name))})]})})]})}function P0({name:u}){return s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,padding:"3px 0",fontFamily:"var(--font-code)",fontSize:13,color:"var(--tx2)"},children:[s.jsx("span",{style:{opacity:.6},children:"📄"})," ",u]})}function tg({name:u,defaultOpen:h,children:d}){const[c,v]=B.useState(h??!1);return s.jsxs("div",{children:[s.jsxs("button",{onClick:()=>v(!c),style:{display:"flex",alignItems:"center",gap:6,padding:"3px 0",background:"none",border:"none",cursor:"pointer",fontFamily:"var(--font-code)",fontSize:13,color:"var(--tx)",fontWeight:500},children:[s.jsx("span",{children:c?"📂":"📁"})," ",u]}),c&&s.jsx("div",{style:{paddingLeft:18,borderLeft:"1px solid var(--bd)",marginLeft:8},children:d})]})}function Iu({children:u}){return s.jsx("div",{style:{border:"1px solid var(--bd)",borderRadius:2,padding:"12px 16px",background:"var(--cdBg)",marginBottom:16},children:u})}Iu.File=P0;Iu.Folder=tg;const eg={Callout:K0,Tabs:X0,Card:Q0,CardGroup:V0,Steps:Z0,Accordion:J0,ChangelogTimeline:Y0,PackageManager:$0,TypeTable:I0,FileTree:Iu,CodeSamples:mm,LinkCard:q0,CardGrid:L0},ng=` + @import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Bricolage+Grotesque:wght@300;400;500;600;700&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;0,700;1,300;1,400;1,700&family=Fira+Code:wght@400;500;600&family=Bodoni+Moda:ital,wght@0,400;0,700;0,900;1,400&family=Space+Grotesk:wght@400;500;600;700&family=Source+Code+Pro:wght@400;500;600&family=Inter:wght@300;400;500;600;700&display=swap'); + + html, body { margin: 0; padding: 0; height: 100%; overflow: clip; } + #tome-root { height: 100%; overflow: clip; } + + .tome-content h1 { display: none; } + .tome-content h2 { font-family: var(--font-body); font-size: 1.35em; font-weight: 600; margin-top: 2em; margin-bottom: 0.5em; letter-spacing: 0.01em; } + .tome-content h3 { font-family: var(--font-body); font-size: 1.15em; font-weight: 600; margin-top: 1.5em; margin-bottom: 0.5em; } + .tome-content h4 { font-family: var(--font-body); font-size: 1.05em; font-weight: 600; margin-top: 1.2em; margin-bottom: 0.5em; } + .tome-content p { color: var(--tx2); line-height: 1.8; margin-bottom: 1em; font-size: 14.5px; } + .tome-content a { color: var(--ac); text-decoration: none; } + .tome-content a:hover { text-decoration: underline; } + .tome-content .heading-anchor { display: none; } + .tome-content ul, .tome-content ol { color: var(--tx2); padding-inline-start: 1.5em; margin-bottom: 1em; } + .tome-content li { margin-bottom: 0.3em; line-height: 1.7; } + .tome-content code { font-family: var(--font-code); font-size: 0.88em; background: var(--cdBg); padding: 0.15em 0.4em; border-radius: 2px; color: var(--ac); } + .tome-content pre { margin-bottom: 1.2em; border-radius: 2px; overflow-x: auto; border: 1px solid var(--bd); } + .tome-content pre code { background: none; padding: 1em 1.2em; display: block; font-size: 12.5px; line-height: 1.7; color: var(--cdTx); } + .tome-content blockquote { border-inline-start: 3px solid var(--ac); padding: 0.5em 1em; margin: 1em 0; background: var(--acD); border-radius: 0 2px 2px 0; } + .tome-content blockquote p { color: var(--tx2); margin: 0; } + .tome-content table { width: 100%; border-collapse: collapse; margin-bottom: 1em; } + .tome-content th, .tome-content td { padding: 0.5em 0.8em; border: 1px solid var(--bd); text-align: start; font-size: 0.9em; } + .tome-content th { background: var(--sf); font-weight: 600; } + .tome-content img { max-width: 100%; border-radius: 2px; cursor: zoom-in; } + .tome-content hr { border: none; border-top: 1px solid var(--bd); margin: 2em 0; } + .tome-mermaid { margin: 1.2em 0; text-align: center; overflow-x: auto; } + .tome-mermaid svg { max-width: 100%; height: auto; overflow: visible; } + .tome-mermaid svg .nodeLabel { overflow: visible; white-space: nowrap; } + /* Ensure mermaid text meets WCAG AA contrast in light mode */ + /* Mermaid v11 uses foreignObject with inline-styled spans — !important needed */ + html:not(.dark) .tome-mermaid svg .nodeLabel, + html:not(.dark) .tome-mermaid svg .nodeLabel span, + html:not(.dark) .tome-mermaid svg .nodeLabel div, + html:not(.dark) .tome-mermaid svg foreignObject div, + html:not(.dark) .tome-mermaid svg foreignObject span { color: #1a1a1a !important; } + html:not(.dark) .tome-mermaid svg .edgeLabel, + html:not(.dark) .tome-mermaid svg .edgeLabel span { color: #333 !important; } + html:not(.dark) .tome-mermaid svg text { fill: #1a1a1a !important; } + html:not(.dark) .tome-mermaid svg .node rect, + html:not(.dark) .tome-mermaid svg .node polygon { stroke: #555 !important; } + /* Dark mode: force bright text in mermaid nodes for readability */ + html.dark .tome-mermaid svg .nodeLabel, + html.dark .tome-mermaid svg .nodeLabel span, + html.dark .tome-mermaid svg .nodeLabel div, + html.dark .tome-mermaid svg foreignObject div, + html.dark .tome-mermaid svg foreignObject span { color: #f0f0f0 !important; } + html.dark .tome-mermaid svg .edgeLabel, + html.dark .tome-mermaid svg .edgeLabel span { color: #ddd !important; } + html.dark .tome-mermaid svg text { fill: #f0f0f0 !important; } + + /* Mobile responsive content */ + @media (max-width: 767px) { + .tome-content h2 { font-size: 1.2em; margin-top: 1.5em; } + .tome-content h3 { font-size: 1.05em; } + .tome-content pre code { font-size: 12px; padding: 0.8em 1em; } + .tome-content table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; } + .tome-content blockquote { margin: 0.8em 0; } + } + + /* Selection style */ + ::selection { background: var(--acD); color: var(--ac); } + + /* Scrollbar style */ + ::-webkit-scrollbar { width: 5px; height: 5px; } + ::-webkit-scrollbar-track { background: transparent; } + ::-webkit-scrollbar-thumb { background: var(--bd); border-radius: 10px; } + + /* Grain overlay */ + .tome-grain::before { + content: ""; position: fixed; inset: 0; z-index: 9999; pointer-events: none; + opacity: .35; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E"); + background-repeat: repeat; background-size: 256px; + } + + /* ── Expressive code blocks ───────────────────────────── */ + + /* Code block wrapper (for titled blocks) */ + .tome-code-block-wrapper { position: relative; margin-bottom: 1.2em; border: 1px solid var(--bd); border-radius: 2px; overflow: hidden; } + .tome-code-block-wrapper pre { margin-bottom: 0; border: none; border-radius: 0; } + .tome-code-title { + font-family: var(--font-code); font-size: 12px; color: var(--tx2); + background: var(--sf); padding: 6px 12px; border-bottom: 1px solid var(--bd); + letter-spacing: 0.01em; font-weight: 500; + } + + /* Line highlighting */ + .tome-content pre .line.tome-line-highlight { + background: rgba(139, 148, 158, 0.1); + display: inline-block; width: 100%; margin: 0 -1.2em; padding: 0 1.2em; + } + html.dark .tome-content pre .line.tome-line-highlight { + background: rgba(200, 210, 220, 0.08); + } + + /* Diff lines */ + .tome-content pre .line.tome-line-added { + background: rgba(34, 197, 94, 0.12); + display: inline-block; width: 100%; margin: 0 -1.2em; padding: 0 1.2em; + } + .tome-content pre .line.tome-line-removed { + background: rgba(239, 68, 68, 0.12); + display: inline-block; width: 100%; margin: 0 -1.2em; padding: 0 1.2em; + } + html.dark .tome-content pre .line.tome-line-added { background: rgba(34, 197, 94, 0.15); } + html.dark .tome-content pre .line.tome-line-removed { background: rgba(239, 68, 68, 0.15); } + + /* Line numbers (CSS counter) */ + .tome-content pre[data-line-numbers] code { + counter-reset: line; + } + .tome-content pre[data-line-numbers] .line::before { + counter-increment: line; + content: counter(line); + display: inline-block; width: 2.5em; margin-inline-end: 1em; + text-align: end; color: var(--txM); opacity: 0.4; + font-size: 0.85em; user-select: none; + border-inline-end: 1px solid var(--bd); padding-inline-end: 0.8em; margin-inline-end: 0.8em; + } + + /* Word highlighting */ + .tome-word-highlight { + background: rgba(139, 148, 158, 0.2); border-radius: 2px; + padding: 1px 3px; margin: 0 -1px; + } + html.dark .tome-word-highlight { + background: rgba(200, 210, 220, 0.15); + } + + /* Copy button */ + .tome-content pre { position: relative; } + .tome-copy-btn { + position: absolute; top: 8px; inset-inline-end: 8px; + font-family: var(--font-code); font-size: 11px; + color: var(--tx2); background: var(--sf); border: 1px solid var(--bd); + padding: 3px 8px; border-radius: 2px; cursor: pointer; + opacity: 0; transition: opacity 0.15s; + z-index: 2; line-height: 1.4; + } + .tome-content pre:hover .tome-copy-btn, + .tome-copy-btn:focus { opacity: 1; } + .tome-copy-btn:hover { background: var(--sfH); } + + /* Shiki dual-theme support */ + .shiki { background: var(--cdBg) !important; } + + /* Dark mode: switch Shiki tokens from light-theme inline colors to --shiki-dark CSS vars */ + html.dark .shiki, + html.dark .shiki span { + color: var(--shiki-dark) !important; + } + + /* Brighten dim comment tokens (github-dark #6A737D is too low-contrast on dark backgrounds) */ + html.dark .shiki span[style*="--shiki-dark:#6A737D"] { + --shiki-dark: #a0aab5 !important; + } + + /* Light mode: darken low-contrast github-light tokens for WCAG AA on --cdBg backgrounds */ + html:not(.dark) .shiki span[style*="color:#6A737D"] { color: #57606a !important; } + html:not(.dark) .shiki span[style*="color:#E36209"] { color: #b35405 !important; } + html:not(.dark) .shiki span[style*="color:#6F42C1"] { color: #5a32a3 !important; } + html:not(.dark) .shiki span[style*="color:#22863A"] { color: #1a6e2e !important; } + html:not(.dark) .shiki span[style*="color:#D73A49"] { color: #b62324 !important; } + html:not(.dark) .shiki span[style*="color:#005CC5"] { color: #0349b4 !important; } + + /* ── Twoslash type hover tooltips ───────────────────── */ + .twoslash-hover { + position: relative; + border-bottom: 1px dotted var(--tx2); + cursor: help; + } + .twoslash-popup-container { + position: absolute; + opacity: 0; + display: none; + z-index: 10; + left: 0; + top: 100%; + margin-top: 4px; + padding: 6px 10px; + background: var(--sf); + border: 1px solid var(--bd); + border-radius: 6px; + font-size: 12px; + font-family: var(--font-code); + color: var(--tx); + white-space: pre-wrap; + max-width: 500px; + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + pointer-events: none; + } + .twoslash-hover:hover .twoslash-popup-container { + opacity: 1; + display: block; + } + /* Twoslash error/warning underlines */ + .twoslash-error { + position: relative; + background: rgba(239, 68, 68, 0.1); + border-bottom: 2px wavy rgba(239, 68, 68, 0.6); + } + /* Twoslash highlighted identifiers */ + .twoslash-highlighted { + background: rgba(139, 148, 158, 0.15); + border-radius: 2px; + padding: 1px 2px; + } + /* Twoslash type annotation line (^?) */ + .twoslash-popup-code .shiki { background: transparent !important; padding: 0; margin: 0; } + .twoslash-popup-code .shiki code { padding: 0; font-size: 12px; } + html.dark .twoslash-popup-container { + background: var(--sf); + border-color: var(--bd); + box-shadow: 0 4px 12px rgba(0,0,0,0.3); + } +`,ko=(Jn.basePath||"/").replace(/\/$/,"");function ag(u){return cm(u,ko,Wn)}function Wu(u){return f0(u,ko,Wn)}const hm=h0(window.location.pathname,window.location.hash,Wn,ko,cm),lg=fm(hm,Wn,dm);function ig(){var W,I,ct,Q;const[u,h]=B.useState(hm),[d,c]=B.useState(null),[v,E]=B.useState(!0),M=B.useRef(0),D=B.useCallback(async(Y,H)=>{const U=++M.current;E(!0);let at;try{at=await fm(Y,Wn,dm)}catch(P){if(M.current!==U)return;console.error(`[tome] Navigation failed for page: ${Y}`,P),at=null}if(M.current!==U)return;const lt=Wu(Y);if(H!=null&&H.replace?window.history.replaceState(null,"",lt):window.history.pushState(null,"",lt),h(Y),c(at),E(!1),!(H!=null&&H.skipScroll)){const P=window.location.hash.slice(1);P?requestAnimationFrame(()=>{const mt=document.getElementById(P);mt&&mt.scrollIntoView({behavior:"smooth",block:"start"})}):window.scrollTo(0,0)}},[]);B.useEffect(()=>{const Y=window.location.hash.slice(1);if(Y&&Wn.some(H=>H.id===Y)){const H=Wu(Y);window.history.replaceState(null,"",H),D(Y,{replace:!0})}else{const H=Wu(u);window.history.replaceState(null,"",H),lg.then(U=>{c(U),E(!1)})}},[]),B.useEffect(()=>{const Y=()=>{const H=ag(window.location.pathname);H&&H!==u&&D(H,{replace:!0,skipScroll:!0})};return window.addEventListener("popstate",Y),()=>window.removeEventListener("popstate",Y)},[u,D]);const z=B.useRef(null),[y,G]=B.useState(()=>{var H,U;if(typeof document>"u")return"light";if(document.documentElement.classList.contains("dark"))return"dark";const Y=((H=Jn.theme)==null?void 0:H.mode)||"auto";return Y==="dark"?"dark":Y==="light"?"light":(U=window.matchMedia)!=null&&U.call(window,"(prefers-color-scheme: dark)").matches?"dark":"light"});B.useEffect(()=>{const Y=new MutationObserver(()=>{const H=document.documentElement.classList.contains("dark");G(H?"dark":"light")});return Y.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),()=>Y.disconnect()},[]),B.useEffect(()=>{const Y=document.querySelectorAll(".tome-mermaid[data-mermaid]");if(Y.length===0)return;let H=!1;const U="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";return(async()=>{try{z.current||(z.current=(await import(U)).default);const at=z.current;if(H)return;const lt=y==="dark",P=getComputedStyle(document.documentElement).getPropertyValue("--font-body").trim()||"sans-serif";at.initialize({startOnLoad:!1,theme:lt?"dark":"default",fontFamily:P,flowchart:{padding:15,nodeSpacing:30,rankSpacing:40}});for(let mt=0;mt{lt.textContent="Failed to load diagram renderer",lt.style.cssText="padding:16px;color:var(--txM);font-size:13px;border:1px dashed var(--bd);border-radius:2px;text-align:center;"})}})(),()=>{H=!0}},[d,v,y]),B.useEffect(()=>{if(v)return;const Y=document.querySelectorAll(".tome-content pre"),H=[];return Y.forEach(U=>{if(U.querySelector(".tome-copy-btn"))return;const at=document.createElement("button");at.className="tome-copy-btn",at.textContent="Copy",at.addEventListener("click",async()=>{const lt=U.querySelector("code");if(lt)try{await navigator.clipboard.writeText(lt.textContent||""),at.textContent="Copied!",setTimeout(()=>{at.textContent="Copy"},2e3)}catch{at.textContent="Failed",setTimeout(()=>{at.textContent="Copy"},2e3)}}),U.appendChild(at),H.push(at)}),()=>{H.forEach(U=>U.remove())}},[d,v]);const R=Wn.map(Y=>({id:Y.id,title:Y.frontmatter.title,description:Y.frontmatter.description})),K=Wn.find(Y=>Y.id===u),nt=g0(K),bt=p0(Jn.editLink,K==null?void 0:K.filePath),Ot=(K==null?void 0:K.locale)||(Zu==null?void 0:Zu.defaultLocale)||"en",jt="ltr";return B.useEffect(()=>{const Y=document.querySelectorAll(".tome-math[data-math]").length>0;if(!Jn.math&&!Y)return;const H="tome-katex-css";if(document.getElementById(H))return;const U=document.createElement("link");U.id=H,U.rel="stylesheet",U.href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css",U.crossOrigin="anonymous",document.head.appendChild(U)},[d,v]),B.useEffect(()=>{const Y=document.querySelectorAll(".tome-math[data-math]");if(Y.length===0)return;let H=!1;const U="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.mjs";return(async()=>{try{const at=(await import(U)).default;if(H)return;for(const lt of Y){const P=lt.getAttribute("data-math");if(P)try{const mt=atob(P),tt=lt.classList.contains("tome-math-block");at.render(mt,lt,{displayMode:tt,throwOnError:!1})}catch(mt){console.warn("[tome] KaTeX render failed:",mt)}}}catch(at){console.warn("[tome] Failed to load KaTeX from CDN:",at)}})(),()=>{H=!0}},[d,v]),s.jsxs(s.Fragment,{children:[s.jsx("style",{children:ng}),s.jsx(r0,{config:Jn,navigation:v0,currentPageId:u,pageHtml:d!=null&&d.isMdx?void 0:v?"":(d==null?void 0:d.html)||"

    Page not found

    ",pageComponent:d!=null&&d.isMdx?d.component:void 0,mdxComponents:eg,pageTitle:(d==null?void 0:d.frontmatter.title)||(v?"":"Not Found"),pageDescription:d==null?void 0:d.frontmatter.description,headings:(d==null?void 0:d.headings)||[],tocEnabled:(d==null?void 0:d.frontmatter.toc)!==!1,editUrl:bt,lastUpdated:K==null?void 0:K.lastUpdated,changelogEntries:d!=null&&d.isMdx||d==null?void 0:d.changelogEntries,apiManifest:!(d!=null&&d.isMdx)&&(d!=null&&d.isApiReference)?d.apiManifest:void 0,apiBaseUrl:(W=Jn.api)==null?void 0:W.baseUrl,apiPlayground:(I=Jn.api)==null?void 0:I.playground,apiAuth:(ct=Jn.api)==null?void 0:ct.auth,ApiReferenceComponent:N0,onNavigate:D,allPages:R,docContext:x0,versioning:void 0,currentVersion:nt,basePath:ko,isDraft:((Q=K==null?void 0:K.frontmatter)==null?void 0:Q.draft)===!0,dir:jt,i18n:void 0,currentLocale:Ot,overrides:b0})]})}const om=document.getElementById("tome-root");om&&wh.createRoot(om).render(s.jsx(ig,{})); diff --git a/assets/index-CGDazwHL.js b/assets/index-CGDazwHL.js new file mode 100644 index 00000000..355538b6 --- /dev/null +++ b/assets/index-CGDazwHL.js @@ -0,0 +1,75 @@ +const n={frontmatter:{title:"Kit",description:"Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.",hidden:!1,toc:!1,draft:!1},html:`
    + KIT +
    +

    A powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.

    +

    Features

    +
      +
    • Multi-Provider LLM Support — Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more
    • +
    • Built-in Core Tools — bash, read, write, edit, grep, find, ls, spawn_subagent with no MCP overhead
    • +
    • MCP Integration — Connect external MCP servers for expanded capabilities
    • +
    • Extension System — Write custom tools, commands, widgets, and UI modifications in Go
    • +
    • Interactive TUI — Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering
    • +
    • Session Management — Tree-based conversation history with branching support
    • +
    • Non-Interactive Mode — Script-friendly positional args with JSON output
    • +
    • ACP Server — Run Kit as an Agent Client Protocol agent over stdio
    • +
    • Go SDK — Embed Kit in your own applications
    • +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ResourceDescription
    InstallationGet Kit up and running
    Quick StartYour first Kit session
    ConfigurationCustomize Kit for your workflow
    ExtensionsBuild custom tools and UI components
    Go SDKEmbed Kit in your applications
    `,headings:[{depth:2,text:"Features",id:"features"},{depth:2,text:"Quick links",id:"quick-links"}],raw:` +
    + KIT +
    + +A powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system. + +## Features + +- **Multi-Provider LLM Support** — Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more +- **Built-in Core Tools** — bash, read, write, edit, grep, find, ls, spawn_subagent with no MCP overhead +- **MCP Integration** — Connect external MCP servers for expanded capabilities +- **Extension System** — Write custom tools, commands, widgets, and UI modifications in Go +- **Interactive TUI** — Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering +- **Session Management** — Tree-based conversation history with branching support +- **Non-Interactive Mode** — Script-friendly positional args with JSON output +- **ACP Server** — Run Kit as an [Agent Client Protocol](https://agentclientprotocol.com) agent over stdio +- **Go SDK** — Embed Kit in your own applications + +## Quick links + +| Resource | Description | +|----------|-------------| +| [Installation](/installation) | Get Kit up and running | +| [Quick Start](/quick-start) | Your first Kit session | +| [Configuration](/configuration) | Customize Kit for your workflow | +| [Extensions](/extensions/overview) | Build custom tools and UI components | +| [Go SDK](/sdk/overview) | Embed Kit in your applications | +`};export{n as default}; diff --git a/assets/index-Di_r5hA0.css b/assets/index-Di_r5hA0.css new file mode 100644 index 00000000..1baabe9f --- /dev/null +++ b/assets/index-Di_r5hA0.css @@ -0,0 +1 @@ +:root,:root[data-theme=dark],:root[data-theme=light],html,html[data-theme=dark],#tome-root,#tome-root *,[data-theme],body,div{--bg: #08080a !important;--sf: #0e0e12 !important;--sfH: #141418 !important;--bd: #1a1a22 !important;--tx: #e8e0e0 !important;--tx2: #8a8090 !important;--txM: #6a6070 !important;--ac: #e03030 !important;--acD: rgba(224, 48, 48, .12) !important;--acT: #ff4444 !important;--cdBg: #0a0a0e !important;--cdTx: #c8a0a0 !important;--sbBg: #0a0a0d !important;--hdBg: rgba(8, 8, 10, .92) !important}h1,h2,h3,h4,h5,h6{color:#e8e0e0!important;font-style:normal!important} diff --git a/assets/installation-DaBrcZPn.js b/assets/installation-DaBrcZPn.js new file mode 100644 index 00000000..45e06904 --- /dev/null +++ b/assets/installation-DaBrcZPn.js @@ -0,0 +1,78 @@ +const n={frontmatter:{title:"Installation",description:"Install Kit using npm, Go, or build from source.",hidden:!1,toc:!0,draft:!1},html:`

    Installation

    + +
    npm install -g @mark3labs/kit
    +

    Using Go

    +
    go install github.com/mark3labs/kit/cmd/kit@latest
    +

    Building from source

    +
    git clone https://github.com/mark3labs/kit.git
    +cd kit
    +go build -o kit ./cmd/kit
    +

    Verifying the installation

    +

    After installing, verify Kit is available:

    +
    kit --help
    +

    Setting up a provider

    +

    Kit needs at least one LLM provider configured. Set an API key for your preferred provider:

    +
    # Anthropic (default provider)
    +export ANTHROPIC_API_KEY="sk-..."
    +
    +# OpenAI
    +export OPENAI_API_KEY="sk-..."
    +
    +# Google Gemini
    +export GOOGLE_API_KEY="..."
    +

    For OAuth-enabled providers like Anthropic, you can also authenticate interactively:

    +
    kit auth login anthropic
    +

    See Providers for the full list of supported providers and their configuration.

    `,headings:[{depth:2,text:"Using npm (recommended)",id:"using-npm-recommended"},{depth:2,text:"Using Go",id:"using-go"},{depth:2,text:"Building from source",id:"building-from-source"},{depth:2,text:"Verifying the installation",id:"verifying-the-installation"},{depth:2,text:"Setting up a provider",id:"setting-up-a-provider"}],raw:` +# Installation + +## Using npm (recommended) + +\`\`\`bash +npm install -g @mark3labs/kit +\`\`\` + +## Using Go + +\`\`\`bash +go install github.com/mark3labs/kit/cmd/kit@latest +\`\`\` + +## Building from source + +\`\`\`bash +git clone https://github.com/mark3labs/kit.git +cd kit +go build -o kit ./cmd/kit +\`\`\` + +## Verifying the installation + +After installing, verify Kit is available: + +\`\`\`bash +kit --help +\`\`\` + +## Setting up a provider + +Kit needs at least one LLM provider configured. Set an API key for your preferred provider: + +\`\`\`bash +# Anthropic (default provider) +export ANTHROPIC_API_KEY="sk-..." + +# OpenAI +export OPENAI_API_KEY="sk-..." + +# Google Gemini +export GOOGLE_API_KEY="..." +\`\`\` + +For OAuth-enabled providers like Anthropic, you can also authenticate interactively: + +\`\`\`bash +kit auth login anthropic +\`\`\` + +See [Providers](/providers) for the full list of supported providers and their configuration. +`};export{n as default}; diff --git a/assets/json-output-B1QZabVS.js b/assets/json-output-B1QZabVS.js new file mode 100644 index 00000000..afb88fcf --- /dev/null +++ b/assets/json-output-B1QZabVS.js @@ -0,0 +1,240 @@ +const s={frontmatter:{title:"JSON Output",description:"Machine-readable JSON output for scripting and automation.",hidden:!1,toc:!0,draft:!1},html:`

    JSON Output

    +

    Use the --json flag to get structured output for scripting and automation:

    +
    kit "Explain main.go" --json --quiet --no-session
    +

    Response format

    +
    {
    +  "response": "Final assistant response text",
    +  "model": "anthropic/claude-haiku-3-5-20241022",
    +  "stop_reason": "end_turn",
    +  "session_id": "a1b2c3d4e5f6",
    +  "usage": {
    +    "input_tokens": 1024,
    +    "output_tokens": 512,
    +    "total_tokens": 1536,
    +    "cache_read_tokens": 0,
    +    "cache_creation_tokens": 0
    +  },
    +  "messages": [
    +    {
    +      "role": "assistant",
    +      "parts": [
    +        {"type": "text", "data": "..."},
    +        {"type": "tool_call", "data": {"name": "...", "args": "..."}},
    +        {"type": "tool_result", "data": {"name": "...", "result": "..."}}
    +      ]
    +    }
    +  ]
    +}
    +

    Fields

    +

    Top-level

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeDescription
    responsestringThe final assistant response text
    modelstringThe model that was used
    stop_reasonstringWhy the model stopped (e.g., end_turn)
    session_idstringSession identifier (omitted in --no-session mode)
    usageobjectToken usage statistics
    messagesarrayFull conversation history
    +

    Usage

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeDescription
    input_tokensintTokens sent to the model
    output_tokensintTokens generated by the model
    total_tokensintSum of input and output tokens
    cache_read_tokensintTokens read from prompt cache
    cache_creation_tokensintTokens written to prompt cache
    +

    Message parts

    +

    Each message contains a parts array with typed entries:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TypeDescription
    textAssistant text content
    tool_callTool invocation with name and args
    tool_resultTool execution result
    reasoningExtended thinking content
    finishEnd-of-turn marker
    +

    Parsing in scripts

    +

    bash + jq

    +
    result=$(kit "Count files" --json --quiet --no-session)
    +response=$(echo "$result" | jq -r '.response')
    +tokens=$(echo "$result" | jq '.usage.total_tokens')
    +

    Go SDK

    +

    For Go programs, use the SDK's PromptResult method instead of parsing JSON:

    +
    result, err := host.PromptResult(ctx, "Count files")
    +fmt.Println(result.Response)
    +fmt.Println(result.Usage.TotalTokens)
    `,headings:[{depth:2,text:"Response format",id:"response-format"},{depth:2,text:"Fields",id:"fields"},{depth:3,text:"Top-level",id:"top-level"},{depth:3,text:"Usage",id:"usage"},{depth:3,text:"Message parts",id:"message-parts"},{depth:2,text:"Parsing in scripts",id:"parsing-in-scripts"},{depth:3,text:"bash + jq",id:"bash--jq"},{depth:3,text:"Go SDK",id:"go-sdk"}],raw:` +# JSON Output + +Use the \`--json\` flag to get structured output for scripting and automation: + +\`\`\`bash +kit "Explain main.go" --json --quiet --no-session +\`\`\` + +## Response format + +\`\`\`json +{ + "response": "Final assistant response text", + "model": "anthropic/claude-haiku-3-5-20241022", + "stop_reason": "end_turn", + "session_id": "a1b2c3d4e5f6", + "usage": { + "input_tokens": 1024, + "output_tokens": 512, + "total_tokens": 1536, + "cache_read_tokens": 0, + "cache_creation_tokens": 0 + }, + "messages": [ + { + "role": "assistant", + "parts": [ + {"type": "text", "data": "..."}, + {"type": "tool_call", "data": {"name": "...", "args": "..."}}, + {"type": "tool_result", "data": {"name": "...", "result": "..."}} + ] + } + ] +} +\`\`\` + +## Fields + +### Top-level + +| Field | Type | Description | +|-------|------|-------------| +| \`response\` | string | The final assistant response text | +| \`model\` | string | The model that was used | +| \`stop_reason\` | string | Why the model stopped (e.g., \`end_turn\`) | +| \`session_id\` | string | Session identifier (omitted in \`--no-session\` mode) | +| \`usage\` | object | Token usage statistics | +| \`messages\` | array | Full conversation history | + +### Usage + +| Field | Type | Description | +|-------|------|-------------| +| \`input_tokens\` | int | Tokens sent to the model | +| \`output_tokens\` | int | Tokens generated by the model | +| \`total_tokens\` | int | Sum of input and output tokens | +| \`cache_read_tokens\` | int | Tokens read from prompt cache | +| \`cache_creation_tokens\` | int | Tokens written to prompt cache | + +### Message parts + +Each message contains a \`parts\` array with typed entries: + +| Type | Description | +|------|-------------| +| \`text\` | Assistant text content | +| \`tool_call\` | Tool invocation with name and args | +| \`tool_result\` | Tool execution result | +| \`reasoning\` | Extended thinking content | +| \`finish\` | End-of-turn marker | + +## Parsing in scripts + +### bash + jq + +\`\`\`bash +result=$(kit "Count files" --json --quiet --no-session) +response=$(echo "$result" | jq -r '.response') +tokens=$(echo "$result" | jq '.usage.total_tokens') +\`\`\` + +### Go SDK + +For Go programs, use the SDK's \`PromptResult\` method instead of parsing JSON: + +\`\`\`go +result, err := host.PromptResult(ctx, "Count files") +fmt.Println(result.Response) +fmt.Println(result.Usage.TotalTokens) +\`\`\` +`};export{s as default}; diff --git a/assets/loading-CfdMbwrl.js b/assets/loading-CfdMbwrl.js new file mode 100644 index 00000000..50f0e5d1 --- /dev/null +++ b/assets/loading-CfdMbwrl.js @@ -0,0 +1,213 @@ +const s={frontmatter:{title:"Loading Extensions",description:"How Kit discovers and loads extensions.",hidden:!1,toc:!0,draft:!1},html:`

    Loading Extensions

    +

    Auto-discovery

    +

    Kit automatically discovers and loads extensions from these paths, in order:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathScope
    ~/.config/kit/extensions/*.goGlobal single files
    ~/.config/kit/extensions/*/main.goGlobal subdirectory extensions
    .kit/extensions/*.goProject-local single files
    .kit/extensions/*/main.goProject-local subdirectory extensions
    ~/.local/share/kit/git/Global git-installed packages
    .kit/git/Project-local git-installed packages
    +

    Explicit loading

    +

    Load extensions by path using the -e flag:

    +
    kit -e path/to/extension.go
    +

    Load multiple extensions:

    +
    kit -e ext1.go -e ext2.go
    +

    Disabling extensions

    +

    Disable all auto-discovered extensions:

    +
    kit --no-extensions
    +

    You can combine --no-extensions with -e to load only specific extensions:

    +
    kit --no-extensions -e my-extension.go
    +

    Installing from git

    +

    Install extensions from git repositories using kit install:

    +
    # Install globally (to ~/.local/share/kit/git/)
    +kit install https://github.com/user/my-kit-extension.git
    +
    +# Install project-locally (to .kit/git/)
    +kit install -l https://github.com/user/my-kit-extension.git
    +
    +# Update an installed package
    +kit install -u https://github.com/user/my-kit-extension.git
    +
    +# Remove
    +kit install --uninstall my-kit-extension
    +

    Extension structure

    +

    Single-file extensions

    +

    A single .go file with an Init function:

    +
    //go:build ignore
    +
    +package main
    +
    +import "kit/ext"
    +
    +func Init(api ext.API) {
    +    // register handlers, tools, commands, etc.
    +}
    +

    The //go:build ignore directive prevents the Go toolchain from trying to compile the file as part of a normal build.

    +

    Subdirectory extensions

    +

    For more complex extensions, create a directory with a main.go entry point:

    +
    .kit/extensions/my-extension/
    +├── main.go      # Must contain Init(api ext.API)
    +├── helpers.go   # Additional source files
    +└── config.go
    +
    +

    Package-level state

    +

    Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks:

    +
    package main
    +
    +import "kit/ext"
    +
    +var callCount int
    +
    +func Init(api ext.API) {
    +    api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) {
    +        callCount++
    +        ctx.SetFooter(ext.HeaderFooterConfig{
    +            Content: ext.WidgetContent{
    +                Text: fmt.Sprintf("Tools called: %d", callCount),
    +            },
    +        })
    +    })
    +}
    `,headings:[{depth:2,text:"Auto-discovery",id:"auto-discovery"},{depth:2,text:"Explicit loading",id:"explicit-loading"},{depth:2,text:"Disabling extensions",id:"disabling-extensions"},{depth:2,text:"Installing from git",id:"installing-from-git"},{depth:2,text:"Extension structure",id:"extension-structure"},{depth:3,text:"Single-file extensions",id:"single-file-extensions"},{depth:3,text:"Subdirectory extensions",id:"subdirectory-extensions"},{depth:3,text:"Package-level state",id:"package-level-state"}],raw:` +# Loading Extensions + +## Auto-discovery + +Kit automatically discovers and loads extensions from these paths, in order: + +| Path | Scope | +|------|-------| +| \`~/.config/kit/extensions/*.go\` | Global single files | +| \`~/.config/kit/extensions/*/main.go\` | Global subdirectory extensions | +| \`.kit/extensions/*.go\` | Project-local single files | +| \`.kit/extensions/*/main.go\` | Project-local subdirectory extensions | +| \`~/.local/share/kit/git/\` | Global git-installed packages | +| \`.kit/git/\` | Project-local git-installed packages | + +## Explicit loading + +Load extensions by path using the \`-e\` flag: + +\`\`\`bash +kit -e path/to/extension.go +\`\`\` + +Load multiple extensions: + +\`\`\`bash +kit -e ext1.go -e ext2.go +\`\`\` + +## Disabling extensions + +Disable all auto-discovered extensions: + +\`\`\`bash +kit --no-extensions +\`\`\` + +You can combine \`--no-extensions\` with \`-e\` to load only specific extensions: + +\`\`\`bash +kit --no-extensions -e my-extension.go +\`\`\` + +## Installing from git + +Install extensions from git repositories using \`kit install\`: + +\`\`\`bash +# Install globally (to ~/.local/share/kit/git/) +kit install https://github.com/user/my-kit-extension.git + +# Install project-locally (to .kit/git/) +kit install -l https://github.com/user/my-kit-extension.git + +# Update an installed package +kit install -u https://github.com/user/my-kit-extension.git + +# Remove +kit install --uninstall my-kit-extension +\`\`\` + +## Extension structure + +### Single-file extensions + +A single \`.go\` file with an \`Init\` function: + +\`\`\`go +//go:build ignore + +package main + +import "kit/ext" + +func Init(api ext.API) { + // register handlers, tools, commands, etc. +} +\`\`\` + +The \`//go:build ignore\` directive prevents the Go toolchain from trying to compile the file as part of a normal build. + +### Subdirectory extensions + +For more complex extensions, create a directory with a \`main.go\` entry point: + +\`\`\` +.kit/extensions/my-extension/ +├── main.go # Must contain Init(api ext.API) +├── helpers.go # Additional source files +└── config.go +\`\`\` + +### Package-level state + +Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks: + +\`\`\`go +package main + +import "kit/ext" + +var callCount int + +func Init(api ext.API) { + api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) { + callCount++ + ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{ + Text: fmt.Sprintf("Tools called: %d", callCount), + }, + }) + }) +} +\`\`\` +`};export{s as default}; diff --git a/assets/options-DhBmR6ye.js b/assets/options-DhBmR6ye.js new file mode 100644 index 00000000..42bee1fa --- /dev/null +++ b/assets/options-DhBmR6ye.js @@ -0,0 +1,147 @@ +const s={frontmatter:{title:"SDK Options",description:"Configuration options for the Kit Go SDK.",hidden:!1,toc:!0,draft:!1},html:`

    SDK Options

    +

    Pass an Options struct to kit.New() to configure the Kit instance.

    +

    Full options reference

    +
    host, err := kit.New(ctx, &kit.Options{
    +    // Model
    +    Model:        "ollama/llama3",
    +    SystemPrompt: "You are a helpful bot",
    +    ConfigFile:   "/path/to/config.yml",
    +
    +    // Behavior
    +    MaxSteps:     10,
    +    Streaming:    true,
    +    Quiet:        true,
    +    Debug:        true,
    +
    +    // Session
    +    SessionPath:  "./session.jsonl",
    +    SessionDir:   "/custom/sessions/",
    +    Continue:     true,
    +    NoSession:    true,
    +
    +    // Tools
    +    Tools:        []kit.Tool{...},     // Replace default tool set entirely
    +    ExtraTools:   []kit.Tool{...},     // Add tools alongside defaults
    +
    +    // Compaction
    +    AutoCompact:  true,
    +
    +    // Skills
    +    Skills:       []string{"/path/to/skill.md"},
    +    SkillsDir:    "/path/to/skills/",
    +})
    +

    Options fields

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeDefaultDescription
    Modelstringconfig defaultModel string (provider/model format)
    SystemPromptstringSystem prompt text or file path
    ConfigFilestring~/.kit.ymlPath to config file
    MaxStepsint0Max agent steps (0 = unlimited)
    StreamingbooltrueEnable streaming output
    QuietboolfalseSuppress output
    DebugboolfalseEnable debug logging
    SessionPathstringOpen a specific session file
    SessionDirstringBase directory for session discovery
    ContinueboolfalseResume most recent session
    NoSessionboolfalseEphemeral mode (no persistence)
    Tools[]ToolReplace the entire default tool set
    ExtraTools[]ToolAdditional tools alongside core/MCP/extension tools
    AutoCompactboolfalseAuto-compact when near context limit
    CompactionOptions*CompactionOptionsConfiguration for auto-compaction
    Skills[]stringExplicit skill files/dirs to load
    SkillsDirstringOverride default skills directory
    `,headings:[{depth:2,text:"Full options reference",id:"full-options-reference"},{depth:2,text:"Options fields",id:"options-fields"}],raw:'\n# SDK Options\n\nPass an `Options` struct to `kit.New()` to configure the Kit instance.\n\n## Full options reference\n\n```go\nhost, err := kit.New(ctx, &kit.Options{\n // Model\n Model: "ollama/llama3",\n SystemPrompt: "You are a helpful bot",\n ConfigFile: "/path/to/config.yml",\n\n // Behavior\n MaxSteps: 10,\n Streaming: true,\n Quiet: true,\n Debug: true,\n\n // Session\n SessionPath: "./session.jsonl",\n SessionDir: "/custom/sessions/",\n Continue: true,\n NoSession: true,\n\n // Tools\n Tools: []kit.Tool{...}, // Replace default tool set entirely\n ExtraTools: []kit.Tool{...}, // Add tools alongside defaults\n\n // Compaction\n AutoCompact: true,\n\n // Skills\n Skills: []string{"/path/to/skill.md"},\n SkillsDir: "/path/to/skills/",\n})\n```\n\n## Options fields\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `Model` | `string` | config default | Model string (provider/model format) |\n| `SystemPrompt` | `string` | — | System prompt text or file path |\n| `ConfigFile` | `string` | `~/.kit.yml` | Path to config file |\n| `MaxSteps` | `int` | `0` | Max agent steps (0 = unlimited) |\n| `Streaming` | `bool` | `true` | Enable streaming output |\n| `Quiet` | `bool` | `false` | Suppress output |\n| `Debug` | `bool` | `false` | Enable debug logging |\n| `SessionPath` | `string` | — | Open a specific session file |\n| `SessionDir` | `string` | — | Base directory for session discovery |\n| `Continue` | `bool` | `false` | Resume most recent session |\n| `NoSession` | `bool` | `false` | Ephemeral mode (no persistence) |\n| `Tools` | `[]Tool` | — | Replace the entire default tool set |\n| `ExtraTools` | `[]Tool` | — | Additional tools alongside core/MCP/extension tools |\n| `AutoCompact` | `bool` | `false` | Auto-compact when near context limit |\n| `CompactionOptions` | `*CompactionOptions` | — | Configuration for auto-compaction |\n| `Skills` | `[]string` | — | Explicit skill files/dirs to load |\n| `SkillsDir` | `string` | — | Override default skills directory |\n'};export{s as default}; diff --git a/assets/overview-DNz93_Eg.js b/assets/overview-DNz93_Eg.js new file mode 100644 index 00000000..aed49836 --- /dev/null +++ b/assets/overview-DNz93_Eg.js @@ -0,0 +1,56 @@ +const e={frontmatter:{title:"Extension System",description:"Overview of Kit's Go-based extension system.",hidden:!1,toc:!0,draft:!1},html:`

    Extension System

    +

    Extensions are Go source files interpreted at runtime via Yaegi. They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit.

    +

    Minimal extension

    +
    //go:build ignore
    +
    +package main
    +
    +import "kit/ext"
    +
    +func Init(api ext.API) {
    +    api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {
    +        ctx.SetFooter(ext.HeaderFooterConfig{
    +            Content: ext.WidgetContent{Text: "Custom Footer"},
    +        })
    +    })
    +}
    +

    Run it with:

    +
    kit -e examples/extensions/minimal.go
    +

    How extensions work

    +
      +
    1. Kit discovers extension files from auto-discovery paths or explicit -e flags
    2. +
    3. Each .go file is loaded into a Yaegi interpreter with access to the kit/ext package
    4. +
    5. Kit calls the Init(api ext.API) function in each extension
    6. +
    7. The extension registers callbacks, tools, commands, and UI components via the api and ctx objects
    8. +
    +

    Key concepts

    +

    The API object

    +

    Passed to Init(), the API object is used to register lifecycle event handlers and static components:

    +
      +
    • Lifecycle handlersapi.OnSessionStart(...), api.OnToolCall(...), etc.
    • +
    • Toolsapi.RegisterTool(ext.ToolDef{...})
    • +
    • Commandsapi.RegisterCommand(ext.CommandDef{...})
    • +
    • Shortcutsapi.RegisterShortcut(ext.ShortcutDef{...}, handler)
    • +
    • Tool renderersapi.RegisterToolRenderer(ext.ToolRenderConfig{...})
    • +
    • Message renderersapi.RegisterMessageRenderer(ext.MessageRendererConfig{...})
    • +
    • Optionsapi.RegisterOption(ext.OptionDef{...})
    • +
    +

    The Context object

    +

    Passed to event handlers, the Context object provides runtime access to Kit's state and UI:

    +
      +
    • Outputctx.Print(...), ctx.PrintInfo(...), ctx.PrintError(...)
    • +
    • UI componentsctx.SetWidget(...), ctx.SetHeader(...), ctx.SetFooter(...), ctx.SetStatus(...)
    • +
    • Editorctx.SetEditor(...), ctx.ResetEditor()
    • +
    • Promptsctx.PromptSelect(...), ctx.PromptConfirm(...), ctx.PromptInput(...)
    • +
    • Overlaysctx.ShowOverlay(...)
    • +
    • Messagesctx.SendMessage(...), ctx.GetMessages()
    • +
    • Modelctx.SetModel(...), ctx.GetAvailableModels()
    • +
    • Toolsctx.GetAllTools(), ctx.SetActiveTools(...)
    • +
    • Context statsctx.GetContextStats()
    • +
    • Session datactx.AppendEntry(...), ctx.GetEntries(...)
    • +
    • Subagentsctx.SpawnSubagent(...)
    • +
    • LLM completionctx.Complete(...)
    • +
    • Custom eventsctx.EmitCustomEvent(...)
    • +
    • App controlctx.Exit(), ctx.ReloadExtensions()
    • +
    +

    See Capabilities for full details on each component type.

    `,headings:[{depth:2,text:"Minimal extension",id:"minimal-extension"},{depth:2,text:"How extensions work",id:"how-extensions-work"},{depth:2,text:"Key concepts",id:"key-concepts"},{depth:3,text:"The API object",id:"the-api-object"},{depth:3,text:"The Context object",id:"the-context-object"}],raw:'\n# Extension System\n\nExtensions are Go source files interpreted at runtime via [Yaegi](https://github.com/traefik/yaegi). They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit.\n\n## Minimal extension\n\n```go\n//go:build ignore\n\npackage main\n\nimport "kit/ext"\n\nfunc Init(api ext.API) {\n api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {\n ctx.SetFooter(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{Text: "Custom Footer"},\n })\n })\n}\n```\n\nRun it with:\n\n```bash\nkit -e examples/extensions/minimal.go\n```\n\n## How extensions work\n\n1. Kit discovers extension files from [auto-discovery paths](/extensions/loading) or explicit `-e` flags\n2. Each `.go` file is loaded into a Yaegi interpreter with access to the `kit/ext` package\n3. Kit calls the `Init(api ext.API)` function in each extension\n4. The extension registers callbacks, tools, commands, and UI components via the `api` and `ctx` objects\n\n## Key concepts\n\n### The `API` object\n\nPassed to `Init()`, the `API` object is used to register lifecycle event handlers and static components:\n\n- **Lifecycle handlers** — `api.OnSessionStart(...)`, `api.OnToolCall(...)`, etc.\n- **Tools** — `api.RegisterTool(ext.ToolDef{...})`\n- **Commands** — `api.RegisterCommand(ext.CommandDef{...})`\n- **Shortcuts** — `api.RegisterShortcut(ext.ShortcutDef{...}, handler)`\n- **Tool renderers** — `api.RegisterToolRenderer(ext.ToolRenderConfig{...})`\n- **Message renderers** — `api.RegisterMessageRenderer(ext.MessageRendererConfig{...})`\n- **Options** — `api.RegisterOption(ext.OptionDef{...})`\n\n### The `Context` object\n\nPassed to event handlers, the `Context` object provides runtime access to Kit\'s state and UI:\n\n- **Output** — `ctx.Print(...)`, `ctx.PrintInfo(...)`, `ctx.PrintError(...)`\n- **UI components** — `ctx.SetWidget(...)`, `ctx.SetHeader(...)`, `ctx.SetFooter(...)`, `ctx.SetStatus(...)`\n- **Editor** — `ctx.SetEditor(...)`, `ctx.ResetEditor()`\n- **Prompts** — `ctx.PromptSelect(...)`, `ctx.PromptConfirm(...)`, `ctx.PromptInput(...)`\n- **Overlays** — `ctx.ShowOverlay(...)`\n- **Messages** — `ctx.SendMessage(...)`, `ctx.GetMessages()`\n- **Model** — `ctx.SetModel(...)`, `ctx.GetAvailableModels()`\n- **Tools** — `ctx.GetAllTools()`, `ctx.SetActiveTools(...)`\n- **Context stats** — `ctx.GetContextStats()`\n- **Session data** — `ctx.AppendEntry(...)`, `ctx.GetEntries(...)`\n- **Subagents** — `ctx.SpawnSubagent(...)`\n- **LLM completion** — `ctx.Complete(...)`\n- **Custom events** — `ctx.EmitCustomEvent(...)`\n- **App control** — `ctx.Exit()`, `ctx.ReloadExtensions()`\n\nSee [Capabilities](/extensions/capabilities) for full details on each component type.\n'};export{e as default}; diff --git a/assets/overview-DbvqPNef.js b/assets/overview-DbvqPNef.js new file mode 100644 index 00000000..2e1889ad --- /dev/null +++ b/assets/overview-DbvqPNef.js @@ -0,0 +1,215 @@ +const s={frontmatter:{title:"Go SDK",description:"Embed Kit in your Go applications.",hidden:!1,toc:!0,draft:!1},html:`

    Go SDK

    +

    The pkg/kit package lets you embed Kit as a library in your Go applications.

    +

    Installation

    +
    go get github.com/mark3labs/kit/pkg/kit
    +

    Basic usage

    +
    package main
    +
    +import (
    +    "context"
    +    "log"
    +
    +    kit "github.com/mark3labs/kit/pkg/kit"
    +)
    +
    +func main() {
    +    ctx := context.Background()
    +
    +    // Create Kit instance with default configuration
    +    host, err := kit.New(ctx, nil)
    +    if err != nil {
    +        log.Fatal(err)
    +    }
    +    defer host.Close()
    +
    +    // Send a prompt
    +    response, err := host.Prompt(ctx, "What is 2+2?")
    +    if err != nil {
    +        log.Fatal(err)
    +    }
    +
    +    println(response)
    +}
    +

    Multi-turn conversations

    +

    Conversations retain context automatically across calls:

    +
    host.Prompt(ctx, "My name is Alice")
    +response, _ := host.Prompt(ctx, "What's my name?")
    +// response: "Your name is Alice"
    +

    Additional prompt methods

    +

    The SDK provides several prompt variants:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MethodDescription
    Prompt(ctx, message)Simple prompt, returns response string
    PromptWithCallbacks(ctx, message, ...)With tool call and streaming callbacks
    PromptWithOptions(ctx, message, opts)With per-call options
    PromptResult(ctx, message)Returns full TurnResult with usage stats
    PromptResultWithFiles(ctx, message, files)Multimodal with file attachments
    Steer(ctx, instruction)System-level steering without user message
    FollowUp(ctx, text)Continue without new user input
    +

    Event system

    +

    Subscribe to events for monitoring:

    +
    unsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) {
    +    fmt.Println("Tool called:", event.Name)
    +})
    +defer unsubscribe()
    +
    +host.OnToolResult(func(event kit.ToolResultEvent) {
    +    fmt.Println("Tool result:", event.Name)
    +})
    +
    +host.OnStreaming(func(event kit.MessageUpdateEvent) {
    +    fmt.Print(event.Chunk)
    +})
    +

    Model management

    +

    Switch models at runtime:

    +
    host.SetModel(ctx, "openai/gpt-4o")
    +info := host.GetModelInfo()
    +models := host.GetAvailableModels()
    +

    Context and compaction

    +

    Monitor and manage context usage:

    +
    tokens := host.EstimateContextTokens()
    +stats := host.GetContextStats()
    +
    +if host.ShouldCompact() {
    +    result, err := host.Compact(ctx, nil, "")
    +}
    +

    See Options, Callbacks, and Sessions for more details.

    `,headings:[{depth:2,text:"Installation",id:"installation"},{depth:2,text:"Basic usage",id:"basic-usage"},{depth:2,text:"Multi-turn conversations",id:"multi-turn-conversations"},{depth:2,text:"Additional prompt methods",id:"additional-prompt-methods"},{depth:2,text:"Event system",id:"event-system"},{depth:2,text:"Model management",id:"model-management"},{depth:2,text:"Context and compaction",id:"context-and-compaction"}],raw:` +# Go SDK + +The \`pkg/kit\` package lets you embed Kit as a library in your Go applications. + +## Installation + +\`\`\`bash +go get github.com/mark3labs/kit/pkg/kit +\`\`\` + +## Basic usage + +\`\`\`go +package main + +import ( + "context" + "log" + + kit "github.com/mark3labs/kit/pkg/kit" +) + +func main() { + ctx := context.Background() + + // Create Kit instance with default configuration + host, err := kit.New(ctx, nil) + if err != nil { + log.Fatal(err) + } + defer host.Close() + + // Send a prompt + response, err := host.Prompt(ctx, "What is 2+2?") + if err != nil { + log.Fatal(err) + } + + println(response) +} +\`\`\` + +## Multi-turn conversations + +Conversations retain context automatically across calls: + +\`\`\`go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +\`\`\` + +## Additional prompt methods + +The SDK provides several prompt variants: + +| Method | Description | +|--------|-------------| +| \`Prompt(ctx, message)\` | Simple prompt, returns response string | +| \`PromptWithCallbacks(ctx, message, ...)\` | With tool call and streaming callbacks | +| \`PromptWithOptions(ctx, message, opts)\` | With per-call options | +| \`PromptResult(ctx, message)\` | Returns full \`TurnResult\` with usage stats | +| \`PromptResultWithFiles(ctx, message, files)\` | Multimodal with file attachments | +| \`Steer(ctx, instruction)\` | System-level steering without user message | +| \`FollowUp(ctx, text)\` | Continue without new user input | + +## Event system + +Subscribe to events for monitoring: + +\`\`\`go +unsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Println("Tool called:", event.Name) +}) +defer unsubscribe() + +host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Println("Tool result:", event.Name) +}) + +host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +\`\`\` + +## Model management + +Switch models at runtime: + +\`\`\`go +host.SetModel(ctx, "openai/gpt-4o") +info := host.GetModelInfo() +models := host.GetAvailableModels() +\`\`\` + +## Context and compaction + +Monitor and manage context usage: + +\`\`\`go +tokens := host.EstimateContextTokens() +stats := host.GetContextStats() + +if host.ShouldCompact() { + result, err := host.Compact(ctx, nil, "") +} +\`\`\` + +See [Options](/sdk/options), [Callbacks](/sdk/callbacks), and [Sessions](/sdk/sessions) for more details. +`};export{s as default}; diff --git a/assets/providers-B05lw6S_.js b/assets/providers-B05lw6S_.js new file mode 100644 index 00000000..36fccfcb --- /dev/null +++ b/assets/providers-B05lw6S_.js @@ -0,0 +1,224 @@ +const s={frontmatter:{title:"Providers",description:"Supported LLM providers and model configuration.",hidden:!1,toc:!0,draft:!1},html:`

    Providers

    +

    Kit supports a wide range of LLM providers through a unified provider/model string format.

    +

    Supported providers

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ProviderPrefixDescription
    Anthropicanthropic/Claude models (native, prompt caching, OAuth)
    OpenAIopenai/GPT models
    Googlegoogle/ or gemini/Gemini models
    Ollamaollama/Local models
    Azure OpenAIazure/Azure-hosted OpenAI
    AWS Bedrockbedrock/Bedrock models
    Google Vertexgoogle-vertex-anthropic/Claude on Vertex AI
    OpenRouteropenrouter/Multi-provider router
    Vercel AIvercel/Vercel AI SDK models
    Auto-routedanyAny provider from the models.dev database
    +

    Model string format

    +
    provider/model            # Standard format
    +anthropic/claude-sonnet-4-5-20250929
    +openai/gpt-4o
    +ollama/llama3
    +google/gemini-2.0-flash-exp
    +

    Model aliases

    +

    Kit provides aliases for commonly used models:

    +
    claude-opus-latest claude-opus-4-20250514
    +claude-sonnet-latest claude-sonnet-4-5-20250929
    +claude-4-opus-latest claude-opus-4-20250514
    +claude-4-sonnet-latest claude-sonnet-4-5-20250929
    +claude-3-7-sonnet-latest claude-3-7-sonnet-20250219
    +claude-3-5-sonnet-latest claude-3-5-sonnet-20241022
    +claude-3-5-haiku-latest claude-3-5-haiku-20241022
    +claude-3-opus-latest claude-3-opus-20240229
    +

    Specifying a model

    +

    Via CLI flag:

    +
    kit --model openai/gpt-4o
    +kit -m ollama/llama3
    +

    Via config file:

    +
    model: anthropic/claude-sonnet-4-5-20250929
    +

    Via environment variable:

    +
    export KIT_MODEL="google/gemini-2.0-flash-exp"
    +

    Authentication

    +

    API keys

    +

    Set the appropriate environment variable for your provider:

    +
    export ANTHROPIC_API_KEY="sk-..."
    +export OPENAI_API_KEY="sk-..."
    +export GOOGLE_API_KEY="..."
    +

    Or pass it directly:

    +
    kit --provider-api-key "sk-..." --model openai/gpt-4o
    +

    OAuth

    +

    For providers that support OAuth (e.g., Anthropic):

    +
    kit auth login anthropic     # Start OAuth flow
    +kit auth status              # Check authentication status
    +kit auth logout anthropic    # Remove credentials
    +

    Custom provider URL

    +

    For self-hosted or proxy endpoints:

    +
    kit --provider-url "https://my-proxy.example.com/v1" --model openai/gpt-4o
    +

    Model database

    +

    Kit ships with a local model database that maps provider names to API configurations. You can manage it with:

    +
    kit models                   # List available models
    +kit models openai            # Filter by provider
    +kit models --all             # Show all providers
    +kit update-models            # Update from models.dev
    +kit update-models embedded   # Reset to bundled database
    `,headings:[{depth:2,text:"Supported providers",id:"supported-providers"},{depth:2,text:"Model string format",id:"model-string-format"},{depth:2,text:"Model aliases",id:"model-aliases"},{depth:2,text:"Specifying a model",id:"specifying-a-model"},{depth:2,text:"Authentication",id:"authentication"},{depth:3,text:"API keys",id:"api-keys"},{depth:3,text:"OAuth",id:"oauth"},{depth:3,text:"Custom provider URL",id:"custom-provider-url"},{depth:2,text:"Model database",id:"model-database"}],raw:` +# Providers + +Kit supports a wide range of LLM providers through a unified \`provider/model\` string format. + +## Supported providers + +| Provider | Prefix | Description | +|----------|--------|-------------| +| **Anthropic** | \`anthropic/\` | Claude models (native, prompt caching, OAuth) | +| **OpenAI** | \`openai/\` | GPT models | +| **Google** | \`google/\` or \`gemini/\` | Gemini models | +| **Ollama** | \`ollama/\` | Local models | +| **Azure OpenAI** | \`azure/\` | Azure-hosted OpenAI | +| **AWS Bedrock** | \`bedrock/\` | Bedrock models | +| **Google Vertex** | \`google-vertex-anthropic/\` | Claude on Vertex AI | +| **OpenRouter** | \`openrouter/\` | Multi-provider router | +| **Vercel AI** | \`vercel/\` | Vercel AI SDK models | +| **Auto-routed** | any | Any provider from the models.dev database | + +## Model string format + +\`\`\`bash +provider/model # Standard format +anthropic/claude-sonnet-4-5-20250929 +openai/gpt-4o +ollama/llama3 +google/gemini-2.0-flash-exp +\`\`\` + +## Model aliases + +Kit provides aliases for commonly used models: + +\`\`\`bash +claude-opus-latest → claude-opus-4-20250514 +claude-sonnet-latest → claude-sonnet-4-5-20250929 +claude-4-opus-latest → claude-opus-4-20250514 +claude-4-sonnet-latest → claude-sonnet-4-5-20250929 +claude-3-7-sonnet-latest → claude-3-7-sonnet-20250219 +claude-3-5-sonnet-latest → claude-3-5-sonnet-20241022 +claude-3-5-haiku-latest → claude-3-5-haiku-20241022 +claude-3-opus-latest → claude-3-opus-20240229 +\`\`\` + +## Specifying a model + +Via CLI flag: + +\`\`\`bash +kit --model openai/gpt-4o +kit -m ollama/llama3 +\`\`\` + +Via config file: + +\`\`\`yaml +model: anthropic/claude-sonnet-4-5-20250929 +\`\`\` + +Via environment variable: + +\`\`\`bash +export KIT_MODEL="google/gemini-2.0-flash-exp" +\`\`\` + +## Authentication + +### API keys + +Set the appropriate environment variable for your provider: + +\`\`\`bash +export ANTHROPIC_API_KEY="sk-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +\`\`\` + +Or pass it directly: + +\`\`\`bash +kit --provider-api-key "sk-..." --model openai/gpt-4o +\`\`\` + +### OAuth + +For providers that support OAuth (e.g., Anthropic): + +\`\`\`bash +kit auth login anthropic # Start OAuth flow +kit auth status # Check authentication status +kit auth logout anthropic # Remove credentials +\`\`\` + +### Custom provider URL + +For self-hosted or proxy endpoints: + +\`\`\`bash +kit --provider-url "https://my-proxy.example.com/v1" --model openai/gpt-4o +\`\`\` + +## Model database + +Kit ships with a local model database that maps provider names to API configurations. You can manage it with: + +\`\`\`bash +kit models # List available models +kit models openai # Filter by provider +kit models --all # Show all providers +kit update-models # Update from models.dev +kit update-models embedded # Reset to bundled database +\`\`\` +`};export{s as default}; diff --git a/assets/quick-start-B51YvXk3.js b/assets/quick-start-B51YvXk3.js new file mode 100644 index 00000000..0658b36d --- /dev/null +++ b/assets/quick-start-B51YvXk3.js @@ -0,0 +1,117 @@ +const s={frontmatter:{title:"Quick Start",description:"Get up and running with Kit in minutes.",hidden:!1,toc:!0,draft:!1},html:`

    Quick Start

    +

    Basic usage

    +

    Start an interactive session:

    +
    kit
    +

    Run a one-off prompt:

    +
    kit "List files in src/"
    +

    Attach files as context using the @ prefix:

    +
    kit @main.go @test.go "Review these files"
    +

    Use a specific model:

    +
    kit --model anthropic/claude-sonnet-4-5-20250929
    +

    Non-interactive mode

    +

    Kit can run as a non-interactive tool for scripting and automation.

    +

    Get JSON output:

    +
    kit "Explain main.go" --json
    +

    Quiet mode (final response only, no TUI):

    +
    kit "Run tests" --quiet
    +

    Ephemeral mode (no session file created):

    +
    kit "Quick question" --no-session
    +

    Resuming sessions

    +

    Continue the most recent session for the current directory:

    +
    kit --continue
    +# or
    +kit -c
    +

    Pick from previous sessions interactively:

    +
    kit --resume
    +# or
    +kit -r
    +

    ACP server mode

    +

    Kit can run as an ACP (Agent Client Protocol) agent server, enabling ACP-compatible clients (such as OpenCode) to drive Kit as a remote coding agent over stdio:

    +
    # Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout)
    +kit acp
    +
    +# With debug logging to stderr
    +kit acp --debug
    +

    The ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol.

    `,headings:[{depth:2,text:"Basic usage",id:"basic-usage"},{depth:2,text:"Non-interactive mode",id:"non-interactive-mode"},{depth:2,text:"Resuming sessions",id:"resuming-sessions"},{depth:2,text:"ACP server mode",id:"acp-server-mode"}],raw:` +# Quick Start + +## Basic usage + +Start an interactive session: + +\`\`\`bash +kit +\`\`\` + +Run a one-off prompt: + +\`\`\`bash +kit "List files in src/" +\`\`\` + +Attach files as context using the \`@\` prefix: + +\`\`\`bash +kit @main.go @test.go "Review these files" +\`\`\` + +Use a specific model: + +\`\`\`bash +kit --model anthropic/claude-sonnet-4-5-20250929 +\`\`\` + +## Non-interactive mode + +Kit can run as a non-interactive tool for scripting and automation. + +Get JSON output: + +\`\`\`bash +kit "Explain main.go" --json +\`\`\` + +Quiet mode (final response only, no TUI): + +\`\`\`bash +kit "Run tests" --quiet +\`\`\` + +Ephemeral mode (no session file created): + +\`\`\`bash +kit "Quick question" --no-session +\`\`\` + +## Resuming sessions + +Continue the most recent session for the current directory: + +\`\`\`bash +kit --continue +# or +kit -c +\`\`\` + +Pick from previous sessions interactively: + +\`\`\`bash +kit --resume +# or +kit -r +\`\`\` + +## ACP server mode + +Kit can run as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server, enabling ACP-compatible clients (such as [OpenCode](https://github.com/sst/opencode)) to drive Kit as a remote coding agent over stdio: + +\`\`\`bash +# Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout) +kit acp + +# With debug logging to stderr +kit acp --debug +\`\`\` + +The ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol. +`};export{s as default}; diff --git a/assets/sessions-BM7WkgkF.js b/assets/sessions-BM7WkgkF.js new file mode 100644 index 00000000..c7562295 --- /dev/null +++ b/assets/sessions-BM7WkgkF.js @@ -0,0 +1,77 @@ +const s={frontmatter:{title:"Session Management",description:"How Kit persists and manages conversation sessions.",hidden:!1,toc:!0,draft:!1},html:`

    Session Management

    +

    Kit uses a tree-based session model that supports branching and forking conversations.

    +

    Session storage

    +

    Sessions are stored as JSONL (JSON Lines) files:

    +
    ~/.kit/sessions/<cwd-path>/<timestamp>_<id>.jsonl
    +
    +

    Path separators in the working directory are replaced with --. For example, /home/user/project becomes home--user--project.

    +

    Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths.

    +

    Resuming sessions

    +

    Continue most recent

    +

    Resume the most recent session for the current directory:

    +
    kit --continue
    +kit -c
    +

    Interactive picker

    +

    Choose from previous sessions interactively:

    +
    kit --resume
    +kit -r
    +

    Open a specific session

    +
    kit --session path/to/session.jsonl
    +kit -s path/to/session.jsonl
    +

    Ephemeral mode

    +

    Run without creating a session file:

    +
    kit --no-session
    +

    This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed.

    `,headings:[{depth:2,text:"Session storage",id:"session-storage"},{depth:2,text:"Resuming sessions",id:"resuming-sessions"},{depth:3,text:"Continue most recent",id:"continue-most-recent"},{depth:3,text:"Interactive picker",id:"interactive-picker"},{depth:3,text:"Open a specific session",id:"open-a-specific-session"},{depth:2,text:"Ephemeral mode",id:"ephemeral-mode"}],raw:` +# Session Management + +Kit uses a tree-based session model that supports branching and forking conversations. + +## Session storage + +Sessions are stored as JSONL (JSON Lines) files: + +\`\`\` +~/.kit/sessions//_.jsonl +\`\`\` + +Path separators in the working directory are replaced with \`--\`. For example, \`/home/user/project\` becomes \`home--user--project\`. + +Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths. + +## Resuming sessions + +### Continue most recent + +Resume the most recent session for the current directory: + +\`\`\`bash +kit --continue +kit -c +\`\`\` + +### Interactive picker + +Choose from previous sessions interactively: + +\`\`\`bash +kit --resume +kit -r +\`\`\` + +### Open a specific session + +\`\`\`bash +kit --session path/to/session.jsonl +kit -s path/to/session.jsonl +\`\`\` + +## Ephemeral mode + +Run without creating a session file: + +\`\`\`bash +kit --no-session +\`\`\` + +This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed. +`};export{s as default}; diff --git a/assets/sessions-X-l1qojs.js b/assets/sessions-X-l1qojs.js new file mode 100644 index 00000000..e51d8b09 --- /dev/null +++ b/assets/sessions-X-l1qojs.js @@ -0,0 +1,142 @@ +const s={frontmatter:{title:"SDK Sessions",description:"Session management in the Kit Go SDK.",hidden:!1,toc:!0,draft:!1},html:`

    SDK Sessions

    +

    Automatic persistence

    +

    By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls:

    +
    host.Prompt(ctx, "My name is Alice")
    +response, _ := host.Prompt(ctx, "What's my name?")
    +// response: "Your name is Alice"
    +

    Accessing session info

    +
    // Get the current session file path
    +path := host.GetSessionPath()
    +
    +// Get the session ID
    +id := host.GetSessionID()
    +
    +// Get the current model string
    +model := host.GetModelString()
    +

    Configuring sessions via Options

    +

    Session behavior is configured at initialization:

    +
    // Open a specific session file
    +host, _ := kit.New(ctx, &kit.Options{
    +    SessionPath: "./my-session.jsonl",
    +})
    +
    +// Resume the most recent session for the current directory
    +host, _ := kit.New(ctx, &kit.Options{
    +    Continue: true,
    +})
    +
    +// Ephemeral mode (no file persistence)
    +host, _ := kit.New(ctx, &kit.Options{
    +    NoSession: true,
    +})
    +
    +// Custom session directory
    +host, _ := kit.New(ctx, &kit.Options{
    +    SessionDir: "/custom/sessions/",
    +})
    +

    Clearing history

    +

    Clear the in-memory conversation history (does not delete the session file):

    +
    host.ClearSession()
    +

    Tree-based sessions

    +

    Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths:

    +
    // Access the tree session manager
    +ts := host.GetTreeSession()
    +
    +// Branch from a specific entry
    +err := host.Branch("entry-id-123")
    +

    Listing and managing sessions

    +

    Package-level functions for session discovery:

    +
    // List sessions for a specific directory
    +sessions := kit.ListSessions("/home/user/project")
    +
    +// List all sessions across all directories
    +all := kit.ListAllSessions()
    +
    +// Delete a session file
    +kit.DeleteSession("/path/to/session.jsonl")
    `,headings:[{depth:2,text:"Automatic persistence",id:"automatic-persistence"},{depth:2,text:"Accessing session info",id:"accessing-session-info"},{depth:2,text:"Configuring sessions via Options",id:"configuring-sessions-via-options"},{depth:2,text:"Clearing history",id:"clearing-history"},{depth:2,text:"Tree-based sessions",id:"tree-based-sessions"},{depth:2,text:"Listing and managing sessions",id:"listing-and-managing-sessions"}],raw:` +# SDK Sessions + +## Automatic persistence + +By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls: + +\`\`\`go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +\`\`\` + +## Accessing session info + +\`\`\`go +// Get the current session file path +path := host.GetSessionPath() + +// Get the session ID +id := host.GetSessionID() + +// Get the current model string +model := host.GetModelString() +\`\`\` + +## Configuring sessions via Options + +Session behavior is configured at initialization: + +\`\`\`go +// Open a specific session file +host, _ := kit.New(ctx, &kit.Options{ + SessionPath: "./my-session.jsonl", +}) + +// Resume the most recent session for the current directory +host, _ := kit.New(ctx, &kit.Options{ + Continue: true, +}) + +// Ephemeral mode (no file persistence) +host, _ := kit.New(ctx, &kit.Options{ + NoSession: true, +}) + +// Custom session directory +host, _ := kit.New(ctx, &kit.Options{ + SessionDir: "/custom/sessions/", +}) +\`\`\` + +## Clearing history + +Clear the in-memory conversation history (does not delete the session file): + +\`\`\`go +host.ClearSession() +\`\`\` + +## Tree-based sessions + +Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths: + +\`\`\`go +// Access the tree session manager +ts := host.GetTreeSession() + +// Branch from a specific entry +err := host.Branch("entry-id-123") +\`\`\` + +## Listing and managing sessions + +Package-level functions for session discovery: + +\`\`\`go +// List sessions for a specific directory +sessions := kit.ListSessions("/home/user/project") + +// List all sessions across all directories +all := kit.ListAllSessions() + +// Delete a session file +kit.DeleteSession("/path/to/session.jsonl") +\`\`\` +`};export{s as default}; diff --git a/assets/subagents-ChkZbdDR.js b/assets/subagents-ChkZbdDR.js new file mode 100644 index 00000000..6bd6613f --- /dev/null +++ b/assets/subagents-ChkZbdDR.js @@ -0,0 +1,136 @@ +const s={frontmatter:{title:"Subagents",description:"Multi-agent orchestration with Kit subagents.",hidden:!1,toc:!0,draft:!1},html:`

    Subagents

    +

    Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents.

    +

    Subprocess pattern

    +

    Spawn Kit as a subprocess for isolated agent execution:

    +
    kit "Analyze codebase" \\
    +    --json \\
    +    --no-session \\
    +    --no-extensions \\
    +    --quiet \\
    +    --model anthropic/claude-haiku-3-5-20241022
    +

    Key flags for subprocess usage:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlagPurpose
    --quietStdout only, no TUI
    --no-sessionEphemeral, no persistence
    --no-extensionsPrevent recursive extension loading
    --jsonMachine-readable output
    --system-promptCustom system prompt (string or file path)
    +

    Positional arguments are the prompt. @file arguments attach file content as context.

    +

    Built-in spawn_subagent tool

    +

    Kit includes a built-in spawn_subagent tool that the LLM can use to delegate tasks to independent child agents:

    +
    spawn_subagent(
    +    task: "Analyze the test files and summarize coverage",
    +    model: "anthropic/claude-haiku-3-5-20241022",   // optional
    +    system_prompt: "You are a test analysis expert.",  // optional
    +    timeout_seconds: 300                               // optional, max 1800
    +)
    +
    +

    Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel.

    +

    Extension subagents

    +

    Extensions can spawn subagents programmatically:

    +
    result := ctx.SpawnSubagent(ext.SubagentConfig{
    +    Task:         "Review this code for security issues",
    +    Model:        "anthropic/claude-sonnet-4-5-20250929",
    +    SystemPrompt: "You are a security auditor.",
    +})
    +

    Go SDK subagents

    +

    The SDK provides in-process subagent spawning:

    +
    result, err := host.Subagent(ctx, kit.SubagentConfig{
    +    Task:         "Summarize the changes in this PR",
    +    Model:        "anthropic/claude-haiku-3-5-20241022",
    +    SystemPrompt: "You are a code reviewer.",
    +    Timeout:      5 * time.Minute,
    +})
    `,headings:[{depth:2,text:"Subprocess pattern",id:"subprocess-pattern"},{depth:2,text:"Built-in spawn_subagent tool",id:"built-in-spawn_subagent-tool"},{depth:2,text:"Extension subagents",id:"extension-subagents"},{depth:2,text:"Go SDK subagents",id:"go-sdk-subagents"}],raw:` +# Subagents + +Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents. + +## Subprocess pattern + +Spawn Kit as a subprocess for isolated agent execution: + +\`\`\`bash +kit "Analyze codebase" \\ + --json \\ + --no-session \\ + --no-extensions \\ + --quiet \\ + --model anthropic/claude-haiku-3-5-20241022 +\`\`\` + +Key flags for subprocess usage: + +| Flag | Purpose | +|------|---------| +| \`--quiet\` | Stdout only, no TUI | +| \`--no-session\` | Ephemeral, no persistence | +| \`--no-extensions\` | Prevent recursive extension loading | +| \`--json\` | Machine-readable output | +| \`--system-prompt\` | Custom system prompt (string or file path) | + +Positional arguments are the prompt. \`@file\` arguments attach file content as context. + +## Built-in spawn_subagent tool + +Kit includes a built-in \`spawn_subagent\` tool that the LLM can use to delegate tasks to independent child agents: + +\`\`\` +spawn_subagent( + task: "Analyze the test files and summarize coverage", + model: "anthropic/claude-haiku-3-5-20241022", // optional + system_prompt: "You are a test analysis expert.", // optional + timeout_seconds: 300 // optional, max 1800 +) +\`\`\` + +Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel. + +## Extension subagents + +Extensions can spawn subagents programmatically: + +\`\`\`go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Review this code for security issues", + Model: "anthropic/claude-sonnet-4-5-20250929", + SystemPrompt: "You are a security auditor.", +}) +\`\`\` + +## Go SDK subagents + +The SDK provides in-process subagent spawning: + +\`\`\`go +result, err := host.Subagent(ctx, kit.SubagentConfig{ + Task: "Summarize the changes in this PR", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a code reviewer.", + Timeout: 5 * time.Minute, +}) +\`\`\` +`};export{s as default}; diff --git a/assets/testing-COLNxuKj.js b/assets/testing-COLNxuKj.js new file mode 100644 index 00000000..e286ae69 --- /dev/null +++ b/assets/testing-COLNxuKj.js @@ -0,0 +1,130 @@ +const s={frontmatter:{title:"Testing with tmux",description:"Test Kit's TUI non-interactively using tmux.",hidden:!1,toc:!0,draft:!1},html:`

    Testing with tmux

    +

    Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development.

    +

    Basic pattern

    +
    # Start Kit in a detached tmux session
    +tmux new-session -d -s kittest -x 120 -y 40 \\
    +  "output/kit -e ext.go --no-session 2>kit_stderr.log"
    +
    +# Wait for startup
    +sleep 3
    +
    +# Capture the current screen
    +tmux capture-pane -t kittest -p
    +
    +# Send input
    +tmux send-keys -t kittest '/command' Enter
    +
    +# Wait for response
    +sleep 2
    +
    +# Capture updated screen
    +tmux capture-pane -t kittest -p
    +
    +# Cleanup
    +tmux kill-session -t kittest
    +

    Testing extensions

    +

    When testing extensions, the pattern is:

    +
      +
    1. Build Kit with your changes
    2. +
    3. Start Kit in tmux with the extension loaded
    4. +
    5. Send slash commands or prompts
    6. +
    7. Capture and verify the screen output
    8. +
    9. Check stderr logs for errors
    10. +
    +
    # Build first
    +go build -o output/kit ./cmd/kit
    +
    +# Start with extension
    +tmux new-session -d -s kittest -x 120 -y 40 \\
    +  "output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log"
    +
    +sleep 3
    +
    +# Verify widget appears in screen
    +tmux capture-pane -t kittest -p | grep "Status"
    +
    +# Send a slash command
    +tmux send-keys -t kittest '/stats' Enter
    +sleep 1
    +tmux capture-pane -t kittest -p
    +
    +# Cleanup
    +tmux kill-session -t kittest
    +

    Tips

    +
      +
    • Use -x and -y to set consistent terminal dimensions
    • +
    • Redirect stderr to a log file (2>kit.log) for debugging
    • +
    • Use --no-session to avoid creating session files during tests
    • +
    • Add sufficient sleep between commands for the TUI to render
    • +
    • Use grep on captured pane output to verify specific content
    • +
    `,headings:[{depth:2,text:"Basic pattern",id:"basic-pattern"},{depth:2,text:"Testing extensions",id:"testing-extensions"},{depth:2,text:"Tips",id:"tips"}],raw:` +# Testing with tmux + +Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development. + +## Basic pattern + +\`\`\`bash +# Start Kit in a detached tmux session +tmux new-session -d -s kittest -x 120 -y 40 \\ + "output/kit -e ext.go --no-session 2>kit_stderr.log" + +# Wait for startup +sleep 3 + +# Capture the current screen +tmux capture-pane -t kittest -p + +# Send input +tmux send-keys -t kittest '/command' Enter + +# Wait for response +sleep 2 + +# Capture updated screen +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +\`\`\` + +## Testing extensions + +When testing extensions, the pattern is: + +1. Build Kit with your changes +2. Start Kit in tmux with the extension loaded +3. Send slash commands or prompts +4. Capture and verify the screen output +5. Check stderr logs for errors + +\`\`\`bash +# Build first +go build -o output/kit ./cmd/kit + +# Start with extension +tmux new-session -d -s kittest -x 120 -y 40 \\ + "output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log" + +sleep 3 + +# Verify widget appears in screen +tmux capture-pane -t kittest -p | grep "Status" + +# Send a slash command +tmux send-keys -t kittest '/stats' Enter +sleep 1 +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +\`\`\` + +## Tips + +- Use \`-x\` and \`-y\` to set consistent terminal dimensions +- Redirect stderr to a log file (\`2>kit.log\`) for debugging +- Use \`--no-session\` to avoid creating session files during tests +- Add sufficient \`sleep\` between commands for the TUI to render +- Use \`grep\` on captured pane output to verify specific content +`};export{s as default}; diff --git a/assets/theme-BIHI7g3E.js b/assets/theme-BIHI7g3E.js new file mode 100644 index 00000000..b480ffe6 --- /dev/null +++ b/assets/theme-BIHI7g3E.js @@ -0,0 +1 @@ +const e={};export{e as default}; diff --git a/cli/commands/index.html b/cli/commands/index.html new file mode 100644 index 00000000..5cc08504 --- /dev/null +++ b/cli/commands/index.html @@ -0,0 +1,77 @@ + + + + + +Commands | Kit + + + + + + + +
    +

    Commands

    +# Commands + +## Authentication + +For OAuth-enabled providers like Anthropic. + +```bash +kit auth login [provider] # Start OAuth flow (e.g., anthropic) +kit auth logout [provider] # Remove credentials for provider +kit auth status # Check authentication status +``` + +## Model database + +Manage the local model database that maps provider names to API configurations. + +```bash +kit models [provider] # List available models (optionally filter by provider) +kit models --all # Show all providers (not just Fantasy-compatible) +kit update-models [source] # Update model database +``` + +The `update-models` command accepts an optional source argument: +- *(none)* — update from [models.dev](https://models.dev) +- A URL — fetch from a custom endpoint +- A file path — load from a local file +- `embedded` — reset to the bundled database + +## Extension management + +```bash +kit extensions list # List discovered extensions +kit extensions validate # Validate extension files +kit extensions init # Generate example extension template +``` + +### Installing extensions from git + +```bash +kit install # Install extensions from git repositories +kit install -l # Install to project-local .kit/git/ directory +kit install -u # Update an already-installed package +kit install --uninstall # Remove an installed package +kit install --all # Install all extensions without prompting +``` + +## Skills + +```bash +kit skill # Install the Kit extensions skill via skills.sh +``` + +## ACP server + +Run Kit as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout. + +```bash +kit acp # Start as ACP agent +kit acp --debug # With debug logging to stderr +```
    + + \ No newline at end of file diff --git a/cli/flags/index.html b/cli/flags/index.html new file mode 100644 index 00000000..01619ec6 --- /dev/null +++ b/cli/flags/index.html @@ -0,0 +1,78 @@ + + + + + +Global Flags | Kit + + + + + + + +
    +

    Global Flags

    +# Global Flags + +All flags can be passed to the root `kit` command. + +## Model and provider + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--model` | `-m` | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) | +| `--provider-api-key` | — | — | API key for the provider | +| `--provider-url` | — | — | Base URL for provider API | +| `--tls-skip-verify` | — | `false` | Skip TLS certificate verification | + +## Session management + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--session` | `-s` | — | Open specific JSONL session file | +| `--continue` | `-c` | `false` | Resume most recent session for current directory | +| `--resume` | `-r` | `false` | Interactive session picker | +| `--no-session` | — | `false` | Ephemeral mode, no persistence | + +## Behavior + +These flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode. + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--quiet` | — | `false` | Suppress all output (non-interactive only) | +| `--json` | — | `false` | Output response as JSON (non-interactive only) | +| `--no-exit` | — | `false` | Enter interactive mode after prompt completes | +| `--max-steps` | — | `0` | Maximum agent steps (0 for unlimited) | +| `--stream` | — | `true` | Enable streaming output | +| `--compact` | — | `false` | Enable compact output mode | +| `--auto-compact` | — | `false` | Auto-compact conversation near context limit | + +## Extensions + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--extension` | `-e` | — | Load additional extension file(s) (repeatable) | +| `--no-extensions` | — | `false` | Disable all extensions | + +## Generation parameters + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--max-tokens` | — | `4096` | Maximum tokens in response | +| `--temperature` | — | `0.7` | Randomness 0.0–1.0 | +| `--top-p` | — | `0.95` | Nucleus sampling 0.0–1.0 | +| `--top-k` | — | `40` | Limit top K tokens | +| `--stop-sequences` | — | — | Custom stop sequences (comma-separated) | +| `--thinking-level` | — | `off` | Extended thinking level: off, minimal, low, medium, high | + +## System + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--config` | — | `~/.kit.yml` | Config file path | +| `--system-prompt` | — | — | System prompt text or file path | +| `--debug` | — | `false` | Enable debug logging |
    + + \ No newline at end of file diff --git a/configuration/index.html b/configuration/index.html new file mode 100644 index 00000000..1559dc4b --- /dev/null +++ b/configuration/index.html @@ -0,0 +1,108 @@ + + + + + +Configuration | Kit + + + + + + + +
    +

    Configuration

    +# Configuration + +Kit looks for configuration in the following locations, in order of priority: + +1. CLI flags +2. Environment variables (with `KIT_` prefix) +3. `./.kit.yml` / `./.kit.yaml` / `./.kit.json` (project-local) +4. `~/.kit.yml` / `~/.kit.yaml` / `~/.kit.json` (global) + +## Basic configuration + +Create `~/.kit.yml`: + +```yaml +model: anthropic/claude-sonnet-4-5-20250929 +max-tokens: 4096 +temperature: 0.7 +stream: true +``` + +## All configuration keys + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `model` | string | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) | +| `max-tokens` | int | `4096` | Maximum tokens in response | +| `temperature` | float | `0.7` | Randomness 0.0–1.0 | +| `top-p` | float | `0.95` | Nucleus sampling 0.0–1.0 | +| `top-k` | int | `40` | Limit top K tokens | +| `stream` | bool | `true` | Enable streaming output | +| `debug` | bool | `false` | Enable debug logging | +| `compact` | bool | `false` | Enable compact output mode | +| `system-prompt` | string | — | System prompt text or file path | +| `max-steps` | int | `0` | Maximum agent steps (0 = unlimited) | +| `thinking-level` | string | `off` | Extended thinking: off, minimal, low, medium, high | +| `provider-api-key` | string | — | API key for the provider | +| `provider-url` | string | — | Base URL for provider API | +| `tls-skip-verify` | bool | `false` | Skip TLS certificate verification | +| `stop-sequences` | list | — | Custom stop sequences | +| `theme` | string | — | UI theme | +| `markdown-theme` | string | — | Markdown rendering theme | + +## Environment variables + +Any configuration key can be set via environment variable with the `KIT_` prefix. Hyphens become underscores: + +```bash +export KIT_MODEL="openai/gpt-4o" +export KIT_MAX_TOKENS="8192" +export KIT_TEMPERATURE="0.5" +``` + +Provider API keys use their own environment variables: + +```bash +export ANTHROPIC_API_KEY="sk-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +``` + +## MCP server configuration + +Add external MCP servers to your `.kit.yml`: + +```yaml +mcpServers: + filesystem: + type: local + command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"] + environment: + LOG_LEVEL: "info" + allowedTools: ["read_file", "write_file"] + excludedTools: ["delete_file"] + + search: + type: remote + url: "https://mcp.example.com/search" +``` + +### MCP server fields + +| Field | Type | Description | +|-------|------|-------------| +| `type` | string | `local` (stdio) or `remote` (streamable HTTP) | +| `command` | list | Command and args for local servers | +| `environment` | map | Environment variables for the server process | +| `url` | string | URL for remote servers | +| `allowedTools` | list | Whitelist of tool names to expose | +| `excludedTools` | list | Blacklist of tool names to hide | + +A legacy format with `transport`, `args`, `env`, and `headers` fields is also supported.
    + + \ No newline at end of file diff --git a/development/index.html b/development/index.html new file mode 100644 index 00000000..b2c35a94 --- /dev/null +++ b/development/index.html @@ -0,0 +1,96 @@ + + + + + +Development | Kit + + + + + + + +
    +

    Development

    +# Development + +## Build and test + +```bash +# Build +go build -o output/kit ./cmd/kit + +# Run all tests +go test -race ./... + +# Run a specific test +go test -race ./cmd -run TestScriptExecution + +# Lint +go vet ./... + +# Format +go fmt ./... +``` + +## Project structure + +``` +cmd/kit/ - CLI entry point (main.go) +cmd/ - CLI command implementations (root, auth, models, etc.) +pkg/kit/ - Go SDK for embedding Kit +internal/app/ - Application orchestrator (agent loop, message store, queue) +internal/agent/ - Agent execution and tool dispatch +internal/auth/ - OAuth authentication and credential storage +internal/acpserver/ - ACP (Agent Client Protocol) server +internal/clipboard/ - Cross-platform clipboard operations +internal/compaction/ - Conversation compaction and summarization +internal/config/ - Configuration management +internal/core/ - Built-in tools (bash, read, write, edit, grep, find, ls) +internal/extensions/ - Yaegi extension system +internal/kitsetup/ - Initial setup wizard +internal/message/ - Message content types and structured content blocks +internal/models/ - Provider and model management +internal/session/ - Session persistence (tree-based JSONL) +internal/skills/ - Skill loading and system prompt composition +internal/tools/ - MCP tool integration +internal/ui/ - Bubble Tea TUI components +examples/extensions/ - Example extension files +npm/ - NPM package wrapper for distribution +``` + +## Architecture overview + +Kit is built around a few key architectural patterns: + +### Multi-provider LLM support + +The `llm.Provider` interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API. + +### MCP client-server model + +External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in `.kit.yml`. + +### Extension system + +Extensions are Go source files interpreted at runtime by Yaegi. The `internal/extensions/` package manages loading, symbol export, and lifecycle dispatch. See the [Extension System](/extensions/overview) docs for details. + +### TUI architecture + +The interactive terminal UI is built with [Bubble Tea v2](https://github.com/charmbracelet/bubbletea), using a parent-child model where `AppModel` manages child components (`InputComponent`, `StreamComponent`, etc.). + +### Decoupling pattern + +`cmd/root.go` contains converter functions (e.g., `widgetProviderForUI()`) that bridge `internal/extensions/` types to `internal/ui/` types. The UI never imports the extensions package directly. + +## Contributing + +Contributions are welcome! Please see the [contribution guide](https://github.com/mark3labs/kit/blob/master/contribute/contribute.md) for guidelines. + +## Community + +- [Discord](https://discord.gg/RqSS2NQVsY) +- [GitHub Issues](https://github.com/mark3labs/kit/issues)
    + + \ No newline at end of file diff --git a/extensions/capabilities/index.html b/extensions/capabilities/index.html new file mode 100644 index 00000000..94ea17bb --- /dev/null +++ b/extensions/capabilities/index.html @@ -0,0 +1,269 @@ + + + + + +Capabilities | Kit + + + + + + + +
    +

    Capabilities

    +# Extension Capabilities + +## Lifecycle events + +Extensions can hook into 18 lifecycle events: + +| Event | Description | +|-------|-------------| +| `OnSessionStart` | Session initialized | +| `OnSessionShutdown` | Session ending | +| `OnBeforeAgentStart` | Before the agent loop begins | +| `OnAgentStart` | Agent loop started | +| `OnAgentEnd` | Agent loop completed | +| `OnToolCall` | Tool call requested by the model | +| `OnToolExecutionStart` | Tool execution beginning | +| `OnToolExecutionEnd` | Tool execution completed | +| `OnToolResult` | Tool result returned | +| `OnInput` | User input received | +| `OnMessageStart` | Assistant message started | +| `OnMessageUpdate` | Streaming text chunk received | +| `OnMessageEnd` | Assistant message completed | +| `OnModelChange` | Model switched | +| `OnContextPrepare` | Context being assembled for the model | +| `OnBeforeFork` | Before forking a conversation branch | +| `OnBeforeSessionSwitch` | Before switching sessions | +| `OnBeforeCompact` | Before conversation compaction | + +### Example + +```go +api.OnToolCall(func(event ext.ToolCallEvent, ctx ext.Context) { + ctx.PrintInfo("Calling tool: " + event.Name) +}) + +api.OnAgentEnd(func(_ ext.AgentEndEvent, ctx ext.Context) { + ctx.PrintInfo("Agent finished") +}) +``` + +## Tools + +Register custom tools that the LLM can invoke: + +```go +api.RegisterTool(ext.ToolDef{ + Name: "weather", + Description: "Get current weather for a location", + Parameters: map[string]ext.ParameterDef{ + "city": {Type: "string", Description: "City name", Required: true}, + }, + Handler: func(ctx ext.Context, params map[string]any) (string, error) { + city := params["city"].(string) + return "Sunny, 72°F in " + city, nil + }, +}) +``` + +## Commands + +Register slash commands that users can invoke directly: + +```go +api.RegisterCommand(ext.CommandDef{ + Name: "stats", + Description: "Show context statistics", + Handler: func(ctx ext.Context, args string) { + stats := ctx.GetContextStats() + ctx.PrintInfo(fmt.Sprintf("Tokens: %d", stats.TotalTokens)) + }, +}) +``` + +## Widgets + +Add persistent status displays above or below the input area: + +```go +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 1,234"}, +}) + +// Update later +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 2,456"}, +}) + +// Remove +ctx.RemoveWidget("token-count") +``` + +## Headers and footers + +Persistent content above and below the conversation: + +```go +ctx.SetHeader(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Project: my-app | Branch: main"}, +}) + +ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Plan Mode (read-only)"}, +}) +``` + +## Status bar + +Custom status bar entries: + +```go +ctx.SetStatus("mode", "Planning") +ctx.RemoveStatus("mode") +``` + +## Shortcuts + +Global keyboard shortcuts: + +```go +api.RegisterShortcut(ext.ShortcutDef{ + Key: "ctrl+t", + Description: "Toggle plan mode", +}, func(ctx ext.Context) { + // handle shortcut +}) +``` + +## Overlays + +Modal dialogs with markdown content: + +```go +ctx.ShowOverlay(ext.OverlayConfig{ + Title: "Help", + Content: "# Keyboard Shortcuts\n\n- **ctrl+t** — Toggle plan mode\n- **ctrl+s** — Save session", +}) +``` + +## Tool renderers + +Customize how specific tool calls are displayed in the TUI: + +```go +api.RegisterToolRenderer(ext.ToolRenderConfig{ + ToolName: "bash", + Render: func(name, args, result string, isError bool) string { + return "$ " + args + "\n" + result + }, +}) +``` + +## Message renderers + +Custom rendering for assistant messages: + +```go +api.RegisterMessageRenderer(ext.MessageRendererConfig{ + Name: "custom", + Render: func(content string) string { + return ">> " + content + }, +}) +``` + +## Editor interceptors + +Handle key events and wrap the editor's rendering: + +```go +ctx.SetEditor(ext.EditorConfig{ + HandleKey: func(key, text string) ext.EditorKeyAction { + if key == "escape" { + return ext.EditorKeyAction{Handled: true} + } + return ext.EditorKeyAction{Handled: false} + }, +}) +``` + +## Interactive prompts + +Select, confirm, input, and multi-select dialogs: + +```go +// Single select +response := ctx.PromptSelect(ext.PromptSelectConfig{ + Title: "Choose a model", + Options: []string{"claude-sonnet", "gpt-4o", "llama3"}, +}) + +// Confirm +confirmed := ctx.PromptConfirm(ext.PromptConfirmConfig{ + Title: "Delete this file?", +}) + +// Text input +name := ctx.PromptInput(ext.PromptInputConfig{ + Title: "Enter project name", + Placeholder: "my-project", +}) +``` + +## Options + +Register configurable extension options: + +```go +api.RegisterOption(ext.OptionDef{ + Name: "auto-commit", + Description: "Automatically commit on shutdown", + DefaultValue: "false", +}) +``` + +## Subagents + +Spawn in-process child Kit instances: + +```go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Analyze the test files and summarize coverage", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a test analysis expert.", +}) +``` + +## LLM completion + +Make direct model calls without going through the agent loop: + +```go +response := ctx.Complete(ext.CompleteRequest{ + Prompt: "Summarize this in one sentence: " + content, +}) +``` + +## Custom events + +Inter-extension communication: + +```go +// Emit +ctx.EmitCustomEvent("my-extension:data-ready", payload) + +// Listen +api.OnCustomEvent("my-extension:data-ready", func(data any, ctx ext.Context) { + // handle event +}) +```
    + + \ No newline at end of file diff --git a/extensions/examples/index.html b/extensions/examples/index.html new file mode 100644 index 00000000..898f64f2 --- /dev/null +++ b/extensions/examples/index.html @@ -0,0 +1,86 @@ + + + + + +Examples | Kit + + + + + + + +
    +

    Examples

    +# Extension Examples + +Kit ships with a rich set of example extensions in the `examples/extensions/` directory. These serve as both documentation and starting points for your own extensions. + +## UI and display + +| Extension | Description | +|-----------|-------------| +| `minimal.go` | Clean UI with custom footer | +| `branded-output.go` | Branded output rendering | +| `header-footer-demo.go` | Custom headers and footers | +| `widget-status.go` | Persistent status widgets | +| `overlay-demo.go` | Modal dialogs | +| `tool-renderer-demo.go` | Custom tool call rendering | +| `custom-editor-demo.go` | Vim-like modal editor | +| `pirate.go` | Pirate-themed personality | + +## Workflow and automation + +| Extension | Description | +|-----------|-------------| +| `auto-commit.go` | Auto-commit changes on shutdown | +| `plan-mode.go` | Read-only planning mode | +| `permission-gate.go` | Permission gating for destructive tools | +| `confirm-destructive.go` | Confirm destructive operations | +| `protected-paths.go` | Path protection for sensitive files | +| `project-rules.go` | Project-specific rules injection | +| `compact-notify.go` | Notification on conversation compaction | + +## Interactive features + +| Extension | Description | +|-----------|-------------| +| `prompt-demo.go` | Interactive prompts (select/confirm/input) | +| `bookmark.go` | Bookmark conversations | +| `inline-bash.go` | Inline bash execution | +| `interactive-shell.go` | Interactive shell integration | +| `notify.go` | Desktop notifications | + +## Agent and context + +| Extension | Description | +|-----------|-------------| +| `tool-logger.go` | Log all tool calls | +| `context-inject.go` | Inject context into conversations | +| `summarize.go` | Conversation summarization | +| `lsp-diagnostics.go` | LSP diagnostic integration | + +## Multi-agent + +| Extension | Description | +|-----------|-------------| +| `kit-kit.go` | Kit-in-Kit sub-agent spawning | +| `subagent-widget.go` | Multi-agent orchestration with status widget | +| `subagent-test.go` | Subagent testing utilities | + +## Development + +| Extension | Description | +|-----------|-------------| +| `dev-reload.go` | Development live-reload | + +## Subdirectory extensions + +| Directory | Description | +|-----------|-------------| +| `kit-kit-agents/` | Multi-agent orchestration example | +| `kit-telegram/` | Telegram bot integration | +| `status-tools/` | Status bar tool examples |
    + + \ No newline at end of file diff --git a/extensions/loading/index.html b/extensions/loading/index.html new file mode 100644 index 00000000..e295c86c --- /dev/null +++ b/extensions/loading/index.html @@ -0,0 +1,131 @@ + + + + + +Loading Extensions | Kit + + + + + + + +
    +

    Loading Extensions

    +# Loading Extensions + +## Auto-discovery + +Kit automatically discovers and loads extensions from these paths, in order: + +| Path | Scope | +|------|-------| +| `~/.config/kit/extensions/*.go` | Global single files | +| `~/.config/kit/extensions/*/main.go` | Global subdirectory extensions | +| `.kit/extensions/*.go` | Project-local single files | +| `.kit/extensions/*/main.go` | Project-local subdirectory extensions | +| `~/.local/share/kit/git/` | Global git-installed packages | +| `.kit/git/` | Project-local git-installed packages | + +## Explicit loading + +Load extensions by path using the `-e` flag: + +```bash +kit -e path/to/extension.go +``` + +Load multiple extensions: + +```bash +kit -e ext1.go -e ext2.go +``` + +## Disabling extensions + +Disable all auto-discovered extensions: + +```bash +kit --no-extensions +``` + +You can combine `--no-extensions` with `-e` to load only specific extensions: + +```bash +kit --no-extensions -e my-extension.go +``` + +## Installing from git + +Install extensions from git repositories using `kit install`: + +```bash +# Install globally (to ~/.local/share/kit/git/) +kit install https://github.com/user/my-kit-extension.git + +# Install project-locally (to .kit/git/) +kit install -l https://github.com/user/my-kit-extension.git + +# Update an installed package +kit install -u https://github.com/user/my-kit-extension.git + +# Remove +kit install --uninstall my-kit-extension +``` + +## Extension structure + +### Single-file extensions + +A single `.go` file with an `Init` function: + +```go +//go:build ignore + +package main + +import "kit/ext" + +func Init(api ext.API) { + // register handlers, tools, commands, etc. +} +``` + +The `//go:build ignore` directive prevents the Go toolchain from trying to compile the file as part of a normal build. + +### Subdirectory extensions + +For more complex extensions, create a directory with a `main.go` entry point: + +``` +.kit/extensions/my-extension/ +├── main.go # Must contain Init(api ext.API) +├── helpers.go # Additional source files +└── config.go +``` + +### Package-level state + +Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks: + +```go +package main + +import "kit/ext" + +var callCount int + +func Init(api ext.API) { + api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) { + callCount++ + ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{ + Text: fmt.Sprintf("Tools called: %d", callCount), + }, + }) + }) +} +```
    + + \ No newline at end of file diff --git a/extensions/overview/index.html b/extensions/overview/index.html new file mode 100644 index 00000000..bea46e6a --- /dev/null +++ b/extensions/overview/index.html @@ -0,0 +1,86 @@ + + + + + +Extension System | Kit + + + + + + + +
    +

    Extension System

    +# Extension System + +Extensions are Go source files interpreted at runtime via [Yaegi](https://github.com/traefik/yaegi). They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit. + +## Minimal extension + +```go +//go:build ignore + +package main + +import "kit/ext" + +func Init(api ext.API) { + api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) { + ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Custom Footer"}, + }) + }) +} +``` + +Run it with: + +```bash +kit -e examples/extensions/minimal.go +``` + +## How extensions work + +1. Kit discovers extension files from [auto-discovery paths](/extensions/loading) or explicit `-e` flags +2. Each `.go` file is loaded into a Yaegi interpreter with access to the `kit/ext` package +3. Kit calls the `Init(api ext.API)` function in each extension +4. The extension registers callbacks, tools, commands, and UI components via the `api` and `ctx` objects + +## Key concepts + +### The `API` object + +Passed to `Init()`, the `API` object is used to register lifecycle event handlers and static components: + +- **Lifecycle handlers** — `api.OnSessionStart(...)`, `api.OnToolCall(...)`, etc. +- **Tools** — `api.RegisterTool(ext.ToolDef{...})` +- **Commands** — `api.RegisterCommand(ext.CommandDef{...})` +- **Shortcuts** — `api.RegisterShortcut(ext.ShortcutDef{...}, handler)` +- **Tool renderers** — `api.RegisterToolRenderer(ext.ToolRenderConfig{...})` +- **Message renderers** — `api.RegisterMessageRenderer(ext.MessageRendererConfig{...})` +- **Options** — `api.RegisterOption(ext.OptionDef{...})` + +### The `Context` object + +Passed to event handlers, the `Context` object provides runtime access to Kit's state and UI: + +- **Output** — `ctx.Print(...)`, `ctx.PrintInfo(...)`, `ctx.PrintError(...)` +- **UI components** — `ctx.SetWidget(...)`, `ctx.SetHeader(...)`, `ctx.SetFooter(...)`, `ctx.SetStatus(...)` +- **Editor** — `ctx.SetEditor(...)`, `ctx.ResetEditor()` +- **Prompts** — `ctx.PromptSelect(...)`, `ctx.PromptConfirm(...)`, `ctx.PromptInput(...)` +- **Overlays** — `ctx.ShowOverlay(...)` +- **Messages** — `ctx.SendMessage(...)`, `ctx.GetMessages()` +- **Model** — `ctx.SetModel(...)`, `ctx.GetAvailableModels()` +- **Tools** — `ctx.GetAllTools()`, `ctx.SetActiveTools(...)` +- **Context stats** — `ctx.GetContextStats()` +- **Session data** — `ctx.AppendEntry(...)`, `ctx.GetEntries(...)` +- **Subagents** — `ctx.SpawnSubagent(...)` +- **LLM completion** — `ctx.Complete(...)` +- **Custom events** — `ctx.EmitCustomEvent(...)` +- **App control** — `ctx.Exit()`, `ctx.ReloadExtensions()` + +See [Capabilities](/extensions/capabilities) for full details on each component type.
    + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..b1458d98 --- /dev/null +++ b/index.html @@ -0,0 +1,24 @@ + + + + + + Kit Documentation + + + + + + + + + +
    + + diff --git a/installation/index.html b/installation/index.html new file mode 100644 index 00000000..3664982f --- /dev/null +++ b/installation/index.html @@ -0,0 +1,69 @@ + + + + + +Installation | Kit + + + + + + + +
    +

    Installation

    +# Installation + +## Using npm (recommended) + +```bash +npm install -g @mark3labs/kit +``` + +## Using Go + +```bash +go install github.com/mark3labs/kit/cmd/kit@latest +``` + +## Building from source + +```bash +git clone https://github.com/mark3labs/kit.git +cd kit +go build -o kit ./cmd/kit +``` + +## Verifying the installation + +After installing, verify Kit is available: + +```bash +kit --help +``` + +## Setting up a provider + +Kit needs at least one LLM provider configured. Set an API key for your preferred provider: + +```bash +# Anthropic (default provider) +export ANTHROPIC_API_KEY="sk-..." + +# OpenAI +export OPENAI_API_KEY="sk-..." + +# Google Gemini +export GOOGLE_API_KEY="..." +``` + +For OAuth-enabled providers like Anthropic, you can also authenticate interactively: + +```bash +kit auth login anthropic +``` + +See [Providers](/providers) for the full list of supported providers and their configuration.
    + + \ No newline at end of file diff --git a/llms-full.txt b/llms-full.txt new file mode 100644 index 00000000..a7313308 --- /dev/null +++ b/llms-full.txt @@ -0,0 +1,1810 @@ +# Kit + +--- + +## JSON Output + +# JSON Output + +Use the `--json` flag to get structured output for scripting and automation: + +```bash +kit "Explain main.go" --json --quiet --no-session +``` + +## Response format + +```json +{ + "response": "Final assistant response text", + "model": "anthropic/claude-haiku-3-5-20241022", + "stop_reason": "end_turn", + "session_id": "a1b2c3d4e5f6", + "usage": { + "input_tokens": 1024, + "output_tokens": 512, + "total_tokens": 1536, + "cache_read_tokens": 0, + "cache_creation_tokens": 0 + }, + "messages": [ + { + "role": "assistant", + "parts": [ + {"type": "text", "data": "..."}, + {"type": "tool_call", "data": {"name": "...", "args": "..."}}, + {"type": "tool_result", "data": {"name": "...", "result": "..."}} + ] + } + ] +} +``` + +## Fields + +### Top-level + +| Field | Type | Description | +|-------|------|-------------| +| `response` | string | The final assistant response text | +| `model` | string | The model that was used | +| `stop_reason` | string | Why the model stopped (e.g., `end_turn`) | +| `session_id` | string | Session identifier (omitted in `--no-session` mode) | +| `usage` | object | Token usage statistics | +| `messages` | array | Full conversation history | + +### Usage + +| Field | Type | Description | +|-------|------|-------------| +| `input_tokens` | int | Tokens sent to the model | +| `output_tokens` | int | Tokens generated by the model | +| `total_tokens` | int | Sum of input and output tokens | +| `cache_read_tokens` | int | Tokens read from prompt cache | +| `cache_creation_tokens` | int | Tokens written to prompt cache | + +### Message parts + +Each message contains a `parts` array with typed entries: + +| Type | Description | +|------|-------------| +| `text` | Assistant text content | +| `tool_call` | Tool invocation with name and args | +| `tool_result` | Tool execution result | +| `reasoning` | Extended thinking content | +| `finish` | End-of-turn marker | + +## Parsing in scripts + +### bash + jq + +```bash +result=$(kit "Count files" --json --quiet --no-session) +response=$(echo "$result" | jq -r '.response') +tokens=$(echo "$result" | jq '.usage.total_tokens') +``` + +### Go SDK + +For Go programs, use the SDK's `PromptResult` method instead of parsing JSON: + +```go +result, err := host.PromptResult(ctx, "Count files") +fmt.Println(result.Response) +fmt.Println(result.Usage.TotalTokens) +``` + +--- + +## Subagents + +# Subagents + +Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents. + +## Subprocess pattern + +Spawn Kit as a subprocess for isolated agent execution: + +```bash +kit "Analyze codebase" \ + --json \ + --no-session \ + --no-extensions \ + --quiet \ + --model anthropic/claude-haiku-3-5-20241022 +``` + +Key flags for subprocess usage: + +| Flag | Purpose | +|------|---------| +| `--quiet` | Stdout only, no TUI | +| `--no-session` | Ephemeral, no persistence | +| `--no-extensions` | Prevent recursive extension loading | +| `--json` | Machine-readable output | +| `--system-prompt` | Custom system prompt (string or file path) | + +Positional arguments are the prompt. `@file` arguments attach file content as context. + +## Built-in spawn_subagent tool + +Kit includes a built-in `spawn_subagent` tool that the LLM can use to delegate tasks to independent child agents: + +``` +spawn_subagent( + task: "Analyze the test files and summarize coverage", + model: "anthropic/claude-haiku-3-5-20241022", // optional + system_prompt: "You are a test analysis expert.", // optional + timeout_seconds: 300 // optional, max 1800 +) +``` + +Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel. + +## Extension subagents + +Extensions can spawn subagents programmatically: + +```go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Review this code for security issues", + Model: "anthropic/claude-sonnet-4-5-20250929", + SystemPrompt: "You are a security auditor.", +}) +``` + +## Go SDK subagents + +The SDK provides in-process subagent spawning: + +```go +result, err := host.Subagent(ctx, kit.SubagentConfig{ + Task: "Summarize the changes in this PR", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a code reviewer.", + Timeout: 5 * time.Minute, +}) +``` + +--- + +## Testing with tmux + +# Testing with tmux + +Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development. + +## Basic pattern + +```bash +# Start Kit in a detached tmux session +tmux new-session -d -s kittest -x 120 -y 40 \ + "output/kit -e ext.go --no-session 2>kit_stderr.log" + +# Wait for startup +sleep 3 + +# Capture the current screen +tmux capture-pane -t kittest -p + +# Send input +tmux send-keys -t kittest '/command' Enter + +# Wait for response +sleep 2 + +# Capture updated screen +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +``` + +## Testing extensions + +When testing extensions, the pattern is: + +1. Build Kit with your changes +2. Start Kit in tmux with the extension loaded +3. Send slash commands or prompts +4. Capture and verify the screen output +5. Check stderr logs for errors + +```bash +# Build first +go build -o output/kit ./cmd/kit + +# Start with extension +tmux new-session -d -s kittest -x 120 -y 40 \ + "output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log" + +sleep 3 + +# Verify widget appears in screen +tmux capture-pane -t kittest -p | grep "Status" + +# Send a slash command +tmux send-keys -t kittest '/stats' Enter +sleep 1 +tmux capture-pane -t kittest -p + +# Cleanup +tmux kill-session -t kittest +``` + +## Tips + +- Use `-x` and `-y` to set consistent terminal dimensions +- Redirect stderr to a log file (`2>kit.log`) for debugging +- Use `--no-session` to avoid creating session files during tests +- Add sufficient `sleep` between commands for the TUI to render +- Use `grep` on captured pane output to verify specific content + +--- + +## Commands + +# Commands + +## Authentication + +For OAuth-enabled providers like Anthropic. + +```bash +kit auth login [provider] # Start OAuth flow (e.g., anthropic) +kit auth logout [provider] # Remove credentials for provider +kit auth status # Check authentication status +``` + +## Model database + +Manage the local model database that maps provider names to API configurations. + +```bash +kit models [provider] # List available models (optionally filter by provider) +kit models --all # Show all providers (not just Fantasy-compatible) +kit update-models [source] # Update model database +``` + +The `update-models` command accepts an optional source argument: +- *(none)* — update from [models.dev](https://models.dev) +- A URL — fetch from a custom endpoint +- A file path — load from a local file +- `embedded` — reset to the bundled database + +## Extension management + +```bash +kit extensions list # List discovered extensions +kit extensions validate # Validate extension files +kit extensions init # Generate example extension template +``` + +### Installing extensions from git + +```bash +kit install # Install extensions from git repositories +kit install -l # Install to project-local .kit/git/ directory +kit install -u # Update an already-installed package +kit install --uninstall # Remove an installed package +kit install --all # Install all extensions without prompting +``` + +## Skills + +```bash +kit skill # Install the Kit extensions skill via skills.sh +``` + +## ACP server + +Run Kit as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout. + +```bash +kit acp # Start as ACP agent +kit acp --debug # With debug logging to stderr +``` + +--- + +## Global Flags + +# Global Flags + +All flags can be passed to the root `kit` command. + +## Model and provider + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--model` | `-m` | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) | +| `--provider-api-key` | — | — | API key for the provider | +| `--provider-url` | — | — | Base URL for provider API | +| `--tls-skip-verify` | — | `false` | Skip TLS certificate verification | + +## Session management + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--session` | `-s` | — | Open specific JSONL session file | +| `--continue` | `-c` | `false` | Resume most recent session for current directory | +| `--resume` | `-r` | `false` | Interactive session picker | +| `--no-session` | — | `false` | Ephemeral mode, no persistence | + +## Behavior + +These flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode. + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--quiet` | — | `false` | Suppress all output (non-interactive only) | +| `--json` | — | `false` | Output response as JSON (non-interactive only) | +| `--no-exit` | — | `false` | Enter interactive mode after prompt completes | +| `--max-steps` | — | `0` | Maximum agent steps (0 for unlimited) | +| `--stream` | — | `true` | Enable streaming output | +| `--compact` | — | `false` | Enable compact output mode | +| `--auto-compact` | — | `false` | Auto-compact conversation near context limit | + +## Extensions + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--extension` | `-e` | — | Load additional extension file(s) (repeatable) | +| `--no-extensions` | — | `false` | Disable all extensions | + +## Generation parameters + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--max-tokens` | — | `4096` | Maximum tokens in response | +| `--temperature` | — | `0.7` | Randomness 0.0–1.0 | +| `--top-p` | — | `0.95` | Nucleus sampling 0.0–1.0 | +| `--top-k` | — | `40` | Limit top K tokens | +| `--stop-sequences` | — | — | Custom stop sequences (comma-separated) | +| `--thinking-level` | — | `off` | Extended thinking level: off, minimal, low, medium, high | + +## System + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--config` | — | `~/.kit.yml` | Config file path | +| `--system-prompt` | — | — | System prompt text or file path | +| `--debug` | — | `false` | Enable debug logging | + +--- + +## Configuration + +# Configuration + +Kit looks for configuration in the following locations, in order of priority: + +1. CLI flags +2. Environment variables (with `KIT_` prefix) +3. `./.kit.yml` / `./.kit.yaml` / `./.kit.json` (project-local) +4. `~/.kit.yml` / `~/.kit.yaml` / `~/.kit.json` (global) + +## Basic configuration + +Create `~/.kit.yml`: + +```yaml +model: anthropic/claude-sonnet-4-5-20250929 +max-tokens: 4096 +temperature: 0.7 +stream: true +``` + +## All configuration keys + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `model` | string | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) | +| `max-tokens` | int | `4096` | Maximum tokens in response | +| `temperature` | float | `0.7` | Randomness 0.0–1.0 | +| `top-p` | float | `0.95` | Nucleus sampling 0.0–1.0 | +| `top-k` | int | `40` | Limit top K tokens | +| `stream` | bool | `true` | Enable streaming output | +| `debug` | bool | `false` | Enable debug logging | +| `compact` | bool | `false` | Enable compact output mode | +| `system-prompt` | string | — | System prompt text or file path | +| `max-steps` | int | `0` | Maximum agent steps (0 = unlimited) | +| `thinking-level` | string | `off` | Extended thinking: off, minimal, low, medium, high | +| `provider-api-key` | string | — | API key for the provider | +| `provider-url` | string | — | Base URL for provider API | +| `tls-skip-verify` | bool | `false` | Skip TLS certificate verification | +| `stop-sequences` | list | — | Custom stop sequences | +| `theme` | string | — | UI theme | +| `markdown-theme` | string | — | Markdown rendering theme | + +## Environment variables + +Any configuration key can be set via environment variable with the `KIT_` prefix. Hyphens become underscores: + +```bash +export KIT_MODEL="openai/gpt-4o" +export KIT_MAX_TOKENS="8192" +export KIT_TEMPERATURE="0.5" +``` + +Provider API keys use their own environment variables: + +```bash +export ANTHROPIC_API_KEY="sk-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +``` + +## MCP server configuration + +Add external MCP servers to your `.kit.yml`: + +```yaml +mcpServers: + filesystem: + type: local + command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"] + environment: + LOG_LEVEL: "info" + allowedTools: ["read_file", "write_file"] + excludedTools: ["delete_file"] + + search: + type: remote + url: "https://mcp.example.com/search" +``` + +### MCP server fields + +| Field | Type | Description | +|-------|------|-------------| +| `type` | string | `local` (stdio) or `remote` (streamable HTTP) | +| `command` | list | Command and args for local servers | +| `environment` | map | Environment variables for the server process | +| `url` | string | URL for remote servers | +| `allowedTools` | list | Whitelist of tool names to expose | +| `excludedTools` | list | Blacklist of tool names to hide | + +A legacy format with `transport`, `args`, `env`, and `headers` fields is also supported. + +--- + +## Development + +# Development + +## Build and test + +```bash +# Build +go build -o output/kit ./cmd/kit + +# Run all tests +go test -race ./... + +# Run a specific test +go test -race ./cmd -run TestScriptExecution + +# Lint +go vet ./... + +# Format +go fmt ./... +``` + +## Project structure + +``` +cmd/kit/ - CLI entry point (main.go) +cmd/ - CLI command implementations (root, auth, models, etc.) +pkg/kit/ - Go SDK for embedding Kit +internal/app/ - Application orchestrator (agent loop, message store, queue) +internal/agent/ - Agent execution and tool dispatch +internal/auth/ - OAuth authentication and credential storage +internal/acpserver/ - ACP (Agent Client Protocol) server +internal/clipboard/ - Cross-platform clipboard operations +internal/compaction/ - Conversation compaction and summarization +internal/config/ - Configuration management +internal/core/ - Built-in tools (bash, read, write, edit, grep, find, ls) +internal/extensions/ - Yaegi extension system +internal/kitsetup/ - Initial setup wizard +internal/message/ - Message content types and structured content blocks +internal/models/ - Provider and model management +internal/session/ - Session persistence (tree-based JSONL) +internal/skills/ - Skill loading and system prompt composition +internal/tools/ - MCP tool integration +internal/ui/ - Bubble Tea TUI components +examples/extensions/ - Example extension files +npm/ - NPM package wrapper for distribution +``` + +## Architecture overview + +Kit is built around a few key architectural patterns: + +### Multi-provider LLM support + +The `llm.Provider` interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API. + +### MCP client-server model + +External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in `.kit.yml`. + +### Extension system + +Extensions are Go source files interpreted at runtime by Yaegi. The `internal/extensions/` package manages loading, symbol export, and lifecycle dispatch. See the [Extension System](/extensions/overview) docs for details. + +### TUI architecture + +The interactive terminal UI is built with [Bubble Tea v2](https://github.com/charmbracelet/bubbletea), using a parent-child model where `AppModel` manages child components (`InputComponent`, `StreamComponent`, etc.). + +### Decoupling pattern + +`cmd/root.go` contains converter functions (e.g., `widgetProviderForUI()`) that bridge `internal/extensions/` types to `internal/ui/` types. The UI never imports the extensions package directly. + +## Contributing + +Contributions are welcome! Please see the [contribution guide](https://github.com/mark3labs/kit/blob/master/contribute/contribute.md) for guidelines. + +## Community + +- [Discord](https://discord.gg/RqSS2NQVsY) +- [GitHub Issues](https://github.com/mark3labs/kit/issues) + +--- + +## Capabilities + +# Extension Capabilities + +## Lifecycle events + +Extensions can hook into 18 lifecycle events: + +| Event | Description | +|-------|-------------| +| `OnSessionStart` | Session initialized | +| `OnSessionShutdown` | Session ending | +| `OnBeforeAgentStart` | Before the agent loop begins | +| `OnAgentStart` | Agent loop started | +| `OnAgentEnd` | Agent loop completed | +| `OnToolCall` | Tool call requested by the model | +| `OnToolExecutionStart` | Tool execution beginning | +| `OnToolExecutionEnd` | Tool execution completed | +| `OnToolResult` | Tool result returned | +| `OnInput` | User input received | +| `OnMessageStart` | Assistant message started | +| `OnMessageUpdate` | Streaming text chunk received | +| `OnMessageEnd` | Assistant message completed | +| `OnModelChange` | Model switched | +| `OnContextPrepare` | Context being assembled for the model | +| `OnBeforeFork` | Before forking a conversation branch | +| `OnBeforeSessionSwitch` | Before switching sessions | +| `OnBeforeCompact` | Before conversation compaction | + +### Example + +```go +api.OnToolCall(func(event ext.ToolCallEvent, ctx ext.Context) { + ctx.PrintInfo("Calling tool: " + event.Name) +}) + +api.OnAgentEnd(func(_ ext.AgentEndEvent, ctx ext.Context) { + ctx.PrintInfo("Agent finished") +}) +``` + +## Tools + +Register custom tools that the LLM can invoke: + +```go +api.RegisterTool(ext.ToolDef{ + Name: "weather", + Description: "Get current weather for a location", + Parameters: map[string]ext.ParameterDef{ + "city": {Type: "string", Description: "City name", Required: true}, + }, + Handler: func(ctx ext.Context, params map[string]any) (string, error) { + city := params["city"].(string) + return "Sunny, 72°F in " + city, nil + }, +}) +``` + +## Commands + +Register slash commands that users can invoke directly: + +```go +api.RegisterCommand(ext.CommandDef{ + Name: "stats", + Description: "Show context statistics", + Handler: func(ctx ext.Context, args string) { + stats := ctx.GetContextStats() + ctx.PrintInfo(fmt.Sprintf("Tokens: %d", stats.TotalTokens)) + }, +}) +``` + +## Widgets + +Add persistent status displays above or below the input area: + +```go +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 1,234"}, +}) + +// Update later +ctx.SetWidget(ext.WidgetConfig{ + ID: "token-count", + Position: "bottom", + Content: ext.WidgetContent{Text: "Tokens: 2,456"}, +}) + +// Remove +ctx.RemoveWidget("token-count") +``` + +## Headers and footers + +Persistent content above and below the conversation: + +```go +ctx.SetHeader(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Project: my-app | Branch: main"}, +}) + +ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Plan Mode (read-only)"}, +}) +``` + +## Status bar + +Custom status bar entries: + +```go +ctx.SetStatus("mode", "Planning") +ctx.RemoveStatus("mode") +``` + +## Shortcuts + +Global keyboard shortcuts: + +```go +api.RegisterShortcut(ext.ShortcutDef{ + Key: "ctrl+t", + Description: "Toggle plan mode", +}, func(ctx ext.Context) { + // handle shortcut +}) +``` + +## Overlays + +Modal dialogs with markdown content: + +```go +ctx.ShowOverlay(ext.OverlayConfig{ + Title: "Help", + Content: "# Keyboard Shortcuts\n\n- **ctrl+t** — Toggle plan mode\n- **ctrl+s** — Save session", +}) +``` + +## Tool renderers + +Customize how specific tool calls are displayed in the TUI: + +```go +api.RegisterToolRenderer(ext.ToolRenderConfig{ + ToolName: "bash", + Render: func(name, args, result string, isError bool) string { + return "$ " + args + "\n" + result + }, +}) +``` + +## Message renderers + +Custom rendering for assistant messages: + +```go +api.RegisterMessageRenderer(ext.MessageRendererConfig{ + Name: "custom", + Render: func(content string) string { + return ">> " + content + }, +}) +``` + +## Editor interceptors + +Handle key events and wrap the editor's rendering: + +```go +ctx.SetEditor(ext.EditorConfig{ + HandleKey: func(key, text string) ext.EditorKeyAction { + if key == "escape" { + return ext.EditorKeyAction{Handled: true} + } + return ext.EditorKeyAction{Handled: false} + }, +}) +``` + +## Interactive prompts + +Select, confirm, input, and multi-select dialogs: + +```go +// Single select +response := ctx.PromptSelect(ext.PromptSelectConfig{ + Title: "Choose a model", + Options: []string{"claude-sonnet", "gpt-4o", "llama3"}, +}) + +// Confirm +confirmed := ctx.PromptConfirm(ext.PromptConfirmConfig{ + Title: "Delete this file?", +}) + +// Text input +name := ctx.PromptInput(ext.PromptInputConfig{ + Title: "Enter project name", + Placeholder: "my-project", +}) +``` + +## Options + +Register configurable extension options: + +```go +api.RegisterOption(ext.OptionDef{ + Name: "auto-commit", + Description: "Automatically commit on shutdown", + DefaultValue: "false", +}) +``` + +## Subagents + +Spawn in-process child Kit instances: + +```go +result := ctx.SpawnSubagent(ext.SubagentConfig{ + Task: "Analyze the test files and summarize coverage", + Model: "anthropic/claude-haiku-3-5-20241022", + SystemPrompt: "You are a test analysis expert.", +}) +``` + +## LLM completion + +Make direct model calls without going through the agent loop: + +```go +response := ctx.Complete(ext.CompleteRequest{ + Prompt: "Summarize this in one sentence: " + content, +}) +``` + +## Custom events + +Inter-extension communication: + +```go +// Emit +ctx.EmitCustomEvent("my-extension:data-ready", payload) + +// Listen +api.OnCustomEvent("my-extension:data-ready", func(data any, ctx ext.Context) { + // handle event +}) +``` + +--- + +## Examples + +# Extension Examples + +Kit ships with a rich set of example extensions in the `examples/extensions/` directory. These serve as both documentation and starting points for your own extensions. + +## UI and display + +| Extension | Description | +|-----------|-------------| +| `minimal.go` | Clean UI with custom footer | +| `branded-output.go` | Branded output rendering | +| `header-footer-demo.go` | Custom headers and footers | +| `widget-status.go` | Persistent status widgets | +| `overlay-demo.go` | Modal dialogs | +| `tool-renderer-demo.go` | Custom tool call rendering | +| `custom-editor-demo.go` | Vim-like modal editor | +| `pirate.go` | Pirate-themed personality | + +## Workflow and automation + +| Extension | Description | +|-----------|-------------| +| `auto-commit.go` | Auto-commit changes on shutdown | +| `plan-mode.go` | Read-only planning mode | +| `permission-gate.go` | Permission gating for destructive tools | +| `confirm-destructive.go` | Confirm destructive operations | +| `protected-paths.go` | Path protection for sensitive files | +| `project-rules.go` | Project-specific rules injection | +| `compact-notify.go` | Notification on conversation compaction | + +## Interactive features + +| Extension | Description | +|-----------|-------------| +| `prompt-demo.go` | Interactive prompts (select/confirm/input) | +| `bookmark.go` | Bookmark conversations | +| `inline-bash.go` | Inline bash execution | +| `interactive-shell.go` | Interactive shell integration | +| `notify.go` | Desktop notifications | + +## Agent and context + +| Extension | Description | +|-----------|-------------| +| `tool-logger.go` | Log all tool calls | +| `context-inject.go` | Inject context into conversations | +| `summarize.go` | Conversation summarization | +| `lsp-diagnostics.go` | LSP diagnostic integration | + +## Multi-agent + +| Extension | Description | +|-----------|-------------| +| `kit-kit.go` | Kit-in-Kit sub-agent spawning | +| `subagent-widget.go` | Multi-agent orchestration with status widget | +| `subagent-test.go` | Subagent testing utilities | + +## Development + +| Extension | Description | +|-----------|-------------| +| `dev-reload.go` | Development live-reload | + +## Subdirectory extensions + +| Directory | Description | +|-----------|-------------| +| `kit-kit-agents/` | Multi-agent orchestration example | +| `kit-telegram/` | Telegram bot integration | +| `status-tools/` | Status bar tool examples | + +--- + +## Loading Extensions + +# Loading Extensions + +## Auto-discovery + +Kit automatically discovers and loads extensions from these paths, in order: + +| Path | Scope | +|------|-------| +| `~/.config/kit/extensions/*.go` | Global single files | +| `~/.config/kit/extensions/*/main.go` | Global subdirectory extensions | +| `.kit/extensions/*.go` | Project-local single files | +| `.kit/extensions/*/main.go` | Project-local subdirectory extensions | +| `~/.local/share/kit/git/` | Global git-installed packages | +| `.kit/git/` | Project-local git-installed packages | + +## Explicit loading + +Load extensions by path using the `-e` flag: + +```bash +kit -e path/to/extension.go +``` + +Load multiple extensions: + +```bash +kit -e ext1.go -e ext2.go +``` + +## Disabling extensions + +Disable all auto-discovered extensions: + +```bash +kit --no-extensions +``` + +You can combine `--no-extensions` with `-e` to load only specific extensions: + +```bash +kit --no-extensions -e my-extension.go +``` + +## Installing from git + +Install extensions from git repositories using `kit install`: + +```bash +# Install globally (to ~/.local/share/kit/git/) +kit install https://github.com/user/my-kit-extension.git + +# Install project-locally (to .kit/git/) +kit install -l https://github.com/user/my-kit-extension.git + +# Update an installed package +kit install -u https://github.com/user/my-kit-extension.git + +# Remove +kit install --uninstall my-kit-extension +``` + +## Extension structure + +### Single-file extensions + +A single `.go` file with an `Init` function: + +```go +//go:build ignore + +package main + +import "kit/ext" + +func Init(api ext.API) { + // register handlers, tools, commands, etc. +} +``` + +The `//go:build ignore` directive prevents the Go toolchain from trying to compile the file as part of a normal build. + +### Subdirectory extensions + +For more complex extensions, create a directory with a `main.go` entry point: + +``` +.kit/extensions/my-extension/ +├── main.go # Must contain Init(api ext.API) +├── helpers.go # Additional source files +└── config.go +``` + +### Package-level state + +Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks: + +```go +package main + +import "kit/ext" + +var callCount int + +func Init(api ext.API) { + api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) { + callCount++ + ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{ + Text: fmt.Sprintf("Tools called: %d", callCount), + }, + }) + }) +} +``` + +--- + +## Extension System + +# Extension System + +Extensions are Go source files interpreted at runtime via [Yaegi](https://github.com/traefik/yaegi). They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit. + +## Minimal extension + +```go +//go:build ignore + +package main + +import "kit/ext" + +func Init(api ext.API) { + api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) { + ctx.SetFooter(ext.HeaderFooterConfig{ + Content: ext.WidgetContent{Text: "Custom Footer"}, + }) + }) +} +``` + +Run it with: + +```bash +kit -e examples/extensions/minimal.go +``` + +## How extensions work + +1. Kit discovers extension files from [auto-discovery paths](/extensions/loading) or explicit `-e` flags +2. Each `.go` file is loaded into a Yaegi interpreter with access to the `kit/ext` package +3. Kit calls the `Init(api ext.API)` function in each extension +4. The extension registers callbacks, tools, commands, and UI components via the `api` and `ctx` objects + +## Key concepts + +### The `API` object + +Passed to `Init()`, the `API` object is used to register lifecycle event handlers and static components: + +- **Lifecycle handlers** — `api.OnSessionStart(...)`, `api.OnToolCall(...)`, etc. +- **Tools** — `api.RegisterTool(ext.ToolDef{...})` +- **Commands** — `api.RegisterCommand(ext.CommandDef{...})` +- **Shortcuts** — `api.RegisterShortcut(ext.ShortcutDef{...}, handler)` +- **Tool renderers** — `api.RegisterToolRenderer(ext.ToolRenderConfig{...})` +- **Message renderers** — `api.RegisterMessageRenderer(ext.MessageRendererConfig{...})` +- **Options** — `api.RegisterOption(ext.OptionDef{...})` + +### The `Context` object + +Passed to event handlers, the `Context` object provides runtime access to Kit's state and UI: + +- **Output** — `ctx.Print(...)`, `ctx.PrintInfo(...)`, `ctx.PrintError(...)` +- **UI components** — `ctx.SetWidget(...)`, `ctx.SetHeader(...)`, `ctx.SetFooter(...)`, `ctx.SetStatus(...)` +- **Editor** — `ctx.SetEditor(...)`, `ctx.ResetEditor()` +- **Prompts** — `ctx.PromptSelect(...)`, `ctx.PromptConfirm(...)`, `ctx.PromptInput(...)` +- **Overlays** — `ctx.ShowOverlay(...)` +- **Messages** — `ctx.SendMessage(...)`, `ctx.GetMessages()` +- **Model** — `ctx.SetModel(...)`, `ctx.GetAvailableModels()` +- **Tools** — `ctx.GetAllTools()`, `ctx.SetActiveTools(...)` +- **Context stats** — `ctx.GetContextStats()` +- **Session data** — `ctx.AppendEntry(...)`, `ctx.GetEntries(...)` +- **Subagents** — `ctx.SpawnSubagent(...)` +- **LLM completion** — `ctx.Complete(...)` +- **Custom events** — `ctx.EmitCustomEvent(...)` +- **App control** — `ctx.Exit()`, `ctx.ReloadExtensions()` + +See [Capabilities](/extensions/capabilities) for full details on each component type. + +--- + +## Kit + +
    + KIT +
    + +A powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system. + +## Features + +- **Multi-Provider LLM Support** — Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more +- **Built-in Core Tools** — bash, read, write, edit, grep, find, ls, spawn_subagent with no MCP overhead +- **MCP Integration** — Connect external MCP servers for expanded capabilities +- **Extension System** — Write custom tools, commands, widgets, and UI modifications in Go +- **Interactive TUI** — Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering +- **Session Management** — Tree-based conversation history with branching support +- **Non-Interactive Mode** — Script-friendly positional args with JSON output +- **ACP Server** — Run Kit as an [Agent Client Protocol](https://agentclientprotocol.com) agent over stdio +- **Go SDK** — Embed Kit in your own applications + +## Quick links + +| Resource | Description | +|----------|-------------| +| [Installation](/installation) | Get Kit up and running | +| [Quick Start](/quick-start) | Your first Kit session | +| [Configuration](/configuration) | Customize Kit for your workflow | +| [Extensions](/extensions/overview) | Build custom tools and UI components | +| [Go SDK](/sdk/overview) | Embed Kit in your applications | + +--- + +## Installation + +# Installation + +## Using npm (recommended) + +```bash +npm install -g @mark3labs/kit +``` + +## Using Go + +```bash +go install github.com/mark3labs/kit/cmd/kit@latest +``` + +## Building from source + +```bash +git clone https://github.com/mark3labs/kit.git +cd kit +go build -o kit ./cmd/kit +``` + +## Verifying the installation + +After installing, verify Kit is available: + +```bash +kit --help +``` + +## Setting up a provider + +Kit needs at least one LLM provider configured. Set an API key for your preferred provider: + +```bash +# Anthropic (default provider) +export ANTHROPIC_API_KEY="sk-..." + +# OpenAI +export OPENAI_API_KEY="sk-..." + +# Google Gemini +export GOOGLE_API_KEY="..." +``` + +For OAuth-enabled providers like Anthropic, you can also authenticate interactively: + +```bash +kit auth login anthropic +``` + +See [Providers](/providers) for the full list of supported providers and their configuration. + +--- + +## Providers + +# Providers + +Kit supports a wide range of LLM providers through a unified `provider/model` string format. + +## Supported providers + +| Provider | Prefix | Description | +|----------|--------|-------------| +| **Anthropic** | `anthropic/` | Claude models (native, prompt caching, OAuth) | +| **OpenAI** | `openai/` | GPT models | +| **Google** | `google/` or `gemini/` | Gemini models | +| **Ollama** | `ollama/` | Local models | +| **Azure OpenAI** | `azure/` | Azure-hosted OpenAI | +| **AWS Bedrock** | `bedrock/` | Bedrock models | +| **Google Vertex** | `google-vertex-anthropic/` | Claude on Vertex AI | +| **OpenRouter** | `openrouter/` | Multi-provider router | +| **Vercel AI** | `vercel/` | Vercel AI SDK models | +| **Auto-routed** | any | Any provider from the models.dev database | + +## Model string format + +```bash +provider/model # Standard format +anthropic/claude-sonnet-4-5-20250929 +openai/gpt-4o +ollama/llama3 +google/gemini-2.0-flash-exp +``` + +## Model aliases + +Kit provides aliases for commonly used models: + +```bash +claude-opus-latest → claude-opus-4-20250514 +claude-sonnet-latest → claude-sonnet-4-5-20250929 +claude-4-opus-latest → claude-opus-4-20250514 +claude-4-sonnet-latest → claude-sonnet-4-5-20250929 +claude-3-7-sonnet-latest → claude-3-7-sonnet-20250219 +claude-3-5-sonnet-latest → claude-3-5-sonnet-20241022 +claude-3-5-haiku-latest → claude-3-5-haiku-20241022 +claude-3-opus-latest → claude-3-opus-20240229 +``` + +## Specifying a model + +Via CLI flag: + +```bash +kit --model openai/gpt-4o +kit -m ollama/llama3 +``` + +Via config file: + +```yaml +model: anthropic/claude-sonnet-4-5-20250929 +``` + +Via environment variable: + +```bash +export KIT_MODEL="google/gemini-2.0-flash-exp" +``` + +## Authentication + +### API keys + +Set the appropriate environment variable for your provider: + +```bash +export ANTHROPIC_API_KEY="sk-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +``` + +Or pass it directly: + +```bash +kit --provider-api-key "sk-..." --model openai/gpt-4o +``` + +### OAuth + +For providers that support OAuth (e.g., Anthropic): + +```bash +kit auth login anthropic # Start OAuth flow +kit auth status # Check authentication status +kit auth logout anthropic # Remove credentials +``` + +### Custom provider URL + +For self-hosted or proxy endpoints: + +```bash +kit --provider-url "https://my-proxy.example.com/v1" --model openai/gpt-4o +``` + +## Model database + +Kit ships with a local model database that maps provider names to API configurations. You can manage it with: + +```bash +kit models # List available models +kit models openai # Filter by provider +kit models --all # Show all providers +kit update-models # Update from models.dev +kit update-models embedded # Reset to bundled database +``` + +--- + +## Quick Start + +# Quick Start + +## Basic usage + +Start an interactive session: + +```bash +kit +``` + +Run a one-off prompt: + +```bash +kit "List files in src/" +``` + +Attach files as context using the `@` prefix: + +```bash +kit @main.go @test.go "Review these files" +``` + +Use a specific model: + +```bash +kit --model anthropic/claude-sonnet-4-5-20250929 +``` + +## Non-interactive mode + +Kit can run as a non-interactive tool for scripting and automation. + +Get JSON output: + +```bash +kit "Explain main.go" --json +``` + +Quiet mode (final response only, no TUI): + +```bash +kit "Run tests" --quiet +``` + +Ephemeral mode (no session file created): + +```bash +kit "Quick question" --no-session +``` + +## Resuming sessions + +Continue the most recent session for the current directory: + +```bash +kit --continue +# or +kit -c +``` + +Pick from previous sessions interactively: + +```bash +kit --resume +# or +kit -r +``` + +## ACP server mode + +Kit can run as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server, enabling ACP-compatible clients (such as [OpenCode](https://github.com/sst/opencode)) to drive Kit as a remote coding agent over stdio: + +```bash +# Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout) +kit acp + +# With debug logging to stderr +kit acp --debug +``` + +The ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol. + +--- + +## Callbacks + +# Callbacks + +## PromptWithCallbacks + +The `PromptWithCallbacks` method provides real-time visibility into tool calls and streaming output: + +```go +response, err := host.PromptWithCallbacks( + ctx, + "List files in current directory", + func(name, args string) { + // Called when the model invokes a tool + fmt.Println("Calling tool:", name) + }, + func(name, args, result string, isError bool) { + // Called when a tool returns its result + if isError { + fmt.Println("Tool failed:", name) + } + }, + func(chunk string) { + // Called for each streaming text chunk + fmt.Print(chunk) + }, +) +``` + +### Callback signatures + +| Callback | Signature | When | +|----------|-----------|------| +| `onToolCall` | `func(name, args string)` | Model requests a tool call | +| `onToolResult` | `func(name, args, result string, isError bool)` | Tool execution completes | +| `onStreaming` | `func(chunk string)` | Streaming text chunk received | + +Any callback can be `nil` if you don't need it: + +```go +// Only care about streaming output +response, err := host.PromptWithCallbacks(ctx, "Hello", nil, nil, func(chunk string) { + fmt.Print(chunk) +}) +``` + +## Event-based monitoring + +For more granular control, use the event subscription API: + +```go +// Subscribe returns an unsubscribe function +unsub := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Printf("Tool: %s, Args: %s\n", event.Name, event.Args) +}) +defer unsub() + +unsub2 := host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Printf("Result: %s (error: %v)\n", event.Name, event.IsError) +}) +defer unsub2() + +unsub3 := host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +defer unsub3() + +unsub4 := host.OnResponse(func(event kit.ResponseEvent) { + fmt.Println("Final response received") +}) +defer unsub4() + +unsub5 := host.OnTurnStart(func(event kit.TurnStartEvent) { + fmt.Println("Turn started") +}) +defer unsub5() + +unsub6 := host.OnTurnEnd(func(event kit.TurnEndEvent) { + fmt.Println("Turn ended") +}) +defer unsub6() +``` + +## Hook system + +Hooks allow you to intercept and modify behavior. Unlike events, hooks can modify or cancel operations: + +```go +// Intercept tool calls before execution +host.OnBeforeToolCall(0, func(ctx context.Context, name string, args string) (string, error) { + if name == "bash" { + log.Println("Bash command:", args) + } + return args, nil // return modified args or error to cancel +}) + +// Process results after tool execution +host.OnAfterToolResult(0, func(ctx context.Context, name string, result string) (string, error) { + return result, nil +}) + +// Before/after each agent turn +host.OnBeforeTurn(0, func(ctx context.Context) error { + return nil +}) + +host.OnAfterTurn(0, func(ctx context.Context) error { + return nil +}) +``` + +The first argument is a priority (lower = runs first). + +--- + +## SDK Options + +# SDK Options + +Pass an `Options` struct to `kit.New()` to configure the Kit instance. + +## Full options reference + +```go +host, err := kit.New(ctx, &kit.Options{ + // Model + Model: "ollama/llama3", + SystemPrompt: "You are a helpful bot", + ConfigFile: "/path/to/config.yml", + + // Behavior + MaxSteps: 10, + Streaming: true, + Quiet: true, + Debug: true, + + // Session + SessionPath: "./session.jsonl", + SessionDir: "/custom/sessions/", + Continue: true, + NoSession: true, + + // Tools + Tools: []kit.Tool{...}, // Replace default tool set entirely + ExtraTools: []kit.Tool{...}, // Add tools alongside defaults + + // Compaction + AutoCompact: true, + + // Skills + Skills: []string{"/path/to/skill.md"}, + SkillsDir: "/path/to/skills/", +}) +``` + +## Options fields + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `Model` | `string` | config default | Model string (provider/model format) | +| `SystemPrompt` | `string` | — | System prompt text or file path | +| `ConfigFile` | `string` | `~/.kit.yml` | Path to config file | +| `MaxSteps` | `int` | `0` | Max agent steps (0 = unlimited) | +| `Streaming` | `bool` | `true` | Enable streaming output | +| `Quiet` | `bool` | `false` | Suppress output | +| `Debug` | `bool` | `false` | Enable debug logging | +| `SessionPath` | `string` | — | Open a specific session file | +| `SessionDir` | `string` | — | Base directory for session discovery | +| `Continue` | `bool` | `false` | Resume most recent session | +| `NoSession` | `bool` | `false` | Ephemeral mode (no persistence) | +| `Tools` | `[]Tool` | — | Replace the entire default tool set | +| `ExtraTools` | `[]Tool` | — | Additional tools alongside core/MCP/extension tools | +| `AutoCompact` | `bool` | `false` | Auto-compact when near context limit | +| `CompactionOptions` | `*CompactionOptions` | — | Configuration for auto-compaction | +| `Skills` | `[]string` | — | Explicit skill files/dirs to load | +| `SkillsDir` | `string` | — | Override default skills directory | + +--- + +## Go SDK + +# Go SDK + +The `pkg/kit` package lets you embed Kit as a library in your Go applications. + +## Installation + +```bash +go get github.com/mark3labs/kit/pkg/kit +``` + +## Basic usage + +```go +package main + +import ( + "context" + "log" + + kit "github.com/mark3labs/kit/pkg/kit" +) + +func main() { + ctx := context.Background() + + // Create Kit instance with default configuration + host, err := kit.New(ctx, nil) + if err != nil { + log.Fatal(err) + } + defer host.Close() + + // Send a prompt + response, err := host.Prompt(ctx, "What is 2+2?") + if err != nil { + log.Fatal(err) + } + + println(response) +} +``` + +## Multi-turn conversations + +Conversations retain context automatically across calls: + +```go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +``` + +## Additional prompt methods + +The SDK provides several prompt variants: + +| Method | Description | +|--------|-------------| +| `Prompt(ctx, message)` | Simple prompt, returns response string | +| `PromptWithCallbacks(ctx, message, ...)` | With tool call and streaming callbacks | +| `PromptWithOptions(ctx, message, opts)` | With per-call options | +| `PromptResult(ctx, message)` | Returns full `TurnResult` with usage stats | +| `PromptResultWithFiles(ctx, message, files)` | Multimodal with file attachments | +| `Steer(ctx, instruction)` | System-level steering without user message | +| `FollowUp(ctx, text)` | Continue without new user input | + +## Event system + +Subscribe to events for monitoring: + +```go +unsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Println("Tool called:", event.Name) +}) +defer unsubscribe() + +host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Println("Tool result:", event.Name) +}) + +host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +``` + +## Model management + +Switch models at runtime: + +```go +host.SetModel(ctx, "openai/gpt-4o") +info := host.GetModelInfo() +models := host.GetAvailableModels() +``` + +## Context and compaction + +Monitor and manage context usage: + +```go +tokens := host.EstimateContextTokens() +stats := host.GetContextStats() + +if host.ShouldCompact() { + result, err := host.Compact(ctx, nil, "") +} +``` + +See [Options](/sdk/options), [Callbacks](/sdk/callbacks), and [Sessions](/sdk/sessions) for more details. + +--- + +## SDK Sessions + +# SDK Sessions + +## Automatic persistence + +By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls: + +```go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +``` + +## Accessing session info + +```go +// Get the current session file path +path := host.GetSessionPath() + +// Get the session ID +id := host.GetSessionID() + +// Get the current model string +model := host.GetModelString() +``` + +## Configuring sessions via Options + +Session behavior is configured at initialization: + +```go +// Open a specific session file +host, _ := kit.New(ctx, &kit.Options{ + SessionPath: "./my-session.jsonl", +}) + +// Resume the most recent session for the current directory +host, _ := kit.New(ctx, &kit.Options{ + Continue: true, +}) + +// Ephemeral mode (no file persistence) +host, _ := kit.New(ctx, &kit.Options{ + NoSession: true, +}) + +// Custom session directory +host, _ := kit.New(ctx, &kit.Options{ + SessionDir: "/custom/sessions/", +}) +``` + +## Clearing history + +Clear the in-memory conversation history (does not delete the session file): + +```go +host.ClearSession() +``` + +## Tree-based sessions + +Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths: + +```go +// Access the tree session manager +ts := host.GetTreeSession() + +// Branch from a specific entry +err := host.Branch("entry-id-123") +``` + +## Listing and managing sessions + +Package-level functions for session discovery: + +```go +// List sessions for a specific directory +sessions := kit.ListSessions("/home/user/project") + +// List all sessions across all directories +all := kit.ListAllSessions() + +// Delete a session file +kit.DeleteSession("/path/to/session.jsonl") +``` + +--- + +## Session Management + +# Session Management + +Kit uses a tree-based session model that supports branching and forking conversations. + +## Session storage + +Sessions are stored as JSONL (JSON Lines) files: + +``` +~/.kit/sessions//_.jsonl +``` + +Path separators in the working directory are replaced with `--`. For example, `/home/user/project` becomes `home--user--project`. + +Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths. + +## Resuming sessions + +### Continue most recent + +Resume the most recent session for the current directory: + +```bash +kit --continue +kit -c +``` + +### Interactive picker + +Choose from previous sessions interactively: + +```bash +kit --resume +kit -r +``` + +### Open a specific session + +```bash +kit --session path/to/session.jsonl +kit -s path/to/session.jsonl +``` + +## Ephemeral mode + +Run without creating a session file: + +```bash +kit --no-session +``` + +This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed. diff --git a/llms.txt b/llms.txt new file mode 100644 index 00000000..d3486f43 --- /dev/null +++ b/llms.txt @@ -0,0 +1,24 @@ +# Kit + +> Documentation site powered by Tome + +- [JSON Output](https://go-kit.dev/advanced/json-output) - Machine-readable JSON output for scripting and automation. +- [Subagents](https://go-kit.dev/advanced/subagents) - Multi-agent orchestration with Kit subagents. +- [Testing with tmux](https://go-kit.dev/advanced/testing) - Test Kit's TUI non-interactively using tmux. +- [Commands](https://go-kit.dev/cli/commands) - Complete reference for all Kit CLI subcommands. +- [Global Flags](https://go-kit.dev/cli/flags) - Complete reference for all Kit CLI flags. +- [Configuration](https://go-kit.dev/configuration) - Configure Kit using config files, environment variables, and CLI flags. +- [Development](https://go-kit.dev/development) - Build, test, and contribute to Kit. +- [Capabilities](https://go-kit.dev/extensions/capabilities) - All extension capabilities — lifecycle events, tools, commands, widgets, and more. +- [Examples](https://go-kit.dev/extensions/examples) - Catalog of example extensions included with Kit. +- [Loading Extensions](https://go-kit.dev/extensions/loading) - How Kit discovers and loads extensions. +- [Extension System](https://go-kit.dev/extensions/overview) - Overview of Kit's Go-based extension system. +- [Kit](https://go-kit.dev/) - Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system. +- [Installation](https://go-kit.dev/installation) - Install Kit using npm, Go, or build from source. +- [Providers](https://go-kit.dev/providers) - Supported LLM providers and model configuration. +- [Quick Start](https://go-kit.dev/quick-start) - Get up and running with Kit in minutes. +- [Callbacks](https://go-kit.dev/sdk/callbacks) - Monitor tool calls and streaming output with the Kit Go SDK. +- [SDK Options](https://go-kit.dev/sdk/options) - Configuration options for the Kit Go SDK. +- [Go SDK](https://go-kit.dev/sdk/overview) - Embed Kit in your Go applications. +- [SDK Sessions](https://go-kit.dev/sdk/sessions) - Session management in the Kit Go SDK. +- [Session Management](https://go-kit.dev/sessions) - How Kit persists and manages conversation sessions. \ No newline at end of file diff --git a/logo.jpg b/logo.jpg new file mode 100644 index 00000000..cb0183e6 Binary files /dev/null and b/logo.jpg differ diff --git a/mcp.json b/mcp.json new file mode 100644 index 00000000..058b7e0e --- /dev/null +++ b/mcp.json @@ -0,0 +1,310 @@ +{ + "name": "Kit", + "version": "1.0.0", + "pages": [ + { + "url": "/advanced/json-output", + "title": "JSON Output", + "description": "Machine-readable JSON output for scripting and automation.", + "headings": [ + "Response format", + "Fields", + "Top-level", + "Usage", + "Message parts", + "Parsing in scripts", + "bash + jq", + "Go SDK" + ], + "tags": [], + "content": "\n# JSON Output\n\nUse the `--json` flag to get structured output for scripting and automation:\n\n```bash\nkit \"Explain main.go\" --json --quiet --no-session\n```\n\n## Response format\n\n```json\n{\n \"response\": \"Final assistant response text\",\n \"model\": \"anthropic/claude-haiku-3-5-20241022\",\n \"stop_reason\": \"end_turn\",\n \"session_id\": \"a1b2c3d4e5f6\",\n \"usage\": {\n \"input_tokens\": 1024,\n \"output_tokens\": 512,\n \"total_tokens\": 1536,\n \"cache_read_tokens\": 0,\n \"cache_creation_tokens\": 0\n },\n \"messages\": [\n {\n \"role\": \"assistant\",\n \"parts\": [\n {\"type\": \"text\", \"data\": \"...\"},\n {\"type\": \"tool_call\", \"data\": {\"name\": \"...\", \"args\": \"...\"}},\n {\"type\": \"tool_result\", \"data\": {\"name\": \"...\", \"result\": \"...\"}}\n ]\n }\n ]\n}\n```\n\n## Fields\n\n### Top-level\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `response` | string | The final assistant response text |\n| `model` | string | The model that was used |\n| `stop_reason` | string | Why the model stopped (e.g., `end_turn`) |\n| `session_id` | string | Session identifier (omitted in `--no-session` mode) |\n| `usage` | object | Token usage statistics |\n| `messages` | array | Full conversation history |\n\n### Usage\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `input_tokens` | int | Tokens sent to the model |\n| `output_tokens` | int | Tokens generated by the model |\n| `total_tokens` | int | Sum of input and output tokens |\n| `cache_read_tokens` | int | Tokens read from prompt cache |\n| `cache_creation_tokens` | int | Tokens written to prompt cache |\n\n### Message parts\n\nEach message contains a `parts` array with typed entries:\n\n| Type | Description |\n|------|-------------|\n| `text` | Assistant text content |\n| `tool_call` | Tool invocation with name and args |\n| `tool_result` | Tool execution result |\n| `reasoning` | Extended thinking content |\n| `finish` | End-of-turn marker |\n\n## Parsing in scripts\n\n### bash + jq\n\n```bash\nresult=$(kit \"Count files\" --json --quiet --no-session)\nresponse=$(echo \"$result\" | jq -r '.response')\ntokens=$(echo \"$result\" | jq '.usage.total_tokens')\n```\n\n### Go SDK\n\nFor Go programs, use the SDK's `PromptResult` method instead of parsing JSON:\n\n```go\nresult, err := host.PromptResult(ctx, \"Count files\")\nfmt.Println(result.Response)\nfmt.Println(result.Usage.TotalTokens)\n```\n" + }, + { + "url": "/advanced/subagents", + "title": "Subagents", + "description": "Multi-agent orchestration with Kit subagents.", + "headings": [ + "Subprocess pattern", + "Built-in spawn_subagent tool", + "Extension subagents", + "Go SDK subagents" + ], + "tags": [], + "content": "\n# Subagents\n\nKit supports multi-agent orchestration through both subprocess spawning and in-process subagents.\n\n## Subprocess pattern\n\nSpawn Kit as a subprocess for isolated agent execution:\n\n```bash\nkit \"Analyze codebase\" \\\n --json \\\n --no-session \\\n --no-extensions \\\n --quiet \\\n --model anthropic/claude-haiku-3-5-20241022\n```\n\nKey flags for subprocess usage:\n\n| Flag | Purpose |\n|------|---------|\n| `--quiet` | Stdout only, no TUI |\n| `--no-session` | Ephemeral, no persistence |\n| `--no-extensions` | Prevent recursive extension loading |\n| `--json` | Machine-readable output |\n| `--system-prompt` | Custom system prompt (string or file path) |\n\nPositional arguments are the prompt. `@file` arguments attach file content as context.\n\n## Built-in spawn_subagent tool\n\nKit includes a built-in `spawn_subagent` tool that the LLM can use to delegate tasks to independent child agents:\n\n```\nspawn_subagent(\n task: \"Analyze the test files and summarize coverage\",\n model: \"anthropic/claude-haiku-3-5-20241022\", // optional\n system_prompt: \"You are a test analysis expert.\", // optional\n timeout_seconds: 300 // optional, max 1800\n)\n```\n\nSubagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel.\n\n## Extension subagents\n\nExtensions can spawn subagents programmatically:\n\n```go\nresult := ctx.SpawnSubagent(ext.SubagentConfig{\n Task: \"Review this code for security issues\",\n Model: \"anthropic/claude-sonnet-4-5-20250929\",\n SystemPrompt: \"You are a security auditor.\",\n})\n```\n\n## Go SDK subagents\n\nThe SDK provides in-process subagent spawning:\n\n```go\nresult, err := host.Subagent(ctx, kit.SubagentConfig{\n Task: \"Summarize the changes in this PR\",\n Model: \"anthropic/claude-haiku-3-5-20241022\",\n SystemPrompt: \"You are a code reviewer.\",\n Timeout: 5 * time.Minute,\n})\n```\n" + }, + { + "url": "/advanced/testing", + "title": "Testing with tmux", + "description": "Test Kit's TUI non-interactively using tmux.", + "headings": [ + "Basic pattern", + "Testing extensions", + "Tips" + ], + "tags": [], + "content": "\n# Testing with tmux\n\nKit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development.\n\n## Basic pattern\n\n```bash\n# Start Kit in a detached tmux session\ntmux new-session -d -s kittest -x 120 -y 40 \\\n \"output/kit -e ext.go --no-session 2>kit_stderr.log\"\n\n# Wait for startup\nsleep 3\n\n# Capture the current screen\ntmux capture-pane -t kittest -p\n\n# Send input\ntmux send-keys -t kittest '/command' Enter\n\n# Wait for response\nsleep 2\n\n# Capture updated screen\ntmux capture-pane -t kittest -p\n\n# Cleanup\ntmux kill-session -t kittest\n```\n\n## Testing extensions\n\nWhen testing extensions, the pattern is:\n\n1. Build Kit with your changes\n2. Start Kit in tmux with the extension loaded\n3. Send slash commands or prompts\n4. Capture and verify the screen output\n5. Check stderr logs for errors\n\n```bash\n# Build first\ngo build -o output/kit ./cmd/kit\n\n# Start with extension\ntmux new-session -d -s kittest -x 120 -y 40 \\\n \"output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log\"\n\nsleep 3\n\n# Verify widget appears in screen\ntmux capture-pane -t kittest -p | grep \"Status\"\n\n# Send a slash command\ntmux send-keys -t kittest '/stats' Enter\nsleep 1\ntmux capture-pane -t kittest -p\n\n# Cleanup\ntmux kill-session -t kittest\n```\n\n## Tips\n\n- Use `-x` and `-y` to set consistent terminal dimensions\n- Redirect stderr to a log file (`2>kit.log`) for debugging\n- Use `--no-session` to avoid creating session files during tests\n- Add sufficient `sleep` between commands for the TUI to render\n- Use `grep` on captured pane output to verify specific content\n" + }, + { + "url": "/cli/commands", + "title": "Commands", + "description": "Complete reference for all Kit CLI subcommands.", + "headings": [ + "Authentication", + "Model database", + "Extension management", + "Installing extensions from git", + "Skills", + "ACP server" + ], + "tags": [], + "content": "\n# Commands\n\n## Authentication\n\nFor OAuth-enabled providers like Anthropic.\n\n```bash\nkit auth login [provider] # Start OAuth flow (e.g., anthropic)\nkit auth logout [provider] # Remove credentials for provider\nkit auth status # Check authentication status\n```\n\n## Model database\n\nManage the local model database that maps provider names to API configurations.\n\n```bash\nkit models [provider] # List available models (optionally filter by provider)\nkit models --all # Show all providers (not just Fantasy-compatible)\nkit update-models [source] # Update model database\n```\n\nThe `update-models` command accepts an optional source argument:\n- *(none)* — update from [models.dev](https://models.dev)\n- A URL — fetch from a custom endpoint\n- A file path — load from a local file\n- `embedded` — reset to the bundled database\n\n## Extension management\n\n```bash\nkit extensions list # List discovered extensions\nkit extensions validate # Validate extension files\nkit extensions init # Generate example extension template\n```\n\n### Installing extensions from git\n\n```bash\nkit install # Install extensions from git repositories\nkit install -l # Install to project-local .kit/git/ directory\nkit install -u # Update an already-installed package\nkit install --uninstall # Remove an installed package\nkit install --all # Install all extensions without prompting\n```\n\n## Skills\n\n```bash\nkit skill # Install the Kit extensions skill via skills.sh\n```\n\n## ACP server\n\nRun Kit as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout.\n\n```bash\nkit acp # Start as ACP agent\nkit acp --debug # With debug logging to stderr\n```\n" + }, + { + "url": "/cli/flags", + "title": "Global Flags", + "description": "Complete reference for all Kit CLI flags.", + "headings": [ + "Model and provider", + "Session management", + "Behavior", + "Extensions", + "Generation parameters", + "System" + ], + "tags": [], + "content": "\n# Global Flags\n\nAll flags can be passed to the root `kit` command.\n\n## Model and provider\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--model` | `-m` | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) |\n| `--provider-api-key` | — | — | API key for the provider |\n| `--provider-url` | — | — | Base URL for provider API |\n| `--tls-skip-verify` | — | `false` | Skip TLS certificate verification |\n\n## Session management\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--session` | `-s` | — | Open specific JSONL session file |\n| `--continue` | `-c` | `false` | Resume most recent session for current directory |\n| `--resume` | `-r` | `false` | Interactive session picker |\n| `--no-session` | — | `false` | Ephemeral mode, no persistence |\n\n## Behavior\n\nThese flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode.\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--quiet` | — | `false` | Suppress all output (non-interactive only) |\n| `--json` | — | `false` | Output response as JSON (non-interactive only) |\n| `--no-exit` | — | `false` | Enter interactive mode after prompt completes |\n| `--max-steps` | — | `0` | Maximum agent steps (0 for unlimited) |\n| `--stream` | — | `true` | Enable streaming output |\n| `--compact` | — | `false` | Enable compact output mode |\n| `--auto-compact` | — | `false` | Auto-compact conversation near context limit |\n\n## Extensions\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--extension` | `-e` | — | Load additional extension file(s) (repeatable) |\n| `--no-extensions` | — | `false` | Disable all extensions |\n\n## Generation parameters\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--max-tokens` | — | `4096` | Maximum tokens in response |\n| `--temperature` | — | `0.7` | Randomness 0.0–1.0 |\n| `--top-p` | — | `0.95` | Nucleus sampling 0.0–1.0 |\n| `--top-k` | — | `40` | Limit top K tokens |\n| `--stop-sequences` | — | — | Custom stop sequences (comma-separated) |\n| `--thinking-level` | — | `off` | Extended thinking level: off, minimal, low, medium, high |\n\n## System\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--config` | — | `~/.kit.yml` | Config file path |\n| `--system-prompt` | — | — | System prompt text or file path |\n| `--debug` | — | `false` | Enable debug logging |\n" + }, + { + "url": "/configuration", + "title": "Configuration", + "description": "Configure Kit using config files, environment variables, and CLI flags.", + "headings": [ + "Basic configuration", + "All configuration keys", + "Environment variables", + "MCP server configuration", + "MCP server fields" + ], + "tags": [], + "content": "\n# Configuration\n\nKit looks for configuration in the following locations, in order of priority:\n\n1. CLI flags\n2. Environment variables (with `KIT_` prefix)\n3. `./.kit.yml` / `./.kit.yaml` / `./.kit.json` (project-local)\n4. `~/.kit.yml` / `~/.kit.yaml` / `~/.kit.json` (global)\n\n## Basic configuration\n\nCreate `~/.kit.yml`:\n\n```yaml\nmodel: anthropic/claude-sonnet-4-5-20250929\nmax-tokens: 4096\ntemperature: 0.7\nstream: true\n```\n\n## All configuration keys\n\n| Key | Type | Default | Description |\n|-----|------|---------|-------------|\n| `model` | string | `anthropic/claude-sonnet-4-5-20250929` | Model to use (provider/model format) |\n| `max-tokens` | int | `4096` | Maximum tokens in response |\n| `temperature` | float | `0.7` | Randomness 0.0–1.0 |\n| `top-p` | float | `0.95` | Nucleus sampling 0.0–1.0 |\n| `top-k` | int | `40` | Limit top K tokens |\n| `stream` | bool | `true` | Enable streaming output |\n| `debug` | bool | `false` | Enable debug logging |\n| `compact` | bool | `false` | Enable compact output mode |\n| `system-prompt` | string | — | System prompt text or file path |\n| `max-steps` | int | `0` | Maximum agent steps (0 = unlimited) |\n| `thinking-level` | string | `off` | Extended thinking: off, minimal, low, medium, high |\n| `provider-api-key` | string | — | API key for the provider |\n| `provider-url` | string | — | Base URL for provider API |\n| `tls-skip-verify` | bool | `false` | Skip TLS certificate verification |\n| `stop-sequences` | list | — | Custom stop sequences |\n| `theme` | string | — | UI theme |\n| `markdown-theme` | string | — | Markdown rendering theme |\n\n## Environment variables\n\nAny configuration key can be set via environment variable with the `KIT_` prefix. Hyphens become underscores:\n\n```bash\nexport KIT_MODEL=\"openai/gpt-4o\"\nexport KIT_MAX_TOKENS=\"8192\"\nexport KIT_TEMPERATURE=\"0.5\"\n```\n\nProvider API keys use their own environment variables:\n\n```bash\nexport ANTHROPIC_API_KEY=\"sk-...\"\nexport OPENAI_API_KEY=\"sk-...\"\nexport GOOGLE_API_KEY=\"...\"\n```\n\n## MCP server configuration\n\nAdd external MCP servers to your `.kit.yml`:\n\n```yaml\nmcpServers:\n filesystem:\n type: local\n command: [\"npx\", \"-y\", \"@modelcontextprotocol/server-filesystem\", \"/path/to/allowed\"]\n environment:\n LOG_LEVEL: \"info\"\n allowedTools: [\"read_file\", \"write_file\"]\n excludedTools: [\"delete_file\"]\n\n search:\n type: remote\n url: \"https://mcp.example.com/search\"\n```\n\n### MCP server fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | string | `local` (stdio) or `remote` (streamable HTTP) |\n| `command` | list | Command and args for local servers |\n| `environment` | map | Environment variables for the server process |\n| `url` | string | URL for remote servers |\n| `allowedTools` | list | Whitelist of tool names to expose |\n| `excludedTools` | list | Blacklist of tool names to hide |\n\nA legacy format with `transport`, `args`, `env`, and `headers` fields is also supported.\n" + }, + { + "url": "/development", + "title": "Development", + "description": "Build, test, and contribute to Kit.", + "headings": [ + "Build and test", + "Project structure", + "Architecture overview", + "Multi-provider LLM support", + "MCP client-server model", + "Extension system", + "TUI architecture", + "Decoupling pattern", + "Contributing", + "Community" + ], + "tags": [], + "content": "\n# Development\n\n## Build and test\n\n```bash\n# Build\ngo build -o output/kit ./cmd/kit\n\n# Run all tests\ngo test -race ./...\n\n# Run a specific test\ngo test -race ./cmd -run TestScriptExecution\n\n# Lint\ngo vet ./...\n\n# Format\ngo fmt ./...\n```\n\n## Project structure\n\n```\ncmd/kit/ - CLI entry point (main.go)\ncmd/ - CLI command implementations (root, auth, models, etc.)\npkg/kit/ - Go SDK for embedding Kit\ninternal/app/ - Application orchestrator (agent loop, message store, queue)\ninternal/agent/ - Agent execution and tool dispatch\ninternal/auth/ - OAuth authentication and credential storage\ninternal/acpserver/ - ACP (Agent Client Protocol) server\ninternal/clipboard/ - Cross-platform clipboard operations\ninternal/compaction/ - Conversation compaction and summarization\ninternal/config/ - Configuration management\ninternal/core/ - Built-in tools (bash, read, write, edit, grep, find, ls)\ninternal/extensions/ - Yaegi extension system\ninternal/kitsetup/ - Initial setup wizard\ninternal/message/ - Message content types and structured content blocks\ninternal/models/ - Provider and model management\ninternal/session/ - Session persistence (tree-based JSONL)\ninternal/skills/ - Skill loading and system prompt composition\ninternal/tools/ - MCP tool integration\ninternal/ui/ - Bubble Tea TUI components\nexamples/extensions/ - Example extension files\nnpm/ - NPM package wrapper for distribution\n```\n\n## Architecture overview\n\nKit is built around a few key architectural patterns:\n\n### Multi-provider LLM support\n\nThe `llm.Provider` interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API.\n\n### MCP client-server model\n\nExternal tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in `.kit.yml`.\n\n### Extension system\n\nExtensions are Go source files interpreted at runtime by Yaegi. The `internal/extensions/` package manages loading, symbol export, and lifecycle dispatch. See the [Extension System](/extensions/overview) docs for details.\n\n### TUI architecture\n\nThe interactive terminal UI is built with [Bubble Tea v2](https://github.com/charmbracelet/bubbletea), using a parent-child model where `AppModel` manages child components (`InputComponent`, `StreamComponent`, etc.).\n\n### Decoupling pattern\n\n`cmd/root.go` contains converter functions (e.g., `widgetProviderForUI()`) that bridge `internal/extensions/` types to `internal/ui/` types. The UI never imports the extensions package directly.\n\n## Contributing\n\nContributions are welcome! Please see the [contribution guide](https://github.com/mark3labs/kit/blob/master/contribute/contribute.md) for guidelines.\n\n## Community\n\n- [Discord](https://discord.gg/RqSS2NQVsY)\n- [GitHub Issues](https://github.com/mark3labs/kit/issues)\n" + }, + { + "url": "/extensions/capabilities", + "title": "Capabilities", + "description": "All extension capabilities — lifecycle events, tools, commands, widgets, and more.", + "headings": [ + "Lifecycle events", + "Example", + "Tools", + "Commands", + "Widgets", + "Headers and footers", + "Status bar", + "Shortcuts", + "Overlays", + "Tool renderers", + "Message renderers", + "Editor interceptors", + "Interactive prompts", + "Options", + "Subagents", + "LLM completion", + "Custom events" + ], + "tags": [], + "content": "\n# Extension Capabilities\n\n## Lifecycle events\n\nExtensions can hook into 18 lifecycle events:\n\n| Event | Description |\n|-------|-------------|\n| `OnSessionStart` | Session initialized |\n| `OnSessionShutdown` | Session ending |\n| `OnBeforeAgentStart` | Before the agent loop begins |\n| `OnAgentStart` | Agent loop started |\n| `OnAgentEnd` | Agent loop completed |\n| `OnToolCall` | Tool call requested by the model |\n| `OnToolExecutionStart` | Tool execution beginning |\n| `OnToolExecutionEnd` | Tool execution completed |\n| `OnToolResult` | Tool result returned |\n| `OnInput` | User input received |\n| `OnMessageStart` | Assistant message started |\n| `OnMessageUpdate` | Streaming text chunk received |\n| `OnMessageEnd` | Assistant message completed |\n| `OnModelChange` | Model switched |\n| `OnContextPrepare` | Context being assembled for the model |\n| `OnBeforeFork` | Before forking a conversation branch |\n| `OnBeforeSessionSwitch` | Before switching sessions |\n| `OnBeforeCompact` | Before conversation compaction |\n\n### Example\n\n```go\napi.OnToolCall(func(event ext.ToolCallEvent, ctx ext.Context) {\n ctx.PrintInfo(\"Calling tool: \" + event.Name)\n})\n\napi.OnAgentEnd(func(_ ext.AgentEndEvent, ctx ext.Context) {\n ctx.PrintInfo(\"Agent finished\")\n})\n```\n\n## Tools\n\nRegister custom tools that the LLM can invoke:\n\n```go\napi.RegisterTool(ext.ToolDef{\n Name: \"weather\",\n Description: \"Get current weather for a location\",\n Parameters: map[string]ext.ParameterDef{\n \"city\": {Type: \"string\", Description: \"City name\", Required: true},\n },\n Handler: func(ctx ext.Context, params map[string]any) (string, error) {\n city := params[\"city\"].(string)\n return \"Sunny, 72°F in \" + city, nil\n },\n})\n```\n\n## Commands\n\nRegister slash commands that users can invoke directly:\n\n```go\napi.RegisterCommand(ext.CommandDef{\n Name: \"stats\",\n Description: \"Show context statistics\",\n Handler: func(ctx ext.Context, args string) {\n stats := ctx.GetContextStats()\n ctx.PrintInfo(fmt.Sprintf(\"Tokens: %d\", stats.TotalTokens))\n },\n})\n```\n\n## Widgets\n\nAdd persistent status displays above or below the input area:\n\n```go\nctx.SetWidget(ext.WidgetConfig{\n ID: \"token-count\",\n Position: \"bottom\",\n Content: ext.WidgetContent{Text: \"Tokens: 1,234\"},\n})\n\n// Update later\nctx.SetWidget(ext.WidgetConfig{\n ID: \"token-count\",\n Position: \"bottom\",\n Content: ext.WidgetContent{Text: \"Tokens: 2,456\"},\n})\n\n// Remove\nctx.RemoveWidget(\"token-count\")\n```\n\n## Headers and footers\n\nPersistent content above and below the conversation:\n\n```go\nctx.SetHeader(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{Text: \"Project: my-app | Branch: main\"},\n})\n\nctx.SetFooter(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{Text: \"Plan Mode (read-only)\"},\n})\n```\n\n## Status bar\n\nCustom status bar entries:\n\n```go\nctx.SetStatus(\"mode\", \"Planning\")\nctx.RemoveStatus(\"mode\")\n```\n\n## Shortcuts\n\nGlobal keyboard shortcuts:\n\n```go\napi.RegisterShortcut(ext.ShortcutDef{\n Key: \"ctrl+t\",\n Description: \"Toggle plan mode\",\n}, func(ctx ext.Context) {\n // handle shortcut\n})\n```\n\n## Overlays\n\nModal dialogs with markdown content:\n\n```go\nctx.ShowOverlay(ext.OverlayConfig{\n Title: \"Help\",\n Content: \"# Keyboard Shortcuts\\n\\n- **ctrl+t** — Toggle plan mode\\n- **ctrl+s** — Save session\",\n})\n```\n\n## Tool renderers\n\nCustomize how specific tool calls are displayed in the TUI:\n\n```go\napi.RegisterToolRenderer(ext.ToolRenderConfig{\n ToolName: \"bash\",\n Render: func(name, args, result string, isError bool) string {\n return \"$ \" + args + \"\\n\" + result\n },\n})\n```\n\n## Message renderers\n\nCustom rendering for assistant messages:\n\n```go\napi.RegisterMessageRenderer(ext.MessageRendererConfig{\n Name: \"custom\",\n Render: func(content string) string {\n return \">> \" + content\n },\n})\n```\n\n## Editor interceptors\n\nHandle key events and wrap the editor's rendering:\n\n```go\nctx.SetEditor(ext.EditorConfig{\n HandleKey: func(key, text string) ext.EditorKeyAction {\n if key == \"escape\" {\n return ext.EditorKeyAction{Handled: true}\n }\n return ext.EditorKeyAction{Handled: false}\n },\n})\n```\n\n## Interactive prompts\n\nSelect, confirm, input, and multi-select dialogs:\n\n```go\n// Single select\nresponse := ctx.PromptSelect(ext.PromptSelectConfig{\n Title: \"Choose a model\",\n Options: []string{\"claude-sonnet\", \"gpt-4o\", \"llama3\"},\n})\n\n// Confirm\nconfirmed := ctx.PromptConfirm(ext.PromptConfirmConfig{\n Title: \"Delete this file?\",\n})\n\n// Text input\nname := ctx.PromptInput(ext.PromptInputConfig{\n Title: \"Enter project name\",\n Placeholder: \"my-project\",\n})\n```\n\n## Options\n\nRegister configurable extension options:\n\n```go\napi.RegisterOption(ext.OptionDef{\n Name: \"auto-commit\",\n Description: \"Automatically commit on shutdown\",\n DefaultValue: \"false\",\n})\n```\n\n## Subagents\n\nSpawn in-process child Kit instances:\n\n```go\nresult := ctx.SpawnSubagent(ext.SubagentConfig{\n Task: \"Analyze the test files and summarize coverage\",\n Model: \"anthropic/claude-haiku-3-5-20241022\",\n SystemPrompt: \"You are a test analysis expert.\",\n})\n```\n\n## LLM completion\n\nMake direct model calls without going through the agent loop:\n\n```go\nresponse := ctx.Complete(ext.CompleteRequest{\n Prompt: \"Summarize this in one sentence: \" + content,\n})\n```\n\n## Custom events\n\nInter-extension communication:\n\n```go\n// Emit\nctx.EmitCustomEvent(\"my-extension:data-ready\", payload)\n\n// Listen\napi.OnCustomEvent(\"my-extension:data-ready\", func(data any, ctx ext.Context) {\n // handle event\n})\n```\n" + }, + { + "url": "/extensions/examples", + "title": "Examples", + "description": "Catalog of example extensions included with Kit.", + "headings": [ + "UI and display", + "Workflow and automation", + "Interactive features", + "Agent and context", + "Multi-agent", + "Development", + "Subdirectory extensions" + ], + "tags": [], + "content": "\n# Extension Examples\n\nKit ships with a rich set of example extensions in the `examples/extensions/` directory. These serve as both documentation and starting points for your own extensions.\n\n## UI and display\n\n| Extension | Description |\n|-----------|-------------|\n| `minimal.go` | Clean UI with custom footer |\n| `branded-output.go` | Branded output rendering |\n| `header-footer-demo.go` | Custom headers and footers |\n| `widget-status.go` | Persistent status widgets |\n| `overlay-demo.go` | Modal dialogs |\n| `tool-renderer-demo.go` | Custom tool call rendering |\n| `custom-editor-demo.go` | Vim-like modal editor |\n| `pirate.go` | Pirate-themed personality |\n\n## Workflow and automation\n\n| Extension | Description |\n|-----------|-------------|\n| `auto-commit.go` | Auto-commit changes on shutdown |\n| `plan-mode.go` | Read-only planning mode |\n| `permission-gate.go` | Permission gating for destructive tools |\n| `confirm-destructive.go` | Confirm destructive operations |\n| `protected-paths.go` | Path protection for sensitive files |\n| `project-rules.go` | Project-specific rules injection |\n| `compact-notify.go` | Notification on conversation compaction |\n\n## Interactive features\n\n| Extension | Description |\n|-----------|-------------|\n| `prompt-demo.go` | Interactive prompts (select/confirm/input) |\n| `bookmark.go` | Bookmark conversations |\n| `inline-bash.go` | Inline bash execution |\n| `interactive-shell.go` | Interactive shell integration |\n| `notify.go` | Desktop notifications |\n\n## Agent and context\n\n| Extension | Description |\n|-----------|-------------|\n| `tool-logger.go` | Log all tool calls |\n| `context-inject.go` | Inject context into conversations |\n| `summarize.go` | Conversation summarization |\n| `lsp-diagnostics.go` | LSP diagnostic integration |\n\n## Multi-agent\n\n| Extension | Description |\n|-----------|-------------|\n| `kit-kit.go` | Kit-in-Kit sub-agent spawning |\n| `subagent-widget.go` | Multi-agent orchestration with status widget |\n| `subagent-test.go` | Subagent testing utilities |\n\n## Development\n\n| Extension | Description |\n|-----------|-------------|\n| `dev-reload.go` | Development live-reload |\n\n## Subdirectory extensions\n\n| Directory | Description |\n|-----------|-------------|\n| `kit-kit-agents/` | Multi-agent orchestration example |\n| `kit-telegram/` | Telegram bot integration |\n| `status-tools/` | Status bar tool examples |\n" + }, + { + "url": "/extensions/loading", + "title": "Loading Extensions", + "description": "How Kit discovers and loads extensions.", + "headings": [ + "Auto-discovery", + "Explicit loading", + "Disabling extensions", + "Installing from git", + "Extension structure", + "Single-file extensions", + "Subdirectory extensions", + "Package-level state" + ], + "tags": [], + "content": "\n# Loading Extensions\n\n## Auto-discovery\n\nKit automatically discovers and loads extensions from these paths, in order:\n\n| Path | Scope |\n|------|-------|\n| `~/.config/kit/extensions/*.go` | Global single files |\n| `~/.config/kit/extensions/*/main.go` | Global subdirectory extensions |\n| `.kit/extensions/*.go` | Project-local single files |\n| `.kit/extensions/*/main.go` | Project-local subdirectory extensions |\n| `~/.local/share/kit/git/` | Global git-installed packages |\n| `.kit/git/` | Project-local git-installed packages |\n\n## Explicit loading\n\nLoad extensions by path using the `-e` flag:\n\n```bash\nkit -e path/to/extension.go\n```\n\nLoad multiple extensions:\n\n```bash\nkit -e ext1.go -e ext2.go\n```\n\n## Disabling extensions\n\nDisable all auto-discovered extensions:\n\n```bash\nkit --no-extensions\n```\n\nYou can combine `--no-extensions` with `-e` to load only specific extensions:\n\n```bash\nkit --no-extensions -e my-extension.go\n```\n\n## Installing from git\n\nInstall extensions from git repositories using `kit install`:\n\n```bash\n# Install globally (to ~/.local/share/kit/git/)\nkit install https://github.com/user/my-kit-extension.git\n\n# Install project-locally (to .kit/git/)\nkit install -l https://github.com/user/my-kit-extension.git\n\n# Update an installed package\nkit install -u https://github.com/user/my-kit-extension.git\n\n# Remove\nkit install --uninstall my-kit-extension\n```\n\n## Extension structure\n\n### Single-file extensions\n\nA single `.go` file with an `Init` function:\n\n```go\n//go:build ignore\n\npackage main\n\nimport \"kit/ext\"\n\nfunc Init(api ext.API) {\n // register handlers, tools, commands, etc.\n}\n```\n\nThe `//go:build ignore` directive prevents the Go toolchain from trying to compile the file as part of a normal build.\n\n### Subdirectory extensions\n\nFor more complex extensions, create a directory with a `main.go` entry point:\n\n```\n.kit/extensions/my-extension/\n├── main.go # Must contain Init(api ext.API)\n├── helpers.go # Additional source files\n└── config.go\n```\n\n### Package-level state\n\nYaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks:\n\n```go\npackage main\n\nimport \"kit/ext\"\n\nvar callCount int\n\nfunc Init(api ext.API) {\n api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) {\n callCount++\n ctx.SetFooter(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{\n Text: fmt.Sprintf(\"Tools called: %d\", callCount),\n },\n })\n })\n}\n```\n" + }, + { + "url": "/extensions/overview", + "title": "Extension System", + "description": "Overview of Kit's Go-based extension system.", + "headings": [ + "Minimal extension", + "How extensions work", + "Key concepts", + "The API object", + "The Context object" + ], + "tags": [], + "content": "\n# Extension System\n\nExtensions are Go source files interpreted at runtime via [Yaegi](https://github.com/traefik/yaegi). They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit.\n\n## Minimal extension\n\n```go\n//go:build ignore\n\npackage main\n\nimport \"kit/ext\"\n\nfunc Init(api ext.API) {\n api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {\n ctx.SetFooter(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{Text: \"Custom Footer\"},\n })\n })\n}\n```\n\nRun it with:\n\n```bash\nkit -e examples/extensions/minimal.go\n```\n\n## How extensions work\n\n1. Kit discovers extension files from [auto-discovery paths](/extensions/loading) or explicit `-e` flags\n2. Each `.go` file is loaded into a Yaegi interpreter with access to the `kit/ext` package\n3. Kit calls the `Init(api ext.API)` function in each extension\n4. The extension registers callbacks, tools, commands, and UI components via the `api` and `ctx` objects\n\n## Key concepts\n\n### The `API` object\n\nPassed to `Init()`, the `API` object is used to register lifecycle event handlers and static components:\n\n- **Lifecycle handlers** — `api.OnSessionStart(...)`, `api.OnToolCall(...)`, etc.\n- **Tools** — `api.RegisterTool(ext.ToolDef{...})`\n- **Commands** — `api.RegisterCommand(ext.CommandDef{...})`\n- **Shortcuts** — `api.RegisterShortcut(ext.ShortcutDef{...}, handler)`\n- **Tool renderers** — `api.RegisterToolRenderer(ext.ToolRenderConfig{...})`\n- **Message renderers** — `api.RegisterMessageRenderer(ext.MessageRendererConfig{...})`\n- **Options** — `api.RegisterOption(ext.OptionDef{...})`\n\n### The `Context` object\n\nPassed to event handlers, the `Context` object provides runtime access to Kit's state and UI:\n\n- **Output** — `ctx.Print(...)`, `ctx.PrintInfo(...)`, `ctx.PrintError(...)`\n- **UI components** — `ctx.SetWidget(...)`, `ctx.SetHeader(...)`, `ctx.SetFooter(...)`, `ctx.SetStatus(...)`\n- **Editor** — `ctx.SetEditor(...)`, `ctx.ResetEditor()`\n- **Prompts** — `ctx.PromptSelect(...)`, `ctx.PromptConfirm(...)`, `ctx.PromptInput(...)`\n- **Overlays** — `ctx.ShowOverlay(...)`\n- **Messages** — `ctx.SendMessage(...)`, `ctx.GetMessages()`\n- **Model** — `ctx.SetModel(...)`, `ctx.GetAvailableModels()`\n- **Tools** — `ctx.GetAllTools()`, `ctx.SetActiveTools(...)`\n- **Context stats** — `ctx.GetContextStats()`\n- **Session data** — `ctx.AppendEntry(...)`, `ctx.GetEntries(...)`\n- **Subagents** — `ctx.SpawnSubagent(...)`\n- **LLM completion** — `ctx.Complete(...)`\n- **Custom events** — `ctx.EmitCustomEvent(...)`\n- **App control** — `ctx.Exit()`, `ctx.ReloadExtensions()`\n\nSee [Capabilities](/extensions/capabilities) for full details on each component type.\n" + }, + { + "url": "/", + "title": "Kit", + "description": "Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.", + "headings": [ + "Features", + "Quick links" + ], + "tags": [], + "content": "\n
    \n \"KIT\"\n
    \n\nA powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.\n\n## Features\n\n- **Multi-Provider LLM Support** — Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more\n- **Built-in Core Tools** — bash, read, write, edit, grep, find, ls, spawn_subagent with no MCP overhead\n- **MCP Integration** — Connect external MCP servers for expanded capabilities\n- **Extension System** — Write custom tools, commands, widgets, and UI modifications in Go\n- **Interactive TUI** — Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering\n- **Session Management** — Tree-based conversation history with branching support\n- **Non-Interactive Mode** — Script-friendly positional args with JSON output\n- **ACP Server** — Run Kit as an [Agent Client Protocol](https://agentclientprotocol.com) agent over stdio\n- **Go SDK** — Embed Kit in your own applications\n\n## Quick links\n\n| Resource | Description |\n|----------|-------------|\n| [Installation](/installation) | Get Kit up and running |\n| [Quick Start](/quick-start) | Your first Kit session |\n| [Configuration](/configuration) | Customize Kit for your workflow |\n| [Extensions](/extensions/overview) | Build custom tools and UI components |\n| [Go SDK](/sdk/overview) | Embed Kit in your applications |\n" + }, + { + "url": "/installation", + "title": "Installation", + "description": "Install Kit using npm, Go, or build from source.", + "headings": [ + "Using npm (recommended)", + "Using Go", + "Building from source", + "Verifying the installation", + "Setting up a provider" + ], + "tags": [], + "content": "\n# Installation\n\n## Using npm (recommended)\n\n```bash\nnpm install -g @mark3labs/kit\n```\n\n## Using Go\n\n```bash\ngo install github.com/mark3labs/kit/cmd/kit@latest\n```\n\n## Building from source\n\n```bash\ngit clone https://github.com/mark3labs/kit.git\ncd kit\ngo build -o kit ./cmd/kit\n```\n\n## Verifying the installation\n\nAfter installing, verify Kit is available:\n\n```bash\nkit --help\n```\n\n## Setting up a provider\n\nKit needs at least one LLM provider configured. Set an API key for your preferred provider:\n\n```bash\n# Anthropic (default provider)\nexport ANTHROPIC_API_KEY=\"sk-...\"\n\n# OpenAI\nexport OPENAI_API_KEY=\"sk-...\"\n\n# Google Gemini\nexport GOOGLE_API_KEY=\"...\"\n```\n\nFor OAuth-enabled providers like Anthropic, you can also authenticate interactively:\n\n```bash\nkit auth login anthropic\n```\n\nSee [Providers](/providers) for the full list of supported providers and their configuration.\n" + }, + { + "url": "/providers", + "title": "Providers", + "description": "Supported LLM providers and model configuration.", + "headings": [ + "Supported providers", + "Model string format", + "Model aliases", + "Specifying a model", + "Authentication", + "API keys", + "OAuth", + "Custom provider URL", + "Model database" + ], + "tags": [], + "content": "\n# Providers\n\nKit supports a wide range of LLM providers through a unified `provider/model` string format.\n\n## Supported providers\n\n| Provider | Prefix | Description |\n|----------|--------|-------------|\n| **Anthropic** | `anthropic/` | Claude models (native, prompt caching, OAuth) |\n| **OpenAI** | `openai/` | GPT models |\n| **Google** | `google/` or `gemini/` | Gemini models |\n| **Ollama** | `ollama/` | Local models |\n| **Azure OpenAI** | `azure/` | Azure-hosted OpenAI |\n| **AWS Bedrock** | `bedrock/` | Bedrock models |\n| **Google Vertex** | `google-vertex-anthropic/` | Claude on Vertex AI |\n| **OpenRouter** | `openrouter/` | Multi-provider router |\n| **Vercel AI** | `vercel/` | Vercel AI SDK models |\n| **Auto-routed** | any | Any provider from the models.dev database |\n\n## Model string format\n\n```bash\nprovider/model # Standard format\nanthropic/claude-sonnet-4-5-20250929\nopenai/gpt-4o\nollama/llama3\ngoogle/gemini-2.0-flash-exp\n```\n\n## Model aliases\n\nKit provides aliases for commonly used models:\n\n```bash\nclaude-opus-latest → claude-opus-4-20250514\nclaude-sonnet-latest → claude-sonnet-4-5-20250929\nclaude-4-opus-latest → claude-opus-4-20250514\nclaude-4-sonnet-latest → claude-sonnet-4-5-20250929\nclaude-3-7-sonnet-latest → claude-3-7-sonnet-20250219\nclaude-3-5-sonnet-latest → claude-3-5-sonnet-20241022\nclaude-3-5-haiku-latest → claude-3-5-haiku-20241022\nclaude-3-opus-latest → claude-3-opus-20240229\n```\n\n## Specifying a model\n\nVia CLI flag:\n\n```bash\nkit --model openai/gpt-4o\nkit -m ollama/llama3\n```\n\nVia config file:\n\n```yaml\nmodel: anthropic/claude-sonnet-4-5-20250929\n```\n\nVia environment variable:\n\n```bash\nexport KIT_MODEL=\"google/gemini-2.0-flash-exp\"\n```\n\n## Authentication\n\n### API keys\n\nSet the appropriate environment variable for your provider:\n\n```bash\nexport ANTHROPIC_API_KEY=\"sk-...\"\nexport OPENAI_API_KEY=\"sk-...\"\nexport GOOGLE_API_KEY=\"...\"\n```\n\nOr pass it directly:\n\n```bash\nkit --provider-api-key \"sk-...\" --model openai/gpt-4o\n```\n\n### OAuth\n\nFor providers that support OAuth (e.g., Anthropic):\n\n```bash\nkit auth login anthropic # Start OAuth flow\nkit auth status # Check authentication status\nkit auth logout anthropic # Remove credentials\n```\n\n### Custom provider URL\n\nFor self-hosted or proxy endpoints:\n\n```bash\nkit --provider-url \"https://my-proxy.example.com/v1\" --model openai/gpt-4o\n```\n\n## Model database\n\nKit ships with a local model database that maps provider names to API configurations. You can manage it with:\n\n```bash\nkit models # List available models\nkit models openai # Filter by provider\nkit models --all # Show all providers\nkit update-models # Update from models.dev\nkit update-models embedded # Reset to bundled database\n```\n" + }, + { + "url": "/quick-start", + "title": "Quick Start", + "description": "Get up and running with Kit in minutes.", + "headings": [ + "Basic usage", + "Non-interactive mode", + "Resuming sessions", + "ACP server mode" + ], + "tags": [], + "content": "\n# Quick Start\n\n## Basic usage\n\nStart an interactive session:\n\n```bash\nkit\n```\n\nRun a one-off prompt:\n\n```bash\nkit \"List files in src/\"\n```\n\nAttach files as context using the `@` prefix:\n\n```bash\nkit @main.go @test.go \"Review these files\"\n```\n\nUse a specific model:\n\n```bash\nkit --model anthropic/claude-sonnet-4-5-20250929\n```\n\n## Non-interactive mode\n\nKit can run as a non-interactive tool for scripting and automation.\n\nGet JSON output:\n\n```bash\nkit \"Explain main.go\" --json\n```\n\nQuiet mode (final response only, no TUI):\n\n```bash\nkit \"Run tests\" --quiet\n```\n\nEphemeral mode (no session file created):\n\n```bash\nkit \"Quick question\" --no-session\n```\n\n## Resuming sessions\n\nContinue the most recent session for the current directory:\n\n```bash\nkit --continue\n# or\nkit -c\n```\n\nPick from previous sessions interactively:\n\n```bash\nkit --resume\n# or\nkit -r\n```\n\n## ACP server mode\n\nKit can run as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server, enabling ACP-compatible clients (such as [OpenCode](https://github.com/sst/opencode)) to drive Kit as a remote coding agent over stdio:\n\n```bash\n# Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout)\nkit acp\n\n# With debug logging to stderr\nkit acp --debug\n```\n\nThe ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol.\n" + }, + { + "url": "/sdk/callbacks", + "title": "Callbacks", + "description": "Monitor tool calls and streaming output with the Kit Go SDK.", + "headings": [ + "PromptWithCallbacks", + "Callback signatures", + "Event-based monitoring", + "Hook system" + ], + "tags": [], + "content": "\n# Callbacks\n\n## PromptWithCallbacks\n\nThe `PromptWithCallbacks` method provides real-time visibility into tool calls and streaming output:\n\n```go\nresponse, err := host.PromptWithCallbacks(\n ctx,\n \"List files in current directory\",\n func(name, args string) {\n // Called when the model invokes a tool\n fmt.Println(\"Calling tool:\", name)\n },\n func(name, args, result string, isError bool) {\n // Called when a tool returns its result\n if isError {\n fmt.Println(\"Tool failed:\", name)\n }\n },\n func(chunk string) {\n // Called for each streaming text chunk\n fmt.Print(chunk)\n },\n)\n```\n\n### Callback signatures\n\n| Callback | Signature | When |\n|----------|-----------|------|\n| `onToolCall` | `func(name, args string)` | Model requests a tool call |\n| `onToolResult` | `func(name, args, result string, isError bool)` | Tool execution completes |\n| `onStreaming` | `func(chunk string)` | Streaming text chunk received |\n\nAny callback can be `nil` if you don't need it:\n\n```go\n// Only care about streaming output\nresponse, err := host.PromptWithCallbacks(ctx, \"Hello\", nil, nil, func(chunk string) {\n fmt.Print(chunk)\n})\n```\n\n## Event-based monitoring\n\nFor more granular control, use the event subscription API:\n\n```go\n// Subscribe returns an unsubscribe function\nunsub := host.OnToolCall(func(event kit.ToolCallEvent) {\n fmt.Printf(\"Tool: %s, Args: %s\\n\", event.Name, event.Args)\n})\ndefer unsub()\n\nunsub2 := host.OnToolResult(func(event kit.ToolResultEvent) {\n fmt.Printf(\"Result: %s (error: %v)\\n\", event.Name, event.IsError)\n})\ndefer unsub2()\n\nunsub3 := host.OnStreaming(func(event kit.MessageUpdateEvent) {\n fmt.Print(event.Chunk)\n})\ndefer unsub3()\n\nunsub4 := host.OnResponse(func(event kit.ResponseEvent) {\n fmt.Println(\"Final response received\")\n})\ndefer unsub4()\n\nunsub5 := host.OnTurnStart(func(event kit.TurnStartEvent) {\n fmt.Println(\"Turn started\")\n})\ndefer unsub5()\n\nunsub6 := host.OnTurnEnd(func(event kit.TurnEndEvent) {\n fmt.Println(\"Turn ended\")\n})\ndefer unsub6()\n```\n\n## Hook system\n\nHooks allow you to intercept and modify behavior. Unlike events, hooks can modify or cancel operations:\n\n```go\n// Intercept tool calls before execution\nhost.OnBeforeToolCall(0, func(ctx context.Context, name string, args string) (string, error) {\n if name == \"bash\" {\n log.Println(\"Bash command:\", args)\n }\n return args, nil // return modified args or error to cancel\n})\n\n// Process results after tool execution\nhost.OnAfterToolResult(0, func(ctx context.Context, name string, result string) (string, error) {\n return result, nil\n})\n\n// Before/after each agent turn\nhost.OnBeforeTurn(0, func(ctx context.Context) error {\n return nil\n})\n\nhost.OnAfterTurn(0, func(ctx context.Context) error {\n return nil\n})\n```\n\nThe first argument is a priority (lower = runs first).\n" + }, + { + "url": "/sdk/options", + "title": "SDK Options", + "description": "Configuration options for the Kit Go SDK.", + "headings": [ + "Full options reference", + "Options fields" + ], + "tags": [], + "content": "\n# SDK Options\n\nPass an `Options` struct to `kit.New()` to configure the Kit instance.\n\n## Full options reference\n\n```go\nhost, err := kit.New(ctx, &kit.Options{\n // Model\n Model: \"ollama/llama3\",\n SystemPrompt: \"You are a helpful bot\",\n ConfigFile: \"/path/to/config.yml\",\n\n // Behavior\n MaxSteps: 10,\n Streaming: true,\n Quiet: true,\n Debug: true,\n\n // Session\n SessionPath: \"./session.jsonl\",\n SessionDir: \"/custom/sessions/\",\n Continue: true,\n NoSession: true,\n\n // Tools\n Tools: []kit.Tool{...}, // Replace default tool set entirely\n ExtraTools: []kit.Tool{...}, // Add tools alongside defaults\n\n // Compaction\n AutoCompact: true,\n\n // Skills\n Skills: []string{\"/path/to/skill.md\"},\n SkillsDir: \"/path/to/skills/\",\n})\n```\n\n## Options fields\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `Model` | `string` | config default | Model string (provider/model format) |\n| `SystemPrompt` | `string` | — | System prompt text or file path |\n| `ConfigFile` | `string` | `~/.kit.yml` | Path to config file |\n| `MaxSteps` | `int` | `0` | Max agent steps (0 = unlimited) |\n| `Streaming` | `bool` | `true` | Enable streaming output |\n| `Quiet` | `bool` | `false` | Suppress output |\n| `Debug` | `bool` | `false` | Enable debug logging |\n| `SessionPath` | `string` | — | Open a specific session file |\n| `SessionDir` | `string` | — | Base directory for session discovery |\n| `Continue` | `bool` | `false` | Resume most recent session |\n| `NoSession` | `bool` | `false` | Ephemeral mode (no persistence) |\n| `Tools` | `[]Tool` | — | Replace the entire default tool set |\n| `ExtraTools` | `[]Tool` | — | Additional tools alongside core/MCP/extension tools |\n| `AutoCompact` | `bool` | `false` | Auto-compact when near context limit |\n| `CompactionOptions` | `*CompactionOptions` | — | Configuration for auto-compaction |\n| `Skills` | `[]string` | — | Explicit skill files/dirs to load |\n| `SkillsDir` | `string` | — | Override default skills directory |\n" + }, + { + "url": "/sdk/overview", + "title": "Go SDK", + "description": "Embed Kit in your Go applications.", + "headings": [ + "Installation", + "Basic usage", + "Multi-turn conversations", + "Additional prompt methods", + "Event system", + "Model management", + "Context and compaction" + ], + "tags": [], + "content": "\n# Go SDK\n\nThe `pkg/kit` package lets you embed Kit as a library in your Go applications.\n\n## Installation\n\n```bash\ngo get github.com/mark3labs/kit/pkg/kit\n```\n\n## Basic usage\n\n```go\npackage main\n\nimport (\n \"context\"\n \"log\"\n\n kit \"github.com/mark3labs/kit/pkg/kit\"\n)\n\nfunc main() {\n ctx := context.Background()\n\n // Create Kit instance with default configuration\n host, err := kit.New(ctx, nil)\n if err != nil {\n log.Fatal(err)\n }\n defer host.Close()\n\n // Send a prompt\n response, err := host.Prompt(ctx, \"What is 2+2?\")\n if err != nil {\n log.Fatal(err)\n }\n\n println(response)\n}\n```\n\n## Multi-turn conversations\n\nConversations retain context automatically across calls:\n\n```go\nhost.Prompt(ctx, \"My name is Alice\")\nresponse, _ := host.Prompt(ctx, \"What's my name?\")\n// response: \"Your name is Alice\"\n```\n\n## Additional prompt methods\n\nThe SDK provides several prompt variants:\n\n| Method | Description |\n|--------|-------------|\n| `Prompt(ctx, message)` | Simple prompt, returns response string |\n| `PromptWithCallbacks(ctx, message, ...)` | With tool call and streaming callbacks |\n| `PromptWithOptions(ctx, message, opts)` | With per-call options |\n| `PromptResult(ctx, message)` | Returns full `TurnResult` with usage stats |\n| `PromptResultWithFiles(ctx, message, files)` | Multimodal with file attachments |\n| `Steer(ctx, instruction)` | System-level steering without user message |\n| `FollowUp(ctx, text)` | Continue without new user input |\n\n## Event system\n\nSubscribe to events for monitoring:\n\n```go\nunsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) {\n fmt.Println(\"Tool called:\", event.Name)\n})\ndefer unsubscribe()\n\nhost.OnToolResult(func(event kit.ToolResultEvent) {\n fmt.Println(\"Tool result:\", event.Name)\n})\n\nhost.OnStreaming(func(event kit.MessageUpdateEvent) {\n fmt.Print(event.Chunk)\n})\n```\n\n## Model management\n\nSwitch models at runtime:\n\n```go\nhost.SetModel(ctx, \"openai/gpt-4o\")\ninfo := host.GetModelInfo()\nmodels := host.GetAvailableModels()\n```\n\n## Context and compaction\n\nMonitor and manage context usage:\n\n```go\ntokens := host.EstimateContextTokens()\nstats := host.GetContextStats()\n\nif host.ShouldCompact() {\n result, err := host.Compact(ctx, nil, \"\")\n}\n```\n\nSee [Options](/sdk/options), [Callbacks](/sdk/callbacks), and [Sessions](/sdk/sessions) for more details.\n" + }, + { + "url": "/sdk/sessions", + "title": "SDK Sessions", + "description": "Session management in the Kit Go SDK.", + "headings": [ + "Automatic persistence", + "Accessing session info", + "Configuring sessions via Options", + "Clearing history", + "Tree-based sessions", + "Listing and managing sessions" + ], + "tags": [], + "content": "\n# SDK Sessions\n\n## Automatic persistence\n\nBy default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls:\n\n```go\nhost.Prompt(ctx, \"My name is Alice\")\nresponse, _ := host.Prompt(ctx, \"What's my name?\")\n// response: \"Your name is Alice\"\n```\n\n## Accessing session info\n\n```go\n// Get the current session file path\npath := host.GetSessionPath()\n\n// Get the session ID\nid := host.GetSessionID()\n\n// Get the current model string\nmodel := host.GetModelString()\n```\n\n## Configuring sessions via Options\n\nSession behavior is configured at initialization:\n\n```go\n// Open a specific session file\nhost, _ := kit.New(ctx, &kit.Options{\n SessionPath: \"./my-session.jsonl\",\n})\n\n// Resume the most recent session for the current directory\nhost, _ := kit.New(ctx, &kit.Options{\n Continue: true,\n})\n\n// Ephemeral mode (no file persistence)\nhost, _ := kit.New(ctx, &kit.Options{\n NoSession: true,\n})\n\n// Custom session directory\nhost, _ := kit.New(ctx, &kit.Options{\n SessionDir: \"/custom/sessions/\",\n})\n```\n\n## Clearing history\n\nClear the in-memory conversation history (does not delete the session file):\n\n```go\nhost.ClearSession()\n```\n\n## Tree-based sessions\n\nKit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths:\n\n```go\n// Access the tree session manager\nts := host.GetTreeSession()\n\n// Branch from a specific entry\nerr := host.Branch(\"entry-id-123\")\n```\n\n## Listing and managing sessions\n\nPackage-level functions for session discovery:\n\n```go\n// List sessions for a specific directory\nsessions := kit.ListSessions(\"/home/user/project\")\n\n// List all sessions across all directories\nall := kit.ListAllSessions()\n\n// Delete a session file\nkit.DeleteSession(\"/path/to/session.jsonl\")\n```\n" + }, + { + "url": "/sessions", + "title": "Session Management", + "description": "How Kit persists and manages conversation sessions.", + "headings": [ + "Session storage", + "Resuming sessions", + "Continue most recent", + "Interactive picker", + "Open a specific session", + "Ephemeral mode" + ], + "tags": [], + "content": "\n# Session Management\n\nKit uses a tree-based session model that supports branching and forking conversations.\n\n## Session storage\n\nSessions are stored as JSONL (JSON Lines) files:\n\n```\n~/.kit/sessions//_.jsonl\n```\n\nPath separators in the working directory are replaced with `--`. For example, `/home/user/project` becomes `home--user--project`.\n\nEach line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths.\n\n## Resuming sessions\n\n### Continue most recent\n\nResume the most recent session for the current directory:\n\n```bash\nkit --continue\nkit -c\n```\n\n### Interactive picker\n\nChoose from previous sessions interactively:\n\n```bash\nkit --resume\nkit -r\n```\n\n### Open a specific session\n\n```bash\nkit --session path/to/session.jsonl\nkit -s path/to/session.jsonl\n```\n\n## Ephemeral mode\n\nRun without creating a session file:\n\n```bash\nkit --no-session\n```\n\nThis is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed.\n" + } + ] +} \ No newline at end of file diff --git a/providers/index.html b/providers/index.html new file mode 100644 index 00000000..efcd7036 --- /dev/null +++ b/providers/index.html @@ -0,0 +1,129 @@ + + + + + +Providers | Kit + + + + + + + +
    +

    Providers

    +# Providers + +Kit supports a wide range of LLM providers through a unified `provider/model` string format. + +## Supported providers + +| Provider | Prefix | Description | +|----------|--------|-------------| +| **Anthropic** | `anthropic/` | Claude models (native, prompt caching, OAuth) | +| **OpenAI** | `openai/` | GPT models | +| **Google** | `google/` or `gemini/` | Gemini models | +| **Ollama** | `ollama/` | Local models | +| **Azure OpenAI** | `azure/` | Azure-hosted OpenAI | +| **AWS Bedrock** | `bedrock/` | Bedrock models | +| **Google Vertex** | `google-vertex-anthropic/` | Claude on Vertex AI | +| **OpenRouter** | `openrouter/` | Multi-provider router | +| **Vercel AI** | `vercel/` | Vercel AI SDK models | +| **Auto-routed** | any | Any provider from the models.dev database | + +## Model string format + +```bash +provider/model # Standard format +anthropic/claude-sonnet-4-5-20250929 +openai/gpt-4o +ollama/llama3 +google/gemini-2.0-flash-exp +``` + +## Model aliases + +Kit provides aliases for commonly used models: + +```bash +claude-opus-latest → claude-opus-4-20250514 +claude-sonnet-latest → claude-sonnet-4-5-20250929 +claude-4-opus-latest → claude-opus-4-20250514 +claude-4-sonnet-latest → claude-sonnet-4-5-20250929 +claude-3-7-sonnet-latest → claude-3-7-sonnet-20250219 +claude-3-5-sonnet-latest → claude-3-5-sonnet-20241022 +claude-3-5-haiku-latest → claude-3-5-haiku-20241022 +claude-3-opus-latest → claude-3-opus-20240229 +``` + +## Specifying a model + +Via CLI flag: + +```bash +kit --model openai/gpt-4o +kit -m ollama/llama3 +``` + +Via config file: + +```yaml +model: anthropic/claude-sonnet-4-5-20250929 +``` + +Via environment variable: + +```bash +export KIT_MODEL="google/gemini-2.0-flash-exp" +``` + +## Authentication + +### API keys + +Set the appropriate environment variable for your provider: + +```bash +export ANTHROPIC_API_KEY="sk-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +``` + +Or pass it directly: + +```bash +kit --provider-api-key "sk-..." --model openai/gpt-4o +``` + +### OAuth + +For providers that support OAuth (e.g., Anthropic): + +```bash +kit auth login anthropic # Start OAuth flow +kit auth status # Check authentication status +kit auth logout anthropic # Remove credentials +``` + +### Custom provider URL + +For self-hosted or proxy endpoints: + +```bash +kit --provider-url "https://my-proxy.example.com/v1" --model openai/gpt-4o +``` + +## Model database + +Kit ships with a local model database that maps provider names to API configurations. You can manage it with: + +```bash +kit models # List available models +kit models openai # Filter by provider +kit models --all # Show all providers +kit update-models # Update from models.dev +kit update-models embedded # Reset to bundled database +```
    + + \ No newline at end of file diff --git a/quick-start/index.html b/quick-start/index.html new file mode 100644 index 00000000..9833ae8e --- /dev/null +++ b/quick-start/index.html @@ -0,0 +1,98 @@ + + + + + +Quick Start | Kit + + + + + + + +
    +

    Quick Start

    +# Quick Start + +## Basic usage + +Start an interactive session: + +```bash +kit +``` + +Run a one-off prompt: + +```bash +kit "List files in src/" +``` + +Attach files as context using the `@` prefix: + +```bash +kit @main.go @test.go "Review these files" +``` + +Use a specific model: + +```bash +kit --model anthropic/claude-sonnet-4-5-20250929 +``` + +## Non-interactive mode + +Kit can run as a non-interactive tool for scripting and automation. + +Get JSON output: + +```bash +kit "Explain main.go" --json +``` + +Quiet mode (final response only, no TUI): + +```bash +kit "Run tests" --quiet +``` + +Ephemeral mode (no session file created): + +```bash +kit "Quick question" --no-session +``` + +## Resuming sessions + +Continue the most recent session for the current directory: + +```bash +kit --continue +# or +kit -c +``` + +Pick from previous sessions interactively: + +```bash +kit --resume +# or +kit -r +``` + +## ACP server mode + +Kit can run as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server, enabling ACP-compatible clients (such as [OpenCode](https://github.com/sst/opencode)) to drive Kit as a remote coding agent over stdio: + +```bash +# Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout) +kit acp + +# With debug logging to stderr +kit acp --debug +``` + +The ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol.
    + + \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 00000000..6755fa02 --- /dev/null +++ b/robots.txt @@ -0,0 +1,42 @@ +# Tome Documentation Site +# https://tome.dev + +User-agent: * +Allow: / + +# AI Crawlers — explicitly allowed +User-agent: GPTBot +Allow: / + +User-agent: ClaudeBot +Allow: / + +User-agent: Claude-Web +Allow: / + +User-agent: Amazonbot +Allow: / + +User-agent: anthropic-ai +Allow: / + +User-agent: Bytespider +Allow: / + +User-agent: CCBot +Allow: / + +User-agent: cohere-ai +Allow: / + +User-agent: PerplexityBot +Allow: / + +# Machine-readable resources +Sitemap: https://go-kit.dev/sitemap.xml + +# AI/LLM Resources +# llms.txt: https://go-kit.dev/llms.txt +# llms-full.txt: https://go-kit.dev/llms-full.txt +# skill.md: https://go-kit.dev/skill.md +# MCP manifest: https://go-kit.dev/mcp.json diff --git a/sdk/callbacks/index.html b/sdk/callbacks/index.html new file mode 100644 index 00000000..a468335f --- /dev/null +++ b/sdk/callbacks/index.html @@ -0,0 +1,127 @@ + + + + + +Callbacks | Kit + + + + + + + +
    +

    Callbacks

    +# Callbacks + +## PromptWithCallbacks + +The `PromptWithCallbacks` method provides real-time visibility into tool calls and streaming output: + +```go +response, err := host.PromptWithCallbacks( + ctx, + "List files in current directory", + func(name, args string) { + // Called when the model invokes a tool + fmt.Println("Calling tool:", name) + }, + func(name, args, result string, isError bool) { + // Called when a tool returns its result + if isError { + fmt.Println("Tool failed:", name) + } + }, + func(chunk string) { + // Called for each streaming text chunk + fmt.Print(chunk) + }, +) +``` + +### Callback signatures + +| Callback | Signature | When | +|----------|-----------|------| +| `onToolCall` | `func(name, args string)` | Model requests a tool call | +| `onToolResult` | `func(name, args, result string, isError bool)` | Tool execution completes | +| `onStreaming` | `func(chunk string)` | Streaming text chunk received | + +Any callback can be `nil` if you don't need it: + +```go +// Only care about streaming output +response, err := host.PromptWithCallbacks(ctx, "Hello", nil, nil, func(chunk string) { + fmt.Print(chunk) +}) +``` + +## Event-based monitoring + +For more granular control, use the event subscription API: + +```go +// Subscribe returns an unsubscribe function +unsub := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Printf("Tool: %s, Args: %s\n", event.Name, event.Args) +}) +defer unsub() + +unsub2 := host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Printf("Result: %s (error: %v)\n", event.Name, event.IsError) +}) +defer unsub2() + +unsub3 := host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +defer unsub3() + +unsub4 := host.OnResponse(func(event kit.ResponseEvent) { + fmt.Println("Final response received") +}) +defer unsub4() + +unsub5 := host.OnTurnStart(func(event kit.TurnStartEvent) { + fmt.Println("Turn started") +}) +defer unsub5() + +unsub6 := host.OnTurnEnd(func(event kit.TurnEndEvent) { + fmt.Println("Turn ended") +}) +defer unsub6() +``` + +## Hook system + +Hooks allow you to intercept and modify behavior. Unlike events, hooks can modify or cancel operations: + +```go +// Intercept tool calls before execution +host.OnBeforeToolCall(0, func(ctx context.Context, name string, args string) (string, error) { + if name == "bash" { + log.Println("Bash command:", args) + } + return args, nil // return modified args or error to cancel +}) + +// Process results after tool execution +host.OnAfterToolResult(0, func(ctx context.Context, name string, result string) (string, error) { + return result, nil +}) + +// Before/after each agent turn +host.OnBeforeTurn(0, func(ctx context.Context) error { + return nil +}) + +host.OnAfterTurn(0, func(ctx context.Context) error { + return nil +}) +``` + +The first argument is a priority (lower = runs first).
    + + \ No newline at end of file diff --git a/sdk/options/index.html b/sdk/options/index.html new file mode 100644 index 00000000..9c0e1a3b --- /dev/null +++ b/sdk/options/index.html @@ -0,0 +1,76 @@ + + + + + +SDK Options | Kit + + + + + + + +
    +

    SDK Options

    +# SDK Options + +Pass an `Options` struct to `kit.New()` to configure the Kit instance. + +## Full options reference + +```go +host, err := kit.New(ctx, &kit.Options{ + // Model + Model: "ollama/llama3", + SystemPrompt: "You are a helpful bot", + ConfigFile: "/path/to/config.yml", + + // Behavior + MaxSteps: 10, + Streaming: true, + Quiet: true, + Debug: true, + + // Session + SessionPath: "./session.jsonl", + SessionDir: "/custom/sessions/", + Continue: true, + NoSession: true, + + // Tools + Tools: []kit.Tool{...}, // Replace default tool set entirely + ExtraTools: []kit.Tool{...}, // Add tools alongside defaults + + // Compaction + AutoCompact: true, + + // Skills + Skills: []string{"/path/to/skill.md"}, + SkillsDir: "/path/to/skills/", +}) +``` + +## Options fields + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `Model` | `string` | config default | Model string (provider/model format) | +| `SystemPrompt` | `string` | — | System prompt text or file path | +| `ConfigFile` | `string` | `~/.kit.yml` | Path to config file | +| `MaxSteps` | `int` | `0` | Max agent steps (0 = unlimited) | +| `Streaming` | `bool` | `true` | Enable streaming output | +| `Quiet` | `bool` | `false` | Suppress output | +| `Debug` | `bool` | `false` | Enable debug logging | +| `SessionPath` | `string` | — | Open a specific session file | +| `SessionDir` | `string` | — | Base directory for session discovery | +| `Continue` | `bool` | `false` | Resume most recent session | +| `NoSession` | `bool` | `false` | Ephemeral mode (no persistence) | +| `Tools` | `[]Tool` | — | Replace the entire default tool set | +| `ExtraTools` | `[]Tool` | — | Additional tools alongside core/MCP/extension tools | +| `AutoCompact` | `bool` | `false` | Auto-compact when near context limit | +| `CompactionOptions` | `*CompactionOptions` | — | Configuration for auto-compaction | +| `Skills` | `[]string` | — | Explicit skill files/dirs to load | +| `SkillsDir` | `string` | — | Override default skills directory |
    + + \ No newline at end of file diff --git a/sdk/overview/index.html b/sdk/overview/index.html new file mode 100644 index 00000000..9c40cc61 --- /dev/null +++ b/sdk/overview/index.html @@ -0,0 +1,126 @@ + + + + + +Go SDK | Kit + + + + + + + +
    +

    Go SDK

    +# Go SDK + +The `pkg/kit` package lets you embed Kit as a library in your Go applications. + +## Installation + +```bash +go get github.com/mark3labs/kit/pkg/kit +``` + +## Basic usage + +```go +package main + +import ( + "context" + "log" + + kit "github.com/mark3labs/kit/pkg/kit" +) + +func main() { + ctx := context.Background() + + // Create Kit instance with default configuration + host, err := kit.New(ctx, nil) + if err != nil { + log.Fatal(err) + } + defer host.Close() + + // Send a prompt + response, err := host.Prompt(ctx, "What is 2+2?") + if err != nil { + log.Fatal(err) + } + + println(response) +} +``` + +## Multi-turn conversations + +Conversations retain context automatically across calls: + +```go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +``` + +## Additional prompt methods + +The SDK provides several prompt variants: + +| Method | Description | +|--------|-------------| +| `Prompt(ctx, message)` | Simple prompt, returns response string | +| `PromptWithCallbacks(ctx, message, ...)` | With tool call and streaming callbacks | +| `PromptWithOptions(ctx, message, opts)` | With per-call options | +| `PromptResult(ctx, message)` | Returns full `TurnResult` with usage stats | +| `PromptResultWithFiles(ctx, message, files)` | Multimodal with file attachments | +| `Steer(ctx, instruction)` | System-level steering without user message | +| `FollowUp(ctx, text)` | Continue without new user input | + +## Event system + +Subscribe to events for monitoring: + +```go +unsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) { + fmt.Println("Tool called:", event.Name) +}) +defer unsubscribe() + +host.OnToolResult(func(event kit.ToolResultEvent) { + fmt.Println("Tool result:", event.Name) +}) + +host.OnStreaming(func(event kit.MessageUpdateEvent) { + fmt.Print(event.Chunk) +}) +``` + +## Model management + +Switch models at runtime: + +```go +host.SetModel(ctx, "openai/gpt-4o") +info := host.GetModelInfo() +models := host.GetAvailableModels() +``` + +## Context and compaction + +Monitor and manage context usage: + +```go +tokens := host.EstimateContextTokens() +stats := host.GetContextStats() + +if host.ShouldCompact() { + result, err := host.Compact(ctx, nil, "") +} +``` + +See [Options](/sdk/options), [Callbacks](/sdk/callbacks), and [Sessions](/sdk/sessions) for more details.
    + + \ No newline at end of file diff --git a/sdk/sessions/index.html b/sdk/sessions/index.html new file mode 100644 index 00000000..5d8ddbd1 --- /dev/null +++ b/sdk/sessions/index.html @@ -0,0 +1,102 @@ + + + + + +SDK Sessions | Kit + + + + + + + +
    +

    SDK Sessions

    +# SDK Sessions + +## Automatic persistence + +By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls: + +```go +host.Prompt(ctx, "My name is Alice") +response, _ := host.Prompt(ctx, "What's my name?") +// response: "Your name is Alice" +``` + +## Accessing session info + +```go +// Get the current session file path +path := host.GetSessionPath() + +// Get the session ID +id := host.GetSessionID() + +// Get the current model string +model := host.GetModelString() +``` + +## Configuring sessions via Options + +Session behavior is configured at initialization: + +```go +// Open a specific session file +host, _ := kit.New(ctx, &kit.Options{ + SessionPath: "./my-session.jsonl", +}) + +// Resume the most recent session for the current directory +host, _ := kit.New(ctx, &kit.Options{ + Continue: true, +}) + +// Ephemeral mode (no file persistence) +host, _ := kit.New(ctx, &kit.Options{ + NoSession: true, +}) + +// Custom session directory +host, _ := kit.New(ctx, &kit.Options{ + SessionDir: "/custom/sessions/", +}) +``` + +## Clearing history + +Clear the in-memory conversation history (does not delete the session file): + +```go +host.ClearSession() +``` + +## Tree-based sessions + +Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths: + +```go +// Access the tree session manager +ts := host.GetTreeSession() + +// Branch from a specific entry +err := host.Branch("entry-id-123") +``` + +## Listing and managing sessions + +Package-level functions for session discovery: + +```go +// List sessions for a specific directory +sessions := kit.ListSessions("/home/user/project") + +// List all sessions across all directories +all := kit.ListAllSessions() + +// Delete a session file +kit.DeleteSession("/path/to/session.jsonl") +```
    + + \ No newline at end of file diff --git a/search.json b/search.json new file mode 100644 index 00000000..b9ec9084 --- /dev/null +++ b/search.json @@ -0,0 +1,333 @@ +{ + "version": 1, + "generator": "tome", + "site": "Kit", + "totalPages": 20, + "searchEndpoint": "/pagefind/pagefind.js", + "pages": [ + { + "id": "advanced/json-output", + "url": "https://go-kit.dev/advanced/json-output", + "title": "JSON Output", + "description": "Machine-readable JSON output for scripting and automation.", + "headings": [ + "Response format", + "Fields", + "Top-level", + "Usage", + "Message parts", + "Parsing in scripts", + "bash + jq", + "Go SDK" + ], + "tags": [], + "wordCount": 331 + }, + { + "id": "advanced/subagents", + "url": "https://go-kit.dev/advanced/subagents", + "title": "Subagents", + "description": "Multi-agent orchestration with Kit subagents.", + "headings": [ + "Subprocess pattern", + "Built-in spawn_subagent tool", + "Extension subagents", + "Go SDK subagents" + ], + "tags": [], + "wordCount": 247 + }, + { + "id": "advanced/testing", + "url": "https://go-kit.dev/advanced/testing", + "title": "Testing with tmux", + "description": "Test Kit's TUI non-interactively using tmux.", + "headings": [ + "Basic pattern", + "Testing extensions", + "Tips" + ], + "tags": [], + "wordCount": 264 + }, + { + "id": "cli/commands", + "url": "https://go-kit.dev/cli/commands", + "title": "Commands", + "description": "Complete reference for all Kit CLI subcommands.", + "headings": [ + "Authentication", + "Model database", + "Extension management", + "Installing extensions from git", + "Skills", + "ACP server" + ], + "tags": [], + "wordCount": 258 + }, + { + "id": "cli/flags", + "url": "https://go-kit.dev/cli/flags", + "title": "Global Flags", + "description": "Complete reference for all Kit CLI flags.", + "headings": [ + "Model and provider", + "Session management", + "Behavior", + "Extensions", + "Generation parameters", + "System" + ], + "tags": [], + "wordCount": 434 + }, + { + "id": "configuration", + "url": "https://go-kit.dev/configuration", + "title": "Configuration", + "description": "Configure Kit using config files, environment variables, and CLI flags.", + "headings": [ + "Basic configuration", + "All configuration keys", + "Environment variables", + "MCP server configuration", + "MCP server fields" + ], + "tags": [], + "wordCount": 444 + }, + { + "id": "development", + "url": "https://go-kit.dev/development", + "title": "Development", + "description": "Build, test, and contribute to Kit.", + "headings": [ + "Build and test", + "Project structure", + "Architecture overview", + "Multi-provider LLM support", + "MCP client-server model", + "Extension system", + "TUI architecture", + "Decoupling pattern", + "Contributing", + "Community" + ], + "tags": [], + "wordCount": 350 + }, + { + "id": "extensions/capabilities", + "url": "https://go-kit.dev/extensions/capabilities", + "title": "Capabilities", + "description": "All extension capabilities — lifecycle events, tools, commands, widgets, and more.", + "headings": [ + "Lifecycle events", + "Example", + "Tools", + "Commands", + "Widgets", + "Headers and footers", + "Status bar", + "Shortcuts", + "Overlays", + "Tool renderers", + "Message renderers", + "Editor interceptors", + "Interactive prompts", + "Options", + "Subagents", + "LLM completion", + "Custom events" + ], + "tags": [], + "wordCount": 638 + }, + { + "id": "extensions/examples", + "url": "https://go-kit.dev/extensions/examples", + "title": "Examples", + "description": "Catalog of example extensions included with Kit.", + "headings": [ + "UI and display", + "Workflow and automation", + "Interactive features", + "Agent and context", + "Multi-agent", + "Development", + "Subdirectory extensions" + ], + "tags": [], + "wordCount": 318 + }, + { + "id": "extensions/loading", + "url": "https://go-kit.dev/extensions/loading", + "title": "Loading Extensions", + "description": "How Kit discovers and loads extensions.", + "headings": [ + "Auto-discovery", + "Explicit loading", + "Disabling extensions", + "Installing from git", + "Extension structure", + "Single-file extensions", + "Subdirectory extensions", + "Package-level state" + ], + "tags": [], + "wordCount": 302 + }, + { + "id": "extensions/overview", + "url": "https://go-kit.dev/extensions/overview", + "title": "Extension System", + "description": "Overview of Kit's Go-based extension system.", + "headings": [ + "Minimal extension", + "How extensions work", + "Key concepts", + "The API object", + "The Context object" + ], + "tags": [], + "wordCount": 286 + }, + { + "id": "index", + "url": "https://go-kit.dev/", + "title": "Kit", + "description": "Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.", + "headings": [ + "Features", + "Quick links" + ], + "tags": [], + "wordCount": 216 + }, + { + "id": "installation", + "url": "https://go-kit.dev/installation", + "title": "Installation", + "description": "Install Kit using npm, Go, or build from source.", + "headings": [ + "Using npm (recommended)", + "Using Go", + "Building from source", + "Verifying the installation", + "Setting up a provider" + ], + "tags": [], + "wordCount": 116 + }, + { + "id": "providers", + "url": "https://go-kit.dev/providers", + "title": "Providers", + "description": "Supported LLM providers and model configuration.", + "headings": [ + "Supported providers", + "Model string format", + "Model aliases", + "Specifying a model", + "Authentication", + "API keys", + "OAuth", + "Custom provider URL", + "Model database" + ], + "tags": [], + "wordCount": 343 + }, + { + "id": "quick-start", + "url": "https://go-kit.dev/quick-start", + "title": "Quick Start", + "description": "Get up and running with Kit in minutes.", + "headings": [ + "Basic usage", + "Non-interactive mode", + "Resuming sessions", + "ACP server mode" + ], + "tags": [], + "wordCount": 212 + }, + { + "id": "sdk/callbacks", + "url": "https://go-kit.dev/sdk/callbacks", + "title": "Callbacks", + "description": "Monitor tool calls and streaming output with the Kit Go SDK.", + "headings": [ + "PromptWithCallbacks", + "Callback signatures", + "Event-based monitoring", + "Hook system" + ], + "tags": [], + "wordCount": 356 + }, + { + "id": "sdk/options", + "url": "https://go-kit.dev/sdk/options", + "title": "SDK Options", + "description": "Configuration options for the Kit Go SDK.", + "headings": [ + "Full options reference", + "Options fields" + ], + "tags": [], + "wordCount": 309 + }, + { + "id": "sdk/overview", + "url": "https://go-kit.dev/sdk/overview", + "title": "Go SDK", + "description": "Embed Kit in your Go applications.", + "headings": [ + "Installation", + "Basic usage", + "Multi-turn conversations", + "Additional prompt methods", + "Event system", + "Model management", + "Context and compaction" + ], + "tags": [], + "wordCount": 287 + }, + { + "id": "sdk/sessions", + "url": "https://go-kit.dev/sdk/sessions", + "title": "SDK Sessions", + "description": "Session management in the Kit Go SDK.", + "headings": [ + "Automatic persistence", + "Accessing session info", + "Configuring sessions via Options", + "Clearing history", + "Tree-based sessions", + "Listing and managing sessions" + ], + "tags": [], + "wordCount": 241 + }, + { + "id": "sessions", + "url": "https://go-kit.dev/sessions", + "title": "Session Management", + "description": "How Kit persists and manages conversation sessions.", + "headings": [ + "Session storage", + "Resuming sessions", + "Continue most recent", + "Interactive picker", + "Open a specific session", + "Ephemeral mode" + ], + "tags": [], + "wordCount": 152 + } + ] +} \ No newline at end of file diff --git a/sessions/index.html b/sessions/index.html new file mode 100644 index 00000000..8d4274d8 --- /dev/null +++ b/sessions/index.html @@ -0,0 +1,69 @@ + + + + + +Session Management | Kit + + + + + + + +
    +

    Session Management

    +# Session Management + +Kit uses a tree-based session model that supports branching and forking conversations. + +## Session storage + +Sessions are stored as JSONL (JSON Lines) files: + +``` +~/.kit/sessions//_.jsonl +``` + +Path separators in the working directory are replaced with `--`. For example, `/home/user/project` becomes `home--user--project`. + +Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths. + +## Resuming sessions + +### Continue most recent + +Resume the most recent session for the current directory: + +```bash +kit --continue +kit -c +``` + +### Interactive picker + +Choose from previous sessions interactively: + +```bash +kit --resume +kit -r +``` + +### Open a specific session + +```bash +kit --session path/to/session.jsonl +kit -s path/to/session.jsonl +``` + +## Ephemeral mode + +Run without creating a session file: + +```bash +kit --no-session +``` + +This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed.
    + + \ No newline at end of file diff --git a/skill.md b/skill.md new file mode 100644 index 00000000..0e9020a9 --- /dev/null +++ b/skill.md @@ -0,0 +1,56 @@ +# Kit + +> Documentation site powered by [Tome](https://tome.dev) + +## Overview + +This is the documentation for **Kit**. It is a static documentation site with full-text search, structured data, and machine-readable formats. + +## Available Resources + +| Resource | Path | Description | +|----------|------|-------------| +| llms.txt | /llms.txt | Lightweight page index with titles, descriptions, and URLs | +| llms-full.txt | /llms-full.txt | Full raw markdown content of all pages | +| MCP manifest | /mcp.json | Machine-readable page metadata with headings and tags | +| skill.md | /skill.md | This file — agent capabilities and site structure | +| robots.txt | /robots.txt | Crawler directives with AI agent permissions | +| Search API | /search.json | Pagefind search index metadata for programmatic search | + +## Site Structure + +### Pages + +- **[JSON Output](https://go-kit.dev/advanced/json-output)** — Machine-readable JSON output for scripting and automation. +- **[Subagents](https://go-kit.dev/advanced/subagents)** — Multi-agent orchestration with Kit subagents. +- **[Testing with tmux](https://go-kit.dev/advanced/testing)** — Test Kit's TUI non-interactively using tmux. +- **[Commands](https://go-kit.dev/cli/commands)** — Complete reference for all Kit CLI subcommands. +- **[Global Flags](https://go-kit.dev/cli/flags)** — Complete reference for all Kit CLI flags. +- **[Configuration](https://go-kit.dev/configuration)** — Configure Kit using config files, environment variables, and CLI flags. +- **[Development](https://go-kit.dev/development)** — Build, test, and contribute to Kit. +- **[Capabilities](https://go-kit.dev/extensions/capabilities)** — All extension capabilities — lifecycle events, tools, commands, widgets, and more. +- **[Examples](https://go-kit.dev/extensions/examples)** — Catalog of example extensions included with Kit. +- **[Loading Extensions](https://go-kit.dev/extensions/loading)** — How Kit discovers and loads extensions. +- **[Extension System](https://go-kit.dev/extensions/overview)** — Overview of Kit's Go-based extension system. +- **[Kit](https://go-kit.dev/)** — Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system. +- **[Installation](https://go-kit.dev/installation)** — Install Kit using npm, Go, or build from source. +- **[Providers](https://go-kit.dev/providers)** — Supported LLM providers and model configuration. +- **[Quick Start](https://go-kit.dev/quick-start)** — Get up and running with Kit in minutes. +- **[Callbacks](https://go-kit.dev/sdk/callbacks)** — Monitor tool calls and streaming output with the Kit Go SDK. +- **[SDK Options](https://go-kit.dev/sdk/options)** — Configuration options for the Kit Go SDK. +- **[Go SDK](https://go-kit.dev/sdk/overview)** — Embed Kit in your Go applications. +- **[SDK Sessions](https://go-kit.dev/sdk/sessions)** — Session management in the Kit Go SDK. +- **[Session Management](https://go-kit.dev/sessions)** — How Kit persists and manages conversation sessions. + +## How to Use This Site + +### For AI Agents + +1. **Quick overview**: Read `/llms.txt` for a page index with titles and URLs +2. **Full content**: Read `/llms-full.txt` for complete raw markdown of all pages +3. **Structured data**: Parse `/mcp.json` for machine-readable metadata including headings, tags, and content +4. **Search**: Use Pagefind search at `/pagefind/pagefind.js` or check `/search.json` for index metadata + +### Capabilities + +- **Search provider**: local