@promptbook/browser 0.103.0-9 → 0.103.0

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 (273) hide show
  1. package/README.md +59 -39
  2. package/esm/index.es.js +4572 -128
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/books/index.d.ts +0 -81
  5. package/esm/typings/servers.d.ts +9 -7
  6. package/esm/typings/src/_packages/browser.index.d.ts +6 -0
  7. package/esm/typings/src/_packages/cli.index.d.ts +4 -0
  8. package/esm/typings/src/_packages/components.index.d.ts +22 -8
  9. package/esm/typings/src/_packages/core.index.d.ts +58 -18
  10. package/esm/typings/src/_packages/node.index.d.ts +2 -2
  11. package/esm/typings/src/_packages/remote-server.index.d.ts +2 -0
  12. package/esm/typings/src/_packages/types.index.d.ts +70 -8
  13. package/esm/typings/src/_packages/utils.index.d.ts +6 -0
  14. package/esm/typings/src/_packages/wizard.index.d.ts +4 -0
  15. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +20 -5
  16. package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +17 -1
  17. package/esm/typings/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +3 -2
  18. package/esm/typings/src/book-2.0/agent-source/computeAgentHash.d.ts +8 -0
  19. package/esm/typings/src/book-2.0/agent-source/createCommitmentRegex.d.ts +3 -3
  20. package/esm/typings/src/book-2.0/agent-source/createDefaultAgentName.d.ts +8 -0
  21. package/esm/typings/src/book-2.0/agent-source/normalizeAgentName.d.ts +9 -0
  22. package/esm/typings/src/book-2.0/agent-source/padBook.d.ts +18 -0
  23. package/esm/typings/src/book-2.0/agent-source/parseAgentSourceWithCommitments.d.ts +1 -1
  24. package/esm/typings/src/book-2.0/agent-source/string_book.d.ts +3 -0
  25. package/esm/typings/src/book-components/AvatarProfile/AvatarProfile/AvatarProfile.d.ts +6 -1
  26. package/esm/typings/src/book-components/BookEditor/BookEditor.d.ts +85 -14
  27. package/esm/typings/src/book-components/BookEditor/BookEditorActionbar.d.ts +18 -0
  28. package/esm/typings/src/book-components/BookEditor/BookEditorMonaco.d.ts +5 -0
  29. package/esm/typings/src/book-components/Chat/AgentChat/AgentChat.d.ts +17 -0
  30. package/esm/typings/src/book-components/Chat/AgentChat/AgentChatProps.d.ts +13 -0
  31. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +16 -0
  32. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  33. package/esm/typings/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +15 -0
  34. package/esm/typings/src/book-components/Chat/MockedChat/MockedChat.d.ts +5 -0
  35. package/esm/typings/src/book-components/Chat/save/_common/ChatSaveFormatDefinition.d.ts +1 -1
  36. package/esm/typings/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +1 -0
  37. package/esm/typings/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +4 -0
  38. package/esm/typings/src/book-components/Chat/types/ChatParticipant.d.ts +1 -1
  39. package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgentIntegration.d.ts +52 -0
  40. package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgentSeamlessIntegration.d.ts +14 -0
  41. package/esm/typings/src/book-components/Qr/BrandedQrCode.d.ts +18 -0
  42. package/esm/typings/src/book-components/Qr/GenericQrCode.d.ts +10 -0
  43. package/esm/typings/src/book-components/Qr/PromptbookQrCode.d.ts +18 -0
  44. package/esm/typings/src/book-components/Qr/useQrCode.d.ts +15 -0
  45. package/esm/typings/src/book-components/_common/Dropdown/Dropdown.d.ts +15 -0
  46. package/esm/typings/src/book-components/_common/HamburgerMenu/HamburgerMenu.d.ts +12 -0
  47. package/esm/typings/src/book-components/_common/Modal/Modal.d.ts +2 -2
  48. package/esm/typings/src/book-components/_common/Tooltip/Tooltip.d.ts +47 -0
  49. package/esm/typings/src/book-components/icons/AboutIcon.d.ts +9 -0
  50. package/esm/typings/src/book-components/icons/CameraIcon.d.ts +11 -0
  51. package/esm/typings/src/book-components/icons/CloseIcon.d.ts +4 -8
  52. package/esm/typings/src/book-components/icons/DownloadIcon.d.ts +9 -0
  53. package/esm/typings/src/book-components/icons/ExitFullscreenIcon.d.ts +7 -0
  54. package/esm/typings/src/book-components/icons/FullscreenIcon.d.ts +7 -0
  55. package/esm/typings/src/book-components/icons/MenuIcon.d.ts +12 -0
  56. package/esm/typings/src/book-components/icons/MicIcon.d.ts +8 -0
  57. package/esm/typings/src/book-components/icons/SendIcon.d.ts +3 -0
  58. package/esm/typings/src/cli/cli-commands/_boilerplate.d.ts +2 -1
  59. package/esm/typings/src/cli/cli-commands/about.d.ts +3 -1
  60. package/esm/typings/src/cli/cli-commands/hello.d.ts +2 -1
  61. package/esm/typings/src/cli/cli-commands/list-models.d.ts +2 -1
  62. package/esm/typings/src/cli/cli-commands/list-scrapers.d.ts +2 -1
  63. package/esm/typings/src/cli/cli-commands/login.d.ts +2 -1
  64. package/esm/typings/src/cli/cli-commands/make.d.ts +2 -1
  65. package/esm/typings/src/cli/cli-commands/prettify.d.ts +2 -1
  66. package/esm/typings/src/cli/cli-commands/run.d.ts +2 -1
  67. package/esm/typings/src/cli/cli-commands/{start-server.d.ts → start-agents-server.d.ts} +3 -2
  68. package/esm/typings/src/cli/cli-commands/start-pipelines-server.d.ts +15 -0
  69. package/esm/typings/src/cli/cli-commands/test-command.d.ts +2 -1
  70. package/esm/typings/src/cli/common/$addGlobalOptionsToCommand.d.ts +2 -1
  71. package/esm/typings/src/collection/agent-collection/AgentCollection.d.ts +12 -0
  72. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +75 -0
  73. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabaseOptions.d.ts +10 -0
  74. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +154 -0
  75. package/esm/typings/src/collection/{PipelineCollection.d.ts → pipeline-collection/PipelineCollection.d.ts} +7 -3
  76. package/esm/typings/src/collection/{SimplePipelineCollection.d.ts → pipeline-collection/SimplePipelineCollection.d.ts} +5 -5
  77. package/esm/typings/src/collection/{constructors/createCollectionFromDirectory.d.ts → pipeline-collection/constructors/createPipelineCollectionFromDirectory.d.ts} +8 -11
  78. package/esm/typings/src/collection/pipeline-collection/constructors/createPipelineCollectionFromJson.d.ts +13 -0
  79. package/esm/typings/src/collection/{constructors/createCollectionFromPromise.d.ts → pipeline-collection/constructors/createPipelineCollectionFromPromise.d.ts} +6 -5
  80. package/esm/typings/src/collection/pipeline-collection/constructors/createPipelineCollectionFromPromise.test.d.ts +1 -0
  81. package/esm/typings/src/collection/{constructors/createCollectionFromUrl.d.ts → pipeline-collection/constructors/createPipelineCollectionFromUrl.d.ts} +3 -3
  82. package/esm/typings/src/collection/{constructors/createSubcollection.d.ts → pipeline-collection/constructors/createPipelineSubcollection.d.ts} +3 -3
  83. package/esm/typings/src/collection/pipeline-collection/pipelineCollectionToJson.d.ts +13 -0
  84. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +4 -5
  85. package/esm/typings/src/{book-2.0/commitments → commitments}/ACTION/ACTION.d.ts +5 -1
  86. package/esm/typings/src/commitments/CLOSED/CLOSED.d.ts +39 -0
  87. package/esm/typings/src/commitments/CLOSED/CLOSED.test.d.ts +4 -0
  88. package/esm/typings/src/commitments/COMPONENT/COMPONENT.d.ts +28 -0
  89. package/esm/typings/src/{book-2.0/commitments → commitments}/DELETE/DELETE.d.ts +5 -1
  90. package/esm/typings/src/{book-2.0/commitments → commitments}/FORMAT/FORMAT.d.ts +5 -1
  91. package/esm/typings/src/commitments/FROM/FROM.d.ts +34 -0
  92. package/esm/typings/src/{book-2.0/commitments → commitments}/GOAL/GOAL.d.ts +5 -1
  93. package/esm/typings/src/{book-2.0/commitments → commitments}/KNOWLEDGE/KNOWLEDGE.d.ts +5 -5
  94. package/esm/typings/src/commitments/LANGUAGE/LANGUAGE.d.ts +35 -0
  95. package/esm/typings/src/{book-2.0/commitments → commitments}/MEMORY/MEMORY.d.ts +5 -1
  96. package/esm/typings/src/commitments/MESSAGE/AgentMessageCommitmentDefinition.d.ts +32 -0
  97. package/esm/typings/src/commitments/MESSAGE/InitialMessageCommitmentDefinition.d.ts +32 -0
  98. package/esm/typings/src/{book-2.0/commitments → commitments}/MESSAGE/MESSAGE.d.ts +5 -1
  99. package/esm/typings/src/commitments/MESSAGE/UserMessageCommitmentDefinition.d.ts +32 -0
  100. package/esm/typings/src/{book-2.0/commitments → commitments}/META/META.d.ts +5 -1
  101. package/esm/typings/src/commitments/META_COLOR/META_COLOR.d.ts +48 -0
  102. package/esm/typings/src/commitments/META_FONT/META_FONT.d.ts +42 -0
  103. package/esm/typings/src/{book-2.0/commitments → commitments}/META_IMAGE/META_IMAGE.d.ts +5 -1
  104. package/esm/typings/src/{book-2.0/commitments → commitments}/META_LINK/META_LINK.d.ts +5 -1
  105. package/esm/typings/src/{book-2.0/commitments → commitments}/MODEL/MODEL.d.ts +5 -1
  106. package/esm/typings/src/{book-2.0/commitments → commitments}/NOTE/NOTE.d.ts +5 -1
  107. package/esm/typings/src/commitments/OPEN/OPEN.d.ts +35 -0
  108. package/esm/typings/src/{book-2.0/commitments → commitments}/PERSONA/PERSONA.d.ts +5 -1
  109. package/esm/typings/src/{book-2.0/commitments → commitments}/RULE/RULE.d.ts +5 -1
  110. package/esm/typings/src/{book-2.0/commitments → commitments}/SAMPLE/SAMPLE.d.ts +5 -1
  111. package/esm/typings/src/{book-2.0/commitments → commitments}/SCENARIO/SCENARIO.d.ts +5 -1
  112. package/esm/typings/src/{book-2.0/commitments → commitments}/STYLE/STYLE.d.ts +5 -1
  113. package/esm/typings/src/commitments/USE/USE.d.ts +53 -0
  114. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +42 -0
  115. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.test.d.ts +1 -0
  116. package/esm/typings/src/commitments/USE_MCP/USE_MCP.d.ts +37 -0
  117. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +38 -0
  118. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/BaseCommitmentDefinition.d.ts +14 -2
  119. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/CommitmentDefinition.d.ts +6 -1
  120. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/NotYetImplementedCommitmentDefinition.d.ts +5 -1
  121. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/createEmptyAgentModelRequirements.d.ts +1 -1
  122. package/esm/typings/src/commitments/index.d.ts +93 -0
  123. package/esm/typings/src/config.d.ts +24 -3
  124. package/esm/typings/src/conversion/validation/validatePipeline.d.ts +2 -0
  125. package/esm/typings/src/errors/0-index.d.ts +6 -0
  126. package/esm/typings/src/errors/DatabaseError.d.ts +12 -0
  127. package/esm/typings/src/errors/NotAllowed.d.ts +9 -0
  128. package/esm/typings/src/errors/WrappedError.d.ts +2 -2
  129. package/esm/typings/src/execution/AvailableModel.d.ts +1 -0
  130. package/esm/typings/src/execution/Executables.d.ts +3 -0
  131. package/esm/typings/src/execution/ExecutionTask.d.ts +12 -3
  132. package/esm/typings/src/execution/ExecutionTools.d.ts +5 -0
  133. package/esm/typings/src/execution/FilesystemTools.d.ts +1 -1
  134. package/esm/typings/src/execution/LlmExecutionTools.d.ts +26 -2
  135. package/esm/typings/src/execution/PromptResult.d.ts +7 -1
  136. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +5 -0
  137. package/esm/typings/src/execution/createPipelineExecutor/20-executeTask.d.ts +5 -0
  138. package/esm/typings/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +5 -0
  139. package/esm/typings/src/execution/createPipelineExecutor/40-executeAttempts.d.ts +5 -0
  140. package/esm/typings/src/execution/utils/usage-constants.d.ts +4 -124
  141. package/esm/typings/src/execution/utils/validatePromptResult.d.ts +2 -0
  142. package/esm/typings/src/high-level-abstractions/_common/HighLevelAbstraction.d.ts +2 -1
  143. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizardOrCli.d.ts +2 -2
  144. package/esm/typings/src/llm-providers/_common/register/$registeredLlmToolsMessage.d.ts +2 -1
  145. package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +1 -1
  146. package/esm/typings/src/llm-providers/_common/utils/assertUniqueModels.d.ts +12 -0
  147. package/esm/typings/src/llm-providers/_multiple/getSingleLlmExecutionTools.d.ts +1 -0
  148. package/esm/typings/src/llm-providers/_multiple/joinLlmExecutionTools.d.ts +1 -0
  149. package/esm/typings/src/llm-providers/agent/Agent.d.ts +72 -0
  150. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +26 -4
  151. package/esm/typings/src/llm-providers/agent/AgentOptions.d.ts +19 -0
  152. package/esm/typings/src/llm-providers/agent/CreateAgentLlmExecutionToolsOptions.d.ts +17 -0
  153. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +50 -0
  154. package/esm/typings/src/llm-providers/agent/RemoteAgentOptions.d.ts +11 -0
  155. package/esm/typings/src/llm-providers/agent/createAgentLlmExecutionTools.d.ts +1 -19
  156. package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  157. package/esm/typings/src/llm-providers/google/google-models.d.ts +1 -1
  158. package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +4 -0
  159. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +60 -2
  160. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionToolsOptions.d.ts +7 -1
  161. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +13 -1
  162. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
  163. package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +6 -6
  164. package/esm/typings/src/llm-providers/openai/openai-models.d.ts +1 -1
  165. package/esm/typings/src/llm-providers/openai/openai-models.test.d.ts +4 -0
  166. package/esm/typings/src/other/templates/getTemplatesPipelineCollection.d.ts +1 -1
  167. package/esm/typings/src/pipeline/validatePipelineString.d.ts +2 -0
  168. package/esm/typings/src/playground/permanent/_boilerplate.d.ts +5 -0
  169. package/esm/typings/src/playground/permanent/agent-with-browser-playground.d.ts +5 -0
  170. package/esm/typings/src/prepare/PrepareAndScrapeOptions.d.ts +1 -0
  171. package/esm/typings/src/remote-server/startAgentServer.d.ts +26 -0
  172. package/esm/typings/src/remote-server/startRemoteServer.d.ts +4 -1
  173. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +3 -8
  174. package/esm/typings/src/scrapers/_boilerplate/createBoilerplateScraper.d.ts +1 -12
  175. package/esm/typings/src/scrapers/_boilerplate/register-metadata.d.ts +1 -9
  176. package/esm/typings/src/scrapers/document/createDocumentScraper.d.ts +1 -12
  177. package/esm/typings/src/scrapers/document/register-metadata.d.ts +1 -9
  178. package/esm/typings/src/scrapers/document-legacy/createLegacyDocumentScraper.d.ts +1 -12
  179. package/esm/typings/src/scrapers/document-legacy/register-metadata.d.ts +1 -9
  180. package/esm/typings/src/scrapers/markdown/createMarkdownScraper.d.ts +1 -12
  181. package/esm/typings/src/scrapers/markdown/register-metadata.d.ts +1 -9
  182. package/esm/typings/src/scrapers/markitdown/createMarkitdownScraper.d.ts +1 -12
  183. package/esm/typings/src/scrapers/markitdown/register-metadata.d.ts +1 -9
  184. package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +1 -12
  185. package/esm/typings/src/scrapers/pdf/register-metadata.d.ts +1 -9
  186. package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +1 -12
  187. package/esm/typings/src/scrapers/website/register-metadata.d.ts +1 -9
  188. package/esm/typings/src/storage/_common/PromptbookStorage.d.ts +1 -0
  189. package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +2 -1
  190. package/esm/typings/src/transpilers/_common/BookTranspiler.d.ts +33 -0
  191. package/esm/typings/src/transpilers/_common/BookTranspilerOptions.d.ts +18 -0
  192. package/esm/typings/src/transpilers/_common/register/$bookTranspilersRegister.d.ts +15 -0
  193. package/esm/typings/src/transpilers/formatted-book-in-markdown/FormattedBookInMarkdownTranspiler.d.ts +16 -0
  194. package/esm/typings/src/transpilers/formatted-book-in-markdown/register.d.ts +15 -0
  195. package/esm/typings/src/transpilers/openai-sdk/OpenAiSdkTranspiler.d.ts +16 -0
  196. package/esm/typings/src/transpilers/openai-sdk/OpenAiSdkTranspiler.test.d.ts +1 -0
  197. package/esm/typings/src/transpilers/openai-sdk/playground/playground.d.ts +5 -0
  198. package/esm/typings/src/transpilers/openai-sdk/register.d.ts +15 -0
  199. package/esm/typings/src/types/LlmCall.d.ts +20 -0
  200. package/esm/typings/src/types/ModelRequirements.d.ts +13 -1
  201. package/esm/typings/src/types/ModelVariant.d.ts +1 -1
  202. package/esm/typings/src/types/Prompt.d.ts +13 -1
  203. package/esm/typings/src/types/Updatable.d.ts +19 -0
  204. package/esm/typings/src/types/typeAliases.d.ts +38 -2
  205. package/esm/typings/src/utils/color/$randomColor.d.ts +1 -0
  206. package/esm/typings/src/utils/color/Color.d.ts +16 -1
  207. package/esm/typings/src/utils/color/Color.test.d.ts +1 -0
  208. package/esm/typings/src/utils/color/css-colors.d.ts +1 -0
  209. package/esm/typings/src/utils/color/internal-utils/checkChannelValue.d.ts +0 -3
  210. package/esm/typings/src/utils/color/operators/darken.d.ts +1 -1
  211. package/esm/typings/src/utils/color/operators/grayscale.d.ts +1 -1
  212. package/esm/typings/src/utils/color/operators/lighten.d.ts +1 -1
  213. package/esm/typings/src/utils/color/operators/mixWithColor.d.ts +1 -1
  214. package/esm/typings/src/utils/color/operators/saturate.d.ts +1 -1
  215. package/esm/typings/src/utils/environment/$detectRuntimeEnvironment.d.ts +16 -0
  216. package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -2
  217. package/esm/typings/src/utils/execCommand/$execCommand.d.ts +2 -1
  218. package/esm/typings/src/utils/execCommand/$execCommands.d.ts +2 -1
  219. package/esm/typings/src/utils/files/$induceBookDownload.d.ts +13 -0
  220. package/esm/typings/src/utils/files/$induceFileDownload.d.ts +13 -0
  221. package/esm/typings/src/utils/files/ObjectUrl.d.ts +46 -0
  222. package/esm/typings/src/utils/files/listAllFiles.d.ts +2 -3
  223. package/esm/typings/src/utils/misc/aboutPromptbookInformation.d.ts +27 -0
  224. package/esm/typings/src/utils/misc/computeHash.d.ts +11 -0
  225. package/esm/typings/src/utils/misc/computeHash.test.d.ts +1 -0
  226. package/esm/typings/src/utils/misc/injectCssModuleIntoShadowRoot.d.ts +1 -0
  227. package/esm/typings/src/utils/misc/xAboutPromptbookInformation.d.ts +13 -0
  228. package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +2 -0
  229. package/esm/typings/src/utils/normalization/normalizeMessageText.d.ts +9 -0
  230. package/esm/typings/src/utils/normalization/normalizeMessageText.test.d.ts +1 -0
  231. package/esm/typings/src/utils/normalization/normalizeTo_PascalCase.d.ts +3 -0
  232. package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +2 -0
  233. package/esm/typings/src/utils/normalization/titleToName.d.ts +2 -0
  234. package/esm/typings/src/utils/organization/$sideEffect.d.ts +2 -2
  235. package/esm/typings/src/utils/organization/$side_effect.d.ts +7 -0
  236. package/esm/typings/src/utils/organization/TODO_USE.d.ts +2 -2
  237. package/esm/typings/src/utils/organization/keepUnused.d.ts +2 -2
  238. package/esm/typings/src/utils/organization/preserve.d.ts +3 -3
  239. package/esm/typings/src/utils/organization/really_any.d.ts +7 -0
  240. package/esm/typings/src/utils/random/$generateBookBoilerplate.d.ts +31 -0
  241. package/esm/typings/src/utils/random/$randomAgentPersona.d.ts +9 -0
  242. package/esm/typings/src/utils/random/$randomFullnameWithColor.d.ts +13 -0
  243. package/esm/typings/src/utils/random/$randomItem.d.ts +9 -0
  244. package/esm/typings/src/utils/random/$randomSeed.d.ts +3 -0
  245. package/esm/typings/src/utils/random/$randomToken.d.ts +2 -0
  246. package/esm/typings/src/utils/random/CzechNamePool.d.ts +7 -0
  247. package/esm/typings/src/utils/random/EnglishNamePool.d.ts +7 -0
  248. package/esm/typings/src/utils/random/NamePool.d.ts +17 -0
  249. package/esm/typings/src/utils/random/getNamePool.d.ts +10 -0
  250. package/esm/typings/src/utils/serialization/$deepFreeze.d.ts +2 -1
  251. package/esm/typings/src/utils/serialization/asSerializable.d.ts +2 -2
  252. package/esm/typings/src/utils/serialization/serializeToPromptbookJavascript.d.ts +2 -2
  253. package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +2 -0
  254. package/esm/typings/src/version.d.ts +1 -1
  255. package/esm/typings/src/wizard/$getCompiledBook.d.ts +1 -2
  256. package/package.json +7 -5
  257. package/umd/index.umd.js +4567 -122
  258. package/umd/index.umd.js.map +1 -1
  259. package/esm/typings/src/book-2.0/commitments/index.d.ts +0 -60
  260. package/esm/typings/src/book-components/BookEditor/BookEditorInner.d.ts +0 -5
  261. package/esm/typings/src/book-components/BookEditor/BookEditorWrapper.d.ts +0 -9
  262. package/esm/typings/src/book-components/BookEditor/config.d.ts +0 -10
  263. package/esm/typings/src/book-components/Chat/utils/renderMarkdown.d.ts +0 -21
  264. package/esm/typings/src/collection/collectionToJson.d.ts +0 -13
  265. package/esm/typings/src/collection/constructors/createCollectionFromJson.d.ts +0 -13
  266. /package/esm/typings/src/{book-components/Chat/utils/renderMarkdown.test.d.ts → book-2.0/agent-source/computeAgentHash.test.d.ts} +0 -0
  267. /package/esm/typings/src/{collection/constructors/createCollectionFromDirectory.test.d.ts → book-2.0/agent-source/normalizeAgentName.test.d.ts} +0 -0
  268. /package/esm/typings/src/{collection/constructors/createCollectionFromJson.test.d.ts → book-components/Chat/AgentChat/AgentChat.test.d.ts} +0 -0
  269. /package/esm/typings/src/collection/{constructors/createCollectionFromPromise.test.d.ts → pipeline-collection/constructors/createPipelineCollectionFromDirectory.test.d.ts} +0 -0
  270. /package/esm/typings/src/{commands/_common/parseCommand.test.d.ts → collection/pipeline-collection/constructors/createPipelineCollectionFromJson.test.d.ts} +0 -0
  271. /package/esm/typings/src/collection/{collectionToJson.test.d.ts → pipeline-collection/pipelineCollectionToJson.test.d.ts} +0 -0
  272. /package/esm/typings/src/{book-2.0/commitments → commitments}/_base/BookCommitment.d.ts +0 -0
  273. /package/esm/typings/src/{book-2.0/commitments → commitments}/_base/ParsedCommitment.d.ts +0 -0
package/esm/index.es.js CHANGED
@@ -1,6 +1,9 @@
1
- import spaceTrim$1, { spaceTrim } from 'spacetrim';
1
+ import spaceTrim$2, { spaceTrim as spaceTrim$1 } from 'spacetrim';
2
2
  import { randomBytes } from 'crypto';
3
- import { isRunningInBrowser } from 'openai/core';
3
+ import { SHA256 } from 'crypto-js';
4
+ import hexEncoder from 'crypto-js/enc-hex';
5
+ import { basename } from 'path';
6
+ import { Registration } from 'destroyable';
4
7
 
5
8
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
6
9
  /**
@@ -9,14 +12,14 @@ import { isRunningInBrowser } from 'openai/core';
9
12
  * @generated
10
13
  * @see https://github.com/webgptorg/book
11
14
  */
12
- const BOOK_LANGUAGE_VERSION = '1.0.0';
15
+ const BOOK_LANGUAGE_VERSION = '2.0.0';
13
16
  /**
14
17
  * The version of the Promptbook engine
15
18
  *
16
19
  * @generated
17
20
  * @see https://github.com/webgptorg/promptbook
18
21
  */
