@@ -18,10 +18,10 @@ namespace Microsoft.SemanticKernel.Plugins.Core.CodeInterpreter;
18
18
/// <summary>
19
19
/// A plugin for running Python code in an Azure Container Apps dynamic sessions code interpreter.
20
20
/// </summary>
21
- public partial class SessionsPythonPlugin
21
+ public sealed partial class SessionsPythonPlugin
22
22
{
23
23
private static readonly string s_assemblyVersion = typeof ( Kernel ) . Assembly . GetName ( ) . Version ! . ToString ( ) ;
24
- private const string ApiVersion = "2024-02 -02-preview" ;
24
+ private const string ApiVersion = "2024-10 -02-preview" ;
25
25
private readonly Uri _poolManagementEndpoint ;
26
26
private readonly SessionsPythonSettings _settings ;
27
27
private readonly Func < Task < string > > ? _authTokenProvider ;
@@ -90,14 +90,11 @@ public async Task<string> ExecuteCodeAsync([Description("The valid Python code t
90
90
91
91
using var httpClient = this . _httpClientFactory . CreateClient ( ) ;
92
92
93
- var requestBody = new
94
- {
95
- properties = new SessionsPythonCodeExecutionProperties ( this . _settings , code )
96
- } ;
93
+ var requestBody = new SessionsPythonCodeExecutionProperties ( this . _settings , code ) ;
97
94
98
95
await this . AddHeadersAsync ( httpClient ) . ConfigureAwait ( false ) ;
99
96
100
- using var request = new HttpRequestMessage ( HttpMethod . Post , this . _poolManagementEndpoint + $ "python/execute? api-version={ ApiVersion } ")
97
+ using var request = new HttpRequestMessage ( HttpMethod . Post , $ " { this . _poolManagementEndpoint } /executions?identifier= { this . _settings . SessionId } & api-version={ ApiVersion } ")
101
98
{
102
99
Content = new StringContent ( JsonSerializer . Serialize ( requestBody ) , Encoding . UTF8 , "application/json" )
103
100
} ;
@@ -110,17 +107,19 @@ public async Task<string> ExecuteCodeAsync([Description("The valid Python code t
110
107
throw new HttpRequestException ( $ "Failed to execute python code. Status: { response . StatusCode } . Details: { errorBody } .") ;
111
108
}
112
109
113
- var jsonElementResult = JsonSerializer . Deserialize < JsonElement > ( await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ) ;
110
+ var responseContent = JsonSerializer . Deserialize < JsonElement > ( await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ) ;
111
+
112
+ var result = responseContent . GetProperty ( "result" ) ;
114
113
115
114
return $ """
116
115
Status:
117
- { jsonElementResult . GetProperty ( "status" ) . GetRawText ( ) }
116
+ { responseContent . GetProperty ( "status" ) . GetRawText ( ) }
118
117
Result:
119
- { jsonElementResult . GetProperty ( "result " ) . GetRawText ( ) }
118
+ { result . GetProperty ( "executionResult " ) . GetRawText ( ) }
120
119
Stdout:
121
- { jsonElementResult . GetProperty ( "stdout" ) . GetRawText ( ) }
120
+ { result . GetProperty ( "stdout" ) . GetRawText ( ) }
122
121
Stderr:
123
- { jsonElementResult . GetProperty ( "stderr" ) . GetRawText ( ) }
122
+ { result . GetProperty ( "stderr" ) . GetRawText ( ) }
124
123
""" ;
125
124
}
126
125
@@ -135,33 +134,33 @@ private async Task AddHeadersAsync(HttpClient httpClient)
135
134
}
136
135
137
136
/// <summary>
138
- /// Upload a file to the session pool .
137
+ /// Uploads a file to the `/mnt/data` directory of the current session .
139
138
/// </summary>
140
- /// <param name="remoteFilePath ">The path to the file in the session .</param>
139
+ /// <param name="remoteFileName ">The name of the remote file, relative to `/mnt/data` .</param>
141
140
/// <param name="localFilePath">The path to the file on the local machine.</param>
142
141
/// <returns>The metadata of the uploaded file.</returns>
143
142
/// <exception cref="ArgumentNullException"></exception>
144
143
/// <exception cref="HttpRequestException"></exception>
145
- [ KernelFunction , Description ( "Uploads a file for the current session id pool ." ) ]
144
+ [ KernelFunction , Description ( "Uploads a file to the `/mnt/data` directory of the current session ." ) ]
146
145
public async Task < SessionsRemoteFileMetadata > UploadFileAsync (
147
- [ Description ( "The path to the file in the session ." ) ] string remoteFilePath ,
148
- [ Description ( "The path to the file on the local machine." ) ] string ? localFilePath )
146
+ [ Description ( "The name of the remote file, relative to `/mnt/data` ." ) ] string remoteFileName ,
147
+ [ Description ( "The path to the file on the local machine." ) ] string localFilePath )
149
148
{
150
- Verify . NotNullOrWhiteSpace ( remoteFilePath , nameof ( remoteFilePath ) ) ;
149
+ Verify . NotNullOrWhiteSpace ( remoteFileName , nameof ( remoteFileName ) ) ;
151
150
Verify . NotNullOrWhiteSpace ( localFilePath , nameof ( localFilePath ) ) ;
152
151
153
- this . _logger . LogInformation ( "Uploading file: {LocalFilePath} to {RemoteFilePath}" , localFilePath , remoteFilePath ) ;
152
+ this . _logger . LogInformation ( "Uploading file: {LocalFilePath} to {RemoteFilePath}" , localFilePath , remoteFileName ) ;
154
153
155
154
using var httpClient = this . _httpClientFactory . CreateClient ( ) ;
156
155
157
156
await this . AddHeadersAsync ( httpClient ) . ConfigureAwait ( false ) ;
158
157
159
158
using var fileContent = new ByteArrayContent ( File . ReadAllBytes ( localFilePath ) ) ;
160
- using var request = new HttpRequestMessage ( HttpMethod . Post , $ "{ this . _poolManagementEndpoint } files/upload ?identifier={ this . _settings . SessionId } &api-version={ ApiVersion } ")
159
+ using var request = new HttpRequestMessage ( HttpMethod . Post , $ "{ this . _poolManagementEndpoint } files?identifier={ this . _settings . SessionId } &api-version={ ApiVersion } ")
161
160
{
162
161
Content = new MultipartFormDataContent
163
162
{
164
- { fileContent , "file" , remoteFilePath } ,
163
+ { fileContent , "file" , remoteFileName } ,
165
164
}
166
165
} ;
167
166
@@ -173,30 +172,30 @@ public async Task<SessionsRemoteFileMetadata> UploadFileAsync(
173
172
throw new HttpRequestException ( $ "Failed to upload file. Status code: { response . StatusCode } . Details: { errorBody } .") ;
174
173
}
175
174
176
- var JsonElementResult = JsonSerializer . Deserialize < JsonElement > ( await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ) ;
175
+ var stringContent = await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
177
176
178
- return JsonSerializer . Deserialize < SessionsRemoteFileMetadata > ( JsonElementResult . GetProperty ( "value" ) [ 0 ] . GetProperty ( "properties" ) . GetRawText ( ) ) ! ;
177
+ return JsonSerializer . Deserialize < SessionsRemoteFileMetadata > ( stringContent ) ! ;
179
178
}
180
179
181
180
/// <summary>
182
- /// Downloads a file from the current Session ID .
181
+ /// Downloads a file from the `/mnt/data` directory of the current session .
183
182
/// </summary>
184
- /// <param name="remoteFilePath"> The path to download the file from , relative to `/mnt/data`. </param>
185
- /// <param name="localFilePath"> The path to save the downloaded file to. If not provided won't save it in the disk.</param>
186
- /// <returns> The data of the downloaded file as byte array. </returns>
187
- [ KernelFunction , Description ( "Downloads a file from the current Session ID ." ) ]
183
+ /// <param name="remoteFileName"> The name of the remote file to download , relative to `/mnt/data`.</param>
184
+ /// <param name="localFilePath">The path to save the downloaded file to. If not provided won't save it in the disk.</param>
185
+ /// <returns>The data of the downloaded file as byte array.</returns>
186
+ [ KernelFunction , Description ( "Downloads a file from the `/mnt/data` directory of the current session ." ) ]
188
187
public async Task < byte [ ] > DownloadFileAsync (
189
- [ Description ( "The path to download the file from , relative to `/mnt/data`." ) ] string remoteFilePath ,
188
+ [ Description ( "The name of the remote file to download , relative to `/mnt/data`." ) ] string remoteFileName ,
190
189
[ Description ( "The path to save the downloaded file to. If not provided won't save it in the disk." ) ] string ? localFilePath = null )
191
190
{
192
- Verify . NotNullOrWhiteSpace ( remoteFilePath , nameof ( remoteFilePath ) ) ;
191
+ Verify . NotNullOrWhiteSpace ( remoteFileName , nameof ( remoteFileName ) ) ;
193
192
194
- this . _logger . LogTrace ( "Downloading file: {RemoteFilePath} to {LocalFilePath}" , remoteFilePath , localFilePath ) ;
193
+ this . _logger . LogTrace ( "Downloading file: {RemoteFilePath} to {LocalFilePath}" , remoteFileName , localFilePath ) ;
195
194
196
195
using var httpClient = this . _httpClientFactory . CreateClient ( ) ;
197
196
await this . AddHeadersAsync ( httpClient ) . ConfigureAwait ( false ) ;
198
197
199
- var response = await httpClient . GetAsync ( new Uri ( $ "{ this . _poolManagementEndpoint } python/downloadFile ?identifier={ this . _settings . SessionId } &filename= { remoteFilePath } &api-version={ ApiVersion } ") ) . ConfigureAwait ( false ) ;
198
+ var response = await httpClient . GetAsync ( new Uri ( $ "{ this . _poolManagementEndpoint } /files/ { Uri . EscapeDataString ( remoteFileName ) } /content ?identifier={ this . _settings . SessionId } &api-version={ ApiVersion } ") ) . ConfigureAwait ( false ) ;
200
199
if ( ! response . IsSuccessStatusCode )
201
200
{
202
201
var errorBody = await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
@@ -221,10 +220,10 @@ public async Task<byte[]> DownloadFileAsync(
221
220
}
222
221
223
222
/// <summary>
224
- /// Lists all files in the provided session id pool .
223
+ /// Lists all entities: files or directories in the `/mnt/data` directory of the current session .
225
224
/// </summary>
226
- /// <returns> The list of files in the session. </returns>
227
- [ KernelFunction , Description ( "Lists all files in the provided session id pool ." ) ]
225
+ /// <returns>The list of files in the session.</returns>
226
+ [ KernelFunction , Description ( "Lists all entities: files or directories in the `/mnt/data` directory of the current session ." ) ]
228
227
public async Task < IReadOnlyList < SessionsRemoteFileMetadata > > ListFilesAsync ( )
229
228
{
230
229
this . _logger . LogTrace ( "Listing files for Session ID: {SessionId}" , this . _settings . SessionId ) ;
@@ -243,14 +242,7 @@ public async Task<IReadOnlyList<SessionsRemoteFileMetadata>> ListFilesAsync()
243
242
244
243
var files = jsonElementResult . GetProperty ( "value" ) ;
245
244
246
- var result = new SessionsRemoteFileMetadata [ files . GetArrayLength ( ) ] ;
247
-
248
- for ( var i = 0 ; i < result . Length ; i ++ )
249
- {
250
- result [ i ] = JsonSerializer . Deserialize < SessionsRemoteFileMetadata > ( files [ i ] . GetProperty ( "properties" ) . GetRawText ( ) ) ! ;
251
- }
252
-
253
- return result ;
245
+ return files . Deserialize < SessionsRemoteFileMetadata [ ] > ( ) ! ;
254
246
}
255
247
256
248
private static Uri GetBaseEndpoint ( Uri endpoint )
0 commit comments