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