Repository: oceanprotocol/vscode-extension
Pull request #84: Select compute environment
Author: login: giurgiur99
Created: 2025-05-02T07:50:49Z | Merged: 2025-05-07T17:03:04Z

Fixes #76 

Changes proposed in this PR:

- Use dropdown to select compute environment to be used.
- Auto-fetch envs and validate response


Linked issue #76: List all the available environments with corresponding resources. Filter envs by c2d options.
List all the available environments with corresponding resources, avoiding enforcement on user side.
Allow user to filter envs by providing its resources needs.



Diff:
diff --git a/package.json b/package.json
index 9fd9708..36becca 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
   "publisher": "OceanProtocol",
   "displayName": "Ocean Nodes VS Code Extension",
   "description": "Easily publish assets and test your algorithms with the official Ocean Protocol vscode extension.",
-  "version": "0.0.5",
+  "version": "0.0.6",
   "engines": {
     "vscode": "^1.96.0"
   },
diff --git a/src/extension.ts b/src/extension.ts
index e32ed75..9bf7aa5 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -7,6 +7,7 @@ import {
   checkComputeStatus,
   computeStart,
   delay,
+  getComputeEnvironments,
   getComputeLogs,
   getComputeResult,
   saveOutput,
@@ -57,6 +58,16 @@ export async function activate(context: vscode.ExtensionContext) {
     })
     context.subscriptions.push(testCommand)
 
