agentuity-vscode 0.1.6 → 0.1.7

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.
@@ -1,8 +1,9 @@
1
1
  import * as vscode from 'vscode';
2
- import { getCliClient } from '../../core/cliClient';
2
+ import { getCliClient, type SandboxCreateOptions } from '../../core/cliClient';
3
3
  import { getAuthStatus } from '../../core/auth';
4
4
  import { hasProject, getCurrentProject } from '../../core/project';
5
5
  import { getDevServerManager } from '../devServer';
6
+ import { getSandboxManager, formatBytes } from '../../core/sandboxManager';
6
7
 
7
8
  export interface GetAgentsInput {
8
9
  includeDetails?: boolean;
@@ -486,6 +487,237 @@ export class GetHealthSummaryTool implements vscode.LanguageModelTool<GetHealthS
486
487
  }
487
488
  }
488
489
 
490
+ // ==================== Sandbox Tools ====================
491
+
492
+ export interface ListSandboxesInput {
493
+ status?: 'creating' | 'idle' | 'running' | 'terminated' | 'failed';
494
+ }
495
+
496
+ export class ListSandboxesTool implements vscode.LanguageModelTool<ListSandboxesInput> {
497
+ async invoke(
498
+ options: vscode.LanguageModelToolInvocationOptions<ListSandboxesInput>,
499
+ _token: vscode.CancellationToken
500
+ ): Promise<vscode.LanguageModelToolResult> {
501
+ const cli = getCliClient();
502
+ const result = await cli.sandboxList({ status: options.input.status });
503
+
504
+ if (!result.success || !result.data) {
505
+ throw new Error(`Failed to list sandboxes: ${result.error || 'Unknown error'}`);
506
+ }
507
+
508
+ const sandboxes = result.data.map((s) => ({
509
+ id: s.sandboxId,
510
+ status: s.status,
511
+ region: s.region,
512
+ createdAt: s.createdAt,
513
+ resources: s.resources,
514
+ executions: s.executions,
515
+ }));
516
+
517
+ return new vscode.LanguageModelToolResult([
518
+ new vscode.LanguageModelTextPart(JSON.stringify(sandboxes, null, 2)),
519
+ ]);
520
+ }
521
+
522
+ async prepareInvocation(
523
+ _options: vscode.LanguageModelToolInvocationPrepareOptions<ListSandboxesInput>,
524
+ _token: vscode.CancellationToken
525
+ ): Promise<vscode.PreparedToolInvocation> {
526
+ return {
527
+ invocationMessage: 'Listing sandboxes...',
528
+ };
529
+ }
530
+ }
531
+
532
+ export interface CreateSandboxInput {
533
+ memory?: string;
534
+ cpu?: string;
535
+ network?: boolean;
536
+ snapshot?: string;
537
+ dependencies?: string[];
538
+ }
539
+
540
+ export class CreateSandboxTool implements vscode.LanguageModelTool<CreateSandboxInput> {
541
+ async invoke(
542
+ options: vscode.LanguageModelToolInvocationOptions<CreateSandboxInput>,
543
+ _token: vscode.CancellationToken
544
+ ): Promise<vscode.LanguageModelToolResult> {
545
+ const cli = getCliClient();
546
+ const createOptions: SandboxCreateOptions = {
547
+ memory: options.input.memory,
548
+ cpu: options.input.cpu,
549
+ network: options.input.network,
550
+ snapshot: options.input.snapshot,
551
+ dependencies: options.input.dependencies,
552
+ };
553
+
554
+ const result = await cli.sandboxCreate(createOptions);
555
+
556
+ if (!result.success || !result.data) {
557
+ throw new Error(`Failed to create sandbox: ${result.error || 'Unknown error'}`);
558
+ }
559
+
560
+ return new vscode.LanguageModelToolResult([
561
+ new vscode.LanguageModelTextPart(
562
+ `Sandbox created successfully!\n\nID: ${result.data.sandboxId}\nStatus: ${result.data.status}\nRegion: ${result.data.region}`
563
+ ),
564
+ ]);
565
+ }
566
+
567
+ async prepareInvocation(
568
+ _options: vscode.LanguageModelToolInvocationPrepareOptions<CreateSandboxInput>,
569
+ _token: vscode.CancellationToken
570
+ ): Promise<vscode.PreparedToolInvocation> {
571
+ return {
572
+ invocationMessage: 'Creating sandbox...',
573
+ confirmationMessages: {
574
+ title: 'Create Sandbox',
575
+ message: new vscode.MarkdownString(
576
+ 'This will create a new sandbox environment in the cloud.\n\nDo you want to continue?'
577
+ ),
578
+ },
579
+ };
580
+ }
581
+ }
582
+
583
+ export interface SyncToSandboxInput {
584
+ sandboxId: string;
585
+ }
586
+
587
+ export class SyncToSandboxTool implements vscode.LanguageModelTool<SyncToSandboxInput> {
588
+ async invoke(
589
+ options: vscode.LanguageModelToolInvocationOptions<SyncToSandboxInput>,
590
+ _token: vscode.CancellationToken
591
+ ): Promise<vscode.LanguageModelToolResult> {
592
+ const { sandboxId } = options.input;
593
+ if (!sandboxId) {
594
+ throw new Error('Sandbox ID is required.');
595
+ }
596
+
597
+ if (!vscode.workspace.workspaceFolders?.length) {
598
+ throw new Error('No workspace folder open to sync.');
599
+ }
600
+
601
+ try {
602
+ const manager = getSandboxManager();
603
+ const result = await manager.syncToSandbox(sandboxId);
604
+
605
+ return new vscode.LanguageModelToolResult([
606
+ new vscode.LanguageModelTextPart(
607
+ `Synced ${result.filesUploaded} files (${formatBytes(result.bytesTransferred)}) in ${(result.duration / 1000).toFixed(1)}s`
608
+ ),
609
+ ]);
610
+ } catch (err) {
611
+ throw new Error(
612
+ `Failed to sync: ${err instanceof Error ? err.message : 'Unknown error'}`
613
+ );
614
+ }
615
+ }
616
+
617
+ async prepareInvocation(
618
+ options: vscode.LanguageModelToolInvocationPrepareOptions<SyncToSandboxInput>,
619
+ _token: vscode.CancellationToken
620
+ ): Promise<vscode.PreparedToolInvocation> {
621
+ return {
622
+ invocationMessage: `Syncing workspace to sandbox ${options.input.sandboxId?.substring(0, 8)}...`,
623
+ confirmationMessages: {
624
+ title: 'Sync to Sandbox',
625
+ message: new vscode.MarkdownString(
626
+ 'This will upload your workspace files to the sandbox.\n\nDo you want to continue?'
627
+ ),
628
+ },
629
+ };
630
+ }
631
+ }
632
+
633
+ export interface ExecuteInSandboxInput {
634
+ sandboxId: string;
635
+ command: string;
636
+ }
637
+
638
+ export class ExecuteInSandboxTool implements vscode.LanguageModelTool<ExecuteInSandboxInput> {
639
+ async invoke(
640
+ options: vscode.LanguageModelToolInvocationOptions<ExecuteInSandboxInput>,
641
+ _token: vscode.CancellationToken
642
+ ): Promise<vscode.LanguageModelToolResult> {
643
+ const { sandboxId, command } = options.input;
644
+ if (!sandboxId || !command) {
645
+ throw new Error('Sandbox ID and command are required.');
646
+ }
647
+
648
+ const cli = getCliClient();
649
+ const cliPath = cli.getCliPath();
650
+
651
+ // Execute in terminal for streaming output
652
+ const terminal = vscode.window.createTerminal({
653
+ name: `Sandbox: ${sandboxId.slice(0, 8)}`,
654
+ iconPath: new vscode.ThemeIcon('vm'),
655
+ });
656
+ terminal.show();
657
+ terminal.sendText(`${cliPath} cloud sandbox exec ${sandboxId} -- ${command}`);
658
+
659
+ return new vscode.LanguageModelToolResult([
660
+ new vscode.LanguageModelTextPart(
661
+ `Executing "${command}" in sandbox ${sandboxId}. Check the terminal for output.`
662
+ ),
663
+ ]);
664
+ }
665
+
666
+ async prepareInvocation(
667
+ options: vscode.LanguageModelToolInvocationPrepareOptions<ExecuteInSandboxInput>,
668
+ _token: vscode.CancellationToken
669
+ ): Promise<vscode.PreparedToolInvocation> {
670
+ return {
671
+ invocationMessage: `Executing command in sandbox ${options.input.sandboxId?.substring(0, 8)}...`,
672
+ confirmationMessages: {
673
+ title: 'Execute in Sandbox',
674
+ message: new vscode.MarkdownString(
675
+ `This will execute the following command in the sandbox:\n\n\`\`\`\n${options.input.command}\n\`\`\`\n\nDo you want to continue?`
676
+ ),
677
+ },
678
+ };
679
+ }
680
+ }
681
+
682
+ export interface CreateSnapshotInput {
683
+ sandboxId: string;
684
+ tag?: string;
685
+ }
686
+
687
+ export class CreateSnapshotTool implements vscode.LanguageModelTool<CreateSnapshotInput> {
688
+ async invoke(
689
+ options: vscode.LanguageModelToolInvocationOptions<CreateSnapshotInput>,
690
+ _token: vscode.CancellationToken
691
+ ): Promise<vscode.LanguageModelToolResult> {
692
+ const { sandboxId, tag } = options.input;
693
+ if (!sandboxId) {
694
+ throw new Error('Sandbox ID is required.');
695
+ }
696
+
697
+ const cli = getCliClient();
698
+ const result = await cli.snapshotCreate(sandboxId, tag);
699
+
700
+ if (!result.success || !result.data) {
701
+ throw new Error(`Failed to create snapshot: ${result.error || 'Unknown error'}`);
702
+ }
703
+
704
+ return new vscode.LanguageModelToolResult([
705
+ new vscode.LanguageModelTextPart(
706
+ `Snapshot created!\n\nID: ${result.data.snapshotId}\nSize: ${formatBytes(result.data.sizeBytes)}\nFiles: ${result.data.fileCount}${tag ? `\nTag: ${tag}` : ''}`
707
+ ),
708
+ ]);
709
+ }
710
+
711
+ async prepareInvocation(
712
+ options: vscode.LanguageModelToolInvocationPrepareOptions<CreateSnapshotInput>,
713
+ _token: vscode.CancellationToken
714
+ ): Promise<vscode.PreparedToolInvocation> {
715
+ return {
716
+ invocationMessage: `Creating snapshot of sandbox ${options.input.sandboxId?.substring(0, 8)}...`,
717
+ };
718
+ }
719
+ }
720
+
489
721
  export function registerAgentTools(context: vscode.ExtensionContext): void {
490
722
  if (!vscode.lm?.registerTool) {
491
723
  return;
@@ -523,6 +755,27 @@ export function registerAgentTools(context: vscode.ExtensionContext): void {
523
755
  context.subscriptions.push(
524
756
  vscode.lm.registerTool('agentuity_get_health_summary', new GetHealthSummaryTool())
525
757
  );
758
+
759
+ // Sandbox tools
760
+ context.subscriptions.push(
761
+ vscode.lm.registerTool('agentuity_list_sandboxes', new ListSandboxesTool())
762
+ );
763
+
764
+ context.subscriptions.push(
765
+ vscode.lm.registerTool('agentuity_create_sandbox', new CreateSandboxTool())
766
+ );
767
+
768
+ context.subscriptions.push(
769
+ vscode.lm.registerTool('agentuity_sync_to_sandbox', new SyncToSandboxTool())
770
+ );
771
+
772
+ context.subscriptions.push(
773
+ vscode.lm.registerTool('agentuity_execute_in_sandbox', new ExecuteInSandboxTool())
774
+ );
775
+
776
+ context.subscriptions.push(
777
+ vscode.lm.registerTool('agentuity_create_snapshot', new CreateSnapshotTool())
778
+ );
526
779
  } catch {
527
780
  // LM API not available
528
781
  }