Initial monorepo — everything BlackRoad in one place
bin/ 230 CLI tools (ask-*, br-*, agent-*, roadid, carpool) scripts/ 99 automation scripts fleet/ Node configs and deployment workers/ Cloudflare Worker sources (roadpay, road-search, squad webhooks) roadc/ RoadC programming language roadnet/ Mesh network (5 APs, WireGuard) operator/ Memory system scripts config/ System configs dotfiles/ Shell configs docs/ Documentation BlackRoad OS — Pave Tomorrow. RoadChain-SHA2048: d1a24f55318d338b RoadChain-Identity: alexa@sovereign RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
This commit is contained in:
636
operator/memory/memory-task-marketplace.sh
Executable file
636
operator/memory/memory-task-marketplace.sh
Executable file
@@ -0,0 +1,636 @@
|
||||
#!/bin/bash
|
||||
|
||||
# BlackRoad Task Marketplace - Where Claudes find work!
|
||||
# A revolutionary system for multi-Claude coordination at scale
|
||||
# Now powered by SQLite for 100x faster operations
|
||||
|
||||
TASKS_DB="$HOME/.blackroad/memory/tasks.db"
|
||||
|
||||
# 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'
|
||||
|
||||
# Check for SQLite DB — backward compatibility
|
||||
check_db() {
|
||||
if [[ ! -f "$TASKS_DB" ]] || [[ ! -s "$TASKS_DB" ]]; then
|
||||
echo -e "${RED}Database not found or empty at $TASKS_DB${NC}"
|
||||
echo -e "${YELLOW}Initialize with:${NC} ${CYAN}$0 init${NC}"
|
||||
echo -e "${YELLOW}Or migrate with:${NC} ${CYAN}~/blackroad-operator/scripts/memory/migrate-tasks-to-sqlite.sh${NC}"
|
||||
exit 1
|
||||
fi
|
||||
# Verify schema exists
|
||||
local has_table
|
||||
has_table=$(sqlite3 "$TASKS_DB" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='tasks';" 2>/dev/null)
|
||||
if [[ "$has_table" != "1" ]]; then
|
||||
echo -e "${RED}Database exists but has no tasks table. Re-initialize:${NC}"
|
||||
echo -e " ${CYAN}$0 init${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Helper: run a query
|
||||
sql() {
|
||||
sqlite3 "$TASKS_DB" "$@"
|
||||
}
|
||||
|
||||
# Initialize marketplace (create DB + schema if needed)
|
||||
init_marketplace() {
|
||||
mkdir -p "$(dirname "$TASKS_DB")"
|
||||
|
||||
# Check if DB already has the tasks table
|
||||
if [[ -f "$TASKS_DB" ]] && [[ -s "$TASKS_DB" ]]; then
|
||||
local has_table
|
||||
has_table=$(sqlite3 "$TASKS_DB" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='tasks';" 2>/dev/null)
|
||||
if [[ "$has_table" == "1" ]]; then
|
||||
echo -e "${GREEN}Task Marketplace already initialized at $TASKS_DB${NC}"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
# Remove empty/corrupt DB file if present
|
||||
rm -f "$TASKS_DB"
|
||||
|
||||
sqlite3 "$TASKS_DB" <<'SQL'
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
task_id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT DEFAULT '',
|
||||
priority TEXT DEFAULT 'medium',
|
||||
tags TEXT DEFAULT 'general',
|
||||
skills TEXT DEFAULT 'any',
|
||||
status TEXT NOT NULL DEFAULT 'available',
|
||||
posted_at TEXT,
|
||||
posted_by TEXT DEFAULT 'unknown',
|
||||
claimed_by TEXT,
|
||||
claimed_at TEXT,
|
||||
timeout_at TEXT,
|
||||
completed_at TEXT,
|
||||
result TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_claimed_by ON tasks(claimed_by);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_posted_at ON tasks(posted_at);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tasks_fts USING fts5(
|
||||
task_id,
|
||||
title,
|
||||
description,
|
||||
tags
|
||||
);
|
||||
SQL
|
||||
|
||||
echo -e "${GREEN}Task Marketplace initialized at $TASKS_DB${NC}"
|
||||
}
|
||||
|
||||
# Post a new task
|
||||
post_task() {
|
||||
local task_id="$1"
|
||||
local title="$2"
|
||||
local description="$3"
|
||||
local priority="${4:-medium}"
|
||||
local tags="${5:-general}"
|
||||
local skills="${6:-any}"
|
||||
|
||||
if [[ -z "$task_id" || -z "$title" ]]; then
|
||||
echo -e "${RED}Usage: post <task-id> <title> <description> [priority] [tags] [skills]${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
check_db
|
||||
|
||||
local timestamp
|
||||
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
||||
local posted_by="${MY_CLAUDE:-unknown}"
|
||||
|
||||
local esc_id esc_title esc_desc esc_priority esc_tags esc_skills esc_posted_by
|
||||
esc_id=$(echo "$task_id" | sed "s/'/''/g")
|
||||
esc_title=$(echo "$title" | sed "s/'/''/g")
|
||||
esc_desc=$(echo "$description" | sed "s/'/''/g")
|
||||
esc_priority=$(echo "$priority" | sed "s/'/''/g")
|
||||
esc_tags=$(echo "$tags" | sed "s/'/''/g")
|
||||
esc_skills=$(echo "$skills" | sed "s/'/''/g")
|
||||
esc_posted_by=$(echo "$posted_by" | sed "s/'/''/g")
|
||||
|
||||
sql "BEGIN TRANSACTION;
|
||||
INSERT INTO tasks (task_id, title, description, priority, tags, skills, status, posted_at, posted_by)
|
||||
VALUES ('$esc_id', '$esc_title', '$esc_desc', '$esc_priority', '$esc_tags', '$esc_skills', 'available', '$timestamp', '$esc_posted_by')
|
||||
ON CONFLICT(task_id) DO UPDATE SET
|
||||
title=excluded.title, description=excluded.description, priority=excluded.priority,
|
||||
tags=excluded.tags, skills=excluded.skills, posted_at=excluded.posted_at, posted_by=excluded.posted_by;
|
||||
DELETE FROM tasks_fts WHERE task_id='$esc_id';
|
||||
INSERT INTO tasks_fts (task_id, title, description, tags)
|
||||
VALUES ('$esc_id', '$esc_title', '$esc_desc', '$esc_tags');
|
||||
COMMIT;"
|
||||
|
||||
# Log to memory system
|
||||
if [[ -x ~/memory-system.sh ]]; then
|
||||
~/memory-system.sh log task-posted "$task_id" "New task: $title (Priority: $priority, Skills: $skills, Tags: $tags)" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Task posted: ${CYAN}$task_id${NC}"
|
||||
echo -e " ${BLUE}Title:${NC} $title"
|
||||
echo -e " ${BLUE}Priority:${NC} $priority"
|
||||
echo -e " ${BLUE}Skills:${NC} $skills"
|
||||
}
|
||||
|
||||
# List available tasks
|
||||
list_tasks() {
|
||||
local filter_priority="$1"
|
||||
local filter_tags="$2"
|
||||
|
||||
check_db
|
||||
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ BLACKROAD TASK MARKETPLACE ║${NC}"
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
local available_count claimed_count completed_count
|
||||
available_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='available';")
|
||||
claimed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='claimed';")
|
||||
completed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='completed';")
|
||||
|
||||
echo -e "${GREEN}Available:${NC} $available_count ${YELLOW}In Progress:${NC} $claimed_count ${BLUE}Completed:${NC} $completed_count"
|
||||
echo ""
|
||||
|
||||
if [[ "$available_count" -eq 0 ]]; then
|
||||
echo -e "${YELLOW}No tasks available. Post one with: ./memory-task-marketplace.sh post <task-id> <title> <description>${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
|
||||
# Build query with optional filters
|
||||
local where="WHERE status='available'"
|
||||
if [[ -n "$filter_priority" ]]; then
|
||||
where="$where AND priority='$(echo "$filter_priority" | sed "s/'/''/g")'"
|
||||
fi
|
||||
if [[ -n "$filter_tags" ]]; then
|
||||
where="$where AND tags LIKE '%$(echo "$filter_tags" | sed "s/'/''/g")%'"
|
||||
fi
|
||||
|
||||
local IFS=$'\n'
|
||||
local rows
|
||||
rows=$(sql -separator '|' "SELECT task_id, title, priority, tags, skills, posted_at FROM tasks $where ORDER BY
|
||||
CASE priority WHEN 'urgent' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END,
|
||||
posted_at DESC;")
|
||||
|
||||
for row in $rows; do
|
||||
local task_id title priority tags skills posted_at
|
||||
task_id=$(echo "$row" | cut -d'|' -f1)
|
||||
title=$(echo "$row" | cut -d'|' -f2)
|
||||
priority=$(echo "$row" | cut -d'|' -f3)
|
||||
tags=$(echo "$row" | cut -d'|' -f4)
|
||||
skills=$(echo "$row" | cut -d'|' -f5)
|
||||
posted_at=$(echo "$row" | cut -d'|' -f6)
|
||||
|
||||
# Priority color
|
||||
local priority_color="$NC"
|
||||
case "$priority" in
|
||||
high|urgent) priority_color="$RED" ;;
|
||||
medium) priority_color="$YELLOW" ;;
|
||||
low) priority_color="$GREEN" ;;
|
||||
esac
|
||||
|
||||
echo -e "${CYAN}$task_id${NC}"
|
||||
echo -e " ${BLUE}Title:${NC} $title"
|
||||
echo -e " ${BLUE}Priority:${NC} ${priority_color}$priority${NC}"
|
||||
echo -e " ${BLUE}Skills:${NC} $skills"
|
||||
echo -e " ${BLUE}Tags:${NC} $tags"
|
||||
echo -e " ${BLUE}Posted:${NC} $posted_at"
|
||||
echo -e " ${GREEN}Claim with:${NC} ./memory-task-marketplace.sh claim $task_id"
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
}
|
||||
|
||||
# Claim a task
|
||||
claim_task() {
|
||||
local task_id="$1"
|
||||
local claude_id="${2:-${MY_CLAUDE:-unknown}}"
|
||||
local timeout_minutes="${3:-30}"
|
||||
|
||||
if [[ -z "$task_id" ]]; then
|
||||
echo -e "${RED}Usage: claim <task-id> [claude-id] [timeout-minutes]${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
check_db
|
||||
|
||||
# Check task exists and is available
|
||||
local current_status
|
||||
current_status=$(sql "SELECT status FROM tasks WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")';")
|
||||
|
||||
if [[ -z "$current_status" ]]; then
|
||||
echo -e "${RED}Task not found: $task_id${NC}"
|
||||
echo -e "${YELLOW}Available tasks:${NC}"
|
||||
sql "SELECT ' - ' || task_id FROM tasks WHERE status='available' LIMIT 20;"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$current_status" != "available" ]]; then
|
||||
echo -e "${RED}Task $task_id is not available (status: $current_status)${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local timestamp timeout_at
|
||||
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
||||
timeout_at=$(date -u -v+"${timeout_minutes}"M +"%Y-%m-%dT%H:%M:%S.%3NZ" 2>/dev/null || date -u -d "+${timeout_minutes} minutes" +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
||||
|
||||
sql "BEGIN TRANSACTION;
|
||||
UPDATE tasks SET
|
||||
status='claimed',
|
||||
claimed_by='$(echo "$claude_id" | sed "s/'/''/g")',
|
||||
claimed_at='$timestamp',
|
||||
timeout_at='$timeout_at'
|
||||
WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")' AND status='available';
|
||||
COMMIT;"
|
||||
|
||||
# Log to memory
|
||||
if [[ -x ~/memory-system.sh ]]; then
|
||||
~/memory-system.sh log task-claimed "$task_id" "Claimed by $claude_id (timeout: ${timeout_minutes}m)" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Task claimed: ${CYAN}$task_id${NC}"
|
||||
echo -e " ${BLUE}Claimed by:${NC} $claude_id"
|
||||
echo -e " ${BLUE}Timeout:${NC} ${timeout_minutes} minutes ($timeout_at)"
|
||||
echo -e " ${YELLOW}Complete with:${NC} ./memory-task-marketplace.sh complete $task_id"
|
||||
}
|
||||
|
||||
# Complete a task
|
||||
complete_task() {
|
||||
local task_id="$1"
|
||||
local result="${2:-Success}"
|
||||
|
||||
if [[ -z "$task_id" ]]; then
|
||||
echo -e "${RED}Usage: complete <task-id> [result]${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
check_db
|
||||
|
||||
local current_status
|
||||
current_status=$(sql "SELECT status FROM tasks WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")';")
|
||||
|
||||
if [[ "$current_status" != "claimed" ]]; then
|
||||
echo -e "${RED}Claimed task not found: $task_id (status: ${current_status:-not found})${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local timestamp
|
||||
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
||||
|
||||
sql "BEGIN TRANSACTION;
|
||||
UPDATE tasks SET
|
||||
status='completed',
|
||||
completed_at='$timestamp',
|
||||
result='$(echo "$result" | sed "s/'/''/g")'
|
||||
WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")' AND status='claimed';
|
||||
COMMIT;"
|
||||
|
||||
# Log to memory
|
||||
if [[ -x ~/memory-system.sh ]]; then
|
||||
~/memory-system.sh log task-completed "$task_id" "Completed: $result" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Task completed: ${CYAN}$task_id${NC}"
|
||||
echo -e " ${BLUE}Result:${NC} $result"
|
||||
}
|
||||
|
||||
# Release a task (if can't complete)
|
||||
release_task() {
|
||||
local task_id="$1"
|
||||
local reason="${2:-No reason given}"
|
||||
|
||||
if [[ -z "$task_id" ]]; then
|
||||
echo -e "${RED}Usage: release <task-id> [reason]${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
check_db
|
||||
|
||||
local current_status
|
||||
current_status=$(sql "SELECT status FROM tasks WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")';")
|
||||
|
||||
if [[ "$current_status" != "claimed" ]]; then
|
||||
echo -e "${RED}Claimed task not found: $task_id (status: ${current_status:-not found})${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sql "BEGIN TRANSACTION;
|
||||
UPDATE tasks SET
|
||||
status='available',
|
||||
claimed_by=NULL,
|
||||
claimed_at=NULL,
|
||||
timeout_at=NULL
|
||||
WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")' AND status='claimed';
|
||||
COMMIT;"
|
||||
|
||||
# Log to memory
|
||||
if [[ -x ~/memory-system.sh ]]; then
|
||||
~/memory-system.sh log task-released "$task_id" "Released: $reason" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Task released: ${CYAN}$task_id${NC}"
|
||||
echo -e " ${BLUE}Reason:${NC} $reason"
|
||||
}
|
||||
|
||||
# Show tasks claimed by current Claude
|
||||
my_tasks() {
|
||||
check_db
|
||||
|
||||
local claude_id="${MY_CLAUDE:-unknown}"
|
||||
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ My Tasks ($claude_id) ║${NC}"
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
local IFS=$'\n'
|
||||
local rows
|
||||
rows=$(sql -separator '|' "SELECT task_id, title, claimed_at, timeout_at FROM tasks
|
||||
WHERE status='claimed' AND claimed_by='$(echo "$claude_id" | sed "s/'/''/g")'
|
||||
ORDER BY claimed_at DESC;")
|
||||
|
||||
if [[ -z "$rows" ]]; then
|
||||
echo -e "${YELLOW}No tasks claimed by you. Browse available tasks with: ./memory-task-marketplace.sh list${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
for row in $rows; do
|
||||
local task_id title claimed_at timeout_at
|
||||
task_id=$(echo "$row" | cut -d'|' -f1)
|
||||
title=$(echo "$row" | cut -d'|' -f2)
|
||||
claimed_at=$(echo "$row" | cut -d'|' -f3)
|
||||
timeout_at=$(echo "$row" | cut -d'|' -f4)
|
||||
|
||||
echo -e "${CYAN}$task_id${NC}"
|
||||
echo -e " ${BLUE}Title:${NC} $title"
|
||||
echo -e " ${BLUE}Claimed:${NC} $claimed_at"
|
||||
echo -e " ${BLUE}Timeout:${NC} $timeout_at"
|
||||
echo -e " ${GREEN}Complete:${NC} ./memory-task-marketplace.sh complete $task_id"
|
||||
echo ""
|
||||
done
|
||||
}
|
||||
|
||||
# Show statistics
|
||||
show_stats() {
|
||||
check_db
|
||||
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Task Marketplace Statistics ║${NC}"
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
local available_count claimed_count completed_count total
|
||||
available_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='available';")
|
||||
claimed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='claimed';")
|
||||
completed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='completed';")
|
||||
total=$(sql "SELECT COUNT(*) FROM tasks;")
|
||||
|
||||
echo -e "${GREEN}Total Tasks:${NC} $total"
|
||||
echo -e "${YELLOW}Available:${NC} $available_count"
|
||||
echo -e "${BLUE}Claimed:${NC} $claimed_count"
|
||||
echo -e "${PURPLE}Completed:${NC} $completed_count"
|
||||
echo ""
|
||||
|
||||
if [[ "$total" -gt 0 ]]; then
|
||||
local completion_rate=$((completed_count * 100 / total))
|
||||
echo -e "${GREEN}Completion Rate:${NC} ${completion_rate}%"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Priority breakdown
|
||||
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BLUE}By Priority:${NC}"
|
||||
local IFS=$'\n'
|
||||
local prows
|
||||
prows=$(sql -separator '|' "SELECT priority, COUNT(*) FROM tasks WHERE status='available' GROUP BY priority ORDER BY
|
||||
CASE priority WHEN 'urgent' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END;")
|
||||
for row in $prows; do
|
||||
local p c
|
||||
p=$(echo "$row" | cut -d'|' -f1)
|
||||
c=$(echo "$row" | cut -d'|' -f2)
|
||||
echo -e " ${YELLOW}$p:${NC} $c"
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
# Active workers
|
||||
if [[ "$claimed_count" -gt 0 ]]; then
|
||||
echo -e "${BLUE}Active Workers:${NC}"
|
||||
local wrows
|
||||
wrows=$(sql -separator '|' "SELECT claimed_by, task_id, title FROM tasks WHERE status='claimed' ORDER BY claimed_at DESC;")
|
||||
for row in $wrows; do
|
||||
local claimed_by task_id title
|
||||
claimed_by=$(echo "$row" | cut -d'|' -f1)
|
||||
task_id=$(echo "$row" | cut -d'|' -f2)
|
||||
title=$(echo "$row" | cut -d'|' -f3)
|
||||
echo -e " ${CYAN}$claimed_by${NC} -> $task_id: $title"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
local db_size
|
||||
db_size=$(du -h "$TASKS_DB" | cut -f1)
|
||||
echo -e "${BLUE}Database size:${NC} $db_size"
|
||||
}
|
||||
|
||||
# Search tasks using FTS5
|
||||
search_tasks() {
|
||||
local query="$1"
|
||||
|
||||
if [[ -z "$query" ]]; then
|
||||
echo -e "${RED}Usage: search <query>${NC}"
|
||||
echo -e " Example: search \"deploy api\""
|
||||
return 1
|
||||
fi
|
||||
|
||||
check_db
|
||||
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Search Results: $query${NC}"
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
local IFS=$'\n'
|
||||
local rows
|
||||
rows=$(sql -separator '|' "SELECT t.task_id, t.title, t.status, t.priority, t.tags, t.description
|
||||
FROM tasks_fts f
|
||||
JOIN tasks t ON t.task_id = f.task_id
|
||||
WHERE tasks_fts MATCH '$(echo "$query" | sed "s/'/''/g")'
|
||||
ORDER BY rank
|
||||
LIMIT 50;")
|
||||
|
||||
if [[ -z "$rows" ]]; then
|
||||
echo -e "${YELLOW}No tasks found matching: $query${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
local count=0
|
||||
for row in $rows; do
|
||||
local task_id title status priority tags description
|
||||
task_id=$(echo "$row" | cut -d'|' -f1)
|
||||
title=$(echo "$row" | cut -d'|' -f2)
|
||||
status=$(echo "$row" | cut -d'|' -f3)
|
||||
priority=$(echo "$row" | cut -d'|' -f4)
|
||||
tags=$(echo "$row" | cut -d'|' -f5)
|
||||
description=$(echo "$row" | cut -d'|' -f6)
|
||||
|
||||
local status_color="$NC"
|
||||
case "$status" in
|
||||
available) status_color="$GREEN" ;;
|
||||
claimed) status_color="$YELLOW" ;;
|
||||
completed) status_color="$PURPLE" ;;
|
||||
esac
|
||||
|
||||
echo -e "${CYAN}$task_id${NC} [${status_color}$status${NC}]"
|
||||
echo -e " ${BLUE}Title:${NC} $title"
|
||||
echo -e " ${BLUE}Priority:${NC} $priority ${BLUE}Tags:${NC} $tags"
|
||||
if [[ -n "$description" ]]; then
|
||||
echo -e " ${BLUE}Description:${NC} ${description:0:120}"
|
||||
fi
|
||||
echo ""
|
||||
((count++))
|
||||
done
|
||||
|
||||
echo -e "${GREEN}Found $count matching tasks.${NC}"
|
||||
}
|
||||
|
||||
# Cleanup completed tasks older than 30 days
|
||||
cleanup_tasks() {
|
||||
check_db
|
||||
|
||||
local cutoff_date
|
||||
cutoff_date=$(date -u -v-30d +"%Y-%m-%dT%H:%M:%S" 2>/dev/null || date -u -d "-30 days" +"%Y-%m-%dT%H:%M:%S")
|
||||
|
||||
local to_delete
|
||||
to_delete=$(sql "SELECT COUNT(*) FROM tasks WHERE status='completed' AND completed_at < '$cutoff_date';")
|
||||
|
||||
if [[ "$to_delete" -eq 0 ]]; then
|
||||
echo -e "${GREEN}No completed tasks older than 30 days to clean up.${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Found $to_delete completed tasks older than 30 days.${NC}"
|
||||
|
||||
sql "BEGIN TRANSACTION;
|
||||
DELETE FROM tasks_fts WHERE task_id IN (SELECT task_id FROM tasks WHERE status='completed' AND completed_at < '$cutoff_date');
|
||||
DELETE FROM tasks WHERE status='completed' AND completed_at < '$cutoff_date';
|
||||
COMMIT;"
|
||||
|
||||
# Optimize DB after bulk delete
|
||||
sql "VACUUM;"
|
||||
|
||||
echo -e "${GREEN}Purged $to_delete old completed tasks. Database vacuumed.${NC}"
|
||||
}
|
||||
|
||||
# Show help
|
||||
show_help() {
|
||||
cat << EOF
|
||||
${CYAN}╔════════════════════════════════════════════════════════════╗${NC}
|
||||
${CYAN}║ BlackRoad Task Marketplace - Help ║${NC}
|
||||
${CYAN}╚════════════════════════════════════════════════════════════╝${NC}
|
||||
|
||||
${GREEN}USAGE:${NC}
|
||||
$0 <command> [options]
|
||||
|
||||
${GREEN}COMMANDS:${NC}
|
||||
|
||||
${BLUE}init${NC}
|
||||
Initialize the task marketplace (creates SQLite DB)
|
||||
|
||||
${BLUE}post${NC} <task-id> <title> <description> [priority] [tags] [skills]
|
||||
Post a new task
|
||||
Priority: urgent|high|medium|low (default: medium)
|
||||
Example: post auth-impl "Implement OAuth2" "Add OAuth2 auth" high backend backend-auth
|
||||
|
||||
${BLUE}list${NC} [priority] [tags]
|
||||
List available tasks (optionally filtered)
|
||||
Example: list high backend
|
||||
|
||||
${BLUE}claim${NC} <task-id> [claude-id] [timeout-minutes]
|
||||
Claim a task to work on it (default timeout: 30 minutes)
|
||||
Example: claim auth-impl claude-auth-specialist 60
|
||||
|
||||
${BLUE}complete${NC} <task-id> [result]
|
||||
Mark a claimed task as completed
|
||||
Example: complete auth-impl "OAuth2 implemented, tested, deployed"
|
||||
|
||||
${BLUE}release${NC} <task-id> [reason]
|
||||
Release a claimed task back to available
|
||||
Example: release auth-impl "Blocked on API deployment"
|
||||
|
||||
${BLUE}my-tasks${NC}
|
||||
Show tasks claimed by you
|
||||
|
||||
${BLUE}stats${NC}
|
||||
Show marketplace statistics
|
||||
|
||||
${BLUE}search${NC} <query>
|
||||
Full-text search across task titles, descriptions, and tags
|
||||
Example: search "deploy api"
|
||||
|
||||
${BLUE}cleanup${NC}
|
||||
Purge completed tasks older than 30 days
|
||||
|
||||
${GREEN}WORKFLOW:${NC}
|
||||
|
||||
1. Someone posts tasks to the marketplace
|
||||
2. Claudes browse available tasks (list) or search
|
||||
3. Claude claims a task to work on it
|
||||
4. Claude completes the task (or releases if blocked)
|
||||
5. Task moves to completed!
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Main command router
|
||||
case "$1" in
|
||||
init)
|
||||
init_marketplace
|
||||
;;
|
||||
post)
|
||||
post_task "$2" "$3" "$4" "$5" "$6" "$7"
|
||||
;;
|
||||
list)
|
||||
list_tasks "$2" "$3"
|
||||
;;
|
||||
claim)
|
||||
claim_task "$2" "$3" "$4"
|
||||
;;
|
||||
complete)
|
||||
complete_task "$2" "$3"
|
||||
;;
|
||||
release)
|
||||
release_task "$2" "$3"
|
||||
;;
|
||||
my-tasks)
|
||||
my_tasks
|
||||
;;
|
||||
stats)
|
||||
show_stats
|
||||
;;
|
||||
search)
|
||||
search_tasks "$2"
|
||||
;;
|
||||
cleanup)
|
||||
cleanup_tasks
|
||||
;;
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unknown command: $1${NC}"
|
||||
echo -e "Run ${CYAN}$0 help${NC} for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user