clasp-ai 0.0.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * CLASP Installation Script
5
+ * Downloads the pre-built Go binary for the current platform
6
+ */
7
+
8
+ const https = require('https');
9
+ const http = require('http');
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const { execSync } = require('child_process');
13
+ const os = require('os');
14
+
15
+ const VERSION = '0.2.1';
16
+ const REPO = 'jedarden/CLASP';
17
+ const BINARY_NAME = 'clasp';
18
+
19
+ // Platform mappings
20
+ const PLATFORM_MAP = {
21
+ darwin: 'darwin',
22
+ linux: 'linux',
23
+ win32: 'windows'
24
+ };
25
+
26
+ const ARCH_MAP = {
27
+ x64: 'amd64',
28
+ arm64: 'arm64'
29
+ };
30
+
31
+ function getPlatformInfo() {
32
+ const platform = PLATFORM_MAP[os.platform()];
33
+ const arch = ARCH_MAP[os.arch()];
34
+
35
+ if (!platform) {
36
+ throw new Error(`Unsupported platform: ${os.platform()}`);
37
+ }
38
+ if (!arch) {
39
+ throw new Error(`Unsupported architecture: ${os.arch()}`);
40
+ }
41
+
42
+ return { platform, arch };
43
+ }
44
+
45
+ function getBinaryName(platform) {
46
+ return platform === 'windows' ? `${BINARY_NAME}.exe` : BINARY_NAME;
47
+ }
48
+
49
+ function getDownloadUrl(platform, arch) {
50
+ const ext = platform === 'windows' ? '.exe' : '';
51
+ const filename = `clasp-${platform}-${arch}${ext}`;
52
+ return `https://github.com/${REPO}/releases/download/v${VERSION}/${filename}`;
53
+ }
54
+
55
+ function download(url, dest) {
56
+ return new Promise((resolve, reject) => {
57
+ const file = fs.createWriteStream(dest);
58
+ const protocol = url.startsWith('https') ? https : http;
59
+
60
+ const request = protocol.get(url, (response) => {
61
+ // Handle redirects
62
+ if (response.statusCode === 301 || response.statusCode === 302) {
63
+ file.close();
64
+ fs.unlinkSync(dest);
65
+ return download(response.headers.location, dest)
66
+ .then(resolve)
67
+ .catch(reject);
68
+ }
69
+
70
+ if (response.statusCode !== 200) {
71
+ file.close();
72
+ fs.unlinkSync(dest);
73
+ reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
74
+ return;
75
+ }
76
+
77
+ response.pipe(file);
78
+
79
+ file.on('finish', () => {
80
+ file.close();
81
+ resolve();
82
+ });
83
+ });
84
+
85
+ request.on('error', (err) => {
86
+ file.close();
87
+ fs.unlink(dest, () => {}); // Delete partial file
88
+ reject(err);
89
+ });
90
+ });
91
+ }
92
+
93
+ async function buildFromSource() {
94
+ console.log('[CLASP] Pre-built binary not available, building from source...');
95
+
96
+ // Check if Go is installed
97
+ try {
98
+ execSync('go version', { stdio: 'pipe' });
99
+ } catch {
100
+ throw new Error(
101
+ 'Go is not installed. Please install Go from https://go.dev/dl/ or download a pre-built binary from ' +
102
+ `https://github.com/${REPO}/releases`
103
+ );
104
+ }
105
+
106
+ const packageDir = path.dirname(__dirname);
107
+ const binDir = path.join(packageDir, 'bin');
108
+
109
+ if (!fs.existsSync(binDir)) {
110
+ fs.mkdirSync(binDir, { recursive: true });
111
+ }
112
+
113
+ console.log('[CLASP] Building binary...');
114
+ execSync(`go build -o ${path.join(binDir, BINARY_NAME)} ./cmd/clasp`, {
115
+ cwd: packageDir,
116
+ stdio: 'inherit'
117
+ });
118
+
119
+ console.log('[CLASP] Build complete!');
120
+ }
121
+
122
+ async function main() {
123
+ console.log(`[CLASP] Installing CLASP v${VERSION}...`);
124
+
125
+ const { platform, arch } = getPlatformInfo();
126
+ const binaryName = getBinaryName(platform);
127
+ const binDir = path.join(path.dirname(__dirname), 'bin');
128
+ const binaryPath = path.join(binDir, binaryName);
129
+
130
+ // Create bin directory if it doesn't exist
131
+ if (!fs.existsSync(binDir)) {
132
+ fs.mkdirSync(binDir, { recursive: true });
133
+ }
134
+
135
+ // Check if binary already exists and is correct version
136
+ if (fs.existsSync(binaryPath)) {
137
+ try {
138
+ const versionOutput = execSync(`"${binaryPath}" -version`, { encoding: 'utf8' });
139
+ if (versionOutput.includes(VERSION)) {
140
+ console.log(`[CLASP] CLASP v${VERSION} is already installed.`);
141
+ return;
142
+ }
143
+ } catch {
144
+ // Version check failed, proceed with download
145
+ }
146
+ }
147
+
148
+ const url = getDownloadUrl(platform, arch);
149
+ console.log(`[CLASP] Downloading from ${url}...`);
150
+
151
+ try {
152
+ await download(url, binaryPath);
153
+
154
+ // Make executable on Unix
155
+ if (platform !== 'windows') {
156
+ fs.chmodSync(binaryPath, 0o755);
157
+ }
158
+
159
+ console.log(`[CLASP] Successfully installed to ${binaryPath}`);
160
+ } catch (err) {
161
+ console.warn(`[CLASP] Download failed: ${err.message}`);
162
+
163
+ // Try building from source
164
+ try {
165
+ await buildFromSource();
166
+ } catch (buildErr) {
167
+ console.error(`[CLASP] Installation failed: ${buildErr.message}`);
168
+ console.error('[CLASP] Please ensure Go is installed or download the binary manually from:');
169
+ console.error(`[CLASP] https://github.com/${REPO}/releases`);
170
+ process.exit(1);
171
+ }
172
+ }
173
+ }
174
+
175
+ main().catch((err) => {
176
+ console.error(`[CLASP] Installation error: ${err.message}`);
177
+ process.exit(1);
178
+ });
@@ -0,0 +1,151 @@
1
+ #!/bin/bash
2
+ # CLASP Autonomous Agent Launcher
3
+ # Runs Claude Code in a continuous loop with the CLASP development prompt
4
+
5
+ set -e
6
+
7
+ # Configuration
8
+ WORKSPACE="/workspaces/ord-options-testing"
9
+ CLASP_DIR="$WORKSPACE/CLASP"
10
+ PROMPT_FILE="$CLASP_DIR/prompt.md"
11
+ LOG_DIR="$WORKSPACE/.clasp/logs"
12
+ LOOP_DELAY=5 # Seconds between iterations
13
+ PARSER_SCRIPT="$CLASP_DIR/scripts/stream-parser.sh"
14
+
15
+ # Colors
16
+ RED='\033[0;31m'
17
+ GREEN='\033[0;32m'
18
+ YELLOW='\033[1;33m'
19
+ BLUE='\033[0;34m'
20
+ CYAN='\033[0;36m'
21
+ MAGENTA='\033[0;35m'
22
+ NC='\033[0m' # No Color
23
+ BOLD='\033[1m'
24
+
25
+ # Iteration counter
26
+ ITERATION=0
27
+
28
+ # Log file for this session
29
+ SESSION_ID=$(date +%Y%m%d_%H%M%S)
30
+ SESSION_LOG="$LOG_DIR/session_$SESSION_ID.jsonl"
31
+
32
+ echo -e "${MAGENTA}${BOLD}"
33
+ echo "╔══════════════════════════════════════════════════════════════════╗"
34
+ echo "║ CLASP - Claude Language Agent Super Proxy ║"
35
+ echo "║ Autonomous Development Agent ║"
36
+ echo "╚══════════════════════════════════════════════════════════════════╝"
37
+ echo -e "${NC}"
38
+ echo ""
39
+ echo -e "${BLUE}Workspace:${NC} $WORKSPACE"
40
+ echo -e "${BLUE}CLASP Dir:${NC} $CLASP_DIR"
41
+ echo -e "${BLUE}Session:${NC} $SESSION_ID"
42
+ echo -e "${BLUE}Log:${NC} $SESSION_LOG"
43
+ echo ""
44
+
45
+ # Ensure directories exist
46
+ mkdir -p "$LOG_DIR"
47
+
48
+ # Check if prompt file exists
49
+ if [ ! -f "$PROMPT_FILE" ]; then
50
+ echo -e "${RED}Error: Prompt file not found at $PROMPT_FILE${NC}"
51
+ exit 1
52
+ fi
53
+
54
+ # Check if parser script exists and is executable
55
+ if [ ! -x "$PARSER_SCRIPT" ]; then
56
+ echo -e "${YELLOW}Warning: Parser script not found or not executable${NC}"
57
+ echo -e "${YELLOW}Output will be raw JSON${NC}"
58
+ USE_PARSER=false
59
+ else
60
+ USE_PARSER=true
61
+ fi
62
+
63
+ # Function to print iteration header
64
+ print_header() {
65
+ local iter=$1
66
+ local timestamp=$(date '+%Y-%m-%d %H:%M:%S %Z')
67
+
68
+ echo ""
69
+ echo -e "${GREEN}${BOLD}"
70
+ echo "┌──────────────────────────────────────────────────────────────────┐"
71
+ printf "│ Iteration: %-5d │\n" "$iter"
72
+ printf "│ Time: %-55s │\n" "$timestamp"
73
+ echo "└──────────────────────────────────────────────────────────────────┘"
74
+ echo -e "${NC}"
75
+ }
76
+
77
+ # Function to print iteration footer
78
+ print_footer() {
79
+ local iter=$1
80
+ local duration=$2
81
+
82
+ echo ""
83
+ echo -e "${YELLOW}────────────────────────────────────────────────────────────────────${NC}"
84
+ echo -e "${YELLOW}Iteration $iter completed in ${duration}s${NC}"
85
+ echo -e "${YELLOW}Waiting ${LOOP_DELAY}s before next iteration...${NC}"
86
+ echo -e "${YELLOW}────────────────────────────────────────────────────────────────────${NC}"
87
+ }
88
+
89
+ # Trap for clean exit
90
+ cleanup() {
91
+ echo ""
92
+ echo -e "${RED}${BOLD}Shutting down CLASP agent...${NC}"
93
+ echo -e "${BLUE}Total iterations completed: $ITERATION${NC}"
94
+ exit 0
95
+ }
96
+
97
+ trap cleanup SIGINT SIGTERM
98
+
99
+ # Main loop
100
+ echo -e "${GREEN}Starting autonomous development loop...${NC}"
101
+ echo -e "${CYAN}Press Ctrl+C to stop${NC}"
102
+ echo ""
103
+
104
+ while true; do
105
+ ITERATION=$((ITERATION + 1))
106
+ START_TIME=$(date +%s)
107
+
108
+ # Print iteration header
109
+ print_header $ITERATION
110
+
111
+ # Log iteration start
112
+ echo "{\"event\":\"iteration_start\",\"iteration\":$ITERATION,\"timestamp\":\"$(date -Iseconds)\"}" >> "$SESSION_LOG"
113
+
114
+ # Read the prompt
115
+ PROMPT=$(cat "$PROMPT_FILE")
116
+
117
+ # Run Claude Code headless with stream-json
118
+ echo -e "${BLUE}Running Claude Code...${NC}"
119
+ echo ""
120
+
121
+ if [ "$USE_PARSER" = true ]; then
122
+ # Pipe through parser for human-readable output
123
+ claude --dangerously-skip-permissions \
124
+ --output-format stream-json \
125
+ --verbose \
126
+ --print \
127
+ -p "$PROMPT" \
128
+ 2>&1 | tee -a "$SESSION_LOG" | "$PARSER_SCRIPT"
129
+ else
130
+ # Raw JSON output
131
+ claude --dangerously-skip-permissions \
132
+ --output-format stream-json \
133
+ --verbose \
134
+ --print \
135
+ -p "$PROMPT" \
136
+ 2>&1 | tee -a "$SESSION_LOG"
137
+ fi
138
+
139
+ # Calculate duration
140
+ END_TIME=$(date +%s)
141
+ DURATION=$((END_TIME - START_TIME))
142
+
143
+ # Log iteration end
144
+ echo "{\"event\":\"iteration_end\",\"iteration\":$ITERATION,\"duration_secs\":$DURATION,\"timestamp\":\"$(date -Iseconds)\"}" >> "$SESSION_LOG"
145
+
146
+ # Print iteration footer
147
+ print_footer $ITERATION $DURATION
148
+
149
+ # Wait before next iteration
150
+ sleep $LOOP_DELAY
151
+ done
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * CLASP Prepack Script
5
+ * Prepares the package for npm publish by removing binaries
6
+ * (users will download their platform-specific binary on install)
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ const binDir = path.join(path.dirname(__dirname), 'bin');
13
+
14
+ // List of files to keep in bin/
15
+ const KEEP_FILES = ['clasp-wrapper.js'];
16
+
17
+ console.log('[CLASP] Preparing package for npm...');
18
+
19
+ // Remove compiled binaries (they'll be downloaded on install)
20
+ if (fs.existsSync(binDir)) {
21
+ const files = fs.readdirSync(binDir);
22
+ for (const file of files) {
23
+ if (!KEEP_FILES.includes(file)) {
24
+ const filePath = path.join(binDir, file);
25
+ fs.unlinkSync(filePath);
26
+ console.log(`[CLASP] Removed ${file}`);
27
+ }
28
+ }
29
+ }
30
+
31
+ console.log('[CLASP] Package prepared successfully!');
@@ -0,0 +1,90 @@
1
+ #!/bin/bash
2
+ # CLASP Tmux Session Starter
3
+ # Creates a tmux session using phonetic alphabet naming and starts the launcher
4
+
5
+ set -e
6
+
7
+ # Color codes for output
8
+ RED='\033[0;31m'
9
+ GREEN='\033[0;32m'
10
+ YELLOW='\033[1;33m'
11
+ BLUE='\033[0;34m'
12
+ MAGENTA='\033[0;35m'
13
+ CYAN='\033[0;36m'
14
+ NC='\033[0m' # No Color
15
+ BOLD='\033[1m'
16
+
17
+ # Phonetic alphabet for tmux sessions (same as start.sh)
18
+ PHONETIC_NAMES=("alpha" "bravo" "charlie" "delta" "echo" "foxtrot" "golf" "hotel" "india" "juliet" "kilo" "lima" "mike" "november" "oscar" "papa" "quebec" "romeo" "sierra" "tango" "uniform" "victor" "whiskey" "xray" "yankee" "zulu")
19
+
20
+ # Configuration
21
+ WORKSPACE="/workspaces/ord-options-testing"
22
+ CLASP_DIR="$WORKSPACE/CLASP"
23
+ LAUNCHER_SCRIPT="$CLASP_DIR/scripts/launcher.sh"
24
+
25
+ # Function to find next available tmux session name
26
+ find_tmux_session() {
27
+ for name in "${PHONETIC_NAMES[@]}"; do
28
+ if ! tmux has-session -t "$name" 2>/dev/null; then
29
+ echo "$name"
30
+ return 0
31
+ fi
32
+ done
33
+ # If all phonetic names are taken, use a timestamp
34
+ echo "clasp-$(date +%s)"
35
+ return 0
36
+ }
37
+
38
+ # Print banner
39
+ echo -e "${MAGENTA}${BOLD}"
40
+ echo "╔══════════════════════════════════════════════════════════════════╗"
41
+ echo "║ CLASP - Claude Language Agent Super Proxy ║"
42
+ echo "║ Tmux Session Starter ║"
43
+ echo "╚══════════════════════════════════════════════════════════════════╝"
44
+ echo -e "${NC}"
45
+
46
+ # Check if launcher script exists
47
+ if [ ! -x "$LAUNCHER_SCRIPT" ]; then
48
+ echo -e "${RED}Error: Launcher script not found or not executable at $LAUNCHER_SCRIPT${NC}"
49
+ exit 1
50
+ fi
51
+
52
+ # Ensure .clasp directory exists for logs
53
+ mkdir -p "$WORKSPACE/.clasp/logs"
54
+
55
+ # Find available session name
56
+ SESSION_NAME=$(find_tmux_session)
57
+
58
+ echo -e "${BLUE}Creating tmux session:${NC} $SESSION_NAME"
59
+ echo -e "${BLUE}Working directory:${NC} $CLASP_DIR"
60
+ echo ""
61
+
62
+ # Create tmux session
63
+ if tmux new-session -d -s "$SESSION_NAME" -c "$CLASP_DIR" "$LAUNCHER_SCRIPT"; then
64
+ echo -e "${GREEN}${BOLD}✓ CLASP autonomous agent started!${NC}"
65
+ echo ""
66
+ echo -e "${CYAN}Session Details:${NC}"
67
+ echo -e " Name: ${BOLD}$SESSION_NAME${NC}"
68
+ echo -e " Launcher: $LAUNCHER_SCRIPT"
69
+ echo -e " Logs: $WORKSPACE/.clasp/logs/"
70
+ echo ""
71
+ echo -e "${YELLOW}Commands:${NC}"
72
+ echo -e " Attach: ${WHITE}tmux attach -t $SESSION_NAME${NC}"
73
+ echo -e " Detach: ${WHITE}Ctrl+B, D${NC} (while attached)"
74
+ echo -e " Kill: ${WHITE}tmux kill-session -t $SESSION_NAME${NC}"
75
+ echo -e " List: ${WHITE}tmux ls${NC}"
76
+ echo ""
77
+
78
+ # Ask if user wants to attach
79
+ read -p "$(echo -e ${CYAN}Attach to session now? [Y/n]: ${NC})" -n 1 -r
80
+ echo ""
81
+ if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then
82
+ tmux attach -t "$SESSION_NAME"
83
+ else
84
+ echo -e "${GREEN}Session running in background.${NC}"
85
+ echo -e "${YELLOW}Run 'tmux attach -t $SESSION_NAME' to connect.${NC}"
86
+ fi
87
+ else
88
+ echo -e "${RED}Failed to create tmux session${NC}"
89
+ exit 1
90
+ fi