- Auth: Login/Register con creacion de clinica - Dashboard: KPIs reales, graficas recharts - Pacientes: CRUD completo con busqueda - Agenda: FullCalendar, drag-and-drop, vista recepcion - Expediente: Notas SOAP, signos vitales, CIE-10 - Facturacion: Facturas con IVA, campos CFDI SAT - Inventario: Productos, stock, movimientos, alertas - Configuracion: Clinica, equipo, catalogo servicios - Supabase self-hosted: 18 tablas con RLS multi-tenant - Docker + Nginx para produccion Co-Authored-By: claude-flow <ruv@ruv.net>
354 lines
9.6 KiB
Bash
Executable File
354 lines
9.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Claude Flow V3 - Optimized Swarm Communications
|
|
# Non-blocking, batched, priority-based inter-agent messaging
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
SWARM_DIR="$PROJECT_ROOT/.claude-flow/swarm"
|
|
QUEUE_DIR="$SWARM_DIR/queue"
|
|
BATCH_DIR="$SWARM_DIR/batch"
|
|
POOL_FILE="$SWARM_DIR/connection-pool.json"
|
|
|
|
mkdir -p "$QUEUE_DIR" "$BATCH_DIR"
|
|
|
|
# Priority levels
|
|
PRIORITY_CRITICAL=0
|
|
PRIORITY_HIGH=1
|
|
PRIORITY_NORMAL=2
|
|
PRIORITY_LOW=3
|
|
|
|
# Batch settings
|
|
BATCH_SIZE=10
|
|
BATCH_TIMEOUT_MS=100
|
|
|
|
# =============================================================================
|
|
# NON-BLOCKING MESSAGE QUEUE
|
|
# =============================================================================
|
|
|
|
# Enqueue message (instant return, async processing)
|
|
enqueue() {
|
|
local to="${1:-*}"
|
|
local content="${2:-}"
|
|
local priority="${3:-$PRIORITY_NORMAL}"
|
|
local msg_type="${4:-context}"
|
|
|
|
local msg_id="msg_$(date +%s%N)"
|
|
local timestamp=$(date +%s)
|
|
|
|
# Write to priority queue (non-blocking)
|
|
cat > "$QUEUE_DIR/${priority}_${msg_id}.json" << EOF
|
|
{"id":"$msg_id","to":"$to","content":"$content","type":"$msg_type","priority":$priority,"timestamp":$timestamp}
|
|
EOF
|
|
|
|
echo "$msg_id"
|
|
}
|
|
|
|
# Process queue in background
|
|
process_queue() {
|
|
local processed=0
|
|
|
|
# Process by priority (0=critical first)
|
|
for priority in 0 1 2 3; do
|
|
shopt -s nullglob
|
|
for msg_file in "$QUEUE_DIR"/${priority}_*.json; do
|
|
[ -f "$msg_file" ] || continue
|
|
|
|
# Process message
|
|
local msg=$(cat "$msg_file")
|
|
local to=$(echo "$msg" | jq -r '.to' 2>/dev/null)
|
|
|
|
# Route to agent mailbox
|
|
if [ "$to" != "*" ]; then
|
|
mkdir -p "$SWARM_DIR/mailbox/$to"
|
|
mv "$msg_file" "$SWARM_DIR/mailbox/$to/"
|
|
else
|
|
# Broadcast - copy to all agent mailboxes
|
|
for agent_dir in "$SWARM_DIR/mailbox"/*; do
|
|
[ -d "$agent_dir" ] && cp "$msg_file" "$agent_dir/"
|
|
done
|
|
rm "$msg_file"
|
|
fi
|
|
|
|
processed=$((processed + 1))
|
|
done
|
|
done
|
|
|
|
echo "$processed"
|
|
}
|
|
|
|
# =============================================================================
|
|
# MESSAGE BATCHING
|
|
# =============================================================================
|
|
|
|
# Add to batch (collects messages, flushes when full or timeout)
|
|
batch_add() {
|
|
local agent_id="${1:-}"
|
|
local content="${2:-}"
|
|
local batch_file="$BATCH_DIR/${agent_id}.batch"
|
|
|
|
# Append to batch
|
|
echo "$content" >> "$batch_file"
|
|
|
|
# Check batch size
|
|
local count=$(wc -l < "$batch_file" 2>/dev/null || echo "0")
|
|
|
|
if [ "$count" -ge "$BATCH_SIZE" ]; then
|
|
batch_flush "$agent_id"
|
|
fi
|
|
}
|
|
|
|
# Flush batch (send all at once)
|
|
batch_flush() {
|
|
local agent_id="${1:-}"
|
|
local batch_file="$BATCH_DIR/${agent_id}.batch"
|
|
|
|
if [ -f "$batch_file" ]; then
|
|
local content=$(cat "$batch_file")
|
|
rm "$batch_file"
|
|
|
|
# Send as single batched message
|
|
enqueue "$agent_id" "$content" "$PRIORITY_NORMAL" "batch"
|
|
fi
|
|
}
|
|
|
|
# Flush all pending batches
|
|
batch_flush_all() {
|
|
shopt -s nullglob
|
|
for batch_file in "$BATCH_DIR"/*.batch; do
|
|
[ -f "$batch_file" ] || continue
|
|
local agent_id=$(basename "$batch_file" .batch)
|
|
batch_flush "$agent_id"
|
|
done
|
|
}
|
|
|
|
# =============================================================================
|
|
# CONNECTION POOLING
|
|
# =============================================================================
|
|
|
|
# Initialize connection pool
|
|
pool_init() {
|
|
cat > "$POOL_FILE" << EOF
|
|
{
|
|
"maxConnections": 10,
|
|
"activeConnections": 0,
|
|
"available": [],
|
|
"inUse": [],
|
|
"lastUpdated": "$(date -Iseconds)"
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Get connection from pool (or create new)
|
|
pool_acquire() {
|
|
local agent_id="${1:-}"
|
|
|
|
if [ ! -f "$POOL_FILE" ]; then
|
|
pool_init
|
|
fi
|
|
|
|
# Check for available connection
|
|
local available=$(jq -r '.available[0] // ""' "$POOL_FILE" 2>/dev/null)
|
|
|
|
if [ -n "$available" ]; then
|
|
# Reuse existing connection
|
|
jq ".available = .available[1:] | .inUse += [\"$available\"]" "$POOL_FILE" > "$POOL_FILE.tmp" && mv "$POOL_FILE.tmp" "$POOL_FILE"
|
|
echo "$available"
|
|
else
|
|
# Create new connection ID
|
|
local conn_id="conn_$(date +%s%N | tail -c 8)"
|
|
jq ".inUse += [\"$conn_id\"] | .activeConnections += 1" "$POOL_FILE" > "$POOL_FILE.tmp" && mv "$POOL_FILE.tmp" "$POOL_FILE"
|
|
echo "$conn_id"
|
|
fi
|
|
}
|
|
|
|
# Release connection back to pool
|
|
pool_release() {
|
|
local conn_id="${1:-}"
|
|
|
|
if [ -f "$POOL_FILE" ]; then
|
|
jq ".inUse = (.inUse | map(select(. != \"$conn_id\"))) | .available += [\"$conn_id\"]" "$POOL_FILE" > "$POOL_FILE.tmp" && mv "$POOL_FILE.tmp" "$POOL_FILE"
|
|
fi
|
|
}
|
|
|
|
# =============================================================================
|
|
# ASYNC PATTERN BROADCAST
|
|
# =============================================================================
|
|
|
|
# Broadcast pattern to swarm (non-blocking)
|
|
broadcast_pattern_async() {
|
|
local strategy="${1:-}"
|
|
local domain="${2:-general}"
|
|
local quality="${3:-0.7}"
|
|
|
|
# Fire and forget
|
|
(
|
|
local broadcast_id="pattern_$(date +%s%N)"
|
|
|
|
# Write pattern broadcast
|
|
mkdir -p "$SWARM_DIR/patterns"
|
|
cat > "$SWARM_DIR/patterns/$broadcast_id.json" << EOF
|
|
{"id":"$broadcast_id","strategy":"$strategy","domain":"$domain","quality":$quality,"timestamp":$(date +%s),"status":"pending"}
|
|
EOF
|
|
|
|
# Notify all agents via queue
|
|
enqueue "*" "{\"type\":\"pattern_broadcast\",\"id\":\"$broadcast_id\"}" "$PRIORITY_HIGH" "event"
|
|
|
|
) &
|
|
|
|
echo "pattern_broadcast_queued"
|
|
}
|
|
|
|
# =============================================================================
|
|
# OPTIMIZED CONSENSUS
|
|
# =============================================================================
|
|
|
|
# Start consensus (non-blocking)
|
|
start_consensus_async() {
|
|
local question="${1:-}"
|
|
local options="${2:-}"
|
|
local timeout="${3:-30}"
|
|
|
|
(
|
|
local consensus_id="consensus_$(date +%s%N)"
|
|
mkdir -p "$SWARM_DIR/consensus"
|
|
|
|
cat > "$SWARM_DIR/consensus/$consensus_id.json" << EOF
|
|
{"id":"$consensus_id","question":"$question","options":"$options","votes":{},"timeout":$timeout,"created":$(date +%s),"status":"open"}
|
|
EOF
|
|
|
|
# Notify agents
|
|
enqueue "*" "{\"type\":\"consensus_request\",\"id\":\"$consensus_id\"}" "$PRIORITY_HIGH" "event"
|
|
|
|
# Auto-resolve after timeout (background)
|
|
(
|
|
sleep "$timeout"
|
|
if [ -f "$SWARM_DIR/consensus/$consensus_id.json" ]; then
|
|
jq '.status = "resolved"' "$SWARM_DIR/consensus/$consensus_id.json" > "$SWARM_DIR/consensus/$consensus_id.json.tmp" && mv "$SWARM_DIR/consensus/$consensus_id.json.tmp" "$SWARM_DIR/consensus/$consensus_id.json"
|
|
fi
|
|
) &
|
|
|
|
echo "$consensus_id"
|
|
) &
|
|
}
|
|
|
|
# Vote on consensus (non-blocking)
|
|
vote_async() {
|
|
local consensus_id="${1:-}"
|
|
local vote="${2:-}"
|
|
local agent_id="${AGENTIC_FLOW_AGENT_ID:-anonymous}"
|
|
|
|
(
|
|
local file="$SWARM_DIR/consensus/$consensus_id.json"
|
|
if [ -f "$file" ]; then
|
|
jq ".votes[\"$agent_id\"] = \"$vote\"" "$file" > "$file.tmp" && mv "$file.tmp" "$file"
|
|
fi
|
|
) &
|
|
}
|
|
|
|
# =============================================================================
|
|
# PERFORMANCE METRICS
|
|
# =============================================================================
|
|
|
|
get_comms_stats() {
|
|
local queued=$(ls "$QUEUE_DIR"/*.json 2>/dev/null | wc -l | tr -d '[:space:]')
|
|
queued=${queued:-0}
|
|
local batched=$(ls "$BATCH_DIR"/*.batch 2>/dev/null | wc -l | tr -d '[:space:]')
|
|
batched=${batched:-0}
|
|
local patterns=$(ls "$SWARM_DIR/patterns"/*.json 2>/dev/null | wc -l | tr -d '[:space:]')
|
|
patterns=${patterns:-0}
|
|
local consensus=$(ls "$SWARM_DIR/consensus"/*.json 2>/dev/null | wc -l | tr -d '[:space:]')
|
|
consensus=${consensus:-0}
|
|
|
|
local pool_active=0
|
|
if [ -f "$POOL_FILE" ]; then
|
|
pool_active=$(jq '.activeConnections // 0' "$POOL_FILE" 2>/dev/null | tr -d '[:space:]')
|
|
pool_active=${pool_active:-0}
|
|
fi
|
|
|
|
echo "{\"queue\":$queued,\"batch\":$batched,\"patterns\":$patterns,\"consensus\":$consensus,\"pool\":$pool_active}"
|
|
}
|
|
|
|
# =============================================================================
|
|
# MAIN DISPATCHER
|
|
# =============================================================================
|
|
|
|
case "${1:-help}" in
|
|
# Queue operations
|
|
"enqueue"|"send")
|
|
enqueue "${2:-*}" "${3:-}" "${4:-2}" "${5:-context}"
|
|
;;
|
|
"process")
|
|
process_queue
|
|
;;
|
|
|
|
# Batch operations
|
|
"batch")
|
|
batch_add "${2:-}" "${3:-}"
|
|
;;
|
|
"flush")
|
|
batch_flush_all
|
|
;;
|
|
|
|
# Pool operations
|
|
"acquire")
|
|
pool_acquire "${2:-}"
|
|
;;
|
|
"release")
|
|
pool_release "${2:-}"
|
|
;;
|
|
|
|
# Async operations
|
|
"broadcast-pattern")
|
|
broadcast_pattern_async "${2:-}" "${3:-general}" "${4:-0.7}"
|
|
;;
|
|
"consensus")
|
|
start_consensus_async "${2:-}" "${3:-}" "${4:-30}"
|
|
;;
|
|
"vote")
|
|
vote_async "${2:-}" "${3:-}"
|
|
;;
|
|
|
|
# Stats
|
|
"stats")
|
|
get_comms_stats
|
|
;;
|
|
|
|
"help"|*)
|
|
cat << 'EOF'
|
|
Claude Flow V3 - Optimized Swarm Communications
|
|
|
|
Non-blocking, batched, priority-based inter-agent messaging.
|
|
|
|
Usage: swarm-comms.sh <command> [args]
|
|
|
|
Queue (Non-blocking):
|
|
enqueue <to> <content> [priority] [type] Add to queue (instant return)
|
|
process Process pending queue
|
|
|
|
Batching:
|
|
batch <agent> <content> Add to batch
|
|
flush Flush all batches
|
|
|
|
Connection Pool:
|
|
acquire [agent] Get connection from pool
|
|
release <conn_id> Return connection to pool
|
|
|
|
Async Operations:
|
|
broadcast-pattern <strategy> [domain] [quality] Async pattern broadcast
|
|
consensus <question> <options> [timeout] Start async consensus
|
|
vote <consensus_id> <vote> Vote (non-blocking)
|
|
|
|
Stats:
|
|
stats Get communication stats
|
|
|
|
Priority Levels:
|
|
0 = Critical (processed first)
|
|
1 = High
|
|
2 = Normal (default)
|
|
3 = Low
|
|
EOF
|
|
;;
|
|
esac
|