WIP: bacon + sample.el file copied from tabby

This commit is contained in:
Tristan D. 2024-10-14 18:31:06 +02:00
parent 1e0ca489fa
commit 58b04b09d1
Signed by: tristan
SSH key fingerprint: SHA256:9oFM1J63hYWJjCnLG6C0fxBS15rwNcWwdQNMOHYKJ/4
4 changed files with 525 additions and 5 deletions

View file

@ -140,6 +140,7 @@
customNodeModules customNodeModules
customRustToolchain customRustToolchain
self.packages.${system}.myllamacpp self.packages.${system}.myllamacpp
bacon
binaryen binaryen
cacert cacert
cargo-bloat cargo-bloat

View file

@ -2,13 +2,42 @@
## Hot reload for dev ## Hot reload for dev
```elisp ```elisp
(module-load "/media/SanDisk/ai/tools/redvault-ai/target/release/deps/libemacs_rs_module-9ad53dadcc38727d.so")
(module-load "~/code/redvault-ai/target/release/deps/libemacs_rs_module-9ad53dadcc38727d.so")
(defun hotreload-el-rs () (defun hotreload-el-rs ()
(interactive) (interactive)
(rs-module/load "/media/SanDisk/ai/tools/redvault-ai/target/debug/libredvault_el_rs.so") (rs-module/load "~/code/redvault-ai/target/debug/libredvault_el_rs.so")
(redvault-el-rs/say-hello "Asd")) (redvault-el-rs/say-hello "Asd"))
``` ```
## Planning
### Interface
#### Notes
- how to trigger
- lisp based idle delay foo
- when to dismiss
- when scrolling, moving cursor
- when triggered via `redvai-complete`
- current-buffer
- current-point
#### Boundry
Rust:
- make requests, gather related files and built repo-level context for qwen model
- push response(s) into overlay
Lisp:
- trigger completions (either kebind or idle-delay)
- dismiss completions (when moving cursor away)
- basic mode

View file

@ -1,4 +1,4 @@
use emacs::{defun, Env, Result, Value}; use emacs::{defun, Env, IntoLisp, Result, Value};
// Emacs won't load the module without this. // Emacs won't load the module without this.
emacs::plugin_is_GPL_compatible!(); emacs::plugin_is_GPL_compatible!();
@ -6,13 +6,31 @@ emacs::plugin_is_GPL_compatible!();
// Register the initialization hook that Emacs will call when it loads the module. // Register the initialization hook that Emacs will call when it loads the module.
#[emacs::module(separator = "/")] #[emacs::module(separator = "/")]
fn init(env: &Env) -> Result<Value<'_>> { fn init(env: &Env) -> Result<Value<'_>> {
env.message("Test loading!"); env.message("Test loading!")?;
env.message("Done loading!") env.message("Done loading!")
} }
// #[defun]
// fn listify_vec(vector: Vector) -> Result<Value> {
// let mut args = vec![];
// for e in vector {
// args.push(e)
// }
// vector.0.env.call("list", &args)
// }
// Define a function callable by Lisp code. // Define a function callable by Lisp code.
#[defun] #[defun]
fn say_hello(env: &Env, name: String) -> Result<Value<'_>> { fn say_hello(env: &Env, name: String) -> Result<Value<'_>> {
env.message(&format!("Helloo Broooooooo, {}!", name)) // env.message(&format!("Helloo Broooooooo, {}!", name))
env.call(
"message",
[format!("Henlo whatup, {}!", name).as_str().into_lisp(env)?],
)
}
#[defun]
fn open_test_overlay(_env: &Env) -> Result<Value<'_>> {
todo!()
} }

View file

