@promptbook/browser 0.103.0-47 → 0.103.0-49

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