agentuity-vscode 0.1.7 → 0.1.9
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/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "agentuity-vscode",
|
|
3
3
|
"displayName": "Agentuity VSCode Extension",
|
|
4
4
|
"description": "Build, deploy, and manage AI agents with Agentuity",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.9",
|
|
6
6
|
"publisher": "agentuity",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"repository": {
|
|
@@ -653,7 +653,7 @@
|
|
|
653
653
|
},
|
|
654
654
|
"agentuity.sandbox.defaultRemotePath": {
|
|
655
655
|
"type": "string",
|
|
656
|
-
"default": "/home/agentuity
|
|
656
|
+
"default": "/home/agentuity",
|
|
657
657
|
"description": "Default path in sandbox for synced files"
|
|
658
658
|
}
|
|
659
659
|
}
|
|
@@ -978,8 +978,8 @@
|
|
|
978
978
|
},
|
|
979
979
|
"remotePath": {
|
|
980
980
|
"type": "string",
|
|
981
|
-
"description": "Remote path in sandbox (default: /home/agentuity
|
|
982
|
-
"default": "/home/agentuity
|
|
981
|
+
"description": "Remote path in sandbox (default: /home/agentuity)",
|
|
982
|
+
"default": "/home/agentuity"
|
|
983
983
|
},
|
|
984
984
|
"respectGitignore": {
|
|
985
985
|
"type": "boolean",
|
package/src/core/cliClient.ts
CHANGED
|
@@ -521,7 +521,7 @@ export class CliClient {
|
|
|
521
521
|
}
|
|
522
522
|
|
|
523
523
|
/** Default home path in sandboxes */
|
|
524
|
-
static readonly SANDBOX_HOME = '/home/agentuity
|
|
524
|
+
static readonly SANDBOX_HOME = '/home/agentuity';
|
|
525
525
|
|
|
526
526
|
/**
|
|
527
527
|
* Create a new sandbox.
|
|
@@ -589,7 +589,9 @@ export class CliClient {
|
|
|
589
589
|
}
|
|
590
590
|
|
|
591
591
|
// CLI returns { sandboxes: [...], total: N }, extract the array
|
|
592
|
-
const result = await this.exec<{ sandboxes: SandboxInfo[]; total: number }>(args, {
|
|
592
|
+
const result = await this.exec<{ sandboxes: SandboxInfo[]; total: number }>(args, {
|
|
593
|
+
format: 'json',
|
|
594
|
+
});
|
|
593
595
|
if (result.success && result.data) {
|
|
594
596
|
return { success: true, data: result.data.sandboxes || [], exitCode: result.exitCode };
|
|
595
597
|
}
|
|
@@ -611,7 +613,15 @@ export class CliClient {
|
|
|
611
613
|
*/
|
|
612
614
|
async sandboxDelete(sandboxId: string): Promise<CliResult<void>> {
|
|
613
615
|
return this.exec<void>(
|
|
614
|
-
[
|
|
616
|
+
[
|
|
617
|
+
'cloud',
|
|
618
|
+
'sandbox',
|
|
619
|
+
'delete',
|
|
620
|
+
sandboxId,
|
|
621
|
+
'--confirm',
|
|
622
|
+
'--region',
|
|
623
|
+
this.getSandboxRegion(),
|
|
624
|
+
],
|
|
615
625
|
{ format: 'json' }
|
|
616
626
|
);
|
|
617
627
|
}
|
|
@@ -652,9 +662,12 @@ export class CliClient {
|
|
|
652
662
|
args.push('-l', '--region', this.getSandboxRegion());
|
|
653
663
|
|
|
654
664
|
// CLI returns { files: [...], total: N }, extract the array and add name from path
|
|
655
|
-
const result = await this.exec<{
|
|
665
|
+
const result = await this.exec<{
|
|
666
|
+
files: Array<Omit<SandboxFileInfo, 'name'>>;
|
|
667
|
+
total: number;
|
|
668
|
+
}>(args, { format: 'json' });
|
|
656
669
|
if (result.success && result.data) {
|
|
657
|
-
const files = (result.data.files || []).map(f => ({
|
|
670
|
+
const files = (result.data.files || []).map((f) => ({
|
|
658
671
|
...f,
|
|
659
672
|
name: f.path.split('/').pop() || f.path, // Extract filename from path
|
|
660
673
|
}));
|
|
@@ -705,7 +718,15 @@ export class CliClient {
|
|
|
705
718
|
archivePath: string,
|
|
706
719
|
destPath?: string
|
|
707
720
|
): Promise<CliResult<void>> {
|
|
708
|
-
const args = [
|
|
721
|
+
const args = [
|
|
722
|
+
'cloud',
|
|
723
|
+
'sandbox',
|
|
724
|
+
'upload',
|
|
725
|
+
sandboxId,
|
|
726
|
+
archivePath,
|
|
727
|
+
'--region',
|
|
728
|
+
this.getSandboxRegion(),
|
|
729
|
+
];
|
|
709
730
|
if (destPath) {
|
|
710
731
|
args.push('--path', destPath);
|
|
711
732
|
}
|
|
@@ -720,7 +741,15 @@ export class CliClient {
|
|
|
720
741
|
outputPath: string,
|
|
721
742
|
sourcePath?: string
|
|
722
743
|
): Promise<CliResult<void>> {
|
|
723
|
-
const args = [
|
|
744
|
+
const args = [
|
|
745
|
+
'cloud',
|
|
746
|
+
'sandbox',
|
|
747
|
+
'download',
|
|
748
|
+
sandboxId,
|
|
749
|
+
outputPath,
|
|
750
|
+
'--region',
|
|
751
|
+
this.getSandboxRegion(),
|
|
752
|
+
];
|
|
724
753
|
if (sourcePath) {
|
|
725
754
|
args.push('--path', sourcePath);
|
|
726
755
|
}
|
|
@@ -735,7 +764,15 @@ export class CliClient {
|
|
|
735
764
|
remotePath: string,
|
|
736
765
|
recursive = false
|
|
737
766
|
): Promise<CliResult<void>> {
|
|
738
|
-
const args = [
|
|
767
|
+
const args = [
|
|
768
|
+
'cloud',
|
|
769
|
+
'sandbox',
|
|
770
|
+
'mkdir',
|
|
771
|
+
sandboxId,
|
|
772
|
+
remotePath,
|
|
773
|
+
'--region',
|
|
774
|
+
this.getSandboxRegion(),
|
|
775
|
+
];
|
|
739
776
|
if (recursive) {
|
|
740
777
|
args.push('-p');
|
|
741
778
|
}
|
|
@@ -760,7 +797,15 @@ export class CliClient {
|
|
|
760
797
|
remotePath: string,
|
|
761
798
|
recursive = false
|
|
762
799
|
): Promise<CliResult<void>> {
|
|
763
|
-
const args = [
|
|
800
|
+
const args = [
|
|
801
|
+
'cloud',
|
|
802
|
+
'sandbox',
|
|
803
|
+
'rmdir',
|
|
804
|
+
sandboxId,
|
|
805
|
+
remotePath,
|
|
806
|
+
'--region',
|
|
807
|
+
this.getSandboxRegion(),
|
|
808
|
+
];
|
|
764
809
|
if (recursive) {
|
|
765
810
|
args.push('-r');
|
|
766
811
|
}
|
|
@@ -811,7 +856,15 @@ export class CliClient {
|
|
|
811
856
|
* Create a snapshot of a sandbox.
|
|
812
857
|
*/
|
|
813
858
|
async snapshotCreate(sandboxId: string, tag?: string): Promise<CliResult<SnapshotInfo>> {
|
|
814
|
-
const args = [
|
|
859
|
+
const args = [
|
|
860
|
+
'cloud',
|
|
861
|
+
'sandbox',
|
|
862
|
+
'snapshot',
|
|
863
|
+
'create',
|
|
864
|
+
sandboxId,
|
|
865
|
+
'--region',
|
|
866
|
+
this.getSandboxRegion(),
|
|
867
|
+
];
|
|
815
868
|
if (tag) {
|
|
816
869
|
args.push('--tag', tag);
|
|
817
870
|
}
|
|
@@ -827,7 +880,9 @@ export class CliClient {
|
|
|
827
880
|
args.push('--sandbox', sandboxId);
|
|
828
881
|
}
|
|
829
882
|
// CLI returns { snapshots: [], total: N }
|
|
830
|
-
const result = await this.exec<{ snapshots: SnapshotInfo[]; total: number }>(args, {
|
|
883
|
+
const result = await this.exec<{ snapshots: SnapshotInfo[]; total: number }>(args, {
|
|
884
|
+
format: 'json',
|
|
885
|
+
});
|
|
831
886
|
if (result.success && result.data) {
|
|
832
887
|
return { success: true, data: result.data.snapshots || [], exitCode: result.exitCode };
|
|
833
888
|
}
|
|
@@ -849,7 +904,16 @@ export class CliClient {
|
|
|
849
904
|
*/
|
|
850
905
|
async snapshotDelete(snapshotId: string): Promise<CliResult<void>> {
|
|
851
906
|
return this.exec<void>(
|
|
852
|
-
[
|
|
907
|
+
[
|
|
908
|
+
'cloud',
|
|
909
|
+
'sandbox',
|
|
910
|
+
'snapshot',
|
|
911
|
+
'delete',
|
|
912
|
+
snapshotId,
|
|
913
|
+
'--confirm',
|
|
914
|
+
'--region',
|
|
915
|
+
this.getSandboxRegion(),
|
|
916
|
+
],
|
|
853
917
|
{ format: 'json' }
|
|
854
918
|
);
|
|
855
919
|
}
|
|
@@ -858,7 +922,15 @@ export class CliClient {
|
|
|
858
922
|
* Tag or untag a snapshot.
|
|
859
923
|
*/
|
|
860
924
|
async snapshotTag(snapshotId: string, tag: string | null): Promise<CliResult<void>> {
|
|
861
|
-
const args = [
|
|
925
|
+
const args = [
|
|
926
|
+
'cloud',
|
|
927
|
+
'sandbox',
|
|
928
|
+
'snapshot',
|
|
929
|
+
'tag',
|
|
930
|
+
snapshotId,
|
|
931
|
+
'--region',
|
|
932
|
+
this.getSandboxRegion(),
|
|
933
|
+
];
|
|
862
934
|
if (tag === null) {
|
|
863
935
|
args.push('--clear');
|
|
864
936
|
} else {
|
|
@@ -1174,8 +1246,14 @@ export interface SessionLog {
|
|
|
1174
1246
|
}
|
|
1175
1247
|
|
|
1176
1248
|
// Sandbox types
|
|
1177
|
-
export type SandboxStatus = 'creating' | 'idle' | 'running' | 'terminated' | 'failed';
|
|
1178
|
-
export type ExecutionStatus =
|
|
1249
|
+
export type SandboxStatus = 'creating' | 'idle' | 'running' | 'terminated' | 'failed' | 'deleted';
|
|
1250
|
+
export type ExecutionStatus =
|
|
1251
|
+
| 'queued'
|
|
1252
|
+
| 'running'
|
|
1253
|
+
| 'completed'
|
|
1254
|
+
| 'failed'
|
|
1255
|
+
| 'timeout'
|
|
1256
|
+
| 'cancelled';
|
|
1179
1257
|
|
|
1180
1258
|
export interface SandboxResources {
|
|
1181
1259
|
memory?: string;
|
|
@@ -176,7 +176,11 @@ export class SandboxManager {
|
|
|
176
176
|
const bytesTransferred = stats.size;
|
|
177
177
|
|
|
178
178
|
// Upload and extract
|
|
179
|
-
const uploadResult = await this.cliClient.sandboxUpload(
|
|
179
|
+
const uploadResult = await this.cliClient.sandboxUpload(
|
|
180
|
+
sandboxId,
|
|
181
|
+
archivePath,
|
|
182
|
+
remotePath
|
|
183
|
+
);
|
|
180
184
|
if (!uploadResult.success) {
|
|
181
185
|
throw new Error(`Failed to upload files: ${uploadResult.error}`);
|
|
182
186
|
}
|
|
@@ -207,7 +211,12 @@ export class SandboxManager {
|
|
|
207
211
|
remotePath: string,
|
|
208
212
|
localPath: string
|
|
209
213
|
): Promise<void> {
|
|
210
|
-
const result = await this.cliClient.sandboxCpFromSandbox(
|
|
214
|
+
const result = await this.cliClient.sandboxCpFromSandbox(
|
|
215
|
+
sandboxId,
|
|
216
|
+
remotePath,
|
|
217
|
+
localPath,
|
|
218
|
+
true
|
|
219
|
+
);
|
|
211
220
|
if (!result.success) {
|
|
212
221
|
throw new Error(`Failed to download files: ${result.error}`);
|
|
213
222
|
}
|
|
@@ -608,9 +608,7 @@ export class SyncToSandboxTool implements vscode.LanguageModelTool<SyncToSandbox
|
|
|
608
608
|
),
|
|
609
609
|
]);
|
|
610
610
|
} catch (err) {
|
|
611
|
-
throw new Error(
|
|
612
|
-
`Failed to sync: ${err instanceof Error ? err.message : 'Unknown error'}`
|
|
613
|
-
);
|
|
611
|
+
throw new Error(`Failed to sync: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
614
612
|
}
|
|
615
613
|
}
|
|
616
614
|
|
|
@@ -41,9 +41,7 @@ let saveListener: vscode.Disposable | undefined;
|
|
|
41
41
|
const uploadDebounceTimers: Map<string, NodeJS.Timeout> = new Map();
|
|
42
42
|
const UPLOAD_DEBOUNCE_MS = 1000; // 1 second debounce
|
|
43
43
|
|
|
44
|
-
export function registerSandboxExplorer(
|
|
45
|
-
context: vscode.ExtensionContext
|
|
46
|
-
): SandboxTreeDataProvider {
|
|
44
|
+
export function registerSandboxExplorer(context: vscode.ExtensionContext): SandboxTreeDataProvider {
|
|
47
45
|
// Initialize sandbox manager
|
|
48
46
|
initSandboxManager(context);
|
|
49
47
|
|
|
@@ -171,13 +169,10 @@ function registerCommands(
|
|
|
171
169
|
|
|
172
170
|
// Link sandbox
|
|
173
171
|
context.subscriptions.push(
|
|
174
|
-
vscode.commands.registerCommand(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
await linkSandbox(item.sandboxData.sandboxId, provider);
|
|
179
|
-
}
|
|
180
|
-
)
|
|
172
|
+
vscode.commands.registerCommand('agentuity.sandbox.link', async (item?: SandboxTreeItem) => {
|
|
173
|
+
if (!item?.sandboxData) return;
|
|
174
|
+
await linkSandbox(item.sandboxData.sandboxId, provider);
|
|
175
|
+
})
|
|
181
176
|
);
|
|
182
177
|
|
|
183
178
|
// Unlink sandbox
|
|
@@ -193,45 +188,42 @@ function registerCommands(
|
|
|
193
188
|
|
|
194
189
|
// Sync project to sandbox
|
|
195
190
|
context.subscriptions.push(
|
|
196
|
-
vscode.commands.registerCommand(
|
|
197
|
-
|
|
198
|
-
async (item?: SandboxTreeItem) => {
|
|
199
|
-
let sandboxId: string | undefined;
|
|
191
|
+
vscode.commands.registerCommand('agentuity.sandbox.sync', async (item?: SandboxTreeItem) => {
|
|
192
|
+
let sandboxId: string | undefined;
|
|
200
193
|
|
|
201
|
-
|
|
202
|
-
|
|
194
|
+
if (item?.sandboxData) {
|
|
195
|
+
sandboxId = item.sandboxData.sandboxId;
|
|
196
|
+
} else {
|
|
197
|
+
// Try to get from linked sandboxes
|
|
198
|
+
const linked = getSandboxManager().getLinkedSandboxes();
|
|
199
|
+
if (linked.length === 0) {
|
|
200
|
+
vscode.window.showWarningMessage(
|
|
201
|
+
'No sandbox linked to this workspace. Link a sandbox first.'
|
|
202
|
+
);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (linked.length === 1) {
|
|
206
|
+
sandboxId = linked[0].sandboxId;
|
|
203
207
|
} else {
|
|
204
|
-
//
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
// Pick one
|
|
216
|
-
const picked = await vscode.window.showQuickPick(
|
|
217
|
-
linked.map((l) => ({
|
|
218
|
-
label: l.name || l.sandboxId,
|
|
219
|
-
description: l.sandboxId,
|
|
220
|
-
sandboxId: l.sandboxId,
|
|
221
|
-
})),
|
|
222
|
-
{ placeHolder: 'Select sandbox to sync to' }
|
|
223
|
-
);
|
|
224
|
-
if (picked) {
|
|
225
|
-
sandboxId = picked.sandboxId;
|
|
226
|
-
}
|
|
208
|
+
// Pick one
|
|
209
|
+
const picked = await vscode.window.showQuickPick(
|
|
210
|
+
linked.map((l) => ({
|
|
211
|
+
label: l.name || l.sandboxId,
|
|
212
|
+
description: l.sandboxId,
|
|
213
|
+
sandboxId: l.sandboxId,
|
|
214
|
+
})),
|
|
215
|
+
{ placeHolder: 'Select sandbox to sync to' }
|
|
216
|
+
);
|
|
217
|
+
if (picked) {
|
|
218
|
+
sandboxId = picked.sandboxId;
|
|
227
219
|
}
|
|
228
220
|
}
|
|
221
|
+
}
|
|
229
222
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
223
|
+
if (sandboxId) {
|
|
224
|
+
await syncToSandbox(sandboxId, provider);
|
|
233
225
|
}
|
|
234
|
-
)
|
|
226
|
+
})
|
|
235
227
|
);
|
|
236
228
|
|
|
237
229
|
// Execute command in sandbox
|
|
@@ -272,7 +264,11 @@ function registerCommands(
|
|
|
272
264
|
'agentuity.sandbox.download',
|
|
273
265
|
async (item?: SandboxTreeItem) => {
|
|
274
266
|
if (!item?.parentSandboxId || !item?.filePath) return;
|
|
275
|
-
await downloadFromSandbox(
|
|
267
|
+
await downloadFromSandbox(
|
|
268
|
+
item.parentSandboxId,
|
|
269
|
+
item.filePath,
|
|
270
|
+
item.itemType === 'directory'
|
|
271
|
+
);
|
|
276
272
|
}
|
|
277
273
|
)
|
|
278
274
|
);
|
|
@@ -283,7 +279,12 @@ function registerCommands(
|
|
|
283
279
|
'agentuity.sandbox.deleteFile',
|
|
284
280
|
async (item?: SandboxTreeItem) => {
|
|
285
281
|
if (!item?.parentSandboxId || !item?.filePath) return;
|
|
286
|
-
await deleteFile(
|
|
282
|
+
await deleteFile(
|
|
283
|
+
item.parentSandboxId,
|
|
284
|
+
item.filePath,
|
|
285
|
+
item.itemType === 'directory',
|
|
286
|
+
provider
|
|
287
|
+
);
|
|
287
288
|
}
|
|
288
289
|
)
|
|
289
290
|
);
|
|
@@ -445,13 +446,10 @@ function registerCommands(
|
|
|
445
446
|
|
|
446
447
|
// Upload from explorer (context menu)
|
|
447
448
|
context.subscriptions.push(
|
|
448
|
-
vscode.commands.registerCommand(
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
await uploadToSandbox(uri);
|
|
453
|
-
}
|
|
454
|
-
)
|
|
449
|
+
vscode.commands.registerCommand('agentuity.sandbox.upload', async (uri?: vscode.Uri) => {
|
|
450
|
+
if (!uri) return;
|
|
451
|
+
await uploadToSandbox(uri);
|
|
452
|
+
})
|
|
455
453
|
);
|
|
456
454
|
}
|
|
457
455
|
|
|
@@ -677,10 +675,12 @@ async function syncToSandbox(sandboxId: string, provider: SandboxTreeDataProvide
|
|
|
677
675
|
}
|
|
678
676
|
|
|
679
677
|
async function execInSandbox(sandboxId: string, prefilledCommand?: string): Promise<void> {
|
|
680
|
-
const command =
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
678
|
+
const command =
|
|
679
|
+
prefilledCommand ??
|
|
680
|
+
(await vscode.window.showInputBox({
|
|
681
|
+
prompt: 'Enter command to execute',
|
|
682
|
+
placeHolder: 'npm test',
|
|
683
|
+
}));
|
|
684
684
|
|
|
685
685
|
if (!command) return;
|
|
686
686
|
|
|
@@ -702,7 +702,9 @@ function executeInTerminal(sandboxId: string, command: string): void {
|
|
|
702
702
|
}
|
|
703
703
|
|
|
704
704
|
terminal.show();
|
|
705
|
-
terminal.sendText(
|
|
705
|
+
terminal.sendText(
|
|
706
|
+
`${cliPath} cloud sandbox exec ${sandboxId} --region ${cli.getSandboxRegion()} -- ${command}`
|
|
707
|
+
);
|
|
706
708
|
}
|
|
707
709
|
|
|
708
710
|
function disposeTerminals(): void {
|
|
@@ -813,9 +815,7 @@ async function createSandboxFile(
|
|
|
813
815
|
const doc = await vscode.workspace.openTextDocument(localPath);
|
|
814
816
|
await vscode.window.showTextDocument(doc, { preview: false });
|
|
815
817
|
|
|
816
|
-
vscode.window.showInformationMessage(
|
|
817
|
-
`New file will be created at ${remotePath} when you save`
|
|
818
|
-
);
|
|
818
|
+
vscode.window.showInformationMessage(`New file will be created at ${remotePath} when you save`);
|
|
819
819
|
}
|
|
820
820
|
|
|
821
821
|
async function createSandboxFolder(
|
|
@@ -960,7 +960,9 @@ async function viewExecution(executionId: string): Promise<void> {
|
|
|
960
960
|
const stdoutContent = await fetchStreamContent(exec.stdoutStreamUrl);
|
|
961
961
|
lines.push(stdoutContent || '(empty)');
|
|
962
962
|
} catch (err) {
|
|
963
|
-
lines.push(
|
|
963
|
+
lines.push(
|
|
964
|
+
`(failed to fetch: ${err instanceof Error ? err.message : 'unknown error'})`
|
|
965
|
+
);
|
|
964
966
|
}
|
|
965
967
|
}
|
|
966
968
|
|
|
@@ -971,11 +973,17 @@ async function viewExecution(executionId: string): Promise<void> {
|
|
|
971
973
|
const stderrContent = await fetchStreamContent(exec.stderrStreamUrl);
|
|
972
974
|
lines.push(stderrContent || '(empty)');
|
|
973
975
|
} catch (err) {
|
|
974
|
-
lines.push(
|
|
976
|
+
lines.push(
|
|
977
|
+
`(failed to fetch: ${err instanceof Error ? err.message : 'unknown error'})`
|
|
978
|
+
);
|
|
975
979
|
}
|
|
976
980
|
}
|
|
977
981
|
|
|
978
|
-
await openReadonlyDocument(
|
|
982
|
+
await openReadonlyDocument(
|
|
983
|
+
lines.join('\n'),
|
|
984
|
+
'log',
|
|
985
|
+
`execution-${executionId.slice(0, 8)}`
|
|
986
|
+
);
|
|
979
987
|
} else {
|
|
980
988
|
vscode.window.showErrorMessage(`Failed to get execution: ${result.error}`);
|
|
981
989
|
}
|
|
@@ -1108,10 +1116,7 @@ async function syncEnvFile(sandboxId: string): Promise<void> {
|
|
|
1108
1116
|
}
|
|
1109
1117
|
}
|
|
1110
1118
|
|
|
1111
|
-
async function createSnapshot(
|
|
1112
|
-
sandboxId: string,
|
|
1113
|
-
provider: SandboxTreeDataProvider
|
|
1114
|
-
): Promise<void> {
|
|
1119
|
+
async function createSnapshot(sandboxId: string, provider: SandboxTreeDataProvider): Promise<void> {
|
|
1115
1120
|
const tag = await vscode.window.showInputBox({
|
|
1116
1121
|
prompt: 'Enter a tag for this snapshot (optional)',
|
|
1117
1122
|
placeHolder: 'v1.0 or latest',
|
|
@@ -1218,7 +1223,11 @@ async function viewSnapshotFile(snapshot: SnapshotInfo, filePath: string): Promi
|
|
|
1218
1223
|
async () => {
|
|
1219
1224
|
try {
|
|
1220
1225
|
// Create temp directory for snapshot files
|
|
1221
|
-
const snapshotTmpDir = path.join(
|
|
1226
|
+
const snapshotTmpDir = path.join(
|
|
1227
|
+
os.tmpdir(),
|
|
1228
|
+
'agentuity-snapshots',
|
|
1229
|
+
snapshot.snapshotId.slice(0, 12)
|
|
1230
|
+
);
|
|
1222
1231
|
fs.mkdirSync(snapshotTmpDir, { recursive: true });
|
|
1223
1232
|
|
|
1224
1233
|
const archivePath = path.join(snapshotTmpDir, 'snapshot.tar.gz');
|
|
@@ -1301,14 +1310,22 @@ async function downloadFile(url: string, destPath: string): Promise<void> {
|
|
|
1301
1310
|
|
|
1302
1311
|
request.on('error', (err) => {
|
|
1303
1312
|
file.close();
|
|
1304
|
-
try {
|
|
1313
|
+
try {
|
|
1314
|
+
fs.unlinkSync(destPath);
|
|
1315
|
+
} catch {
|
|
1316
|
+
/* ignore cleanup errors */
|
|
1317
|
+
}
|
|
1305
1318
|
reject(err);
|
|
1306
1319
|
});
|
|
1307
1320
|
|
|
1308
1321
|
request.setTimeout(60000, () => {
|
|
1309
1322
|
request.destroy();
|
|
1310
1323
|
file.close();
|
|
1311
|
-
try {
|
|
1324
|
+
try {
|
|
1325
|
+
fs.unlinkSync(destPath);
|
|
1326
|
+
} catch {
|
|
1327
|
+
/* ignore cleanup errors */
|
|
1328
|
+
}
|
|
1312
1329
|
reject(new Error('Download timeout'));
|
|
1313
1330
|
});
|
|
1314
1331
|
});
|
|
@@ -1356,12 +1373,7 @@ async function uploadToSandbox(uri: vscode.Uri): Promise<void> {
|
|
|
1356
1373
|
const stats = await vscode.workspace.fs.stat(uri);
|
|
1357
1374
|
const isDir = stats.type === vscode.FileType.Directory;
|
|
1358
1375
|
|
|
1359
|
-
const result = await cli.sandboxCpToSandbox(
|
|
1360
|
-
sandboxId,
|
|
1361
|
-
uri.fsPath,
|
|
1362
|
-
remotePath,
|
|
1363
|
-
isDir
|
|
1364
|
-
);
|
|
1376
|
+
const result = await cli.sandboxCpToSandbox(sandboxId, uri.fsPath, remotePath, isDir);
|
|
1365
1377
|
|
|
1366
1378
|
if (result.success) {
|
|
1367
1379
|
vscode.window.showInformationMessage(`Uploaded to ${remotePath}`);
|
|
@@ -83,10 +83,7 @@ export class SandboxTreeItem extends vscode.TreeItem {
|
|
|
83
83
|
const isLinked = this.linkedData !== undefined;
|
|
84
84
|
|
|
85
85
|
// Set icon based on status
|
|
86
|
-
this.iconPath = new vscode.ThemeIcon(
|
|
87
|
-
this.getStatusIcon(status),
|
|
88
|
-
this.getStatusColor(status)
|
|
89
|
-
);
|
|
86
|
+
this.iconPath = new vscode.ThemeIcon(this.getStatusIcon(status), this.getStatusColor(status));
|
|
90
87
|
|
|
91
88
|
// Set context value for menu targeting
|
|
92
89
|
let contextValue = `sandbox.${status}`;
|
|
@@ -282,7 +279,9 @@ export class SandboxTreeItem extends vscode.TreeItem {
|
|
|
282
279
|
this.tooltip = [
|
|
283
280
|
`ID: ${this.executionData.executionId}`,
|
|
284
281
|
`Status: ${status}`,
|
|
285
|
-
this.executionData.exitCode !== undefined
|
|
282
|
+
this.executionData.exitCode !== undefined
|
|
283
|
+
? `Exit Code: ${this.executionData.exitCode}`
|
|
284
|
+
: '',
|
|
286
285
|
this.executionData.durationMs !== undefined
|
|
287
286
|
? `Duration: ${(this.executionData.durationMs / 1000).toFixed(2)}s`
|
|
288
287
|
: '',
|
|
@@ -347,7 +346,9 @@ export class SandboxTreeItem extends vscode.TreeItem {
|
|
|
347
346
|
* Tree data provider for the sandbox explorer.
|
|
348
347
|
*/
|
|
349
348
|
export class SandboxTreeDataProvider implements vscode.TreeDataProvider<SandboxTreeItem> {
|
|
350
|
-
private _onDidChangeTreeData = new vscode.EventEmitter<
|
|
349
|
+
private _onDidChangeTreeData = new vscode.EventEmitter<
|
|
350
|
+
SandboxTreeItem | undefined | null | void
|
|
351
|
+
>();
|
|
351
352
|
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
|
352
353
|
|
|
353
354
|
private sandboxes: SandboxInfo[] = [];
|
|
@@ -410,13 +411,21 @@ export class SandboxTreeDataProvider implements vscode.TreeDataProvider<SandboxT
|
|
|
410
411
|
|
|
411
412
|
if (authStatus.state === 'unknown') {
|
|
412
413
|
return [
|
|
413
|
-
new SandboxTreeItem(
|
|
414
|
+
new SandboxTreeItem(
|
|
415
|
+
'Checking auth...',
|
|
416
|
+
vscode.TreeItemCollapsibleState.None,
|
|
417
|
+
'message'
|
|
418
|
+
),
|
|
414
419
|
];
|
|
415
420
|
}
|
|
416
421
|
|
|
417
422
|
if (authStatus.state === 'cli-missing') {
|
|
418
423
|
return [
|
|
419
|
-
new SandboxTreeItem(
|
|
424
|
+
new SandboxTreeItem(
|
|
425
|
+
'CLI not installed',
|
|
426
|
+
vscode.TreeItemCollapsibleState.None,
|
|
427
|
+
'message'
|
|
428
|
+
),
|
|
420
429
|
];
|
|
421
430
|
}
|
|
422
431
|
|
|
@@ -427,7 +436,9 @@ export class SandboxTreeDataProvider implements vscode.TreeDataProvider<SandboxT
|
|
|
427
436
|
}
|
|
428
437
|
|
|
429
438
|
if (this.loading) {
|
|
430
|
-
return [
|
|
439
|
+
return [
|
|
440
|
+
new SandboxTreeItem('Loading...', vscode.TreeItemCollapsibleState.None, 'message'),
|
|
441
|
+
];
|
|
431
442
|
}
|
|
432
443
|
|
|
433
444
|
if (this.error) {
|
|
@@ -500,10 +511,7 @@ export class SandboxTreeDataProvider implements vscode.TreeDataProvider<SandboxT
|
|
|
500
511
|
return items;
|
|
501
512
|
}
|
|
502
513
|
|
|
503
|
-
private getSandboxCategories(
|
|
504
|
-
sandbox: SandboxInfo,
|
|
505
|
-
linked?: LinkedSandbox
|
|
506
|
-
): SandboxTreeItem[] {
|
|
514
|
+
private getSandboxCategories(sandbox: SandboxInfo, linked?: LinkedSandbox): SandboxTreeItem[] {
|
|
507
515
|
return [
|
|
508
516
|
new SandboxTreeItem(
|
|
509
517
|
'Files',
|
|
@@ -589,9 +597,7 @@ export class SandboxTreeDataProvider implements vscode.TreeDataProvider<SandboxT
|
|
|
589
597
|
});
|
|
590
598
|
|
|
591
599
|
if (directChildren.length === 0) {
|
|
592
|
-
return [
|
|
593
|
-
new SandboxTreeItem('(empty)', vscode.TreeItemCollapsibleState.None, 'message'),
|
|
594
|
-
];
|
|
600
|
+
return [new SandboxTreeItem('(empty)', vscode.TreeItemCollapsibleState.None, 'message')];
|
|
595
601
|
}
|
|
596
602
|
|
|
597
603
|
// Sort: directories first, then files, alphabetically
|
|
@@ -696,7 +702,14 @@ export class SandboxTreeDataProvider implements vscode.TreeDataProvider<SandboxT
|
|
|
696
702
|
vscode.TreeItemCollapsibleState.None,
|
|
697
703
|
'snapshotFile',
|
|
698
704
|
undefined,
|
|
699
|
-
{
|
|
705
|
+
{
|
|
706
|
+
path: file.path,
|
|
707
|
+
name: fileName,
|
|
708
|
+
size: file.size,
|
|
709
|
+
isDir: false,
|
|
710
|
+
mode: '',
|
|
711
|
+
modTime: '',
|
|
712
|
+
},
|
|
700
713
|
snapshotData, // Pass snapshot data so we have access to downloadUrl
|
|
701
714
|
undefined,
|
|
702
715
|
undefined,
|