Merge branch 'main' into sgoedecke/mcp
This commit is contained in:
+53
-35
@@ -48971,6 +48971,57 @@ function getPathFromMapKey(mapKey) {
|
|||||||
return mapKey.slice(pathStart);
|
return mapKey.slice(pathStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to load content from a file or use fallback input
|
||||||
|
* @param filePathInput - Input name for the file path
|
||||||
|
* @param contentInput - Input name for the direct content
|
||||||
|
* @param defaultValue - Default value to use if neither file nor content is provided
|
||||||
|
* @returns The loaded content
|
||||||
|
*/
|
||||||
|
function loadContentFromFileOrInput(filePathInput, contentInput, defaultValue) {
|
||||||
|
const filePath = coreExports.getInput(filePathInput);
|
||||||
|
const contentString = coreExports.getInput(contentInput);
|
||||||
|
if (filePath !== undefined && filePath !== '') {
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
throw new Error(`File for ${filePathInput} was not found: ${filePath}`);
|
||||||
|
}
|
||||||
|
return fs.readFileSync(filePath, 'utf-8');
|
||||||
|
}
|
||||||
|
else if (contentString !== undefined && contentString !== '') {
|
||||||
|
return contentString;
|
||||||
|
}
|
||||||
|
else if (defaultValue !== undefined) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error(`Neither ${filePathInput} nor ${contentInput} was set`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Helper function to handle unexpected responses from AI service
|
||||||
|
* @param response - The response object from the AI service
|
||||||
|
* @throws Error with appropriate error message based on response content
|
||||||
|
*/
|
||||||
|
function handleUnexpectedResponse(response) {
|
||||||
|
// Extract x-ms-error-code from headers if available
|
||||||
|
const errorCode = response.headers['x-ms-error-code'];
|
||||||
|
const errorCodeMsg = errorCode ? ` (error code: ${errorCode})` : '';
|
||||||
|
// Check if response body exists and contains error details
|
||||||
|
if (response.body && response.body.error) {
|
||||||
|
throw response.body.error;
|
||||||
|
}
|
||||||
|
// Handle case where response body is missing
|
||||||
|
if (!response.body) {
|
||||||
|
throw new Error(`Failed to get response from AI service (status: ${response.status})${errorCodeMsg}. ` +
|
||||||
|
'Please check network connection and endpoint configuration.');
|
||||||
|
}
|
||||||
|
// Handle other error cases
|
||||||
|
throw new Error(`AI service returned error response (status: ${response.status})${errorCodeMsg}: ` +
|
||||||
|
(typeof response.body === 'string'
|
||||||
|
? response.body
|
||||||
|
: JSON.stringify(response.body)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple one-shot inference without tools
|
* Simple one-shot inference without tools
|
||||||
*/
|
*/
|
||||||
@@ -48994,10 +49045,7 @@ async function simpleInference(request) {
|
|||||||
body: requestBody
|
body: requestBody
|
||||||
});
|
});
|
||||||
if (isUnexpected(response)) {
|
if (isUnexpected(response)) {
|
||||||
throw new Error('An error occurred while fetching the response (' +
|
handleUnexpectedResponse(response);
|
||||||
response.status +
|
|
||||||
'): ' +
|
|
||||||
response.body);
|
|
||||||
}
|
}
|
||||||
const modelResponse = response.body.choices[0].message.content;
|
const modelResponse = response.body.choices[0].message.content;
|
||||||
coreExports.info(`Model response: ${modelResponse || 'No response content'}`);
|
coreExports.info(`Model response: ${modelResponse || 'No response content'}`);
|
||||||
@@ -49034,10 +49082,7 @@ async function mcpInference(request, githubMcpClient) {
|
|||||||
body: requestBody
|
body: requestBody
|
||||||
});
|
});
|
||||||
if (isUnexpected(response)) {
|
if (isUnexpected(response)) {
|
||||||
throw new Error('An error occurred while fetching the response (' +
|
handleUnexpectedResponse(response);
|
||||||
response.status +
|
|
||||||
'): ' +
|
|
||||||
response.body);
|
|
||||||
}
|
}
|
||||||
const assistantMessage = response.body.choices[0].message;
|
const assistantMessage = response.body.choices[0].message;
|
||||||
const modelResponse = assistantMessage.content;
|
const modelResponse = assistantMessage.content;
|
||||||
@@ -49068,33 +49113,6 @@ async function mcpInference(request, githubMcpClient) {
|
|||||||
return lastAssistantMessage?.content || null;
|
return lastAssistantMessage?.content || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to load content from a file or use fallback input
|
|
||||||
* @param filePathInput - Input name for the file path
|
|
||||||
* @param contentInput - Input name for the direct content
|
|
||||||
* @param defaultValue - Default value to use if neither file nor content is provided
|
|
||||||
* @returns The loaded content
|
|
||||||
*/
|
|
||||||
function loadContentFromFileOrInput(filePathInput, contentInput, defaultValue) {
|
|
||||||
const filePath = coreExports.getInput(filePathInput);
|
|
||||||
const contentString = coreExports.getInput(contentInput);
|
|
||||||
if (filePath !== undefined && filePath !== '') {
|
|
||||||
if (!fs.existsSync(filePath)) {
|
|
||||||
throw new Error(`File for ${filePathInput} was not found: ${filePath}`);
|
|
||||||
}
|
|
||||||
return fs.readFileSync(filePath, 'utf-8');
|
|
||||||
}
|
|
||||||
else if (contentString !== undefined && contentString !== '') {
|
|
||||||
return contentString;
|
|
||||||
}
|
|
||||||
else if (defaultValue !== undefined) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Error(`Neither ${filePathInput} nor ${contentInput} was set`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const RESPONSE_FILE = 'modelResponse.txt';
|
const RESPONSE_FILE = 'modelResponse.txt';
|
||||||
/**
|
/**
|
||||||
* The main function for the action.
|
* The main function for the action.
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
|
import { GetChatCompletionsDefaultResponse } from '@azure-rest/ai-inference'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,3 +30,37 @@ export function loadContentFromFileOrInput(
|
|||||||
throw new Error(`Neither ${filePathInput} nor ${contentInput} was set`)
|
throw new Error(`Neither ${filePathInput} nor ${contentInput} was set`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to handle unexpected responses from AI service
|
||||||
|
* @param response - The response object from the AI service
|
||||||
|
* @throws Error with appropriate error message based on response content
|
||||||
|
*/
|
||||||
|
export function handleUnexpectedResponse(
|
||||||
|
response: GetChatCompletionsDefaultResponse
|
||||||
|
): never {
|
||||||
|
// Extract x-ms-error-code from headers if available
|
||||||
|
const errorCode = response.headers['x-ms-error-code']
|
||||||
|
const errorCodeMsg = errorCode ? ` (error code: ${errorCode})` : ''
|
||||||
|
|
||||||
|
// Check if response body exists and contains error details
|
||||||
|
if (response.body && response.body.error) {
|
||||||
|
throw response.body.error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle case where response body is missing
|
||||||
|
if (!response.body) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to get response from AI service (status: ${response.status})${errorCodeMsg}. ` +
|
||||||
|
'Please check network connection and endpoint configuration.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle other error cases
|
||||||
|
throw new Error(
|
||||||
|
`AI service returned error response (status: ${response.status})${errorCodeMsg}: ` +
|
||||||
|
(typeof response.body === 'string'
|
||||||
|
? response.body
|
||||||
|
: JSON.stringify(response.body))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
+3
-12
@@ -2,6 +2,7 @@ import * as core from '@actions/core'
|
|||||||
import ModelClient, { isUnexpected } from '@azure-rest/ai-inference'
|
import ModelClient, { isUnexpected } from '@azure-rest/ai-inference'
|
||||||
import { AzureKeyCredential } from '@azure/core-auth'
|
import { AzureKeyCredential } from '@azure/core-auth'
|
||||||
import { GitHubMCPClient, executeToolCalls } from './mcp.js'
|
import { GitHubMCPClient, executeToolCalls } from './mcp.js'
|
||||||
|
import { handleUnexpectedResponse } from './helpers.js'
|
||||||
|
|
||||||
export interface InferenceRequest {
|
export interface InferenceRequest {
|
||||||
systemPrompt: string
|
systemPrompt: string
|
||||||
@@ -57,12 +58,7 @@ export async function simpleInference(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (isUnexpected(response)) {
|
if (isUnexpected(response)) {
|
||||||
throw new Error(
|
handleUnexpectedResponse(response)
|
||||||
'An error occurred while fetching the response (' +
|
|
||||||
response.status +
|
|
||||||
'): ' +
|
|
||||||
response.body
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const modelResponse = response.body.choices[0].message.content
|
const modelResponse = response.body.choices[0].message.content
|
||||||
@@ -116,12 +112,7 @@ export async function mcpInference(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (isUnexpected(response)) {
|
if (isUnexpected(response)) {
|
||||||
throw new Error(
|
handleUnexpectedResponse(response)
|
||||||
'An error occurred while fetching the response (' +
|
|
||||||
response.status +
|
|
||||||
'): ' +
|
|
||||||
response.body
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const assistantMessage = response.body.choices[0].message
|
const assistantMessage = response.body.choices[0].message
|
||||||
|
|||||||
Reference in New Issue
Block a user