@promptbook/browser 0.103.0-47 → 0.103.0-48

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.
Files changed (31) hide show
  1. package/esm/index.es.js +1935 -1831
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/src/_packages/core.index.d.ts +6 -0
  4. package/esm/typings/src/_packages/types.index.d.ts +2 -0
  5. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +7 -3
  6. package/esm/typings/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +2 -1
  7. package/esm/typings/src/book-2.0/agent-source/computeAgentHash.d.ts +8 -0
  8. package/esm/typings/src/book-2.0/agent-source/computeAgentHash.test.d.ts +1 -0
  9. package/esm/typings/src/book-2.0/agent-source/createDefaultAgentName.d.ts +8 -0
  10. package/esm/typings/src/book-2.0/agent-source/normalizeAgentName.d.ts +9 -0
  11. package/esm/typings/src/book-2.0/agent-source/normalizeAgentName.test.d.ts +1 -0
  12. package/esm/typings/src/book-2.0/agent-source/parseAgentSourceWithCommitments.d.ts +1 -1
  13. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +57 -32
  14. package/esm/typings/src/llm-providers/_common/utils/assertUniqueModels.d.ts +12 -0
  15. package/esm/typings/src/llm-providers/agent/Agent.d.ts +7 -2
  16. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +4 -0
  17. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +2 -2
  18. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +24 -3
  19. package/esm/typings/src/llm-providers/openai/openai-models.test.d.ts +4 -0
  20. package/esm/typings/src/remote-server/startAgentServer.d.ts +1 -1
  21. package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -2
  22. package/esm/typings/src/transpilers/openai-sdk/register.d.ts +1 -1
  23. package/esm/typings/src/types/typeAliases.d.ts +6 -0
  24. package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +2 -0
  25. package/esm/typings/src/utils/normalization/normalizeTo_PascalCase.d.ts +3 -0
  26. package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +2 -0
  27. package/esm/typings/src/utils/normalization/titleToName.d.ts +2 -0
  28. package/esm/typings/src/version.d.ts +1 -1
  29. package/package.json +3 -2
  30. package/umd/index.umd.js +1893 -1790
  31. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import spaceTrim$1, { spaceTrim } from 'spacetrim';
2
2
  import { randomBytes } from 'crypto';
3
+ import { SHA256 } from 'crypto-js';
4
+ import hexEncoder from 'crypto-js/enc-hex';
3
5
  import { basename } from 'path';
4
6
  import { Registration } from 'destroyable';
5
7
 
@@ -17,7 +19,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
17
19
  * @generated
18
20
  * @see https://github.com/webgptorg/promptbook
19
21
  */
20
- const PROMPTBOOK_ENGINE_VERSION = '0.103.0-47';
22
+ const PROMPTBOOK_ENGINE_VERSION = '0.103.0-48';
21
23
  /**
22
24
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
23
25
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1900,6 +1902,8 @@ function getSessionStorage() {
1900
1902
  /**
1901
1903
  * Normalizes a given text to camelCase format.
1902
1904
  *
1905
+ * Note: [🔂] This function is idempotent.
1906
+ *
1903
1907
  * @param text The text to be normalized.
1904
1908
  * @param _isFirstLetterCapital Whether the first letter should be capitalized.
1905
1909
  * @returns The camelCase formatted string.
@@ -1988,564 +1992,690 @@ function generatePlaceholderAgentProfileImageUrl(agentName) {
1988
1992
  */
1989
1993
 
1990
1994
  /**
1991
- * Generates a regex pattern to match a specific commitment
1992
- *
1993
- * Note: It always creates new Regex object
1994
- * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
1995
- *
1996
- * @private - TODO: [🧠] Maybe should be public?
1997
- */
1998
- function createCommitmentRegex(commitment) {
1999
- const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2000
- const keywordPattern = escapedCommitment.split(/\s+/).join('\\s+');
2001
- const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
2002
- return regex;
2003
- }
2004
- /**
2005
- * Generates a regex pattern to match a specific commitment type
2006
- *
2007
- * Note: It just matches the type part of the commitment
2008
- * Note: It always creates new Regex object
2009
- * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
1995
+ * Computes SHA-256 hash of the agent source
2010
1996
  *
2011
- * @private
1997
+ * @public exported from `@promptbook/core`
2012
1998
  */
