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