update
This commit is contained in:
@@ -1,34 +0,0 @@
|
|||||||
# finish.sh Test Container
|
|
||||||
FROM ubuntu:22.04
|
|
||||||
|
|
||||||
LABEL maintainer="finish contributors"
|
|
||||||
LABEL description="Test environment for finish.sh"
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
# Install dependencies including BATS for testing
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
bash \
|
|
||||||
bash-completion \
|
|
||||||
curl \
|
|
||||||
wget \
|
|
||||||
jq \
|
|
||||||
bc \
|
|
||||||
vim \
|
|
||||||
git \
|
|
||||||
bats \
|
|
||||||
&& apt-get clean && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /opt/finish
|
|
||||||
|
|
||||||
# Copy all files
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Make scripts executable
|
|
||||||
RUN chmod +x finish.sh
|
|
||||||
|
|
||||||
# Run tests by default
|
|
||||||
ENTRYPOINT ["bats"]
|
|
||||||
CMD ["tests"]
|
|
||||||
50
finish.sh
50
finish.sh
@@ -259,16 +259,21 @@ log_request() {
|
|||||||
openai_completion() {
|
openai_completion() {
|
||||||
local content status_code response_body default_user_input user_input api_key payload endpoint timeout attempt max_attempts
|
local content status_code response_body default_user_input user_input api_key payload endpoint timeout attempt max_attempts
|
||||||
local log_file debug_log
|
local log_file debug_log
|
||||||
|
|
||||||
|
# Ensure configuration (provider, endpoint, etc.) is loaded before checks
|
||||||
|
acsh_load_config
|
||||||
|
|
||||||
|
log_file=${ACSH_LOG_FILE:-"$HOME/.finish/finish.log"}
|
||||||
|
debug_log="$HOME/.finish/debug.log"
|
||||||
endpoint=${ACSH_ENDPOINT:-"http://plato.lan:1234/v1/chat/completions"}
|
endpoint=${ACSH_ENDPOINT:-"http://plato.lan:1234/v1/chat/completions"}
|
||||||
timeout=${ACSH_TIMEOUT:-30}
|
timeout=${ACSH_TIMEOUT:-30}
|
||||||
default_user_input="Write two to six most likely commands given the provided information"
|
default_user_input="Write two to six most likely commands given the provided information"
|
||||||
user_input=${*:-$default_user_input}
|
user_input=${*:-$default_user_input}
|
||||||
log_file=${ACSH_LOG_FILE:-"$HOME/.finish/finish.log"}
|
|
||||||
debug_log="$HOME/.finish/debug.log"
|
|
||||||
|
|
||||||
|
# Only check for API key if not using local providers that don't require it
|
||||||
if [[ -z "$ACSH_ACTIVE_API_KEY" && ${ACSH_PROVIDER^^} != "OLLAMA" && ${ACSH_PROVIDER^^} != "LMSTUDIO" ]]; then
|
if [[ -z "$ACSH_ACTIVE_API_KEY" && ${ACSH_PROVIDER^^} != "OLLAMA" && ${ACSH_PROVIDER^^} != "LMSTUDIO" ]]; then
|
||||||
echo_error "ACSH_ACTIVE_API_KEY not set. Please set it with: export ${ACSH_PROVIDER^^}_API_KEY=<your-api-key>"
|
echo_error "ACSH_ACTIVE_API_KEY not set. Please set it with: export ${ACSH_PROVIDER^^}_API_KEY=<your-api-key>"
|
||||||
return
|
return 1
|
||||||
fi
|
fi
|
||||||
api_key="${ACSH_ACTIVE_API_KEY}"
|
api_key="${ACSH_ACTIVE_API_KEY}"
|
||||||
payload=$(_build_payload "$user_input")
|
payload=$(_build_payload "$user_input")
|
||||||
@@ -300,9 +305,16 @@ openai_completion() {
|
|||||||
if [[ "${ACSH_PROVIDER^^}" == "OLLAMA" ]]; then
|
if [[ "${ACSH_PROVIDER^^}" == "OLLAMA" ]]; then
|
||||||
\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" --data "$payload" -N > "$temp_file"
|
\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" --data "$payload" -N > "$temp_file"
|
||||||
else
|
else
|
||||||
\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" \
|
if [[ -n "$api_key" ]]; then
|
||||||
-H "Content-Type: application/json" \
|
\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" \
|
||||||
-d "$payload" -N > "$temp_file"
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $api_key" \
|
||||||
|
-d "$payload" -N > "$temp_file"
|
||||||
|
else
|
||||||
|
\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$payload" -N > "$temp_file"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
status_code=$(tail -n1 "$temp_file")
|
status_code=$(tail -n1 "$temp_file")
|
||||||
@@ -330,9 +342,16 @@ openai_completion() {
|
|||||||
if [[ "${ACSH_PROVIDER^^}" == "OLLAMA" ]]; then
|
if [[ "${ACSH_PROVIDER^^}" == "OLLAMA" ]]; then
|
||||||
response=$(\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" --data "$payload")
|
response=$(\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" --data "$payload")
|
||||||
else
|
else
|
||||||
response=$(\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" \
|
if [[ -n "$api_key" ]]; then
|
||||||
-H "Content-Type: application/json" \
|
response=$(\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" \
|
||||||
-d "$payload")
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $api_key" \
|
||||||
|
-d "$payload")
|
||||||
|
else
|
||||||
|
response=$(\curl -s -m "$timeout" -w "\n%{http_code}" "$endpoint" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$payload")
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
status_code=$(echo "$response" | tail -n1)
|
status_code=$(echo "$response" | tail -n1)
|
||||||
response_body=$(echo "$response" | sed '$d')
|
response_body=$(echo "$response" | sed '$d')
|
||||||
@@ -362,8 +381,8 @@ openai_completion() {
|
|||||||
500) echo_error "Internal Server Error: An unexpected error occurred on the API server." ;;
|
500) echo_error "Internal Server Error: An unexpected error occurred on the API server." ;;
|
||||||
*) echo_error "Unknown Error: Unexpected status code $status_code received. Response: $response_body" ;;
|
*) echo_error "Unknown Error: Unexpected status code $status_code received. Response: $response_body" ;;
|
||||||
esac
|
esac
|
||||||
return
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${ACSH_PROVIDER^^}" == "OLLAMA" ]]; then
|
if [[ "${ACSH_PROVIDER^^}" == "OLLAMA" ]]; then
|
||||||
content=$(echo "$response_body" | jq -r '.message.content')
|
content=$(echo "$response_body" | jq -r '.message.content')
|
||||||
@@ -393,7 +412,7 @@ openai_completion() {
|
|||||||
|
|
||||||
if [[ -z "$completions" ]]; then
|
if [[ -z "$completions" ]]; then
|
||||||
echo_error "Failed to parse completions from API response. Check $debug_log for details."
|
echo_error "Failed to parse completions from API response. Check $debug_log for details."
|
||||||
return
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "$completions"
|
echo -n "$completions"
|
||||||
@@ -446,13 +465,6 @@ _finishsh() {
|
|||||||
if [[ ${#COMPREPLY[@]} -eq 0 && $COMP_TYPE -eq 63 ]]; then
|
if [[ ${#COMPREPLY[@]} -eq 0 && $COMP_TYPE -eq 63 ]]; then
|
||||||
local completions user_input user_input_hash
|
local completions user_input user_input_hash
|
||||||
acsh_load_config
|
acsh_load_config
|
||||||
if [[ -z "$ACSH_ACTIVE_API_KEY" && ${ACSH_PROVIDER^^} != "OLLAMA" && ${ACSH_PROVIDER^^} != "LMSTUDIO" ]]; then
|
|
||||||
local provider_key="${ACSH_PROVIDER}_API_KEY"
|
|
||||||
provider_key=$(echo "$provider_key" | tr '[:lower:]' '[:upper:]')
|
|
||||||
echo_error "${provider_key} is not set. Please set it using: export ${provider_key}=<your-api-key> or disable finish via: finish disable"
|
|
||||||
echo
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if [[ -n "${COMP_WORDS[*]}" ]]; then
|
if [[ -n "${COMP_WORDS[*]}" ]]; then
|
||||||
command="${COMP_WORDS[0]}"
|
command="${COMP_WORDS[0]}"
|
||||||
if [[ -n "$COMP_CWORD" && "$COMP_CWORD" -lt "${#COMP_WORDS[@]}" ]]; then
|
if [[ -n "$COMP_CWORD" && "$COMP_CWORD" -lt "${#COMP_WORDS[@]}" ]]; then
|
||||||
|
|||||||
@@ -7,3 +7,6 @@ cd "$SCRIPT_DIR"
|
|||||||
|
|
||||||
# Execute the tests
|
# Execute the tests
|
||||||
bash ./tests/test_finish.sh
|
bash ./tests/test_finish.sh
|
||||||
|
|
||||||
|
# Also try the local Ollama end-to-end test (skips if Ollama not running)
|
||||||
|
bash ./tests/test_finish_ollama.sh
|
||||||
|
|||||||
@@ -16,6 +16,28 @@ assert_nonempty() {
|
|||||||
assert_contains() {
|
assert_contains() {
|
||||||
if [[ ! "$1" =~ $2 ]]; then fail "$3"; fi
|
if [[ ! "$1" =~ $2 ]]; then fail "$3"; fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Ensure output does not contain any of the common error phrases.
|
||||||
|
assert_no_common_errors() {
|
||||||
|
local output="$1"
|
||||||
|
local -a patterns=(
|
||||||
|
"ACSH_ACTIVE_API_KEY not set"
|
||||||
|
"Bad Request"
|
||||||
|
"Unauthorized"
|
||||||
|
"Too Many Requests"
|
||||||
|
"Internal Server Error"
|
||||||
|
"Unknown Error"
|
||||||
|
"Failed to parse completions"
|
||||||
|
"SyntaxError"
|
||||||
|
"ERROR:"
|
||||||
|
)
|
||||||
|
for pat in "${patterns[@]}"; do
|
||||||
|
if grep -qE "$pat" <<<"$output"; then
|
||||||
|
printf "Test failed: output contains error pattern '%s'\nFull output follows:\n%s\n" "$pat" "$output"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
# --------------------------------
|
# --------------------------------
|
||||||
|
|
||||||
echo "=== SETUP ==="
|
echo "=== SETUP ==="
|
||||||
@@ -50,6 +72,7 @@ pass "finish config contains lmstudio"
|
|||||||
out=$(finish command "ls # show largest files" 2>&1) ; code=$?
|
out=$(finish command "ls # show largest files" 2>&1) ; code=$?
|
||||||
assert_ok $code "finish command did not exit 0"
|
assert_ok $code "finish command did not exit 0"
|
||||||
assert_nonempty "$out" "finish command returned empty output"
|
assert_nonempty "$out" "finish command returned empty output"
|
||||||
|
assert_no_common_errors "$out"
|
||||||
pass "finish command executed and returned output"
|
pass "finish command executed and returned output"
|
||||||
|
|
||||||
# ------------------------------- CLEANUP --------------------------------
|
# ------------------------------- CLEANUP --------------------------------
|
||||||
|
|||||||
112
tests/test_finish_ollama.sh
Executable file
112
tests/test_finish_ollama.sh
Executable file
@@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ----- tiny test framework -----
|
||||||
|
pass() { printf "✔ %s\n" "$1"; }
|
||||||
|
fail() { printf "✘ %s\n" "$1"; exit 1; }
|
||||||
|
|
||||||
|
assert_ok() {
|
||||||
|
if [[ $1 -ne 0 ]]; then fail "$2"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_nonempty() {
|
||||||
|
if [[ -z "$1" ]]; then fail "$2"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_contains() {
|
||||||
|
if [[ ! "$1" =~ $2 ]]; then fail "$3"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure output does not contain any of the common error phrases.
|
||||||
|
assert_no_common_errors() {
|
||||||
|
local output="$1"
|
||||||
|
local -a patterns=(
|
||||||
|
"ACSH_ACTIVE_API_KEY not set"
|
||||||
|
"Bad Request"
|
||||||
|
"Unauthorized"
|
||||||
|
"Too Many Requests"
|
||||||
|
"Internal Server Error"
|
||||||
|
"Unknown Error"
|
||||||
|
"Failed to parse completions"
|
||||||
|
"SyntaxError"
|
||||||
|
"ERROR:"
|
||||||
|
)
|
||||||
|
for pat in "${patterns[@]}"; do
|
||||||
|
if grep -qE "$pat" <<<"$output"; then
|
||||||
|
printf "Test failed: output contains error pattern '%s'\nFull output follows:\n%s\n" "$pat" "$output"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
# --------------------------------
|
||||||
|
|
||||||
|
echo "=== OLLAMA TEST: SETUP ==="
|
||||||
|
|
||||||
|
# Always run from the repo root for predictable paths
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR/.."
|
||||||
|
|
||||||
|
# Install finish (adds to PATH and shell rc files)
|
||||||
|
bash ./docs/install.sh main
|
||||||
|
|
||||||
|
# Load the updated shell rc so `finish` is available on PATH in this session
|
||||||
|
if [[ -f ~/.bashrc ]]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source ~/.bashrc || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- Check prerequisites for local Ollama ----
|
||||||
|
OLLAMA_URL=${OLLAMA_URL:-"http://localhost:11434"}
|
||||||
|
|
||||||
|
echo "Checking Ollama at $OLLAMA_URL ..."
|
||||||
|
if ! curl -fsS --max-time 2 "$OLLAMA_URL/api/version" >/dev/null 2>&1; then
|
||||||
|
echo "SKIP: Ollama is not reachable at $OLLAMA_URL. Start it with: 'ollama serve' and ensure a model is pulled (e.g., 'ollama pull llama3')."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to discover an installed model; prefer the first listed
|
||||||
|
MODEL=$(curl -fsS "$OLLAMA_URL/api/tags" | jq -r '.models[0].name // empty' || echo "")
|
||||||
|
if [[ -z "$MODEL" ]]; then
|
||||||
|
echo "SKIP: No local Ollama models found. Pull one first, e.g.: 'ollama pull llama3:latest'"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using Ollama model: $MODEL"
|
||||||
|
|
||||||
|
# -------------------------------- TESTS --------------------------------
|
||||||
|
|
||||||
|
# 1) configure finish to use local Ollama
|
||||||
|
finish config set provider ollama
|
||||||
|
finish config set endpoint "$OLLAMA_URL/api/chat"
|
||||||
|
finish config set model "$MODEL"
|
||||||
|
|
||||||
|
# 2) which finish should return something
|
||||||
|
out=$(which finish 2>&1) ; code=$?
|
||||||
|
assert_ok $code "which finish should exit 0"
|
||||||
|
assert_nonempty "$out" "which finish returned empty output"
|
||||||
|
pass "which finish returns path"
|
||||||
|
|
||||||
|
# 3) finish output should contain 'finish.sh'
|
||||||
|
out=$(finish 2>&1) ; code=$?
|
||||||
|
assert_ok $code "finish should exit 0"
|
||||||
|
assert_contains "$out" "finish\.sh" "finish output does not contain finish.sh"
|
||||||
|
pass "finish outputs reference to finish.sh"
|
||||||
|
|
||||||
|
# 4) config should mention ollama
|
||||||
|
out=$(finish config 2>&1) ; code=$?
|
||||||
|
assert_ok $code "finish config should exit 0"
|
||||||
|
assert_contains "$out" "ollama" "finish config missing ollama provider"
|
||||||
|
pass "finish config contains ollama"
|
||||||
|
|
||||||
|
# 5) finish command should run and return output
|
||||||
|
out=$(finish command "ls # show largest files" 2>&1) ; code=$?
|
||||||
|
assert_ok $code "finish command did not exit 0"
|
||||||
|
assert_nonempty "$out" "finish command returned empty output"
|
||||||
|
assert_no_common_errors "$out"
|
||||||
|
pass "finish command executed and returned output (ollama)"
|
||||||
|
|
||||||
|
# ------------------------------- CLEANUP --------------------------------
|
||||||
|
echo "=== OLLAMA TEST: CLEANUP ==="
|
||||||
|
finish remove -y || true
|
||||||
|
|
||||||
|
echo "Ollama test passed."
|
||||||
Reference in New Issue
Block a user