agentuity-vscode 0.1.10 → 0.1.12
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/.vscodeignore +4 -0
- package/dist/extension.js +14361 -0
- package/package.json +1 -1
- package/resources/icon.png +0 -0
- package/src/core/cliClient.ts +128 -147
- package/src/core/sandboxManager.ts +46 -5
- package/src/features/chat/agentTools.ts +71 -3
- package/src/features/sandboxExplorer/index.ts +160 -36
- package/src/features/sandboxExplorer/sandboxTreeData.ts +77 -22
- package/src/features/sandboxExplorer/statusBar.ts +15 -2
package/package.json
CHANGED
package/resources/icon.png
CHANGED
|
Binary file
|
package/src/core/cliClient.ts
CHANGED
|
@@ -103,19 +103,6 @@ export class CliClient {
|
|
|
103
103
|
return args;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
/**
|
|
107
|
-
* Append --region flag to args using region from agentuity.json.
|
|
108
|
-
* Used for commands that require region but don't accept --dir.
|
|
109
|
-
* The --region flag is a subcommand option, so it must come after the command.
|
|
110
|
-
*/
|
|
111
|
-
private withRegion(args: string[]): string[] {
|
|
112
|
-
const region = this.getProjectRegion();
|
|
113
|
-
if (region) {
|
|
114
|
-
return [...args, '--region', region];
|
|
115
|
-
}
|
|
116
|
-
return args;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
106
|
/**
|
|
120
107
|
* Get the environment variables for CLI execution.
|
|
121
108
|
* Sets TERM_PROGRAM=vscode to ensure CLI disables interactive mode.
|
|
@@ -329,19 +316,26 @@ export class CliClient {
|
|
|
329
316
|
return this.exec<string>(['ai', 'prompt', 'llm'], { format: 'text' });
|
|
330
317
|
}
|
|
331
318
|
|
|
332
|
-
// Database methods (require region - pass --region from agentuity.json)
|
|
333
319
|
async listDatabases(): Promise<CliResult<DbListResponse>> {
|
|
334
|
-
return this.exec<DbListResponse>(
|
|
320
|
+
return this.exec<DbListResponse>(['cloud', 'db', 'list'], {
|
|
335
321
|
format: 'json',
|
|
336
322
|
});
|
|
337
323
|
}
|
|
338
324
|
|
|
339
325
|
async getDatabase(name: string): Promise<CliResult<DbInfo>> {
|
|
340
|
-
return this.exec<DbInfo>(
|
|
326
|
+
return this.exec<DbInfo>(['cloud', 'db', 'get', name], {
|
|
341
327
|
format: 'json',
|
|
342
328
|
});
|
|
343
329
|
}
|
|
344
330
|
|
|
331
|
+
async createDatabase(options: DbCreateOptions): Promise<CliResult<DbInfo>> {
|
|
332
|
+
const args = ['cloud', 'db', 'create', '--name', options.name];
|
|
333
|
+
if (options.description) {
|
|
334
|
+
args.push('--description', options.description);
|
|
335
|
+
}
|
|
336
|
+
return this.exec<DbInfo>(args, { format: 'json', timeout: 60000 });
|
|
337
|
+
}
|
|
338
|
+
|
|
345
339
|
async getDbLogs(
|
|
346
340
|
name: string,
|
|
347
341
|
opts?: { limit?: number; hasError?: boolean; sessionId?: string }
|
|
@@ -356,12 +350,11 @@ export class CliClient {
|
|
|
356
350
|
if (opts?.sessionId) {
|
|
357
351
|
args.push('--session-id', opts.sessionId);
|
|
358
352
|
}
|
|
359
|
-
return this.exec<DbQueryLog[]>(
|
|
353
|
+
return this.exec<DbQueryLog[]>(args, { format: 'json', timeout: 60000 });
|
|
360
354
|
}
|
|
361
355
|
|
|
362
|
-
// Storage methods (require region - pass --region from agentuity.json)
|
|
363
356
|
async listStorageBuckets(): Promise<CliResult<StorageListResponse>> {
|
|
364
|
-
return this.exec<StorageListResponse>(
|
|
357
|
+
return this.exec<StorageListResponse>(['cloud', 'storage', 'list'], {
|
|
365
358
|
format: 'json',
|
|
366
359
|
});
|
|
367
360
|
}
|
|
@@ -374,7 +367,7 @@ export class CliClient {
|
|
|
374
367
|
if (prefix) {
|
|
375
368
|
args.push(prefix);
|
|
376
369
|
}
|
|
377
|
-
return this.exec<StorageListResponse>(
|
|
370
|
+
return this.exec<StorageListResponse>(args, { format: 'json' });
|
|
378
371
|
}
|
|
379
372
|
|
|
380
373
|
async getStorageFileMetadata(
|
|
@@ -382,7 +375,7 @@ export class CliClient {
|
|
|
382
375
|
filename: string
|
|
383
376
|
): Promise<CliResult<StorageFileMetadataResponse>> {
|
|
384
377
|
return this.exec<StorageFileMetadataResponse>(
|
|
385
|
-
|
|
378
|
+
['cloud', 'storage', 'download', bucket, filename, '--metadata'],
|
|
386
379
|
{ format: 'json' }
|
|
387
380
|
);
|
|
388
381
|
}
|
|
@@ -509,17 +502,6 @@ export class CliClient {
|
|
|
509
502
|
|
|
510
503
|
// ==================== Sandbox Methods ====================
|
|
511
504
|
|
|
512
|
-
/** Default region for sandbox operations when no agentuity.json is present */
|
|
513
|
-
private readonly defaultSandboxRegion = 'usc';
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* Get the region for sandbox operations.
|
|
517
|
-
* Uses region from agentuity.json if present, otherwise falls back to default.
|
|
518
|
-
*/
|
|
519
|
-
getSandboxRegion(): string {
|
|
520
|
-
return this.getProjectRegion() ?? this.defaultSandboxRegion;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
505
|
/** Default home path in sandboxes */
|
|
524
506
|
static readonly SANDBOX_HOME = '/home/agentuity';
|
|
525
507
|
|
|
@@ -527,8 +509,23 @@ export class CliClient {
|
|
|
527
509
|
* Create a new sandbox.
|
|
528
510
|
*/
|
|
529
511
|
async sandboxCreate(options: SandboxCreateOptions = {}): Promise<CliResult<SandboxInfo>> {
|
|
530
|
-
const
|
|
512
|
+
const region = this.getProjectRegion() ?? 'usc';
|
|
513
|
+
const args = ['cloud', 'sandbox', 'create', '--region', region];
|
|
531
514
|
|
|
515
|
+
// New runtime/name/description options
|
|
516
|
+
if (options.runtime) {
|
|
517
|
+
args.push('--runtime', options.runtime);
|
|
518
|
+
}
|
|
519
|
+
if (options.runtimeId) {
|
|
520
|
+
args.push('--runtime-id', options.runtimeId);
|
|
521
|
+
}
|
|
522
|
+
if (options.name) {
|
|
523
|
+
args.push('--name', options.name);
|
|
524
|
+
}
|
|
525
|
+
if (options.description) {
|
|
526
|
+
args.push('--description', options.description);
|
|
527
|
+
}
|
|
528
|
+
// Existing options
|
|
532
529
|
if (options.memory) {
|
|
533
530
|
args.push('--memory', options.memory);
|
|
534
531
|
}
|
|
@@ -541,6 +538,9 @@ export class CliClient {
|
|
|
541
538
|
if (options.network) {
|
|
542
539
|
args.push('--network');
|
|
543
540
|
}
|
|
541
|
+
if (options.port !== undefined) {
|
|
542
|
+
args.push('--port', String(options.port));
|
|
543
|
+
}
|
|
544
544
|
if (options.idleTimeout) {
|
|
545
545
|
args.push('--idle-timeout', String(options.idleTimeout));
|
|
546
546
|
}
|
|
@@ -569,11 +569,30 @@ export class CliClient {
|
|
|
569
569
|
return this.exec<SandboxInfo>(args, { format: 'json', timeout: 120000 });
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
/**
|
|
573
|
+
* List available sandbox runtimes.
|
|
574
|
+
*/
|
|
575
|
+
async sandboxRuntimeList(
|
|
576
|
+
params: SandboxRuntimeListParams = {}
|
|
577
|
+
): Promise<CliResult<SandboxRuntimeListResponse>> {
|
|
578
|
+
const args = ['cloud', 'sandbox', 'runtime', 'list'];
|
|
579
|
+
|
|
580
|
+
if (params.limit !== undefined) {
|
|
581
|
+
args.push('--limit', String(params.limit));
|
|
582
|
+
}
|
|
583
|
+
if (params.offset !== undefined) {
|
|
584
|
+
args.push('--offset', String(params.offset));
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return this.exec<SandboxRuntimeListResponse>(args, { format: 'json' });
|
|
588
|
+
}
|
|
589
|
+
|
|
572
590
|
/**
|
|
573
591
|
* List sandboxes with optional filtering.
|
|
592
|
+
* Uses --all flag to list all sandboxes regardless of project context.
|
|
574
593
|
*/
|
|
575
594
|
async sandboxList(filter: SandboxListFilter = {}): Promise<CliResult<SandboxInfo[]>> {
|
|
576
|
-
const args = ['cloud', 'sandbox', 'list', '--
|
|
595
|
+
const args = ['cloud', 'sandbox', 'list', '--all'];
|
|
577
596
|
|
|
578
597
|
if (filter.status) {
|
|
579
598
|
args.push('--status', filter.status);
|
|
@@ -588,7 +607,6 @@ export class CliClient {
|
|
|
588
607
|
args.push('--offset', String(filter.offset));
|
|
589
608
|
}
|
|
590
609
|
|
|
591
|
-
// CLI returns { sandboxes: [...], total: N }, extract the array
|
|
592
610
|
const result = await this.exec<{ sandboxes: SandboxInfo[]; total: number }>(args, {
|
|
593
611
|
format: 'json',
|
|
594
612
|
});
|
|
@@ -602,28 +620,16 @@ export class CliClient {
|
|
|
602
620
|
* Get detailed information about a sandbox.
|
|
603
621
|
*/
|
|
604
622
|
async sandboxGet(sandboxId: string): Promise<CliResult<SandboxInfo>> {
|
|
605
|
-
return this.exec<SandboxInfo>(
|
|
606
|
-
['cloud', 'sandbox', 'get', sandboxId, '--region', this.getSandboxRegion()],
|
|
607
|
-
{ format: 'json' }
|
|
608
|
-
);
|
|
623
|
+
return this.exec<SandboxInfo>(['cloud', 'sandbox', 'get', sandboxId], { format: 'json' });
|
|
609
624
|
}
|
|
610
625
|
|
|
611
626
|
/**
|
|
612
627
|
* Delete a sandbox.
|
|
613
628
|
*/
|
|
614
629
|
async sandboxDelete(sandboxId: string): Promise<CliResult<void>> {
|
|
615
|
-
return this.exec<void>(
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
'sandbox',
|
|
619
|
-
'delete',
|
|
620
|
-
sandboxId,
|
|
621
|
-
'--confirm',
|
|
622
|
-
'--region',
|
|
623
|
-
this.getSandboxRegion(),
|
|
624
|
-
],
|
|
625
|
-
{ format: 'json' }
|
|
626
|
-
);
|
|
630
|
+
return this.exec<void>(['cloud', 'sandbox', 'delete', sandboxId, '--confirm'], {
|
|
631
|
+
format: 'json',
|
|
632
|
+
});
|
|
627
633
|
}
|
|
628
634
|
|
|
629
635
|
/**
|
|
@@ -635,7 +641,7 @@ export class CliClient {
|
|
|
635
641
|
command: string[],
|
|
636
642
|
options: SandboxExecOptions = {}
|
|
637
643
|
): Promise<CliResult<ExecutionInfo>> {
|
|
638
|
-
const args = ['cloud', 'sandbox', 'exec', sandboxId
|
|
644
|
+
const args = ['cloud', 'sandbox', 'exec', sandboxId];
|
|
639
645
|
|
|
640
646
|
if (options.timeout) {
|
|
641
647
|
args.push('--timeout', String(options.timeout));
|
|
@@ -655,13 +661,11 @@ export class CliClient {
|
|
|
655
661
|
*/
|
|
656
662
|
async sandboxLs(sandboxId: string, remotePath?: string): Promise<CliResult<SandboxFileInfo[]>> {
|
|
657
663
|
const args = ['cloud', 'sandbox', 'files', sandboxId];
|
|
658
|
-
// Only add path if specified (omit for root listing)
|
|
659
664
|
if (remotePath) {
|
|
660
665
|
args.push(remotePath);
|
|
661
666
|
}
|
|
662
|
-
args.push('-l'
|
|
667
|
+
args.push('-l');
|
|
663
668
|
|
|
664
|
-
// CLI returns { files: [...], total: N }, extract the array and add name from path
|
|
665
669
|
const result = await this.exec<{
|
|
666
670
|
files: Array<Omit<SandboxFileInfo, 'name'>>;
|
|
667
671
|
total: number;
|
|
@@ -669,7 +673,7 @@ export class CliClient {
|
|
|
669
673
|
if (result.success && result.data) {
|
|
670
674
|
const files = (result.data.files || []).map((f) => ({
|
|
671
675
|
...f,
|
|
672
|
-
name: f.path.split('/').pop() || f.path,
|
|
676
|
+
name: f.path.split('/').pop() || f.path,
|
|
673
677
|
}));
|
|
674
678
|
return { success: true, data: files, exitCode: result.exitCode };
|
|
675
679
|
}
|
|
@@ -685,7 +689,7 @@ export class CliClient {
|
|
|
685
689
|
remotePath: string,
|
|
686
690
|
recursive = false
|
|
687
691
|
): Promise<CliResult<SandboxCpResult>> {
|
|
688
|
-
const args = ['cloud', 'sandbox', 'cp'
|
|
692
|
+
const args = ['cloud', 'sandbox', 'cp'];
|
|
689
693
|
if (recursive) {
|
|
690
694
|
args.push('-r');
|
|
691
695
|
}
|
|
@@ -702,7 +706,7 @@ export class CliClient {
|
|
|
702
706
|
localPath: string,
|
|
703
707
|
recursive = false
|
|
704
708
|
): Promise<CliResult<SandboxCpResult>> {
|
|
705
|
-
const args = ['cloud', 'sandbox', 'cp'
|
|
709
|
+
const args = ['cloud', 'sandbox', 'cp'];
|
|
706
710
|
if (recursive) {
|
|
707
711
|
args.push('-r');
|
|
708
712
|
}
|
|
@@ -718,15 +722,7 @@ export class CliClient {
|
|
|
718
722
|
archivePath: string,
|
|
719
723
|
destPath?: string
|
|
720
724
|
): Promise<CliResult<void>> {
|
|
721
|
-
const args = [
|
|
722
|
-
'cloud',
|
|
723
|
-
'sandbox',
|
|
724
|
-
'upload',
|
|
725
|
-
sandboxId,
|
|
726
|
-
archivePath,
|
|
727
|
-
'--region',
|
|
728
|
-
this.getSandboxRegion(),
|
|
729
|
-
];
|
|
725
|
+
const args = ['cloud', 'sandbox', 'upload', sandboxId, archivePath];
|
|
730
726
|
if (destPath) {
|
|
731
727
|
args.push('--path', destPath);
|
|
732
728
|
}
|
|
@@ -741,15 +737,7 @@ export class CliClient {
|
|
|
741
737
|
outputPath: string,
|
|
742
738
|
sourcePath?: string
|
|
743
739
|
): Promise<CliResult<void>> {
|
|
744
|
-
const args = [
|
|
745
|
-
'cloud',
|
|
746
|
-
'sandbox',
|
|
747
|
-
'download',
|
|
748
|
-
sandboxId,
|
|
749
|
-
outputPath,
|
|
750
|
-
'--region',
|
|
751
|
-
this.getSandboxRegion(),
|
|
752
|
-
];
|
|
740
|
+
const args = ['cloud', 'sandbox', 'download', sandboxId, outputPath];
|
|
753
741
|
if (sourcePath) {
|
|
754
742
|
args.push('--path', sourcePath);
|
|
755
743
|
}
|
|
@@ -764,15 +752,7 @@ export class CliClient {
|
|
|
764
752
|
remotePath: string,
|
|
765
753
|
recursive = false
|
|
766
754
|
): Promise<CliResult<void>> {
|
|
767
|
-
const args = [
|
|
768
|
-
'cloud',
|
|
769
|
-
'sandbox',
|
|
770
|
-
'mkdir',
|
|
771
|
-
sandboxId,
|
|
772
|
-
remotePath,
|
|
773
|
-
'--region',
|
|
774
|
-
this.getSandboxRegion(),
|
|
775
|
-
];
|
|
755
|
+
const args = ['cloud', 'sandbox', 'mkdir', sandboxId, remotePath];
|
|
776
756
|
if (recursive) {
|
|
777
757
|
args.push('-p');
|
|
778
758
|
}
|
|
@@ -783,10 +763,7 @@ export class CliClient {
|
|
|
783
763
|
* Remove a file from a sandbox.
|
|
784
764
|
*/
|
|
785
765
|
async sandboxRm(sandboxId: string, remotePath: string): Promise<CliResult<void>> {
|
|
786
|
-
return this.exec<void>(
|
|
787
|
-
['cloud', 'sandbox', 'rm', sandboxId, remotePath, '--region', this.getSandboxRegion()],
|
|
788
|
-
{ format: 'json' }
|
|
789
|
-
);
|
|
766
|
+
return this.exec<void>(['cloud', 'sandbox', 'rm', sandboxId, remotePath], { format: 'json' });
|
|
790
767
|
}
|
|
791
768
|
|
|
792
769
|
/**
|
|
@@ -797,15 +774,7 @@ export class CliClient {
|
|
|
797
774
|
remotePath: string,
|
|
798
775
|
recursive = false
|
|
799
776
|
): Promise<CliResult<void>> {
|
|
800
|
-
const args = [
|
|
801
|
-
'cloud',
|
|
802
|
-
'sandbox',
|
|
803
|
-
'rmdir',
|
|
804
|
-
sandboxId,
|
|
805
|
-
remotePath,
|
|
806
|
-
'--region',
|
|
807
|
-
this.getSandboxRegion(),
|
|
808
|
-
];
|
|
777
|
+
const args = ['cloud', 'sandbox', 'rmdir', sandboxId, remotePath];
|
|
809
778
|
if (recursive) {
|
|
810
779
|
args.push('-r');
|
|
811
780
|
}
|
|
@@ -819,7 +788,7 @@ export class CliClient {
|
|
|
819
788
|
sandboxId: string,
|
|
820
789
|
vars: Record<string, string>
|
|
821
790
|
): Promise<CliResult<SandboxEnvResult>> {
|
|
822
|
-
const args = ['cloud', 'sandbox', 'env', sandboxId
|
|
791
|
+
const args = ['cloud', 'sandbox', 'env', sandboxId];
|
|
823
792
|
for (const [key, value] of Object.entries(vars)) {
|
|
824
793
|
args.push(`${key}=${value}`);
|
|
825
794
|
}
|
|
@@ -833,7 +802,7 @@ export class CliClient {
|
|
|
833
802
|
sandboxId: string,
|
|
834
803
|
varNames: string[]
|
|
835
804
|
): Promise<CliResult<SandboxEnvResult>> {
|
|
836
|
-
const args = ['cloud', 'sandbox', 'env', sandboxId
|
|
805
|
+
const args = ['cloud', 'sandbox', 'env', sandboxId];
|
|
837
806
|
for (const name of varNames) {
|
|
838
807
|
args.push('--delete', name);
|
|
839
808
|
}
|
|
@@ -844,10 +813,9 @@ export class CliClient {
|
|
|
844
813
|
* Get environment variables from a sandbox.
|
|
845
814
|
*/
|
|
846
815
|
async sandboxEnvGet(sandboxId: string): Promise<CliResult<SandboxEnvResult>> {
|
|
847
|
-
return this.exec<SandboxEnvResult>(
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
);
|
|
816
|
+
return this.exec<SandboxEnvResult>(['cloud', 'sandbox', 'env', sandboxId], {
|
|
817
|
+
format: 'json',
|
|
818
|
+
});
|
|
851
819
|
}
|
|
852
820
|
|
|
853
821
|
// ==================== Snapshot Methods ====================
|
|
@@ -856,15 +824,7 @@ export class CliClient {
|
|
|
856
824
|
* Create a snapshot of a sandbox.
|
|
857
825
|
*/
|
|
858
826
|
async snapshotCreate(sandboxId: string, tag?: string): Promise<CliResult<SnapshotInfo>> {
|
|
859
|
-
const args = [
|
|
860
|
-
'cloud',
|
|
861
|
-
'sandbox',
|
|
862
|
-
'snapshot',
|
|
863
|
-
'create',
|
|
864
|
-
sandboxId,
|
|
865
|
-
'--region',
|
|
866
|
-
this.getSandboxRegion(),
|
|
867
|
-
];
|
|
827
|
+
const args = ['cloud', 'sandbox', 'snapshot', 'create', sandboxId];
|
|
868
828
|
if (tag) {
|
|
869
829
|
args.push('--tag', tag);
|
|
870
830
|
}
|
|
@@ -875,11 +835,10 @@ export class CliClient {
|
|
|
875
835
|
* List snapshots with optional sandbox filter.
|
|
876
836
|
*/
|
|
877
837
|
async snapshotList(sandboxId?: string): Promise<CliResult<SnapshotInfo[]>> {
|
|
878
|
-
const args = ['cloud', 'sandbox', 'snapshot', 'list'
|
|
838
|
+
const args = ['cloud', 'sandbox', 'snapshot', 'list'];
|
|
879
839
|
if (sandboxId) {
|
|
880
840
|
args.push('--sandbox', sandboxId);
|
|
881
841
|
}
|
|
882
|
-
// CLI returns { snapshots: [], total: N }
|
|
883
842
|
const result = await this.exec<{ snapshots: SnapshotInfo[]; total: number }>(args, {
|
|
884
843
|
format: 'json',
|
|
885
844
|
});
|
|
@@ -893,44 +852,25 @@ export class CliClient {
|
|
|
893
852
|
* Get detailed information about a snapshot.
|
|
894
853
|
*/
|
|
895
854
|
async snapshotGet(snapshotId: string): Promise<CliResult<SnapshotInfo>> {
|
|
896
|
-
return this.exec<SnapshotInfo>(
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
);
|
|
855
|
+
return this.exec<SnapshotInfo>(['cloud', 'sandbox', 'snapshot', 'get', snapshotId], {
|
|
856
|
+
format: 'json',
|
|
857
|
+
});
|
|
900
858
|
}
|
|
901
859
|
|
|
902
860
|
/**
|
|
903
861
|
* Delete a snapshot.
|
|
904
862
|
*/
|
|
905
863
|
async snapshotDelete(snapshotId: string): Promise<CliResult<void>> {
|
|
906
|
-
return this.exec<void>(
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
'sandbox',
|
|
910
|
-
'snapshot',
|
|
911
|
-
'delete',
|
|
912
|
-
snapshotId,
|
|
913
|
-
'--confirm',
|
|
914
|
-
'--region',
|
|
915
|
-
this.getSandboxRegion(),
|
|
916
|
-
],
|
|
917
|
-
{ format: 'json' }
|
|
918
|
-
);
|
|
864
|
+
return this.exec<void>(['cloud', 'sandbox', 'snapshot', 'delete', snapshotId, '--confirm'], {
|
|
865
|
+
format: 'json',
|
|
866
|
+
});
|
|
919
867
|
}
|
|
920
868
|
|
|
921
869
|
/**
|
|
922
870
|
* Tag or untag a snapshot.
|
|
923
871
|
*/
|
|
924
872
|
async snapshotTag(snapshotId: string, tag: string | null): Promise<CliResult<void>> {
|
|
925
|
-
const args = [
|
|
926
|
-
'cloud',
|
|
927
|
-
'sandbox',
|
|
928
|
-
'snapshot',
|
|
929
|
-
'tag',
|
|
930
|
-
snapshotId,
|
|
931
|
-
'--region',
|
|
932
|
-
this.getSandboxRegion(),
|
|
933
|
-
];
|
|
873
|
+
const args = ['cloud', 'sandbox', 'snapshot', 'tag', snapshotId];
|
|
934
874
|
if (tag === null) {
|
|
935
875
|
args.push('--clear');
|
|
936
876
|
} else {
|
|
@@ -945,9 +885,8 @@ export class CliClient {
|
|
|
945
885
|
* List executions for a sandbox.
|
|
946
886
|
*/
|
|
947
887
|
async executionList(sandboxId: string): Promise<CliResult<ExecutionInfo[]>> {
|
|
948
|
-
// CLI returns { executions: [] }
|
|
949
888
|
const result = await this.exec<{ executions: ExecutionInfo[] }>(
|
|
950
|
-
['cloud', 'sandbox', 'execution', 'list', sandboxId
|
|
889
|
+
['cloud', 'sandbox', 'execution', 'list', sandboxId],
|
|
951
890
|
{ format: 'json' }
|
|
952
891
|
);
|
|
953
892
|
if (result.success && result.data) {
|
|
@@ -960,10 +899,9 @@ export class CliClient {
|
|
|
960
899
|
* Get detailed information about an execution.
|
|
961
900
|
*/
|
|
962
901
|
async executionGet(executionId: string): Promise<CliResult<ExecutionInfo>> {
|
|
963
|
-
return this.exec<ExecutionInfo>(
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
);
|
|
902
|
+
return this.exec<ExecutionInfo>(['cloud', 'sandbox', 'execution', 'get', executionId], {
|
|
903
|
+
format: 'json',
|
|
904
|
+
});
|
|
967
905
|
}
|
|
968
906
|
|
|
969
907
|
dispose(): void {
|
|
@@ -1026,12 +964,19 @@ export interface KvGetResponse {
|
|
|
1026
964
|
export interface DbInfo {
|
|
1027
965
|
name: string;
|
|
1028
966
|
url: string;
|
|
967
|
+
description?: string | null;
|
|
968
|
+
region?: string;
|
|
1029
969
|
}
|
|
1030
970
|
|
|
1031
971
|
export interface DbListResponse {
|
|
1032
972
|
databases: DbInfo[];
|
|
1033
973
|
}
|
|
1034
974
|
|
|
975
|
+
export interface DbCreateOptions {
|
|
976
|
+
name: string;
|
|
977
|
+
description?: string;
|
|
978
|
+
}
|
|
979
|
+
|
|
1035
980
|
export interface DbQueryLog {
|
|
1036
981
|
timestamp: string;
|
|
1037
982
|
command: string;
|
|
@@ -1270,13 +1215,29 @@ export interface SandboxInfo {
|
|
|
1270
1215
|
resources?: SandboxResources;
|
|
1271
1216
|
stdoutStreamUrl?: string;
|
|
1272
1217
|
stderrStreamUrl?: string;
|
|
1218
|
+
// New fields from sandbox improvements
|
|
1219
|
+
name?: string;
|
|
1220
|
+
description?: string;
|
|
1221
|
+
runtimeId?: string;
|
|
1222
|
+
runtimeName?: string;
|
|
1223
|
+
// Network/URL fields
|
|
1224
|
+
identifier?: string;
|
|
1225
|
+
networkPort?: number;
|
|
1226
|
+
url?: string;
|
|
1273
1227
|
}
|
|
1274
1228
|
|
|
1275
1229
|
export interface SandboxCreateOptions {
|
|
1230
|
+
// New fields from sandbox improvements
|
|
1231
|
+
runtime?: string;
|
|
1232
|
+
runtimeId?: string;
|
|
1233
|
+
name?: string;
|
|
1234
|
+
description?: string;
|
|
1235
|
+
// Existing fields
|
|
1276
1236
|
memory?: string;
|
|
1277
1237
|
cpu?: string;
|
|
1278
1238
|
disk?: string;
|
|
1279
1239
|
network?: boolean;
|
|
1240
|
+
port?: number; // 1024-65535, enables network automatically
|
|
1280
1241
|
idleTimeout?: number;
|
|
1281
1242
|
execTimeout?: number;
|
|
1282
1243
|
env?: Record<string, string>;
|
|
@@ -1341,6 +1302,26 @@ export interface SandboxEnvResult {
|
|
|
1341
1302
|
env: Record<string, string>;
|
|
1342
1303
|
}
|
|
1343
1304
|
|
|
1305
|
+
// Sandbox runtime types
|
|
1306
|
+
export interface SandboxRuntime {
|
|
1307
|
+
id: string;
|
|
1308
|
+
name: string;
|
|
1309
|
+
description?: string;
|
|
1310
|
+
iconUrl?: string;
|
|
1311
|
+
url?: string;
|
|
1312
|
+
tags?: string[];
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
export interface SandboxRuntimeListParams {
|
|
1316
|
+
limit?: number;
|
|
1317
|
+
offset?: number;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
export interface SandboxRuntimeListResponse {
|
|
1321
|
+
runtimes: SandboxRuntime[];
|
|
1322
|
+
total: number;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1344
1325
|
// Singleton
|
|
1345
1326
|
let _cliClient: CliClient | undefined;
|
|
1346
1327
|
|
|
@@ -17,6 +17,11 @@ export interface LinkedSandbox {
|
|
|
17
17
|
linkedAt: string;
|
|
18
18
|
lastSyncedAt?: string;
|
|
19
19
|
remotePath: string;
|
|
20
|
+
// New fields from sandbox improvements
|
|
21
|
+
description?: string;
|
|
22
|
+
runtimeId?: string;
|
|
23
|
+
runtimeName?: string;
|
|
24
|
+
region?: string;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
/**
|
|
@@ -80,11 +85,12 @@ export class SandboxManager {
|
|
|
80
85
|
throw new Error('No workspace folder open');
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
// Verify sandbox exists
|
|
88
|
+
// Verify sandbox exists and get its info
|
|
84
89
|
const result = await this.cliClient.sandboxGet(sandboxId);
|
|
85
|
-
if (!result.success) {
|
|
90
|
+
if (!result.success || !result.data) {
|
|
86
91
|
throw new Error(`Failed to verify sandbox: ${result.error}`);
|
|
87
92
|
}
|
|
93
|
+
const sandboxInfo = result.data;
|
|
88
94
|
|
|
89
95
|
const allLinked = this.context.workspaceState.get<Record<string, LinkedSandbox[]>>(
|
|
90
96
|
LINKED_SANDBOXES_KEY,
|
|
@@ -100,6 +106,7 @@ export class SandboxManager {
|
|
|
100
106
|
...workspaceLinks[existingIndex],
|
|
101
107
|
name: options.name ?? workspaceLinks[existingIndex].name,
|
|
102
108
|
remotePath: options.remotePath ?? workspaceLinks[existingIndex].remotePath,
|
|
109
|
+
region: sandboxInfo.region ?? workspaceLinks[existingIndex].region,
|
|
103
110
|
};
|
|
104
111
|
} else {
|
|
105
112
|
// Add new link
|
|
@@ -108,6 +115,7 @@ export class SandboxManager {
|
|
|
108
115
|
name: options.name,
|
|
109
116
|
linkedAt: new Date().toISOString(),
|
|
110
117
|
remotePath: options.remotePath ?? DEFAULT_SANDBOX_PATH,
|
|
118
|
+
region: sandboxInfo.region,
|
|
111
119
|
});
|
|
112
120
|
}
|
|
113
121
|
|
|
@@ -428,20 +436,53 @@ export class SandboxManager {
|
|
|
428
436
|
/**
|
|
429
437
|
* Refresh sandbox info for all linked sandboxes.
|
|
430
438
|
* Returns info about which sandboxes are still valid.
|
|
439
|
+
* Also updates linked sandbox metadata with new fields from the API.
|
|
431
440
|
*/
|
|
432
441
|
async refreshLinkedSandboxes(): Promise<Map<string, SandboxInfo | null>> {
|
|
433
|
-
const
|
|
442
|
+
const workspaceKey = this.getWorkspaceKey();
|
|
443
|
+
if (!workspaceKey) {
|
|
444
|
+
return new Map();
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const allLinked = this.context.workspaceState.get<Record<string, LinkedSandbox[]>>(
|
|
448
|
+
LINKED_SANDBOXES_KEY,
|
|
449
|
+
{}
|
|
450
|
+
);
|
|
451
|
+
const workspaceLinks = allLinked[workspaceKey] || [];
|
|
434
452
|
const results = new Map<string, SandboxInfo | null>();
|
|
453
|
+
let needsUpdate = false;
|
|
435
454
|
|
|
436
|
-
for (const link of
|
|
455
|
+
for (const link of workspaceLinks) {
|
|
437
456
|
const result = await this.cliClient.sandboxGet(link.sandboxId);
|
|
438
457
|
if (result.success && result.data) {
|
|
439
|
-
|
|
458
|
+
const info = result.data;
|
|
459
|
+
results.set(link.sandboxId, info);
|
|
460
|
+
|
|
461
|
+
// Update linked sandbox with new fields from API
|
|
462
|
+
if (
|
|
463
|
+
info.name !== link.name ||
|
|
464
|
+
info.description !== link.description ||
|
|
465
|
+
info.runtimeId !== link.runtimeId ||
|
|
466
|
+
info.runtimeName !== link.runtimeName
|
|
467
|
+
) {
|
|
468
|
+
link.name = info.name ?? link.name;
|
|
469
|
+
link.description = info.description;
|
|
470
|
+
link.runtimeId = info.runtimeId;
|
|
471
|
+
link.runtimeName = info.runtimeName;
|
|
472
|
+
needsUpdate = true;
|
|
473
|
+
}
|
|
440
474
|
} else {
|
|
441
475
|
results.set(link.sandboxId, null);
|
|
442
476
|
}
|
|
443
477
|
}
|
|
444
478
|
|
|
479
|
+
// Persist updated metadata if changed
|
|
480
|
+
if (needsUpdate) {
|
|
481
|
+
allLinked[workspaceKey] = workspaceLinks;
|
|
482
|
+
await this.context.workspaceState.update(LINKED_SANDBOXES_KEY, allLinked);
|
|
483
|
+
_onLinkedSandboxesChanged.fire(workspaceLinks);
|
|
484
|
+
}
|
|
485
|
+
|
|
445
486
|
return results;
|
|
446
487
|
}
|
|
447
488
|
|