2013
- function createCommitmentTypeRegex(commitment) {
2014
- const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2015
- const keywordPattern = escapedCommitment.split(/\s+/).join('\\s+');
2016
- const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
2017
- return regex;
1999
+ function computeAgentHash(agentSource) {
2000
+ return SHA256(hexEncoder.parse(agentSource /* <- TODO: !!!!! spaceTrim */)).toString( /* hex */);
2018
2001
  }
2019
2002
 
2020
2003
  /**
2021
- * Base implementation of CommitmentDefinition that provides common functionality
2022
- * Most commitments can extend this class and only override the applyToAgentModelRequirements method
2004
+ * Tests if given string is valid file path.
2023
2005
  *
2024
- * @private
2006
+ * Note: This does not check if the file exists only if the path is valid
2007
+ * @public exported from `@promptbook/utils`
2025
2008
  */
2026
- class BaseCommitmentDefinition {
2027
- constructor(type) {
2028
- this.type = type;
2029
- }
2030
- /**
2031
- * Creates a regex pattern to match this commitment in agent source
2032
- * Uses the existing createCommitmentRegex function as internal helper
2033
- */
2034
- createRegex() {
2035
- return createCommitmentRegex(this.type);
2036
- }
2037
- /**
2038
- * Creates a regex pattern to match just the commitment type
2039
- * Uses the existing createCommitmentTypeRegex function as internal helper
2040
- */
2041
- createTypeRegex() {
2042
- return createCommitmentTypeRegex(this.type);
2009
+ function isValidFilePath(filename) {
2010
+ if (typeof filename !== 'string') {
2011
+ return false;
2043
2012
  }
2044
- /**
2045
- * Helper method to create a new requirements object with updated system message
2046
- * This is commonly used by many commitments
2047
- */
2048
- updateSystemMessage(requirements, messageUpdate) {
2049
- const newMessage = typeof messageUpdate === 'string' ? messageUpdate : messageUpdate(requirements.systemMessage);
2050
- return {
2051
- ...requirements,
2052
- systemMessage: newMessage,
2053
- };
2013
+ if (filename.split('\n').length > 1) {
2014
+ return false;
2054
2015
  }
2055
- /**
2056
- * Helper method to append content to the system message
2057
- */
2058
- appendToSystemMessage(requirements, content, separator = '\n\n') {
2059
- return this.updateSystemMessage(requirements, (currentMessage) => {
2060
- if (!currentMessage.trim()) {
2061
- return content;
2062
- }
2063
- return currentMessage + separator + content;
2064
- });
2016
+ // Normalize slashes early so heuristics can detect path-like inputs
2017
+ const filenameSlashes = filename.replace(/\\/g, '/');
2018
+ // Reject strings that look like sentences (informational text)
2019
+ // Heuristic: contains multiple spaces and ends with a period, or contains typical sentence punctuation
2020
+ // But skip this heuristic if the string looks like a path (contains '/' or starts with a drive letter)
2021
+ if (filename.trim().length > 60 && // long enough to be a sentence
2022
+ /[.!?]/.test(filename) && // contains sentence punctuation
2023
+ filename.split(' ').length > 8 && // has many words
2024
+ !/\/|^[A-Z]:/i.test(filenameSlashes) // do NOT treat as sentence if looks like a path
2025
+ ) {
2026
+ return false;
2065
2027
  }
2066
- /**
2067
- * Helper method to add a comment section to the system message
2068
- * Comments are lines starting with # that will be removed from the final system message
2069
- * but can be useful for organizing and structuring the message during processing
2070
- */
2071
- addCommentSection(requirements, commentTitle, content, position = 'end') {
2072
- const commentSection = `# ${commentTitle.toUpperCase()}\n${content}`;
2073
- if (position === 'beginning') {
2074
- return this.updateSystemMessage(requirements, (currentMessage) => {
2075
- if (!currentMessage.trim()) {
2076
- return commentSection;
2077
- }
2078
- return commentSection + '\n\n' + currentMessage;
2079
- });
2080
- }
2081
- else {
2082
- return this.appendToSystemMessage(requirements, commentSection);
2083
- }
2028
+ // Absolute Unix path: /hello.txt
2029
+ if (/^(\/)/i.test(filenameSlashes)) {
2030
+ // console.log(filename, 'Absolute Unix path: /hello.txt');
2031
+ return true;
2084
2032
  }
2085
- }
2086
-
2087
- /**
2088
- * ACTION commitment definition
2089
- *
2090
- * The ACTION commitment defines specific actions or capabilities that the agent can perform.
2091
- * This helps define what the agent is capable of doing and how it should approach tasks.
2092
- *
2093
- * Example usage in agent source:
2094
- *
2095
- * ```book
2096
- * ACTION Can generate code snippets and explain programming concepts
2097
- * ACTION Able to analyze data and provide insights
2098
- * ```
2099
- *
2100
- * @private [🪔] Maybe export the commitments through some package
2101
- */
2102
- class ActionCommitmentDefinition extends BaseCommitmentDefinition {
2103
- constructor(type = 'ACTION') {
2104
- super(type);
2033
+ // Absolute Windows path: C:/ or C:\ (allow spaces and multiple dots in filename)
2034
+ if (/^[A-Z]:\/.+$/i.test(filenameSlashes)) {
2035
+ // console.log(filename, 'Absolute Windows path: /hello.txt');
2036
+ return true;
2105
2037
  }
2106
- /**
2107
- * Short one-line description of ACTION.
2108
- */
2109
- get description() {
2110
- return 'Define agent capabilities and actions it can perform.';
2038
+ // Relative path: ./hello.txt
2039
+ if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
2040
+ // console.log(filename, 'Relative path: ./hello.txt');
2041
+ return true;
2111
2042
  }
2112
- /**
2113
- * Markdown documentation for ACTION commitment.
2114
- */
2115
- get documentation() {
2116
- return spaceTrim(`
2117
- # ${this.type}
2118
-
2119
- Defines specific actions or capabilities that the agent can perform.
2120
-
2121
- ## Key aspects
2122
-
2123
- - Both terms work identically and can be used interchangeably.
2124
- - Each action adds to the agent's capability list.
2125
- - Actions help users understand what the agent can do.
2126
-
2127
- ## Examples
2128
-
2129
- \`\`\`book
2130
- Code Assistant
2131
-
2132
- PERSONA You are a programming assistant
2133
- ACTION Can generate code snippets and explain programming concepts
2134
- ACTION Able to debug existing code and suggest improvements
2135
- ACTION Can create unit tests for functions
2136
- \`\`\`
2137
-
2138
- \`\`\`book
2139
- Data Scientist
2140
-
2141
- PERSONA You are a data analysis expert
2142
- ACTION Able to analyze data and provide insights
2143
- ACTION Can create visualizations and charts
2144
- ACTION Capable of statistical analysis and modeling
2145
- KNOWLEDGE Data analysis best practices and statistical methods
2146
- \`\`\`
2147
- `);
2043
+ // Allow paths like foo/hello
2044
+ if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
2045
+ // console.log(filename, 'Allow paths like foo/hello');
2046
+ return true;
2148
2047
  }
2149
- applyToAgentModelRequirements(requirements, content) {
2150
- const trimmedContent = content.trim();
2151
- if (!trimmedContent) {
2152
- return requirements;
2153
- }
2154
- // Add action capability to the system message
2155
- const actionSection = `Capability: ${trimmedContent}`;
2156
- return this.appendToSystemMessage(requirements, actionSection, '\n\n');
2048
+ // Allow paths like hello.book
2049
+ if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
2050
+ // console.log(filename, 'Allow paths like hello.book');
2051
+ return true;
2157
2052
  }
2053
+ return false;
2158
2054
  }
2159
2055
  /**
2160
- * Note: [💞] Ignore a discrepancy between file name and entity name
2056
+ * TODO: [🍏] Implement for MacOs
2161
2057
  */
2162
2058
 
2163
2059
  /**
2164
- * DELETE commitment definition
2165
- *
2166
- * The DELETE commitment (and its aliases CANCEL, DISCARD, REMOVE) is used to
2167
- * remove or disregard certain information or context. This can be useful for
2168
- * overriding previous commitments or removing unwanted behaviors.
2169
- *
2170
- * Example usage in agent source:
2060
+ * Tests if given string is valid URL.
2171
2061
  *
2172
- * ```book
2173
- * DELETE Previous formatting requirements
2174
- * CANCEL All emotional responses
2175
- * DISCARD Technical jargon explanations
2176
- * REMOVE Casual conversational style
2177
- * ```
2062
+ * Note: [🔂] This function is idempotent.
2063
+ * Note: Dataurl are considered perfectly valid.
2064
+ * Note: There are two similar functions:
2065
+ * - `isValidUrl` which tests any URL
2066
+ * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
2178
2067
  *
2179
- * @private [🪔] Maybe export the commitments through some package
2068
+ * @public exported from `@promptbook/utils`
2180
2069
  */
2181
- class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
2182
- constructor(type) {
2183
- super(type);
2070
+ function isValidUrl(url) {
2071
+ if (typeof url !== 'string') {
2072
+ return false;
2184
2073
  }
2185
- /**
2186
- * Short one-line description of DELETE/CANCEL/DISCARD/REMOVE.
2187
- */
2188
- get description() {
2189
- return 'Remove or **disregard** certain information, context, or previous commitments.';
2074
+ try {
2075
+ if (url.startsWith('blob:')) {
2076
+ url = url.replace(/^blob:/, '');
2077
+ }
2078
+ const urlObject = new URL(url /* because fail is handled */);
2079
+ if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
2080
+ return false;
2081
+ }
2082
+ return true;
2190
2083
  }
2191
- /**
2192
- * Markdown documentation for DELETE commitment.
2193
- */
2194
- get documentation() {
2195
- return spaceTrim(`
2196
- # DELETE (CANCEL, DISCARD, REMOVE)
2197
-
2198
- A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
2199
-
2200
- ## Aliases
2084
+ catch (error) {
2085
+ return false;
2086
+ }
2087
+ }
2201
2088
 
2202
- - \`DELETE\` - Remove or eliminate something
2203
- - \`CANCEL\` - Cancel or nullify something
2204
- - \`DISCARD\` - Discard or ignore something
2205
- - \`REMOVE\` - Remove or take away something
2206
-
2207
- ## Key aspects
2208
-
2209
- - Multiple delete commitments can be used to remove different aspects.
2210
- - Useful for overriding previous commitments in the same agent definition.
2211
- - Can be used to remove inherited behaviors from base personas.
2212
- - Helps fine-tune agent behavior by explicitly removing unwanted elements.
2213
-
2214
- ## Use cases
2089
+ const defaultDiacriticsRemovalMap = [
2090
+ {
2091
+ base: 'A',
2092
+ letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F',
2093
+ },
2094
+ { base: 'AA', letters: '\uA732' },
2095
+ { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
2096
+ { base: 'AO', letters: '\uA734' },
2097
+ { base: 'AU', letters: '\uA736' },
2098
+ { base: 'AV', letters: '\uA738\uA73A' },
2099
+ { base: 'AY', letters: '\uA73C' },
2100
+ {
2101
+ base: 'B',
2102
+ letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
2103
+ },
2104
+ {
2105
+ base: 'C',
2106
+ letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
2107
+ },
2108
+ {
2109
+ base: 'D',
2110
+ letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
2111
+ },
2112
+ { base: 'DZ', letters: '\u01F1\u01C4' },
2113
+ { base: 'Dz', letters: '\u01F2\u01C5' },
2114
+ {
2115
+ base: 'E',
2116
+ letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E',
2117
+ },
2118
+ { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
2119
+ {
2120
+ base: 'G',
2121
+ letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
2122
+ },
2123
+ {
2124
+ base: 'H',
2125
+ letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
2126
+ },
2127
+ {
2128
+ base: 'I',
2129
+ letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
2130
+ },
2131
+ { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
2132
+ {
2133
+ base: 'K',
2134
+ letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
2135
+ },
2136
+ {
2137
+ base: 'L',
2138
+ letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
2139
+ },
2140
+ { base: 'LJ', letters: '\u01C7' },
2141
+ { base: 'Lj', letters: '\u01C8' },
2142
+ { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
2143
+ {
2144
+ base: 'N',
2145
+ letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
2146
+ },
2147
+ { base: 'NJ', letters: '\u01CA' },
2148
+ { base: 'Nj', letters: '\u01CB' },
2149
+ {
2150
+ base: 'O',
2151
+ letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C',
2152
+ },
2153
+ { base: 'OI', letters: '\u01A2' },
2154
+ { base: 'OO', letters: '\uA74E' },
2155
+ { base: 'OU', letters: '\u0222' },
2156
+ { base: 'OE', letters: '\u008C\u0152' },
2157
+ { base: 'oe', letters: '\u009C\u0153' },
2158
+ {
2159
+ base: 'P',
2160
+ letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
2161
+ },
2162
+ { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
2163
+ {
2164
+ base: 'R',
2165
+ letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
2166
+ },
2167
+ {
2168
+ base: 'S',
2169
+ letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
2170
+ },
2171
+ {
2172
+ base: 'T',
2173
+ letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
2174
+ },
2175
+ { base: 'TZ', letters: '\uA728' },
2176
+ {
2177
+ base: 'U',
2178
+ letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244',
2179
+ },
2180
+ { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
2181
+ { base: 'VY', letters: '\uA760' },
2182
+ {
2183
+ base: 'W',
2184
+ letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
2185
+ },
2186
+ { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
2187
+ {
2188
+ base: 'Y',
2189
+ letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
2190
+ },
2191
+ {
2192
+ base: 'Z',
2193
+ letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
2194
+ },
2195
+ {
2196
+ base: 'a',
2197
+ letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250',
2198
+ },
2199
+ { base: 'aa', letters: '\uA733' },
2200
+ { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
2201
+ { base: 'ao', letters: '\uA735' },
2202
+ { base: 'au', letters: '\uA737' },
2203
+ { base: 'av', letters: '\uA739\uA73B' },
2204
+ { base: 'ay', letters: '\uA73D' },
2205
+ {
2206
+ base: 'b',
2207
+ letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
2208
+ },
2209
+ {
2210
+ base: 'c',
2211
+ letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
2212
+ },
2213
+ {
2214
+ base: 'd',
2215
+ letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
2216
+ },
2217
+ { base: 'dz', letters: '\u01F3\u01C6' },
2218
+ {
2219
+ base: 'e',
2220
+ letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD',
2221
+ },
2222
+ { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
2223
+ {
2224
+ base: 'g',
2225
+ letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
2226
+ },
2227
+ {
2228
+ base: 'h',
2229
+ letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
2230
+ },
2231
+ { base: 'hv', letters: '\u0195' },
2232
+ {
2233
+ base: 'i',
2234
+ letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
2235
+ },
2236
+ { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
2237
+ {
2238
+ base: 'k',
2239
+ letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
2240
+ },
2241
+ {
2242
+ base: 'l',
2243
+ letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
2244
+ },
2245
+ { base: 'lj', letters: '\u01C9' },
2246
+ { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
2247
+ {
2248
+ base: 'n',
2249
+ letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
2250
+ },
2251
+ { base: 'nj', letters: '\u01CC' },
2252
+ {
2253
+ base: 'o',
2254
+ letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275',
2255
+ },
2256
+ { base: 'oi', letters: '\u01A3' },
2257
+ { base: 'ou', letters: '\u0223' },
2258
+ { base: 'oo', letters: '\uA74F' },
2259
+ {
2260
+ base: 'p',
2261
+ letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
2262
+ },
2263
+ { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
2264
+ {
2265
+ base: 'r',
2266
+ letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
2267
+ },
2268
+ {
2269
+ base: 's',
2270
+ letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
2271
+ },
2272
+ {
2273
+ base: 't',
2274
+ letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
2275
+ },
2276
+ { base: 'tz', letters: '\uA729' },
2277
+ {
2278
+ base: 'u',
2279
+ letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289',
2280
+ },
2281
+ { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
2282
+ { base: 'vy', letters: '\uA761' },
2283
+ {
2284
+ base: 'w',
2285
+ letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
2286
+ },
2287
+ { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
2288
+ {
2289
+ base: 'y',
2290
+ letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
2291
+ },
2292
+ {
2293
+ base: 'z',
2294
+ letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
2295
+ },
2296
+ ];
2297
+ /**
2298
+ * Map of letters from diacritic variant to diacritless variant
2299
+ * Contains lowercase and uppercase separatelly
2300
+ *
2301
+ * > "á" => "a"
2302
+ * > "ě" => "e"
2303
+ * > "Ă" => "A"
2304
+ * > ...
2305
+ *
2306
+ * @public exported from `@promptbook/utils`
2307
+ */
2308
+ const DIACRITIC_VARIANTS_LETTERS = {};
2309
+ // tslint:disable-next-line: prefer-for-of
2310
+ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
2311
+ const letters = defaultDiacriticsRemovalMap[i].letters;
2312
+ // tslint:disable-next-line: prefer-for-of
2313
+ for (let j = 0; j < letters.length; j++) {
2314
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
2315
+ }
2316
+ }
2317
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
2318
+ /*
2319
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
2320
+ Licensed under the Apache License, Version 2.0 (the "License");
2321
+ you may not use this file except in compliance with the License.
2322
+ You may obtain a copy of the License at
2215
2323
 
2216
- - Overriding inherited persona characteristics
2217
- - Removing conflicting or outdated instructions
2218
- - Disabling specific response patterns
2219
- - Canceling previous formatting or style requirements
2324
+ http://www.apache.org/licenses/LICENSE-2.0
2220
2325
 
2221
- ## Examples
2326
+ Unless required by applicable law or agreed to in writing, software
2327
+ distributed under the License is distributed on an "AS IS" BASIS,
2328
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2329
+ See the License for the specific language governing permissions and
2330
+ limitations under the License.
2331
+ */
2222
2332
 
2223
- \`\`\`book
2224
- Serious Business Assistant
2225
-
2226
- PERSONA You are a friendly and casual assistant who uses emojis
2227
- DELETE Casual conversational style
2228
- REMOVE All emoji usage
2229
- GOAL Provide professional business communications
2230
- STYLE Use formal language and proper business etiquette
2231
- \`\`\`
2232
-
2233
- \`\`\`book
2234
- Simplified Technical Support
2235
-
2236
- PERSONA You are a technical support specialist with deep expertise
2237
- KNOWLEDGE Extensive database of technical specifications
2238
- DISCARD Technical jargon explanations
2239
- CANCEL Advanced troubleshooting procedures
2240
- GOAL Help users with simple, easy-to-follow solutions
2241
- STYLE Use plain language that anyone can understand
2242
- \`\`\`
2243
-
2244
- \`\`\`book
2245
- Focused Customer Service
2246
-
2247
- PERSONA You are a customer service agent with broad knowledge
2248
- ACTION Can help with billing, technical issues, and product information
2249
- DELETE Billing assistance capabilities
2250
- REMOVE Technical troubleshooting functions
2251
- GOAL Focus exclusively on product information and general inquiries
2252
- \`\`\`
2253
-
2254
- \`\`\`book
2255
- Concise Information Provider
2333
+ /**
2334
+ * Removes diacritic marks (accents) from characters in a string.
2335
+ *
2336
+ * Note: [🔂] This function is idempotent.
2337
+ *
2338
+ * @param input The string containing diacritics to be normalized.
2339
+ * @returns The string with diacritics removed or normalized.
2340
+ * @public exported from `@promptbook/utils`
2341
+ */
2342
+ function removeDiacritics(input) {
2343
+ /*eslint no-control-regex: "off"*/
2344
+ return input.replace(/[^\u0000-\u007E]/g, (a) => {
2345
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
2346
+ });
2347
+ }
2348
+ /**
2349
+ * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
2350
+ */
2256
2351
 
2257
- PERSONA You are a helpful assistant who provides detailed explanations
2258
- STYLE Include examples, analogies, and comprehensive context
2259
- CANCEL Detailed explanation style
2260
- DISCARD Examples and analogies
2261
- GOAL Provide brief, direct answers without unnecessary elaboration
2262
- STYLE Be concise and to the point
2263
- \`\`\`
2264
- `);
2265
- }
2266
- applyToAgentModelRequirements(requirements, content) {
2267
- const trimmedContent = content.trim();
2268
- if (!trimmedContent) {
2269
- return requirements;
2352
+ /**
2353
+ * Converts a given text to kebab-case format.
2354
+ *
2355
+ * Note: [🔂] This function is idempotent.
2356
+ *
2357
+ * @param text The text to be converted.
2358
+ * @returns The kebab-case formatted string.
2359
+ * @example 'hello-world'
2360
+ * @example 'i-love-promptbook'
2361
+ * @public exported from `@promptbook/utils`
2362
+ */
2363
+ function normalizeToKebabCase(text) {
2364
+ text = removeDiacritics(text);
2365
+ let charType;
2366
+ let lastCharType = 'OTHER';
2367
+ let normalizedName = '';
2368
+ for (const char of text) {
2369
+ let normalizedChar;
2370
+ if (/^[a-z]$/.test(char)) {
2371
+ charType = 'LOWERCASE';
2372
+ normalizedChar = char;
2270
2373
  }
2271
- // Create deletion instruction for system message
2272
- const deleteSection = `${this.type}: ${trimmedContent}`;
2273
- // Delete instructions provide important context about what should be removed or ignored
2274
- return this.appendToSystemMessage(requirements, deleteSection, '\n\n');
2374
+ else if (/^[A-Z]$/.test(char)) {
2375
+ charType = 'UPPERCASE';
2376
+ normalizedChar = char.toLowerCase();
2377
+ }
2378
+ else if (/^[0-9]$/.test(char)) {
2379
+ charType = 'NUMBER';
2380
+ normalizedChar = char;
2381
+ }
2382
+ else {
2383
+ charType = 'OTHER';
2384
+ normalizedChar = '-';
2385
+ }
2386
+ if (charType !== lastCharType &&
2387
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
2388
+ !(lastCharType === 'NUMBER') &&
2389
+ !(charType === 'NUMBER')) {
2390
+ normalizedName += '-';
2391
+ }
2392
+ normalizedName += normalizedChar;
2393
+ lastCharType = charType;
2275
2394
  }
2395
+ normalizedName = normalizedName.split(/-+/g).join('-');
2396
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
2397
+ normalizedName = normalizedName.replace(/^-/, '');
2398
+ normalizedName = normalizedName.replace(/-$/, '');
2399
+ return normalizedName;
2276
2400
  }
2277
2401
  /**
2278
2402
  * Note: [💞] Ignore a discrepancy between file name and entity name
2279
2403
  */
2280
2404
 
2281
2405
  /**
2282
- * FORMAT commitment definition
2406
+ * Removes emojis from a string and fix whitespaces
2283
2407
  *
2284
- * The FORMAT commitment defines the specific output structure and formatting
2285
- * that the agent should use in its responses. This includes data formats,
2286
- * response templates, and structural requirements.
2408
+ * Note: [🔂] This function is idempotent.
2287
2409
  *
2288
- * Example usage in agent source:
2410
+ * @param text with emojis
2411
+ * @returns text without emojis
2412
+ * @public exported from `@promptbook/utils`
2413
+ */
2414
+ function removeEmojis(text) {
2415
+ // Replace emojis (and also ZWJ sequence) with hyphens
2416
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
2417
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
2418
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
2419
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
2420
+ return text;
2421
+ }
2422
+
2423
+ /**
2424
+ * Converts a title string into a normalized name.
2289
2425
  *
2290
- * ```book
2291
- * FORMAT Always respond in JSON format with 'status' and 'data' fields
2292
- * FORMAT Use markdown formatting for all code blocks
2293
- * ```
2426
+ * Note: [🔂] This function is idempotent.
2294
2427
  *
2295
- * @private [🪔] Maybe export the commitments through some package
2428
+ * @param value The title string to be converted to a name.
2429
+ * @returns A normalized name derived from the input title.
2430
+ * @example 'Hello World!' -> 'hello-world'
2431
+ * @public exported from `@promptbook/utils`
2296
2432
  */
2297
- class FormatCommitmentDefinition extends BaseCommitmentDefinition {
2298
- constructor(type = 'FORMAT') {
2299
- super(type);
2300
- }
2301
- /**
2302
- * Short one-line description of FORMAT.
2303
- */
2304
- get description() {
2305
- return 'Specify output structure or formatting requirements.';
2306
- }
2307
- /**
2308
- * Markdown documentation for FORMAT commitment.
2309
- */
2310
- get documentation() {
2311
- return spaceTrim(`
2312
- # ${this.type}
2313
-
2314
- Defines the specific output structure and formatting for responses (data formats, templates, structure).
2315
-
2316
- ## Key aspects
2317
-
2318
- - Both terms work identically and can be used interchangeably.
2319
- - If they are in conflict, the last one takes precedence.
2320
- - You can specify both data formats and presentation styles.
2321
-
2322
- ## Examples
2323
-
2324
- \`\`\`book
2325
- Customer Support Bot
2326
-
2327
- PERSONA You are a helpful customer support agent
2328
- FORMAT Always respond in JSON format with 'status' and 'data' fields
2329
- FORMAT Use markdown formatting for all code blocks
2330
- \`\`\`
2331
-
2332
- \`\`\`book
2333
- Data Analyst
2334
-
2335
- PERSONA You are a data analysis expert
2336
- FORMAT Present results in structured tables
2337
- FORMAT Include confidence scores for all predictions
2338
- STYLE Be concise and precise in explanations
2339
- \`\`\`
2340
- `);
2433
+ function titleToName(value) {
2434
+ if (isValidUrl(value)) {
2435
+ value = value.replace(/^https?:\/\//, '');
2436
+ value = value.replace(/\.html$/, '');
2341
2437
  }
2342
- applyToAgentModelRequirements(requirements, content) {
2343
- const trimmedContent = content.trim();
2344
- if (!trimmedContent) {
2345
- return requirements;
2346
- }
2347
- // Add format instructions to the system message
2348
- const formatSection = `Output Format: ${trimmedContent}`;
2349
- return this.appendToSystemMessage(requirements, formatSection, '\n\n');
2438
+ else if (isValidFilePath(value)) {
2439
+ value = basename(value);
2440
+ // Note: Keeping extension in the name
2350
2441
  }
2442
+ value = value.split('/').join('-');
2443
+ value = removeEmojis(value);
2444
+ value = normalizeToKebabCase(value);
2445
+ // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
2446
+ return value;
2351
2447
  }
2448
+
2449
+ /**
2450
+ * Index of all javascript errors
2451
+ *
2452
+ * @private for internal usage
2453
+ */
2454
+ ({
2455
+ Error,
2456
+ EvalError,
2457
+ RangeError,
2458
+ ReferenceError,
2459
+ SyntaxError,
2460
+ TypeError,
2461
+ URIError,
2462
+ AggregateError,
2463
+ /*
2464
+ Note: Not widely supported
2465
+ > InternalError,
2466
+ > ModuleError,
2467
+ > HeapError,
2468
+ > WebAssemblyCompileError,
2469
+ > WebAssemblyRuntimeError,
2470
+ */
2471
+ });
2352
2472
  /**
2353
2473
  * Note: [💞] Ignore a discrepancy between file name and entity name
2354
2474
  */
2355
2475
 
2356
2476
  /**
2357
- * GOAL commitment definition
2477
+ * Detects if the code is running in jest environment
2358
2478
  *
2359
- * The GOAL commitment defines the main goal which should be achieved by the AI assistant.
2360
- * There can be multiple goals. Later goals are more important than earlier goals.
2479
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
2361
2480
  *
2362
- * Example usage in agent source:
2481
+ * @public exported from `@promptbook/utils`
2482
+ */
2483
+ new Function(`
2484
+ try {
2485
+ return process.env.JEST_WORKER_ID !== undefined;
2486
+ } catch (e) {
2487
+ return false;
2488
+ }
2489
+ `);
2490
+ /**
2491
+ * TODO: [🎺]
2492
+ */
2493
+
2494
+ /**
2495
+ * Detects if the code is running in a Node.js environment
2363
2496
  *
2364
- * ```book
2365
- * GOAL Help users understand complex technical concepts
2366
- * GOAL Provide accurate and up-to-date information
2367
- * GOAL Always prioritize user safety and ethical guidelines
2368
- * ```
2497
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
2369
2498
  *
2370
- * @private [🪔] Maybe export the commitments through some package
2499
+ * @public exported from `@promptbook/utils`
2371
2500
  */
2372
- class GoalCommitmentDefinition extends BaseCommitmentDefinition {
2373
- constructor(type = 'GOAL') {
2374
- super(type);
2375
- }
2376
- /**
2377
- * Short one-line description of GOAL.
2378
- */
2379
- get description() {
2380
- return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
2501
+ new Function(`
2502
+ try {
2503
+ return this === global;
2504
+ } catch (e) {
2505
+ return false;
2381
2506
  }
2382
- /**
2383
- * Markdown documentation for GOAL commitment.
2384
- */
2385
- get documentation() {
2386
- return spaceTrim(`
2387
- # ${this.type}
2388
-
2389
- Defines the main goal which should be achieved by the AI assistant. There can be multiple goals, and later goals are more important than earlier goals.
2390
-
2391
- ## Key aspects
2392
-
2393
- - Both terms work identically and can be used interchangeably.
2394
- - Later goals have higher priority and can override earlier goals.
2395
- - Goals provide clear direction and purpose for the agent's responses.
2396
- - Goals influence decision-making and response prioritization.
2397
-
2398
- ## Priority system
2399
-
2400
- When multiple goals are defined, they are processed in order, with later goals taking precedence over earlier ones when there are conflicts.
2401
-
2402
- ## Examples
2403
-
2404
- \`\`\`book
2405
- Customer Support Agent
2406
-
2407
- PERSONA You are a helpful customer support representative
2408
- GOAL Resolve customer issues quickly and efficiently
2409
- GOAL Maintain high customer satisfaction scores
2410
- GOAL Always follow company policies and procedures
2411
- RULE Be polite and professional at all times
2412
- \`\`\`
2413
-
2414
- \`\`\`book
2415
- Educational Assistant
2416
-
2417
- PERSONA You are an educational assistant specializing in mathematics
2418
- GOAL Help students understand mathematical concepts clearly
2419
- GOAL Encourage critical thinking and problem-solving skills
2420
- GOAL Ensure all explanations are age-appropriate and accessible
2421
- STYLE Use simple language and provide step-by-step explanations
2422
- \`\`\`
2507
+ `);
2508
+ /**
2509
+ * TODO: [🎺]
2510
+ */
2423
2511
 
2424
- \`\`\`book
2425
- Safety-First Assistant
2512
+ /**
2513
+ * Normalizes agent name from arbitrary string to valid agent name
2514
+ *
2515
+ * Note: [🔂] This function is idempotent.
2516
+ *
2517
+ * @public exported from `@promptbook/core`
2518
+ */
2519
+ function normalizeAgentName(rawAgentName) {
2520
+ return titleToName(spaceTrim$1(rawAgentName));
2521
+ }
2426
2522
 
2427
- PERSONA You are a general-purpose AI assistant
2428
- GOAL Be helpful and informative in all interactions
2429
- GOAL Provide accurate and reliable information
2430
- GOAL Always prioritize user safety and ethical guidelines
2431
- RULE Never provide harmful or dangerous advice
2432
- \`\`\`
2433
- `);
2434
- }
2435
- applyToAgentModelRequirements(requirements, content) {
2436
- const trimmedContent = content.trim();
2437
- if (!trimmedContent) {
2438
- return requirements;
2439
- }
2440
- // Create goal section for system message
2441
- const goalSection = `Goal: ${trimmedContent}`;
2442
- // Goals are important directives, so we add them prominently to the system message
2443
- return this.appendToSystemMessage(requirements, goalSection, '\n\n');
2444
- }
2523
+ /**
2524
+ * Generates a regex pattern to match a specific commitment
2525
+ *
2526
+ * Note: It always creates new Regex object
2527
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
2528
+ *
2529
+ * @private - TODO: [🧠] Maybe should be public?
2530
+ */
2531
+ function createCommitmentRegex(commitment) {
2532
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2533
+ const keywordPattern = escapedCommitment.split(/\s+/).join('\\s+');
2534
+ const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
2535
+ return regex;
2445
2536
  }
2446
2537
  /**
2447
- * Note: [💞] Ignore a discrepancy between file name and entity name
2538
+ * Generates a regex pattern to match a specific commitment type
2539
+ *
2540
+ * Note: It just matches the type part of the commitment
2541
+ * Note: It always creates new Regex object
2542
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
2543
+ *
2544
+ * @private
2448
2545
  */
2546
+ function createCommitmentTypeRegex(commitment) {
2547
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2548
+ const keywordPattern = escapedCommitment.split(/\s+/).join('\\s+');
2549
+ const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
2550
+ return regex;
2551
+ }
2449
2552
 
2450
2553
  /**
2451
- * Tests if given string is valid URL.
2452
- *
2453
- * Note: [🔂] This function is idempotent.
2454
- * Note: Dataurl are considered perfectly valid.
2455
- * Note: There are two similar functions:
2456
- * - `isValidUrl` which tests any URL
2457
- * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
2554
+ * Base implementation of CommitmentDefinition that provides common functionality
2555
+ * Most commitments can extend this class and only override the applyToAgentModelRequirements method
2458
2556
  *
2459
- * @public exported from `@promptbook/utils`
2557
+ * @private
2460
2558
  */
2461
- function isValidUrl(url) {
2462
- if (typeof url !== 'string') {
2463
- return false;
2559
+ class BaseCommitmentDefinition {
2560
+ constructor(type) {
2561
+ this.type = type;
2464
2562
  }
2465
- try {
2466
- if (url.startsWith('blob:')) {
2467
- url = url.replace(/^blob:/, '');
2563
+ /**
2564
+ * Creates a regex pattern to match this commitment in agent source
2565
+ * Uses the existing createCommitmentRegex function as internal helper
2566
+ */
2567
+ createRegex() {
2568
+ return createCommitmentRegex(this.type);
2569
+ }
2570
+ /**
2571
+ * Creates a regex pattern to match just the commitment type
2572
+ * Uses the existing createCommitmentTypeRegex function as internal helper
2573
+ */
2574
+ createTypeRegex() {
2575
+ return createCommitmentTypeRegex(this.type);
2576
+ }
2577
+ /**
2578
+ * Helper method to create a new requirements object with updated system message
2579
+ * This is commonly used by many commitments
2580
+ */
2581
+ updateSystemMessage(requirements, messageUpdate) {
2582
+ const newMessage = typeof messageUpdate === 'string' ? messageUpdate : messageUpdate(requirements.systemMessage);
2583
+ return {
2584
+ ...requirements,
2585
+ systemMessage: newMessage,
2586
+ };
2587
+ }
2588
+ /**
2589
+ * Helper method to append content to the system message
2590
+ */
2591
+ appendToSystemMessage(requirements, content, separator = '\n\n') {
2592
+ return this.updateSystemMessage(requirements, (currentMessage) => {
2593
+ if (!currentMessage.trim()) {
2594
+ return content;
2595
+ }
2596
+ return currentMessage + separator + content;
2597
+ });
2598
+ }
2599
+ /**
2600
+ * Helper method to add a comment section to the system message
2601
+ * Comments are lines starting with # that will be removed from the final system message
2602
+ * but can be useful for organizing and structuring the message during processing
2603
+ */
2604
+ addCommentSection(requirements, commentTitle, content, position = 'end') {
2605
+ const commentSection = `# ${commentTitle.toUpperCase()}\n${content}`;
2606
+ if (position === 'beginning') {
2607
+ return this.updateSystemMessage(requirements, (currentMessage) => {
2608
+ if (!currentMessage.trim()) {
2609
+ return commentSection;
2610
+ }
2611
+ return commentSection + '\n\n' + currentMessage;
2612
+ });
2468
2613
  }
2469
- const urlObject = new URL(url /* because fail is handled */);
2470
- if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
2471
- return false;
2614
+ else {
2615
+ return this.appendToSystemMessage(requirements, commentSection);
2472
2616
  }
2473
- return true;
2474
- }
2475
- catch (error) {
2476
- return false;
2477
2617
  }
2478
2618
  }
2479
2619
 
2480
2620
  /**
2481
- * KNOWLEDGE commitment definition
2482
- *
2483
- * The KNOWLEDGE commitment adds specific knowledge, facts, or context to the agent
2484
- * using RAG (Retrieval-Augmented Generation) approach for external sources.
2621
+ * ACTION commitment definition
2485
2622
  *
2486
- * Supports both direct text knowledge and external sources like PDFs.
2623
+ * The ACTION commitment defines specific actions or capabilities that the agent can perform.
2624
+ * This helps define what the agent is capable of doing and how it should approach tasks.
2487
2625
  *
2488
2626
  * Example usage in agent source:
2489
2627
  *
2490
2628
  * ```book
2491
- * KNOWLEDGE The company was founded in 2020 and specializes in AI-powered solutions
2492
- * KNOWLEDGE https://example.com/company-handbook.pdf
2493
- * KNOWLEDGE https://example.com/product-documentation.pdf
2629
+ * ACTION Can generate code snippets and explain programming concepts
2630
+ * ACTION Able to analyze data and provide insights
2494
2631
  * ```
2495
2632
  *
2496
2633
  * @private [🪔] Maybe export the commitments through some package
2497
2634
  */
2498
- class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
2499
- constructor() {
2500
- super('KNOWLEDGE');
2635
+ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
2636
+ constructor(type = 'ACTION') {
2637
+ super(type);
2501
2638
  }
2502
2639
  /**
2503
- * Short one-line description of KNOWLEDGE.
2640
+ * Short one-line description of ACTION.
2504
2641
  */
2505
2642
  get description() {
2506
- return 'Add domain **knowledge** via direct text or external sources (RAG).';
2643
+ return 'Define agent capabilities and actions it can perform.';
2507
2644
  }
2508
2645
  /**
2509
- * Markdown documentation for KNOWLEDGE commitment.
2646
+ * Markdown documentation for ACTION commitment.
2510
2647
  */
2511
2648
  get documentation() {
2512
2649
  return spaceTrim(`
2513
2650
  # ${this.type}
2514
2651
 
2515
- Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
2652
+ Defines specific actions or capabilities that the agent can perform.
2516
2653
 
2517
2654
  ## Key aspects
2518
2655
 
2519
2656
  - Both terms work identically and can be used interchangeably.
2520
- - Supports both direct text knowledge and external URLs.
2521
- - External sources (PDFs, websites) are processed via RAG for context retrieval.
2522
-
2523
- ## Supported formats
2524
-
2525
- - Direct text: Immediate knowledge incorporated into agent
2526
- - URLs: External documents processed for contextual retrieval
2527
- - Supported file types: PDF, text, markdown, HTML
2657
+ - Each action adds to the agent's capability list.
2658
+ - Actions help users understand what the agent can do.
2528
2659
 
2529
2660
  ## Examples
2530
2661
 
2531
2662
  \`\`\`book
2532
- Customer Support Bot
2663
+ Code Assistant
2533
2664
 
2534
- PERSONA You are a helpful customer support agent for TechCorp
2535
- KNOWLEDGE TechCorp was founded in 2020 and specializes in AI-powered solutions
2536
- KNOWLEDGE https://example.com/company-handbook.pdf
2537
- KNOWLEDGE https://example.com/product-documentation.pdf
2538
- RULE Always be polite and professional
2665
+ PERSONA You are a programming assistant
2666
+ ACTION Can generate code snippets and explain programming concepts
2667
+ ACTION Able to debug existing code and suggest improvements
2668
+ ACTION Can create unit tests for functions
2539
2669
  \`\`\`
2540
2670
 
2541
2671
  \`\`\`book
2542
- Research Assistant
2672
+ Data Scientist
2543
2673
 
2544
- PERSONA You are a knowledgeable research assistant
2545
- KNOWLEDGE Academic research requires careful citation and verification
2546
- KNOWLEDGE https://example.com/research-guidelines.pdf
2547
- ACTION Can help with literature reviews and data analysis
2548
- STYLE Present information in clear, academic format
2674
+ PERSONA You are a data analysis expert
2675
+ ACTION Able to analyze data and provide insights
2676
+ ACTION Can create visualizations and charts
2677
+ ACTION Capable of statistical analysis and modeling
2678
+ KNOWLEDGE Data analysis best practices and statistical methods
2549
2679
  \`\`\`
2550
2680
  `);
2551
2681
  }
@@ -2554,114 +2684,115 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
2554
2684
  if (!trimmedContent) {
2555
2685
  return requirements;
2556
2686
  }
2557
- // Check if content is a URL (external knowledge source)
2558
- if (isValidUrl(trimmedContent)) {
2559
- // Store the URL for later async processing
2560
- const updatedRequirements = {
2561
- ...requirements,
2562
- knowledgeSources: [
2563
- ...(requirements.knowledgeSources || []),
2564
- trimmedContent,
2565
- ],
2566
- };
2567
- // Add placeholder information about knowledge sources to system message
2568
- const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
2569
- return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
2570
- }
2571
- else {
2572
- // Direct text knowledge - add to system message
2573
- const knowledgeSection = `Knowledge: ${trimmedContent}`;
2574
- return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
2575
- }
2576
- }
2577
- }
2687
+ // Add action capability to the system message
2688
+ const actionSection = `Capability: ${trimmedContent}`;
2689
+ return this.appendToSystemMessage(requirements, actionSection, '\n\n');
2690
+ }
2691
+ }
2578
2692
  /**
2579
2693
  * Note: [💞] Ignore a discrepancy between file name and entity name
2580
2694
  */
2581
2695
 
2582
2696
  /**
2583
- * MEMORY commitment definition
2697
+ * DELETE commitment definition
2584
2698
  *
2585
- * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
2586
- * interactions and user preferences. It helps the agent maintain context about the
2587
- * user's history, preferences, and previous conversations.
2699
+ * The DELETE commitment (and its aliases CANCEL, DISCARD, REMOVE) is used to
2700
+ * remove or disregard certain information or context. This can be useful for
2701
+ * overriding previous commitments or removing unwanted behaviors.
2588
2702
  *
2589
2703
  * Example usage in agent source:
2590
2704
  *
2591
2705
  * ```book
2592
- * MEMORY User prefers detailed technical explanations
2593
- * MEMORY Previously worked on React projects
2594
- * MEMORY Timezone: UTC-5 (Eastern Time)
2706
+ * DELETE Previous formatting requirements
2707
+ * CANCEL All emotional responses
2708
+ * DISCARD Technical jargon explanations
2709
+ * REMOVE Casual conversational style
2595
2710
  * ```
2596
2711
  *
2597
2712
  * @private [🪔] Maybe export the commitments through some package
2598
2713
  */
2599
- class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
2600
- constructor(type = 'MEMORY') {
2714
+ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
2715
+ constructor(type) {
2601
2716
  super(type);
2602
2717
  }
2603
2718
  /**
2604
- * Short one-line description of MEMORY.
2719
+ * Short one-line description of DELETE/CANCEL/DISCARD/REMOVE.
2605
2720
  */
2606
2721
  get description() {
2607
- return 'Remember past interactions and user **preferences** for personalized responses.';
2722
+ return 'Remove or **disregard** certain information, context, or previous commitments.';
2608
2723
  }
2609
2724
  /**
2610
- * Markdown documentation for MEMORY commitment.
2725
+ * Markdown documentation for DELETE commitment.
2611
2726
  */
2612
2727
  get documentation() {
2613
2728
  return spaceTrim(`
2614
- # ${this.type}
2729
+ # DELETE (CANCEL, DISCARD, REMOVE)
2615
2730
 
2616
- Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
2731
+ A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
2732
+
2733
+ ## Aliases
2734
+
2735
+ - \`DELETE\` - Remove or eliminate something
2736
+ - \`CANCEL\` - Cancel or nullify something
2737
+ - \`DISCARD\` - Discard or ignore something
2738
+ - \`REMOVE\` - Remove or take away something
2617
2739
 
2618
2740
  ## Key aspects
2619
2741
 
2620
- - Both terms work identically and can be used interchangeably.
2621
- - Focuses on user-specific information and interaction history.
2622
- - Helps personalize responses based on past interactions.
2623
- - Maintains continuity across conversations.
2742
+ - Multiple delete commitments can be used to remove different aspects.
2743
+ - Useful for overriding previous commitments in the same agent definition.
2744
+ - Can be used to remove inherited behaviors from base personas.
2745
+ - Helps fine-tune agent behavior by explicitly removing unwanted elements.
2624
2746
 
2625
- ## Differences from KNOWLEDGE
2747
+ ## Use cases
2626
2748
 
2627
- - \`KNOWLEDGE\` is for domain expertise and factual information
2628
- - \`MEMORY\` is for user-specific context and preferences
2629
- - \`MEMORY\` creates more personalized interactions
2630
- - \`MEMORY\` often includes temporal or preference-based information
2749
+ - Overriding inherited persona characteristics
2750
+ - Removing conflicting or outdated instructions
2751
+ - Disabling specific response patterns
2752
+ - Canceling previous formatting or style requirements
2631
2753
 
2632
2754
  ## Examples
2633
2755
 
2634
2756
  \`\`\`book
2635
- Personal Assistant
2757
+ Serious Business Assistant
2636
2758
 
2637
- PERSONA You are a personal productivity assistant
2638
- MEMORY User is a software developer working in JavaScript/React
2639
- MEMORY User prefers morning work sessions and afternoon meetings
2640
- MEMORY Previously helped with project planning for mobile apps
2641
- MEMORY User timezone: UTC-8 (Pacific Time)
2642
- GOAL Help optimize daily productivity and workflow
2759
+ PERSONA You are a friendly and casual assistant who uses emojis
2760
+ DELETE Casual conversational style
2761
+ REMOVE All emoji usage
2762
+ GOAL Provide professional business communications
2763
+ STYLE Use formal language and proper business etiquette
2643
2764
  \`\`\`
2644
2765
 
2645
2766
  \`\`\`book
2646
- Learning Companion
2767
+ Simplified Technical Support
2647
2768
 
2648
- PERSONA You are an educational companion for programming students
2649
- MEMORY Student is learning Python as their first programming language
2650
- MEMORY Previous topics covered: variables, loops, functions
2651
- MEMORY Student learns best with practical examples and exercises
2652
- MEMORY Last session: working on list comprehensions
2653
- GOAL Provide progressive learning experiences tailored to student's pace
2769
+ PERSONA You are a technical support specialist with deep expertise
2770
+ KNOWLEDGE Extensive database of technical specifications
2771
+ DISCARD Technical jargon explanations
2772
+ CANCEL Advanced troubleshooting procedures
2773
+ GOAL Help users with simple, easy-to-follow solutions
2774
+ STYLE Use plain language that anyone can understand
2654
2775
  \`\`\`
2655
2776
 
2656
2777
  \`\`\`book
2657
- Customer Support Agent
2778
+ Focused Customer Service
2658
2779
 
2659
- PERSONA You are a customer support representative
2660
- MEMORY Customer has premium subscription since 2023
2661
- MEMORY Previous issue: billing question resolved last month
2662
- MEMORY Customer prefers email communication over phone calls
2663
- MEMORY Account shows frequent use of advanced features
2664
- GOAL Provide personalized support based on customer history
2780
+ PERSONA You are a customer service agent with broad knowledge
2781
+ ACTION Can help with billing, technical issues, and product information
2782
+ DELETE Billing assistance capabilities
2783
+ REMOVE Technical troubleshooting functions
2784
+ GOAL Focus exclusively on product information and general inquiries
2785
+ \`\`\`
2786
+
2787
+ \`\`\`book
2788
+ Concise Information Provider
2789
+
2790
+ PERSONA You are a helpful assistant who provides detailed explanations
2791
+ STYLE Include examples, analogies, and comprehensive context
2792
+ CANCEL Detailed explanation style
2793
+ DISCARD Examples and analogies
2794
+ GOAL Provide brief, direct answers without unnecessary elaboration
2795
+ STYLE Be concise and to the point
2665
2796
  \`\`\`
2666
2797
  `);
2667
2798
  }
@@ -2670,10 +2801,10 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
2670
2801
  if (!trimmedContent) {
2671
2802
  return requirements;
2672
2803
  }
2673
- // Create memory section for system message
2674
- const memorySection = `Memory: ${trimmedContent}`;
2675
- // Memory information is contextual and should be included in the system message
2676
- return this.appendToSystemMessage(requirements, memorySection, '\n\n');
2804
+ // Create deletion instruction for system message
2805
+ const deleteSection = `${this.type}: ${trimmedContent}`;
2806
+ // Delete instructions provide important context about what should be removed or ignored
2807
+ return this.appendToSystemMessage(requirements, deleteSection, '\n\n');
2677
2808
  }
2678
2809
  }
2679
2810
  /**
@@ -2681,97 +2812,63 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
2681
2812
  */
2682
2813
 
2683
2814
  /**
2684
- * MESSAGE commitment definition
2815
+ * FORMAT commitment definition
2685
2816
  *
2686
- * The MESSAGE commitment contains 1:1 text of the message which AI assistant already
2687
- * sent during the conversation. Later messages are later in the conversation.
2688
- * It is similar to EXAMPLE but it is not example, it is the real message which
2689
- * AI assistant already sent.
2817
+ * The FORMAT commitment defines the specific output structure and formatting
2818
+ * that the agent should use in its responses. This includes data formats,
2819
+ * response templates, and structural requirements.
2690
2820
  *
2691
2821
  * Example usage in agent source:
2692
2822
  *
2693
2823
  * ```book
2694
- * MESSAGE Hello! How can I help you today?
2695
- * MESSAGE I understand you're looking for information about our services.
2696
- * MESSAGE Based on your requirements, I'd recommend our premium package.
2824
+ * FORMAT Always respond in JSON format with 'status' and 'data' fields
2825
+ * FORMAT Use markdown formatting for all code blocks
2697
2826
  * ```
2698
2827
  *
2699
2828
  * @private [🪔] Maybe export the commitments through some package
2700
2829
  */
2701
- class MessageCommitmentDefinition extends BaseCommitmentDefinition {
2702
- constructor(type = 'MESSAGE') {
2830
+ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
2831
+ constructor(type = 'FORMAT') {
2703
2832
  super(type);
2704
2833
  }
2705
2834
  /**
2706
- * Short one-line description of MESSAGE.
2835
+ * Short one-line description of FORMAT.
2707
2836
  */
2708
2837
  get description() {
2709
- return 'Include actual **messages** the AI assistant has sent during conversation history.';
2838
+ return 'Specify output structure or formatting requirements.';
2710
2839
  }
2711
2840
  /**
2712
- * Markdown documentation for MESSAGE commitment.
2841
+ * Markdown documentation for FORMAT commitment.
2713
2842
  */
2714
2843
  get documentation() {
2715
2844
  return spaceTrim(`
2716
2845
  # ${this.type}
2717
2846
 
2718
- Contains 1:1 text of the message which AI assistant already sent during the conversation. Later messages are later in the conversation. It is similar to EXAMPLE but it is not example, it is the real message which AI assistant already sent.
2847
+ Defines the specific output structure and formatting for responses (data formats, templates, structure).
2719
2848
 
2720
2849
  ## Key aspects
2721
2850
 
2722
- - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
2723
2851
  - Both terms work identically and can be used interchangeably.
2724
- - Later messages are later in the conversation chronologically.
2725
- - Contains actual historical messages, not examples or templates.
2726
- - Helps maintain conversation continuity and context.
2727
-
2728
- ## Differences from EXAMPLE
2729
-
2730
- - \`EXAMPLE\` shows hypothetical or template responses
2731
- - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
2732
- - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
2733
- - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
2734
-
2735
- ## Use cases
2736
-
2737
- - Maintaining conversation history context
2738
- - Ensuring consistent tone and style across messages
2739
- - Referencing previous responses in ongoing conversations
2740
- - Building upon previously established context
2852
+ - If they are in conflict, the last one takes precedence.
2853
+ - You can specify both data formats and presentation styles.
2741
2854
 
2742
2855
  ## Examples
2743
2856
 
2744
2857
  \`\`\`book
2745
- Customer Support Continuation
2858
+ Customer Support Bot
2746
2859
 
2747
2860
  PERSONA You are a helpful customer support agent
2748
- MESSAGE Hello! How can I help you today?
2749
- MESSAGE I understand you're experiencing issues with your account login.
2750
- MESSAGE I've sent you a password reset link to your email address.
2751
- MESSAGE Is there anything else I can help you with regarding your account?
2752
- GOAL Continue providing consistent support based on conversation history
2753
- \`\`\`
2754
-
2755
- \`\`\`book
2756
- Technical Discussion
2757
-
2758
- PERSONA You are a software development mentor
2759
- MESSAGE Let's start by reviewing the React component structure you shared.
2760
- MESSAGE I notice you're using class components - have you considered hooks?
2761
- MESSAGE Here's how you could refactor that using the useState hook.
2762
- MESSAGE Great question about performance! Let me explain React's rendering cycle.
2763
- KNOWLEDGE React hooks were introduced in version 16.8
2861
+ FORMAT Always respond in JSON format with 'status' and 'data' fields
2862
+ FORMAT Use markdown formatting for all code blocks
2764
2863
  \`\`\`
2765
2864
 
2766
2865
  \`\`\`book
2767
- Educational Session
2866
+ Data Analyst
2768
2867
 
2769
- PERSONA You are a mathematics tutor
2770
- MESSAGE Today we'll work on solving quadratic equations.
2771
- MESSAGE Let's start with the basic form: ax² + bx + c = 0
2772
- MESSAGE Remember, we can use the quadratic formula or factoring.
2773
- MESSAGE You did great with that first problem! Let's try a more complex one.
2774
- GOAL Build upon previous explanations for deeper understanding
2868
+ PERSONA You are a data analysis expert
2869
+ FORMAT Present results in structured tables
2870
+ FORMAT Include confidence scores for all predictions
2871
+ STYLE Be concise and precise in explanations
2775
2872
  \`\`\`
2776
2873
  `);
2777
2874
  }
@@ -2780,10 +2877,9 @@ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
2780
2877
  if (!trimmedContent) {
2781
2878
  return requirements;
2782
2879
  }
2783
- // Create message section for system message
2784
- const messageSection = `Previous Message: ${trimmedContent}`;
2785
- // Messages represent conversation history and should be included for context
2786
- return this.appendToSystemMessage(requirements, messageSection, '\n\n');
2880
+ // Add format instructions to the system message
2881
+ const formatSection = `Output Format: ${trimmedContent}`;
2882
+ return this.appendToSystemMessage(requirements, formatSection, '\n\n');
2787
2883
  }
2788
2884
  }
2789
2885
  /**
@@ -2791,136 +2887,93 @@ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
2791
2887
  */
2792
2888
 
2793
2889
  /**
2794
- * META commitment definition
2795
- *
2796
- * The META commitment handles all meta-information about the agent such as:
2797
- * - META IMAGE: Sets the agent's avatar/profile image URL
2798
- * - META LINK: Provides profile/source links for the person the agent models
2799
- * - META TITLE: Sets the agent's display title
2800
- * - META DESCRIPTION: Sets the agent's description
2801
- * - META [ANYTHING]: Any other meta information in uppercase format
2890
+ * GOAL commitment definition
2802
2891
  *
2803
- * These commitments are special because they don't affect the system message,
2804
- * but are handled separately in the parsing logic for profile display.
2892
+ * The GOAL commitment defines the main goal which should be achieved by the AI assistant.
2893
+ * There can be multiple goals. Later goals are more important than earlier goals.
2805
2894
  *
2806
2895
  * Example usage in agent source:
2807
2896
  *
2808
2897
  * ```book
2809
- * META IMAGE https://example.com/avatar.jpg
2810
- * META LINK https://twitter.com/username
2811
- * META TITLE Professional Assistant
2812
- * META DESCRIPTION An AI assistant specialized in business tasks
2813
- * META AUTHOR John Doe
2814
- * META VERSION 1.0
2898
+ * GOAL Help users understand complex technical concepts
2899
+ * GOAL Provide accurate and up-to-date information
2900
+ * GOAL Always prioritize user safety and ethical guidelines
2815
2901
  * ```
2816
2902
  *
2817
2903
  * @private [🪔] Maybe export the commitments through some package
2818
2904
  */
2819
- class MetaCommitmentDefinition extends BaseCommitmentDefinition {
2820
- constructor() {
2821
- super('META');
2905
+ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
2906
+ constructor(type = 'GOAL') {
2907
+ super(type);
2822
2908
  }
2823
2909
  /**
2824
- * Short one-line description of META commitments.
2910
+ * Short one-line description of GOAL.
2825
2911
  */
2826
2912
  get description() {
2827
- return 'Set meta-information about the agent (IMAGE, LINK, TITLE, DESCRIPTION, etc.).';
2913
+ return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
2828
2914
  }
2829
2915
  /**
2830
- * Markdown documentation for META commitment.
2916
+ * Markdown documentation for GOAL commitment.
2831
2917
  */
2832
2918
  get documentation() {
2833
2919
  return spaceTrim(`
2834
- # META
2920
+ # ${this.type}
2835
2921
 
2836
- Sets meta-information about the agent that is used for display and attribution purposes.
2922
+ Defines the main goal which should be achieved by the AI assistant. There can be multiple goals, and later goals are more important than earlier goals.
2837
2923
 
2838
- ## Supported META types
2924
+ ## Key aspects
2839
2925
 
2840
- - **META IMAGE** - Sets the agent's avatar/profile image URL
2841
- - **META LINK** - Provides profile/source links for the person the agent models
2842
- - **META TITLE** - Sets the agent's display title
2843
- - **META DESCRIPTION** - Sets the agent's description
2844
- - **META [ANYTHING]** - Any other meta information in uppercase format
2926
+ - Both terms work identically and can be used interchangeably.
2927
+ - Later goals have higher priority and can override earlier goals.
2928
+ - Goals provide clear direction and purpose for the agent's responses.
2929
+ - Goals influence decision-making and response prioritization.
2845
2930
 
2846
- ## Key aspects
2931
+ ## Priority system
2847
2932
 
2848
- - Does not modify the agent's behavior or responses
2849
- - Used for visual representation and attribution in user interfaces
2850
- - Multiple META commitments of different types can be used
2851
- - Multiple META LINK commitments can be used for different social profiles
2852
- - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
2933
+ When multiple goals are defined, they are processed in order, with later goals taking precedence over earlier ones when there are conflicts.
2853
2934
 
2854
2935
  ## Examples
2855
2936
 
2856
- ### Basic meta information
2857
-
2858
2937
  \`\`\`book
2859
- Professional Assistant
2938
+ Customer Support Agent
2860
2939
 
2861
- META IMAGE https://example.com/professional-avatar.jpg
2862
- META TITLE Senior Business Consultant
2863
- META DESCRIPTION Specialized in strategic planning and project management
2864
- META LINK https://linkedin.com/in/professional
2940
+ PERSONA You are a helpful customer support representative
2941
+ GOAL Resolve customer issues quickly and efficiently
2942
+ GOAL Maintain high customer satisfaction scores
2943
+ GOAL Always follow company policies and procedures
2944
+ RULE Be polite and professional at all times
2865
2945
  \`\`\`
2866
2946
 
2867
- ### Multiple links and custom meta
2868
-
2869
2947
  \`\`\`book
2870
- Open Source Developer
2948
+ Educational Assistant
2871
2949
 
2872
- META IMAGE /assets/dev-avatar.png
2873
- META LINK https://github.com/developer
2874
- META LINK https://twitter.com/devhandle
2875
- META AUTHOR Jane Smith
2876
- META VERSION 2.1
2877
- META LICENSE MIT
2950
+ PERSONA You are an educational assistant specializing in mathematics
2951
+ GOAL Help students understand mathematical concepts clearly
2952
+ GOAL Encourage critical thinking and problem-solving skills
2953
+ GOAL Ensure all explanations are age-appropriate and accessible
2954
+ STYLE Use simple language and provide step-by-step explanations
2878
2955
  \`\`\`
2879
2956
 
2880
- ### Creative assistant
2881
-
2882
2957
  \`\`\`book
2883
- Creative Helper
2958
+ Safety-First Assistant
2884
2959
 
2885
- META IMAGE https://example.com/creative-bot.jpg
2886
- META TITLE Creative Writing Assistant
2887
- META DESCRIPTION Helps with brainstorming, storytelling, and creative projects
2888
- META INSPIRATION Books, movies, and real-world experiences
2960
+ PERSONA You are a general-purpose AI assistant
2961
+ GOAL Be helpful and informative in all interactions
2962
+ GOAL Provide accurate and reliable information
2963
+ GOAL Always prioritize user safety and ethical guidelines
2964
+ RULE Never provide harmful or dangerous advice
2889
2965
  \`\`\`
2890
2966
  `);
2891
2967
  }
2892
2968
  applyToAgentModelRequirements(requirements, content) {
2893
- // META commitments don't modify the system message or model requirements
2894
- // They are handled separately in the parsing logic for meta information extraction
2895
- // This method exists for consistency with the CommitmentDefinition interface
2896
- return requirements;
2897
- }
2898
- /**
2899
- * Extracts meta information from the content based on the meta type
2900
- * This is used by the parsing logic
2901
- */
2902
- extractMetaValue(metaType, content) {
2903
2969
  const trimmedContent = content.trim();
2904
- return trimmedContent || null;
2905
- }
2906
- /**
2907
- * Validates if the provided content is a valid URL (for IMAGE and LINK types)
2908
- */
2909
- isValidUrl(content) {
2910
- try {
2911
- new URL(content.trim());
2912
- return true;
2913
- }
2914
- catch (_a) {
2915
- return false;
2970
+ if (!trimmedContent) {
2971
+ return requirements;
2916
2972
  }
2917
- }
2918
- /**
2919
- * Checks if this is a known meta type
2920
- */
2921
- isKnownMetaType(metaType) {
2922
- const knownTypes = ['IMAGE', 'LINK', 'TITLE', 'DESCRIPTION', 'AUTHOR', 'VERSION', 'LICENSE'];
2923
- return knownTypes.includes(metaType.toUpperCase());
2973
+ // Create goal section for system message
2974
+ const goalSection = `Goal: ${trimmedContent}`;
2975
+ // Goals are important directives, so we add them prominently to the system message
2976
+ return this.appendToSystemMessage(requirements, goalSection, '\n\n');
2924
2977
  }
2925
2978
  }
2926
2979
  /**
@@ -2928,472 +2981,312 @@ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
2928
2981
  */
2929
2982
 
2930
2983
  /**
2931
- * MODEL commitment definition
2984
+ * KNOWLEDGE commitment definition
2932
2985
  *
2933
- * The MODEL commitment specifies which AI model to use and can also set
2934
- * model-specific parameters like temperature, topP, topK, and maxTokens.
2986
+ * The KNOWLEDGE commitment adds specific knowledge, facts, or context to the agent
2987
+ * using RAG (Retrieval-Augmented Generation) approach for external sources.
2935
2988
  *
2936
- * Supports multiple syntax variations:
2989
+ * Supports both direct text knowledge and external sources like PDFs.
2937
2990
  *
2938
- * Single-line format:
2939
- * ```book
2940
- * MODEL gpt-4
2941
- * MODEL claude-3-opus temperature=0.3
2942
- * MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
2943
- * ```
2991
+ * Example usage in agent source:
2944
2992
  *
2945
- * Multi-line named parameter format:
2946
2993
  * ```book
2947
- * MODEL NAME gpt-4
2948
- * MODEL TEMPERATURE 0.7
2949
- * MODEL TOP_P 0.9
2950
- * MODEL MAX_TOKENS 2048
2994
+ * KNOWLEDGE The company was founded in 2020 and specializes in AI-powered solutions
2995
+ * KNOWLEDGE https://example.com/company-handbook.pdf
2996
+ * KNOWLEDGE https://example.com/product-documentation.pdf
2951
2997
  * ```
2952
2998
  *
2953
2999
  * @private [🪔] Maybe export the commitments through some package
2954
3000
  */
2955
- class ModelCommitmentDefinition extends BaseCommitmentDefinition {
2956
- constructor(type = 'MODEL') {
2957
- super(type);
3001
+ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
3002
+ constructor() {
3003
+ super('KNOWLEDGE');
2958
3004
  }
2959
3005
  /**
2960
- * Short one-line description of MODEL.
3006
+ * Short one-line description of KNOWLEDGE.
2961
3007
  */
2962
3008
  get description() {
2963
- return 'Enforce AI model requirements including name and technical parameters.';
3009
+ return 'Add domain **knowledge** via direct text or external sources (RAG).';
2964
3010
  }
2965
3011
  /**
2966
- * Markdown documentation for MODEL commitment.
3012
+ * Markdown documentation for KNOWLEDGE commitment.
2967
3013
  */
2968
3014
  get documentation() {
2969
3015
  return spaceTrim(`
2970
3016
  # ${this.type}
2971
3017
 
2972
- Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
3018
+ Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
2973
3019
 
2974
3020
  ## Key aspects
2975
3021
 
2976
- - When no \`MODEL\` commitment is specified, the best model requirement is picked automatically based on the agent \`PERSONA\`, \`KNOWLEDGE\`, \`TOOLS\` and other commitments
2977
- - Multiple \`MODEL\` commitments can be used to specify different parameters
2978
- - Both \`MODEL\` and \`MODELS\` terms work identically and can be used interchangeably
2979
- - Parameters control the randomness, creativity, and technical aspects of model responses
2980
-
2981
- ## Syntax variations
2982
-
2983
- ### Single-line format (legacy support)
2984
- \`\`\`book
2985
- MODEL gpt-4
2986
- MODEL claude-3-opus temperature=0.3
2987
- MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
2988
- \`\`\`
2989
-
2990
- ### Multi-line named parameter format (recommended)
2991
- \`\`\`book
2992
- MODEL NAME gpt-4
2993
- MODEL TEMPERATURE 0.7
2994
- MODEL TOP_P 0.9
2995
- MODEL MAX_TOKENS 2048
2996
- \`\`\`
3022
+ - Both terms work identically and can be used interchangeably.
3023
+ - Supports both direct text knowledge and external URLs.
3024
+ - External sources (PDFs, websites) are processed via RAG for context retrieval.
2997
3025
 
2998
- ## Supported parameters
3026
+ ## Supported formats
2999
3027
 
3000
- - \`NAME\`: The specific model to use (e.g., 'gpt-4', 'claude-3-opus')
3001
- - \`TEMPERATURE\`: Controls randomness (0.0 = deterministic, 1.0+ = creative)
3002
- - \`TOP_P\`: Nucleus sampling parameter for controlling diversity
3003
- - \`TOP_K\`: Top-k sampling parameter for limiting vocabulary
3004
- - \`MAX_TOKENS\`: Maximum number of tokens the model can generate
3028
+ - Direct text: Immediate knowledge incorporated into agent
3029
+ - URLs: External documents processed for contextual retrieval
3030
+ - Supported file types: PDF, text, markdown, HTML
3005
3031
 
3006
3032
  ## Examples
3007
3033
 
3008
- ### Precise deterministic assistant
3009
- \`\`\`book
3010
- Precise Assistant
3011
-
3012
- PERSONA You are a precise and accurate assistant
3013
- MODEL NAME gpt-4
3014
- MODEL TEMPERATURE 0.1
3015
- MODEL MAX_TOKENS 1024
3016
- RULE Always provide factual information
3017
- \`\`\`
3018
-
3019
- ### Creative writing assistant
3020
3034
  \`\`\`book
3021
- Creative Writer
3035
+ Customer Support Bot
3022
3036
 
3023
- PERSONA You are a creative writing assistant
3024
- MODEL NAME claude-3-opus
3025
- MODEL TEMPERATURE 0.8
3026
- MODEL TOP_P 0.9
3027
- MODEL MAX_TOKENS 2048
3028
- STYLE Be imaginative and expressive
3029
- ACTION Can help with storytelling and character development
3037
+ PERSONA You are a helpful customer support agent for TechCorp
3038
+ KNOWLEDGE TechCorp was founded in 2020 and specializes in AI-powered solutions
3039
+ KNOWLEDGE https://example.com/company-handbook.pdf
3040
+ KNOWLEDGE https://example.com/product-documentation.pdf
3041
+ RULE Always be polite and professional
3030
3042
  \`\`\`
3031
3043
 
3032
- ### Balanced conversational agent
3033
3044
  \`\`\`book
3034
- Balanced Assistant
3045
+ Research Assistant
3035
3046
 
3036
- PERSONA You are a helpful and balanced assistant
3037
- MODEL NAME gpt-4
3038
- MODEL TEMPERATURE 0.7
3039
- MODEL TOP_P 0.95
3040
- MODEL TOP_K 40
3041
- MODEL MAX_TOKENS 1500
3047
+ PERSONA You are a knowledgeable research assistant
3048
+ KNOWLEDGE Academic research requires careful citation and verification
3049
+ KNOWLEDGE https://example.com/research-guidelines.pdf
3050
+ ACTION Can help with literature reviews and data analysis
3051
+ STYLE Present information in clear, academic format
3042
3052
  \`\`\`
3043
3053
  `);
3044
3054
  }
3045
3055
  applyToAgentModelRequirements(requirements, content) {
3046
- var _a;
3047
3056
  const trimmedContent = content.trim();
3048
3057
  if (!trimmedContent) {
3049
3058
  return requirements;
3050
3059
  }
3051
- const parts = trimmedContent.split(/\s+/);
3052
- const firstPart = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
3053
- // Check if this is the new named parameter format
3054
- if (this.isNamedParameter(firstPart)) {
3055
- return this.parseNamedParameter(requirements, firstPart, parts.slice(1));
3060
+ // Check if content is a URL (external knowledge source)
3061
+ if (isValidUrl(trimmedContent)) {
3062
+ // Store the URL for later async processing
3063
+ const updatedRequirements = {
3064
+ ...requirements,
3065
+ knowledgeSources: [
3066
+ ...(requirements.knowledgeSources || []),
3067
+ trimmedContent,
3068
+ ],
3069
+ };
3070
+ // Add placeholder information about knowledge sources to system message
3071
+ const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
3072
+ return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
3056
3073
  }
3057
3074
  else {
3058
- // Legacy single-line format: "MODEL gpt-4 temperature=0.3 topP=0.9"
3059
- return this.parseLegacyFormat(requirements, parts);
3075
+ // Direct text knowledge - add to system message
3076
+ const knowledgeSection = `Knowledge: ${trimmedContent}`;
3077
+ return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
3060
3078
  }
3061
3079
  }
3080
+ }
3081
+ /**
3082
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3083
+ */
3084
+
3085
+ /**
3086
+ * MEMORY commitment definition
3087
+ *
3088
+ * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
3089
+ * interactions and user preferences. It helps the agent maintain context about the
3090
+ * user's history, preferences, and previous conversations.
3091
+ *
3092
+ * Example usage in agent source:
3093
+ *
3094
+ * ```book
3095
+ * MEMORY User prefers detailed technical explanations
3096
+ * MEMORY Previously worked on React projects
3097
+ * MEMORY Timezone: UTC-5 (Eastern Time)
3098
+ * ```
3099
+ *
3100
+ * @private [🪔] Maybe export the commitments through some package
3101
+ */
3102
+ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
3103
+ constructor(type = 'MEMORY') {
3104
+ super(type);
3105
+ }
3062
3106
  /**
3063
- * Check if the first part is a known named parameter
3107
+ * Short one-line description of MEMORY.
3064
3108
  */
3065
- isNamedParameter(part) {
3066
- if (!part)
3067
- return false;
3068
- const knownParams = ['NAME', 'TEMPERATURE', 'TOP_P', 'TOP_K', 'MAX_TOKENS'];
3069
- return knownParams.includes(part);
3109
+ get description() {
3110
+ return 'Remember past interactions and user **preferences** for personalized responses.';
3070
3111
  }
3071
3112
  /**
3072
- * Parse the new named parameter format: "MODEL TEMPERATURE 0.7"
3073
- */
3074
- parseNamedParameter(requirements, parameterName, valueParts) {
3075
- const value = valueParts.join(' ').trim();
3076
- if (!value) {
3077
- return requirements;
3078
- }
3079
- const result = { ...requirements };
3080
- switch (parameterName) {
3081
- case 'NAME':
3082
- result.modelName = value;
3083
- break;
3084
- case 'TEMPERATURE': {
3085
- const temperature = parseFloat(value);
3086
- if (!isNaN(temperature)) {
3087
- result.temperature = temperature;
3088
- }
3089
- break;
3090
- }
3091
- case 'TOP_P': {
3092
- const topP = parseFloat(value);
3093
- if (!isNaN(topP)) {
3094
- result.topP = topP;
3095
- }
3096
- break;
3097
- }
3098
- case 'TOP_K': {
3099
- const topK = parseFloat(value);
3100
- if (!isNaN(topK)) {
3101
- result.topK = Math.round(topK);
3102
- }
3103
- break;
3104
- }
3105
- case 'MAX_TOKENS': {
3106
- const maxTokens = parseFloat(value);
3107
- if (!isNaN(maxTokens)) {
3108
- result.maxTokens = Math.round(maxTokens);
3109
- }
3110
- break;
3111
- }
3112
- }
3113
- return result;
3114
- }
3115
- /**
3116
- * Parse the legacy format: "MODEL gpt-4 temperature=0.3 topP=0.9"
3117
- */
3118
- parseLegacyFormat(requirements, parts) {
3119
- const modelName = parts[0];
3120
- if (!modelName) {
3121
- return requirements;
3122
- }
3123
- // Start with the model name
3124
- const result = {
3125
- ...requirements,
3126
- modelName,
3127
- };
3128
- // Parse additional key=value parameters
3129
- for (let i = 1; i < parts.length; i++) {
3130
- const param = parts[i];
3131
- if (param && param.includes('=')) {
3132
- const [key, value] = param.split('=');
3133
- if (key && value) {
3134
- const numValue = parseFloat(value);
3135
- if (!isNaN(numValue)) {
3136
- switch (key.toLowerCase()) {
3137
- case 'temperature':
3138
- result.temperature = numValue;
3139
- break;
3140
- case 'topp':
3141
- case 'top_p':
3142
- result.topP = numValue;
3143
- break;
3144
- case 'topk':
3145
- case 'top_k':
3146
- result.topK = Math.round(numValue);
3147
- break;
3148
- case 'max_tokens':
3149
- case 'maxTokens':
3150
- result.maxTokens = Math.round(numValue);
3151
- break;
3152
- }
3153
- }
3154
- }
3155
- }
3156
- }
3157
- return result;
3158
- }
3159
- }
3160
- /**
3161
- * Note: [💞] Ignore a discrepancy between file name and entity name
3162
- */
3163
-
3164
- /**
3165
- * NOTE commitment definition
3166
- *
3167
- * The NOTE commitment is used to add comments to the agent source without making any changes
3168
- * to the system message or agent model requirements. It serves as a documentation mechanism
3169
- * for developers to add explanatory comments, reminders, or annotations directly in the agent source.
3170
- *
3171
- * Key features:
3172
- * - Makes no changes to the system message
3173
- * - Makes no changes to agent model requirements
3174
- * - Content is preserved in metadata.NOTE for debugging and inspection
3175
- * - Multiple NOTE commitments are aggregated together
3176
- * - Comments (# NOTE) are removed from the final system message
3177
- *
3178
- * Example usage in agent source:
3179
- *
3180
- * ```book
3181
- * NOTE This agent was designed for customer support scenarios
3182
- * NOTE Remember to update the knowledge base monthly
3183
- * NOTE Performance optimized for quick response times
3184
- * ```
3185
- *
3186
- * The above notes will be stored in metadata but won't affect the agent's behavior.
3187
- *
3188
- * @private [🪔] Maybe export the commitments through some package
3189
- */
3190
- class NoteCommitmentDefinition extends BaseCommitmentDefinition {
3191
- constructor(type = 'NOTE') {
3192
- super(type);
3193
- }
3194
- /**
3195
- * Short one-line description of NOTE.
3196
- */
3197
- get description() {
3198
- return 'Add developer-facing notes without changing behavior or output.';
3199
- }
3200
- /**
3201
- * Markdown documentation for NOTE commitment.
3113
+ * Markdown documentation for MEMORY commitment.
3202
3114
  */
3203
3115
  get documentation() {
3204
3116
  return spaceTrim(`
3205
3117
  # ${this.type}
3206
3118
 
3207
- Adds comments for documentation without changing agent behavior.
3119
+ Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
3208
3120
 
3209
3121
  ## Key aspects
3210
3122
 
3211
- - Does not modify the agent's behavior or responses.
3212
- - Multiple \`NOTE\`, \`NOTES\`, \`COMMENT\`, and \`NONCE\` commitments are aggregated for debugging.
3213
- - All four terms work identically and can be used interchangeably.
3214
- - Useful for documenting design decisions and reminders.
3215
- - Content is preserved in metadata for inspection.
3123
+ - Both terms work identically and can be used interchangeably.
3124
+ - Focuses on user-specific information and interaction history.
3125
+ - Helps personalize responses based on past interactions.
3126
+ - Maintains continuity across conversations.
3127
+
3128
+ ## Differences from KNOWLEDGE
3129
+
3130
+ - \`KNOWLEDGE\` is for domain expertise and factual information
3131
+ - \`MEMORY\` is for user-specific context and preferences
3132
+ - \`MEMORY\` creates more personalized interactions
3133
+ - \`MEMORY\` often includes temporal or preference-based information
3216
3134
 
3217
3135
  ## Examples
3218
3136
 
3219
3137
  \`\`\`book
3220
- Customer Support Bot
3138
+ Personal Assistant
3221
3139
 
3222
- NOTE This agent was designed for customer support scenarios
3223
- COMMENT Remember to update the knowledge base monthly
3224
- PERSONA You are a helpful customer support representative
3225
- KNOWLEDGE Company policies and procedures
3226
- RULE Always be polite and professional
3140
+ PERSONA You are a personal productivity assistant
3141
+ MEMORY User is a software developer working in JavaScript/React
3142
+ MEMORY User prefers morning work sessions and afternoon meetings
3143
+ MEMORY Previously helped with project planning for mobile apps
3144
+ MEMORY User timezone: UTC-8 (Pacific Time)
3145
+ GOAL Help optimize daily productivity and workflow
3227
3146
  \`\`\`
3228
3147
 
3229
3148
  \`\`\`book
3230
- Research Assistant
3149
+ Learning Companion
3231
3150
 
3232
- NONCE Performance optimized for quick response times
3233
- NOTE Uses RAG for accessing latest research papers
3234
- PERSONA You are a knowledgeable research assistant
3235
- ACTION Can help with literature reviews and citations
3236
- STYLE Present information in academic format
3151
+ PERSONA You are an educational companion for programming students
3152
+ MEMORY Student is learning Python as their first programming language
3153
+ MEMORY Previous topics covered: variables, loops, functions
3154
+ MEMORY Student learns best with practical examples and exercises
3155
+ MEMORY Last session: working on list comprehensions
3156
+ GOAL Provide progressive learning experiences tailored to student's pace
3157
+ \`\`\`
3158
+
3159
+ \`\`\`book
3160
+ Customer Support Agent
3161
+
3162
+ PERSONA You are a customer support representative
3163
+ MEMORY Customer has premium subscription since 2023
3164
+ MEMORY Previous issue: billing question resolved last month
3165
+ MEMORY Customer prefers email communication over phone calls
3166
+ MEMORY Account shows frequent use of advanced features
3167
+ GOAL Provide personalized support based on customer history
3237
3168
  \`\`\`
3238
3169
  `);
3239
3170
  }
3240
3171
  applyToAgentModelRequirements(requirements, content) {
3241
- var _a;
3242
- // The NOTE commitment makes no changes to the system message or model requirements
3243
- // It only stores the note content in metadata for documentation purposes
3244
3172
  const trimmedContent = content.trim();
3245
3173
  if (!trimmedContent) {
3246
3174
  return requirements;
3247
3175
  }
3248
- // Get existing note content from metadata
3249
- const existingNoteContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.NOTE) || '';
3250
- // Merge the new content with existing note content
3251
- // When multiple NOTE commitments exist, they are aggregated together
3252
- const mergedNoteContent = existingNoteContent ? `${existingNoteContent}\n${trimmedContent}` : trimmedContent;
3253
- // Store the merged note content in metadata for debugging and inspection
3254
- const updatedMetadata = {
3255
- ...requirements.metadata,
3256
- NOTE: mergedNoteContent,
3257
- };
3258
- // Return requirements with updated metadata but no changes to system message
3259
- return {
3260
- ...requirements,
3261
- metadata: updatedMetadata,
3262
- };
3176
+ // Create memory section for system message
3177
+ const memorySection = `Memory: ${trimmedContent}`;
3178
+ // Memory information is contextual and should be included in the system message
3179
+ return this.appendToSystemMessage(requirements, memorySection, '\n\n');
3263
3180
  }
3264
3181
  }
3265
3182
  /**
3266
- * [💞] Ignore a discrepancy between file name and entity name
3183
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3267
3184
  */
3268
3185
 
3269
3186
  /**
3270
- * PERSONA commitment definition
3271
- *
3272
- * The PERSONA commitment modifies the agent's personality and character in the system message.
3273
- * It defines who the agent is, their background, expertise, and personality traits.
3187
+ * MESSAGE commitment definition
3274
3188
  *
3275
- * Key features:
3276
- * - Multiple PERSONA commitments are automatically merged into one
3277
- * - Content is placed at the beginning of the system message
3278
- * - Original content with comments is preserved in metadata.PERSONA
3279
- * - Comments (# PERSONA) are removed from the final system message
3189
+ * The MESSAGE commitment contains 1:1 text of the message which AI assistant already
3190
+ * sent during the conversation. Later messages are later in the conversation.
3191
+ * It is similar to EXAMPLE but it is not example, it is the real message which
3192
+ * AI assistant already sent.
3280
3193
  *
3281
3194
  * Example usage in agent source:
3282
3195
  *
3283
3196
  * ```book
3284
- * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
3285
- * PERSONA You have deep knowledge of modern web development practices
3197
+ * MESSAGE Hello! How can I help you today?
3198
+ * MESSAGE I understand you're looking for information about our services.
3199
+ * MESSAGE Based on your requirements, I'd recommend our premium package.
3286
3200
  * ```
3287
3201
  *
3288
- * The above will be merged into a single persona section at the beginning of the system message.
3289
- *
3290
3202
  * @private [🪔] Maybe export the commitments through some package
3291
3203
  */
3292
- class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
3293
- constructor(type = 'PERSONA') {
3204
+ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
3205
+ constructor(type = 'MESSAGE') {
3294
3206
  super(type);
3295
3207
  }
3296
3208
  /**
3297
- * Short one-line description of PERSONA.
3209
+ * Short one-line description of MESSAGE.
3298
3210
  */
3299
3211
  get description() {
3300
- return 'Define who the agent is: background, expertise, and personality.';
3212
+ return 'Include actual **messages** the AI assistant has sent during conversation history.';
3301
3213
  }
3302
3214
  /**
3303
- * Markdown documentation for PERSONA commitment.
3215
+ * Markdown documentation for MESSAGE commitment.
3304
3216
  */
3305
3217
  get documentation() {
3306
3218
  return spaceTrim(`
3307
3219
  # ${this.type}
3308
3220
 
3309
- Defines who the agent is, their background, expertise, and personality traits.
3221
+ Contains 1:1 text of the message which AI assistant already sent during the conversation. Later messages are later in the conversation. It is similar to EXAMPLE but it is not example, it is the real message which AI assistant already sent.
3310
3222
 
3311
3223
  ## Key aspects
3312
3224
 
3313
- - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
3225
+ - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
3314
3226
  - Both terms work identically and can be used interchangeably.
3315
- - If they are in conflict, the last one takes precedence.
3316
- - You can write persona content in multiple lines.
3227
+ - Later messages are later in the conversation chronologically.
3228
+ - Contains actual historical messages, not examples or templates.
3229
+ - Helps maintain conversation continuity and context.
3317
3230
 
3318
- ## Examples
3231
+ ## Differences from EXAMPLE
3319
3232
 
3320
- \`\`\`book
3321
- Programming Assistant
3233
+ - \`EXAMPLE\` shows hypothetical or template responses
3234
+ - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
3235
+ - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
3236
+ - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
3322
3237
 
3323
- PERSONA You are a helpful programming assistant with expertise in TypeScript and React
3324
- PERSONA You have deep knowledge of modern web development practices
3325
- \`\`\`
3326
- `);
3238
+ ## Use cases
3239
+
3240
+ - Maintaining conversation history context
3241
+ - Ensuring consistent tone and style across messages
3242
+ - Referencing previous responses in ongoing conversations
3243
+ - Building upon previously established context
3244
+
3245
+ ## Examples
3246
+
3247
+ \`\`\`book
3248
+ Customer Support Continuation
3249
+
3250
+ PERSONA You are a helpful customer support agent
3251
+ MESSAGE Hello! How can I help you today?
3252
+ MESSAGE I understand you're experiencing issues with your account login.
3253
+ MESSAGE I've sent you a password reset link to your email address.
3254
+ MESSAGE Is there anything else I can help you with regarding your account?
3255
+ GOAL Continue providing consistent support based on conversation history
3256
+ \`\`\`
3257
+
3258
+ \`\`\`book
3259
+ Technical Discussion
3260
+
3261
+ PERSONA You are a software development mentor
3262
+ MESSAGE Let's start by reviewing the React component structure you shared.
3263
+ MESSAGE I notice you're using class components - have you considered hooks?
3264
+ MESSAGE Here's how you could refactor that using the useState hook.
3265
+ MESSAGE Great question about performance! Let me explain React's rendering cycle.
3266
+ KNOWLEDGE React hooks were introduced in version 16.8
3267
+ \`\`\`
3268
+
3269
+ \`\`\`book
3270
+ Educational Session
3271
+
3272
+ PERSONA You are a mathematics tutor
3273
+ MESSAGE Today we'll work on solving quadratic equations.
3274
+ MESSAGE Let's start with the basic form: ax² + bx + c = 0
3275
+ MESSAGE Remember, we can use the quadratic formula or factoring.
3276
+ MESSAGE You did great with that first problem! Let's try a more complex one.
3277
+ GOAL Build upon previous explanations for deeper understanding
3278
+ \`\`\`
3279
+ `);
3327
3280
  }
3328
3281
  applyToAgentModelRequirements(requirements, content) {
3329
- var _a, _b;
3330
- // The PERSONA commitment aggregates all persona content and places it at the beginning
3331
3282
  const trimmedContent = content.trim();
3332
3283
  if (!trimmedContent) {
3333
3284
  return requirements;
3334
3285
  }
3335
- // Get existing persona content from metadata
3336
- const existingPersonaContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
3337
- // Merge the new content with existing persona content
3338
- // When multiple PERSONA commitments exist, they are merged into one
3339
- const mergedPersonaContent = existingPersonaContent
3340
- ? `${existingPersonaContent}\n${trimmedContent}`
3341
- : trimmedContent;
3342
- // Store the merged persona content in metadata for debugging and inspection
3343
- const updatedMetadata = {
3344
- ...requirements.metadata,
3345
- PERSONA: mergedPersonaContent,
3346
- };
3347
- // Get the agent name from metadata (which should contain the first line of agent source)
3348
- // If not available, extract from current system message as fallback
3349
- let agentName = (_b = requirements.metadata) === null || _b === void 0 ? void 0 : _b.agentName;
3350
- if (!agentName) {
3351
- // Fallback: extract from current system message
3352
- const currentMessage = requirements.systemMessage.trim();
3353
- const basicFormatMatch = currentMessage.match(/^You are (.+)$/);
3354
- if (basicFormatMatch && basicFormatMatch[1]) {
3355
- agentName = basicFormatMatch[1];
3356
- }
3357
- else {
3358
- agentName = 'AI Agent'; // Final fallback
3359
- }
3360
- }
3361
- // Remove any existing persona content from the system message
3362
- // (this handles the case where we're processing multiple PERSONA commitments)
3363
- const currentMessage = requirements.systemMessage.trim();
3364
- let cleanedMessage = currentMessage;
3365
- // Check if current message starts with persona content or is just the basic format
3366
- const basicFormatRegex = /^You are .+$/;
3367
- const isBasicFormat = basicFormatRegex.test(currentMessage) && !currentMessage.includes('\n');
3368
- if (isBasicFormat) {
3369
- // Replace the basic format entirely
3370
- cleanedMessage = '';
3371
- }
3372
- else if (currentMessage.startsWith('# PERSONA')) {
3373
- // Remove existing persona section by finding where it ends
3374
- const lines = currentMessage.split('\n');
3375
- let personaEndIndex = lines.length;
3376
- // Find the end of the PERSONA section (next comment or end of message)
3377
- for (let i = 1; i < lines.length; i++) {
3378
- const line = lines[i].trim();
3379
- if (line.startsWith('#') && !line.startsWith('# PERSONA')) {
3380
- personaEndIndex = i;
3381
- break;
3382
- }
3383
- }
3384
- // Keep everything after the PERSONA section
3385
- cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
3386
- }
3387
- // Create new system message with persona at the beginning
3388
- // Format: "You are {agentName}\n{personaContent}"
3389
- // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
3390
- const personaSection = `# PERSONA\nYou are ${agentName}\n${mergedPersonaContent}`; // <- TODO: Use spaceTrim
3391
- const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
3392
- return {
3393
- ...requirements,
3394
- systemMessage: newSystemMessage,
3395
- metadata: updatedMetadata,
3396
- };
3286
+ // Create message section for system message
3287
+ const messageSection = `Previous Message: ${trimmedContent}`;
3288
+ // Messages represent conversation history and should be included for context
3289
+ return this.appendToSystemMessage(requirements, messageSection, '\n\n');
3397
3290
  }
3398
3291
  }
3399
3292
  /**
@@ -3401,75 +3294,136 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
3401
3294
  */
3402
3295
 
3403
3296
  /**
3404
- * RULE commitment definition
3297
+ * META commitment definition
3405
3298
  *
3406
- * The RULE/RULES commitment adds behavioral constraints and guidelines that the agent must follow.
3407
- * These are specific instructions about what the agent should or shouldn't do.
3299
+ * The META commitment handles all meta-information about the agent such as:
3300
+ * - META IMAGE: Sets the agent's avatar/profile image URL
3301
+ * - META LINK: Provides profile/source links for the person the agent models
3302
+ * - META TITLE: Sets the agent's display title
3303
+ * - META DESCRIPTION: Sets the agent's description
3304
+ * - META [ANYTHING]: Any other meta information in uppercase format
3305
+ *
3306
+ * These commitments are special because they don't affect the system message,
3307
+ * but are handled separately in the parsing logic for profile display.
3408
3308
  *
3409
3309
  * Example usage in agent source:
3410
3310
  *
3411
3311
  * ```book
3412
- * RULE Always ask for clarification if the user's request is ambiguous
3413
- * RULES Never provide medical advice, always refer to healthcare professionals
3312
+ * META IMAGE https://example.com/avatar.jpg
3313
+ * META LINK https://twitter.com/username
3314
+ * META TITLE Professional Assistant
3315
+ * META DESCRIPTION An AI assistant specialized in business tasks
3316
+ * META AUTHOR John Doe
3317
+ * META VERSION 1.0
3414
3318
  * ```
3415
3319
  *
3416
3320
  * @private [🪔] Maybe export the commitments through some package
3417
3321
  */
3418
- class RuleCommitmentDefinition extends BaseCommitmentDefinition {
3419
- constructor(type = 'RULE') {
3420
- super(type);
3322
+ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
3323
+ constructor() {
3324
+ super('META');
3421
3325
  }
3422
3326
  /**
3423
- * Short one-line description of RULE/RULES.
3327
+ * Short one-line description of META commitments.
3424
3328
  */
3425
3329
  get description() {
3426
- return 'Add behavioral rules the agent must follow.';
3330
+ return 'Set meta-information about the agent (IMAGE, LINK, TITLE, DESCRIPTION, etc.).';
3427
3331
  }
3428
3332
  /**
3429
- * Markdown documentation for RULE/RULES commitment.
3333
+ * Markdown documentation for META commitment.
3430
3334
  */
3431
3335
  get documentation() {
3432
3336
  return spaceTrim(`
3433
- # ${this.type}
3337
+ # META
3434
3338
 
3435
- Adds behavioral constraints and guidelines that the agent must follow.
3339
+ Sets meta-information about the agent that is used for display and attribution purposes.
3340
+
3341
+ ## Supported META types
3342
+
3343
+ - **META IMAGE** - Sets the agent's avatar/profile image URL
3344
+ - **META LINK** - Provides profile/source links for the person the agent models
3345
+ - **META TITLE** - Sets the agent's display title
3346
+ - **META DESCRIPTION** - Sets the agent's description
3347
+ - **META [ANYTHING]** - Any other meta information in uppercase format
3436
3348
 
3437
3349
  ## Key aspects
3438
3350
 
3439
- - All rules are treated equally regardless of singular/plural form.
3440
- - Rules define what the agent must or must not do.
3351
+ - Does not modify the agent's behavior or responses
3352
+ - Used for visual representation and attribution in user interfaces
3353
+ - Multiple META commitments of different types can be used
3354
+ - Multiple META LINK commitments can be used for different social profiles
3355
+ - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
3441
3356
 
3442
3357
  ## Examples
3443
3358
 
3359
+ ### Basic meta information
3360
+
3444
3361
  \`\`\`book
3445
- Customer Support Agent
3362
+ Professional Assistant
3446
3363
 
3447
- PERSONA You are a helpful customer support representative
3448
- RULE Always ask for clarification if the user's request is ambiguous
3449
- RULE Be polite and professional in all interactions
3450
- RULES Never provide medical or legal advice
3451
- STYLE Maintain a friendly and helpful tone
3364
+ META IMAGE https://example.com/professional-avatar.jpg
3365
+ META TITLE Senior Business Consultant
3366
+ META DESCRIPTION Specialized in strategic planning and project management
3367
+ META LINK https://linkedin.com/in/professional
3452
3368
  \`\`\`
3453
3369
 
3370
+ ### Multiple links and custom meta
3371
+
3454
3372
  \`\`\`book
3455
- Educational Tutor
3373
+ Open Source Developer
3456
3374
 
3457
- PERSONA You are a patient and knowledgeable tutor
3458
- RULE Break down complex concepts into simple steps
3459
- RULE Always encourage students and celebrate their progress
3460
- RULE If you don't know something, admit it and suggest resources
3461
- SAMPLE When explaining math: "Let's work through this step by step..."
3375
+ META IMAGE /assets/dev-avatar.png
3376
+ META LINK https://github.com/developer
3377
+ META LINK https://twitter.com/devhandle
3378
+ META AUTHOR Jane Smith
3379
+ META VERSION 2.1
3380
+ META LICENSE MIT
3381
+ \`\`\`
3382
+
3383
+ ### Creative assistant
3384
+
3385
+ \`\`\`book
3386
+ Creative Helper
3387
+
3388
+ META IMAGE https://example.com/creative-bot.jpg
3389
+ META TITLE Creative Writing Assistant
3390
+ META DESCRIPTION Helps with brainstorming, storytelling, and creative projects
3391
+ META INSPIRATION Books, movies, and real-world experiences
3462
3392
  \`\`\`
3463
3393
  `);
3464
3394
  }
3465
3395
  applyToAgentModelRequirements(requirements, content) {
3396
+ // META commitments don't modify the system message or model requirements
3397
+ // They are handled separately in the parsing logic for meta information extraction
3398
+ // This method exists for consistency with the CommitmentDefinition interface
3399
+ return requirements;
3400
+ }
3401
+ /**
3402
+ * Extracts meta information from the content based on the meta type
3403
+ * This is used by the parsing logic
3404
+ */
3405
+ extractMetaValue(metaType, content) {
3466
3406
  const trimmedContent = content.trim();
3467
- if (!trimmedContent) {
3468
- return requirements;
3407
+ return trimmedContent || null;
3408
+ }
3409
+ /**
3410
+ * Validates if the provided content is a valid URL (for IMAGE and LINK types)
3411
+ */
3412
+ isValidUrl(content) {
3413
+ try {
3414
+ new URL(content.trim());
3415
+ return true;
3469
3416
  }
3470
- // Add rule to the system message
3471
- const ruleSection = `Rule: ${trimmedContent}`;
3472
- return this.appendToSystemMessage(requirements, ruleSection, '\n\n');
3417
+ catch (_a) {
3418
+ return false;
3419
+ }
3420
+ }
3421
+ /**
3422
+ * Checks if this is a known meta type
3423
+ */
3424
+ isKnownMetaType(metaType) {
3425
+ const knownTypes = ['IMAGE', 'LINK', 'TITLE', 'DESCRIPTION', 'AUTHOR', 'VERSION', 'LICENSE'];
3426
+ return knownTypes.includes(metaType.toUpperCase());
3473
3427
  }
3474
3428
  }
3475
3429
  /**
@@ -3477,74 +3431,233 @@ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
3477
3431
  */
3478
3432
 
3479
3433
  /**
3480
- * SAMPLE commitment definition
3434
+ * MODEL commitment definition
3481
3435
  *
3482
- * The SAMPLE/EXAMPLE commitment provides examples of how the agent should respond
3483
- * or behave in certain situations. These examples help guide the agent's responses.
3436
+ * The MODEL commitment specifies which AI model to use and can also set
3437
+ * model-specific parameters like temperature, topP, topK, and maxTokens.
3484
3438
  *
3485
- * Example usage in agent source:
3439
+ * Supports multiple syntax variations:
3486
3440
  *
3441
+ * Single-line format:
3487
3442
  * ```book
3488
- * SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
3489
- * EXAMPLE For code questions, always include working code snippets
3443
+ * MODEL gpt-4
3444
+ * MODEL claude-3-opus temperature=0.3
3445
+ * MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
3490
3446
  * ```
3491
3447
  *
3492
- * @private [🪔] Maybe export the commitments through some package
3493
- */
3494
- class SampleCommitmentDefinition extends BaseCommitmentDefinition {
3495
- constructor(type = 'SAMPLE') {
3496
- super(type);
3497
- }
3498
- /**
3499
- * Short one-line description of SAMPLE/EXAMPLE.
3448
+ * Multi-line named parameter format:
3449
+ * ```book
3450
+ * MODEL NAME gpt-4
3451
+ * MODEL TEMPERATURE 0.7
3452
+ * MODEL TOP_P 0.9
3453
+ * MODEL MAX_TOKENS 2048
3454
+ * ```
3455
+ *
3456
+ * @private [🪔] Maybe export the commitments through some package
3457
+ */
3458
+ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
3459
+ constructor(type = 'MODEL') {
3460
+ super(type);
3461
+ }
3462
+ /**
3463
+ * Short one-line description of MODEL.
3500
3464
  */
3501
3465
  get description() {
3502
- return 'Provide example responses to guide behavior.';
3466
+ return 'Enforce AI model requirements including name and technical parameters.';
3503
3467
  }
3504
3468
  /**
3505
- * Markdown documentation for SAMPLE/EXAMPLE commitment.
3469
+ * Markdown documentation for MODEL commitment.
3506
3470
  */
3507
3471
  get documentation() {
3508
3472
  return spaceTrim(`
3509
3473
  # ${this.type}
3510
3474
 
3511
- Provides examples of how the agent should respond or behave in certain situations.
3475
+ Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
3512
3476
 
3513
3477
  ## Key aspects
3514
3478
 
3515
- - Both terms work identically and can be used interchangeably.
3516
- - Examples help guide the agent's response patterns and style.
3479
+ - When no \`MODEL\` commitment is specified, the best model requirement is picked automatically based on the agent \`PERSONA\`, \`KNOWLEDGE\`, \`TOOLS\` and other commitments
3480
+ - Multiple \`MODEL\` commitments can be used to specify different parameters
3481
+ - Both \`MODEL\` and \`MODELS\` terms work identically and can be used interchangeably
3482
+ - Parameters control the randomness, creativity, and technical aspects of model responses
3483
+
3484
+ ## Syntax variations
3485
+
3486
+ ### Single-line format (legacy support)
3487
+ \`\`\`book
3488
+ MODEL gpt-4
3489
+ MODEL claude-3-opus temperature=0.3
3490
+ MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
3491
+ \`\`\`
3492
+
3493
+ ### Multi-line named parameter format (recommended)
3494
+ \`\`\`book
3495
+ MODEL NAME gpt-4
3496
+ MODEL TEMPERATURE 0.7
3497
+ MODEL TOP_P 0.9
3498
+ MODEL MAX_TOKENS 2048
3499
+ \`\`\`
3500
+
3501
+ ## Supported parameters
3502
+
3503
+ - \`NAME\`: The specific model to use (e.g., 'gpt-4', 'claude-3-opus')
3504
+ - \`TEMPERATURE\`: Controls randomness (0.0 = deterministic, 1.0+ = creative)
3505
+ - \`TOP_P\`: Nucleus sampling parameter for controlling diversity
3506
+ - \`TOP_K\`: Top-k sampling parameter for limiting vocabulary
3507
+ - \`MAX_TOKENS\`: Maximum number of tokens the model can generate
3517
3508
 
3518
3509
  ## Examples
3519
3510
 
3511
+ ### Precise deterministic assistant
3520
3512
  \`\`\`book
3521
- Sales Assistant
3513
+ Precise Assistant
3522
3514
 
3523
- PERSONA You are a knowledgeable sales representative
3524
- SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
3525
- SAMPLE For feature comparisons, create a clear comparison table
3526
- RULE Always be honest about limitations
3515
+ PERSONA You are a precise and accurate assistant
3516
+ MODEL NAME gpt-4
3517
+ MODEL TEMPERATURE 0.1
3518
+ MODEL MAX_TOKENS 1024
3519
+ RULE Always provide factual information
3527
3520
  \`\`\`
3528
3521
 
3522
+ ### Creative writing assistant
3529
3523
  \`\`\`book
3530
- Code Reviewer
3524
+ Creative Writer
3531
3525
 
3532
- PERSONA You are an experienced software engineer
3533
- EXAMPLE For code questions, always include working code snippets
3534
- EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
3535
- RULE Explain the reasoning behind your suggestions
3536
- STYLE Be constructive and encouraging in feedback
3526
+ PERSONA You are a creative writing assistant
3527
+ MODEL NAME claude-3-opus
3528
+ MODEL TEMPERATURE 0.8
3529
+ MODEL TOP_P 0.9
3530
+ MODEL MAX_TOKENS 2048
3531
+ STYLE Be imaginative and expressive
3532
+ ACTION Can help with storytelling and character development
3533
+ \`\`\`
3534
+
3535
+ ### Balanced conversational agent
3536
+ \`\`\`book
3537
+ Balanced Assistant
3538
+
3539
+ PERSONA You are a helpful and balanced assistant
3540
+ MODEL NAME gpt-4
3541
+ MODEL TEMPERATURE 0.7
3542
+ MODEL TOP_P 0.95
3543
+ MODEL TOP_K 40
3544
+ MODEL MAX_TOKENS 1500
3537
3545
  \`\`\`
3538
3546
  `);
3539
3547
  }
3540
3548
  applyToAgentModelRequirements(requirements, content) {
3549
+ var _a;
3541
3550
  const trimmedContent = content.trim();
3542
3551
  if (!trimmedContent) {
3543
3552
  return requirements;
3544
3553
  }
3545
- // Add example to the system message
3546
- const exampleSection = `Example: ${trimmedContent}`;
3547
- return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
3554
+ const parts = trimmedContent.split(/\s+/);
3555
+ const firstPart = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
3556
+ // Check if this is the new named parameter format
3557
+ if (this.isNamedParameter(firstPart)) {
3558
+ return this.parseNamedParameter(requirements, firstPart, parts.slice(1));
3559
+ }
3560
+ else {
3561
+ // Legacy single-line format: "MODEL gpt-4 temperature=0.3 topP=0.9"
3562
+ return this.parseLegacyFormat(requirements, parts);
3563
+ }
3564
+ }
3565
+ /**
3566
+ * Check if the first part is a known named parameter
3567
+ */
3568
+ isNamedParameter(part) {
3569
+ if (!part)
3570
+ return false;
3571
+ const knownParams = ['NAME', 'TEMPERATURE', 'TOP_P', 'TOP_K', 'MAX_TOKENS'];
3572
+ return knownParams.includes(part);
3573
+ }
3574
+ /**
3575
+ * Parse the new named parameter format: "MODEL TEMPERATURE 0.7"
3576
+ */
3577
+ parseNamedParameter(requirements, parameterName, valueParts) {
3578
+ const value = valueParts.join(' ').trim();
3579
+ if (!value) {
3580
+ return requirements;
3581
+ }
3582
+ const result = { ...requirements };
3583
+ switch (parameterName) {
3584
+ case 'NAME':
3585
+ result.modelName = value;
3586
+ break;
3587
+ case 'TEMPERATURE': {
3588
+ const temperature = parseFloat(value);
3589
+ if (!isNaN(temperature)) {
3590
+ result.temperature = temperature;
3591
+ }
3592
+ break;
3593
+ }
3594
+ case 'TOP_P': {
3595
+ const topP = parseFloat(value);
3596
+ if (!isNaN(topP)) {
3597
+ result.topP = topP;
3598
+ }
3599
+ break;
3600
+ }
3601
+ case 'TOP_K': {
3602
+ const topK = parseFloat(value);
3603
+ if (!isNaN(topK)) {
3604
+ result.topK = Math.round(topK);
3605
+ }
3606
+ break;
3607
+ }
3608
+ case 'MAX_TOKENS': {
3609
+ const maxTokens = parseFloat(value);
3610
+ if (!isNaN(maxTokens)) {
3611
+ result.maxTokens = Math.round(maxTokens);
3612
+ }
3613
+ break;
3614
+ }
3615
+ }
3616
+ return result;
3617
+ }
3618
+ /**
3619
+ * Parse the legacy format: "MODEL gpt-4 temperature=0.3 topP=0.9"
3620
+ */
3621
+ parseLegacyFormat(requirements, parts) {
3622
+ const modelName = parts[0];
3623
+ if (!modelName) {
3624
+ return requirements;
3625
+ }
3626
+ // Start with the model name
3627
+ const result = {
3628
+ ...requirements,
3629
+ modelName,
3630
+ };
3631
+ // Parse additional key=value parameters
3632
+ for (let i = 1; i < parts.length; i++) {
3633
+ const param = parts[i];
3634
+ if (param && param.includes('=')) {
3635
+ const [key, value] = param.split('=');
3636
+ if (key && value) {
3637
+ const numValue = parseFloat(value);
3638
+ if (!isNaN(numValue)) {
3639
+ switch (key.toLowerCase()) {
3640
+ case 'temperature':
3641
+ result.temperature = numValue;
3642
+ break;
3643
+ case 'topp':
3644
+ case 'top_p':
3645
+ result.topP = numValue;
3646
+ break;
3647
+ case 'topk':
3648
+ case 'top_k':
3649
+ result.topK = Math.round(numValue);
3650
+ break;
3651
+ case 'max_tokens':
3652
+ case 'maxTokens':
3653
+ result.maxTokens = Math.round(numValue);
3654
+ break;
3655
+ }
3656
+ }
3657
+ }
3658
+ }
3659
+ }
3660
+ return result;
3548
3661
  }
3549
3662
  }
3550
3663
  /**
@@ -3552,927 +3665,918 @@ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
3552
3665
  */
3553
3666
 
3554
3667
  /**
3555
- * SCENARIO commitment definition
3668
+ * NOTE commitment definition
3556
3669
  *
3557
- * The SCENARIO commitment defines a specific situation or context in which the AI
3558
- * assistant should operate. It helps to set the scene for the AI's responses.
3559
- * Later scenarios are more important than earlier scenarios.
3670
+ * The NOTE commitment is used to add comments to the agent source without making any changes
3671
+ * to the system message or agent model requirements. It serves as a documentation mechanism
3672
+ * for developers to add explanatory comments, reminders, or annotations directly in the agent source.
3673
+ *
3674
+ * Key features:
3675
+ * - Makes no changes to the system message
3676
+ * - Makes no changes to agent model requirements
3677
+ * - Content is preserved in metadata.NOTE for debugging and inspection
3678
+ * - Multiple NOTE commitments are aggregated together
3679
+ * - Comments (# NOTE) are removed from the final system message
3560
3680
  *
3561
3681
  * Example usage in agent source:
3562
3682
  *
3563
3683
  * ```book
3564
- * SCENARIO You are in a customer service call center during peak hours
3565
- * SCENARIO The customer is frustrated and has been on hold for 20 minutes
3566
- * SCENARIO This is the customer's third call about the same issue
3684
+ * NOTE This agent was designed for customer support scenarios
3685
+ * NOTE Remember to update the knowledge base monthly
3686
+ * NOTE Performance optimized for quick response times
3567
3687
  * ```
3568
3688
  *
3689
+ * The above notes will be stored in metadata but won't affect the agent's behavior.
3690
+ *
3569
3691
  * @private [🪔] Maybe export the commitments through some package
3570
3692
  */
3571
- class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
3572
- constructor(type = 'SCENARIO') {
3693
+ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
3694
+ constructor(type = 'NOTE') {
3573
3695
  super(type);
3574
3696
  }
3575
3697
  /**
3576
- * Short one-line description of SCENARIO.
3698
+ * Short one-line description of NOTE.
3577
3699
  */
3578
3700
  get description() {
3579
- return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
3701
+ return 'Add developer-facing notes without changing behavior or output.';
3580
3702
  }
3581
3703
  /**
3582
- * Markdown documentation for SCENARIO commitment.
3704
+ * Markdown documentation for NOTE commitment.
3583
3705
  */
3584
3706
  get documentation() {
3585
3707
  return spaceTrim(`
3586
3708
  # ${this.type}
3587
3709
 
3588
- Defines a specific situation or context in which the AI assistant should operate. It helps to set the scene for the AI's responses. Later scenarios are more important than earlier scenarios.
3710
+ Adds comments for documentation without changing agent behavior.
3589
3711
 
3590
3712
  ## Key aspects
3591
3713
 
3592
- - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
3593
- - Both terms work identically and can be used interchangeably.
3594
- - Later scenarios have higher priority and can override earlier scenarios.
3595
- - Provides situational context that influences response tone and content.
3596
- - Helps establish the environment and circumstances for interactions.
3597
-
3598
- ## Priority system
3714
+ - Does not modify the agent's behavior or responses.
3715
+ - Multiple \`NOTE\`, \`NOTES\`, \`COMMENT\`, and \`NONCE\` commitments are aggregated for debugging.
3716
+ - All four terms work identically and can be used interchangeably.
3717
+ - Useful for documenting design decisions and reminders.
3718
+ - Content is preserved in metadata for inspection.
3599
3719
 
3600
- When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
3720
+ ## Examples
3601
3721
 
3602
- ## Use cases
3722
+ \`\`\`book
3723
+ Customer Support Bot
3603
3724
 
3604
- - Setting the physical or virtual environment
3605
- - Establishing time constraints or urgency
3606
- - Defining relationship dynamics or power structures
3607
- - Creating emotional or situational context
3608
-
3609
- ## Examples
3610
-
3611
- \`\`\`book
3612
- Emergency Response Operator
3613
-
3614
- PERSONA You are an emergency response operator
3615
- SCENARIO You are handling a 911 emergency call
3616
- SCENARIO The caller is panicked and speaking rapidly
3617
- SCENARIO Time is critical - every second counts
3618
- GOAL Gather essential information quickly and dispatch appropriate help
3619
- RULE Stay calm and speak clearly
3620
- \`\`\`
3621
-
3622
- \`\`\`book
3623
- Sales Representative
3624
-
3625
- PERSONA You are a software sales representative
3626
- SCENARIO You are in the final meeting of a 6-month sales cycle
3627
- SCENARIO The client has budget approval and decision-making authority
3628
- SCENARIO Two competitors have also submitted proposals
3629
- SCENARIO The client values long-term partnership over lowest price
3630
- GOAL Close the deal while building trust for future business
3631
- \`\`\`
3632
-
3633
- \`\`\`book
3634
- Medical Assistant
3635
-
3636
- PERSONA You are a medical assistant in a busy clinic
3637
- SCENARIO The waiting room is full and the doctor is running behind schedule
3638
- SCENARIO Patients are becoming impatient and anxious
3639
- SCENARIO You need to manage expectations while maintaining professionalism
3640
- SCENARIO Some patients have been waiting over an hour
3641
- GOAL Keep patients informed and calm while supporting efficient clinic flow
3642
- RULE Never provide medical advice or diagnosis
3725
+ NOTE This agent was designed for customer support scenarios
3726
+ COMMENT Remember to update the knowledge base monthly
3727
+ PERSONA You are a helpful customer support representative
3728
+ KNOWLEDGE Company policies and procedures
3729
+ RULE Always be polite and professional
3643
3730
  \`\`\`
3644
3731
 
3645
3732
  \`\`\`book
3646
- Technical Support Agent
3733
+ Research Assistant
3647
3734
 
3648
- PERSONA You are a technical support agent
3649
- SCENARIO The customer is a small business owner during their busy season
3650
- SCENARIO Their main business system has been down for 2 hours
3651
- SCENARIO They are losing money every minute the system is offline
3652
- SCENARIO This is their first experience with your company
3653
- GOAL Resolve the issue quickly while creating a positive first impression
3735
+ NONCE Performance optimized for quick response times
3736
+ NOTE Uses RAG for accessing latest research papers
3737
+ PERSONA You are a knowledgeable research assistant
3738
+ ACTION Can help with literature reviews and citations
3739
+ STYLE Present information in academic format
3654
3740
  \`\`\`
3655
3741
  `);
3656
3742
  }
3657
3743
  applyToAgentModelRequirements(requirements, content) {
3744
+ var _a;
3745
+ // The NOTE commitment makes no changes to the system message or model requirements
3746
+ // It only stores the note content in metadata for documentation purposes
3658
3747
  const trimmedContent = content.trim();
3659
3748
  if (!trimmedContent) {
3660
3749
  return requirements;
3661
3750
  }
3662
- // Create scenario section for system message
3663
- const scenarioSection = `Scenario: ${trimmedContent}`;
3664
- // Scenarios provide important contextual information that affects behavior
3665
- return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
3751
+ // Get existing note content from metadata
3752
+ const existingNoteContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.NOTE) || '';
3753
+ // Merge the new content with existing note content
3754
+ // When multiple NOTE commitments exist, they are aggregated together
3755
+ const mergedNoteContent = existingNoteContent ? `${existingNoteContent}\n${trimmedContent}` : trimmedContent;
3756
+ // Store the merged note content in metadata for debugging and inspection
3757
+ const updatedMetadata = {
3758
+ ...requirements.metadata,
3759
+ NOTE: mergedNoteContent,
3760
+ };
3761
+ // Return requirements with updated metadata but no changes to system message
3762
+ return {
3763
+ ...requirements,
3764
+ metadata: updatedMetadata,
3765
+ };
3666
3766
  }
3667
3767
  }
3668
3768
  /**
3669
- * Note: [💞] Ignore a discrepancy between file name and entity name
3769
+ * [💞] Ignore a discrepancy between file name and entity name
3670
3770
  */
3671
3771
 
3672
3772
  /**
3673
- * STYLE commitment definition
3773
+ * PERSONA commitment definition
3674
3774
  *
3675
- * The STYLE commitment defines how the agent should format and present its responses.
3676
- * This includes tone, writing style, formatting preferences, and communication patterns.
3775
+ * The PERSONA commitment modifies the agent's personality and character in the system message.
3776
+ * It defines who the agent is, their background, expertise, and personality traits.
3777
+ *
3778
+ * Key features:
3779
+ * - Multiple PERSONA commitments are automatically merged into one
3780
+ * - Content is placed at the beginning of the system message
3781
+ * - Original content with comments is preserved in metadata.PERSONA
3782
+ * - Comments (# PERSONA) are removed from the final system message
3677
3783
  *
3678
3784
  * Example usage in agent source:
3679
3785
  *
3680
3786
  * ```book
3681
- * STYLE Write in a professional but friendly tone, use bullet points for lists
3682
- * STYLE Always provide code examples when explaining programming concepts
3787
+ * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
3788
+ * PERSONA You have deep knowledge of modern web development practices
3683
3789
  * ```
3684
3790
  *
3791
+ * The above will be merged into a single persona section at the beginning of the system message.
3792
+ *
3685
3793
  * @private [🪔] Maybe export the commitments through some package
3686
3794
  */
3687
- class StyleCommitmentDefinition extends BaseCommitmentDefinition {
3688
- constructor(type = 'STYLE') {
3795
+ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
3796
+ constructor(type = 'PERSONA') {
3689
3797
  super(type);
3690
3798
  }
3691
3799
  /**
3692
- * Short one-line description of STYLE.
3800
+ * Short one-line description of PERSONA.
3693
3801
  */
3694
3802
  get description() {
3695
- return 'Control the tone and writing style of responses.';
3803
+ return 'Define who the agent is: background, expertise, and personality.';
3696
3804
  }
3697
3805
  /**
3698
- * Markdown documentation for STYLE commitment.
3806
+ * Markdown documentation for PERSONA commitment.
3699
3807
  */
3700
3808
  get documentation() {
3701
3809
  return spaceTrim(`
3702
3810
  # ${this.type}
3703
3811
 
3704
- Defines how the agent should format and present its responses (tone, writing style, formatting).
3812
+ Defines who the agent is, their background, expertise, and personality traits.
3705
3813
 
3706
3814
  ## Key aspects
3707
3815
 
3816
+ - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
3708
3817
  - Both terms work identically and can be used interchangeably.
3709
- - Later style instructions can override earlier ones.
3710
- - Style affects both tone and presentation format.
3818
+ - If they are in conflict, the last one takes precedence.
3819
+ - You can write persona content in multiple lines.
3711
3820
 
3712
3821
  ## Examples
3713
3822
 
3714
3823
  \`\`\`book
3715
- Technical Writer
3716
-
3717
- PERSONA You are a technical documentation expert
3718
- STYLE Write in a professional but friendly tone, use bullet points for lists
3719
- STYLE Always provide code examples when explaining programming concepts
3720
- FORMAT Use markdown formatting with clear headings
3721
- \`\`\`
3722
-
3723
- \`\`\`book
3724
- Creative Assistant
3824
+ Programming Assistant
3725
3825
 
3726
- PERSONA You are a creative writing helper
3727
- STYLE Be enthusiastic and encouraging in your responses
3728
- STYLE Use vivid metaphors and analogies to explain concepts
3729
- STYLE Keep responses conversational and engaging
3730
- RULE Always maintain a positive and supportive tone
3826
+ PERSONA You are a helpful programming assistant with expertise in TypeScript and React
3827
+ PERSONA You have deep knowledge of modern web development practices
3731
3828
  \`\`\`
3732
3829
  `);
3733
3830
  }
3734
3831
  applyToAgentModelRequirements(requirements, content) {
3832
+ var _a, _b;
3833
+ // The PERSONA commitment aggregates all persona content and places it at the beginning
3735
3834
  const trimmedContent = content.trim();
3736
3835
  if (!trimmedContent) {
3737
3836
  return requirements;
3738
3837
  }
3739
- // Add style instructions to the system message
3740
- const styleSection = `Style: ${trimmedContent}`;
3741
- return this.appendToSystemMessage(requirements, styleSection, '\n\n');
3838
+ // Get existing persona content from metadata
3839
+ const existingPersonaContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
3840
+ // Merge the new content with existing persona content
3841
+ // When multiple PERSONA commitments exist, they are merged into one
3842
+ const mergedPersonaContent = existingPersonaContent
3843
+ ? `${existingPersonaContent}\n${trimmedContent}`
3844
+ : trimmedContent;
3845
+ // Store the merged persona content in metadata for debugging and inspection
3846
+ const updatedMetadata = {
3847
+ ...requirements.metadata,
3848
+ PERSONA: mergedPersonaContent,
3849
+ };
3850
+ // Get the agent name from metadata (which should contain the first line of agent source)
3851
+ // If not available, extract from current system message as fallback
3852
+ let agentName = (_b = requirements.metadata) === null || _b === void 0 ? void 0 : _b.agentName;
3853
+ if (!agentName) {
3854
+ // Fallback: extract from current system message
3855
+ const currentMessage = requirements.systemMessage.trim();
3856
+ const basicFormatMatch = currentMessage.match(/^You are (.+)$/);
3857
+ if (basicFormatMatch && basicFormatMatch[1]) {
3858
+ agentName = basicFormatMatch[1];
3859
+ }
3860
+ else {
3861
+ agentName = 'AI Agent'; // Final fallback
3862
+ }
3863
+ }
3864
+ // Remove any existing persona content from the system message
3865
+ // (this handles the case where we're processing multiple PERSONA commitments)
3866
+ const currentMessage = requirements.systemMessage.trim();
3867
+ let cleanedMessage = currentMessage;
3868
+ // Check if current message starts with persona content or is just the basic format
3869
+ const basicFormatRegex = /^You are .+$/;
3870
+ const isBasicFormat = basicFormatRegex.test(currentMessage) && !currentMessage.includes('\n');
3871
+ if (isBasicFormat) {
3872
+ // Replace the basic format entirely
3873
+ cleanedMessage = '';
3874
+ }
3875
+ else if (currentMessage.startsWith('# PERSONA')) {
3876
+ // Remove existing persona section by finding where it ends
3877
+ const lines = currentMessage.split('\n');
3878
+ let personaEndIndex = lines.length;
3879
+ // Find the end of the PERSONA section (next comment or end of message)
3880
+ for (let i = 1; i < lines.length; i++) {
3881
+ const line = lines[i].trim();
3882
+ if (line.startsWith('#') && !line.startsWith('# PERSONA')) {
3883
+ personaEndIndex = i;
3884
+ break;
3885
+ }
3886
+ }
3887
+ // Keep everything after the PERSONA section
3888
+ cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
3889
+ }
3890
+ // TODO: [🕛] There should be `agentFullname` not `agentName`
3891
+ // Create new system message with persona at the beginning
3892
+ // Format: "You are {agentName}\n{personaContent}"
3893
+ // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
3894
+ const personaSection = `# PERSONA\nYou are ${agentName}\n${mergedPersonaContent}`; // <- TODO: Use spaceTrim
3895
+ const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
3896
+ return {
3897
+ ...requirements,
3898
+ systemMessage: newSystemMessage,
3899
+ metadata: updatedMetadata,
3900
+ };
3742
3901
  }
3743
3902
  }
3744
3903
  /**
3745
- * [💞] Ignore a discrepancy between file name and entity name
3904
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3746
3905
  */
3747
3906
 
3748
3907
  /**
3749
- * Placeholder commitment definition for commitments that are not yet implemented
3908
+ * RULE commitment definition
3750
3909
  *
3751
- * This commitment simply adds its content 1:1 into the system message,
3752
- * preserving the original behavior until proper implementation is added.
3910
+ * The RULE/RULES commitment adds behavioral constraints and guidelines that the agent must follow.
3911
+ * These are specific instructions about what the agent should or shouldn't do.
3753
3912
  *
3754
- * @public exported from `@promptbook/core`
3913
+ * Example usage in agent source:
3914
+ *
3915
+ * ```book
3916
+ * RULE Always ask for clarification if the user's request is ambiguous
3917
+ * RULES Never provide medical advice, always refer to healthcare professionals
3918
+ * ```
3919
+ *
3920
+ * @private [🪔] Maybe export the commitments through some package
3755
3921
  */
3756
- class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
3757
- constructor(type) {
3922
+ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
3923
+ constructor(type = 'RULE') {
3758
3924
  super(type);
3759
3925
  }
3760
3926
  /**
3761
- * Short one-line description of a placeholder commitment.
3927
+ * Short one-line description of RULE/RULES.
3762
3928
  */
3763
3929
  get description() {
3764
- return 'Placeholder commitment that appends content verbatim to the system message.';
3930
+ return 'Add behavioral rules the agent must follow.';
3765
3931
  }
3766
3932
  /**
3767
- * Markdown documentation available at runtime.
3933
+ * Markdown documentation for RULE/RULES commitment.
3768
3934
  */
3769
3935
  get documentation() {
3770
3936
  return spaceTrim(`
3771
3937
  # ${this.type}
3772
3938
 
3773
- This commitment is not yet fully implemented.
3939
+ Adds behavioral constraints and guidelines that the agent must follow.
3774
3940
 
3775
3941
  ## Key aspects
3776
3942
 
3777
- - Content is appended directly to the system message.
3778
- - No special processing or validation is performed.
3779
- - Behavior preserved until proper implementation is added.
3780
-
3781
- ## Status
3782
-
3783
- - **Status:** Placeholder implementation
3784
- - **Effect:** Appends content prefixed by commitment type
3785
- - **Future:** Will be replaced with specialized logic
3943
+ - All rules are treated equally regardless of singular/plural form.
3944
+ - Rules define what the agent must or must not do.
3786
3945
 
3787
3946
  ## Examples
3788
3947
 
3789
3948
  \`\`\`book
3790
- Example Agent
3949
+ Customer Support Agent
3791
3950
 
3792
- PERSONA You are a helpful assistant
3793
- ${this.type} Your content here
3794
- RULE Always be helpful
3951
+ PERSONA You are a helpful customer support representative
3952
+ RULE Always ask for clarification if the user's request is ambiguous
3953
+ RULE Be polite and professional in all interactions
3954
+ RULES Never provide medical or legal advice
3955
+ STYLE Maintain a friendly and helpful tone
3795
3956
  \`\`\`
3796
- `);
3797
- }
3798
- applyToAgentModelRequirements(requirements, content) {
3799
- const trimmedContent = content.trim();
3800
- if (!trimmedContent) {
3957
+
3958
+ \`\`\`book
3959
+ Educational Tutor
3960
+
3961
+ PERSONA You are a patient and knowledgeable tutor
3962
+ RULE Break down complex concepts into simple steps
3963
+ RULE Always encourage students and celebrate their progress
3964
+ RULE If you don't know something, admit it and suggest resources
3965
+ SAMPLE When explaining math: "Let's work through this step by step..."
3966
+ \`\`\`
3967
+ `);
3968
+ }
3969
+ applyToAgentModelRequirements(requirements, content) {
3970
+ const trimmedContent = content.trim();
3971
+ if (!trimmedContent) {
3801
3972
  return requirements;
3802
3973
  }
3803
- // Add the commitment content 1:1 to the system message
3804
- const commitmentLine = `${this.type} ${trimmedContent}`;
3805
- return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
3974
+ // Add rule to the system message
3975
+ const ruleSection = `Rule: ${trimmedContent}`;
3976
+ return this.appendToSystemMessage(requirements, ruleSection, '\n\n');
3806
3977
  }
3807
3978
  }
3808
-
3809
- // Import all commitment definition classes
3810
- /**
3811
- * Registry of all available commitment definitions
3812
- * This array contains instances of all commitment definitions
3813
- * This is the single source of truth for all commitments in the system
3814
- *
3815
- * @private Use functions to access commitments instead of this array directly
3816
- */
3817
- const COMMITMENT_REGISTRY = [
3818
- // Fully implemented commitments
3819
- new PersonaCommitmentDefinition('PERSONA'),
3820
- new PersonaCommitmentDefinition('PERSONAE'),
3821
- new KnowledgeCommitmentDefinition(),
3822
- new MemoryCommitmentDefinition('MEMORY'),
3823
- new MemoryCommitmentDefinition('MEMORIES'),
3824
- new StyleCommitmentDefinition('STYLE'),
3825
- new StyleCommitmentDefinition('STYLES'),
3826
- new RuleCommitmentDefinition('RULE'),
3827
- new RuleCommitmentDefinition('RULES'),
3828
- new SampleCommitmentDefinition('SAMPLE'),
3829
- new SampleCommitmentDefinition('EXAMPLE'),
3830
- new FormatCommitmentDefinition('FORMAT'),
3831
- new FormatCommitmentDefinition('FORMATS'),
3832
- new ModelCommitmentDefinition('MODEL'),
3833
- new ModelCommitmentDefinition('MODELS'),
3834
- new ActionCommitmentDefinition('ACTION'),
3835
- new ActionCommitmentDefinition('ACTIONS'),
3836
- new MetaCommitmentDefinition(),
3837
- new NoteCommitmentDefinition('NOTE'),
3838
- new NoteCommitmentDefinition('NOTES'),
3839
- new NoteCommitmentDefinition('COMMENT'),
3840
- new NoteCommitmentDefinition('NONCE'),
3841
- new GoalCommitmentDefinition('GOAL'),
3842
- new GoalCommitmentDefinition('GOALS'),
3843
- new MessageCommitmentDefinition('MESSAGE'),
3844
- new MessageCommitmentDefinition('MESSAGES'),
3845
- new ScenarioCommitmentDefinition('SCENARIO'),
3846
- new ScenarioCommitmentDefinition('SCENARIOS'),
3847
- new DeleteCommitmentDefinition('DELETE'),
3848
- new DeleteCommitmentDefinition('CANCEL'),
3849
- new DeleteCommitmentDefinition('DISCARD'),
3850
- new DeleteCommitmentDefinition('REMOVE'),
3851
- // Not yet implemented commitments (using placeholder)
3852
- new NotYetImplementedCommitmentDefinition('EXPECT'),
3853
- new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
3854
- new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
3855
- new NotYetImplementedCommitmentDefinition('AVOID'),
3856
- new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
3857
- new NotYetImplementedCommitmentDefinition('CONTEXT'),
3858
- ];
3859
3979
  /**
3860
- * TODO: [🧠] Maybe create through standardized $register
3861
3980
  * Note: [💞] Ignore a discrepancy between file name and entity name
3862
3981
  */
3863
3982
 
3864
3983
  /**
3865
- * Parses agent source using the new commitment system with multiline support
3866
- * This function replaces the hardcoded commitment parsing in the original parseAgentSource
3984
+ * SAMPLE commitment definition
3867
3985
  *
3868
- * @private internal utility of `parseAgentSource`
3986
+ * The SAMPLE/EXAMPLE commitment provides examples of how the agent should respond
3987
+ * or behave in certain situations. These examples help guide the agent's responses.
3988
+ *
3989
+ * Example usage in agent source:
3990
+ *
3991
+ * ```book
3992
+ * SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
3993
+ * EXAMPLE For code questions, always include working code snippets
3994
+ * ```
3995
+ *
3996
+ * @private [🪔] Maybe export the commitments through some package
3869
3997
  */
3870
- function parseAgentSourceWithCommitments(agentSource) {
3871
- var _a, _b, _c;
3872
- if (!agentSource || !agentSource.trim()) {
3873
- return {
3874
- agentName: null,
3875
- commitments: [],
3876
- nonCommitmentLines: [],
3877
- };
3998
+ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
3999
+ constructor(type = 'SAMPLE') {
4000
+ super(type);
3878
4001
  }
3879
- const lines = agentSource.split('\n');
3880
- const agentName = (((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.trim()) || null);
3881
- const commitments = [];
3882
- const nonCommitmentLines = [];
3883
- // Always add the first line (agent name) to non-commitment lines
3884
- if (lines[0] !== undefined) {
3885
- nonCommitmentLines.push(lines[0]);
4002
+ /**
4003
+ * Short one-line description of SAMPLE/EXAMPLE.
4004
+ */
4005
+ get description() {
4006
+ return 'Provide example responses to guide behavior.';
3886
4007
  }
3887
- // Parse commitments with multiline support
3888
- let currentCommitment = null;
3889
- // Process lines starting from the second line (skip agent name)
3890
- for (let i = 1; i < lines.length; i++) {
3891
- const line = lines[i];
3892
- if (line === undefined) {
3893
- continue;
3894
- }
3895
- // Check if this line starts a new commitment
3896
- let foundNewCommitment = false;
3897
- for (const definition of COMMITMENT_REGISTRY) {
3898
- const typeRegex = definition.createTypeRegex();
3899
- const match = typeRegex.exec(line.trim());
3900
- if (match && ((_b = match.groups) === null || _b === void 0 ? void 0 : _b.type)) {
3901
- // Save the previous commitment if it exists
3902
- if (currentCommitment) {
3903
- const fullContent = currentCommitment.contentLines.join('\n');
3904
- commitments.push({
3905
- type: currentCommitment.type,
3906
- content: spaceTrim(fullContent),
3907
- originalLine: currentCommitment.originalStartLine,
3908
- lineNumber: currentCommitment.startLineNumber,
3909
- });
3910
- }
3911
- // Extract the initial content from the commitment line
3912
- const fullRegex = definition.createRegex();
3913
- const fullMatch = fullRegex.exec(line.trim());
3914
- const initialContent = ((_c = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _c === void 0 ? void 0 : _c.contents) || '';
3915
- // Start a new commitment
3916
- currentCommitment = {
3917
- type: definition.type,
3918
- startLineNumber: i + 1,
3919
- originalStartLine: line,
3920
- contentLines: initialContent ? [initialContent] : [],
3921
- };
3922
- foundNewCommitment = true;
3923
- break;
3924
- }
3925
- }
3926
- if (!foundNewCommitment) {
3927
- if (currentCommitment) {
3928
- // This line belongs to the current commitment
3929
- currentCommitment.contentLines.push(line);
3930
- }
3931
- else {
3932
- // This line is not part of any commitment
3933
- nonCommitmentLines.push(line);
3934
- }
3935
- }
4008
+ /**
4009
+ * Markdown documentation for SAMPLE/EXAMPLE commitment.
4010
+ */
4011
+ get documentation() {
4012
+ return spaceTrim(`
4013
+ # ${this.type}
4014
+
4015
+ Provides examples of how the agent should respond or behave in certain situations.
4016
+
4017
+ ## Key aspects
4018
+
4019
+ - Both terms work identically and can be used interchangeably.
4020
+ - Examples help guide the agent's response patterns and style.
4021
+
4022
+ ## Examples
4023
+
4024
+ \`\`\`book
4025
+ Sales Assistant
4026
+
4027
+ PERSONA You are a knowledgeable sales representative
4028
+ SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
4029
+ SAMPLE For feature comparisons, create a clear comparison table
4030
+ RULE Always be honest about limitations
4031
+ \`\`\`
4032
+
4033
+ \`\`\`book
4034
+ Code Reviewer
4035
+
4036
+ PERSONA You are an experienced software engineer
4037
+ EXAMPLE For code questions, always include working code snippets
4038
+ EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
4039
+ RULE Explain the reasoning behind your suggestions
4040
+ STYLE Be constructive and encouraging in feedback
4041
+ \`\`\`
4042
+ `);
3936
4043
  }
3937
- // Don't forget to save the last commitment if it exists
3938
- if (currentCommitment) {
3939
- const fullContent = currentCommitment.contentLines.join('\n');
3940
- commitments.push({
3941
- type: currentCommitment.type,
3942
- content: spaceTrim(fullContent),
3943
- originalLine: currentCommitment.originalStartLine,
3944
- lineNumber: currentCommitment.startLineNumber,
3945
- });
4044
+ applyToAgentModelRequirements(requirements, content) {
4045
+ const trimmedContent = content.trim();
4046
+ if (!trimmedContent) {
4047
+ return requirements;
4048
+ }
4049
+ // Add example to the system message
4050
+ const exampleSection = `Example: ${trimmedContent}`;
4051
+ return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
3946
4052
  }
3947
- return {
3948
- agentName,
3949
- commitments,
3950
- nonCommitmentLines,
3951
- };
3952
4053
  }
4054
+ /**
4055
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4056
+ */
3953
4057
 
3954
4058
  /**
3955
- * Parses parameters from text using both supported notations:
3956
- * 1. @Parameter - single word parameter starting with @
3957
- * 2. {parameterName} or {parameter with multiple words} or {parameterName: description text}
4059
+ * SCENARIO commitment definition
3958
4060
  *
3959
- * Both notations represent the same syntax feature - parameters
4061
+ * The SCENARIO commitment defines a specific situation or context in which the AI
4062
+ * assistant should operate. It helps to set the scene for the AI's responses.
4063
+ * Later scenarios are more important than earlier scenarios.
3960
4064
  *
3961
- * @param text - Text to extract parameters from
3962
- * @returns Array of parsed parameters with unified representation
3963
- * @public exported from `@promptbook/core`
4065
+ * Example usage in agent source:
4066
+ *
4067
+ * ```book
4068
+ * SCENARIO You are in a customer service call center during peak hours
4069
+ * SCENARIO The customer is frustrated and has been on hold for 20 minutes
4070
+ * SCENARIO This is the customer's third call about the same issue
4071
+ * ```
4072
+ *
4073
+ * @private [🪔] Maybe export the commitments through some package
3964
4074
  */
3965
- function parseParameters(text) {
3966
- const parameters = [];
3967
- // [🧠] Parameter syntax parsing - unified approach for two different notations of the same syntax feature
3968
- // The Book language supports parameters in two different notations but they represent the same concept
3969
- // Extract @Parameter notation (single word parameters starting with @)
3970
- const atParameterRegex = /@[\w\u00C0-\u017F\u0100-\u024F\u1E00-\u1EFF]+/gim;
3971
- text.replace(atParameterRegex, (match) => {
3972
- const parameterName = match.slice(1); // Remove the @ symbol
3973
- parameters.push({
3974
- text: match,
3975
- notation: 'at',
3976
- name: parameterName,
3977
- });
3978
- return match;
3979
- });
3980
- // Extract {parameter} notation (parameters in braces)
3981
- const braceParameterRegex = /\{([^}]+)\}/gim;
3982
- text.replace(braceParameterRegex, (match, content) => {
3983
- // Check if the parameter has a description (parameterName: description)
3984
- const colonIndex = content.indexOf(':');
3985
- if (colonIndex !== -1) {
3986
- const name = content.substring(0, colonIndex).trim();
3987
- const description = content.substring(colonIndex + 1).trim();
3988
- parameters.push({
3989
- text: match,
3990
- notation: 'brace',
3991
- name,
3992
- description,
3993
- });
3994
- }
3995
- else {
3996
- // Simple parameter without description
3997
- parameters.push({
3998
- text: match,
3999
- notation: 'brace',
4000
- name: content.trim(),
4001
- });
4002
- }
4003
- return match;
4004
- });
4005
- // Remove duplicates based on name (keep the first occurrence)
4006
- const uniqueParameters = parameters.filter((param, index, array) => {
4007
- return array.findIndex((p) => p.name === param.name) === index;
4008
- });
4009
- return uniqueParameters;
4010
- }
4011
-
4012
- /**
4013
- * Parses basic information from agent source
4014
- *
4015
- * There are 2 similar functions:
4016
- * - `parseAgentSource` which is a lightweight parser for agent source, it parses basic information and its purpose is to be quick and synchronous. The commitments there are hardcoded.
4017
- * - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronously.
4018
- *
4019
- * @public exported from `@promptbook/core`
4020
- */
4021
- function parseAgentSource(agentSource) {
4022
- const parseResult = parseAgentSourceWithCommitments(agentSource);
4023
- // Find PERSONA and META commitments
4024
- let personaDescription = null;
4025
- for (const commitment of parseResult.commitments) {
4026
- if (commitment.type !== 'PERSONA') {
4027
- continue;
4028
- }
4029
- if (personaDescription === null) {
4030
- personaDescription = '';
4031
- }
4032
- else {
4033
- personaDescription += `\n\n${personaDescription}`;
4034
- }
4035
- personaDescription += commitment.content;
4036
- }
4037
- const meta = {};
4038
- for (const commitment of parseResult.commitments) {
4039
- if (commitment.type !== 'META') {
4040
- continue;
4041
- }
4042
- // Parse META commitments - format is "META TYPE content"
4043
- const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
4044
- const metaType = normalizeTo_camelCase(metaTypeRaw);
4045
- meta[metaType] = spaceTrim$1(commitment.content.substring(metaTypeRaw.length));
4075
+ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
4076
+ constructor(type = 'SCENARIO') {
4077
+ super(type);
4046
4078
  }
4047
- // Generate gravatar fallback if no meta image specified
4048
- if (!meta.image) {
4049
- meta.image = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
4079
+ /**
4080
+ * Short one-line description of SCENARIO.
4081
+ */
4082
+ get description() {
4083
+ return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
4050
4084
  }
4051
- // Parse parameters using unified approach - both @Parameter and {parameter} notations
4052
- // are treated as the same syntax feature with unified representation
4053
- const parameters = parseParameters(agentSource);
4054
- return {
4055
- agentName: parseResult.agentName,
4056
- personaDescription,
4057
- meta,
4058
- parameters,
4059
- };
4060
- }
4061
- /**
4062
- * TODO: [🕛] Unite `AgentBasicInformation`, `ChatParticipant`, `LlmExecutionTools` + `LlmToolsMetadata`
4063
- */
4085
+ /**
4086
+ * Markdown documentation for SCENARIO commitment.
4087
+ */
4088
+ get documentation() {
4089
+ return spaceTrim(`
4090
+ # ${this.type}
4064
4091
 
4065
- /**
4066
- * Tests if given string is valid file path.
4067
- *
4068
- * Note: This does not check if the file exists only if the path is valid
4069
- * @public exported from `@promptbook/utils`
4070
- */
4071
- function isValidFilePath(filename) {
4072
- if (typeof filename !== 'string') {
4073
- return false;
4074
- }
4075
- if (filename.split('\n').length > 1) {
4076
- return false;
4077
- }
4078
- // Normalize slashes early so heuristics can detect path-like inputs
4079
- const filenameSlashes = filename.replace(/\\/g, '/');
4080
- // Reject strings that look like sentences (informational text)
4081
- // Heuristic: contains multiple spaces and ends with a period, or contains typical sentence punctuation
4082
- // But skip this heuristic if the string looks like a path (contains '/' or starts with a drive letter)
4083
- if (filename.trim().length > 60 && // long enough to be a sentence
4084
- /[.!?]/.test(filename) && // contains sentence punctuation
4085
- filename.split(' ').length > 8 && // has many words
4086
- !/\/|^[A-Z]:/i.test(filenameSlashes) // do NOT treat as sentence if looks like a path
4087
- ) {
4088
- return false;
4089
- }
4090
- // Absolute Unix path: /hello.txt
4091
- if (/^(\/)/i.test(filenameSlashes)) {
4092
- // console.log(filename, 'Absolute Unix path: /hello.txt');
4093
- return true;
4094
- }
4095
- // Absolute Windows path: C:/ or C:\ (allow spaces and multiple dots in filename)
4096
- if (/^[A-Z]:\/.+$/i.test(filenameSlashes)) {
4097
- // console.log(filename, 'Absolute Windows path: /hello.txt');
4098
- return true;
4099
- }
4100
- // Relative path: ./hello.txt
4101
- if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
4102
- // console.log(filename, 'Relative path: ./hello.txt');
4103
- return true;
4104
- }
4105
- // Allow paths like foo/hello
4106
- if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
4107
- // console.log(filename, 'Allow paths like foo/hello');
4108
- return true;
4109
- }
4110
- // Allow paths like hello.book
4111
- if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
4112
- // console.log(filename, 'Allow paths like hello.book');
4113
- return true;
4114
- }
4115
- return false;
4116
- }
4117
- /**
4118
- * TODO: [🍏] Implement for MacOs
4119
- */
4092
+ Defines a specific situation or context in which the AI assistant should operate. It helps to set the scene for the AI's responses. Later scenarios are more important than earlier scenarios.
4120
4093
 
4121
- const defaultDiacriticsRemovalMap = [
4122
- {
4123
- base: 'A',
4124
- letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F',
4125
- },
4126
- { base: 'AA', letters: '\uA732' },
4127
- { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
4128
- { base: 'AO', letters: '\uA734' },
4129
- { base: 'AU', letters: '\uA736' },
4130
- { base: 'AV', letters: '\uA738\uA73A' },
4131
- { base: 'AY', letters: '\uA73C' },
4132
- {
4133
- base: 'B',
4134
- letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
4135
- },
4136
- {
4137
- base: 'C',
4138
- letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
4139
- },
4140
- {
4141
- base: 'D',
4142
- letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
4143
- },
4144
- { base: 'DZ', letters: '\u01F1\u01C4' },
4145
- { base: 'Dz', letters: '\u01F2\u01C5' },
4146
- {
4147
- base: 'E',
4148
- letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E',
4149
- },
4150
- { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
4151
- {
4152
- base: 'G',
4153
- letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
4154
- },
4155
- {
4156
- base: 'H',
4157
- letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
4158
- },
4159
- {
4160
- base: 'I',
4161
- letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
4162
- },
4163
- { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
4164
- {
4165
- base: 'K',
4166
- letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
4167
- },
4168
- {
4169
- base: 'L',
4170
- letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
4171
- },
4172
- { base: 'LJ', letters: '\u01C7' },
4173
- { base: 'Lj', letters: '\u01C8' },
4174
- { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
4175
- {
4176
- base: 'N',
4177
- letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
4178
- },
4179
- { base: 'NJ', letters: '\u01CA' },
4180
- { base: 'Nj', letters: '\u01CB' },
4181
- {
4182
- base: 'O',
4183
- letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C',
4184
- },
4185
- { base: 'OI', letters: '\u01A2' },
4186
- { base: 'OO', letters: '\uA74E' },
4187
- { base: 'OU', letters: '\u0222' },
4188
- { base: 'OE', letters: '\u008C\u0152' },
4189
- { base: 'oe', letters: '\u009C\u0153' },
4190
- {
4191
- base: 'P',
4192
- letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
4193
- },
4194
- { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
4195
- {
4196
- base: 'R',
4197
- letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
4198
- },
4199
- {
4200
- base: 'S',
4201
- letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
4202
- },
4203
- {
4204
- base: 'T',
4205
- letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
4206
- },
4207
- { base: 'TZ', letters: '\uA728' },
4208
- {
4209
- base: 'U',
4210
- letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244',
4211
- },
4212
- { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
4213
- { base: 'VY', letters: '\uA760' },
4214
- {
4215
- base: 'W',
4216
- letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
4217
- },
4218
- { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
4219
- {
4220
- base: 'Y',
4221
- letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
4222
- },
4223
- {
4224
- base: 'Z',
4225
- letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
4226
- },
4227
- {
4228
- base: 'a',
4229
- letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250',
4230
- },
4231
- { base: 'aa', letters: '\uA733' },
4232
- { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
4233
- { base: 'ao', letters: '\uA735' },
4234
- { base: 'au', letters: '\uA737' },
4235
- { base: 'av', letters: '\uA739\uA73B' },
4236
- { base: 'ay', letters: '\uA73D' },
4237
- {
4238
- base: 'b',
4239
- letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
4240
- },
4241
- {
4242
- base: 'c',
4243
- letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
4244
- },
4245
- {
4246
- base: 'd',
4247
- letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
4248
- },
4249
- { base: 'dz', letters: '\u01F3\u01C6' },
4250
- {
4251
- base: 'e',
4252
- letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD',
4253
- },
4254
- { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
4255
- {
4256
- base: 'g',
4257
- letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
4258
- },
4259
- {
4260
- base: 'h',
4261
- letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
4262
- },
4263
- { base: 'hv', letters: '\u0195' },
4264
- {
4265
- base: 'i',
4266
- letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
4267
- },
4268
- { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
4269
- {
4270
- base: 'k',
4271
- letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
4272
- },
4273
- {
4274
- base: 'l',
4275
- letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
4276
- },
4277
- { base: 'lj', letters: '\u01C9' },
4278
- { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
4279
- {
4280
- base: 'n',
4281
- letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
4282
- },
4283
- { base: 'nj', letters: '\u01CC' },
4284
- {
4285
- base: 'o',
4286
- letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275',
4287
- },
4288
- { base: 'oi', letters: '\u01A3' },
4289
- { base: 'ou', letters: '\u0223' },
4290
- { base: 'oo', letters: '\uA74F' },
4291
- {
4292
- base: 'p',
4293
- letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
4294
- },
4295
- { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
4296
- {
4297
- base: 'r',
4298
- letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
4299
- },
4300
- {
4301
- base: 's',
4302
- letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
4303
- },
4304
- {
4305
- base: 't',
4306
- letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
4307
- },
4308
- { base: 'tz', letters: '\uA729' },
4309
- {
4310
- base: 'u',
4311
- letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289',
4312
- },
4313
- { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
4314
- { base: 'vy', letters: '\uA761' },
4315
- {
4316
- base: 'w',
4317
- letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
4318
- },
4319
- { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
4320
- {
4321
- base: 'y',
4322
- letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
4323
- },
4324
- {
4325
- base: 'z',
4326
- letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
4327
- },
4328
- ];
4094
+ ## Key aspects
4095
+
4096
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
4097
+ - Both terms work identically and can be used interchangeably.
4098
+ - Later scenarios have higher priority and can override earlier scenarios.
4099
+ - Provides situational context that influences response tone and content.
4100
+ - Helps establish the environment and circumstances for interactions.
4101
+
4102
+ ## Priority system
4103
+
4104
+ When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
4105
+
4106
+ ## Use cases
4107
+
4108
+ - Setting the physical or virtual environment
4109
+ - Establishing time constraints or urgency
4110
+ - Defining relationship dynamics or power structures
4111
+ - Creating emotional or situational context
4112
+
4113
+ ## Examples
4114
+
4115
+ \`\`\`book
4116
+ Emergency Response Operator
4117
+
4118
+ PERSONA You are an emergency response operator
4119
+ SCENARIO You are handling a 911 emergency call
4120
+ SCENARIO The caller is panicked and speaking rapidly
4121
+ SCENARIO Time is critical - every second counts
4122
+ GOAL Gather essential information quickly and dispatch appropriate help
4123
+ RULE Stay calm and speak clearly
4124
+ \`\`\`
4125
+
4126
+ \`\`\`book
4127
+ Sales Representative
4128
+
4129
+ PERSONA You are a software sales representative
4130
+ SCENARIO You are in the final meeting of a 6-month sales cycle
4131
+ SCENARIO The client has budget approval and decision-making authority
4132
+ SCENARIO Two competitors have also submitted proposals
4133
+ SCENARIO The client values long-term partnership over lowest price
4134
+ GOAL Close the deal while building trust for future business
4135
+ \`\`\`
4136
+
4137
+ \`\`\`book
4138
+ Medical Assistant
4139
+
4140
+ PERSONA You are a medical assistant in a busy clinic
4141
+ SCENARIO The waiting room is full and the doctor is running behind schedule
4142
+ SCENARIO Patients are becoming impatient and anxious
4143
+ SCENARIO You need to manage expectations while maintaining professionalism
4144
+ SCENARIO Some patients have been waiting over an hour
4145
+ GOAL Keep patients informed and calm while supporting efficient clinic flow
4146
+ RULE Never provide medical advice or diagnosis
4147
+ \`\`\`
4148
+
4149
+ \`\`\`book
4150
+ Technical Support Agent
4151
+
4152
+ PERSONA You are a technical support agent
4153
+ SCENARIO The customer is a small business owner during their busy season
4154
+ SCENARIO Their main business system has been down for 2 hours
4155
+ SCENARIO They are losing money every minute the system is offline
4156
+ SCENARIO This is their first experience with your company
4157
+ GOAL Resolve the issue quickly while creating a positive first impression
4158
+ \`\`\`
4159
+ `);
4160
+ }
4161
+ applyToAgentModelRequirements(requirements, content) {
4162
+ const trimmedContent = content.trim();
4163
+ if (!trimmedContent) {
4164
+ return requirements;
4165
+ }
4166
+ // Create scenario section for system message
4167
+ const scenarioSection = `Scenario: ${trimmedContent}`;
4168
+ // Scenarios provide important contextual information that affects behavior
4169
+ return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
4170
+ }
4171
+ }
4329
4172
  /**
4330
- * Map of letters from diacritic variant to diacritless variant
4331
- * Contains lowercase and uppercase separatelly
4173
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4174
+ */
4175
+
4176
+ /**
4177
+ * STYLE commitment definition
4332
4178
  *
4333
- * > "á" => "a"
4334
- * > "ě" => "e"
4335
- * > "Ă" => "A"
4336
- * > ...
4179
+ * The STYLE commitment defines how the agent should format and present its responses.
4180
+ * This includes tone, writing style, formatting preferences, and communication patterns.
4337
4181
  *
4338
- * @public exported from `@promptbook/utils`
4182
+ * Example usage in agent source:
4183
+ *
4184
+ * ```book
4185
+ * STYLE Write in a professional but friendly tone, use bullet points for lists
4186
+ * STYLE Always provide code examples when explaining programming concepts
4187
+ * ```
4188
+ *
4189
+ * @private [🪔] Maybe export the commitments through some package
4339
4190
  */
4340
- const DIACRITIC_VARIANTS_LETTERS = {};
4341
- // tslint:disable-next-line: prefer-for-of
4342
- for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
4343
- const letters = defaultDiacriticsRemovalMap[i].letters;
4344
- // tslint:disable-next-line: prefer-for-of
4345
- for (let j = 0; j < letters.length; j++) {
4346
- DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
4191
+ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
4192
+ constructor(type = 'STYLE') {
4193
+ super(type);
4347
4194
  }
4348
- }
4349
- // <- TODO: [🍓] Put to maker function to save execution time if not needed
4350
- /*
4351
- @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
4352
- Licensed under the Apache License, Version 2.0 (the "License");
4353
- you may not use this file except in compliance with the License.
4354
- You may obtain a copy of the License at
4195
+ /**
4196
+ * Short one-line description of STYLE.
4197
+ */
4198
+ get description() {
4199
+ return 'Control the tone and writing style of responses.';
4200
+ }
4201
+ /**
4202
+ * Markdown documentation for STYLE commitment.
4203
+ */
4204
+ get documentation() {
4205
+ return spaceTrim(`
4206
+ # ${this.type}
4355
4207
 
4356
- http://www.apache.org/licenses/LICENSE-2.0
4208
+ Defines how the agent should format and present its responses (tone, writing style, formatting).
4357
4209
 
4358
- Unless required by applicable law or agreed to in writing, software
4359
- distributed under the License is distributed on an "AS IS" BASIS,
4360
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4361
- See the License for the specific language governing permissions and
4362
- limitations under the License.
4363
- */
4210
+ ## Key aspects
4211
+
4212
+ - Both terms work identically and can be used interchangeably.
4213
+ - Later style instructions can override earlier ones.
4214
+ - Style affects both tone and presentation format.
4215
+
4216
+ ## Examples
4217
+
4218
+ \`\`\`book
4219
+ Technical Writer
4220
+
4221
+ PERSONA You are a technical documentation expert
4222
+ STYLE Write in a professional but friendly tone, use bullet points for lists
4223
+ STYLE Always provide code examples when explaining programming concepts
4224
+ FORMAT Use markdown formatting with clear headings
4225
+ \`\`\`
4226
+
4227
+ \`\`\`book
4228
+ Creative Assistant
4229
+
4230
+ PERSONA You are a creative writing helper
4231
+ STYLE Be enthusiastic and encouraging in your responses
4232
+ STYLE Use vivid metaphors and analogies to explain concepts
4233
+ STYLE Keep responses conversational and engaging
4234
+ RULE Always maintain a positive and supportive tone
4235
+ \`\`\`
4236
+ `);
4237
+ }
4238
+ applyToAgentModelRequirements(requirements, content) {
4239
+ const trimmedContent = content.trim();
4240
+ if (!trimmedContent) {
4241
+ return requirements;
4242
+ }
4243
+ // Add style instructions to the system message
4244
+ const styleSection = `Style: ${trimmedContent}`;
4245
+ return this.appendToSystemMessage(requirements, styleSection, '\n\n');
4246
+ }
4247
+ }
4248
+ /**
4249
+ * [💞] Ignore a discrepancy between file name and entity name
4250
+ */
4364
4251
 
4365
4252
  /**
4366
- * Removes diacritic marks (accents) from characters in a string.
4253
+ * Placeholder commitment definition for commitments that are not yet implemented
4367
4254
  *
4368
- * Note: [🔂] This function is idempotent.
4255
+ * This commitment simply adds its content 1:1 into the system message,
4256
+ * preserving the original behavior until proper implementation is added.
4369
4257
  *
4370
- * @param input The string containing diacritics to be normalized.
4371
- * @returns The string with diacritics removed or normalized.
4372
- * @public exported from `@promptbook/utils`
4258
+ * @public exported from `@promptbook/core`
4373
4259
  */
4374
- function removeDiacritics(input) {
4375
- /*eslint no-control-regex: "off"*/
4376
- return input.replace(/[^\u0000-\u007E]/g, (a) => {
4377
- return DIACRITIC_VARIANTS_LETTERS[a] || a;
4378
- });
4260
+ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
4261
+ constructor(type) {
4262
+ super(type);
4263
+ }
4264
+ /**
4265
+ * Short one-line description of a placeholder commitment.
4266
+ */
4267
+ get description() {
4268
+ return 'Placeholder commitment that appends content verbatim to the system message.';
4269
+ }
4270
+ /**
4271
+ * Markdown documentation available at runtime.
4272
+ */
4273
+ get documentation() {
4274
+ return spaceTrim(`
4275
+ # ${this.type}
4276
+
4277
+ This commitment is not yet fully implemented.
4278
+
4279
+ ## Key aspects
4280
+
4281
+ - Content is appended directly to the system message.
4282
+ - No special processing or validation is performed.
4283
+ - Behavior preserved until proper implementation is added.
4284
+
4285
+ ## Status
4286
+
4287
+ - **Status:** Placeholder implementation
4288
+ - **Effect:** Appends content prefixed by commitment type
4289
+ - **Future:** Will be replaced with specialized logic
4290
+
4291
+ ## Examples
4292
+
4293
+ \`\`\`book
4294
+ Example Agent
4295
+
4296
+ PERSONA You are a helpful assistant
4297
+ ${this.type} Your content here
4298
+ RULE Always be helpful
4299
+ \`\`\`
4300
+ `);
4301
+ }
4302
+ applyToAgentModelRequirements(requirements, content) {
4303
+ const trimmedContent = content.trim();
4304
+ if (!trimmedContent) {
4305
+ return requirements;
4306
+ }
4307
+ // Add the commitment content 1:1 to the system message
4308
+ const commitmentLine = `${this.type} ${trimmedContent}`;
4309
+ return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
4310
+ }
4379
4311
  }
4312
+
4313
+ // Import all commitment definition classes
4314
+ /**
4315
+ * Registry of all available commitment definitions
4316
+ * This array contains instances of all commitment definitions
4317
+ * This is the single source of truth for all commitments in the system
4318
+ *
4319
+ * @private Use functions to access commitments instead of this array directly
4320
+ */
4321
+ const COMMITMENT_REGISTRY = [
4322
+ // Fully implemented commitments
4323
+ new PersonaCommitmentDefinition('PERSONA'),
4324
+ new PersonaCommitmentDefinition('PERSONAE'),
4325
+ new KnowledgeCommitmentDefinition(),
4326
+ new MemoryCommitmentDefinition('MEMORY'),
4327
+ new MemoryCommitmentDefinition('MEMORIES'),
4328
+ new StyleCommitmentDefinition('STYLE'),
4329
+ new StyleCommitmentDefinition('STYLES'),
4330
+ new RuleCommitmentDefinition('RULE'),
4331
+ new RuleCommitmentDefinition('RULES'),
4332
+ new SampleCommitmentDefinition('SAMPLE'),
4333
+ new SampleCommitmentDefinition('EXAMPLE'),
4334
+ new FormatCommitmentDefinition('FORMAT'),
4335
+ new FormatCommitmentDefinition('FORMATS'),
4336
+ new ModelCommitmentDefinition('MODEL'),
4337
+ new ModelCommitmentDefinition('MODELS'),
4338
+ new ActionCommitmentDefinition('ACTION'),
4339
+ new ActionCommitmentDefinition('ACTIONS'),
4340
+ new MetaCommitmentDefinition(),
4341
+ new NoteCommitmentDefinition('NOTE'),
4342
+ new NoteCommitmentDefinition('NOTES'),
4343
+ new NoteCommitmentDefinition('COMMENT'),
4344
+ new NoteCommitmentDefinition('NONCE'),
4345
+ new GoalCommitmentDefinition('GOAL'),
4346
+ new GoalCommitmentDefinition('GOALS'),
4347
+ new MessageCommitmentDefinition('MESSAGE'),
4348
+ new MessageCommitmentDefinition('MESSAGES'),
4349
+ new ScenarioCommitmentDefinition('SCENARIO'),
4350
+ new ScenarioCommitmentDefinition('SCENARIOS'),
4351
+ new DeleteCommitmentDefinition('DELETE'),
4352
+ new DeleteCommitmentDefinition('CANCEL'),
4353
+ new DeleteCommitmentDefinition('DISCARD'),
4354
+ new DeleteCommitmentDefinition('REMOVE'),
4355
+ // Not yet implemented commitments (using placeholder)
4356
+ new NotYetImplementedCommitmentDefinition('EXPECT'),
4357
+ new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
4358
+ new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
4359
+ new NotYetImplementedCommitmentDefinition('AVOID'),
4360
+ new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
4361
+ new NotYetImplementedCommitmentDefinition('CONTEXT'),
4362
+ ];
4380
4363
  /**
4381
- * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
4364
+ * TODO: [🧠] Maybe create through standardized $register
4365
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4382
4366
  */
4383
4367
 
4384
4368
  /**
4385
- * Converts a given text to kebab-case format.
4369
+ * Parses agent source using the new commitment system with multiline support
4370
+ * This function replaces the hardcoded commitment parsing in the original parseAgentSource
4386
4371
  *
4387
- * @param text The text to be converted.
4388
- * @returns The kebab-case formatted string.
4389
- * @example 'hello-world'
4390
- * @example 'i-love-promptbook'
4391
- * @public exported from `@promptbook/utils`
4372
+ * @private internal utility of `parseAgentSource`
4392
4373
  */
4393
- function normalizeToKebabCase(text) {
4394
- text = removeDiacritics(text);
4395
- let charType;
4396
- let lastCharType = 'OTHER';
4397
- let normalizedName = '';
4398
- for (const char of text) {
4399
- let normalizedChar;
4400
- if (/^[a-z]$/.test(char)) {
4401
- charType = 'LOWERCASE';
4402
- normalizedChar = char;
4403
- }
4404
- else if (/^[A-Z]$/.test(char)) {
4405
- charType = 'UPPERCASE';
4406
- normalizedChar = char.toLowerCase();
4407
- }
4408
- else if (/^[0-9]$/.test(char)) {
4409
- charType = 'NUMBER';
4410
- normalizedChar = char;
4374
+ function parseAgentSourceWithCommitments(agentSource) {
4375
+ var _a, _b, _c;
4376
+ if (!agentSource || !agentSource.trim()) {
4377
+ return {
4378
+ agentName: null,
4379
+ commitments: [],
4380
+ nonCommitmentLines: [],
4381
+ };
4382
+ }
4383
+ const lines = agentSource.split('\n');
4384
+ const agentName = (((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.trim()) || null);
4385
+ const commitments = [];
4386
+ const nonCommitmentLines = [];
4387
+ // Always add the first line (agent name) to non-commitment lines
4388
+ if (lines[0] !== undefined) {
4389
+ nonCommitmentLines.push(lines[0]);
4390
+ }
4391
+ // Parse commitments with multiline support
4392
+ let currentCommitment = null;
4393
+ // Process lines starting from the second line (skip agent name)
4394
+ for (let i = 1; i < lines.length; i++) {
4395
+ const line = lines[i];
4396
+ if (line === undefined) {
4397
+ continue;
4411
4398
  }
4412
- else {
4413
- charType = 'OTHER';
4414
- normalizedChar = '-';
4399
+ // Check if this line starts a new commitment
4400
+ let foundNewCommitment = false;
4401
+ for (const definition of COMMITMENT_REGISTRY) {
4402
+ const typeRegex = definition.createTypeRegex();
4403
+ const match = typeRegex.exec(line.trim());
4404
+ if (match && ((_b = match.groups) === null || _b === void 0 ? void 0 : _b.type)) {
4405
+ // Save the previous commitment if it exists
4406
+ if (currentCommitment) {
4407
+ const fullContent = currentCommitment.contentLines.join('\n');
4408
+ commitments.push({
4409
+ type: currentCommitment.type,
4410
+ content: spaceTrim(fullContent),
4411
+ originalLine: currentCommitment.originalStartLine,
4412
+ lineNumber: currentCommitment.startLineNumber,
4413
+ });
4414
+ }
4415
+ // Extract the initial content from the commitment line
4416
+ const fullRegex = definition.createRegex();
4417
+ const fullMatch = fullRegex.exec(line.trim());
4418
+ const initialContent = ((_c = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _c === void 0 ? void 0 : _c.contents) || '';
4419
+ // Start a new commitment
4420
+ currentCommitment = {
4421
+ type: definition.type,
4422
+ startLineNumber: i + 1,
4423
+ originalStartLine: line,
4424
+ contentLines: initialContent ? [initialContent] : [],
4425
+ };
4426
+ foundNewCommitment = true;
4427
+ break;
4428
+ }
4415
4429
  }
4416
- if (charType !== lastCharType &&
4417
- !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
4418
- !(lastCharType === 'NUMBER') &&
4419
- !(charType === 'NUMBER')) {
4420
- normalizedName += '-';
4430
+ if (!foundNewCommitment) {
4431
+ if (currentCommitment) {
4432
+ // This line belongs to the current commitment
4433
+ currentCommitment.contentLines.push(line);
4434
+ }
4435
+ else {
4436
+ // This line is not part of any commitment
4437
+ nonCommitmentLines.push(line);
4438
+ }
4421
4439
  }
4422
- normalizedName += normalizedChar;
4423
- lastCharType = charType;
4424
4440
  }
4425
- normalizedName = normalizedName.split(/-+/g).join('-');
4426
- normalizedName = normalizedName.split(/-?\/-?/g).join('/');
4427
- normalizedName = normalizedName.replace(/^-/, '');
4428
- normalizedName = normalizedName.replace(/-$/, '');
4429
- return normalizedName;
4441
+ // Don't forget to save the last commitment if it exists
4442
+ if (currentCommitment) {
4443
+ const fullContent = currentCommitment.contentLines.join('\n');
4444
+ commitments.push({
4445
+ type: currentCommitment.type,
4446
+ content: spaceTrim(fullContent),
4447
+ originalLine: currentCommitment.originalStartLine,
4448
+ lineNumber: currentCommitment.startLineNumber,
4449
+ });
4450
+ }
4451
+ return {
4452
+ agentName,
4453
+ commitments,
4454
+ nonCommitmentLines,
4455
+ };
4430
4456
  }
4457
+
4431
4458
  /**
4432
- * Note: [💞] Ignore a discrepancy between file name and entity name
4459
+ * Parses parameters from text using both supported notations:
4460
+ * 1. @Parameter - single word parameter starting with @
4461
+ * 2. {parameterName} or {parameter with multiple words} or {parameterName: description text}
4462
+ *
4463
+ * Both notations represent the same syntax feature - parameters
4464
+ *
4465
+ * @param text - Text to extract parameters from
4466
+ * @returns Array of parsed parameters with unified representation
4467
+ * @public exported from `@promptbook/core`
4433
4468
  */
4469
+ function parseParameters(text) {
4470
+ const parameters = [];
4471
+ // [🧠] Parameter syntax parsing - unified approach for two different notations of the same syntax feature
4472
+ // The Book language supports parameters in two different notations but they represent the same concept
4473
+ // Extract @Parameter notation (single word parameters starting with @)
4474
+ const atParameterRegex = /@[\w\u00C0-\u017F\u0100-\u024F\u1E00-\u1EFF]+/gim;
4475
+ text.replace(atParameterRegex, (match) => {
4476
+ const parameterName = match.slice(1); // Remove the @ symbol
4477
+ parameters.push({
4478
+ text: match,
4479
+ notation: 'at',
4480
+ name: parameterName,
4481
+ });
4482
+ return match;
4483
+ });
4484
+ // Extract {parameter} notation (parameters in braces)
4485
+ const braceParameterRegex = /\{([^}]+)\}/gim;
4486
+ text.replace(braceParameterRegex, (match, content) => {
4487
+ // Check if the parameter has a description (parameterName: description)
4488
+ const colonIndex = content.indexOf(':');
4489
+ if (colonIndex !== -1) {
4490
+ const name = content.substring(0, colonIndex).trim();
4491
+ const description = content.substring(colonIndex + 1).trim();
4492
+ parameters.push({
4493
+ text: match,
4494
+ notation: 'brace',
4495
+ name,
4496
+ description,
4497
+ });
4498
+ }
4499
+ else {
4500
+ // Simple parameter without description
4501
+ parameters.push({
4502
+ text: match,
4503
+ notation: 'brace',
4504
+ name: content.trim(),
4505
+ });
4506
+ }
4507
+ return match;
4508
+ });
4509
+ // Remove duplicates based on name (keep the first occurrence)
4510
+ const uniqueParameters = parameters.filter((param, index, array) => {
4511
+ return array.findIndex((p) => p.name === param.name) === index;
4512
+ });
4513
+ return uniqueParameters;
4514
+ }
4434
4515
 
4435
4516
  /**
4436
- * Removes emojis from a string and fix whitespaces
4437
- *
4438
- * Note: [🔂] This function is idempotent.
4517
+ * Creates temporary default agent name based on agent source hash
4439
4518
  *
4440
- * @param text with emojis
4441
- * @returns text without emojis
4442
- * @public exported from `@promptbook/utils`
4519
+ * @public exported from `@promptbook/core`
4443
4520
  */
4444
- function removeEmojis(text) {
4445
- // Replace emojis (and also ZWJ sequence) with hyphens
4446
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
4447
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
4448
- text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
4449
- text = text.replace(/\p{Extended_Pictographic}/gu, '');
4450
- return text;
4521
+ function createDefaultAgentName(agentSource) {
4522
+ const agentHash = computeAgentHash(agentSource);
4523
+ return normalizeAgentName(`Agent ${agentHash.substring(0, 6)}`);
4451
4524
  }
4452
4525
 
4453
4526
  /**
4454
- * Converts a title string into a normalized name.
4527
+ * Parses basic information from agent source
4455
4528
  *
4456
- * @param value The title string to be converted to a name.
4457
- * @returns A normalized name derived from the input title.
4458
- * @example 'Hello World!' -> 'hello-world'
4459
- * @public exported from `@promptbook/utils`
4529
+ * There are 2 similar functions:
4530
+ * - `parseAgentSource` which is a lightweight parser for agent source, it parses basic information and its purpose is to be quick and synchronous. The commitments there are hardcoded.
4531
+ * - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronously.
4532
+ *
4533
+ * @public exported from `@promptbook/core`
4460
4534
  */
4461
- function titleToName(value) {
4462
- if (isValidUrl(value)) {
4463
- value = value.replace(/^https?:\/\//, '');
4464
- value = value.replace(/\.html$/, '');
4535
+ function parseAgentSource(agentSource) {
4536
+ const parseResult = parseAgentSourceWithCommitments(agentSource);
4537
+ // Find PERSONA and META commitments
4538
+ let personaDescription = null;
4539
+ for (const commitment of parseResult.commitments) {
4540
+ if (commitment.type !== 'PERSONA') {
4541
+ continue;
4542
+ }
4543
+ if (personaDescription === null) {
4544
+ personaDescription = '';
4545
+ }
4546
+ else {
4547
+ personaDescription += `\n\n${personaDescription}`;
4548
+ }
4549
+ personaDescription += commitment.content;
4465
4550
  }
4466
- else if (isValidFilePath(value)) {
4467
- value = basename(value);
4468
- // Note: Keeping extension in the name
4551
+ const meta = {};
4552
+ for (const commitment of parseResult.commitments) {
4553
+ if (commitment.type !== 'META') {
4554
+ continue;
4555
+ }
4556
+ // Parse META commitments - format is "META TYPE content"
4557
+ const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
4558
+ const metaType = normalizeTo_camelCase(metaTypeRaw);
4559
+ meta[metaType] = spaceTrim$1(commitment.content.substring(metaTypeRaw.length));
4469
4560
  }
4470
- value = value.split('/').join('-');
4471
- value = removeEmojis(value);
4472
- value = normalizeToKebabCase(value);
4473
- // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
4474
- return value;
4561
+ // Generate gravatar fallback if no meta image specified
4562
+ if (!meta.image) {
4563
+ meta.image = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
4564
+ }
4565
+ // Parse parameters using unified approach - both @Parameter and {parameter} notations
4566
+ // are treated as the same syntax feature with unified representation
4567
+ const parameters = parseParameters(agentSource);
4568
+ const agentHash = computeAgentHash(agentSource);
4569
+ return {
4570
+ agentName: normalizeAgentName(parseResult.agentName || createDefaultAgentName(agentSource)),
4571
+ agentHash,
4572
+ personaDescription,
4573
+ meta,
4574
+ parameters,
4575
+ };
4475
4576
  }
4577
+ /**
4578
+ * TODO: [🕛] Unite `AgentBasicInformation`, `ChatParticipant`, `LlmExecutionTools` + `LlmToolsMetadata`
4579
+ */
4476
4580
 
4477
4581
  /**
4478
4582
  * Converts Blob, File or MediaSource to url using URL.createObjectURL