@hyperpuncher/pi-ui 0.38.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/dist/npm/server-main.js +633 -0
- package/package.json +77 -0
- package/static/app/attachment-file.js +99 -0
- package/static/app/basecoat.js +57 -0
- package/static/app/code-copy.js +32 -0
- package/static/app/dialogs.js +153 -0
- package/static/app/display-refresh.js +125 -0
- package/static/app/display-refresh_test.ts +86 -0
- package/static/app/file-links.js +69 -0
- package/static/app/file-links_test.ts +13 -0
- package/static/app/file-transfer.js +463 -0
- package/static/app/file-transfer_test.ts +174 -0
- package/static/app/main.js +122 -0
- package/static/app/message-scroll.js +343 -0
- package/static/app/message-scroll_test.ts +28 -0
- package/static/app/model-search.js +37 -0
- package/static/app/model-search_test.ts +31 -0
- package/static/app/pickers.js +289 -0
- package/static/app/pickers_test.ts +40 -0
- package/static/app/prompt-history.js +100 -0
- package/static/app/prompt-history_test.ts +51 -0
- package/static/app/prompt.js +99 -0
- package/static/app/session-performance.js +56 -0
- package/static/app/vim-scroll.js +161 -0
- package/static/app/window-focus.js +43 -0
- package/static/app/window-focus_test.ts +83 -0
- package/static/app.css +2 -0
- package/static/basecoat.vendor.js +1 -0
- package/static/build/chunks/abap-sc56dbra.js +1 -0
- package/static/build/chunks/actionscript-3-8wkk0yve.js +1 -0
- package/static/build/chunks/ada-wkh6yxhp.js +1 -0
- package/static/build/chunks/ahk-vk45ms9x.js +1 -0
- package/static/build/chunks/ahk2-ap9fnbvc.js +1 -0
- package/static/build/chunks/andromeeda-zy6mvqwb.js +1 -0
- package/static/build/chunks/angular-html-61dpttc3.js +1 -0
- package/static/build/chunks/angular-ts-hwtqv276.js +1 -0
- package/static/build/chunks/apache-750k8mss.js +1 -0
- package/static/build/chunks/apex-vpts0jxm.js +1 -0
- package/static/build/chunks/apl-jkh6rwt8.js +1 -0
- package/static/build/chunks/applescript-zb2jfj46.js +1 -0
- package/static/build/chunks/ara-4yjpz89z.js +1 -0
- package/static/build/chunks/asciidoc-5xj8s3ay.js +1 -0
- package/static/build/chunks/asm-x6ejak5x.js +1 -0
- package/static/build/chunks/astro-9cd9b7yr.js +1 -0
- package/static/build/chunks/aurora-x-gp6v3669.js +1 -0
- package/static/build/chunks/awk-mpdee6bv.js +1 -0
- package/static/build/chunks/ayu-dark-hbtcbdtr.js +1 -0
- package/static/build/chunks/ayu-light-m7rwwssv.js +1 -0
- package/static/build/chunks/ayu-mirage-5z71k1jj.js +1 -0
- package/static/build/chunks/ballerina-7c4wt1p4.js +1 -0
- package/static/build/chunks/bat-9778z743.js +1 -0
- package/static/build/chunks/beancount-xs0qfpeg.js +1 -0
- package/static/build/chunks/berry-pmbyf94p.js +1 -0
- package/static/build/chunks/bibtex-nnkgf3bz.js +1 -0
- package/static/build/chunks/bicep-vqhsh01p.js +1 -0
- package/static/build/chunks/bird2-za6bpr1n.js +1 -0
- package/static/build/chunks/blade-s6ew6vqn.js +1 -0
- package/static/build/chunks/bsl-z36cmzeg.js +1 -0
- package/static/build/chunks/c-kmp7y11e.js +1 -0
- package/static/build/chunks/c3-1g0cgjqv.js +1 -0
- package/static/build/chunks/cadence-a23a7f13.js +1 -0
- package/static/build/chunks/cairo-r6vd4awx.js +1 -0
- package/static/build/chunks/catppuccin-frappe-05b7n5ms.js +1 -0
- package/static/build/chunks/catppuccin-latte-c7x59n84.js +1 -0
- package/static/build/chunks/catppuccin-macchiato-xq6zfjrk.js +1 -0
- package/static/build/chunks/catppuccin-mocha-xreqmgt9.js +1 -0
- package/static/build/chunks/chapel-717mc8q1.js +1 -0
- package/static/build/chunks/clarity-g6gq1dzn.js +1 -0
- package/static/build/chunks/clojure-pm54sv44.js +1 -0
- package/static/build/chunks/cmake-f1skxqyd.js +1 -0
- package/static/build/chunks/cobol-mys3qens.js +1 -0
- package/static/build/chunks/code-theme-y49p9zss.js +5 -0
- package/static/build/chunks/codeowners-1ys5r05d.js +1 -0
- package/static/build/chunks/codeql-tdw0bqwy.js +1 -0
- package/static/build/chunks/coffee-t9hejzk2.js +1 -0
- package/static/build/chunks/common-lisp-9hjzm22t.js +1 -0
- package/static/build/chunks/coq-fjr6d63p.js +1 -0
- package/static/build/chunks/cpp-1r5860gr.js +1 -0
- package/static/build/chunks/crystal-a1jynptt.js +1 -0
- package/static/build/chunks/csharp-4zp5c1yn.js +1 -0
- package/static/build/chunks/css-j5q0mhnm.js +1 -0
- package/static/build/chunks/csv-a39nx9ry.js +1 -0
- package/static/build/chunks/cue-tg9vgj1q.js +1 -0
- package/static/build/chunks/cypher-p1j7vh0k.js +1 -0
- package/static/build/chunks/d-1f7cc6re.js +1 -0
- package/static/build/chunks/dark-plus-zvzcxs8s.js +1 -0
- package/static/build/chunks/dart-8jekq66r.js +1 -0
- package/static/build/chunks/dax-2aph6zqg.js +1 -0
- package/static/build/chunks/desktop-fqy4qx2w.js +1 -0
- package/static/build/chunks/diff-hqj2qf6m.js +1 -0
- package/static/build/chunks/docker-cht4a1ht.js +1 -0
- package/static/build/chunks/dotenv-txd2x2vy.js +1 -0
- package/static/build/chunks/dracula-6abcnchd.js +1 -0
- package/static/build/chunks/dracula-soft-zyfsdrw6.js +1 -0
- package/static/build/chunks/dream-maker-0gsm31aq.js +1 -0
- package/static/build/chunks/edge-9h036g3s.js +1 -0
- package/static/build/chunks/elixir-7pyn80vc.js +1 -0
- package/static/build/chunks/elm-62v0vnec.js +1 -0
- package/static/build/chunks/emacs-lisp-58kh6hv8.js +1 -0
- package/static/build/chunks/erb-947psegf.js +1 -0
- package/static/build/chunks/erlang-vbf5hbwd.js +1 -0
- package/static/build/chunks/everforest-dark-g7rhmq33.js +1 -0
- package/static/build/chunks/everforest-light-spn7qghr.js +1 -0
- package/static/build/chunks/fennel-h323g5dt.js +1 -0
- package/static/build/chunks/fish-7qbmmjce.js +1 -0
- package/static/build/chunks/fluent-3sdffhr3.js +1 -0
- package/static/build/chunks/fonts-pcnzbv4q.js +1 -0
- package/static/build/chunks/fortran-fixed-form-azemmg4k.js +1 -0
- package/static/build/chunks/fortran-free-form-5njt96mh.js +1 -0
- package/static/build/chunks/fsharp-9eex114p.js +1 -0
- package/static/build/chunks/gdresource-v8yzpggb.js +1 -0
- package/static/build/chunks/gdscript-1snw12w7.js +1 -0
- package/static/build/chunks/gdshader-fmknssp0.js +1 -0
- package/static/build/chunks/genie-4gwgqcc6.js +1 -0
- package/static/build/chunks/gherkin-vjt0p14p.js +1 -0
- package/static/build/chunks/git-commit-z15avpkz.js +1 -0
- package/static/build/chunks/git-rebase-wj5kdx44.js +1 -0
- package/static/build/chunks/github-dark-default-q5m3jmep.js +1 -0
- package/static/build/chunks/github-dark-dimmed-0v34f529.js +1 -0
- package/static/build/chunks/github-dark-high-contrast-62grsqa6.js +1 -0
- package/static/build/chunks/github-dark-r3j6b7er.js +1 -0
- package/static/build/chunks/github-light-default-xgca5we2.js +1 -0
- package/static/build/chunks/github-light-high-contrast-0ee3g9rt.js +1 -0
- package/static/build/chunks/github-light-z1qp6zt5.js +1 -0
- package/static/build/chunks/gleam-znte7hjc.js +1 -0
- package/static/build/chunks/glimmer-js-nph8hwdq.js +1 -0
- package/static/build/chunks/glimmer-ts-fzpx4w3e.js +1 -0
- package/static/build/chunks/glsl-mzc3yta4.js +1 -0
- package/static/build/chunks/gn-3cqh8dtz.js +1 -0
- package/static/build/chunks/gnuplot-r8spf6zm.js +1 -0
- package/static/build/chunks/go-ac27dc57.js +1 -0
- package/static/build/chunks/graphql-f6vq7p23.js +1 -0
- package/static/build/chunks/groovy-p8r8bd0c.js +1 -0
- package/static/build/chunks/gruvbox-dark-hard-0zvxnx0e.js +1 -0
- package/static/build/chunks/gruvbox-dark-medium-qvjwy81n.js +1 -0
- package/static/build/chunks/gruvbox-dark-soft-mhtpt38s.js +1 -0
- package/static/build/chunks/gruvbox-light-hard-nrwjbbts.js +1 -0
- package/static/build/chunks/gruvbox-light-medium-qbwkw432.js +1 -0
- package/static/build/chunks/gruvbox-light-soft-rmkm778k.js +1 -0
- package/static/build/chunks/hack-a2wva0c2.js +1 -0
- package/static/build/chunks/haml-hmfn055t.js +1 -0
- package/static/build/chunks/handlebars-54kh2jwn.js +1 -0
- package/static/build/chunks/haskell-vkvkgtsh.js +1 -0
- package/static/build/chunks/haxe-yk1p58qs.js +1 -0
- package/static/build/chunks/hcl-mq3znmzm.js +1 -0
- package/static/build/chunks/hjson-ma7dfjrp.js +1 -0
- package/static/build/chunks/hlsl-jcfmchrk.js +1 -0
- package/static/build/chunks/horizon-bright-9s4tt51x.js +1 -0
- package/static/build/chunks/horizon-fm23m9qj.js +1 -0
- package/static/build/chunks/houston-fx2psmvq.js +1 -0
- package/static/build/chunks/html-derivative-xw79bbzd.js +1 -0
- package/static/build/chunks/html-nawteed7.js +1 -0
- package/static/build/chunks/http-72kn3sp8.js +1 -0
- package/static/build/chunks/hurl-eve0v3e8.js +1 -0
- package/static/build/chunks/hxml-8pcfrsh9.js +1 -0
- package/static/build/chunks/hy-989jkx6q.js +1 -0
- package/static/build/chunks/imba-cm19z6hg.js +1 -0
- package/static/build/chunks/index-gt9ev6v8.js +518 -0
- package/static/build/chunks/ini-a7zcn1v0.js +1 -0
- package/static/build/chunks/java-mjc9q3md.js +1 -0
- package/static/build/chunks/javascript-n8j33v1m.js +1 -0
- package/static/build/chunks/jinja-a6q4x5tm.js +1 -0
- package/static/build/chunks/jison-nj6cbyz2.js +1 -0
- package/static/build/chunks/json-bvza2dkb.js +1 -0
- package/static/build/chunks/json5-a53a0ked.js +1 -0
- package/static/build/chunks/jsonc-5tyv9mjd.js +1 -0
- package/static/build/chunks/jsonl-prv0dcjv.js +1 -0
- package/static/build/chunks/jsonnet-5gdjahsx.js +1 -0
- package/static/build/chunks/jssm-mwsp2p7j.js +1 -0
- package/static/build/chunks/jsx-75v76p5q.js +1 -0
- package/static/build/chunks/julia-45twp29b.js +1 -0
- package/static/build/chunks/just-ct7367ec.js +1 -0
- package/static/build/chunks/kanagawa-dragon-fbqq2bhk.js +1 -0
- package/static/build/chunks/kanagawa-lotus-zgxv1mgm.js +1 -0
- package/static/build/chunks/kanagawa-wave-wedn0ksa.js +1 -0
- package/static/build/chunks/kdl-n6ez9ngv.js +1 -0
- package/static/build/chunks/kotlin-ghtz1y98.js +1 -0
- package/static/build/chunks/kusto-43yprh9t.js +1 -0
- package/static/build/chunks/laserwave-2fz4nxs5.js +1 -0
- package/static/build/chunks/latex-httjryda.js +1 -0
- package/static/build/chunks/lean-49ww85t0.js +1 -0
- package/static/build/chunks/less-47m6fdq2.js +1 -0
- package/static/build/chunks/light-plus-5tghbj4b.js +1 -0
- package/static/build/chunks/liquid-r4gqgph0.js +1 -0
- package/static/build/chunks/llvm-zesbzx6h.js +1 -0
- package/static/build/chunks/log-n0g1tx1y.js +1 -0
- package/static/build/chunks/logo-j5ze60v0.js +1 -0
- package/static/build/chunks/lua-15pct4hw.js +1 -0
- package/static/build/chunks/luau-75hm4mxn.js +1 -0
- package/static/build/chunks/main-02cnngb2.js +2 -0
- package/static/build/chunks/main-06tnp3sh.js +2 -0
- package/static/build/chunks/main-0a9vnbak.js +2 -0
- package/static/build/chunks/main-0b281zv9.js +2 -0
- package/static/build/chunks/main-0nb87rgr.js +2 -0
- package/static/build/chunks/main-0w2eqgkm.js +2 -0
- package/static/build/chunks/main-1n8jg8rf.js +2 -0
- package/static/build/chunks/main-1q6650cv.js +2 -0
- package/static/build/chunks/main-1swy7s7h.js +2 -0
- package/static/build/chunks/main-1xeedcwa.js +2 -0
- package/static/build/chunks/main-2xnnvrcx.js +2 -0
- package/static/build/chunks/main-2zhgrhtb.js +2 -0
- package/static/build/chunks/main-3r9xmt0z.js +2 -0
- package/static/build/chunks/main-3s35k63z.js +2 -0
- package/static/build/chunks/main-3srxnktc.js +2 -0
- package/static/build/chunks/main-4sa6jbv9.js +2 -0
- package/static/build/chunks/main-61mzprk0.js +9 -0
- package/static/build/chunks/main-689tj0r4.js +2 -0
- package/static/build/chunks/main-6e7tjcht.js +2 -0
- package/static/build/chunks/main-6hjptvkk.js +2 -0
- package/static/build/chunks/main-6v87p7j0.js +2 -0
- package/static/build/chunks/main-77tx7a8q.js +2 -0
- package/static/build/chunks/main-7fchxg57.js +7 -0
- package/static/build/chunks/main-83kpz2vm.js +2 -0
- package/static/build/chunks/main-8vy6mdxc.js +2 -0
- package/static/build/chunks/main-98b1m2e8.js +2 -0
- package/static/build/chunks/main-9hkj1fvj.js +2 -0
- package/static/build/chunks/main-9r4kp1re.js +2 -0
- package/static/build/chunks/main-9rd1xskg.js +2 -0
- package/static/build/chunks/main-9rh1hxyw.js +2 -0
- package/static/build/chunks/main-9v5c2hm4.js +2 -0
- package/static/build/chunks/main-aw75bv70.js +2 -0
- package/static/build/chunks/main-b1wctdb9.js +2 -0
- package/static/build/chunks/main-brrygrcd.js +2 -0
- package/static/build/chunks/main-bxkfh3s9.js +2 -0
- package/static/build/chunks/main-capt12kv.js +2 -0
- package/static/build/chunks/main-cbea0k4t.js +2 -0
- package/static/build/chunks/main-cs7592x8.js +2 -0
- package/static/build/chunks/main-d04rg092.js +2 -0
- package/static/build/chunks/main-d4pbngvb.js +2 -0
- package/static/build/chunks/main-d96ygjmk.js +2 -0
- package/static/build/chunks/main-dbxf9vvb.js +2 -0
- package/static/build/chunks/main-e0bf1hc7.js +2 -0
- package/static/build/chunks/main-e1qp4v0e.js +2 -0
- package/static/build/chunks/main-ed67cb17.js +2 -0
- package/static/build/chunks/main-ef0zm6td.js +2 -0
- package/static/build/chunks/main-epkkzhsq.js +2 -0
- package/static/build/chunks/main-f1t9zy21.js +2 -0
- package/static/build/chunks/main-g4ry2z87.js +2 -0
- package/static/build/chunks/main-h9p54b6w.js +2 -0
- package/static/build/chunks/main-hp9qyk20.js +2 -0
- package/static/build/chunks/main-hv1v7a2c.js +2 -0
- package/static/build/chunks/main-jr2gz2ea.js +2 -0
- package/static/build/chunks/main-kktqjawn.js +2 -0
- package/static/build/chunks/main-knre9pdj.js +2 -0
- package/static/build/chunks/main-m9qkdc8e.js +2 -0
- package/static/build/chunks/main-mcptmf3e.js +2 -0
- package/static/build/chunks/main-mmmydrw7.js +2 -0
- package/static/build/chunks/main-mqmtpd6m.js +2 -0
- package/static/build/chunks/main-n8b99y0n.js +2 -0
- package/static/build/chunks/main-nex51cmy.js +2 -0
- package/static/build/chunks/main-nzkzztjw.js +2 -0
- package/static/build/chunks/main-p5c2apac.js +2 -0
- package/static/build/chunks/main-p8efbnm1.js +2 -0
- package/static/build/chunks/main-q9q129d1.js +2 -0
- package/static/build/chunks/main-qbf61mtn.js +2 -0
- package/static/build/chunks/main-rb1nkcm0.js +2 -0
- package/static/build/chunks/main-spgna5r3.js +2 -0
- package/static/build/chunks/main-tqpmccz6.js +2 -0
- package/static/build/chunks/main-v7n0f428.js +2 -0
- package/static/build/chunks/main-v9j8veta.js +2 -0
- package/static/build/chunks/main-w5g9070a.js +2 -0
- package/static/build/chunks/main-wbpws0v9.js +2 -0
- package/static/build/chunks/main-wcnadmhs.js +1530 -0
- package/static/build/chunks/main-x61973bh.js +2 -0
- package/static/build/chunks/main-xqc8f31a.js +2 -0
- package/static/build/chunks/main-xtaq3qt4.js +2 -0
- package/static/build/chunks/main-xvgwadfa.js +2 -0
- package/static/build/chunks/main-y0dvfpw7.js +2 -0
- package/static/build/chunks/main-ynjqm60c.js +2 -0
- package/static/build/chunks/main-ypk8hvc0.js +2 -0
- package/static/build/chunks/main-zjsthwaz.js +2 -0
- package/static/build/chunks/main-zy79z3j0.js +2 -0
- package/static/build/chunks/make-82gdkt9b.js +1 -0
- package/static/build/chunks/markdown-5tkrg1ah.js +1 -0
- package/static/build/chunks/marko-qafrqcsm.js +1 -0
- package/static/build/chunks/material-theme-darker-fnv6smqw.js +1 -0
- package/static/build/chunks/material-theme-lighter-35th362e.js +1 -0
- package/static/build/chunks/material-theme-ocean-4dq3ahw3.js +1 -0
- package/static/build/chunks/material-theme-p7k291d1.js +1 -0
- package/static/build/chunks/material-theme-palenight-yhd4pmvh.js +1 -0
- package/static/build/chunks/matlab-mbnxwt6q.js +1 -0
- package/static/build/chunks/mdc-w29armgh.js +1 -0
- package/static/build/chunks/mdx-53tq2vwd.js +1 -0
- package/static/build/chunks/mermaid-kp8v57t9.js +1 -0
- package/static/build/chunks/min-dark-rtx0tqrz.js +1 -0
- package/static/build/chunks/min-light-5m66fg5h.js +1 -0
- package/static/build/chunks/mipsasm-may8rjf3.js +1 -0
- package/static/build/chunks/mojo-ezqmbs71.js +1 -0
- package/static/build/chunks/monokai-79awbcqn.js +1 -0
- package/static/build/chunks/moonbit-57vh5qgn.js +1 -0
- package/static/build/chunks/move-71jrpzz7.js +1 -0
- package/static/build/chunks/narrat-n4xxr8p6.js +1 -0
- package/static/build/chunks/nextflow-c0gn0hzt.js +1 -0
- package/static/build/chunks/nextflow-groovy-13xg49y5.js +1 -0
- package/static/build/chunks/nginx-vtb8rwdx.js +1 -0
- package/static/build/chunks/night-owl-light-05jd94v7.js +1 -0
- package/static/build/chunks/night-owl-y5p2e2yz.js +1 -0
- package/static/build/chunks/nim-nfvgqc30.js +1 -0
- package/static/build/chunks/nix-rkxmnaat.js +1 -0
- package/static/build/chunks/nord-akta5pm4.js +1 -0
- package/static/build/chunks/nsis-6c1fw7sy.js +1 -0
- package/static/build/chunks/nushell-pvtw3a6j.js +1 -0
- package/static/build/chunks/objective-c-jd7171g7.js +1 -0
- package/static/build/chunks/objective-cpp-6v7n9hk7.js +1 -0
- package/static/build/chunks/ocaml-kjv8t7w5.js +1 -0
- package/static/build/chunks/odin-58v0n0xa.js +1 -0
- package/static/build/chunks/one-dark-pro-pbp84hvh.js +1 -0
- package/static/build/chunks/one-light-jpadzfmm.js +1 -0
- package/static/build/chunks/openscad-0xnz3sah.js +1 -0
- package/static/build/chunks/org-xe4jzp20.js +1 -0
- package/static/build/chunks/pascal-f75emr3j.js +1 -0
- package/static/build/chunks/perl-zp07ased.js +1 -0
- package/static/build/chunks/php-fjm4srka.js +1 -0
- package/static/build/chunks/pierre-dark-2sng8cw6.js +1 -0
- package/static/build/chunks/pierre-dark-protanopia-deuteranopia-615mrd5v.js +1 -0
- package/static/build/chunks/pierre-dark-soft-xpc8stwc.js +1 -0
- package/static/build/chunks/pierre-dark-tritanopia-nw71c9hw.js +1 -0
- package/static/build/chunks/pierre-dark-vibrant-dtc0vftx.js +1 -0
- package/static/build/chunks/pierre-light-mtkcs9xq.js +1 -0
- package/static/build/chunks/pierre-light-protanopia-deuteranopia-d84wh0sh.js +1 -0
- package/static/build/chunks/pierre-light-soft-f0vxkd08.js +1 -0
- package/static/build/chunks/pierre-light-tritanopia-prpe8fpj.js +1 -0
- package/static/build/chunks/pierre-light-vibrant-y1syd51f.js +1 -0
- package/static/build/chunks/pkl-x0wayphd.js +1 -0
- package/static/build/chunks/plastic-5dg6r26t.js +1 -0
- package/static/build/chunks/plsql-259gvzn9.js +1 -0
- package/static/build/chunks/po-6kcxkqtd.js +1 -0
- package/static/build/chunks/poimandres-p8seewrs.js +1 -0
- package/static/build/chunks/polar-b1ev80vb.js +1 -0
- package/static/build/chunks/postcss-kxdxws93.js +1 -0
- package/static/build/chunks/powerquery-ved4pq1y.js +1 -0
- package/static/build/chunks/powershell-6j0w6ann.js +1 -0
- package/static/build/chunks/prisma-7r1mj2qq.js +1 -0
- package/static/build/chunks/prolog-7a8gwgvm.js +1 -0
- package/static/build/chunks/proto-s5e2jd7n.js +1 -0
- package/static/build/chunks/pug-8cxb8b6f.js +1 -0
- package/static/build/chunks/puppet-d1048c00.js +1 -0
- package/static/build/chunks/purescript-vqffe1a1.js +1 -0
- package/static/build/chunks/python-7z2eacwy.js +1 -0
- package/static/build/chunks/qml-51nrq0re.js +1 -0
- package/static/build/chunks/qmldir-q0jk1gzg.js +1 -0
- package/static/build/chunks/qss-6far86jw.js +1 -0
- package/static/build/chunks/r-qkm8ck5x.js +1 -0
- package/static/build/chunks/racket-mzbdy2fp.js +1 -0
- package/static/build/chunks/raku-se52tvjp.js +1 -0
- package/static/build/chunks/razor-y9b1j8td.js +1 -0
- package/static/build/chunks/rbs-00y9vc5r.js +1 -0
- package/static/build/chunks/red-tkj5bw1z.js +1 -0
- package/static/build/chunks/reg-9z4ax2nc.js +1 -0
- package/static/build/chunks/regexp-99svsrmp.js +1 -0
- package/static/build/chunks/rel-tf2jya2v.js +1 -0
- package/static/build/chunks/riscv-hpebp724.js +1 -0
- package/static/build/chunks/ron-s3mfhwnh.js +1 -0
- package/static/build/chunks/rose-pine-dawn-apmj5y1p.js +1 -0
- package/static/build/chunks/rose-pine-moon-mgx7zgjy.js +1 -0
- package/static/build/chunks/rose-pine-vgbee1jh.js +1 -0
- package/static/build/chunks/rosmsg-vgsgfpe4.js +1 -0
- package/static/build/chunks/rst-xnf3rrzd.js +1 -0
- package/static/build/chunks/ruby-gysj44ty.js +1 -0
- package/static/build/chunks/rust-bzv74qkx.js +1 -0
- package/static/build/chunks/sas-t4zftd7j.js +1 -0
- package/static/build/chunks/sass-tnsj7t5t.js +1 -0
- package/static/build/chunks/scala-vsjg5eg2.js +1 -0
- package/static/build/chunks/scheme-yhv7mnk9.js +1 -0
- package/static/build/chunks/scss-vt2fyer8.js +1 -0
- package/static/build/chunks/sdbl-jv670bae.js +1 -0
- package/static/build/chunks/shaderlab-csszkf9s.js +1 -0
- package/static/build/chunks/shellscript-t3jf42zg.js +1 -0
- package/static/build/chunks/shellsession-e1m2zj1m.js +1 -0
- package/static/build/chunks/slack-dark-ntnagayj.js +1 -0
- package/static/build/chunks/slack-ochin-kge218j8.js +1 -0
- package/static/build/chunks/smalltalk-q8bgts0p.js +1 -0
- package/static/build/chunks/smithy-m7r7jeg3.js +1 -0
- package/static/build/chunks/snazzy-light-57mzezsa.js +1 -0
- package/static/build/chunks/solarized-dark-0r80rpr7.js +1 -0
- package/static/build/chunks/solarized-light-1e0p6z46.js +1 -0
- package/static/build/chunks/solidity-vb1zcsry.js +1 -0
- package/static/build/chunks/soy-bzh2aynk.js +1 -0
- package/static/build/chunks/sparql-6t8g6rdd.js +1 -0
- package/static/build/chunks/splunk-50bpjgv6.js +1 -0
- package/static/build/chunks/sql-kkaf039q.js +1 -0
- package/static/build/chunks/ssh-config-715bkrac.js +1 -0
- package/static/build/chunks/stata-zhvjkw4g.js +1 -0
- package/static/build/chunks/stylus-b8aj4z6s.js +1 -0
- package/static/build/chunks/surrealql-4w27b1xf.js +1 -0
- package/static/build/chunks/svelte-6vty1ayf.js +1 -0
- package/static/build/chunks/swift-2w2k3des.js +1 -0
- package/static/build/chunks/synthwave-84-007ndkbp.js +1 -0
- package/static/build/chunks/system-verilog-hzg0fpex.js +1 -0
- package/static/build/chunks/systemd-d3k4d1av.js +1 -0
- package/static/build/chunks/talonscript-fw295t4h.js +1 -0
- package/static/build/chunks/tasl-8n3br9kn.js +1 -0
- package/static/build/chunks/tcl-e485436v.js +1 -0
- package/static/build/chunks/templ-535cbmg6.js +1 -0
- package/static/build/chunks/terraform-k8aqghnt.js +1 -0
- package/static/build/chunks/tex-9yx3fnmk.js +1 -0
- package/static/build/chunks/tokyo-night-rvkd4sna.js +1 -0
- package/static/build/chunks/toml-bypjcbh1.js +1 -0
- package/static/build/chunks/ts-tags-zyfv802m.js +1 -0
- package/static/build/chunks/tsv-2n58sktq.js +1 -0
- package/static/build/chunks/tsx-gnkw8sgq.js +1 -0
- package/static/build/chunks/turtle-sf93b8kj.js +1 -0
- package/static/build/chunks/twig-8gw76pn3.js +1 -0
- package/static/build/chunks/typescript-077c9w1h.js +1 -0
- package/static/build/chunks/typespec-8r8ncprb.js +1 -0
- package/static/build/chunks/typst-yg6690gs.js +1 -0
- package/static/build/chunks/v-tdjz29z1.js +1 -0
- package/static/build/chunks/vala-trffggt0.js +1 -0
- package/static/build/chunks/vb-1dx16kyy.js +1 -0
- package/static/build/chunks/verilog-sv7hb60t.js +1 -0
- package/static/build/chunks/vesper-005phtef.js +1 -0
- package/static/build/chunks/vhdl-qck3dqgh.js +1 -0
- package/static/build/chunks/viml-m54vetp0.js +1 -0
- package/static/build/chunks/vitesse-black-sxfaa2kz.js +1 -0
- package/static/build/chunks/vitesse-dark-fhxvesec.js +1 -0
- package/static/build/chunks/vitesse-light-cygqrsgb.js +1 -0
- package/static/build/chunks/vue-html-5ex4htv4.js +1 -0
- package/static/build/chunks/vue-n8p10w4p.js +1 -0
- package/static/build/chunks/vue-vine-y2qnwmqn.js +1 -0
- package/static/build/chunks/vyper-r9v6ymtz.js +1 -0
- package/static/build/chunks/wasm-c0aw8acq.js +1 -0
- package/static/build/chunks/wasm-eftreyx0.js +1 -0
- package/static/build/chunks/wenyan-pn35fr2w.js +1 -0
- package/static/build/chunks/wgsl-akmafmem.js +1 -0
- package/static/build/chunks/wikitext-yp9d6pan.js +1 -0
- package/static/build/chunks/wit-rg9t2t2j.js +1 -0
- package/static/build/chunks/wolfram-m5vswcfg.js +1 -0
- package/static/build/chunks/workspace-review-3scrbyaw.js +1361 -0
- package/static/build/chunks/xml-8pftb6y7.js +1 -0
- package/static/build/chunks/xsl-w4bvqyjy.js +1 -0
- package/static/build/chunks/yaml-a56qt88c.js +1 -0
- package/static/build/chunks/zenscript-pp2pffj8.js +1 -0
- package/static/build/chunks/zig-53aewpf9.js +1 -0
- package/static/build/main.js +6 -0
- package/static/build/pierre-worker.js +156 -0
- package/static/favicon.svg +1 -0
- package/static/file-uri.js +18 -0
- package/static/file-uri_test.ts +35 -0
- package/static/icon-180.png +0 -0
- package/static/icon-192.png +0 -0
- package/static/icon-512.png +0 -0
- package/static/manifest.webmanifest +23 -0
- package/static/notification-icon.png +0 -0
- package/static/theme.js +17 -0
- package/static/vendor/datastar-inspector.min.js +1021 -0
- package/static/vendor/datastar.js +10 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export function bindFileLinks() {
|
|
2
|
+
document.addEventListener(
|
|
3
|
+
"click",
|
|
4
|
+
(event) => {
|
|
5
|
+
if (event.button !== 0) return;
|
|
6
|
+
const link =
|
|
7
|
+
event.target instanceof Element ? event.target.closest("a[href]") : null;
|
|
8
|
+
if (!(link instanceof HTMLAnchorElement)) return;
|
|
9
|
+
const markedUri = link.getAttribute("data-pi-file-link") ?? "";
|
|
10
|
+
const uri = isFileUri(markedUri) ? markedUri : link.href;
|
|
11
|
+
if (!isFileUri(uri)) return;
|
|
12
|
+
|
|
13
|
+
// File navigation is forbidden from the HTTP UI. Claim the click even if
|
|
14
|
+
// another client handler already prevented it, then delegate to the backend.
|
|
15
|
+
event.preventDefault();
|
|
16
|
+
void followFileLink(uri);
|
|
17
|
+
},
|
|
18
|
+
{ capture: true },
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isFileUri(uri) {
|
|
23
|
+
try {
|
|
24
|
+
return new URL(uri).protocol === "file:";
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function followFileLink(uri) {
|
|
31
|
+
const endpoint = document.body.dataset.filesOpenEndpoint;
|
|
32
|
+
if (!endpoint) return;
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(endpoint, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: { "content-type": "application/json" },
|
|
38
|
+
body: JSON.stringify({ uri }),
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) throw new Error(await responseError(response));
|
|
41
|
+
if (response.status === 204) return;
|
|
42
|
+
|
|
43
|
+
const blobUrl = URL.createObjectURL(await response.blob());
|
|
44
|
+
const download = document.createElement("a");
|
|
45
|
+
download.href = blobUrl;
|
|
46
|
+
download.download = downloadName(response);
|
|
47
|
+
download.click();
|
|
48
|
+
setTimeout(() => URL.revokeObjectURL(blobUrl), 0);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
alert(error instanceof Error ? error.message : "Could not open the file.");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function responseError(response) {
|
|
55
|
+
try {
|
|
56
|
+
const body = await response.json();
|
|
57
|
+
return body.error || body.message || "Could not open the file.";
|
|
58
|
+
} catch {
|
|
59
|
+
return "Could not open the file.";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function downloadName(response) {
|
|
64
|
+
try {
|
|
65
|
+
return decodeURIComponent(response.headers.get("x-pi-file-name")) || "download";
|
|
66
|
+
} catch {
|
|
67
|
+
return "download";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { assertEquals } from "#testing/assertions";
|
|
4
|
+
|
|
5
|
+
import { isFileUri } from "./file-links.js";
|
|
6
|
+
|
|
7
|
+
test("file link detection accepts only file URIs", () => {
|
|
8
|
+
assertEquals(isFileUri("file:///home/user/report.html"), true);
|
|
9
|
+
assertEquals(isFileUri("file://server/share/report.html"), true);
|
|
10
|
+
assertEquals(isFileUri("https://example.com/report.html"), false);
|
|
11
|
+
assertEquals(isFileUri("/home/user/report.html"), false);
|
|
12
|
+
assertEquals(isFileUri("not a URI"), false);
|
|
13
|
+
});
|
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { fileUriToPath } from "../file-uri.js";
|
|
2
|
+
import { attachmentFileIcons, attachmentFileKind } from "./attachment-file.js";
|
|
3
|
+
import { closePickers } from "./pickers.js";
|
|
4
|
+
import { promptInput } from "./prompt.js";
|
|
5
|
+
|
|
6
|
+
const FILE_REFERENCE_TYPES = [
|
|
7
|
+
"text/uri-list",
|
|
8
|
+
"x-special/gnome-copied-files",
|
|
9
|
+
"text/plain",
|
|
10
|
+
];
|
|
11
|
+
const MAX_TRANSFER_FILES = 10;
|
|
12
|
+
const MAX_TRANSFER_FILE_BYTES = 20 * 1024 * 1024;
|
|
13
|
+
const MAX_TRANSFER_TOTAL_BYTES = 50 * 1024 * 1024;
|
|
14
|
+
const AVIF_JPEG_QUALITY = 0.85;
|
|
15
|
+
let dragDepth = 0;
|
|
16
|
+
let submitting = false;
|
|
17
|
+
const attachments = [];
|
|
18
|
+
|
|
19
|
+
export function hasFiles(data) {
|
|
20
|
+
if (!data) return false;
|
|
21
|
+
if (data.files?.length) return true;
|
|
22
|
+
return [...data.types].some((type) => type === "Files" || type === "text/uri-list");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function pick() {
|
|
26
|
+
showTransferError("");
|
|
27
|
+
const input = document.createElement("input");
|
|
28
|
+
input.type = "file";
|
|
29
|
+
input.multiple = true;
|
|
30
|
+
input.addEventListener(
|
|
31
|
+
"change",
|
|
32
|
+
() => {
|
|
33
|
+
if (input.files?.length) void insert(input.files);
|
|
34
|
+
},
|
|
35
|
+
{ once: true },
|
|
36
|
+
);
|
|
37
|
+
input.click();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function enterDrag() {
|
|
41
|
+
dragDepth += 1;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function leaveDrag() {
|
|
46
|
+
dragDepth = Math.max(0, dragDepth - 1);
|
|
47
|
+
return dragDepth > 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function resetDrag() {
|
|
51
|
+
dragDepth = 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function insert(data) {
|
|
55
|
+
if (!data) return;
|
|
56
|
+
showTransferError("");
|
|
57
|
+
const transferred = transferredFiles(data);
|
|
58
|
+
const needsImageHandling = transferred.some(
|
|
59
|
+
(file) => isAvifImageFile(file) || isHeicImageFile(file),
|
|
60
|
+
);
|
|
61
|
+
const paths = extractTransferredFilePaths(data);
|
|
62
|
+
if (paths.length > 0 && !needsImageHandling) {
|
|
63
|
+
const unsupported = unsupportedImagePathError(paths);
|
|
64
|
+
if (unsupported) {
|
|
65
|
+
showTransferError(unsupported);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
addPathAttachments(paths);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (transferred.length === 0) return;
|
|
72
|
+
const validationError = validateTransferredFiles(transferred);
|
|
73
|
+
if (validationError) {
|
|
74
|
+
showTransferError(validationError);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let files;
|
|
78
|
+
try {
|
|
79
|
+
files = await prepareTransferredImages(transferred);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(error);
|
|
82
|
+
showTransferError(error?.message || "Could not prepare the selected images.");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const preparedValidationError = validateTransferredFiles(files);
|
|
86
|
+
if (preparedValidationError) {
|
|
87
|
+
showTransferError(preparedValidationError);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const uploaded = await uploadTransferredFiles(files);
|
|
91
|
+
for (let index = 0; index < uploaded.length; index += 1) {
|
|
92
|
+
addAttachment({ path: uploaded[index], file: files[index] });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function hasAttachments() {
|
|
97
|
+
return attachments.length > 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function canSubmit(prompt) {
|
|
101
|
+
return !submitting && (prompt.trim() !== "" || hasAttachments());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function submit(endpoint, prompt, streamingBehavior) {
|
|
105
|
+
if (!canSubmit(prompt)) return false;
|
|
106
|
+
const submittedAttachments = [...attachments];
|
|
107
|
+
const submittedPrompt = composePrompt(
|
|
108
|
+
prompt,
|
|
109
|
+
submittedAttachments.map(({ path }) => path),
|
|
110
|
+
);
|
|
111
|
+
const formData = new FormData();
|
|
112
|
+
formData.set("prompt", submittedPrompt);
|
|
113
|
+
if (streamingBehavior) formData.set("streamingBehavior", streamingBehavior);
|
|
114
|
+
for (const { file } of submittedAttachments) {
|
|
115
|
+
if (file?.type.startsWith("image/"))
|
|
116
|
+
formData.append("image", file, file.name || "pasted-image");
|
|
117
|
+
}
|
|
118
|
+
submitting = true;
|
|
119
|
+
try {
|
|
120
|
+
const response = await fetch(endpoint, { method: "POST", body: formData });
|
|
121
|
+
await response.text();
|
|
122
|
+
if (!response.ok)
|
|
123
|
+
throw new Error(`Prompt was not accepted (${response.status}).`);
|
|
124
|
+
removeSubmittedAttachments(submittedAttachments);
|
|
125
|
+
showTransferError("");
|
|
126
|
+
return true;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
restoreSubmittedPrompt(prompt);
|
|
129
|
+
showTransferError(error?.message || "Could not send the prompt.");
|
|
130
|
+
return false;
|
|
131
|
+
} finally {
|
|
132
|
+
submitting = false;
|
|
133
|
+
document
|
|
134
|
+
.getElementById("prompt-box")
|
|
135
|
+
?.dispatchEvent(
|
|
136
|
+
new CustomEvent("pi-ui-prompt-submit-finished", { bubbles: true }),
|
|
137
|
+
);
|
|
138
|
+
renderAttachments();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function extractTransferredFilePaths(data) {
|
|
143
|
+
const references =
|
|
144
|
+
"getData" in data
|
|
145
|
+
? FILE_REFERENCE_TYPES.flatMap((type) => data.getData(type).split(/\r?\n/))
|
|
146
|
+
: [];
|
|
147
|
+
for (const file of transferredFiles(data)) {
|
|
148
|
+
references.push(file.path ?? "", file.webkitRelativePath ?? "");
|
|
149
|
+
}
|
|
150
|
+
return [...new Set(references.map(fileReferenceToPath).filter(Boolean))];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function transferredFiles(data) {
|
|
154
|
+
if (data.files) return [...data.files];
|
|
155
|
+
return Array.from(data);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function isAvifImageFile(file) {
|
|
159
|
+
return file.type?.toLowerCase() === "image/avif" || /\.avif$/i.test(file.name ?? "");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function isHeicImageFile(file) {
|
|
163
|
+
return (
|
|
164
|
+
/^(?:image\/)?hei[cf]$/i.test(file.type ?? "") ||
|
|
165
|
+
/\.hei[cf]$/i.test(file.name ?? "")
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function jpegFileName(name) {
|
|
170
|
+
return /\.avif$/i.test(name)
|
|
171
|
+
? name.replace(/\.avif$/i, ".jpg")
|
|
172
|
+
: `${name || "image"}.jpg`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async function prepareTransferredImages(files) {
|
|
176
|
+
const prepared = [];
|
|
177
|
+
for (const file of files) {
|
|
178
|
+
if (isHeicImageFile(file)) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
"HEIC and HEIF images are not supported. Convert them to JPEG or PNG first.",
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
prepared.push(isAvifImageFile(file) ? await convertAvifToJpeg(file) : file);
|
|
184
|
+
}
|
|
185
|
+
return prepared;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export async function convertAvifToJpeg(file) {
|
|
189
|
+
let bitmap;
|
|
190
|
+
try {
|
|
191
|
+
bitmap = await createImageBitmap(file);
|
|
192
|
+
const canvas = document.createElement("canvas");
|
|
193
|
+
canvas.width = bitmap.width;
|
|
194
|
+
canvas.height = bitmap.height;
|
|
195
|
+
const context = canvas.getContext("2d");
|
|
196
|
+
if (!context) throw new Error("Canvas image conversion is unavailable.");
|
|
197
|
+
context.fillStyle = "white";
|
|
198
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
199
|
+
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
|
|
200
|
+
const blob = await new Promise((resolve, reject) => {
|
|
201
|
+
canvas.toBlob(
|
|
202
|
+
(result) =>
|
|
203
|
+
result ? resolve(result) : reject(new Error("JPEG encoding failed.")),
|
|
204
|
+
"image/jpeg",
|
|
205
|
+
AVIF_JPEG_QUALITY,
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
return new File([blob], jpegFileName(file.name), {
|
|
209
|
+
type: "image/jpeg",
|
|
210
|
+
lastModified: file.lastModified,
|
|
211
|
+
});
|
|
212
|
+
} catch (error) {
|
|
213
|
+
throw new Error(`Could not convert ${file.name || "the AVIF image"} to JPEG.`, {
|
|
214
|
+
cause: error,
|
|
215
|
+
});
|
|
216
|
+
} finally {
|
|
217
|
+
bitmap?.close();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function unsupportedImagePathError(paths) {
|
|
222
|
+
if (paths.some((path) => /\.hei[cf]$/i.test(path))) {
|
|
223
|
+
return "HEIC and HEIF images are not supported. Convert them to JPEG or PNG first.";
|
|
224
|
+
}
|
|
225
|
+
if (paths.some((path) => /\.avif$/i.test(path))) {
|
|
226
|
+
return "AVIF images must be dropped, pasted, or selected with the browser file picker so they can be converted.";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function fileReferenceToPath(value) {
|
|
231
|
+
const reference = value.trim();
|
|
232
|
+
if (
|
|
233
|
+
!reference ||
|
|
234
|
+
reference.startsWith("#") ||
|
|
235
|
+
reference === "copy" ||
|
|
236
|
+
reference === "cut"
|
|
237
|
+
) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
const uriPath = fileUriToPath(reference);
|
|
241
|
+
if (uriPath) return uriPath;
|
|
242
|
+
if (reference.startsWith("/") || /^[A-Za-z]:[\\/]/.test(reference)) return reference;
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function validateTransferredFiles(files) {
|
|
247
|
+
if (files.length > MAX_TRANSFER_FILES) {
|
|
248
|
+
return `Attach at most ${MAX_TRANSFER_FILES} files at a time.`;
|
|
249
|
+
}
|
|
250
|
+
if (files.some((file) => file.size > MAX_TRANSFER_FILE_BYTES)) {
|
|
251
|
+
return "Dropped or pasted files must be 20 MiB or smaller; use the Files button for larger files.";
|
|
252
|
+
}
|
|
253
|
+
const totalBytes = files.reduce((total, file) => total + file.size, 0);
|
|
254
|
+
if (totalBytes > MAX_TRANSFER_TOTAL_BYTES) {
|
|
255
|
+
return "Dropped or pasted files must total 50 MiB or less.";
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function uploadTransferredFiles(files) {
|
|
260
|
+
const formData = new FormData();
|
|
261
|
+
for (const file of files) formData.append("file", file, file.name || "pasted-file");
|
|
262
|
+
try {
|
|
263
|
+
const endpoint = document.body.dataset.filesImportEndpoint;
|
|
264
|
+
const response = await fetch(endpoint, { method: "POST", body: formData });
|
|
265
|
+
const result = await response.json().catch(() => ({}));
|
|
266
|
+
if (!response.ok) {
|
|
267
|
+
showTransferError(
|
|
268
|
+
result.message?.constructor === String
|
|
269
|
+
? result.message
|
|
270
|
+
: "Could not transfer the selected files.",
|
|
271
|
+
);
|
|
272
|
+
return [];
|
|
273
|
+
}
|
|
274
|
+
showTransferError("");
|
|
275
|
+
return Array.isArray(result.paths) ? result.paths : [];
|
|
276
|
+
} catch {
|
|
277
|
+
showTransferError("Could not transfer the selected files.");
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function showTransferError(message) {
|
|
283
|
+
const input = promptInput();
|
|
284
|
+
if (!input) return;
|
|
285
|
+
let error = document.getElementById("file-transfer-error");
|
|
286
|
+
if (!(error instanceof HTMLParagraphElement)) {
|
|
287
|
+
error = document.createElement("p");
|
|
288
|
+
error.id = "file-transfer-error";
|
|
289
|
+
error.className = "text-destructive mb-1 px-1 text-xs";
|
|
290
|
+
error.setAttribute("role", "alert");
|
|
291
|
+
error.setAttribute("aria-live", "polite");
|
|
292
|
+
input.before(error);
|
|
293
|
+
}
|
|
294
|
+
error.textContent = message;
|
|
295
|
+
error.hidden = !message;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function formatFileReferences(paths) {
|
|
299
|
+
return `${paths.map((path) => `@${path}`).join("\n")}\n`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function composePrompt(prompt, paths) {
|
|
303
|
+
const references = formatFileReferences(paths);
|
|
304
|
+
return prompt.trim() ? `${references}${prompt}` : references.trimEnd();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function addPathAttachments(paths) {
|
|
308
|
+
for (const path of paths) addAttachment({ path });
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function addAttachment({ path, file }) {
|
|
312
|
+
if (!path || attachments.some((attachment) => attachment.path === path)) return;
|
|
313
|
+
attachments.push({
|
|
314
|
+
path,
|
|
315
|
+
file,
|
|
316
|
+
previewUrl: file?.type.startsWith("image/")
|
|
317
|
+
? URL.createObjectURL(file)
|
|
318
|
+
: undefined,
|
|
319
|
+
});
|
|
320
|
+
renderAttachments();
|
|
321
|
+
promptInput()?.focus();
|
|
322
|
+
closePickers(true);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function restoreSubmittedPrompt(prompt) {
|
|
326
|
+
const input = promptInput();
|
|
327
|
+
if (!input || input.value !== "" || !prompt) return;
|
|
328
|
+
input.value = prompt;
|
|
329
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function removeSubmittedAttachments(submitted) {
|
|
333
|
+
for (const attachment of submitted) {
|
|
334
|
+
const index = attachments.indexOf(attachment);
|
|
335
|
+
if (index < 0) continue;
|
|
336
|
+
attachments.splice(index, 1);
|
|
337
|
+
if (attachment.previewUrl) URL.revokeObjectURL(attachment.previewUrl);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function removeAttachment(path) {
|
|
342
|
+
const index = attachments.findIndex((attachment) => attachment.path === path);
|
|
343
|
+
if (index < 0) return;
|
|
344
|
+
const [attachment] = attachments.splice(index, 1);
|
|
345
|
+
if (attachment.previewUrl) URL.revokeObjectURL(attachment.previewUrl);
|
|
346
|
+
renderAttachments();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function renderAttachments() {
|
|
350
|
+
const tray = document.getElementById("prompt-attachments");
|
|
351
|
+
if (!(tray instanceof HTMLElement)) return;
|
|
352
|
+
tray.replaceChildren(...attachments.map(renderAttachment));
|
|
353
|
+
tray.hidden = attachments.length === 0;
|
|
354
|
+
const send = document.querySelector("[data-send-trigger]");
|
|
355
|
+
if (send instanceof HTMLButtonElement)
|
|
356
|
+
send.disabled = !canSubmit(promptInput()?.value ?? "");
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function renderAttachment(attachment) {
|
|
360
|
+
const name = attachment.file?.name || displayName(attachment.path);
|
|
361
|
+
if (attachment.previewUrl) {
|
|
362
|
+
const item = document.createElement("button");
|
|
363
|
+
item.type = "button";
|
|
364
|
+
item.className =
|
|
365
|
+
"group relative size-16 shrink-0 cursor-pointer overflow-visible rounded-md border bg-muted/40 p-0 shadow-sm";
|
|
366
|
+
item.setAttribute("aria-label", `Remove ${name}`);
|
|
367
|
+
item.addEventListener("click", () => removeAttachment(attachment.path));
|
|
368
|
+
const preview = document.createElement("span");
|
|
369
|
+
preview.className = "block size-full overflow-clip rounded-md";
|
|
370
|
+
const image = document.createElement("img");
|
|
371
|
+
image.className = "size-full object-cover";
|
|
372
|
+
image.style.overflowClipMargin = "unset";
|
|
373
|
+
image.src = attachment.previewUrl;
|
|
374
|
+
image.alt = name;
|
|
375
|
+
preview.append(image);
|
|
376
|
+
item.append(preview, removeBadge());
|
|
377
|
+
return item;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const item = document.createElement("button");
|
|
381
|
+
item.type = "button";
|
|
382
|
+
item.className =
|
|
383
|
+
"group relative flex h-16 max-w-52 items-center gap-2 overflow-visible rounded-lg border bg-card p-2 pr-3 text-left text-card-foreground shadow-sm";
|
|
384
|
+
item.setAttribute("aria-label", `Remove ${name}`);
|
|
385
|
+
item.addEventListener("click", () => removeAttachment(attachment.path));
|
|
386
|
+
const extension = fileExtension(name);
|
|
387
|
+
const kind = attachmentFileKind(name, attachment.file?.type);
|
|
388
|
+
const icon = document.createElement("span");
|
|
389
|
+
icon.className =
|
|
390
|
+
"flex size-11 shrink-0 flex-col items-center justify-center gap-0.5 rounded-md border bg-muted text-muted-foreground";
|
|
391
|
+
icon.dataset.fileKind = kind;
|
|
392
|
+
icon.append(attachmentFileIcon(kind));
|
|
393
|
+
if (extension) {
|
|
394
|
+
const extensionElement = document.createElement("span");
|
|
395
|
+
extensionElement.className = "font-mono text-[9px] leading-none uppercase";
|
|
396
|
+
extensionElement.textContent = extension;
|
|
397
|
+
icon.append(extensionElement);
|
|
398
|
+
}
|
|
399
|
+
item.append(icon);
|
|
400
|
+
const details = document.createElement("span");
|
|
401
|
+
details.className = "min-w-0";
|
|
402
|
+
const nameElement = document.createElement("span");
|
|
403
|
+
nameElement.className = "block truncate text-xs font-medium";
|
|
404
|
+
nameElement.textContent = name;
|
|
405
|
+
details.append(nameElement);
|
|
406
|
+
const meta = document.createElement("span");
|
|
407
|
+
meta.className = "block truncate text-[10px] text-muted-foreground";
|
|
408
|
+
meta.textContent = attachment.file ? formatBytes(attachment.file.size) : "local file";
|
|
409
|
+
details.append(meta);
|
|
410
|
+
item.append(details, removeBadge());
|
|
411
|
+
return item;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function removeBadge() {
|
|
415
|
+
const badge = document.createElement("span");
|
|
416
|
+
badge.className =
|
|
417
|
+
"absolute -top-1.5 -right-1.5 grid size-5 place-items-center rounded-full border border-primary bg-primary text-xs text-primary-foreground opacity-0 shadow-sm transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100";
|
|
418
|
+
badge.textContent = "×";
|
|
419
|
+
badge.setAttribute("aria-hidden", "true");
|
|
420
|
+
return badge;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function displayName(path) {
|
|
424
|
+
return path.split(/[\\/]/).filter(Boolean).at(-1) || path;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function fileExtension(name) {
|
|
428
|
+
const extension = name.includes(".") ? name.split(".").at(-1) : "";
|
|
429
|
+
return extension.slice(0, 4).toLowerCase();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function attachmentFileIcon(kind) {
|
|
433
|
+
const namespace = "http://www.w3.org/2000/svg";
|
|
434
|
+
const icon = attachmentFileIcons[kind] ?? attachmentFileIcons.file;
|
|
435
|
+
const svg = document.createElementNS(namespace, "svg");
|
|
436
|
+
svg.setAttribute("class", "size-5");
|
|
437
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
438
|
+
svg.setAttribute("fill", "none");
|
|
439
|
+
svg.setAttribute("stroke", "currentColor");
|
|
440
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
441
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
442
|
+
svg.setAttribute("stroke-width", "2");
|
|
443
|
+
svg.setAttribute("aria-hidden", "true");
|
|
444
|
+
for (const data of icon.paths) {
|
|
445
|
+
const path = document.createElementNS(namespace, "path");
|
|
446
|
+
path.setAttribute("d", data);
|
|
447
|
+
svg.append(path);
|
|
448
|
+
}
|
|
449
|
+
if (icon.circle) {
|
|
450
|
+
const circle = document.createElementNS(namespace, "circle");
|
|
451
|
+
for (const [name, value] of Object.entries(icon.circle)) {
|
|
452
|
+
circle.setAttribute(name, String(value));
|
|
453
|
+
}
|
|
454
|
+
svg.append(circle);
|
|
455
|
+
}
|
|
456
|
+
return svg;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function formatBytes(bytes) {
|
|
460
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
461
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
462
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
463
|
+
}
|