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