@promptbook/editable 0.82.0-3 → 0.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/esm/index.es.js +3744 -322
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/editable.index.d.ts +74 -0
- package/esm/typings/src/_packages/types.index.d.ts +26 -0
- package/esm/typings/src/commands/BOOK_VERSION/BookVersionCommand.d.ts +1 -1
- package/esm/typings/src/commands/BOOK_VERSION/bookVersionCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/FOREACH/ForeachCommand.d.ts +1 -1
- package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/FORMAT/formatCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/FORMFACTOR/FormfactorCommand.d.ts +1 -1
- package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/JOKER/JokerCommand.d.ts +1 -1
- package/esm/typings/src/commands/JOKER/jokerCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/KNOWLEDGE/KnowledgeCommand.d.ts +2 -2
- package/esm/typings/src/commands/KNOWLEDGE/knowledgeCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/KNOWLEDGE/utils/{sourceContentToName.d.ts → knowledgeSourceContentToName.d.ts} +2 -2
- package/esm/typings/src/commands/MODEL/ModelCommand.d.ts +2 -1
- package/esm/typings/src/commands/MODEL/modelCommandParser.d.ts +2 -1
- package/esm/typings/src/commands/PARAMETER/ParameterCommand.d.ts +1 -1
- package/esm/typings/src/commands/PARAMETER/parameterCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/PERSONA/PersonaCommand.d.ts +1 -1
- package/esm/typings/src/commands/PERSONA/personaCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/POSTPROCESS/PostprocessCommand.d.ts +1 -1
- package/esm/typings/src/commands/POSTPROCESS/postprocessCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/SECTION/SectionCommand.d.ts +1 -1
- package/esm/typings/src/commands/SECTION/sectionCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/URL/UrlCommand.d.ts +1 -1
- package/esm/typings/src/commands/URL/urlCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/X_ACTION/ActionCommand.d.ts +1 -1
- package/esm/typings/src/commands/X_ACTION/actionCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/X_INSTRUMENT/InstrumentCommand.d.ts +1 -1
- package/esm/typings/src/commands/X_INSTRUMENT/instrumentCommandParser.d.ts +1 -1
- package/esm/typings/src/commands/_common/getParserForCommand.d.ts +1 -1
- package/esm/typings/src/commands/_common/parseCommand.d.ts +1 -1
- package/esm/typings/src/commands/_common/stringifyCommand.d.ts +1 -0
- package/esm/typings/src/commands/_common/types/CommandParser.d.ts +8 -0
- package/esm/typings/src/commands/_common/types/CommandUsagePlaces.d.ts +2 -0
- package/esm/typings/src/commands/index.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineJson/KnowledgeSourceJson.d.ts +1 -1
- package/package.json +4 -2
- package/umd/index.umd.js +3764 -325
- package/umd/index.umd.js.map +1 -1
- /package/esm/typings/src/commands/KNOWLEDGE/utils/{sourceContentToName.test.d.ts → knowledgeSourceContentToName.test.d.ts} +0 -0
package/esm/index.es.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
2
|
+
import { unparse, parse } from 'papaparse';
|
|
3
|
+
import { SHA256 } from 'crypto-js';
|
|
4
|
+
import hexEncoder from 'crypto-js/enc-hex';
|
|
2
5
|
|
|
3
6
|
// ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
|
|
4
7
|
/**
|
|
@@ -14,7 +17,7 @@ var BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
14
17
|
* @generated
|
|
15
18
|
* @see https://github.com/webgptorg/promptbook
|
|
16
19
|
*/
|
|
17
|
-
var PROMPTBOOK_ENGINE_VERSION = '0.82.0
|
|
20
|
+
var PROMPTBOOK_ENGINE_VERSION = '0.82.0';
|
|
18
21
|
/**
|
|
19
22
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
20
23
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -62,6 +65,44 @@ var __assign = function() {
|
|
|
62
65
|
return __assign.apply(this, arguments);
|
|
63
66
|
};
|
|
64
67
|
|
|
68
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
69
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
70
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
71
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
72
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
73
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
74
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function __generator(thisArg, body) {
|
|
79
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
80
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
81
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
82
|
+
function step(op) {
|
|
83
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
84
|
+
while (_) try {
|
|
85
|
+
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;
|
|
86
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
87
|
+
switch (op[0]) {
|
|
88
|
+
case 0: case 1: t = op; break;
|
|
89
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
90
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
91
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
92
|
+
default:
|
|
93
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
94
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
95
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
96
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
97
|
+
if (t[2]) _.ops.pop();
|
|
98
|
+
_.trys.pop(); continue;
|
|
99
|
+
}
|
|
100
|
+
op = body.call(thisArg, _);
|
|
101
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
102
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
65
106
|
function __values(o) {
|
|
66
107
|
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
67
108
|
if (m) return m.call(o);
|
|
@@ -102,128 +143,23 @@ function __spreadArray(to, from, pack) {
|
|
|
102
143
|
}
|
|
103
144
|
|
|
104
145
|
/**
|
|
105
|
-
*
|
|
146
|
+
* Returns the same value that is passed as argument.
|
|
147
|
+
* No side effects.
|
|
106
148
|
*
|
|
107
|
-
*
|
|
108
|
-
*/
|
|
109
|
-
function removePipelineCommand(options) {
|
|
110
|
-
var e_1, _a;
|
|
111
|
-
var command = options.command, pipeline = options.pipeline;
|
|
112
|
-
var lines = pipeline.split('\n');
|
|
113
|
-
// TODO: [🧽] DRY
|
|
114
|
-
var currentType = 'MARKDOWN';
|
|
115
|
-
var newLines = [];
|
|
116
|
-
try {
|
|
117
|
-
for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
|
|
118
|
-
var line = lines_1_1.value;
|
|
119
|
-
if (currentType === 'MARKDOWN') {
|
|
120
|
-
if (line.startsWith('```')) {
|
|
121
|
-
currentType = 'CODE_BLOCK';
|
|
122
|
-
}
|
|
123
|
-
else if (line.includes('<!--')) {
|
|
124
|
-
currentType = 'COMMENT';
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
else if (currentType === 'CODE_BLOCK') {
|
|
128
|
-
if (line.startsWith('```')) {
|
|
129
|
-
currentType = 'MARKDOWN';
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
else if (currentType === 'COMMENT') {
|
|
133
|
-
if (line.includes('-->')) {
|
|
134
|
-
currentType = 'MARKDOWN';
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (currentType === 'MARKDOWN' && /^(-|\d\))/m.test(line) && line.toUpperCase().includes(command)) {
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
newLines.push(line);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
144
|
-
finally {
|
|
145
|
-
try {
|
|
146
|
-
if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
|
|
147
|
-
}
|
|
148
|
-
finally { if (e_1) throw e_1.error; }
|
|
149
|
-
}
|
|
150
|
-
var newPipeline = spaceTrim(newLines.join('\n'));
|
|
151
|
-
return newPipeline;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
|
|
149
|
+
* Note: It can be usefull for:
|
|
156
150
|
*
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
var PipelineLogicError = /** @class */ (function (_super) {
|
|
160
|
-
__extends(PipelineLogicError, _super);
|
|
161
|
-
function PipelineLogicError(message) {
|
|
162
|
-
var _this = _super.call(this, message) || this;
|
|
163
|
-
_this.name = 'PipelineLogicError';
|
|
164
|
-
Object.setPrototypeOf(_this, PipelineLogicError.prototype);
|
|
165
|
-
return _this;
|
|
166
|
-
}
|
|
167
|
-
return PipelineLogicError;
|
|
168
|
-
}(Error));
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Function `renamePipelineParameter` will find all usable parameters for given task
|
|
172
|
-
* In other words, it will find all parameters that are not used in the task itseld and all its dependencies
|
|
151
|
+
* 1) Leveling indentation
|
|
152
|
+
* 2) Putting always-true or always-false conditions without getting eslint errors
|
|
173
153
|
*
|
|
174
|
-
* @
|
|
175
|
-
* @
|
|
154
|
+
* @param value any values
|
|
155
|
+
* @returns the same values
|
|
156
|
+
* @private within the repository
|
|
176
157
|
*/
|
|
177
|
-
function
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (pipeline.parameters.some(function (parameter) { return parameter.name === newParameterName; })) {
|
|
181
|
-
throw new PipelineLogicError("Can not replace {".concat(oldParameterName, "} to {").concat(newParameterName, "} because {").concat(newParameterName, "} is already used in the pipeline"));
|
|
182
|
-
}
|
|
183
|
-
var renamedPipeline = __assign(__assign({}, pipeline), {
|
|
184
|
-
// <- TODO: [🪓] This should be without `as $PipelineJson`
|
|
185
|
-
parameters: __spreadArray([], __read(pipeline.parameters), false), tasks: __spreadArray([], __read(pipeline.tasks), false) });
|
|
186
|
-
try {
|
|
187
|
-
for (var _c = __values(renamedPipeline.parameters), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
188
|
-
var parameter = _d.value;
|
|
189
|
-
if (parameter.name !== oldParameterName) {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
parameter.name = newParameterName;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
196
|
-
finally {
|
|
197
|
-
try {
|
|
198
|
-
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
199
|
-
}
|
|
200
|
-
finally { if (e_1) throw e_1.error; }
|
|
201
|
-
}
|
|
202
|
-
try {
|
|
203
|
-
for (var _e = __values(renamedPipeline.tasks), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
204
|
-
var task = _f.value;
|
|
205
|
-
if (task.resultingParameterName === oldParameterName) {
|
|
206
|
-
task.resultingParameterName = newParameterName;
|
|
207
|
-
}
|
|
208
|
-
task.dependentParameterNames = task.dependentParameterNames.map(function (dependentParameterName) {
|
|
209
|
-
return dependentParameterName === oldParameterName ? newParameterName : dependentParameterName;
|
|
210
|
-
});
|
|
211
|
-
task.content = task.content.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
|
|
212
|
-
task.title = task.title.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
|
|
213
|
-
task.description =
|
|
214
|
-
task.description === undefined
|
|
215
|
-
? undefined
|
|
216
|
-
: task.description.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
220
|
-
finally {
|
|
221
|
-
try {
|
|
222
|
-
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
|
|
223
|
-
}
|
|
224
|
-
finally { if (e_2) throw e_2.error; }
|
|
158
|
+
function just(value) {
|
|
159
|
+
if (value === undefined) {
|
|
160
|
+
return undefined;
|
|
225
161
|
}
|
|
226
|
-
return
|
|
162
|
+
return value;
|
|
227
163
|
}
|
|
228
164
|
|
|
229
165
|
/**
|
|
@@ -270,56 +206,6 @@ Object.freeze({
|
|
|
270
206
|
* TODO: [🧠][🧜♂️] Maybe join remoteUrl and path into single value
|
|
271
207
|
*/
|
|
272
208
|
|
|
273
|
-
/**
|
|
274
|
-
* Orders JSON object by keys
|
|
275
|
-
*
|
|
276
|
-
* @returns The same type of object as the input re-ordered
|
|
277
|
-
* @public exported from `@promptbook/utils`
|
|
278
|
-
*/
|
|
279
|
-
function orderJson(options) {
|
|
280
|
-
var value = options.value, order = options.order;
|
|
281
|
-
var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
|
|
282
|
-
return orderedValue;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Freezes the given object and all its nested objects recursively
|
|
287
|
-
*
|
|
288
|
-
* Note: `$` is used to indicate that this function is not a pure function - it mutates given object
|
|
289
|
-
* Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
|
|
290
|
-
*
|
|
291
|
-
* @returns The same object as the input, but deeply frozen
|
|
292
|
-
* @public exported from `@promptbook/utils`
|
|
293
|
-
*/
|
|
294
|
-
function $deepFreeze(objectValue) {
|
|
295
|
-
var e_1, _a;
|
|
296
|
-
if (Array.isArray(objectValue)) {
|
|
297
|
-
return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
|
|
298
|
-
}
|
|
299
|
-
var propertyNames = Object.getOwnPropertyNames(objectValue);
|
|
300
|
-
try {
|
|
301
|
-
for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
|
|
302
|
-
var propertyName = propertyNames_1_1.value;
|
|
303
|
-
var value = objectValue[propertyName];
|
|
304
|
-
if (value && typeof value === 'object') {
|
|
305
|
-
$deepFreeze(value);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
310
|
-
finally {
|
|
311
|
-
try {
|
|
312
|
-
if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
|
|
313
|
-
}
|
|
314
|
-
finally { if (e_1) throw e_1.error; }
|
|
315
|
-
}
|
|
316
|
-
Object.freeze(objectValue);
|
|
317
|
-
return objectValue;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
321
|
-
*/
|
|
322
|
-
|
|
323
209
|
/**
|
|
324
210
|
* Make error report URL for the given error
|
|
325
211
|
*
|
|
@@ -355,216 +241,3752 @@ var UnexpectedError = /** @class */ (function (_super) {
|
|
|
355
241
|
}(Error));
|
|
356
242
|
|
|
357
243
|
/**
|
|
358
|
-
*
|
|
359
|
-
* If not, throws an UnexpectedError with a rich error message and tracking
|
|
244
|
+
* This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
|
|
360
245
|
*
|
|
361
|
-
*
|
|
362
|
-
* - `undefined` is not serializable
|
|
363
|
-
* - `NaN` is not serializable
|
|
364
|
-
* - Objects and arrays are serializable if all their properties are serializable
|
|
365
|
-
* - Functions are not serializable
|
|
366
|
-
* - Circular references are not serializable
|
|
367
|
-
* - `Date` objects are not serializable
|
|
368
|
-
* - `Map` and `Set` objects are not serializable
|
|
369
|
-
* - `RegExp` objects are not serializable
|
|
370
|
-
* - `Error` objects are not serializable
|
|
371
|
-
* - `Symbol` objects are not serializable
|
|
372
|
-
* - And much more...
|
|
373
|
-
*
|
|
374
|
-
* @throws UnexpectedError if the value is not serializable as JSON
|
|
375
|
-
* @public exported from `@promptbook/utils`
|
|
246
|
+
* @public exported from `@promptbook/core`
|
|
376
247
|
*/
|
|
377
|
-
function
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return;
|
|
248
|
+
var ParseError = /** @class */ (function (_super) {
|
|
249
|
+
__extends(ParseError, _super);
|
|
250
|
+
function ParseError(message) {
|
|
251
|
+
var _this = _super.call(this, message) || this;
|
|
252
|
+
_this.name = 'ParseError';
|
|
253
|
+
Object.setPrototypeOf(_this, ParseError.prototype);
|
|
254
|
+
return _this;
|
|
385
255
|
}
|
|
386
|
-
|
|
387
|
-
|
|
256
|
+
return ParseError;
|
|
257
|
+
}(Error));
|
|
258
|
+
/**
|
|
259
|
+
* TODO: Maybe split `ParseError` and `ApplyError`
|
|
260
|
+
*/
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Parses the boilerplate command
|
|
264
|
+
*
|
|
265
|
+
* Note: @@@ This command is used as boilerplate for new commands - it should NOT be used in any `.book.md` file
|
|
266
|
+
*
|
|
267
|
+
* @see `documentationUrl` for more details
|
|
268
|
+
* @private within the commands folder
|
|
269
|
+
*/
|
|
270
|
+
var boilerplateCommandParser = {
|
|
271
|
+
/**
|
|
272
|
+
* Name of the command
|
|
273
|
+
*/
|
|
274
|
+
name: 'BOILERPLATE',
|
|
275
|
+
/**
|
|
276
|
+
* Aliases for the BOILERPLATE command
|
|
277
|
+
*/
|
|
278
|
+
aliasNames: ['BP'],
|
|
279
|
+
/**
|
|
280
|
+
* BOILERPLATE command can be used in:
|
|
281
|
+
*/
|
|
282
|
+
isUsedInPipelineHead: true,
|
|
283
|
+
isUsedInPipelineTask: true,
|
|
284
|
+
/**
|
|
285
|
+
* Description of the BOILERPLATE command
|
|
286
|
+
*/
|
|
287
|
+
description: "@@",
|
|
288
|
+
/**
|
|
289
|
+
* Link to documentation
|
|
290
|
+
*/
|
|
291
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
292
|
+
/**
|
|
293
|
+
* Example usages of the BOILERPLATE command
|
|
294
|
+
*/
|
|
295
|
+
examples: ['BOILERPLATE foo', 'BOILERPLATE bar', 'BP foo', 'BP bar'],
|
|
296
|
+
/**
|
|
297
|
+
* Parses the BOILERPLATE command
|
|
298
|
+
*/
|
|
299
|
+
parse: function (input) {
|
|
300
|
+
var args = input.args;
|
|
301
|
+
if (args.length !== 1) {
|
|
302
|
+
throw new ParseError("BOILERPLATE command requires exactly one argument");
|
|
303
|
+
}
|
|
304
|
+
var value = args[0].toLowerCase();
|
|
305
|
+
if (value.includes('brr')) {
|
|
306
|
+
throw new ParseError("BOILERPLATE value can not contain brr");
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
type: 'BOILERPLATE',
|
|
310
|
+
value: value,
|
|
311
|
+
};
|
|
312
|
+
},
|
|
313
|
+
/**
|
|
314
|
+
* Apply the BOILERPLATE command to the `pipelineJson`
|
|
315
|
+
*
|
|
316
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
317
|
+
*/
|
|
318
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
319
|
+
throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
|
|
320
|
+
},
|
|
321
|
+
/**
|
|
322
|
+
* Apply the BOILERPLATE command to the `pipelineJson`
|
|
323
|
+
*
|
|
324
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
325
|
+
*/
|
|
326
|
+
$applyToTaskJson: function (command, $taskJson, $pipelineJson) {
|
|
327
|
+
throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
|
|
328
|
+
},
|
|
329
|
+
/**
|
|
330
|
+
* Converts the BOILERPLATE command back to string
|
|
331
|
+
*
|
|
332
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
333
|
+
*/
|
|
334
|
+
stringify: function (command) {
|
|
335
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
336
|
+
},
|
|
337
|
+
/**
|
|
338
|
+
* Reads the BOILERPLATE command from the `PipelineJson`
|
|
339
|
+
*
|
|
340
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
341
|
+
*/
|
|
342
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
343
|
+
throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
|
|
344
|
+
},
|
|
345
|
+
/**
|
|
346
|
+
* Reads the BOILERPLATE command from the `TaskJson`
|
|
347
|
+
*
|
|
348
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
349
|
+
*/
|
|
350
|
+
takeFromTaskJson: function ($taskJson) {
|
|
351
|
+
throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* This error type indicates that some part of the code is not implemented yet
|
|
357
|
+
*
|
|
358
|
+
* @public exported from `@promptbook/core`
|
|
359
|
+
*/
|
|
360
|
+
var NotYetImplementedError = /** @class */ (function (_super) {
|
|
361
|
+
__extends(NotYetImplementedError, _super);
|
|
362
|
+
function NotYetImplementedError(message) {
|
|
363
|
+
var _this = _super.call(this, spaceTrim$1(function (block) { return "\n ".concat(block(message), "\n\n Note: This feature is not implemented yet but it will be soon.\n\n If you want speed up the implementation or just read more, look here:\n https://github.com/webgptorg/promptbook\n\n Or contact us on me@pavolhejny.com\n\n "); })) || this;
|
|
364
|
+
_this.name = 'NotYetImplementedError';
|
|
365
|
+
Object.setPrototypeOf(_this, NotYetImplementedError.prototype);
|
|
366
|
+
return _this;
|
|
388
367
|
}
|
|
389
|
-
|
|
390
|
-
|
|
368
|
+
return NotYetImplementedError;
|
|
369
|
+
}(Error));
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Tests if given string is valid semantic version
|
|
373
|
+
*
|
|
374
|
+
* Note: There are two simmilar functions:
|
|
375
|
+
* - `isValidSemanticVersion` which tests any semantic version
|
|
376
|
+
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
377
|
+
*
|
|
378
|
+
* @public exported from `@promptbook/utils`
|
|
379
|
+
*/
|
|
380
|
+
function isValidSemanticVersion(version) {
|
|
381
|
+
if (typeof version !== 'string') {
|
|
382
|
+
return false;
|
|
391
383
|
}
|
|
392
|
-
|
|
393
|
-
return;
|
|
384
|
+
if (version.startsWith('0.0.0')) {
|
|
385
|
+
return false;
|
|
394
386
|
}
|
|
395
|
-
|
|
396
|
-
|
|
387
|
+
return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Tests if given string is valid promptbook version
|
|
392
|
+
* It looks into list of known promptbook versions.
|
|
393
|
+
*
|
|
394
|
+
* @see https://www.npmjs.com/package/promptbook?activeTab=versions
|
|
395
|
+
* Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
|
|
396
|
+
* Note: There are two simmilar functions:
|
|
397
|
+
* - `isValidSemanticVersion` which tests any semantic version
|
|
398
|
+
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
399
|
+
*
|
|
400
|
+
* @public exported from `@promptbook/utils`
|
|
401
|
+
*/
|
|
402
|
+
function isValidPromptbookVersion(version) {
|
|
403
|
+
if (!isValidSemanticVersion(version)) {
|
|
404
|
+
return false;
|
|
397
405
|
}
|
|
398
|
-
|
|
399
|
-
|
|
406
|
+
if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
|
|
407
|
+
return false;
|
|
400
408
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
409
|
+
// <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Parses the BOOK_VERSION command
|
|
415
|
+
*
|
|
416
|
+
* @see `documentationUrl` for more details
|
|
417
|
+
* @public exported from `@promptbook/editable`
|
|
418
|
+
*/
|
|
419
|
+
var bookVersionCommandParser = {
|
|
420
|
+
/**
|
|
421
|
+
* Name of the command
|
|
422
|
+
*/
|
|
423
|
+
name: 'BOOK_VERSION',
|
|
424
|
+
aliasNames: ['PTBK_VERSION', 'PROMPTBOOK_VERSION', 'BOOK'],
|
|
425
|
+
/**
|
|
426
|
+
* BOILERPLATE command can be used in:
|
|
427
|
+
*/
|
|
428
|
+
isUsedInPipelineHead: true,
|
|
429
|
+
isUsedInPipelineTask: false,
|
|
430
|
+
/**
|
|
431
|
+
* Description of the BOOK_VERSION command
|
|
432
|
+
*/
|
|
433
|
+
description: "Which version of the Book language is the .book.md using",
|
|
434
|
+
/**
|
|
435
|
+
* Link to documentation
|
|
436
|
+
*/
|
|
437
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/69',
|
|
438
|
+
/**
|
|
439
|
+
* Example usages of the BOOK_VERSION command
|
|
440
|
+
*/
|
|
441
|
+
examples: ["BOOK VERSION ".concat(BOOK_LANGUAGE_VERSION), "BOOK ".concat(BOOK_LANGUAGE_VERSION)],
|
|
442
|
+
/**
|
|
443
|
+
* Parses the BOOK_VERSION command
|
|
444
|
+
*/
|
|
445
|
+
parse: function (input) {
|
|
446
|
+
var args = input.args;
|
|
447
|
+
var bookVersion = args.pop();
|
|
448
|
+
if (bookVersion === undefined) {
|
|
449
|
+
throw new ParseError("Version is required");
|
|
404
450
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (value instanceof Date) {
|
|
408
|
-
throw new UnexpectedError(spaceTrim(function (block) { return "\n `".concat(name, "` is Date\n\n Use `string_date_iso8601` instead\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
451
|
+
if (!isValidPromptbookVersion(bookVersion)) {
|
|
452
|
+
throw new ParseError("Invalid Promptbook version \"".concat(bookVersion, "\""));
|
|
409
453
|
}
|
|
410
|
-
|
|
411
|
-
throw new
|
|
412
|
-
}
|
|
413
|
-
else if (value instanceof Set) {
|
|
414
|
-
throw new UnexpectedError("".concat(name, " is Set"));
|
|
454
|
+
if (args.length > 0 && !(((args.length === 1 && args[0]) || '').toUpperCase() === 'VERSION')) {
|
|
455
|
+
throw new ParseError("Can not have more than one Promptbook version");
|
|
415
456
|
}
|
|
416
|
-
|
|
417
|
-
|
|
457
|
+
return {
|
|
458
|
+
type: 'BOOK_VERSION',
|
|
459
|
+
bookVersion: bookVersion,
|
|
460
|
+
};
|
|
461
|
+
},
|
|
462
|
+
/**
|
|
463
|
+
* Apply the BOOK_VERSION command to the `pipelineJson`
|
|
464
|
+
*
|
|
465
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
466
|
+
*/
|
|
467
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
468
|
+
// TODO: Warn if the version is overridden
|
|
469
|
+
$pipelineJson.bookVersion = command.bookVersion;
|
|
470
|
+
},
|
|
471
|
+
/**
|
|
472
|
+
* Converts the BOOK_VERSION command back to string
|
|
473
|
+
*
|
|
474
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
475
|
+
*/
|
|
476
|
+
stringify: function (command) {
|
|
477
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
478
|
+
},
|
|
479
|
+
/**
|
|
480
|
+
* Reads the BOOK_VERSION command from the `PipelineJson`
|
|
481
|
+
*
|
|
482
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
483
|
+
*/
|
|
484
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
485
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Units of text measurement
|
|
491
|
+
*
|
|
492
|
+
* @see https://github.com/webgptorg/promptbook/discussions/30
|
|
493
|
+
* @public exported from `@promptbook/core`
|
|
494
|
+
*/
|
|
495
|
+
var EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'LINES', 'PARAGRAPHS', 'PAGES'];
|
|
496
|
+
/**
|
|
497
|
+
* TODO: [💝] Unite object for expecting amount and format - remove format
|
|
498
|
+
*/
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Function parseNumber will parse number from string
|
|
502
|
+
*
|
|
503
|
+
* Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
|
|
504
|
+
* Note: it also works only with decimal numbers
|
|
505
|
+
*
|
|
506
|
+
* @returns parsed number
|
|
507
|
+
* @throws {ParseError} if the value is not a number
|
|
508
|
+
*
|
|
509
|
+
* @public exported from `@promptbook/utils`
|
|
510
|
+
*/
|
|
511
|
+
function parseNumber(value) {
|
|
512
|
+
var originalValue = value;
|
|
513
|
+
if (typeof value === 'number') {
|
|
514
|
+
value = value.toString(); // <- TODO: Maybe more efficient way to do this
|
|
515
|
+
}
|
|
516
|
+
if (typeof value !== 'string') {
|
|
517
|
+
return 0;
|
|
518
|
+
}
|
|
519
|
+
value = value.trim();
|
|
520
|
+
if (value.startsWith('+')) {
|
|
521
|
+
return parseNumber(value.substring(1));
|
|
522
|
+
}
|
|
523
|
+
if (value.startsWith('-')) {
|
|
524
|
+
var number = parseNumber(value.substring(1));
|
|
525
|
+
if (number === 0) {
|
|
526
|
+
return 0; // <- Note: To prevent -0
|
|
418
527
|
}
|
|
419
|
-
|
|
420
|
-
|
|
528
|
+
return -number;
|
|
529
|
+
}
|
|
530
|
+
value = value.replace(/,/g, '.');
|
|
531
|
+
value = value.toUpperCase();
|
|
532
|
+
if (value === '') {
|
|
533
|
+
return 0;
|
|
534
|
+
}
|
|
535
|
+
if (value === '♾' || value.startsWith('INF')) {
|
|
536
|
+
return Infinity;
|
|
537
|
+
}
|
|
538
|
+
if (value.includes('/')) {
|
|
539
|
+
var _a = __read(value.split('/'), 2), numerator_ = _a[0], denominator_ = _a[1];
|
|
540
|
+
var numerator = parseNumber(numerator_);
|
|
541
|
+
var denominator = parseNumber(denominator_);
|
|
542
|
+
if (denominator === 0) {
|
|
543
|
+
throw new ParseError("Unable to parse number from \"".concat(originalValue, "\" because denominator is zero"));
|
|
421
544
|
}
|
|
422
|
-
|
|
545
|
+
return numerator / denominator;
|
|
546
|
+
}
|
|
547
|
+
if (/^(NAN|NULL|NONE|UNDEFINED|ZERO|NO.*)$/.test(value)) {
|
|
548
|
+
return 0;
|
|
549
|
+
}
|
|
550
|
+
if (value.includes('E')) {
|
|
551
|
+
var _b = __read(value.split('E'), 2), significand = _b[0], exponent = _b[1];
|
|
552
|
+
return parseNumber(significand) * Math.pow(10, parseNumber(exponent));
|
|
553
|
+
}
|
|
554
|
+
if (!/^[0-9.]+$/.test(value) || value.split('.').length > 2) {
|
|
555
|
+
throw new ParseError("Unable to parse number from \"".concat(originalValue, "\""));
|
|
556
|
+
}
|
|
557
|
+
var num = parseFloat(value);
|
|
558
|
+
if (isNaN(num)) {
|
|
559
|
+
throw new ParseError("Unexpected NaN when parsing number from \"".concat(originalValue, "\""));
|
|
560
|
+
}
|
|
561
|
+
return num;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* TODO: Maybe use sth. like safe-eval in fraction/calculation case @see https://www.npmjs.com/package/safe-eval
|
|
565
|
+
* TODO: [🧠][🌻] Maybe export through `@promptbook/markdown-utils` not `@promptbook/utils`
|
|
566
|
+
*/
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Parses the expect command
|
|
570
|
+
*
|
|
571
|
+
* @see `documentationUrl` for more details
|
|
572
|
+
* @public exported from `@promptbook/editable`
|
|
573
|
+
*/
|
|
574
|
+
var expectCommandParser = {
|
|
575
|
+
/**
|
|
576
|
+
* Name of the command
|
|
577
|
+
*/
|
|
578
|
+
name: 'EXPECT',
|
|
579
|
+
/**
|
|
580
|
+
* BOILERPLATE command can be used in:
|
|
581
|
+
*/
|
|
582
|
+
isUsedInPipelineHead: false,
|
|
583
|
+
isUsedInPipelineTask: true,
|
|
584
|
+
/**
|
|
585
|
+
* Description of the FORMAT command
|
|
586
|
+
*/
|
|
587
|
+
description: spaceTrim("\n Expect command describes the desired output of the task *(after post-processing)*\n It can set limits for the maximum/minimum length of the output, measured in characters, words, sentences, paragraphs or some other shape of the output.\n "),
|
|
588
|
+
/**
|
|
589
|
+
* Link to documentation
|
|
590
|
+
*/
|
|
591
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/30',
|
|
592
|
+
/**
|
|
593
|
+
* Example usages of the FORMAT command
|
|
594
|
+
*/
|
|
595
|
+
examples: [
|
|
596
|
+
'EXPECT MIN 100 Characters',
|
|
597
|
+
'EXPECT MAX 10 Words',
|
|
598
|
+
'EXPECT EXACTLY 3 Sentences',
|
|
599
|
+
'EXPECT EXACTLY 1 Paragraph',
|
|
600
|
+
// <- TODO: 'EXPECT 1 Paragraph',
|
|
601
|
+
],
|
|
602
|
+
/**
|
|
603
|
+
* Parses the FORMAT command
|
|
604
|
+
*/
|
|
605
|
+
parse: function (input) {
|
|
606
|
+
var e_1, _a;
|
|
607
|
+
var args = input.args;
|
|
608
|
+
try {
|
|
609
|
+
var sign = void 0;
|
|
610
|
+
var signRaw = args.shift();
|
|
611
|
+
if (/^exact/i.test(signRaw)) {
|
|
612
|
+
sign = 'EXACTLY';
|
|
613
|
+
}
|
|
614
|
+
else if (/^min/i.test(signRaw)) {
|
|
615
|
+
sign = 'MINIMUM';
|
|
616
|
+
}
|
|
617
|
+
else if (/^max/i.test(signRaw)) {
|
|
618
|
+
sign = 'MAXIMUM';
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
throw new ParseError("Invalid sign \"".concat(signRaw, "\", expected EXACTLY, MIN or MAX"));
|
|
622
|
+
}
|
|
623
|
+
var amountRaw = args.shift();
|
|
624
|
+
var amount = parseNumber(amountRaw);
|
|
625
|
+
if (amount < 0) {
|
|
626
|
+
throw new ParseError('Amount must be positive number or zero');
|
|
627
|
+
}
|
|
628
|
+
if (amount !== Math.floor(amount)) {
|
|
629
|
+
throw new ParseError('Amount must be whole number');
|
|
630
|
+
}
|
|
631
|
+
var unitRaw = args.shift();
|
|
632
|
+
var unit = undefined;
|
|
423
633
|
try {
|
|
424
|
-
for (var
|
|
425
|
-
var
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
634
|
+
for (var EXPECTATION_UNITS_1 = __values(EXPECTATION_UNITS), EXPECTATION_UNITS_1_1 = EXPECTATION_UNITS_1.next(); !EXPECTATION_UNITS_1_1.done; EXPECTATION_UNITS_1_1 = EXPECTATION_UNITS_1.next()) {
|
|
635
|
+
var existingUnit = EXPECTATION_UNITS_1_1.value;
|
|
636
|
+
var existingUnitText = existingUnit;
|
|
637
|
+
existingUnitText = existingUnitText.substring(0, existingUnitText.length - 1);
|
|
638
|
+
if (existingUnitText === 'CHARACTER') {
|
|
639
|
+
existingUnitText = 'CHAR';
|
|
640
|
+
}
|
|
641
|
+
if (new RegExp("^".concat(existingUnitText.toLowerCase())).test(unitRaw.toLowerCase()) ||
|
|
642
|
+
new RegExp("^".concat(unitRaw.toLowerCase())).test(existingUnitText.toLowerCase())) {
|
|
643
|
+
if (unit !== undefined) {
|
|
644
|
+
throw new ParseError("Ambiguous unit \"".concat(unitRaw, "\""));
|
|
645
|
+
}
|
|
646
|
+
unit = existingUnit;
|
|
429
647
|
}
|
|
430
|
-
checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
|
|
431
648
|
}
|
|
432
649
|
}
|
|
433
650
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
434
651
|
finally {
|
|
435
652
|
try {
|
|
436
|
-
if (
|
|
653
|
+
if (EXPECTATION_UNITS_1_1 && !EXPECTATION_UNITS_1_1.done && (_a = EXPECTATION_UNITS_1.return)) _a.call(EXPECTATION_UNITS_1);
|
|
437
654
|
}
|
|
438
655
|
finally { if (e_1) throw e_1.error; }
|
|
439
656
|
}
|
|
440
|
-
|
|
441
|
-
|
|
657
|
+
if (unit === undefined) {
|
|
658
|
+
throw new ParseError("Invalid unit \"".concat(unitRaw, "\""));
|
|
442
659
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
660
|
+
return {
|
|
661
|
+
type: 'EXPECT',
|
|
662
|
+
sign: sign,
|
|
663
|
+
unit: unit,
|
|
664
|
+
amount: amount,
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
if (!(error instanceof Error)) {
|
|
669
|
+
throw error;
|
|
448
670
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
671
|
+
throw new ParseError(spaceTrim(function (block) {
|
|
672
|
+
return "\n Invalid FORMAT command\n ".concat(block(error.message), ":\n ");
|
|
673
|
+
}));
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
/**
|
|
677
|
+
* Apply the FORMAT command to the `pipelineJson`
|
|
678
|
+
*
|
|
679
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
680
|
+
*/
|
|
681
|
+
$applyToTaskJson: function (command, $taskJson) {
|
|
682
|
+
// eslint-disable-next-line no-case-declarations
|
|
683
|
+
var unit = command.unit.toLowerCase();
|
|
684
|
+
$taskJson.expectations = $taskJson.expectations || {};
|
|
685
|
+
$taskJson.expectations[unit] = $taskJson.expectations[unit] || {};
|
|
686
|
+
if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
|
|
687
|
+
if ($taskJson.expectations[unit].min !== undefined) {
|
|
688
|
+
throw new ParseError("Already defined minumum ".concat($taskJson.expectations[unit].min, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
|
|
466
689
|
}
|
|
467
|
-
|
|
468
|
-
|
|
690
|
+
$taskJson.expectations[unit].min = command.amount;
|
|
691
|
+
} /* not else */
|
|
692
|
+
if (command.sign === 'MAXIMUM' || command.sign === 'EXACTLY') {
|
|
693
|
+
if ($taskJson.expectations[unit].max !== undefined) {
|
|
694
|
+
throw new ParseError("Already defined maximum ".concat($taskJson.expectations[unit].max, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
|
|
695
|
+
}
|
|
696
|
+
$taskJson.expectations[unit].max = command.amount;
|
|
469
697
|
}
|
|
698
|
+
},
|
|
699
|
+
/**
|
|
700
|
+
* Converts the FORMAT command back to string
|
|
701
|
+
*
|
|
702
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
703
|
+
*/
|
|
704
|
+
stringify: function (command) {
|
|
705
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
706
|
+
},
|
|
707
|
+
/**
|
|
708
|
+
* Reads the FORMAT command from the `TaskJson`
|
|
709
|
+
*
|
|
710
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
711
|
+
*/
|
|
712
|
+
takeFromTaskJson: function ($taskJson) {
|
|
713
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
714
|
+
},
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* This error indicates problems parsing the format value
|
|
719
|
+
*
|
|
720
|
+
* For example, when the format value is not a valid JSON or CSV
|
|
721
|
+
* This is not thrown directly but in extended classes
|
|
722
|
+
*
|
|
723
|
+
* @public exported from `@promptbook/core`
|
|
724
|
+
*/
|
|
725
|
+
var AbstractFormatError = /** @class */ (function (_super) {
|
|
726
|
+
__extends(AbstractFormatError, _super);
|
|
727
|
+
// Note: To allow instanceof do not put here error `name`
|
|
728
|
+
// public readonly name = 'AbstractFormatError';
|
|
729
|
+
function AbstractFormatError(message) {
|
|
730
|
+
var _this = _super.call(this, message) || this;
|
|
731
|
+
Object.setPrototypeOf(_this, AbstractFormatError.prototype);
|
|
732
|
+
return _this;
|
|
470
733
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
734
|
+
return AbstractFormatError;
|
|
735
|
+
}(Error));
|
|
736
|
+
|
|
475
737
|
/**
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
738
|
+
* This error indicates problem with parsing of CSV
|
|
739
|
+
*
|
|
740
|
+
* @public exported from `@promptbook/core`
|
|
479
741
|
*/
|
|
742
|
+
var CsvFormatError = /** @class */ (function (_super) {
|
|
743
|
+
__extends(CsvFormatError, _super);
|
|
744
|
+
function CsvFormatError(message) {
|
|
745
|
+
var _this = _super.call(this, message) || this;
|
|
746
|
+
_this.name = 'CsvFormatError';
|
|
747
|
+
Object.setPrototypeOf(_this, CsvFormatError.prototype);
|
|
748
|
+
return _this;
|
|
749
|
+
}
|
|
750
|
+
return CsvFormatError;
|
|
751
|
+
}(AbstractFormatError));
|
|
480
752
|
|
|
481
753
|
/**
|
|
482
754
|
* @@@
|
|
483
755
|
*
|
|
756
|
+
* @public exported from `@promptbook/core`
|
|
757
|
+
*/
|
|
758
|
+
var MANDATORY_CSV_SETTINGS = Object.freeze({
|
|
759
|
+
header: true,
|
|
760
|
+
// encoding: 'utf-8',
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Definition for CSV spreadsheet
|
|
765
|
+
*
|
|
766
|
+
* @public exported from `@promptbook/core`
|
|
767
|
+
* <- TODO: [🏢] Export from package `@promptbook/csv`
|
|
768
|
+
*/
|
|
769
|
+
var CsvFormatDefinition = {
|
|
770
|
+
formatName: 'CSV',
|
|
771
|
+
aliases: ['SPREADSHEET', 'TABLE'],
|
|
772
|
+
isValid: function (value, settings, schema) {
|
|
773
|
+
return true;
|
|
774
|
+
},
|
|
775
|
+
canBeValid: function (partialValue, settings, schema) {
|
|
776
|
+
return true;
|
|
777
|
+
},
|
|
778
|
+
heal: function (value, settings, schema) {
|
|
779
|
+
throw new Error('Not implemented');
|
|
780
|
+
},
|
|
781
|
+
subvalueDefinitions: [
|
|
782
|
+
{
|
|
783
|
+
subvalueName: 'ROW',
|
|
784
|
+
mapValues: function (value, outputParameterName, settings, mapCallback) {
|
|
785
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
786
|
+
var csv, mappedData;
|
|
787
|
+
var _this = this;
|
|
788
|
+
return __generator(this, function (_a) {
|
|
789
|
+
switch (_a.label) {
|
|
790
|
+
case 0:
|
|
791
|
+
csv = parse(value, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS));
|
|
792
|
+
if (csv.errors.length !== 0) {
|
|
793
|
+
throw new CsvFormatError(spaceTrim(function (block) { return "\n CSV parsing error\n\n Error(s) from CSV parsing:\n ".concat(block(csv.errors.map(function (error) { return error.message; }).join('\n\n')), "\n\n The CSV setings:\n ").concat(block(JSON.stringify(__assign(__assign({}, settings), MANDATORY_CSV_SETTINGS), null, 2)), "\n\n The CSV data:\n ").concat(block(value), "\n "); }));
|
|
794
|
+
}
|
|
795
|
+
return [4 /*yield*/, Promise.all(csv.data.map(function (row, index) { return __awaiter(_this, void 0, void 0, function () {
|
|
796
|
+
var _a, _b;
|
|
797
|
+
var _c;
|
|
798
|
+
return __generator(this, function (_d) {
|
|
799
|
+
switch (_d.label) {
|
|
800
|
+
case 0:
|
|
801
|
+
if (row[outputParameterName]) {
|
|
802
|
+
throw new CsvFormatError("Can not overwrite existing column \"".concat(outputParameterName, "\" in CSV row"));
|
|
803
|
+
}
|
|
804
|
+
_a = [__assign({}, row)];
|
|
805
|
+
_c = {};
|
|
806
|
+
_b = outputParameterName;
|
|
807
|
+
return [4 /*yield*/, mapCallback(row, index)];
|
|
808
|
+
case 1: return [2 /*return*/, __assign.apply(void 0, _a.concat([(_c[_b] = _d.sent(), _c)]))];
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
}); }))];
|
|
812
|
+
case 1:
|
|
813
|
+
mappedData = _a.sent();
|
|
814
|
+
return [2 /*return*/, unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
},
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
subvalueName: 'CELL',
|
|
822
|
+
mapValues: function (value, outputParameterName, settings, mapCallback) {
|
|
823
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
824
|
+
var csv, mappedData;
|
|
825
|
+
var _this = this;
|
|
826
|
+
return __generator(this, function (_a) {
|
|
827
|
+
switch (_a.label) {
|
|
828
|
+
case 0:
|
|
829
|
+
csv = parse(value, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS));
|
|
830
|
+
if (csv.errors.length !== 0) {
|
|
831
|
+
throw new CsvFormatError(spaceTrim(function (block) { return "\n CSV parsing error\n\n Error(s) from CSV parsing:\n ".concat(block(csv.errors.map(function (error) { return error.message; }).join('\n\n')), "\n\n The CSV setings:\n ").concat(block(JSON.stringify(__assign(__assign({}, settings), MANDATORY_CSV_SETTINGS), null, 2)), "\n\n The CSV data:\n ").concat(block(value), "\n "); }));
|
|
832
|
+
}
|
|
833
|
+
return [4 /*yield*/, Promise.all(csv.data.map(function (row, rowIndex) { return __awaiter(_this, void 0, void 0, function () {
|
|
834
|
+
var _this = this;
|
|
835
|
+
return __generator(this, function (_a) {
|
|
836
|
+
return [2 /*return*/, /* not await */ Promise.all(Object.entries(row).map(function (_a, columnIndex) {
|
|
837
|
+
var _b = __read(_a, 2), key = _b[0], value = _b[1];
|
|
838
|
+
return __awaiter(_this, void 0, void 0, function () {
|
|
839
|
+
var index;
|
|
840
|
+
var _c;
|
|
841
|
+
return __generator(this, function (_d) {
|
|
842
|
+
index = rowIndex * Object.keys(row).length + columnIndex;
|
|
843
|
+
return [2 /*return*/, /* not await */ mapCallback((_c = {}, _c[key] = value, _c), index)];
|
|
844
|
+
});
|
|
845
|
+
});
|
|
846
|
+
}))];
|
|
847
|
+
});
|
|
848
|
+
}); }))];
|
|
849
|
+
case 1:
|
|
850
|
+
mappedData = _a.sent();
|
|
851
|
+
return [2 /*return*/, unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
},
|
|
856
|
+
},
|
|
857
|
+
],
|
|
858
|
+
};
|
|
859
|
+
/**
|
|
860
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
|
|
861
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
|
|
862
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement `heal
|
|
863
|
+
* TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
|
|
864
|
+
* TODO: [🏢] Allow to expect something inside CSV objects and other formats
|
|
865
|
+
*/
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
869
|
+
*
|
|
484
870
|
* @public exported from `@promptbook/utils`
|
|
485
871
|
*/
|
|
486
|
-
function
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
872
|
+
function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
873
|
+
try {
|
|
874
|
+
JSON.parse(value);
|
|
875
|
+
return true;
|
|
876
|
+
}
|
|
877
|
+
catch (error) {
|
|
878
|
+
if (!(error instanceof Error)) {
|
|
879
|
+
throw error;
|
|
880
|
+
}
|
|
881
|
+
if (error.message.includes('Unexpected token')) {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
return false;
|
|
885
|
+
}
|
|
499
886
|
}
|
|
887
|
+
|
|
500
888
|
/**
|
|
501
|
-
*
|
|
889
|
+
* Definition for JSON format
|
|
890
|
+
*
|
|
891
|
+
* @private still in development [🏢]
|
|
892
|
+
*/
|
|
893
|
+
var JsonFormatDefinition = {
|
|
894
|
+
formatName: 'JSON',
|
|
895
|
+
mimeType: 'application/json',
|
|
896
|
+
isValid: function (value, settings, schema) {
|
|
897
|
+
return isValidJsonString(value);
|
|
898
|
+
},
|
|
899
|
+
canBeValid: function (partialValue, settings, schema) {
|
|
900
|
+
return true;
|
|
901
|
+
},
|
|
902
|
+
heal: function (value, settings, schema) {
|
|
903
|
+
throw new Error('Not implemented');
|
|
904
|
+
},
|
|
905
|
+
subvalueDefinitions: [],
|
|
906
|
+
};
|
|
907
|
+
/**
|
|
908
|
+
* TODO: [🧠] Maybe propper instance of object
|
|
909
|
+
* TODO: [0] Make string_serialized_json
|
|
910
|
+
* TODO: [1] Make type for JSON Settings and Schema
|
|
911
|
+
* TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
|
|
912
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement simple `isValid`
|
|
913
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement partial `canBeValid`
|
|
914
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement `heal
|
|
915
|
+
* TODO: [🍓] In `JsonFormatDefinition` implement `subvalueDefinitions`
|
|
916
|
+
* TODO: [🏢] Allow to expect something inside JSON objects and other formats
|
|
502
917
|
*/
|
|
503
918
|
|
|
504
919
|
/**
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
* 1) Checks if the value is serializable as JSON
|
|
508
|
-
* 2) Makes a deep clone of the object
|
|
509
|
-
* 2) Orders the object properties
|
|
510
|
-
* 2) Deeply freezes the cloned object
|
|
920
|
+
* Definition for any text - this will be always valid
|
|
511
921
|
*
|
|
512
|
-
* Note: This
|
|
922
|
+
* Note: This is not useful for validation, but for splitting and mapping with `subvalueDefinitions`
|
|
513
923
|
*
|
|
514
|
-
* @
|
|
515
|
-
* @public exported from `@promptbook/utils`
|
|
924
|
+
* @public exported from `@promptbook/core`
|
|
516
925
|
*/
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
926
|
+
var TextFormatDefinition = {
|
|
927
|
+
formatName: 'TEXT',
|
|
928
|
+
isValid: function (value) {
|
|
929
|
+
return typeof value === 'string';
|
|
930
|
+
},
|
|
931
|
+
canBeValid: function (partialValue) {
|
|
932
|
+
return typeof partialValue === 'string';
|
|
933
|
+
},
|
|
934
|
+
heal: function () {
|
|
935
|
+
throw new UnexpectedError('It does not make sense to call `TextFormatDefinition.heal`');
|
|
936
|
+
},
|
|
937
|
+
subvalueDefinitions: [
|
|
938
|
+
{
|
|
939
|
+
subvalueName: 'LINE',
|
|
940
|
+
mapValues: function (value, outputParameterName, settings, mapCallback) {
|
|
941
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
942
|
+
var lines, mappedLines;
|
|
943
|
+
return __generator(this, function (_a) {
|
|
944
|
+
switch (_a.label) {
|
|
945
|
+
case 0:
|
|
946
|
+
lines = value.split('\n');
|
|
947
|
+
return [4 /*yield*/, Promise.all(lines.map(function (lineContent, lineNumber) {
|
|
948
|
+
// TODO: [🧠] Maybe option to skip empty line
|
|
949
|
+
/* not await */ return mapCallback({
|
|
950
|
+
lineContent: lineContent,
|
|
951
|
+
// TODO: [🧠] Maybe also put here `lineNumber`
|
|
952
|
+
}, lineNumber);
|
|
953
|
+
}))];
|
|
954
|
+
case 1:
|
|
955
|
+
mappedLines = _a.sent();
|
|
956
|
+
return [2 /*return*/, mappedLines.join('\n')];
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
});
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
// <- TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
|
|
963
|
+
],
|
|
964
|
+
};
|
|
534
965
|
/**
|
|
535
|
-
* TODO: [
|
|
966
|
+
* TODO: [1] Make type for XML Text and Schema
|
|
967
|
+
* TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
|
|
968
|
+
* TODO: [🍓] In `TextFormatDefinition` implement simple `isValid`
|
|
969
|
+
* TODO: [🍓] In `TextFormatDefinition` implement partial `canBeValid`
|
|
970
|
+
* TODO: [🍓] In `TextFormatDefinition` implement `heal
|
|
971
|
+
* TODO: [🍓] In `TextFormatDefinition` implement `subvalueDefinitions`
|
|
972
|
+
* TODO: [🏢] Allow to expect something inside each item of list and other formats
|
|
536
973
|
*/
|
|
537
974
|
|
|
538
975
|
/**
|
|
539
|
-
*
|
|
976
|
+
* Definition for XML format
|
|
540
977
|
*
|
|
541
|
-
* @private
|
|
978
|
+
* @private still in development [🏢]
|
|
542
979
|
*/
|
|
543
|
-
var
|
|
980
|
+
var XmlFormatDefinition = {
|
|
981
|
+
formatName: 'XML',
|
|
982
|
+
mimeType: 'application/xml',
|
|
983
|
+
isValid: function (value, settings, schema) {
|
|
984
|
+
return true;
|
|
985
|
+
},
|
|
986
|
+
canBeValid: function (partialValue, settings, schema) {
|
|
987
|
+
return true;
|
|
988
|
+
},
|
|
989
|
+
heal: function (value, settings, schema) {
|
|
990
|
+
throw new Error('Not implemented');
|
|
991
|
+
},
|
|
992
|
+
subvalueDefinitions: [],
|
|
993
|
+
};
|
|
544
994
|
/**
|
|
545
|
-
*
|
|
995
|
+
* TODO: [🧠] Maybe propper instance of object
|
|
996
|
+
* TODO: [0] Make string_serialized_xml
|
|
997
|
+
* TODO: [1] Make type for XML Settings and Schema
|
|
998
|
+
* TODO: [🧠] What to use for validating XMLs - XSD,...
|
|
999
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
|
|
1000
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
|
|
1001
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement `heal
|
|
1002
|
+
* TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
|
|
1003
|
+
* TODO: [🏢] Allow to expect something inside XML and other formats
|
|
1004
|
+
*/
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Definitions for all formats supported by Promptbook
|
|
546
1008
|
*
|
|
547
|
-
* @
|
|
1009
|
+
* @private internal index of `...` <- TODO [🏢]
|
|
548
1010
|
*/
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
'knowledge',
|
|
556
|
-
'examples',
|
|
557
|
-
'modelName',
|
|
558
|
-
'currentDate',
|
|
559
|
-
// <- TODO: list here all command names
|
|
560
|
-
// <- TODO: Add more like 'date', 'modelName',...
|
|
561
|
-
// <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
|
|
562
|
-
],
|
|
563
|
-
});
|
|
1011
|
+
var FORMAT_DEFINITIONS = [
|
|
1012
|
+
JsonFormatDefinition,
|
|
1013
|
+
XmlFormatDefinition,
|
|
1014
|
+
TextFormatDefinition,
|
|
1015
|
+
CsvFormatDefinition,
|
|
1016
|
+
];
|
|
564
1017
|
/**
|
|
565
1018
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
566
1019
|
*/
|
|
567
1020
|
|
|
1021
|
+
/**
|
|
1022
|
+
* @@@
|
|
1023
|
+
*
|
|
1024
|
+
* @param text @@@
|
|
1025
|
+
* @returns @@@
|
|
1026
|
+
* @example 'HELLO_WORLD'
|
|
1027
|
+
* @example 'I_LOVE_PROMPTBOOK'
|
|
1028
|
+
* @public exported from `@promptbook/utils`
|
|
1029
|
+
*/
|
|
1030
|
+
function normalizeTo_SCREAMING_CASE(text) {
|
|
1031
|
+
var e_1, _a;
|
|
1032
|
+
var charType;
|
|
1033
|
+
var lastCharType = 'OTHER';
|
|
1034
|
+
var normalizedName = '';
|
|
1035
|
+
try {
|
|
1036
|
+
for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
|
|
1037
|
+
var char = text_1_1.value;
|
|
1038
|
+
var normalizedChar = void 0;
|
|
1039
|
+
if (/^[a-z]$/.test(char)) {
|
|
1040
|
+
charType = 'LOWERCASE';
|
|
1041
|
+
normalizedChar = char.toUpperCase();
|
|
1042
|
+
}
|
|
1043
|
+
else if (/^[A-Z]$/.test(char)) {
|
|
1044
|
+
charType = 'UPPERCASE';
|
|
1045
|
+
normalizedChar = char;
|
|
1046
|
+
}
|
|
1047
|
+
else if (/^[0-9]$/.test(char)) {
|
|
1048
|
+
charType = 'NUMBER';
|
|
1049
|
+
normalizedChar = char;
|
|
1050
|
+
}
|
|
1051
|
+
else {
|
|
1052
|
+
charType = 'OTHER';
|
|
1053
|
+
normalizedChar = '_';
|
|
1054
|
+
}
|
|
1055
|
+
if (charType !== lastCharType &&
|
|
1056
|
+
!(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
|
|
1057
|
+
!(lastCharType === 'NUMBER') &&
|
|
1058
|
+
!(charType === 'NUMBER')) {
|
|
1059
|
+
normalizedName += '_';
|
|
1060
|
+
}
|
|
1061
|
+
normalizedName += normalizedChar;
|
|
1062
|
+
lastCharType = charType;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1066
|
+
finally {
|
|
1067
|
+
try {
|
|
1068
|
+
if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
|
|
1069
|
+
}
|
|
1070
|
+
finally { if (e_1) throw e_1.error; }
|
|
1071
|
+
}
|
|
1072
|
+
normalizedName = normalizedName.replace(/_+/g, '_');
|
|
1073
|
+
normalizedName = normalizedName.replace(/_?\/_?/g, '/');
|
|
1074
|
+
normalizedName = normalizedName.replace(/^_/, '');
|
|
1075
|
+
normalizedName = normalizedName.replace(/_$/, '');
|
|
1076
|
+
return normalizedName;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* TODO: Tests
|
|
1080
|
+
* > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: 'Moje tabule' })).toEqual('/VtG7sR9rRJqwNEdM2/Moje tabule');
|
|
1081
|
+
* > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: 'ěščřžžýáíúů' })).toEqual('/VtG7sR9rRJqwNEdM2/escrzyaieuu');
|
|
1082
|
+
* > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: ' ahoj ' })).toEqual('/VtG7sR9rRJqwNEdM2/ahoj');
|
|
1083
|
+
* > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: ' ahoj_ahojAhoj ahoj ' })).toEqual('/VtG7sR9rRJqwNEdM2/ahoj-ahoj-ahoj-ahoj');
|
|
1084
|
+
* TODO: [🌺] Use some intermediate util splitWords
|
|
1085
|
+
*/
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* Orders JSON object by keys
|
|
1089
|
+
*
|
|
1090
|
+
* @returns The same type of object as the input re-ordered
|
|
1091
|
+
* @public exported from `@promptbook/utils`
|
|
1092
|
+
*/
|
|
1093
|
+
function orderJson(options) {
|
|
1094
|
+
var value = options.value, order = options.order;
|
|
1095
|
+
var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
|
|
1096
|
+
return orderedValue;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* Freezes the given object and all its nested objects recursively
|
|
1101
|
+
*
|
|
1102
|
+
* Note: `$` is used to indicate that this function is not a pure function - it mutates given object
|
|
1103
|
+
* Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
|
|
1104
|
+
*
|
|
1105
|
+
* @returns The same object as the input, but deeply frozen
|
|
1106
|
+
* @public exported from `@promptbook/utils`
|
|
1107
|
+
*/
|
|
1108
|
+
function $deepFreeze(objectValue) {
|
|
1109
|
+
var e_1, _a;
|
|
1110
|
+
if (Array.isArray(objectValue)) {
|
|
1111
|
+
return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
|
|
1112
|
+
}
|
|
1113
|
+
var propertyNames = Object.getOwnPropertyNames(objectValue);
|
|
1114
|
+
try {
|
|
1115
|
+
for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
|
|
1116
|
+
var propertyName = propertyNames_1_1.value;
|
|
1117
|
+
var value = objectValue[propertyName];
|
|
1118
|
+
if (value && typeof value === 'object') {
|
|
1119
|
+
$deepFreeze(value);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1124
|
+
finally {
|
|
1125
|
+
try {
|
|
1126
|
+
if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
|
|
1127
|
+
}
|
|
1128
|
+
finally { if (e_1) throw e_1.error; }
|
|
1129
|
+
}
|
|
1130
|
+
Object.freeze(objectValue);
|
|
1131
|
+
return objectValue;
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
1135
|
+
*/
|
|
1136
|
+
|
|
1137
|
+
/**
|
|
1138
|
+
* Checks if the value is [🚉] serializable as JSON
|
|
1139
|
+
* If not, throws an UnexpectedError with a rich error message and tracking
|
|
1140
|
+
*
|
|
1141
|
+
* - Almost all primitives are serializable BUT:
|
|
1142
|
+
* - `undefined` is not serializable
|
|
1143
|
+
* - `NaN` is not serializable
|
|
1144
|
+
* - Objects and arrays are serializable if all their properties are serializable
|
|
1145
|
+
* - Functions are not serializable
|
|
1146
|
+
* - Circular references are not serializable
|
|
1147
|
+
* - `Date` objects are not serializable
|
|
1148
|
+
* - `Map` and `Set` objects are not serializable
|
|
1149
|
+
* - `RegExp` objects are not serializable
|
|
1150
|
+
* - `Error` objects are not serializable
|
|
1151
|
+
* - `Symbol` objects are not serializable
|
|
1152
|
+
* - And much more...
|
|
1153
|
+
*
|
|
1154
|
+
* @throws UnexpectedError if the value is not serializable as JSON
|
|
1155
|
+
* @public exported from `@promptbook/utils`
|
|
1156
|
+
*/
|
|
1157
|
+
function checkSerializableAsJson(options) {
|
|
1158
|
+
var e_1, _a;
|
|
1159
|
+
var value = options.value, name = options.name, message = options.message;
|
|
1160
|
+
if (value === undefined) {
|
|
1161
|
+
throw new UnexpectedError("".concat(name, " is undefined"));
|
|
1162
|
+
}
|
|
1163
|
+
else if (value === null) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
else if (typeof value === 'boolean') {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
else if (typeof value === 'number' && !isNaN(value)) {
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
else if (typeof value === 'string') {
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
else if (typeof value === 'symbol') {
|
|
1176
|
+
throw new UnexpectedError("".concat(name, " is symbol"));
|
|
1177
|
+
}
|
|
1178
|
+
else if (typeof value === 'function') {
|
|
1179
|
+
throw new UnexpectedError("".concat(name, " is function"));
|
|
1180
|
+
}
|
|
1181
|
+
else if (typeof value === 'object' && Array.isArray(value)) {
|
|
1182
|
+
for (var i = 0; i < value.length; i++) {
|
|
1183
|
+
checkSerializableAsJson({ name: "".concat(name, "[").concat(i, "]"), value: value[i], message: message });
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
else if (typeof value === 'object') {
|
|
1187
|
+
if (value instanceof Date) {
|
|
1188
|
+
throw new UnexpectedError(spaceTrim(function (block) { return "\n `".concat(name, "` is Date\n\n Use `string_date_iso8601` instead\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
1189
|
+
}
|
|
1190
|
+
else if (value instanceof Map) {
|
|
1191
|
+
throw new UnexpectedError("".concat(name, " is Map"));
|
|
1192
|
+
}
|
|
1193
|
+
else if (value instanceof Set) {
|
|
1194
|
+
throw new UnexpectedError("".concat(name, " is Set"));
|
|
1195
|
+
}
|
|
1196
|
+
else if (value instanceof RegExp) {
|
|
1197
|
+
throw new UnexpectedError("".concat(name, " is RegExp"));
|
|
1198
|
+
}
|
|
1199
|
+
else if (value instanceof Error) {
|
|
1200
|
+
throw new UnexpectedError(spaceTrim(function (block) { return "\n `".concat(name, "` is unserialized Error\n\n Use function `serializeError`\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n\n "); }));
|
|
1201
|
+
}
|
|
1202
|
+
else {
|
|
1203
|
+
try {
|
|
1204
|
+
for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
1205
|
+
var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
|
|
1206
|
+
if (subValue === undefined) {
|
|
1207
|
+
// Note: undefined in object is serializable - it is just omited
|
|
1208
|
+
continue;
|
|
1209
|
+
}
|
|
1210
|
+
checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1214
|
+
finally {
|
|
1215
|
+
try {
|
|
1216
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1217
|
+
}
|
|
1218
|
+
finally { if (e_1) throw e_1.error; }
|
|
1219
|
+
}
|
|
1220
|
+
try {
|
|
1221
|
+
JSON.stringify(value); // <- TODO: [0]
|
|
1222
|
+
}
|
|
1223
|
+
catch (error) {
|
|
1224
|
+
if (!(error instanceof Error)) {
|
|
1225
|
+
throw error;
|
|
1226
|
+
}
|
|
1227
|
+
throw new UnexpectedError(spaceTrim(function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.stack || error.message), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
1228
|
+
}
|
|
1229
|
+
/*
|
|
1230
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
1231
|
+
const seen = new Set();
|
|
1232
|
+
const stack = [{ value }];
|
|
1233
|
+
while (stack.length > 0) {
|
|
1234
|
+
const { value } = stack.pop()!;
|
|
1235
|
+
if (typeof value === 'object' && value !== null) {
|
|
1236
|
+
if (seen.has(value)) {
|
|
1237
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
1238
|
+
}
|
|
1239
|
+
seen.add(value);
|
|
1240
|
+
if (Array.isArray(value)) {
|
|
1241
|
+
stack.push(...value.map((value) => ({ value })));
|
|
1242
|
+
} else {
|
|
1243
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
*/
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
throw new UnexpectedError(spaceTrim(function (block) { return "\n `".concat(name, "` is unknown type\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1257
|
+
* TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1258
|
+
* Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1259
|
+
*/
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* @@@
|
|
1263
|
+
*
|
|
1264
|
+
* @public exported from `@promptbook/utils`
|
|
1265
|
+
*/
|
|
1266
|
+
function deepClone(objectValue) {
|
|
1267
|
+
return JSON.parse(JSON.stringify(objectValue));
|
|
1268
|
+
/*
|
|
1269
|
+
TODO: [🧠] Is there a better implementation?
|
|
1270
|
+
> const propertyNames = Object.getOwnPropertyNames(objectValue);
|
|
1271
|
+
> for (const propertyName of propertyNames) {
|
|
1272
|
+
> const value = (objectValue as really_any)[propertyName];
|
|
1273
|
+
> if (value && typeof value === 'object') {
|
|
1274
|
+
> deepClone(value);
|
|
1275
|
+
> }
|
|
1276
|
+
> }
|
|
1277
|
+
> return Object.assign({}, objectValue);
|
|
1278
|
+
*/
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
1282
|
+
*/
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
* Utility to export a JSON object from a function
|
|
1286
|
+
*
|
|
1287
|
+
* 1) Checks if the value is serializable as JSON
|
|
1288
|
+
* 2) Makes a deep clone of the object
|
|
1289
|
+
* 2) Orders the object properties
|
|
1290
|
+
* 2) Deeply freezes the cloned object
|
|
1291
|
+
*
|
|
1292
|
+
* Note: This function does not mutates the given object
|
|
1293
|
+
*
|
|
1294
|
+
* @returns The same type of object as the input but read-only and re-ordered
|
|
1295
|
+
* @public exported from `@promptbook/utils`
|
|
1296
|
+
*/
|
|
1297
|
+
function exportJson(options) {
|
|
1298
|
+
var name = options.name, value = options.value, order = options.order, message = options.message;
|
|
1299
|
+
checkSerializableAsJson({ name: name, value: value, message: message });
|
|
1300
|
+
var orderedValue =
|
|
1301
|
+
// TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
|
|
1302
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1303
|
+
// @ts-ignore
|
|
1304
|
+
order === undefined
|
|
1305
|
+
? deepClone(value)
|
|
1306
|
+
: orderJson({
|
|
1307
|
+
value: value,
|
|
1308
|
+
// <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
|
|
1309
|
+
order: order,
|
|
1310
|
+
});
|
|
1311
|
+
$deepFreeze(orderedValue);
|
|
1312
|
+
return orderedValue;
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* TODO: [🧠] Is there a way how to meaningfully test this utility
|
|
1316
|
+
*/
|
|
1317
|
+
|
|
1318
|
+
/**
|
|
1319
|
+
* Nonce which is used for replacing things in strings
|
|
1320
|
+
*
|
|
1321
|
+
* @private within the repository
|
|
1322
|
+
*/
|
|
1323
|
+
var REPLACING_NONCE = 'u$k42k%!V2zo34w7Fu#@QUHYPW';
|
|
1324
|
+
/**
|
|
1325
|
+
* The names of the parameters that are reserved for special purposes
|
|
1326
|
+
*
|
|
1327
|
+
* @public exported from `@promptbook/core`
|
|
1328
|
+
*/
|
|
1329
|
+
var RESERVED_PARAMETER_NAMES = exportJson({
|
|
1330
|
+
name: 'RESERVED_PARAMETER_NAMES',
|
|
1331
|
+
message: "The names of the parameters that are reserved for special purposes",
|
|
1332
|
+
value: [
|
|
1333
|
+
'content',
|
|
1334
|
+
'context',
|
|
1335
|
+
'knowledge',
|
|
1336
|
+
'examples',
|
|
1337
|
+
'modelName',
|
|
1338
|
+
'currentDate',
|
|
1339
|
+
// <- TODO: list here all command names
|
|
1340
|
+
// <- TODO: Add more like 'date', 'modelName',...
|
|
1341
|
+
// <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
|
|
1342
|
+
],
|
|
1343
|
+
});
|
|
1344
|
+
/**
|
|
1345
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
1346
|
+
*/
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* @@@
|
|
1350
|
+
*
|
|
1351
|
+
* @param text @@@
|
|
1352
|
+
* @param _isFirstLetterCapital @@@
|
|
1353
|
+
* @returns @@@
|
|
1354
|
+
* @example 'helloWorld'
|
|
1355
|
+
* @example 'iLovePromptbook'
|
|
1356
|
+
* @public exported from `@promptbook/utils`
|
|
1357
|
+
*/
|
|
1358
|
+
function normalizeTo_camelCase(text, _isFirstLetterCapital) {
|
|
1359
|
+
var e_1, _a;
|
|
1360
|
+
if (_isFirstLetterCapital === void 0) { _isFirstLetterCapital = false; }
|
|
1361
|
+
var charType;
|
|
1362
|
+
var lastCharType = null;
|
|
1363
|
+
var normalizedName = '';
|
|
1364
|
+
try {
|
|
1365
|
+
for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
|
|
1366
|
+
var char = text_1_1.value;
|
|
1367
|
+
var normalizedChar = void 0;
|
|
1368
|
+
if (/^[a-z]$/.test(char)) {
|
|
1369
|
+
charType = 'LOWERCASE';
|
|
1370
|
+
normalizedChar = char;
|
|
1371
|
+
}
|
|
1372
|
+
else if (/^[A-Z]$/.test(char)) {
|
|
1373
|
+
charType = 'UPPERCASE';
|
|
1374
|
+
normalizedChar = char.toLowerCase();
|
|
1375
|
+
}
|
|
1376
|
+
else if (/^[0-9]$/.test(char)) {
|
|
1377
|
+
charType = 'NUMBER';
|
|
1378
|
+
normalizedChar = char;
|
|
1379
|
+
}
|
|
1380
|
+
else {
|
|
1381
|
+
charType = 'OTHER';
|
|
1382
|
+
normalizedChar = '';
|
|
1383
|
+
}
|
|
1384
|
+
if (!lastCharType) {
|
|
1385
|
+
if (_isFirstLetterCapital) {
|
|
1386
|
+
normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
else if (charType !== lastCharType &&
|
|
1390
|
+
!(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
|
|
1391
|
+
!(lastCharType === 'NUMBER') &&
|
|
1392
|
+
!(charType === 'NUMBER')) {
|
|
1393
|
+
normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
|
|
1394
|
+
}
|
|
1395
|
+
normalizedName += normalizedChar;
|
|
1396
|
+
lastCharType = charType;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1400
|
+
finally {
|
|
1401
|
+
try {
|
|
1402
|
+
if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
|
|
1403
|
+
}
|
|
1404
|
+
finally { if (e_1) throw e_1.error; }
|
|
1405
|
+
}
|
|
1406
|
+
return normalizedName;
|
|
1407
|
+
}
|
|
1408
|
+
/**
|
|
1409
|
+
* TODO: [🌺] Use some intermediate util splitWords
|
|
1410
|
+
*/
|
|
1411
|
+
|
|
1412
|
+
var defaultDiacriticsRemovalMap = [
|
|
1413
|
+
{
|
|
1414
|
+
base: 'A',
|
|
1415
|
+
letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F',
|
|
1416
|
+
},
|
|
1417
|
+
{ base: 'AA', letters: '\uA732' },
|
|
1418
|
+
{ base: 'AE', letters: '\u00C6\u01FC\u01E2' },
|
|
1419
|
+
{ base: 'AO', letters: '\uA734' },
|
|
1420
|
+
{ base: 'AU', letters: '\uA736' },
|
|
1421
|
+
{ base: 'AV', letters: '\uA738\uA73A' },
|
|
1422
|
+
{ base: 'AY', letters: '\uA73C' },
|
|
1423
|
+
{
|
|
1424
|
+
base: 'B',
|
|
1425
|
+
letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
|
|
1426
|
+
},
|
|
1427
|
+
{
|
|
1428
|
+
base: 'C',
|
|
1429
|
+
letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
base: 'D',
|
|
1433
|
+
letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
|
|
1434
|
+
},
|
|
1435
|
+
{ base: 'DZ', letters: '\u01F1\u01C4' },
|
|
1436
|
+
{ base: 'Dz', letters: '\u01F2\u01C5' },
|
|
1437
|
+
{
|
|
1438
|
+
base: 'E',
|
|
1439
|
+
letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E',
|
|
1440
|
+
},
|
|
1441
|
+
{ base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
|
|
1442
|
+
{
|
|
1443
|
+
base: 'G',
|
|
1444
|
+
letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
base: 'H',
|
|
1448
|
+
letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
|
|
1449
|
+
},
|
|
1450
|
+
{
|
|
1451
|
+
base: 'I',
|
|
1452
|
+
letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
|
|
1453
|
+
},
|
|
1454
|
+
{ base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
|
|
1455
|
+
{
|
|
1456
|
+
base: 'K',
|
|
1457
|
+
letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
|
|
1458
|
+
},
|
|
1459
|
+
{
|
|
1460
|
+
base: 'L',
|
|
1461
|
+
letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
|
|
1462
|
+
},
|
|
1463
|
+
{ base: 'LJ', letters: '\u01C7' },
|
|
1464
|
+
{ base: 'Lj', letters: '\u01C8' },
|
|
1465
|
+
{ base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
|
|
1466
|
+
{
|
|
1467
|
+
base: 'N',
|
|
1468
|
+
letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
|
|
1469
|
+
},
|
|
1470
|
+
{ base: 'NJ', letters: '\u01CA' },
|
|
1471
|
+
{ base: 'Nj', letters: '\u01CB' },
|
|
1472
|
+
{
|
|
1473
|
+
base: 'O',
|
|
1474
|
+
letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C',
|
|
1475
|
+
},
|
|
1476
|
+
{ base: 'OI', letters: '\u01A2' },
|
|
1477
|
+
{ base: 'OO', letters: '\uA74E' },
|
|
1478
|
+
{ base: 'OU', letters: '\u0222' },
|
|
1479
|
+
{ base: 'OE', letters: '\u008C\u0152' },
|
|
1480
|
+
{ base: 'oe', letters: '\u009C\u0153' },
|
|
1481
|
+
{
|
|
1482
|
+
base: 'P',
|
|
1483
|
+
letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
|
|
1484
|
+
},
|
|
1485
|
+
{ base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
|
|
1486
|
+
{
|
|
1487
|
+
base: 'R',
|
|
1488
|
+
letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
base: 'S',
|
|
1492
|
+
letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
|
|
1493
|
+
},
|
|
1494
|
+
{
|
|
1495
|
+
base: 'T',
|
|
1496
|
+
letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
|
|
1497
|
+
},
|
|
1498
|
+
{ base: 'TZ', letters: '\uA728' },
|
|
1499
|
+
{
|
|
1500
|
+
base: 'U',
|
|
1501
|
+
letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244',
|
|
1502
|
+
},
|
|
1503
|
+
{ base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
|
|
1504
|
+
{ base: 'VY', letters: '\uA760' },
|
|
1505
|
+
{
|
|
1506
|
+
base: 'W',
|
|
1507
|
+
letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
|
|
1508
|
+
},
|
|
1509
|
+
{ base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
|
|
1510
|
+
{
|
|
1511
|
+
base: 'Y',
|
|
1512
|
+
letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
|
|
1513
|
+
},
|
|
1514
|
+
{
|
|
1515
|
+
base: 'Z',
|
|
1516
|
+
letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
base: 'a',
|
|
1520
|
+
letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250',
|
|
1521
|
+
},
|
|
1522
|
+
{ base: 'aa', letters: '\uA733' },
|
|
1523
|
+
{ base: 'ae', letters: '\u00E6\u01FD\u01E3' },
|
|
1524
|
+
{ base: 'ao', letters: '\uA735' },
|
|
1525
|
+
{ base: 'au', letters: '\uA737' },
|
|
1526
|
+
{ base: 'av', letters: '\uA739\uA73B' },
|
|
1527
|
+
{ base: 'ay', letters: '\uA73D' },
|
|
1528
|
+
{
|
|
1529
|
+
base: 'b',
|
|
1530
|
+
letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
|
|
1531
|
+
},
|
|
1532
|
+
{
|
|
1533
|
+
base: 'c',
|
|
1534
|
+
letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
|
|
1535
|
+
},
|
|
1536
|
+
{
|
|
1537
|
+
base: 'd',
|
|
1538
|
+
letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
|
|
1539
|
+
},
|
|
1540
|
+
{ base: 'dz', letters: '\u01F3\u01C6' },
|
|
1541
|
+
{
|
|
1542
|
+
base: 'e',
|
|
1543
|
+
letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD',
|
|
1544
|
+
},
|
|
1545
|
+
{ base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
|
|
1546
|
+
{
|
|
1547
|
+
base: 'g',
|
|
1548
|
+
letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
base: 'h',
|
|
1552
|
+
letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
|
|
1553
|
+
},
|
|
1554
|
+
{ base: 'hv', letters: '\u0195' },
|
|
1555
|
+
{
|
|
1556
|
+
base: 'i',
|
|
1557
|
+
letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
|
|
1558
|
+
},
|
|
1559
|
+
{ base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
|
|
1560
|
+
{
|
|
1561
|
+
base: 'k',
|
|
1562
|
+
letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
base: 'l',
|
|
1566
|
+
letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
|
|
1567
|
+
},
|
|
1568
|
+
{ base: 'lj', letters: '\u01C9' },
|
|
1569
|
+
{ base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
|
|
1570
|
+
{
|
|
1571
|
+
base: 'n',
|
|
1572
|
+
letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
|
|
1573
|
+
},
|
|
1574
|
+
{ base: 'nj', letters: '\u01CC' },
|
|
1575
|
+
{
|
|
1576
|
+
base: 'o',
|
|
1577
|
+
letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275',
|
|
1578
|
+
},
|
|
1579
|
+
{ base: 'oi', letters: '\u01A3' },
|
|
1580
|
+
{ base: 'ou', letters: '\u0223' },
|
|
1581
|
+
{ base: 'oo', letters: '\uA74F' },
|
|
1582
|
+
{
|
|
1583
|
+
base: 'p',
|
|
1584
|
+
letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
|
|
1585
|
+
},
|
|
1586
|
+
{ base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
|
|
1587
|
+
{
|
|
1588
|
+
base: 'r',
|
|
1589
|
+
letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
|
|
1590
|
+
},
|
|
1591
|
+
{
|
|
1592
|
+
base: 's',
|
|
1593
|
+
letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
|
|
1594
|
+
},
|
|
1595
|
+
{
|
|
1596
|
+
base: 't',
|
|
1597
|
+
letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
|
|
1598
|
+
},
|
|
1599
|
+
{ base: 'tz', letters: '\uA729' },
|
|
1600
|
+
{
|
|
1601
|
+
base: 'u',
|
|
1602
|
+
letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289',
|
|
1603
|
+
},
|
|
1604
|
+
{ base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
|
|
1605
|
+
{ base: 'vy', letters: '\uA761' },
|
|
1606
|
+
{
|
|
1607
|
+
base: 'w',
|
|
1608
|
+
letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
|
|
1609
|
+
},
|
|
1610
|
+
{ base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
|
|
1611
|
+
{
|
|
1612
|
+
base: 'y',
|
|
1613
|
+
letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
base: 'z',
|
|
1617
|
+
letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
|
|
1618
|
+
},
|
|
1619
|
+
];
|
|
1620
|
+
/**
|
|
1621
|
+
* Map of letters from diacritic variant to diacritless variant
|
|
1622
|
+
* Contains lowercase and uppercase separatelly
|
|
1623
|
+
*
|
|
1624
|
+
* > "á" => "a"
|
|
1625
|
+
* > "ě" => "e"
|
|
1626
|
+
* > "Ă" => "A"
|
|
1627
|
+
* > ...
|
|
1628
|
+
*
|
|
1629
|
+
* @public exported from `@promptbook/utils`
|
|
1630
|
+
*/
|
|
1631
|
+
var DIACRITIC_VARIANTS_LETTERS = {};
|
|
1632
|
+
// tslint:disable-next-line: prefer-for-of
|
|
1633
|
+
for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
|
|
1634
|
+
var letters = defaultDiacriticsRemovalMap[i].letters;
|
|
1635
|
+
// tslint:disable-next-line: prefer-for-of
|
|
1636
|
+
for (var j = 0; j < letters.length; j++) {
|
|
1637
|
+
DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
// <- TODO: [🍓] Put to maker function to save execution time if not needed
|
|
1641
|
+
/*
|
|
1642
|
+
@see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
|
|
1643
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
1644
|
+
you may not use this file except in compliance with the License.
|
|
1645
|
+
You may obtain a copy of the License at
|
|
1646
|
+
|
|
1647
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
1648
|
+
|
|
1649
|
+
Unless required by applicable law or agreed to in writing, software
|
|
1650
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
1651
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1652
|
+
See the License for the specific language governing permissions and
|
|
1653
|
+
limitations under the License.
|
|
1654
|
+
*/
|
|
1655
|
+
|
|
1656
|
+
/**
|
|
1657
|
+
* @@@
|
|
1658
|
+
*
|
|
1659
|
+
* @param input @@@
|
|
1660
|
+
* @returns @@@
|
|
1661
|
+
* @public exported from `@promptbook/utils`
|
|
1662
|
+
*/
|
|
1663
|
+
function removeDiacritics(input) {
|
|
1664
|
+
/*eslint no-control-regex: "off"*/
|
|
1665
|
+
return input.replace(/[^\u0000-\u007E]/g, function (a) {
|
|
1666
|
+
return DIACRITIC_VARIANTS_LETTERS[a] || a;
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
|
|
1671
|
+
*/
|
|
1672
|
+
|
|
1673
|
+
/**
|
|
1674
|
+
* Removes emojis from a string and fix whitespaces
|
|
1675
|
+
*
|
|
1676
|
+
* @param text with emojis
|
|
1677
|
+
* @returns text without emojis
|
|
1678
|
+
* @public exported from `@promptbook/utils`
|
|
1679
|
+
*/
|
|
1680
|
+
function removeEmojis(text) {
|
|
1681
|
+
// Replace emojis (and also ZWJ sequence) with hyphens
|
|
1682
|
+
text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
|
|
1683
|
+
text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
|
|
1684
|
+
text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
|
|
1685
|
+
text = text.replace(/\p{Extended_Pictographic}/gu, '');
|
|
1686
|
+
return text;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* Removes quotes from a string
|
|
1691
|
+
*
|
|
1692
|
+
* Tip: This is very usefull for post-processing of the result of the LLM model
|
|
1693
|
+
* Note: This function removes only the same quotes from the beginning and the end of the string
|
|
1694
|
+
* Note: There are two simmilar functions:
|
|
1695
|
+
* - `removeQuotes` which removes only bounding quotes
|
|
1696
|
+
* - `unwrapResult` which removes whole introduce sentence
|
|
1697
|
+
*
|
|
1698
|
+
* @param text optionally quoted text
|
|
1699
|
+
* @returns text without quotes
|
|
1700
|
+
* @public exported from `@promptbook/utils`
|
|
1701
|
+
*/
|
|
1702
|
+
function removeQuotes(text) {
|
|
1703
|
+
if (text.startsWith('"') && text.endsWith('"')) {
|
|
1704
|
+
return text.slice(1, -1);
|
|
1705
|
+
}
|
|
1706
|
+
if (text.startsWith('\'') && text.endsWith('\'')) {
|
|
1707
|
+
return text.slice(1, -1);
|
|
1708
|
+
}
|
|
1709
|
+
return text;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
/**
|
|
1713
|
+
* Function `validateParameterName` will @@@
|
|
1714
|
+
*
|
|
1715
|
+
* @param parameterName @@@
|
|
1716
|
+
* @returns @@@
|
|
1717
|
+
* @throws {ParseError} @@@
|
|
1718
|
+
* @private within the repository
|
|
1719
|
+
*/
|
|
1720
|
+
function validateParameterName(parameterName) {
|
|
1721
|
+
var e_1, _a;
|
|
1722
|
+
var rawParameterName = parameterName;
|
|
1723
|
+
try {
|
|
1724
|
+
for (var _b = __values([
|
|
1725
|
+
['`', '`'],
|
|
1726
|
+
['{', '}'],
|
|
1727
|
+
['[', ']'],
|
|
1728
|
+
['(', ')'],
|
|
1729
|
+
['<', '>'],
|
|
1730
|
+
]), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
1731
|
+
var _d = __read(_c.value, 2), start = _d[0], end = _d[1];
|
|
1732
|
+
if (parameterName.substring(0, 1) === start &&
|
|
1733
|
+
parameterName.substring(parameterName.length - 1, parameterName.length) === end
|
|
1734
|
+
// <- TODO: More universal that 1 character
|
|
1735
|
+
) {
|
|
1736
|
+
parameterName = parameterName.substring(1, parameterName.length - 1);
|
|
1737
|
+
// <- TODO: More universal that 1 character
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1742
|
+
finally {
|
|
1743
|
+
try {
|
|
1744
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1745
|
+
}
|
|
1746
|
+
finally { if (e_1) throw e_1.error; }
|
|
1747
|
+
}
|
|
1748
|
+
// TODO: [🐠] Following try-catch block should be part of common validators logic
|
|
1749
|
+
try {
|
|
1750
|
+
/*
|
|
1751
|
+
Note: We don't need to check for spaces because we are going to normalize the parameter name to camelCase
|
|
1752
|
+
if (parameterName.includes(' ')) {
|
|
1753
|
+
throw new ParseError(`Parameter name cannot contain spaces`);
|
|
1754
|
+
}
|
|
1755
|
+
*/
|
|
1756
|
+
if (parameterName.includes('.')) {
|
|
1757
|
+
throw new ParseError("Parameter name cannot contain dots");
|
|
1758
|
+
}
|
|
1759
|
+
if (parameterName.includes('/') || parameterName.includes('\\')) {
|
|
1760
|
+
throw new ParseError("Parameter name cannot contain slashes");
|
|
1761
|
+
}
|
|
1762
|
+
if (parameterName.includes('(') ||
|
|
1763
|
+
parameterName.includes(')') ||
|
|
1764
|
+
parameterName.includes('{') ||
|
|
1765
|
+
parameterName.includes('}') ||
|
|
1766
|
+
parameterName.includes('[') ||
|
|
1767
|
+
parameterName.includes(']')) {
|
|
1768
|
+
throw new ParseError("Parameter name cannot contain braces");
|
|
1769
|
+
}
|
|
1770
|
+
parameterName = removeDiacritics(parameterName);
|
|
1771
|
+
parameterName = removeEmojis(parameterName);
|
|
1772
|
+
parameterName = removeQuotes(parameterName);
|
|
1773
|
+
parameterName = normalizeTo_camelCase(parameterName);
|
|
1774
|
+
if (parameterName === '') {
|
|
1775
|
+
throw new ParseError("Parameter name cannot be empty");
|
|
1776
|
+
}
|
|
1777
|
+
if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
|
|
1778
|
+
throw new ParseError("{".concat(parameterName, "} is a reserved parameter name"));
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
catch (error) {
|
|
1782
|
+
if (!(error instanceof ParseError)) {
|
|
1783
|
+
throw error;
|
|
1784
|
+
}
|
|
1785
|
+
throw new ParseError(spaceTrim(function (block) { return "\n ".concat(block(error.message), "\n\n Tried to validate parameter name:\n ").concat(block(rawParameterName), "\n "); }));
|
|
1786
|
+
}
|
|
1787
|
+
return parameterName;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
/**
|
|
1791
|
+
* Parses the foreach command
|
|
1792
|
+
*
|
|
1793
|
+
* Note: @@@ This command is used as foreach for new commands - it should NOT be used in any `.book.md` file
|
|
1794
|
+
*
|
|
1795
|
+
* @see `documentationUrl` for more details
|
|
1796
|
+
* @public exported from `@promptbook/editable`
|
|
1797
|
+
*/
|
|
1798
|
+
var foreachCommandParser = {
|
|
1799
|
+
/**
|
|
1800
|
+
* Name of the command
|
|
1801
|
+
*/
|
|
1802
|
+
name: 'FOREACH',
|
|
1803
|
+
/**
|
|
1804
|
+
* Aliases for the FOREACH command
|
|
1805
|
+
*/
|
|
1806
|
+
aliasNames: ['FOR', 'EACH'],
|
|
1807
|
+
/**
|
|
1808
|
+
* FOREACH command can be used in:
|
|
1809
|
+
*/
|
|
1810
|
+
isUsedInPipelineHead: false,
|
|
1811
|
+
isUsedInPipelineTask: true,
|
|
1812
|
+
/**
|
|
1813
|
+
* Description of the FOREACH command
|
|
1814
|
+
*/
|
|
1815
|
+
description: "@@",
|
|
1816
|
+
/**
|
|
1817
|
+
* Link to documentation
|
|
1818
|
+
*/
|
|
1819
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/148',
|
|
1820
|
+
/**
|
|
1821
|
+
* Example usages of the FOREACH command
|
|
1822
|
+
*/
|
|
1823
|
+
examples: [
|
|
1824
|
+
'FOREACH Text Line `{customers}` -> `{customer}`',
|
|
1825
|
+
'FOREACH Csv Cell `{customers}` -> `{cell}`',
|
|
1826
|
+
'FOREACH Csv Row `{customers}` -> `{firstName}`, `{lastName}`, `+{email}`',
|
|
1827
|
+
'FOR Text Line `{customers}` -> `{customer}`',
|
|
1828
|
+
'EACH Text Line `{customers}` -> `{customer}`',
|
|
1829
|
+
],
|
|
1830
|
+
/**
|
|
1831
|
+
* Parses the FOREACH command
|
|
1832
|
+
*/
|
|
1833
|
+
parse: function (input) {
|
|
1834
|
+
var args = input.args;
|
|
1835
|
+
var formatName = normalizeTo_SCREAMING_CASE(args[0] || '');
|
|
1836
|
+
var subformatName = normalizeTo_SCREAMING_CASE(args[1] || '');
|
|
1837
|
+
var parameterNameArg = args[2] || '';
|
|
1838
|
+
var assignSign = args[3];
|
|
1839
|
+
var formatDefinition = FORMAT_DEFINITIONS.find(function (formatDefinition) {
|
|
1840
|
+
return __spreadArray([formatDefinition.formatName], __read((formatDefinition.aliases || [])), false).includes(formatName);
|
|
1841
|
+
});
|
|
1842
|
+
if (formatDefinition === undefined) {
|
|
1843
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Unsupported format \"".concat(formatName, "\"\n\n Available formats:\n ").concat(block(FORMAT_DEFINITIONS.map(function (formatDefinition) { return formatDefinition.formatName; })
|
|
1844
|
+
.map(function (formatName) { return "- ".concat(formatName); })
|
|
1845
|
+
.join('\n')), "\n "); }));
|
|
1846
|
+
// <- TODO: [🏢] List all supported format names
|
|
1847
|
+
}
|
|
1848
|
+
var subvalueDefinition = formatDefinition.subvalueDefinitions.find(function (subvalueDefinition) {
|
|
1849
|
+
return __spreadArray([subvalueDefinition.subvalueName], __read((subvalueDefinition.aliases || [])), false).includes(subformatName);
|
|
1850
|
+
});
|
|
1851
|
+
if (subvalueDefinition === undefined) {
|
|
1852
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Unsupported subformat name \"".concat(subformatName, "\" for format \"").concat(formatName, "\"\n\n Available subformat names for format \"").concat(formatDefinition.formatName, "\":\n ").concat(block(formatDefinition.subvalueDefinitions
|
|
1853
|
+
.map(function (subvalueDefinition) { return subvalueDefinition.subvalueName; })
|
|
1854
|
+
.map(function (subvalueName) { return "- ".concat(subvalueName); })
|
|
1855
|
+
.join('\n')), "\n "); }));
|
|
1856
|
+
// <- TODO: [🏢] List all supported subformat names for the format
|
|
1857
|
+
}
|
|
1858
|
+
if (assignSign !== '->') {
|
|
1859
|
+
throw new ParseError("FOREACH command must have '->' to assign the value to the parameter");
|
|
1860
|
+
}
|
|
1861
|
+
var parameterName = validateParameterName(parameterNameArg);
|
|
1862
|
+
var outputSubparameterName = null;
|
|
1863
|
+
// TODO: [4] DRY
|
|
1864
|
+
var inputSubparameterNames = args
|
|
1865
|
+
.slice(4)
|
|
1866
|
+
.map(function (parameterName) { return parameterName.split(',').join(' ').trim(); })
|
|
1867
|
+
.filter(function (parameterName) { return !parameterName.includes('+'); })
|
|
1868
|
+
.filter(function (parameterName) { return parameterName !== ''; })
|
|
1869
|
+
.map(validateParameterName);
|
|
1870
|
+
// TODO: [4] DRY
|
|
1871
|
+
var outputSubparameterNames = args
|
|
1872
|
+
.slice(4)
|
|
1873
|
+
.map(function (parameterName) { return parameterName.split(',').join(' ').trim(); })
|
|
1874
|
+
.filter(function (parameterName) { return parameterName.includes('+'); })
|
|
1875
|
+
.map(function (parameterName) { return parameterName.split('+').join(''); })
|
|
1876
|
+
.map(validateParameterName);
|
|
1877
|
+
if (outputSubparameterNames.length === 1) {
|
|
1878
|
+
outputSubparameterName = outputSubparameterNames[0];
|
|
1879
|
+
}
|
|
1880
|
+
else if (outputSubparameterNames.length > 1) {
|
|
1881
|
+
throw new ParseError("FOREACH command can not have more than one output subparameter");
|
|
1882
|
+
}
|
|
1883
|
+
if (inputSubparameterNames.length === 0) {
|
|
1884
|
+
throw new ParseError("FOREACH command must have at least one input subparameter");
|
|
1885
|
+
}
|
|
1886
|
+
if (outputSubparameterName === null) {
|
|
1887
|
+
// TODO: Following code should be unhardcoded from here and moved to the format definition
|
|
1888
|
+
if (formatName === 'CSV' && subformatName === 'CELL') {
|
|
1889
|
+
outputSubparameterName = 'newCell';
|
|
1890
|
+
}
|
|
1891
|
+
else if (formatName === 'TEXT' && subformatName === 'LINE') {
|
|
1892
|
+
outputSubparameterName = 'newLine';
|
|
1893
|
+
}
|
|
1894
|
+
else {
|
|
1895
|
+
throw new ParseError(spaceTrim("\n FOREACH ".concat(formatName, " ").concat(subformatName, " must specify output subparameter\n\n Correct example:\n - FOREACH ").concat(formatName, " ").concat(subformatName, " {").concat(parameterName, "} -> {inputSubparameterName1}, {inputSubparameterName2}, +{outputSubparameterName}\n\n ")));
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
return {
|
|
1899
|
+
type: 'FOREACH',
|
|
1900
|
+
formatName: formatName,
|
|
1901
|
+
subformatName: subformatName,
|
|
1902
|
+
parameterName: parameterName,
|
|
1903
|
+
inputSubparameterNames: inputSubparameterNames,
|
|
1904
|
+
outputSubparameterName: outputSubparameterName,
|
|
1905
|
+
};
|
|
1906
|
+
},
|
|
1907
|
+
/**
|
|
1908
|
+
* Apply the FOREACH command to the `pipelineJson`
|
|
1909
|
+
*
|
|
1910
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
1911
|
+
*/
|
|
1912
|
+
$applyToTaskJson: function (command, $taskJson, $pipelineJson) {
|
|
1913
|
+
var formatName = command.formatName, subformatName = command.subformatName, parameterName = command.parameterName, inputSubparameterNames = command.inputSubparameterNames, outputSubparameterName = command.outputSubparameterName;
|
|
1914
|
+
// TODO: [🍭] Detect double use
|
|
1915
|
+
// TODO: [🍭] Detect usage with JOKER and don't allow it
|
|
1916
|
+
$taskJson.foreach = {
|
|
1917
|
+
formatName: formatName,
|
|
1918
|
+
subformatName: subformatName,
|
|
1919
|
+
parameterName: parameterName,
|
|
1920
|
+
inputSubparameterNames: inputSubparameterNames,
|
|
1921
|
+
outputSubparameterName: outputSubparameterName,
|
|
1922
|
+
};
|
|
1923
|
+
// Note: [🍭] FOREACH apply has some sideeffects on different places in codebase
|
|
1924
|
+
},
|
|
1925
|
+
/**
|
|
1926
|
+
* Converts the FOREACH command back to string
|
|
1927
|
+
*
|
|
1928
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
1929
|
+
*/
|
|
1930
|
+
stringify: function (command) {
|
|
1931
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
1932
|
+
},
|
|
1933
|
+
/**
|
|
1934
|
+
* Reads the FOREACH command from the `TaskJson`
|
|
1935
|
+
*
|
|
1936
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
1937
|
+
*/
|
|
1938
|
+
takeFromTaskJson: function ($taskJson) {
|
|
1939
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
1940
|
+
},
|
|
1941
|
+
};
|
|
1942
|
+
/**
|
|
1943
|
+
* TODO: [🍭] Make .book.md file with examples of the FOREACH with wrong parsing and logic
|
|
1944
|
+
*/
|
|
1945
|
+
|
|
1946
|
+
/**
|
|
1947
|
+
* Parses the format command
|
|
1948
|
+
*
|
|
1949
|
+
* @see `documentationUrl` for more details
|
|
1950
|
+
* @public exported from `@promptbook/editable`
|
|
1951
|
+
*/
|
|
1952
|
+
var formatCommandParser = {
|
|
1953
|
+
/**
|
|
1954
|
+
* Name of the command
|
|
1955
|
+
*/
|
|
1956
|
+
name: 'FORMAT',
|
|
1957
|
+
/**
|
|
1958
|
+
* BOILERPLATE command can be used in:
|
|
1959
|
+
*/
|
|
1960
|
+
isUsedInPipelineHead: false,
|
|
1961
|
+
isUsedInPipelineTask: true,
|
|
1962
|
+
/**
|
|
1963
|
+
* Description of the FORMAT command
|
|
1964
|
+
*/
|
|
1965
|
+
description: spaceTrim("\n Format command describes the desired output of the task (after post-processing)\n It can set limits for the maximum/minimum length of the output, measured in characters, words, sentences, paragraphs or some other shape of the output.\n "),
|
|
1966
|
+
/**
|
|
1967
|
+
* Link to documentation
|
|
1968
|
+
*/
|
|
1969
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/30',
|
|
1970
|
+
/**
|
|
1971
|
+
* Example usages of the FORMAT command
|
|
1972
|
+
*/
|
|
1973
|
+
examples: ['FORMAT JSON'],
|
|
1974
|
+
/**
|
|
1975
|
+
* Parses the FORMAT command
|
|
1976
|
+
*/
|
|
1977
|
+
parse: function (input) {
|
|
1978
|
+
var normalized = input.normalized;
|
|
1979
|
+
if (!normalized.startsWith('FORMAT_JSON')) {
|
|
1980
|
+
throw new ParseError("For now only JSON format is supported, in future we will support more formats");
|
|
1981
|
+
}
|
|
1982
|
+
return {
|
|
1983
|
+
type: 'FORMAT',
|
|
1984
|
+
format: 'JSON',
|
|
1985
|
+
};
|
|
1986
|
+
// <- TODO: [🦽] Why this is constantly removed by repair-imports.ts
|
|
1987
|
+
// [🥤]
|
|
1988
|
+
},
|
|
1989
|
+
/**
|
|
1990
|
+
* Apply the FORMAT command to the `pipelineJson`
|
|
1991
|
+
*
|
|
1992
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
1993
|
+
*/
|
|
1994
|
+
$applyToTaskJson: function (command, $taskJson) {
|
|
1995
|
+
if ($taskJson.format !== undefined && command.format !== $taskJson.format) {
|
|
1996
|
+
throw new ParseError("Format format is already defined to \"".concat($taskJson.format, "\".\n Now you try to redefine it by \"").concat(command.format, "\""));
|
|
1997
|
+
}
|
|
1998
|
+
$taskJson.format = command.format;
|
|
1999
|
+
},
|
|
2000
|
+
/**
|
|
2001
|
+
* Converts the FORMAT command back to string
|
|
2002
|
+
*
|
|
2003
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2004
|
+
*/
|
|
2005
|
+
stringify: function (command) {
|
|
2006
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
2007
|
+
},
|
|
2008
|
+
/**
|
|
2009
|
+
* Reads the FORMAT command from the `TaskJson`
|
|
2010
|
+
*
|
|
2011
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2012
|
+
*/
|
|
2013
|
+
takeFromTaskJson: function ($taskJson) {
|
|
2014
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2015
|
+
},
|
|
2016
|
+
};
|
|
2017
|
+
|
|
2018
|
+
/**
|
|
2019
|
+
* @@@
|
|
2020
|
+
*
|
|
2021
|
+
* @public exported from `@promptbook/core`
|
|
2022
|
+
*/
|
|
2023
|
+
var ChatbotFormfactorDefinition = {
|
|
2024
|
+
name: 'CHATBOT',
|
|
2025
|
+
aliasNames: ['CHAT'],
|
|
2026
|
+
description: "@@@",
|
|
2027
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/174",
|
|
2028
|
+
pipelineInterface: {
|
|
2029
|
+
inputParameters: [
|
|
2030
|
+
{
|
|
2031
|
+
name: 'previousTitle',
|
|
2032
|
+
description: "Previous title of the conversation",
|
|
2033
|
+
isInput: true,
|
|
2034
|
+
isOutput: false,
|
|
2035
|
+
},
|
|
2036
|
+
{
|
|
2037
|
+
name: 'previousConversationSummary',
|
|
2038
|
+
description: "Previous conversation summary",
|
|
2039
|
+
isInput: true,
|
|
2040
|
+
isOutput: false,
|
|
2041
|
+
},
|
|
2042
|
+
{ name: 'userMessage', description: "User message", isInput: true, isOutput: false },
|
|
2043
|
+
],
|
|
2044
|
+
outputParameters: [
|
|
2045
|
+
{ name: 'title', description: "Title of the conversation", isInput: false, isOutput: true },
|
|
2046
|
+
{ name: 'conversationSummary', description: "Summary of the conversation", isInput: false, isOutput: true },
|
|
2047
|
+
{ name: 'chatbotResponse', description: "Chatbot response", isInput: false, isOutput: true },
|
|
2048
|
+
],
|
|
2049
|
+
},
|
|
2050
|
+
};
|
|
2051
|
+
|
|
2052
|
+
/**
|
|
2053
|
+
* Generator is form of app that @@@
|
|
2054
|
+
*
|
|
2055
|
+
* @public exported from `@promptbook/core`
|
|
2056
|
+
*/
|
|
2057
|
+
var GeneratorFormfactorDefinition = {
|
|
2058
|
+
name: 'GENERATOR',
|
|
2059
|
+
description: "Generates any kind (in HTML with possible scripts and css format) of content from input message",
|
|
2060
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
|
|
2061
|
+
pipelineInterface: {
|
|
2062
|
+
inputParameters: [
|
|
2063
|
+
{
|
|
2064
|
+
name: 'inputMessage',
|
|
2065
|
+
description: "Input message to be image made from",
|
|
2066
|
+
isInput: true,
|
|
2067
|
+
isOutput: false,
|
|
2068
|
+
},
|
|
2069
|
+
],
|
|
2070
|
+
outputParameters: [
|
|
2071
|
+
{
|
|
2072
|
+
name: 'result',
|
|
2073
|
+
description: "Result in HTML to be shown to user",
|
|
2074
|
+
isInput: false,
|
|
2075
|
+
isOutput: true,
|
|
2076
|
+
},
|
|
2077
|
+
],
|
|
2078
|
+
},
|
|
2079
|
+
};
|
|
2080
|
+
|
|
2081
|
+
/**
|
|
2082
|
+
* @@@
|
|
2083
|
+
*
|
|
2084
|
+
* @see https://github.com/webgptorg/promptbook/discussions/171
|
|
2085
|
+
*
|
|
2086
|
+
* @public exported from `@promptbook/core`
|
|
2087
|
+
*/
|
|
2088
|
+
var GENERIC_PIPELINE_INTERFACE = {
|
|
2089
|
+
inputParameters: [],
|
|
2090
|
+
outputParameters: [],
|
|
2091
|
+
};
|
|
2092
|
+
/**
|
|
2093
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2094
|
+
*/
|
|
2095
|
+
|
|
2096
|
+
/**
|
|
2097
|
+
* @@@
|
|
2098
|
+
*
|
|
2099
|
+
* @public exported from `@promptbook/core`
|
|
2100
|
+
*/
|
|
2101
|
+
var GenericFormfactorDefinition = {
|
|
2102
|
+
name: 'GENERIC',
|
|
2103
|
+
description: "@@@",
|
|
2104
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/173",
|
|
2105
|
+
pipelineInterface: GENERIC_PIPELINE_INTERFACE,
|
|
2106
|
+
};
|
|
2107
|
+
|
|
2108
|
+
/**
|
|
2109
|
+
* Image generator is form of app that generates image from input message
|
|
2110
|
+
*
|
|
2111
|
+
* @public exported from `@promptbook/core`
|
|
2112
|
+
*/
|
|
2113
|
+
var ImageGeneratorFormfactorDefinition = {
|
|
2114
|
+
name: 'IMAGE_GENERATOR',
|
|
2115
|
+
description: "Generates prompt for image generation from input message",
|
|
2116
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
|
|
2117
|
+
pipelineInterface: {
|
|
2118
|
+
inputParameters: [
|
|
2119
|
+
{
|
|
2120
|
+
name: 'inputMessage',
|
|
2121
|
+
description: "Input message to be image made from",
|
|
2122
|
+
isInput: true,
|
|
2123
|
+
isOutput: false,
|
|
2124
|
+
},
|
|
2125
|
+
],
|
|
2126
|
+
outputParameters: [
|
|
2127
|
+
{
|
|
2128
|
+
name: 'prompt',
|
|
2129
|
+
description: "Prompt to be used for image generation",
|
|
2130
|
+
isInput: false,
|
|
2131
|
+
isOutput: true,
|
|
2132
|
+
},
|
|
2133
|
+
],
|
|
2134
|
+
},
|
|
2135
|
+
};
|
|
2136
|
+
|
|
2137
|
+
/**
|
|
2138
|
+
* Matcher is form of app that @@@
|
|
2139
|
+
*
|
|
2140
|
+
* @public exported from `@promptbook/core`
|
|
2141
|
+
*/
|
|
2142
|
+
var MatcherFormfactorDefinition = {
|
|
2143
|
+
name: 'EXPERIMENTAL_MATCHER',
|
|
2144
|
+
description: "@@@",
|
|
2145
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/177",
|
|
2146
|
+
pipelineInterface: {
|
|
2147
|
+
inputParameters: [
|
|
2148
|
+
/* @@@ */
|
|
2149
|
+
{
|
|
2150
|
+
name: 'nonce',
|
|
2151
|
+
description: 'Just to prevent EXPERIMENTAL_MATCHER to be set as implicit formfactor',
|
|
2152
|
+
isInput: true,
|
|
2153
|
+
isOutput: false,
|
|
2154
|
+
},
|
|
2155
|
+
],
|
|
2156
|
+
outputParameters: [
|
|
2157
|
+
/* @@@ */
|
|
2158
|
+
],
|
|
2159
|
+
},
|
|
2160
|
+
};
|
|
2161
|
+
|
|
2162
|
+
/**
|
|
2163
|
+
* Sheets is form of app that @@@
|
|
2164
|
+
*
|
|
2165
|
+
* @public exported from `@promptbook/core`
|
|
2166
|
+
*/
|
|
2167
|
+
var SheetsFormfactorDefinition = {
|
|
2168
|
+
name: 'SHEETS',
|
|
2169
|
+
aliasNames: ['SHEETS', 'SHEET'],
|
|
2170
|
+
description: "@@@",
|
|
2171
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/176",
|
|
2172
|
+
pipelineInterface: {
|
|
2173
|
+
inputParameters: [
|
|
2174
|
+
{
|
|
2175
|
+
name: 'inputSheet',
|
|
2176
|
+
description: "Input sheet to be processed as csv",
|
|
2177
|
+
isInput: true,
|
|
2178
|
+
isOutput: false,
|
|
2179
|
+
},
|
|
2180
|
+
],
|
|
2181
|
+
outputParameters: [
|
|
2182
|
+
{
|
|
2183
|
+
name: 'outputSheet',
|
|
2184
|
+
description: "Output sheet as csv",
|
|
2185
|
+
isInput: false,
|
|
2186
|
+
isOutput: true,
|
|
2187
|
+
},
|
|
2188
|
+
],
|
|
2189
|
+
},
|
|
2190
|
+
};
|
|
2191
|
+
|
|
2192
|
+
/**
|
|
2193
|
+
* Translator is form of app that @@@
|
|
2194
|
+
*
|
|
2195
|
+
* @public exported from `@promptbook/core`
|
|
2196
|
+
*/
|
|
2197
|
+
var TranslatorFormfactorDefinition = {
|
|
2198
|
+
name: 'TRANSLATOR',
|
|
2199
|
+
description: "@@@",
|
|
2200
|
+
documentationUrl: "https://github.com/webgptorg/promptbook/discussions/175",
|
|
2201
|
+
pipelineInterface: {
|
|
2202
|
+
inputParameters: [
|
|
2203
|
+
{
|
|
2204
|
+
name: 'inputMessage',
|
|
2205
|
+
description: "Input message to be translated",
|
|
2206
|
+
isInput: true,
|
|
2207
|
+
isOutput: false,
|
|
2208
|
+
},
|
|
2209
|
+
],
|
|
2210
|
+
outputParameters: [
|
|
2211
|
+
{
|
|
2212
|
+
name: 'outputMessage',
|
|
2213
|
+
description: "Translated output message",
|
|
2214
|
+
isInput: false,
|
|
2215
|
+
isOutput: true,
|
|
2216
|
+
},
|
|
2217
|
+
],
|
|
2218
|
+
// <- TODO: [🤓] Maybe add {summary}
|
|
2219
|
+
// <- TODO: [🧠] maybe change to {inputText}, {inputText} / or make system for any name of first input and first outpur parameter
|
|
2220
|
+
},
|
|
2221
|
+
};
|
|
2222
|
+
|
|
2223
|
+
/**
|
|
2224
|
+
* All available formfactor definitions
|
|
2225
|
+
*
|
|
2226
|
+
* @public exported from `@promptbook/core`
|
|
2227
|
+
*/
|
|
2228
|
+
var FORMFACTOR_DEFINITIONS = [
|
|
2229
|
+
GenericFormfactorDefinition,
|
|
2230
|
+
ChatbotFormfactorDefinition,
|
|
2231
|
+
TranslatorFormfactorDefinition,
|
|
2232
|
+
SheetsFormfactorDefinition,
|
|
2233
|
+
MatcherFormfactorDefinition,
|
|
2234
|
+
GeneratorFormfactorDefinition,
|
|
2235
|
+
ImageGeneratorFormfactorDefinition,
|
|
2236
|
+
];
|
|
2237
|
+
/**
|
|
2238
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2239
|
+
*/
|
|
2240
|
+
|
|
2241
|
+
/**
|
|
2242
|
+
* Parses the formfactor command
|
|
2243
|
+
*
|
|
2244
|
+
* Note: @@@ This command is used as formfactor for new commands - it should NOT be used in any `.book.md` file
|
|
2245
|
+
*
|
|
2246
|
+
* @see `documentationUrl` for more details
|
|
2247
|
+
* @public exported from `@promptbook/editable`
|
|
2248
|
+
*/
|
|
2249
|
+
var formfactorCommandParser = {
|
|
2250
|
+
/**
|
|
2251
|
+
* Name of the command
|
|
2252
|
+
*/
|
|
2253
|
+
name: 'FORMFACTOR',
|
|
2254
|
+
/**
|
|
2255
|
+
* Aliases for the FORMFACTOR command
|
|
2256
|
+
*/
|
|
2257
|
+
aliasNames: ['FORM', 'FF'],
|
|
2258
|
+
/**
|
|
2259
|
+
* FORMFACTOR command can be used in:
|
|
2260
|
+
*/
|
|
2261
|
+
isUsedInPipelineHead: true,
|
|
2262
|
+
isUsedInPipelineTask: false,
|
|
2263
|
+
/**
|
|
2264
|
+
* Description of the FORMFACTOR command
|
|
2265
|
+
*/
|
|
2266
|
+
description: "@@",
|
|
2267
|
+
/**
|
|
2268
|
+
* Link to documentation
|
|
2269
|
+
*/
|
|
2270
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/168',
|
|
2271
|
+
/**
|
|
2272
|
+
* Example usages of the FORMFACTOR command
|
|
2273
|
+
*/
|
|
2274
|
+
examples: ['FORMFACTOR Chatbot', 'FF Chat'],
|
|
2275
|
+
/**
|
|
2276
|
+
* Parses the FORMFACTOR command
|
|
2277
|
+
*/
|
|
2278
|
+
parse: function (input) {
|
|
2279
|
+
var args = input.args;
|
|
2280
|
+
if (args.length !== 1) {
|
|
2281
|
+
throw new ParseError("FORMFACTOR command requires exactly one argument");
|
|
2282
|
+
}
|
|
2283
|
+
var formfactorNameCandidate = args[0].toUpperCase();
|
|
2284
|
+
var formfactor = FORMFACTOR_DEFINITIONS.find(function (definition) {
|
|
2285
|
+
return __spreadArray([definition.name], __read(__assign({ aliasNames: [] }, definition).aliasNames), false).includes(formfactorNameCandidate);
|
|
2286
|
+
});
|
|
2287
|
+
if (formfactor === undefined) {
|
|
2288
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Unknown formfactor name \"".concat(formfactorNameCandidate, "\"\n\n Available formfactors:\n ").concat(block(FORMFACTOR_DEFINITIONS.map(function (_a) {
|
|
2289
|
+
var name = _a.name;
|
|
2290
|
+
return "- ".concat(name);
|
|
2291
|
+
}).join('\n')), "\n "); }));
|
|
2292
|
+
}
|
|
2293
|
+
return {
|
|
2294
|
+
type: 'FORMFACTOR',
|
|
2295
|
+
formfactorName: formfactor.name,
|
|
2296
|
+
};
|
|
2297
|
+
},
|
|
2298
|
+
/**
|
|
2299
|
+
* Apply the FORMFACTOR command to the `pipelineJson`
|
|
2300
|
+
*
|
|
2301
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
2302
|
+
*/
|
|
2303
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
2304
|
+
if ($pipelineJson.formfactorName !== undefined && $pipelineJson.formfactorName !== command.formfactorName) {
|
|
2305
|
+
throw new ParseError(spaceTrim("\n Redefinition of `FORMFACTOR` in the pipeline head\n\n You have used:\n 1) FORMFACTOR `".concat($pipelineJson.formfactorName, "`\n 2) FORMFACTOR `").concat(command.formfactorName, "`\n ")));
|
|
2306
|
+
}
|
|
2307
|
+
$pipelineJson.formfactorName = command.formfactorName;
|
|
2308
|
+
},
|
|
2309
|
+
/**
|
|
2310
|
+
* Converts the FORMFACTOR command back to string
|
|
2311
|
+
*
|
|
2312
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2313
|
+
*/
|
|
2314
|
+
stringify: function (command) {
|
|
2315
|
+
return "FORMFACTOR ".concat(command.formfactorName);
|
|
2316
|
+
},
|
|
2317
|
+
/**
|
|
2318
|
+
* Reads the FORMFACTOR command from the `PipelineJson`
|
|
2319
|
+
*
|
|
2320
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2321
|
+
*/
|
|
2322
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
2323
|
+
return [
|
|
2324
|
+
{
|
|
2325
|
+
type: 'FORMFACTOR',
|
|
2326
|
+
formfactorName: pipelineJson.formfactorName,
|
|
2327
|
+
},
|
|
2328
|
+
];
|
|
2329
|
+
},
|
|
2330
|
+
};
|
|
2331
|
+
|
|
2332
|
+
/**
|
|
2333
|
+
* Parses the joker command
|
|
2334
|
+
*
|
|
2335
|
+
* @see `documentationUrl` for more details
|
|
2336
|
+
* @public exported from `@promptbook/editable`
|
|
2337
|
+
*/
|
|
2338
|
+
var jokerCommandParser = {
|
|
2339
|
+
/**
|
|
2340
|
+
* Name of the command
|
|
2341
|
+
*/
|
|
2342
|
+
name: 'JOKER',
|
|
2343
|
+
/**
|
|
2344
|
+
* BOILERPLATE command can be used in:
|
|
2345
|
+
*/
|
|
2346
|
+
isUsedInPipelineHead: false,
|
|
2347
|
+
isUsedInPipelineTask: true,
|
|
2348
|
+
/**
|
|
2349
|
+
* Description of the JOKER command
|
|
2350
|
+
*/
|
|
2351
|
+
description: "Joker parameter is used instead of executing the task result if jokers value meets the expectations requirements",
|
|
2352
|
+
/**
|
|
2353
|
+
* Link to documentation
|
|
2354
|
+
*/
|
|
2355
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/66',
|
|
2356
|
+
/**
|
|
2357
|
+
* Example usages of the JOKER command
|
|
2358
|
+
*/
|
|
2359
|
+
examples: ['JOKER {documentTitle}'],
|
|
2360
|
+
/**
|
|
2361
|
+
* Parses the JOKER command
|
|
2362
|
+
*/
|
|
2363
|
+
parse: function (input) {
|
|
2364
|
+
var args = input.args;
|
|
2365
|
+
if (args.length !== 1) {
|
|
2366
|
+
throw new ParseError("JOKE command expects exactly one parameter name");
|
|
2367
|
+
}
|
|
2368
|
+
var parameterNameArg = args[0] || '';
|
|
2369
|
+
var parameterName = validateParameterName(parameterNameArg);
|
|
2370
|
+
return {
|
|
2371
|
+
type: 'JOKER',
|
|
2372
|
+
parameterName: parameterName,
|
|
2373
|
+
};
|
|
2374
|
+
},
|
|
2375
|
+
/**
|
|
2376
|
+
* Apply the JOKER command to the `pipelineJson`
|
|
2377
|
+
*
|
|
2378
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
2379
|
+
*/
|
|
2380
|
+
$applyToTaskJson: function (command, $taskJson) {
|
|
2381
|
+
$taskJson.jokerParameterNames = $taskJson.jokerParameterNames || [];
|
|
2382
|
+
$taskJson.jokerParameterNames.push(command.parameterName);
|
|
2383
|
+
},
|
|
2384
|
+
/**
|
|
2385
|
+
* Converts the JOKER command back to string
|
|
2386
|
+
*
|
|
2387
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2388
|
+
*/
|
|
2389
|
+
stringify: function (command) {
|
|
2390
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
2391
|
+
},
|
|
2392
|
+
/**
|
|
2393
|
+
* Reads the JOKER command from the `TaskJson`
|
|
2394
|
+
*
|
|
2395
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2396
|
+
*/
|
|
2397
|
+
takeFromTaskJson: function ($taskJson) {
|
|
2398
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2399
|
+
},
|
|
2400
|
+
};
|
|
2401
|
+
|
|
2402
|
+
/**
|
|
2403
|
+
* Tests if given string is valid URL.
|
|
2404
|
+
*
|
|
2405
|
+
* Note: This does not check if the file exists only if the path is valid
|
|
2406
|
+
* @public exported from `@promptbook/utils`
|
|
2407
|
+
*/
|
|
2408
|
+
function isValidFilePath(filename) {
|
|
2409
|
+
if (typeof filename !== 'string') {
|
|
2410
|
+
return false;
|
|
2411
|
+
}
|
|
2412
|
+
if (filename.split('\n').length > 1) {
|
|
2413
|
+
return false;
|
|
2414
|
+
}
|
|
2415
|
+
if (filename.split(' ').length >
|
|
2416
|
+
5 /* <- TODO: [🧠][🈷] Make some better non-arbitrary way how to distinct filenames from informational texts */) {
|
|
2417
|
+
return false;
|
|
2418
|
+
}
|
|
2419
|
+
var filenameSlashes = filename.split('\\').join('/');
|
|
2420
|
+
// Absolute Unix path: /hello.txt
|
|
2421
|
+
if (/^(\/)/i.test(filenameSlashes)) {
|
|
2422
|
+
// console.log(filename, 'Absolute Unix path: /hello.txt');
|
|
2423
|
+
return true;
|
|
2424
|
+
}
|
|
2425
|
+
// Absolute Windows path: /hello.txt
|
|
2426
|
+
if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
|
|
2427
|
+
// console.log(filename, 'Absolute Windows path: /hello.txt');
|
|
2428
|
+
return true;
|
|
2429
|
+
}
|
|
2430
|
+
// Relative path: ./hello.txt
|
|
2431
|
+
if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
|
|
2432
|
+
// console.log(filename, 'Relative path: ./hello.txt');
|
|
2433
|
+
return true;
|
|
2434
|
+
}
|
|
2435
|
+
// Allow paths like foo/hello
|
|
2436
|
+
if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
|
|
2437
|
+
// console.log(filename, 'Allow paths like foo/hello');
|
|
2438
|
+
return true;
|
|
2439
|
+
}
|
|
2440
|
+
// Allow paths like hello.book
|
|
2441
|
+
if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
|
|
2442
|
+
// console.log(filename, 'Allow paths like hello.book');
|
|
2443
|
+
return true;
|
|
2444
|
+
}
|
|
2445
|
+
return false;
|
|
2446
|
+
}
|
|
2447
|
+
/**
|
|
2448
|
+
* TODO: [🍏] Implement for MacOs
|
|
2449
|
+
*/
|
|
2450
|
+
|
|
2451
|
+
/**
|
|
2452
|
+
* Tests if given string is valid URL.
|
|
2453
|
+
*
|
|
2454
|
+
* Note: Dataurl are considered perfectly valid.
|
|
2455
|
+
* Note: There are two simmilar functions:
|
|
2456
|
+
* - `isValidUrl` which tests any URL
|
|
2457
|
+
* - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
|
|
2458
|
+
*
|
|
2459
|
+
* @public exported from `@promptbook/utils`
|
|
2460
|
+
*/
|
|
2461
|
+
function isValidUrl(url) {
|
|
2462
|
+
if (typeof url !== 'string') {
|
|
2463
|
+
return false;
|
|
2464
|
+
}
|
|
2465
|
+
try {
|
|
2466
|
+
if (url.startsWith('blob:')) {
|
|
2467
|
+
url = url.replace(/^blob:/, '');
|
|
2468
|
+
}
|
|
2469
|
+
var urlObject = new URL(url /* because fail is handled */);
|
|
2470
|
+
if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
|
|
2471
|
+
return false;
|
|
2472
|
+
}
|
|
2473
|
+
return true;
|
|
2474
|
+
}
|
|
2475
|
+
catch (error) {
|
|
2476
|
+
return false;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
/**
|
|
2481
|
+
* @@@
|
|
2482
|
+
*
|
|
2483
|
+
* @param text @@@
|
|
2484
|
+
* @returns @@@
|
|
2485
|
+
* @example 'hello-world'
|
|
2486
|
+
* @example 'i-love-promptbook'
|
|
2487
|
+
* @public exported from `@promptbook/utils`
|
|
2488
|
+
*/
|
|
2489
|
+
function normalizeToKebabCase(text) {
|
|
2490
|
+
var e_1, _a;
|
|
2491
|
+
text = removeDiacritics(text);
|
|
2492
|
+
var charType;
|
|
2493
|
+
var lastCharType = 'OTHER';
|
|
2494
|
+
var normalizedName = '';
|
|
2495
|
+
try {
|
|
2496
|
+
for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
|
|
2497
|
+
var char = text_1_1.value;
|
|
2498
|
+
var normalizedChar = void 0;
|
|
2499
|
+
if (/^[a-z]$/.test(char)) {
|
|
2500
|
+
charType = 'LOWERCASE';
|
|
2501
|
+
normalizedChar = char;
|
|
2502
|
+
}
|
|
2503
|
+
else if (/^[A-Z]$/.test(char)) {
|
|
2504
|
+
charType = 'UPPERCASE';
|
|
2505
|
+
normalizedChar = char.toLowerCase();
|
|
2506
|
+
}
|
|
2507
|
+
else if (/^[0-9]$/.test(char)) {
|
|
2508
|
+
charType = 'NUMBER';
|
|
2509
|
+
normalizedChar = char;
|
|
2510
|
+
}
|
|
2511
|
+
else {
|
|
2512
|
+
charType = 'OTHER';
|
|
2513
|
+
normalizedChar = '-';
|
|
2514
|
+
}
|
|
2515
|
+
if (charType !== lastCharType &&
|
|
2516
|
+
!(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
|
|
2517
|
+
!(lastCharType === 'NUMBER') &&
|
|
2518
|
+
!(charType === 'NUMBER')) {
|
|
2519
|
+
normalizedName += '-';
|
|
2520
|
+
}
|
|
2521
|
+
normalizedName += normalizedChar;
|
|
2522
|
+
lastCharType = charType;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
2526
|
+
finally {
|
|
2527
|
+
try {
|
|
2528
|
+
if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
|
|
2529
|
+
}
|
|
2530
|
+
finally { if (e_1) throw e_1.error; }
|
|
2531
|
+
}
|
|
2532
|
+
normalizedName = normalizedName.split(/-+/g).join('-');
|
|
2533
|
+
normalizedName = normalizedName.split(/-?\/-?/g).join('/');
|
|
2534
|
+
normalizedName = normalizedName.replace(/^-/, '');
|
|
2535
|
+
normalizedName = normalizedName.replace(/-$/, '');
|
|
2536
|
+
return normalizedName;
|
|
2537
|
+
}
|
|
2538
|
+
/**
|
|
2539
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2540
|
+
*/
|
|
2541
|
+
|
|
2542
|
+
/**
|
|
2543
|
+
* Creates unique name for the source
|
|
2544
|
+
*
|
|
2545
|
+
* @public exported from `@promptbook/editable`
|
|
2546
|
+
*/
|
|
2547
|
+
function knowledgeSourceContentToName(knowledgeSourceContent) {
|
|
2548
|
+
var hash = SHA256(hexEncoder.parse(JSON.stringify(knowledgeSourceContent)))
|
|
2549
|
+
// <- TODO: [🥬] Encapsulate sha256 to some private utility function
|
|
2550
|
+
.toString( /* hex */)
|
|
2551
|
+
.substring(0, 20);
|
|
2552
|
+
// <- TODO: [🥬] Make some system for hashes and ids of promptbook
|
|
2553
|
+
var semanticName = normalizeToKebabCase(knowledgeSourceContent.substring(0, 20));
|
|
2554
|
+
var pieces = ['source', semanticName, hash].filter(function (piece) { return piece !== ''; });
|
|
2555
|
+
var name = pieces.join('-').split('--').join('-');
|
|
2556
|
+
// <- TODO: Use MAX_FILENAME_LENGTH
|
|
2557
|
+
return name;
|
|
2558
|
+
}
|
|
2559
|
+
/**
|
|
2560
|
+
* TODO: [🐱🐉][🧠] Make some smart crop NOT source-i-m-pavol-a-develop-... BUT source-i-m-pavol-a-developer-...
|
|
2561
|
+
*/
|
|
2562
|
+
|
|
2563
|
+
/**
|
|
2564
|
+
* Parses the knowledge command
|
|
2565
|
+
*
|
|
2566
|
+
* @see `documentationUrl` for more details
|
|
2567
|
+
* @public exported from `@promptbook/editable`
|
|
2568
|
+
*/
|
|
2569
|
+
var knowledgeCommandParser = {
|
|
2570
|
+
/**
|
|
2571
|
+
* Name of the command
|
|
2572
|
+
*/
|
|
2573
|
+
name: 'KNOWLEDGE',
|
|
2574
|
+
/**
|
|
2575
|
+
* BOILERPLATE command can be used in:
|
|
2576
|
+
*/
|
|
2577
|
+
isUsedInPipelineHead: true,
|
|
2578
|
+
isUsedInPipelineTask: false,
|
|
2579
|
+
/**
|
|
2580
|
+
* Description of the KNOWLEDGE command
|
|
2581
|
+
*/
|
|
2582
|
+
description: "Tells promptbook which external knowledge to use",
|
|
2583
|
+
/**
|
|
2584
|
+
* Link to documentation
|
|
2585
|
+
*/
|
|
2586
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/41',
|
|
2587
|
+
/**
|
|
2588
|
+
* Example usages of the KNOWLEDGE command
|
|
2589
|
+
*/
|
|
2590
|
+
examples: [
|
|
2591
|
+
'KNOWLEDGE https://www.pavolhejny.com/',
|
|
2592
|
+
'KNOWLEDGE ./hejny-cv.txt',
|
|
2593
|
+
'KNOWLEDGE ./hejny-cv.md',
|
|
2594
|
+
'KNOWLEDGE ./hejny-cv.pdf',
|
|
2595
|
+
'KNOWLEDGE ./hejny-cv.docx',
|
|
2596
|
+
// <- TODO: [😿] Allow ONLY files scoped in the (sub)directory NOT ../ and test it
|
|
2597
|
+
],
|
|
2598
|
+
/**
|
|
2599
|
+
* Parses the KNOWLEDGE command
|
|
2600
|
+
*/
|
|
2601
|
+
parse: function (input) {
|
|
2602
|
+
var args = input.args;
|
|
2603
|
+
var knowledgeSourceContent = spaceTrim(args[0] || '');
|
|
2604
|
+
if (knowledgeSourceContent === '') {
|
|
2605
|
+
throw new ParseError("Source is not defined");
|
|
2606
|
+
}
|
|
2607
|
+
// TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
|
|
2608
|
+
if (knowledgeSourceContent.startsWith('http://')) {
|
|
2609
|
+
throw new ParseError("Source is not secure");
|
|
2610
|
+
}
|
|
2611
|
+
if (!(isValidFilePath(knowledgeSourceContent) || isValidUrl(knowledgeSourceContent))) {
|
|
2612
|
+
throw new ParseError("Source not valid");
|
|
2613
|
+
}
|
|
2614
|
+
if (knowledgeSourceContent.startsWith('../') ||
|
|
2615
|
+
knowledgeSourceContent.startsWith('/') ||
|
|
2616
|
+
/^[A-Z]:[\\/]+/i.test(knowledgeSourceContent)) {
|
|
2617
|
+
throw new ParseError("Source cannot be outside of the .book.md folder");
|
|
2618
|
+
}
|
|
2619
|
+
return {
|
|
2620
|
+
type: 'KNOWLEDGE',
|
|
2621
|
+
knowledgeSourceContent: knowledgeSourceContent,
|
|
2622
|
+
};
|
|
2623
|
+
},
|
|
2624
|
+
/**
|
|
2625
|
+
* Apply the KNOWLEDGE command to the `pipelineJson`
|
|
2626
|
+
*
|
|
2627
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
2628
|
+
*/
|
|
2629
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
2630
|
+
var knowledgeSourceContent = command.knowledgeSourceContent;
|
|
2631
|
+
$pipelineJson.knowledgeSources.push({
|
|
2632
|
+
name: knowledgeSourceContentToName(knowledgeSourceContent),
|
|
2633
|
+
knowledgeSourceContent: knowledgeSourceContent,
|
|
2634
|
+
});
|
|
2635
|
+
},
|
|
2636
|
+
/**
|
|
2637
|
+
* Converts the KNOWLEDGE command back to string
|
|
2638
|
+
*
|
|
2639
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2640
|
+
*/
|
|
2641
|
+
stringify: function (command) {
|
|
2642
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
2643
|
+
},
|
|
2644
|
+
/**
|
|
2645
|
+
* Reads the KNOWLEDGE command from the `PipelineJson`
|
|
2646
|
+
*
|
|
2647
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2648
|
+
*/
|
|
2649
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
2650
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2651
|
+
},
|
|
2652
|
+
};
|
|
2653
|
+
/**
|
|
2654
|
+
* Note: [⛱] There are two types of KNOWLEDGE commands *...(read more in [⛱])*
|
|
2655
|
+
*/
|
|
2656
|
+
|
|
2657
|
+
/**
|
|
2658
|
+
* @@@
|
|
2659
|
+
*
|
|
2660
|
+
* @public exported from `@promptbook/core`
|
|
2661
|
+
*/
|
|
2662
|
+
var MODEL_VARIANTS = ['COMPLETION', 'CHAT', 'EMBEDDING' /* <- TODO [🏳] */ /* <- [🤖] */];
|
|
2663
|
+
|
|
2664
|
+
/**
|
|
2665
|
+
* Parses the model command
|
|
2666
|
+
*
|
|
2667
|
+
* @see `documentationUrl` for more details
|
|
2668
|
+
* @deprecated Option to manually set the model requirements is not recommended to use, use `PERSONA` instead
|
|
2669
|
+
* @public exported from `@promptbook/editable`
|
|
2670
|
+
*/
|
|
2671
|
+
var modelCommandParser = {
|
|
2672
|
+
/**
|
|
2673
|
+
* Name of the command
|
|
2674
|
+
*/
|
|
2675
|
+
name: 'MODEL',
|
|
2676
|
+
/**
|
|
2677
|
+
* BOILERPLATE command can be used in:
|
|
2678
|
+
*/
|
|
2679
|
+
isUsedInPipelineHead: true,
|
|
2680
|
+
isUsedInPipelineTask: true,
|
|
2681
|
+
/**
|
|
2682
|
+
* Description of the MODEL command
|
|
2683
|
+
*/
|
|
2684
|
+
description: "Tells which `modelRequirements` (for example which model) to use for the prompt task execution",
|
|
2685
|
+
/**
|
|
2686
|
+
* Link to documentation
|
|
2687
|
+
*/
|
|
2688
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/67',
|
|
2689
|
+
/**
|
|
2690
|
+
* Example usages of the MODEL command
|
|
2691
|
+
*/
|
|
2692
|
+
examples: ['MODEL VARIANT Chat', 'MODEL NAME `gpt-4`'],
|
|
2693
|
+
/**
|
|
2694
|
+
* Parses the MODEL command
|
|
2695
|
+
*/
|
|
2696
|
+
parse: function (input) {
|
|
2697
|
+
var args = input.args, normalized = input.normalized;
|
|
2698
|
+
var availableVariantsMessage = spaceTrim(function (block) { return "\n Available variants are:\n ".concat(block(MODEL_VARIANTS.map(function (variantName) {
|
|
2699
|
+
return "- ".concat(variantName).concat(variantName !== 'EMBEDDING' ? '' : ' (Not available in pipeline)');
|
|
2700
|
+
}).join('\n')), "\n "); });
|
|
2701
|
+
// TODO: Make this more elegant and dynamically
|
|
2702
|
+
if (normalized.startsWith('MODEL_VARIANT')) {
|
|
2703
|
+
if (normalized === 'MODEL_VARIANT_CHAT') {
|
|
2704
|
+
return {
|
|
2705
|
+
type: 'MODEL',
|
|
2706
|
+
key: 'modelVariant',
|
|
2707
|
+
value: 'CHAT',
|
|
2708
|
+
};
|
|
2709
|
+
}
|
|
2710
|
+
else if (normalized === 'MODEL_VARIANT_COMPLETION') {
|
|
2711
|
+
return {
|
|
2712
|
+
type: 'MODEL',
|
|
2713
|
+
key: 'modelVariant',
|
|
2714
|
+
value: 'COMPLETION',
|
|
2715
|
+
};
|
|
2716
|
+
// <- Note: [🤖]
|
|
2717
|
+
}
|
|
2718
|
+
else if (normalized.startsWith('MODEL_VARIANT_EMBED')) {
|
|
2719
|
+
spaceTrim(function (block) { return "\n Embedding model can not be used in pipeline\n\n ".concat(block(availableVariantsMessage), "\n "); });
|
|
2720
|
+
}
|
|
2721
|
+
else {
|
|
2722
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Unknown model variant in command:\n\n ".concat(block(availableVariantsMessage), "\n "); }));
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
if (normalized.startsWith('MODEL_NAME')) {
|
|
2726
|
+
return {
|
|
2727
|
+
type: 'MODEL',
|
|
2728
|
+
key: 'modelName',
|
|
2729
|
+
value: args.pop(),
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
else {
|
|
2733
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Unknown model key in command.\n\n Supported model keys are:\n ".concat(block(['variant', 'name'].join(', ')), "\n\n Example:\n - MODEL VARIANT Chat\n - MODEL NAME gpt-4\n "); }));
|
|
2734
|
+
}
|
|
2735
|
+
},
|
|
2736
|
+
/**
|
|
2737
|
+
* Apply the MODEL command to the `pipelineJson`
|
|
2738
|
+
*
|
|
2739
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
2740
|
+
*/
|
|
2741
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
2742
|
+
$pipelineJson.defaultModelRequirements = $pipelineJson.defaultModelRequirements || {};
|
|
2743
|
+
// TODO: [🚜] DRY
|
|
2744
|
+
if ($pipelineJson.defaultModelRequirements[command.key] !== undefined) {
|
|
2745
|
+
if ($pipelineJson.defaultModelRequirements[command.key] === command.value) {
|
|
2746
|
+
console.warn("Multiple commands `MODEL ".concat(command.key, " ").concat(command.value, "` in the pipeline head"));
|
|
2747
|
+
// <- TODO: [🚎][💩] Some better way how to get warnings from pipeline parsing / logic
|
|
2748
|
+
}
|
|
2749
|
+
else {
|
|
2750
|
+
throw new ParseError(spaceTrim("\n Redefinition of `MODEL ".concat(command.key, "` in the pipeline head\n\n You have used:\n 1) `MODEL ").concat(command.key, " ").concat($pipelineJson.defaultModelRequirements[command.key], "`\n 2) `MODEL ").concat(command.key, " ").concat(command.value, "`\n ")));
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
$pipelineJson.defaultModelRequirements[command.key] = command.value;
|
|
2754
|
+
},
|
|
2755
|
+
/**
|
|
2756
|
+
* Apply the MODEL command to the `pipelineJson`
|
|
2757
|
+
*
|
|
2758
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
2759
|
+
*/
|
|
2760
|
+
$applyToTaskJson: function (command, $taskJson, $pipelineJson) {
|
|
2761
|
+
if ($taskJson.taskType !== 'PROMPT_TASK') {
|
|
2762
|
+
throw new ParseError("MODEL command can only be used in PROMPT_TASK block");
|
|
2763
|
+
}
|
|
2764
|
+
$taskJson.modelRequirements = $taskJson.modelRequirements || {};
|
|
2765
|
+
// TODO: [🚜] DRY
|
|
2766
|
+
if ($taskJson.modelRequirements[command.key] !== undefined) {
|
|
2767
|
+
if ($taskJson.modelRequirements[command.key] === command.value) {
|
|
2768
|
+
console.warn("Multiple commands `MODEL ".concat({
|
|
2769
|
+
modelName: 'NAME',
|
|
2770
|
+
modelVariant: 'VARIANT',
|
|
2771
|
+
maxTokens: '???',
|
|
2772
|
+
}[command.key], " ").concat(command.value, "` in the task \"").concat($taskJson.title || $taskJson.name, "\""));
|
|
2773
|
+
}
|
|
2774
|
+
else {
|
|
2775
|
+
throw new ParseError(spaceTrim("\n Redefinition of MODEL `".concat(command.key, "` in the task \"").concat($taskJson.title || $taskJson.name, "\"\n\n You have used:\n - MODEL ").concat(command.key, " ").concat($taskJson.modelRequirements[command.key], "\n - MODEL ").concat(command.key, " ").concat(command.value, "\n ")));
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
if (command.value === ($pipelineJson.defaultModelRequirements || {})[command.key]) {
|
|
2779
|
+
console.log(spaceTrim("\n Setting MODEL `".concat(command.key, "` in the task \"").concat($taskJson.title || $taskJson.name, "\" to the same value as in the pipeline head\n\n In pipeline head:\n - MODEL ").concat(command.key, " ").concat(($pipelineJson.defaultModelRequirements || {})[command.key], "\n\n But same value is used in the task:\n - MODEL ").concat(command.key, " ").concat(command.value, "\n ")));
|
|
2780
|
+
}
|
|
2781
|
+
$taskJson.modelRequirements[command.key] = command.value;
|
|
2782
|
+
},
|
|
2783
|
+
/**
|
|
2784
|
+
* Converts the MODEL command back to string
|
|
2785
|
+
*
|
|
2786
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2787
|
+
*/
|
|
2788
|
+
stringify: function (command) {
|
|
2789
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
2790
|
+
},
|
|
2791
|
+
/**
|
|
2792
|
+
* Reads the MODEL command from the `PipelineJson`
|
|
2793
|
+
*
|
|
2794
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2795
|
+
*/
|
|
2796
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
2797
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2798
|
+
},
|
|
2799
|
+
/**
|
|
2800
|
+
* Reads the MODEL command from the `TaskJson`
|
|
2801
|
+
*
|
|
2802
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2803
|
+
*/
|
|
2804
|
+
takeFromTaskJson: function ($taskJson) {
|
|
2805
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2806
|
+
},
|
|
2807
|
+
};
|
|
2808
|
+
|
|
2809
|
+
/**
|
|
2810
|
+
* Parses the parameter command
|
|
2811
|
+
*
|
|
2812
|
+
* @see `documentationUrl` for more details
|
|
2813
|
+
* @public exported from `@promptbook/editable`
|
|
2814
|
+
*/
|
|
2815
|
+
var parameterCommandParser = {
|
|
2816
|
+
/**
|
|
2817
|
+
* Name of the command
|
|
2818
|
+
*/
|
|
2819
|
+
name: 'PARAMETER',
|
|
2820
|
+
/**
|
|
2821
|
+
* Aliases for the PARAMETER command
|
|
2822
|
+
*/
|
|
2823
|
+
aliasNames: ['PARAM', 'INPUT_PARAM', 'OUTPUT_PARAM', 'INPUT_PARAMETER', 'OUTPUT_PARAMETER'],
|
|
2824
|
+
/*
|
|
2825
|
+
Note: [🦈] No need for extra alias name because it is already preprocessed
|
|
2826
|
+
*/
|
|
2827
|
+
/**
|
|
2828
|
+
* BOILERPLATE command can be used in:
|
|
2829
|
+
*/
|
|
2830
|
+
isUsedInPipelineHead: true,
|
|
2831
|
+
isUsedInPipelineTask: true,
|
|
2832
|
+
/**
|
|
2833
|
+
* Description of the PARAMETER command
|
|
2834
|
+
*/
|
|
2835
|
+
description: "Describes one parameter of the task",
|
|
2836
|
+
/**
|
|
2837
|
+
* Link to documentation
|
|
2838
|
+
*/
|
|
2839
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/68',
|
|
2840
|
+
/**
|
|
2841
|
+
* Example usages of the PARAMETER command
|
|
2842
|
+
*/
|
|
2843
|
+
examples: ['PARAMETER {title} Title of the book', 'OUTPUT PARAMETER {websiteContent} Content of the book'],
|
|
2844
|
+
/**
|
|
2845
|
+
* Parses the PARAMETER command
|
|
2846
|
+
*/
|
|
2847
|
+
parse: function (input) {
|
|
2848
|
+
var normalized = input.normalized, args = input.args, raw = input.raw;
|
|
2849
|
+
var parameterNameRaw = args.shift() || '';
|
|
2850
|
+
var parameterDescriptionRaw = args.join(' ');
|
|
2851
|
+
// <- TODO: When [🥶] fixed, change to:
|
|
2852
|
+
// > const parameterDescriptionRaw = rawArgs.split(parameterNameRaw).join('').trim();
|
|
2853
|
+
if (parameterDescriptionRaw && parameterDescriptionRaw.match(/\{(?<embeddedParameterName>[a-z0-9_]+)\}/im)) {
|
|
2854
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Parameter `{".concat(parameterNameRaw, "}` can not contain another parameter in description\n\n The description:\n ").concat(block(parameterDescriptionRaw), "\n "); }));
|
|
2855
|
+
}
|
|
2856
|
+
var isInput = normalized.startsWith('INPUT');
|
|
2857
|
+
var isOutput = normalized.startsWith('OUTPUT');
|
|
2858
|
+
if (raw.startsWith('> {')) {
|
|
2859
|
+
isInput = false;
|
|
2860
|
+
isOutput = false;
|
|
2861
|
+
}
|
|
2862
|
+
var parameterName = validateParameterName(parameterNameRaw);
|
|
2863
|
+
var parameterDescription = parameterDescriptionRaw.trim() || null;
|
|
2864
|
+
return {
|
|
2865
|
+
type: 'PARAMETER',
|
|
2866
|
+
parameterName: parameterName,
|
|
2867
|
+
parameterDescription: parameterDescription,
|
|
2868
|
+
isInput: isInput,
|
|
2869
|
+
isOutput: isOutput,
|
|
2870
|
+
};
|
|
2871
|
+
},
|
|
2872
|
+
/**
|
|
2873
|
+
* Apply the PARAMETER command to the `pipelineJson`
|
|
2874
|
+
*
|
|
2875
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
2876
|
+
*/
|
|
2877
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
2878
|
+
// Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
|
|
2879
|
+
},
|
|
2880
|
+
/**
|
|
2881
|
+
* Apply the PARAMETER command to the `pipelineJson`
|
|
2882
|
+
*
|
|
2883
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
2884
|
+
*/
|
|
2885
|
+
$applyToTaskJson: function (command, $taskJson, $pipelineJson) {
|
|
2886
|
+
// Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
|
|
2887
|
+
},
|
|
2888
|
+
/**
|
|
2889
|
+
* Converts the PARAMETER command back to string
|
|
2890
|
+
*
|
|
2891
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2892
|
+
*/
|
|
2893
|
+
stringify: function (command) {
|
|
2894
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
2895
|
+
},
|
|
2896
|
+
/**
|
|
2897
|
+
* Reads the PARAMETER command from the `PipelineJson`
|
|
2898
|
+
*
|
|
2899
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2900
|
+
*/
|
|
2901
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
2902
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2903
|
+
},
|
|
2904
|
+
/**
|
|
2905
|
+
* Reads the PARAMETER command from the `TaskJson`
|
|
2906
|
+
*
|
|
2907
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2908
|
+
*/
|
|
2909
|
+
takeFromTaskJson: function ($taskJson) {
|
|
2910
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2911
|
+
},
|
|
2912
|
+
};
|
|
2913
|
+
|
|
2914
|
+
/**
|
|
2915
|
+
* Parses the persona command
|
|
2916
|
+
*
|
|
2917
|
+
* @see `documentationUrl` for more details
|
|
2918
|
+
* @public exported from `@promptbook/editable`
|
|
2919
|
+
*/
|
|
2920
|
+
var personaCommandParser = {
|
|
2921
|
+
/**
|
|
2922
|
+
* Name of the command
|
|
2923
|
+
*/
|
|
2924
|
+
name: 'PERSONA',
|
|
2925
|
+
/**
|
|
2926
|
+
* Aliases for the PERSONA command
|
|
2927
|
+
*/
|
|
2928
|
+
aliasNames: ['PERSON'],
|
|
2929
|
+
/**
|
|
2930
|
+
* PERSONA command can be used in:
|
|
2931
|
+
*/
|
|
2932
|
+
isUsedInPipelineHead: true,
|
|
2933
|
+
isUsedInPipelineTask: true,
|
|
2934
|
+
/**
|
|
2935
|
+
* Description of the PERSONA command
|
|
2936
|
+
*/
|
|
2937
|
+
description: "Persona command is used to specify who the system is, it will be transformed into system message, top_t,...",
|
|
2938
|
+
/**
|
|
2939
|
+
* Link to documentation
|
|
2940
|
+
*/
|
|
2941
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/22',
|
|
2942
|
+
/**
|
|
2943
|
+
* Example usages of the PERSONA command
|
|
2944
|
+
*/
|
|
2945
|
+
examples: ['PERSONA Jane, skilled copywriter', 'PERSONA Joe, male 28 years old, programmer'],
|
|
2946
|
+
/**
|
|
2947
|
+
* Parses the PERSONA command
|
|
2948
|
+
*/
|
|
2949
|
+
parse: function (input) {
|
|
2950
|
+
var rawArgs = input.rawArgs;
|
|
2951
|
+
var _a = __read(rawArgs.split(/[,;:]/, 2), 2), personaNameRaw = _a[0], personaDescriptionRaw = _a[1];
|
|
2952
|
+
var personaName = (personaNameRaw || '').trim();
|
|
2953
|
+
if (personaName === '') {
|
|
2954
|
+
throw new ParseError("You must set name for the persona");
|
|
2955
|
+
}
|
|
2956
|
+
var personaDescription = (personaDescriptionRaw || '').trim();
|
|
2957
|
+
if (personaDescription === '') {
|
|
2958
|
+
personaDescription = null;
|
|
2959
|
+
}
|
|
2960
|
+
return {
|
|
2961
|
+
type: 'PERSONA',
|
|
2962
|
+
personaName: personaName,
|
|
2963
|
+
personaDescription: personaDescription,
|
|
2964
|
+
};
|
|
2965
|
+
},
|
|
2966
|
+
/**
|
|
2967
|
+
* Apply the PERSONA command to the `pipelineJson`
|
|
2968
|
+
*
|
|
2969
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
2970
|
+
*/
|
|
2971
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
2972
|
+
$applyToTaskJson(command, null, $pipelineJson);
|
|
2973
|
+
},
|
|
2974
|
+
$applyToTaskJson: $applyToTaskJson,
|
|
2975
|
+
/**
|
|
2976
|
+
* Converts the PERSONA command back to string
|
|
2977
|
+
*
|
|
2978
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2979
|
+
*/
|
|
2980
|
+
stringify: function (command) {
|
|
2981
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
2982
|
+
},
|
|
2983
|
+
/**
|
|
2984
|
+
* Reads the PERSONA command from the `PipelineJson`
|
|
2985
|
+
*
|
|
2986
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2987
|
+
*/
|
|
2988
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
2989
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2990
|
+
},
|
|
2991
|
+
/**
|
|
2992
|
+
* Reads the PERSONA command from the `TaskJson`
|
|
2993
|
+
*
|
|
2994
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
2995
|
+
*/
|
|
2996
|
+
takeFromTaskJson: function ($taskJson) {
|
|
2997
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
2998
|
+
},
|
|
2999
|
+
};
|
|
3000
|
+
/**
|
|
3001
|
+
* Apply the PERSONA command to the `pipelineJson`
|
|
3002
|
+
*
|
|
3003
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
3004
|
+
*/
|
|
3005
|
+
function $applyToTaskJson(command, $taskJson, $pipelineJson) {
|
|
3006
|
+
var personaName = command.personaName, personaDescription = command.personaDescription;
|
|
3007
|
+
if ($taskJson !== null) {
|
|
3008
|
+
if ($taskJson.taskType !== 'PROMPT_TASK') {
|
|
3009
|
+
throw new ParseError("PERSONA command can be used only in PROMPT_TASK block");
|
|
3010
|
+
}
|
|
3011
|
+
$taskJson.personaName = personaName;
|
|
3012
|
+
}
|
|
3013
|
+
var persona = $pipelineJson.personas.find(function (persona) { return persona.name === personaName; });
|
|
3014
|
+
if (persona === undefined) {
|
|
3015
|
+
$pipelineJson.personas.push({
|
|
3016
|
+
name: personaName,
|
|
3017
|
+
description: personaDescription || '',
|
|
3018
|
+
});
|
|
3019
|
+
return;
|
|
3020
|
+
}
|
|
3021
|
+
if (persona.description === personaDescription) {
|
|
3022
|
+
return;
|
|
3023
|
+
}
|
|
3024
|
+
if (personaDescription === null) {
|
|
3025
|
+
return;
|
|
3026
|
+
}
|
|
3027
|
+
if (persona.description === '') {
|
|
3028
|
+
persona.description = personaDescription;
|
|
3029
|
+
return;
|
|
3030
|
+
}
|
|
3031
|
+
console.warn(spaceTrim("\n\n Persona \"".concat(personaName, "\" is defined multiple times with different description:\n\n First definition:\n ").concat(persona.description, "\n\n Second definition:\n ").concat(personaDescription, "\n\n ")));
|
|
3032
|
+
persona.description += spaceTrim('\n\n' + personaDescription);
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
/**
|
|
3036
|
+
* @@@
|
|
3037
|
+
*
|
|
3038
|
+
* @param javascriptName @@@
|
|
3039
|
+
* @returns @@@
|
|
3040
|
+
* @public exported from `@promptbook/utils`
|
|
3041
|
+
*/
|
|
3042
|
+
function isValidJavascriptName(javascriptName) {
|
|
3043
|
+
if (typeof javascriptName !== 'string') {
|
|
3044
|
+
return false;
|
|
3045
|
+
}
|
|
3046
|
+
return /^[a-zA-Z_$][0-9a-zA-Z_$]*$/i.test(javascriptName);
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
/**
|
|
3050
|
+
* Parses the postprocess command
|
|
3051
|
+
*
|
|
3052
|
+
* @see `documentationUrl` for more details
|
|
3053
|
+
* @public exported from `@promptbook/editable`
|
|
3054
|
+
*/
|
|
3055
|
+
var postprocessCommandParser = {
|
|
3056
|
+
/**
|
|
3057
|
+
* Name of the command
|
|
3058
|
+
*/
|
|
3059
|
+
name: 'POSTPROCESS',
|
|
3060
|
+
aliasNames: ['POSTPROCESSING', 'PP'],
|
|
3061
|
+
/**
|
|
3062
|
+
* BOILERPLATE command can be used in:
|
|
3063
|
+
*/
|
|
3064
|
+
isUsedInPipelineHead: false,
|
|
3065
|
+
isUsedInPipelineTask: true,
|
|
3066
|
+
/**
|
|
3067
|
+
* Description of the POSTPROCESS command
|
|
3068
|
+
*/
|
|
3069
|
+
description: "Defines the postprocess function to be used on the result from LLM and before the result is validated",
|
|
3070
|
+
/**
|
|
3071
|
+
* Link to documentation
|
|
3072
|
+
*/
|
|
3073
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/31',
|
|
3074
|
+
/**
|
|
3075
|
+
* Example usages of the POSTPROCESS command
|
|
3076
|
+
*/
|
|
3077
|
+
examples: [
|
|
3078
|
+
'POSTPROCESS unwrapResult' /* <- TODO: Make it `POSTPROCESS` examples dynamic, load from all possible postprocess functions */,
|
|
3079
|
+
],
|
|
3080
|
+
/**
|
|
3081
|
+
* Parses the POSTPROCESS command
|
|
3082
|
+
*/
|
|
3083
|
+
parse: function (input) {
|
|
3084
|
+
var args = input.args;
|
|
3085
|
+
var functionName = args.pop();
|
|
3086
|
+
if (functionName === undefined) {
|
|
3087
|
+
throw new ParseError("Postprocess function name is required");
|
|
3088
|
+
}
|
|
3089
|
+
if (!isValidJavascriptName(functionName)) {
|
|
3090
|
+
throw new ParseError("Invalid postprocess function name \"".concat(functionName, "\""));
|
|
3091
|
+
}
|
|
3092
|
+
if (args.length > 0) {
|
|
3093
|
+
throw new ParseError("Can not have more than one postprocess function");
|
|
3094
|
+
}
|
|
3095
|
+
return {
|
|
3096
|
+
type: 'POSTPROCESS',
|
|
3097
|
+
functionName: functionName,
|
|
3098
|
+
};
|
|
3099
|
+
},
|
|
3100
|
+
/**
|
|
3101
|
+
* Apply the POSTPROCESS command to the `pipelineJson`
|
|
3102
|
+
*
|
|
3103
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
3104
|
+
*/
|
|
3105
|
+
$applyToTaskJson: function (command, $taskJson) {
|
|
3106
|
+
$taskJson.postprocessingFunctionNames = $taskJson.postprocessingFunctionNames || [];
|
|
3107
|
+
$taskJson.postprocessingFunctionNames.push(command.functionName);
|
|
3108
|
+
},
|
|
3109
|
+
/**
|
|
3110
|
+
* Converts the POSTPROCESS command back to string
|
|
3111
|
+
*
|
|
3112
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3113
|
+
*/
|
|
3114
|
+
stringify: function (command) {
|
|
3115
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
3116
|
+
},
|
|
3117
|
+
/**
|
|
3118
|
+
* Reads the POSTPROCESS command from the `TaskJson`
|
|
3119
|
+
*
|
|
3120
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3121
|
+
*/
|
|
3122
|
+
takeFromTaskJson: function ($taskJson) {
|
|
3123
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
3124
|
+
},
|
|
3125
|
+
};
|
|
3126
|
+
|
|
3127
|
+
/**
|
|
3128
|
+
* All available task types
|
|
3129
|
+
*
|
|
3130
|
+
* There is is distinction between task types and section types
|
|
3131
|
+
* - Every section in markdown has its SectionType
|
|
3132
|
+
* - Some sections are tasks but other can be non-task sections
|
|
3133
|
+
*
|
|
3134
|
+
* @public exported from `@promptbook/core`
|
|
3135
|
+
*/
|
|
3136
|
+
var TaskTypes = [
|
|
3137
|
+
'PROMPT',
|
|
3138
|
+
'SIMPLE',
|
|
3139
|
+
'SCRIPT',
|
|
3140
|
+
'DIALOG',
|
|
3141
|
+
// <- [🅱]
|
|
3142
|
+
];
|
|
3143
|
+
|
|
3144
|
+
/**
|
|
3145
|
+
* All available sections which are not tasks
|
|
3146
|
+
*
|
|
3147
|
+
* @public exported from `@promptbook/core`
|
|
3148
|
+
*/
|
|
3149
|
+
var NonTaskSectionTypes = ['EXAMPLE', 'KNOWLEDGE', 'INSTRUMENT', 'ACTION'];
|
|
3150
|
+
/**
|
|
3151
|
+
* All available section types
|
|
3152
|
+
*
|
|
3153
|
+
* There is is distinction between task types and section types
|
|
3154
|
+
* - Every section in markdown has its SectionType
|
|
3155
|
+
* - Some sections are tasks but other can be non-task sections
|
|
3156
|
+
*
|
|
3157
|
+
* @public exported from `@promptbook/core`
|
|
3158
|
+
*/
|
|
3159
|
+
var SectionTypes = __spreadArray(__spreadArray([], __read(TaskTypes.map(function (TaskType) { return "".concat(TaskType, "_TASK"); })), false), __read(NonTaskSectionTypes), false);
|
|
3160
|
+
|
|
3161
|
+
/**
|
|
3162
|
+
* Parses the section command
|
|
3163
|
+
*
|
|
3164
|
+
* @see `documentationUrl` for more details
|
|
3165
|
+
* @public exported from `@promptbook/editable`
|
|
3166
|
+
*/
|
|
3167
|
+
var sectionCommandParser = {
|
|
3168
|
+
/**
|
|
3169
|
+
* Name of the command
|
|
3170
|
+
*/
|
|
3171
|
+
name: 'SECTION',
|
|
3172
|
+
/**
|
|
3173
|
+
* Aliases for the SECTION command
|
|
3174
|
+
*/
|
|
3175
|
+
aliasNames: [
|
|
3176
|
+
'PROMPT',
|
|
3177
|
+
'SIMPLE',
|
|
3178
|
+
'SCRIPT',
|
|
3179
|
+
'DIALOG',
|
|
3180
|
+
'SAMPLE',
|
|
3181
|
+
'EXAMPLE',
|
|
3182
|
+
'KNOWLEDGE',
|
|
3183
|
+
'INSTRUMENT',
|
|
3184
|
+
'ACTION', // <- Note: [⛱]
|
|
3185
|
+
],
|
|
3186
|
+
/**
|
|
3187
|
+
* Aliases for the SECTION command
|
|
3188
|
+
*/
|
|
3189
|
+
deprecatedNames: ['TEMPLATE', 'BLOCK', 'EXECUTE'],
|
|
3190
|
+
/**
|
|
3191
|
+
* BOILERPLATE command can be used in:
|
|
3192
|
+
*/
|
|
3193
|
+
isUsedInPipelineHead: false,
|
|
3194
|
+
isUsedInPipelineTask: true,
|
|
3195
|
+
/**
|
|
3196
|
+
* Description of the SECTION command
|
|
3197
|
+
*/
|
|
3198
|
+
description: "Defines the purpose of the markdown section - if its a task and which type or something else",
|
|
3199
|
+
/**
|
|
3200
|
+
* Link to documentation
|
|
3201
|
+
*/
|
|
3202
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/64',
|
|
3203
|
+
/**
|
|
3204
|
+
* Example usages of the SECTION command
|
|
3205
|
+
*/
|
|
3206
|
+
examples: [
|
|
3207
|
+
// Short form:
|
|
3208
|
+
'PROMPT',
|
|
3209
|
+
'SIMPLE',
|
|
3210
|
+
'SCRIPT',
|
|
3211
|
+
'DIALOG',
|
|
3212
|
+
// <- [🅱]
|
|
3213
|
+
'EXAMPLE',
|
|
3214
|
+
'KNOWLEDGE',
|
|
3215
|
+
'INSTRUMENT',
|
|
3216
|
+
'ACTION',
|
|
3217
|
+
// -----------------
|
|
3218
|
+
// Recommended (reversed) form:
|
|
3219
|
+
'PROMPT SECTION',
|
|
3220
|
+
'SIMPLE SECTION',
|
|
3221
|
+
'SCRIPT SECTION',
|
|
3222
|
+
'DIALOG SECTION',
|
|
3223
|
+
// <- [🅱]
|
|
3224
|
+
'EXAMPLE SECTION',
|
|
3225
|
+
'KNOWLEDGE SECTION',
|
|
3226
|
+
'INSTRUMENT SECTION',
|
|
3227
|
+
'ACTION SECTION',
|
|
3228
|
+
// -----------------
|
|
3229
|
+
// Standard form:
|
|
3230
|
+
'SECTION PROMPT',
|
|
3231
|
+
'SECTION SIMPLE',
|
|
3232
|
+
'SECTION SCRIPT',
|
|
3233
|
+
'SECTION DIALOG',
|
|
3234
|
+
// <- [🅱]
|
|
3235
|
+
'SECTION EXAMPLE',
|
|
3236
|
+
'SECTION KNOWLEDGE',
|
|
3237
|
+
'SECTION INSTRUMENT',
|
|
3238
|
+
'SECTION ACTION',
|
|
3239
|
+
],
|
|
3240
|
+
// TODO: [♓️] order: -10 /* <- Note: Putting before other commands */
|
|
3241
|
+
/**
|
|
3242
|
+
* Parses the SECTION command
|
|
3243
|
+
*/
|
|
3244
|
+
parse: function (input) {
|
|
3245
|
+
var normalized = input.normalized;
|
|
3246
|
+
normalized = normalized.split('SAMPLE').join('EXAMPLE');
|
|
3247
|
+
normalized = normalized.split('EXECUTE_').join('');
|
|
3248
|
+
normalized = normalized.split('DIALOGUE').join('DIALOG');
|
|
3249
|
+
var taskTypes = SectionTypes.filter(function (sectionType) {
|
|
3250
|
+
return normalized.includes(sectionType.split('_TASK').join(''));
|
|
3251
|
+
});
|
|
3252
|
+
if (taskTypes.length !== 1) {
|
|
3253
|
+
throw new ParseError(spaceTrim(function (block) { return "\n Unknown section type \"".concat(normalized, "\"\n\n Supported section types are:\n ").concat(block(SectionTypes.join(', ')), "\n "); }));
|
|
3254
|
+
}
|
|
3255
|
+
var taskType = taskTypes[0];
|
|
3256
|
+
return {
|
|
3257
|
+
type: 'SECTION',
|
|
3258
|
+
taskType: taskType,
|
|
3259
|
+
};
|
|
3260
|
+
},
|
|
3261
|
+
/**
|
|
3262
|
+
* Apply the SECTION command to the `pipelineJson`
|
|
3263
|
+
*
|
|
3264
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
3265
|
+
*/
|
|
3266
|
+
$applyToTaskJson: function (command, $taskJson, $pipelineJson) {
|
|
3267
|
+
if ($taskJson.isSectionTypeSet === true) {
|
|
3268
|
+
throw new ParseError(spaceTrim("\n Section type is already defined in the section.\n It can be defined only once.\n "));
|
|
3269
|
+
}
|
|
3270
|
+
$taskJson.isSectionTypeSet = true;
|
|
3271
|
+
// TODO: [🍧][💩] Rearrange better - but at bottom and unwrap from function
|
|
3272
|
+
var expectResultingParameterName = function () {
|
|
3273
|
+
if ($taskJson.resultingParameterName) {
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
throw new ParseError("Task section and example section must end with return statement -> {parameterName}");
|
|
3277
|
+
};
|
|
3278
|
+
if ($taskJson.content === undefined) {
|
|
3279
|
+
throw new UnexpectedError("Content is missing in the taskJson - probbably commands are applied in wrong order");
|
|
3280
|
+
}
|
|
3281
|
+
if (command.taskType === 'EXAMPLE') {
|
|
3282
|
+
expectResultingParameterName();
|
|
3283
|
+
var parameter = $pipelineJson.parameters.find(function (param) { return param.name === $taskJson.resultingParameterName; });
|
|
3284
|
+
if (parameter === undefined) {
|
|
3285
|
+
// TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
|
|
3286
|
+
throw new ParseError("Parameter `{".concat($taskJson.resultingParameterName, "}` is not defined so can not define example value of it"));
|
|
3287
|
+
}
|
|
3288
|
+
parameter.exampleValues = parameter.exampleValues || [];
|
|
3289
|
+
parameter.exampleValues.push($taskJson.content);
|
|
3290
|
+
$taskJson.isTask = false;
|
|
3291
|
+
return;
|
|
3292
|
+
}
|
|
3293
|
+
if (command.taskType === 'KNOWLEDGE') {
|
|
3294
|
+
knowledgeCommandParser.$applyToPipelineJson({
|
|
3295
|
+
type: 'KNOWLEDGE',
|
|
3296
|
+
knowledgeSourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
|
|
3297
|
+
}, $pipelineJson);
|
|
3298
|
+
$taskJson.isTask = false;
|
|
3299
|
+
return;
|
|
3300
|
+
}
|
|
3301
|
+
if (command.taskType === 'ACTION') {
|
|
3302
|
+
console.error(new NotYetImplementedError('Actions are not implemented yet'));
|
|
3303
|
+
$taskJson.isTask = false;
|
|
3304
|
+
return;
|
|
3305
|
+
}
|
|
3306
|
+
if (command.taskType === 'INSTRUMENT') {
|
|
3307
|
+
console.error(new NotYetImplementedError('Instruments are not implemented yet'));
|
|
3308
|
+
$taskJson.isTask = false;
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
expectResultingParameterName();
|
|
3312
|
+
$taskJson.taskType = command.taskType;
|
|
3313
|
+
$taskJson.isTask = true;
|
|
3314
|
+
},
|
|
3315
|
+
/**
|
|
3316
|
+
* Converts the SECTION command back to string
|
|
3317
|
+
*
|
|
3318
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3319
|
+
*/
|
|
3320
|
+
stringify: function (command) {
|
|
3321
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
3322
|
+
},
|
|
3323
|
+
/**
|
|
3324
|
+
* Reads the SECTION command from the `TaskJson`
|
|
3325
|
+
*
|
|
3326
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3327
|
+
*/
|
|
3328
|
+
takeFromTaskJson: function ($taskJson) {
|
|
3329
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
3330
|
+
},
|
|
3331
|
+
};
|
|
3332
|
+
/**
|
|
3333
|
+
* Note: [⛱] There are two types of KNOWLEDGE, ACTION and INSTRUMENT commands:
|
|
3334
|
+
* 1) There are commands `KNOWLEDGE`, `ACTION` and `INSTRUMENT` used in the pipeline head, they just define the knowledge, action or instrument as single line after the command
|
|
3335
|
+
* - KNOWLEDGE Look at https://en.wikipedia.org/wiki/Artificial_intelligence
|
|
3336
|
+
* 2) `KNOWLEDGE SECTION` which has short form `KNOWLEDGE` is used in the sectiom, does not refer the line itself, but the content of the section block
|
|
3337
|
+
* - KNOWLEDGE SECTION
|
|
3338
|
+
*
|
|
3339
|
+
* ```
|
|
3340
|
+
* Look at https://en.wikipedia.org/wiki/Artificial_intelligence
|
|
3341
|
+
* ```
|
|
3342
|
+
*/
|
|
3343
|
+
|
|
3344
|
+
/**
|
|
3345
|
+
* Checks if an URL is reserved for private networks or localhost.
|
|
3346
|
+
*
|
|
3347
|
+
* Note: There are two simmilar functions:
|
|
3348
|
+
* - `isUrlOnPrivateNetwork` which tests full URL
|
|
3349
|
+
* - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
|
|
3350
|
+
*
|
|
3351
|
+
* @public exported from `@promptbook/utils`
|
|
3352
|
+
*/
|
|
3353
|
+
function isHostnameOnPrivateNetwork(hostname) {
|
|
3354
|
+
if (hostname === 'example.com' ||
|
|
3355
|
+
hostname === 'localhost' ||
|
|
3356
|
+
hostname.endsWith('.localhost') ||
|
|
3357
|
+
hostname.endsWith('.local') ||
|
|
3358
|
+
hostname.endsWith('.test') ||
|
|
3359
|
+
hostname === '127.0.0.1' ||
|
|
3360
|
+
hostname === '::1') {
|
|
3361
|
+
return true;
|
|
3362
|
+
}
|
|
3363
|
+
if (hostname.includes(':')) {
|
|
3364
|
+
// IPv6
|
|
3365
|
+
var ipParts = hostname.split(':');
|
|
3366
|
+
return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
|
|
3367
|
+
}
|
|
3368
|
+
else {
|
|
3369
|
+
// IPv4
|
|
3370
|
+
var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
|
|
3371
|
+
return (ipParts[0] === 10 ||
|
|
3372
|
+
(ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
|
|
3373
|
+
(ipParts[0] === 192 && ipParts[1] === 168));
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3377
|
+
/**
|
|
3378
|
+
* Checks if an IP address or hostname is reserved for private networks or localhost.
|
|
3379
|
+
*
|
|
3380
|
+
* Note: There are two simmilar functions:
|
|
3381
|
+
* - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
|
|
3382
|
+
* - `isHostnameOnPrivateNetwork` which tests just hostname
|
|
3383
|
+
*
|
|
3384
|
+
* @param {string} ipAddress - The IP address to check.
|
|
3385
|
+
* @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
|
|
3386
|
+
* @public exported from `@promptbook/utils`
|
|
3387
|
+
*/
|
|
3388
|
+
function isUrlOnPrivateNetwork(url) {
|
|
3389
|
+
if (typeof url === 'string') {
|
|
3390
|
+
url = new URL(url);
|
|
3391
|
+
}
|
|
3392
|
+
return isHostnameOnPrivateNetwork(url.hostname);
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
/**
|
|
3396
|
+
* Tests if given string is valid pipeline URL URL.
|
|
3397
|
+
*
|
|
3398
|
+
* Note: There are two simmilar functions:
|
|
3399
|
+
* - `isValidUrl` which tests any URL
|
|
3400
|
+
* - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
|
|
3401
|
+
*
|
|
3402
|
+
* @public exported from `@promptbook/utils`
|
|
3403
|
+
*/
|
|
3404
|
+
function isValidPipelineUrl(url) {
|
|
3405
|
+
if (!isValidUrl(url)) {
|
|
3406
|
+
return false;
|
|
3407
|
+
}
|
|
3408
|
+
if (!url.startsWith('https://')) {
|
|
3409
|
+
return false;
|
|
3410
|
+
}
|
|
3411
|
+
if (url.includes('#')) {
|
|
3412
|
+
// TODO: [🐠]
|
|
3413
|
+
return false;
|
|
3414
|
+
}
|
|
3415
|
+
if (isUrlOnPrivateNetwork(url)) {
|
|
3416
|
+
return false;
|
|
3417
|
+
}
|
|
3418
|
+
return true;
|
|
3419
|
+
}
|
|
3420
|
+
/**
|
|
3421
|
+
* TODO: [🐠] Maybe more info why the URL is invalid
|
|
3422
|
+
*/
|
|
3423
|
+
|
|
3424
|
+
/**
|
|
3425
|
+
* Parses the url command
|
|
3426
|
+
*
|
|
3427
|
+
* @see `documentationUrl` for more details
|
|
3428
|
+
* @public exported from `@promptbook/editable`
|
|
3429
|
+
*/
|
|
3430
|
+
var urlCommandParser = {
|
|
3431
|
+
/**
|
|
3432
|
+
* Name of the command
|
|
3433
|
+
*/
|
|
3434
|
+
name: 'URL',
|
|
3435
|
+
aliasNames: ['PIPELINE_URL'],
|
|
3436
|
+
/*
|
|
3437
|
+
Note: [🛵] No need for this alias name because it is already preprocessed
|
|
3438
|
+
aliasNames: ['HTTPS'],
|
|
3439
|
+
*/
|
|
3440
|
+
/**
|
|
3441
|
+
* BOILERPLATE command can be used in:
|
|
3442
|
+
*/
|
|
3443
|
+
isUsedInPipelineHead: true,
|
|
3444
|
+
isUsedInPipelineTask: false,
|
|
3445
|
+
/**
|
|
3446
|
+
* Description of the URL command
|
|
3447
|
+
*/
|
|
3448
|
+
description: "Declares unique URL for the pipeline",
|
|
3449
|
+
/**
|
|
3450
|
+
* Link to documentation
|
|
3451
|
+
*/
|
|
3452
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/70',
|
|
3453
|
+
/**
|
|
3454
|
+
* Example usages of the URL command
|
|
3455
|
+
*/
|
|
3456
|
+
examples: [
|
|
3457
|
+
'PIPELINE URL https://promptbook.studio/library/write-cv.book.md',
|
|
3458
|
+
'URL https://promptbook.studio/library/write-cv.book.md',
|
|
3459
|
+
'https://promptbook.studio/library/write-cv.book.md',
|
|
3460
|
+
],
|
|
3461
|
+
/**
|
|
3462
|
+
* Parses the URL command
|
|
3463
|
+
*/
|
|
3464
|
+
parse: function (input) {
|
|
3465
|
+
var args = input.args;
|
|
3466
|
+
var pipelineUrl = args.pop();
|
|
3467
|
+
if (pipelineUrl === undefined) {
|
|
3468
|
+
throw new ParseError("URL is required");
|
|
3469
|
+
}
|
|
3470
|
+
// TODO: [🧠][🚲] This should be maybe tested as logic not parse
|
|
3471
|
+
if (!isValidPipelineUrl(pipelineUrl)) {
|
|
3472
|
+
throw new ParseError("Invalid pipeline URL \"".concat(pipelineUrl, "\""));
|
|
3473
|
+
}
|
|
3474
|
+
if (args.length > 0) {
|
|
3475
|
+
throw new ParseError("Can not have more than one pipeline URL");
|
|
3476
|
+
}
|
|
3477
|
+
/*
|
|
3478
|
+
TODO: [🐠 Maybe more info from `isValidPipelineUrl`:
|
|
3479
|
+
if (pipelineUrl.protocol !== 'https:') {
|
|
3480
|
+
throw new ParseError(`Protocol must be HTTPS`);
|
|
3481
|
+
}
|
|
3482
|
+
|
|
3483
|
+
if (pipelineUrl.hash !== '') {
|
|
3484
|
+
throw new ParseError(
|
|
3485
|
+
spaceTrim(
|
|
3486
|
+
`
|
|
3487
|
+
URL must not contain hash
|
|
3488
|
+
Hash is used for identification of the section of the pipeline
|
|
3489
|
+
`,
|
|
3490
|
+
),
|
|
3491
|
+
);
|
|
3492
|
+
}
|
|
3493
|
+
*/
|
|
3494
|
+
return {
|
|
3495
|
+
type: 'URL',
|
|
3496
|
+
pipelineUrl: new URL(pipelineUrl),
|
|
3497
|
+
};
|
|
3498
|
+
},
|
|
3499
|
+
/**
|
|
3500
|
+
* Apply the URL command to the `pipelineJson`
|
|
3501
|
+
*
|
|
3502
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
3503
|
+
*/
|
|
3504
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
3505
|
+
$pipelineJson.pipelineUrl = command.pipelineUrl.href;
|
|
3506
|
+
},
|
|
3507
|
+
/**
|
|
3508
|
+
* Converts the URL command back to string
|
|
3509
|
+
*
|
|
3510
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3511
|
+
*/
|
|
3512
|
+
stringify: function (command) {
|
|
3513
|
+
return "---"; // <- TODO: [🛋] Implement
|
|
3514
|
+
},
|
|
3515
|
+
/**
|
|
3516
|
+
* Reads the URL command from the `PipelineJson`
|
|
3517
|
+
*
|
|
3518
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3519
|
+
*/
|
|
3520
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
3521
|
+
throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
|
|
3522
|
+
},
|
|
3523
|
+
};
|
|
3524
|
+
|
|
3525
|
+
/**
|
|
3526
|
+
* Parses the action command
|
|
3527
|
+
*
|
|
3528
|
+
* @see `documentationUrl` for more details
|
|
3529
|
+
* @public exported from `@promptbook/editable`
|
|
3530
|
+
*/
|
|
3531
|
+
var actionCommandParser = {
|
|
3532
|
+
/**
|
|
3533
|
+
* Name of the command
|
|
3534
|
+
*/
|
|
3535
|
+
name: 'ACTION',
|
|
3536
|
+
/**
|
|
3537
|
+
* ACTION command can be used in:
|
|
3538
|
+
*/
|
|
3539
|
+
isUsedInPipelineHead: true,
|
|
3540
|
+
isUsedInPipelineTask: false,
|
|
3541
|
+
/**
|
|
3542
|
+
* Description of the ACTION command
|
|
3543
|
+
*/
|
|
3544
|
+
description: "Actions influences from the pipeline or task into external world. Like turning on a light, sending an email, etc.",
|
|
3545
|
+
/**
|
|
3546
|
+
* Link to documentation
|
|
3547
|
+
*/
|
|
3548
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/72',
|
|
3549
|
+
/**
|
|
3550
|
+
* Example usages of the ACTION command
|
|
3551
|
+
*/
|
|
3552
|
+
examples: ['ACTION'],
|
|
3553
|
+
/**
|
|
3554
|
+
* Parses the ACTION command
|
|
3555
|
+
*/
|
|
3556
|
+
parse: function (input) {
|
|
3557
|
+
input.args;
|
|
3558
|
+
return {
|
|
3559
|
+
type: 'ACTION',
|
|
3560
|
+
};
|
|
3561
|
+
},
|
|
3562
|
+
/**
|
|
3563
|
+
* Apply the ACTION command to the `pipelineJson`
|
|
3564
|
+
*
|
|
3565
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
3566
|
+
*/
|
|
3567
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
3568
|
+
console.error(new NotYetImplementedError('[🛠] Actions are not implemented yet'));
|
|
3569
|
+
},
|
|
3570
|
+
/**
|
|
3571
|
+
* Converts the ACTION command back to string
|
|
3572
|
+
*
|
|
3573
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3574
|
+
*/
|
|
3575
|
+
stringify: function (command) {
|
|
3576
|
+
throw new NotYetImplementedError('[🛠] Actions are not implemented yet');
|
|
3577
|
+
},
|
|
3578
|
+
/**
|
|
3579
|
+
* Reads the ACTION command from the `PipelineJson`
|
|
3580
|
+
*
|
|
3581
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3582
|
+
*/
|
|
3583
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
3584
|
+
throw new NotYetImplementedError('[🛠] Actions are not implemented yet');
|
|
3585
|
+
},
|
|
3586
|
+
};
|
|
3587
|
+
/**
|
|
3588
|
+
* Note: [⛱] There are two types of ACTION commands *...(read more in [⛱])*
|
|
3589
|
+
*/
|
|
3590
|
+
|
|
3591
|
+
/**
|
|
3592
|
+
* Parses the instrument command
|
|
3593
|
+
*
|
|
3594
|
+
* @see `documentationUrl` for more details
|
|
3595
|
+
* @public exported from `@promptbook/editable`
|
|
3596
|
+
*/
|
|
3597
|
+
var instrumentCommandParser = {
|
|
3598
|
+
/**
|
|
3599
|
+
* Name of the command
|
|
3600
|
+
*/
|
|
3601
|
+
name: 'INSTRUMENT',
|
|
3602
|
+
/**
|
|
3603
|
+
* INSTRUMENT command can be used in:
|
|
3604
|
+
*/
|
|
3605
|
+
isUsedInPipelineHead: true,
|
|
3606
|
+
isUsedInPipelineTask: false,
|
|
3607
|
+
/**
|
|
3608
|
+
* Description of the INSTRUMENT command
|
|
3609
|
+
*/
|
|
3610
|
+
description: "Instrument command is used to specify the instrument to be used in the pipeline or task like search, calculate, etc.",
|
|
3611
|
+
/**
|
|
3612
|
+
* Link to documentation
|
|
3613
|
+
*/
|
|
3614
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/71',
|
|
3615
|
+
/**
|
|
3616
|
+
* Example usages of the INSTRUMENT command
|
|
3617
|
+
*/
|
|
3618
|
+
examples: ['INSTRUMENT'],
|
|
3619
|
+
/**
|
|
3620
|
+
* Parses the INSTRUMENT command
|
|
3621
|
+
*/
|
|
3622
|
+
parse: function (input) {
|
|
3623
|
+
input.args;
|
|
3624
|
+
return {
|
|
3625
|
+
type: 'INSTRUMENT',
|
|
3626
|
+
};
|
|
3627
|
+
},
|
|
3628
|
+
/**
|
|
3629
|
+
* Apply the INSTRUMENT command to the `pipelineJson`
|
|
3630
|
+
*
|
|
3631
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
3632
|
+
*/
|
|
3633
|
+
$applyToPipelineJson: function (command, $pipelineJson) {
|
|
3634
|
+
console.error(new NotYetImplementedError('[🛠] Instruments are not implemented yet'));
|
|
3635
|
+
},
|
|
3636
|
+
/**
|
|
3637
|
+
* Converts the INSTRUMENT command back to string
|
|
3638
|
+
*
|
|
3639
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3640
|
+
*/
|
|
3641
|
+
stringify: function (command) {
|
|
3642
|
+
throw new NotYetImplementedError('[🛠] Instruments are not implemented yet');
|
|
3643
|
+
},
|
|
3644
|
+
/**
|
|
3645
|
+
* Reads the INSTRUMENT command from the `PipelineJson`
|
|
3646
|
+
*
|
|
3647
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
3648
|
+
*/
|
|
3649
|
+
takeFromPipelineJson: function (pipelineJson) {
|
|
3650
|
+
throw new NotYetImplementedError('[🛠] Instruments are not implemented yet');
|
|
3651
|
+
},
|
|
3652
|
+
};
|
|
3653
|
+
/**
|
|
3654
|
+
* Note: [⛱] There are two types of INSTRUMENT commands *...(read more in [⛱])*
|
|
3655
|
+
*/
|
|
3656
|
+
|
|
3657
|
+
/**
|
|
3658
|
+
* All available command parsers
|
|
3659
|
+
*
|
|
3660
|
+
* @public exported from `@promptbook/editable`
|
|
3661
|
+
*/
|
|
3662
|
+
var COMMANDS = [
|
|
3663
|
+
sectionCommandParser,
|
|
3664
|
+
expectCommandParser,
|
|
3665
|
+
formatCommandParser,
|
|
3666
|
+
jokerCommandParser,
|
|
3667
|
+
modelCommandParser,
|
|
3668
|
+
parameterCommandParser,
|
|
3669
|
+
postprocessCommandParser,
|
|
3670
|
+
bookVersionCommandParser,
|
|
3671
|
+
formfactorCommandParser,
|
|
3672
|
+
urlCommandParser,
|
|
3673
|
+
knowledgeCommandParser,
|
|
3674
|
+
actionCommandParser,
|
|
3675
|
+
instrumentCommandParser,
|
|
3676
|
+
personaCommandParser,
|
|
3677
|
+
foreachCommandParser,
|
|
3678
|
+
boilerplateCommandParser, // <- TODO: Only in development, remove in production
|
|
3679
|
+
// <- Note: [♓️][💩] This is the order of the commands in the pipeline, BUT its not used in parsing and before usage maybe it should be done better
|
|
3680
|
+
];
|
|
3681
|
+
/**
|
|
3682
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3683
|
+
*/
|
|
3684
|
+
|
|
3685
|
+
/**
|
|
3686
|
+
* Gets the parser for the command
|
|
3687
|
+
*
|
|
3688
|
+
* @returns the parser for the command
|
|
3689
|
+
* @throws {UnexpectedError} if the parser is not found
|
|
3690
|
+
*
|
|
3691
|
+
* @public exported from `@promptbook/editable`
|
|
3692
|
+
*/
|
|
3693
|
+
function getParserForCommand(command) {
|
|
3694
|
+
var commandParser = COMMANDS.find(function (commandParser) { return commandParser.name === command.type; });
|
|
3695
|
+
if (commandParser === undefined) {
|
|
3696
|
+
throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Command ".concat(command.type, " parser is not found\n\n ").concat(block(JSON.stringify(command, null, 4)
|
|
3697
|
+
.split('\n')
|
|
3698
|
+
.map(function (line) { return "> ".concat(line); })
|
|
3699
|
+
.join('\n')), "\n "); }));
|
|
3700
|
+
}
|
|
3701
|
+
return commandParser;
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3704
|
+
/**
|
|
3705
|
+
* Removes Markdown formatting tags from a string.
|
|
3706
|
+
*
|
|
3707
|
+
* @param {string} str - The string to remove Markdown tags from.
|
|
3708
|
+
* @returns {string} The input string with all Markdown tags removed.
|
|
3709
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
3710
|
+
*/
|
|
3711
|
+
function removeMarkdownFormatting(str) {
|
|
3712
|
+
// Remove bold formatting
|
|
3713
|
+
str = str.replace(/\*\*(.*?)\*\*/g, '$1');
|
|
3714
|
+
// Remove italic formatting
|
|
3715
|
+
str = str.replace(/\*(.*?)\*/g, '$1');
|
|
3716
|
+
// Remove code formatting
|
|
3717
|
+
str = str.replace(/`(.*?)`/g, '$1');
|
|
3718
|
+
return str;
|
|
3719
|
+
}
|
|
3720
|
+
|
|
3721
|
+
/**
|
|
3722
|
+
* Parses one line of ul/ol to command
|
|
3723
|
+
*
|
|
3724
|
+
* @returns parsed command object
|
|
3725
|
+
* @throws {ParseError} if the command is invalid
|
|
3726
|
+
*
|
|
3727
|
+
* @public exported from `@promptbook/editable`
|
|
3728
|
+
*/
|
|
3729
|
+
function parseCommand(raw, usagePlace) {
|
|
3730
|
+
if (raw.includes('\n') || raw.includes('\r')) {
|
|
3731
|
+
throw new ParseError('Command can not contain new line characters' /* <- TODO: [🚞] */);
|
|
3732
|
+
}
|
|
3733
|
+
// TODO: Unit test all this processing and parsing
|
|
3734
|
+
var normalized = raw.trim();
|
|
3735
|
+
normalized = normalized.split('`').join('');
|
|
3736
|
+
normalized = normalized.split('"').join('');
|
|
3737
|
+
normalized = normalized.split("'").join('');
|
|
3738
|
+
normalized = normalized.split('~').join('');
|
|
3739
|
+
normalized = normalized.split('[').join('');
|
|
3740
|
+
normalized = normalized.split(']').join('');
|
|
3741
|
+
normalized = normalized.split('(').join('');
|
|
3742
|
+
normalized = normalized.split(')').join('');
|
|
3743
|
+
normalized = normalizeTo_SCREAMING_CASE(normalized);
|
|
3744
|
+
var items = raw
|
|
3745
|
+
.trim()
|
|
3746
|
+
// Note: [🐡]
|
|
3747
|
+
.split(/^>/)
|
|
3748
|
+
.join('')
|
|
3749
|
+
// ---
|
|
3750
|
+
.trim()
|
|
3751
|
+
.split(/["'`]/)
|
|
3752
|
+
.join('')
|
|
3753
|
+
.trim()
|
|
3754
|
+
// Note: [🛵]:
|
|
3755
|
+
.split(/^http/)
|
|
3756
|
+
.join('URL http')
|
|
3757
|
+
// ---
|
|
3758
|
+
// Note: [🦈]
|
|
3759
|
+
.split(/^{/)
|
|
3760
|
+
.join('PARAMETER {')
|
|
3761
|
+
// ---
|
|
3762
|
+
.split(' ')
|
|
3763
|
+
.map(function (part) { return part.trim(); })
|
|
3764
|
+
.filter(function (item) { return item !== ''; })
|
|
3765
|
+
.map(removeMarkdownFormatting)
|
|
3766
|
+
.map(function (item) { return item.trim(); });
|
|
3767
|
+
if (items.length === 0 || items[0] === '') {
|
|
3768
|
+
throw new ParseError(spaceTrim$1(function (block) {
|
|
3769
|
+
return "\n Malformed command:\n - ".concat(raw, "\n\n Supported commands are:\n ").concat(block(getSupportedCommandsMessage()), "\n\n ");
|
|
3770
|
+
}));
|
|
3771
|
+
}
|
|
3772
|
+
// Note: Taking command name from beginning of the line
|
|
3773
|
+
// FOO | BAR Arg1 Arg2 Arg3
|
|
3774
|
+
// FOO BAR | Arg1 Arg2 Arg3
|
|
3775
|
+
for (var commandNameSegmentsCount = 0; commandNameSegmentsCount < Math.min(items.length, 3); commandNameSegmentsCount++) {
|
|
3776
|
+
var commandNameRaw = items.slice(0, commandNameSegmentsCount + 1).join('_');
|
|
3777
|
+
var args = items.slice(commandNameSegmentsCount + 1);
|
|
3778
|
+
var rawArgs = raw
|
|
3779
|
+
.substring(commandNameRaw.length)
|
|
3780
|
+
.trim();
|
|
3781
|
+
var command = parseCommandVariant({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args, commandNameRaw: commandNameRaw });
|
|
3782
|
+
if (command !== null) {
|
|
3783
|
+
return command;
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
// Note: Taking command name from end of the line
|
|
3787
|
+
// Arg1 Arg2 Arg3 | FOO
|
|
3788
|
+
{
|
|
3789
|
+
var commandNameRaw = items.slice(-1).join('_');
|
|
3790
|
+
var args = items.slice(0, -1); // <- Note: This is probbably not correct
|
|
3791
|
+
var rawArgs = raw
|
|
3792
|
+
.substring(0, raw.length - commandNameRaw.length)
|
|
3793
|
+
.trim();
|
|
3794
|
+
var command = parseCommandVariant({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args, commandNameRaw: commandNameRaw });
|
|
3795
|
+
if (command !== null) {
|
|
3796
|
+
return command;
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
throw new ParseError(spaceTrim$1(function (block) {
|
|
3800
|
+
return "\n Malformed or unknown command:\n - ".concat(raw, "\n\n Supported commands are:\n ").concat(block(getSupportedCommandsMessage()), "\n\n ");
|
|
3801
|
+
}));
|
|
3802
|
+
}
|
|
3803
|
+
/**
|
|
3804
|
+
* @@@
|
|
3805
|
+
*/
|
|
3806
|
+
function getSupportedCommandsMessage() {
|
|
3807
|
+
return COMMANDS.flatMap(function (_a) {
|
|
3808
|
+
var name = _a.name, aliasNames = _a.aliasNames, description = _a.description, documentationUrl = _a.documentationUrl;
|
|
3809
|
+
// <- Note: [🦦] Its strange that this type assertion is needed
|
|
3810
|
+
return __spreadArray([
|
|
3811
|
+
"- **".concat(name, "** ").concat(description, ", see [discussion](").concat(documentationUrl, ")")
|
|
3812
|
+
], __read((aliasNames || []).map(function (aliasName) { return " - **".concat(aliasName, "** Alias for **").concat(name, "**"); })), false);
|
|
3813
|
+
}).join('\n');
|
|
3814
|
+
}
|
|
3815
|
+
/**
|
|
3816
|
+
* @@@
|
|
3817
|
+
*/
|
|
3818
|
+
function parseCommandVariant(input) {
|
|
3819
|
+
var e_1, _a;
|
|
3820
|
+
var commandNameRaw = input.commandNameRaw, usagePlace = input.usagePlace, normalized = input.normalized, args = input.args, raw = input.raw, rawArgs = input.rawArgs;
|
|
3821
|
+
var commandName = normalizeTo_SCREAMING_CASE(commandNameRaw);
|
|
3822
|
+
var _loop_1 = function (commandParser) {
|
|
3823
|
+
// <- Note: [🦦] Its strange that this type assertion is needed
|
|
3824
|
+
var name_1 = commandParser.name, isUsedInPipelineHead = commandParser.isUsedInPipelineHead, isUsedInPipelineTask = commandParser.isUsedInPipelineTask, aliasNames = commandParser.aliasNames, deprecatedNames = commandParser.deprecatedNames, parse = commandParser.parse;
|
|
3825
|
+
if (just(false)) ;
|
|
3826
|
+
else if (usagePlace === 'PIPELINE_HEAD' && !isUsedInPipelineHead) {
|
|
3827
|
+
return "continue";
|
|
3828
|
+
}
|
|
3829
|
+
else if (usagePlace === 'PIPELINE_TASK' && !isUsedInPipelineTask) {
|
|
3830
|
+
return "continue";
|
|
3831
|
+
}
|
|
3832
|
+
var names = __spreadArray(__spreadArray([name_1], __read((aliasNames || [])), false), __read((deprecatedNames || [])), false);
|
|
3833
|
+
if (names.includes(commandName)) {
|
|
3834
|
+
try {
|
|
3835
|
+
return { value: parse({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args }) };
|
|
3836
|
+
}
|
|
3837
|
+
catch (error) {
|
|
3838
|
+
if (!(error instanceof ParseError)) {
|
|
3839
|
+
throw error;
|
|
3840
|
+
}
|
|
3841
|
+
throw new ParseError(spaceTrim$1(function (block) {
|
|
3842
|
+
return "\n Invalid ".concat(commandName, " command:\n\n Your command:\n - ").concat(raw, "\n\n The detailed error:\n ").concat(block(error.message), "\n\n Usage of ").concat(commandName, ":\n ").concat(block(commandParser.examples.map(function (example) { return "- ".concat(example); }).join('\n')), "\n\n All supported commands are:\n ").concat(block(getSupportedCommandsMessage()), "\n\n ");
|
|
3843
|
+
}));
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
};
|
|
3847
|
+
try {
|
|
3848
|
+
for (var _b = __values(COMMANDS), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
3849
|
+
var commandParser = _c.value;
|
|
3850
|
+
var state_1 = _loop_1(commandParser);
|
|
3851
|
+
if (typeof state_1 === "object")
|
|
3852
|
+
return state_1.value;
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
3856
|
+
finally {
|
|
3857
|
+
try {
|
|
3858
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
3859
|
+
}
|
|
3860
|
+
finally { if (e_1) throw e_1.error; }
|
|
3861
|
+
}
|
|
3862
|
+
return null;
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
/**
|
|
3866
|
+
* Function `removePipelineCommand` will remove one command from pipeline string
|
|
3867
|
+
*
|
|
3868
|
+
* @public exported from `@promptbook/editable`
|
|
3869
|
+
*/
|
|
3870
|
+
function removePipelineCommand(options) {
|
|
3871
|
+
var e_1, _a;
|
|
3872
|
+
var command = options.command, pipeline = options.pipeline;
|
|
3873
|
+
var lines = pipeline.split('\n');
|
|
3874
|
+
// TODO: [🧽] DRY
|
|
3875
|
+
var currentType = 'MARKDOWN';
|
|
3876
|
+
var newLines = [];
|
|
3877
|
+
try {
|
|
3878
|
+
for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
|
|
3879
|
+
var line = lines_1_1.value;
|
|
3880
|
+
if (currentType === 'MARKDOWN') {
|
|
3881
|
+
if (line.startsWith('```')) {
|
|
3882
|
+
currentType = 'CODE_BLOCK';
|
|
3883
|
+
}
|
|
3884
|
+
else if (line.includes('<!--')) {
|
|
3885
|
+
currentType = 'COMMENT';
|
|
3886
|
+
}
|
|
3887
|
+
}
|
|
3888
|
+
else if (currentType === 'CODE_BLOCK') {
|
|
3889
|
+
if (line.startsWith('```')) {
|
|
3890
|
+
currentType = 'MARKDOWN';
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
else if (currentType === 'COMMENT') {
|
|
3894
|
+
if (line.includes('-->')) {
|
|
3895
|
+
currentType = 'MARKDOWN';
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
if (currentType === 'MARKDOWN' && /^(-|\d\))/m.test(line) && line.toUpperCase().includes(command)) {
|
|
3899
|
+
continue;
|
|
3900
|
+
}
|
|
3901
|
+
newLines.push(line);
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
3905
|
+
finally {
|
|
3906
|
+
try {
|
|
3907
|
+
if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
|
|
3908
|
+
}
|
|
3909
|
+
finally { if (e_1) throw e_1.error; }
|
|
3910
|
+
}
|
|
3911
|
+
var newPipeline = spaceTrim(newLines.join('\n'));
|
|
3912
|
+
return newPipeline;
|
|
3913
|
+
}
|
|
3914
|
+
|
|
3915
|
+
/**
|
|
3916
|
+
* This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
|
|
3917
|
+
*
|
|
3918
|
+
* @public exported from `@promptbook/core`
|
|
3919
|
+
*/
|
|
3920
|
+
var PipelineLogicError = /** @class */ (function (_super) {
|
|
3921
|
+
__extends(PipelineLogicError, _super);
|
|
3922
|
+
function PipelineLogicError(message) {
|
|
3923
|
+
var _this = _super.call(this, message) || this;
|
|
3924
|
+
_this.name = 'PipelineLogicError';
|
|
3925
|
+
Object.setPrototypeOf(_this, PipelineLogicError.prototype);
|
|
3926
|
+
return _this;
|
|
3927
|
+
}
|
|
3928
|
+
return PipelineLogicError;
|
|
3929
|
+
}(Error));
|
|
3930
|
+
|
|
3931
|
+
/**
|
|
3932
|
+
* Function `renamePipelineParameter` will find all usable parameters for given task
|
|
3933
|
+
* In other words, it will find all parameters that are not used in the task itseld and all its dependencies
|
|
3934
|
+
*
|
|
3935
|
+
* @throws {PipelineLogicError} If the new parameter name is already used in the pipeline
|
|
3936
|
+
* @public exported from `@promptbook/editable`
|
|
3937
|
+
*/
|
|
3938
|
+
function renamePipelineParameter(options) {
|
|
3939
|
+
var e_1, _a, e_2, _b;
|
|
3940
|
+
var pipeline = options.pipeline, oldParameterName = options.oldParameterName, newParameterName = options.newParameterName;
|
|
3941
|
+
if (pipeline.parameters.some(function (parameter) { return parameter.name === newParameterName; })) {
|
|
3942
|
+
throw new PipelineLogicError("Can not replace {".concat(oldParameterName, "} to {").concat(newParameterName, "} because {").concat(newParameterName, "} is already used in the pipeline"));
|
|
3943
|
+
}
|
|
3944
|
+
var renamedPipeline = __assign(__assign({}, pipeline), {
|
|
3945
|
+
// <- TODO: [🪓] This should be without `as $PipelineJson`
|
|
3946
|
+
parameters: __spreadArray([], __read(pipeline.parameters), false), tasks: __spreadArray([], __read(pipeline.tasks), false) });
|
|
3947
|
+
try {
|
|
3948
|
+
for (var _c = __values(renamedPipeline.parameters), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
3949
|
+
var parameter = _d.value;
|
|
3950
|
+
if (parameter.name !== oldParameterName) {
|
|
3951
|
+
continue;
|
|
3952
|
+
}
|
|
3953
|
+
parameter.name = newParameterName;
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
3957
|
+
finally {
|
|
3958
|
+
try {
|
|
3959
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
3960
|
+
}
|
|
3961
|
+
finally { if (e_1) throw e_1.error; }
|
|
3962
|
+
}
|
|
3963
|
+
try {
|
|
3964
|
+
for (var _e = __values(renamedPipeline.tasks), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
3965
|
+
var task = _f.value;
|
|
3966
|
+
if (task.resultingParameterName === oldParameterName) {
|
|
3967
|
+
task.resultingParameterName = newParameterName;
|
|
3968
|
+
}
|
|
3969
|
+
task.dependentParameterNames = task.dependentParameterNames.map(function (dependentParameterName) {
|
|
3970
|
+
return dependentParameterName === oldParameterName ? newParameterName : dependentParameterName;
|
|
3971
|
+
});
|
|
3972
|
+
task.content = task.content.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
|
|
3973
|
+
task.title = task.title.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
|
|
3974
|
+
task.description =
|
|
3975
|
+
task.description === undefined
|
|
3976
|
+
? undefined
|
|
3977
|
+
: task.description.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
3981
|
+
finally {
|
|
3982
|
+
try {
|
|
3983
|
+
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
|
|
3984
|
+
}
|
|
3985
|
+
finally { if (e_2) throw e_2.error; }
|
|
3986
|
+
}
|
|
3987
|
+
return renamedPipeline;
|
|
3988
|
+
}
|
|
3989
|
+
|
|
568
3990
|
// <- TODO: Auto convert to type `import { ... } from 'type-fest';`
|
|
569
3991
|
/**
|
|
570
3992
|
* Tests if the value is [🚉] serializable as JSON
|
|
@@ -626,5 +4048,5 @@ function stringifyPipelineJson(pipeline) {
|
|
|
626
4048
|
* TODO: [🍙] Make some standard order of json properties
|
|
627
4049
|
*/
|
|
628
4050
|
|
|
629
|
-
export { BOOK_LANGUAGE_VERSION, PROMPTBOOK_ENGINE_VERSION, removePipelineCommand, renamePipelineParameter, stringifyPipelineJson };
|
|
4051
|
+
export { BOOK_LANGUAGE_VERSION, COMMANDS, PROMPTBOOK_ENGINE_VERSION, actionCommandParser, bookVersionCommandParser, expectCommandParser, foreachCommandParser, formatCommandParser, formfactorCommandParser, getParserForCommand, instrumentCommandParser, jokerCommandParser, knowledgeCommandParser, knowledgeSourceContentToName, modelCommandParser, parameterCommandParser, parseCommand, personaCommandParser, postprocessCommandParser, removePipelineCommand, renamePipelineParameter, sectionCommandParser, stringifyPipelineJson, urlCommandParser };
|
|
630
4052
|
//# sourceMappingURL=index.es.js.map
|