@promptbook/cli 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 +1 -1
- 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
|
@@ -47,7 +47,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
47
47
|
* @generated
|
|
48
48
|
* @see https://github.com/webgptorg/promptbook
|
|
49
49
|
*/
|
|
50
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.108.0-0';
|
|
51
51
|
/**
|
|
52
52
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
53
53
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -4267,13 +4267,125 @@ function escapePromptParameterValue(value, options) {
|
|
|
4267
4267
|
return value.replace(pattern, '\\$&');
|
|
4268
4268
|
}
|
|
4269
4269
|
/**
|
|
4270
|
-
* Builds
|
|
4270
|
+
* Builds numeric parameter name used in prompt placeholders.
|
|
4271
4271
|
*
|
|
4272
4272
|
* @param index Zero-based parameter index.
|
|
4273
4273
|
*/
|
|
4274
|
-
function
|
|
4274
|
+
function buildNumericParameterName(index) {
|
|
4275
4275
|
return `${index + 1}`;
|
|
4276
4276
|
}
|
|
4277
|
+
/**
|
|
4278
|
+
* Builds alphabetic parameter name used in prompt placeholders.
|
|
4279
|
+
*
|
|
4280
|
+
* @param index Zero-based parameter index.
|
|
4281
|
+
*/
|
|
4282
|
+
function buildAlphabeticParameterName(index) {
|
|
4283
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyz';
|
|
4284
|
+
let result = '';
|
|
4285
|
+
let remaining = index;
|
|
4286
|
+
while (remaining >= 0) {
|
|
4287
|
+
result = alphabet[remaining % alphabet.length] + result;
|
|
4288
|
+
remaining = Math.floor(remaining / alphabet.length) - 1;
|
|
4289
|
+
}
|
|
4290
|
+
return result;
|
|
4291
|
+
}
|
|
4292
|
+
/**
|
|
4293
|
+
* Converts a positive integer into a Roman numeral string.
|
|
4294
|
+
*
|
|
4295
|
+
* @param value Positive integer value.
|
|
4296
|
+
*/
|
|
4297
|
+
function toRomanNumeral(value) {
|
|
4298
|
+
const romanTable = [
|
|
4299
|
+
{ symbol: 'M', value: 1000 },
|
|
4300
|
+
{ symbol: 'CM', value: 900 },
|
|
4301
|
+
{ symbol: 'D', value: 500 },
|
|
4302
|
+
{ symbol: 'CD', value: 400 },
|
|
4303
|
+
{ symbol: 'C', value: 100 },
|
|
4304
|
+
{ symbol: 'XC', value: 90 },
|
|
4305
|
+
{ symbol: 'L', value: 50 },
|
|
4306
|
+
{ symbol: 'XL', value: 40 },
|
|
4307
|
+
{ symbol: 'X', value: 10 },
|
|
4308
|
+
{ symbol: 'IX', value: 9 },
|
|
4309
|
+
{ symbol: 'V', value: 5 },
|
|
4310
|
+
{ symbol: 'IV', value: 4 },
|
|
4311
|
+
{ symbol: 'I', value: 1 },
|
|
4312
|
+
];
|
|
4313
|
+
let remaining = Math.max(1, Math.floor(value));
|
|
4314
|
+
let result = '';
|
|
4315
|
+
for (const entry of romanTable) {
|
|
4316
|
+
while (remaining >= entry.value) {
|
|
4317
|
+
result += entry.symbol;
|
|
4318
|
+
remaining -= entry.value;
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
return result;
|
|
4322
|
+
}
|
|
4323
|
+
/**
|
|
4324
|
+
* Builds Roman numeral parameter name used in prompt placeholders.
|
|
4325
|
+
*
|
|
4326
|
+
* @param index Zero-based parameter index.
|
|
4327
|
+
*/
|
|
4328
|
+
function buildRomanParameterName(index) {
|
|
4329
|
+
return toRomanNumeral(index + 1);
|
|
4330
|
+
}
|
|
4331
|
+
/**
|
|
4332
|
+
* Creates a parameter name builder that prefixes another builder.
|
|
4333
|
+
*
|
|
4334
|
+
* @param prefix Prefix to add.
|
|
4335
|
+
* @param builder Base builder to wrap.
|
|
4336
|
+
*/
|
|
4337
|
+
function buildPrefixedParameterName(prefix, builder) {
|
|
4338
|
+
return (index) => `${prefix}${builder(index)}`;
|
|
4339
|
+
}
|
|
4340
|
+
/**
|
|
4341
|
+
* Ordered list of strategies for parameter naming.
|
|
4342
|
+
*/
|
|
4343
|
+
const PARAMETER_NAME_STRATEGIES = [
|
|
4344
|
+
{ buildName: buildNumericParameterName },
|
|
4345
|
+
{ buildName: buildAlphabeticParameterName },
|
|
4346
|
+
{ buildName: buildRomanParameterName },
|
|
4347
|
+
{ buildName: buildPrefixedParameterName('p', buildNumericParameterName) },
|
|
4348
|
+
{ buildName: buildPrefixedParameterName('p', buildAlphabeticParameterName) },
|
|
4349
|
+
];
|
|
4350
|
+
/**
|
|
4351
|
+
* Collects bracketed tokens from parameter values to avoid placeholder collisions.
|
|
4352
|
+
*
|
|
4353
|
+
* @param values Parameter values to scan.
|
|
4354
|
+
*/
|
|
4355
|
+
function collectBracketedParameterTokens(values) {
|
|
4356
|
+
const tokens = new Set();
|
|
4357
|
+
for (const value of values) {
|
|
4358
|
+
const pattern = /{(\w+)}/g;
|
|
4359
|
+
let match;
|
|
4360
|
+
while ((match = pattern.exec(value)) !== null) {
|
|
4361
|
+
const token = match[1];
|
|
4362
|
+
if (token) {
|
|
4363
|
+
tokens.add(token);
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
return tokens;
|
|
4368
|
+
}
|
|
4369
|
+
/**
|
|
4370
|
+
* Builds parameter names used in prompt placeholders while avoiding collisions.
|
|
4371
|
+
*
|
|
4372
|
+
* @param values Parameter values to scan for conflicting tokens.
|
|
4373
|
+
*/
|
|
4374
|
+
function buildParameterNames(values) {
|
|
4375
|
+
const count = values.length;
|
|
4376
|
+
if (count === 0) {
|
|
4377
|
+
return [];
|
|
4378
|
+
}
|
|
4379
|
+
const conflicts = collectBracketedParameterTokens(values);
|
|
4380
|
+
for (const strategy of PARAMETER_NAME_STRATEGIES) {
|
|
4381
|
+
const names = Array.from({ length: count }, (_, index) => strategy.buildName(index));
|
|
4382
|
+
const hasConflict = names.some((name) => conflicts.has(name));
|
|
4383
|
+
if (!hasConflict) {
|
|
4384
|
+
return names;
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
return Array.from({ length: count }, (_, index) => `${REPLACING_NONCE}${index + 1}`);
|
|
4388
|
+
}
|
|
4277
4389
|
/**
|
|
4278
4390
|
* Formats the placeholder used in the prompt body for a parameter.
|
|
4279
4391
|
*
|
|
@@ -4328,26 +4440,40 @@ function prompt(strings, ...values) {
|
|
|
4328
4440
|
return new PromptString(spaceTrim$2(strings.join('')));
|
|
4329
4441
|
}
|
|
4330
4442
|
const stringsWithHiddenParameters = strings.map((stringsItem) => hideBrackets(stringsItem));
|
|
4331
|
-
const
|
|
4332
|
-
const name = buildParameterName(index);
|
|
4443
|
+
const parameterMetadata = values.map((value) => {
|
|
4333
4444
|
const isPrompt = isPromptString(value);
|
|
4334
4445
|
const stringValue = isPrompt ? value.toString() : valueToString(value);
|
|
4335
4446
|
const isInline = isPrompt ? true : shouldInlineParameterValue(stringValue);
|
|
4336
4447
|
const jsonValue = !isPrompt && !isInline ? normalizeJsonString(stringValue) : null;
|
|
4448
|
+
return { isPrompt, stringValue, isInline, jsonValue };
|
|
4449
|
+
});
|
|
4450
|
+
const parameterNames = buildParameterNames(parameterMetadata.map((entry) => entry.stringValue));
|
|
4451
|
+
const parameterEntries = parameterMetadata.map((entry, index) => {
|
|
4452
|
+
var _a;
|
|
4453
|
+
const name = (_a = parameterNames[index]) !== null && _a !== void 0 ? _a : buildNumericParameterName(index);
|
|
4337
4454
|
const promptMarker = `${REPLACING_NONCE}prompt-${index}`;
|
|
4338
4455
|
const parameterMarker = `${REPLACING_NONCE}parameter-${index}`;
|
|
4339
|
-
const templateValue = isPrompt
|
|
4456
|
+
const templateValue = entry.isPrompt
|
|
4340
4457
|
? promptMarker
|
|
4341
|
-
: isInline
|
|
4342
|
-
? escapePromptParameterValue(stringValue, { includeBraces: false })
|
|
4458
|
+
: entry.isInline
|
|
4459
|
+
? escapePromptParameterValue(entry.stringValue, { includeBraces: false })
|
|
4343
4460
|
: parameterMarker;
|
|
4344
|
-
return {
|
|
4461
|
+
return {
|
|
4462
|
+
name,
|
|
4463
|
+
stringValue: entry.stringValue,
|
|
4464
|
+
jsonValue: entry.jsonValue,
|
|
4465
|
+
isPrompt: entry.isPrompt,
|
|
4466
|
+
isInline: entry.isInline,
|
|
4467
|
+
promptMarker,
|
|
4468
|
+
parameterMarker,
|
|
4469
|
+
templateValue,
|
|
4470
|
+
};
|
|
4345
4471
|
});
|
|
4346
4472
|
const parameters = Object.fromEntries(parameterEntries.map((entry) => [entry.name, entry.templateValue]));
|
|
4347
|
-
const
|
|
4473
|
+
const parameterNamesOrdered = parameterEntries.map((entry) => entry.name);
|
|
4348
4474
|
// Combine strings and values
|
|
4349
4475
|
let pipelineString = stringsWithHiddenParameters.reduce((result, stringsItem, i) => {
|
|
4350
|
-
const parameterName =
|
|
4476
|
+
const parameterName = parameterNamesOrdered[i];
|
|
4351
4477
|
return parameterName === undefined
|
|
4352
4478
|
? `${result}${stringsItem}`
|
|
4353
4479
|
: `${result}${stringsItem}${formatParameterPlaceholder(parameterName)}`;
|
|
@@ -4360,7 +4486,7 @@ function prompt(strings, ...values) {
|
|
|
4360
4486
|
if (!(error instanceof PipelineExecutionError)) {
|
|
4361
4487
|
throw error;
|
|
4362
4488
|
}
|
|
4363
|
-
console.error({ pipelineString, parameters, parameterNames, error });
|
|
4489
|
+
console.error({ pipelineString, parameters, parameterNames: parameterNamesOrdered, error });
|
|
4364
4490
|
throw new UnexpectedError(spaceTrim$2((block) => `
|
|
4365
4491
|
Internal error in prompt template literal
|
|
4366
4492
|
|
|
@@ -4375,9 +4501,7 @@ function prompt(strings, ...values) {
|
|
|
4375
4501
|
continue;
|
|
4376
4502
|
}
|
|
4377
4503
|
if (!entry.isInline) {
|
|
4378
|
-
pipelineString = pipelineString
|
|
4379
|
-
.split(entry.parameterMarker)
|
|
4380
|
-
.join(formatParameterPlaceholder(entry.name));
|
|
4504
|
+
pipelineString = pipelineString.split(entry.parameterMarker).join(formatParameterPlaceholder(entry.name));
|
|
4381
4505
|
}
|
|
4382
4506
|
}
|
|
4383
4507
|
const structuredParameters = parameterEntries.filter((entry) => !entry.isPrompt && !entry.isInline);
|
|
@@ -4539,18 +4663,6 @@ const CountUtils = {
|
|
|
4539
4663
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
4540
4664
|
*/
|
|
4541
4665
|
|
|
4542
|
-
/**
|
|
4543
|
-
* Simple wrapper `new Date().toISOString()`
|
|
4544
|
-
*
|
|
4545
|
-
* Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
|
|
4546
|
-
*
|
|
4547
|
-
* @returns string_date branded type
|
|
4548
|
-
* @public exported from `@promptbook/utils`
|
|
4549
|
-
*/
|
|
4550
|
-
function $getCurrentDate() {
|
|
4551
|
-
return new Date().toISOString();
|
|
4552
|
-
}
|
|
4553
|
-
|
|
4554
4666
|
/**
|
|
4555
4667
|
* Computes SHA-256 hash of the given object
|
|
4556
4668
|
*
|
|
@@ -4574,103 +4686,564 @@ function capitalize(word) {
|
|
|
4574
4686
|
return word.substring(0, 1).toUpperCase() + word.substring(1);
|
|
4575
4687
|
}
|
|
4576
4688
|
|
|
4689
|
+
// spell-checker: disable
|
|
4577
4690
|
/**
|
|
4578
|
-
*
|
|
4691
|
+
* @@@
|
|
4579
4692
|
*
|
|
4580
|
-
* @
|
|
4581
|
-
*/
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
'
|
|
4589
|
-
'
|
|
4590
|
-
'
|
|
4591
|
-
'
|
|
4592
|
-
'
|
|
4593
|
-
'
|
|
4594
|
-
'
|
|
4595
|
-
'
|
|
4596
|
-
'
|
|
4597
|
-
'
|
|
4598
|
-
'
|
|
4599
|
-
'
|
|
4693
|
+
* @private utility of `linguisticHash`
|
|
4694
|
+
*/
|
|
4695
|
+
const ADJECTIVES$1 = [
|
|
4696
|
+
'červený',
|
|
4697
|
+
'modrý',
|
|
4698
|
+
'zelený',
|
|
4699
|
+
'žlutý',
|
|
4700
|
+
'rychlý',
|
|
4701
|
+
'pomalý',
|
|
4702
|
+
'jasný',
|
|
4703
|
+
'temný',
|
|
4704
|
+
'veselý',
|
|
4705
|
+
'smutný',
|
|
4706
|
+
'statečný',
|
|
4707
|
+
'klidný',
|
|
4708
|
+
'chytrý',
|
|
4709
|
+
'bystrý',
|
|
4710
|
+
'dychtivý',
|
|
4711
|
+
'honosný',
|
|
4712
|
+
'velkolepý',
|
|
4713
|
+
'hravý',
|
|
4714
|
+
'laskavý',
|
|
4715
|
+
'šťastný',
|
|
4716
|
+
'hrdý',
|
|
4717
|
+
'pošetilý',
|
|
4718
|
+
'moudrý',
|
|
4719
|
+
'mladý',
|
|
4720
|
+
'starý',
|
|
4721
|
+
'veliký',
|
|
4722
|
+
'malý',
|
|
4723
|
+
'drobný',
|
|
4724
|
+
'obrovský',
|
|
4725
|
+
'krátký',
|
|
4726
|
+
'dlouhý',
|
|
4727
|
+
'blízký',
|
|
4728
|
+
'vzdálený',
|
|
4729
|
+
'vnitřní',
|
|
4730
|
+
'vnější',
|
|
4731
|
+
'trpělivý',
|
|
4732
|
+
'stálý',
|
|
4733
|
+
'ušlechtilý',
|
|
4734
|
+
'čistý',
|
|
4735
|
+
'špinavý',
|
|
4736
|
+
'čerstvý',
|
|
4737
|
+
'zvětralý',
|
|
4738
|
+
'ostrý',
|
|
4739
|
+
'tupý',
|
|
4740
|
+
'tlustý',
|
|
4741
|
+
'tenký',
|
|
4742
|
+
'široký',
|
|
4743
|
+
'úzký',
|
|
4744
|
+
'hluboký',
|
|
4745
|
+
'mělký',
|
|
4746
|
+
'mocný',
|
|
4747
|
+
'jemný',
|
|
4748
|
+
'divoký',
|
|
4749
|
+
'tichý',
|
|
4750
|
+
'hlučný',
|
|
4751
|
+
'pokojný',
|
|
4752
|
+
'rušný',
|
|
4753
|
+
'prázdný',
|
|
4754
|
+
'plný',
|
|
4755
|
+
'kulatý',
|
|
4756
|
+
'hranatý',
|
|
4757
|
+
'plochý',
|
|
4758
|
+
'křivý',
|
|
4759
|
+
'tvrdý',
|
|
4760
|
+
'měkký',
|
|
4761
|
+
'teplý',
|
|
4762
|
+
'chladný',
|
|
4763
|
+
'sladký',
|
|
4764
|
+
'kyselý',
|
|
4765
|
+
'hořký',
|
|
4766
|
+
'slaný',
|
|
4767
|
+
'silný',
|
|
4768
|
+
'slabý',
|
|
4769
|
+
'pevný',
|
|
4770
|
+
'pružný',
|
|
4771
|
+
'křehký',
|
|
4772
|
+
'houževnatý',
|
|
4773
|
+
'lesklý',
|
|
4774
|
+
'matný',
|
|
4775
|
+
'kluzký',
|
|
4776
|
+
'lepkavý',
|
|
4777
|
+
'svěží',
|
|
4778
|
+
'vybledlý',
|
|
4779
|
+
'mlhavý',
|
|
4780
|
+
'bouřlivý',
|
|
4781
|
+
'slunný',
|
|
4782
|
+
'větrný',
|
|
4783
|
+
'deštivý',
|
|
4784
|
+
'mrazivý',
|
|
4785
|
+
'zlatý',
|
|
4786
|
+
'stříbrný',
|
|
4787
|
+
'ledový',
|
|
4788
|
+
'žhavý',
|
|
4789
|
+
'prastarý',
|
|
4790
|
+
'moderní',
|
|
4791
|
+
'skrytý',
|
|
4792
|
+
'ztracený',
|
|
4793
|
+
'nalezený',
|
|
4794
|
+
'magický',
|
|
4795
|
+
'tajemný',
|
|
4796
|
+
'kosmický',
|
|
4797
|
+
'hvězdný',
|
|
4798
|
+
'měsíční',
|
|
4799
|
+
'sluneční',
|
|
4800
|
+
'mlžný',
|
|
4801
|
+
'ranní',
|
|
4802
|
+
'večerní',
|
|
4803
|
+
'noční',
|
|
4804
|
+
'denní',
|
|
4805
|
+
'osamělý',
|
|
4806
|
+
'společenský',
|
|
4807
|
+
'soukromý',
|
|
4808
|
+
'veřejný',
|
|
4809
|
+
'tajný',
|
|
4810
|
+
'slavný',
|
|
4811
|
+
'jistý',
|
|
4812
|
+
'neurčitý',
|
|
4813
|
+
'prostý',
|
|
4814
|
+
'snadný',
|
|
4815
|
+
'krotký',
|
|
4816
|
+
'mírný',
|
|
4817
|
+
'horký',
|
|
4818
|
+
'suchý',
|
|
4819
|
+
'mokrý',
|
|
4820
|
+
'vlhký',
|
|
4821
|
+
'promočený',
|
|
4822
|
+
'vyprahlý',
|
|
4823
|
+
'hladový',
|
|
4824
|
+
'žíznivý',
|
|
4825
|
+
'ospalý',
|
|
4826
|
+
'bdělý',
|
|
4827
|
+
'unavený',
|
|
4828
|
+
'líný',
|
|
4829
|
+
'neklidný',
|
|
4830
|
+
'nestálý',
|
|
4831
|
+
'odvážný',
|
|
4832
|
+
'bázlivý',
|
|
4833
|
+
'upřímný',
|
|
4834
|
+
'věrný',
|
|
4835
|
+
'pravý',
|
|
4836
|
+
'falešný',
|
|
4837
|
+
'spravedlivý',
|
|
4838
|
+
'jednoduchý',
|
|
4839
|
+
'složitý',
|
|
4840
|
+
'přirozený',
|
|
4841
|
+
'umělý',
|
|
4842
|
+
'živý',
|
|
4843
|
+
'mrtvý',
|
|
4844
|
+
'zvídavý',
|
|
4845
|
+
'zvláštní',
|
|
4846
|
+
'běžný',
|
|
4847
|
+
'vzácný',
|
|
4848
|
+
'jedinečný',
|
|
4849
|
+
'základní',
|
|
4850
|
+
'prvotní',
|
|
4851
|
+
'hbitý',
|
|
4600
4852
|
];
|
|
4601
|
-
const
|
|
4602
|
-
|
|
4603
|
-
'
|
|
4604
|
-
'
|
|
4605
|
-
'
|
|
4606
|
-
'
|
|
4607
|
-
'
|
|
4608
|
-
'
|
|
4609
|
-
'
|
|
4610
|
-
'
|
|
4611
|
-
'
|
|
4612
|
-
'
|
|
4613
|
-
'
|
|
4614
|
-
'
|
|
4615
|
-
'
|
|
4616
|
-
'
|
|
4853
|
+
const NOUNS$1 = [
|
|
4854
|
+
'jablko',
|
|
4855
|
+
'nebe',
|
|
4856
|
+
'strom',
|
|
4857
|
+
'liška',
|
|
4858
|
+
'kočka',
|
|
4859
|
+
'pták',
|
|
4860
|
+
'pes',
|
|
4861
|
+
'řeka',
|
|
4862
|
+
'hora',
|
|
4863
|
+
'les',
|
|
4864
|
+
'oceán',
|
|
4865
|
+
'hvězda',
|
|
4866
|
+
'měsíc',
|
|
4867
|
+
'slunce',
|
|
4868
|
+
'mrak',
|
|
4869
|
+
'květ',
|
|
4870
|
+
'list',
|
|
4871
|
+
'kámen',
|
|
4872
|
+
'vítr',
|
|
4873
|
+
'déšť',
|
|
4874
|
+
'oheň',
|
|
4875
|
+
'led',
|
|
4876
|
+
'kniha',
|
|
4877
|
+
'sen',
|
|
4878
|
+
'píseň',
|
|
4879
|
+
'cesta',
|
|
4880
|
+
'brána',
|
|
4881
|
+
'klíč',
|
|
4882
|
+
'lampa',
|
|
4883
|
+
'mapa',
|
|
4884
|
+
'dům',
|
|
4885
|
+
'město',
|
|
4886
|
+
'most',
|
|
4887
|
+
'pole',
|
|
4888
|
+
'zahrada',
|
|
4889
|
+
'jezero',
|
|
4890
|
+
'pláž',
|
|
4891
|
+
'ostrov',
|
|
4892
|
+
'údolí',
|
|
4893
|
+
'poušť',
|
|
4894
|
+
'svět',
|
|
4895
|
+
'duch',
|
|
4896
|
+
'srdce',
|
|
4897
|
+
'mysl',
|
|
4898
|
+
'duše',
|
|
4899
|
+
'život',
|
|
4900
|
+
'čas',
|
|
4901
|
+
'prostor',
|
|
4902
|
+
'světlo',
|
|
4903
|
+
'stín',
|
|
4904
|
+
'zvuk',
|
|
4905
|
+
'hudba',
|
|
4906
|
+
'hlas',
|
|
4907
|
+
'slovo',
|
|
4908
|
+
'stránka',
|
|
4909
|
+
'příběh',
|
|
4910
|
+
'perla',
|
|
4911
|
+
'zlato',
|
|
4912
|
+
'stříbro',
|
|
4913
|
+
'krystal',
|
|
4914
|
+
'diamant',
|
|
4915
|
+
'smaragd',
|
|
4916
|
+
'rubín',
|
|
4917
|
+
'stezka',
|
|
4918
|
+
'vrchol',
|
|
4919
|
+
'břeh',
|
|
4920
|
+
'vlna',
|
|
4921
|
+
'příliv',
|
|
4922
|
+
'plamen',
|
|
4923
|
+
'jiskra',
|
|
4924
|
+
'paprsek',
|
|
4925
|
+
'semínko',
|
|
4926
|
+
'kořen',
|
|
4927
|
+
'větev',
|
|
4928
|
+
'pupen',
|
|
4929
|
+
'trn',
|
|
4930
|
+
'kůra',
|
|
4931
|
+
'skořápka',
|
|
4932
|
+
'pírko',
|
|
4933
|
+
'křídlo',
|
|
4934
|
+
'dráp',
|
|
4935
|
+
'tlapa',
|
|
4936
|
+
'hnízdo',
|
|
4937
|
+
'jeskyně',
|
|
4938
|
+
'hájek',
|
|
4939
|
+
'věž',
|
|
4940
|
+
'hrad',
|
|
4941
|
+
'koruna',
|
|
4942
|
+
'meč',
|
|
4943
|
+
'štít',
|
|
4944
|
+
'mince',
|
|
4945
|
+
'drahokam',
|
|
4946
|
+
'prsten',
|
|
4947
|
+
'zvonek',
|
|
4948
|
+
'hodiny',
|
|
4949
|
+
'kompas',
|
|
4950
|
+
'kotva',
|
|
4951
|
+
'pochodeň',
|
|
4952
|
+
'flétna',
|
|
4953
|
+
'harfa',
|
|
4954
|
+
'buben',
|
|
4955
|
+
'čočka',
|
|
4956
|
+
'sklo',
|
|
4957
|
+
'písek',
|
|
4958
|
+
'prach',
|
|
4959
|
+
'mlha',
|
|
4960
|
+
'rosa',
|
|
4961
|
+
'svítání',
|
|
4962
|
+
'soumrak',
|
|
4963
|
+
'noc',
|
|
4964
|
+
'den',
|
|
4965
|
+
'rok',
|
|
4966
|
+
'věk',
|
|
4967
|
+
'blesk',
|
|
4968
|
+
'kapka',
|
|
4969
|
+
'bouře',
|
|
4970
|
+
'sníh',
|
|
4971
|
+
'kroupa',
|
|
4972
|
+
'kouř',
|
|
4973
|
+
'pára',
|
|
4974
|
+
'plyn',
|
|
4975
|
+
'kov',
|
|
4976
|
+
'skála',
|
|
4977
|
+
'hlína',
|
|
4978
|
+
'sůl',
|
|
4979
|
+
'cukr',
|
|
4980
|
+
'dřevo',
|
|
4981
|
+
'kost',
|
|
4982
|
+
'kůže',
|
|
4983
|
+
'tělo',
|
|
4984
|
+
'krev',
|
|
4985
|
+
'buňka',
|
|
4986
|
+
'atom',
|
|
4987
|
+
'tep',
|
|
4988
|
+
'dech',
|
|
4989
|
+
'vzdech',
|
|
4990
|
+
'jméno',
|
|
4991
|
+
'ozvěna',
|
|
4992
|
+
'obraz',
|
|
4993
|
+
'vize',
|
|
4994
|
+
'myšlenka',
|
|
4995
|
+
'nápad',
|
|
4996
|
+
'plán',
|
|
4997
|
+
'cíl',
|
|
4998
|
+
'přání',
|
|
4999
|
+
'naděje',
|
|
5000
|
+
'strach',
|
|
5001
|
+
'radost',
|
|
5002
|
+
'láska',
|
|
5003
|
+
'nenávist',
|
|
5004
|
+
'vůle',
|
|
5005
|
+
'síla',
|
|
5006
|
+
'energie',
|
|
5007
|
+
'pohyb',
|
|
5008
|
+
'rychlost',
|
|
5009
|
+
'místo',
|
|
5010
|
+
'bod',
|
|
5011
|
+
'linie',
|
|
5012
|
+
'tvar',
|
|
5013
|
+
'forma',
|
|
5014
|
+
'velikost',
|
|
5015
|
+
'hmota',
|
|
5016
|
+
'váha',
|
|
5017
|
+
'teplo',
|
|
5018
|
+
'chlad',
|
|
5019
|
+
'barva',
|
|
5020
|
+
'tón',
|
|
5021
|
+
'rytmus',
|
|
5022
|
+
'nálada',
|
|
5023
|
+
'stav',
|
|
5024
|
+
'krok',
|
|
5025
|
+
'pád',
|
|
5026
|
+
'skok',
|
|
5027
|
+
'běh',
|
|
5028
|
+
'let',
|
|
5029
|
+
'klid',
|
|
5030
|
+
'úkol',
|
|
5031
|
+
'práce',
|
|
5032
|
+
'hra',
|
|
5033
|
+
'sport',
|
|
5034
|
+
'umění',
|
|
5035
|
+
'řemeslo',
|
|
5036
|
+
'nástroj',
|
|
5037
|
+
'loď',
|
|
5038
|
+
'člun',
|
|
5039
|
+
'auto',
|
|
5040
|
+
'kolo',
|
|
5041
|
+
'vlak',
|
|
5042
|
+
'letadlo',
|
|
5043
|
+
'uzel',
|
|
5044
|
+
'síť',
|
|
5045
|
+
'krabice',
|
|
5046
|
+
'taška',
|
|
5047
|
+
'dóza',
|
|
5048
|
+
'hrnek',
|
|
5049
|
+
'miska',
|
|
5050
|
+
'talíř',
|
|
5051
|
+
'lžíce',
|
|
5052
|
+
'vidlička',
|
|
5053
|
+
'nůž',
|
|
5054
|
+
'pánev',
|
|
5055
|
+
'hrnec',
|
|
5056
|
+
'postel',
|
|
5057
|
+
'stůl',
|
|
5058
|
+
'židle',
|
|
5059
|
+
'dveře',
|
|
5060
|
+
'stěna',
|
|
5061
|
+
'střecha',
|
|
5062
|
+
'podlaha',
|
|
5063
|
+
'okno',
|
|
5064
|
+
'chodba',
|
|
4617
5065
|
];
|
|
4618
|
-
const
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
5066
|
+
const VERBS$1 = [
|
|
5067
|
+
'skáče',
|
|
5068
|
+
'tančí',
|
|
5069
|
+
'letí',
|
|
5070
|
+
'běží',
|
|
5071
|
+
'zpívá',
|
|
5072
|
+
'svítí',
|
|
5073
|
+
'roste',
|
|
5074
|
+
'plyne',
|
|
5075
|
+
'padá',
|
|
5076
|
+
'stoupá',
|
|
5077
|
+
'spí',
|
|
5078
|
+
'kráčí',
|
|
5079
|
+
'mluví',
|
|
5080
|
+
'myslí',
|
|
5081
|
+
'sní',
|
|
5082
|
+
'hledá',
|
|
5083
|
+
'nachází',
|
|
5084
|
+
'dává',
|
|
5085
|
+
'bere',
|
|
5086
|
+
'tvoří',
|
|
5087
|
+
'hoří',
|
|
5088
|
+
'mrzne',
|
|
5089
|
+
'taje',
|
|
5090
|
+
'dýchá',
|
|
5091
|
+
'pulzuje',
|
|
5092
|
+
'bije',
|
|
5093
|
+
'žije',
|
|
5094
|
+
'učí',
|
|
5095
|
+
'ví',
|
|
5096
|
+
'skrývá',
|
|
5097
|
+
'ukazuje',
|
|
5098
|
+
'láme',
|
|
5099
|
+
'opravuje',
|
|
5100
|
+
'ztrácí',
|
|
5101
|
+
'nalézá',
|
|
5102
|
+
'začíná',
|
|
5103
|
+
'končí',
|
|
5104
|
+
'plave',
|
|
5105
|
+
'pluje',
|
|
5106
|
+
'klouže',
|
|
5107
|
+
'točí',
|
|
5108
|
+
'mění',
|
|
5109
|
+
'bledne',
|
|
5110
|
+
'mizí',
|
|
5111
|
+
'rodí',
|
|
5112
|
+
'hučí',
|
|
5113
|
+
'pláče',
|
|
5114
|
+
'závodí',
|
|
5115
|
+
'plíží',
|
|
5116
|
+
'sleduje',
|
|
5117
|
+
'slyší',
|
|
5118
|
+
'cítí',
|
|
5119
|
+
'touží',
|
|
5120
|
+
'doufá',
|
|
5121
|
+
'miluje',
|
|
5122
|
+
'bloudí',
|
|
5123
|
+
'putuje',
|
|
5124
|
+
'cestuje',
|
|
5125
|
+
'překračuje',
|
|
5126
|
+
'potkává',
|
|
5127
|
+
'drží',
|
|
5128
|
+
'sdílí',
|
|
5129
|
+
'jiskří',
|
|
5130
|
+
'plápolá',
|
|
5131
|
+
'léčí',
|
|
5132
|
+
'řeší',
|
|
5133
|
+
'otevírá',
|
|
5134
|
+
'zavírá',
|
|
5135
|
+
'zvedá',
|
|
5136
|
+
'táhne',
|
|
5137
|
+
'tlačí',
|
|
5138
|
+
'hází',
|
|
5139
|
+
'chytá',
|
|
5140
|
+
'dělá',
|
|
5141
|
+
'vidí',
|
|
5142
|
+
'chutná',
|
|
5143
|
+
'voní',
|
|
5144
|
+
'spěchá',
|
|
5145
|
+
'zastaví',
|
|
5146
|
+
'jde',
|
|
5147
|
+
'přichází',
|
|
5148
|
+
'odchází',
|
|
5149
|
+
'jedná',
|
|
5150
|
+
'existuje',
|
|
5151
|
+
'zmenšuje',
|
|
5152
|
+
'rozšiřuje',
|
|
5153
|
+
'zužuje',
|
|
5154
|
+
'hřeje',
|
|
5155
|
+
'chladí',
|
|
5156
|
+
'suší',
|
|
5157
|
+
'máčí',
|
|
5158
|
+
'plní',
|
|
5159
|
+
'vyprazdňuje',
|
|
5160
|
+
'pouští',
|
|
5161
|
+
'získává',
|
|
5162
|
+
'vítězí',
|
|
5163
|
+
'selhává',
|
|
5164
|
+
'zkouší',
|
|
5165
|
+
'používá',
|
|
5166
|
+
'dostává',
|
|
5167
|
+
'měří',
|
|
5168
|
+
'stojí',
|
|
5169
|
+
'dosahuje',
|
|
5170
|
+
'míjí',
|
|
5171
|
+
'udeří',
|
|
5172
|
+
'vede',
|
|
5173
|
+
'následuje',
|
|
5174
|
+
'pomáhá',
|
|
5175
|
+
'slouží',
|
|
5176
|
+
'trénuje',
|
|
5177
|
+
'kóduje',
|
|
5178
|
+
'píše',
|
|
5179
|
+
'čte',
|
|
5180
|
+
'kreslí',
|
|
5181
|
+
'maluje',
|
|
5182
|
+
'tvaruje',
|
|
5183
|
+
'spojuje',
|
|
5184
|
+
'dělí',
|
|
5185
|
+
'váže',
|
|
5186
|
+
'zraňuje',
|
|
5187
|
+
'chrání',
|
|
5188
|
+
'bojuje',
|
|
5189
|
+
'brání',
|
|
5190
|
+
'útočí',
|
|
5191
|
+
'uniká',
|
|
5192
|
+
'lapá',
|
|
5193
|
+
'osvobozuje',
|
|
5194
|
+
'poutá',
|
|
5195
|
+
'spřádá',
|
|
5196
|
+
'tká',
|
|
5197
|
+
'vrhá',
|
|
5198
|
+
'nese',
|
|
5199
|
+
'přenáší',
|
|
5200
|
+
'vrací',
|
|
5201
|
+
'zrychluje',
|
|
5202
|
+
'zpomaluje',
|
|
5203
|
+
'probouzí',
|
|
5204
|
+
'uspává',
|
|
5205
|
+
'šeptá',
|
|
5206
|
+
'volá',
|
|
5207
|
+
'hledí',
|
|
5208
|
+
'čeká',
|
|
5209
|
+
'bdí',
|
|
5210
|
+
'rozkvétá',
|
|
5211
|
+
'klíčí',
|
|
5212
|
+
'zraje',
|
|
5213
|
+
'chvěje',
|
|
5214
|
+
'třpytí',
|
|
5215
|
+
'shromažďuje',
|
|
5216
|
+
'rozhazuje',
|
|
5217
|
+
'tápe',
|
|
5218
|
+
'žhne',
|
|
5219
|
+
'vibruje',
|
|
5220
|
+
'šumí',
|
|
5221
|
+
'stéká',
|
|
5222
|
+
'vypráví',
|
|
5223
|
+
'plánuje',
|
|
5224
|
+
'počítá',
|
|
5225
|
+
'váhá',
|
|
5226
|
+
'riskuje',
|
|
4623
5227
|
];
|
|
4624
5228
|
/**
|
|
4625
|
-
*
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
const expandedHash = `${hash}${hash}`;
|
|
4629
|
-
const start = (segmentIndex * HASH_SEGMENT_LENGTH + segmentIndex) % hash.length;
|
|
4630
|
-
return parseInt(expandedHash.substring(start, start + HASH_SEGMENT_LENGTH), 16);
|
|
4631
|
-
}
|
|
4632
|
-
/**
|
|
4633
|
-
* Picks a deterministic item from a list based on the hash seed.
|
|
4634
|
-
*/
|
|
4635
|
-
function pickFromHash(hash, segmentIndex, list) {
|
|
4636
|
-
const seed = getHashSeed(hash, segmentIndex);
|
|
4637
|
-
return list[seed % list.length];
|
|
4638
|
-
}
|
|
4639
|
-
/**
|
|
4640
|
-
* Index constants for story part selection to avoid magic numbers.
|
|
4641
|
-
*/
|
|
4642
|
-
const ADJECTIVE3_INDEX = 9;
|
|
4643
|
-
const NOUN3_INDEX = 10;
|
|
4644
|
-
/**
|
|
4645
|
-
* Creates the deterministic story parts used by the sentence templates.
|
|
5229
|
+
* Czech word lists used by the linguistic hash.
|
|
5230
|
+
*
|
|
5231
|
+
* @private utility of `linguisticHash`
|
|
4646
5232
|
*/
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
adjective1: pickFromHash(hash, 3, ADJECTIVES),
|
|
4653
|
-
noun1: pickFromHash(hash, 4, NOUNS),
|
|
4654
|
-
verb1: pickFromHash(hash, 5, VERBS),
|
|
4655
|
-
adjective2: pickFromHash(hash, 6, ADJECTIVES),
|
|
4656
|
-
noun2: pickFromHash(hash, 7, NOUNS),
|
|
4657
|
-
verb2: pickFromHash(hash, 8, VERBS),
|
|
4658
|
-
adjective3: pickFromHash(hash, ADJECTIVE3_INDEX, ADJECTIVES),
|
|
4659
|
-
noun3: pickFromHash(hash, NOUN3_INDEX, NOUNS),
|
|
4660
|
-
};
|
|
4661
|
-
}
|
|
5233
|
+
const LINGUISTIC_HASH_WORD_LISTS_CS = {
|
|
5234
|
+
adjective: ADJECTIVES$1,
|
|
5235
|
+
noun: NOUNS$1,
|
|
5236
|
+
verb: VERBS$1,
|
|
5237
|
+
};
|
|
4662
5238
|
/**
|
|
4663
|
-
*
|
|
5239
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
4664
5240
|
*/
|
|
4665
|
-
|
|
5241
|
+
|
|
4666
5242
|
/**
|
|
4667
|
-
*
|
|
5243
|
+
* @@@
|
|
5244
|
+
*
|
|
5245
|
+
* @private utility of `linguisticHash`
|
|
4668
5246
|
*/
|
|
4669
|
-
function createStorySentence(hash) {
|
|
4670
|
-
const parts = createStoryParts(hash);
|
|
4671
|
-
const template = pickFromHash(hash, STORY_TEMPLATE_INDEX, STORY_TEMPLATES);
|
|
4672
|
-
return template(parts).trim();
|
|
4673
|
-
}
|
|
4674
5247
|
const ADJECTIVES = [
|
|
4675
5248
|
'red',
|
|
4676
5249
|
'blue',
|
|
@@ -5345,8 +5918,215 @@ const VERBS = [
|
|
|
5345
5918
|
'spinning',
|
|
5346
5919
|
];
|
|
5347
5920
|
/**
|
|
5348
|
-
*
|
|
5921
|
+
* English word lists used by the linguistic hash.
|
|
5922
|
+
*
|
|
5923
|
+
* @private utility of `linguisticHash`
|
|
5924
|
+
*/
|
|
5925
|
+
const LINGUISTIC_HASH_WORD_LISTS_EN = {
|
|
5926
|
+
adjective: ADJECTIVES,
|
|
5927
|
+
noun: NOUNS,
|
|
5928
|
+
verb: VERBS,
|
|
5929
|
+
};
|
|
5930
|
+
/**
|
|
5931
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
5932
|
+
*/
|
|
5933
|
+
|
|
5934
|
+
/**
|
|
5935
|
+
* Default language used for linguistic hashes.
|
|
5936
|
+
*
|
|
5937
|
+
* @private utility of `linguisticHash`
|
|
5938
|
+
*/
|
|
5939
|
+
const DEFAULT_LINGUISTIC_HASH_LANGUAGE = 'en';
|
|
5940
|
+
/**
|
|
5941
|
+
* @@@
|
|
5942
|
+
*
|
|
5943
|
+
* @private utility of `linguisticHash`
|
|
5944
|
+
*/
|
|
5945
|
+
const LANGUAGE_CONFIGS = {
|
|
5946
|
+
en: {
|
|
5947
|
+
language: 'en',
|
|
5948
|
+
label: 'English',
|
|
5949
|
+
wordLists: LINGUISTIC_HASH_WORD_LISTS_EN,
|
|
5950
|
+
},
|
|
5951
|
+
cs: {
|
|
5952
|
+
language: 'cs',
|
|
5953
|
+
label: 'Czech',
|
|
5954
|
+
wordLists: LINGUISTIC_HASH_WORD_LISTS_CS,
|
|
5955
|
+
},
|
|
5956
|
+
};
|
|
5957
|
+
/**
|
|
5958
|
+
* Normalizes a requested language to a supported linguistic hash language.
|
|
5959
|
+
*
|
|
5960
|
+
* @private utility of `linguisticHash`
|
|
5961
|
+
*/
|
|
5962
|
+
function normalizeLinguisticHashLanguage(language) {
|
|
5963
|
+
if (typeof language !== 'string') {
|
|
5964
|
+
return DEFAULT_LINGUISTIC_HASH_LANGUAGE;
|
|
5965
|
+
}
|
|
5966
|
+
const normalized = language.trim().toLowerCase();
|
|
5967
|
+
if (normalized === 'cs') {
|
|
5968
|
+
return 'cs';
|
|
5969
|
+
}
|
|
5970
|
+
if (normalized === 'en') {
|
|
5971
|
+
return 'en';
|
|
5972
|
+
}
|
|
5973
|
+
return DEFAULT_LINGUISTIC_HASH_LANGUAGE;
|
|
5974
|
+
}
|
|
5975
|
+
/**
|
|
5976
|
+
* Returns the language configuration for linguistic hash generation.
|
|
5977
|
+
*
|
|
5978
|
+
* @private utility of `linguisticHash`
|
|
5979
|
+
*/
|
|
5980
|
+
function getLinguisticHashLanguageConfig(language) {
|
|
5981
|
+
const normalized = normalizeLinguisticHashLanguage(language);
|
|
5982
|
+
return LANGUAGE_CONFIGS[normalized];
|
|
5983
|
+
}
|
|
5984
|
+
|
|
5985
|
+
// <- TODO: !!!! Remove re-exports
|
|
5986
|
+
/**
|
|
5987
|
+
* Creates a human-readable hash as a short, story-like phrase.
|
|
5988
|
+
*
|
|
5989
|
+
* @param wordCount how many words to include (defaults to {@link DEFAULT_LINGUISTIC_HASH_WORD_COUNT}, clamped to
|
|
5990
|
+
* {@link MIN_LINGUISTIC_HASH_WORD_COUNT}..{@link MAX_LINGUISTIC_HASH_WORD_COUNT})
|
|
5991
|
+
* @param language optional language code (defaults to {@link DEFAULT_LINGUISTIC_HASH_LANGUAGE})
|
|
5992
|
+
*
|
|
5993
|
+
* @public exported from `@promptbook/utils`
|
|
5994
|
+
*/
|
|
5995
|
+
async function linguisticHash(input, wordCount, language) {
|
|
5996
|
+
const hash = computeHash(input);
|
|
5997
|
+
const normalizedWordCount = normalizeLinguisticHashWordCount(wordCount);
|
|
5998
|
+
const languageConfig = getLinguisticHashLanguageConfig(language);
|
|
5999
|
+
const words = createLinguisticHashWords(hash, normalizedWordCount, languageConfig.wordLists);
|
|
6000
|
+
return capitalize(words.join(' '));
|
|
6001
|
+
}
|
|
6002
|
+
/**
|
|
6003
|
+
* @@@
|
|
6004
|
+
*
|
|
6005
|
+
* @private utility of `linguisticHash`
|
|
6006
|
+
*/
|
|
6007
|
+
const HASH_SEGMENT_LENGTH = 8;
|
|
6008
|
+
/**
|
|
6009
|
+
* The minimum number of words for a linguistic hash.
|
|
6010
|
+
*
|
|
6011
|
+
* @private utility of `linguisticHash`
|
|
6012
|
+
*/
|
|
6013
|
+
const MIN_LINGUISTIC_HASH_WORD_COUNT = 1;
|
|
6014
|
+
/**
|
|
6015
|
+
* The default number of words for a linguistic hash.
|
|
6016
|
+
*
|
|
6017
|
+
* @private utility of `linguisticHash`
|
|
6018
|
+
*/
|
|
6019
|
+
const DEFAULT_LINGUISTIC_HASH_WORD_COUNT = 7;
|
|
6020
|
+
/**
|
|
6021
|
+
* Extracts a deterministic numeric seed from a SHA-256 hash.
|
|
6022
|
+
*
|
|
6023
|
+
* @private utility of `linguisticHash`
|
|
6024
|
+
*/
|
|
6025
|
+
function getHashSeed(hash, segmentIndex) {
|
|
6026
|
+
const expandedHash = `${hash}${hash}`;
|
|
6027
|
+
const start = (segmentIndex * HASH_SEGMENT_LENGTH + segmentIndex) % hash.length;
|
|
6028
|
+
return parseInt(expandedHash.substring(start, start + HASH_SEGMENT_LENGTH), 16);
|
|
6029
|
+
}
|
|
6030
|
+
/**
|
|
6031
|
+
* Picks a deterministic item from a list based on the hash seed.
|
|
6032
|
+
*
|
|
6033
|
+
* @private utility of `linguisticHash`
|
|
6034
|
+
*/
|
|
6035
|
+
function pickFromHash(hash, segmentIndex, list) {
|
|
6036
|
+
const seed = getHashSeed(hash, segmentIndex);
|
|
6037
|
+
return list[seed % list.length];
|
|
6038
|
+
}
|
|
6039
|
+
/**
|
|
6040
|
+
* Ordered word kinds used to build the linguistic hash output.
|
|
6041
|
+
*
|
|
6042
|
+
* @private utility of `linguisticHash`
|
|
6043
|
+
*/
|
|
6044
|
+
const WORD_SEQUENCE = [
|
|
6045
|
+
'adjective',
|
|
6046
|
+
'noun',
|
|
6047
|
+
'verb',
|
|
6048
|
+
'adjective',
|
|
6049
|
+
'noun',
|
|
6050
|
+
'verb',
|
|
6051
|
+
'adjective',
|
|
6052
|
+
'noun',
|
|
6053
|
+
'verb',
|
|
6054
|
+
'adjective',
|
|
6055
|
+
'noun',
|
|
6056
|
+
'verb',
|
|
6057
|
+
'adjective',
|
|
6058
|
+
'noun',
|
|
6059
|
+
'verb',
|
|
6060
|
+
'adjective',
|
|
6061
|
+
'noun',
|
|
6062
|
+
'verb',
|
|
6063
|
+
'adjective',
|
|
6064
|
+
'noun',
|
|
6065
|
+
];
|
|
6066
|
+
/**
|
|
6067
|
+
* The maximum number of words for a linguistic hash.
|
|
6068
|
+
*
|
|
6069
|
+
* @private utility of `linguisticHash`
|
|
6070
|
+
*/
|
|
6071
|
+
const MAX_LINGUISTIC_HASH_WORD_COUNT = WORD_SEQUENCE.length;
|
|
6072
|
+
/**
|
|
6073
|
+
* Index of the noun used for single-word hashes.
|
|
6074
|
+
*
|
|
6075
|
+
* @private utility of `linguisticHash`
|
|
6076
|
+
*/
|
|
6077
|
+
const SINGLE_WORD_INDEX = 1;
|
|
6078
|
+
/**
|
|
6079
|
+
* Normalizes the word count to a supported integer range.
|
|
6080
|
+
*
|
|
6081
|
+
* @private utility of `linguisticHash`
|
|
6082
|
+
*/
|
|
6083
|
+
function normalizeLinguisticHashWordCount(wordCount) {
|
|
6084
|
+
if (typeof wordCount !== 'number' || !Number.isFinite(wordCount)) {
|
|
6085
|
+
return DEFAULT_LINGUISTIC_HASH_WORD_COUNT;
|
|
6086
|
+
}
|
|
6087
|
+
const rounded = Math.round(wordCount);
|
|
6088
|
+
return Math.min(MAX_LINGUISTIC_HASH_WORD_COUNT, Math.max(MIN_LINGUISTIC_HASH_WORD_COUNT, rounded));
|
|
6089
|
+
}
|
|
6090
|
+
/**
|
|
6091
|
+
* Picks a deterministic word from the hash by kind.
|
|
6092
|
+
*
|
|
6093
|
+
* @private utility of `linguisticHash`
|
|
6094
|
+
*/
|
|
6095
|
+
function pickWordFromHash(hash, segmentIndex, wordKind, wordLists) {
|
|
6096
|
+
return pickFromHash(hash, segmentIndex, wordLists[wordKind]);
|
|
6097
|
+
}
|
|
6098
|
+
/**
|
|
6099
|
+
* Creates the deterministic word sequence used for the linguistic hash output.
|
|
6100
|
+
*
|
|
6101
|
+
* @private utility of `linguisticHash`
|
|
6102
|
+
*/
|
|
6103
|
+
function createLinguisticHashWordSequence(hash, wordLists) {
|
|
6104
|
+
return WORD_SEQUENCE.map((wordKind, index) => pickWordFromHash(hash, index, wordKind, wordLists));
|
|
6105
|
+
}
|
|
6106
|
+
/**
|
|
6107
|
+
* Selects the requested number of words from the hash output.
|
|
6108
|
+
*
|
|
6109
|
+
* @private utility of `linguisticHash`
|
|
5349
6110
|
*/
|
|
6111
|
+
function createLinguisticHashWords(hash, wordCount, wordLists) {
|
|
6112
|
+
const words = createLinguisticHashWordSequence(hash, wordLists);
|
|
6113
|
+
if (wordCount === 1) {
|
|
6114
|
+
return [words[SINGLE_WORD_INDEX]];
|
|
6115
|
+
}
|
|
6116
|
+
return words.slice(0, wordCount);
|
|
6117
|
+
}
|
|
6118
|
+
|
|
6119
|
+
/**
|
|
6120
|
+
* Simple wrapper `new Date().toISOString()`
|
|
6121
|
+
*
|
|
6122
|
+
* Note: `$` is used to indicate that this function is not a pure function - it is not deterministic because it depends on the current time
|
|
6123
|
+
*
|
|
6124
|
+
* @returns string_date branded type
|
|
6125
|
+
* @public exported from `@promptbook/utils`
|
|
6126
|
+
*/
|
|
6127
|
+
function $getCurrentDate() {
|
|
6128
|
+
return new Date().toISOString();
|
|
6129
|
+
}
|
|
5350
6130
|
|
|
5351
6131
|
/**
|
|
5352
6132
|
* Function parseNumber will parse number from string
|
|
@@ -28151,17 +28931,32 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28151
28931
|
});
|
|
28152
28932
|
}
|
|
28153
28933
|
async createNewAssistant(options) {
|
|
28934
|
+
var _a, _b, _c;
|
|
28154
28935
|
if (!this.isCreatingNewAssistantsAllowed) {
|
|
28155
28936
|
throw new NotAllowed(`Creating new assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
|
|
28156
28937
|
}
|
|
28157
28938
|
// await this.playground();
|
|
28158
28939
|
const { name, instructions, knowledgeSources, tools } = options;
|
|
28940
|
+
const preparationStartedAtMs = Date.now();
|
|
28941
|
+
const knowledgeSourcesCount = (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0;
|
|
28942
|
+
const toolsCount = (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0;
|
|
28943
|
+
if (this.options.isVerbose) {
|
|
28944
|
+
console.info('[🤰]', 'Starting OpenAI assistant creation', {
|
|
28945
|
+
name,
|
|
28946
|
+
knowledgeSourcesCount,
|
|
28947
|
+
toolsCount,
|
|
28948
|
+
instructionsLength: instructions.length,
|
|
28949
|
+
});
|
|
28950
|
+
}
|
|
28159
28951
|
const client = await this.getClient();
|
|
28160
28952
|
let vectorStoreId;
|
|
28161
28953
|
// If knowledge sources are provided, create a vector store with them
|
|
28162
28954
|
if (knowledgeSources && knowledgeSources.length > 0) {
|
|
28163
28955
|
if (this.options.isVerbose) {
|
|
28164
|
-
console.info(
|
|
28956
|
+
console.info('[🤰]', 'Creating vector store with knowledge sources', {
|
|
28957
|
+
name,
|
|
28958
|
+
knowledgeSourcesCount,
|
|
28959
|
+
});
|
|
28165
28960
|
}
|
|
28166
28961
|
// Create a vector store
|
|
28167
28962
|
const vectorStore = await client.beta.vectorStores.create({
|
|
@@ -28169,12 +28964,22 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28169
28964
|
});
|
|
28170
28965
|
vectorStoreId = vectorStore.id;
|
|
28171
28966
|
if (this.options.isVerbose) {
|
|
28172
|
-
console.info(
|
|
28967
|
+
console.info('[🤰]', 'Vector store created', {
|
|
28968
|
+
vectorStoreId,
|
|
28969
|
+
});
|
|
28173
28970
|
}
|
|
28174
28971
|
// Upload files from knowledge sources to the vector store
|
|
28175
28972
|
const fileStreams = [];
|
|
28176
|
-
for (const source of knowledgeSources) {
|
|
28973
|
+
for (const [index, source] of knowledgeSources.entries()) {
|
|
28177
28974
|
try {
|
|
28975
|
+
if (this.options.isVerbose) {
|
|
28976
|
+
console.info('[🤰]', 'Processing knowledge source', {
|
|
28977
|
+
index: index + 1,
|
|
28978
|
+
total: knowledgeSources.length,
|
|
28979
|
+
source,
|
|
28980
|
+
sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
|
|
28981
|
+
});
|
|
28982
|
+
}
|
|
28178
28983
|
// Check if it's a URL
|
|
28179
28984
|
if (source.startsWith('http://') || source.startsWith('https://')) {
|
|
28180
28985
|
// Download the file
|
|
@@ -28219,7 +29024,10 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28219
29024
|
files: fileStreams,
|
|
28220
29025
|
});
|
|
28221
29026
|
if (this.options.isVerbose) {
|
|
28222
|
-
console.info(
|
|
29027
|
+
console.info('[🤰]', 'Uploaded files to vector store', {
|
|
29028
|
+
vectorStoreId,
|
|
29029
|
+
fileCount: fileStreams.length,
|
|
29030
|
+
});
|
|
28223
29031
|
}
|
|
28224
29032
|
}
|
|
28225
29033
|
catch (error) {
|
|
@@ -28247,8 +29055,21 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28247
29055
|
},
|
|
28248
29056
|
};
|
|
28249
29057
|
}
|
|
29058
|
+
if (this.options.isVerbose) {
|
|
29059
|
+
console.info('[🤰]', 'Creating OpenAI assistant', {
|
|
29060
|
+
name,
|
|
29061
|
+
model: assistantConfig.model,
|
|
29062
|
+
toolCount: (_c = assistantConfig === null || assistantConfig === void 0 ? void 0 : assistantConfig.tools) === null || _c === void 0 ? void 0 : _c.length,
|
|
29063
|
+
hasVectorStore: Boolean(vectorStoreId),
|
|
29064
|
+
});
|
|
29065
|
+
}
|
|
28250
29066
|
const assistant = await client.beta.assistants.create(assistantConfig);
|
|
28251
|
-
|
|
29067
|
+
if (this.options.isVerbose) {
|
|
29068
|
+
console.info('[🤰]', 'OpenAI assistant created', {
|
|
29069
|
+
assistantId: assistant.id,
|
|
29070
|
+
elapsedMs: Date.now() - preparationStartedAtMs,
|
|
29071
|
+
});
|
|
29072
|
+
}
|
|
28252
29073
|
// TODO: [🐱🚀] Try listing existing assistants
|
|
28253
29074
|
// TODO: [🐱🚀] Try marking existing assistants by DISCRIMINANT
|
|
28254
29075
|
// TODO: [🐱🚀] Allow to update and reconnect to existing assistants
|
|
@@ -28259,17 +29080,34 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28259
29080
|
});
|
|
28260
29081
|
}
|
|
28261
29082
|
async updateAssistant(options) {
|
|
29083
|
+
var _a, _b, _c, _d;
|
|
28262
29084
|
if (!this.isCreatingNewAssistantsAllowed) {
|
|
28263
29085
|
throw new NotAllowed(`Updating assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
|
|
28264
29086
|
}
|
|
28265
29087
|
const { assistantId, name, instructions, knowledgeSources, tools } = options;
|
|
29088
|
+
const preparationStartedAtMs = Date.now();
|
|
29089
|
+
const knowledgeSourcesCount = (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0;
|
|
29090
|
+
const toolsCount = (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0;
|
|
29091
|
+
if (this.options.isVerbose) {
|
|
29092
|
+
console.info('[🤰]', 'Starting OpenAI assistant update', {
|
|
29093
|
+
assistantId,
|
|
29094
|
+
name,
|
|
29095
|
+
knowledgeSourcesCount,
|
|
29096
|
+
toolsCount,
|
|
29097
|
+
instructionsLength: (_c = instructions === null || instructions === void 0 ? void 0 : instructions.length) !== null && _c !== void 0 ? _c : 0,
|
|
29098
|
+
});
|
|
29099
|
+
}
|
|
28266
29100
|
const client = await this.getClient();
|
|
28267
29101
|
let vectorStoreId;
|
|
28268
29102
|
// If knowledge sources are provided, create a vector store with them
|
|
28269
29103
|
// TODO: [🧠] Reuse vector store creation logic from createNewAssistant
|
|
28270
29104
|
if (knowledgeSources && knowledgeSources.length > 0) {
|
|
28271
29105
|
if (this.options.isVerbose) {
|
|
28272
|
-
console.info(
|
|
29106
|
+
console.info('[🤰]', 'Creating vector store for assistant update', {
|
|
29107
|
+
assistantId,
|
|
29108
|
+
name,
|
|
29109
|
+
knowledgeSourcesCount,
|
|
29110
|
+
});
|
|
28273
29111
|
}
|
|
28274
29112
|
// Create a vector store
|
|
28275
29113
|
const vectorStore = await client.beta.vectorStores.create({
|
|
@@ -28277,12 +29115,22 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28277
29115
|
});
|
|
28278
29116
|
vectorStoreId = vectorStore.id;
|
|
28279
29117
|
if (this.options.isVerbose) {
|
|
28280
|
-
console.info(
|
|
29118
|
+
console.info('[🤰]', 'Vector store created for assistant update', {
|
|
29119
|
+
vectorStoreId,
|
|
29120
|
+
});
|
|
28281
29121
|
}
|
|
28282
29122
|
// Upload files from knowledge sources to the vector store
|
|
28283
29123
|
const fileStreams = [];
|
|
28284
|
-
for (const source of knowledgeSources) {
|
|
29124
|
+
for (const [index, source] of knowledgeSources.entries()) {
|
|
28285
29125
|
try {
|
|
29126
|
+
if (this.options.isVerbose) {
|
|
29127
|
+
console.info('[🤰]', 'Processing knowledge source for update', {
|
|
29128
|
+
index: index + 1,
|
|
29129
|
+
total: knowledgeSources.length,
|
|
29130
|
+
source,
|
|
29131
|
+
sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
|
|
29132
|
+
});
|
|
29133
|
+
}
|
|
28286
29134
|
// Check if it's a URL
|
|
28287
29135
|
if (source.startsWith('http://') || source.startsWith('https://')) {
|
|
28288
29136
|
// Download the file
|
|
@@ -28327,7 +29175,10 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28327
29175
|
files: fileStreams,
|
|
28328
29176
|
});
|
|
28329
29177
|
if (this.options.isVerbose) {
|
|
28330
|
-
console.info(
|
|
29178
|
+
console.info('[🤰]', 'Uploaded files to vector store for update', {
|
|
29179
|
+
vectorStoreId,
|
|
29180
|
+
fileCount: fileStreams.length,
|
|
29181
|
+
});
|
|
28331
29182
|
}
|
|
28332
29183
|
}
|
|
28333
29184
|
catch (error) {
|
|
@@ -28351,9 +29202,20 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28351
29202
|
},
|
|
28352
29203
|
};
|
|
28353
29204
|
}
|
|
29205
|
+
if (this.options.isVerbose) {
|
|
29206
|
+
console.info('[🤰]', 'Updating OpenAI assistant', {
|
|
29207
|
+
assistantId,
|
|
29208
|
+
name,
|
|
29209
|
+
toolCount: (_d = assistantUpdate === null || assistantUpdate === void 0 ? void 0 : assistantUpdate.tools) === null || _d === void 0 ? void 0 : _d.length,
|
|
29210
|
+
hasVectorStore: Boolean(vectorStoreId),
|
|
29211
|
+
});
|
|
29212
|
+
}
|
|
28354
29213
|
const assistant = await client.beta.assistants.update(assistantId, assistantUpdate);
|
|
28355
29214
|
if (this.options.isVerbose) {
|
|
28356
|
-
console.
|
|
29215
|
+
console.info('[🤰]', 'OpenAI assistant updated', {
|
|
29216
|
+
assistantId: assistant.id,
|
|
29217
|
+
elapsedMs: Date.now() - preparationStartedAtMs,
|
|
29218
|
+
});
|
|
28357
29219
|
}
|
|
28358
29220
|
return new OpenAiAssistantExecutionTools({
|
|
28359
29221
|
...this.options,
|
|
@@ -30952,6 +31814,21 @@ function book(strings, ...values) {
|
|
|
30952
31814
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
30953
31815
|
*/
|
|
30954
31816
|
|
|
31817
|
+
/**
|
|
31818
|
+
* Tool call name emitted while preparing a GPT assistant for an agent.
|
|
31819
|
+
*
|
|
31820
|
+
* @public exported from `@promptbook/types`
|
|
31821
|
+
*/
|
|
31822
|
+
const ASSISTANT_PREPARATION_TOOL_CALL_NAME = 'assistant_preparation';
|
|
31823
|
+
/**
|
|
31824
|
+
* Checks whether a tool call is the assistant preparation marker.
|
|
31825
|
+
*
|
|
31826
|
+
* @public exported from `@promptbook/types`
|
|
31827
|
+
*/
|
|
31828
|
+
function isAssistantPreparationToolCall(toolCall) {
|
|
31829
|
+
return toolCall.name === ASSISTANT_PREPARATION_TOOL_CALL_NAME;
|
|
31830
|
+
}
|
|
31831
|
+
|
|
30955
31832
|
/*! *****************************************************************************
|
|
30956
31833
|
Copyright (c) Microsoft Corporation.
|
|
30957
31834
|
|
|
@@ -31064,14 +31941,27 @@ function humanizeAiTextEmdashed(aiText) {
|
|
|
31064
31941
|
* @public exported from `@promptbook/markdown-utils`
|
|
31065
31942
|
*/
|
|
31066
31943
|
function humanizeAiTextQuotes(aiText) {
|
|
31067
|
-
return aiText
|
|
31068
|
-
.replace(/[“”„‟«»❝❞〝〞〟"]/g, '"')
|
|
31069
|
-
.replace(/[‚‘’‛‹›❛❜'ʼ]/g, "'");
|
|
31944
|
+
return aiText.replace(/[“”„‟«»❝❞〝〞〟"]/g, '"').replace(/[‚‘’‛‹›❛❜'ʼ]/g, "'");
|
|
31070
31945
|
}
|
|
31071
31946
|
/**
|
|
31072
31947
|
* Note: [🏂] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
|
|
31073
31948
|
*/
|
|
31074
31949
|
|
|
31950
|
+
/**
|
|
31951
|
+
* Remove bracketed source citation artifacts like `\u30105:1\u2020source\u3011`.
|
|
31952
|
+
*
|
|
31953
|
+
* Note: [??] This function is idempotent.
|
|
31954
|
+
* Tip: If you want to do the full cleanup, look for `humanizeAiText` exported `@promptbook/markdown-utils`
|
|
31955
|
+
*
|
|
31956
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
31957
|
+
*/
|
|
31958
|
+
function humanizeAiTextSources(aiText) {
|
|
31959
|
+
return aiText.replace(/[ \t]*\u3010\s*\d+(?:\s*:\s*\d+)?\s*\u2020source\s*\u3011/g, '');
|
|
31960
|
+
}
|
|
31961
|
+
/**
|
|
31962
|
+
* Note: [??] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
|
|
31963
|
+
*/
|
|
31964
|
+
|
|
31075
31965
|
/**
|
|
31076
31966
|
* Change unprintable hard spaces to regular spaces and drop zero-width spaces
|
|
31077
31967
|
*
|
|
@@ -31081,9 +31971,7 @@ function humanizeAiTextQuotes(aiText) {
|
|
|
31081
31971
|
* @public exported from `@promptbook/markdown-utils`
|
|
31082
31972
|
*/
|
|
31083
31973
|
function humanizeAiTextWhitespace(aiText) {
|
|
31084
|
-
return aiText
|
|
31085
|
-
.replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g, ' ')
|
|
31086
|
-
.replace(/[\u200B\uFEFF\u2060]/g, '');
|
|
31974
|
+
return aiText.replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g, ' ').replace(/[\u200B\uFEFF\u2060]/g, '');
|
|
31087
31975
|
}
|
|
31088
31976
|
/**
|
|
31089
31977
|
* Note: [🏂] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
|
|
@@ -31102,6 +31990,7 @@ function humanizeAiText(aiText) {
|
|
|
31102
31990
|
cleanedText = humanizeAiTextEllipsis(cleanedText);
|
|
31103
31991
|
cleanedText = humanizeAiTextEmdashed(cleanedText);
|
|
31104
31992
|
cleanedText = humanizeAiTextQuotes(cleanedText);
|
|
31993
|
+
cleanedText = humanizeAiTextSources(cleanedText);
|
|
31105
31994
|
cleanedText = humanizeAiTextWhitespace(cleanedText);
|
|
31106
31995
|
return cleanedText;
|
|
31107
31996
|
}
|
|
@@ -31362,6 +32251,33 @@ class OpenAiAgentExecutionTools extends OpenAiExecutionTools {
|
|
|
31362
32251
|
}
|
|
31363
32252
|
}
|
|
31364
32253
|
|
|
32254
|
+
/**
|
|
32255
|
+
* Emits a progress update to signal assistant preparation before long setup work.
|
|
32256
|
+
*/
|
|
32257
|
+
function emitAssistantPreparationProgress(options) {
|
|
32258
|
+
const startedAt = $getCurrentDate();
|
|
32259
|
+
options.onProgress({
|
|
32260
|
+
content: '',
|
|
32261
|
+
modelName: options.modelName,
|
|
32262
|
+
timing: {
|
|
32263
|
+
start: startedAt,
|
|
32264
|
+
complete: startedAt,
|
|
32265
|
+
},
|
|
32266
|
+
usage: UNCERTAIN_USAGE,
|
|
32267
|
+
rawPromptContent: options.prompt.content,
|
|
32268
|
+
rawRequest: null,
|
|
32269
|
+
rawResponse: {
|
|
32270
|
+
status: 'assistant_preparation',
|
|
32271
|
+
},
|
|
32272
|
+
toolCalls: [
|
|
32273
|
+
{
|
|
32274
|
+
name: ASSISTANT_PREPARATION_TOOL_CALL_NAME,
|
|
32275
|
+
arguments: options.phase ? { phase: options.phase } : {},
|
|
32276
|
+
createdAt: startedAt,
|
|
32277
|
+
},
|
|
32278
|
+
],
|
|
32279
|
+
});
|
|
32280
|
+
}
|
|
31365
32281
|
/**
|
|
31366
32282
|
* Execution Tools for calling LLM models with a predefined agent "soul"
|
|
31367
32283
|
* This wraps underlying LLM execution tools and applies agent-specific system prompts and requirements
|
|
@@ -31420,10 +32336,32 @@ class AgentLlmExecutionTools {
|
|
|
31420
32336
|
*/
|
|
31421
32337
|
async getModelRequirements() {
|
|
31422
32338
|
if (this._cachedModelRequirements === null) {
|
|
32339
|
+
const preparationStartedAtMs = Date.now();
|
|
32340
|
+
if (this.options.isVerbose) {
|
|
32341
|
+
console.info('[🤰]', 'Preparing agent model requirements', {
|
|
32342
|
+
agent: this.title,
|
|
32343
|
+
});
|
|
32344
|
+
}
|
|
31423
32345
|
// Get available models from underlying LLM tools for best model selection
|
|
32346
|
+
const availableModelsStartedAtMs = Date.now();
|
|
31424
32347
|
const availableModels = await this.options.llmTools.listModels();
|
|
32348
|
+
if (this.options.isVerbose) {
|
|
32349
|
+
console.info('[🤰]', 'Available models resolved for agent', {
|
|
32350
|
+
agent: this.title,
|
|
32351
|
+
modelCount: availableModels.length,
|
|
32352
|
+
elapsedMs: Date.now() - availableModelsStartedAtMs,
|
|
32353
|
+
});
|
|
32354
|
+
}
|
|
32355
|
+
const requirementsStartedAtMs = Date.now();
|
|
31425
32356
|
this._cachedModelRequirements = await createAgentModelRequirements(this.options.agentSource, undefined, // Let the function pick the best model
|
|
31426
32357
|
availableModels);
|
|
32358
|
+
if (this.options.isVerbose) {
|
|
32359
|
+
console.info('[🤰]', 'Agent model requirements ready', {
|
|
32360
|
+
agent: this.title,
|
|
32361
|
+
elapsedMs: Date.now() - requirementsStartedAtMs,
|
|
32362
|
+
totalElapsedMs: Date.now() - preparationStartedAtMs,
|
|
32363
|
+
});
|
|
32364
|
+
}
|
|
31427
32365
|
}
|
|
31428
32366
|
return this._cachedModelRequirements;
|
|
31429
32367
|
}
|
|
@@ -31577,14 +32515,26 @@ class AgentLlmExecutionTools {
|
|
|
31577
32515
|
if (cached) {
|
|
31578
32516
|
if (cached.requirementsHash === requirementsHash) {
|
|
31579
32517
|
if (this.options.isVerbose) {
|
|
31580
|
-
console.
|
|
32518
|
+
console.info('[🤰]', 'Using cached OpenAI Assistant', {
|
|
32519
|
+
agent: this.title,
|
|
32520
|
+
assistantId: cached.assistantId,
|
|
32521
|
+
});
|
|
31581
32522
|
}
|
|
31582
32523
|
assistant = this.options.llmTools.getAssistant(cached.assistantId);
|
|
31583
32524
|
}
|
|
31584
32525
|
else {
|
|
31585
32526
|
if (this.options.isVerbose) {
|
|
31586
|
-
console.
|
|
32527
|
+
console.info('[🤰]', 'Updating OpenAI Assistant', {
|
|
32528
|
+
agent: this.title,
|
|
32529
|
+
assistantId: cached.assistantId,
|
|
32530
|
+
});
|
|
31587
32531
|
}
|
|
32532
|
+
emitAssistantPreparationProgress({
|
|
32533
|
+
onProgress,
|
|
32534
|
+
prompt,
|
|
32535
|
+
modelName: this.modelName,
|
|
32536
|
+
phase: 'Updating assistant',
|
|
32537
|
+
});
|
|
31588
32538
|
assistant = await this.options.llmTools.updateAssistant({
|
|
31589
32539
|
assistantId: cached.assistantId,
|
|
31590
32540
|
name: this.title,
|
|
@@ -31600,9 +32550,17 @@ class AgentLlmExecutionTools {
|
|
|
31600
32550
|
}
|
|
31601
32551
|
else {
|
|
31602
32552
|
if (this.options.isVerbose) {
|
|
31603
|
-
console.
|
|
32553
|
+
console.info('[🤰]', 'Creating new OpenAI Assistant', {
|
|
32554
|
+
agent: this.title,
|
|
32555
|
+
});
|
|
31604
32556
|
}
|
|
31605
32557
|
// <- TODO: [🐱🚀] Check also `isCreatingNewAssistantsAllowed` and warn about it
|
|
32558
|
+
emitAssistantPreparationProgress({
|
|
32559
|
+
onProgress,
|
|
32560
|
+
prompt,
|
|
32561
|
+
modelName: this.modelName,
|
|
32562
|
+
phase: 'Creating assistant',
|
|
32563
|
+
});
|
|
31606
32564
|
assistant = await this.options.llmTools.createNewAssistant({
|
|
31607
32565
|
name: this.title,
|
|
31608
32566
|
instructions: modelRequirements.systemMessage,
|
|
@@ -31675,6 +32633,58 @@ AgentLlmExecutionTools.vectorStoreCache = new Map();
|
|
|
31675
32633
|
*/
|
|
31676
32634
|
|
|
31677
32635
|
var _Agent_instances, _Agent_selfLearnNonce, _Agent_selfLearnSamples, _Agent_selfLearnTeacher;
|
|
32636
|
+
/**
|
|
32637
|
+
* Creates an empty commitment breakdown for self-learning summaries.
|
|
32638
|
+
*/
|
|
32639
|
+
function createEmptySelfLearningCommitmentCounts() {
|
|
32640
|
+
return {
|
|
32641
|
+
total: 0,
|
|
32642
|
+
knowledge: 0,
|
|
32643
|
+
rule: 0,
|
|
32644
|
+
persona: 0,
|
|
32645
|
+
other: 0,
|
|
32646
|
+
};
|
|
32647
|
+
}
|
|
32648
|
+
/**
|
|
32649
|
+
* Summarizes teacher commitments into user-friendly counts for self-learning.
|
|
32650
|
+
*/
|
|
32651
|
+
function summarizeTeacherCommitments(commitments) {
|
|
32652
|
+
var _a, _b;
|
|
32653
|
+
const counts = createEmptySelfLearningCommitmentCounts();
|
|
32654
|
+
const lines = commitments
|
|
32655
|
+
.split(/\r?\n/)
|
|
32656
|
+
.map((line) => line.trim())
|
|
32657
|
+
.filter((line) => line.length > 0 && line !== '---' && !line.startsWith('```'));
|
|
32658
|
+
for (const line of lines) {
|
|
32659
|
+
const keyword = (_b = (_a = line.split(/\s+/)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : '';
|
|
32660
|
+
if (!/^[A-Z][A-Z_-]*$/.test(keyword)) {
|
|
32661
|
+
continue;
|
|
32662
|
+
}
|
|
32663
|
+
counts.total += 1;
|
|
32664
|
+
if (keyword === 'KNOWLEDGE') {
|
|
32665
|
+
counts.knowledge += 1;
|
|
32666
|
+
}
|
|
32667
|
+
else if (keyword === 'RULE') {
|
|
32668
|
+
counts.rule += 1;
|
|
32669
|
+
}
|
|
32670
|
+
else if (keyword === 'PERSONA') {
|
|
32671
|
+
counts.persona += 1;
|
|
32672
|
+
}
|
|
32673
|
+
else {
|
|
32674
|
+
counts.other += 1;
|
|
32675
|
+
}
|
|
32676
|
+
}
|
|
32677
|
+
return counts;
|
|
32678
|
+
}
|
|
32679
|
+
/**
|
|
32680
|
+
* Builds the teacher summary payload for the self-learning tool call.
|
|
32681
|
+
*/
|
|
32682
|
+
function buildTeacherSummary(commitments, used) {
|
|
32683
|
+
return {
|
|
32684
|
+
used,
|
|
32685
|
+
commitmentTypes: summarizeTeacherCommitments(commitments),
|
|
32686
|
+
};
|
|
32687
|
+
}
|
|
31678
32688
|
/**
|
|
31679
32689
|
* Represents one AI Agent
|
|
31680
32690
|
*
|
|
@@ -31849,16 +32859,29 @@ class Agent extends AgentLlmExecutionTools {
|
|
|
31849
32859
|
// Note: [2] Do the append of the samples
|
|
31850
32860
|
await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnSamples).call(this, prompt, result);
|
|
31851
32861
|
// Note: [3] Asynchronously call the teacher agent and invoke the silver link. When the teacher fails, keep just the samples
|
|
31852
|
-
|
|
32862
|
+
let teacherSummary = null;
|
|
32863
|
+
try {
|
|
32864
|
+
teacherSummary = await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnTeacher).call(this, prompt, result);
|
|
32865
|
+
}
|
|
32866
|
+
catch (error) {
|
|
31853
32867
|
// !!!!! if (this.options.isVerbose) {
|
|
31854
32868
|
console.error(colors.bgCyan('[Self-learning]') + colors.red(' Failed to learn from teacher agent'));
|
|
31855
32869
|
console.error(error);
|
|
31856
32870
|
// }
|
|
31857
|
-
|
|
32871
|
+
teacherSummary = this.teacherAgent ? buildTeacherSummary('', true) : null;
|
|
32872
|
+
}
|
|
31858
32873
|
// Note: [4] Notify end of self-learning
|
|
32874
|
+
const completedAt = new Date().toISOString();
|
|
32875
|
+
const selfLearningResult = {
|
|
32876
|
+
success: true,
|
|
32877
|
+
startedAt: selfLearningToolCall.createdAt,
|
|
32878
|
+
completedAt,
|
|
32879
|
+
samplesAdded: 1,
|
|
32880
|
+
teacher: teacherSummary || undefined,
|
|
32881
|
+
};
|
|
31859
32882
|
const completedSelfLearningToolCall = {
|
|
31860
32883
|
...selfLearningToolCall,
|
|
31861
|
-
result:
|
|
32884
|
+
result: selfLearningResult,
|
|
31862
32885
|
};
|
|
31863
32886
|
const finalResult = {
|
|
31864
32887
|
...result,
|
|
@@ -31907,7 +32930,7 @@ async function _Agent_selfLearnNonce() {
|
|
|
31907
32930
|
async function _Agent_selfLearnTeacher(prompt, result) {
|
|
31908
32931
|
// [1] Call the teacher agent // <- !!!!! Emojis
|
|
31909
32932
|
if (this.teacherAgent === null) {
|
|
31910
|
-
return;
|
|
32933
|
+
return null;
|
|
31911
32934
|
}
|
|
31912
32935
|
console.info(colors.bgCyan('[Self-learning]') + colors.cyan(' Teacher'));
|
|
31913
32936
|
const teacherResult = await this.teacherAgent.callChatModel({
|
|
@@ -31962,7 +32985,7 @@ async function _Agent_selfLearnTeacher(prompt, result) {
|
|
|
31962
32985
|
if (teacherCommitments === '') {
|
|
31963
32986
|
console.info(colors.bgCyan('[Self-learning]') +
|
|
31964
32987
|
colors.cyan(' Teacher agent did not provide new commitments to learn'));
|
|
31965
|
-
return;
|
|
32988
|
+
return buildTeacherSummary('', true);
|
|
31966
32989
|
}
|
|
31967
32990
|
// [2] Append to the current source
|
|
31968
32991
|
const currentSource = this.agentSource.value;
|
|
@@ -31970,6 +32993,7 @@ async function _Agent_selfLearnTeacher(prompt, result) {
|
|
|
31970
32993
|
// <- TODO: [🈲] Use some object-based way how to append on book (with sections `---`)
|
|
31971
32994
|
// [3] Update the source
|
|
31972
32995
|
this.agentSource.next(newSource);
|
|
32996
|
+
return buildTeacherSummary(teacherCommitments, true);
|
|
31973
32997
|
};
|
|
31974
32998
|
/**
|
|
31975
32999
|
* TODO: [🧠][😰]Agent is not working with the parameters, should it be?
|
|
@@ -32133,6 +33157,8 @@ class RemoteAgent extends Agent {
|
|
|
32133
33157
|
// <- TODO: [🐱🚀] Maybe use promptbookFetch
|
|
32134
33158
|
let content = '';
|
|
32135
33159
|
const toolCalls = [];
|
|
33160
|
+
const preparationToolCalls = [];
|
|
33161
|
+
let hasReceivedModelOutput = false;
|
|
32136
33162
|
const normalizeToolCall = (toolCall) => {
|
|
32137
33163
|
if (toolCall.createdAt) {
|
|
32138
33164
|
return toolCall;
|
|
@@ -32179,6 +33205,17 @@ class RemoteAgent extends Agent {
|
|
|
32179
33205
|
const upsertToolCalls = (incomingToolCalls) => {
|
|
32180
33206
|
for (const toolCall of incomingToolCalls) {
|
|
32181
33207
|
const normalized = normalizeToolCall(toolCall);
|
|
33208
|
+
if (isAssistantPreparationToolCall(normalized)) {
|
|
33209
|
+
if (hasReceivedModelOutput) {
|
|
33210
|
+
continue;
|
|
33211
|
+
}
|
|
33212
|
+
preparationToolCalls.length = 0;
|
|
33213
|
+
preparationToolCalls.push(normalized);
|
|
33214
|
+
continue;
|
|
33215
|
+
}
|
|
33216
|
+
if (preparationToolCalls.length > 0) {
|
|
33217
|
+
preparationToolCalls.length = 0;
|
|
33218
|
+
}
|
|
32182
33219
|
const key = getToolCallKey(normalized);
|
|
32183
33220
|
const existingIndex = toolCalls.findIndex((existing) => getToolCallKey(existing) === key);
|
|
32184
33221
|
if (existingIndex === -1) {
|
|
@@ -32189,6 +33226,10 @@ class RemoteAgent extends Agent {
|
|
|
32189
33226
|
}
|
|
32190
33227
|
}
|
|
32191
33228
|
};
|
|
33229
|
+
/**
|
|
33230
|
+
* Builds the tool call list including any preparation marker still active.
|
|
33231
|
+
*/
|
|
33232
|
+
const getActiveToolCalls = () => preparationToolCalls.length > 0 ? [...preparationToolCalls, ...toolCalls] : toolCalls;
|
|
32192
33233
|
if (!bookResponse.body) {
|
|
32193
33234
|
content = await bookResponse.text();
|
|
32194
33235
|
}
|
|
@@ -32225,7 +33266,7 @@ class RemoteAgent extends Agent {
|
|
|
32225
33266
|
rawPromptContent: {},
|
|
32226
33267
|
rawRequest: {},
|
|
32227
33268
|
rawResponse: {},
|
|
32228
|
-
toolCalls:
|
|
33269
|
+
toolCalls: getActiveToolCalls(),
|
|
32229
33270
|
});
|
|
32230
33271
|
sawToolCalls = true;
|
|
32231
33272
|
isToolCallLine = true;
|
|
@@ -32253,6 +33294,10 @@ class RemoteAgent extends Agent {
|
|
|
32253
33294
|
// console.debug('RemoteAgent chunk:', textChunk);
|
|
32254
33295
|
content += textChunk;
|
|
32255
33296
|
}
|
|
33297
|
+
if (!hasReceivedModelOutput && content.trim().length > 0) {
|
|
33298
|
+
hasReceivedModelOutput = true;
|
|
33299
|
+
preparationToolCalls.length = 0;
|
|
33300
|
+
}
|
|
32256
33301
|
onProgress({
|
|
32257
33302
|
content,
|
|
32258
33303
|
modelName: this.modelName,
|
|
@@ -32261,7 +33306,7 @@ class RemoteAgent extends Agent {
|
|
|
32261
33306
|
rawPromptContent: {},
|
|
32262
33307
|
rawRequest: {},
|
|
32263
33308
|
rawResponse: {},
|
|
32264
|
-
toolCalls,
|
|
33309
|
+
toolCalls: getActiveToolCalls(),
|
|
32265
33310
|
});
|
|
32266
33311
|
}
|
|
32267
33312
|
}
|
|
@@ -32269,6 +33314,10 @@ class RemoteAgent extends Agent {
|
|
|
32269
33314
|
const lastChunk = decoder.decode();
|
|
32270
33315
|
if (lastChunk) {
|
|
32271
33316
|
content += lastChunk;
|
|
33317
|
+
if (!hasReceivedModelOutput && content.trim().length > 0) {
|
|
33318
|
+
hasReceivedModelOutput = true;
|
|
33319
|
+
preparationToolCalls.length = 0;
|
|
33320
|
+
}
|
|
32272
33321
|
onProgress({
|
|
32273
33322
|
content: lastChunk,
|
|
32274
33323
|
modelName: this.modelName,
|
|
@@ -32277,7 +33326,7 @@ class RemoteAgent extends Agent {
|
|
|
32277
33326
|
rawPromptContent: {},
|
|
32278
33327
|
rawRequest: {},
|
|
32279
33328
|
rawResponse: {},
|
|
32280
|
-
toolCalls,
|
|
33329
|
+
toolCalls: getActiveToolCalls(),
|
|
32281
33330
|
});
|
|
32282
33331
|
}
|
|
32283
33332
|
}
|