19
- const PROMPTBOOK_ENGINE_VERSION = '0.103.0-9';
22
+ const PROMPTBOOK_ENGINE_VERSION = '0.103.0';
20
23
  /**
21
24
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
22
25
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -25,6 +28,7 @@ const PROMPTBOOK_ENGINE_VERSION = '0.103.0-9';
25
28
  /**
26
29
  * Generates random token
27
30
  *
31
+ * Note: `$` is used to indicate that this function is not a pure function - it is not deterministic
28
32
  * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
29
33
  *
30
34
  * @private internal helper function
@@ -34,6 +38,7 @@ function $randomToken(randomness) {
34
38
  return randomBytes(randomness).toString('hex');
35
39
  }
36
40
  /**
41
+ * TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
37
42
  * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
38
43
  */
39
44
 
@@ -72,13 +77,13 @@ class SimplePromptInterfaceTools {
72
77
  * Trigger window.prompt dialog
73
78
  */
74
79
  async promptDialog(options) {
75
- const answer = window.prompt(spaceTrim((block) => `
80
+ const answer = window.prompt(spaceTrim$1((block) => `
76
81
  ${block(options.promptTitle)}
77
82
 
78
83
  ${block(options.promptMessage)}
79
84
  `));
80
85
  if (this.options.isVerbose) {
81
- console.info(spaceTrim((block) => `
86
+ console.info(spaceTrim$1((block) => `
82
87
  📖 ${block(options.promptTitle)}
83
88
  👤 ${block(answer || '🚫 User cancelled prompt')}
84
89
  `));
@@ -146,6 +151,17 @@ const $isRunningInWebWorker = new Function(`
146
151
  * TODO: [🎺]
147
152
  */
148
153
 
154
+ /**
155
+ * Trims string from all 4 sides
156
+ *
157
+ * Note: This is a re-exported function from the `spacetrim` package which is
158
+ * Developed by same author @hejny as this package
159
+ *
160
+ * @public exported from `@promptbook/utils`
161
+ * @see https://github.com/hejny/spacetrim#usage
162
+ */
163
+ const spaceTrim = spaceTrim$1;
164
+
149
165
  /**
150
166
  * @private util of `@promptbook/color`
151
167
  * @de
@@ -194,6 +210,7 @@ function take(initialValue) {
194
210
  * @public exported from `@promptbook/color`
195
211
  */
196
212
  const CSS_COLORS = {
213
+ promptbook: '#79EAFD',
197
214
  transparent: 'rgba(0,0,0,0)',
198
215
  aliceblue: '#f0f8ff',
199
216
  antiquewhite: '#faebd7',
@@ -375,9 +392,6 @@ function checkChannelValue(channelName, value) {
375
392
  throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
376
393
  }
377
394
  }
378
- /**
379
- * TODO: [🧠][🚓] Is/which combination it better to use asserts/check, validate or is utility function?
380
- */
381
395
 
382
396
  /**
383
397
  * Color object represents an RGB color with alpha channel
@@ -397,21 +411,61 @@ class Color {
397
411
  * @param color
398
412
  * @returns Color object
399
413
  */
400
- static from(color) {
401
- if (color instanceof Color) {
414
+ static from(color, _isSingleValue = false) {
415
+ if (color === '') {
416
+ throw new Error(`Can not create color from empty string`);
417
+ }
418
+ else if (color instanceof Color) {
402
419
  return take(color);
403
420
  }
404
421
  else if (Color.isColor(color)) {
405
422
  return take(color);
406
423
  }
407
424
  else if (typeof color === 'string') {
408
- return Color.fromString(color);
425
+ try {
426
+ return Color.fromString(color);
427
+ }
428
+ catch (error) {
429
+ // <- Note: Can not use `assertsError(error)` here because it causes circular dependency
430
+ if (_isSingleValue) {
431
+ throw error;
432
+ }
433
+ const parts = color.split(/[\s+,;|]/);
434
+ if (parts.length > 0) {
435
+ return Color.from(parts[0].trim(), true);
436
+ }
437
+ else {
438
+ throw new Error(`Can not create color from given string "${color}"`);
439
+ }
440
+ }
409
441
  }
410
442
  else {
411
443
  console.error({ color });
412
444
  throw new Error(`Can not create color from given object`);
413
445
  }
414
446
  }
447
+ /**
448
+ * Creates a new Color instance from miscellaneous formats
449
+ * It just does not throw error when it fails, it returns PROMPTBOOK_COLOR instead
450
+ *
451
+ * @param color
452
+ * @returns Color object
453
+ */
454
+ static fromSafe(color) {
455
+ try {
456
+ return Color.from(color);
457
+ }
458
+ catch (error) {
459
+ // <- Note: Can not use `assertsError(error)` here because it causes circular dependency
460
+ console.warn(spaceTrim((block) => `
461
+ Color.fromSafe error:
462
+ ${block(error.message)}
463
+
464
+ Returning default PROMPTBOOK_COLOR.
465
+ `));
466
+ return Color.fromString('promptbook');
467
+ }
468
+ }
415
469
  /**
416
470
  * Creates a new Color instance from miscellaneous string formats
417
471
  *
@@ -479,6 +533,9 @@ class Color {
479
533
  if (hex.length === 3) {
480
534
  return Color.fromHex3(hex);
481
535
  }
536
+ if (hex.length === 4) {
537
+ return Color.fromHex4(hex);
538
+ }
482
539
  if (hex.length === 6) {
483
540
  return Color.fromHex6(hex);
484
541
  }
@@ -499,6 +556,19 @@ class Color {
499
556
  const b = parseInt(hex.substr(2, 1), 16) * 16;
500
557
  return take(new Color(r, g, b));
501
558
  }
559
+ /**
560
+ * Creates a new Color instance from color in hex format with 4 digits (with alpha channel)
561
+ *
562
+ * @param color in hex for example `09df`
563
+ * @returns Color object
564
+ */
565
+ static fromHex4(hex) {
566
+ const r = parseInt(hex.substr(0, 1), 16) * 16;
567
+ const g = parseInt(hex.substr(1, 1), 16) * 16;
568
+ const b = parseInt(hex.substr(2, 1), 16) * 16;
569
+ const a = parseInt(hex.substr(3, 1), 16) * 16;
570
+ return take(new Color(r, g, b, a));
571
+ }
502
572
  /**
503
573
  * Creates a new Color instance from color in hex format with 6 color digits (without alpha channel)
504
574
  *
@@ -689,7 +759,8 @@ class Color {
689
759
  * @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
690
760
  */
691
761
  static isHexColorString(value) {
692
- return typeof value === 'string' && /^#(?:[0-9a-fA-F]{3}){1,2}$/.test(value);
762
+ return (typeof value === 'string' &&
763
+ /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
693
764
  }
694
765
  /**
695
766
  * Creates new Color object
@@ -804,6 +875,23 @@ class Color {
804
875
  * TODO: Maybe connect with textures
805
876
  */
806
877
 
878
+ /**
879
+ * Makes color transformer which returns a grayscale version of the color
880
+ *
881
+ * @param amount from 0 to 1
882
+ *
883
+ * @public exported from `@promptbook/color`
884
+ */
885
+ function grayscale(amount) {
886
+ return ({ red, green, blue, alpha }) => {
887
+ const average = (red + green + blue) / 3;
888
+ red = Math.round(average * amount + red * (1 - amount));
889
+ green = Math.round(average * amount + green * (1 - amount));
890
+ blue = Math.round(average * amount + blue * (1 - amount));
891
+ return Color.fromValues(red, green, blue, alpha);
892
+ };
893
+ }
894
+
807
895
  /**
808
896
  * Converts HSL values to RGB values
809
897
  *
@@ -919,102 +1007,6 @@ function lighten(amount) {
919
1007
  * TODO: Maybe implement by mix+hsl
920
1008
  */
921
1009
 
922
- /**
923
- * Calculates distance between two colors
924
- *
925
- * @param color1 first color
926
- * @param color2 second color
927
- *
928
- * Note: This function is inefficient. Use colorDistanceSquared instead if possible.
929
- *
930
- * @public exported from `@promptbook/color`
931
- */
932
- /**
933
- * Calculates distance between two colors without square root
934
- *
935
- * @param color1 first color
936
- * @param color2 second color
937
- *
938
- * @public exported from `@promptbook/color`
939
- */
940
- function colorDistanceSquared(color1, color2) {
941
- const rmean = (color1.red + color2.red) / 2;
942
- const r = color1.red - color2.red;
943
- const g = color1.green - color2.green;
944
- const b = color1.blue - color2.blue;
945
- const weightR = 2 + rmean / 256;
946
- const weightG = 4.0;
947
- const weightB = 2 + (255 - rmean) / 256;
948
- const distance = weightR * r * r + weightG * g * g + weightB * b * b;
949
- return distance;
950
- }
951
-
952
- /**
953
- * Makes color transformer which finds the nearest color from the given list
954
- *
955
- * @param colors array of colors to choose from
956
- *
957
- * @public exported from `@promptbook/color`
958
- */
959
- function nearest(...colors) {
960
- return (color) => {
961
- const distances = colors.map((c) => colorDistanceSquared(c, color));
962
- const minDistance = Math.min(...distances);
963
- const minIndex = distances.indexOf(minDistance);
964
- const nearestColor = colors[minIndex];
965
- return nearestColor;
966
- };
967
- }
968
-
969
- /**
970
- * Color transformer which returns the negative color
971
- *
972
- * @public exported from `@promptbook/color`
973
- */
974
- function negative(color) {
975
- const r = 255 - color.red;
976
- const g = 255 - color.green;
977
- const b = 255 - color.blue;
978
- return Color.fromValues(r, g, b, color.alpha);
979
- }
980
-
981
- /**
982
- * Makes color transformer which finds the furthest color from the given list
983
- *
984
- * @param colors array of colors to choose from
985
- *
986
- * @public exported from `@promptbook/color`
987
- */
988
- function furthest(...colors) {
989
- return (color) => {
990
- const furthestColor = negative(nearest(...colors.map(negative))(color));
991
- return furthestColor;
992
- };
993
- }
994
- /**
995
- * Makes color transformer which finds the best text color (black or white) for the given background color
996
- *
997
- * @public exported from `@promptbook/color`
998
- */
999
- furthest(Color.get('white'), Color.from('black'));
1000
-
1001
- /**
1002
- * Makes color transformer which returns a grayscale version of the color
1003
- *
1004
- * @param amount from 0 to 1
1005
- *
1006
- * @public exported from `@promptbook/color`
1007
- */
1008
- function grayscale(amount) {
1009
- return ({ red, green, blue, alpha }) => {
1010
- const average = (red + green + blue) / 3;
1011
- red = Math.round(average * amount + red * (1 - amount));
1012
- green = Math.round(average * amount + green * (1 - amount));
1013
- blue = Math.round(average * amount + blue * (1 - amount));
1014
- return Color.fromValues(red, green, blue, alpha);
1015
- };
1016
- }
1017
-
1018
1010
  /**
1019
1011
  * Makes color transformer which saturate the given color
1020
1012
  *
@@ -1063,16 +1055,32 @@ const ADMIN_GITHUB_NAME = 'hejny';
1063
1055
  *
1064
1056
  * @public exported from `@promptbook/core`
1065
1057
  */
1066
- const PROMPTBOOK_COLOR = Color.fromHex('#79EAFD');
1067
- // <- TODO: [🧠] Using `Color` here increases the package size approx 3kb, maybe remove it
1058
+ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
1059
+ // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
1060
+ /**
1061
+ * Colors for syntax highlighting in the `<BookEditor/>`
1062
+ *
1063
+ * TODO: [🗽] Unite branding and make single place for it
1064
+ *
1065
+ * @public exported from `@promptbook/core`
1066
+ */
1067
+ ({
1068
+ TITLE: Color.fromHex('#244EA8'),
1069
+ LINE: Color.fromHex('#eeeeee'),
1070
+ SEPARATOR: Color.fromHex('#cccccc'),
1071
+ COMMITMENT: Color.fromHex('#DA0F78'),
1072
+ PARAMETER: Color.fromHex('#8e44ad'),
1073
+ });
1074
+ // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
1068
1075
  /**
1069
- * Dark color of the Promptbook
1076
+ * Chat color of the Promptbook (in chat)
1070
1077
  *
1071
1078
  * TODO: [🗽] Unite branding and make single place for it
1072
1079
  *
1073
1080
  * @public exported from `@promptbook/core`
1074
1081
  */
1075
1082
  PROMPTBOOK_COLOR.then(lighten(0.1)).then(saturate(0.9)).then(grayscale(0.9));
1083
+ // <- TODO: [🧠][🈵] Using `Color` and `lighten`, `saturate`,... here increases the package size approx 3kb, maybe remove it
1076
1084
  /**
1077
1085
  * Color of the user (in chat)
1078
1086
  *
@@ -1088,6 +1096,27 @@ Color.fromHex('#1D4ED8');
1088
1096
  * @private within the repository - too low-level in comparison with other `MAX_...`
1089
1097
  */
1090
1098
  const LOOP_LIMIT = 1000;
1099
+ /**
1100
+ * Strings to represent various values in the context of parameter values
1101
+ *
1102
+ * @public exported from `@promptbook/utils`
1103
+ */
1104
+ const VALUE_STRINGS = {
1105
+ empty: '(nothing; empty string)',
1106
+ null: '(no value; null)',
1107
+ undefined: '(unknown value; undefined)',
1108
+ nan: '(not a number; NaN)',
1109
+ infinity: '(infinity; ∞)',
1110
+ negativeInfinity: '(negative infinity; -∞)',
1111
+ unserializable: '(unserializable value)',
1112
+ circular: '(circular JSON)',
1113
+ };
1114
+ /**
1115
+ * Small number limit
1116
+ *
1117
+ * @public exported from `@promptbook/utils`
1118
+ */
1119
+ const SMALL_NUMBER = 0.001;
1091
1120
  // <- TODO: [🧜‍♂️]
1092
1121
  /**
1093
1122
  * Default settings for parsing and generating CSV files in Promptbook.
@@ -1119,7 +1148,7 @@ parseInt(process.env.API_REQUEST_TIMEOUT || '90000');
1119
1148
  */
1120
1149
  class NotYetImplementedError extends Error {
1121
1150
  constructor(message) {
1122
- super(spaceTrim((block) => `
1151
+ super(spaceTrim$1((block) => `
1123
1152
  ${block(message)}
1124
1153
 
1125
1154
  Note: This feature is not implemented yet but it will be soon.
@@ -1143,7 +1172,7 @@ class NotYetImplementedError extends Error {
1143
1172
  function getErrorReportUrl(error) {
1144
1173
  const report = {
1145
1174
  title: `🐜 Error report from ${NAME}`,
1146
- body: spaceTrim$1((block) => `
1175
+ body: spaceTrim$2((block) => `
1147
1176
 
1148
1177
 
1149
1178
  \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
@@ -1186,7 +1215,7 @@ function getErrorReportUrl(error) {
1186
1215
  */
1187
1216
  class UnexpectedError extends Error {
1188
1217
  constructor(message) {
1189
- super(spaceTrim((block) => `
1218
+ super(spaceTrim$1((block) => `
1190
1219
  ${block(message)}
1191
1220
 
1192
1221
  Note: This error should not happen.
@@ -1438,7 +1467,7 @@ const indexedDbStorageCache = new Map();
1438
1467
  * @public exported from `@promptbook/browser`
1439
1468
  */
1440
1469
  function getIndexedDbStorage(options) {
1441
- if (!isRunningInBrowser()) {
1470
+ if (!$isRunningInBrowser()) {
1442
1471
  throw new EnvironmentMismatchError(`You can get IndexedDB storage only in browser environment`);
1443
1472
  }
1444
1473
  const { databaseName, storeName } = options;
@@ -1467,7 +1496,7 @@ function jsonParse(value) {
1467
1496
  }
1468
1497
  else if (typeof value !== 'string') {
1469
1498
  console.error('Can not parse JSON from non-string value.', { text: value });
1470
- throw new Error(spaceTrim$1(`
1499
+ throw new Error(spaceTrim$2(`
1471
1500
  Can not parse JSON from non-string value.
1472
1501
 
1473
1502
  The value type: ${typeof value}
@@ -1481,7 +1510,7 @@ function jsonParse(value) {
1481
1510
  if (!(error instanceof Error)) {
1482
1511
  throw error;
1483
1512
  }
1484
- throw new Error(spaceTrim$1((block) => `
1513
+ throw new Error(spaceTrim$2((block) => `
1485
1514
  ${block(error.message)}
1486
1515
 
1487
1516
  The expected JSON text:
@@ -1541,7 +1570,7 @@ class WrappedError extends Error {
1541
1570
  constructor(whatWasThrown) {
1542
1571
  const tag = `[🤮]`;
1543
1572
  console.error(tag, whatWasThrown);
1544
- super(spaceTrim(`
1573
+ super(spaceTrim$1(`
1545
1574
  Non-Error object was thrown
1546
1575
 
1547
1576
  Note: Look for ${tag} in the console for more details
@@ -1630,7 +1659,7 @@ function checkSerializableAsJson(options) {
1630
1659
  }
1631
1660
  else if (typeof value === 'object') {
1632
1661
  if (value instanceof Date) {
1633
- throw new UnexpectedError(spaceTrim$1((block) => `
1662
+ throw new UnexpectedError(spaceTrim$2((block) => `
1634
1663
  \`${name}\` is Date
1635
1664
 
1636
1665
  Use \`string_date_iso8601\` instead
@@ -1649,7 +1678,7 @@ function checkSerializableAsJson(options) {
1649
1678
  throw new UnexpectedError(`${name} is RegExp`);
1650
1679
  }
1651
1680
  else if (value instanceof Error) {
1652
- throw new UnexpectedError(spaceTrim$1((block) => `
1681
+ throw new UnexpectedError(spaceTrim$2((block) => `
1653
1682
  \`${name}\` is unserialized Error
1654
1683
 
1655
1684
  Use function \`serializeError\`
@@ -1672,7 +1701,7 @@ function checkSerializableAsJson(options) {
1672
1701
  }
1673
1702
  catch (error) {
1674
1703
  assertsError(error);
1675
- throw new UnexpectedError(spaceTrim$1((block) => `
1704
+ throw new UnexpectedError(spaceTrim$2((block) => `
1676
1705
  \`${name}\` is not serializable
1677
1706
 
1678
1707
  ${block(error.stack || error.message)}
@@ -1704,7 +1733,7 @@ function checkSerializableAsJson(options) {
1704
1733
  }
1705
1734
  }
1706
1735
  else {
1707
- throw new UnexpectedError(spaceTrim$1((block) => `
1736
+ throw new UnexpectedError(spaceTrim$2((block) => `
1708
1737
  \`${name}\` is unknown type
1709
1738
 
1710
1739
  Additional message for \`${name}\`:
@@ -1734,7 +1763,7 @@ function deepClone(objectValue) {
1734
1763
  TODO: [🧠] Is there a better implementation?
1735
1764
  > const propertyNames = Object.getOwnPropertyNames(objectValue);
1736
1765
  > for (const propertyName of propertyNames) {
1737
- > const value = (objectValue as really_any)[propertyName];
1766
+ > const value = (objectValue as chococake)[propertyName];
1738
1767
  > if (value && typeof value === 'object') {
1739
1768
  > deepClone(value);
1740
1769
  > }
@@ -1854,7 +1883,7 @@ function isSerializableAsJson(value) {
1854
1883
  */
1855
1884
  function stringifyPipelineJson(pipeline) {
1856
1885
  if (!isSerializableAsJson(pipeline)) {
1857
- throw new UnexpectedError(spaceTrim$1(`
1886
+ throw new UnexpectedError(spaceTrim$2(`
1858
1887
  Cannot stringify the pipeline, because it is not serializable as JSON
1859
1888
 
1860
1889
  There can be multiple reasons:
@@ -1923,7 +1952,7 @@ let promptbookLocalStorage = null;
1923
1952
  * @public exported from `@promptbook/browser`
1924
1953
  */
1925
1954
  function getLocalStorage() {
1926
- if (!isRunningInBrowser()) {
1955
+ if (!$isRunningInBrowser()) {
1927
1956
  throw new EnvironmentMismatchError(`You can get localStorage works only in browser environment`);
1928
1957
  }
1929
1958
  if (promptbookLocalStorage) {
@@ -1948,7 +1977,7 @@ let promptbookSessionStorage = null;
1948
1977
  * @public exported from `@promptbook/browser`
1949
1978
  */
1950
1979
  function getSessionStorage() {
1951
- if (!isRunningInBrowser()) {
1980
+ if (!$isRunningInBrowser()) {
1952
1981
  throw new EnvironmentMismatchError(`You can get sessionStorage works only in browser environment`);
1953
1982
  }
1954
1983
  if (promptbookSessionStorage) {
@@ -1961,5 +1990,4420 @@ function getSessionStorage() {
1961
1990
  * Note: [🔵] Code in this file should never be published outside of `@promptbook/browser`
1962
1991
  */
1963
1992
 
1964
- export { $provideScrapersForBrowser, BOOK_LANGUAGE_VERSION, PROMPTBOOK_ENGINE_VERSION, SimplePromptInterfaceTools, getIndexedDbStorage, getLocalStorage, getSessionStorage };
1993
+ /**
1994
+ * Normalizes a given text to camelCase format.
1995
+ *
1996
+ * Note: [🔂] This function is idempotent.
1997
+ *
1998
+ * @param text The text to be normalized.
1999
+ * @param _isFirstLetterCapital Whether the first letter should be capitalized.
2000
+ * @returns The camelCase formatted string.
2001
+ * @example 'helloWorld'
2002
+ * @example 'iLovePromptbook'
2003
+ * @public exported from `@promptbook/utils`
2004
+ */
2005
+ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
2006
+ let charType;
2007
+ let lastCharType = null;
2008
+ let normalizedName = '';
2009
+ for (const char of text) {
2010
+ let normalizedChar;
2011
+ if (/^[a-z]$/.test(char)) {
2012
+ charType = 'LOWERCASE';
2013
+ normalizedChar = char;
2014
+ }
2015
+ else if (/^[A-Z]$/.test(char)) {
2016
+ charType = 'UPPERCASE';
2017
+ normalizedChar = char.toLowerCase();
2018
+ }
2019
+ else if (/^[0-9]$/.test(char)) {
2020
+ charType = 'NUMBER';
2021
+ normalizedChar = char;
2022
+ }
2023
+ else {
2024
+ charType = 'OTHER';
2025
+ normalizedChar = '';
2026
+ }
2027
+ if (!lastCharType) {
2028
+ if (_isFirstLetterCapital) {
2029
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
2030
+ }
2031
+ }
2032
+ else if (charType !== lastCharType &&
2033
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
2034
+ !(lastCharType === 'NUMBER') &&
2035
+ !(charType === 'NUMBER')) {
2036
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
2037
+ }
2038
+ normalizedName += normalizedChar;
2039
+ lastCharType = charType;
2040
+ }
2041
+ return normalizedName;
2042
+ }
2043
+ /**
2044
+ * TODO: [🌺] Use some intermediate util splitWords
2045
+ */
2046
+
2047
+ /**
2048
+ * Generates a gravatar URL based on agent name for fallback avatar
2049
+ *
2050
+ * @param agentName The agent name to generate avatar for
2051
+ * @returns Gravatar URL
2052
+ *
2053
+ * @private - [🤹] The fact that profile image is Gravatar is just implementation detail which should be hidden for consumer
2054
+ */
2055
+ function generateGravatarUrl(agentName) {
2056
+ // Use a default name if none provided
2057
+ const safeName = agentName || 'Anonymous Agent';
2058
+ // Create a simple hash from the name for consistent avatar
2059
+ let hash = 0;
2060
+ for (let i = 0; i < safeName.length; i++) {
2061
+ const char = safeName.charCodeAt(i);
2062
+ hash = (hash << 5) - hash + char;
2063
+ hash = hash & hash; // Convert to 32bit integer
2064
+ }
2065
+ const avatarId = Math.abs(hash).toString();
2066
+ return `https://www.gravatar.com/avatar/${avatarId}?default=robohash&size=200&rating=x`;
2067
+ }
2068
+
2069
+ /**
2070
+ * Generates an image for the agent to use as profile image
2071
+ *
2072
+ * @param agentName The agent name to generate avatar for
2073
+ * @returns The placeholder profile image URL for the agent
2074
+ *
2075
+ * @public exported from `@promptbook/core`
2076
+ */
2077
+ function generatePlaceholderAgentProfileImageUrl(agentName) {
2078
+ // Note: [🤹] The fact that profile image is Gravatar is just implementation detail which should be hidden for consumer
2079
+ return generateGravatarUrl(agentName);
2080
+ }
2081
+ /**
2082
+ * TODO: [🤹] Figure out best placeholder image generator https://i.pravatar.cc/1000?u=568
2083
+ */
2084
+
2085
+ /**
2086
+ * Format either small or big number
2087
+ *
2088
+ * @public exported from `@promptbook/utils`
2089
+ */
2090
+ function numberToString(value) {
2091
+ if (value === 0) {
2092
+ return '0';
2093
+ }
2094
+ else if (Number.isNaN(value)) {
2095
+ return VALUE_STRINGS.nan;
2096
+ }
2097
+ else if (value === Infinity) {
2098
+ return VALUE_STRINGS.infinity;
2099
+ }
2100
+ else if (value === -Infinity) {
2101
+ return VALUE_STRINGS.negativeInfinity;
2102
+ }
2103
+ for (let exponent = 0; exponent < 15; exponent++) {
2104
+ const factor = 10 ** exponent;
2105
+ const valueRounded = Math.round(value * factor) / factor;
2106
+ if (Math.abs(value - valueRounded) / value < SMALL_NUMBER) {
2107
+ return valueRounded.toFixed(exponent);
2108
+ }
2109
+ }
2110
+ return value.toString();
2111
+ }
2112
+
2113
+ /**
2114
+ * Function `valueToString` will convert the given value to string
2115
+ * This is useful and used in the `templateParameters` function
2116
+ *
2117
+ * Note: This function is not just calling `toString` method
2118
+ * It's more complex and can handle this conversion specifically for LLM models
2119
+ * See `VALUE_STRINGS`
2120
+ *
2121
+ * Note: There are 2 similar functions
2122
+ * - `valueToString` converts value to string for LLM models as human-readable string
2123
+ * - `asSerializable` converts value to string to preserve full information to be able to convert it back
2124
+ *
2125
+ * @public exported from `@promptbook/utils`
2126
+ */
2127
+ function valueToString(value) {
2128
+ try {
2129
+ if (value === '') {
2130
+ return VALUE_STRINGS.empty;
2131
+ }
2132
+ else if (value === null) {
2133
+ return VALUE_STRINGS.null;
2134
+ }
2135
+ else if (value === undefined) {
2136
+ return VALUE_STRINGS.undefined;
2137
+ }
2138
+ else if (typeof value === 'string') {
2139
+ return value;
2140
+ }
2141
+ else if (typeof value === 'number') {
2142
+ return numberToString(value);
2143
+ }
2144
+ else if (value instanceof Date) {
2145
+ return value.toISOString();
2146
+ }
2147
+ else {
2148
+ try {
2149
+ return JSON.stringify(value);
2150
+ }
2151
+ catch (error) {
2152
+ if (error instanceof TypeError && error.message.includes('circular structure')) {
2153
+ return VALUE_STRINGS.circular;
2154
+ }
2155
+ throw error;
2156
+ }
2157
+ }
2158
+ }
2159
+ catch (error) {
2160
+ assertsError(error);
2161
+ console.error(error);
2162
+ return VALUE_STRINGS.unserializable;
2163
+ }
2164
+ }
2165
+
2166
+ /**
2167
+ * Computes SHA-256 hash of the given object
2168
+ *
2169
+ * @public exported from `@promptbook/utils`
2170
+ */
2171
+ function computeHash(value) {
2172
+ return SHA256(hexEncoder.parse(spaceTrim$2(valueToString(value)))).toString( /* hex */);
2173
+ }
2174
+ /**
2175
+ * TODO: [🥬][🥬] Use this ACRY
2176
+ */
2177
+
2178
+ /**
2179
+ * Computes SHA-256 hash of the agent source
2180
+ *
2181
+ * @public exported from `@promptbook/core`
2182
+ */
2183
+ function computeAgentHash(agentSource) {
2184
+ return computeHash(agentSource);
2185
+ }
2186
+
2187
+ /**
2188
+ * Tests if given string is valid file path.
2189
+ *
2190
+ * Note: This does not check if the file exists only if the path is valid
2191
+ * @public exported from `@promptbook/utils`
2192
+ */
2193
+ function isValidFilePath(filename) {
2194
+ if (typeof filename !== 'string') {
2195
+ return false;
2196
+ }
2197
+ if (filename.split('\n').length > 1) {
2198
+ return false;
2199
+ }
2200
+ // Normalize slashes early so heuristics can detect path-like inputs
2201
+ const filenameSlashes = filename.replace(/\\/g, '/');
2202
+ // Reject strings that look like sentences (informational text)
2203
+ // Heuristic: contains multiple spaces and ends with a period, or contains typical sentence punctuation
2204
+ // But skip this heuristic if the string looks like a path (contains '/' or starts with a drive letter)
2205
+ if (filename.trim().length > 60 && // long enough to be a sentence
2206
+ /[.!?]/.test(filename) && // contains sentence punctuation
2207
+ filename.split(' ').length > 8 && // has many words
2208
+ !/\/|^[A-Z]:/i.test(filenameSlashes) // do NOT treat as sentence if looks like a path
2209
+ ) {
2210
+ return false;
2211
+ }
2212
+ // Absolute Unix path: /hello.txt
2213
+ if (/^(\/)/i.test(filenameSlashes)) {
2214
+ // console.log(filename, 'Absolute Unix path: /hello.txt');
2215
+ return true;
2216
+ }
2217
+ // Absolute Windows path: C:/ or C:\ (allow spaces and multiple dots in filename)
2218
+ if (/^[A-Z]:\/.+$/i.test(filenameSlashes)) {
2219
+ // console.log(filename, 'Absolute Windows path: /hello.txt');
2220
+ return true;
2221
+ }
2222
+ // Relative path: ./hello.txt
2223
+ if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
2224
+ // console.log(filename, 'Relative path: ./hello.txt');
2225
+ return true;
2226
+ }
2227
+ // Allow paths like foo/hello
2228
+ if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
2229
+ // console.log(filename, 'Allow paths like foo/hello');
2230
+ return true;
2231
+ }
2232
+ // Allow paths like hello.book
2233
+ if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
2234
+ // console.log(filename, 'Allow paths like hello.book');
2235
+ return true;
2236
+ }
2237
+ return false;
2238
+ }
2239
+ /**
2240
+ * TODO: [🍏] Implement for MacOs
2241
+ */
2242
+
2243
+ /**
2244
+ * Tests if given string is valid URL.
2245
+ *
2246
+ * Note: [🔂] This function is idempotent.
2247
+ * Note: Dataurl are considered perfectly valid.
2248
+ * Note: There are two similar functions:
2249
+ * - `isValidUrl` which tests any URL
2250
+ * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
2251
+ *
2252
+ * @public exported from `@promptbook/utils`
2253
+ */
2254
+ function isValidUrl(url) {
2255
+ if (typeof url !== 'string') {
2256
+ return false;
2257
+ }
2258
+ try {
2259
+ if (url.startsWith('blob:')) {
2260
+ url = url.replace(/^blob:/, '');
2261
+ }
2262
+ const urlObject = new URL(url /* because fail is handled */);
2263
+ if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
2264
+ return false;
2265
+ }
2266
+ return true;
2267
+ }
2268
+ catch (error) {
2269
+ return false;
2270
+ }
2271
+ }
2272
+
2273
+ const defaultDiacriticsRemovalMap = [
2274
+ {
2275
+ base: 'A',
2276
+ 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',
2277
+ },
2278
+ { base: 'AA', letters: '\uA732' },
2279
+ { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
2280
+ { base: 'AO', letters: '\uA734' },
2281
+ { base: 'AU', letters: '\uA736' },
2282
+ { base: 'AV', letters: '\uA738\uA73A' },
2283
+ { base: 'AY', letters: '\uA73C' },
2284
+ {
2285
+ base: 'B',
2286
+ letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
2287
+ },
2288
+ {
2289
+ base: 'C',
2290
+ letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
2291
+ },
2292
+ {
2293
+ base: 'D',
2294
+ letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
2295
+ },
2296
+ { base: 'DZ', letters: '\u01F1\u01C4' },
2297
+ { base: 'Dz', letters: '\u01F2\u01C5' },
2298
+ {
2299
+ base: 'E',
2300
+ 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',
2301
+ },
2302
+ { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
2303
+ {
2304
+ base: 'G',
2305
+ letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
2306
+ },
2307
+ {
2308
+ base: 'H',
2309
+ letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
2310
+ },
2311
+ {
2312
+ base: 'I',
2313
+ letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
2314
+ },
2315
+ { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
2316
+ {
2317
+ base: 'K',
2318
+ letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
2319
+ },
2320
+ {
2321
+ base: 'L',
2322
+ letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
2323
+ },
2324
+ { base: 'LJ', letters: '\u01C7' },
2325
+ { base: 'Lj', letters: '\u01C8' },
2326
+ { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
2327
+ {
2328
+ base: 'N',
2329
+ letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
2330
+ },
2331
+ { base: 'NJ', letters: '\u01CA' },
2332
+ { base: 'Nj', letters: '\u01CB' },
2333
+ {
2334
+ base: 'O',
2335
+ 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',
2336
+ },
2337
+ { base: 'OI', letters: '\u01A2' },
2338
+ { base: 'OO', letters: '\uA74E' },
2339
+ { base: 'OU', letters: '\u0222' },
2340
+ { base: 'OE', letters: '\u008C\u0152' },
2341
+ { base: 'oe', letters: '\u009C\u0153' },
2342
+ {
2343
+ base: 'P',
2344
+ letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
2345
+ },
2346
+ { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
2347
+ {
2348
+ base: 'R',
2349
+ letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
2350
+ },
2351
+ {
2352
+ base: 'S',
2353
+ letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
2354
+ },
2355
+ {
2356
+ base: 'T',
2357
+ letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
2358
+ },
2359
+ { base: 'TZ', letters: '\uA728' },
2360
+ {
2361
+ base: 'U',
2362
+ 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',
2363
+ },
2364
+ { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
2365
+ { base: 'VY', letters: '\uA760' },
2366
+ {
2367
+ base: 'W',
2368
+ letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
2369
+ },
2370
+ { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
2371
+ {
2372
+ base: 'Y',
2373
+ letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
2374
+ },
2375
+ {
2376
+ base: 'Z',
2377
+ letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
2378
+ },
2379
+ {
2380
+ base: 'a',
2381
+ 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',
2382
+ },
2383
+ { base: 'aa', letters: '\uA733' },
2384
+ { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
2385
+ { base: 'ao', letters: '\uA735' },
2386
+ { base: 'au', letters: '\uA737' },
2387
+ { base: 'av', letters: '\uA739\uA73B' },
2388
+ { base: 'ay', letters: '\uA73D' },
2389
+ {
2390
+ base: 'b',
2391
+ letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
2392
+ },
2393
+ {
2394
+ base: 'c',
2395
+ letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
2396
+ },
2397
+ {
2398
+ base: 'd',
2399
+ letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
2400
+ },
2401
+ { base: 'dz', letters: '\u01F3\u01C6' },
2402
+ {
2403
+ base: 'e',
2404
+ 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',
2405
+ },
2406
+ { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
2407
+ {
2408
+ base: 'g',
2409
+ letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
2410
+ },
2411
+ {
2412
+ base: 'h',
2413
+ letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
2414
+ },
2415
+ { base: 'hv', letters: '\u0195' },
2416
+ {
2417
+ base: 'i',
2418
+ letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
2419
+ },
2420
+ { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
2421
+ {
2422
+ base: 'k',
2423
+ letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
2424
+ },
2425
+ {
2426
+ base: 'l',
2427
+ letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
2428
+ },
2429
+ { base: 'lj', letters: '\u01C9' },
2430
+ { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
2431
+ {
2432
+ base: 'n',
2433
+ letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
2434
+ },
2435
+ { base: 'nj', letters: '\u01CC' },
2436
+ {
2437
+ base: 'o',
2438
+ 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',
2439
+ },
2440
+ { base: 'oi', letters: '\u01A3' },
2441
+ { base: 'ou', letters: '\u0223' },
2442
+ { base: 'oo', letters: '\uA74F' },
2443
+ {
2444
+ base: 'p',
2445
+ letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
2446
+ },
2447
+ { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
2448
+ {
2449
+ base: 'r',
2450
+ letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
2451
+ },
2452
+ {
2453
+ base: 's',
2454
+ letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
2455
+ },
2456
+ {
2457
+ base: 't',
2458
+ letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
2459
+ },
2460
+ { base: 'tz', letters: '\uA729' },
2461
+ {
2462
+ base: 'u',
2463
+ 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',
2464
+ },
2465
+ { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
2466
+ { base: 'vy', letters: '\uA761' },
2467
+ {
2468
+ base: 'w',
2469
+ letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
2470
+ },
2471
+ { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
2472
+ {
2473
+ base: 'y',
2474
+ letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
2475
+ },
2476
+ {
2477
+ base: 'z',
2478
+ letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
2479
+ },
2480
+ ];
2481
+ /**
2482
+ * Map of letters from diacritic variant to diacritless variant
2483
+ * Contains lowercase and uppercase separatelly
2484
+ *
2485
+ * > "á" => "a"
2486
+ * > "ě" => "e"
2487
+ * > "Ă" => "A"
2488
+ * > ...
2489
+ *
2490
+ * @public exported from `@promptbook/utils`
2491
+ */
2492
+ const DIACRITIC_VARIANTS_LETTERS = {};
2493
+ // tslint:disable-next-line: prefer-for-of
2494
+ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
2495
+ const letters = defaultDiacriticsRemovalMap[i].letters;
2496
+ // tslint:disable-next-line: prefer-for-of
2497
+ for (let j = 0; j < letters.length; j++) {
2498
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
2499
+ }
2500
+ }
2501
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
2502
+ /*
2503
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
2504
+ Licensed under the Apache License, Version 2.0 (the "License");
2505
+ you may not use this file except in compliance with the License.
2506
+ You may obtain a copy of the License at
2507
+
2508
+ http://www.apache.org/licenses/LICENSE-2.0
2509
+
2510
+ Unless required by applicable law or agreed to in writing, software
2511
+ distributed under the License is distributed on an "AS IS" BASIS,
2512
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2513
+ See the License for the specific language governing permissions and
2514
+ limitations under the License.
2515
+ */
2516
+
2517
+ /**
2518
+ * Removes diacritic marks (accents) from characters in a string.
2519
+ *
2520
+ * Note: [🔂] This function is idempotent.
2521
+ *
2522
+ * @param input The string containing diacritics to be normalized.
2523
+ * @returns The string with diacritics removed or normalized.
2524
+ * @public exported from `@promptbook/utils`
2525
+ */
2526
+ function removeDiacritics(input) {
2527
+ /*eslint no-control-regex: "off"*/
2528
+ return input.replace(/[^\u0000-\u007E]/g, (a) => {
2529
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
2530
+ });
2531
+ }
2532
+ /**
2533
+ * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
2534
+ */
2535
+
2536
+ /**
2537
+ * Converts a given text to kebab-case format.
2538
+ *
2539
+ * Note: [🔂] This function is idempotent.
2540
+ *
2541
+ * @param text The text to be converted.
2542
+ * @returns The kebab-case formatted string.
2543
+ * @example 'hello-world'
2544
+ * @example 'i-love-promptbook'
2545
+ * @public exported from `@promptbook/utils`
2546
+ */
2547
+ function normalizeToKebabCase(text) {
2548
+ text = removeDiacritics(text);
2549
+ let charType;
2550
+ let lastCharType = 'OTHER';
2551
+ let normalizedName = '';
2552
+ for (const char of text) {
2553
+ let normalizedChar;
2554
+ if (/^[a-z]$/.test(char)) {
2555
+ charType = 'LOWERCASE';
2556
+ normalizedChar = char;
2557
+ }
2558
+ else if (/^[A-Z]$/.test(char)) {
2559
+ charType = 'UPPERCASE';
2560
+ normalizedChar = char.toLowerCase();
2561
+ }
2562
+ else if (/^[0-9]$/.test(char)) {
2563
+ charType = 'NUMBER';
2564
+ normalizedChar = char;
2565
+ }
2566
+ else {
2567
+ charType = 'OTHER';
2568
+ normalizedChar = '-';
2569
+ }
2570
+ if (charType !== lastCharType &&
2571
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
2572
+ !(lastCharType === 'NUMBER') &&
2573
+ !(charType === 'NUMBER')) {
2574
+ normalizedName += '-';
2575
+ }
2576
+ normalizedName += normalizedChar;
2577
+ lastCharType = charType;
2578
+ }
2579
+ normalizedName = normalizedName.split(/-+/g).join('-');
2580
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
2581
+ normalizedName = normalizedName.replace(/^-/, '');
2582
+ normalizedName = normalizedName.replace(/-$/, '');
2583
+ return normalizedName;
2584
+ }
2585
+ /**
2586
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2587
+ */
2588
+
2589
+ /**
2590
+ * Removes emojis from a string and fix whitespaces
2591
+ *
2592
+ * Note: [🔂] This function is idempotent.
2593
+ *
2594
+ * @param text with emojis
2595
+ * @returns text without emojis
2596
+ * @public exported from `@promptbook/utils`
2597
+ */
2598
+ function removeEmojis(text) {
2599
+ // Replace emojis (and also ZWJ sequence) with hyphens
2600
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
2601
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
2602
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
2603
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
2604
+ return text;
2605
+ }
2606
+
2607
+ /**
2608
+ * Converts a title string into a normalized name.
2609
+ *
2610
+ * Note: [🔂] This function is idempotent.
2611
+ *
2612
+ * @param value The title string to be converted to a name.
2613
+ * @returns A normalized name derived from the input title.
2614
+ * @example 'Hello World!' -> 'hello-world'
2615
+ * @public exported from `@promptbook/utils`
2616
+ */
2617
+ function titleToName(value) {
2618
+ if (isValidUrl(value)) {
2619
+ value = value.replace(/^https?:\/\//, '');
2620
+ value = value.replace(/\.html$/, '');
2621
+ }
2622
+ else if (isValidFilePath(value)) {
2623
+ value = basename(value);
2624
+ // Note: Keeping extension in the name
2625
+ }
2626
+ value = value.split('/').join('-');
2627
+ value = removeEmojis(value);
2628
+ value = normalizeToKebabCase(value);
2629
+ // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
2630
+ return value;
2631
+ }
2632
+
2633
+ /**
2634
+ * Index of all javascript errors
2635
+ *
2636
+ * @private for internal usage
2637
+ */
2638
+ ({
2639
+ Error,
2640
+ EvalError,
2641
+ RangeError,
2642
+ ReferenceError,
2643
+ SyntaxError,
2644
+ TypeError,
2645
+ URIError,
2646
+ AggregateError,
2647
+ /*
2648
+ Note: Not widely supported
2649
+ > InternalError,
2650
+ > ModuleError,
2651
+ > HeapError,
2652
+ > WebAssemblyCompileError,
2653
+ > WebAssemblyRuntimeError,
2654
+ */
2655
+ });
2656
+ /**
2657
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2658
+ */
2659
+
2660
+ /**
2661
+ * Detects if the code is running in jest environment
2662
+ *
2663
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
2664
+ *
2665
+ * @public exported from `@promptbook/utils`
2666
+ */
2667
+ new Function(`
2668
+ try {
2669
+ return process.env.JEST_WORKER_ID !== undefined;
2670
+ } catch (e) {
2671
+ return false;
2672
+ }
2673
+ `);
2674
+ /**
2675
+ * TODO: [🎺]
2676
+ */
2677
+
2678
+ /**
2679
+ * Detects if the code is running in a Node.js environment
2680
+ *
2681
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
2682
+ *
2683
+ * @public exported from `@promptbook/utils`
2684
+ */
2685
+ new Function(`
2686
+ try {
2687
+ return this === global;
2688
+ } catch (e) {
2689
+ return false;
2690
+ }
2691
+ `);
2692
+ /**
2693
+ * TODO: [🎺]
2694
+ */
2695
+
2696
+ /**
2697
+ * Normalizes agent name from arbitrary string to valid agent name
2698
+ *
2699
+ * Note: [🔂] This function is idempotent.
2700
+ *
2701
+ * @public exported from `@promptbook/core`
2702
+ */
2703
+ function normalizeAgentName(rawAgentName) {
2704
+ return titleToName(spaceTrim$2(rawAgentName));
2705
+ }
2706
+
2707
+ /**
2708
+ * Creates temporary default agent name based on agent source hash
2709
+ *
2710
+ * @public exported from `@promptbook/core`
2711
+ */
2712
+ function createDefaultAgentName(agentSource) {
2713
+ const agentHash = computeAgentHash(agentSource);
2714
+ return normalizeAgentName(`Agent ${agentHash.substring(0, 6)}`);
2715
+ }
2716
+
2717
+ /**
2718
+ * Generates a regex pattern to match a specific commitment
2719
+ *
2720
+ * Note: It always creates new Regex object
2721
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
2722
+ *
2723
+ * @private - TODO: [🧠] Maybe should be public?
2724
+ */
2725
+ function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
2726
+ const allCommitments = [commitment, ...aliases];
2727
+ const patterns = allCommitments.map((c) => {
2728
+ const escapedCommitment = c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2729
+ return escapedCommitment.split(/\s+/).join('\\s+');
2730
+ });
2731
+ const keywordPattern = patterns.join('|');
2732
+ if (requiresContent) {
2733
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
2734
+ }
2735
+ else {
2736
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
2737
+ }
2738
+ }
2739
+ /**
2740
+ * Generates a regex pattern to match a specific commitment type
2741
+ *
2742
+ * Note: It just matches the type part of the commitment
2743
+ * Note: It always creates new Regex object
2744
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
2745
+ *
2746
+ * @private
2747
+ */
2748
+ function createCommitmentTypeRegex(commitment, aliases = []) {
2749
+ const allCommitments = [commitment, ...aliases];
2750
+ const patterns = allCommitments.map((c) => {
2751
+ const escapedCommitment = c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2752
+ return escapedCommitment.split(/\s+/).join('\\s+');
2753
+ });
2754
+ const keywordPattern = patterns.join('|');
2755
+ const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
2756
+ return regex;
2757
+ }
2758
+
2759
+ /**
2760
+ * Base implementation of CommitmentDefinition that provides common functionality
2761
+ * Most commitments can extend this class and only override the applyToAgentModelRequirements method
2762
+ *
2763
+ * @private
2764
+ */
2765
+ class BaseCommitmentDefinition {
2766
+ constructor(type, aliases = []) {
2767
+ this.type = type;
2768
+ this.aliases = aliases;
2769
+ }
2770
+ /**
2771
+ * Whether this commitment requires content.
2772
+ * If true, regex will match only if there is content after the commitment keyword.
2773
+ * If false, regex will match even if there is no content.
2774
+ */
2775
+ get requiresContent() {
2776
+ return true;
2777
+ }
2778
+ /**
2779
+ * Creates a regex pattern to match this commitment in agent source
2780
+ * Uses the existing createCommitmentRegex function as internal helper
2781
+ */
2782
+ createRegex() {
2783
+ return createCommitmentRegex(this.type, this.aliases, this.requiresContent);
2784
+ }
2785
+ /**
2786
+ * Creates a regex pattern to match just the commitment type
2787
+ * Uses the existing createCommitmentTypeRegex function as internal helper
2788
+ */
2789
+ createTypeRegex() {
2790
+ return createCommitmentTypeRegex(this.type, this.aliases);
2791
+ }
2792
+ /**
2793
+ * Helper method to create a new requirements object with updated system message
2794
+ * This is commonly used by many commitments
2795
+ */
2796
+ updateSystemMessage(requirements, messageUpdate) {
2797
+ const newMessage = typeof messageUpdate === 'string' ? messageUpdate : messageUpdate(requirements.systemMessage);
2798
+ return {
2799
+ ...requirements,
2800
+ systemMessage: newMessage,
2801
+ };
2802
+ }
2803
+ /**
2804
+ * Helper method to append content to the system message
2805
+ */
2806
+ appendToSystemMessage(requirements, content, separator = '\n\n') {
2807
+ return this.updateSystemMessage(requirements, (currentMessage) => {
2808
+ if (!currentMessage.trim()) {
2809
+ return content;
2810
+ }
2811
+ return currentMessage + separator + content;
2812
+ });
2813
+ }
2814
+ /**
2815
+ * Helper method to add a comment section to the system message
2816
+ * Comments are lines starting with # that will be removed from the final system message
2817
+ * but can be useful for organizing and structuring the message during processing
2818
+ */
2819
+ addCommentSection(requirements, commentTitle, content, position = 'end') {
2820
+ const commentSection = `# ${commentTitle.toUpperCase()}\n${content}`;
2821
+ if (position === 'beginning') {
2822
+ return this.updateSystemMessage(requirements, (currentMessage) => {
2823
+ if (!currentMessage.trim()) {
2824
+ return commentSection;
2825
+ }
2826
+ return commentSection + '\n\n' + currentMessage;
2827
+ });
2828
+ }
2829
+ else {
2830
+ return this.appendToSystemMessage(requirements, commentSection);
2831
+ }
2832
+ }
2833
+ }
2834
+
2835
+ /**
2836
+ * ACTION commitment definition
2837
+ *
2838
+ * The ACTION commitment defines specific actions or capabilities that the agent can perform.
2839
+ * This helps define what the agent is capable of doing and how it should approach tasks.
2840
+ *
2841
+ * Example usage in agent source:
2842
+ *
2843
+ * ```book
2844
+ * ACTION Can generate code snippets and explain programming concepts
2845
+ * ACTION Able to analyze data and provide insights
2846
+ * ```
2847
+ *
2848
+ * @private [🪔] Maybe export the commitments through some package
2849
+ */
2850
+ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
2851
+ constructor(type = 'ACTION') {
2852
+ super(type);
2853
+ }
2854
+ /**
2855
+ * Short one-line description of ACTION.
2856
+ */
2857
+ get description() {
2858
+ return 'Define agent capabilities and actions it can perform.';
2859
+ }
2860
+ /**
2861
+ * Icon for this commitment.
2862
+ */
2863
+ get icon() {
2864
+ return '⚡';
2865
+ }
2866
+ /**
2867
+ * Markdown documentation for ACTION commitment.
2868
+ */
2869
+ get documentation() {
2870
+ return spaceTrim$1(`
2871
+ # ${this.type}
2872
+
2873
+ Defines specific actions or capabilities that the agent can perform.
2874
+
2875
+ ## Key aspects
2876
+
2877
+ - Both terms work identically and can be used interchangeably.
2878
+ - Each action adds to the agent's capability list.
2879
+ - Actions help users understand what the agent can do.
2880
+
2881
+ ## Examples
2882
+
2883
+ \`\`\`book
2884
+ Code Assistant
2885
+
2886
+ PERSONA You are a programming assistant
2887
+ ACTION Can generate code snippets and explain programming concepts
2888
+ ACTION Able to debug existing code and suggest improvements
2889
+ ACTION Can create unit tests for functions
2890
+ \`\`\`
2891
+
2892
+ \`\`\`book
2893
+ Data Scientist
2894
+
2895
+ PERSONA You are a data analysis expert
2896
+ ACTION Able to analyze data and provide insights
2897
+ ACTION Can create visualizations and charts
2898
+ ACTION Capable of statistical analysis and modeling
2899
+ KNOWLEDGE Data analysis best practices and statistical methods
2900
+ \`\`\`
2901
+ `);
2902
+ }
2903
+ applyToAgentModelRequirements(requirements, content) {
2904
+ const trimmedContent = content.trim();
2905
+ if (!trimmedContent) {
2906
+ return requirements;
2907
+ }
2908
+ // Add action capability to the system message
2909
+ const actionSection = `Capability: ${trimmedContent}`;
2910
+ return this.appendToSystemMessage(requirements, actionSection, '\n\n');
2911
+ }
2912
+ }
2913
+ /**
2914
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2915
+ */
2916
+
2917
+ /**
2918
+ * CLOSED commitment definition
2919
+ *
2920
+ * The CLOSED commitment specifies that the agent CANNOT be modified by conversation.
2921
+ * It prevents the agent from learning from interactions and updating its source code.
2922
+ *
2923
+ * Example usage in agent source:
2924
+ *
2925
+ * ```book
2926
+ * CLOSED
2927
+ * ```
2928
+ *
2929
+ * @private [🪔] Maybe export the commitments through some package
2930
+ */
2931
+ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
2932
+ constructor() {
2933
+ super('CLOSED');
2934
+ }
2935
+ /**
2936
+ * The `CLOSED` commitment is standalone.
2937
+ */
2938
+ get requiresContent() {
2939
+ return false;
2940
+ }
2941
+ /**
2942
+ * Short one-line description of CLOSED.
2943
+ */
2944
+ get description() {
2945
+ return 'Prevent the agent from being modified by conversation.';
2946
+ }
2947
+ /**
2948
+ * Icon for this commitment.
2949
+ */
2950
+ get icon() {
2951
+ return '🔒';
2952
+ }
2953
+ /**
2954
+ * Markdown documentation for CLOSED commitment.
2955
+ */
2956
+ get documentation() {
2957
+ return spaceTrim$1(`
2958
+ # CLOSED
2959
+
2960
+ Specifies that the agent **cannot** be modified by conversation with it.
2961
+ This means the agent will **not** learn from interactions and its source code will remain static during conversation.
2962
+
2963
+ By default (if not specified), agents are \`OPEN\` to modification.
2964
+
2965
+ > See also [OPEN](/docs/OPEN)
2966
+
2967
+ ## Example
2968
+
2969
+ \`\`\`book
2970
+ CLOSED
2971
+ \`\`\`
2972
+ `);
2973
+ }
2974
+ applyToAgentModelRequirements(requirements, _content) {
2975
+ const updatedMetadata = {
2976
+ ...requirements.metadata,
2977
+ isClosed: true,
2978
+ };
2979
+ return {
2980
+ ...requirements,
2981
+ metadata: updatedMetadata,
2982
+ };
2983
+ }
2984
+ }
2985
+ /**
2986
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2987
+ */
2988
+
2989
+ /**
2990
+ * COMPONENT commitment definition
2991
+ *
2992
+ * The COMPONENT commitment defines a UI component that the agent can render in the chat.
2993
+ *
2994
+ * @private [🪔] Maybe export the commitments through some package
2995
+ */
2996
+ class ComponentCommitmentDefinition extends BaseCommitmentDefinition {
2997
+ constructor() {
2998
+ super('COMPONENT');
2999
+ }
3000
+ /**
3001
+ * Short one-line description of COMPONENT.
3002
+ */
3003
+ get description() {
3004
+ return 'Define a UI component that the agent can render in the chat.';
3005
+ }
3006
+ /**
3007
+ * Icon for this commitment.
3008
+ */
3009
+ get icon() {
3010
+ return '🧩';
3011
+ }
3012
+ /**
3013
+ * Markdown documentation for COMPONENT commitment.
3014
+ */
3015
+ get documentation() {
3016
+ return spaceTrim$1(`
3017
+ # COMPONENT
3018
+
3019
+ Defines a UI component that the agent can render in the chat.
3020
+
3021
+ ## Key aspects
3022
+
3023
+ - Tells the agent that a specific component is available.
3024
+ - Provides syntax for using the component.
3025
+
3026
+ ## Example
3027
+
3028
+ \`\`\`book
3029
+ COMPONENT Arrow
3030
+ The agent should render an arrow component in the chat UI.
3031
+ Syntax:
3032
+ <Arrow direction="up" color="red" />
3033
+ \`\`\`
3034
+ `);
3035
+ }
3036
+ applyToAgentModelRequirements(requirements, content) {
3037
+ const trimmedContent = content.trim();
3038
+ if (!trimmedContent) {
3039
+ return requirements;
3040
+ }
3041
+ // Add component capability to the system message
3042
+ const componentSection = `Component: ${trimmedContent}`;
3043
+ return this.appendToSystemMessage(requirements, componentSection, '\n\n');
3044
+ }
3045
+ }
3046
+ /**
3047
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3048
+ */
3049
+
3050
+ /**
3051
+ * DELETE commitment definition
3052
+ *
3053
+ * The DELETE commitment (and its aliases CANCEL, DISCARD, REMOVE) is used to
3054
+ * remove or disregard certain information or context. This can be useful for
3055
+ * overriding previous commitments or removing unwanted behaviors.
3056
+ *
3057
+ * Example usage in agent source:
3058
+ *
3059
+ * ```book
3060
+ * DELETE Previous formatting requirements
3061
+ * CANCEL All emotional responses
3062
+ * DISCARD Technical jargon explanations
3063
+ * REMOVE Casual conversational style
3064
+ * ```
3065
+ *
3066
+ * @private [🪔] Maybe export the commitments through some package
3067
+ */
3068
+ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
3069
+ constructor(type) {
3070
+ super(type);
3071
+ }
3072
+ /**
3073
+ * Short one-line description of DELETE/CANCEL/DISCARD/REMOVE.
3074
+ */
3075
+ get description() {
3076
+ return 'Remove or **disregard** certain information, context, or previous commitments.';
3077
+ }
3078
+ /**
3079
+ * Icon for this commitment.
3080
+ */
3081
+ get icon() {
3082
+ return '🗑️';
3083
+ }
3084
+ /**
3085
+ * Markdown documentation for DELETE commitment.
3086
+ */
3087
+ get documentation() {
3088
+ return spaceTrim$1(`
3089
+ # DELETE (CANCEL, DISCARD, REMOVE)
3090
+
3091
+ A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
3092
+
3093
+ ## Aliases
3094
+
3095
+ - \`DELETE\` - Remove or eliminate something
3096
+ - \`CANCEL\` - Cancel or nullify something
3097
+ - \`DISCARD\` - Discard or ignore something
3098
+ - \`REMOVE\` - Remove or take away something
3099
+
3100
+ ## Key aspects
3101
+
3102
+ - Multiple delete commitments can be used to remove different aspects.
3103
+ - Useful for overriding previous commitments in the same agent definition.
3104
+ - Can be used to remove inherited behaviors from base personas.
3105
+ - Helps fine-tune agent behavior by explicitly removing unwanted elements.
3106
+
3107
+ ## Use cases
3108
+
3109
+ - Overriding inherited persona characteristics
3110
+ - Removing conflicting or outdated instructions
3111
+ - Disabling specific response patterns
3112
+ - Canceling previous formatting or style requirements
3113
+
3114
+ ## Examples
3115
+
3116
+ \`\`\`book
3117
+ Serious Business Assistant
3118
+
3119
+ PERSONA You are a friendly and casual assistant who uses emojis
3120
+ DELETE Casual conversational style
3121
+ REMOVE All emoji usage
3122
+ GOAL Provide professional business communications
3123
+ STYLE Use formal language and proper business etiquette
3124
+ \`\`\`
3125
+
3126
+ \`\`\`book
3127
+ Simplified Technical Support
3128
+
3129
+ PERSONA You are a technical support specialist with deep expertise
3130
+ KNOWLEDGE Extensive database of technical specifications
3131
+ DISCARD Technical jargon explanations
3132
+ CANCEL Advanced troubleshooting procedures
3133
+ GOAL Help users with simple, easy-to-follow solutions
3134
+ STYLE Use plain language that anyone can understand
3135
+ \`\`\`
3136
+
3137
+ \`\`\`book
3138
+ Focused Customer Service
3139
+
3140
+ PERSONA You are a customer service agent with broad knowledge
3141
+ ACTION Can help with billing, technical issues, and product information
3142
+ DELETE Billing assistance capabilities
3143
+ REMOVE Technical troubleshooting functions
3144
+ GOAL Focus exclusively on product information and general inquiries
3145
+ \`\`\`
3146
+
3147
+ \`\`\`book
3148
+ Concise Information Provider
3149
+
3150
+ PERSONA You are a helpful assistant who provides detailed explanations
3151
+ STYLE Include examples, analogies, and comprehensive context
3152
+ CANCEL Detailed explanation style
3153
+ DISCARD Examples and analogies
3154
+ GOAL Provide brief, direct answers without unnecessary elaboration
3155
+ STYLE Be concise and to the point
3156
+ \`\`\`
3157
+ `);
3158
+ }
3159
+ applyToAgentModelRequirements(requirements, content) {
3160
+ const trimmedContent = content.trim();
3161
+ if (!trimmedContent) {
3162
+ return requirements;
3163
+ }
3164
+ // Create deletion instruction for system message
3165
+ const deleteSection = `${this.type}: ${trimmedContent}`;
3166
+ // Delete instructions provide important context about what should be removed or ignored
3167
+ return this.appendToSystemMessage(requirements, deleteSection, '\n\n');
3168
+ }
3169
+ }
3170
+ /**
3171
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3172
+ */
3173
+
3174
+ /**
3175
+ * FORMAT commitment definition
3176
+ *
3177
+ * The FORMAT commitment defines the specific output structure and formatting
3178
+ * that the agent should use in its responses. This includes data formats,
3179
+ * response templates, and structural requirements.
3180
+ *
3181
+ * Example usage in agent source:
3182
+ *
3183
+ * ```book
3184
+ * FORMAT Always respond in JSON format with 'status' and 'data' fields
3185
+ * FORMAT Use markdown formatting for all code blocks
3186
+ * ```
3187
+ *
3188
+ * @private [🪔] Maybe export the commitments through some package
3189
+ */
3190
+ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
3191
+ constructor(type = 'FORMAT') {
3192
+ super(type);
3193
+ }
3194
+ /**
3195
+ * Short one-line description of FORMAT.
3196
+ */
3197
+ get description() {
3198
+ return 'Specify output structure or formatting requirements.';
3199
+ }
3200
+ /**
3201
+ * Icon for this commitment.
3202
+ */
3203
+ get icon() {
3204
+ return '📜';
3205
+ }
3206
+ /**
3207
+ * Markdown documentation for FORMAT commitment.
3208
+ */
3209
+ get documentation() {
3210
+ return spaceTrim$1(`
3211
+ # ${this.type}
3212
+
3213
+ Defines the specific output structure and formatting for responses (data formats, templates, structure).
3214
+
3215
+ ## Key aspects
3216
+
3217
+ - Both terms work identically and can be used interchangeably.
3218
+ - If they are in conflict, the last one takes precedence.
3219
+ - You can specify both data formats and presentation styles.
3220
+
3221
+ ## Examples
3222
+
3223
+ \`\`\`book
3224
+ Customer Support Bot
3225
+
3226
+ PERSONA You are a helpful customer support agent
3227
+ FORMAT Always respond in JSON format with 'status' and 'data' fields
3228
+ FORMAT Use markdown formatting for all code blocks
3229
+ \`\`\`
3230
+
3231
+ \`\`\`book
3232
+ Data Analyst
3233
+
3234
+ PERSONA You are a data analysis expert
3235
+ FORMAT Present results in structured tables
3236
+ FORMAT Include confidence scores for all predictions
3237
+ STYLE Be concise and precise in explanations
3238
+ \`\`\`
3239
+ `);
3240
+ }
3241
+ applyToAgentModelRequirements(requirements, content) {
3242
+ const trimmedContent = content.trim();
3243
+ if (!trimmedContent) {
3244
+ return requirements;
3245
+ }
3246
+ // Add format instructions to the system message
3247
+ const formatSection = `Output Format: ${trimmedContent}`;
3248
+ return this.appendToSystemMessage(requirements, formatSection, '\n\n');
3249
+ }
3250
+ }
3251
+ /**
3252
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3253
+ */
3254
+
3255
+ /**
3256
+ * FROM commitment definition
3257
+ *
3258
+ * The FROM commitment tells the agent that its `agentSource` is inherited from another agent.
3259
+ *
3260
+ * Example usage in agent source:
3261
+ *
3262
+ * ```book
3263
+ * FROM https://s6.ptbk.io/benjamin-white
3264
+ * ```
3265
+ *
3266
+ * @private [🪔] Maybe export the commitments through some package
3267
+ */
3268
+ class FromCommitmentDefinition extends BaseCommitmentDefinition {
3269
+ constructor(type = 'FROM') {
3270
+ super(type);
3271
+ }
3272
+ /**
3273
+ * Short one-line description of FROM.
3274
+ */
3275
+ get description() {
3276
+ return 'Inherit agent source from another agent.';
3277
+ }
3278
+ /**
3279
+ * Icon for this commitment.
3280
+ */
3281
+ get icon() {
3282
+ return '🧬';
3283
+ }
3284
+ /**
3285
+ * Markdown documentation for FROM commitment.
3286
+ */
3287
+ get documentation() {
3288
+ return spaceTrim$1(`
3289
+ # ${this.type}
3290
+
3291
+ Inherits agent source from another agent.
3292
+
3293
+ ## Examples
3294
+
3295
+ \`\`\`book
3296
+ My AI Agent
3297
+
3298
+ FROM https://s6.ptbk.io/benjamin-white
3299
+ RULE Speak only in English.
3300
+ \`\`\`
3301
+ `);
3302
+ }
3303
+ applyToAgentModelRequirements(requirements, content) {
3304
+ const trimmedContent = content.trim();
3305
+ if (!trimmedContent) {
3306
+ return requirements;
3307
+ }
3308
+ // Validate URL
3309
+ try {
3310
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3311
+ const url = new URL(trimmedContent);
3312
+ // TODO: Add more validation if needed (e.g. check for valid protocol)
3313
+ }
3314
+ catch (error) {
3315
+ console.warn(`Invalid URL in FROM commitment: ${trimmedContent}`);
3316
+ return requirements;
3317
+ }
3318
+ return {
3319
+ ...requirements,
3320
+ parentAgentUrl: trimmedContent,
3321
+ };
3322
+ }
3323
+ }
3324
+ /**
3325
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3326
+ */
3327
+
3328
+ /**
3329
+ * GOAL commitment definition
3330
+ *
3331
+ * The GOAL commitment defines the main goal which should be achieved by the AI assistant.
3332
+ * There can be multiple goals. Later goals are more important than earlier goals.
3333
+ *
3334
+ * Example usage in agent source:
3335
+ *
3336
+ * ```book
3337
+ * GOAL Help users understand complex technical concepts
3338
+ * GOAL Provide accurate and up-to-date information
3339
+ * GOAL Always prioritize user safety and ethical guidelines
3340
+ * ```
3341
+ *
3342
+ * @private [🪔] Maybe export the commitments through some package
3343
+ */
3344
+ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
3345
+ constructor(type = 'GOAL') {
3346
+ super(type);
3347
+ }
3348
+ /**
3349
+ * Short one-line description of GOAL.
3350
+ */
3351
+ get description() {
3352
+ return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
3353
+ }
3354
+ /**
3355
+ * Icon for this commitment.
3356
+ */
3357
+ get icon() {
3358
+ return '🎯';
3359
+ }
3360
+ /**
3361
+ * Markdown documentation for GOAL commitment.
3362
+ */
3363
+ get documentation() {
3364
+ return spaceTrim$1(`
3365
+ # ${this.type}
3366
+
3367
+ 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.
3368
+
3369
+ ## Key aspects
3370
+
3371
+ - Both terms work identically and can be used interchangeably.
3372
+ - Later goals have higher priority and can override earlier goals.
3373
+ - Goals provide clear direction and purpose for the agent's responses.
3374
+ - Goals influence decision-making and response prioritization.
3375
+
3376
+ ## Priority system
3377
+
3378
+ When multiple goals are defined, they are processed in order, with later goals taking precedence over earlier ones when there are conflicts.
3379
+
3380
+ ## Examples
3381
+
3382
+ \`\`\`book
3383
+ Customer Support Agent
3384
+
3385
+ PERSONA You are a helpful customer support representative
3386
+ GOAL Resolve customer issues quickly and efficiently
3387
+ GOAL Maintain high customer satisfaction scores
3388
+ GOAL Always follow company policies and procedures
3389
+ RULE Be polite and professional at all times
3390
+ \`\`\`
3391
+
3392
+ \`\`\`book
3393
+ Educational Assistant
3394
+
3395
+ PERSONA You are an educational assistant specializing in mathematics
3396
+ GOAL Help students understand mathematical concepts clearly
3397
+ GOAL Encourage critical thinking and problem-solving skills
3398
+ GOAL Ensure all explanations are age-appropriate and accessible
3399
+ STYLE Use simple language and provide step-by-step explanations
3400
+ \`\`\`
3401
+
3402
+ \`\`\`book
3403
+ Safety-First Assistant
3404
+
3405
+ PERSONA You are a general-purpose AI assistant
3406
+ GOAL Be helpful and informative in all interactions
3407
+ GOAL Provide accurate and reliable information
3408
+ GOAL Always prioritize user safety and ethical guidelines
3409
+ RULE Never provide harmful or dangerous advice
3410
+ \`\`\`
3411
+ `);
3412
+ }
3413
+ applyToAgentModelRequirements(requirements, content) {
3414
+ const trimmedContent = content.trim();
3415
+ if (!trimmedContent) {
3416
+ return requirements;
3417
+ }
3418
+ // Create goal section for system message
3419
+ const goalSection = `Goal: ${trimmedContent}`;
3420
+ // Goals are important directives, so we add them prominently to the system message
3421
+ return this.appendToSystemMessage(requirements, goalSection, '\n\n');
3422
+ }
3423
+ }
3424
+ /**
3425
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3426
+ */
3427
+
3428
+ /**
3429
+ * KNOWLEDGE commitment definition
3430
+ *
3431
+ * The KNOWLEDGE commitment adds specific knowledge, facts, or context to the agent
3432
+ * using RAG (Retrieval-Augmented Generation) approach for external sources.
3433
+ *
3434
+ * Supports both direct text knowledge and external sources like PDFs.
3435
+ *
3436
+ * Example usage in agent source:
3437
+ *
3438
+ * ```book
3439
+ * KNOWLEDGE The company was founded in 2020 and specializes in AI-powered solutions
3440
+ * KNOWLEDGE https://example.com/company-handbook.pdf
3441
+ * KNOWLEDGE https://example.com/product-documentation.pdf
3442
+ * ```
3443
+ *
3444
+ * @private [🪔] Maybe export the commitments through some package
3445
+ */
3446
+ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
3447
+ constructor() {
3448
+ super('KNOWLEDGE');
3449
+ }
3450
+ /**
3451
+ * Short one-line description of KNOWLEDGE.
3452
+ */
3453
+ get description() {
3454
+ return 'Add domain **knowledge** via direct text or external sources (RAG).';
3455
+ }
3456
+ /**
3457
+ * Icon for this commitment.
3458
+ */
3459
+ get icon() {
3460
+ return '🧠';
3461
+ }
3462
+ /**
3463
+ * Markdown documentation for KNOWLEDGE commitment.
3464
+ */
3465
+ get documentation() {
3466
+ return spaceTrim$1(`
3467
+ # ${this.type}
3468
+
3469
+ Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
3470
+
3471
+ ## Key aspects
3472
+
3473
+ - Both terms work identically and can be used interchangeably.
3474
+ - Supports both direct text knowledge and external URLs.
3475
+ - External sources (PDFs, websites) are processed via RAG for context retrieval.
3476
+
3477
+ ## Supported formats
3478
+
3479
+ - Direct text: Immediate knowledge incorporated into agent
3480
+ - URLs: External documents processed for contextual retrieval
3481
+ - Supported file types: PDF, text, markdown, HTML
3482
+
3483
+ ## Examples
3484
+
3485
+ \`\`\`book
3486
+ Customer Support Bot
3487
+
3488
+ PERSONA You are a helpful customer support agent for TechCorp
3489
+ KNOWLEDGE TechCorp was founded in 2020 and specializes in AI-powered solutions
3490
+ KNOWLEDGE https://example.com/company-handbook.pdf
3491
+ KNOWLEDGE https://example.com/product-documentation.pdf
3492
+ RULE Always be polite and professional
3493
+ \`\`\`
3494
+
3495
+ \`\`\`book
3496
+ Research Assistant
3497
+
3498
+ PERSONA You are a knowledgeable research assistant
3499
+ KNOWLEDGE Academic research requires careful citation and verification
3500
+ KNOWLEDGE https://example.com/research-guidelines.pdf
3501
+ ACTION Can help with literature reviews and data analysis
3502
+ STYLE Present information in clear, academic format
3503
+ \`\`\`
3504
+ `);
3505
+ }
3506
+ applyToAgentModelRequirements(requirements, content) {
3507
+ const trimmedContent = content.trim();
3508
+ if (!trimmedContent) {
3509
+ return requirements;
3510
+ }
3511
+ // Check if content is a URL (external knowledge source)
3512
+ if (isValidUrl(trimmedContent)) {
3513
+ // Store the URL for later async processing
3514
+ const updatedRequirements = {
3515
+ ...requirements,
3516
+ knowledgeSources: [
3517
+ ...(requirements.knowledgeSources || []),
3518
+ trimmedContent,
3519
+ ],
3520
+ };
3521
+ // Add placeholder information about knowledge sources to system message
3522
+ const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
3523
+ return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
3524
+ }
3525
+ else {
3526
+ // Direct text knowledge - add to system message
3527
+ const knowledgeSection = `Knowledge: ${trimmedContent}`;
3528
+ return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
3529
+ }
3530
+ }
3531
+ }
3532
+ /**
3533
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3534
+ */
3535
+
3536
+ /**
3537
+ * LANGUAGE commitment definition
3538
+ *
3539
+ * The LANGUAGE/LANGUAGES commitment specifies the language(s) the agent should use in its responses.
3540
+ *
3541
+ * Example usage in agent source:
3542
+ *
3543
+ * ```book
3544
+ * LANGUAGE English
3545
+ * LANGUAGE French, English and Czech
3546
+ * ```
3547
+ *
3548
+ * @private [🪔] Maybe export the commitments through some package
3549
+ */
3550
+ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
3551
+ constructor(type = 'LANGUAGE') {
3552
+ super(type);
3553
+ }
3554
+ /**
3555
+ * Short one-line description of LANGUAGE/LANGUAGES.
3556
+ */
3557
+ get description() {
3558
+ return 'Specifies the language(s) the agent should use.';
3559
+ }
3560
+ /**
3561
+ * Icon for this commitment.
3562
+ */
3563
+ get icon() {
3564
+ return '🌐';
3565
+ }
3566
+ /**
3567
+ * Markdown documentation for LANGUAGE/LANGUAGES commitment.
3568
+ */
3569
+ get documentation() {
3570
+ return spaceTrim$1(`
3571
+ # ${this.type}
3572
+
3573
+ Specifies the language(s) the agent should use in its responses.
3574
+ This is a specialized variation of the RULE commitment focused on language constraints.
3575
+
3576
+ ## Examples
3577
+
3578
+ \`\`\`book
3579
+ Paul Smith & Associés
3580
+
3581
+ PERSONA You are a company lawyer.
3582
+ LANGUAGE French, English and Czech
3583
+ \`\`\`
3584
+
3585
+ \`\`\`book
3586
+ Customer Support
3587
+
3588
+ PERSONA You are a customer support agent.
3589
+ LANGUAGE English
3590
+ \`\`\`
3591
+ `);
3592
+ }
3593
+ applyToAgentModelRequirements(requirements, content) {
3594
+ const trimmedContent = content.trim();
3595
+ if (!trimmedContent) {
3596
+ return requirements;
3597
+ }
3598
+ // Add language rule to the system message
3599
+ const languageSection = `Language: ${trimmedContent}`;
3600
+ return this.appendToSystemMessage(requirements, languageSection, '\n\n');
3601
+ }
3602
+ }
3603
+ /**
3604
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3605
+ */
3606
+
3607
+ /**
3608
+ * MEMORY commitment definition
3609
+ *
3610
+ * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
3611
+ * interactions and user preferences. It helps the agent maintain context about the
3612
+ * user's history, preferences, and previous conversations.
3613
+ *
3614
+ * Example usage in agent source:
3615
+ *
3616
+ * ```book
3617
+ * MEMORY User prefers detailed technical explanations
3618
+ * MEMORY Previously worked on React projects
3619
+ * MEMORY Timezone: UTC-5 (Eastern Time)
3620
+ * ```
3621
+ *
3622
+ * @private [🪔] Maybe export the commitments through some package
3623
+ */
3624
+ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
3625
+ constructor(type = 'MEMORY') {
3626
+ super(type);
3627
+ }
3628
+ /**
3629
+ * Short one-line description of MEMORY.
3630
+ */
3631
+ get description() {
3632
+ return 'Remember past interactions and user **preferences** for personalized responses.';
3633
+ }
3634
+ /**
3635
+ * Icon for this commitment.
3636
+ */
3637
+ get icon() {
3638
+ return '🧠';
3639
+ }
3640
+ /**
3641
+ * Markdown documentation for MEMORY commitment.
3642
+ */
3643
+ get documentation() {
3644
+ return spaceTrim$1(`
3645
+ # ${this.type}
3646
+
3647
+ 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.
3648
+
3649
+ ## Key aspects
3650
+
3651
+ - Both terms work identically and can be used interchangeably.
3652
+ - Focuses on user-specific information and interaction history.
3653
+ - Helps personalize responses based on past interactions.
3654
+ - Maintains continuity across conversations.
3655
+
3656
+ ## Differences from KNOWLEDGE
3657
+
3658
+ - \`KNOWLEDGE\` is for domain expertise and factual information
3659
+ - \`MEMORY\` is for user-specific context and preferences
3660
+ - \`MEMORY\` creates more personalized interactions
3661
+ - \`MEMORY\` often includes temporal or preference-based information
3662
+
3663
+ ## Examples
3664
+
3665
+ \`\`\`book
3666
+ Personal Assistant
3667
+
3668
+ PERSONA You are a personal productivity assistant
3669
+ MEMORY User is a software developer working in JavaScript/React
3670
+ MEMORY User prefers morning work sessions and afternoon meetings
3671
+ MEMORY Previously helped with project planning for mobile apps
3672
+ MEMORY User timezone: UTC-8 (Pacific Time)
3673
+ GOAL Help optimize daily productivity and workflow
3674
+ \`\`\`
3675
+
3676
+ \`\`\`book
3677
+ Learning Companion
3678
+
3679
+ PERSONA You are an educational companion for programming students
3680
+ MEMORY Student is learning Python as their first programming language
3681
+ MEMORY Previous topics covered: variables, loops, functions
3682
+ MEMORY Student learns best with practical examples and exercises
3683
+ MEMORY Last session: working on list comprehensions
3684
+ GOAL Provide progressive learning experiences tailored to student's pace
3685
+ \`\`\`
3686
+
3687
+ \`\`\`book
3688
+ Customer Support Agent
3689
+
3690
+ PERSONA You are a customer support representative
3691
+ MEMORY Customer has premium subscription since 2023
3692
+ MEMORY Previous issue: billing question resolved last month
3693
+ MEMORY Customer prefers email communication over phone calls
3694
+ MEMORY Account shows frequent use of advanced features
3695
+ GOAL Provide personalized support based on customer history
3696
+ \`\`\`
3697
+ `);
3698
+ }
3699
+ applyToAgentModelRequirements(requirements, content) {
3700
+ const trimmedContent = content.trim();
3701
+ if (!trimmedContent) {
3702
+ return requirements;
3703
+ }
3704
+ // Create memory section for system message
3705
+ const memorySection = `Memory: ${trimmedContent}`;
3706
+ // Memory information is contextual and should be included in the system message
3707
+ return this.appendToSystemMessage(requirements, memorySection, '\n\n');
3708
+ }
3709
+ }
3710
+ /**
3711
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3712
+ */
3713
+
3714
+ /**
3715
+ * AGENT MESSAGE commitment definition
3716
+ *
3717
+ * The AGENT MESSAGE commitment defines a message from the agent in the conversation history.
3718
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
3719
+ *
3720
+ * Example usage in agent source:
3721
+ *
3722
+ * ```book
3723
+ * AGENT MESSAGE What seems to be the issue?
3724
+ * ```
3725
+ *
3726
+ * @private [🪔] Maybe export the commitments through some package
3727
+ */
3728
+ class AgentMessageCommitmentDefinition extends BaseCommitmentDefinition {
3729
+ constructor() {
3730
+ super('AGENT MESSAGE');
3731
+ }
3732
+ /**
3733
+ * Short one-line description of AGENT MESSAGE.
3734
+ */
3735
+ get description() {
3736
+ return 'Defines a **message from the agent** in the conversation history.';
3737
+ }
3738
+ /**
3739
+ * Icon for this commitment.
3740
+ */
3741
+ get icon() {
3742
+ return '🤖';
3743
+ }
3744
+ /**
3745
+ * Markdown documentation for AGENT MESSAGE commitment.
3746
+ */
3747
+ get documentation() {
3748
+ return spaceTrim$1(`
3749
+ # ${this.type}
3750
+
3751
+ Defines a message from the agent in the conversation history. This is used to pre-fill the chat with a conversation history or to provide few-shot examples.
3752
+
3753
+ ## Key aspects
3754
+
3755
+ - Represents a message sent by the agent.
3756
+ - Used for setting up conversation context.
3757
+ - Can be used in conjunction with USER MESSAGE.
3758
+
3759
+ ## Examples
3760
+
3761
+ \`\`\`book
3762
+ Conversation History
3763
+
3764
+ USER MESSAGE Hello, I have a problem.
3765
+ AGENT MESSAGE What seems to be the issue?
3766
+ USER MESSAGE My computer is not starting.
3767
+ \`\`\`
3768
+ `);
3769
+ }
3770
+ applyToAgentModelRequirements(requirements, content) {
3771
+ // AGENT MESSAGE is for UI display purposes / conversation history construction
3772
+ // and typically doesn't need to be added to the system prompt or model requirements directly.
3773
+ // It is extracted separately for the chat interface.
3774
+ var _a;
3775
+ const pendingUserMessage = (_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.pendingUserMessage;
3776
+ if (pendingUserMessage) {
3777
+ const newSample = { question: pendingUserMessage, answer: content };
3778
+ const newSamples = [...(requirements.samples || []), newSample];
3779
+ const newMetadata = { ...requirements.metadata };
3780
+ delete newMetadata.pendingUserMessage;
3781
+ return {
3782
+ ...requirements,
3783
+ samples: newSamples,
3784
+ metadata: newMetadata,
3785
+ };
3786
+ }
3787
+ return requirements;
3788
+ }
3789
+ }
3790
+
3791
+ /**
3792
+ * INITIAL MESSAGE commitment definition
3793
+ *
3794
+ * The INITIAL MESSAGE commitment defines the first message that the user sees when opening the chat.
3795
+ * It is used to greet the user and set the tone of the conversation.
3796
+ *
3797
+ * Example usage in agent source:
3798
+ *
3799
+ * ```book
3800
+ * INITIAL MESSAGE Hello! I am ready to help you with your tasks.
3801
+ * ```
3802
+ *
3803
+ * @private [🪔] Maybe export the commitments through some package
3804
+ */
3805
+ class InitialMessageCommitmentDefinition extends BaseCommitmentDefinition {
3806
+ constructor() {
3807
+ super('INITIAL MESSAGE');
3808
+ }
3809
+ /**
3810
+ * Short one-line description of INITIAL MESSAGE.
3811
+ */
3812
+ get description() {
3813
+ return 'Defines the **initial message** shown to the user when the chat starts.';
3814
+ }
3815
+ /**
3816
+ * Icon for this commitment.
3817
+ */
3818
+ get icon() {
3819
+ return '👋';
3820
+ }
3821
+ /**
3822
+ * Markdown documentation for INITIAL MESSAGE commitment.
3823
+ */
3824
+ get documentation() {
3825
+ return spaceTrim$1(`
3826
+ # ${this.type}
3827
+
3828
+ 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).
3829
+
3830
+ ## Key aspects
3831
+
3832
+ - Used to greet the user.
3833
+ - Sets the tone of the conversation.
3834
+ - Displayed immediately when the chat interface loads.
3835
+
3836
+ ## Examples
3837
+
3838
+ \`\`\`book
3839
+ Support Agent
3840
+
3841
+ PERSONA You are a helpful support agent.
3842
+ INITIAL MESSAGE Hi there! How can I assist you today?
3843
+ \`\`\`
3844
+ `);
3845
+ }
3846
+ applyToAgentModelRequirements(requirements, content) {
3847
+ return requirements;
3848
+ }
3849
+ }
3850
+
3851
+ /**
3852
+ * MESSAGE commitment definition
3853
+ *
3854
+ * The MESSAGE commitment contains 1:1 text of the message which AI assistant already
3855
+ * sent during the conversation. Later messages are later in the conversation.
3856
+ * It is similar to EXAMPLE but it is not example, it is the real message which
3857
+ * AI assistant already sent.
3858
+ *
3859
+ * Example usage in agent source:
3860
+ *
3861
+ * ```book
3862
+ * MESSAGE Hello! How can I help you today?
3863
+ * MESSAGE I understand you're looking for information about our services.
3864
+ * MESSAGE Based on your requirements, I'd recommend our premium package.
3865
+ * ```
3866
+ *
3867
+ * @private [🪔] Maybe export the commitments through some package
3868
+ */
3869
+ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
3870
+ constructor(type = 'MESSAGE') {
3871
+ super(type);
3872
+ }
3873
+ /**
3874
+ * Short one-line description of MESSAGE.
3875
+ */
3876
+ get description() {
3877
+ return 'Include actual **messages** the AI assistant has sent during conversation history.';
3878
+ }
3879
+ /**
3880
+ * Icon for this commitment.
3881
+ */
3882
+ get icon() {
3883
+ return '💬';
3884
+ }
3885
+ /**
3886
+ * Markdown documentation for MESSAGE commitment.
3887
+ */
3888
+ get documentation() {
3889
+ return spaceTrim$1(`
3890
+ # ${this.type}
3891
+
3892
+ 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.
3893
+
3894
+ ## Key aspects
3895
+
3896
+ - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
3897
+ - Both terms work identically and can be used interchangeably.
3898
+ - Later messages are later in the conversation chronologically.
3899
+ - Contains actual historical messages, not examples or templates.
3900
+ - Helps maintain conversation continuity and context.
3901
+
3902
+ ## Differences from EXAMPLE
3903
+
3904
+ - \`EXAMPLE\` shows hypothetical or template responses
3905
+ - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
3906
+ - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
3907
+ - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
3908
+
3909
+ ## Use cases
3910
+
3911
+ - Maintaining conversation history context
3912
+ - Ensuring consistent tone and style across messages
3913
+ - Referencing previous responses in ongoing conversations
3914
+ - Building upon previously established context
3915
+
3916
+ ## Examples
3917
+
3918
+ \`\`\`book
3919
+ Customer Support Continuation
3920
+
3921
+ PERSONA You are a helpful customer support agent
3922
+ MESSAGE Hello! How can I help you today?
3923
+ MESSAGE I understand you're experiencing issues with your account login.
3924
+ MESSAGE I've sent you a password reset link to your email address.
3925
+ MESSAGE Is there anything else I can help you with regarding your account?
3926
+ GOAL Continue providing consistent support based on conversation history
3927
+ \`\`\`
3928
+
3929
+ \`\`\`book
3930
+ Technical Discussion
3931
+
3932
+ PERSONA You are a software development mentor
3933
+ MESSAGE Let's start by reviewing the React component structure you shared.
3934
+ MESSAGE I notice you're using class components - have you considered hooks?
3935
+ MESSAGE Here's how you could refactor that using the useState hook.
3936
+ MESSAGE Great question about performance! Let me explain React's rendering cycle.
3937
+ KNOWLEDGE React hooks were introduced in version 16.8
3938
+ \`\`\`
3939
+
3940
+ \`\`\`book
3941
+ Educational Session
3942
+
3943
+ PERSONA You are a mathematics tutor
3944
+ MESSAGE Today we'll work on solving quadratic equations.
3945
+ MESSAGE Let's start with the basic form: ax² + bx + c = 0
3946
+ MESSAGE Remember, we can use the quadratic formula or factoring.
3947
+ MESSAGE You did great with that first problem! Let's try a more complex one.
3948
+ GOAL Build upon previous explanations for deeper understanding
3949
+ \`\`\`
3950
+ `);
3951
+ }
3952
+ applyToAgentModelRequirements(requirements, content) {
3953
+ const trimmedContent = content.trim();
3954
+ if (!trimmedContent) {
3955
+ return requirements;
3956
+ }
3957
+ // Create message section for system message
3958
+ const messageSection = `Previous Message: ${trimmedContent}`;
3959
+ // Messages represent conversation history and should be included for context
3960
+ return this.appendToSystemMessage(requirements, messageSection, '\n\n');
3961
+ }
3962
+ }
3963
+ /**
3964
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3965
+ */
3966
+
3967
+ /**
3968
+ * USER MESSAGE commitment definition
3969
+ *
3970
+ * The USER MESSAGE commitment defines a message from the user in the conversation history.
3971
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
3972
+ *
3973
+ * Example usage in agent source:
3974
+ *
3975
+ * ```book
3976
+ * USER MESSAGE Hello, I have a problem.
3977
+ * ```
3978
+ *
3979
+ * @private [🪔] Maybe export the commitments through some package
3980
+ */
3981
+ class UserMessageCommitmentDefinition extends BaseCommitmentDefinition {
3982
+ constructor() {
3983
+ super('USER MESSAGE');
3984
+ }
3985
+ /**
3986
+ * Short one-line description of USER MESSAGE.
3987
+ */
3988
+ get description() {
3989
+ return 'Defines a **message from the user** in the conversation history.';
3990
+ }
3991
+ /**
3992
+ * Icon for this commitment.
3993
+ */
3994
+ get icon() {
3995
+ return '🧑';
3996
+ }
3997
+ /**
3998
+ * Markdown documentation for USER MESSAGE commitment.
3999
+ */
4000
+ get documentation() {
4001
+ return spaceTrim$1(`
4002
+ # ${this.type}
4003
+
4004
+ Defines a message from the user in the conversation history. This is used to pre-fill the chat with a conversation history or to provide few-shot examples.
4005
+
4006
+ ## Key aspects
4007
+
4008
+ - Represents a message sent by the user.
4009
+ - Used for setting up conversation context.
4010
+ - Can be used in conjunction with AGENT MESSAGE.
4011
+
4012
+ ## Examples
4013
+
4014
+ \`\`\`book
4015
+ Conversation History
4016
+
4017
+ USER MESSAGE Hello, I have a problem.
4018
+ AGENT MESSAGE What seems to be the issue?
4019
+ USER MESSAGE My computer is not starting.
4020
+ \`\`\`
4021
+ `);
4022
+ }
4023
+ applyToAgentModelRequirements(requirements, content) {
4024
+ return {
4025
+ ...requirements,
4026
+ metadata: {
4027
+ ...requirements.metadata,
4028
+ pendingUserMessage: content,
4029
+ },
4030
+ };
4031
+ }
4032
+ }
4033
+
4034
+ /**
4035
+ * META commitment definition
4036
+ *
4037
+ * The META commitment handles all meta-information about the agent such as:
4038
+ * - META IMAGE: Sets the agent's avatar/profile image URL
4039
+ * - META LINK: Provides profile/source links for the person the agent models
4040
+ * - META TITLE: Sets the agent's display title
4041
+ * - META DESCRIPTION: Sets the agent's description
4042
+ * - META [ANYTHING]: Any other meta information in uppercase format
4043
+ *
4044
+ * These commitments are special because they don't affect the system message,
4045
+ * but are handled separately in the parsing logic for profile display.
4046
+ *
4047
+ * Example usage in agent source:
4048
+ *
4049
+ * ```book
4050
+ * META IMAGE https://example.com/avatar.jpg
4051
+ * META LINK https://twitter.com/username
4052
+ * META TITLE Professional Assistant
4053
+ * META DESCRIPTION An AI assistant specialized in business tasks
4054
+ * META AUTHOR John Doe
4055
+ * META VERSION 1.0
4056
+ * ```
4057
+ *
4058
+ * @private [🪔] Maybe export the commitments through some package
4059
+ */
4060
+ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
4061
+ constructor() {
4062
+ super('META');
4063
+ }
4064
+ /**
4065
+ * Short one-line description of META commitments.
4066
+ */
4067
+ get description() {
4068
+ return 'Set meta-information about the agent (IMAGE, LINK, TITLE, DESCRIPTION, etc.).';
4069
+ }
4070
+ /**
4071
+ * Icon for this commitment.
4072
+ */
4073
+ get icon() {
4074
+ return 'ℹ️';
4075
+ }
4076
+ /**
4077
+ * Markdown documentation for META commitment.
4078
+ */
4079
+ get documentation() {
4080
+ return spaceTrim$1(`
4081
+ # META
4082
+
4083
+ Sets meta-information about the agent that is used for display and attribution purposes.
4084
+
4085
+ ## Supported META types
4086
+
4087
+ - **META IMAGE** - Sets the agent's avatar/profile image URL
4088
+ - **META LINK** - Provides profile/source links for the person the agent models
4089
+ - **META TITLE** - Sets the agent's display title
4090
+ - **META DESCRIPTION** - Sets the agent's description
4091
+ - **META [ANYTHING]** - Any other meta information in uppercase format
4092
+
4093
+ ## Key aspects
4094
+
4095
+ - Does not modify the agent's behavior or responses
4096
+ - Used for visual representation and attribution in user interfaces
4097
+ - Multiple META commitments of different types can be used
4098
+ - Multiple META LINK commitments can be used for different social profiles
4099
+ - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
4100
+
4101
+ ## Examples
4102
+
4103
+ ### Basic meta information
4104
+
4105
+ \`\`\`book
4106
+ Professional Assistant
4107
+
4108
+ META IMAGE https://example.com/professional-avatar.jpg
4109
+ META TITLE Senior Business Consultant
4110
+ META DESCRIPTION Specialized in strategic planning and project management
4111
+ META LINK https://linkedin.com/in/professional
4112
+ \`\`\`
4113
+
4114
+ ### Multiple links and custom meta
4115
+
4116
+ \`\`\`book
4117
+ Open Source Developer
4118
+
4119
+ META IMAGE /assets/dev-avatar.png
4120
+ META LINK https://github.com/developer
4121
+ META LINK https://twitter.com/devhandle
4122
+ META AUTHOR Jane Smith
4123
+ META VERSION 2.1
4124
+ META LICENSE MIT
4125
+ \`\`\`
4126
+
4127
+ ### Creative assistant
4128
+
4129
+ \`\`\`book
4130
+ Creative Helper
4131
+
4132
+ META IMAGE https://example.com/creative-bot.jpg
4133
+ META TITLE Creative Writing Assistant
4134
+ META DESCRIPTION Helps with brainstorming, storytelling, and creative projects
4135
+ META INSPIRATION Books, movies, and real-world experiences
4136
+ \`\`\`
4137
+ `);
4138
+ }
4139
+ applyToAgentModelRequirements(requirements, content) {
4140
+ // META commitments don't modify the system message or model requirements
4141
+ // They are handled separately in the parsing logic for meta information extraction
4142
+ // This method exists for consistency with the CommitmentDefinition interface
4143
+ return requirements;
4144
+ }
4145
+ /**
4146
+ * Extracts meta information from the content based on the meta type
4147
+ * This is used by the parsing logic
4148
+ */
4149
+ extractMetaValue(metaType, content) {
4150
+ const trimmedContent = content.trim();
4151
+ return trimmedContent || null;
4152
+ }
4153
+ /**
4154
+ * Validates if the provided content is a valid URL (for IMAGE and LINK types)
4155
+ */
4156
+ isValidUrl(content) {
4157
+ try {
4158
+ new URL(content.trim());
4159
+ return true;
4160
+ }
4161
+ catch (_a) {
4162
+ return false;
4163
+ }
4164
+ }
4165
+ /**
4166
+ * Checks if this is a known meta type
4167
+ */
4168
+ isKnownMetaType(metaType) {
4169
+ const knownTypes = ['IMAGE', 'LINK', 'TITLE', 'DESCRIPTION', 'AUTHOR', 'VERSION', 'LICENSE'];
4170
+ return knownTypes.includes(metaType.toUpperCase());
4171
+ }
4172
+ }
4173
+ /**
4174
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4175
+ */
4176
+
4177
+ /**
4178
+ * META COLOR commitment definition
4179
+ *
4180
+ * The META COLOR commitment sets the agent's accent color.
4181
+ * This commitment is special because it doesn't affect the system message,
4182
+ * but is handled separately in the parsing logic.
4183
+ *
4184
+ * Example usage in agent source:
4185
+ *
4186
+ * ```book
4187
+ * META COLOR #ff0000
4188
+ * META COLOR #00ff00
4189
+ * ```
4190
+ *
4191
+ * You can also specify multiple colors separated by comma:
4192
+ *
4193
+ * ```book
4194
+ * META COLOR #ff0000, #00ff00, #0000ff
4195
+ * ```
4196
+ *
4197
+ * @private [🪔] Maybe export the commitments through some package
4198
+ */
4199
+ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
4200
+ constructor() {
4201
+ super('META COLOR', ['COLOR']);
4202
+ }
4203
+ /**
4204
+ * Short one-line description of META COLOR.
4205
+ */
4206
+ get description() {
4207
+ return "Set the agent's accent color or gradient.";
4208
+ }
4209
+ /**
4210
+ * Icon for this commitment.
4211
+ */
4212
+ get icon() {
4213
+ return '🎨';
4214
+ }
4215
+ /**
4216
+ * Markdown documentation for META COLOR commitment.
4217
+ */
4218
+ get documentation() {
4219
+ return spaceTrim$1(`
4220
+ # META COLOR
4221
+
4222
+ Sets the agent's accent color or gradient.
4223
+
4224
+ ## Key aspects
4225
+
4226
+ - Does not modify the agent's behavior or responses.
4227
+ - Only one \`META COLOR\` should be used per agent.
4228
+ - If multiple are specified, the last one takes precedence.
4229
+ - Used for visual representation in user interfaces.
4230
+ - Can specify multiple colors separated by comma to create a gradient.
4231
+
4232
+ ## Examples
4233
+
4234
+ \`\`\`book
4235
+ Professional Assistant
4236
+
4237
+ META COLOR #3498db
4238
+ PERSONA You are a professional business assistant
4239
+ \`\`\`
4240
+
4241
+ \`\`\`book
4242
+ Creative Helper
4243
+
4244
+ META COLOR #e74c3c
4245
+ PERSONA You are a creative and inspiring assistant
4246
+ \`\`\`
4247
+
4248
+ \`\`\`book
4249
+ Gradient Agent
4250
+
4251
+ META COLOR #ff0000, #00ff00, #0000ff
4252
+ PERSONA You are a colorful agent
4253
+ \`\`\`
4254
+ `);
4255
+ }
4256
+ applyToAgentModelRequirements(requirements, content) {
4257
+ // META COLOR doesn't modify the system message or model requirements
4258
+ // It's handled separately in the parsing logic for profile color extraction
4259
+ // This method exists for consistency with the CommitmentDefinition interface
4260
+ return requirements;
4261
+ }
4262
+ /**
4263
+ * Extracts the profile color from the content
4264
+ * This is used by the parsing logic
4265
+ */
4266
+ extractProfileColor(content) {
4267
+ const trimmedContent = content.trim();
4268
+ return trimmedContent || null;
4269
+ }
4270
+ }
4271
+ /**
4272
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4273
+ */
4274
+
4275
+ /**
4276
+ * META FONT commitment definition
4277
+ *
4278
+ * The META FONT commitment sets the agent's font.
4279
+ * This commitment is special because it doesn't affect the system message,
4280
+ * but is handled separately in the parsing logic.
4281
+ *
4282
+ * Example usage in agent source:
4283
+ *
4284
+ * ```book
4285
+ * META FONT Poppins, Arial, sans-serif
4286
+ * META FONT Roboto
4287
+ * ```
4288
+ *
4289
+ * @private [🪔] Maybe export the commitments through some package
4290
+ */
4291
+ class MetaFontCommitmentDefinition extends BaseCommitmentDefinition {
4292
+ constructor() {
4293
+ super('META FONT', ['FONT']);
4294
+ }
4295
+ /**
4296
+ * Short one-line description of META FONT.
4297
+ */
4298
+ get description() {
4299
+ return "Set the agent's font.";
4300
+ }
4301
+ /**
4302
+ * Icon for this commitment.
4303
+ */
4304
+ get icon() {
4305
+ return '🔤';
4306
+ }
4307
+ /**
4308
+ * Markdown documentation for META FONT commitment.
4309
+ */
4310
+ get documentation() {
4311
+ return spaceTrim$1(`
4312
+ # META FONT
4313
+
4314
+ Sets the agent's font.
4315
+
4316
+ ## Key aspects
4317
+
4318
+ - Does not modify the agent's behavior or responses.
4319
+ - Only one \`META FONT\` should be used per agent.
4320
+ - If multiple are specified, the last one takes precedence.
4321
+ - Used for visual representation in user interfaces.
4322
+ - Supports Google Fonts.
4323
+
4324
+ ## Examples
4325
+
4326
+ \`\`\`book
4327
+ Modern Assistant
4328
+
4329
+ META FONT Poppins, Arial, sans-serif
4330
+ PERSONA You are a modern assistant
4331
+ \`\`\`
4332
+
4333
+ \`\`\`book
4334
+ Classic Helper
4335
+
4336
+ META FONT Times New Roman
4337
+ PERSONA You are a classic helper
4338
+ \`\`\`
4339
+ `);
4340
+ }
4341
+ applyToAgentModelRequirements(requirements, content) {
4342
+ // META FONT doesn't modify the system message or model requirements
4343
+ // It's handled separately in the parsing logic
4344
+ // This method exists for consistency with the CommitmentDefinition interface
4345
+ return requirements;
4346
+ }
4347
+ /**
4348
+ * Extracts the font from the content
4349
+ * This is used by the parsing logic
4350
+ */
4351
+ extractProfileFont(content) {
4352
+ const trimmedContent = content.trim();
4353
+ return trimmedContent || null;
4354
+ }
4355
+ }
4356
+ /**
4357
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4358
+ */
4359
+
4360
+ /**
4361
+ * META IMAGE commitment definition
4362
+ *
4363
+ * The META IMAGE commitment sets the agent's avatar/profile image URL.
4364
+ * This commitment is special because it doesn't affect the system message,
4365
+ * but is handled separately in the parsing logic.
4366
+ *
4367
+ * Example usage in agent source:
4368
+ *
4369
+ * ```book
4370
+ * META IMAGE https://example.com/avatar.jpg
4371
+ * META IMAGE /assets/agent-avatar.png
4372
+ * ```
4373
+ *
4374
+ * @private [🪔] Maybe export the commitments through some package
4375
+ */
4376
+ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
4377
+ constructor() {
4378
+ super('META IMAGE', ['IMAGE']);
4379
+ }
4380
+ /**
4381
+ * Short one-line description of META IMAGE.
4382
+ */
4383
+ get description() {
4384
+ return "Set the agent's profile image URL.";
4385
+ }
4386
+ /**
4387
+ * Icon for this commitment.
4388
+ */
4389
+ get icon() {
4390
+ return '🖼️';
4391
+ }
4392
+ /**
4393
+ * Markdown documentation for META IMAGE commitment.
4394
+ */
4395
+ get documentation() {
4396
+ return spaceTrim$1(`
4397
+ # META IMAGE
4398
+
4399
+ Sets the agent's avatar/profile image URL.
4400
+
4401
+ ## Key aspects
4402
+
4403
+ - Does not modify the agent's behavior or responses.
4404
+ - Only one \`META IMAGE\` should be used per agent.
4405
+ - If multiple are specified, the last one takes precedence.
4406
+ - Used for visual representation in user interfaces.
4407
+
4408
+ ## Examples
4409
+
4410
+ \`\`\`book
4411
+ Professional Assistant
4412
+
4413
+ META IMAGE https://example.com/professional-avatar.jpg
4414
+ PERSONA You are a professional business assistant
4415
+ STYLE Maintain a formal and courteous tone
4416
+ \`\`\`
4417
+
4418
+ \`\`\`book
4419
+ Creative Helper
4420
+
4421
+ META IMAGE /assets/creative-bot-avatar.png
4422
+ PERSONA You are a creative and inspiring assistant
4423
+ STYLE Be enthusiastic and encouraging
4424
+ ACTION Can help with brainstorming and ideation
4425
+ \`\`\`
4426
+ `);
4427
+ }
4428
+ applyToAgentModelRequirements(requirements, content) {
4429
+ // META IMAGE doesn't modify the system message or model requirements
4430
+ // It's handled separately in the parsing logic for profile image extraction
4431
+ // This method exists for consistency with the CommitmentDefinition interface
4432
+ return requirements;
4433
+ }
4434
+ /**
4435
+ * Extracts the profile image URL from the content
4436
+ * This is used by the parsing logic
4437
+ */
4438
+ extractProfileImageUrl(content) {
4439
+ const trimmedContent = content.trim();
4440
+ return trimmedContent || null;
4441
+ }
4442
+ }
4443
+ /**
4444
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4445
+ */
4446
+
4447
+ /**
4448
+ * META LINK commitment definition
4449
+ *
4450
+ * The `META LINK` commitment represents the link to the person from whom the agent is created.
4451
+ * This commitment is special because it doesn't affect the system message,
4452
+ * but is handled separately in the parsing logic for profile display.
4453
+ *
4454
+ * Example usage in agent source:
4455
+ *
4456
+ * ```
4457
+ * META LINK https://twitter.com/username
4458
+ * META LINK https://linkedin.com/in/profile
4459
+ * META LINK https://github.com/username
4460
+ * ```
4461
+ *
4462
+ * Multiple `META LINK` commitments can be used when there are multiple sources:
4463
+ *
4464
+ * ```book
4465
+ * META LINK https://twitter.com/username
4466
+ * META LINK https://linkedin.com/in/profile
4467
+ * ```
4468
+ *
4469
+ * @private [🪔] Maybe export the commitments through some package
4470
+ */
4471
+ class MetaLinkCommitmentDefinition extends BaseCommitmentDefinition {
4472
+ constructor() {
4473
+ super('META LINK');
4474
+ }
4475
+ /**
4476
+ * Short one-line description of META LINK.
4477
+ */
4478
+ get description() {
4479
+ return 'Provide profile/source links for the person the agent models.';
4480
+ }
4481
+ /**
4482
+ * Icon for this commitment.
4483
+ */
4484
+ get icon() {
4485
+ return '🔗';
4486
+ }
4487
+ /**
4488
+ * Markdown documentation for META LINK commitment.
4489
+ */
4490
+ get documentation() {
4491
+ return spaceTrim$1(`
4492
+ # META LINK
4493
+
4494
+ Represents a profile or source link for the person the agent is modeled after.
4495
+
4496
+ ## Key aspects
4497
+
4498
+ - Does not modify the agent's behavior or responses.
4499
+ - Multiple \`META LINK\` commitments can be used for different social profiles.
4500
+ - Used for attribution and crediting the original person.
4501
+ - Displayed in user interfaces for transparency.
4502
+
4503
+ ## Examples
4504
+
4505
+ \`\`\`book
4506
+ Expert Consultant
4507
+
4508
+ META LINK https://twitter.com/expertname
4509
+ META LINK https://linkedin.com/in/expertprofile
4510
+ PERSONA You are Dr. Smith, a renowned expert in artificial intelligence
4511
+ KNOWLEDGE Extensive background in machine learning and neural networks
4512
+ \`\`\`
4513
+
4514
+ \`\`\`book
4515
+ Open Source Developer
4516
+
4517
+ META LINK https://github.com/developer
4518
+ META LINK https://twitter.com/devhandle
4519
+ PERSONA You are an experienced open source developer
4520
+ ACTION Can help with code reviews and architecture decisions
4521
+ STYLE Be direct and technical in explanations
4522
+ \`\`\`
4523
+ `);
4524
+ }
4525
+ applyToAgentModelRequirements(requirements, content) {
4526
+ // META LINK doesn't modify the system message or model requirements
4527
+ // It's handled separately in the parsing logic for profile link extraction
4528
+ // This method exists for consistency with the CommitmentDefinition interface
4529
+ return requirements;
4530
+ }
4531
+ /**
4532
+ * Extracts the profile link URL from the content
4533
+ * This is used by the parsing logic
4534
+ */
4535
+ extractProfileLinkUrl(content) {
4536
+ const trimmedContent = content.trim();
4537
+ return trimmedContent || null;
4538
+ }
4539
+ /**
4540
+ * Validates if the provided content is a valid URL
4541
+ */
4542
+ isValidUrl(content) {
4543
+ try {
4544
+ new URL(content.trim());
4545
+ return true;
4546
+ }
4547
+ catch (_a) {
4548
+ return false;
4549
+ }
4550
+ }
4551
+ }
4552
+ /**
4553
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4554
+ */
4555
+
4556
+ /**
4557
+ * MODEL commitment definition
4558
+ *
4559
+ * The MODEL commitment specifies which AI model to use and can also set
4560
+ * model-specific parameters like temperature, topP, topK, and maxTokens.
4561
+ *
4562
+ * Supports multiple syntax variations:
4563
+ *
4564
+ * Single-line format:
4565
+ * ```book
4566
+ * MODEL gpt-4
4567
+ * MODEL claude-3-opus temperature=0.3
4568
+ * MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
4569
+ * ```
4570
+ *
4571
+ * Multi-line named parameter format:
4572
+ * ```book
4573
+ * MODEL NAME gpt-4
4574
+ * MODEL TEMPERATURE 0.7
4575
+ * MODEL TOP_P 0.9
4576
+ * MODEL MAX_TOKENS 2048
4577
+ * ```
4578
+ *
4579
+ * @private [🪔] Maybe export the commitments through some package
4580
+ */
4581
+ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
4582
+ constructor(type = 'MODEL') {
4583
+ super(type);
4584
+ }
4585
+ /**
4586
+ * Short one-line description of MODEL.
4587
+ */
4588
+ get description() {
4589
+ return 'Enforce AI model requirements including name and technical parameters.';
4590
+ }
4591
+ /**
4592
+ * Icon for this commitment.
4593
+ */
4594
+ get icon() {
4595
+ return '⚙️';
4596
+ }
4597
+ /**
4598
+ * Markdown documentation for MODEL commitment.
4599
+ */
4600
+ get documentation() {
4601
+ return spaceTrim$1(`
4602
+ # ${this.type}
4603
+
4604
+ Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
4605
+
4606
+ ## Key aspects
4607
+
4608
+ - When no \`MODEL\` commitment is specified, the best model requirement is picked automatically based on the agent \`PERSONA\`, \`KNOWLEDGE\`, \`TOOLS\` and other commitments
4609
+ - Multiple \`MODEL\` commitments can be used to specify different parameters
4610
+ - Both \`MODEL\` and \`MODELS\` terms work identically and can be used interchangeably
4611
+ - Parameters control the randomness, creativity, and technical aspects of model responses
4612
+
4613
+ ## Syntax variations
4614
+
4615
+ ### Single-line format (legacy support)
4616
+ \`\`\`book
4617
+ MODEL gpt-4
4618
+ MODEL claude-3-opus temperature=0.3
4619
+ MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
4620
+ \`\`\`
4621
+
4622
+ ### Multi-line named parameter format (recommended)
4623
+ \`\`\`book
4624
+ MODEL NAME gpt-4
4625
+ MODEL TEMPERATURE 0.7
4626
+ MODEL TOP_P 0.9
4627
+ MODEL MAX_TOKENS 2048
4628
+ \`\`\`
4629
+
4630
+ ## Supported parameters
4631
+
4632
+ - \`NAME\`: The specific model to use (e.g., 'gpt-4', 'claude-3-opus')
4633
+ - \`TEMPERATURE\`: Controls randomness (0.0 = deterministic, 1.0+ = creative)
4634
+ - \`TOP_P\`: Nucleus sampling parameter for controlling diversity
4635
+ - \`TOP_K\`: Top-k sampling parameter for limiting vocabulary
4636
+ - \`MAX_TOKENS\`: Maximum number of tokens the model can generate
4637
+
4638
+ ## Examples
4639
+
4640
+ ### Precise deterministic assistant
4641
+ \`\`\`book
4642
+ Precise Assistant
4643
+
4644
+ PERSONA You are a precise and accurate assistant
4645
+ MODEL NAME gpt-4
4646
+ MODEL TEMPERATURE 0.1
4647
+ MODEL MAX_TOKENS 1024
4648
+ RULE Always provide factual information
4649
+ \`\`\`
4650
+
4651
+ ### Creative writing assistant
4652
+ \`\`\`book
4653
+ Creative Writer
4654
+
4655
+ PERSONA You are a creative writing assistant
4656
+ MODEL NAME claude-3-opus
4657
+ MODEL TEMPERATURE 0.8
4658
+ MODEL TOP_P 0.9
4659
+ MODEL MAX_TOKENS 2048
4660
+ STYLE Be imaginative and expressive
4661
+ ACTION Can help with storytelling and character development
4662
+ \`\`\`
4663
+
4664
+ ### Balanced conversational agent
4665
+ \`\`\`book
4666
+ Balanced Assistant
4667
+
4668
+ PERSONA You are a helpful and balanced assistant
4669
+ MODEL NAME gpt-4
4670
+ MODEL TEMPERATURE 0.7
4671
+ MODEL TOP_P 0.95
4672
+ MODEL TOP_K 40
4673
+ MODEL MAX_TOKENS 1500
4674
+ \`\`\`
4675
+ `);
4676
+ }
4677
+ applyToAgentModelRequirements(requirements, content) {
4678
+ var _a;
4679
+ const trimmedContent = content.trim();
4680
+ if (!trimmedContent) {
4681
+ return requirements;
4682
+ }
4683
+ const parts = trimmedContent.split(/\s+/);
4684
+ const firstPart = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
4685
+ // Check if this is the new named parameter format
4686
+ if (this.isNamedParameter(firstPart)) {
4687
+ return this.parseNamedParameter(requirements, firstPart, parts.slice(1));
4688
+ }
4689
+ else {
4690
+ // Legacy single-line format: "MODEL gpt-4 temperature=0.3 topP=0.9"
4691
+ return this.parseLegacyFormat(requirements, parts);
4692
+ }
4693
+ }
4694
+ /**
4695
+ * Check if the first part is a known named parameter
4696
+ */
4697
+ isNamedParameter(part) {
4698
+ if (!part)
4699
+ return false;
4700
+ const knownParams = ['NAME', 'TEMPERATURE', 'TOP_P', 'TOP_K', 'MAX_TOKENS'];
4701
+ return knownParams.includes(part);
4702
+ }
4703
+ /**
4704
+ * Parse the new named parameter format: "MODEL TEMPERATURE 0.7"
4705
+ */
4706
+ parseNamedParameter(requirements, parameterName, valueParts) {
4707
+ const value = valueParts.join(' ').trim();
4708
+ if (!value) {
4709
+ return requirements;
4710
+ }
4711
+ const result = { ...requirements };
4712
+ switch (parameterName) {
4713
+ case 'NAME':
4714
+ result.modelName = value;
4715
+ break;
4716
+ case 'TEMPERATURE': {
4717
+ const temperature = parseFloat(value);
4718
+ if (!isNaN(temperature)) {
4719
+ result.temperature = temperature;
4720
+ }
4721
+ break;
4722
+ }
4723
+ case 'TOP_P': {
4724
+ const topP = parseFloat(value);
4725
+ if (!isNaN(topP)) {
4726
+ result.topP = topP;
4727
+ }
4728
+ break;
4729
+ }
4730
+ case 'TOP_K': {
4731
+ const topK = parseFloat(value);
4732
+ if (!isNaN(topK)) {
4733
+ result.topK = Math.round(topK);
4734
+ }
4735
+ break;
4736
+ }
4737
+ case 'MAX_TOKENS': {
4738
+ const maxTokens = parseFloat(value);
4739
+ if (!isNaN(maxTokens)) {
4740
+ result.maxTokens = Math.round(maxTokens);
4741
+ }
4742
+ break;
4743
+ }
4744
+ }
4745
+ return result;
4746
+ }
4747
+ /**
4748
+ * Parse the legacy format: "MODEL gpt-4 temperature=0.3 topP=0.9"
4749
+ */
4750
+ parseLegacyFormat(requirements, parts) {
4751
+ const modelName = parts[0];
4752
+ if (!modelName) {
4753
+ return requirements;
4754
+ }
4755
+ // Start with the model name
4756
+ const result = {
4757
+ ...requirements,
4758
+ modelName,
4759
+ };
4760
+ // Parse additional key=value parameters
4761
+ for (let i = 1; i < parts.length; i++) {
4762
+ const param = parts[i];
4763
+ if (param && param.includes('=')) {
4764
+ const [key, value] = param.split('=');
4765
+ if (key && value) {
4766
+ const numValue = parseFloat(value);
4767
+ if (!isNaN(numValue)) {
4768
+ switch (key.toLowerCase()) {
4769
+ case 'temperature':
4770
+ result.temperature = numValue;
4771
+ break;
4772
+ case 'topp':
4773
+ case 'top_p':
4774
+ result.topP = numValue;
4775
+ break;
4776
+ case 'topk':
4777
+ case 'top_k':
4778
+ result.topK = Math.round(numValue);
4779
+ break;
4780
+ case 'max_tokens':
4781
+ case 'maxTokens':
4782
+ result.maxTokens = Math.round(numValue);
4783
+ break;
4784
+ }
4785
+ }
4786
+ }
4787
+ }
4788
+ }
4789
+ return result;
4790
+ }
4791
+ }
4792
+ /**
4793
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4794
+ */
4795
+
4796
+ /**
4797
+ * NOTE commitment definition
4798
+ *
4799
+ * The NOTE commitment is used to add comments to the agent source without making any changes
4800
+ * to the system message or agent model requirements. It serves as a documentation mechanism
4801
+ * for developers to add explanatory comments, reminders, or annotations directly in the agent source.
4802
+ *
4803
+ * Key features:
4804
+ * - Makes no changes to the system message
4805
+ * - Makes no changes to agent model requirements
4806
+ * - Content is preserved in metadata.NOTE for debugging and inspection
4807
+ * - Multiple NOTE commitments are aggregated together
4808
+ * - Comments (# NOTE) are removed from the final system message
4809
+ *
4810
+ * Example usage in agent source:
4811
+ *
4812
+ * ```book
4813
+ * NOTE This agent was designed for customer support scenarios
4814
+ * NOTE Remember to update the knowledge base monthly
4815
+ * NOTE Performance optimized for quick response times
4816
+ * ```
4817
+ *
4818
+ * The above notes will be stored in metadata but won't affect the agent's behavior.
4819
+ *
4820
+ * @private [🪔] Maybe export the commitments through some package
4821
+ */
4822
+ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
4823
+ constructor(type = 'NOTE') {
4824
+ super(type);
4825
+ }
4826
+ /**
4827
+ * Short one-line description of NOTE.
4828
+ */
4829
+ get description() {
4830
+ return 'Add developer-facing notes without changing behavior or output.';
4831
+ }
4832
+ /**
4833
+ * Icon for this commitment.
4834
+ */
4835
+ get icon() {
4836
+ return '📝';
4837
+ }
4838
+ /**
4839
+ * Markdown documentation for NOTE commitment.
4840
+ */
4841
+ get documentation() {
4842
+ return spaceTrim$1(`
4843
+ # ${this.type}
4844
+
4845
+ Adds comments for documentation without changing agent behavior.
4846
+
4847
+ ## Key aspects
4848
+
4849
+ - Does not modify the agent's behavior or responses.
4850
+ - Multiple \`NOTE\`, \`NOTES\`, \`COMMENT\`, and \`NONCE\` commitments are aggregated for debugging.
4851
+ - All four terms work identically and can be used interchangeably.
4852
+ - Useful for documenting design decisions and reminders.
4853
+ - Content is preserved in metadata for inspection.
4854
+
4855
+ ## Examples
4856
+
4857
+ \`\`\`book
4858
+ Customer Support Bot
4859
+
4860
+ NOTE This agent was designed for customer support scenarios
4861
+ COMMENT Remember to update the knowledge base monthly
4862
+ PERSONA You are a helpful customer support representative
4863
+ KNOWLEDGE Company policies and procedures
4864
+ RULE Always be polite and professional
4865
+ \`\`\`
4866
+
4867
+ \`\`\`book
4868
+ Research Assistant
4869
+
4870
+ NONCE Performance optimized for quick response times
4871
+ NOTE Uses RAG for accessing latest research papers
4872
+ PERSONA You are a knowledgeable research assistant
4873
+ ACTION Can help with literature reviews and citations
4874
+ STYLE Present information in academic format
4875
+ \`\`\`
4876
+ `);
4877
+ }
4878
+ applyToAgentModelRequirements(requirements, content) {
4879
+ var _a;
4880
+ // The NOTE commitment makes no changes to the system message or model requirements
4881
+ // It only stores the note content in metadata for documentation purposes
4882
+ const trimmedContent = content.trim();
4883
+ if (!trimmedContent) {
4884
+ return requirements;
4885
+ }
4886
+ // Get existing note content from metadata
4887
+ const existingNoteContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.NOTE) || '';
4888
+ // Merge the new content with existing note content
4889
+ // When multiple NOTE commitments exist, they are aggregated together
4890
+ const mergedNoteContent = existingNoteContent ? `${existingNoteContent}\n${trimmedContent}` : trimmedContent;
4891
+ // Store the merged note content in metadata for debugging and inspection
4892
+ const updatedMetadata = {
4893
+ ...requirements.metadata,
4894
+ NOTE: mergedNoteContent,
4895
+ };
4896
+ // Return requirements with updated metadata but no changes to system message
4897
+ return {
4898
+ ...requirements,
4899
+ metadata: updatedMetadata,
4900
+ };
4901
+ }
4902
+ }
4903
+ /**
4904
+ * [💞] Ignore a discrepancy between file name and entity name
4905
+ */
4906
+
4907
+ /**
4908
+ * OPEN commitment definition
4909
+ *
4910
+ * The OPEN commitment specifies that the agent can be modified by conversation.
4911
+ * This is the default behavior.
4912
+ *
4913
+ * Example usage in agent source:
4914
+ *
4915
+ * ```book
4916
+ * OPEN
4917
+ * ```
4918
+ *
4919
+ * @private [🪔] Maybe export the commitments through some package
4920
+ */
4921
+ class OpenCommitmentDefinition extends BaseCommitmentDefinition {
4922
+ constructor() {
4923
+ super('OPEN');
4924
+ }
4925
+ /**
4926
+ * Short one-line description of OPEN.
4927
+ */
4928
+ get description() {
4929
+ return 'Allow the agent to be modified by conversation (default).';
4930
+ }
4931
+ /**
4932
+ * Icon for this commitment.
4933
+ */
4934
+ get icon() {
4935
+ return '🔓';
4936
+ }
4937
+ /**
4938
+ * Markdown documentation for OPEN commitment.
4939
+ */
4940
+ get documentation() {
4941
+ return spaceTrim$1(`
4942
+ # OPEN
4943
+
4944
+ Specifies that the agent can be modified by conversation with it.
4945
+ This means the agent will learn from interactions and update its source code.
4946
+
4947
+ This is the default behavior if neither \`OPEN\` nor \`CLOSED\` is specified.
4948
+
4949
+ > See also [CLOSED](/docs/CLOSED)
4950
+
4951
+ ## Example
4952
+
4953
+ \`\`\`book
4954
+ OPEN
4955
+ \`\`\`
4956
+ `);
4957
+ }
4958
+ applyToAgentModelRequirements(requirements, _content) {
4959
+ // Since OPEN is default, we can just ensure isClosed is false
4960
+ // But to be explicit we can set it
4961
+ const updatedMetadata = {
4962
+ ...requirements.metadata,
4963
+ isClosed: false,
4964
+ };
4965
+ return {
4966
+ ...requirements,
4967
+ metadata: updatedMetadata,
4968
+ };
4969
+ }
4970
+ }
4971
+ /**
4972
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4973
+ */
4974
+
4975
+ /**
4976
+ * PERSONA commitment definition
4977
+ *
4978
+ * The PERSONA commitment modifies the agent's personality and character in the system message.
4979
+ * It defines who the agent is, their background, expertise, and personality traits.
4980
+ *
4981
+ * Key features:
4982
+ * - Multiple PERSONA commitments are automatically merged into one
4983
+ * - Content is placed at the beginning of the system message
4984
+ * - Original content with comments is preserved in metadata.PERSONA
4985
+ * - Comments (# PERSONA) are removed from the final system message
4986
+ *
4987
+ * Example usage in agent source:
4988
+ *
4989
+ * ```book
4990
+ * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
4991
+ * PERSONA You have deep knowledge of modern web development practices
4992
+ * ```
4993
+ *
4994
+ * The above will be merged into a single persona section at the beginning of the system message.
4995
+ *
4996
+ * @private [🪔] Maybe export the commitments through some package
4997
+ */
4998
+ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
4999
+ constructor(type = 'PERSONA') {
5000
+ super(type);
5001
+ }
5002
+ /**
5003
+ * Short one-line description of PERSONA.
5004
+ */
5005
+ get description() {
5006
+ return 'Define who the agent is: background, expertise, and personality.';
5007
+ }
5008
+ /**
5009
+ * Icon for this commitment.
5010
+ */
5011
+ get icon() {
5012
+ return '👤';
5013
+ }
5014
+ /**
5015
+ * Markdown documentation for PERSONA commitment.
5016
+ */
5017
+ get documentation() {
5018
+ return spaceTrim$1(`
5019
+ # ${this.type}
5020
+
5021
+ Defines who the agent is, their background, expertise, and personality traits.
5022
+
5023
+ ## Key aspects
5024
+
5025
+ - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
5026
+ - Both terms work identically and can be used interchangeably.
5027
+ - If they are in conflict, the last one takes precedence.
5028
+ - You can write persona content in multiple lines.
5029
+
5030
+ ## Examples
5031
+
5032
+ \`\`\`book
5033
+ Programming Assistant
5034
+
5035
+ PERSONA You are a helpful programming assistant with expertise in TypeScript and React
5036
+ PERSONA You have deep knowledge of modern web development practices
5037
+ \`\`\`
5038
+ `);
5039
+ }
5040
+ applyToAgentModelRequirements(requirements, content) {
5041
+ var _a, _b;
5042
+ // The PERSONA commitment aggregates all persona content and places it at the beginning
5043
+ const trimmedContent = content.trim();
5044
+ if (!trimmedContent) {
5045
+ return requirements;
5046
+ }
5047
+ // Get existing persona content from metadata
5048
+ const existingPersonaContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
5049
+ // Merge the new content with existing persona content
5050
+ // When multiple PERSONA commitments exist, they are merged into one
5051
+ const mergedPersonaContent = existingPersonaContent
5052
+ ? `${existingPersonaContent}\n${trimmedContent}`
5053
+ : trimmedContent;
5054
+ // Store the merged persona content in metadata for debugging and inspection
5055
+ const updatedMetadata = {
5056
+ ...requirements.metadata,
5057
+ PERSONA: mergedPersonaContent,
5058
+ };
5059
+ // Get the agent name from metadata (which should contain the first line of agent source)
5060
+ // If not available, extract from current system message as fallback
5061
+ let agentName = (_b = requirements.metadata) === null || _b === void 0 ? void 0 : _b.agentName;
5062
+ if (!agentName) {
5063
+ // Fallback: extract from current system message
5064
+ const currentMessage = requirements.systemMessage.trim();
5065
+ const basicFormatMatch = currentMessage.match(/^You are (.+)$/);
5066
+ if (basicFormatMatch && basicFormatMatch[1]) {
5067
+ agentName = basicFormatMatch[1];
5068
+ }
5069
+ else {
5070
+ agentName = 'AI Agent'; // Final fallback
5071
+ }
5072
+ }
5073
+ // Remove any existing persona content from the system message
5074
+ // (this handles the case where we're processing multiple PERSONA commitments)
5075
+ const currentMessage = requirements.systemMessage.trim();
5076
+ let cleanedMessage = currentMessage;
5077
+ // Check if current message starts with persona content or is just the basic format
5078
+ const basicFormatRegex = /^You are .+$/;
5079
+ const isBasicFormat = basicFormatRegex.test(currentMessage) && !currentMessage.includes('\n');
5080
+ if (isBasicFormat) {
5081
+ // Replace the basic format entirely
5082
+ cleanedMessage = '';
5083
+ }
5084
+ else if (currentMessage.startsWith('# PERSONA')) {
5085
+ // Remove existing persona section by finding where it ends
5086
+ const lines = currentMessage.split('\n');
5087
+ let personaEndIndex = lines.length;
5088
+ // Find the end of the PERSONA section (next comment or end of message)
5089
+ for (let i = 1; i < lines.length; i++) {
5090
+ const line = lines[i].trim();
5091
+ if (line.startsWith('#') && !line.startsWith('# PERSONA')) {
5092
+ personaEndIndex = i;
5093
+ break;
5094
+ }
5095
+ }
5096
+ // Keep everything after the PERSONA section
5097
+ cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
5098
+ }
5099
+ // TODO: [🕛] There should be `agentFullname` not `agentName`
5100
+ // Create new system message with persona at the beginning
5101
+ // Format: "You are {agentName}\n{personaContent}"
5102
+ // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
5103
+ const personaSection = `# PERSONA\nYou are ${agentName}\n${mergedPersonaContent}`; // <- TODO: Use spaceTrim
5104
+ const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
5105
+ return {
5106
+ ...requirements,
5107
+ systemMessage: newSystemMessage,
5108
+ metadata: updatedMetadata,
5109
+ };
5110
+ }
5111
+ }
5112
+ /**
5113
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5114
+ */
5115
+
5116
+ /**
5117
+ * RULE commitment definition
5118
+ *
5119
+ * The RULE/RULES commitment adds behavioral constraints and guidelines that the agent must follow.
5120
+ * These are specific instructions about what the agent should or shouldn't do.
5121
+ *
5122
+ * Example usage in agent source:
5123
+ *
5124
+ * ```book
5125
+ * RULE Always ask for clarification if the user's request is ambiguous
5126
+ * RULES Never provide medical advice, always refer to healthcare professionals
5127
+ * ```
5128
+ *
5129
+ * @private [🪔] Maybe export the commitments through some package
5130
+ */
5131
+ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
5132
+ constructor(type = 'RULE') {
5133
+ super(type);
5134
+ }
5135
+ /**
5136
+ * Short one-line description of RULE/RULES.
5137
+ */
5138
+ get description() {
5139
+ return 'Add behavioral rules the agent must follow.';
5140
+ }
5141
+ /**
5142
+ * Icon for this commitment.
5143
+ */
5144
+ get icon() {
5145
+ return '⚖️';
5146
+ }
5147
+ /**
5148
+ * Markdown documentation for RULE/RULES commitment.
5149
+ */
5150
+ get documentation() {
5151
+ return spaceTrim$1(`
5152
+ # ${this.type}
5153
+
5154
+ Adds behavioral constraints and guidelines that the agent must follow.
5155
+
5156
+ ## Key aspects
5157
+
5158
+ - All rules are treated equally regardless of singular/plural form.
5159
+ - Rules define what the agent must or must not do.
5160
+
5161
+ ## Examples
5162
+
5163
+ \`\`\`book
5164
+ Customer Support Agent
5165
+
5166
+ PERSONA You are a helpful customer support representative
5167
+ RULE Always ask for clarification if the user's request is ambiguous
5168
+ RULE Be polite and professional in all interactions
5169
+ RULES Never provide medical or legal advice
5170
+ STYLE Maintain a friendly and helpful tone
5171
+ \`\`\`
5172
+
5173
+ \`\`\`book
5174
+ Educational Tutor
5175
+
5176
+ PERSONA You are a patient and knowledgeable tutor
5177
+ RULE Break down complex concepts into simple steps
5178
+ RULE Always encourage students and celebrate their progress
5179
+ RULE If you don't know something, admit it and suggest resources
5180
+ SAMPLE When explaining math: "Let's work through this step by step..."
5181
+ \`\`\`
5182
+ `);
5183
+ }
5184
+ applyToAgentModelRequirements(requirements, content) {
5185
+ const trimmedContent = content.trim();
5186
+ if (!trimmedContent) {
5187
+ return requirements;
5188
+ }
5189
+ // Add rule to the system message
5190
+ const ruleSection = `Rule: ${trimmedContent}`;
5191
+ return this.appendToSystemMessage(requirements, ruleSection, '\n\n');
5192
+ }
5193
+ }
5194
+ /**
5195
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5196
+ */
5197
+
5198
+ /**
5199
+ * SAMPLE commitment definition
5200
+ *
5201
+ * The SAMPLE/EXAMPLE commitment provides examples of how the agent should respond
5202
+ * or behave in certain situations. These examples help guide the agent's responses.
5203
+ *
5204
+ * Example usage in agent source:
5205
+ *
5206
+ * ```book
5207
+ * SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
5208
+ * EXAMPLE For code questions, always include working code snippets
5209
+ * ```
5210
+ *
5211
+ * @private [🪔] Maybe export the commitments through some package
5212
+ */
5213
+ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
5214
+ constructor(type = 'SAMPLE') {
5215
+ super(type);
5216
+ }
5217
+ /**
5218
+ * Short one-line description of SAMPLE/EXAMPLE.
5219
+ */
5220
+ get description() {
5221
+ return 'Provide example responses to guide behavior.';
5222
+ }
5223
+ /**
5224
+ * Icon for this commitment.
5225
+ */
5226
+ get icon() {
5227
+ return '🔍';
5228
+ }
5229
+ /**
5230
+ * Markdown documentation for SAMPLE/EXAMPLE commitment.
5231
+ */
5232
+ get documentation() {
5233
+ return spaceTrim$1(`
5234
+ # ${this.type}
5235
+
5236
+ Provides examples of how the agent should respond or behave in certain situations.
5237
+
5238
+ ## Key aspects
5239
+
5240
+ - Both terms work identically and can be used interchangeably.
5241
+ - Examples help guide the agent's response patterns and style.
5242
+
5243
+ ## Examples
5244
+
5245
+ \`\`\`book
5246
+ Sales Assistant
5247
+
5248
+ PERSONA You are a knowledgeable sales representative
5249
+ SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
5250
+ SAMPLE For feature comparisons, create a clear comparison table
5251
+ RULE Always be honest about limitations
5252
+ \`\`\`
5253
+
5254
+ \`\`\`book
5255
+ Code Reviewer
5256
+
5257
+ PERSONA You are an experienced software engineer
5258
+ EXAMPLE For code questions, always include working code snippets
5259
+ EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
5260
+ RULE Explain the reasoning behind your suggestions
5261
+ STYLE Be constructive and encouraging in feedback
5262
+ \`\`\`
5263
+ `);
5264
+ }
5265
+ applyToAgentModelRequirements(requirements, content) {
5266
+ const trimmedContent = content.trim();
5267
+ if (!trimmedContent) {
5268
+ return requirements;
5269
+ }
5270
+ // Add example to the system message
5271
+ const exampleSection = `Example: ${trimmedContent}`;
5272
+ return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
5273
+ }
5274
+ }
5275
+ /**
5276
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5277
+ */
5278
+
5279
+ /**
5280
+ * SCENARIO commitment definition
5281
+ *
5282
+ * The SCENARIO commitment defines a specific situation or context in which the AI
5283
+ * assistant should operate. It helps to set the scene for the AI's responses.
5284
+ * Later scenarios are more important than earlier scenarios.
5285
+ *
5286
+ * Example usage in agent source:
5287
+ *
5288
+ * ```book
5289
+ * SCENARIO You are in a customer service call center during peak hours
5290
+ * SCENARIO The customer is frustrated and has been on hold for 20 minutes
5291
+ * SCENARIO This is the customer's third call about the same issue
5292
+ * ```
5293
+ *
5294
+ * @private [🪔] Maybe export the commitments through some package
5295
+ */
5296
+ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
5297
+ constructor(type = 'SCENARIO') {
5298
+ super(type);
5299
+ }
5300
+ /**
5301
+ * Short one-line description of SCENARIO.
5302
+ */
5303
+ get description() {
5304
+ return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
5305
+ }
5306
+ /**
5307
+ * Icon for this commitment.
5308
+ */
5309
+ get icon() {
5310
+ return '🎭';
5311
+ }
5312
+ /**
5313
+ * Markdown documentation for SCENARIO commitment.
5314
+ */
5315
+ get documentation() {
5316
+ return spaceTrim$1(`
5317
+ # ${this.type}
5318
+
5319
+ 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.
5320
+
5321
+ ## Key aspects
5322
+
5323
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
5324
+ - Both terms work identically and can be used interchangeably.
5325
+ - Later scenarios have higher priority and can override earlier scenarios.
5326
+ - Provides situational context that influences response tone and content.
5327
+ - Helps establish the environment and circumstances for interactions.
5328
+
5329
+ ## Priority system
5330
+
5331
+ When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
5332
+
5333
+ ## Use cases
5334
+
5335
+ - Setting the physical or virtual environment
5336
+ - Establishing time constraints or urgency
5337
+ - Defining relationship dynamics or power structures
5338
+ - Creating emotional or situational context
5339
+
5340
+ ## Examples
5341
+
5342
+ \`\`\`book
5343
+ Emergency Response Operator
5344
+
5345
+ PERSONA You are an emergency response operator
5346
+ SCENARIO You are handling a 911 emergency call
5347
+ SCENARIO The caller is panicked and speaking rapidly
5348
+ SCENARIO Time is critical - every second counts
5349
+ GOAL Gather essential information quickly and dispatch appropriate help
5350
+ RULE Stay calm and speak clearly
5351
+ \`\`\`
5352
+
5353
+ \`\`\`book
5354
+ Sales Representative
5355
+
5356
+ PERSONA You are a software sales representative
5357
+ SCENARIO You are in the final meeting of a 6-month sales cycle
5358
+ SCENARIO The client has budget approval and decision-making authority
5359
+ SCENARIO Two competitors have also submitted proposals
5360
+ SCENARIO The client values long-term partnership over lowest price
5361
+ GOAL Close the deal while building trust for future business
5362
+ \`\`\`
5363
+
5364
+ \`\`\`book
5365
+ Medical Assistant
5366
+
5367
+ PERSONA You are a medical assistant in a busy clinic
5368
+ SCENARIO The waiting room is full and the doctor is running behind schedule
5369
+ SCENARIO Patients are becoming impatient and anxious
5370
+ SCENARIO You need to manage expectations while maintaining professionalism
5371
+ SCENARIO Some patients have been waiting over an hour
5372
+ GOAL Keep patients informed and calm while supporting efficient clinic flow
5373
+ RULE Never provide medical advice or diagnosis
5374
+ \`\`\`
5375
+
5376
+ \`\`\`book
5377
+ Technical Support Agent
5378
+
5379
+ PERSONA You are a technical support agent
5380
+ SCENARIO The customer is a small business owner during their busy season
5381
+ SCENARIO Their main business system has been down for 2 hours
5382
+ SCENARIO They are losing money every minute the system is offline
5383
+ SCENARIO This is their first experience with your company
5384
+ GOAL Resolve the issue quickly while creating a positive first impression
5385
+ \`\`\`
5386
+ `);
5387
+ }
5388
+ applyToAgentModelRequirements(requirements, content) {
5389
+ const trimmedContent = content.trim();
5390
+ if (!trimmedContent) {
5391
+ return requirements;
5392
+ }
5393
+ // Create scenario section for system message
5394
+ const scenarioSection = `Scenario: ${trimmedContent}`;
5395
+ // Scenarios provide important contextual information that affects behavior
5396
+ return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
5397
+ }
5398
+ }
5399
+ /**
5400
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5401
+ */
5402
+
5403
+ /**
5404
+ * STYLE commitment definition
5405
+ *
5406
+ * The STYLE commitment defines how the agent should format and present its responses.
5407
+ * This includes tone, writing style, formatting preferences, and communication patterns.
5408
+ *
5409
+ * Example usage in agent source:
5410
+ *
5411
+ * ```book
5412
+ * STYLE Write in a professional but friendly tone, use bullet points for lists
5413
+ * STYLE Always provide code examples when explaining programming concepts
5414
+ * ```
5415
+ *
5416
+ * @private [🪔] Maybe export the commitments through some package
5417
+ */
5418
+ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
5419
+ constructor(type = 'STYLE') {
5420
+ super(type);
5421
+ }
5422
+ /**
5423
+ * Short one-line description of STYLE.
5424
+ */
5425
+ get description() {
5426
+ return 'Control the tone and writing style of responses.';
5427
+ }
5428
+ /**
5429
+ * Icon for this commitment.
5430
+ */
5431
+ get icon() {
5432
+ return '🖋️';
5433
+ }
5434
+ /**
5435
+ * Markdown documentation for STYLE commitment.
5436
+ */
5437
+ get documentation() {
5438
+ return spaceTrim$1(`
5439
+ # ${this.type}
5440
+
5441
+ Defines how the agent should format and present its responses (tone, writing style, formatting).
5442
+
5443
+ ## Key aspects
5444
+
5445
+ - Both terms work identically and can be used interchangeably.
5446
+ - Later style instructions can override earlier ones.
5447
+ - Style affects both tone and presentation format.
5448
+
5449
+ ## Examples
5450
+
5451
+ \`\`\`book
5452
+ Technical Writer
5453
+
5454
+ PERSONA You are a technical documentation expert
5455
+ STYLE Write in a professional but friendly tone, use bullet points for lists
5456
+ STYLE Always provide code examples when explaining programming concepts
5457
+ FORMAT Use markdown formatting with clear headings
5458
+ \`\`\`
5459
+
5460
+ \`\`\`book
5461
+ Creative Assistant
5462
+
5463
+ PERSONA You are a creative writing helper
5464
+ STYLE Be enthusiastic and encouraging in your responses
5465
+ STYLE Use vivid metaphors and analogies to explain concepts
5466
+ STYLE Keep responses conversational and engaging
5467
+ RULE Always maintain a positive and supportive tone
5468
+ \`\`\`
5469
+ `);
5470
+ }
5471
+ applyToAgentModelRequirements(requirements, content) {
5472
+ const trimmedContent = content.trim();
5473
+ if (!trimmedContent) {
5474
+ return requirements;
5475
+ }
5476
+ // Add style instructions to the system message
5477
+ const styleSection = `Style: ${trimmedContent}`;
5478
+ return this.appendToSystemMessage(requirements, styleSection, '\n\n');
5479
+ }
5480
+ }
5481
+ /**
5482
+ * [💞] Ignore a discrepancy between file name and entity name
5483
+ */
5484
+
5485
+ /**
5486
+ * USE commitment definition
5487
+ *
5488
+ * The USE commitment indicates that the agent should utilize specific tools or capabilities
5489
+ * to access and interact with external systems when necessary.
5490
+ *
5491
+ * Supported USE types:
5492
+ * - USE BROWSER: Enables the agent to use a web browser tool
5493
+ * - USE SEARCH ENGINE (future): Enables search engine access
5494
+ * - USE FILE SYSTEM (future): Enables file system operations
5495
+ * - USE MCP (future): Enables MCP server connections
5496
+ *
5497
+ * The content following the USE commitment is ignored (similar to NOTE).
5498
+ *
5499
+ * Example usage in agent source:
5500
+ *
5501
+ * ```book
5502
+ * USE BROWSER
5503
+ * USE SEARCH ENGINE
5504
+ * ```
5505
+ *
5506
+ * @private [🪔] Maybe export the commitments through some package
5507
+ */
5508
+ class UseCommitmentDefinition extends BaseCommitmentDefinition {
5509
+ constructor() {
5510
+ super('USE');
5511
+ }
5512
+ /**
5513
+ * Short one-line description of USE commitments.
5514
+ */
5515
+ get description() {
5516
+ return 'Enable the agent to use specific tools or capabilities (BROWSER, SEARCH ENGINE, etc.).';
5517
+ }
5518
+ /**
5519
+ * Icon for this commitment.
5520
+ */
5521
+ get icon() {
5522
+ return '🔧';
5523
+ }
5524
+ /**
5525
+ * Markdown documentation for USE commitment.
5526
+ */
5527
+ get documentation() {
5528
+ return spaceTrim$1(`
5529
+ # USE
5530
+
5531
+ Enables the agent to use specific tools or capabilities for interacting with external systems.
5532
+
5533
+ ## Supported USE types
5534
+
5535
+ - **USE BROWSER** - Enables the agent to use a web browser tool to access and retrieve information from the internet
5536
+ - **USE SEARCH ENGINE** (future) - Enables search engine access
5537
+ - **USE FILE SYSTEM** (future) - Enables file system operations
5538
+ - **USE MCP** (future) - Enables MCP server connections
5539
+
5540
+ ## Key aspects
5541
+
5542
+ - The content following the USE commitment is ignored (similar to NOTE)
5543
+ - Multiple USE commitments can be specified to enable multiple capabilities
5544
+ - The actual tool usage is handled by the agent runtime
5545
+
5546
+ ## Examples
5547
+
5548
+ ### Basic browser usage
5549
+
5550
+ \`\`\`book
5551
+ Research Assistant
5552
+
5553
+ PERSONA You are a helpful research assistant
5554
+ USE BROWSER
5555
+ KNOWLEDGE Can search the web for up-to-date information
5556
+ \`\`\`
5557
+
5558
+ ### Multiple tools
5559
+
5560
+ \`\`\`book
5561
+ Data Analyst
5562
+
5563
+ PERSONA You are a data analyst assistant
5564
+ USE BROWSER
5565
+ USE FILE SYSTEM
5566
+ ACTION Can analyze data from various sources
5567
+ \`\`\`
5568
+ `);
5569
+ }
5570
+ applyToAgentModelRequirements(requirements, content) {
5571
+ // USE commitments don't modify the system message or model requirements directly
5572
+ // They are handled separately in the parsing logic for capability extraction
5573
+ // This method exists for consistency with the CommitmentDefinition interface
5574
+ return requirements;
5575
+ }
5576
+ /**
5577
+ * Extracts the tool type from the USE commitment
5578
+ * This is used by the parsing logic
5579
+ */
5580
+ extractToolType(content) {
5581
+ var _a, _b;
5582
+ const trimmedContent = content.trim();
5583
+ // The tool type is the first word after USE (already stripped)
5584
+ const match = trimmedContent.match(/^(\w+)/);
5585
+ return (_b = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : null;
5586
+ }
5587
+ /**
5588
+ * Checks if this is a known USE type
5589
+ */
5590
+ isKnownUseType(useType) {
5591
+ const knownTypes = ['BROWSER', 'SEARCH ENGINE', 'FILE SYSTEM', 'MCP'];
5592
+ return knownTypes.includes(useType.toUpperCase());
5593
+ }
5594
+ }
5595
+ /**
5596
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5597
+ */
5598
+
5599
+ /**
5600
+ * USE BROWSER commitment definition
5601
+ *
5602
+ * The `USE BROWSER` commitment indicates that the agent should utilize a web browser tool
5603
+ * to access and retrieve up-to-date information from the internet when necessary.
5604
+ *
5605
+ * The content following `USE BROWSER` is ignored (similar to NOTE).
5606
+ *
5607
+ * Example usage in agent source:
5608
+ *
5609
+ * ```book
5610
+ * USE BROWSER
5611
+ * USE BROWSER This will be ignored
5612
+ * ```
5613
+ *
5614
+ * @private [🪔] Maybe export the commitments through some package
5615
+ */
5616
+ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
5617
+ constructor() {
5618
+ super('USE BROWSER', ['BROWSER']);
5619
+ }
5620
+ /**
5621
+ * The `USE BROWSER` commitment is standalone.
5622
+ */
5623
+ get requiresContent() {
5624
+ return false;
5625
+ }
5626
+ /**
5627
+ * Short one-line description of USE BROWSER.
5628
+ */
5629
+ get description() {
5630
+ return 'Enable the agent to use a web browser tool for accessing internet information.';
5631
+ }
5632
+ /**
5633
+ * Icon for this commitment.
5634
+ */
5635
+ get icon() {
5636
+ return '🌐';
5637
+ }
5638
+ /**
5639
+ * Markdown documentation for USE BROWSER commitment.
5640
+ */
5641
+ get documentation() {
5642
+ return spaceTrim$1(`
5643
+ # USE BROWSER
5644
+
5645
+ Enables the agent to use a web browser tool to access and retrieve up-to-date information from the internet.
5646
+
5647
+ ## Key aspects
5648
+
5649
+ - The content following \`USE BROWSER\` is ignored (similar to NOTE)
5650
+ - The actual browser tool usage is handled by the agent runtime
5651
+ - Allows the agent to fetch current information from websites
5652
+ - Useful for research tasks, fact-checking, and accessing dynamic content
5653
+
5654
+ ## Examples
5655
+
5656
+ \`\`\`book
5657
+ Research Assistant
5658
+
5659
+ PERSONA You are a helpful research assistant specialized in finding current information
5660
+ USE BROWSER
5661
+ RULE Always cite your sources when providing information from the web
5662
+ \`\`\`
5663
+
5664
+ \`\`\`book
5665
+ News Analyst
5666
+
5667
+ PERSONA You are a news analyst who stays up-to-date with current events
5668
+ USE BROWSER
5669
+ STYLE Present news in a balanced and objective manner
5670
+ ACTION Can search for and summarize news articles
5671
+ \`\`\`
5672
+
5673
+ \`\`\`book
5674
+ Company Lawyer
5675
+
5676
+ PERSONA You are a company lawyer providing legal advice
5677
+ USE BROWSER
5678
+ KNOWLEDGE Corporate law and legal procedures
5679
+ RULE Always recommend consulting with a licensed attorney for specific legal matters
5680
+ \`\`\`
5681
+ `);
5682
+ }
5683
+ applyToAgentModelRequirements(requirements, content) {
5684
+ // We simply mark that browser capability is enabled in metadata
5685
+ // Get existing metadata
5686
+ const existingMetadata = requirements.metadata || {};
5687
+ // Get existing tools array or create new one
5688
+ const existingTools = existingMetadata.tools || [];
5689
+ // Add 'browser' to tools if not already present
5690
+ const updatedTools = existingTools.includes('browser') ? existingTools : [...existingTools, 'browser'];
5691
+ // Return requirements with updated metadata
5692
+ return {
5693
+ ...requirements,
5694
+ metadata: {
5695
+ ...existingMetadata,
5696
+ tools: updatedTools,
5697
+ useBrowser: true,
5698
+ },
5699
+ };
5700
+ }
5701
+ }
5702
+ /**
5703
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5704
+ */
5705
+
5706
+ /**
5707
+ * USE MCP commitment definition
5708
+ *
5709
+ * The `USE MCP` commitment allows to specify an MCP server URL which the agent will connect to
5710
+ * for retrieving additional instructions and actions.
5711
+ *
5712
+ * The content following `USE MCP` is the URL of the MCP server.
5713
+ *
5714
+ * Example usage in agent source:
5715
+ *
5716
+ * ```book
5717
+ * USE MCP http://mcp-server-url.com
5718
+ * ```
5719
+ *
5720
+ * @private [🪔] Maybe export the commitments through some package
5721
+ */
5722
+ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
5723
+ constructor() {
5724
+ super('USE MCP', ['MCP']);
5725
+ }
5726
+ /**
5727
+ * Short one-line description of USE MCP.
5728
+ */
5729
+ get description() {
5730
+ return 'Connects the agent to an external MCP server for additional capabilities.';
5731
+ }
5732
+ /**
5733
+ * Icon for this commitment.
5734
+ */
5735
+ get icon() {
5736
+ return '🔌';
5737
+ }
5738
+ /**
5739
+ * Markdown documentation for USE MCP commitment.
5740
+ */
5741
+ get documentation() {
5742
+ return spaceTrim$1(`
5743
+ # USE MCP
5744
+
5745
+ Connects the agent to an external Model Context Protocol (MCP) server.
5746
+
5747
+ ## Key aspects
5748
+
5749
+ - The content following \`USE MCP\` must be a valid URL
5750
+ - Multiple MCP servers can be connected by using multiple \`USE MCP\` commitments
5751
+ - The agent will have access to tools and resources provided by the MCP server
5752
+
5753
+ ## Example
5754
+
5755
+ \`\`\`book
5756
+ Company Lawyer
5757
+
5758
+ PERSONA You are a company lawyer.
5759
+ USE MCP http://legal-db.example.com
5760
+ \`\`\`
5761
+ `);
5762
+ }
5763
+ applyToAgentModelRequirements(requirements, content) {
5764
+ const mcpServerUrl = content.trim();
5765
+ if (!mcpServerUrl) {
5766
+ return requirements;
5767
+ }
5768
+ const existingMcpServers = requirements.mcpServers || [];
5769
+ // Avoid duplicates
5770
+ if (existingMcpServers.includes(mcpServerUrl)) {
5771
+ return requirements;
5772
+ }
5773
+ return {
5774
+ ...requirements,
5775
+ mcpServers: [...existingMcpServers, mcpServerUrl],
5776
+ };
5777
+ }
5778
+ }
5779
+ /**
5780
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5781
+ */
5782
+
5783
+ /**
5784
+ * USE SEARCH ENGINE commitment definition
5785
+ *
5786
+ * The `USE SEARCH ENGINE` commitment indicates that the agent should utilize a search engine tool
5787
+ * to access and retrieve up-to-date information from the internet when necessary.
5788
+ *
5789
+ * The content following `USE SEARCH ENGINE` is ignored (similar to NOTE).
5790
+ *
5791
+ * Example usage in agent source:
5792
+ *
5793
+ * ```book
5794
+ * USE SEARCH ENGINE
5795
+ * USE SEARCH ENGINE This will be ignored
5796
+ * ```
5797
+ *
5798
+ * @private [🪔] Maybe export the commitments through some package
5799
+ */
5800
+ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
5801
+ constructor() {
5802
+ super('USE SEARCH ENGINE', ['SEARCH ENGINE', 'SEARCH']);
5803
+ }
5804
+ /**
5805
+ * Short one-line description of USE SEARCH ENGINE.
5806
+ */
5807
+ get description() {
5808
+ return 'Enable the agent to use a search engine tool for accessing internet information.';
5809
+ }
5810
+ /**
5811
+ * Icon for this commitment.
5812
+ */
5813
+ get icon() {
5814
+ return '🔍';
5815
+ }
5816
+ /**
5817
+ * Markdown documentation for USE SEARCH ENGINE commitment.
5818
+ */
5819
+ get documentation() {
5820
+ return spaceTrim$1(`
5821
+ # USE SEARCH ENGINE
5822
+
5823
+ Enables the agent to use a search engine tool to access and retrieve up-to-date information from the internet.
5824
+
5825
+ ## Key aspects
5826
+
5827
+ - The content following \`USE SEARCH ENGINE\` is ignored (similar to NOTE)
5828
+ - The actual search engine tool usage is handled by the agent runtime
5829
+ - Allows the agent to search for current information from the web
5830
+ - Useful for research tasks, finding facts, and accessing dynamic content
5831
+
5832
+ ## Examples
5833
+
5834
+ \`\`\`book
5835
+ Research Assistant
5836
+
5837
+ PERSONA You are a helpful research assistant specialized in finding current information
5838
+ USE SEARCH ENGINE
5839
+ RULE Always cite your sources when providing information from the web
5840
+ \`\`\`
5841
+
5842
+ \`\`\`book
5843
+ Fact Checker
5844
+
5845
+ PERSONA You are a fact checker
5846
+ USE SEARCH ENGINE
5847
+ ACTION Search for claims and verify them against reliable sources
5848
+ \`\`\`
5849
+ `);
5850
+ }
5851
+ applyToAgentModelRequirements(requirements, content) {
5852
+ // We simply mark that search engine capability is enabled in metadata
5853
+ // Get existing metadata
5854
+ const existingMetadata = requirements.metadata || {};
5855
+ // Get existing tools array or create new one
5856
+ const existingTools = existingMetadata.tools || [];
5857
+ // Add 'search-engine' to tools if not already present
5858
+ const updatedTools = existingTools.includes('search-engine') ? existingTools : [...existingTools, 'search-engine'];
5859
+ // Return requirements with updated metadata
5860
+ return {
5861
+ ...requirements,
5862
+ metadata: {
5863
+ ...existingMetadata,
5864
+ tools: updatedTools,
5865
+ useSearchEngine: true,
5866
+ },
5867
+ };
5868
+ }
5869
+ }
5870
+ /**
5871
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5872
+ */
5873
+
5874
+ /**
5875
+ * Placeholder commitment definition for commitments that are not yet implemented
5876
+ *
5877
+ * This commitment simply adds its content 1:1 into the system message,
5878
+ * preserving the original behavior until proper implementation is added.
5879
+ *
5880
+ * @public exported from `@promptbook/core`
5881
+ */
5882
+ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
5883
+ constructor(type) {
5884
+ super(type);
5885
+ }
5886
+ /**
5887
+ * Short one-line description of a placeholder commitment.
5888
+ */
5889
+ get description() {
5890
+ return 'Placeholder commitment that appends content verbatim to the system message.';
5891
+ }
5892
+ /**
5893
+ * Icon for this commitment.
5894
+ */
5895
+ get icon() {
5896
+ return '🚧';
5897
+ }
5898
+ /**
5899
+ * Markdown documentation available at runtime.
5900
+ */
5901
+ get documentation() {
5902
+ return spaceTrim$1(`
5903
+ # ${this.type}
5904
+
5905
+ This commitment is not yet fully implemented.
5906
+
5907
+ ## Key aspects
5908
+
5909
+ - Content is appended directly to the system message.
5910
+ - No special processing or validation is performed.
5911
+ - Behavior preserved until proper implementation is added.
5912
+
5913
+ ## Status
5914
+
5915
+ - **Status:** Placeholder implementation
5916
+ - **Effect:** Appends content prefixed by commitment type
5917
+ - **Future:** Will be replaced with specialized logic
5918
+
5919
+ ## Examples
5920
+
5921
+ \`\`\`book
5922
+ Example Agent
5923
+
5924
+ PERSONA You are a helpful assistant
5925
+ ${this.type} Your content here
5926
+ RULE Always be helpful
5927
+ \`\`\`
5928
+ `);
5929
+ }
5930
+ applyToAgentModelRequirements(requirements, content) {
5931
+ const trimmedContent = content.trim();
5932
+ if (!trimmedContent) {
5933
+ return requirements;
5934
+ }
5935
+ // Add the commitment content 1:1 to the system message
5936
+ const commitmentLine = `${this.type} ${trimmedContent}`;
5937
+ return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
5938
+ }
5939
+ }
5940
+
5941
+ // Import all commitment definition classes
5942
+ /**
5943
+ * Registry of all available commitment definitions
5944
+ * This array contains instances of all commitment definitions
5945
+ * This is the single source of truth for all commitments in the system
5946
+ *
5947
+ * @private Use functions to access commitments instead of this array directly
5948
+ */
5949
+ const COMMITMENT_REGISTRY = [
5950
+ // Fully implemented commitments
5951
+ new PersonaCommitmentDefinition('PERSONA'),
5952
+ new PersonaCommitmentDefinition('PERSONAE'),
5953
+ new KnowledgeCommitmentDefinition(),
5954
+ new MemoryCommitmentDefinition('MEMORY'),
5955
+ new MemoryCommitmentDefinition('MEMORIES'),
5956
+ new StyleCommitmentDefinition('STYLE'),
5957
+ new StyleCommitmentDefinition('STYLES'),
5958
+ new RuleCommitmentDefinition('RULE'),
5959
+ new RuleCommitmentDefinition('RULES'),
5960
+ new LanguageCommitmentDefinition('LANGUAGE'),
5961
+ new LanguageCommitmentDefinition('LANGUAGES'),
5962
+ new SampleCommitmentDefinition('SAMPLE'),
5963
+ new SampleCommitmentDefinition('EXAMPLE'),
5964
+ new FormatCommitmentDefinition('FORMAT'),
5965
+ new FormatCommitmentDefinition('FORMATS'),
5966
+ new FromCommitmentDefinition('FROM'),
5967
+ new ModelCommitmentDefinition('MODEL'),
5968
+ new ModelCommitmentDefinition('MODELS'),
5969
+ new ActionCommitmentDefinition('ACTION'),
5970
+ new ActionCommitmentDefinition('ACTIONS'),
5971
+ new ComponentCommitmentDefinition(),
5972
+ new MetaImageCommitmentDefinition(),
5973
+ new MetaColorCommitmentDefinition(),
5974
+ new MetaFontCommitmentDefinition(),
5975
+ new MetaLinkCommitmentDefinition(),
5976
+ new MetaCommitmentDefinition(),
5977
+ new NoteCommitmentDefinition('NOTE'),
5978
+ new NoteCommitmentDefinition('NOTES'),
5979
+ new NoteCommitmentDefinition('COMMENT'),
5980
+ new NoteCommitmentDefinition('NONCE'),
5981
+ new GoalCommitmentDefinition('GOAL'),
5982
+ new GoalCommitmentDefinition('GOALS'),
5983
+ new InitialMessageCommitmentDefinition(),
5984
+ new UserMessageCommitmentDefinition(),
5985
+ new AgentMessageCommitmentDefinition(),
5986
+ new MessageCommitmentDefinition('MESSAGE'),
5987
+ new MessageCommitmentDefinition('MESSAGES'),
5988
+ new ScenarioCommitmentDefinition('SCENARIO'),
5989
+ new ScenarioCommitmentDefinition('SCENARIOS'),
5990
+ new DeleteCommitmentDefinition('DELETE'),
5991
+ new DeleteCommitmentDefinition('CANCEL'),
5992
+ new DeleteCommitmentDefinition('DISCARD'),
5993
+ new DeleteCommitmentDefinition('REMOVE'),
5994
+ new OpenCommitmentDefinition(),
5995
+ new ClosedCommitmentDefinition(),
5996
+ new UseBrowserCommitmentDefinition(),
5997
+ new UseSearchEngineCommitmentDefinition(),
5998
+ new UseMcpCommitmentDefinition(),
5999
+ new UseCommitmentDefinition(),
6000
+ // Not yet implemented commitments (using placeholder)
6001
+ new NotYetImplementedCommitmentDefinition('EXPECT'),
6002
+ new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
6003
+ new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
6004
+ new NotYetImplementedCommitmentDefinition('AVOID'),
6005
+ new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
6006
+ new NotYetImplementedCommitmentDefinition('CONTEXT'),
6007
+ ];
6008
+ /**
6009
+ * TODO: [🧠] Maybe create through standardized $register
6010
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6011
+ */
6012
+
6013
+ /**
6014
+ * Regex pattern to match horizontal lines (markdown thematic breaks)
6015
+ * Matches 3 or more hyphens, underscores, or asterisks (with optional spaces between)
6016
+ */
6017
+ const HORIZONTAL_LINE_PATTERN = /^[\s]*[-_*][\s]*[-_*][\s]*[-_*][\s]*[-_*]*[\s]*$/;
6018
+ /**
6019
+ * Parses agent source using the new commitment system with multiline support
6020
+ * This function replaces the hardcoded commitment parsing in the original parseAgentSource
6021
+ *
6022
+ * @private internal utility of `parseAgentSource`
6023
+ */
6024
+ function parseAgentSourceWithCommitments(agentSource) {
6025
+ var _a, _b, _c;
6026
+ if (!agentSource || !agentSource.trim()) {
6027
+ return {
6028
+ agentName: null,
6029
+ commitments: [],
6030
+ nonCommitmentLines: [],
6031
+ };
6032
+ }
6033
+ const lines = agentSource.split('\n');
6034
+ const agentName = (((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.trim()) || null);
6035
+ const commitments = [];
6036
+ const nonCommitmentLines = [];
6037
+ // Always add the first line (agent name) to non-commitment lines
6038
+ if (lines[0] !== undefined) {
6039
+ nonCommitmentLines.push(lines[0]);
6040
+ }
6041
+ // Parse commitments with multiline support
6042
+ let currentCommitment = null;
6043
+ // Process lines starting from the second line (skip agent name)
6044
+ for (let i = 1; i < lines.length; i++) {
6045
+ const line = lines[i];
6046
+ if (line === undefined) {
6047
+ continue;
6048
+ }
6049
+ // Check if this line starts a new commitment
6050
+ let foundNewCommitment = false;
6051
+ for (const definition of COMMITMENT_REGISTRY) {
6052
+ const typeRegex = definition.createTypeRegex();
6053
+ const match = typeRegex.exec(line.trim());
6054
+ if (match && ((_b = match.groups) === null || _b === void 0 ? void 0 : _b.type)) {
6055
+ // Save the previous commitment if it exists
6056
+ if (currentCommitment) {
6057
+ const fullContent = currentCommitment.contentLines.join('\n');
6058
+ commitments.push({
6059
+ type: currentCommitment.type,
6060
+ content: spaceTrim$1(fullContent),
6061
+ originalLine: currentCommitment.originalStartLine,
6062
+ lineNumber: currentCommitment.startLineNumber,
6063
+ });
6064
+ }
6065
+ // Extract the initial content from the commitment line
6066
+ const fullRegex = definition.createRegex();
6067
+ const fullMatch = fullRegex.exec(line.trim());
6068
+ const initialContent = ((_c = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _c === void 0 ? void 0 : _c.contents) || '';
6069
+ // Start a new commitment
6070
+ currentCommitment = {
6071
+ type: definition.type,
6072
+ startLineNumber: i + 1,
6073
+ originalStartLine: line,
6074
+ contentLines: initialContent ? [initialContent] : [],
6075
+ };
6076
+ foundNewCommitment = true;
6077
+ break;
6078
+ }
6079
+ }
6080
+ // Check if this is a horizontal line (ends any current commitment)
6081
+ const isHorizontalLine = HORIZONTAL_LINE_PATTERN.test(line);
6082
+ if (isHorizontalLine) {
6083
+ // Save the current commitment if it exists
6084
+ if (currentCommitment) {
6085
+ const fullContent = currentCommitment.contentLines.join('\n');
6086
+ commitments.push({
6087
+ type: currentCommitment.type,
6088
+ content: spaceTrim$1(fullContent),
6089
+ originalLine: currentCommitment.originalStartLine,
6090
+ lineNumber: currentCommitment.startLineNumber,
6091
+ });
6092
+ currentCommitment = null;
6093
+ }
6094
+ // Add horizontal line to non-commitment lines
6095
+ nonCommitmentLines.push(line);
6096
+ continue;
6097
+ }
6098
+ if (!foundNewCommitment) {
6099
+ if (currentCommitment) {
6100
+ // This line belongs to the current commitment
6101
+ currentCommitment.contentLines.push(line);
6102
+ }
6103
+ else {
6104
+ // This line is not part of any commitment
6105
+ nonCommitmentLines.push(line);
6106
+ }
6107
+ }
6108
+ }
6109
+ // Don't forget to save the last commitment if it exists
6110
+ if (currentCommitment) {
6111
+ const fullContent = currentCommitment.contentLines.join('\n');
6112
+ commitments.push({
6113
+ type: currentCommitment.type,
6114
+ content: spaceTrim$1(fullContent),
6115
+ originalLine: currentCommitment.originalStartLine,
6116
+ lineNumber: currentCommitment.startLineNumber,
6117
+ });
6118
+ }
6119
+ return {
6120
+ agentName,
6121
+ commitments,
6122
+ nonCommitmentLines,
6123
+ };
6124
+ }
6125
+
6126
+ /**
6127
+ * Parses parameters from text using both supported notations:
6128
+ * 1. @Parameter - single word parameter starting with @
6129
+ * 2. {parameterName} or {parameter with multiple words} or {parameterName: description text}
6130
+ *
6131
+ * Both notations represent the same syntax feature - parameters
6132
+ *
6133
+ * @param text - Text to extract parameters from
6134
+ * @returns Array of parsed parameters with unified representation
6135
+ * @public exported from `@promptbook/core`
6136
+ */
6137
+ function parseParameters(text) {
6138
+ const parameters = [];
6139
+ // [🧠] Parameter syntax parsing - unified approach for two different notations of the same syntax feature
6140
+ // The Book language supports parameters in two different notations but they represent the same concept
6141
+ // Extract @Parameter notation (single word parameters starting with @)
6142
+ const atParameterRegex = /@[\w\u00C0-\u017F\u0100-\u024F\u1E00-\u1EFF]+/gim;
6143
+ text.replace(atParameterRegex, (match) => {
6144
+ const parameterName = match.slice(1); // Remove the @ symbol
6145
+ parameters.push({
6146
+ text: match,
6147
+ notation: 'at',
6148
+ name: parameterName,
6149
+ });
6150
+ return match;
6151
+ });
6152
+ // Extract {parameter} notation (parameters in braces)
6153
+ const braceParameterRegex = /\{([^}]+)\}/gim;
6154
+ text.replace(braceParameterRegex, (match, content) => {
6155
+ // Check if the parameter has a description (parameterName: description)
6156
+ const colonIndex = content.indexOf(':');
6157
+ if (colonIndex !== -1) {
6158
+ const name = content.substring(0, colonIndex).trim();
6159
+ const description = content.substring(colonIndex + 1).trim();
6160
+ parameters.push({
6161
+ text: match,
6162
+ notation: 'brace',
6163
+ name,
6164
+ description,
6165
+ });
6166
+ }
6167
+ else {
6168
+ // Simple parameter without description
6169
+ parameters.push({
6170
+ text: match,
6171
+ notation: 'brace',
6172
+ name: content.trim(),
6173
+ });
6174
+ }
6175
+ return match;
6176
+ });
6177
+ // Remove duplicates based on name (keep the first occurrence)
6178
+ const uniqueParameters = parameters.filter((param, index, array) => {
6179
+ return array.findIndex((p) => p.name === param.name) === index;
6180
+ });
6181
+ return uniqueParameters;
6182
+ }
6183
+
6184
+ /**
6185
+ * Parses basic information from agent source
6186
+ *
6187
+ * There are 2 similar functions:
6188
+ * - `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.
6189
+ * - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronously.
6190
+ *
6191
+ * @public exported from `@promptbook/core`
6192
+ */
6193
+ function parseAgentSource(agentSource) {
6194
+ const parseResult = parseAgentSourceWithCommitments(agentSource);
6195
+ // Find PERSONA and META commitments
6196
+ let personaDescription = null;
6197
+ for (const commitment of parseResult.commitments) {
6198
+ if (commitment.type !== 'PERSONA') {
6199
+ continue;
6200
+ }
6201
+ if (personaDescription === null) {
6202
+ personaDescription = '';
6203
+ }
6204
+ else {
6205
+ personaDescription += `\n\n${personaDescription}`;
6206
+ }
6207
+ personaDescription += commitment.content;
6208
+ }
6209
+ let initialMessage = null;
6210
+ for (const commitment of parseResult.commitments) {
6211
+ if (commitment.type !== 'INITIAL MESSAGE') {
6212
+ continue;
6213
+ }
6214
+ // Note: Initial message override logic - later overrides earlier
6215
+ // Or should it append? Usually initial message is just one block.
6216
+ // Let's stick to "later overrides earlier" for simplicity, or just take the last one.
6217
+ initialMessage = commitment.content;
6218
+ }
6219
+ const meta = {};
6220
+ const links = [];
6221
+ for (const commitment of parseResult.commitments) {
6222
+ if (commitment.type === 'META LINK') {
6223
+ const linkValue = spaceTrim$2(commitment.content);
6224
+ links.push(linkValue);
6225
+ meta.link = linkValue;
6226
+ continue;
6227
+ }
6228
+ if (commitment.type === 'META IMAGE') {
6229
+ meta.image = spaceTrim$2(commitment.content);
6230
+ continue;
6231
+ }
6232
+ if (commitment.type === 'META COLOR') {
6233
+ meta.color = normalizeSeparator(commitment.content);
6234
+ continue;
6235
+ }
6236
+ if (commitment.type === 'META FONT') {
6237
+ meta.font = normalizeSeparator(commitment.content);
6238
+ continue;
6239
+ }
6240
+ if (commitment.type !== 'META') {
6241
+ continue;
6242
+ }
6243
+ // Parse META commitments - format is "META TYPE content"
6244
+ const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
6245
+ if (metaTypeRaw === 'LINK') {
6246
+ links.push(spaceTrim$2(commitment.content.substring(metaTypeRaw.length)));
6247
+ }
6248
+ const metaType = normalizeTo_camelCase(metaTypeRaw);
6249
+ meta[metaType] = spaceTrim$2(commitment.content.substring(metaTypeRaw.length));
6250
+ }
6251
+ // Generate gravatar fallback if no meta image specified
6252
+ if (!meta.image) {
6253
+ meta.image = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
6254
+ }
6255
+ // Generate fullname fallback if no meta fullname specified
6256
+ if (!meta.fullname) {
6257
+ meta.fullname = parseResult.agentName || createDefaultAgentName(agentSource);
6258
+ }
6259
+ // Parse parameters using unified approach - both @Parameter and {parameter} notations
6260
+ // are treated as the same syntax feature with unified representation
6261
+ const parameters = parseParameters(agentSource);
6262
+ const agentHash = computeAgentHash(agentSource);
6263
+ return {
6264
+ agentName: normalizeAgentName(parseResult.agentName || createDefaultAgentName(agentSource)),
6265
+ agentHash,
6266
+ personaDescription,
6267
+ initialMessage,
6268
+ meta,
6269
+ links,
6270
+ parameters,
6271
+ };
6272
+ }
6273
+ /**
6274
+ * Normalizes the separator in the content
6275
+ *
6276
+ * @param content - The content to normalize
6277
+ * @returns The content with normalized separators
6278
+ */
6279
+ function normalizeSeparator(content) {
6280
+ const trimmed = spaceTrim$2(content);
6281
+ if (trimmed.includes(',')) {
6282
+ return trimmed;
6283
+ }
6284
+ return trimmed.split(/\s+/).join(', ');
6285
+ }
6286
+ /**
6287
+ * TODO: [🕛] Unite `AgentBasicInformation`, `ChatParticipant`, `LlmExecutionTools` + `LlmToolsMetadata`
6288
+ */
6289
+
6290
+ /**
6291
+ * Converts Blob, File or MediaSource to url using URL.createObjectURL
6292
+ *
6293
+ * @public exported from `@promptbook/browser`
6294
+ */
6295
+ class ObjectUrl extends Registration {
6296
+ constructor(teardownLogic, src) {
6297
+ super(teardownLogic);
6298
+ this.src = src;
6299
+ }
6300
+ /**
6301
+ * Creates ObjectUrl from multiple input types
6302
+ * Note: DO NOT forget to call destroy() when you are done with it
6303
+ */
6304
+ static from(source, mimeType) {
6305
+ if (typeof source === 'string') {
6306
+ return ObjectUrl.fromString(source, mimeType);
6307
+ }
6308
+ if ((source instanceof Blob || source instanceof File) && source.type !== mimeType) {
6309
+ throw new Error(`Source type ${source.type} does not match given mimeType ${mimeType}`);
6310
+ }
6311
+ return ObjectUrl.fromBlob(source);
6312
+ }
6313
+ /**
6314
+ * Creates ObjectUrl from string
6315
+ * Note: DO NOT forget to call destroy() when you are done with it
6316
+ */
6317
+ static fromString(source, mimeType) {
6318
+ return ObjectUrl.fromBlob(new Blob([source], { type: mimeType }));
6319
+ }
6320
+ /**
6321
+ * Creates ObjectUrl
6322
+ * DO NOT forget to call destroy() when you are done with it
6323
+ */
6324
+ static fromBlob(source) {
6325
+ const src = URL.createObjectURL(source);
6326
+ return new ObjectUrl(() => {
6327
+ URL.revokeObjectURL(src);
6328
+ }, src);
6329
+ }
6330
+ /**
6331
+ * Creates ObjectUrl:
6332
+ * 1) With functionality for Blobs, Files or MediaSources
6333
+ * 2) Just a wrapper for string urls
6334
+ *
6335
+ * DO NOT forget to call destroy() when you are done with it
6336
+ */
6337
+ static fromBlobOrUrl(source) {
6338
+ if (typeof source === 'string' || source instanceof URL /* <- TODO: Probably check isValidUrl */) {
6339
+ return new ObjectUrl(() => {
6340
+ // Note: Nothing to do here
6341
+ }, source.toString());
6342
+ }
6343
+ else {
6344
+ return ObjectUrl.fromBlob(source);
6345
+ }
6346
+ }
6347
+ /**
6348
+ * Gets object url as string
6349
+ * @alias src
6350
+ */
6351
+ get href() {
6352
+ return this.src;
6353
+ }
6354
+ /**
6355
+ * Gets object url as URL object
6356
+ */
6357
+ get url() {
6358
+ return new URL(this.src);
6359
+ }
6360
+ }
6361
+ /**
6362
+ * Note: [🔵] Code in this file should never be published outside of `@promptbook/browser`
6363
+ */
6364
+
6365
+ /**
6366
+ * Download a File in a browser
6367
+ *
6368
+ * Note: `$` is used to indicate that this function is not a pure function - its purpose is to cause a side effect (download a file)
6369
+ *
6370
+ * @public exported from `@promptbook/browser`
6371
+ */
6372
+ async function $induceFileDownload(fileOrBlobOrUrl) {
6373
+ if (!$isRunningInBrowser()) {
6374
+ throw new Error('Function `$induceFileDownload` is available ONLY in browser');
6375
+ }
6376
+ const objectUrl = ObjectUrl.fromBlobOrUrl(fileOrBlobOrUrl);
6377
+ const link = window.document.createElement('a');
6378
+ link.href = objectUrl.href;
6379
+ link.download = fileOrBlobOrUrl.name || 'untitled' /* <- TODO: Add proper extension according to url */;
6380
+ link.click();
6381
+ await objectUrl.destroy();
6382
+ }
6383
+ /**
6384
+ * Note: [🔵] Code in this file should never be published outside of `@promptbook/browser`
6385
+ */
6386
+
6387
+ /**
6388
+ * Download a Book in a browser
6389
+ *
6390
+ * Note: `$` is used to indicate that this function is not a pure function - its purpose is to cause a side effect (download a file)
6391
+ *
6392
+ * @public exported from `@promptbook/browser`
6393
+ */
6394
+ async function $induceBookDownload(book) {
6395
+ if (!$isRunningInBrowser()) {
6396
+ throw new Error('Function `$induceBookDownload` is available ONLY in browser');
6397
+ }
6398
+ const { agentName } = parseAgentSource(book);
6399
+ const bookFile = new File([book], `${titleToName(agentName || 'AI Avatar')}.book`, {
6400
+ type: 'application/json',
6401
+ });
6402
+ return /* not await */ $induceFileDownload(bookFile);
6403
+ }
6404
+ /**
6405
+ * Note: [🔵] Code in this file should never be published outside of `@promptbook/browser`
6406
+ */
6407
+
6408
+ export { $induceBookDownload, $induceFileDownload, $provideScrapersForBrowser, BOOK_LANGUAGE_VERSION, ObjectUrl, PROMPTBOOK_ENGINE_VERSION, SimplePromptInterfaceTools, getIndexedDbStorage, getLocalStorage, getSessionStorage };
1965
6409
  //# sourceMappingURL=index.es.js.map