@promptbook/remote-server 0.106.0-0 → 0.108.0-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/esm/index.es.js +1190 -141
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +4 -0
- package/esm/typings/src/_packages/markdown-utils.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +15 -1
- package/esm/typings/src/_packages/utils.index.d.ts +2 -2
- package/esm/typings/src/book-components/BookEditor/BookEditor.d.ts +26 -2
- package/esm/typings/src/book-components/Chat/types/ChatMessage.d.ts +10 -2
- package/esm/typings/src/book-components/Chat/utils/getChatMessageTimingDisplay.d.ts +26 -0
- package/esm/typings/src/book-components/Chat/utils/{getToolCallChipletText.d.ts → getToolCallChipletInfo.d.ts} +8 -8
- package/esm/typings/src/types/ToolCall.d.ts +76 -1
- package/esm/typings/src/utils/linguistic-hash/LinguisticHashLanguage.d.ts +41 -0
- package/esm/typings/src/utils/linguistic-hash/linguisticHash.d.ts +37 -0
- package/esm/typings/src/utils/linguistic-hash/linguisticHashTypes.d.ts +19 -0
- package/esm/typings/src/utils/linguistic-hash/linguisticHashWords.cs.d.ts +10 -0
- package/esm/typings/src/utils/linguistic-hash/linguisticHashWords.en.d.ts +10 -0
- package/esm/typings/src/utils/markdown/humanizeAiTextSources.d.ts +13 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +1190 -141
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/utils/misc/linguisticHash.d.ts +0 -9
- /package/esm/typings/src/utils/{misc → linguistic-hash}/linguisticHash.test.d.ts +0 -0
package/esm/index.es.js
CHANGED
|
@@ -39,7 +39,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
39
39
|
* @generated
|
|
40
40
|
* @see https://github.com/webgptorg/promptbook
|
|
41
41
|
*/
|
|
42
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
42
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.108.0-0';
|
|
43
43
|
/**
|
|
44
44
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
45
45
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -8192,13 +8192,125 @@ function escapePromptParameterValue(value, options) {
|
|
|
8192
8192
|
return value.replace(pattern, '\\$&');
|
|
8193
8193
|
}
|
|
8194
8194
|
/**
|
|
8195
|
-
* Builds
|
|
8195
|
+
* Builds numeric parameter name used in prompt placeholders.
|
|
8196
8196
|
*
|
|
8197
8197
|
* @param index Zero-based parameter index.
|
|
8198
8198
|
*/
|
|
8199
|
-
function
|
|
8199
|
+
function buildNumericParameterName(index) {
|
|
8200
8200
|
return `${index + 1}`;
|
|
8201
8201
|
}
|
|
8202
|
+
/**
|
|
8203
|
+
* Builds alphabetic parameter name used in prompt placeholders.
|
|
8204
|
+
*
|
|
8205
|
+
* @param index Zero-based parameter index.
|
|
8206
|
+
*/
|
|
8207
|
+
function buildAlphabeticParameterName(index) {
|
|
8208
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyz';
|
|
8209
|
+
let result = '';
|
|
8210
|
+
let remaining = index;
|
|
8211
|
+
while (remaining >= 0) {
|
|
8212
|
+
result = alphabet[remaining % alphabet.length] + result;
|
|
8213
|
+
remaining = Math.floor(remaining / alphabet.length) - 1;
|
|
8214
|
+
}
|
|
8215
|
+
return result;
|
|
8216
|
+
}
|
|
8217
|
+
/**
|
|
8218
|
+
* Converts a positive integer into a Roman numeral string.
|
|
8219
|
+
*
|
|
8220
|
+
* @param value Positive integer value.
|
|
8221
|
+
*/
|
|
8222
|
+
function toRomanNumeral(value) {
|
|
8223
|
+
const romanTable = [
|
|
8224
|
+
{ symbol: 'M', value: 1000 },
|
|
8225
|
+
{ symbol: 'CM', value: 900 },
|
|
8226
|
+
{ symbol: 'D', value: 500 },
|
|
8227
|
+
{ symbol: 'CD', value: 400 },
|
|
8228
|
+
{ symbol: 'C', value: 100 },
|
|
8229
|
+
{ symbol: 'XC', value: 90 },
|
|
8230
|
+
{ symbol: 'L', value: 50 },
|
|
8231
|
+
{ symbol: 'XL', value: 40 },
|
|
8232
|
+
{ symbol: 'X', value: 10 },
|
|
8233
|
+
{ symbol: 'IX', value: 9 },
|
|
8234
|
+
{ symbol: 'V', value: 5 },
|
|
8235
|
+
{ symbol: 'IV', value: 4 },
|
|
8236
|
+
{ symbol: 'I', value: 1 },
|
|
8237
|
+
];
|
|
8238
|
+
let remaining = Math.max(1, Math.floor(value));
|
|
8239
|
+
let result = '';
|
|
8240
|
+
for (const entry of romanTable) {
|
|
8241
|
+
while (remaining >= entry.value) {
|
|
8242
|
+
result += entry.symbol;
|
|
8243
|
+
remaining -= entry.value;
|
|
8244
|
+
}
|
|
8245
|
+
}
|
|
8246
|
+
return result;
|
|
8247
|
+
}
|
|
8248
|
+
/**
|
|
8249
|
+
* Builds Roman numeral parameter name used in prompt placeholders.
|
|
8250
|
+
*
|
|
8251
|
+
* @param index Zero-based parameter index.
|
|
8252
|
+
*/
|
|
8253
|
+
function buildRomanParameterName(index) {
|
|
8254
|
+
return toRomanNumeral(index + 1);
|
|
8255
|
+
}
|
|
8256
|
+
/**
|
|
8257
|
+
* Creates a parameter name builder that prefixes another builder.
|
|
8258
|
+
*
|
|
8259
|
+
* @param prefix Prefix to add.
|
|
8260
|
+
* @param builder Base builder to wrap.
|
|
8261
|
+
*/
|
|
8262
|
+
function buildPrefixedParameterName(prefix, builder) {
|
|
8263
|
+
return (index) => `${prefix}${builder(index)}`;
|
|
8264
|
+
}
|
|
8265
|
+
/**
|
|
8266
|
+
* Ordered list of strategies for parameter naming.
|
|
8267
|
+
*/
|
|
8268
|
+
const PARAMETER_NAME_STRATEGIES = [
|
|
8269
|
+
{ buildName: buildNumericParameterName },
|
|
8270
|
+
{ buildName: buildAlphabeticParameterName },
|
|
8271
|
+
{ buildName: buildRomanParameterName },
|
|
8272
|
+
{ buildName: buildPrefixedParameterName('p', buildNumericParameterName) },
|
|
8273
|
+
{ buildName: buildPrefixedParameterName('p', buildAlphabeticParameterName) },
|
|
8274
|
+
];
|
|
8275
|
+
/**
|
|
8276
|
+
* Collects bracketed tokens from parameter values to avoid placeholder collisions.
|
|
8277
|
+
*
|
|
8278
|
+
* @param values Parameter values to scan.
|
|
8279
|
+
*/
|
|
8280
|
+
function collectBracketedParameterTokens(values) {
|
|
8281
|
+
const tokens = new Set();
|
|
8282
|
+
for (const value of values) {
|
|
8283
|
+
const pattern = /{(\w+)}/g;
|
|
8284
|
+
let match;
|
|
8285
|
+
while ((match = pattern.exec(value)) !== null) {
|
|
8286
|
+
const token = match[1];
|
|
8287
|
+
if (token) {
|
|
8288
|
+
tokens.add(token);
|
|
8289
|
+
}
|
|
8290
|
+
}
|
|
8291
|
+
}
|
|
8292
|
+
return tokens;
|
|
8293
|
+
}
|
|
8294
|
+
/**
|
|
8295
|
+
* Builds parameter names used in prompt placeholders while avoiding collisions.
|
|
8296
|
+
*
|
|
8297
|
+
* @param values Parameter values to scan for conflicting tokens.
|
|
8298
|
+
*/
|
|
8299
|
+
function buildParameterNames(values) {
|
|
8300
|
+
const count = values.length;
|
|
8301
|
+
if (count === 0) {
|
|
8302
|
+
return [];
|
|
8303
|
+
}
|
|
8304
|
+
const conflicts = collectBracketedParameterTokens(values);
|
|
8305
|
+
for (const strategy of PARAMETER_NAME_STRATEGIES) {
|
|
8306
|
+
const names = Array.from({ length: count }, (_, index) => strategy.buildName(index));
|
|
8307
|
+
const hasConflict = names.some((name) => conflicts.has(name));
|
|
8308
|
+
if (!hasConflict) {
|
|
8309
|
+
return names;
|
|
8310
|
+
}
|
|
8311
|
+
}
|
|
8312
|
+
return Array.from({ length: count }, (_, index) => `${REPLACING_NONCE}${index + 1}`);
|
|
8313
|
+
}
|
|
8202
8314
|
/**
|
|
8203
8315
|
* Formats the placeholder used in the prompt body for a parameter.
|
|
8204
8316
|
*
|
|
@@ -8253,26 +8365,40 @@ function prompt(strings, ...values) {
|
|
|
8253
8365
|
return new PromptString(spaceTrim$2(strings.join('')));
|
|
8254
8366
|
}
|
|
8255
8367
|
const stringsWithHiddenParameters = strings.map((stringsItem) => hideBrackets(stringsItem));
|
|
8256
|
-
const
|
|
8257
|
-
const name = buildParameterName(index);
|
|
8368
|
+
const parameterMetadata = values.map((value) => {
|
|
8258
8369
|
const isPrompt = isPromptString(value);
|
|
8259
8370
|
const stringValue = isPrompt ? value.toString() : valueToString(value);
|
|
8260
8371
|
const isInline = isPrompt ? true : shouldInlineParameterValue(stringValue);
|
|
8261
8372
|
const jsonValue = !isPrompt && !isInline ? normalizeJsonString(stringValue) : null;
|
|
8373
|
+
return { isPrompt, stringValue, isInline, jsonValue };
|
|
8374
|
+
});
|
|
8375
|
+
const parameterNames = buildParameterNames(parameterMetadata.map((entry) => entry.stringValue));
|
|
8376
|
+
const parameterEntries = parameterMetadata.map((entry, index) => {
|
|
8377
|
+
var _a;
|
|
8378
|
+
const name = (_a = parameterNames[index]) !== null && _a !== void 0 ? _a : buildNumericParameterName(index);
|
|
8262
8379
|
const promptMarker = `${REPLACING_NONCE}prompt-${index}`;
|
|
8263
8380
|
const parameterMarker = `${REPLACING_NONCE}parameter-${index}`;
|
|
8264
|
-
const templateValue = isPrompt
|
|
8381
|
+
const templateValue = entry.isPrompt
|
|
8265
8382
|
? promptMarker
|
|
8266
|
-
: isInline
|
|
8267
|
-
? escapePromptParameterValue(stringValue, { includeBraces: false })
|
|
8383
|
+
: entry.isInline
|
|
8384
|
+
? escapePromptParameterValue(entry.stringValue, { includeBraces: false })
|
|
8268
8385
|
: parameterMarker;
|
|
8269
|
-
return {
|
|
8386
|
+
return {
|
|
8387
|
+
name,
|
|
8388
|
+
stringValue: entry.stringValue,
|
|
8389
|
+
jsonValue: entry.jsonValue,
|
|
8390
|
+
isPrompt: entry.isPrompt,
|
|
8391
|
+
isInline: entry.isInline,
|
|
8392
|
+
promptMarker,
|
|
8393
|
+
parameterMarker,
|
|
8394
|
+
templateValue,
|
|
8395
|
+
};
|
|
8270
8396
|
});
|
|
8271
8397
|
const parameters = Object.fromEntries(parameterEntries.map((entry) => [entry.name, entry.templateValue]));
|
|
8272
|
-
const
|
|
8398
|
+
const parameterNamesOrdered = parameterEntries.map((entry) => entry.name);
|
|
8273
8399
|
// Combine strings and values
|
|
8274
8400
|
let pipelineString = stringsWithHiddenParameters.reduce((result, stringsItem, i) => {
|
|
8275
|
-
const parameterName =
|
|
8401
|
+
const parameterName = parameterNamesOrdered[i];
|
|
8276
8402
|
return parameterName === undefined
|
|
8277
8403
|
? `${result}${stringsItem}`
|
|
8278
8404
|
: `${result}${stringsItem}${formatParameterPlaceholder(parameterName)}`;
|
|
@@ -8285,7 +8411,7 @@ function prompt(strings, ...values) {
|
|
|
8285
8411
|
if (!(error instanceof PipelineExecutionError)) {
|
|
8286
8412
|
throw error;
|
|
8287
8413
|
}
|
|
8288
|
-
console.error({ pipelineString, parameters, parameterNames, error });
|
|
8414
|
+
console.error({ pipelineString, parameters, parameterNames: parameterNamesOrdered, error });
|
|
8289
8415
|
throw new UnexpectedError(spaceTrim$2((block) => `
|
|
8290
8416
|
Internal error in prompt template literal
|
|
8291
8417
|
|
|
@@ -8300,9 +8426,7 @@ function prompt(strings, ...values) {
|
|
|
8300
8426
|
continue;
|
|
8301
8427
|
}
|
|
8302
8428
|
if (!entry.isInline) {
|
|
8303
|
-
pipelineString = pipelineString
|
|
8304
|
-
.split(entry.parameterMarker)
|
|
8305
|
-
.join(formatParameterPlaceholder(entry.name));
|
|
8429
|
+
pipelineString = pipelineString.split(entry.parameterMarker).join(formatParameterPlaceholder(entry.name));
|
|
8306
8430
|
}
|
|
8307
8431
|
}
|
|
8308
8432
|
const structuredParameters = parameterEntries.filter((entry) => !entry.isPrompt && !entry.isInline);
|
|
@@ -8322,18 +8446,6 @@ function prompt(strings, ...values) {
|
|
|
8322
8446
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
8323
8447
|
*/
|
|
8324
8448
|
|
|
8325
|
-
/**
|
|
8326
|
-
* Simple wrapper `new Date().toISOString()`
|
|
8327
|
-
*
|
|
8328
|
-
* Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
|
|
8329
|
-
*
|
|
8330
|
-
* @returns string_date branded type
|
|
8331
|
-
* @public exported from `@promptbook/utils`
|
|
8332
|
-
*/
|
|
8333
|
-
function $getCurrentDate() {
|
|
8334
|
-
return new Date().toISOString();
|
|
8335
|
-
}
|
|
8336
|
-
|
|
8337
8449
|
/**
|
|
8338
8450
|
* Computes SHA-256 hash of the given object
|
|
8339
8451
|
*
|
|
@@ -8346,103 +8458,564 @@ function computeHash(value) {
|
|
|
8346
8458
|
* TODO: [🥬][🥬] Use this ACRY
|
|
8347
8459
|
*/
|
|
8348
8460
|
|
|
8461
|
+
// spell-checker: disable
|
|
8349
8462
|
/**
|
|
8350
|
-
*
|
|
8463
|
+
* @@@
|
|
8351
8464
|
*
|
|
8352
|
-
* @
|
|
8353
|
-
*/
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
'
|
|
8361
|
-
'
|
|
8362
|
-
'
|
|
8363
|
-
'
|
|
8364
|
-
'
|
|
8365
|
-
'
|
|
8366
|
-
'
|
|
8367
|
-
'
|
|
8368
|
-
'
|
|
8369
|
-
'
|
|
8370
|
-
'
|
|
8371
|
-
'
|
|
8465
|
+
* @private utility of `linguisticHash`
|
|
8466
|
+
*/
|
|
8467
|
+
const ADJECTIVES$1 = [
|
|
8468
|
+
'červený',
|
|
8469
|
+
'modrý',
|
|
8470
|
+
'zelený',
|
|
8471
|
+
'žlutý',
|
|
8472
|
+
'rychlý',
|
|
8473
|
+
'pomalý',
|
|
8474
|
+
'jasný',
|
|
8475
|
+
'temný',
|
|
8476
|
+
'veselý',
|
|
8477
|
+
'smutný',
|
|
8478
|
+
'statečný',
|
|
8479
|
+
'klidný',
|
|
8480
|
+
'chytrý',
|
|
8481
|
+
'bystrý',
|
|
8482
|
+
'dychtivý',
|
|
8483
|
+
'honosný',
|
|
8484
|
+
'velkolepý',
|
|
8485
|
+
'hravý',
|
|
8486
|
+
'laskavý',
|
|
8487
|
+
'šťastný',
|
|
8488
|
+
'hrdý',
|
|
8489
|
+
'pošetilý',
|
|
8490
|
+
'moudrý',
|
|
8491
|
+
'mladý',
|
|
8492
|
+
'starý',
|
|
8493
|
+
'veliký',
|
|
8494
|
+
'malý',
|
|
8495
|
+
'drobný',
|
|
8496
|
+
'obrovský',
|
|
8497
|
+
'krátký',
|
|
8498
|
+
'dlouhý',
|
|
8499
|
+
'blízký',
|
|
8500
|
+
'vzdálený',
|
|
8501
|
+
'vnitřní',
|
|
8502
|
+
'vnější',
|
|
8503
|
+
'trpělivý',
|
|
8504
|
+
'stálý',
|
|
8505
|
+
'ušlechtilý',
|
|
8506
|
+
'čistý',
|
|
8507
|
+
'špinavý',
|
|
8508
|
+
'čerstvý',
|
|
8509
|
+
'zvětralý',
|
|
8510
|
+
'ostrý',
|
|
8511
|
+
'tupý',
|
|
8512
|
+
'tlustý',
|
|
8513
|
+
'tenký',
|
|
8514
|
+
'široký',
|
|
8515
|
+
'úzký',
|
|
8516
|
+
'hluboký',
|
|
8517
|
+
'mělký',
|
|
8518
|
+
'mocný',
|
|
8519
|
+
'jemný',
|
|
8520
|
+
'divoký',
|
|
8521
|
+
'tichý',
|
|
8522
|
+
'hlučný',
|
|
8523
|
+
'pokojný',
|
|
8524
|
+
'rušný',
|
|
8525
|
+
'prázdný',
|
|
8526
|
+
'plný',
|
|
8527
|
+
'kulatý',
|
|
8528
|
+
'hranatý',
|
|
8529
|
+
'plochý',
|
|
8530
|
+
'křivý',
|
|
8531
|
+
'tvrdý',
|
|
8532
|
+
'měkký',
|
|
8533
|
+
'teplý',
|
|
8534
|
+
'chladný',
|
|
8535
|
+
'sladký',
|
|
8536
|
+
'kyselý',
|
|
8537
|
+
'hořký',
|
|
8538
|
+
'slaný',
|
|
8539
|
+
'silný',
|
|
8540
|
+
'slabý',
|
|
8541
|
+
'pevný',
|
|
8542
|
+
'pružný',
|
|
8543
|
+
'křehký',
|
|
8544
|
+
'houževnatý',
|
|
8545
|
+
'lesklý',
|
|
8546
|
+
'matný',
|
|
8547
|
+
'kluzký',
|
|
8548
|
+
'lepkavý',
|
|
8549
|
+
'svěží',
|
|
8550
|
+
'vybledlý',
|
|
8551
|
+
'mlhavý',
|
|
8552
|
+
'bouřlivý',
|
|
8553
|
+
'slunný',
|
|
8554
|
+
'větrný',
|
|
8555
|
+
'deštivý',
|
|
8556
|
+
'mrazivý',
|
|
8557
|
+
'zlatý',
|
|
8558
|
+
'stříbrný',
|
|
8559
|
+
'ledový',
|
|
8560
|
+
'žhavý',
|
|
8561
|
+
'prastarý',
|
|
8562
|
+
'moderní',
|
|
8563
|
+
'skrytý',
|
|
8564
|
+
'ztracený',
|
|
8565
|
+
'nalezený',
|
|
8566
|
+
'magický',
|
|
8567
|
+
'tajemný',
|
|
8568
|
+
'kosmický',
|
|
8569
|
+
'hvězdný',
|
|
8570
|
+
'měsíční',
|
|
8571
|
+
'sluneční',
|
|
8572
|
+
'mlžný',
|
|
8573
|
+
'ranní',
|
|
8574
|
+
'večerní',
|
|
8575
|
+
'noční',
|
|
8576
|
+
'denní',
|
|
8577
|
+
'osamělý',
|
|
8578
|
+
'společenský',
|
|
8579
|
+
'soukromý',
|
|
8580
|
+
'veřejný',
|
|
8581
|
+
'tajný',
|
|
8582
|
+
'slavný',
|
|
8583
|
+
'jistý',
|
|
8584
|
+
'neurčitý',
|
|
8585
|
+
'prostý',
|
|
8586
|
+
'snadný',
|
|
8587
|
+
'krotký',
|
|
8588
|
+
'mírný',
|
|
8589
|
+
'horký',
|
|
8590
|
+
'suchý',
|
|
8591
|
+
'mokrý',
|
|
8592
|
+
'vlhký',
|
|
8593
|
+
'promočený',
|
|
8594
|
+
'vyprahlý',
|
|
8595
|
+
'hladový',
|
|
8596
|
+
'žíznivý',
|
|
8597
|
+
'ospalý',
|
|
8598
|
+
'bdělý',
|
|
8599
|
+
'unavený',
|
|
8600
|
+
'líný',
|
|
8601
|
+
'neklidný',
|
|
8602
|
+
'nestálý',
|
|
8603
|
+
'odvážný',
|
|
8604
|
+
'bázlivý',
|
|
8605
|
+
'upřímný',
|
|
8606
|
+
'věrný',
|
|
8607
|
+
'pravý',
|
|
8608
|
+
'falešný',
|
|
8609
|
+
'spravedlivý',
|
|
8610
|
+
'jednoduchý',
|
|
8611
|
+
'složitý',
|
|
8612
|
+
'přirozený',
|
|
8613
|
+
'umělý',
|
|
8614
|
+
'živý',
|
|
8615
|
+
'mrtvý',
|
|
8616
|
+
'zvídavý',
|
|
8617
|
+
'zvláštní',
|
|
8618
|
+
'běžný',
|
|
8619
|
+
'vzácný',
|
|
8620
|
+
'jedinečný',
|
|
8621
|
+
'základní',
|
|
8622
|
+
'prvotní',
|
|
8623
|
+
'hbitý',
|
|
8372
8624
|
];
|
|
8373
|
-
const
|
|
8374
|
-
|
|
8375
|
-
'
|
|
8376
|
-
'
|
|
8377
|
-
'
|
|
8378
|
-
'
|
|
8379
|
-
'
|
|
8380
|
-
'
|
|
8381
|
-
'
|
|
8382
|
-
'
|
|
8383
|
-
'
|
|
8384
|
-
'
|
|
8385
|
-
'
|
|
8386
|
-
'
|
|
8387
|
-
'
|
|
8388
|
-
'
|
|
8625
|
+
const NOUNS$1 = [
|
|
8626
|
+
'jablko',
|
|
8627
|
+
'nebe',
|
|
8628
|
+
'strom',
|
|
8629
|
+
'liška',
|
|
8630
|
+
'kočka',
|
|
8631
|
+
'pták',
|
|
8632
|
+
'pes',
|
|
8633
|
+
'řeka',
|
|
8634
|
+
'hora',
|
|
8635
|
+
'les',
|
|
8636
|
+
'oceán',
|
|
8637
|
+
'hvězda',
|
|
8638
|
+
'měsíc',
|
|
8639
|
+
'slunce',
|
|
8640
|
+
'mrak',
|
|
8641
|
+
'květ',
|
|
8642
|
+
'list',
|
|
8643
|
+
'kámen',
|
|
8644
|
+
'vítr',
|
|
8645
|
+
'déšť',
|
|
8646
|
+
'oheň',
|
|
8647
|
+
'led',
|
|
8648
|
+
'kniha',
|
|
8649
|
+
'sen',
|
|
8650
|
+
'píseň',
|
|
8651
|
+
'cesta',
|
|
8652
|
+
'brána',
|
|
8653
|
+
'klíč',
|
|
8654
|
+
'lampa',
|
|
8655
|
+
'mapa',
|
|
8656
|
+
'dům',
|
|
8657
|
+
'město',
|
|
8658
|
+
'most',
|
|
8659
|
+
'pole',
|
|
8660
|
+
'zahrada',
|
|
8661
|
+
'jezero',
|
|
8662
|
+
'pláž',
|
|
8663
|
+
'ostrov',
|
|
8664
|
+
'údolí',
|
|
8665
|
+
'poušť',
|
|
8666
|
+
'svět',
|
|
8667
|
+
'duch',
|
|
8668
|
+
'srdce',
|
|
8669
|
+
'mysl',
|
|
8670
|
+
'duše',
|
|
8671
|
+
'život',
|
|
8672
|
+
'čas',
|
|
8673
|
+
'prostor',
|
|
8674
|
+
'světlo',
|
|
8675
|
+
'stín',
|
|
8676
|
+
'zvuk',
|
|
8677
|
+
'hudba',
|
|
8678
|
+
'hlas',
|
|
8679
|
+
'slovo',
|
|
8680
|
+
'stránka',
|
|
8681
|
+
'příběh',
|
|
8682
|
+
'perla',
|
|
8683
|
+
'zlato',
|
|
8684
|
+
'stříbro',
|
|
8685
|
+
'krystal',
|
|
8686
|
+
'diamant',
|
|
8687
|
+
'smaragd',
|
|
8688
|
+
'rubín',
|
|
8689
|
+
'stezka',
|
|
8690
|
+
'vrchol',
|
|
8691
|
+
'břeh',
|
|
8692
|
+
'vlna',
|
|
8693
|
+
'příliv',
|
|
8694
|
+
'plamen',
|
|
8695
|
+
'jiskra',
|
|
8696
|
+
'paprsek',
|
|
8697
|
+
'semínko',
|
|
8698
|
+
'kořen',
|
|
8699
|
+
'větev',
|
|
8700
|
+
'pupen',
|
|
8701
|
+
'trn',
|
|
8702
|
+
'kůra',
|
|
8703
|
+
'skořápka',
|
|
8704
|
+
'pírko',
|
|
8705
|
+
'křídlo',
|
|
8706
|
+
'dráp',
|
|
8707
|
+
'tlapa',
|
|
8708
|
+
'hnízdo',
|
|
8709
|
+
'jeskyně',
|
|
8710
|
+
'hájek',
|
|
8711
|
+
'věž',
|
|
8712
|
+
'hrad',
|
|
8713
|
+
'koruna',
|
|
8714
|
+
'meč',
|
|
8715
|
+
'štít',
|
|
8716
|
+
'mince',
|
|
8717
|
+
'drahokam',
|
|
8718
|
+
'prsten',
|
|
8719
|
+
'zvonek',
|
|
8720
|
+
'hodiny',
|
|
8721
|
+
'kompas',
|
|
8722
|
+
'kotva',
|
|
8723
|
+
'pochodeň',
|
|
8724
|
+
'flétna',
|
|
8725
|
+
'harfa',
|
|
8726
|
+
'buben',
|
|
8727
|
+
'čočka',
|
|
8728
|
+
'sklo',
|
|
8729
|
+
'písek',
|
|
8730
|
+
'prach',
|
|
8731
|
+
'mlha',
|
|
8732
|
+
'rosa',
|
|
8733
|
+
'svítání',
|
|
8734
|
+
'soumrak',
|
|
8735
|
+
'noc',
|
|
8736
|
+
'den',
|
|
8737
|
+
'rok',
|
|
8738
|
+
'věk',
|
|
8739
|
+
'blesk',
|
|
8740
|
+
'kapka',
|
|
8741
|
+
'bouře',
|
|
8742
|
+
'sníh',
|
|
8743
|
+
'kroupa',
|
|
8744
|
+
'kouř',
|
|
8745
|
+
'pára',
|
|
8746
|
+
'plyn',
|
|
8747
|
+
'kov',
|
|
8748
|
+
'skála',
|
|
8749
|
+
'hlína',
|
|
8750
|
+
'sůl',
|
|
8751
|
+
'cukr',
|
|
8752
|
+
'dřevo',
|
|
8753
|
+
'kost',
|
|
8754
|
+
'kůže',
|
|
8755
|
+
'tělo',
|
|
8756
|
+
'krev',
|
|
8757
|
+
'buňka',
|
|
8758
|
+
'atom',
|
|
8759
|
+
'tep',
|
|
8760
|
+
'dech',
|
|
8761
|
+
'vzdech',
|
|
8762
|
+
'jméno',
|
|
8763
|
+
'ozvěna',
|
|
8764
|
+
'obraz',
|
|
8765
|
+
'vize',
|
|
8766
|
+
'myšlenka',
|
|
8767
|
+
'nápad',
|
|
8768
|
+
'plán',
|
|
8769
|
+
'cíl',
|
|
8770
|
+
'přání',
|
|
8771
|
+
'naděje',
|
|
8772
|
+
'strach',
|
|
8773
|
+
'radost',
|
|
8774
|
+
'láska',
|
|
8775
|
+
'nenávist',
|
|
8776
|
+
'vůle',
|
|
8777
|
+
'síla',
|
|
8778
|
+
'energie',
|
|
8779
|
+
'pohyb',
|
|
8780
|
+
'rychlost',
|
|
8781
|
+
'místo',
|
|
8782
|
+
'bod',
|
|
8783
|
+
'linie',
|
|
8784
|
+
'tvar',
|
|
8785
|
+
'forma',
|
|
8786
|
+
'velikost',
|
|
8787
|
+
'hmota',
|
|
8788
|
+
'váha',
|
|
8789
|
+
'teplo',
|
|
8790
|
+
'chlad',
|
|
8791
|
+
'barva',
|
|
8792
|
+
'tón',
|
|
8793
|
+
'rytmus',
|
|
8794
|
+
'nálada',
|
|
8795
|
+
'stav',
|
|
8796
|
+
'krok',
|
|
8797
|
+
'pád',
|
|
8798
|
+
'skok',
|
|
8799
|
+
'běh',
|
|
8800
|
+
'let',
|
|
8801
|
+
'klid',
|
|
8802
|
+
'úkol',
|
|
8803
|
+
'práce',
|
|
8804
|
+
'hra',
|
|
8805
|
+
'sport',
|
|
8806
|
+
'umění',
|
|
8807
|
+
'řemeslo',
|
|
8808
|
+
'nástroj',
|
|
8809
|
+
'loď',
|
|
8810
|
+
'člun',
|
|
8811
|
+
'auto',
|
|
8812
|
+
'kolo',
|
|
8813
|
+
'vlak',
|
|
8814
|
+
'letadlo',
|
|
8815
|
+
'uzel',
|
|
8816
|
+
'síť',
|
|
8817
|
+
'krabice',
|
|
8818
|
+
'taška',
|
|
8819
|
+
'dóza',
|
|
8820
|
+
'hrnek',
|
|
8821
|
+
'miska',
|
|
8822
|
+
'talíř',
|
|
8823
|
+
'lžíce',
|
|
8824
|
+
'vidlička',
|
|
8825
|
+
'nůž',
|
|
8826
|
+
'pánev',
|
|
8827
|
+
'hrnec',
|
|
8828
|
+
'postel',
|
|
8829
|
+
'stůl',
|
|
8830
|
+
'židle',
|
|
8831
|
+
'dveře',
|
|
8832
|
+
'stěna',
|
|
8833
|
+
'střecha',
|
|
8834
|
+
'podlaha',
|
|
8835
|
+
'okno',
|
|
8836
|
+
'chodba',
|
|
8389
8837
|
];
|
|
8390
|
-
const
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8838
|
+
const VERBS$1 = [
|
|
8839
|
+
'skáče',
|
|
8840
|
+
'tančí',
|
|
8841
|
+
'letí',
|
|
8842
|
+
'běží',
|
|
8843
|
+
'zpívá',
|
|
8844
|
+
'svítí',
|
|
8845
|
+
'roste',
|
|
8846
|
+
'plyne',
|
|
8847
|
+
'padá',
|
|
8848
|
+
'stoupá',
|
|
8849
|
+
'spí',
|
|
8850
|
+
'kráčí',
|
|
8851
|
+
'mluví',
|
|
8852
|
+
'myslí',
|
|
8853
|
+
'sní',
|
|
8854
|
+
'hledá',
|
|
8855
|
+
'nachází',
|
|
8856
|
+
'dává',
|
|
8857
|
+
'bere',
|
|
8858
|
+
'tvoří',
|
|
8859
|
+
'hoří',
|
|
8860
|
+
'mrzne',
|
|
8861
|
+
'taje',
|
|
8862
|
+
'dýchá',
|
|
8863
|
+
'pulzuje',
|
|
8864
|
+
'bije',
|
|
8865
|
+
'žije',
|
|
8866
|
+
'učí',
|
|
8867
|
+
'ví',
|
|
8868
|
+
'skrývá',
|
|
8869
|
+
'ukazuje',
|
|
8870
|
+
'láme',
|
|
8871
|
+
'opravuje',
|
|
8872
|
+
'ztrácí',
|
|
8873
|
+
'nalézá',
|
|
8874
|
+
'začíná',
|
|
8875
|
+
'končí',
|
|
8876
|
+
'plave',
|
|
8877
|
+
'pluje',
|
|
8878
|
+
'klouže',
|
|
8879
|
+
'točí',
|
|
8880
|
+
'mění',
|
|
8881
|
+
'bledne',
|
|
8882
|
+
'mizí',
|
|
8883
|
+
'rodí',
|
|
8884
|
+
'hučí',
|
|
8885
|
+
'pláče',
|
|
8886
|
+
'závodí',
|
|
8887
|
+
'plíží',
|
|
8888
|
+
'sleduje',
|
|
8889
|
+
'slyší',
|
|
8890
|
+
'cítí',
|
|
8891
|
+
'touží',
|
|
8892
|
+
'doufá',
|
|
8893
|
+
'miluje',
|
|
8894
|
+
'bloudí',
|
|
8895
|
+
'putuje',
|
|
8896
|
+
'cestuje',
|
|
8897
|
+
'překračuje',
|
|
8898
|
+
'potkává',
|
|
8899
|
+
'drží',
|
|
8900
|
+
'sdílí',
|
|
8901
|
+
'jiskří',
|
|
8902
|
+
'plápolá',
|
|
8903
|
+
'léčí',
|
|
8904
|
+
'řeší',
|
|
8905
|
+
'otevírá',
|
|
8906
|
+
'zavírá',
|
|
8907
|
+
'zvedá',
|
|
8908
|
+
'táhne',
|
|
8909
|
+
'tlačí',
|
|
8910
|
+
'hází',
|
|
8911
|
+
'chytá',
|
|
8912
|
+
'dělá',
|
|
8913
|
+
'vidí',
|
|
8914
|
+
'chutná',
|
|
8915
|
+
'voní',
|
|
8916
|
+
'spěchá',
|
|
8917
|
+
'zastaví',
|
|
8918
|
+
'jde',
|
|
8919
|
+
'přichází',
|
|
8920
|
+
'odchází',
|
|
8921
|
+
'jedná',
|
|
8922
|
+
'existuje',
|
|
8923
|
+
'zmenšuje',
|
|
8924
|
+
'rozšiřuje',
|
|
8925
|
+
'zužuje',
|
|
8926
|
+
'hřeje',
|
|
8927
|
+
'chladí',
|
|
8928
|
+
'suší',
|
|
8929
|
+
'máčí',
|
|
8930
|
+
'plní',
|
|
8931
|
+
'vyprazdňuje',
|
|
8932
|
+
'pouští',
|
|
8933
|
+
'získává',
|
|
8934
|
+
'vítězí',
|
|
8935
|
+
'selhává',
|
|
8936
|
+
'zkouší',
|
|
8937
|
+
'používá',
|
|
8938
|
+
'dostává',
|
|
8939
|
+
'měří',
|
|
8940
|
+
'stojí',
|
|
8941
|
+
'dosahuje',
|
|
8942
|
+
'míjí',
|
|
8943
|
+
'udeří',
|
|
8944
|
+
'vede',
|
|
8945
|
+
'následuje',
|
|
8946
|
+
'pomáhá',
|
|
8947
|
+
'slouží',
|
|
8948
|
+
'trénuje',
|
|
8949
|
+
'kóduje',
|
|
8950
|
+
'píše',
|
|
8951
|
+
'čte',
|
|
8952
|
+
'kreslí',
|
|
8953
|
+
'maluje',
|
|
8954
|
+
'tvaruje',
|
|
8955
|
+
'spojuje',
|
|
8956
|
+
'dělí',
|
|
8957
|
+
'váže',
|
|
8958
|
+
'zraňuje',
|
|
8959
|
+
'chrání',
|
|
8960
|
+
'bojuje',
|
|
8961
|
+
'brání',
|
|
8962
|
+
'útočí',
|
|
8963
|
+
'uniká',
|
|
8964
|
+
'lapá',
|
|
8965
|
+
'osvobozuje',
|
|
8966
|
+
'poutá',
|
|
8967
|
+
'spřádá',
|
|
8968
|
+
'tká',
|
|
8969
|
+
'vrhá',
|
|
8970
|
+
'nese',
|
|
8971
|
+
'přenáší',
|
|
8972
|
+
'vrací',
|
|
8973
|
+
'zrychluje',
|
|
8974
|
+
'zpomaluje',
|
|
8975
|
+
'probouzí',
|
|
8976
|
+
'uspává',
|
|
8977
|
+
'šeptá',
|
|
8978
|
+
'volá',
|
|
8979
|
+
'hledí',
|
|
8980
|
+
'čeká',
|
|
8981
|
+
'bdí',
|
|
8982
|
+
'rozkvétá',
|
|
8983
|
+
'klíčí',
|
|
8984
|
+
'zraje',
|
|
8985
|
+
'chvěje',
|
|
8986
|
+
'třpytí',
|
|
8987
|
+
'shromažďuje',
|
|
8988
|
+
'rozhazuje',
|
|
8989
|
+
'tápe',
|
|
8990
|
+
'žhne',
|
|
8991
|
+
'vibruje',
|
|
8992
|
+
'šumí',
|
|
8993
|
+
'stéká',
|
|
8994
|
+
'vypráví',
|
|
8995
|
+
'plánuje',
|
|
8996
|
+
'počítá',
|
|
8997
|
+
'váhá',
|
|
8998
|
+
'riskuje',
|
|
8395
8999
|
];
|
|
8396
9000
|
/**
|
|
8397
|
-
*
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
const expandedHash = `${hash}${hash}`;
|
|
8401
|
-
const start = (segmentIndex * HASH_SEGMENT_LENGTH + segmentIndex) % hash.length;
|
|
8402
|
-
return parseInt(expandedHash.substring(start, start + HASH_SEGMENT_LENGTH), 16);
|
|
8403
|
-
}
|
|
8404
|
-
/**
|
|
8405
|
-
* Picks a deterministic item from a list based on the hash seed.
|
|
8406
|
-
*/
|
|
8407
|
-
function pickFromHash(hash, segmentIndex, list) {
|
|
8408
|
-
const seed = getHashSeed(hash, segmentIndex);
|
|
8409
|
-
return list[seed % list.length];
|
|
8410
|
-
}
|
|
8411
|
-
/**
|
|
8412
|
-
* Index constants for story part selection to avoid magic numbers.
|
|
8413
|
-
*/
|
|
8414
|
-
const ADJECTIVE3_INDEX = 9;
|
|
8415
|
-
const NOUN3_INDEX = 10;
|
|
8416
|
-
/**
|
|
8417
|
-
* Creates the deterministic story parts used by the sentence templates.
|
|
9001
|
+
* Czech word lists used by the linguistic hash.
|
|
9002
|
+
*
|
|
9003
|
+
* @private utility of `linguisticHash`
|
|
8418
9004
|
*/
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
adjective1: pickFromHash(hash, 3, ADJECTIVES),
|
|
8425
|
-
noun1: pickFromHash(hash, 4, NOUNS),
|
|
8426
|
-
verb1: pickFromHash(hash, 5, VERBS),
|
|
8427
|
-
adjective2: pickFromHash(hash, 6, ADJECTIVES),
|
|
8428
|
-
noun2: pickFromHash(hash, 7, NOUNS),
|
|
8429
|
-
verb2: pickFromHash(hash, 8, VERBS),
|
|
8430
|
-
adjective3: pickFromHash(hash, ADJECTIVE3_INDEX, ADJECTIVES),
|
|
8431
|
-
noun3: pickFromHash(hash, NOUN3_INDEX, NOUNS),
|
|
8432
|
-
};
|
|
8433
|
-
}
|
|
9005
|
+
const LINGUISTIC_HASH_WORD_LISTS_CS = {
|
|
9006
|
+
adjective: ADJECTIVES$1,
|
|
9007
|
+
noun: NOUNS$1,
|
|
9008
|
+
verb: VERBS$1,
|
|
9009
|
+
};
|
|
8434
9010
|
/**
|
|
8435
|
-
*
|
|
9011
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
8436
9012
|
*/
|
|
8437
|
-
|
|
9013
|
+
|
|
8438
9014
|
/**
|
|
8439
|
-
*
|
|
9015
|
+
* @@@
|
|
9016
|
+
*
|
|
9017
|
+
* @private utility of `linguisticHash`
|
|
8440
9018
|
*/
|
|
8441
|
-
function createStorySentence(hash) {
|
|
8442
|
-
const parts = createStoryParts(hash);
|
|
8443
|
-
const template = pickFromHash(hash, STORY_TEMPLATE_INDEX, STORY_TEMPLATES);
|
|
8444
|
-
return template(parts).trim();
|
|
8445
|
-
}
|
|
8446
9019
|
const ADJECTIVES = [
|
|
8447
9020
|
'red',
|
|
8448
9021
|
'blue',
|
|
@@ -9117,8 +9690,215 @@ const VERBS = [
|
|
|
9117
9690
|
'spinning',
|
|
9118
9691
|
];
|
|
9119
9692
|
/**
|
|
9120
|
-
*
|
|
9693
|
+
* English word lists used by the linguistic hash.
|
|
9694
|
+
*
|
|
9695
|
+
* @private utility of `linguisticHash`
|
|
9696
|
+
*/
|
|
9697
|
+
const LINGUISTIC_HASH_WORD_LISTS_EN = {
|
|
9698
|
+
adjective: ADJECTIVES,
|
|
9699
|
+
noun: NOUNS,
|
|
9700
|
+
verb: VERBS,
|
|
9701
|
+
};
|
|
9702
|
+
/**
|
|
9703
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
9704
|
+
*/
|
|
9705
|
+
|
|
9706
|
+
/**
|
|
9707
|
+
* Default language used for linguistic hashes.
|
|
9708
|
+
*
|
|
9709
|
+
* @private utility of `linguisticHash`
|
|
9710
|
+
*/
|
|
9711
|
+
const DEFAULT_LINGUISTIC_HASH_LANGUAGE = 'en';
|
|
9712
|
+
/**
|
|
9713
|
+
* @@@
|
|
9714
|
+
*
|
|
9715
|
+
* @private utility of `linguisticHash`
|
|
9716
|
+
*/
|
|
9717
|
+
const LANGUAGE_CONFIGS = {
|
|
9718
|
+
en: {
|
|
9719
|
+
language: 'en',
|
|
9720
|
+
label: 'English',
|
|
9721
|
+
wordLists: LINGUISTIC_HASH_WORD_LISTS_EN,
|
|
9722
|
+
},
|
|
9723
|
+
cs: {
|
|
9724
|
+
language: 'cs',
|
|
9725
|
+
label: 'Czech',
|
|
9726
|
+
wordLists: LINGUISTIC_HASH_WORD_LISTS_CS,
|
|
9727
|
+
},
|
|
9728
|
+
};
|
|
9729
|
+
/**
|
|
9730
|
+
* Normalizes a requested language to a supported linguistic hash language.
|
|
9731
|
+
*
|
|
9732
|
+
* @private utility of `linguisticHash`
|
|
9733
|
+
*/
|
|
9734
|
+
function normalizeLinguisticHashLanguage(language) {
|
|
9735
|
+
if (typeof language !== 'string') {
|
|
9736
|
+
return DEFAULT_LINGUISTIC_HASH_LANGUAGE;
|
|
9737
|
+
}
|
|
9738
|
+
const normalized = language.trim().toLowerCase();
|
|
9739
|
+
if (normalized === 'cs') {
|
|
9740
|
+
return 'cs';
|
|
9741
|
+
}
|
|
9742
|
+
if (normalized === 'en') {
|
|
9743
|
+
return 'en';
|
|
9744
|
+
}
|
|
9745
|
+
return DEFAULT_LINGUISTIC_HASH_LANGUAGE;
|
|
9746
|
+
}
|
|
9747
|
+
/**
|
|
9748
|
+
* Returns the language configuration for linguistic hash generation.
|
|
9749
|
+
*
|
|
9750
|
+
* @private utility of `linguisticHash`
|
|
9751
|
+
*/
|
|
9752
|
+
function getLinguisticHashLanguageConfig(language) {
|
|
9753
|
+
const normalized = normalizeLinguisticHashLanguage(language);
|
|
9754
|
+
return LANGUAGE_CONFIGS[normalized];
|
|
9755
|
+
}
|
|
9756
|
+
|
|
9757
|
+
// <- TODO: !!!! Remove re-exports
|
|
9758
|
+
/**
|
|
9759
|
+
* Creates a human-readable hash as a short, story-like phrase.
|
|
9760
|
+
*
|
|
9761
|
+
* @param wordCount how many words to include (defaults to {@link DEFAULT_LINGUISTIC_HASH_WORD_COUNT}, clamped to
|
|
9762
|
+
* {@link MIN_LINGUISTIC_HASH_WORD_COUNT}..{@link MAX_LINGUISTIC_HASH_WORD_COUNT})
|
|
9763
|
+
* @param language optional language code (defaults to {@link DEFAULT_LINGUISTIC_HASH_LANGUAGE})
|
|
9764
|
+
*
|
|
9765
|
+
* @public exported from `@promptbook/utils`
|
|
9766
|
+
*/
|
|
9767
|
+
async function linguisticHash(input, wordCount, language) {
|
|
9768
|
+
const hash = computeHash(input);
|
|
9769
|
+
const normalizedWordCount = normalizeLinguisticHashWordCount(wordCount);
|
|
9770
|
+
const languageConfig = getLinguisticHashLanguageConfig(language);
|
|
9771
|
+
const words = createLinguisticHashWords(hash, normalizedWordCount, languageConfig.wordLists);
|
|
9772
|
+
return capitalize(words.join(' '));
|
|
9773
|
+
}
|
|
9774
|
+
/**
|
|
9775
|
+
* @@@
|
|
9776
|
+
*
|
|
9777
|
+
* @private utility of `linguisticHash`
|
|
9778
|
+
*/
|
|
9779
|
+
const HASH_SEGMENT_LENGTH = 8;
|
|
9780
|
+
/**
|
|
9781
|
+
* The minimum number of words for a linguistic hash.
|
|
9782
|
+
*
|
|
9783
|
+
* @private utility of `linguisticHash`
|
|
9784
|
+
*/
|
|
9785
|
+
const MIN_LINGUISTIC_HASH_WORD_COUNT = 1;
|
|
9786
|
+
/**
|
|
9787
|
+
* The default number of words for a linguistic hash.
|
|
9788
|
+
*
|
|
9789
|
+
* @private utility of `linguisticHash`
|
|
9790
|
+
*/
|
|
9791
|
+
const DEFAULT_LINGUISTIC_HASH_WORD_COUNT = 7;
|
|
9792
|
+
/**
|
|
9793
|
+
* Extracts a deterministic numeric seed from a SHA-256 hash.
|
|
9794
|
+
*
|
|
9795
|
+
* @private utility of `linguisticHash`
|
|
9796
|
+
*/
|
|
9797
|
+
function getHashSeed(hash, segmentIndex) {
|
|
9798
|
+
const expandedHash = `${hash}${hash}`;
|
|
9799
|
+
const start = (segmentIndex * HASH_SEGMENT_LENGTH + segmentIndex) % hash.length;
|
|
9800
|
+
return parseInt(expandedHash.substring(start, start + HASH_SEGMENT_LENGTH), 16);
|
|
9801
|
+
}
|
|
9802
|
+
/**
|
|
9803
|
+
* Picks a deterministic item from a list based on the hash seed.
|
|
9804
|
+
*
|
|
9805
|
+
* @private utility of `linguisticHash`
|
|
9806
|
+
*/
|
|
9807
|
+
function pickFromHash(hash, segmentIndex, list) {
|
|
9808
|
+
const seed = getHashSeed(hash, segmentIndex);
|
|
9809
|
+
return list[seed % list.length];
|
|
9810
|
+
}
|
|
9811
|
+
/**
|
|
9812
|
+
* Ordered word kinds used to build the linguistic hash output.
|
|
9813
|
+
*
|
|
9814
|
+
* @private utility of `linguisticHash`
|
|
9815
|
+
*/
|
|
9816
|
+
const WORD_SEQUENCE = [
|
|
9817
|
+
'adjective',
|
|
9818
|
+
'noun',
|
|
9819
|
+
'verb',
|
|
9820
|
+
'adjective',
|
|
9821
|
+
'noun',
|
|
9822
|
+
'verb',
|
|
9823
|
+
'adjective',
|
|
9824
|
+
'noun',
|
|
9825
|
+
'verb',
|
|
9826
|
+
'adjective',
|
|
9827
|
+
'noun',
|
|
9828
|
+
'verb',
|
|
9829
|
+
'adjective',
|
|
9830
|
+
'noun',
|
|
9831
|
+
'verb',
|
|
9832
|
+
'adjective',
|
|
9833
|
+
'noun',
|
|
9834
|
+
'verb',
|
|
9835
|
+
'adjective',
|
|
9836
|
+
'noun',
|
|
9837
|
+
];
|
|
9838
|
+
/**
|
|
9839
|
+
* The maximum number of words for a linguistic hash.
|
|
9840
|
+
*
|
|
9841
|
+
* @private utility of `linguisticHash`
|
|
9842
|
+
*/
|
|
9843
|
+
const MAX_LINGUISTIC_HASH_WORD_COUNT = WORD_SEQUENCE.length;
|
|
9844
|
+
/**
|
|
9845
|
+
* Index of the noun used for single-word hashes.
|
|
9846
|
+
*
|
|
9847
|
+
* @private utility of `linguisticHash`
|
|
9848
|
+
*/
|
|
9849
|
+
const SINGLE_WORD_INDEX = 1;
|
|
9850
|
+
/**
|
|
9851
|
+
* Normalizes the word count to a supported integer range.
|
|
9852
|
+
*
|
|
9853
|
+
* @private utility of `linguisticHash`
|
|
9854
|
+
*/
|
|
9855
|
+
function normalizeLinguisticHashWordCount(wordCount) {
|
|
9856
|
+
if (typeof wordCount !== 'number' || !Number.isFinite(wordCount)) {
|
|
9857
|
+
return DEFAULT_LINGUISTIC_HASH_WORD_COUNT;
|
|
9858
|
+
}
|
|
9859
|
+
const rounded = Math.round(wordCount);
|
|
9860
|
+
return Math.min(MAX_LINGUISTIC_HASH_WORD_COUNT, Math.max(MIN_LINGUISTIC_HASH_WORD_COUNT, rounded));
|
|
9861
|
+
}
|
|
9862
|
+
/**
|
|
9863
|
+
* Picks a deterministic word from the hash by kind.
|
|
9864
|
+
*
|
|
9865
|
+
* @private utility of `linguisticHash`
|
|
9866
|
+
*/
|
|
9867
|
+
function pickWordFromHash(hash, segmentIndex, wordKind, wordLists) {
|
|
9868
|
+
return pickFromHash(hash, segmentIndex, wordLists[wordKind]);
|
|
9869
|
+
}
|
|
9870
|
+
/**
|
|
9871
|
+
* Creates the deterministic word sequence used for the linguistic hash output.
|
|
9872
|
+
*
|
|
9873
|
+
* @private utility of `linguisticHash`
|
|
9121
9874
|
*/
|
|
9875
|
+
function createLinguisticHashWordSequence(hash, wordLists) {
|
|
9876
|
+
return WORD_SEQUENCE.map((wordKind, index) => pickWordFromHash(hash, index, wordKind, wordLists));
|
|
9877
|
+
}
|
|
9878
|
+
/**
|
|
9879
|
+
* Selects the requested number of words from the hash output.
|
|
9880
|
+
*
|
|
9881
|
+
* @private utility of `linguisticHash`
|
|
9882
|
+
*/
|
|
9883
|
+
function createLinguisticHashWords(hash, wordCount, wordLists) {
|
|
9884
|
+
const words = createLinguisticHashWordSequence(hash, wordLists);
|
|
9885
|
+
if (wordCount === 1) {
|
|
9886
|
+
return [words[SINGLE_WORD_INDEX]];
|
|
9887
|
+
}
|
|
9888
|
+
return words.slice(0, wordCount);
|
|
9889
|
+
}
|
|
9890
|
+
|
|
9891
|
+
/**
|
|
9892
|
+
* Simple wrapper `new Date().toISOString()`
|
|
9893
|
+
*
|
|
9894
|
+
* Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
|
|
9895
|
+
*
|
|
9896
|
+
* @returns string_date branded type
|
|
9897
|
+
* @public exported from `@promptbook/utils`
|
|
9898
|
+
*/
|
|
9899
|
+
function $getCurrentDate() {
|
|
9900
|
+
return new Date().toISOString();
|
|
9901
|
+
}
|
|
9122
9902
|
|
|
9123
9903
|
/**
|
|
9124
9904
|
* Makes first letter of a string lowercase
|
|
@@ -16610,6 +17390,21 @@ function book(strings, ...values) {
|
|
|
16610
17390
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
16611
17391
|
*/
|
|
16612
17392
|
|
|
17393
|
+
/**
|
|
17394
|
+
* Tool call name emitted while preparing a GPT assistant for an agent.
|
|
17395
|
+
*
|
|
17396
|
+
* @public exported from `@promptbook/types`
|
|
17397
|
+
*/
|
|
17398
|
+
const ASSISTANT_PREPARATION_TOOL_CALL_NAME = 'assistant_preparation';
|
|
17399
|
+
/**
|
|
17400
|
+
* Checks whether a tool call is the assistant preparation marker.
|
|
17401
|
+
*
|
|
17402
|
+
* @public exported from `@promptbook/types`
|
|
17403
|
+
*/
|
|
17404
|
+
function isAssistantPreparationToolCall(toolCall) {
|
|
17405
|
+
return toolCall.name === ASSISTANT_PREPARATION_TOOL_CALL_NAME;
|
|
17406
|
+
}
|
|
17407
|
+
|
|
16613
17408
|
/*! *****************************************************************************
|
|
16614
17409
|
Copyright (c) Microsoft Corporation.
|
|
16615
17410
|
|
|
@@ -17735,14 +18530,27 @@ function humanizeAiTextEmdashed(aiText) {
|
|
|
17735
18530
|
* @public exported from `@promptbook/markdown-utils`
|
|
17736
18531
|
*/
|
|
17737
18532
|
function humanizeAiTextQuotes(aiText) {
|
|
17738
|
-
return aiText
|
|
17739
|
-
.replace(/[“”„‟«»❝❞〝〞〟"]/g, '"')
|
|
17740
|
-
.replace(/[‚‘’‛‹›❛❜'ʼ]/g, "'");
|
|
18533
|
+
return aiText.replace(/[“”„‟«»❝❞〝〞〟"]/g, '"').replace(/[‚‘’‛‹›❛❜'ʼ]/g, "'");
|
|
17741
18534
|
}
|
|
17742
18535
|
/**
|
|
17743
18536
|
* Note: [🏂] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
|
|
17744
18537
|
*/
|
|
17745
18538
|
|
|
18539
|
+
/**
|
|
18540
|
+
* Remove bracketed source citation artifacts like `\u30105:1\u2020source\u3011`.
|
|
18541
|
+
*
|
|
18542
|
+
* Note: [??] This function is idempotent.
|
|
18543
|
+
* Tip: If you want to do the full cleanup, look for `humanizeAiText` exported `@promptbook/markdown-utils`
|
|
18544
|
+
*
|
|
18545
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
18546
|
+
*/
|
|
18547
|
+
function humanizeAiTextSources(aiText) {
|
|
18548
|
+
return aiText.replace(/[ \t]*\u3010\s*\d+(?:\s*:\s*\d+)?\s*\u2020source\s*\u3011/g, '');
|
|
18549
|
+
}
|
|
18550
|
+
/**
|
|
18551
|
+
* Note: [??] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
|
|
18552
|
+
*/
|
|
18553
|
+
|
|
17746
18554
|
/**
|
|
17747
18555
|
* Change unprintable hard spaces to regular spaces and drop zero-width spaces
|
|
17748
18556
|
*
|
|
@@ -17752,9 +18560,7 @@ function humanizeAiTextQuotes(aiText) {
|
|
|
17752
18560
|
* @public exported from `@promptbook/markdown-utils`
|
|
17753
18561
|
*/
|
|
17754
18562
|
function humanizeAiTextWhitespace(aiText) {
|
|
17755
|
-
return aiText
|
|
17756
|
-
.replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g, ' ')
|
|
17757
|
-
.replace(/[\u200B\uFEFF\u2060]/g, '');
|
|
18563
|
+
return aiText.replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g, ' ').replace(/[\u200B\uFEFF\u2060]/g, '');
|
|
17758
18564
|
}
|
|
17759
18565
|
/**
|
|
17760
18566
|
* Note: [🏂] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
|
|
@@ -17773,6 +18579,7 @@ function humanizeAiText(aiText) {
|
|
|
17773
18579
|
cleanedText = humanizeAiTextEllipsis(cleanedText);
|
|
17774
18580
|
cleanedText = humanizeAiTextEmdashed(cleanedText);
|
|
17775
18581
|
cleanedText = humanizeAiTextQuotes(cleanedText);
|
|
18582
|
+
cleanedText = humanizeAiTextSources(cleanedText);
|
|
17776
18583
|
cleanedText = humanizeAiTextWhitespace(cleanedText);
|
|
17777
18584
|
return cleanedText;
|
|
17778
18585
|
}
|
|
@@ -20263,17 +21070,32 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20263
21070
|
});
|
|
20264
21071
|
}
|
|
20265
21072
|
async createNewAssistant(options) {
|
|
21073
|
+
var _a, _b, _c;
|
|
20266
21074
|
if (!this.isCreatingNewAssistantsAllowed) {
|
|
20267
21075
|
throw new NotAllowed(`Creating new assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
|
|
20268
21076
|
}
|
|
20269
21077
|
// await this.playground();
|
|
20270
21078
|
const { name, instructions, knowledgeSources, tools } = options;
|
|
21079
|
+
const preparationStartedAtMs = Date.now();
|
|
21080
|
+
const knowledgeSourcesCount = (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0;
|
|
21081
|
+
const toolsCount = (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0;
|
|
21082
|
+
if (this.options.isVerbose) {
|
|
21083
|
+
console.info('[🤰]', 'Starting OpenAI assistant creation', {
|
|
21084
|
+
name,
|
|
21085
|
+
knowledgeSourcesCount,
|
|
21086
|
+
toolsCount,
|
|
21087
|
+
instructionsLength: instructions.length,
|
|
21088
|
+
});
|
|
21089
|
+
}
|
|
20271
21090
|
const client = await this.getClient();
|
|
20272
21091
|
let vectorStoreId;
|
|
20273
21092
|
// If knowledge sources are provided, create a vector store with them
|
|
20274
21093
|
if (knowledgeSources && knowledgeSources.length > 0) {
|
|
20275
21094
|
if (this.options.isVerbose) {
|
|
20276
|
-
console.info(
|
|
21095
|
+
console.info('[🤰]', 'Creating vector store with knowledge sources', {
|
|
21096
|
+
name,
|
|
21097
|
+
knowledgeSourcesCount,
|
|
21098
|
+
});
|
|
20277
21099
|
}
|
|
20278
21100
|
// Create a vector store
|
|
20279
21101
|
const vectorStore = await client.beta.vectorStores.create({
|
|
@@ -20281,12 +21103,22 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20281
21103
|
});
|
|
20282
21104
|
vectorStoreId = vectorStore.id;
|
|
20283
21105
|
if (this.options.isVerbose) {
|
|
20284
|
-
console.info(
|
|
21106
|
+
console.info('[🤰]', 'Vector store created', {
|
|
21107
|
+
vectorStoreId,
|
|
21108
|
+
});
|
|
20285
21109
|
}
|
|
20286
21110
|
// Upload files from knowledge sources to the vector store
|
|
20287
21111
|
const fileStreams = [];
|
|
20288
|
-
for (const source of knowledgeSources) {
|
|
21112
|
+
for (const [index, source] of knowledgeSources.entries()) {
|
|
20289
21113
|
try {
|
|
21114
|
+
if (this.options.isVerbose) {
|
|
21115
|
+
console.info('[🤰]', 'Processing knowledge source', {
|
|
21116
|
+
index: index + 1,
|
|
21117
|
+
total: knowledgeSources.length,
|
|
21118
|
+
source,
|
|
21119
|
+
sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
|
|
21120
|
+
});
|
|
21121
|
+
}
|
|
20290
21122
|
// Check if it's a URL
|
|
20291
21123
|
if (source.startsWith('http://') || source.startsWith('https://')) {
|
|
20292
21124
|
// Download the file
|
|
@@ -20331,7 +21163,10 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20331
21163
|
files: fileStreams,
|
|
20332
21164
|
});
|
|
20333
21165
|
if (this.options.isVerbose) {
|
|
20334
|
-
console.info(
|
|
21166
|
+
console.info('[🤰]', 'Uploaded files to vector store', {
|
|
21167
|
+
vectorStoreId,
|
|
21168
|
+
fileCount: fileStreams.length,
|
|
21169
|
+
});
|
|
20335
21170
|
}
|
|
20336
21171
|
}
|
|
20337
21172
|
catch (error) {
|
|
@@ -20359,8 +21194,21 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20359
21194
|
},
|
|
20360
21195
|
};
|
|
20361
21196
|
}
|
|
21197
|
+
if (this.options.isVerbose) {
|
|
21198
|
+
console.info('[🤰]', 'Creating OpenAI assistant', {
|
|
21199
|
+
name,
|
|
21200
|
+
model: assistantConfig.model,
|
|
21201
|
+
toolCount: (_c = assistantConfig === null || assistantConfig === void 0 ? void 0 : assistantConfig.tools) === null || _c === void 0 ? void 0 : _c.length,
|
|
21202
|
+
hasVectorStore: Boolean(vectorStoreId),
|
|
21203
|
+
});
|
|
21204
|
+
}
|
|
20362
21205
|
const assistant = await client.beta.assistants.create(assistantConfig);
|
|
20363
|
-
|
|
21206
|
+
if (this.options.isVerbose) {
|
|
21207
|
+
console.info('[🤰]', 'OpenAI assistant created', {
|
|
21208
|
+
assistantId: assistant.id,
|
|
21209
|
+
elapsedMs: Date.now() - preparationStartedAtMs,
|
|
21210
|
+
});
|
|
21211
|
+
}
|
|
20364
21212
|
// TODO: [🐱🚀] Try listing existing assistants
|
|
20365
21213
|
// TODO: [🐱🚀] Try marking existing assistants by DISCRIMINANT
|
|
20366
21214
|
// TODO: [🐱🚀] Allow to update and reconnect to existing assistants
|
|
@@ -20371,17 +21219,34 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20371
21219
|
});
|
|
20372
21220
|
}
|
|
20373
21221
|
async updateAssistant(options) {
|
|
21222
|
+
var _a, _b, _c, _d;
|
|
20374
21223
|
if (!this.isCreatingNewAssistantsAllowed) {
|
|
20375
21224
|
throw new NotAllowed(`Updating assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
|
|
20376
21225
|
}
|
|
20377
21226
|
const { assistantId, name, instructions, knowledgeSources, tools } = options;
|
|
21227
|
+
const preparationStartedAtMs = Date.now();
|
|
21228
|
+
const knowledgeSourcesCount = (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0;
|
|
21229
|
+
const toolsCount = (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0;
|
|
21230
|
+
if (this.options.isVerbose) {
|
|
21231
|
+
console.info('[🤰]', 'Starting OpenAI assistant update', {
|
|
21232
|
+
assistantId,
|
|
21233
|
+
name,
|
|
21234
|
+
knowledgeSourcesCount,
|
|
21235
|
+
toolsCount,
|
|
21236
|
+
instructionsLength: (_c = instructions === null || instructions === void 0 ? void 0 : instructions.length) !== null && _c !== void 0 ? _c : 0,
|
|
21237
|
+
});
|
|
21238
|
+
}
|
|
20378
21239
|
const client = await this.getClient();
|
|
20379
21240
|
let vectorStoreId;
|
|
20380
21241
|
// If knowledge sources are provided, create a vector store with them
|
|
20381
21242
|
// TODO: [🧠] Reuse vector store creation logic from createNewAssistant
|
|
20382
21243
|
if (knowledgeSources && knowledgeSources.length > 0) {
|
|
20383
21244
|
if (this.options.isVerbose) {
|
|
20384
|
-
console.info(
|
|
21245
|
+
console.info('[🤰]', 'Creating vector store for assistant update', {
|
|
21246
|
+
assistantId,
|
|
21247
|
+
name,
|
|
21248
|
+
knowledgeSourcesCount,
|
|
21249
|
+
});
|
|
20385
21250
|
}
|
|
20386
21251
|
// Create a vector store
|
|
20387
21252
|
const vectorStore = await client.beta.vectorStores.create({
|
|
@@ -20389,12 +21254,22 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20389
21254
|
});
|
|
20390
21255
|
vectorStoreId = vectorStore.id;
|
|
20391
21256
|
if (this.options.isVerbose) {
|
|
20392
|
-
console.info(
|
|
21257
|
+
console.info('[🤰]', 'Vector store created for assistant update', {
|
|
21258
|
+
vectorStoreId,
|
|
21259
|
+
});
|
|
20393
21260
|
}
|
|
20394
21261
|
// Upload files from knowledge sources to the vector store
|
|
20395
21262
|
const fileStreams = [];
|
|
20396
|
-
for (const source of knowledgeSources) {
|
|
21263
|
+
for (const [index, source] of knowledgeSources.entries()) {
|
|
20397
21264
|
try {
|
|
21265
|
+
if (this.options.isVerbose) {
|
|
21266
|
+
console.info('[🤰]', 'Processing knowledge source for update', {
|
|
21267
|
+
index: index + 1,
|
|
21268
|
+
total: knowledgeSources.length,
|
|
21269
|
+
source,
|
|
21270
|
+
sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
|
|
21271
|
+
});
|
|
21272
|
+
}
|
|
20398
21273
|
// Check if it's a URL
|
|
20399
21274
|
if (source.startsWith('http://') || source.startsWith('https://')) {
|
|
20400
21275
|
// Download the file
|
|
@@ -20439,7 +21314,10 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20439
21314
|
files: fileStreams,
|
|
20440
21315
|
});
|
|
20441
21316
|
if (this.options.isVerbose) {
|
|
20442
|
-
console.info(
|
|
21317
|
+
console.info('[🤰]', 'Uploaded files to vector store for update', {
|
|
21318
|
+
vectorStoreId,
|
|
21319
|
+
fileCount: fileStreams.length,
|
|
21320
|
+
});
|
|
20443
21321
|
}
|
|
20444
21322
|
}
|
|
20445
21323
|
catch (error) {
|
|
@@ -20463,9 +21341,20 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
20463
21341
|
},
|
|
20464
21342
|
};
|
|
20465
21343
|
}
|
|
21344
|
+
if (this.options.isVerbose) {
|
|
21345
|
+
console.info('[🤰]', 'Updating OpenAI assistant', {
|
|
21346
|
+
assistantId,
|
|
21347
|
+
name,
|
|
21348
|
+
toolCount: (_d = assistantUpdate === null || assistantUpdate === void 0 ? void 0 : assistantUpdate.tools) === null || _d === void 0 ? void 0 : _d.length,
|
|
21349
|
+
hasVectorStore: Boolean(vectorStoreId),
|
|
21350
|
+
});
|
|
21351
|
+
}
|
|
20466
21352
|
const assistant = await client.beta.assistants.update(assistantId, assistantUpdate);
|
|
20467
21353
|
if (this.options.isVerbose) {
|
|
20468
|
-
console.
|
|
21354
|
+
console.info('[🤰]', 'OpenAI assistant updated', {
|
|
21355
|
+
assistantId: assistant.id,
|
|
21356
|
+
elapsedMs: Date.now() - preparationStartedAtMs,
|
|
21357
|
+
});
|
|
20469
21358
|
}
|
|
20470
21359
|
return new OpenAiAssistantExecutionTools({
|
|
20471
21360
|
...this.options,
|
|
@@ -20503,6 +21392,33 @@ const DISCRIMINANT = 'OPEN_AI_ASSISTANT_V1';
|
|
|
20503
21392
|
* TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
|
|
20504
21393
|
*/
|
|
20505
21394
|
|
|
21395
|
+
/**
|
|
21396
|
+
* Emits a progress update to signal assistant preparation before long setup work.
|
|
21397
|
+
*/
|
|
21398
|
+
function emitAssistantPreparationProgress(options) {
|
|
21399
|
+
const startedAt = $getCurrentDate();
|
|
21400
|
+
options.onProgress({
|
|
21401
|
+
content: '',
|
|
21402
|
+
modelName: options.modelName,
|
|
21403
|
+
timing: {
|
|
21404
|
+
start: startedAt,
|
|
21405
|
+
complete: startedAt,
|
|
21406
|
+
},
|
|
21407
|
+
usage: UNCERTAIN_USAGE,
|
|
21408
|
+
rawPromptContent: options.prompt.content,
|
|
21409
|
+
rawRequest: null,
|
|
21410
|
+
rawResponse: {
|
|
21411
|
+
status: 'assistant_preparation',
|
|
21412
|
+
},
|
|
21413
|
+
toolCalls: [
|
|
21414
|
+
{
|
|
21415
|
+
name: ASSISTANT_PREPARATION_TOOL_CALL_NAME,
|
|
21416
|
+
arguments: options.phase ? { phase: options.phase } : {},
|
|
21417
|
+
createdAt: startedAt,
|
|
21418
|
+
},
|
|
21419
|
+
],
|
|
21420
|
+
});
|
|
21421
|
+
}
|
|
20506
21422
|
/**
|
|
20507
21423
|
* Execution Tools for calling LLM models with a predefined agent "soul"
|
|
20508
21424
|
* This wraps underlying LLM execution tools and applies agent-specific system prompts and requirements
|
|
@@ -20561,10 +21477,32 @@ class AgentLlmExecutionTools {
|
|
|
20561
21477
|
*/
|
|
20562
21478
|
async getModelRequirements() {
|
|
20563
21479
|
if (this._cachedModelRequirements === null) {
|
|
21480
|
+
const preparationStartedAtMs = Date.now();
|
|
21481
|
+
if (this.options.isVerbose) {
|
|
21482
|
+
console.info('[🤰]', 'Preparing agent model requirements', {
|
|
21483
|
+
agent: this.title,
|
|
21484
|
+
});
|
|
21485
|
+
}
|
|
20564
21486
|
// Get available models from underlying LLM tools for best model selection
|
|
21487
|
+
const availableModelsStartedAtMs = Date.now();
|
|
20565
21488
|
const availableModels = await this.options.llmTools.listModels();
|
|
21489
|
+
if (this.options.isVerbose) {
|
|
21490
|
+
console.info('[🤰]', 'Available models resolved for agent', {
|
|
21491
|
+
agent: this.title,
|
|
21492
|
+
modelCount: availableModels.length,
|
|
21493
|
+
elapsedMs: Date.now() - availableModelsStartedAtMs,
|
|
21494
|
+
});
|
|
21495
|
+
}
|
|
21496
|
+
const requirementsStartedAtMs = Date.now();
|
|
20566
21497
|
this._cachedModelRequirements = await createAgentModelRequirements(this.options.agentSource, undefined, // Let the function pick the best model
|
|
20567
21498
|
availableModels);
|
|
21499
|
+
if (this.options.isVerbose) {
|
|
21500
|
+
console.info('[🤰]', 'Agent model requirements ready', {
|
|
21501
|
+
agent: this.title,
|
|
21502
|
+
elapsedMs: Date.now() - requirementsStartedAtMs,
|
|
21503
|
+
totalElapsedMs: Date.now() - preparationStartedAtMs,
|
|
21504
|
+
});
|
|
21505
|
+
}
|
|
20568
21506
|
}
|
|
20569
21507
|
return this._cachedModelRequirements;
|
|
20570
21508
|
}
|
|
@@ -20718,14 +21656,26 @@ class AgentLlmExecutionTools {
|
|
|
20718
21656
|
if (cached) {
|
|
20719
21657
|
if (cached.requirementsHash === requirementsHash) {
|
|
20720
21658
|
if (this.options.isVerbose) {
|
|
20721
|
-
console.
|
|
21659
|
+
console.info('[🤰]', 'Using cached OpenAI Assistant', {
|
|
21660
|
+
agent: this.title,
|
|
21661
|
+
assistantId: cached.assistantId,
|
|
21662
|
+
});
|
|
20722
21663
|
}
|
|
20723
21664
|
assistant = this.options.llmTools.getAssistant(cached.assistantId);
|
|
20724
21665
|
}
|
|
20725
21666
|
else {
|
|
20726
21667
|
if (this.options.isVerbose) {
|
|
20727
|
-
console.
|
|
21668
|
+
console.info('[🤰]', 'Updating OpenAI Assistant', {
|
|
21669
|
+
agent: this.title,
|
|
21670
|
+
assistantId: cached.assistantId,
|
|
21671
|
+
});
|
|
20728
21672
|
}
|
|
21673
|
+
emitAssistantPreparationProgress({
|
|
21674
|
+
onProgress,
|
|
21675
|
+
prompt,
|
|
21676
|
+
modelName: this.modelName,
|
|
21677
|
+
phase: 'Updating assistant',
|
|
21678
|
+
});
|
|
20729
21679
|
assistant = await this.options.llmTools.updateAssistant({
|
|
20730
21680
|
assistantId: cached.assistantId,
|
|
20731
21681
|
name: this.title,
|
|
@@ -20741,9 +21691,17 @@ class AgentLlmExecutionTools {
|
|
|
20741
21691
|
}
|
|
20742
21692
|
else {
|
|
20743
21693
|
if (this.options.isVerbose) {
|
|
20744
|
-
console.
|
|
21694
|
+
console.info('[🤰]', 'Creating new OpenAI Assistant', {
|
|
21695
|
+
agent: this.title,
|
|
21696
|
+
});
|
|
20745
21697
|
}
|
|
20746
21698
|
// <- TODO: [🐱🚀] Check also `isCreatingNewAssistantsAllowed` and warn about it
|
|
21699
|
+
emitAssistantPreparationProgress({
|
|
21700
|
+
onProgress,
|
|
21701
|
+
prompt,
|
|
21702
|
+
modelName: this.modelName,
|
|
21703
|
+
phase: 'Creating assistant',
|
|
21704
|
+
});
|
|
20747
21705
|
assistant = await this.options.llmTools.createNewAssistant({
|
|
20748
21706
|
name: this.title,
|
|
20749
21707
|
instructions: modelRequirements.systemMessage,
|
|
@@ -20816,6 +21774,58 @@ AgentLlmExecutionTools.vectorStoreCache = new Map();
|
|
|
20816
21774
|
*/
|
|
20817
21775
|
|
|
20818
21776
|
var _Agent_instances, _Agent_selfLearnNonce, _Agent_selfLearnSamples, _Agent_selfLearnTeacher;
|
|
21777
|
+
/**
|
|
21778
|
+
* Creates an empty commitment breakdown for self-learning summaries.
|
|
21779
|
+
*/
|
|
21780
|
+
function createEmptySelfLearningCommitmentCounts() {
|
|
21781
|
+
return {
|
|
21782
|
+
total: 0,
|
|
21783
|
+
knowledge: 0,
|
|
21784
|
+
rule: 0,
|
|
21785
|
+
persona: 0,
|
|
21786
|
+
other: 0,
|
|
21787
|
+
};
|
|
21788
|
+
}
|
|
21789
|
+
/**
|
|
21790
|
+
* Summarizes teacher commitments into user-friendly counts for self-learning.
|
|
21791
|
+
*/
|
|
21792
|
+
function summarizeTeacherCommitments(commitments) {
|
|
21793
|
+
var _a, _b;
|
|
21794
|
+
const counts = createEmptySelfLearningCommitmentCounts();
|
|
21795
|
+
const lines = commitments
|
|
21796
|
+
.split(/\r?\n/)
|
|
21797
|
+
.map((line) => line.trim())
|
|
21798
|
+
.filter((line) => line.length > 0 && line !== '---' && !line.startsWith('```'));
|
|
21799
|
+
for (const line of lines) {
|
|
21800
|
+
const keyword = (_b = (_a = line.split(/\s+/)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : '';
|
|
21801
|
+
if (!/^[A-Z][A-Z_-]*$/.test(keyword)) {
|
|
21802
|
+
continue;
|
|
21803
|
+
}
|
|
21804
|
+
counts.total += 1;
|
|
21805
|
+
if (keyword === 'KNOWLEDGE') {
|
|
21806
|
+
counts.knowledge += 1;
|
|
21807
|
+
}
|
|
21808
|
+
else if (keyword === 'RULE') {
|
|
21809
|
+
counts.rule += 1;
|
|
21810
|
+
}
|
|
21811
|
+
else if (keyword === 'PERSONA') {
|
|
21812
|
+
counts.persona += 1;
|
|
21813
|
+
}
|
|
21814
|
+
else {
|
|
21815
|
+
counts.other += 1;
|
|
21816
|
+
}
|
|
21817
|
+
}
|
|
21818
|
+
return counts;
|
|
21819
|
+
}
|
|
21820
|
+
/**
|
|
21821
|
+
* Builds the teacher summary payload for the self-learning tool call.
|
|
21822
|
+
*/
|
|
21823
|
+
function buildTeacherSummary(commitments, used) {
|
|
21824
|
+
return {
|
|
21825
|
+
used,
|
|
21826
|
+
commitmentTypes: summarizeTeacherCommitments(commitments),
|
|
21827
|
+
};
|
|
21828
|
+
}
|
|
20819
21829
|
/**
|
|
20820
21830
|
* Represents one AI Agent
|
|
20821
21831
|
*
|
|
@@ -20990,16 +22000,29 @@ class Agent extends AgentLlmExecutionTools {
|
|
|
20990
22000
|
// Note: [2] Do the append of the samples
|
|
20991
22001
|
await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnSamples).call(this, prompt, result);
|
|
20992
22002
|
// Note: [3] Asynchronously call the teacher agent and invoke the silver link. When the teacher fails, keep just the samples
|
|
20993
|
-
|
|
22003
|
+
let teacherSummary = null;
|
|
22004
|
+
try {
|
|
22005
|
+
teacherSummary = await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnTeacher).call(this, prompt, result);
|
|
22006
|
+
}
|
|
22007
|
+
catch (error) {
|
|
20994
22008
|
// !!!!! if (this.options.isVerbose) {
|
|
20995
22009
|
console.error(colors.bgCyan('[Self-learning]') + colors.red(' Failed to learn from teacher agent'));
|
|
20996
22010
|
console.error(error);
|
|
20997
22011
|
// }
|
|
20998
|
-
|
|
22012
|
+
teacherSummary = this.teacherAgent ? buildTeacherSummary('', true) : null;
|
|
22013
|
+
}
|
|
20999
22014
|
// Note: [4] Notify end of self-learning
|
|
22015
|
+
const completedAt = new Date().toISOString();
|
|
22016
|
+
const selfLearningResult = {
|
|
22017
|
+
success: true,
|
|
22018
|
+
startedAt: selfLearningToolCall.createdAt,
|
|
22019
|
+
completedAt,
|
|
22020
|
+
samplesAdded: 1,
|
|
22021
|
+
teacher: teacherSummary || undefined,
|
|
22022
|
+
};
|
|
21000
22023
|
const completedSelfLearningToolCall = {
|
|
21001
22024
|
...selfLearningToolCall,
|
|
21002
|
-
result:
|
|
22025
|
+
result: selfLearningResult,
|
|
21003
22026
|
};
|
|
21004
22027
|
const finalResult = {
|
|
21005
22028
|
...result,
|
|
@@ -21048,7 +22071,7 @@ async function _Agent_selfLearnNonce() {
|
|
|
21048
22071
|
async function _Agent_selfLearnTeacher(prompt, result) {
|
|
21049
22072
|
// [1] Call the teacher agent // <- !!!!! Emojis
|
|
21050
22073
|
if (this.teacherAgent === null) {
|
|
21051
|
-
return;
|
|
22074
|
+
return null;
|
|
21052
22075
|
}
|
|
21053
22076
|
console.info(colors.bgCyan('[Self-learning]') + colors.cyan(' Teacher'));
|
|
21054
22077
|
const teacherResult = await this.teacherAgent.callChatModel({
|
|
@@ -21103,7 +22126,7 @@ async function _Agent_selfLearnTeacher(prompt, result) {
|
|
|
21103
22126
|
if (teacherCommitments === '') {
|
|
21104
22127
|
console.info(colors.bgCyan('[Self-learning]') +
|
|
21105
22128
|
colors.cyan(' Teacher agent did not provide new commitments to learn'));
|
|
21106
|
-
return;
|
|
22129
|
+
return buildTeacherSummary('', true);
|
|
21107
22130
|
}
|
|
21108
22131
|
// [2] Append to the current source
|
|
21109
22132
|
const currentSource = this.agentSource.value;
|
|
@@ -21111,6 +22134,7 @@ async function _Agent_selfLearnTeacher(prompt, result) {
|
|
|
21111
22134
|
// <- TODO: [🈲] Use some object-based way how to append on book (with sections `---`)
|
|
21112
22135
|
// [3] Update the source
|
|
21113
22136
|
this.agentSource.next(newSource);
|
|
22137
|
+
return buildTeacherSummary(teacherCommitments, true);
|
|
21114
22138
|
};
|
|
21115
22139
|
/**
|
|
21116
22140
|
* TODO: [🧠][😰]Agent is not working with the parameters, should it be?
|
|
@@ -21274,6 +22298,8 @@ class RemoteAgent extends Agent {
|
|
|
21274
22298
|
// <- TODO: [🐱🚀] Maybe use promptbookFetch
|
|
21275
22299
|
let content = '';
|
|
21276
22300
|
const toolCalls = [];
|
|
22301
|
+
const preparationToolCalls = [];
|
|
22302
|
+
let hasReceivedModelOutput = false;
|
|
21277
22303
|
const normalizeToolCall = (toolCall) => {
|
|
21278
22304
|
if (toolCall.createdAt) {
|
|
21279
22305
|
return toolCall;
|
|
@@ -21320,6 +22346,17 @@ class RemoteAgent extends Agent {
|
|
|
21320
22346
|
const upsertToolCalls = (incomingToolCalls) => {
|
|
21321
22347
|
for (const toolCall of incomingToolCalls) {
|
|
21322
22348
|
const normalized = normalizeToolCall(toolCall);
|
|
22349
|
+
if (isAssistantPreparationToolCall(normalized)) {
|
|
22350
|
+
if (hasReceivedModelOutput) {
|
|
22351
|
+
continue;
|
|
22352
|
+
}
|
|
22353
|
+
preparationToolCalls.length = 0;
|
|
22354
|
+
preparationToolCalls.push(normalized);
|
|
22355
|
+
continue;
|
|
22356
|
+
}
|
|
22357
|
+
if (preparationToolCalls.length > 0) {
|
|
22358
|
+
preparationToolCalls.length = 0;
|
|
22359
|
+
}
|
|
21323
22360
|
const key = getToolCallKey(normalized);
|
|
21324
22361
|
const existingIndex = toolCalls.findIndex((existing) => getToolCallKey(existing) === key);
|
|
21325
22362
|
if (existingIndex === -1) {
|
|
@@ -21330,6 +22367,10 @@ class RemoteAgent extends Agent {
|
|
|
21330
22367
|
}
|
|
21331
22368
|
}
|
|
21332
22369
|
};
|
|
22370
|
+
/**
|
|
22371
|
+
* Builds the tool call list including any preparation marker still active.
|
|
22372
|
+
*/
|
|
22373
|
+
const getActiveToolCalls = () => preparationToolCalls.length > 0 ? [...preparationToolCalls, ...toolCalls] : toolCalls;
|
|
21333
22374
|
if (!bookResponse.body) {
|
|
21334
22375
|
content = await bookResponse.text();
|
|
21335
22376
|
}
|
|
@@ -21366,7 +22407,7 @@ class RemoteAgent extends Agent {
|
|
|
21366
22407
|
rawPromptContent: {},
|
|
21367
22408
|
rawRequest: {},
|
|
21368
22409
|
rawResponse: {},
|
|
21369
|
-
toolCalls:
|
|
22410
|
+
toolCalls: getActiveToolCalls(),
|
|
21370
22411
|
});
|
|
21371
22412
|
sawToolCalls = true;
|
|
21372
22413
|
isToolCallLine = true;
|
|
@@ -21394,6 +22435,10 @@ class RemoteAgent extends Agent {
|
|
|
21394
22435
|
// console.debug('RemoteAgent chunk:', textChunk);
|
|
21395
22436
|
content += textChunk;
|
|
21396
22437
|
}
|
|
22438
|
+
if (!hasReceivedModelOutput && content.trim().length > 0) {
|
|
22439
|
+
hasReceivedModelOutput = true;
|
|
22440
|
+
preparationToolCalls.length = 0;
|
|
22441
|
+
}
|
|
21397
22442
|
onProgress({
|
|
21398
22443
|
content,
|
|
21399
22444
|
modelName: this.modelName,
|
|
@@ -21402,7 +22447,7 @@ class RemoteAgent extends Agent {
|
|
|
21402
22447
|
rawPromptContent: {},
|
|
21403
22448
|
rawRequest: {},
|
|
21404
22449
|
rawResponse: {},
|
|
21405
|
-
toolCalls,
|
|
22450
|
+
toolCalls: getActiveToolCalls(),
|
|
21406
22451
|
});
|
|
21407
22452
|
}
|
|
21408
22453
|
}
|
|
@@ -21410,6 +22455,10 @@ class RemoteAgent extends Agent {
|
|
|
21410
22455
|
const lastChunk = decoder.decode();
|
|
21411
22456
|
if (lastChunk) {
|
|
21412
22457
|
content += lastChunk;
|
|
22458
|
+
if (!hasReceivedModelOutput && content.trim().length > 0) {
|
|
22459
|
+
hasReceivedModelOutput = true;
|
|
22460
|
+
preparationToolCalls.length = 0;
|
|
22461
|
+
}
|
|
21413
22462
|
onProgress({
|
|
21414
22463
|
content: lastChunk,
|
|
21415
22464
|
modelName: this.modelName,
|
|
@@ -21418,7 +22467,7 @@ class RemoteAgent extends Agent {
|
|
|
21418
22467
|
rawPromptContent: {},
|
|
21419
22468
|
rawRequest: {},
|
|
21420
22469
|
rawResponse: {},
|
|
21421
|
-
toolCalls,
|
|
22470
|
+
toolCalls: getActiveToolCalls(),
|
|
21422
22471
|
});
|
|
21423
22472
|
}
|
|
21424
22473
|
}
|