@microsoft/agents-copilotstudio-client
Version:
Microsoft Copilot Studio Client for JavaScript. Copilot Studio Client.
193 lines • 9.09 kB
JavaScript
;
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CopilotStudioClient = void 0;
const axios_1 = __importDefault(require("axios"));
const powerPlatformEnvironment_1 = require("./powerPlatformEnvironment");
const agents_activity_1 = require("@microsoft/agents-activity");
const executeTurnRequest_1 = require("./executeTurnRequest");
const logger_1 = require("@microsoft/agents-activity/logger");
const package_json_1 = require("../package.json");
const os_1 = __importDefault(require("os"));
const logger = (0, logger_1.debug)('copilot-studio:client');
/**
* Client for interacting with Microsoft Copilot Studio services.
* Provides functionality to start conversations and send messages to Copilot Studio bots.
*/
class CopilotStudioClient {
/**
* Creates an instance of CopilotStudioClient.
* @param settings The connection settings.
* @param token The authentication token.
*/
constructor(settings, token) {
/** The ID of the current conversation. */
this.conversationId = '';
this.settings = settings;
this.client = axios_1.default.create();
this.client.defaults.headers.common.Authorization = `Bearer ${token}`;
this.client.defaults.headers.common['User-Agent'] = CopilotStudioClient.getProductInfo();
}
async postRequestAsync(axiosConfig) {
var _a, _b, _c, _d;
const activities = [];
logger.debug(`>>> SEND TO ${axiosConfig.url}`);
const response = await this.client(axiosConfig);
if (this.settings.useExperimentalEndpoint && !((_a = this.settings.directConnectUrl) === null || _a === void 0 ? void 0 : _a.trim())) {
const islandExperimentalUrl = (_b = response.headers) === null || _b === void 0 ? void 0 : _b[CopilotStudioClient.islandExperimentalUrlHeaderKey];
if (islandExperimentalUrl) {
this.settings.directConnectUrl = islandExperimentalUrl;
logger.debug(`Island Experimental URL: ${islandExperimentalUrl}`);
}
}
this.conversationId = (_d = (_c = response.headers) === null || _c === void 0 ? void 0 : _c[CopilotStudioClient.conversationIdHeaderKey]) !== null && _d !== void 0 ? _d : '';
if (this.conversationId) {
logger.debug(`Conversation ID: ${this.conversationId}`);
}
const sanitizedHeaders = { ...response.headers };
delete sanitizedHeaders['Authorization'];
delete sanitizedHeaders[CopilotStudioClient.conversationIdHeaderKey];
logger.debug('Headers received:', sanitizedHeaders);
const stream = response.data;
const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
let result = '';
const results = [];
const processEvents = async ({ done, value }) => {
if (done) {
logger.debug('Stream complete');
result += value;
results.push(result);
return results;
}
logger.info('Agent is typing ...');
result += value;
return await processEvents(await reader.read());
};
const events = await reader.read().then(processEvents);
events.forEach(event => {
const values = event.toString().split('\n');
const validEvents = values.filter(e => e.substring(0, 4) === 'data' && e !== 'data: end\r');
validEvents.forEach(ve => {
var _a, _b;
try {
const act = agents_activity_1.Activity.fromJson(ve.substring(5, ve.length));
if (act.type === agents_activity_1.ActivityTypes.Message) {
activities.push(act);
if (!this.conversationId.trim()) {
// Did not get it from the header.
this.conversationId = (_b = (_a = act.conversation) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '';
logger.debug(`Conversation ID: ${this.conversationId}`);
}
}
else {
logger.debug(`Activity type: ${act.type}`);
}
}
catch (e) {
logger.error('Error: ', e);
throw e;
}
});
});
return activities;
}
/**
* Appends this package.json version to the User-Agent header.
* - For browser environments, it includes the user agent of the browser.
* - For Node.js environments, it includes the Node.js version, platform, architecture, and release.
* @returns A string containing the product information, including version and user agent.
*/
static getProductInfo() {
const versionString = `CopilotStudioClient.agents-sdk-js/${package_json_1.version}`;
let userAgent;
if (typeof window !== 'undefined' && window.navigator) {
userAgent = `${versionString} ${navigator.userAgent}`;
}
else {
userAgent = `${versionString} nodejs/${process.version} ${os_1.default.platform()}-${os_1.default.arch()}/${os_1.default.release()}`;
}
logger.debug(`User-Agent: ${userAgent}`);
return userAgent;
}
/**
* Starts a new conversation with the Copilot Studio service.
* @param emitStartConversationEvent Whether to emit a start conversation event. Defaults to true.
* @returns A promise that resolves to the initial activity of the conversation.
*/
async startConversationAsync(emitStartConversationEvent = true) {
var _a;
const uriStart = (0, powerPlatformEnvironment_1.getCopilotStudioConnectionUrl)(this.settings);
const body = { emitStartConversationEvent };
const config = {
method: 'post',
url: uriStart,
headers: {
Accept: 'text/event-stream',
'Content-Type': 'application/json',
},
data: body,
responseType: 'stream',
adapter: 'fetch'
};
logger.info('Starting conversation ...');
const values = await this.postRequestAsync(config);
const act = values[0];
logger.info(`Conversation '${(_a = act.conversation) === null || _a === void 0 ? void 0 : _a.id}' started. Received ${values.length} activities.`, values);
return act;
}
/**
* Sends a question to the Copilot Studio service and retrieves the response activities.
* @param question The question to ask.
* @param conversationId The ID of the conversation. Defaults to the current conversation ID.
* @returns A promise that resolves to an array of activities containing the responses.
*/
async askQuestionAsync(question, conversationId = this.conversationId) {
var _a, _b;
const conversationAccount = {
id: conversationId
};
const activityObj = {
type: 'message',
text: question,
conversation: conversationAccount
};
const activity = agents_activity_1.Activity.fromObject(activityObj);
const localConversationId = (_b = (_a = activity.conversation) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : conversationId;
const uriExecute = (0, powerPlatformEnvironment_1.getCopilotStudioConnectionUrl)(this.settings, localConversationId);
const qbody = new executeTurnRequest_1.ExecuteTurnRequest(activity);
const config = {
method: 'post',
url: uriExecute,
headers: {
Accept: 'text/event-stream',
'Content-Type': 'application/json',
},
data: qbody,
responseType: 'stream',
adapter: 'fetch'
};
logger.info(`Asking question: ${question} ...`);
const values = await this.postRequestAsync(config);
logger.info(`Received ${values.length} activities.`, values);
return values;
}
}
exports.CopilotStudioClient = CopilotStudioClient;
/** Header key for conversation ID. */
CopilotStudioClient.conversationIdHeaderKey = 'x-ms-conversationid';
/** Island Header key */
CopilotStudioClient.islandExperimentalUrlHeaderKey = 'x-ms-d2e-experimental';
/**
* Returns the scope URL needed to connect to Copilot Studio from the connection settings.
* This is used for authentication token audience configuration.
* @param settings Copilot Studio connection settings.
* @returns The scope URL for token audience.
*/
CopilotStudioClient.scopeFromSettings = powerPlatformEnvironment_1.getTokenAudience;
//# sourceMappingURL=copilotStudioClient.js.map