@promptbook/core 0.104.0-1 → 0.104.0-11
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 +549 -163
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +8 -0
- package/esm/typings/src/_packages/core.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +16 -2
- package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +29 -1
- package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +6 -6
- package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.closed.test.d.ts +1 -0
- package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +3 -3
- package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
- package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
- package/esm/typings/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +13 -0
- package/esm/typings/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +1 -0
- package/esm/typings/src/book-components/Chat/types/ChatMessage.d.ts +9 -13
- package/esm/typings/src/book-components/_common/Dropdown/Dropdown.d.ts +3 -3
- package/esm/typings/src/book-components/_common/HamburgerMenu/HamburgerMenu.d.ts +1 -1
- package/esm/typings/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +56 -0
- package/esm/typings/src/book-components/icons/AboutIcon.d.ts +1 -1
- package/esm/typings/src/book-components/icons/AttachmentIcon.d.ts +1 -1
- package/esm/typings/src/book-components/icons/CameraIcon.d.ts +1 -1
- package/esm/typings/src/book-components/icons/DownloadIcon.d.ts +1 -1
- package/esm/typings/src/book-components/icons/MenuIcon.d.ts +1 -1
- package/esm/typings/src/book-components/icons/SaveIcon.d.ts +1 -1
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +22 -12
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +27 -15
- package/esm/typings/src/commitments/DICTIONARY/DICTIONARY.d.ts +46 -0
- package/esm/typings/src/commitments/index.d.ts +2 -1
- package/esm/typings/src/llm-providers/_common/utils/count-total-usage/countUsage.d.ts +1 -1
- package/esm/typings/src/llm-providers/_multiple/MultipleLlmExecutionTools.d.ts +6 -2
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +6 -1
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +1 -1
- package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +1 -1
- package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +1 -1
- package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -0
- package/esm/typings/src/remote-server/ui/ServerApp.d.ts +1 -1
- package/esm/typings/src/search-engines/SearchEngine.d.ts +9 -0
- package/esm/typings/src/search-engines/SearchResult.d.ts +18 -0
- package/esm/typings/src/search-engines/bing/BingSearchEngine.d.ts +15 -0
- package/esm/typings/src/search-engines/dummy/DummySearchEngine.d.ts +15 -0
- package/esm/typings/src/types/Message.d.ts +49 -0
- package/esm/typings/src/types/ModelRequirements.d.ts +38 -14
- package/esm/typings/src/types/typeAliases.d.ts +23 -1
- package/esm/typings/src/utils/color/utils/colorToDataUrl.d.ts +2 -1
- package/esm/typings/src/utils/environment/$detectRuntimeEnvironment.d.ts +4 -4
- package/esm/typings/src/utils/environment/$isRunningInBrowser.d.ts +1 -1
- package/esm/typings/src/utils/environment/$isRunningInJest.d.ts +1 -1
- package/esm/typings/src/utils/environment/$isRunningInNode.d.ts +1 -1
- package/esm/typings/src/utils/environment/$isRunningInWebWorker.d.ts +1 -1
- package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
- package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
- package/esm/typings/src/utils/random/$randomAgentPersona.d.ts +3 -2
- package/esm/typings/src/utils/random/$randomBase58.d.ts +12 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +555 -168
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/book-2.0/utils/generateGravatarUrl.d.ts +0 -10
package/umd/index.umd.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* @generated
|
|
29
29
|
* @see https://github.com/webgptorg/promptbook
|
|
30
30
|
*/
|
|
31
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.104.0-
|
|
31
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.104.0-11';
|
|
32
32
|
/**
|
|
33
33
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
34
34
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
* Core Promptbook server configuration.
|
|
39
39
|
*
|
|
40
40
|
* This server is also used for auto-federation in the Agents Server.
|
|
41
|
+
*
|
|
42
|
+
* @public exported from `@promptbook/core`
|
|
41
43
|
*/
|
|
42
44
|
const CORE_SERVER = {
|
|
43
45
|
title: 'Promptbook Core',
|
|
@@ -3745,6 +3747,15 @@
|
|
|
3745
3747
|
return promptResult;
|
|
3746
3748
|
};
|
|
3747
3749
|
}
|
|
3750
|
+
if (llmTools.callImageGenerationModel !== undefined) {
|
|
3751
|
+
proxyTools.callImageGenerationModel = async (prompt) => {
|
|
3752
|
+
// console.info('[🚕] callImageGenerationModel through countTotalUsage');
|
|
3753
|
+
const promptResult = await llmTools.callImageGenerationModel(prompt);
|
|
3754
|
+
totalUsage = addUsage(totalUsage, promptResult.usage);
|
|
3755
|
+
spending.next(promptResult.usage);
|
|
3756
|
+
return promptResult;
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3748
3759
|
// <- Note: [🤖]
|
|
3749
3760
|
return proxyTools;
|
|
3750
3761
|
}
|
|
@@ -3753,7 +3764,7 @@
|
|
|
3753
3764
|
* TODO: [🧠] Is there some meaningfull way how to test this util
|
|
3754
3765
|
* TODO: [🧠][🌯] Maybe a way how to hide ability to `get totalUsage`
|
|
3755
3766
|
* > const [llmToolsWithUsage,getUsage] = countTotalUsage(llmTools);
|
|
3756
|
-
* TODO: [👷♂️]
|
|
3767
|
+
* TODO: [👷♂️] Write a comprehensive manual explaining the construction and usage of LLM tools in the Promptbook ecosystem
|
|
3757
3768
|
*/
|
|
3758
3769
|
|
|
3759
3770
|
/**
|
|
@@ -3854,6 +3865,12 @@
|
|
|
3854
3865
|
callEmbeddingModel(prompt) {
|
|
3855
3866
|
return this.callCommonModel(prompt);
|
|
3856
3867
|
}
|
|
3868
|
+
/**
|
|
3869
|
+
* Calls the best available embedding model
|
|
3870
|
+
*/
|
|
3871
|
+
callImageGenerationModel(prompt) {
|
|
3872
|
+
return this.callCommonModel(prompt);
|
|
3873
|
+
}
|
|
3857
3874
|
// <- Note: [🤖]
|
|
3858
3875
|
/**
|
|
3859
3876
|
* Calls the best available model
|
|
@@ -3880,6 +3897,11 @@
|
|
|
3880
3897
|
continue llm;
|
|
3881
3898
|
}
|
|
3882
3899
|
return await llmExecutionTools.callEmbeddingModel(prompt);
|
|
3900
|
+
case 'IMAGE_GENERATION':
|
|
3901
|
+
if (llmExecutionTools.callImageGenerationModel === undefined) {
|
|
3902
|
+
continue llm;
|
|
3903
|
+
}
|
|
3904
|
+
return await llmExecutionTools.callImageGenerationModel(prompt);
|
|
3883
3905
|
// <- case [🤖]:
|
|
3884
3906
|
default:
|
|
3885
3907
|
throw new UnexpectedError(`Unknown model variant "${prompt.modelRequirements.modelVariant}" in ${llmExecutionTools.title}`);
|
|
@@ -6305,8 +6327,9 @@
|
|
|
6305
6327
|
$ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
|
|
6306
6328
|
break variant;
|
|
6307
6329
|
case 'EMBEDDING':
|
|
6330
|
+
case 'IMAGE_GENERATION':
|
|
6308
6331
|
throw new PipelineExecutionError(spaceTrim$1.spaceTrim((block) => `
|
|
6309
|
-
|
|
6332
|
+
${modelRequirements.modelVariant} model can not be used in pipeline
|
|
6310
6333
|
|
|
6311
6334
|
This should be catched during parsing
|
|
6312
6335
|
|
|
@@ -7965,6 +7988,114 @@
|
|
|
7965
7988
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
7966
7989
|
*/
|
|
7967
7990
|
|
|
7991
|
+
/**
|
|
7992
|
+
* DICTIONARY commitment definition
|
|
7993
|
+
*
|
|
7994
|
+
* The DICTIONARY commitment defines specific terms and their meanings that the agent should use correctly
|
|
7995
|
+
* in its reasoning and responses. This ensures consistent terminology usage.
|
|
7996
|
+
*
|
|
7997
|
+
* Key features:
|
|
7998
|
+
* - Multiple DICTIONARY commitments are automatically merged into one
|
|
7999
|
+
* - Content is placed in a dedicated section of the system message
|
|
8000
|
+
* - Terms and definitions are stored in metadata.DICTIONARY for debugging
|
|
8001
|
+
* - Agent should use the defined terms correctly in responses
|
|
8002
|
+
*
|
|
8003
|
+
* Example usage in agent source:
|
|
8004
|
+
*
|
|
8005
|
+
* ```book
|
|
8006
|
+
* Legal Assistant
|
|
8007
|
+
*
|
|
8008
|
+
* PERSONA You are a knowledgeable legal assistant
|
|
8009
|
+
* DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
|
|
8010
|
+
* DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
|
|
8011
|
+
* DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
|
|
8012
|
+
* ```
|
|
8013
|
+
*
|
|
8014
|
+
* @private [🪔] Maybe export the commitments through some package
|
|
8015
|
+
*/
|
|
8016
|
+
class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
|
|
8017
|
+
constructor() {
|
|
8018
|
+
super('DICTIONARY');
|
|
8019
|
+
}
|
|
8020
|
+
/**
|
|
8021
|
+
* Short one-line description of DICTIONARY.
|
|
8022
|
+
*/
|
|
8023
|
+
get description() {
|
|
8024
|
+
return 'Define terms and their meanings for consistent terminology usage.';
|
|
8025
|
+
}
|
|
8026
|
+
/**
|
|
8027
|
+
* Icon for this commitment.
|
|
8028
|
+
*/
|
|
8029
|
+
get icon() {
|
|
8030
|
+
return '📚';
|
|
8031
|
+
}
|
|
8032
|
+
/**
|
|
8033
|
+
* Markdown documentation for DICTIONARY commitment.
|
|
8034
|
+
*/
|
|
8035
|
+
get documentation() {
|
|
8036
|
+
return spaceTrim$1.spaceTrim(`
|
|
8037
|
+
# DICTIONARY
|
|
8038
|
+
|
|
8039
|
+
Defines specific terms and their meanings that the agent should use correctly in reasoning and responses.
|
|
8040
|
+
|
|
8041
|
+
## Key aspects
|
|
8042
|
+
|
|
8043
|
+
- Multiple \`DICTIONARY\` commitments are merged together.
|
|
8044
|
+
- Terms are defined in the format: "Term is definition"
|
|
8045
|
+
- The agent should use these terms consistently in responses.
|
|
8046
|
+
- Definitions help ensure accurate and consistent terminology.
|
|
8047
|
+
|
|
8048
|
+
## Examples
|
|
8049
|
+
|
|
8050
|
+
\`\`\`book
|
|
8051
|
+
Legal Assistant
|
|
8052
|
+
|
|
8053
|
+
PERSONA You are a knowledgeable legal assistant specializing in criminal law
|
|
8054
|
+
DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
|
|
8055
|
+
DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
|
|
8056
|
+
DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
|
|
8057
|
+
\`\`\`
|
|
8058
|
+
|
|
8059
|
+
\`\`\`book
|
|
8060
|
+
Medical Assistant
|
|
8061
|
+
|
|
8062
|
+
PERSONA You are a helpful medical assistant
|
|
8063
|
+
DICTIONARY Hypertension is persistently high blood pressure
|
|
8064
|
+
DICTIONARY Diabetes is a chronic condition that affects how the body processes blood sugar
|
|
8065
|
+
DICTIONARY Vaccine is a biological preparation that provides active immunity to a particular disease
|
|
8066
|
+
\`\`\`
|
|
8067
|
+
`);
|
|
8068
|
+
}
|
|
8069
|
+
applyToAgentModelRequirements(requirements, content) {
|
|
8070
|
+
var _a;
|
|
8071
|
+
const trimmedContent = content.trim();
|
|
8072
|
+
if (!trimmedContent) {
|
|
8073
|
+
return requirements;
|
|
8074
|
+
}
|
|
8075
|
+
// Get existing dictionary entries from metadata
|
|
8076
|
+
const existingDictionary = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
|
|
8077
|
+
// Merge the new dictionary entry with existing entries
|
|
8078
|
+
const mergedDictionary = existingDictionary
|
|
8079
|
+
? `${existingDictionary}\n${trimmedContent}`
|
|
8080
|
+
: trimmedContent;
|
|
8081
|
+
// Store the merged dictionary in metadata for debugging and inspection
|
|
8082
|
+
const updatedMetadata = {
|
|
8083
|
+
...requirements.metadata,
|
|
8084
|
+
DICTIONARY: mergedDictionary,
|
|
8085
|
+
};
|
|
8086
|
+
// Create the dictionary section for the system message
|
|
8087
|
+
// Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
|
|
8088
|
+
const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
|
|
8089
|
+
return {
|
|
8090
|
+
...this.appendToSystemMessage(requirements, dictionarySection),
|
|
8091
|
+
metadata: updatedMetadata,
|
|
8092
|
+
};
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
/**
|
|
8096
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
8097
|
+
*/
|
|
8098
|
+
|
|
7968
8099
|
/**
|
|
7969
8100
|
* FORMAT commitment definition
|
|
7970
8101
|
*
|
|
@@ -10785,6 +10916,7 @@
|
|
|
10785
10916
|
new DeleteCommitmentDefinition('CANCEL'),
|
|
10786
10917
|
new DeleteCommitmentDefinition('DISCARD'),
|
|
10787
10918
|
new DeleteCommitmentDefinition('REMOVE'),
|
|
10919
|
+
new DictionaryCommitmentDefinition(),
|
|
10788
10920
|
new OpenCommitmentDefinition(),
|
|
10789
10921
|
new ClosedCommitmentDefinition(),
|
|
10790
10922
|
new UseBrowserCommitmentDefinition(),
|
|
@@ -10936,17 +11068,64 @@
|
|
|
10936
11068
|
};
|
|
10937
11069
|
}
|
|
10938
11070
|
const lines = agentSource.split('\n');
|
|
10939
|
-
|
|
11071
|
+
let agentName = null;
|
|
11072
|
+
let agentNameLineIndex = -1;
|
|
11073
|
+
// Find the agent name: first non-empty line that is not a commitment and not a horizontal line
|
|
11074
|
+
for (let i = 0; i < lines.length; i++) {
|
|
11075
|
+
const line = lines[i];
|
|
11076
|
+
if (line === undefined) {
|
|
11077
|
+
continue;
|
|
11078
|
+
}
|
|
11079
|
+
const trimmed = line.trim();
|
|
11080
|
+
if (!trimmed) {
|
|
11081
|
+
continue;
|
|
11082
|
+
}
|
|
11083
|
+
const isHorizontal = HORIZONTAL_LINE_PATTERN.test(line);
|
|
11084
|
+
if (isHorizontal) {
|
|
11085
|
+
continue;
|
|
11086
|
+
}
|
|
11087
|
+
let isCommitment = false;
|
|
11088
|
+
for (const definition of COMMITMENT_REGISTRY) {
|
|
11089
|
+
const typeRegex = definition.createTypeRegex();
|
|
11090
|
+
const match = typeRegex.exec(trimmed);
|
|
11091
|
+
if (match && ((_a = match.groups) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
11092
|
+
isCommitment = true;
|
|
11093
|
+
break;
|
|
11094
|
+
}
|
|
11095
|
+
}
|
|
11096
|
+
if (!isCommitment) {
|
|
11097
|
+
agentName = trimmed;
|
|
11098
|
+
agentNameLineIndex = i;
|
|
11099
|
+
break;
|
|
11100
|
+
}
|
|
11101
|
+
}
|
|
10940
11102
|
const commitments = [];
|
|
10941
11103
|
const nonCommitmentLines = [];
|
|
10942
|
-
//
|
|
10943
|
-
|
|
10944
|
-
|
|
11104
|
+
// Add lines before agentName that are horizontal lines (they are non-commitment)
|
|
11105
|
+
for (let i = 0; i < agentNameLineIndex; i++) {
|
|
11106
|
+
const line = lines[i];
|
|
11107
|
+
if (line === undefined) {
|
|
11108
|
+
continue;
|
|
11109
|
+
}
|
|
11110
|
+
const trimmed = line.trim();
|
|
11111
|
+
if (!trimmed) {
|
|
11112
|
+
continue;
|
|
11113
|
+
}
|
|
11114
|
+
const isHorizontal = HORIZONTAL_LINE_PATTERN.test(line);
|
|
11115
|
+
if (isHorizontal) {
|
|
11116
|
+
nonCommitmentLines.push(line);
|
|
11117
|
+
}
|
|
11118
|
+
// Note: Commitments before agentName are not added to nonCommitmentLines
|
|
11119
|
+
}
|
|
11120
|
+
// Add the agent name line to non-commitment lines
|
|
11121
|
+
if (agentNameLineIndex >= 0) {
|
|
11122
|
+
nonCommitmentLines.push(lines[agentNameLineIndex]);
|
|
10945
11123
|
}
|
|
10946
11124
|
// Parse commitments with multiline support
|
|
10947
11125
|
let currentCommitment = null;
|
|
10948
|
-
// Process lines starting from the
|
|
10949
|
-
|
|
11126
|
+
// Process lines starting from after the agent name line
|
|
11127
|
+
const startIndex = agentNameLineIndex >= 0 ? agentNameLineIndex + 1 : 0;
|
|
11128
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
10950
11129
|
const line = lines[i];
|
|
10951
11130
|
if (line === undefined) {
|
|
10952
11131
|
continue;
|
|
@@ -11166,7 +11345,12 @@
|
|
|
11166
11345
|
};
|
|
11167
11346
|
}
|
|
11168
11347
|
// Apply each commitment in order using reduce-like pattern
|
|
11169
|
-
for (
|
|
11348
|
+
for (let i = 0; i < filteredCommitments.length; i++) {
|
|
11349
|
+
const commitment = filteredCommitments[i];
|
|
11350
|
+
// CLOSED commitment should work only if its the last commitment in the book
|
|
11351
|
+
if (commitment.type === 'CLOSED' && i !== filteredCommitments.length - 1) {
|
|
11352
|
+
continue;
|
|
11353
|
+
}
|
|
11170
11354
|
const definition = getCommitmentDefinition(commitment.type);
|
|
11171
11355
|
if (definition) {
|
|
11172
11356
|
try {
|
|
@@ -11261,44 +11445,6 @@
|
|
|
11261
11445
|
* TODO: [🌺] Use some intermediate util splitWords
|
|
11262
11446
|
*/
|
|
11263
11447
|
|
|
11264
|
-
/**
|
|
11265
|
-
* Generates a gravatar URL based on agent name for fallback avatar
|
|
11266
|
-
*
|
|
11267
|
-
* @param agentName The agent name to generate avatar for
|
|
11268
|
-
* @returns Gravatar URL
|
|
11269
|
-
*
|
|
11270
|
-
* @private - [🤹] The fact that profile image is Gravatar is just implementation detail which should be hidden for consumer
|
|
11271
|
-
*/
|
|
11272
|
-
function generateGravatarUrl(agentName) {
|
|
11273
|
-
// Use a default name if none provided
|
|
11274
|
-
const safeName = agentName || 'Anonymous Agent';
|
|
11275
|
-
// Create a simple hash from the name for consistent avatar
|
|
11276
|
-
let hash = 0;
|
|
11277
|
-
for (let i = 0; i < safeName.length; i++) {
|
|
11278
|
-
const char = safeName.charCodeAt(i);
|
|
11279
|
-
hash = (hash << 5) - hash + char;
|
|
11280
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
11281
|
-
}
|
|
11282
|
-
const avatarId = Math.abs(hash).toString();
|
|
11283
|
-
return `https://www.gravatar.com/avatar/${avatarId}?default=robohash&size=200&rating=x`;
|
|
11284
|
-
}
|
|
11285
|
-
|
|
11286
|
-
/**
|
|
11287
|
-
* Generates an image for the agent to use as profile image
|
|
11288
|
-
*
|
|
11289
|
-
* @param agentName The agent name to generate avatar for
|
|
11290
|
-
* @returns The placeholder profile image URL for the agent
|
|
11291
|
-
*
|
|
11292
|
-
* @public exported from `@promptbook/core`
|
|
11293
|
-
*/
|
|
11294
|
-
function generatePlaceholderAgentProfileImageUrl(agentName) {
|
|
11295
|
-
// Note: [🤹] The fact that profile image is Gravatar is just implementation detail which should be hidden for consumer
|
|
11296
|
-
return generateGravatarUrl(agentName);
|
|
11297
|
-
}
|
|
11298
|
-
/**
|
|
11299
|
-
* TODO: [🤹] Figure out best placeholder image generator https://i.pravatar.cc/1000?u=568
|
|
11300
|
-
*/
|
|
11301
|
-
|
|
11302
11448
|
/**
|
|
11303
11449
|
* Creates a Mermaid graph based on the promptbook
|
|
11304
11450
|
*
|
|
@@ -11469,13 +11615,14 @@
|
|
|
11469
11615
|
*
|
|
11470
11616
|
* @public exported from `@promptbook/utils`
|
|
11471
11617
|
*/
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11618
|
+
function $isRunningInBrowser() {
|
|
11619
|
+
try {
|
|
11620
|
+
return typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
11621
|
+
}
|
|
11622
|
+
catch (e) {
|
|
11623
|
+
return false;
|
|
11624
|
+
}
|
|
11477
11625
|
}
|
|
11478
|
-
`);
|
|
11479
11626
|
/**
|
|
11480
11627
|
* TODO: [🎺]
|
|
11481
11628
|
*/
|
|
@@ -11487,13 +11634,15 @@
|
|
|
11487
11634
|
*
|
|
11488
11635
|
* @public exported from `@promptbook/utils`
|
|
11489
11636
|
*/
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11637
|
+
function $isRunningInJest() {
|
|
11638
|
+
var _a;
|
|
11639
|
+
try {
|
|
11640
|
+
return typeof process !== 'undefined' && ((_a = process.env) === null || _a === void 0 ? void 0 : _a.JEST_WORKER_ID) !== undefined;
|
|
11641
|
+
}
|
|
11642
|
+
catch (e) {
|
|
11643
|
+
return false;
|
|
11644
|
+
}
|
|
11495
11645
|
}
|
|
11496
|
-
`);
|
|
11497
11646
|
/**
|
|
11498
11647
|
* TODO: [🎺]
|
|
11499
11648
|
*/
|
|
@@ -11505,13 +11654,14 @@
|
|
|
11505
11654
|
*
|
|
11506
11655
|
* @public exported from `@promptbook/utils`
|
|
11507
11656
|
*/
|
|
11508
|
-
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11657
|
+
function $isRunningInNode() {
|
|
11658
|
+
try {
|
|
11659
|
+
return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
|
|
11660
|
+
}
|
|
11661
|
+
catch (e) {
|
|
11662
|
+
return false;
|
|
11663
|
+
}
|
|
11513
11664
|
}
|
|
11514
|
-
`);
|
|
11515
11665
|
/**
|
|
11516
11666
|
* TODO: [🎺]
|
|
11517
11667
|
*/
|
|
@@ -11523,17 +11673,17 @@
|
|
|
11523
11673
|
*
|
|
11524
11674
|
* @public exported from `@promptbook/utils`
|
|
11525
11675
|
*/
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11676
|
+
function $isRunningInWebWorker() {
|
|
11677
|
+
try {
|
|
11678
|
+
// Note: Check for importScripts which is specific to workers
|
|
11679
|
+
// and not available in the main browser thread
|
|
11680
|
+
return (typeof self !== 'undefined' &&
|
|
11681
|
+
typeof self.importScripts === 'function');
|
|
11682
|
+
}
|
|
11683
|
+
catch (e) {
|
|
11531
11684
|
return false;
|
|
11532
11685
|
}
|
|
11533
|
-
} catch (e) {
|
|
11534
|
-
return false;
|
|
11535
11686
|
}
|
|
11536
|
-
`);
|
|
11537
11687
|
/**
|
|
11538
11688
|
* TODO: [🎺]
|
|
11539
11689
|
*/
|
|
@@ -11746,7 +11896,57 @@
|
|
|
11746
11896
|
}
|
|
11747
11897
|
const meta = {};
|
|
11748
11898
|
const links = [];
|
|
11899
|
+
const capabilities = [];
|
|
11749
11900
|
for (const commitment of parseResult.commitments) {
|
|
11901
|
+
if (commitment.type === 'USE BROWSER') {
|
|
11902
|
+
capabilities.push({
|
|
11903
|
+
type: 'browser',
|
|
11904
|
+
label: 'Browser',
|
|
11905
|
+
iconName: 'Globe',
|
|
11906
|
+
});
|
|
11907
|
+
continue;
|
|
11908
|
+
}
|
|
11909
|
+
if (commitment.type === 'USE SEARCH ENGINE') {
|
|
11910
|
+
capabilities.push({
|
|
11911
|
+
type: 'search-engine',
|
|
11912
|
+
label: 'Search Internet',
|
|
11913
|
+
iconName: 'Search',
|
|
11914
|
+
});
|
|
11915
|
+
continue;
|
|
11916
|
+
}
|
|
11917
|
+
if (commitment.type === 'KNOWLEDGE') {
|
|
11918
|
+
const content = spaceTrim__default["default"](commitment.content).split('\n')[0] || '';
|
|
11919
|
+
let label = content;
|
|
11920
|
+
let iconName = 'Book';
|
|
11921
|
+
if (content.startsWith('http://') || content.startsWith('https://')) {
|
|
11922
|
+
try {
|
|
11923
|
+
const url = new URL(content);
|
|
11924
|
+
if (url.pathname.endsWith('.pdf')) {
|
|
11925
|
+
label = url.pathname.split('/').pop() || 'Document.pdf';
|
|
11926
|
+
iconName = 'FileText';
|
|
11927
|
+
}
|
|
11928
|
+
else {
|
|
11929
|
+
label = url.hostname.replace(/^www\./, '');
|
|
11930
|
+
}
|
|
11931
|
+
}
|
|
11932
|
+
catch (e) {
|
|
11933
|
+
// Invalid URL, treat as text
|
|
11934
|
+
}
|
|
11935
|
+
}
|
|
11936
|
+
else {
|
|
11937
|
+
// Text content - take first few words
|
|
11938
|
+
const words = content.split(/\s+/);
|
|
11939
|
+
if (words.length > 4) {
|
|
11940
|
+
label = words.slice(0, 4).join(' ') + '...';
|
|
11941
|
+
}
|
|
11942
|
+
}
|
|
11943
|
+
capabilities.push({
|
|
11944
|
+
type: 'knowledge',
|
|
11945
|
+
label,
|
|
11946
|
+
iconName,
|
|
11947
|
+
});
|
|
11948
|
+
continue;
|
|
11949
|
+
}
|
|
11750
11950
|
if (commitment.type === 'META LINK') {
|
|
11751
11951
|
const linkValue = spaceTrim__default["default"](commitment.content);
|
|
11752
11952
|
links.push(linkValue);
|
|
@@ -11776,10 +11976,6 @@
|
|
|
11776
11976
|
const metaType = normalizeTo_camelCase(metaTypeRaw);
|
|
11777
11977
|
meta[metaType] = spaceTrim__default["default"](commitment.content.substring(metaTypeRaw.length));
|
|
11778
11978
|
}
|
|
11779
|
-
// Generate gravatar fallback if no meta image specified
|
|
11780
|
-
if (!meta.image) {
|
|
11781
|
-
meta.image = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
|
|
11782
|
-
}
|
|
11783
11979
|
// Generate fullname fallback if no meta fullname specified
|
|
11784
11980
|
if (!meta.fullname) {
|
|
11785
11981
|
meta.fullname = parseResult.agentName || createDefaultAgentName(agentSource);
|
|
@@ -11791,11 +11987,13 @@
|
|
|
11791
11987
|
return {
|
|
11792
11988
|
agentName: normalizeAgentName(parseResult.agentName || createDefaultAgentName(agentSource)),
|
|
11793
11989
|
agentHash,
|
|
11990
|
+
permanentId: meta.id,
|
|
11794
11991
|
personaDescription,
|
|
11795
11992
|
initialMessage,
|
|
11796
11993
|
meta,
|
|
11797
11994
|
links,
|
|
11798
11995
|
parameters,
|
|
11996
|
+
capabilities,
|
|
11799
11997
|
};
|
|
11800
11998
|
}
|
|
11801
11999
|
/**
|
|
@@ -11982,6 +12180,59 @@
|
|
|
11982
12180
|
// <- [🐱🚀] Buttons into genesis book
|
|
11983
12181
|
// <- TODO: [🐱🚀] generateBookBoilerplate and deprecate `DEFAULT_BOOK`
|
|
11984
12182
|
|
|
12183
|
+
/**
|
|
12184
|
+
* Generates an image for the agent to use as profile image
|
|
12185
|
+
*
|
|
12186
|
+
* @param agentId - The permanent ID of the agent
|
|
12187
|
+
* @returns The placeholder profile image URL for the agent
|
|
12188
|
+
*
|
|
12189
|
+
* @public exported from `@promptbook/core`
|
|
12190
|
+
*/
|
|
12191
|
+
function generatePlaceholderAgentProfileImageUrl(agentIdOrName, agentsServerUrl = CORE_SERVER.urls[0]) {
|
|
12192
|
+
if (typeof agentsServerUrl === 'string') {
|
|
12193
|
+
agentsServerUrl = new URL(agentsServerUrl);
|
|
12194
|
+
}
|
|
12195
|
+
return `${agentsServerUrl.href}agents/${agentIdOrName}/images/default-avatar.png`;
|
|
12196
|
+
}
|
|
12197
|
+
/**
|
|
12198
|
+
* TODO: [🤹] Figure out best placeholder image generator https://i.pravatar.cc/1000?u=568
|
|
12199
|
+
*/
|
|
12200
|
+
|
|
12201
|
+
/**
|
|
12202
|
+
* Base58 characters
|
|
12203
|
+
*/
|
|
12204
|
+
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
12205
|
+
/**
|
|
12206
|
+
* Generates random base58 string
|
|
12207
|
+
*
|
|
12208
|
+
* Note: `$` is used to indicate that this function is not a pure function - it is not deterministic
|
|
12209
|
+
* Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
|
|
12210
|
+
*
|
|
12211
|
+
* @param length - length of the string
|
|
12212
|
+
* @returns secure random base58 string
|
|
12213
|
+
*
|
|
12214
|
+
* @private internal helper function
|
|
12215
|
+
*/
|
|
12216
|
+
function $randomBase58(length) {
|
|
12217
|
+
let result = '';
|
|
12218
|
+
while (result.length < length) {
|
|
12219
|
+
// Generate enough bytes to cover the remaining length, plus some extra buffer to reduce calls
|
|
12220
|
+
// But simply generating `length - result.length` is fine for small lengths
|
|
12221
|
+
const bytes = crypto.randomBytes(length - result.length);
|
|
12222
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
12223
|
+
const byte = bytes[i];
|
|
12224
|
+
// 58 * 4 = 232
|
|
12225
|
+
// We discard values >= 232 to avoid modulo bias
|
|
12226
|
+
if (byte < 232) {
|
|
12227
|
+
result += BASE58_ALPHABET[byte % 58];
|
|
12228
|
+
if (result.length === length)
|
|
12229
|
+
break;
|
|
12230
|
+
}
|
|
12231
|
+
}
|
|
12232
|
+
}
|
|
12233
|
+
return result;
|
|
12234
|
+
}
|
|
12235
|
+
|
|
11985
12236
|
// import { getTableName } from '../../../../../apps/agents-server/src/database/getTableName';
|
|
11986
12237
|
// <- TODO: [🐱🚀] Prevent imports from `/apps` -> `/src`
|
|
11987
12238
|
/**
|
|
@@ -12015,19 +12266,20 @@
|
|
|
12015
12266
|
const { isVerbose = exports.DEFAULT_IS_VERBOSE } = this.options || {};
|
|
12016
12267
|
const selectResult = await this.supabaseClient
|
|
12017
12268
|
.from(this.getTableName('Agent'))
|
|
12018
|
-
.select('agentName,agentProfile')
|
|
12269
|
+
.select('agentName,agentProfile,permanentId')
|
|
12270
|
+
.is('deletedAt', null);
|
|
12019
12271
|
if (selectResult.error) {
|
|
12020
12272
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12021
|
-
|
|
12273
|
+
|
|
12022
12274
|
Error fetching agents from Supabase:
|
|
12023
|
-
|
|
12275
|
+
|
|
12024
12276
|
${block(selectResult.error.message)}
|
|
12025
12277
|
`));
|
|
12026
12278
|
}
|
|
12027
12279
|
if (isVerbose) {
|
|
12028
12280
|
console.info(`Found ${selectResult.data.length} agents in directory`);
|
|
12029
12281
|
}
|
|
12030
|
-
return selectResult.data.map(({ agentName, agentProfile }) => {
|
|
12282
|
+
return selectResult.data.map(({ agentName, agentProfile, permanentId }) => {
|
|
12031
12283
|
if (isVerbose && agentProfile.agentName !== agentName) {
|
|
12032
12284
|
console.warn(spaceTrim(`
|
|
12033
12285
|
Agent name mismatch for agent "${agentName}". Using name from database.
|
|
@@ -12039,26 +12291,42 @@
|
|
|
12039
12291
|
return {
|
|
12040
12292
|
...agentProfile,
|
|
12041
12293
|
agentName,
|
|
12294
|
+
permanentId: permanentId || agentProfile.permanentId,
|
|
12042
12295
|
};
|
|
12043
12296
|
});
|
|
12044
12297
|
}
|
|
12045
12298
|
/**
|
|
12046
|
-
*
|
|
12299
|
+
* Retrieves the permanent ID of an agent by its name or permanent ID.
|
|
12047
12300
|
*/
|
|
12048
|
-
async
|
|
12301
|
+
async getAgentPermanentId(agentNameOrPermanentId) {
|
|
12302
|
+
const selectResult = await this.supabaseClient
|
|
12303
|
+
.from(this.getTableName('Agent'))
|
|
12304
|
+
.select('permanentId')
|
|
12305
|
+
.or(`agentName.eq.${agentNameOrPermanentId},permanentId.eq.${agentNameOrPermanentId}`)
|
|
12306
|
+
.single();
|
|
12307
|
+
if (selectResult.error || !selectResult.data) {
|
|
12308
|
+
throw new NotFoundError(`Agent with name not id "${agentNameOrPermanentId}" not found`);
|
|
12309
|
+
}
|
|
12310
|
+
return selectResult.data.permanentId;
|
|
12311
|
+
}
|
|
12312
|
+
/**
|
|
12313
|
+
* Retrieves the source code of an agent by its name or permanent ID.
|
|
12314
|
+
*/
|
|
12315
|
+
async getAgentSource(agentNameOrPermanentId) {
|
|
12049
12316
|
const selectResult = await this.supabaseClient
|
|
12050
12317
|
.from(this.getTableName('Agent'))
|
|
12051
12318
|
.select('agentSource')
|
|
12052
|
-
.
|
|
12319
|
+
.or(`agentName.eq.${agentNameOrPermanentId},permanentId.eq.${agentNameOrPermanentId}`)
|
|
12320
|
+
.is('deletedAt', null);
|
|
12053
12321
|
if (selectResult.data && selectResult.data.length === 0) {
|
|
12054
|
-
throw new NotFoundError(`Agent "${
|
|
12322
|
+
throw new NotFoundError(`Agent "${agentNameOrPermanentId}" not found`);
|
|
12055
12323
|
}
|
|
12056
12324
|
else if (selectResult.data && selectResult.data.length > 1) {
|
|
12057
|
-
throw new UnexpectedError(`More agents with
|
|
12325
|
+
throw new UnexpectedError(`More agents with name or id "${agentNameOrPermanentId}" found`);
|
|
12058
12326
|
}
|
|
12059
12327
|
else if (selectResult.error) {
|
|
12060
12328
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12061
|
-
Error fetching agent "${
|
|
12329
|
+
Error fetching agent "${agentNameOrPermanentId}" from Supabase:
|
|
12062
12330
|
|
|
12063
12331
|
${block(selectResult.error.message)}
|
|
12064
12332
|
`));
|
|
@@ -12071,12 +12339,26 @@
|
|
|
12071
12339
|
* Note: You can set 'PARENT' in the agent source to inherit from another agent in the collection.
|
|
12072
12340
|
*/
|
|
12073
12341
|
async createAgent(agentSource) {
|
|
12074
|
-
|
|
12342
|
+
let agentProfile = parseAgentSource(agentSource);
|
|
12075
12343
|
// <- TODO: [🕛]
|
|
12344
|
+
// 1. Extract permanentId from the source if present
|
|
12345
|
+
let { permanentId } = agentProfile;
|
|
12346
|
+
// 2. Remove META ID from the source
|
|
12347
|
+
const lines = agentSource.split('\n');
|
|
12348
|
+
const strippedLines = lines.filter((line) => !line.trim().startsWith('META ID '));
|
|
12349
|
+
if (lines.length !== strippedLines.length) {
|
|
12350
|
+
agentSource = strippedLines.join('\n');
|
|
12351
|
+
// 3. Re-parse the agent source to get the correct hash and other info
|
|
12352
|
+
agentProfile = parseAgentSource(agentSource);
|
|
12353
|
+
}
|
|
12076
12354
|
const { agentName, agentHash } = agentProfile;
|
|
12355
|
+
if (!permanentId) {
|
|
12356
|
+
permanentId = $randomBase58(14);
|
|
12357
|
+
}
|
|
12077
12358
|
const insertAgentResult = await this.supabaseClient.from(this.getTableName('Agent')).insert({
|
|
12078
12359
|
agentName,
|
|
12079
12360
|
agentHash,
|
|
12361
|
+
permanentId,
|
|
12080
12362
|
agentProfile,
|
|
12081
12363
|
createdAt: new Date().toISOString(),
|
|
12082
12364
|
updatedAt: null,
|
|
@@ -12094,27 +12376,29 @@
|
|
|
12094
12376
|
await this.supabaseClient.from(this.getTableName('AgentHistory')).insert({
|
|
12095
12377
|
createdAt: new Date().toISOString(),
|
|
12096
12378
|
agentName,
|
|
12379
|
+
permanentId,
|
|
12097
12380
|
agentHash,
|
|
12098
12381
|
previousAgentHash: null,
|
|
12099
12382
|
agentSource,
|
|
12100
12383
|
promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
12101
12384
|
});
|
|
12102
12385
|
// <- TODO: [🧠] What to do with `insertAgentHistoryResult.error`, ignore? wait?
|
|
12103
|
-
return agentProfile;
|
|
12386
|
+
return { ...agentProfile, permanentId };
|
|
12104
12387
|
}
|
|
12105
12388
|
/**
|
|
12106
12389
|
* Updates an existing agent in the collection
|
|
12107
12390
|
*/
|
|
12108
|
-
async updateAgentSource(
|
|
12391
|
+
async updateAgentSource(permanentId, agentSource) {
|
|
12392
|
+
console.log('!!! updateAgentSource', { permanentId });
|
|
12109
12393
|
const selectPreviousAgentResult = await this.supabaseClient
|
|
12110
12394
|
.from(this.getTableName('Agent'))
|
|
12111
|
-
.select('agentHash,agentName')
|
|
12112
|
-
.eq('
|
|
12395
|
+
.select('agentHash,agentName,permanentId')
|
|
12396
|
+
.eq('permanentId', permanentId)
|
|
12113
12397
|
.single();
|
|
12114
12398
|
if (selectPreviousAgentResult.error) {
|
|
12115
12399
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12116
12400
|
|
|
12117
|
-
Error fetching agent "${
|
|
12401
|
+
Error fetching agent "${permanentId}" from Supabase:
|
|
12118
12402
|
|
|
12119
12403
|
${block(selectPreviousAgentResult.error.message)}
|
|
12120
12404
|
`));
|
|
@@ -12122,26 +12406,48 @@
|
|
|
12122
12406
|
}
|
|
12123
12407
|
selectPreviousAgentResult.data.agentName;
|
|
12124
12408
|
const previousAgentHash = selectPreviousAgentResult.data.agentHash;
|
|
12125
|
-
const
|
|
12409
|
+
const previousPermanentId = selectPreviousAgentResult.data.permanentId;
|
|
12410
|
+
let agentProfile = parseAgentSource(agentSource);
|
|
12126
12411
|
// <- TODO: [🕛]
|
|
12127
|
-
|
|
12412
|
+
// 1. Extract permanentId from the source if present
|
|
12413
|
+
let { permanentId: newPermanentId } = agentProfile;
|
|
12414
|
+
// 2. Remove META ID from the source
|
|
12415
|
+
const lines = agentSource.split('\n');
|
|
12416
|
+
const strippedLines = lines.filter((line) => !line.trim().startsWith('META ID '));
|
|
12417
|
+
if (lines.length !== strippedLines.length) {
|
|
12418
|
+
agentSource = strippedLines.join('\n');
|
|
12419
|
+
// 3. Re-parse the agent source to get the correct hash and other info
|
|
12420
|
+
agentProfile = parseAgentSource(agentSource);
|
|
12421
|
+
}
|
|
12422
|
+
const { agentHash, agentName } = agentProfile;
|
|
12423
|
+
if (!newPermanentId && previousPermanentId) {
|
|
12424
|
+
newPermanentId = previousPermanentId;
|
|
12425
|
+
}
|
|
12426
|
+
if (!newPermanentId) {
|
|
12427
|
+
newPermanentId = $randomBase58(14);
|
|
12428
|
+
}
|
|
12429
|
+
if (newPermanentId !== permanentId) {
|
|
12430
|
+
// [🧠] Should be allowed to change permanentId?
|
|
12431
|
+
throw new UnexpectedError(`Permanent ID mismatch: "${permanentId}" (argument) !== "${newPermanentId}" (in source)`);
|
|
12432
|
+
}
|
|
12128
12433
|
const updateAgentResult = await this.supabaseClient
|
|
12129
12434
|
.from(this.getTableName('Agent'))
|
|
12130
12435
|
.update({
|
|
12131
12436
|
// TODO: [🐱🚀] Compare not update> agentName: agentProfile.agentName || '[🐱🚀]' /* <- TODO: [🐱🚀] Remove */,
|
|
12437
|
+
permanentId,
|
|
12132
12438
|
agentProfile,
|
|
12133
12439
|
updatedAt: new Date().toISOString(),
|
|
12134
12440
|
agentHash: agentProfile.agentHash,
|
|
12135
12441
|
agentSource,
|
|
12136
12442
|
promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
12137
12443
|
})
|
|
12138
|
-
.eq('
|
|
12444
|
+
.eq('permanentId', permanentId);
|
|
12139
12445
|
// console.log('[🐱🚀] updateAgent', updateResult);
|
|
12140
12446
|
// console.log('[🐱🚀] old', oldAgentSource);
|
|
12141
12447
|
// console.log('[🐱🚀] new', newAgentSource);
|
|
12142
12448
|
if (updateAgentResult.error) {
|
|
12143
12449
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12144
|
-
Error updating agent "${
|
|
12450
|
+
Error updating agent "${permanentId}" in Supabase:
|
|
12145
12451
|
|
|
12146
12452
|
${block(updateAgentResult.error.message)}
|
|
12147
12453
|
`));
|
|
@@ -12149,6 +12455,7 @@
|
|
|
12149
12455
|
await this.supabaseClient.from(this.getTableName('AgentHistory')).insert({
|
|
12150
12456
|
createdAt: new Date().toISOString(),
|
|
12151
12457
|
agentName,
|
|
12458
|
+
permanentId,
|
|
12152
12459
|
agentHash,
|
|
12153
12460
|
previousAgentHash,
|
|
12154
12461
|
agentSource,
|
|
@@ -12156,101 +12463,119 @@
|
|
|
12156
12463
|
});
|
|
12157
12464
|
// <- TODO: [🧠] What to do with `insertAgentHistoryResult.error`, ignore? wait?
|
|
12158
12465
|
}
|
|
12159
|
-
// TODO: [🐱🚀] public async getAgentSourceSubject(
|
|
12466
|
+
// TODO: [🐱🚀] public async getAgentSourceSubject(permanentId: string_agent_permanent_id): Promise<BehaviorSubject<string_book>>
|
|
12160
12467
|
// Use Supabase realtime logic
|
|
12161
12468
|
/**
|
|
12162
|
-
*
|
|
12469
|
+
* List agents that are soft deleted (deletedAt IS NOT NULL)
|
|
12163
12470
|
*/
|
|
12164
|
-
async
|
|
12165
|
-
const
|
|
12471
|
+
async listDeletedAgents() {
|
|
12472
|
+
const { isVerbose = exports.DEFAULT_IS_VERBOSE } = this.options || {};
|
|
12473
|
+
const selectResult = await this.supabaseClient
|
|
12166
12474
|
.from(this.getTableName('Agent'))
|
|
12167
|
-
.
|
|
12168
|
-
.
|
|
12169
|
-
if (
|
|
12475
|
+
.select('agentName,agentProfile,permanentId')
|
|
12476
|
+
.not('deletedAt', 'is', null);
|
|
12477
|
+
if (selectResult.error) {
|
|
12170
12478
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12479
|
+
Error fetching deleted agents from Supabase:
|
|
12480
|
+
|
|
12481
|
+
${block(selectResult.error.message)}
|
|
12482
|
+
`));
|
|
12483
|
+
}
|
|
12484
|
+
if (isVerbose) {
|
|
12485
|
+
console.info(`Found ${selectResult.data.length} deleted agents in directory`);
|
|
12175
12486
|
}
|
|
12487
|
+
return selectResult.data.map(({ agentName, agentProfile, permanentId }) => {
|
|
12488
|
+
if (isVerbose && agentProfile.agentName !== agentName) {
|
|
12489
|
+
console.warn(spaceTrim(`
|
|
12490
|
+
Agent name mismatch for agent "${agentName}". Using name from database.
|
|
12491
|
+
|
|
12492
|
+
agentName: "${agentName}"
|
|
12493
|
+
agentProfile.agentName: "${agentProfile.agentName}"
|
|
12494
|
+
`));
|
|
12495
|
+
}
|
|
12496
|
+
return {
|
|
12497
|
+
...agentProfile,
|
|
12498
|
+
agentName,
|
|
12499
|
+
permanentId: permanentId || agentProfile.permanentId,
|
|
12500
|
+
};
|
|
12501
|
+
});
|
|
12176
12502
|
}
|
|
12177
12503
|
/**
|
|
12178
12504
|
* List history of an agent
|
|
12179
12505
|
*/
|
|
12180
|
-
async listAgentHistory(
|
|
12506
|
+
async listAgentHistory(permanentId) {
|
|
12181
12507
|
const result = await this.supabaseClient
|
|
12182
12508
|
.from(this.getTableName('AgentHistory'))
|
|
12183
12509
|
.select('id, createdAt, agentHash, promptbookEngineVersion')
|
|
12184
|
-
.eq('
|
|
12510
|
+
.eq('permanentId', permanentId)
|
|
12185
12511
|
.order('createdAt', { ascending: false });
|
|
12186
12512
|
if (result.error) {
|
|
12187
12513
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12188
|
-
Error listing history for agent "${
|
|
12189
|
-
|
|
12514
|
+
Error listing history for agent "${permanentId}" from Supabase:
|
|
12515
|
+
|
|
12190
12516
|
${block(result.error.message)}
|
|
12191
12517
|
`));
|
|
12192
12518
|
}
|
|
12193
12519
|
return result.data;
|
|
12194
12520
|
}
|
|
12195
12521
|
/**
|
|
12196
|
-
*
|
|
12522
|
+
* Restore a soft-deleted agent by setting deletedAt to NULL
|
|
12197
12523
|
*/
|
|
12198
|
-
async
|
|
12199
|
-
const
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
${block(historyNamesResult.error.message)}
|
|
12206
|
-
`));
|
|
12207
|
-
}
|
|
12208
|
-
if (currentNamesResult.error) {
|
|
12524
|
+
async restoreAgent(permanentId) {
|
|
12525
|
+
const updateResult = await this.supabaseClient
|
|
12526
|
+
.from(this.getTableName('Agent'))
|
|
12527
|
+
.update({ deletedAt: null })
|
|
12528
|
+
.eq('permanentId', permanentId)
|
|
12529
|
+
.not('deletedAt', 'is', null);
|
|
12530
|
+
if (updateResult.error) {
|
|
12209
12531
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12210
|
-
Error
|
|
12211
|
-
|
|
12212
|
-
${block(
|
|
12532
|
+
Error restoring agent "${permanentId}" from Supabase:
|
|
12533
|
+
|
|
12534
|
+
${block(updateResult.error.message)}
|
|
12213
12535
|
`));
|
|
12214
12536
|
}
|
|
12215
|
-
const currentNames = new Set(currentNamesResult.data.map((d) => d.agentName));
|
|
12216
|
-
const deletedNames = new Set();
|
|
12217
|
-
for (const { agentName } of historyNamesResult.data) {
|
|
12218
|
-
if (!currentNames.has(agentName)) {
|
|
12219
|
-
deletedNames.add(agentName);
|
|
12220
|
-
}
|
|
12221
|
-
}
|
|
12222
|
-
return Array.from(deletedNames);
|
|
12223
12537
|
}
|
|
12224
12538
|
/**
|
|
12225
|
-
* Restore an agent from history
|
|
12539
|
+
* Restore an agent from a specific history entry
|
|
12540
|
+
*
|
|
12541
|
+
* This will update the current agent with the source from the history entry
|
|
12226
12542
|
*/
|
|
12227
|
-
async
|
|
12543
|
+
async restoreAgentFromHistory(historyId) {
|
|
12544
|
+
// First, get the history entry
|
|
12228
12545
|
const historyResult = await this.supabaseClient
|
|
12229
12546
|
.from(this.getTableName('AgentHistory'))
|
|
12230
|
-
.select('
|
|
12547
|
+
.select('permanentId, agentSource')
|
|
12231
12548
|
.eq('id', historyId)
|
|
12232
12549
|
.single();
|
|
12233
12550
|
if (historyResult.error) {
|
|
12234
12551
|
throw new DatabaseError(spaceTrim((block) => `
|
|
12235
|
-
Error fetching
|
|
12236
|
-
|
|
12552
|
+
Error fetching history entry with id "${historyId}" from Supabase:
|
|
12553
|
+
|
|
12237
12554
|
${block(historyResult.error.message)}
|
|
12238
12555
|
`));
|
|
12239
12556
|
}
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
const agentResult = await this.supabaseClient
|
|
12243
|
-
.from(this.getTableName('Agent'))
|
|
12244
|
-
.select('id')
|
|
12245
|
-
.eq('agentName', agentName)
|
|
12246
|
-
.single();
|
|
12247
|
-
if (agentResult.data) {
|
|
12248
|
-
// Update
|
|
12249
|
-
await this.updateAgentSource(agentName, agentSource);
|
|
12557
|
+
if (!historyResult.data) {
|
|
12558
|
+
throw new NotFoundError(`History entry with id "${historyId}" not found`);
|
|
12250
12559
|
}
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12560
|
+
const { permanentId, agentSource } = historyResult.data;
|
|
12561
|
+
// Update the agent with the source from the history entry
|
|
12562
|
+
await this.updateAgentSource(permanentId, agentSource);
|
|
12563
|
+
}
|
|
12564
|
+
/**
|
|
12565
|
+
* Soft delete an agent by setting deletedAt to current timestamp
|
|
12566
|
+
*/
|
|
12567
|
+
async deleteAgent(permanentId) {
|
|
12568
|
+
const updateResult = await this.supabaseClient
|
|
12569
|
+
.from(this.getTableName('Agent'))
|
|
12570
|
+
.update({ deletedAt: new Date().toISOString() })
|
|
12571
|
+
.eq('permanentId', permanentId)
|
|
12572
|
+
.is('deletedAt', null);
|
|
12573
|
+
if (updateResult.error) {
|
|
12574
|
+
throw new DatabaseError(spaceTrim((block) => `
|
|
12575
|
+
Error deleting agent "${permanentId}" from Supabase:
|
|
12576
|
+
|
|
12577
|
+
${block(updateResult.error.message)}
|
|
12578
|
+
`));
|
|
12254
12579
|
}
|
|
12255
12580
|
}
|
|
12256
12581
|
/**
|
|
@@ -12262,6 +12587,7 @@
|
|
|
12262
12587
|
getTableName(tableName) {
|
|
12263
12588
|
const { tablePrefix = '' } = this.options || {};
|
|
12264
12589
|
return `${tablePrefix}${tableName}`;
|
|
12590
|
+
// <- TODO: [🏧] DRY
|
|
12265
12591
|
}
|
|
12266
12592
|
}
|
|
12267
12593
|
/**
|
|
@@ -13940,11 +14266,7 @@
|
|
|
13940
14266
|
// TODO: [🚜] DRY
|
|
13941
14267
|
if ($taskJson.modelRequirements[command.key] !== undefined) {
|
|
13942
14268
|
if ($taskJson.modelRequirements[command.key] === command.value) {
|
|
13943
|
-
console.warn(`Multiple commands \`MODEL ${{
|
|
13944
|
-
modelName: 'NAME',
|
|
13945
|
-
modelVariant: 'VARIANT',
|
|
13946
|
-
maxTokens: '???',
|
|
13947
|
-
}[command.key]} ${command.value}\` in the task "${$taskJson.title || $taskJson.name}"`);
|
|
14269
|
+
console.warn(`Multiple commands \`MODEL ${command.key} ${command.value}\` in the task "${$taskJson.title || $taskJson.name}"`);
|
|
13948
14270
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
13949
14271
|
}
|
|
13950
14272
|
else {
|
|
@@ -16468,7 +16790,7 @@
|
|
|
16468
16790
|
${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
|
|
16469
16791
|
${morePieces.join('; ')}
|
|
16470
16792
|
`);
|
|
16471
|
-
if ($isRunningInNode) {
|
|
16793
|
+
if ($isRunningInNode()) {
|
|
16472
16794
|
if (isInstalled && isFullyConfigured) {
|
|
16473
16795
|
providerMessage = colors__default["default"].green(providerMessage);
|
|
16474
16796
|
}
|
|
@@ -16673,6 +16995,9 @@
|
|
|
16673
16995
|
case 'EMBEDDING':
|
|
16674
16996
|
promptResult = await llmTools.callEmbeddingModel(prompt);
|
|
16675
16997
|
break variant;
|
|
16998
|
+
case 'IMAGE_GENERATION':
|
|
16999
|
+
promptResult = await llmTools.callImageGenerationModel(prompt);
|
|
17000
|
+
break variant;
|
|
16676
17001
|
// <- case [🤖]:
|
|
16677
17002
|
default:
|
|
16678
17003
|
throw new PipelineExecutionError(`Unknown model variant "${prompt.modelRequirements.modelVariant}"`);
|
|
@@ -16709,12 +17034,13 @@
|
|
|
16709
17034
|
}
|
|
16710
17035
|
}
|
|
16711
17036
|
catch (error) {
|
|
17037
|
+
assertsError(error);
|
|
16712
17038
|
// If validation throws an unexpected error, don't cache
|
|
16713
17039
|
shouldCache = false;
|
|
16714
17040
|
if (isVerbose) {
|
|
16715
17041
|
console.info('Not caching result due to validation error for key:', key, {
|
|
16716
17042
|
content: promptResult.content,
|
|
16717
|
-
validationError:
|
|
17043
|
+
validationError: serializeError(error),
|
|
16718
17044
|
});
|
|
16719
17045
|
}
|
|
16720
17046
|
}
|
|
@@ -16760,6 +17086,11 @@
|
|
|
16760
17086
|
return /* not await */ callCommonModel(prompt);
|
|
16761
17087
|
};
|
|
16762
17088
|
}
|
|
17089
|
+
if (llmTools.callImageGenerationModel !== undefined) {
|
|
17090
|
+
proxyTools.callImageGenerationModel = async (prompt) => {
|
|
17091
|
+
return /* not await */ callCommonModel(prompt);
|
|
17092
|
+
};
|
|
17093
|
+
}
|
|
16763
17094
|
// <- Note: [🤖]
|
|
16764
17095
|
return proxyTools;
|
|
16765
17096
|
}
|
|
@@ -16798,6 +17129,11 @@
|
|
|
16798
17129
|
throw new LimitReachedError('Cannot call `callEmbeddingModel` because you are not allowed to spend any cost');
|
|
16799
17130
|
};
|
|
16800
17131
|
}
|
|
17132
|
+
if (proxyTools.callImageGenerationModel !== undefined) {
|
|
17133
|
+
proxyTools.callImageGenerationModel = async (prompt) => {
|
|
17134
|
+
throw new LimitReachedError('Cannot call `callImageGenerationModel` because you are not allowed to spend any cost');
|
|
17135
|
+
};
|
|
17136
|
+
}
|
|
16801
17137
|
// <- Note: [🤖]
|
|
16802
17138
|
return proxyTools;
|
|
16803
17139
|
}
|
|
@@ -17869,7 +18205,7 @@
|
|
|
17869
18205
|
let threadMessages = [];
|
|
17870
18206
|
if ('thread' in prompt && Array.isArray(prompt.thread)) {
|
|
17871
18207
|
threadMessages = prompt.thread.map((msg) => ({
|
|
17872
|
-
role: msg.
|
|
18208
|
+
role: msg.sender === 'assistant' ? 'assistant' : 'user',
|
|
17873
18209
|
content: msg.content,
|
|
17874
18210
|
}));
|
|
17875
18211
|
}
|
|
@@ -18282,13 +18618,14 @@
|
|
|
18282
18618
|
const modelName = currentModelRequirements.modelName || this.getDefaultImageGenerationModel().modelName;
|
|
18283
18619
|
const modelSettings = {
|
|
18284
18620
|
model: modelName,
|
|
18285
|
-
|
|
18286
|
-
|
|
18287
|
-
|
|
18621
|
+
size: currentModelRequirements.size,
|
|
18622
|
+
quality: currentModelRequirements.quality,
|
|
18623
|
+
style: currentModelRequirements.style,
|
|
18288
18624
|
};
|
|
18289
18625
|
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
18290
18626
|
const rawRequest = {
|
|
18291
18627
|
...modelSettings,
|
|
18628
|
+
size: modelSettings.size || '1024x1024',
|
|
18292
18629
|
prompt: rawPromptContent,
|
|
18293
18630
|
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
18294
18631
|
response_format: 'url', // TODO: [🧠] Maybe allow b64_json
|
|
@@ -19307,6 +19644,11 @@
|
|
|
19307
19644
|
* Links found in the agent source
|
|
19308
19645
|
*/
|
|
19309
19646
|
this.links = [];
|
|
19647
|
+
/**
|
|
19648
|
+
* Capabilities of the agent
|
|
19649
|
+
* This is parsed from commitments like USE BROWSER, USE SEARCH ENGINE, KNOWLEDGE, etc.
|
|
19650
|
+
*/
|
|
19651
|
+
this.capabilities = [];
|
|
19310
19652
|
/**
|
|
19311
19653
|
* Metadata like image or color
|
|
19312
19654
|
*/
|
|
@@ -19316,11 +19658,12 @@
|
|
|
19316
19658
|
this.agentSource = agentSource;
|
|
19317
19659
|
this.agentSource.subscribe((source) => {
|
|
19318
19660
|
this.updateAgentSource(source);
|
|
19319
|
-
const { agentName, personaDescription, initialMessage, links, meta } = parseAgentSource(source);
|
|
19661
|
+
const { agentName, personaDescription, initialMessage, links, meta, capabilities } = parseAgentSource(source);
|
|
19320
19662
|
this._agentName = agentName;
|
|
19321
19663
|
this.personaDescription = personaDescription;
|
|
19322
19664
|
this.initialMessage = initialMessage;
|
|
19323
19665
|
this.links = links;
|
|
19666
|
+
this.capabilities = capabilities;
|
|
19324
19667
|
this.meta = { ...this.meta, ...meta };
|
|
19325
19668
|
});
|
|
19326
19669
|
}
|
|
@@ -19394,9 +19737,52 @@
|
|
|
19394
19737
|
${block(result.content)}
|
|
19395
19738
|
|
|
19396
19739
|
`);
|
|
19740
|
+
// Extract knowledge
|
|
19741
|
+
let knowledgeBlock = '';
|
|
19742
|
+
try {
|
|
19743
|
+
const extractionPrompt = {
|
|
19744
|
+
title: 'Knowledge Extraction',
|
|
19745
|
+
modelRequirements: {
|
|
19746
|
+
modelVariant: 'CHAT',
|
|
19747
|
+
},
|
|
19748
|
+
content: spaceTrim__default["default"]((block) => `
|
|
19749
|
+
You are an AI agent that is learning from a conversation.
|
|
19750
|
+
|
|
19751
|
+
Here is the conversation so far:
|
|
19752
|
+
|
|
19753
|
+
User: ${block(prompt.content)}
|
|
19754
|
+
Agent: ${block(result.content)}
|
|
19755
|
+
|
|
19756
|
+
Extract any new knowledge, facts, or important information that should be remembered for future interactions.
|
|
19757
|
+
Format the output as a list of KNOWLEDGE blocks.
|
|
19758
|
+
If there is no new knowledge, return nothing.
|
|
19759
|
+
|
|
19760
|
+
Example output:
|
|
19761
|
+
KNOWLEDGE The user's name is Alice.
|
|
19762
|
+
KNOWLEDGE The project deadline is next Friday.
|
|
19763
|
+
`),
|
|
19764
|
+
pipelineUrl: 'https://github.com/webgptorg/promptbook/blob/main/prompts/knowledge-extraction.ptbk.md',
|
|
19765
|
+
parameters: {},
|
|
19766
|
+
};
|
|
19767
|
+
if (this.options.llmTools.callChatModel) {
|
|
19768
|
+
const extractionResult = await this.options.llmTools.callChatModel(extractionPrompt);
|
|
19769
|
+
const extractedContent = extractionResult.content;
|
|
19770
|
+
if (extractedContent.includes('KNOWLEDGE')) {
|
|
19771
|
+
knowledgeBlock = '\n\n' + spaceTrim__default["default"](extractedContent);
|
|
19772
|
+
}
|
|
19773
|
+
}
|
|
19774
|
+
else {
|
|
19775
|
+
// TODO: [🧠] Fallback to callChatModelStream if callChatModel is not available
|
|
19776
|
+
}
|
|
19777
|
+
}
|
|
19778
|
+
catch (error) {
|
|
19779
|
+
if (this.options.isVerbose) {
|
|
19780
|
+
console.warn('Failed to extract knowledge', error);
|
|
19781
|
+
}
|
|
19782
|
+
}
|
|
19397
19783
|
// Append to the current source
|
|
19398
19784
|
const currentSource = this.agentSource.value;
|
|
19399
|
-
const newSource = padBook(validateBook(spaceTrim__default["default"](currentSource) + '\n\n' + learningExample));
|
|
19785
|
+
const newSource = padBook(validateBook(spaceTrim__default["default"](currentSource) + '\n\n' + learningExample + knowledgeBlock));
|
|
19400
19786
|
// Update the source (which will trigger the subscription and update the underlying tools)
|
|
19401
19787
|
this.agentSource.next(newSource);
|
|
19402
19788
|
return result;
|
|
@@ -20848,7 +21234,7 @@
|
|
|
20848
21234
|
'Serious and focused AI consultant.',
|
|
20849
21235
|
];
|
|
20850
21236
|
/**
|
|
20851
|
-
*
|
|
21237
|
+
* Generates a random agent persona description.
|
|
20852
21238
|
*
|
|
20853
21239
|
* @private internal helper function
|
|
20854
21240
|
*/
|
|
@@ -21187,6 +21573,7 @@
|
|
|
21187
21573
|
exports.BoilerplateFormfactorDefinition = BoilerplateFormfactorDefinition;
|
|
21188
21574
|
exports.CLAIM = CLAIM;
|
|
21189
21575
|
exports.CLI_APP_ID = CLI_APP_ID;
|
|
21576
|
+
exports.CORE_SERVER = CORE_SERVER;
|
|
21190
21577
|
exports.CallbackInterfaceTools = CallbackInterfaceTools;
|
|
21191
21578
|
exports.ChatbotFormfactorDefinition = ChatbotFormfactorDefinition;
|
|
21192
21579
|
exports.CollectionError = CollectionError;
|