mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-08 05:39:13 +00:00
Create, use reusable function to call Khoj API from elisp
This commit is contained in:
@@ -629,38 +629,67 @@ Use `BOUNDARY' to separate files. This is sent to Khoj server as a POST request.
|
|||||||
;; --------------
|
;; --------------
|
||||||
;; Query Khoj API
|
;; Query Khoj API
|
||||||
;; --------------
|
;; --------------
|
||||||
|
(defun khoj--call-api (path &optional method params callback &rest cbargs)
|
||||||
|
"Sync call API at PATH with METHOD and query PARAMS as kv assoc list.
|
||||||
|
Return json parsed response as alist."
|
||||||
|
(let* ((url-request-method (or method "GET"))
|
||||||
|
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key))))
|
||||||
|
(param-string (if params (url-build-query-string params) ""))
|
||||||
|
(query-url (format "%s%s?%s&client=emacs" khoj-server-url path param-string))
|
||||||
|
(cbargs (if (and (listp cbargs) (listp (car cbargs))) (car cbargs) cbargs))) ; normalize cbargs to (a b) from ((a b)) if required
|
||||||
|
(with-temp-buffer
|
||||||
|
(condition-case ex
|
||||||
|
(progn
|
||||||
|
(url-insert-file-contents query-url)
|
||||||
|
(if (and callback cbargs)
|
||||||
|
(apply callback (json-parse-buffer :object-type 'alist) cbargs)
|
||||||
|
(if callback
|
||||||
|
(funcall callback (json-parse-buffer :object-type 'alist))
|
||||||
|
(json-parse-buffer :object-type 'alist))))
|
||||||
|
('file-error (message "Chat exception: [%s]" ex))))))
|
||||||
|
|
||||||
|
(defun khoj--call-api-async (path &optional method params callback &rest cbargs)
|
||||||
|
"Async call to API at PATH with METHOD and query PARAMS as kv assoc list.
|
||||||
|
Return json parsed response as alist."
|
||||||
|
(let* ((url-request-method (or method "GET"))
|
||||||
|
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key))))
|
||||||
|
(param-string (if params (url-build-query-string params) ""))
|
||||||
|
(cbargs (if (and (listp cbargs) (listp (car cbargs))) (car cbargs) cbargs)) ; normalize cbargs to (a b) from ((a b)) if required
|
||||||
|
(query-url (format "%s%s?%s&client=emacs" khoj-server-url path param-string)))
|
||||||
|
(url-retrieve query-url
|
||||||
|
(lambda (status)
|
||||||
|
(if (plist-get status :error)
|
||||||
|
(message "Chat exception: [%s]" (plist-get status :error))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(re-search-forward "^$")
|
||||||
|
(delete-region (point) (point-min))
|
||||||
|
(if (and callback cbargs)
|
||||||
|
(apply callback (json-parse-buffer :object-type 'alist) cbargs)
|
||||||
|
(if callback
|
||||||
|
(funcall callback (json-parse-buffer :object-type 'alist))
|
||||||
|
(json-parse-buffer :object-type 'alist))))))))
|
||||||
|
|
||||||
(defun khoj--get-enabled-content-types ()
|
(defun khoj--get-enabled-content-types ()
|
||||||
"Get content types enabled for search from API."
|
"Get content types enabled for search from API."
|
||||||
(let ((config-url (format "%s/api/config/types" khoj-server-url))
|
(khoj--call-api "/api/config/types" "GET" nil `(lambda (item) (mapcar #'intern item))))
|
||||||
(url-request-method "GET")
|
|
||||||
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key)))))
|
|
||||||
(with-temp-buffer
|
|
||||||
(url-insert-file-contents config-url)
|
|
||||||
(thread-last
|
|
||||||
(json-parse-buffer :object-type 'alist)
|
|
||||||
(mapcar #'intern)))))
|
|
||||||
|
|
||||||
(defun khoj--construct-search-api-query (query content-type &optional rerank)
|
(defun khoj--query-search-api-and-render-results (query content-type buffer-name &optional rerank title)
|
||||||
"Construct Search API Query.
|
"Query Khoj Search API with QUERY, CONTENT-TYPE and (optional) RERANK as query params
|
||||||
Use QUERY, CONTENT-TYPE and (optional) RERANK as query params"
|
Render results in BUFFER-NAME using search results, CONTENT-TYPE and (optional) TITLE."
|
||||||
(let ((rerank (or rerank "false"))
|
(let ((title (or title query))
|
||||||
(encoded-query (url-hexify-string query)))
|
(rerank (or rerank "false"))
|
||||||
(format "%s/api/search?q=%s&t=%s&r=%s&n=%s&client=emacs" khoj-server-url encoded-query content-type rerank khoj-results-count)))
|
(params `((q ,query) (t ,content-type) (r ,rerank) (n ,khoj-results-count)))
|
||||||
|
(path "/api/search"))
|
||||||
|
(khoj--call-api path
|
||||||
|
"GET"
|
||||||
|
params
|
||||||
|
'khoj--render-search-results
|
||||||
|
content-type title buffer-name)))
|
||||||
|
|
||||||
(defun khoj--query-search-api-and-render-results (query-url content-type query buffer-name)
|
(defun khoj--render-search-results (json-response content-type query buffer-name)
|
||||||
"Query Khoj Search with QUERY-URL.
|
|
||||||
Render results in BUFFER-NAME using QUERY, CONTENT-TYPE."
|
|
||||||
;; get json response from api
|
|
||||||
(with-current-buffer buffer-name
|
|
||||||
(let ((inhibit-read-only t)
|
|
||||||
(url-request-method "GET")
|
|
||||||
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key)))))
|
|
||||||
(erase-buffer)
|
|
||||||
(url-insert-file-contents query-url)))
|
|
||||||
;; render json response into formatted entries
|
;; render json response into formatted entries
|
||||||
(with-current-buffer buffer-name
|
(with-current-buffer buffer-name
|
||||||
(let ((inhibit-read-only t)
|
(let ((inhibit-read-only t))
|
||||||
(json-response (json-parse-buffer :object-type 'alist)))
|
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert
|
(insert
|
||||||
(cond ((equal content-type "org") (khoj--extract-entries-as-org json-response query))
|
(cond ((equal content-type "org") (khoj--extract-entries-as-org json-response query))
|
||||||
@@ -673,15 +702,15 @@ Render results in BUFFER-NAME using QUERY, CONTENT-TYPE."
|
|||||||
(equal content-type "org"))
|
(equal content-type "org"))
|
||||||
(progn (visual-line-mode)
|
(progn (visual-line-mode)
|
||||||
(org-mode)
|
(org-mode)
|
||||||
(setq-local
|
(setq-local
|
||||||
org-startup-folded "showall"
|
org-startup-folded "showall"
|
||||||
org-hide-leading-stars t
|
org-hide-leading-stars t
|
||||||
org-startup-with-inline-images t)
|
org-startup-with-inline-images t)
|
||||||
(org-set-startup-visibility)))
|
(org-set-startup-visibility)))
|
||||||
((equal content-type "markdown") (progn (markdown-mode)
|
((equal content-type "markdown") (progn (markdown-mode)
|
||||||
(visual-line-mode)))
|
(visual-line-mode)))
|
||||||
((equal content-type "image") (progn (shr-render-region (point-min) (point-max))
|
((equal content-type "image") (progn (shr-render-region (point-min) (point-max))
|
||||||
(goto-char (point-min))))
|
(goto-char (point-min))))
|
||||||
(t (fundamental-mode))))
|
(t (fundamental-mode))))
|
||||||
;; keep cursor at top of khoj buffer by default
|
;; keep cursor at top of khoj buffer by default
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
@@ -795,50 +824,23 @@ Render results in BUFFER-NAME using QUERY, CONTENT-TYPE."
|
|||||||
#'khoj--format-chat-response
|
#'khoj--format-chat-response
|
||||||
#'khoj--render-chat-response buffer-name))))
|
#'khoj--render-chat-response buffer-name))))
|
||||||
|
|
||||||
(defun khoj--get-chat-sessions ()
|
|
||||||
"Get all chat sessions from Khoj server."
|
|
||||||
(let* ((url-request-method "GET")
|
|
||||||
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key))))
|
|
||||||
(query-url (format "%s/api/chat/sessions?client=emacs" khoj-server-url)))
|
|
||||||
(with-temp-buffer
|
|
||||||
(condition-case ex
|
|
||||||
(progn
|
|
||||||
(url-insert-file-contents query-url)
|
|
||||||
(json-parse-buffer :object-type 'alist))
|
|
||||||
('file-error (message "Chat exception: [%s]" ex))))))
|
|
||||||
|
|
||||||
|
|
||||||
(defun khoj--query-chat-api (query callback &rest cbargs)
|
(defun khoj--query-chat-api (query callback &rest cbargs)
|
||||||
"Send QUERY to Khoj Chat API and call CALLBACK with the response.
|
"Send QUERY to Khoj Chat API and call CALLBACK with the response.
|
||||||
CBARGS are optional additional arguments to pass to CALLBACK."
|
CBARGS are optional additional arguments to pass to CALLBACK."
|
||||||
(let* ((url-request-method "GET")
|
(khoj--call-api-async "/api/chat"
|
||||||
(encoded-query (url-hexify-string query))
|
"GET"
|
||||||
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key))))
|
`(("q" ,query) ("n" ,khoj-results-count))
|
||||||
(query-url (format "%s/api/chat?q=%s&n=%s&client=emacs" khoj-server-url encoded-query khoj-results-count)))
|
callback cbargs))
|
||||||
(url-retrieve query-url
|
|
||||||
(lambda (status)
|
|
||||||
(if (plist-get status :error)
|
|
||||||
(message "Chat exception: [%s]" (plist-get status :error))
|
|
||||||
(goto-char (point-min))
|
|
||||||
(re-search-forward "^$")
|
|
||||||
(delete-region (point) (point-min))
|
|
||||||
(apply callback (json-parse-buffer :object-type 'alist) cbargs))))))
|
|
||||||
|
|
||||||
|
(defun khoj--get-chat-sessions ()
|
||||||
|
"Get all chat sessions from Khoj server."
|
||||||
|
(khoj--call-api "/api/chat/sessions" "GET"))
|
||||||
|
|
||||||
(defun khoj--get-chat-session (&optional session-id)
|
(defun khoj--get-chat-session (&optional session-id)
|
||||||
"Get chat messages from default or SESSION-ID chat session."
|
"Get chat messages from default or SESSION-ID chat session."
|
||||||
(let* ((url-request-method "GET")
|
(khoj--call-api "/api/chat/history"
|
||||||
(url-request-extra-headers `(("Authorization" . ,(format "Bearer %s" khoj-api-key))))
|
"GET"
|
||||||
(session-id-query-param (if session-id (format "&conversation_id=%s" session-id) ""))
|
(when session-id `(("conversation_id" ,session-id)))))
|
||||||
(query-url (format "%s/api/chat/history?client=emacs%s" khoj-server-url session-id-query-param)))
|
|
||||||
(with-temp-buffer
|
|
||||||
(condition-case ex
|
|
||||||
(progn
|
|
||||||
(url-insert-file-contents query-url)
|
|
||||||
(json-parse-buffer :object-type 'alist))
|
|
||||||
('file-error (cond ((string-match "Internal server error" (nth 2 ex))
|
|
||||||
(message "Chat processor not configured. Configure OpenAI API key and restart it. Exception: [%s]" ex))
|
|
||||||
(t (message "Chat exception: [%s]" ex))))))))
|
|
||||||
|
|
||||||
(defun khoj--open-conversation-session ()
|
(defun khoj--open-conversation-session ()
|
||||||
"Menu to select Khoj conversation session to open."
|
"Menu to select Khoj conversation session to open."
|
||||||
@@ -977,8 +979,7 @@ RECEIVE-DATE is the message receive date."
|
|||||||
"Perform Incremental Search on Khoj. Allow optional RERANK of results."
|
"Perform Incremental Search on Khoj. Allow optional RERANK of results."
|
||||||
(let* ((rerank-str (cond (rerank "true") (t "false")))
|
(let* ((rerank-str (cond (rerank "true") (t "false")))
|
||||||
(khoj-buffer-name (get-buffer-create khoj--search-buffer-name))
|
(khoj-buffer-name (get-buffer-create khoj--search-buffer-name))
|
||||||
(query (minibuffer-contents-no-properties))
|
(query (minibuffer-contents-no-properties)))
|
||||||
(query-url (khoj--construct-search-api-query query khoj--content-type rerank-str)))
|
|
||||||
;; Query khoj API only when user in khoj minibuffer and non-empty query
|
;; Query khoj API only when user in khoj minibuffer and non-empty query
|
||||||
;; Prevents querying if
|
;; Prevents querying if
|
||||||
;; 1. user hasn't started typing query
|
;; 1. user hasn't started typing query
|
||||||
@@ -998,10 +999,10 @@ RECEIVE-DATE is the message receive date."
|
|||||||
(setq khoj--rerank t)
|
(setq khoj--rerank t)
|
||||||
(message "khoj.el: Rerank Results"))
|
(message "khoj.el: Rerank Results"))
|
||||||
(khoj--query-search-api-and-render-results
|
(khoj--query-search-api-and-render-results
|
||||||
query-url
|
|
||||||
khoj--content-type
|
|
||||||
query
|
query
|
||||||
khoj-buffer-name))))))
|
khoj--content-type
|
||||||
|
khoj-buffer-name
|
||||||
|
rerank-str))))))
|
||||||
|
|
||||||
(defun khoj--delete-open-network-connections-to-server ()
|
(defun khoj--delete-open-network-connections-to-server ()
|
||||||
"Delete all network connections to khoj server."
|
"Delete all network connections to khoj server."
|
||||||
@@ -1095,7 +1096,6 @@ Paragraph only starts at first text after blank line."
|
|||||||
;; get paragraph, if in text mode
|
;; get paragraph, if in text mode
|
||||||
(t
|
(t
|
||||||
(khoj--get-current-paragraph-text))))
|
(khoj--get-current-paragraph-text))))
|
||||||
(query-url (khoj--construct-search-api-query query content-type rerank))
|
|
||||||
;; extract heading to show in result buffer from query
|
;; extract heading to show in result buffer from query
|
||||||
(query-title
|
(query-title
|
||||||
(format "Similar to: %s"
|
(format "Similar to: %s"
|
||||||
@@ -1103,10 +1103,11 @@ Paragraph only starts at first text after blank line."
|
|||||||
(buffer-name (get-buffer-create khoj--search-buffer-name)))
|
(buffer-name (get-buffer-create khoj--search-buffer-name)))
|
||||||
(progn
|
(progn
|
||||||
(khoj--query-search-api-and-render-results
|
(khoj--query-search-api-and-render-results
|
||||||
query-url
|
query
|
||||||
content-type
|
content-type
|
||||||
query-title
|
buffer-name
|
||||||
buffer-name)
|
rerank
|
||||||
|
query-title)
|
||||||
(khoj--open-side-pane buffer-name)
|
(khoj--open-side-pane buffer-name)
|
||||||
(goto-char (point-min)))))
|
(goto-char (point-min)))))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user