@ -0,0 +1,472 @@
;;; redvai.el --- Description -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2024 Tristan Druyen
;;
;; Author: Tristan Druyen <tristand@nixos-fw16>
;; Maintainer: Tristan Druyen <tristand@nixos-fw16>
;; Created: Oktober 09, 2024
;; Modified: Oktober 09, 2024
;; Version: 0.0.1
;; Keywords: abbrev bib c calendar comm convenience data docs emulations extensions faces files frames games hardware help hypermedia i18n internal languages lisp local maint mail matching mouse multimedia news outlines processes terminals tex tools unix vc wp
;; Homepage: https://github.com/tristand/redvai
;; Package-Requires: ((emacs "24.3"))
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;;
;; Description
;;
;;; Code:
;;; redvai.el --- An unofficial redvai plugin for Emacs -*- lexical-binding:t -*-
;; Author: Alan Wong <heywym@qq.com>
;; Version: 0.1.1
;; Package-Requires: ((emacs "27.2") (s "1.12.0"))
;; Keywords: redvai, completion, llm, copilot
;; URL: http://github.com/alan-w-255/redvai.el
;;; License:
;; This file is part of redvai.el.
;;
;; Permission is hereby granted, free of charge, to any person obtaining a copy
;; of this software and associated documentation files (the "Software"), to deal
;; in the Software without restriction, including without limitation the rights
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;; copies of the Software, and to permit persons to whom the Software is
;; furnished to do so, subject to the following conditions:
;; The above copyright notice and this permission notice shall be included in all
;; copies or substantial portions of the Software.
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;; SOFTWARE.
;;; Commentary:
;; This package provides an unofficial redvai plugin for Emacs.
;;; Code:
(require 'json)
(require 'cl-lib)
(require 's)
(defgroup redvai nil
"Redvai."
:group 'completion
:prefix "redvai-")
(defconst redvai-version "1.3.2"
"Redvai version.")
;; custom
(defcustom redvai-log-max 10000
"Max size of events buffer. 0 disables, nil means infinite.
Enabling event logging may slightly affect performance."
:group 'redvai
:type 'integer)
(defcustom redvai-node-executable
(if (eq system-type 'windows-nt)
"node.exe"
"node")
"Node executable path."
:group 'redvai
:type 'string)
(defcustom redvai-clear-overlay-ignore-commands nil
"List of commands that should not clear the overlay when called."
:group 'redvai
:type '(repeat function))
(defcustom redvai-enable-predicates nil
"A list of predicate functions with no argument to enable Redvai.
Redvai will be triggered only if all predicates return t."
:group 'redvai
:type '(repeat function))
(defcustom redvai-disable-predicates nil
"A list of predicate functions with no argument to disable Redvai.
Redvai will not be triggered if any predicate returns t."
:type '(repeat function)
:group 'redvai)
(defcustom redvai-idle-delay 0.2
"Time in seconds to wait before starting completion.
Complete immediately if set to 0.
Disable idle completion if set to nil."
:type '(choice
(number :tag "Seconds of delay")
(const :tag "Idle completion disabled" nil))
:group 'redvai)
(defcustom redvai-enable-display-predicates nil
"A list of predicate functions with no argument to enable Redvai.
Redvai will show completions only if all predicates return t."
:type '(repeat function)
:group 'redvai)
(defcustom redvai-disable-display-predicates nil
"A list of predicate functions with no argument to disable Redvai.
Redvai will not show completions if any predicate returns t."
:type '(repeat function)
:group 'redvai)
(defcustom redvai-major-mode-alist '(("rustic" . "rust")
("cperl" . "perl")
("c++" . "cpp")
("clojurec" . "clojure")
("clojurescript" . "clojure")
("objc" . "objective-c")
("cuda" . "cuda-cpp")
("docker-compose" . "dockercompose")
("coffee" . "coffeescript")
("js" . "javascript")
("js2" . "javascript")
("js2-jsx" . "javascriptreact")
("typescript-tsx" . "typescriptreact")
("rjsx" . "typescriptreact")
("less-css" . "less")
("text" . "plaintext")
("ess-r" . "r")
("enh-ruby" . "ruby")
("shell-script" . "shellscript")
("sh" . "shellscript")
("visual-basic" . "vb")
("nxml" . "xml"))
"Alist mapping major mode names (with -mode removed) to Redvai language ID's."
:type '(alist :key-type string :value-type string)
:group 'redvai)
;; vars
(defconst redvai--base-dir
(file-name-directory
(or load-file-name
(buffer-file-name)))
"Directory containing this file.")
(defvar-local redvai--overlay nil
"Overlay for redvai completion.")
;; (defvar redvai--request-id 0
;; "Request id.")
(defvar redvai-mode-map (make-sparse-keymap)
"Keymap for Redvai minor mode.
Use this for custom bindings in `redvai-mode'.")
(defvar redvai-trigger-mode "auto"
"Trigger mode.")
;; (defvar redvai--current-completion-request nil
;; "Current completion request.")
;; (defvar redvai--current-completion-response nil
;; "Current completion response.")
;; (defvar redvai--ongoing-request-id 0
;; "Ongoing request id.")
(defvar redvai--status "initialization_done")
(defvar redvai--post-command-timer nil
"Timer for redvai completion.")
;; utils
(defun redvai--get-language ()
"Get language of current buffer."
(let ((mode (replace-regexp-in-string "-mode\\'\\|-ts-mode\\'" "" (symbol-name major-mode))))
(alist-get mode redvai-major-mode-alist mode nil 'equal)))
;;; completion
(defun redvai--get-completion-context (is-manual)
"Get completion context."
`(:filepath
,(buffer-file-name)
:language
,(redvai--get-language)
:text
,(buffer-substring-no-properties (point-min) (point-max))
:position
,(1- (point))
:clipboard
,(substring-no-properties (or (car kill-ring) ""))
:manually
,(if is-manual
t
:json-false)))
(defun redvai-complete (&optional is-manual)
"Do completion. IS-MANUAL is non-nil if the completion is triggered manually."
(interactive)
;; (when (called-interactively-p 'any)
;; (setq is-manual t))
;; (when (string= redvai--status "initialization_done")
;; (if (not (zerop redvai--ongoing-request-id))
;; (redvai--agent-cancel-request redvai--ongoing-request-id)
;; (let* ((request (redvai--get-completion-context is-manual))
;; (on-response (lambda (response)
;; (redvai--handle-completion-response request response))))
;; (setq redvai--current-completion-request request)
;; (setq redvai--ongoing-request-id
;; (redvai--agent-provide-completions request on-response)))))
)
(defun redvai--handle-completion-response (request response)
"Handle completion response."
;; (when (eql redvai--ongoing-request-id (car response))
;; (setq redvai--ongoing-request-id 0)
;; (when-let* ((choices (plist-get (cadr response) :choices))
;; (choice (car choices)))
;; (setq redvai--current-completion-response response)
;; (redvai--overlay-show-completion request response)
;; (redvai--agent-post-event
;; `(:type
;; "view"
;; :completion_id
;; ,(plist-get (cadr response) :id)
;; :choice_index
;; ,(plist-get choice :index)))))
())
(message (car (list "asd" "def")))
(defun redvai-dismiss ()
"Dismiss completion."
(interactive)
;; (when redvai--current-completion-request
;; (setq redvai--current-completion-request nil)
;; (redvai--clear-overlay)
;; (when-let* ((response redvai--current-completion-response)
;; (completion-id (cadr response))
;; (choices (plist-get (cadr response) :choices))
;; (choice (car choices)))
;; (setq redvai--current-completion-response nil)
;; (redvai--agent-post-event
;; `(:type
;; "dismiss"
;; :completion_id
;; ,completion-id
;; :choice_index
;; ,(plist-get choice :index)))))
)
(defmacro redvai--satisfy-predicates (enable disable)
"Return t if satisfy all predicates in ENABLE and none in DISABLE."
`(and (cl-every (lambda (pred)
(if (functionp pred) (funcall pred) t))
,enable)
(cl-notany (lambda (pred)
(if (functionp pred) (funcall pred) nil))
,disable)))
(defun redvai--satisfy-trigger-predicates ()
(redvai--satisfy-predicates redvai-enable-predicates redvai-disable-predicates))
;;; ui
(defface redvai-overlay-face
'((t :inherit shadow))
"Face for redvai overlay")
(defun redvai--overlay-visible ()
"Return t if the overlay is visible."
(and (overlayp redvai--overlay)
(overlay-buffer redvai--overlay)))
(defun redvai-current-completion ()
"Get current completion."
(and (redvai--overlay-visible)
(overlay-get redvai--overlay 'completion)))
(defconst redvai-completion-map (make-sparse-keymap)
"Keymap for Redvai completion overlay.")
(defun redvai--get-overlay ()
"Create or get overlay for redvai."
(unless (overlayp redvai--overlay)
(setq redvai--overlay (make-overlay 1 1 nil nil t))
(overlay-put redvai--overlay 'keymap redvai-completion-map))
redvai--overlay)
(defun redvai--clear-overlay ()
"Clear overlay."
(interactive)
(when (redvai--overlay-visible)
(delete-overlay redvai--overlay)))
(defun redvai--self-insert (command)
"Handle the case where the char just inserted is the start of the completion.
If so, update the overlays and continue. COMMAND is the
command that triggered `post-command-hook'."
(when (and (eq command 'self-insert-command)
(redvai--overlay-visible)
(redvai--satisfy-display-predicates))
(let* ((ov redvai--overlay)
(completion (overlay-get ov 'completion)))
;; The char just inserted is the next char of completion
(when (eq last-command-event (elt completion 0))
(if (= (length completion) 1)
;; If there is only one char in the completion, accept it
(progn
(overlay-put ov 'completion "")
(redvai-accept-completion))
(redvai--set-overlay-text ov (substring completion 1)))))))
(defun redvai--set-overlay-text (ov completion)
"Set overlay OV with COMPLETION."
(save-restriction
(widen)
(let* ((suffix-replace-chars (overlay-get ov 'suffix-replace-chars))
(p-completion (propertize completion 'face 'redvai-overlay-face)))
(add-text-properties 0 1 '(cursor 1) p-completion)
(overlay-put ov 'after-string p-completion)
(overlay-put ov 'display (char-to-string ?\u200B)) ;; \u200B is a zero-width space. Trick to fix the wrong character inserted position.
(move-overlay ov (point) (+ (point) suffix-replace-chars))
(overlay-put ov 'completion completion))))
;; (defun redvai--overlay-show-completion (request response)
;; "Render overlay."
;; (redvai--clear-overlay)
;; (when-let* ((choices (plist-get (cadr response) :choices))
;; (choice (car choices))
;; (choice-text (plist-get choice :text))
;; ((not (zerop (length choice-text))))
;; (replace-range (plist-get choice :replaceRange))
;; (start (plist-get replace-range :start))
;; (end (plist-get replace-range :end))
;; (pos (plist-get request :position))
;; (prefix-replace-chars (- pos start))
;; (suffix-replace-chars (- end pos))
;; (text (substring choice-text prefix-replace-chars))
;; ((not (zerop (length text))))
;; (ov (redvai--get-overlay)))
;; (when (= (point) (1+ pos))
;; (overlay-put ov 'replace-end (1+ end))
;; (overlay-put ov 'suffix-replace-chars suffix-replace-chars)
;; (overlay-put ov 'completion-id (plist-get (cadr response) :id))
;; (overlay-put ov 'choice-index (plist-get choice :index))
;; (redvai--set-overlay-text ov text))))
(defun redvai-accept-completion (&optional transform-fn)
"Accept completion. Return t if there is a completion.
Use TRANSFORM-FN to transform completion if provided."
(interactive)
(when (redvai--overlay-visible)
(let* ((completion (overlay-get redvai--overlay 'completion))
(_replace-end (overlay-get redvai--overlay 'replace-end))
(suffix-replace-chars (overlay-get redvai--overlay 'suffix-replace-chars))
(completion-id (overlay-get redvai--overlay 'completion-id))
(choice-index (overlay-get redvai--overlay 'choice-index))
(t-completion (funcall (or transform-fn 'identity) completion)))
(redvai--agent-post-event
`(:type
"select"
:completion_id
,completion-id
:choice_index
,choice-index))
(redvai--clear-overlay)
(delete-region (point) (+ (point) suffix-replace-chars))
(insert t-completion)
;; if it is a partial completion
(when (and (s-prefix-p t-completion completion)
(not (s-equals-p t-completion completion)))
(let ((ov (redvai--get-overlay))
(suffix-len (if (< (+ (length t-completion) suffix-replace-chars) (length completion))
suffix-replace-chars
(- (length completion) (length t-completion)))))
(when (< suffix-len 0)
(setq suffix-len 0))
(overlay-put ov 'suffix-replace-chars suffix-len)
(redvai--set-overlay-text ov (s-chop-prefix t-completion completion))))
t)))
(defmacro redvai--define-accept-completion-by-action (func-name action)
"Define function FUNC-NAME to accept completion by ACTION."
`(defun ,func-name (&optional n)
(interactive "p")
(setq n (or n 1))
(redvai-accept-completion (lambda (completion)
(with-temp-buffer
(insert completion)
(goto-char (point-min))
(funcall ,action n)
(buffer-substring-no-properties (point-min) (point)))))))
(redvai--define-accept-completion-by-action redvai-accept-completion-by-word #'forward-word)
(redvai--define-accept-completion-by-action redvai-accept-completion-by-line #'forward-line)
;;; redvai-mode
(defun redvai--mode-enter ()
"Set up redvai mode when entering."
(add-hook 'post-command-hook 'redvai--post-command nil 'local))
(defun redvai--mode-exit ()
"Clean up redvai mode when exiting."
(remove-hook 'post-command-hook #'redvai--post-command 'local))
(defun redvai--satisfy-display-predicates ()
"Return t if all display predicates are satisfied."
(redvai--satisfy-predicates redvai-enable-display-predicates redvai-disable-display-predicates))
(defun redvai-turn-on-unless-buffer-read-only ()
"Turn on `redvai-mode' if the buffer is writable."
(unless buffer-read-only
(redvai-mode 1)))
(defun redvai--post-command-debounce (buffer)
"Complete in BUFFER."
(when (and (buffer-live-p buffer)
(equal (current-buffer) buffer)
redvai-mode
(redvai--satisfy-trigger-predicates))
(redvai-complete)))
(defun redvai--post-command ()
"Complete in `post-command-hook' hook."
(when (and this-command
(not (and (symbolp this-command)
(or
(s-starts-with-p "redvai-" (symbol-name this-command))
(member this-command redvai-clear-overlay-ignore-commands)
(redvai--self-insert this-command)))))
(redvai-dismiss)
(when redvai--post-command-timer
(cancel-timer redvai--post-command-timer))
(setq redvai--post-command-timer
(run-with-idle-timer redvai-idle-delay
nil
'redvai--post-command-debounce
(current-buffer)))))
(advice-add 'keyboard-quit :after #'redvai-dismiss)
;;;###autoload
(define-minor-mode redvai-mode
"Minor mode for Redvai."
:init-value nil
:lighter " Redvai"
(redvai-dismiss)
(if redvai-mode
(redvai--mode-enter)
(redvai--mode-exit)))
(provide 'redvai)
;;; redvai.el ends here