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