@promptbook/browser 0.103.0-10 → 0.103.0-100

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