+    // Add handler for environment loading
+    context.subscriptions.push(
+      vscode.commands.registerCommand(
+        'ocean-protocol.getEnvironments',
+        async (nodeUrl: string) => {
+          return await getComputeEnvironments(nodeUrl)
+        }
+      )
+    )
+
     // Rest of your existing startComputeJob command registration...
     let startComputeJob = vscode.commands.registerCommand(
       'ocean-protocol.startComputeJob',
@@ -67,7 +78,8 @@ export async function activate(context: vscode.ExtensionContext) {
         nodeUrl: string,
         datasetPath?: string,
         dockerImage?: string,
-        dockerTag?: string
+        dockerTag?: string,
+        environmentId?: string
       ) => {
         console.log('1. Starting compute job...')
         console.log('Dataset path:', datasetPath)
@@ -77,6 +89,7 @@ export async function activate(context: vscode.ExtensionContext) {
         console.log('Private key:', privateKey)
         console.log('Docker image:', dockerImage)
         console.log('Docker tag:', dockerTag)
+        console.log('Environment ID:', environmentId)
         const missingParams = []
         !algorithmPath && missingParams.push('algorithm path')
         !nodeUrl && missingParams.push('node URL')
@@ -128,6 +141,7 @@ export async function activate(context: vscode.ExtensionContext) {
               signer,
               nodeUrl,
               fileExtension,
+              environmentId,
               dataset,
               dockerImage,
               dockerTag
diff --git a/src/helpers/compute.ts b/src/helpers/compute.ts
index 30b032c..4fafb77 100644
--- a/src/helpers/compute.ts
+++ b/src/helpers/compute.ts
@@ -42,18 +42,16 @@ export async function computeStart(
   signer: Signer,
   nodeUrl: string,
   fileExtension: string,
+  environmentId?: string,
   dataset?: any,
   dockerImage?: string,
   dockerTag?: string
 ): Promise<ComputeJob> {
   try {
-    const environments = await ProviderInstance.getComputeEnvironments(nodeUrl)
-    if (!environments || environments.length === 0) {
-      throw new Error('No compute environments available')
+    if (!environmentId) {
+      throw new Error('No environment ID provided')
     }
 
-    const environmentId = environments[0].id
-
     const containerConfig = getContainerConfig(fileExtension, dockerImage, dockerTag)
 
     const datasets = dataset ? [dataset] : []
@@ -255,3 +253,12 @@ export async function saveOutput(
     throw new Error(`Failed to save tar output: ${error.message}`)
   }
 }
+
+export async function getComputeEnvironments(nodeUrl: string) {
+  const environments = await ProviderInstance.getComputeEnvironments(nodeUrl)
+  if (!environments || environments.length === 0) {
+    throw new Error('No compute environments available')
+  }
+
+  return environments
+}
diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts
index 6dcfc02..3d010ca 100644
--- a/src/test/extension.test.ts
+++ b/src/test/extension.test.ts
@@ -61,7 +61,13 @@ suite('Ocean Protocol Extension Test Suite', () => {
     sandbox.stub(ProviderInstance, 'getComputeEnvironments').resolves(mockEnvResponse)
     sandbox.stub(ProviderInstance, 'freeComputeStart').resolves(mockComputeResponse)
 
-    const result = await computeStart(mockAlgorithm, mockSigner, mockNodeUrl, 'js')
+    const result = await computeStart(
+      mockAlgorithm,
+      mockSigner,
+      mockNodeUrl,
+      'js',
+      mockEnvResponse[0].id
+    )
 
     assert.strictEqual(result.jobId, 'test-job-id')
     assert.strictEqual(result.statusText, 'Created')
@@ -77,7 +83,13 @@ suite('Ocean Protocol Extension Test Suite', () => {
       .stub(ProviderInstance, 'freeComputeStart')
       .resolves(mockComputeResponse)
 
-    const result = await computeStart(mockAlgorithm, mockSigner, mockNodeUrl, 'py')
+    const result = await computeStart(
+      mockAlgorithm,
+      mockSigner,
+      mockNodeUrl,
+      'py',
+      mockEnvResponse[0].id
+    )
 
     assert.strictEqual(result.jobId, 'test-job-id')
     assert.ok(
@@ -118,8 +130,8 @@ suite('Ocean Protocol Extension Test Suite', () => {
     sandbox.stub(ProviderInstance, 'getComputeEnvironments').resolves([])
 
     await assert.rejects(
-      computeStart(mockAlgorithm, mockSigner, mockNodeUrl, 'js'),
-      /No compute environments available/
+      computeStart(mockAlgorithm, mockSigner, mockNodeUrl, 'js', undefined),
+      /No environment ID provided/
     )
   })
 
diff --git a/src/viewProvider.ts b/src/viewProvider.ts
index d3c2671..b0f83d0 100644
--- a/src/viewProvider.ts
+++ b/src/viewProvider.ts
@@ -73,6 +73,25 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
 
         try {
           switch (data.type) {
+            case 'getEnvironments':
+              try {
+                const environments = await vscode.commands.executeCommand(
+                  'ocean-protocol.getEnvironments',
+                  data.nodeUrl
+                )
+                webviewView.webview.postMessage({
+                  type: 'environmentsLoaded',
+                  environments: environments
+                })
+              } catch (error) {
+                console.error('Error loading environments:', error)
+                webviewView.webview.postMessage({
+                  type: 'environmentsLoaded',
+                  environments: [],
+                  error: 'Failed to load compute environments'
+                })
+              }
+              break
             case 'openFilePicker':
               const options: vscode.OpenDialogOptions = {
                 canSelectMany: false,
@@ -132,9 +151,13 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
                 data.nodeUrl,
                 data.datasetPath,
                 data.dockerImage,
-                data.dockerTag
+                data.dockerTag,
+                data.environmentId
               )
               break
+            case 'copyToClipboard':
+              vscode.env.clipboard.writeText(data.text)
+              break
           }
         } catch (error) {
           console.error('Error handling message:', error)
@@ -254,6 +277,36 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
           #startComputeBtn {
             margin: 15px 0;
           }
+          .environment-section {
+            margin: 15px 0;
+          }
+          .environment-select {
+            width: 100%;
+            padding: 8px;
+            margin: 5px 0;
+            background-color: var(--vscode-dropdown-background);
+            color: var(--vscode-dropdown-foreground);
+            border: 1px solid var(--vscode-dropdown-border);
+          }
+          .environment-details {
+            margin-top: 10px;
+            padding: 10px;
+            background-color: var(--vscode-editor-background);
+            border: 1px solid var(--vscode-input-border);
+            border-radius: 4px;
+            font-size: 0.9em;
+            display: none;
+          }
+          .environment-details.active {
+            display: block;
+          }
+          .environment-details p {
+            margin: 5px 0;
+          }
+          .environment-details .label {
+            font-weight: bold;
+            color: var(--vscode-descriptionForeground);
+          }
         </style>
     </head>
     <body>
@@ -273,6 +326,14 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
                       <label for="nodeUrlInput">Node URL (including port)</label>
                       <input id="nodeUrlInput" placeholder="Enter compute environment ID" value="${this.randomNodeUrl}" />
 
+                      <div class="environment-section">
+                        <label for="environmentSelect">Compute Environment</label>
+                        <select id="environmentSelect" class="environment-select">
+                          <option value="">Loading environments...</option>
+                        </select>
+                        <div id="environmentDetails" class="environment-details"></div>
+                      </div>
+
                       <label>Dataset</label>
                       <button id="selectDatasetBtn">Select Dataset File</button>
                       <div id="selectedDatasetPath" class="selectedFile"></div>
@@ -303,6 +364,12 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
               let selectedAlgorithmPath = '';
               let selectedResultsFolderPath = '';
               let isUsingDefaultAlgorithm = false;
+              let selectedEnvironment = null;
+              let availableEnvironments = [];
+
+              const environmentDetails = document.getElementById('environmentDetails');
+              const nodeUrlInput = document.getElementById('nodeUrlInput');
+              const select = document.getElementById('environmentSelect');
 
               function toggleSection(sectionId) {
                   const header = document.getElementById(sectionId + 'Header');
@@ -360,17 +427,42 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
 
                       vscode.postMessage({ 
                           type: 'startComputeJob',
-                              privateKey: privateKey,
-                              algorithmPath: selectedAlgorithmPath,
-                              resultsFolderPath: selectedResultsFolderPath,
-                              nodeUrl: nodeUrl,
-                              datasetPath: selectedDatasetPath || undefined,
-                              dockerImage: dockerImage || undefined,
-                              dockerTag: dockerTag || undefined
+                          privateKey: privateKey,
+                          algorithmPath: selectedAlgorithmPath,
+                          resultsFolderPath: selectedResultsFolderPath,
+                          nodeUrl: nodeUrl,
+                          datasetPath: selectedDatasetPath || undefined,
+                          dockerImage: dockerImage || undefined,
+                          dockerTag: dockerTag || undefined,
+                          environmentId: document.getElementById('environmentSelect').value || undefined
                       });
                   });
               }
 
+              async function loadEnvironments() {
+                const nodeUrl = nodeUrlInput.value;
+                if (!nodeUrl) return;
+
+                select.innerHTML = '<option value="">Loading environments...</option>';
+                select.disabled = true;
+                environmentDetails.style.display = 'none';
+
+                try {
+                  vscode.postMessage({
+                    type: 'getEnvironments',
+                    nodeUrl: nodeUrl
+                  });
+                } catch (error) {
+                  console.error('Error loading environments:', error);
+                  select.innerHTML = '<option value="">Error loading environments</option>';
+                  select.disabled = true;
+                  environmentDetails.style.display = 'none';
+                }
+              }
+
+              nodeUrlInput.addEventListener('input', loadEnvironments);
+              loadEnvironments();
+
               window.addEventListener('message', event => {
                   const message = event.data;
                   console.log('Received message:', message);
@@ -399,6 +491,128 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
                           selectedResultsFolderPath = message.path;
                           document.getElementById('selectedResultsFolderPath').textContent = message.path;
                           break;
+                      case 'environmentsLoaded':
+                          console.log('Environments loaded:', message.environments);
+                          availableEnvironments = message.environments;
+                          const select = document.getElementById('environmentSelect');
+                          
+                          if (message.error) {
+                            select.innerHTML = '<option value="">' + message.error + '</option>';
+                            select.disabled = true;
+                            document.getElementById('environmentDetails').style.display = 'none';
+                            return;
+                          }
+                          
+                          if (!message.environments || message.environments.length === 0) {
+                            select.innerHTML = '<option value="">No environments available</option>';
+                            select.disabled = true;
+                            document.getElementById('environmentDetails').style.display = 'none';
+                            return;
+                          }
+
+                          select.innerHTML = '';
+                          message.environments.forEach(env => {
+                              const option = document.createElement('option');
+                              option.value = env.id;
+                              const truncatedId = env.id.length > 13 
+                                  ? env.id.substring(0, 6) + '...' + env.id.substring(env.id.length - 4)
+                                  : env.id;
+                              option.textContent = env.platform.os + ' (' + truncatedId + ')';
+                              select.appendChild(option);
+                          });
+                          select.disabled = false;
+                          document.getElementById('environmentDetails').style.display = 'none';
+
+                          function showEnvDetails(envId) {
+                              const detailsDiv = document.getElementById('environmentDetails');
+                              const selectedEnv = availableEnvironments.find(e => e.id === envId);
+                              if (!selectedEnv) {
+                                  detailsDiv.style.display = 'none';
+                                  return;
+                              }
+
+                              // Format environment ID to show first and last few characters
+                              const truncatedId = selectedEnv.id.length > 13 
+                                  ? selectedEnv.id.substring(0, 6) + '...' + selectedEnv.id.substring(selectedEnv.id.length - 4)
+                                  : selectedEnv.id;
+
+                              // Process resources to show min/max values for paid resources
+                              const paidResourceDetails = selectedEnv.resources.map(r => {
+                                  let value = '';
+                                  if (r.id === 'ram' || r.id === 'disk') {
+                                      const minGb = Math.round(r.min / (1024 * 1024 * 1024));
+                                      const maxGb = Math.round(r.max / (1024 * 1024 * 1024));
+                                      value = minGb + '/' + maxGb + ' GB';
+                                  } else {
+                                      value = r.min + '/' + r.max;
+                                  }
+                                  return '<p style="margin: 4px 0;"><span class="label">' + r.id.toUpperCase() + ' (Min/Max):</span> ' + value + '</p>';
+                              }).join('');
+
+                              // Process resources for free tier
+                              const freeResourceDetails = selectedEnv.free.resources.map(r => {
+                                  let value = '';
+                                  if (r.id === 'ram' || r.id === 'disk') {
+                                      const maxGb = Math.round(r.max / (1024 * 1024 * 1024));
+                                      value = maxGb + ' GB';
+                                  } else {
+                                      value = r.max;
+                                  }
+                                  return '<p style="margin: 4px 0;"><span class="label">' + r.id.toUpperCase() + ' (Max):</span> ' + value + '</p>';
+                              }).join('');
+
+                              detailsDiv.innerHTML = 
+                                  '<p><span class="label">Environment ID:</span> ' + truncatedId + '</p>' +
+                                  '<p><span class="label">OS:</span> ' + selectedEnv.platform.os + '</p>' +
+                                  '<p><span class="label">Architecture:</span> ' + selectedEnv.platform.architecture + '</p>' +
+                                  '<div style="margin: 4px 0;">' +
+                                  '<div class="label" style="margin-bottom: 2px;">Consumer Address:</div>' +
+                                  '<div style="display: flex; align-items: center; gap: 8px; background: var(--vscode-input-background); padding: 4px; border-radius: 4px;">' +
+                                  '<span style="font-family: monospace; flex-grow: 1; overflow-x: auto; white-space: nowrap;">' + 
+                                  (selectedEnv.consumerAddress.length > 24 
+                                      ? selectedEnv.consumerAddress.substring(0, 12) + '...' + selectedEnv.consumerAddress.substring(selectedEnv.consumerAddress.length - 8)
+                                      : selectedEnv.consumerAddress) + 
+                                  '</span>' +
+                                  '<button id="copyAddressBtn" ' +
+                                  'style="padding: 2px 8px; margin: 0; width: auto; min-width: 60px; font-size: 0.9em;">Copy</button>' +
+                                  '</div>' +
+                                  '</div>' +
+                                  // '<p><span class="label">Paid Resources:</span></p>' +
+                                  // '<div style="margin-left: 8px;">' + 
+                                  // paidResourceDetails +
+                                  // '<p style="margin: 4px 0;"><span class="label">Max Job Duration:</span> ' + selectedEnv.maxJobDuration + ' seconds</p>' +
+                                  // '</div>' +
+                                  '<p><span class="label">Free Resources:</span></p>' +
+                                  '<div style="margin-left: 8px;">' + 
+                                  freeResourceDetails +
+                                  '<p style="margin: 4px 0;"><span class="label">Max Job Duration:</span> ' + selectedEnv.free.maxJobDuration + ' seconds</p>' +
+                                  '</div>';
+                              detailsDiv.style.display = 'block';
+
+                              const copyBtn = document.getElementById('copyAddressBtn');
+                              if (copyBtn) {
+                                  copyBtn.addEventListener('click', () => {
+                                      vscode.postMessage({
+                                          type: 'copyToClipboard',
+                                          text: selectedEnv.consumerAddress
+                                      });
+                                      copyBtn.textContent = 'Copied!';
+                                      setTimeout(() => {
+                                          copyBtn.textContent = 'Copy';
+                                      }, 1500);
+                                  });
+                              }
+                          }
+
+                          if (select.options.length > 0) {
+                              select.selectedIndex = 0;
+                              showEnvDetails(select.value);
+                          }
+
+                          select.addEventListener('change', function() {
+                              showEnvDetails(this.value);
+                          });
+                          break;
                   }
               });
           </script>


Reviews:
user: login: mariacarmina
body: LGTM! Tested on my side, it works running algos and received algos results too.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T12:42:29Z
user: login: bogdanfazakas
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-07T12:49:58Z
user: login: bogdanfazakas
body: small suggestion but looks good over all 
great job 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-07T12:53:26Z
user: login: giurgiur99
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T13:13:45Z

Review comments:
diff_hunk: @@ -360,17 +423,43 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
 
                       vscode.postMessage({ 
                           type: 'startComputeJob',
-                              privateKey: privateKey,
-                              algorithmPath: selectedAlgorithmPath,
-                              resultsFolderPath: selectedResultsFolderPath,
-                              nodeUrl: nodeUrl,
-                              datasetPath: selectedDatasetPath || undefined,
-                              dockerImage: dockerImage || undefined,
-                              dockerTag: dockerTag || undefined
+                          privateKey: privateKey,
+                          algorithmPath: selectedAlgorithmPath,
+                          resultsFolderPath: selectedResultsFolderPath,
+                          nodeUrl: nodeUrl,
+                          datasetPath: selectedDatasetPath || undefined,
+                          dockerImage: dockerImage || undefined,
+                          dockerTag: dockerTag || undefined,
+                          environmentId: document.getElementById('environmentSelect').value || undefined
                       });
                   });
               }
 
+              async function loadEnvironments() {
+                const nodeUrl = document.getElementById('nodeUrlInput').value;
+                if (!nodeUrl) return;
+
+                const select = document.getElementById('environmentSelect');
+                select.innerHTML = '<option value="">Loading environments...</option>';
+                select.disabled = true;
+                document.getElementById('environmentDetails').style.display = 'none';
+
+                try {
+                  vscode.postMessage({
+                    type: 'getEnvironments',
+                    nodeUrl: nodeUrl
+                  });
+                } catch (error) {
+                  console.error('Error loading environments:', error);
+                  select.innerHTML = '<option value="">Error loading environments</option>';
+                  select.disabled = true;
+                  document.getElementById('environmentDetails').style.display = 'none';
+                }
+              }
+
+              document.getElementById('nodeUrlInput').addEventListener('input', loadEnvironments);
path: src/viewProvider.ts
user: login: bogdanfazakas
body: you are querying  document.getElementById('environmentDetails') and document.getElementById('nodeUrlInput') multiple times witch is doing querying the  DOM multiple times 
worth having something like for eg
```
const select = document.getElementById('environmentSelect');
const environmentDetails = document.getElementById('environmentDetails');
```
created_at: 2025-05-07T12:49:58Z
author_association: MEMBER
diff_hunk: @@ -360,17 +423,43 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
 
                       vscode.postMessage({ 
                           type: 'startComputeJob',
-                              privateKey: privateKey,
-                              algorithmPath: selectedAlgorithmPath,
-                              resultsFolderPath: selectedResultsFolderPath,
-                              nodeUrl: nodeUrl,
-                              datasetPath: selectedDatasetPath || undefined,
-                              dockerImage: dockerImage || undefined,
-                              dockerTag: dockerTag || undefined
+                          privateKey: privateKey,
+                          algorithmPath: selectedAlgorithmPath,
+                          resultsFolderPath: selectedResultsFolderPath,
+                          nodeUrl: nodeUrl,
+                          datasetPath: selectedDatasetPath || undefined,
+                          dockerImage: dockerImage || undefined,
+                          dockerTag: dockerTag || undefined,
+                          environmentId: document.getElementById('environmentSelect').value || undefined
                       });
                   });
               }
 
+              async function loadEnvironments() {
+                const nodeUrl = document.getElementById('nodeUrlInput').value;
+                if (!nodeUrl) return;
+
+                const select = document.getElementById('environmentSelect');
+                select.innerHTML = '<option value="">Loading environments...</option>';
+                select.disabled = true;
+                document.getElementById('environmentDetails').style.display = 'none';
+
+                try {
+                  vscode.postMessage({
+                    type: 'getEnvironments',
+                    nodeUrl: nodeUrl
+                  });
+                } catch (error) {
+                  console.error('Error loading environments:', error);
+                  select.innerHTML = '<option value="">Error loading environments</option>';
+                  select.disabled = true;
+                  document.getElementById('environmentDetails').style.display = 'none';
+                }
+              }
+
+              document.getElementById('nodeUrlInput').addEventListener('input', loadEnvironments);
path: src/viewProvider.ts
user: login: giurgiur99
body: Good catch, fixed
created_at: 2025-05-07T13:13:45Z
author_association: CONTRIBUTOR

PR comments:
user: login: giurgiur99
created_at: 2025-05-02T07:56:29Z
body: The values shown in the box can be adjusted.

<img width="483" alt="Screenshot 2025-04-30 at 13 46 53" src="https://github.com/user-attachments/assets/65f974f3-c976-4287-b538-39bdc5d13f20" />
<img width="483" alt="Screenshot 2025-04-30 at 13 33 56" src="https://github.com/user-attachments/assets/7cec8e92-1480-4842-acca-3d23d9869a12" />
<img width="483" alt="Screenshot 2025-04-30 at 13 33 46" src="https://github.com/user-attachments/assets/2820f4d6-a8e6-406d-bdd5-ea4a73a7a8c0" />

author_association: CONTRIBUTOR
user: login: mariacarmina
created_at: 2025-05-05T11:53:37Z
body: > The values shown in the box can be adjusted.
> 
> <img alt="Screenshot 2025-04-30 at 13 46 53" width="483" src="https://private-user-images.githubusercontent.com/24292234/439840814-65f974f3-c976-4287-b538-39bdc5d13f20.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDY0NDYwMTYsIm5iZiI6MTc0NjQ0NTcxNiwicGF0aCI6Ii8yNDI5MjIzNC80Mzk4NDA4MTQtNjVmOTc0ZjMtYzk3Ni00Mjg3LWI1MzgtMzliZGM1ZDEzZjIwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA1VDExNDgzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTJkMTM4MWZkZWViMGMzMTcwNjhhZDg0MTU3M2U4MzhjOWQwYTkyYmVkMWU5NjdjZWEyNmMyYTM2NDI0NThiMTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.Fnl4n2WvWu_9bPXdiGQ8iiBoLOgzlEBdIPTH4QsUixw"> <img alt="Screenshot 2025-04-30 at 13 33 56" width="483" src="https://private-user-images.githubusercontent.com/24292234/439840821-7cec8e92-1480-4842-acca-3d23d9869a12.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDY0NDYwMTYsIm5iZiI6MTc0NjQ0NTcxNiwicGF0aCI6Ii8yNDI5MjIzNC80Mzk4NDA4MjEtN2NlYzhlOTItMTQ4MC00ODQyLWFjY2EtM2QyM2Q5ODY5YTEyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA1VDExNDgzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWVhOGVmMDhlMDY3MGE3NGI4NTkwOTY1OTg5YjI0Yzg1NGVmNmY5ZmYyNDMxNjI3YWZkYWJlMDE0Y2Y2NDJjMjcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.2yCZIgRmY9Vae6pmU413oGA4N6XrLdQRhxHDMWKj5kg"> <img alt="Screenshot 2025-04-30 at 13 33 46" width="483" src="https://private-user-images.githubusercontent.com/24292234/439840826-2820f4d6-a8e6-406d-bdd5-ea4a73a7a8c0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDY0NDYwMTYsIm5iZiI6MTc0NjQ0NTcxNiwicGF0aCI6Ii8yNDI5MjIzNC80Mzk4NDA4MjYtMjgyMGY0ZDYtYThlNi00MDZkLWJkZDUtZWE0YTczYTdhOGMwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA1VDExNDgzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTU5MjZkNGY2M2E3YzRkNzliYzZmMzE4MWZhM2FlYzRhZjc4Y2FiNjc4NTdkZDc4YzU0ZGVkZTk1N2ZmZjc4MmUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.So8XsdSeZ8wFdDpimeZLzEgDR4UwS7gxolqLBNAYebE">

Nice job, regarding the details that need to be displayed to the user, we can add the environment ID with hash, because maybe we'll have multiple env running on Ubuntu 22.04 LTS but with different resources and the env id will be unique and second thing that it is relevant to add is the `consumerAddress` from the environment, because that address will help the end user to send gas funds for paid compute, for example
author_association: CONTRIBUTOR
user: login: giurgiur99
created_at: 2025-05-05T11:59:31Z
body: > > The values shown in the box can be adjusted.
> > <img alt="Screenshot 2025-04-30 at 13 46 53" width="483" src="https://private-user-images.githubusercontent.com/24292234/439840814-65f974f3-c976-4287-b538-39bdc5d13f20.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDY0NDYwMTYsIm5iZiI6MTc0NjQ0NTcxNiwicGF0aCI6Ii8yNDI5MjIzNC80Mzk4NDA4MTQtNjVmOTc0ZjMtYzk3Ni00Mjg3LWI1MzgtMzliZGM1ZDEzZjIwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA1VDExNDgzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTJkMTM4MWZkZWViMGMzMTcwNjhhZDg0MTU3M2U4MzhjOWQwYTkyYmVkMWU5NjdjZWEyNmMyYTM2NDI0NThiMTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.Fnl4n2WvWu_9bPXdiGQ8iiBoLOgzlEBdIPTH4QsUixw"> <img alt="Screenshot 2025-04-30 at 13 33 56" width="483" src="https://private-user-images.githubusercontent.com/24292234/439840821-7cec8e92-1480-4842-acca-3d23d9869a12.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDY0NDYwMTYsIm5iZiI6MTc0NjQ0NTcxNiwicGF0aCI6Ii8yNDI5MjIzNC80Mzk4NDA4MjEtN2NlYzhlOTItMTQ4MC00ODQyLWFjY2EtM2QyM2Q5ODY5YTEyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA1VDExNDgzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWVhOGVmMDhlMDY3MGE3NGI4NTkwOTY1OTg5YjI0Yzg1NGVmNmY5ZmYyNDMxNjI3YWZkYWJlMDE0Y2Y2NDJjMjcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.2yCZIgRmY9Vae6pmU413oGA4N6XrLdQRhxHDMWKj5kg"> <img alt="Screenshot 2025-04-30 at 13 33 46" width="483" src="https://private-user-images.githubusercontent.com/24292234/439840826-2820f4d6-a8e6-406d-bdd5-ea4a73a7a8c0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDY0NDYwMTYsIm5iZiI6MTc0NjQ0NTcxNiwicGF0aCI6Ii8yNDI5MjIzNC80Mzk4NDA4MjYtMjgyMGY0ZDYtYThlNi00MDZkLWJkZDUtZWE0YTczYTdhOGMwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA1MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNTA1VDExNDgzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTU5MjZkNGY2M2E3YzRkNzliYzZmMzE4MWZhM2FlYzRhZjc4Y2FiNjc4NTdkZDc4YzU0ZGVkZTk1N2ZmZjc4MmUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.So8XsdSeZ8wFdDpimeZLzEgDR4UwS7gxolqLBNAYebE">
> 
> Nice job, regarding the details that need to be displayed to the user, we can add the environment ID with hash, because maybe we'll have multiple env running on Ubuntu 22.04 LTS but with different resources and the env id will be unique and second thing that it is relevant to add is the `consumerAddress` from the environment, because that address will help the end user to send gas funds for paid compute, for example

Thanks 🙏 . Here i was thinking we can have the start and the end of the id, since the string is quite long. Ex: 0xabc.....976
author_association: CONTRIBUTOR
user: login: mariacarmina
created_at: 2025-05-05T12:11:30Z
body: Specify the minumum, maximum resources in the environment details, too.
author_association: CONTRIBUTOR
user: login: giurgiur99
created_at: 2025-05-06T08:08:21Z
body: > Specify the minumum, maximum resources in the environment details, too.

The selection of the compute resources will be done in another issue #85. 
author_association: CONTRIBUTOR
user: login: giurgiur99
created_at: 2025-05-06T08:09:17Z
body: New interface with copy button for consumerAddress and resources grouped by paid and free

<img width="339" alt="Screenshot 2025-05-06 at 11 05 51" src="https://github.com/user-attachments/assets/96e832b9-c7d6-4dc0-90c6-2e8c7c33e7a4" />

author_association: CONTRIBUTOR
user: login: mariacarmina
created_at: 2025-05-07T12:08:06Z
body: Since we need to select the environment and we display the resources for the environment and currently VS code extension supports only free start compute, we can keep only free resources to diaply to end user.
The resources will be parsed in ocean.js -> ocean.js supports resources for freeStartCompute function. We can use the **max limits** for free resources when calling ocean.js function
author_association: CONTRIBUTOR
user: login: giurgiur99
created_at: 2025-05-07T12:14:13Z
body: <img width="377" alt="image" src="https://github.com/user-attachments/assets/bf129d32-b49d-481f-a6b3-88d08bda9dca" />

author_association: CONTRIBUTOR
user: login: mariacarmina
created_at: 2025-05-07T12:33:49Z
body: We can parse the resource parameters in a separate issue (also when paid compute will be integrated). Ocean node has defaults for free (it picks the maximum limits for free).
author_association: CONTRIBUTOR
user: login: mariacarmina
created_at: 2025-05-07T12:36:54Z
body: One more thing, please update package.json version to patch version: 0.0.5 -> `0.0.6`.
author_association: CONTRIBUTOR