@microsoft/teams-ai
Version:
SDK focused on building AI based applications for Microsoft Teams.
173 lines • 5.93 kB
JavaScript
;
/**
* @module teams-ai
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Response = void 0;
/**
* Utilities for working with Large Language Model responses.
*/
class Response {
/**
* Parse all objects from a response string.
* @param {string} text Response text to parse.
* @returns {Record<string, any>[]} Array of parsed objects.
*/
static parseAllObjects(text) {
// First try parsing each line
const objects = [];
const lines = text.split('\n');
if (lines.length > 1) {
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const obj = this.parseJSON(line);
if (obj) {
objects.push(obj);
}
}
}
// Next try parsing the entire text
if (objects.length == 0) {
const obj = this.parseJSON(text);
if (obj) {
objects.push(obj);
}
}
return objects;
}
/**
* Fuzzy JSON parser.
* @template TObject Type of the object to parse.
* @param {string} text text to parse.
* @returns {TObject | undefined} The parsed object or undefined if the object could not be parsed.
*/
static parseJSON(text) {
const startBrace = text.indexOf('{');
if (startBrace >= 0) {
// Find substring
const objText = text.substring(startBrace);
const nesting = ['}'];
let cleaned = '{';
let inString = false;
for (let i = 1; i < objText.length && nesting.length > 0; i++) {
let ch = objText[i];
if (inString) {
cleaned += ch;
if (ch == '\\') {
// Skip escape char
i++;
if (i < objText.length) {
cleaned += objText[i];
}
else {
// Malformed
return undefined;
}
}
else if (ch == '"') {
inString = false;
}
}
else {
switch (ch) {
case '"':
inString = true;
break;
case '{':
nesting.push('}');
break;
case '[':
nesting.push(']');
break;
case '}': {
const closeObject = nesting.pop();
if (closeObject != '}') {
// Malformed
return undefined;
}
break;
}
case ']': {
const closeArray = nesting.pop();
if (closeArray != ']') {
// Malformed
return undefined;
}
break;
}
case '<':
// The model sometimes fails to wrap <some template> with double quotes
ch = `"<`;
break;
case '>':
// Catch the tail end of a template param
ch = `>"`;
break;
}
cleaned += ch;
}
}
// Is the object incomplete?
if (nesting.length > 0) {
// Lets close it and try to parse anyway
cleaned += nesting.reverse().join('');
}
// Parse cleaned up object
try {
const obj = JSON.parse(cleaned);
return Object.keys(obj).length > 0 ? obj : undefined;
}
catch (err) {
return undefined;
}
}
else {
return undefined;
}
}
/**
* Removes any empty fields from an object.
* @remarks
* Empty fields include `null`, `undefined`, `[]`, `{}`, and `""`.
* @param {Record<string, any>} obj The object to clean.
* @returns {Record<string, any>} A cleaned object.
*/
static removeEmptyValuesFromObject(obj) {
const result = {};
for (const key in obj) {
const value = obj[key];
const type = typeof value;
switch (type) {
case 'string':
if (value.length == 0) {
continue;
}
break;
case 'object':
if (value == null) {
continue;
}
else if (Array.isArray(value)) {
// keep empty arrays
}
else if (typeof value.toISOString !== 'function') {
const cleaned = this.removeEmptyValuesFromObject(value);
if (Object.keys(cleaned).length == 0) {
continue;
}
}
break;
case 'undefined':
continue;
}
result[key] = value;
}
return result;
}
}
exports.Response = Response;
//# sourceMappingURL=Response.js.map