generated from google-gemini/aistudio-repository-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagi
More file actions
executable file
·550 lines (492 loc) · 25.1 KB
/
agi
File metadata and controls
executable file
·550 lines (492 loc) · 25.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
#!/usr/bin/env bash
# ~/bin/ai - All-in-One AI Agent Shell (Android/Termux + Desktop)
# Features: CLI frontend, multi-model orchestration, code generation, internet research,
# hashed indexing, verbose thinking, self-cycled dynamics.
set -euo pipefail
IFS=$'\n\t'
# -------------------- CONFIG --------------------
AI_HOME="${AI_HOME:-$HOME/.ai_agent}"
PROJECTS_DIR="${PROJECTS_DIR:-$HOME/ai_projects}"
GIT_DIR="${GIT_DIR:-$HOME/.ai_builder}"
GIT_REPO="git@github.com:Loopshape/BITBOY-AI-DEX.git"
SSH_KEY="$HOME/.ssh/loopshape_rsa"
OLLAMA_BIN="$(command -v ollama || true)"
MEMORY_DB="$AI_HOME/memory.db"
CONFIG_DB="$AI_HOME/config.db"
EVENTS_DB="$AI_HOME/events.db"
# Model defaults - can be overridden by environment variables (AI_MODEL, AI_CODE_MODEL) or config DB
DEFAULT_MESSENGER_MODEL="gemma3:1b"
DEFAULT_COMBINATOR_MODEL="deepseek-r1:1.5b"
DEFAULT_TRADER_MODEL="2244-1"
DEFAULT_CODE_GEN_MODEL="codellama:7b" # A model specialized for code generation
# Dynamic AI parameters loaded/overridden
AI_MESSENGER_MODEL="core:latest"
AI_COMBINATOR_MODEL="coin:latest"
AI_TRADER_MODEL="2244:latest"
AI_CODE_GEN_MODEL="code:latest"
AI_TEMPERATURE="0.74"
AI_TOP_P="0.58"
AI_SEED="love focus rude charge heavy uniform space way sign install world unit"
# Termux detection
IS_TERMUX=false
[[ -n "${PREFIX:-}" && -d "${PREFIX:-}" && "$(uname -o 2>/dev/null)" == "Android" ]] && IS_TERMUX=true
# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; PURPLE='\033[0;35m'; CYAN='\033[0;36m'; NC='\033[0m'
# -------------------- LOGGING --------------------
log() { printf "${BLUE}[%s][AI]${NC} %s\n" "$(date '+%T')" "$*"; }
log_success() { log "${GREEN}$*${NC}"; }
log_warn() { log "${YELLOW}WARN: $*${NC}"; }
log_error() { log "${RED}ERROR: $*${NC}"; exit 1; }
log_info() { log "${CYAN}$*${NC}"; }
log_phase() { echo -e "\n${PURPLE}▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓${NC}"; log "${PURPLE}$*${NC}"; echo -e "${PURPLE}▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓${NC}"; }
# -------------------- DATABASE FUNCTIONS --------------------
sqlite_escape() { echo "$1" | sed "s/'/''/g"; }
init_db() {
sqlite3 "$MEMORY_DB" "CREATE TABLE IF NOT EXISTS memories (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, prompt TEXT, response TEXT, task_id TEXT);" 2>/dev/null || true
sqlite3 "$CONFIG_DB" "CREATE TABLE IF NOT EXISTS config (key TEXT PRIMARY KEY, value TEXT);" 2>/dev/null || true
sqlite3 "$EVENTS_DB" "CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, event_hash TEXT UNIQUE, event_data TEXT);" 2>/dev/null || true
}
set_config() { sqlite3 "$CONFIG_DB" "INSERT OR REPLACE INTO config (key, value) VALUES ('$(sqlite_escape "$1")','$(sqlite_escape "$2")');" ; log_success "Config set: $1=$2"; }
get_config() { sqlite3 "$CONFIG_DB" "SELECT value FROM config WHERE key='$(sqlite_escape "$1")';" 2>/dev/null; }
load_config_values() {
AI_MESSENGER_MODEL="${AI_MODEL:-$(get_config messenger_model || echo "$DEFAULT_MESSENGER_MODEL")}"
AI_COMBINATOR_MODEL="${AI_MODEL:-$(get_config combinator_model || echo "$DEFAULT_COMBINATOR_MODEL")}"
AI_TRADER_MODEL="${AI_MODEL:-$(get_config trader_model || echo "$DEFAULT_TRADER_MODEL")}"
AI_CODE_GEN_MODEL="${AI_CODE_MODEL:-$(get_config code_gen_model || echo "$DEFAULT_CODE_GEN_MODEL")}"
AI_TEMPERATURE="${AI_TEMPERATURE:-$(get_config temperature || echo "0.7")}"
AI_TOP_P="${AI_TOP_P:-$(get_config top_p || echo "0.9")}"
AI_SEED="${AI_SEED:-$(get_config seed || echo "")}"
}
add_to_memory() { sqlite3 "$MEMORY_DB" "INSERT INTO memories (prompt,response,task_id) VALUES ('$(sqlite_escape "$1")','$(sqlite_escape "$2")','$3');" 2>/dev/null; }
search_memory() { sqlite3 -header -column "$MEMORY_DB" "SELECT timestamp,prompt,response FROM memories WHERE prompt LIKE '%$(sqlite_escape "$1")%' ORDER BY timestamp DESC LIMIT 5;" 2>/dev/null; }
clear_memory() {
if confirm_action "Clear all AI memories?"; then
sqlite3 "$MEMORY_DB" "DELETE FROM memories;"
log_success "Memory cleared."
else
log_info "Memory clear canceled."
fi
}
gen_content_hash() { echo -n "$1" | sha256sum | cut -c1-64; }
add_event_to_db() {
local event_data="$1"
local current_timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local event_hash=$(gen_content_hash "$event_data")
if sqlite3 "$EVENTS_DB" "INSERT INTO events (timestamp, event_hash, event_data) VALUES ('$(sqlite_escape "$current_timestamp")', '$(sqlite_escape "$event_hash")', '$(sqlite_escape "$event_data")');" 2>/dev/null; then
log_success "Event added to index with hash: $event_hash"
echo "$event_hash"
else
if sqlite3 "$EVENTS_DB" "SELECT 1 FROM events WHERE event_hash = '$(sqlite_escape "$event_hash")';" 2>/dev/null; then
log_info "Event with hash $event_hash already exists in index."
echo "$event_hash"
else
log_error "Failed to add event to index for hash: $event_hash"
return 1
fi
fi
}
search_events() {
local query="$1"
sqlite3 -header -column "$EVENTS_DB" "SELECT timestamp, event_hash, SUBSTR(event_data, 1, 70) || '...' FROM events WHERE event_hash LIKE '%$(sqlite_escape "$query")%' OR event_data LIKE '%$(sqlite_escape "$query")%' ORDER BY timestamp DESC LIMIT 5;" 2>/dev/null;
}
list_event_index() {
sqlite3 -header -column "$EVENTS_DB" "SELECT timestamp, event_hash, SUBSTR(event_data, 1, 70) || '...' FROM events ORDER BY timestamp DESC LIMIT 10;" 2>/dev/null;
}
clear_events_db() {
if confirm_action "Clear all indexed events?"; then
sqlite3 "$EVENTS_DB" "DELETE FROM events;"
log_success "Event index cleared."
else
log_info "Event index clear canceled."
fi
}
gen_task_id() { echo -n "${1:-}$(date +%s%N)$RANDOM${AI_SEED:-}" | sha256sum | cut -c1-16; }
confirm_action() { echo -e "${YELLOW}CONFIRM: $1${NC}"; read -p "Type 'yes' to confirm: " -r r; [[ "$r" == "yes" ]]; }
# -------------------- TOOLS (AI can decide to use) --------------------
tool_web_search() {
local query="$1"
log_info "AI initiating web search for: $query"
if [[ -z "${AI_INTERNAL_CALL:-}" ]]; then
if ! confirm_action "Search web for: $query"; then
echo "ACTION CANCELED"
return 1
fi
fi
local search_results=$(curl -sL "https://html.duckduckgo.com/html/?q=$(jq -nr --arg q "$query" '$q|@uri')" | lynx -dump -stdin -nolist)
if [[ -z "$search_results" ]]; then
log_warn "Web search for '$query' returned no results or failed."
echo "NO_RESULTS"
return 1
else
log_success "Web search for '$query' completed."
echo "$search_results"
return 0
fi
}
tool_write_file() {
local file_path="$1"
local file_content="$2"
log_info "AI attempting to write file: $file_path"
if [[ -z "${AI_INTERNAL_CALL:-}" ]]; then
if ! confirm_action "Write to file: $file_path"; then
echo "ACTION CANCELED"
return 1
fi
fi
mkdir -p "$(dirname "$file_path")" || { log_error "Failed to create directory for $file_path"; return 1; }
echo -e "$file_content" > "$file_path" || { log_error "Failed to write content to $file_path"; return 1; }
log_success "File written successfully: $file_path"
return 0
}
# -------------------- AI WORKER FUNCTIONS --------------------
ensure_ollama_server() { pgrep -f "ollama serve" >/dev/null || (log "Ollama server starting..."; nohup "$OLLAMA_BIN" serve >/dev/null 2>&1 & sleep 3); }
run_worker_raw_with_verbose_capture() {
local model="$1" system_prompt="$2" conversation_history="$3"
ensure_ollama_server
local response_buffer=""
local verbose_output_buffer=""
local fifo
fifo=$(mktemp -u)
mkfifo "$fifo"
( AI_INTERNAL_CALL="true" \
"$OLLAMA_BIN" run --verbose "$model" --temperature "$AI_TEMPERATURE" --top_p "$AI_TOP_P" ${AI_SEED:+--seed "$AI_SEED"} "$system_prompt"$'\n'"$conversation_history" 2>&1 > "$fifo" ) &
local pid=$!
while IFS= read -r line <"$fifo"; do
[[ -z "$line" ]] && continue
if [[ "$line" =~ ^\>\>\> ]]; then
echo -e "${YELLOW}$line${NC}" >&2
verbose_output_buffer+="$line"$'\n'
elif [[ "$line" =~ ^\{.*\}$ ]]; then
local token
token=$(echo "$line" | jq -r '.response? // empty' 2>/dev/null)
local done_status
done_status=$(echo "$line" | jq -r '.done? // false' 2>/dev/null)
[[ -n "$token" ]] && { printf '%s' "$token"; response_buffer+="$token"; }
[[ "$done_status" == "true" ]] && printf '\n'
else
echo -e "${BLUE}$line${NC}" >&2
verbose_output_buffer+="$line"$'\n'
fi
done
wait "$pid" 2>/dev/null || true
rm -f "$fifo"
echo -e "---AI_RESPONSE_START---\n$response_buffer\n---AI_RESPONSE_END---"
echo -e "---VERBOSE_OUTPUT_START---\n$verbose_output_buffer\n---VERBOSE_OUTPUT_END---"
}
# -------------------- AI ORCHESTRATION MAIN LOOP --------------------
run_ai_orchestration() {
local initial_user_prompt="$1"
log_phase "AI ORCHESTRATION: Starting for prompt: $initial_user_prompt"
local task_id
task_id=$(gen_task_id "$initial_user_prompt")
local task_dir="$PROJECTS_DIR/$task_id"
mkdir -p "$task_dir"
log_success "Task ID: $task_id"
log_info "Workspace: $task_dir"
log_info "Solution will be saved in: $task_dir"
local current_context="$initial_user_prompt"
local total_loops=0
local MAX_LOOPS=7
local solved="false"
local final_ai_response=""
while [[ "$total_loops" -lt "$MAX_LOOPS" && "$solved" == "false" ]]; do
total_loops=$((total_loops + 1))
log_phase "AI Thought Loop #$total_loops"
local relevant_memories
relevant_memories=$(search_memory "$current_context")
local messenger_prompt="MESSENGER analyzing: $current_context. What actions are implied (RESEARCH, GENERATE_CODE, FINAL_ANSWER)? If solved, state [FINAL_ANSWER]."
local combinator_prompt="COMBINATOR brainstorming: $current_context. Suggest specific actions like 'RESEARCH <query>', 'GENERATE_CODE', or a '[FINAL_ANSWER]' if solved."
local m_output_raw
m_output_raw=$(run_worker_raw_with_verbose_capture "$AI_MESSENGER_MODEL" "$messenger_prompt" "$relevant_memories")
local messenger_response
messenger_response=$(echo "$m_output_raw" | sed -n '/---AI_RESPONSE_START---/,/---AI_RESPONSE_END---/{//!p}')
local messenger_verbose
messenger_verbose=$(echo "$m_output_raw" | sed -n '/---VERBOSE_OUTPUT_START---/,/---VERBOSE_OUTPUT_END---/{//!p}')
local c_output_raw
c_output_raw=$(run_worker_raw_with_verbose_capture "$AI_COMBINATOR_MODEL" "$combinator_prompt" "$relevant_memories")
local combinator_response
combinator_response=$(echo "$c_output_raw" | sed -n '/---AI_RESPONSE_START---/,/---AI_RESPONSE_END---/{//!p}')
local combinator_verbose
combinator_verbose=$(echo "$c_output_raw" | sed -n '/---VERBOSE_OUTPUT_START---/,/---VERBOSE_OUTPUT_END---/{//!p}')
add_event_to_db "Messenger Verbose ($task_id, Loop $total_loops):\n$messenger_verbose" >/dev/null
add_event_to_db "Combinator Verbose ($task_id, Loop $total_loops):\n$combinator_verbose" >/dev/null
log_info "Analyzing LLM responses for action triggers..."
local all_llm_responses="$messenger_response"$'\n'"$combinator_response"
local action_decision
action_decision=$(analyze_llm_output_for_action "$all_llm_responses" "$initial_user_prompt")
local research_query=""
if echo "$action_decision" | grep -qi "RESEARCH"; then
research_query=$(echo "$all_llm_responses" | grep -oP '(?i)RESEARCH\s+([^\n\[]+)' | head -n 1 | sed -E 's/.*RESEARCH\s+//i')
if [[ -z "$research_query" ]]; then
log_warn "AI indicated research but no specific query was extracted. Defaulting to prompt-based search."
research_query="$initial_user_prompt relevant information"
fi
fi
log_info "AI Decision: $action_decision"
case "$action_decision" in
"RESEARCH")
log_info "Performing internet research for: '$research_query'"
local research_results
research_results=$(AI_INTERNAL_CALL="true" tool_web_search "$research_query")
if [[ "$research_results" == "NO_RESULTS" || $? -ne 0 ]]; then
log_warn "Internal web search for '$research_query' returned no results. AI will proceed."
current_context+=" (Previous research for '$research_query' yielded no results.)"
else
add_event_to_db "Research Results for '$research_query':\n$research_results" >/dev/null
current_context+=" (Research for '$research_query': $research_results)"
log_success "Research for '$research_query' incorporated into context."
fi
;;
"GENERATE_CODE")
log_info "AI decided to generate code. Preparing prompt for code model..."
local code_gen_instruction="You are an expert programmer. Based on the prompt and context, generate the requested code. Output ONLY the code for the primary file, no conversational text or markdown wrappers.
User Prompt: $initial_user_prompt
Current Context: $current_context
If an HTML file is requested, provide a complete HTML5 document including CDN links for libraries like three.js, gsap, jquery3.
For shell scripts, provide a complete, executable bash script with shebang."
local code_output_raw
code_output_raw=$(run_worker_raw_with_verbose_capture "$AI_CODE_GEN_MODEL" "$code_gen_instruction" "$relevant_memories")
local generated_code
generated_code=$(echo "$code_output_raw" | sed -n '/---AI_RESPONSE_START---/,/---AI_RESPONSE_END---/{//!p}')
local code_gen_verbose
code_gen_verbose=$(echo "$code_output_raw" | sed -n '/---VERBOSE_OUTPUT_START---/,/---VERBOSE_OUTPUT_END---/{//!p}')
add_event_to_db "Code Generation Verbose ($task_id, Loop $total_loops):\n$code_gen_verbose" >/dev/null
if [[ -n "$generated_code" ]]; then
local default_filename="solution_$(date +%s%N).html"
if echo "$initial_user_prompt" | grep -qi "shellscript"; then default_filename="solution_$(date +%s%N).sh"; fi
if echo "$initial_user_prompt" | grep -qi "javascript"; then default_filename="solution_$(date +%s%N).js"; fi
local suggested_path="$task_dir/$default_filename"
echo -e "${GREEN}AI generated a solution. Proposed file path: ${YELLOW}$suggested_path${NC}"
echo -e "${YELLOW}Review the code below. Type 'yes' to save, provide a new path, or 'no' to discard.${NC}"
echo -e "\n---\n${generated_code}\n---"
read -p "Save? (yes/no/[new path]): " -r save_choice
save_choice="${save_choice,,}"
if [[ "$save_choice" == "yes" ]]; then
AI_INTERNAL_CALL="true" tool_write_file "$suggested_path" "$generated_code"
final_ai_response="[FINAL_ANSWER] Solution generated and saved to: $suggested_path"
solved="true"
elif [[ "$save_choice" == "no" ]]; then
log_info "Solution discarded by user."
current_context+=" (Generated code was discarded by user.)"
else
AI_INTERNAL_CALL="true" tool_write_file "$save_choice" "$generated_code"
final_ai_response="[FINAL_ANSWER] Solution generated and saved to: $save_choice"
solved="true"
fi
else
log_warn "AI attempted code generation but produced no output. Will re-evaluate."
current_context+=" (Previous attempt to generate code yielded no output.)"
fi
;;
"FINAL_ANSWER")
log_success "AI produced a final answer."
final_ai_response=$(echo "$all_llm_responses" | grep -oP '\[FINAL_ANSWER\]\s*(.*)' | sed -E 's/\[FINAL_ANSWER\]\s*//i' | head -n 1)
if [[ -z "$final_ai_response" ]]; then
final_ai_response="[FINAL_ANSWER] Problem considered solved based on AI's synthesis: $all_llm_responses"
else
final_ai_response="[FINAL_ANSWER] $final_ai_response"
fi
solved="true"
;;
*)
log_info "No explicit action decided, synthesizing current thoughts for next loop."
local trader_prompt="TRADER synthesizing thoughts. Based on problem: '$initial_user_prompt' and context: '$current_context'. Suggest the next action: 'RESEARCH <query>', 'GENERATE_CODE', or '[FINAL_ANSWER]'.
---MESSENGER---
$messenger_response
---COMBINATOR---
$combinator_response"
local t_output_raw
t_output_raw=$(run_worker_raw_with_verbose_capture "$AI_TRADER_MODEL" "$trader_prompt" "$relevant_memories")
local trader_response
trader_response=$(echo "$t_output_raw" | sed -n '/---AI_RESPONSE_START---/,/---AI_RESPONSE_END---/{//!p}')
local trader_verbose
trader_verbose=$(echo "$t_output_raw" | sed -n '/---VERBOSE_OUTPUT_START---/,/---VERBOSE_OUTPUT_END---/{//!p}')
add_event_to_db "Trader Verbose ($task_id, Loop $total_loops):\n$trader_verbose" >/dev/null
log_info "Trader's current synthesis:\n$trader_response"
current_context+=" (Trader's thoughts: $trader_response)"
;;
esac
done
if [[ "$solved" == "false" ]]; then
log_warn "AI orchestration loop finished without a definitive [FINAL_ANSWER] within $MAX_LOOPS loops."
final_ai_response="AI could not solve the prompt: '$initial_user_prompt' within $MAX_LOOPS loops. Last context: $current_context"
fi
add_to_memory "$initial_user_prompt" "$final_ai_response" "$task_id"
echo "$final_ai_response"
log_info "All verbose thinking logged in event database. Final task context in memory."
return 0
}
analyze_llm_output_for_action() {
local text_to_analyze="$1"
local original_prompt="$2"
if echo "$text_to_analyze" | grep -qi "\[FINAL_ANSWER\]"; then
echo "FINAL_ANSWER"
elif echo "$text_to_analyze" | grep -qi "GENERATE_CODE"; then
echo "GENERATE_CODE"
elif echo "$text_to_analyze" | grep -qi "RESEARCH"; then
echo "RESEARCH"
elif echo "$original_prompt" | grep -qiE '(build|create|implement|write|show).*(html|javascript|js|three.js|webgl|gsap|jquery3|css3|script|file)'; then
echo "GENERATE_CODE"
else
echo "SYNTHESIZE_AND_CONTINUE"
fi
}
# -------------------- HELP & CLI HANDLERS --------------------
show_help() {
echo -e "\033[0;32mEnhanced AI Agent - All-in-One Shell\033[0m"
echo ""
echo -e "\033[0;36mBasic Usage:\033[0m"
echo " ai \"your prompt here\" - Run AI agent with prompt"
echo " ai --help - Show this help"
echo ""
echo -e "\033[0;36mConfiguration:\033[0m"
echo " ai --config view - View configuration"
echo " ai --config set <key> <value> - Set configuration"
echo ""
echo -e "\033[0;36mMemory:\033[0m"
echo " ai --memory search \"query\" - Search memory"
echo " ai --memory clear - Clear memory"
echo ""
echo -e "\033[0;36mEvents:\033[0m"
echo " ai --event search \"query\" - Search indexed event data"
echo " ai --event clear - Clear all indexed event data"
echo ""
echo -e "\033[0;36mHashing:\033[0m"
echo " ai --hash file <path> - Hash a file"
echo " ai --hash event \"text\" - Hash event data"
echo " ai --hash index - Show index of recent event hashes"
echo ""
echo -e "\033[0;36mTools:\033[0m"
echo " ai --tools - List available tools"
echo " ai --web-search \"query\" - Perform a web search"
echo ""
echo -e "\033[0;36mDeveloper/Admin Commands:${NC}"
echo " ai --setup - Install necessary system dependencies"
echo " ai --git - Sync AI builder repository"
echo " ai --websocket-mode - Run as a WebSocket server (requires websocketd)"
echo ""
echo -e "\03...": Override only the code generation model."
echo " AI_TEMPERATURE="...\": Set sampling temperature."
echo ""
echo -e "\033[1;33mExamples:\033[0m"
echo " ai \"Build a simple HTML page with a rotating cube using three.js\""
echo " ai --config set temperature 0.5"
echo " ai --memory search \"python\""
echo " ai --event search \"click\""
}
handle_config() {
case "${1:-}" in
view)
log_info "Current Configuration:"
sqlite3 -header -column "$CONFIG_DB" "SELECT key, value FROM config;"
echo "---"
log_info "Effective AI Agent Models:"
echo " Messenger: $AI_MESSENGER_MODEL"
echo " Combinator: $AI_COMBINATOR_MODEL"
echo " Trader: $AI_TRADER_MODEL"
echo " Code Generator: $AI_CODE_GEN_MODEL"
echo " Temperature: $AI_TEMPERATURE"
echo " Top_p: $AI_TOP_P"
echo " Seed: ${AI_SEED:-'Not set'}"
;;
set)
if [[ -z "${2:-}" || -z "${3:-}" ]]; then log_error "Usage: ai --config set <key> <value>"; fi
set_config "$2" "$3"
;;
*)
log_error "Unknown config command: ${1:-}. Use 'view', 'set'."
;;
esac
}
handle_memory() {
case "${1:-}" in
search)
if [[ -z "${2:-}" ]]; then log_error "Usage: ai --memory search \"query\""; fi
search_memory "$2"
;;
clear)
clear_memory
;;
*)
log_error "Unknown memory command: ${1:-}. Use 'search', 'clear'."
;;
esac
}
handle_event() {
case "${1:-}" in
search)
if [[ -z "${2:-}" ]]; then log_error "Usage: ai --event search \"query\""; fi
search_events "$2"
;;
clear)
clear_events_db
;;
*)
log_error "Unknown event command: ${1:-}. Use 'search', 'clear'."
;;
esac
}
handle_hash() {
case "${1:-}" in
file)
if [[ -z "${2:-}" ]]; then log_error "Usage: ai --hash file <path>"; fi
if [[ -f "$2" ]]; then echo "$(gen_content_hash "$(cat "$2")")"; else log_error "File not found: $2"; fi
;;
event)
if [[ -z "${2:-}" ]]; then log_error "Usage: ai --hash event \"text\""; fi
gen_content_hash "$2"
;;
index)
list_event_index
;;
*)
log_error "Unknown hash command: ${1:-}. Use 'file', 'event', 'index'."
;;
esac
}
# -------------------- MAIN --------------------
main() {
mkdir -p "$AI_HOME" "$PROJECTS_DIR"
init_db
load_config_values
if [[ $# -eq 0 ]]; then
show_help
exit 0
fi
local arg="${1:-}"
shift
case "$arg" in
--help)
show_help
;;
--config) handle_config "$@" ;;
--memory) handle_memory "$@" ;;
--event) handle_event "$@" ;;
--hash) handle_hash "$@" ;;
--tools) list_tools ;;
--web-search)
if [[ $# -eq 0 ]]; then log_error "Usage: ai --web-search \"query\""; fi
tool_web_search "$@"
;;
--setup)
if $IS_TERMUX; then pkg install -y sqlite3 jq curl tree lynx; else sudo apt-get update && sudo apt-get install -y sqlite3 jq curl tree lynx; fi
log_success "Setup complete. Ensure Ollama is installed and running."
;;
--git)
# Placeholder for git_pull_push, not included in final script to reduce complexity
log_info "Git sync functionality placeholder."
;;
--websocket-mode)
# Placeholder for handle_websocket_mode, not included in final script
log_info "WebSocket mode functionality placeholder."
;;
-*)
log_error "Unknown option: $arg. Use 'ai --help' for usage."
;;
*) # Default: Treat as AI prompt
run_ai_orchestration "$arg $*"
;;
esac
}
trap 'log_warn "Interrupted AI orchestration process"; exit 1' INT TERM
[[ "${BASH_SOURCE[0]}" == "${0}" ]] && main "$@"