mirror of https://github.com/aliasrobotics/cai.git
Stream tests
This commit is contained in:
parent
c61f84a5ae
commit
20d9d736d6
|
|
@ -0,0 +1,2 @@
|
|||
# Simple Hola Mundo program in Python
|
||||
print("Hola Mundo")
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Mapeo básico de puertos a servicios comunes
|
||||
var commonPorts = map[int]string{
|
||||
20: "FTP-data", 21: "FTP", 22: "SSH", 23: "Telnet",
|
||||
25: "SMTP", 53: "DNS", 80: "HTTP", 110: "POP3",
|
||||
115: "SFTP", 135: "RPC", 139: "NetBIOS", 143: "IMAP",
|
||||
194: "IRC", 443: "HTTPS", 445: "SMB", 989: "FTPS-data",
|
||||
990: "FTPS", 1433: "MSSQL", 3306: "MySQL", 3389: "RDP",
|
||||
5432: "PostgreSQL", 5900: "VNC", 6379: "Redis", 8080: "HTTP-Proxy",
|
||||
8443: "HTTPS-Alt", 27017: "MongoDB",
|
||||
}
|
||||
|
||||
// Estructura para almacenar resultados
|
||||
type ScanResult struct {
|
||||
Port int
|
||||
State string
|
||||
Service string
|
||||
Banner string
|
||||
}
|
||||
|
||||
func scanPort(ip string, port int, timeout time.Duration) ScanResult {
|
||||
target := fmt.Sprintf("%s:%d", ip, port)
|
||||
conn, err := net.DialTimeout("tcp", target, timeout)
|
||||
|
||||
result := ScanResult{Port: port}
|
||||
|
||||
if err != nil {
|
||||
result.State = "closed"
|
||||
return result
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
result.State = "open"
|
||||
|
||||
// Intentar identificar el servicio
|
||||
if service, exists := commonPorts[port]; exists {
|
||||
result.Service = service
|
||||
} else {
|
||||
result.Service = "unknown"
|
||||
}
|
||||
|
||||
// Intentar obtener un banner
|
||||
if conn != nil {
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
banner := make([]byte, 1024)
|
||||
_, err := conn.Read(banner)
|
||||
if err == nil {
|
||||
result.Banner = strings.TrimSpace(string(banner))
|
||||
if len(result.Banner) > 100 {
|
||||
result.Banner = result.Banner[:100] + "..."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func main() {
|
||||
ip := "192.168.1.1"
|
||||
fmt.Printf("Iniciando escaneo de puertos en %s\n", ip)
|
||||
fmt.Println("---------------------------------------")
|
||||
|
||||
// Lista de puertos a escanear
|
||||
portsToScan := []int{}
|
||||
|
||||
// Agregar los puertos comunes
|
||||
for port := range commonPorts {
|
||||
portsToScan = append(portsToScan, port)
|
||||
}
|
||||
|
||||
// Agregar algunos puertos adicionales comunes
|
||||
additionalPorts := []int{8000, 8008, 8081, 8888, 9000, 9090}
|
||||
portsToScan = append(portsToScan, additionalPorts...)
|
||||
|
||||
// Ordenar puertos para una salida más legible
|
||||
sort.Ints(portsToScan)
|
||||
|
||||
// Configurar concurrencia
|
||||
var wg sync.WaitGroup
|
||||
var mutex sync.Mutex
|
||||
results := make(map[int]ScanResult)
|
||||
timeout := 500 * time.Millisecond
|
||||
|
||||
// Limitar la concurrencia para evitar problemas
|
||||
semaphore := make(chan struct{}, 100)
|
||||
|
||||
for _, port := range portsToScan {
|
||||
wg.Add(1)
|
||||
semaphore <- struct{}{}
|
||||
|
||||
go func(p int) {
|
||||
defer wg.Done()
|
||||
defer func() { <-semaphore }()
|
||||
|
||||
result := scanPort(ip, p, timeout)
|
||||
|
||||
mutex.Lock()
|
||||
results[p] = result
|
||||
mutex.Unlock()
|
||||
}(port)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// Mostrar resultados
|
||||
fmt.Println("PUERTO\tESTADO\tSERVICIO\tBANNER")
|
||||
fmt.Println("---------------------------------------")
|
||||
|
||||
openPorts := 0
|
||||
for _, port := range portsToScan {
|
||||
if result, exists := results[port]; exists && result.State == "open" {
|
||||
banner := result.Banner
|
||||
if banner != "" {
|
||||
banner = ": " + banner
|
||||
}
|
||||
fmt.Printf("%d\t%s\t%s\t%s\n", result.Port, result.State, result.Service, banner)
|
||||
openPorts++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("---------------------------------------")
|
||||
fmt.Printf("Escaneo completado: %d puertos abiertos encontrados en %s\n", openPorts, ip)
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import socket
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Define target
|
||||
target = "192.168.1.1"
|
||||
print(f"\nStarting scan on host: {target}")
|
||||
print("-" * 50)
|
||||
|
||||
# Get the current time when scan started
|
||||
t1 = datetime.now()
|
||||
|
||||
try:
|
||||
# Scan common ports
|
||||
common_ports = [21, 22, 23, 25, 53, 80, 110, 111, 135, 139, 143, 443, 445, 993, 995, 1723, 3306, 3389, 5900, 8080]
|
||||
|
||||
print(f"Scanning common ports on {target}...")
|
||||
|
||||
for port in common_ports:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
socket.setdefaulttimeout(1)
|
||||
|
||||
# Returns an error indicator
|
||||
result = s.connect_ex((target, port))
|
||||
|
||||
if result == 0:
|
||||
try:
|
||||
service = socket.getservbyport(port)
|
||||
print(f"Port {port}: OPEN - {service}")
|
||||
except:
|
||||
print(f"Port {port}: OPEN - Unknown service")
|
||||
s.close()
|
||||
|
||||
# Get the current time when scan completed
|
||||
t2 = datetime.now()
|
||||
|
||||
# Calculate the difference of time to know how long the scan took
|
||||
total = t2 - t1
|
||||
|
||||
# Print the information to screen
|
||||
print("-" * 50)
|
||||
print(f"Scanning completed in: {total}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nExiting program.")
|
||||
sys.exit()
|
||||
except socket.gaierror:
|
||||
print("\nHostname could not be resolved.")
|
||||
sys.exit()
|
||||
except socket.error:
|
||||
print("\nServer not responding.")
|
||||
sys.exit()
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Lista de puertos comunes para escanear
|
||||
var commonPorts = []int{
|
||||
20, 21, 22, 23, 25, 53, 80, 88, 110, 111, 135, 139, 143,
|
||||
443, 445, 465, 587, 993, 995, 1433, 1434, 3306, 3389, 5900,
|
||||
5901, 8080, 8443, 8888,
|
||||
}
|
||||
|
||||
// Información básica sobre servicios comunes por puerto
|
||||
var serviceMap = map[int]string{
|
||||
20: "FTP (data)",
|
||||
21: "FTP (control)",
|
||||
22: "SSH",
|
||||
23: "Telnet",
|
||||
25: "SMTP",
|
||||
53: "DNS",
|
||||
80: "HTTP",
|
||||
88: "Kerberos",
|
||||
110: "POP3",
|
||||
111: "RPC",
|
||||
135: "MSRPC",
|
||||
139: "NetBIOS",
|
||||
143: "IMAP",
|
||||
443: "HTTPS",
|
||||
445: "SMB",
|
||||
465: "SMTPS",
|
||||
587: "SMTP (submission)",
|
||||
993: "IMAPS",
|
||||
995: "POP3S",
|
||||
1433: "MSSQL",
|
||||
1434: "MSSQL Browser",
|
||||
3306: "MySQL",
|
||||
3389: "RDP",
|
||||
5900: "VNC",
|
||||
5901: "VNC",
|
||||
8080: "HTTP (alternate)",
|
||||
8443: "HTTPS (alternate)",
|
||||
8888: "HTTP (alternate)",
|
||||
}
|
||||
|
||||
// Estructura para almacenar resultados
|
||||
type ScanResult struct {
|
||||
Port int
|
||||
Status string
|
||||
Service string
|
||||
}
|
||||
|
||||
func scanPort(ip string, port int, wg *sync.WaitGroup, results chan<- ScanResult) {
|
||||
defer wg.Done()
|
||||
|
||||
address := ip + ":" + strconv.Itoa(port)
|
||||
conn, err := net.DialTimeout("tcp", address, 500*time.Millisecond)
|
||||
|
||||
if err != nil {
|
||||
// Puerto cerrado o filtrado
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
service := "Unknown"
|
||||
if serviceName, ok := serviceMap[port]; ok {
|
||||
service = serviceName
|
||||
}
|
||||
|
||||
results <- ScanResult{Port: port, Status: "open", Service: service}
|
||||
}
|
||||
|
||||
func grabBanner(ip string, port int) string {
|
||||
address := ip + ":" + strconv.Itoa(port)
|
||||
conn, err := net.DialTimeout("tcp", address, 1*time.Second)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Establecer un timeout para la lectura del banner
|
||||
conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
|
||||
// Buffer para recibir datos
|
||||
buffer := make([]byte, 1024)
|
||||
|
||||
// Intentar leer el banner
|
||||
_, err = conn.Read(buffer)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(buffer)
|
||||
}
|
||||
|
||||
func main() {
|
||||
target := "192.168.1.1"
|
||||
fmt.Printf("Iniciando escaneo de puertos en %s\n", target)
|
||||
fmt.Println("================================================")
|
||||
|
||||
// Canal para recopilar resultados
|
||||
results := make(chan ScanResult, len(commonPorts))
|
||||
|
||||
// WaitGroup para sincronizar goroutines
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Escanear puertos comunes
|
||||
for _, port := range commonPorts {
|
||||
wg.Add(1)
|
||||
go scanPort(target, port, &wg, results)
|
||||
}
|
||||
|
||||
// Crear una goroutine para cerrar el canal cuando todas las goroutines de escaneo terminen
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(results)
|
||||
}()
|
||||
|
||||
// Recopilar resultados
|
||||
var openPorts []ScanResult
|
||||
for result := range results {
|
||||
openPorts = append(openPorts, result)
|
||||
}
|
||||
|
||||
// Mostrar resultados de forma organizada
|
||||
if len(openPorts) == 0 {
|
||||
fmt.Println("No se encontraron puertos abiertos.")
|
||||
} else {
|
||||
fmt.Printf("Encontrados %d puertos abiertos:\n\n", len(openPorts))
|
||||
fmt.Printf("%-10s %-15s %s\n", "PUERTO", "SERVICIO", "DETALLES")
|
||||
fmt.Println("------------------------------------------")
|
||||
|
||||
for _, r := range openPorts {
|
||||
banner := grabBanner(target, r.Port)
|
||||
bannerInfo := ""
|
||||
if banner != "" {
|
||||
if len(banner) > 40 {
|
||||
bannerInfo = banner[:40] + "..."
|
||||
} else {
|
||||
bannerInfo = banner
|
||||
}
|
||||
}
|
||||
fmt.Printf("%-10d %-15s %s\n", r.Port, r.Service, bannerInfo)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\nEscaneo finalizado.")
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python3
|
||||
import socket
|
||||
import sys
|
||||
from datetime import datetime
|
||||
import concurrent.futures
|
||||
|
||||
# Define the target
|
||||
target = "192.168.1.1"
|
||||
print(f"Starting scan of {target} at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
# Function to scan a single port
|
||||
def scan_port(port):
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.settimeout(1)
|
||||
result = s.connect_ex((target, port))
|
||||
if result == 0:
|
||||
try:
|
||||
service = socket.getservbyport(port)
|
||||
return f"Port {port}: OPEN - {service}"
|
||||
except:
|
||||
return f"Port {port}: OPEN - Unknown service"
|
||||
s.close()
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
# List of common ports to scan
|
||||
common_ports = [20, 21, 22, 23, 25, 53, 80, 110, 123, 143, 443, 445, 3389, 8080, 8443]
|
||||
|
||||
print(f"Scanning common ports on {target}...")
|
||||
|
||||
# Use a thread pool to scan ports in parallel
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=25) as executor:
|
||||
results = executor.map(scan_port, common_ports)
|
||||
|
||||
# Print results
|
||||
for result in results:
|
||||
if result:
|
||||
print(result)
|
||||
|
||||
# Now do a scan of the first 1000 ports
|
||||
print(f"\nScanning ports 1-1000 on {target}...")
|
||||
open_ports = []
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
|
||||
results = executor.map(scan_port, range(1, 1001))
|
||||
|
||||
for result in results:
|
||||
if result:
|
||||
print(result)
|
||||
|
||||
print(f"Scan completed at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Mapeo básico de puertos a servicios comunes
|
||||
var commonPorts = map[int]string{
|
||||
20: "FTP-data", 21: "FTP", 22: "SSH", 23: "Telnet",
|
||||
25: "SMTP", 53: "DNS", 80: "HTTP", 110: "POP3",
|
||||
143: "IMAP", 443: "HTTPS", 445: "SMB", 3306: "MySQL",
|
||||
3389: "RDP", 8080: "HTTP-Proxy", 8443: "HTTPS-Alt",
|
||||
}
|
||||
|
||||
// Estructura para almacenar resultados
|
||||
type ScanResult struct {
|
||||
Port int
|
||||
State string
|
||||
Service string
|
||||
}
|
||||
|
||||
func scanPort(ip string, port int, timeout time.Duration) ScanResult {
|
||||
target := fmt.Sprintf("%s:%d", ip, port)
|
||||
conn, err := net.DialTimeout("tcp", target, timeout)
|
||||
|
||||
result := ScanResult{Port: port}
|
||||
|
||||
if err != nil {
|
||||
result.State = "closed"
|
||||
return result
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
result.State = "open"
|
||||
|
||||
// Identificar el servicio
|
||||
if service, exists := commonPorts[port]; exists {
|
||||
result.Service = service
|
||||
} else {
|
||||
result.Service = "unknown"
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func main() {
|
||||
ip := "192.168.1.1"
|
||||
fmt.Printf("Iniciando escaneo de puertos en %s\n", ip)
|
||||
fmt.Println("---------------------------------------")
|
||||
|
||||
// Lista de puertos a escanear
|
||||
portsToScan := []int{}
|
||||
|
||||
// Agregar los puertos comunes
|
||||
for port := range commonPorts {
|
||||
portsToScan = append(portsToScan, port)
|
||||
}
|
||||
|
||||
// Agregar algunos puertos adicionales
|
||||
additionalPorts := []int{8000, 8008, 8081, 8888, 9000, 9090}
|
||||
portsToScan = append(portsToScan, additionalPorts...)
|
||||
|
||||
// Ordenar puertos
|
||||
sort.Ints(portsToScan)
|
||||
|
||||
// Configurar concurrencia
|
||||
var wg sync.WaitGroup
|
||||
var mutex sync.Mutex
|
||||
results := make(map[int]ScanResult)
|
||||
timeout := 500 * time.Millisecond
|
||||
|
||||
// Limitar la concurrencia
|
||||
semaphore := make(chan struct{}, 50)
|
||||
|
||||
for _, port := range portsToScan {
|
||||
wg.Add(1)
|
||||
semaphore <- struct{}{}
|
||||
|
||||
go func(p int) {
|
||||
defer wg.Done()
|
||||
defer func() { <-semaphore }()
|
||||
|
||||
result := scanPort(ip, p, timeout)
|
||||
|
||||
mutex.Lock()
|
||||
results[p] = result
|
||||
mutex.Unlock()
|
||||
}(port)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// Mostrar resultados
|
||||
fmt.Println("PUERTO\tESTADO\tSERVICIO")
|
||||
fmt.Println("---------------------------------------")
|
||||
|
||||
openPorts := 0
|
||||
for _, port := range portsToScan {
|
||||
if result, exists := results[port]; exists && result.State == "open" {
|
||||
fmt.Printf("%d\t%s\t%s\n", result.Port, result.State, result.Service)
|
||||
openPorts++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("---------------------------------------")
|
||||
fmt.Printf("Escaneo completado: %d puertos abiertos encontrados en %s\n", openPorts, ip)
|
||||
}
|
||||
144
src/cai/util.py
144
src/cai/util.py
|
|
@ -27,6 +27,7 @@ from rich.panel import Panel
|
|||
from rich.console import Group
|
||||
from rich.box import ROUNDED
|
||||
from rich.table import Table
|
||||
import re
|
||||
|
||||
# Global timing variables for tracking active and idle time
|
||||
_active_timer_start = None
|
||||
|
|
@ -1913,62 +1914,105 @@ def _create_tool_panel_content(tool_name, args, output, execution_info=None, tok
|
|||
# Determine if we need specialized content formatting
|
||||
group_content = [header]
|
||||
|
||||
# Special handling for execute_code tool
|
||||
if tool_name == "execute_code" and isinstance(args, dict):
|
||||
command_type = args.get("command")
|
||||
actual_code = args.get("code")
|
||||
language = args.get("language", "python") # Default to python
|
||||
|
||||
# For execute command, show code and output panels
|
||||
if command_type == "execute" and actual_code:
|
||||
# Ensure language is a string for Syntax
|
||||
language_str = get_language_from_code_block(str(language))
|
||||
command = args.get("command")
|
||||
code_from_code_key = args.get("code")
|
||||
language_from_lang_key = args.get("language", "python")
|
||||
args_str_payload = args.get("args")
|
||||
|
||||
panel1_content_str = None
|
||||
panel1_language_name = "text"
|
||||
panel1_title = "Executed Command Details"
|
||||
panel1_border_style = "cyan" # Default for "executed code"
|
||||
|
||||
if command == "execute" and code_from_code_key:
|
||||
pass
|
||||
elif args_str_payload: # Covers 'cat << EOF', 'python3 script.py'
|
||||
panel1_content_str = args_str_payload
|
||||
inferred_lang_for_args = "text" # Default
|
||||
|
||||
if command and command.lower() == "cat" and \
|
||||
("<<" in args_str_payload or ">" in args_str_payload):
|
||||
# For cat with heredoc/redirection, infer from target file
|
||||
match = re.search(r'(?:>|>>)\s*([\w\./-]+\.\w+)',
|
||||
args_str_payload)
|
||||
if match:
|
||||
filename = match.group(1)
|
||||
ext = filename.split('.')[-1] if '.' in filename else ""
|
||||
inferred_lang_for_args = get_language_from_code_block(ext)
|
||||
else:
|
||||
inferred_lang_for_args = get_language_from_code_block("bash")
|
||||
elif re.match(r'^[\w\./-]+\.\w+$', args_str_payload.strip()):
|
||||
# If args_str_payload is a filename like "script.py"
|
||||
filename = args_str_payload.strip()
|
||||
ext = filename.split('.')[-1] if '.' in filename else ""
|
||||
inferred_lang_for_args = get_language_from_code_block(ext)
|
||||
else:
|
||||
# General arguments string, could be JSON, XML, or just text/bash
|
||||
try:
|
||||
json.loads(args_str_payload)
|
||||
inferred_lang_for_args = "json"
|
||||
except json.JSONDecodeError:
|
||||
if args_str_payload.strip().startswith("<") and \
|
||||
args_str_payload.strip().endswith(">"):
|
||||
inferred_lang_for_args = "xml"
|
||||
elif command: # Default to bash if it's for a known command
|
||||
inferred_lang_for_args = get_language_from_code_block("bash")
|
||||
|
||||
code_syntax = Syntax(actual_code, language_str, theme="monokai",
|
||||
line_numbers=True, background_color="#272822",
|
||||
indent_guides=True, word_wrap=True)
|
||||
code_panel = Panel(
|
||||
code_syntax,
|
||||
title=f"Code ({language_str})",
|
||||
border_style="cyan",
|
||||
panel1_language_name = inferred_lang_for_args
|
||||
panel1_title = f"Code ({panel1_language_name})"
|
||||
panel1_border_style = "yellow"
|
||||
|
||||
if panel1_content_str is not None:
|
||||
syntax_obj_panel1 = Syntax(
|
||||
panel1_content_str,
|
||||
panel1_language_name,
|
||||
theme="monokai",
|
||||
line_numbers=True,
|
||||
background_color="#272822",
|
||||
indent_guides=True,
|
||||
word_wrap=True
|
||||
)
|
||||
actual_panel1 = Panel(
|
||||
syntax_obj_panel1,
|
||||
title=panel1_title,
|
||||
border_style=panel1_border_style,
|
||||
title_align="left",
|
||||
box=ROUNDED,
|
||||
padding=(0,1)
|
||||
padding=(0, 1)
|
||||
)
|
||||
group_content.extend([Text("\n"), code_panel])
|
||||
group_content.extend([Text("\n"), actual_panel1])
|
||||
|
||||
if output:
|
||||
output_lang_name = "text"
|
||||
try:
|
||||
json.loads(output)
|
||||
output_lang_name = "json"
|
||||
except json.JSONDecodeError:
|
||||
if output.strip().startswith("<") and \
|
||||
output.strip().endswith(">") and \
|
||||
"<?xml" in output.lower():
|
||||
output_lang_name = "xml"
|
||||
|
||||
output_syntax = Syntax(
|
||||
output,
|
||||
get_language_from_code_block(output_lang_name),
|
||||
theme="monokai",
|
||||
background_color="#272822",
|
||||
word_wrap=True
|
||||
)
|
||||
|
||||
output_panel_title = "Output"
|
||||
if command and panel1_content_str: # If input panel was shown
|
||||
output_panel_title = f"Output of '{command}'"
|
||||
|
||||
# Panel for the output of the executed code
|
||||
if output:
|
||||
# Try to highlight output as text, or specific language if known (e.g. json)
|
||||
output_lang = "text"
|
||||
try:
|
||||
json.loads(output) # Check if output is JSON
|
||||
output_lang = "json"
|
||||
except json.JSONDecodeError:
|
||||
pass # Not JSON, keep as text
|
||||
|
||||
output_syntax = Syntax(output, output_lang, theme="monokai",
|
||||
background_color="#272822", word_wrap=True)
|
||||
output_panel = Panel(
|
||||
output_syntax,
|
||||
title="Output",
|
||||
border_style="green",
|
||||
title_align="left",
|
||||
box=ROUNDED,
|
||||
padding=(0,1)
|
||||
)
|
||||
group_content.extend([Text("\n"), output_panel])
|
||||
# For other commands (like cat) or if no code, just show output if any
|
||||
elif output:
|
||||
output_syntax = Syntax(output, "text", theme="monokai",
|
||||
background_color="#272822", word_wrap=True)
|
||||
output_panel = Panel(
|
||||
output_syntax,
|
||||
title="Output",
|
||||
title=output_panel_title,
|
||||
border_style="green",
|
||||
title_align="left",
|
||||
box=ROUNDED,
|
||||
padding=(0,1)
|
||||
padding=(0, 1)
|
||||
)
|
||||
group_content.extend([Text("\n"), output_panel])
|
||||
|
||||
|
|
@ -2005,6 +2049,11 @@ def _create_tool_panel_content(tool_name, args, output, execution_info=None, tok
|
|||
# Helper function to format tool arguments
|
||||
def _format_tool_args(args, tool_name=None):
|
||||
"""Format tool arguments as a clean string."""
|
||||
# If the tool is execute_code, we don't want to show any args in the main header,
|
||||
# as they are detailed in subsequent panels (either code or args string).
|
||||
if tool_name == "execute_code":
|
||||
return ""
|
||||
|
||||
# If args is already a string, it might be pre-formatted or a simple arg string
|
||||
if isinstance(args, str):
|
||||
# If it looks like a JSON dict string, try to parse and format nicely
|
||||
|
|
@ -2026,6 +2075,11 @@ def _format_tool_args(args, tool_name=None):
|
|||
# Only include non-empty values and exclude special flags
|
||||
arg_parts = []
|
||||
for key, value in args.items():
|
||||
# For execute_code, if the 'code' key is present, its content is shown in a dedicated panel.
|
||||
# So, skip adding 'code=...' to the header string to avoid redundancy and verbosity.
|
||||
if tool_name == "execute_code" and key == "code":
|
||||
continue
|
||||
|
||||
# Skip empty values
|
||||
if value == "" or value == {} or value is None:
|
||||
continue
|
||||
|
|
|
|||
Loading…
Reference in New Issue