From 094abf53a12486f3ca7aaae13566f7c15f123eee Mon Sep 17 00:00:00 2001 From: Bram Schoenmakers Date: Thu, 21 Dec 2023 22:23:22 +0100 Subject: [PATCH] Initial commit - kagi.el provides FastGPT access from within Emacs --- LICENSE.txt | 21 +++++++++++ kagi.el | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 LICENSE.txt create mode 100644 kagi.el diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..e6fd046 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Bram Schoenmakers + +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. diff --git a/kagi.el b/kagi.el new file mode 100644 index 0000000..c962dd6 --- /dev/null +++ b/kagi.el @@ -0,0 +1,107 @@ +;;; kagi.el --- Kagi API integration with Emacs -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Bram Schoenmakers + +;; Author: Bram Schoenmakers +;; Maintainer: Bram Schoenmakers +;; Created: 16 Dec 2023 +;; Package-Version: 0.1 +;; Package-Requires: ((emacs "28.2") "shell-maker") ; TODO +;; Keywords: convenience +;; URL: TODO + +;; This file is not part of GNU Emacs. + +;; MIT License + +;; Copyright (c) 2023 Bram Schoenmakers + +;; 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: + +;; TODO + +;; API documentation: https://help.kagi.com/kagi/api/fastgpt.html + +;;; Code: + +(require 'shell-maker) + +(defcustom kagi-api-token nil + "The Kagi API token. + +The token can be generated inside your account at https://kagi.com/settings?p=api") + +(defvar kagi-api-fastgpt-url " https://kagi.com/api/v0/fastgpt" + "The Kagi FastGPT API entry point.") + +(defcustom kagi-debug t + "Enable debugging statements.") ;; TODO nil + +(defun kagi--build-curl-command (prompt) + (let* ((input-obj `((query . ,prompt))) + (data (json-encode input-obj)) + (token (cond ((functionp kagi-api-token) (funcall kagi-api-token)) + ((stringp kagi-api-token) kagi-api-token) + (t (error "No API token configured in variable kagi-api-token")))) + (curl-flags `("--silent" + ,(format "--header \"Authorization: Bot %s\"" token) + "--header \"Content-Type: application/json\"" + ,(format "--data '%s'" data)))) + (format "curl %s %s" + (string-join curl-flags " ") + kagi-api-fastgpt-url))) + +(defun kagi--format-references (references) + (string-join (seq-map-indexed (lambda (ref i) + (let ((title (gethash "title" ref)) + (snippet (gethash "snippet" ref)) + (url (gethash "url" ref))) + (format "[%d] %s\n%s\n%s" (1+ i) title snippet url))) + references) + "\n\n")) + +(defun kagi--call-fastgpt (prompt) + (let ((command (kagi--build-curl-command prompt))) + (shell-command-to-string command))) + +(defun kagi--process-prompt (prompt) + (let* ((response (kagi--call-fastgpt prompt)) + (parsed-response (json-parse-string response)) + (data (gethash "data" parsed-response)) + (output (gethash "output" data)) + (references (gethash "references" data))) + (format "%s\n\n%s" output (kagi--format-references references)))) + +(defvar kagi-fastgpt--config + (make-shell-maker-config + :name "FastGPT" + :prompt "fastgpt > " + :execute-command (lambda (command _history callback error-callback) + (funcall callback (kagi--process-prompt command) nil))) + "The FastGPT shell configuration for shell-maker.") + +(defun kagi-fastgpt-shell () + (interactive) + (shell-maker-start kagi-fastgpt--config)) + +(provide 'kagi) + +;;; kagi.el ends here