summaryrefslogtreecommitdiff
path: root/llm-tools-hl.el
diff options
context:
space:
mode:
authorVineet Kumar <git@vineetk.net>2026-05-24 13:50:36 -0400
committerVineet Kumar <git@vineetk.net>2026-05-24 14:10:39 -0400
commit6cb91f228a2f0433a7bc93205df8a5f3bd3b2304 (patch)
tree19c3fa40a70b8663ea4401f88051eac684e3a500 /llm-tools-hl.el
parentd57c422cddf657fab565411ffe9956a32ff37230 (diff)
rename from gptel-tools an add gptel-agent's bash tool
Diffstat (limited to 'llm-tools-hl.el')
-rw-r--r--llm-tools-hl.el107
1 files changed, 107 insertions, 0 deletions
diff --git a/llm-tools-hl.el b/llm-tools-hl.el
new file mode 100644
index 0000000..c682334
--- /dev/null
+++ b/llm-tools-hl.el
@@ -0,0 +1,107 @@
1(defvar llm-tools--hl-bigrams
2 (list "aa" "ab" "ac" "ad" "ae" "af" "ag" "ah" "ai" "aj" "ak" "al" "am" "an"
3 "ao" "ap" "aq" "ar" "as" "at" "au" "av" "aw" "ax" "ay" "az" "ba" "bb"
4 "bc" "bd" "be" "bf" "bg" "bh" "bi" "bj" "bk" "bl" "bm" "bn" "bo" "bp"
5 "br" "bs" "bt" "bu" "bv" "bw" "bx" "by" "bz" "ca" "cb" "cc" "cd" "ce"
6 "cf" "cg" "ch" "ci" "cj" "ck" "cl" "cm" "cn" "co" "cp" "cq" "cr" "cs"
7 "ct" "cu" "cv" "cw" "cx" "cy" "cz" "da" "db" "dc" "dd" "de" "df" "dg"
8 "dh" "di" "dj" "dk" "dl" "dm" "dn" "do" "dp" "dq" "dr" "ds" "dt" "du"
9 "dv" "dw" "dx" "dy" "dz" "ea" "eb" "ec" "ed" "ee" "ef" "eg" "eh" "ei"
10 "ej" "ek" "el" "em" "en" "eo" "ep" "eq" "er" "es" "et" "eu" "ev" "ew"
11 "ex" "ey" "ez" "fa" "fb" "fc" "fd" "fe" "ff" "fg" "fh" "fi" "fj" "fk"
12 "fl" "fm" "fn" "fo" "fp" "fq" "fr" "fs" "ft" "fu" "fv" "fw" "fx" "fy"
13 "fz" "ga" "gb" "gc" "gd" "ge" "gf" "gg" "gh" "gi" "gj" "gl" "gm" "gn"
14 "go" "gp" "gr" "gs" "gt" "gu" "gv" "gw" "gx" "gy" "gz" "ha" "hb" "hc"
15 "hd" "he" "hf" "hg" "hh" "hi" "hj" "hk" "hl" "hm" "hn" "ho" "hp" "hq"
16 "hr" "hs" "ht" "hu" "hv" "hw" "hx" "hy" "hz" "ia" "ib" "ic" "id" "ie"
17 "if" "ig" "ih" "ii" "ij" "ik" "il" "im" "in" "io" "ip" "iq" "ir" "is"
18 "it" "iu" "iv" "iw" "ix" "iy" "iz" "ja" "jb" "jc" "jd" "je" "jf" "jg"
19 "jh" "ji" "jj" "jk" "jl" "jm" "jn" "jo" "jp" "jq" "jr" "js" "jt" "ju"
20 "jw" "jx" "jy" "ka" "kb" "kc" "kd" "ke" "kf" "kg" "kh" "ki" "kj" "kk"
21 "kl" "km" "kn" "ko" "kp" "kr" "ks" "kt" "ku" "kv" "kw" "kx" "ky" "la"
22 "lb" "lc" "ld" "le" "lf" "lg" "lh" "li" "lj" "lk" "ll" "lm" "ln" "lo"
23 "lp" "lr" "ls" "lt" "lu" "lv" "lw" "lx" "ly" "lz" "ma" "mb" "mc" "md"
24 "me" "mf" "mg" "mh" "mi" "mj" "mk" "ml" "mm" "mn" "mo" "mp" "mq" "mr"
25 "ms" "mt" "mu" "mv" "mw" "mx" "my" "mz" "na" "nb" "nc" "nd" "ne" "nf"
26 "ng" "nh" "ni" "nj" "nk" "nl" "nm" "nn" "no" "np" "nr" "ns" "nt" "nu"
27 "nv" "nw" "nx" "ny" "nz" "oa" "ob" "oc" "od" "oe" "of" "og" "oh" "oi"
28 "oj" "ok" "ol" "om" "on" "oo" "op" "oq" "or" "os" "ot" "ou" "ov" "ow"
29 "ox" "oy" "oz" "pa" "pb" "pc" "pd" "pe" "pf" "pg" "ph" "pi" "pj" "pk"
30 "pl" "pm" "pn" "po" "pp" "pq" "pr" "ps" "pt" "pu" "pv" "pw" "px" "py"
31 "pz" "qa" "qb" "qc" "qd" "qe" "qh" "qi" "ql" "qm" "qn" "qo" "qp" "qq"
32 "qr" "qs" "qt" "qu" "qw" "qx" "qy" "ra" "rb" "rc" "rd" "re" "rf" "rg"
33 "rh" "ri" "rk" "rl" "rm" "rn" "ro" "rp" "rq" "rr" "rs" "rt" "ru" "rv"
34 "rw" "rx" "ry" "rz" "sa" "sb" "sc" "sd" "se" "sf" "sg" "sh" "si" "sj"
35 "sk" "sl" "sm" "sn" "so" "sp" "sq" "sr" "ss" "st" "su" "sv" "sw" "sx"
36 "sy" "sz" "ta" "tb" "tc" "td" "te" "tf" "tg" "th" "ti" "tj" "tk" "tl"
37 "tm" "tn" "to" "tp" "tr" "ts" "tt" "tu" "tv" "tw" "tx" "ty" "tz" "ua"
38 "ub" "uc" "ud" "ue" "uf" "ug" "uh" "ui" "uj" "uk" "ul" "um" "un" "uo"
39 "up" "uq" "ur" "us" "ut" "uu" "uv" "uw" "ux" "uy" "uz" "va" "vb" "vc"
40 "vd" "ve" "vf" "vg" "vh" "vi" "vj" "vk" "vl" "vm" "vn" "vo" "vp" "vq"
41 "vr" "vs" "vt" "vu" "vv" "vw" "vx" "vy" "vz" "wa" "wb" "wc" "wd" "we"
42 "wf" "wg" "wh" "wi" "wj" "wk" "wl" "wm" "wn" "wo" "wp" "wr" "ws" "wt"
43 "wu" "wv" "ww" "wx" "wy" "xa" "xb" "xc" "xd" "xe" "xf" "xh" "xi" "xl"
44 "xm" "xn" "xo" "xp" "xr" "xs" "xt" "xu" "xx" "xy" "xz" "ya" "yb" "yc"
45 "yd" "ye" "yf" "yg" "yh" "yi" "yj" "yk" "yl" "ym" "yn" "yo" "yp" "yr"
46 "ys" "yt" "yu" "yv" "yw" "yx" "yy" "yz" "za" "zb" "zc" "zd" "ze" "zf"
47 "zg" "zh" "zi" "zk" "zl" "zm" "zn" "zo" "zp" "zr" "zs" "zt" "zu" "zw"
48 "zx" "zy" "zz")
49 "List of bigrams for use with hashline reads/writes.
50
51Each of the bigrams resolve to a single token in standard LLM
52vocabulary, unlike a hash's hex digits.
53
54Taken from https://github.com/can1357/oh-my-pi.
55Precisely: https://raw.githubusercontent.com/can1357/oh-my-pi/85003ca/packages/coding-agent/src/hashline/bigrams.json")
56
57(defun llm-tools--hl-hash (line)
58 (elt llm-tools--hl-bigrams (% (sxhash line) 647)))
59
60(defun llm-tools--hl-file-lines (file &optional beg end)
61 "Return FILE contents as a list of strings.
62With optional BEG and END (inclusive, 1-based), return the lines between that range."
63 (with-temp-buffer
64 (insert-file-contents-literally file)
65 (let ((lines (string-lines (buffer-string))))
66 (if beg
67 (cl-subseq lines (1- beg) end)
68 lines))))
69
70(defun llm-tools--hl-format-lines (lines &optional start include-content?)
71 "Format LINES in hashline format.
72START is 1-based (default 1).
73If INCLUDE-CONTENT is non-nil, append `|LINE' after each hash."
74 (string-join
75 (cl-mapcar (lambda (line i)
76 (if include-content?
77 (format "%d%2s|%s" i (llm-tools--hl-hash line) line)
78 (format "%d%2s" i (llm-tools--hl-hash line))))
79 lines
80 (number-sequence (or start 1) (+ (or start 1) (1- (length lines)))))
81 "\n"))
82
83(defun llm-tools--hl-file-read (file)
84 "Return FILE contents in hashline format."
85 (llm-tools--hl-format-lines (llm-tools--hl-file-lines file) nil t))
86
87(defun llm-tools--hl-file-read-range (file beg end)
88 "Return FILE contents in hashline format from lines BEG to END."
89 (llm-tools--hl-format-lines (llm-tools--hl-file-lines file beg end) beg t))
90
91;; FIXME might be redundant with =llm-tools--hl-file-line-hash= if I'm only
92;; verifying the hash of the anchors and telling LLM to re-read the
93;; file when they don't match
94(defun llm-tools--hl-file-read-hashes (file)
95 "Return FILE contents in hashline format without content."
96 (llm-tools--hl-format-lines (llm-tools--hl-file-lines file)))
97
98(defun llm-tools--hl-file-line-hash (file n)
99 "Return the hash of the Nth line in FILE."
100 (let ((lines (llm-tools--hl-file-lines file)))
101 (llm-tools--hl-hash (elt lines (1- n)))))
102
103;; before applying patch, first read the file to see if there were any changes
104;; if the llm's replacement text's hashlines do not match current hashlines, reject the request
105;; maybe if it just shifted a little bit (since the anchor is line number and hash of the line's content), there can be some kind of autohealing?
106;; rather, the llm would not format it like the reads. it's just going to provide text according to what the anchors it gives say
107;; so I just need to verify if the anchors didn't change