@magpiecloud/mags 1.8.13 → 1.8.15
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.
- package/README.md +95 -378
- package/bin/mags.js +196 -104
- package/index.js +6 -52
- package/package.json +22 -4
- package/API.md +0 -388
- package/Mags-API.postman_collection.json +0 -374
- package/QUICKSTART.md +0 -295
- package/deploy-page.sh +0 -171
- package/mags +0 -0
- package/mags.sh +0 -270
- package/nodejs/README.md +0 -197
- package/nodejs/bin/mags.js +0 -1146
- package/nodejs/index.js +0 -642
- package/nodejs/package.json +0 -42
- package/python/INTEGRATION.md +0 -800
- package/python/README.md +0 -161
- package/python/dist/magpie_mags-1.3.5-py3-none-any.whl +0 -0
- package/python/dist/magpie_mags-1.3.5.tar.gz +0 -0
- package/python/examples/demo.py +0 -181
- package/python/pyproject.toml +0 -39
- package/python/src/magpie_mags.egg-info/PKG-INFO +0 -182
- package/python/src/magpie_mags.egg-info/SOURCES.txt +0 -9
- package/python/src/magpie_mags.egg-info/dependency_links.txt +0 -1
- package/python/src/magpie_mags.egg-info/requires.txt +0 -1
- package/python/src/magpie_mags.egg-info/top_level.txt +0 -1
- package/python/src/mags/__init__.py +0 -6
- package/python/src/mags/client.py +0 -573
- package/python/test_sdk.py +0 -78
- package/skill.md +0 -153
- package/website/api.html +0 -1095
- package/website/claude-skill.html +0 -481
- package/website/cookbook/hn-marketing.html +0 -410
- package/website/cookbook/hn-marketing.sh +0 -42
- package/website/cookbook.html +0 -282
- package/website/env.js +0 -4
- package/website/index.html +0 -801
- package/website/llms.txt +0 -334
- package/website/login.html +0 -108
- package/website/mags.md +0 -210
- package/website/script.js +0 -453
- package/website/styles.css +0 -908
- package/website/tokens.html +0 -169
- package/website/usage.html +0 -185
package/deploy-page.sh
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Deploy an HTML page to a public Mags URL
|
|
3
|
-
# Usage: ./deploy-page.sh <html-file-or-content> [name]
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
MAGS_API_URL="${MAGS_API_URL:-https://api.magpiecloud.com}"
|
|
8
|
-
MAGS_API_TOKEN="${MAGS_API_TOKEN:-}"
|
|
9
|
-
|
|
10
|
-
# Colors
|
|
11
|
-
RED='\033[0;31m'
|
|
12
|
-
GREEN='\033[0;32m'
|
|
13
|
-
YELLOW='\033[1;33m'
|
|
14
|
-
BLUE='\033[0;34m'
|
|
15
|
-
CYAN='\033[0;36m'
|
|
16
|
-
NC='\033[0m'
|
|
17
|
-
|
|
18
|
-
# Load .env if exists
|
|
19
|
-
if [ -f ".env" ]; then
|
|
20
|
-
export $(grep -v '^#' .env | xargs)
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
if [ -z "$MAGS_API_TOKEN" ]; then
|
|
24
|
-
echo -e "${RED}Error: MAGS_API_TOKEN not set${NC}"
|
|
25
|
-
echo "Set it via: export MAGS_API_TOKEN=your-token"
|
|
26
|
-
exit 1
|
|
27
|
-
fi
|
|
28
|
-
|
|
29
|
-
usage() {
|
|
30
|
-
echo -e "${CYAN}Deploy HTML Page to Mags${NC}"
|
|
31
|
-
echo ""
|
|
32
|
-
echo "Usage: $0 <html-file-or-content> [name]"
|
|
33
|
-
echo ""
|
|
34
|
-
echo "Arguments:"
|
|
35
|
-
echo " html-file-or-content Path to HTML file, or HTML content directly"
|
|
36
|
-
echo " name Optional name for the deployment (default: page)"
|
|
37
|
-
echo ""
|
|
38
|
-
echo "Examples:"
|
|
39
|
-
echo " $0 index.html"
|
|
40
|
-
echo " $0 index.html my-site"
|
|
41
|
-
echo " $0 '<h1>Hello World</h1>'"
|
|
42
|
-
echo ""
|
|
43
|
-
echo "Environment:"
|
|
44
|
-
echo " MAGS_API_TOKEN Your API token (required)"
|
|
45
|
-
echo " MAGS_API_URL API URL (default: https://api.magpiecloud.com)"
|
|
46
|
-
exit 1
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
[ -z "$1" ] && usage
|
|
50
|
-
|
|
51
|
-
INPUT="$1"
|
|
52
|
-
NAME="${2:-page}"
|
|
53
|
-
|
|
54
|
-
# Check if input is a file or raw HTML
|
|
55
|
-
if [ -f "$INPUT" ]; then
|
|
56
|
-
echo -e "${BLUE}Reading HTML from file: $INPUT${NC}"
|
|
57
|
-
HTML_CONTENT=$(cat "$INPUT")
|
|
58
|
-
else
|
|
59
|
-
echo -e "${BLUE}Using provided HTML content${NC}"
|
|
60
|
-
HTML_CONTENT="$INPUT"
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
# Escape the HTML for JSON
|
|
64
|
-
HTML_ESCAPED=$(echo "$HTML_CONTENT" | jq -Rs .)
|
|
65
|
-
|
|
66
|
-
# Create the script that will serve the HTML
|
|
67
|
-
SCRIPT=$(cat << 'SCRIPT_EOF'
|
|
68
|
-
#!/bin/sh
|
|
69
|
-
# Create the HTML file
|
|
70
|
-
cat > /tmp/index.html << 'HTML_CONTENT_MARKER'
|
|
71
|
-
__HTML_PLACEHOLDER__
|
|
72
|
-
HTML_CONTENT_MARKER
|
|
73
|
-
|
|
74
|
-
# Start Python HTTP server on port 8080
|
|
75
|
-
cd /tmp
|
|
76
|
-
echo "Server running on port 8080"
|
|
77
|
-
python3 -m http.server 8080
|
|
78
|
-
SCRIPT_EOF
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
# Replace placeholder with actual HTML
|
|
82
|
-
SCRIPT=$(echo "$SCRIPT" | sed "s|__HTML_PLACEHOLDER__|$(echo "$HTML_CONTENT" | sed 's/|/\\|/g; s/&/\\&/g')|")
|
|
83
|
-
|
|
84
|
-
echo -e "${BLUE}Deploying page...${NC}"
|
|
85
|
-
|
|
86
|
-
# Submit the persistent job
|
|
87
|
-
RESPONSE=$(curl -s -X POST "${MAGS_API_URL}/api/v1/mags-jobs" \
|
|
88
|
-
-H "Authorization: Bearer $MAGS_API_TOKEN" \
|
|
89
|
-
-H "Content-Type: application/json" \
|
|
90
|
-
-d "$(jq -n --arg script "$SCRIPT" --arg name "$NAME" '{
|
|
91
|
-
script: $script,
|
|
92
|
-
type: "inline",
|
|
93
|
-
name: $name,
|
|
94
|
-
persistent: true
|
|
95
|
-
}')")
|
|
96
|
-
|
|
97
|
-
REQUEST_ID=$(echo "$RESPONSE" | jq -r '.request_id // empty')
|
|
98
|
-
|
|
99
|
-
if [ -z "$REQUEST_ID" ]; then
|
|
100
|
-
echo -e "${RED}Failed to deploy:${NC}"
|
|
101
|
-
echo "$RESPONSE" | jq .
|
|
102
|
-
exit 1
|
|
103
|
-
fi
|
|
104
|
-
|
|
105
|
-
echo -e "${GREEN}Deployment started: $REQUEST_ID${NC}"
|
|
106
|
-
|
|
107
|
-
# Wait for job to be running
|
|
108
|
-
echo -e "${BLUE}Waiting for VM to start...${NC}"
|
|
109
|
-
MAX_ATTEMPTS=30
|
|
110
|
-
ATTEMPT=0
|
|
111
|
-
|
|
112
|
-
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
|
|
113
|
-
STATUS_RESP=$(curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${REQUEST_ID}/status" \
|
|
114
|
-
-H "Authorization: Bearer $MAGS_API_TOKEN")
|
|
115
|
-
|
|
116
|
-
STATUS=$(echo "$STATUS_RESP" | jq -r '.status // "unknown"')
|
|
117
|
-
SUBDOMAIN=$(echo "$STATUS_RESP" | jq -r '.subdomain // empty')
|
|
118
|
-
|
|
119
|
-
if [ "$STATUS" = "error" ]; then
|
|
120
|
-
echo -e "${RED}Deployment failed!${NC}"
|
|
121
|
-
echo "$STATUS_RESP" | jq .
|
|
122
|
-
exit 1
|
|
123
|
-
fi
|
|
124
|
-
|
|
125
|
-
if [ "$STATUS" = "running" ]; then
|
|
126
|
-
echo -e " ${GREEN}VM running${NC}"
|
|
127
|
-
break
|
|
128
|
-
fi
|
|
129
|
-
|
|
130
|
-
printf "."
|
|
131
|
-
sleep 1
|
|
132
|
-
ATTEMPT=$((ATTEMPT + 1))
|
|
133
|
-
done
|
|
134
|
-
|
|
135
|
-
if [ "$STATUS" != "running" ]; then
|
|
136
|
-
echo -e "${RED}Timed out waiting for VM to start${NC}"
|
|
137
|
-
exit 1
|
|
138
|
-
fi
|
|
139
|
-
|
|
140
|
-
# Enable URL access
|
|
141
|
-
echo -e "${BLUE}Enabling URL access...${NC}"
|
|
142
|
-
ACCESS_RESP=$(curl -s -X POST "${MAGS_API_URL}/api/v1/mags-jobs/${REQUEST_ID}/access" \
|
|
143
|
-
-H "Authorization: Bearer $MAGS_API_TOKEN" \
|
|
144
|
-
-H "Content-Type: application/json" \
|
|
145
|
-
-d '{"access_type": "url", "port": 8080}')
|
|
146
|
-
|
|
147
|
-
URL=$(echo "$ACCESS_RESP" | jq -r '.url // empty')
|
|
148
|
-
SUCCESS=$(echo "$ACCESS_RESP" | jq -r '.success // false')
|
|
149
|
-
|
|
150
|
-
if [ "$SUCCESS" != "true" ] || [ -z "$URL" ]; then
|
|
151
|
-
echo -e "${YELLOW}Warning: Could not get URL from access endpoint${NC}"
|
|
152
|
-
echo "$ACCESS_RESP" | jq .
|
|
153
|
-
# Fallback: construct URL from subdomain
|
|
154
|
-
URL="https://${SUBDOMAIN}.apps.magpiecloud.com"
|
|
155
|
-
fi
|
|
156
|
-
|
|
157
|
-
echo ""
|
|
158
|
-
echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}"
|
|
159
|
-
echo -e "${GREEN} Page Deployed Successfully!${NC}"
|
|
160
|
-
echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}"
|
|
161
|
-
echo ""
|
|
162
|
-
echo -e " ${CYAN}URL:${NC} ${GREEN}${URL}${NC}"
|
|
163
|
-
echo -e " ${CYAN}Subdomain:${NC} ${SUBDOMAIN}"
|
|
164
|
-
echo -e " ${CYAN}Request ID:${NC} ${REQUEST_ID}"
|
|
165
|
-
echo ""
|
|
166
|
-
echo -e "${YELLOW}Note: The VM will sleep after idle timeout and wake on next request.${NC}"
|
|
167
|
-
echo ""
|
|
168
|
-
echo "To check status:"
|
|
169
|
-
echo " curl -s -H 'Authorization: Bearer \$MAGS_API_TOKEN' \\"
|
|
170
|
-
echo " '${MAGS_API_URL}/api/v1/mags-jobs/${REQUEST_ID}/status' | jq ."
|
|
171
|
-
echo ""
|
package/mags
DELETED
|
Binary file
|
package/mags.sh
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Mags CLI - Execute scripts on Magpie's instant VM infrastructure
|
|
3
|
-
# Usage: ./mags.sh <command> [args]
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
# Configuration
|
|
8
|
-
MAGS_API_URL="${MAGS_API_URL:-https://api.magpiecloud.com}"
|
|
9
|
-
MAGS_API_TOKEN="${MAGS_API_TOKEN:-}"
|
|
10
|
-
|
|
11
|
-
# Colors
|
|
12
|
-
RED='\033[0;31m'
|
|
13
|
-
GREEN='\033[0;32m'
|
|
14
|
-
YELLOW='\033[1;33m'
|
|
15
|
-
BLUE='\033[0;34m'
|
|
16
|
-
CYAN='\033[0;36m'
|
|
17
|
-
NC='\033[0m'
|
|
18
|
-
|
|
19
|
-
# Load .env if exists
|
|
20
|
-
if [ -f ".env" ]; then
|
|
21
|
-
export $(grep -v '^#' .env | xargs)
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
if [ -z "$MAGS_API_TOKEN" ]; then
|
|
25
|
-
echo -e "${RED}Error: MAGS_API_TOKEN not set${NC}"
|
|
26
|
-
echo "Set it via: export MAGS_API_TOKEN=your-token"
|
|
27
|
-
exit 1
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
AUTH_HEADER="Authorization: Bearer $MAGS_API_TOKEN"
|
|
31
|
-
|
|
32
|
-
usage() {
|
|
33
|
-
echo -e "${CYAN}Mags CLI - Instant VM Execution${NC}"
|
|
34
|
-
echo ""
|
|
35
|
-
echo "Usage: $0 <command> [args]"
|
|
36
|
-
echo ""
|
|
37
|
-
echo "Commands:"
|
|
38
|
-
echo " run <script> Execute a script"
|
|
39
|
-
echo " run -w <workspace> <script> Execute with persistent workspace"
|
|
40
|
-
echo " run -p <script> Run persistent VM (stays alive)"
|
|
41
|
-
echo " run -p --url <script> Run persistent VM with public URL"
|
|
42
|
-
echo " status <id> Get job status"
|
|
43
|
-
echo " logs <id> Get job logs"
|
|
44
|
-
echo " list List recent jobs"
|
|
45
|
-
echo " url <id> [port] Enable URL access for a job"
|
|
46
|
-
echo ""
|
|
47
|
-
echo "Examples:"
|
|
48
|
-
echo " $0 run 'echo Hello World'"
|
|
49
|
-
echo " $0 run -w myproject 'apk add python3 && python3 --version'"
|
|
50
|
-
echo " $0 run -p --url 'python3 -m http.server 8080'"
|
|
51
|
-
echo " $0 url abc123-job-id 8080"
|
|
52
|
-
echo " $0 status abc123"
|
|
53
|
-
echo " $0 logs abc123"
|
|
54
|
-
exit 1
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
# Submit a job and wait for completion
|
|
58
|
-
run_job() {
|
|
59
|
-
local script=""
|
|
60
|
-
local workspace=""
|
|
61
|
-
local persistent="false"
|
|
62
|
-
local enable_url="false"
|
|
63
|
-
local port="8080"
|
|
64
|
-
|
|
65
|
-
# Parse flags
|
|
66
|
-
while [[ $# -gt 0 ]]; do
|
|
67
|
-
case "$1" in
|
|
68
|
-
-w|--workspace)
|
|
69
|
-
workspace="$2"
|
|
70
|
-
shift 2
|
|
71
|
-
;;
|
|
72
|
-
-p|--persistent)
|
|
73
|
-
persistent="true"
|
|
74
|
-
shift
|
|
75
|
-
;;
|
|
76
|
-
--url)
|
|
77
|
-
enable_url="true"
|
|
78
|
-
shift
|
|
79
|
-
;;
|
|
80
|
-
--port)
|
|
81
|
-
port="$2"
|
|
82
|
-
shift 2
|
|
83
|
-
;;
|
|
84
|
-
*)
|
|
85
|
-
script="$*"
|
|
86
|
-
break
|
|
87
|
-
;;
|
|
88
|
-
esac
|
|
89
|
-
done
|
|
90
|
-
|
|
91
|
-
if [ -z "$script" ]; then
|
|
92
|
-
echo -e "${RED}Error: No script provided${NC}"
|
|
93
|
-
usage
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
echo -e "${BLUE}Submitting job...${NC}"
|
|
97
|
-
|
|
98
|
-
# Build JSON payload
|
|
99
|
-
local json_payload
|
|
100
|
-
if [ -n "$workspace" ]; then
|
|
101
|
-
json_payload=$(jq -n \
|
|
102
|
-
--arg script "$script" \
|
|
103
|
-
--arg workspace "$workspace" \
|
|
104
|
-
--argjson persistent "$persistent" \
|
|
105
|
-
'{script: $script, type: "inline", workspace_id: $workspace, persistent: $persistent}')
|
|
106
|
-
else
|
|
107
|
-
json_payload=$(jq -n \
|
|
108
|
-
--arg script "$script" \
|
|
109
|
-
--argjson persistent "$persistent" \
|
|
110
|
-
'{script: $script, type: "inline", persistent: $persistent}')
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
|
-
# Submit job
|
|
114
|
-
local response=$(curl -s -X POST "${MAGS_API_URL}/api/v1/mags-jobs" \
|
|
115
|
-
-H "$AUTH_HEADER" \
|
|
116
|
-
-H "Content-Type: application/json" \
|
|
117
|
-
-d "$json_payload")
|
|
118
|
-
|
|
119
|
-
local request_id=$(echo "$response" | jq -r '.request_id // empty')
|
|
120
|
-
|
|
121
|
-
if [ -z "$request_id" ]; then
|
|
122
|
-
echo -e "${RED}Failed to submit job:${NC}"
|
|
123
|
-
echo "$response" | jq .
|
|
124
|
-
exit 1
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
echo -e "${GREEN}Job submitted: ${request_id}${NC}"
|
|
128
|
-
[ -n "$workspace" ] && echo -e "${BLUE}Workspace: ${workspace}${NC}"
|
|
129
|
-
[ "$persistent" = "true" ] && echo -e "${YELLOW}Persistent: VM will stay alive${NC}"
|
|
130
|
-
|
|
131
|
-
# Poll for completion
|
|
132
|
-
local max_attempts=60
|
|
133
|
-
local attempt=0
|
|
134
|
-
local status="pending"
|
|
135
|
-
|
|
136
|
-
while [ $attempt -lt $max_attempts ]; do
|
|
137
|
-
local status_resp=$(curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/status" \
|
|
138
|
-
-H "$AUTH_HEADER")
|
|
139
|
-
|
|
140
|
-
status=$(echo "$status_resp" | jq -r '.status // "unknown"')
|
|
141
|
-
local subdomain=$(echo "$status_resp" | jq -r '.subdomain // empty')
|
|
142
|
-
|
|
143
|
-
if [ "$status" = "completed" ]; then
|
|
144
|
-
local duration=$(echo "$status_resp" | jq -r '.script_duration_ms // 0')
|
|
145
|
-
echo -e "${GREEN}Completed in ${duration}ms${NC}"
|
|
146
|
-
break
|
|
147
|
-
elif [ "$status" = "running" ] && [ "$persistent" = "true" ]; then
|
|
148
|
-
echo -e "${GREEN}VM running${NC}"
|
|
149
|
-
|
|
150
|
-
# Enable URL access if requested
|
|
151
|
-
if [ "$enable_url" = "true" ] && [ -n "$subdomain" ]; then
|
|
152
|
-
echo -e "${BLUE}Enabling URL access on port ${port}...${NC}"
|
|
153
|
-
local access_resp=$(curl -s -X POST "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/access" \
|
|
154
|
-
-H "$AUTH_HEADER" \
|
|
155
|
-
-H "Content-Type: application/json" \
|
|
156
|
-
-d "{\"port\": ${port}}")
|
|
157
|
-
|
|
158
|
-
local success=$(echo "$access_resp" | jq -r '.success // false')
|
|
159
|
-
if [ "$success" = "true" ]; then
|
|
160
|
-
echo -e "${GREEN}URL: https://${subdomain}.apps.magpiecloud.com${NC}"
|
|
161
|
-
else
|
|
162
|
-
echo -e "${YELLOW}Warning: Could not enable URL access${NC}"
|
|
163
|
-
echo "$access_resp" | jq .
|
|
164
|
-
fi
|
|
165
|
-
elif [ -n "$subdomain" ]; then
|
|
166
|
-
echo -e "${CYAN}Subdomain: ${subdomain}${NC}"
|
|
167
|
-
echo -e "${CYAN}To enable URL: $0 url ${request_id} ${port}${NC}"
|
|
168
|
-
fi
|
|
169
|
-
exit 0
|
|
170
|
-
elif [ "$status" = "error" ]; then
|
|
171
|
-
echo -e "${RED}Job failed${NC}"
|
|
172
|
-
echo "$status_resp" | jq .
|
|
173
|
-
exit 1
|
|
174
|
-
fi
|
|
175
|
-
|
|
176
|
-
printf "."
|
|
177
|
-
sleep 1
|
|
178
|
-
attempt=$((attempt + 1))
|
|
179
|
-
done
|
|
180
|
-
|
|
181
|
-
echo ""
|
|
182
|
-
|
|
183
|
-
# Get logs
|
|
184
|
-
echo -e "${CYAN}Output:${NC}"
|
|
185
|
-
curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/logs" \
|
|
186
|
-
-H "$AUTH_HEADER" | jq -r '.logs[] | select(.source == "stdout" or .source == "stderr") | .message' 2>/dev/null || \
|
|
187
|
-
curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/logs" \
|
|
188
|
-
-H "$AUTH_HEADER" | jq -r '.logs[] | "[\(.level)] \(.message)"'
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
enable_url() {
|
|
192
|
-
local request_id="$1"
|
|
193
|
-
local port="${2:-8080}"
|
|
194
|
-
|
|
195
|
-
if [ -z "$request_id" ]; then
|
|
196
|
-
echo -e "${RED}Error: Job ID required${NC}"
|
|
197
|
-
usage
|
|
198
|
-
fi
|
|
199
|
-
|
|
200
|
-
echo -e "${BLUE}Enabling URL access on port ${port}...${NC}"
|
|
201
|
-
|
|
202
|
-
local access_resp=$(curl -s -X POST "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/access" \
|
|
203
|
-
-H "$AUTH_HEADER" \
|
|
204
|
-
-H "Content-Type: application/json" \
|
|
205
|
-
-d "{\"port\": ${port}}")
|
|
206
|
-
|
|
207
|
-
local success=$(echo "$access_resp" | jq -r '.success // false')
|
|
208
|
-
|
|
209
|
-
if [ "$success" = "true" ]; then
|
|
210
|
-
# Get subdomain from status
|
|
211
|
-
local status_resp=$(curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/status" \
|
|
212
|
-
-H "$AUTH_HEADER")
|
|
213
|
-
local subdomain=$(echo "$status_resp" | jq -r '.subdomain // empty')
|
|
214
|
-
|
|
215
|
-
if [ -n "$subdomain" ]; then
|
|
216
|
-
echo -e "${GREEN}URL enabled: https://${subdomain}.apps.magpiecloud.com${NC}"
|
|
217
|
-
else
|
|
218
|
-
echo -e "${GREEN}URL access enabled${NC}"
|
|
219
|
-
fi
|
|
220
|
-
echo "$access_resp" | jq .
|
|
221
|
-
else
|
|
222
|
-
echo -e "${RED}Failed to enable URL access${NC}"
|
|
223
|
-
echo "$access_resp" | jq .
|
|
224
|
-
exit 1
|
|
225
|
-
fi
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
get_status() {
|
|
229
|
-
local request_id="$1"
|
|
230
|
-
curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/status" \
|
|
231
|
-
-H "$AUTH_HEADER" | jq .
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
get_logs() {
|
|
235
|
-
local request_id="$1"
|
|
236
|
-
curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs/${request_id}/logs" \
|
|
237
|
-
-H "$AUTH_HEADER" | jq -r '.logs[] | "[\(.level)] \(.message)"'
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
list_jobs() {
|
|
241
|
-
echo -e "${CYAN}Recent Jobs:${NC}"
|
|
242
|
-
curl -s -X GET "${MAGS_API_URL}/api/v1/mags-jobs?page=1&page_size=10" \
|
|
243
|
-
-H "$AUTH_HEADER" | jq '.jobs[] | {request_id, name, status, workspace_id, script_duration_ms, created_at}'
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
# Main
|
|
247
|
-
case "${1:-}" in
|
|
248
|
-
run)
|
|
249
|
-
shift
|
|
250
|
-
run_job "$@"
|
|
251
|
-
;;
|
|
252
|
-
url)
|
|
253
|
-
shift
|
|
254
|
-
enable_url "$@"
|
|
255
|
-
;;
|
|
256
|
-
status)
|
|
257
|
-
[ -z "$2" ] && usage
|
|
258
|
-
get_status "$2"
|
|
259
|
-
;;
|
|
260
|
-
logs)
|
|
261
|
-
[ -z "$2" ] && usage
|
|
262
|
-
get_logs "$2"
|
|
263
|
-
;;
|
|
264
|
-
list)
|
|
265
|
-
list_jobs
|
|
266
|
-
;;
|
|
267
|
-
*)
|
|
268
|
-
usage
|
|
269
|
-
;;
|
|
270
|
-
esac
|
package/nodejs/README.md
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
# @magpiecloud/mags
|
|
2
|
-
|
|
3
|
-
Execute scripts instantly on Magpie's microVM infrastructure. VMs boot in <100ms from a warm pool.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g @magpiecloud/mags
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
### 1. Login to Magpie
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
mags login
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
This will open your browser to create an API token. Paste the token when prompted, and it will be saved for future use.
|
|
20
|
-
|
|
21
|
-
### 2. Create a sandbox
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
mags new myproject # Local disk only
|
|
25
|
-
mags new myproject -p # With S3 persistence
|
|
26
|
-
mags ssh myproject
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### 3. Or run a script
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
mags run 'echo Hello World'
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Authentication
|
|
36
|
-
|
|
37
|
-
### Interactive Login (Recommended)
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
mags login
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Opens the Magpie dashboard in your browser where you can create an API token. The token is saved to `~/.mags/config.json` and used automatically for all future commands.
|
|
44
|
-
|
|
45
|
-
### Other Auth Commands
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
mags whoami # Check current authentication status
|
|
49
|
-
mags logout # Remove saved credentials
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Environment Variable
|
|
53
|
-
|
|
54
|
-
You can also set the token via environment variable (overrides saved config):
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
export MAGS_API_TOKEN="your-token-here"
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## CLI Commands
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
# Create a sandbox (local disk)
|
|
64
|
-
mags new myproject
|
|
65
|
-
|
|
66
|
-
# Create with S3 persistence
|
|
67
|
-
mags new myproject -p
|
|
68
|
-
|
|
69
|
-
# SSH into it
|
|
70
|
-
mags ssh myproject
|
|
71
|
-
|
|
72
|
-
# Run a simple command
|
|
73
|
-
mags run 'echo Hello'
|
|
74
|
-
|
|
75
|
-
# With persistent workspace (S3 sync)
|
|
76
|
-
mags run -w my-project 'apk add nodejs && node --version'
|
|
77
|
-
|
|
78
|
-
# Persistent VM with public URL
|
|
79
|
-
mags run -w webapp -p --url 'python3 -m http.server 8080'
|
|
80
|
-
|
|
81
|
-
# With startup command (for auto-wake)
|
|
82
|
-
mags run -w webapp -p --url --startup-command 'npm start' 'npm install && npm start'
|
|
83
|
-
|
|
84
|
-
# Custom port
|
|
85
|
-
mags run -w webapp -p --url --port 3000 'npm start'
|
|
86
|
-
|
|
87
|
-
# Enable URL for existing job
|
|
88
|
-
mags url <job-id>
|
|
89
|
-
mags url <job-id> 8080
|
|
90
|
-
|
|
91
|
-
# Other commands
|
|
92
|
-
mags status <job-id>
|
|
93
|
-
mags logs <job-id>
|
|
94
|
-
mags list
|
|
95
|
-
mags stop <job-id>
|
|
96
|
-
|
|
97
|
-
# Install Claude Code skill
|
|
98
|
-
mags setup-claude
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Claude Code Integration
|
|
102
|
-
|
|
103
|
-
Install the Mags skill for Claude Code to run scripts directly from Claude:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
mags setup-claude
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
This lets you use natural language commands like:
|
|
110
|
-
- `/mags run echo Hello World`
|
|
111
|
-
- `/mags create a python environment with numpy and pandas`
|
|
112
|
-
- `/mags run a flask server and give me the public URL`
|
|
113
|
-
|
|
114
|
-
See [mags.run/claude-skill.html](https://mags.run/claude-skill.html) for full documentation.
|
|
115
|
-
|
|
116
|
-
## CLI Flags
|
|
117
|
-
|
|
118
|
-
| Flag | Description | Default |
|
|
119
|
-
|------|-------------|---------|
|
|
120
|
-
| `-w, --workspace` | Workspace ID for persistent storage | auto |
|
|
121
|
-
| `-p, --persistent` | Keep VM alive for URL/SSH access | false |
|
|
122
|
-
| `--url` | Enable public URL access (requires -p) | false |
|
|
123
|
-
| `--port` | Port to expose for URL access | 8080 |
|
|
124
|
-
| `--startup-command` | Command when VM wakes from sleep | none |
|
|
125
|
-
|
|
126
|
-
## SSH Access
|
|
127
|
-
|
|
128
|
-
Connect to any running VM:
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
mags ssh myproject
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Features:
|
|
135
|
-
- Connects via secure proxy (`api.magpiecloud.com:PORT`)
|
|
136
|
-
- Full PTY support for interactive terminals
|
|
137
|
-
- Automatic SSH key management
|
|
138
|
-
- Hostname: `mags-vm`
|
|
139
|
-
|
|
140
|
-
## Workspaces & Persistence
|
|
141
|
-
|
|
142
|
-
When using persistent mode (`-p`), your `/root` directory syncs to S3:
|
|
143
|
-
- **Auto-sync**: Every 30 seconds while running
|
|
144
|
-
- **On stop**: Full sync before VM terminates
|
|
145
|
-
- **On wake**: Previous state restored
|
|
146
|
-
|
|
147
|
-
Without `-p`, data lives on local disk only and is cleaned up when the VM is destroyed.
|
|
148
|
-
|
|
149
|
-
## Node.js SDK
|
|
150
|
-
|
|
151
|
-
```javascript
|
|
152
|
-
const Mags = require('@magpiecloud/mags');
|
|
153
|
-
|
|
154
|
-
const mags = new Mags({
|
|
155
|
-
apiToken: process.env.MAGS_API_TOKEN
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// Run and wait for completion
|
|
159
|
-
const result = await mags.runAndWait('echo Hello World');
|
|
160
|
-
console.log(result.logs);
|
|
161
|
-
|
|
162
|
-
// Run with workspace
|
|
163
|
-
const { requestId } = await mags.run('python script.py', {
|
|
164
|
-
workspaceId: 'myproject',
|
|
165
|
-
persistent: true
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// Get status
|
|
169
|
-
const status = await mags.status(requestId);
|
|
170
|
-
|
|
171
|
-
// Enable URL access
|
|
172
|
-
await mags.enableUrl(requestId, 8080);
|
|
173
|
-
|
|
174
|
-
// List jobs
|
|
175
|
-
const jobs = await mags.list({ page: 1, pageSize: 10 });
|
|
176
|
-
|
|
177
|
-
// Stop a job
|
|
178
|
-
await mags.stop(requestId);
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## Environment Variables
|
|
182
|
-
|
|
183
|
-
| Variable | Description | Default |
|
|
184
|
-
|----------|-------------|---------|
|
|
185
|
-
| `MAGS_API_TOKEN` | Your API token (required) | - |
|
|
186
|
-
| `MAGS_API_URL` | API endpoint | https://api.magpiecloud.com |
|
|
187
|
-
|
|
188
|
-
## Performance
|
|
189
|
-
|
|
190
|
-
- **Warm start**: <100ms (VM from pool)
|
|
191
|
-
- **Cold start**: ~4 seconds (new VM boot)
|
|
192
|
-
- **Script overhead**: ~50ms
|
|
193
|
-
- **Workspace sync**: Every 30 seconds
|
|
194
|
-
|
|
195
|
-
## License
|
|
196
|
-
|
|
197
|
-
MIT
|