@magpiecloud/mags 1.8.12 → 1.8.14
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 +2 -2
- package/bin/mags.js +213 -104
- package/index.js +6 -52
- package/nodejs/index.js +6 -52
- package/package.json +4 -1
- package/python/README.md +6 -2
- package/python/dist/magpie_mags-1.3.6-py3-none-any.whl +0 -0
- package/python/dist/magpie_mags-1.3.6.tar.gz +0 -0
- package/python/pyproject.toml +1 -1
- package/python/src/magpie_mags.egg-info/PKG-INFO +8 -4
- package/python/src/mags/client.py +12 -62
- package/website/api.html +139 -10
- package/website/claude-skill.html +2 -2
- package/website/cookbook/hn-marketing.html +1 -1
- package/website/cookbook.html +3 -3
- package/website/docs.html +677 -0
- package/website/index.html +111 -67
- package/website/login.html +2 -2
- package/website/styles.css +206 -39
- package/website/tokens.html +1 -1
- package/website/usage.html +1 -1
- package/python/dist/magpie_mags-1.3.4-py3-none-any.whl +0 -0
- package/python/dist/magpie_mags-1.3.4.tar.gz +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: magpie-mags
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.6
|
|
4
4
|
Summary: Mags SDK - Execute scripts on Magpie's instant VM infrastructure
|
|
5
5
|
Author: Magpie Cloud
|
|
6
6
|
License: MIT
|
|
@@ -156,19 +156,23 @@ print(f"Jobs: {usage['total_jobs']}, VM seconds: {usage['vm_seconds']:.0f}")
|
|
|
156
156
|
|--------|-------------|
|
|
157
157
|
| `run(script, **opts)` | Submit a job (`persistent`, `no_sleep`, `workspace_id`, ...) |
|
|
158
158
|
| `run_and_wait(script, **opts)` | Submit and block until done |
|
|
159
|
-
| `new(name, **opts)` | Create a persistent
|
|
159
|
+
| `new(name, **opts)` | Create a VM sandbox (`persistent=True` for S3) |
|
|
160
160
|
| `find_job(name_or_id)` | Find a running/sleeping job by name or workspace |
|
|
161
161
|
| `exec(name_or_id, command)` | Run a command on an existing VM via SSH |
|
|
162
162
|
| `stop(name_or_id)` | Stop a running job |
|
|
163
|
+
| `url(name_or_id, port)` | Enable public URL and return full URL |
|
|
163
164
|
| `resize(workspace, disk_gb)` | Resize a workspace's disk |
|
|
164
165
|
| `status(request_id)` | Get job status |
|
|
165
166
|
| `logs(request_id)` | Get job logs |
|
|
166
167
|
| `list_jobs(page, page_size)` | List recent jobs |
|
|
167
|
-
| `update_job(request_id,
|
|
168
|
+
| `update_job(request_id, **opts)` | Update job config (`startup_command`, `no_sleep`) |
|
|
168
169
|
| `enable_access(request_id, port)` | Enable URL or SSH access |
|
|
169
170
|
| `usage(window_days)` | Get usage summary |
|
|
170
171
|
| `upload_file(path)` | Upload a file, returns file ID |
|
|
171
172
|
| `upload_files(paths)` | Upload multiple files |
|
|
173
|
+
| `url_alias_create(sub, ws_id)` | Create a stable URL alias |
|
|
174
|
+
| `url_alias_list()` | List URL aliases |
|
|
175
|
+
| `url_alias_delete(sub)` | Delete a URL alias |
|
|
172
176
|
| `cron_create(**opts)` | Create a cron job |
|
|
173
177
|
| `cron_list()` | List cron jobs |
|
|
174
178
|
| `cron_get(id)` | Get a cron job |
|
|
@@ -179,4 +183,4 @@ print(f"Jobs: {usage['total_jobs']}, VM seconds: {usage['vm_seconds']:.0f}")
|
|
|
179
183
|
|
|
180
184
|
- Website: [mags.run](https://mags.run)
|
|
181
185
|
- Node.js SDK: `npm install @magpiecloud/mags`
|
|
182
|
-
- CLI: `
|
|
186
|
+
- CLI: `npm install -g @magpiecloud/mags`
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
import subprocess
|
|
7
|
-
import tempfile
|
|
8
6
|
import time
|
|
9
7
|
from pathlib import Path
|
|
10
8
|
from typing import Any, Dict, List, Optional
|
|
@@ -355,11 +353,11 @@ class Mags:
|
|
|
355
353
|
return resp
|
|
356
354
|
|
|
357
355
|
def exec(self, name_or_id: str, command: str, *, timeout: int = 30) -> dict:
|
|
358
|
-
"""Execute a command on an existing running/sleeping sandbox
|
|
356
|
+
"""Execute a command on an existing running/sleeping sandbox.
|
|
359
357
|
|
|
360
358
|
Equivalent to ``mags exec <workspace> '<command>'``.
|
|
361
359
|
|
|
362
|
-
Returns ``{"exit_code": int, "output": str}``.
|
|
360
|
+
Returns ``{"exit_code": int, "output": str, "stderr": str}``.
|
|
363
361
|
"""
|
|
364
362
|
job = self.find_job(name_or_id)
|
|
365
363
|
if not job:
|
|
@@ -370,65 +368,17 @@ class Mags:
|
|
|
370
368
|
)
|
|
371
369
|
|
|
372
370
|
request_id = job.get("request_id") or job.get("id")
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
raise MagsError(
|
|
379
|
-
f"Failed to enable SSH access: {access.get('error', 'unknown error')}"
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
ssh_host = access["ssh_host"]
|
|
383
|
-
ssh_port = str(access["ssh_port"])
|
|
384
|
-
ssh_key = access.get("ssh_private_key", "")
|
|
385
|
-
|
|
386
|
-
# Wrap command to handle chroot overlay, same as CLI
|
|
387
|
-
escaped = command.replace("'", "'\\''")
|
|
388
|
-
wrapped = (
|
|
389
|
-
f"if [ -d /overlay/bin ]; then "
|
|
390
|
-
f"chroot /overlay /bin/sh -l -c 'cd /root 2>/dev/null; {escaped}'; "
|
|
391
|
-
f"else cd /root 2>/dev/null; {escaped}; fi"
|
|
371
|
+
resp = self._request(
|
|
372
|
+
"POST",
|
|
373
|
+
f"/mags-jobs/{request_id}/exec",
|
|
374
|
+
json={"command": command, "timeout": timeout},
|
|
375
|
+
timeout=timeout + 10, # HTTP timeout > command timeout
|
|
392
376
|
)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
"-o", "StrictHostKeyChecking=no",
|
|
399
|
-
"-o", "UserKnownHostsFile=/dev/null",
|
|
400
|
-
"-o", "LogLevel=ERROR",
|
|
401
|
-
"-p", ssh_port,
|
|
402
|
-
]
|
|
403
|
-
if ssh_key:
|
|
404
|
-
fd, key_file = tempfile.mkstemp(prefix="mags_ssh_")
|
|
405
|
-
os.write(fd, ssh_key.encode())
|
|
406
|
-
os.close(fd)
|
|
407
|
-
os.chmod(key_file, 0o600)
|
|
408
|
-
ssh_args.extend(["-i", key_file])
|
|
409
|
-
|
|
410
|
-
ssh_args.append(f"root@{ssh_host}")
|
|
411
|
-
ssh_args.append(wrapped)
|
|
412
|
-
|
|
413
|
-
proc = subprocess.run(
|
|
414
|
-
ssh_args,
|
|
415
|
-
capture_output=True,
|
|
416
|
-
text=True,
|
|
417
|
-
timeout=timeout,
|
|
418
|
-
)
|
|
419
|
-
return {
|
|
420
|
-
"exit_code": proc.returncode,
|
|
421
|
-
"output": proc.stdout,
|
|
422
|
-
"stderr": proc.stderr,
|
|
423
|
-
}
|
|
424
|
-
except subprocess.TimeoutExpired:
|
|
425
|
-
raise MagsError(f"Command timed out after {timeout}s")
|
|
426
|
-
finally:
|
|
427
|
-
if key_file:
|
|
428
|
-
try:
|
|
429
|
-
os.unlink(key_file)
|
|
430
|
-
except OSError:
|
|
431
|
-
pass
|
|
377
|
+
return {
|
|
378
|
+
"exit_code": resp.get("exit_code", -1),
|
|
379
|
+
"output": resp.get("stdout", ""),
|
|
380
|
+
"stderr": resp.get("stderr", ""),
|
|
381
|
+
}
|
|
432
382
|
|
|
433
383
|
def usage(self, *, window_days: int = 30) -> dict:
|
|
434
384
|
"""Get aggregated usage summary."""
|
package/website/api.html
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/>
|
|
11
11
|
<meta name="api-base" content="https://api.magpiecloud.com" />
|
|
12
12
|
<meta name="auth-base" content="https://api.magpiecloud.com" />
|
|
13
|
-
<link rel="stylesheet" href="styles.css?v=
|
|
13
|
+
<link rel="stylesheet" href="styles.css?v=8" />
|
|
14
14
|
<script src="env.js"></script>
|
|
15
15
|
<style>
|
|
16
16
|
.endpoint { margin-bottom: 2.5rem; }
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
text-transform: uppercase;
|
|
32
32
|
}
|
|
33
|
-
.method.post { background: rgba(47,
|
|
34
|
-
.method.get { background: rgba(59, 130, 246, 0.
|
|
35
|
-
.method.patch { background: rgba(245, 158, 11, 0.
|
|
36
|
-
.method.delete { background: rgba(239, 68, 68, 0.
|
|
33
|
+
.method.post { background: rgba(47, 155, 102, 0.2); color: #3dbd7e; }
|
|
34
|
+
.method.get { background: rgba(59, 130, 246, 0.2); color: #60a5fa; }
|
|
35
|
+
.method.patch { background: rgba(245, 158, 11, 0.2); color: #fbbf24; }
|
|
36
|
+
.method.delete { background: rgba(239, 68, 68, 0.2); color: #f87171; }
|
|
37
37
|
.url-path {
|
|
38
38
|
font-family: var(--mono);
|
|
39
39
|
font-size: 0.95rem;
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
</div>
|
|
110
110
|
<nav class="nav-links">
|
|
111
111
|
<a href="index.html">Home</a>
|
|
112
|
-
<a href="
|
|
112
|
+
<a href="docs.html">Docs</a>
|
|
113
113
|
<a href="cookbook.html">Cookbook</a>
|
|
114
114
|
<a href="claude-skill.html">Claude Skill</a>
|
|
115
115
|
<a href="https://discord.gg/3avpC2nS" target="_blank" rel="noreferrer">Discord</a>
|
|
@@ -283,11 +283,14 @@ m = Mags(api_token="your-token")
|
|
|
283
283
|
<a href="#get-status">Get Status</a>
|
|
284
284
|
<a href="#get-logs">Get Logs</a>
|
|
285
285
|
<a href="#list-jobs">List Jobs</a>
|
|
286
|
+
<a href="#stop-job">Stop Job</a>
|
|
286
287
|
<a href="#enable-access">Enable Access</a>
|
|
287
288
|
<a href="#update-job">Update Job</a>
|
|
289
|
+
<a href="#sync-workspace">Sync Workspace</a>
|
|
288
290
|
<a href="#upload-file">Upload File</a>
|
|
289
291
|
<a href="#list-workspaces">List Workspaces</a>
|
|
290
292
|
<a href="#delete-workspace">Delete Workspace</a>
|
|
293
|
+
<a href="#url-aliases">URL Aliases</a>
|
|
291
294
|
<a href="#cron-endpoints">Cron Jobs</a>
|
|
292
295
|
</div>
|
|
293
296
|
|
|
@@ -542,12 +545,48 @@ for job in resp["jobs"]:
|
|
|
542
545
|
print(job["request_id"], job["status"])</code></pre>
|
|
543
546
|
</div>
|
|
544
547
|
<div class="tab-content" data-tab="lj-js">
|
|
545
|
-
<pre><code>const resp = await mags.
|
|
548
|
+
<pre><code>const resp = await mags.list({ page: 1, pageSize: 10 });
|
|
546
549
|
resp.jobs.forEach(j => console.log(j.requestId, j.status));</code></pre>
|
|
547
550
|
</div>
|
|
548
551
|
</div>
|
|
549
552
|
</div>
|
|
550
553
|
|
|
554
|
+
<!-- Stop Job -->
|
|
555
|
+
<div class="endpoint card wide" id="stop-job" data-reveal>
|
|
556
|
+
<h3>Stop Job</h3>
|
|
557
|
+
<div class="method-url">
|
|
558
|
+
<span class="method post">POST</span>
|
|
559
|
+
<span class="url-path">/api/v1/mags-jobs/:id/stop</span>
|
|
560
|
+
</div>
|
|
561
|
+
<p>Stop a running or sleeping job. The VM is terminated and the workspace is synced to S3 if persistent.</p>
|
|
562
|
+
|
|
563
|
+
<p class="response-label">Response (200)</p>
|
|
564
|
+
<pre><code>{ "success": true, "message": "Job stopped" }</code></pre>
|
|
565
|
+
|
|
566
|
+
<div class="code-tabs tab-group">
|
|
567
|
+
<p class="response-label">SDK examples</p>
|
|
568
|
+
<div class="tab-bar">
|
|
569
|
+
<button class="tab active" data-tab="sj2-curl">curl</button>
|
|
570
|
+
<button class="tab" data-tab="sj2-py">Python</button>
|
|
571
|
+
<button class="tab" data-tab="sj2-js">Node.js</button>
|
|
572
|
+
<button class="tab" data-tab="sj2-cli">CLI</button>
|
|
573
|
+
</div>
|
|
574
|
+
<div class="tab-content active" data-tab="sj2-curl">
|
|
575
|
+
<pre><code>curl -X POST https://api.magpiecloud.com/api/v1/mags-jobs/$ID/stop \
|
|
576
|
+
-H "Authorization: Bearer $TOKEN"</code></pre>
|
|
577
|
+
</div>
|
|
578
|
+
<div class="tab-content" data-tab="sj2-py">
|
|
579
|
+
<pre><code>m.stop("myproject") # accepts name, workspace ID, or request ID</code></pre>
|
|
580
|
+
</div>
|
|
581
|
+
<div class="tab-content" data-tab="sj2-js">
|
|
582
|
+
<pre><code>await mags.stop('myproject'); // accepts name, workspace ID, or request ID</code></pre>
|
|
583
|
+
</div>
|
|
584
|
+
<div class="tab-content" data-tab="sj2-cli">
|
|
585
|
+
<pre><code>mags stop myproject</code></pre>
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
</div>
|
|
589
|
+
|
|
551
590
|
<!-- Enable Access -->
|
|
552
591
|
<div class="endpoint card wide" id="enable-access" data-reveal>
|
|
553
592
|
<h3>Enable Access (SSH or HTTP)</h3>
|
|
@@ -601,11 +640,11 @@ print(access.get("url"))</code></pre>
|
|
|
601
640
|
</div>
|
|
602
641
|
<div class="tab-content" data-tab="ea-js">
|
|
603
642
|
<pre><code>// SSH access
|
|
604
|
-
const ssh = await mags.enableAccess(requestId,
|
|
643
|
+
const ssh = await mags.enableAccess(requestId, 22);
|
|
605
644
|
console.log(`ssh root@${ssh.sshHost} -p ${ssh.sshPort}`);
|
|
606
645
|
|
|
607
646
|
// HTTP access
|
|
608
|
-
const access = await mags.enableAccess(requestId,
|
|
647
|
+
const access = await mags.enableAccess(requestId, 8080);</code></pre>
|
|
609
648
|
</div>
|
|
610
649
|
</div>
|
|
611
650
|
</div>
|
|
@@ -714,6 +753,37 @@ file_ids = m.upload_files(["script.py", "data.csv"])</code></pre>
|
|
|
714
753
|
</div>
|
|
715
754
|
</div>
|
|
716
755
|
|
|
756
|
+
<!-- Sync Workspace -->
|
|
757
|
+
<div class="endpoint card wide" id="sync-workspace" data-reveal>
|
|
758
|
+
<h3>Sync Workspace</h3>
|
|
759
|
+
<div class="method-url">
|
|
760
|
+
<span class="method post">POST</span>
|
|
761
|
+
<span class="url-path">/api/v1/mags-jobs/:id/sync</span>
|
|
762
|
+
</div>
|
|
763
|
+
<p>Trigger an immediate workspace sync to S3 without stopping the VM.</p>
|
|
764
|
+
|
|
765
|
+
<p class="response-label">Response (200)</p>
|
|
766
|
+
<pre><code>{ "success": true, "message": "Sync initiated" }</code></pre>
|
|
767
|
+
|
|
768
|
+
<div class="code-tabs tab-group">
|
|
769
|
+
<p class="response-label">SDK examples</p>
|
|
770
|
+
<div class="tab-bar">
|
|
771
|
+
<button class="tab active" data-tab="sw-py">Python</button>
|
|
772
|
+
<button class="tab" data-tab="sw-js">Node.js</button>
|
|
773
|
+
<button class="tab" data-tab="sw-cli">CLI</button>
|
|
774
|
+
</div>
|
|
775
|
+
<div class="tab-content active" data-tab="sw-py">
|
|
776
|
+
<pre><code>m.sync(request_id)</code></pre>
|
|
777
|
+
</div>
|
|
778
|
+
<div class="tab-content" data-tab="sw-js">
|
|
779
|
+
<pre><code>await mags.sync(requestId);</code></pre>
|
|
780
|
+
</div>
|
|
781
|
+
<div class="tab-content" data-tab="sw-cli">
|
|
782
|
+
<pre><code>mags sync myproject</code></pre>
|
|
783
|
+
</div>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
|
|
717
787
|
<!-- List Workspaces -->
|
|
718
788
|
<div class="endpoint card wide" id="list-workspaces" data-reveal>
|
|
719
789
|
<h3>List Workspaces</h3>
|
|
@@ -794,6 +864,65 @@ mags workspace delete myproject --force # skip confirmation</code></pre>
|
|
|
794
864
|
</div>
|
|
795
865
|
</div>
|
|
796
866
|
|
|
867
|
+
<!-- URL Aliases -->
|
|
868
|
+
<div class="endpoint card wide" id="url-aliases" data-reveal>
|
|
869
|
+
<h3>URL Aliases</h3>
|
|
870
|
+
<div class="method-url">
|
|
871
|
+
<span class="method post">POST</span>
|
|
872
|
+
<span class="url-path">/api/v1/mags-url-aliases</span>
|
|
873
|
+
</div>
|
|
874
|
+
<div class="method-url" style="margin-left:0.5rem">
|
|
875
|
+
<span class="method get">GET</span>
|
|
876
|
+
<span class="url-path">/api/v1/mags-url-aliases</span>
|
|
877
|
+
</div>
|
|
878
|
+
<div class="method-url" style="margin-left:0.5rem">
|
|
879
|
+
<span class="method delete">DELETE</span>
|
|
880
|
+
<span class="url-path">/api/v1/mags-url-aliases/:subdomain</span>
|
|
881
|
+
</div>
|
|
882
|
+
<p>Create stable, human-readable URL aliases for your sandboxes. Aliases point to a workspace and automatically follow the active VM.</p>
|
|
883
|
+
|
|
884
|
+
<p class="response-label">Create request body</p>
|
|
885
|
+
<table class="field-table">
|
|
886
|
+
<thead>
|
|
887
|
+
<tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr>
|
|
888
|
+
</thead>
|
|
889
|
+
<tbody>
|
|
890
|
+
<tr><td><code>subdomain</code></td><td>string</td><td><span class="required">YES</span></td><td>Subdomain for the alias (e.g. <code>my-api</code>).</td></tr>
|
|
891
|
+
<tr><td><code>workspace_id</code></td><td>string</td><td><span class="required">YES</span></td><td>Workspace to point the alias at.</td></tr>
|
|
892
|
+
<tr><td><code>domain</code></td><td>string</td><td>no</td><td>Custom domain (default: <code>apps.magpiecloud.com</code>).</td></tr>
|
|
893
|
+
</tbody>
|
|
894
|
+
</table>
|
|
895
|
+
|
|
896
|
+
<div class="code-tabs tab-group">
|
|
897
|
+
<p class="response-label">SDK examples</p>
|
|
898
|
+
<div class="tab-bar">
|
|
899
|
+
<button class="tab active" data-tab="ua-cli">CLI</button>
|
|
900
|
+
<button class="tab" data-tab="ua-py">Python</button>
|
|
901
|
+
<button class="tab" data-tab="ua-js">Node.js</button>
|
|
902
|
+
</div>
|
|
903
|
+
<div class="tab-content active" data-tab="ua-cli">
|
|
904
|
+
<pre><code># Create alias
|
|
905
|
+
mags url alias my-api myproject
|
|
906
|
+
|
|
907
|
+
# List aliases
|
|
908
|
+
mags url alias list
|
|
909
|
+
|
|
910
|
+
# Delete alias
|
|
911
|
+
mags url alias remove my-api</code></pre>
|
|
912
|
+
</div>
|
|
913
|
+
<div class="tab-content" data-tab="ua-py">
|
|
914
|
+
<pre><code>m.url_alias_create("my-api", "myproject")
|
|
915
|
+
aliases = m.url_alias_list()
|
|
916
|
+
m.url_alias_delete("my-api")</code></pre>
|
|
917
|
+
</div>
|
|
918
|
+
<div class="tab-content" data-tab="ua-js">
|
|
919
|
+
<pre><code>await mags.urlAliasCreate('my-api', 'myproject');
|
|
920
|
+
const aliases = await mags.urlAliasList();
|
|
921
|
+
await mags.urlAliasDelete('my-api');</code></pre>
|
|
922
|
+
</div>
|
|
923
|
+
</div>
|
|
924
|
+
</div>
|
|
925
|
+
|
|
797
926
|
<!-- Cron Endpoints -->
|
|
798
927
|
<div class="endpoint card wide" id="cron-endpoints" data-reveal>
|
|
799
928
|
<h3>Cron Jobs</h3>
|
|
@@ -961,6 +1090,6 @@ mags cron remove <id></code></pre>
|
|
|
961
1090
|
</div>
|
|
962
1091
|
</footer>
|
|
963
1092
|
|
|
964
|
-
<script src="script.js?v=
|
|
1093
|
+
<script src="script.js?v=8"></script>
|
|
965
1094
|
</body>
|
|
966
1095
|
</html>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/>
|
|
11
11
|
<meta name="api-base" content="https://api.magpiecloud.com" />
|
|
12
12
|
<meta name="auth-base" content="https://api.magpiecloud.com" />
|
|
13
|
-
<link rel="stylesheet" href="styles.css?v=
|
|
13
|
+
<link rel="stylesheet" href="styles.css?v=8" />
|
|
14
14
|
<script src="env.js"></script>
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
<nav class="nav-links">
|
|
26
26
|
<a href="index.html">Home</a>
|
|
27
|
-
<a href="
|
|
27
|
+
<a href="docs.html">Docs</a>
|
|
28
28
|
<a href="api.html">API</a>
|
|
29
29
|
<a href="cookbook.html">Cookbook</a>
|
|
30
30
|
<a href="https://discord.gg/3avpC2nS" target="_blank" rel="noreferrer">Discord</a>
|
package/website/cookbook.html
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/>
|
|
11
11
|
<meta name="api-base" content="https://api.magpiecloud.com" />
|
|
12
12
|
<meta name="auth-base" content="https://api.magpiecloud.com" />
|
|
13
|
-
<link rel="stylesheet" href="styles.css?v=
|
|
13
|
+
<link rel="stylesheet" href="styles.css?v=8" />
|
|
14
14
|
<script src="env.js"></script>
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
<nav class="nav-links">
|
|
26
26
|
<a href="index.html">Home</a>
|
|
27
|
-
<a href="
|
|
27
|
+
<a href="docs.html">Docs</a>
|
|
28
28
|
<a href="api.html">API</a>
|
|
29
29
|
<a href="claude-skill.html">Claude Skill</a>
|
|
30
30
|
<a href="https://discord.gg/3avpC2nS" target="_blank" rel="noreferrer">Discord</a>
|
|
31
31
|
<a href="login.html">Login</a>
|
|
32
32
|
</nav>
|
|
33
33
|
<div class="nav-cta">
|
|
34
|
-
<a class="button ghost" href="
|
|
34
|
+
<a class="button ghost" href="docs.html#quickstart">Get started</a>
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
37
37
|
</header>
|