|
1 | 1 | #!/usr/bin/env bash |
2 | | -# .bashmainrpc — JSON-RPC HTTP AI Service |
3 | | -# Author: Kubu Lee 🧠🔥 |
| 2 | +MODEL_FILE="model.json" |
| 3 | +RPC_LOG="/tmp/bashrpc.log" |
4 | 4 |
|
5 | | -set -euo pipefail |
| 5 | +# Load JSON model |
| 6 | +model=$(jq '.' "$MODEL_FILE") |
6 | 7 |
|
7 | | -# ======================== |
8 | | -# CONFIG |
9 | | -# ======================== |
10 | | -PORT=8088 |
11 | | -HOST="0.0.0.0" |
12 | | -ENV_FILE=".env" |
13 | | -TMP_LOG="/tmp/bashrpc.log" |
14 | | -DATE=$(date '+%Y-%m-%d %H:%M:%S') |
15 | | - |
16 | | -# ======================== |
17 | | -# ENV LOAD |
18 | | -# ======================== |
19 | | -if [ -f "$ENV_FILE" ]; then |
20 | | - export $(grep -v '^#' "$ENV_FILE" | xargs) |
21 | | -else |
22 | | - echo "❌ Missing .env file" |
23 | | - exit 1 |
24 | | -fi |
25 | | - |
26 | | -MODEL="${MODEL:-gpt-4o-mini}" |
27 | | -AI_PROVIDER="${AI_PROVIDER:-openai}" |
28 | | -AI_ENDPOINT="${AI_ENDPOINT:-https://api.openai.com/v1/chat/completions}" |
29 | | - |
30 | | -# ======================== |
31 | | -# CORE FUNCTIONS |
32 | | -# ======================== |
33 | | -ask_ai() { |
34 | | - local prompt="$1" |
35 | | - local response="" |
36 | | - |
37 | | - echo "[$DATE] [AI] $prompt" >> "$TMP_LOG" |
38 | | - |
39 | | - if [[ "$AI_PROVIDER" == "openai" ]]; then |
40 | | - response=$(curl -s "$AI_ENDPOINT" \ |
41 | | - -H "Authorization: Bearer $GPT_API_KEY" \ |
42 | | - -H "Content-Type: application/json" \ |
43 | | - -d "{ |
44 | | - \"model\": \"$MODEL\", |
45 | | - \"messages\": [{\"role\": \"user\", \"content\": \"$prompt\"}] |
46 | | - }" | jq -r '.choices[0].message.content') |
47 | | - else |
48 | | - response=$(curl -s "$AI_ENDPOINT" \ |
49 | | - -H "Content-Type: application/json" \ |
50 | | - -d "{\"prompt\":\"$prompt\"}" | jq -r '.response') |
51 | | - fi |
52 | | - |
53 | | - echo "$response" |
54 | | -} |
55 | | - |
56 | | -sys_info() { |
57 | | - echo "{\"hostname\":\"$(hostname)\",\"uptime\":\"$(uptime -p)\",\"load\":\"$(uptime | awk -F'load average:' '{print $2}')\"}" |
58 | | -} |
59 | | - |
60 | | -# ======================== |
61 | | -# RPC HANDLER |
62 | | -# ======================== |
| 8 | +# Dynamically handle calls |
63 | 9 | handle_rpc() { |
64 | | - local method="$1" |
65 | | - local data="$2" |
| 10 | + local service="$1" |
| 11 | + local method="$2" |
| 12 | + local data="$3" |
| 13 | + |
| 14 | + # Check if service/method exist in model |
| 15 | + if ! jq -e ".services.\"$service\".methods.\"$method\"" <<< "$model" >/dev/null; then |
| 16 | + echo "{\"error\":\"Unknown method $service.$method\"}" |
| 17 | + return |
| 18 | + fi |
66 | 19 |
|
67 | | - case "$method" in |
| 20 | + # Execute service |
| 21 | + case "$service.$method" in |
68 | 22 | ai.ask) |
69 | | - ask_ai "$data" |
| 23 | + curl -s https://api.openai.com/v1/chat/completions \ |
| 24 | + -H "Authorization: Bearer $GPT_API_KEY" \ |
| 25 | + -H "Content-Type: application/json" \ |
| 26 | + -d "{ |
| 27 | + \"model\": \"$(jq -r ".services.ai.model" <<< "$model")\", |
| 28 | + \"messages\": [{\"role\":\"user\",\"content\":\"$data\"}] |
| 29 | + }" | jq -r '.choices[0].message.content' |
70 | 30 | ;; |
71 | 31 | sys.info) |
72 | | - sys_info |
| 32 | + echo "{\"hostname\":\"$(hostname)\",\"uptime\":\"$(uptime -p)\"}" |
73 | 33 | ;; |
74 | 34 | *) |
75 | | - echo "{\"error\":\"Unknown method: $method\"}" |
| 35 | + echo "{\"error\":\"Service not implemented yet\"}" |
76 | 36 | ;; |
77 | 37 | esac |
78 | 38 | } |
79 | 39 |
|
80 | | -# ======================== |
81 | | -# HTTP RESPONSE BUILDER |
82 | | -# ======================== |
83 | | -http_response() { |
84 | | - local status="$1" |
85 | | - local body="$2" |
86 | | - |
87 | | - echo -e "HTTP/1.1 $status\r" |
88 | | - echo -e "Content-Type: application/json\r" |
89 | | - echo -e "Access-Control-Allow-Origin: *\r" |
90 | | - echo -e "Access-Control-Allow-Headers: Content-Type\r" |
91 | | - echo -e "Access-Control-Allow-Methods: POST, GET, OPTIONS\r" |
92 | | - echo -e "\r" |
93 | | - echo "$body" |
94 | | -} |
95 | | - |
96 | | -# ======================== |
97 | | -# MAIN SERVER LOOP |
98 | | -# ======================== |
99 | | -run_server() { |
100 | | - echo "🚀 BashMainRPC JSON-RPC Daemon started" |
101 | | - echo "🌐 Listening on http://$HOST:$PORT" |
102 | | - echo "🧠 Provider: $AI_PROVIDER ($MODEL)" |
103 | | - echo "📜 Logs: $TMP_LOG" |
104 | | - |
105 | | - while true; do |
106 | | - # Listen for connections (HTTP POST JSON-RPC) |
107 | | - ncat -l "$HOST" "$PORT" -k -c ' |
108 | | - read method |
109 | | - while read line && [ "$line" != $'\r' ]; do |
110 | | - headers="$headers$line\n" |
111 | | - done |
112 | | - body=$(cat) |
113 | | - req_method=$(echo "$body" | jq -r ".method") |
114 | | - req_data=$(echo "$body" | jq -r ".data") |
115 | | -
|
116 | | - if [ "$req_method" = "OPTIONS" ]; then |
117 | | - echo -e "HTTP/1.1 204 No Content\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: Content-Type\r\nAccess-Control-Allow-Methods: POST, GET, OPTIONS\r\n\r" |
118 | | - exit 0 |
119 | | - fi |
120 | | -
|
121 | | - response=$(./.bashmainrpc --call "$req_method" "$req_data" | jq -R -s "{result: .}") |
122 | | - ./bashrespond "$response" |
123 | | - ' |
124 | | - done |
125 | | -} |
126 | | - |
127 | | -# ======================== |
128 | | -# LOCAL CALL MODE |
129 | | -# ======================== |
130 | | -if [[ "${1:-}" == "--call" ]]; then |
131 | | - handle_rpc "$2" "$3" |
132 | | - exit 0 |
133 | | -fi |
134 | | - |
135 | | -# ======================== |
136 | | -# RUN SERVER |
137 | | -# ======================== |
138 | | -run_server |
| 40 | +# Example local call |
| 41 | +# ./bashmainrpc ai ask "Explain MDSE" |
| 42 | +handle_rpc "$1" "$2" "$3" |
0 commit comments