@magpiecloud/mags 1.8.3 → 1.8.4
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/bin/mags.js +104 -1
- package/package.json +1 -1
- package/python/dist/magpie_mags-1.3.0-py3-none-any.whl +0 -0
- package/python/dist/magpie_mags-1.3.0.tar.gz +0 -0
- package/python/pyproject.toml +1 -1
- package/python/src/mags/client.py +33 -0
- package/python/dist/magpie_mags-1.2.0-py3-none-any.whl +0 -0
- package/python/dist/magpie_mags-1.2.0.tar.gz +0 -0
package/bin/mags.js
CHANGED
|
@@ -207,6 +207,9 @@ ${colors.bold}Commands:${colors.reset}
|
|
|
207
207
|
logs <name|id> Get job logs
|
|
208
208
|
list List recent jobs
|
|
209
209
|
url <name|id> [port] Enable URL access for a job
|
|
210
|
+
url alias <sub> <workspace> Create a stable URL alias for a workspace
|
|
211
|
+
url alias list List your URL aliases
|
|
212
|
+
url alias remove <subdomain> Delete a URL alias
|
|
210
213
|
stop <name|id> Stop a running job
|
|
211
214
|
resize <workspace> --disk <GB> Resize a workspace's disk (restarts VM)
|
|
212
215
|
sync <workspace|id> Sync workspace to S3 (without stopping)
|
|
@@ -260,6 +263,10 @@ ${colors.bold}Examples:${colors.reset}
|
|
|
260
263
|
mags status myvm
|
|
261
264
|
mags logs myvm
|
|
262
265
|
mags url myvm 8080
|
|
266
|
+
mags url alias my-api myvm # Stable URL: my-api.apps.magpiecloud.com
|
|
267
|
+
mags url alias my-api myvm --lfg # Stable URL: my-api.app.lfg.run
|
|
268
|
+
mags url alias list # List all aliases
|
|
269
|
+
mags url alias remove my-api # Remove alias
|
|
263
270
|
mags setup-claude # Install Claude Code skill
|
|
264
271
|
`);
|
|
265
272
|
process.exit(1);
|
|
@@ -668,6 +675,98 @@ async function enableUrlAccess(nameOrId, port = 8080) {
|
|
|
668
675
|
}
|
|
669
676
|
}
|
|
670
677
|
|
|
678
|
+
async function urlAliasCommand(args) {
|
|
679
|
+
if (args.length === 0) {
|
|
680
|
+
log('red', 'Error: URL alias subcommand required');
|
|
681
|
+
console.log('\nUsage:');
|
|
682
|
+
console.log(' mags url alias <subdomain> <workspace> [--lfg]');
|
|
683
|
+
console.log(' mags url alias list');
|
|
684
|
+
console.log(' mags url alias remove <subdomain>');
|
|
685
|
+
process.exit(1);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const subcommand = args[0];
|
|
689
|
+
|
|
690
|
+
switch (subcommand) {
|
|
691
|
+
case 'list':
|
|
692
|
+
case 'ls':
|
|
693
|
+
await urlAliasList();
|
|
694
|
+
break;
|
|
695
|
+
case 'remove':
|
|
696
|
+
case 'rm':
|
|
697
|
+
case 'delete':
|
|
698
|
+
if (!args[1]) {
|
|
699
|
+
log('red', 'Error: Subdomain required');
|
|
700
|
+
console.log('\nUsage: mags url alias remove <subdomain>');
|
|
701
|
+
process.exit(1);
|
|
702
|
+
}
|
|
703
|
+
await urlAliasRemove(args[1]);
|
|
704
|
+
break;
|
|
705
|
+
default:
|
|
706
|
+
// mags url alias <subdomain> <workspace> [--lfg]
|
|
707
|
+
const subdomain = args[0];
|
|
708
|
+
const workspace = args[1];
|
|
709
|
+
if (!workspace) {
|
|
710
|
+
log('red', 'Error: Workspace required');
|
|
711
|
+
console.log('\nUsage: mags url alias <subdomain> <workspace> [--lfg]');
|
|
712
|
+
process.exit(1);
|
|
713
|
+
}
|
|
714
|
+
const useLfg = args.includes('--lfg');
|
|
715
|
+
await urlAliasCreate(subdomain, workspace, useLfg);
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
async function urlAliasCreate(subdomain, workspaceId, useLfg) {
|
|
721
|
+
const domain = useLfg ? 'app.lfg.run' : 'apps.magpiecloud.com';
|
|
722
|
+
log('blue', `Creating URL alias: ${subdomain}.${domain} → workspace '${workspaceId}'...`);
|
|
723
|
+
|
|
724
|
+
const resp = await request('POST', '/api/v1/mags-url-aliases', {
|
|
725
|
+
subdomain,
|
|
726
|
+
workspace_id: workspaceId,
|
|
727
|
+
domain,
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
if (resp.error) {
|
|
731
|
+
log('red', `Error: ${resp.error}`);
|
|
732
|
+
process.exit(1);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if (resp.url) {
|
|
736
|
+
log('green', `URL alias created: ${resp.url}`);
|
|
737
|
+
} else {
|
|
738
|
+
log('green', `URL alias created: https://${subdomain}.${domain}`);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
async function urlAliasList() {
|
|
743
|
+
const resp = await request('GET', '/api/v1/mags-url-aliases');
|
|
744
|
+
const aliases = resp.aliases || [];
|
|
745
|
+
|
|
746
|
+
if (aliases.length > 0) {
|
|
747
|
+
log('cyan', 'URL Aliases:\n');
|
|
748
|
+
aliases.forEach(a => {
|
|
749
|
+
console.log(` ${colors.bold}${a.subdomain}${colors.reset}`);
|
|
750
|
+
console.log(` URL: ${colors.green}${a.url}${colors.reset}`);
|
|
751
|
+
console.log(` Workspace: ${a.workspace_id} Domain: ${a.domain}`);
|
|
752
|
+
console.log('');
|
|
753
|
+
});
|
|
754
|
+
log('gray', `Total: ${aliases.length} alias(es)`);
|
|
755
|
+
} else {
|
|
756
|
+
log('yellow', 'No URL aliases found');
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
async function urlAliasRemove(subdomain) {
|
|
761
|
+
log('blue', `Removing URL alias '${subdomain}'...`);
|
|
762
|
+
const resp = await request('DELETE', `/api/v1/mags-url-aliases/${subdomain}`);
|
|
763
|
+
if (resp.error) {
|
|
764
|
+
log('red', `Error: ${resp.error}`);
|
|
765
|
+
process.exit(1);
|
|
766
|
+
}
|
|
767
|
+
log('green', resp.message || `URL alias '${subdomain}' removed`);
|
|
768
|
+
}
|
|
769
|
+
|
|
671
770
|
async function getStatus(nameOrId) {
|
|
672
771
|
if (!nameOrId) {
|
|
673
772
|
log('red', 'Error: Job name or ID required');
|
|
@@ -1443,7 +1542,11 @@ async function main() {
|
|
|
1443
1542
|
break;
|
|
1444
1543
|
case 'url':
|
|
1445
1544
|
await requireAuth();
|
|
1446
|
-
|
|
1545
|
+
if (args[1] === 'alias') {
|
|
1546
|
+
await urlAliasCommand(args.slice(2));
|
|
1547
|
+
} else {
|
|
1548
|
+
await enableUrlAccess(args[1], parseInt(args[2]) || 8080);
|
|
1549
|
+
}
|
|
1447
1550
|
break;
|
|
1448
1551
|
case 'status':
|
|
1449
1552
|
await requireAuth();
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
package/python/pyproject.toml
CHANGED
|
@@ -507,3 +507,36 @@ class Mags:
|
|
|
507
507
|
def cron_delete(self, cron_id: str) -> dict:
|
|
508
508
|
"""Delete a cron job."""
|
|
509
509
|
return self._request("DELETE", f"/mags-cron/{cron_id}")
|
|
510
|
+
|
|
511
|
+
# ── URL aliases ──────────────────────────────────────────────────
|
|
512
|
+
|
|
513
|
+
def url_alias_create(
|
|
514
|
+
self,
|
|
515
|
+
subdomain: str,
|
|
516
|
+
workspace_id: str,
|
|
517
|
+
domain: str = "apps.magpiecloud.com",
|
|
518
|
+
) -> dict:
|
|
519
|
+
"""Create a stable URL alias for a workspace.
|
|
520
|
+
|
|
521
|
+
The alias maps ``subdomain.<domain>`` to the active job in the workspace.
|
|
522
|
+
Use ``domain="app.lfg.run"`` for the LFG domain.
|
|
523
|
+
|
|
524
|
+
Returns ``{"id": ..., "subdomain": ..., "url": ...}``.
|
|
525
|
+
"""
|
|
526
|
+
return self._request(
|
|
527
|
+
"POST",
|
|
528
|
+
"/mags-url-aliases",
|
|
529
|
+
json={
|
|
530
|
+
"subdomain": subdomain,
|
|
531
|
+
"workspace_id": workspace_id,
|
|
532
|
+
"domain": domain,
|
|
533
|
+
},
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
def url_alias_list(self) -> dict:
|
|
537
|
+
"""List all URL aliases. Returns ``{"aliases": [...], "total": N}``."""
|
|
538
|
+
return self._request("GET", "/mags-url-aliases")
|
|
539
|
+
|
|
540
|
+
def url_alias_delete(self, subdomain: str) -> dict:
|
|
541
|
+
"""Delete a URL alias by subdomain."""
|
|
542
|
+
return self._request("DELETE", f"/mags-url-aliases/{subdomain}")
|
|
Binary file
|
|
Binary file
|