@webgpt/sdk
Version:
WebGPT SDK is a TypeScript / JavaScript library for interacting with the WebGPT API.
296 lines (280 loc) • 12.6 kB
JavaScript
import { countCharacters, countWords } from '@promptbook/utils';
import { BehaviorSubject } from 'rxjs';
import { io } from 'socket.io-client';
import { spaceTrim } from 'spacetrim';
import { v4 } from 'uuid';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
/**
* This error indicates that idea is not good enough to be accepted.
*/
var IdeaNotAccepted = /** @class */ (function (_super) {
__extends(IdeaNotAccepted, _super);
function IdeaNotAccepted(message) {
var _this = _super.call(this, message) || this;
_this.name = 'NotFoundError';
Object.setPrototypeOf(_this, IdeaNotAccepted.prototype);
return _this;
}
return IdeaNotAccepted;
}(Error));
/**
* This error indicates SDK can not communicate with the remote server.
*/
var TimeoutError = /** @class */ (function (_super) {
__extends(TimeoutError, _super);
function TimeoutError(message) {
var _this = _super.call(this, message) || this;
_this.name = 'TimeoutError';
Object.setPrototypeOf(_this, TimeoutError.prototype);
return _this;
}
return TimeoutError;
}(Error));
/**
* This error should never happen.
* If it happens, it's a bug in the SDK.
*/
var UnexpectedError = /** @class */ (function (_super) {
__extends(UnexpectedError, _super);
function UnexpectedError(message) {
var _this = _super.call(this, message) || this;
_this.name = 'UnexpectedError';
Object.setPrototypeOf(_this, UnexpectedError.prototype);
return _this;
}
return UnexpectedError;
}(Error));
/**
* !!!
*/
function observableToPromise(observable) {
return new Promise(function (resolve, reject) {
var isLastValueSet = false;
var lastValue;
var subscription = observable.subscribe({
next: function (value) {
isLastValueSet = true;
lastValue = value;
},
complete: function () {
if (observable instanceof BehaviorSubject) {
resolve(observable.value);
return;
}
if (!isLastValueSet) {
reject(new UnexpectedError('Observable completed without emitting any value'));
return;
}
resolve(lastValue);
},
error: function (error) {
reject(error);
},
});
return function () { return subscription.unsubscribe(); };
});
}
/**
* Generates random UUID v4
*
* Warning: This function is cryptographically secure (it uses uuid library internally)
*
* @returns uuid branded type
*/
function $randomUuid() {
return v4();
}
var WebgptSdk = /** @class */ (function () {
function WebgptSdk(options) {
this.options = __assign({ remoteUrl: 'https://sdk.webgpt.cz/', path: '/sdk/socket.io' }, options);
}
/**
* Creates a connection to the remote proxy server.
*/
WebgptSdk.prototype.makeConnection = function () {
var _this = this;
return new Promise(function (resolve, reject) {
var socket = io(_this.options.remoteUrl, {
path: _this.options.path,
transports: [/*'websocket', <- TODO: [🌬] Make websocket transport work */ 'polling'],
});
socket.on('connect', function () {
resolve(socket);
});
setTimeout(function () {
reject(new TimeoutError(spaceTrim("\n\n Timeout while connecting to WebGPT SDK server.\n\n - Please, check your internet connection and try again.\n - Make sure that remoteUrl is correct\n It is set to: ".concat(_this.options.remoteUrl, "\n Try to look at \u2191\n\n\n "))));
}, 2000 /* <- TODO: Timeout to config */);
});
};
/**
* Creates a new assignment based on the idea.
*
* @throws {IdeaNotAccepted} If the idea is not good enough
*/
WebgptSdk.prototype.makeAssignment = function (options) {
var _this = this;
var _a = options.id, id = _a === void 0 ? $randomUuid() : _a, idea = options.idea, language = options.language;
if (countCharacters(idea) < 10 || countWords(idea) < 2) {
throw new IdeaNotAccepted('Idea is too short');
}
var subject = new BehaviorSubject({
status: 'RUNNING',
message: 'Creating assignment...',
});
(function () { return __awaiter(_this, void 0, void 0, function () {
var socket;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.makeConnection()];
case 1:
socket = _a.sent();
socket.emit('request', {
apiKey: this.options.apiKey,
sdkVersion: /*version*/ '!!!!',
id: id,
type: 'REQUEST',
taskName: 'MAKE_ASSIGNMENT',
idea: idea,
language: language,
});
socket.on('response', function (response) {
if (id !== response.id) {
return;
}
// TODO: [💢] Maybe no need to check this
if (response.taskName !== 'MAKE_ASSIGNMENT') {
return subject.error(new UnexpectedError("Expected taskName to be 'MAKE_ASSIGNMENT' but got ".concat(response.taskName)));
}
subject.next({
status: 'SUCCESS',
message: response.message,
assignment: response.assignment,
});
subject.complete();
socket.disconnect();
});
socket.on('progress', function (response) {
if (id !== response.id) {
return;
}
// TODO: [💢] Maybe no need to check this
if (response.taskName !== 'MAKE_ASSIGNMENT') {
return subject.error(new UnexpectedError("Expected taskName to be 'MAKE_ASSIGNMENT' but got ".concat(response.taskName)));
}
subject.next(response);
});
socket.on('error', function (error) {
if (id !== error.id) {
return;
}
var errorObject = new Error(error.message);
errorObject.name = error.errorName;
subject.error(errorObject);
// TODO: [🧠] Should we disconnect and close here?
subject.complete();
socket.disconnect();
});
return [2 /*return*/];
}
});
}); })();
return {
id: id,
asObservable: function () {
return subject;
},
asPromise: function () {
return observableToPromise(subject);
},
};
};
/**
* Connects to the existing task based on id
*/
WebgptSdk.prototype.recoverAssignmentMaking = function (id) {
throw new Error('Not implemented yet');
};
WebgptSdk.prototype.makeWebsite = function (options) {
throw new Error('Not implemented yet');
};
WebgptSdk.prototype.recoverWebsiteMaking = function (id) {
throw new Error('Not implemented yet');
};
return WebgptSdk;
}());
/**
* TODO: !!! Annotate all (+with @throws)
*/
export { WebgptSdk };
//# sourceMappingURL=index.es.js.map