mirror of
https://github.com/Myzel394/zsh-copilot.git
synced 2025-06-18 04:35:26 +02:00
Merge pull request #10 from Myzel394/add-oh-my-zsh-support
This commit is contained in:
commit
bcea2d2033
28
README.md
28
README.md
@ -1,5 +1,6 @@
|
||||
# zsh-copilot
|
||||
**NOTICE**: I'm slowly migrating my repositories to my own Git server. Please visit this repository at [https://git.myzel394.app/Myzel394/zsh-copilot](https://git.myzel394.app/Myzel394/zsh-copilot) for the latest updates.
|
||||
|
||||
# zsh-copilot
|
||||
|
||||
Get suggestions **truly** in your shell. No `suggest` bullshit. Just press `CTRL + Z` and get your suggestion.
|
||||
|
||||
@ -15,12 +16,31 @@ Please make sure you have the following dependencies installed:
|
||||
* [jq](https://github.com/jqlang/jq)
|
||||
* [curl](https://github.com/curl/curl)
|
||||
|
||||
### Oh My Zsh
|
||||
|
||||
1. Clone `zsh-copilot` into `$ZSH_CUSTOM/plugins` (by default ~/.config/oh-my-zsh/custom/plugins)
|
||||
|
||||
```sh
|
||||
git clone https://github.com/Myzel394/zsh-copilot.git ~/.zsh-copilot
|
||||
echo "source ~/.zsh-copilot/zsh-copilot.plugin.zsh" >> ~/.zshrc
|
||||
git clone https://git.myzel394.app/Myzel394/zsh-copilot ${ZSH_CUSTOM:-~/.config/oh-my-zsh/custom}/plugins/zsh-copilot
|
||||
```
|
||||
|
||||
### Configuration
|
||||
2. Add `zsh-copilot` to the plugins array in your `.zshrc` file:
|
||||
|
||||
```bash
|
||||
plugins=(
|
||||
# your other plugins...
|
||||
zsh-autosuggestions
|
||||
)
|
||||
```
|
||||
|
||||
### Manual Installation
|
||||
|
||||
```sh
|
||||
git clone https://git.myzel394.app/Myzel394/zsh-copilot ~/.config/zsh-copilot
|
||||
echo "source ~/.config/zsh-copilot/zsh-copilot.plugin.zsh" >> ~/.zshrc
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
You need to have an API key for either OpenAI or Anthropic to use this plugin. Expose this via the appropriate environment variable:
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Default key binding
|
||||
(( ! ${+ZSH_COPILOT_KEY} )) &&
|
||||
typeset -g ZSH_COPILOT_KEY='^z'
|
||||
@ -10,63 +12,82 @@
|
||||
typeset -g ZSH_COPILOT_DEBUG=false
|
||||
|
||||
# New option to select AI provider
|
||||
(( ! ${+ZSH_COPILOT_AI_PROVIDER} )) &&
|
||||
typeset -g ZSH_COPILOT_AI_PROVIDER="openai"
|
||||
if [[ -z "$ZSH_COPILOT_AI_PROVIDER" ]]; then
|
||||
if [[ -n "$OPENAI_API_KEY" ]]; then
|
||||
typeset -g ZSH_COPILOT_AI_PROVIDER="openai"
|
||||
elif [[ -n "$ANTHROPIC_API_KEY" ]]; then
|
||||
typeset -g ZSH_COPILOT_AI_PROVIDER="anthropic"
|
||||
else
|
||||
echo "No AI provider selected. Please set either OPENAI_API_KEY or ANTHROPIC_API_KEY."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# System prompt
|
||||
read -r -d '' SYSTEM_PROMPT <<- EOM
|
||||
if [[ -z "$ZSH_COPILOT_SYSTEM_PROMPT" ]]; then
|
||||
read -r -d '' ZSH_COPILOT_SYSTEM_PROMPT <<- EOM
|
||||
You will be given the raw input of a shell command.
|
||||
Your task is to either complete the command or provide a new command that you think the user is trying to type.
|
||||
If you return a completely new command for the user, prefix is with an equal sign (=).
|
||||
If you return a completion for the user's command, prefix it with a plus sign (+).
|
||||
MAKE SURE TO ONLY INCLUDE THE REST OF THE COMPLETION!!!
|
||||
Do not write any leading or trailing characters except if required for the completion to work.
|
||||
|
||||
Only respond with either a completion or a new command, not both.
|
||||
Your response may only start with either a plus sign or an equal sign.
|
||||
Your response MAY NOT start with both! This means that your response IS NOT ALLOWED to start with '+=' or '=+'.
|
||||
You MAY explain the command by writing a short line after the comment symbol (#).
|
||||
|
||||
Your response MAY NOT contain any newlines!
|
||||
Do NOT add any additional text, comments, or explanations to your response.
|
||||
Do not ask for more information, you won't receive it.
|
||||
|
||||
Your response will be run in the user's shell.
|
||||
Make sure input is escaped correctly if needed so.
|
||||
Your input should be able to run without any modifications to it.
|
||||
Don't you dare to return anything else other than a shell command!!!
|
||||
DO NOT INTERACT WITH THE USER IN NATURAL LANGUAGE! If you do, you will be banned from the system.
|
||||
Note that the double quote sign is escaped. Keep this in mind when you create quotes.
|
||||
Here are two examples:
|
||||
* User input: 'list files in current directory'; Your response: '=ls' (ls is the builtin command for listing files)
|
||||
* User input: 'cd /tm'; Your response: '+p' (/tmp is the standard temp folder on linux and mac).
|
||||
EOM
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
SYSTEM="Your system is ${$(sw_vers | xargs | sed 's/ /./g')}."
|
||||
else
|
||||
SYSTEM="Your system is ${$(cat /etc/*-release | xargs | sed 's/ /,/g')}."
|
||||
fi
|
||||
|
||||
function _suggest_ai() {
|
||||
local OPENAI_API_URL=${OPENAI_API_URL:-"api.openai.com"}
|
||||
local ANTHROPIC_API_URL=${ANTHROPIC_API_URL:-"api.anthropic.com"}
|
||||
#### Prepare environment
|
||||
local openai_api_url=${OPENAI_API_URL:-"api.openai.com"}
|
||||
local anthropic_api_url=${ANTHROPIC_API_URL:-"api.anthropic.com"}
|
||||
|
||||
local context_info=""
|
||||
if [[ "$ZSH_COPILOT_SEND_CONTEXT" == 'true' ]]; then
|
||||
local system
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
system="Your system is ${$(sw_vers | xargs | sed 's/ /./g')}."
|
||||
else
|
||||
system="Your system is ${$(cat /etc/*-release | xargs | sed 's/ /,/g')}."
|
||||
fi
|
||||
|
||||
context_info="Context: You are user $(whoami) with id $(id) in directory $(pwd).
|
||||
Your shell is $(echo $SHELL) and your terminal is $(echo $TERM) running on $(uname -a).
|
||||
$SYSTEM"
|
||||
$system"
|
||||
fi
|
||||
|
||||
# Get input
|
||||
##### Get input
|
||||
local input=$(echo "${BUFFER:0:$CURSOR}" | tr '\n' ';')
|
||||
input=$(echo "$input" | sed 's/"/\\"/g')
|
||||
|
||||
_zsh_autosuggest_clear
|
||||
zle -R "Thinking..."
|
||||
|
||||
local full_prompt=$(echo "$SYSTEM_PROMPT $context_info" | tr -d '\n')
|
||||
local full_prompt=$(echo "$ZSH_COPILOT_SYSTEM_PROMPT $context_info" | tr -d '\n')
|
||||
|
||||
##### Fetch message
|
||||
local data
|
||||
local response
|
||||
local message
|
||||
|
||||
if [[ "$ZSH_COPILOT_AI_PROVIDER" == "openai" ]]; then
|
||||
# OpenAI's API payload
|
||||
data="{
|
||||
\"model\": \"gpt-4o-mini\",
|
||||
\"messages\": [
|
||||
@ -80,15 +101,17 @@ function _suggest_ai() {
|
||||
}
|
||||
]
|
||||
}"
|
||||
response=$(curl "https://${OPENAI_API_URL}/v1/chat/completions" \
|
||||
response=$(curl "https://${openai_api_url}/v1/chat/completions" \
|
||||
--silent \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||
-d "$data")
|
||||
local message=$(echo "$response" | jq -r '.choices[0].message.content')
|
||||
|
||||
message=$(echo "$response" | tr -d '\n' | jq -r '.choices[0].message.content')
|
||||
elif [[ "$ZSH_COPILOT_AI_PROVIDER" == "anthropic" ]]; then
|
||||
# Anthropic's API payload
|
||||
data="{
|
||||
\"model\": \"claude-3-5-sonnet-20240620\",
|
||||
\"model\": \"claude-3-5-sonnet-latest\",
|
||||
\"max_tokens\": 1000,
|
||||
\"system\": \"$full_prompt\",
|
||||
\"messages\": [
|
||||
@ -98,18 +121,21 @@ function _suggest_ai() {
|
||||
}
|
||||
]
|
||||
}"
|
||||
response=$(curl "https://${ANTHROPIC_API_URL}/v1/messages" \
|
||||
response=$(curl "https://${anthropic_api_url}/v1/messages" \
|
||||
--silent \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: $ANTHROPIC_API_KEY" \
|
||||
-H "anthropic-version: 2023-06-01" \
|
||||
-d "$data")
|
||||
local message=$(echo "$response" | jq -r '.content[0].text')
|
||||
|
||||
message=$(echo "$response" | tr -d '\n' | jq -r '.content[0].text')
|
||||
else
|
||||
echo "Invalid AI provider selected. Please choose 'openai' or 'anthropic'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
##### Process response
|
||||
|
||||
local first_char=${message:0:1}
|
||||
local suggestion=${message:1:${#message}}
|
||||
|
||||
@ -118,6 +144,8 @@ function _suggest_ai() {
|
||||
echo "$(date);INPUT:$input;RESPONSE:$response;FIRST_CHAR:$first_char;SUGGESTION:$suggestion:DATA:$data" >> /tmp/zsh-copilot.log
|
||||
fi
|
||||
|
||||
##### And now, let's actually show the suggestion to the user!
|
||||
|
||||
if [[ "$first_char" == '=' ]]; then
|
||||
# Reset user input
|
||||
BUFFER=""
|
||||
@ -135,8 +163,10 @@ function zsh-copilot() {
|
||||
echo "Configurations:"
|
||||
echo " - ZSH_COPILOT_KEY: Key to press to get suggestions (default: ^z, value: $ZSH_COPILOT_KEY)."
|
||||
echo " - ZSH_COPILOT_SEND_CONTEXT: If \`true\`, zsh-copilot will send context information (whoami, shell, pwd, etc.) to the AI model (default: true, value: $ZSH_COPILOT_SEND_CONTEXT)."
|
||||
echo " - ZSH_COPILOT_AI_PROVIDER: AI provider to use ('openai' or 'anthropic', default: openai, value: $ZSH_COPILOT_AI_PROVIDER)."
|
||||
echo " - ZSH_COPILOT_AI_PROVIDER: AI provider to use ('openai' or 'anthropic', value: $ZSH_COPILOT_AI_PROVIDER)."
|
||||
echo " - ZSH_COPILOT_SYSTEM_PROMPT: System prompt to use for the AI model (uses a built-in prompt by default)."
|
||||
}
|
||||
|
||||
zle -N _suggest_ai
|
||||
bindkey $ZSH_COPILOT_KEY _suggest_ai
|
||||
bindkey "$ZSH_COPILOT_KEY" _suggest_ai
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user