@promptbook/wizard 0.113.0-8 → 0.114.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +4 -3
  2. package/esm/index.es.js +1196 -1084
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/src/_packages/components.index.d.ts +8 -0
  5. package/esm/src/_packages/core.index.d.ts +4 -0
  6. package/esm/src/_packages/types.index.d.ts +14 -2
  7. package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +24 -1
  8. package/esm/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
  9. package/esm/src/book-2.0/agent-source/AgentBasicInformation.d.ts +7 -0
  10. package/esm/src/book-2.0/agent-source/parseAgentSource/ParsedAgentProfile.d.ts +1 -1
  11. package/esm/src/book-2.0/book-language-documentation/BookLanguageDocumentationExample.d.ts +5 -13
  12. package/esm/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.d.ts +195 -0
  13. package/esm/src/book-2.0/book-language-documentation/bookLanguageDocumentationExamples.d.ts +2 -1
  14. package/esm/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.d.ts +43 -1
  15. package/esm/src/book-2.0/book-language-documentation/czechBookLanguageManualDictionary.d.ts +10 -0
  16. package/esm/src/book-2.0/book-language-documentation/englishBookLanguageManualDictionary.d.ts +10 -0
  17. package/esm/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.d.ts +33 -0
  18. package/esm/src/book-2.0/book-language-documentation/getBookLanguageManualDictionary.d.ts +15 -0
  19. package/esm/src/book-2.0/book-language-documentation/getSafeCodeBlock.d.ts +10 -0
  20. package/esm/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.d.ts +30 -0
  21. package/esm/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.d.ts +2 -1
  22. package/esm/src/book-2.0/book-language-documentation/toStableAnchorId.d.ts +12 -0
  23. package/esm/src/book-3.0/AgentMessageRunReport.d.ts +78 -0
  24. package/esm/src/book-3.0/agentFolderPaths.d.ts +9 -0
  25. package/esm/src/book-3.0/codexLoginMethod.d.ts +38 -0
  26. package/esm/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
  27. package/esm/src/book-components/BookEditor/BookEditorSyntaxTokenStyles.d.ts +39 -0
  28. package/esm/src/book-components/BookEditor/createBookSourceHighlightStyles.d.ts +12 -0
  29. package/esm/src/book-components/BookEditor/highlightBookSourceToHtml.d.ts +20 -0
  30. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
  31. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
  32. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
  33. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
  34. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
  35. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
  36. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
  37. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
  38. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
  39. package/esm/src/book-components/Chat/Chat/ChatCitationModal.d.ts +5 -0
  40. package/esm/src/book-components/Chat/Chat/ChatCitationModal.test.d.ts +2 -0
  41. package/esm/src/book-components/Chat/Chat/ChatFeedbackStar.d.ts +37 -0
  42. package/esm/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
  43. package/esm/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
  44. package/esm/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
  45. package/esm/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
  46. package/esm/src/book-components/Chat/Chat/ChatMessageList.d.ts +5 -0
  47. package/esm/src/book-components/Chat/Chat/ChatMessageRichContent.d.ts +5 -0
  48. package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +21 -0
  49. package/esm/src/book-components/Chat/Chat/ChatRatingModal.test.d.ts +2 -0
  50. package/esm/src/book-components/Chat/Chat/CitationIframePreview.d.ts +25 -2
  51. package/esm/src/book-components/Chat/Chat/pagePreview/LiveBrowserPreview.d.ts +39 -0
  52. package/esm/src/book-components/Chat/Chat/pagePreview/LiveBrowserPreview.test.d.ts +2 -0
  53. package/esm/src/book-components/Chat/Chat/pagePreview/LiveBrowserPreviewToolbar.d.ts +71 -0
  54. package/esm/src/book-components/Chat/Chat/pagePreview/PagePreviewInputEvent.d.ts +72 -0
  55. package/esm/src/book-components/Chat/Chat/pagePreview/PagePreviewInputQueue.d.ts +64 -0
  56. package/esm/src/book-components/Chat/Chat/pagePreview/PagePreviewInputQueue.test.d.ts +1 -0
  57. package/esm/src/book-components/Chat/Chat/pagePreview/PagePreviewSessionState.d.ts +14 -0
  58. package/esm/src/book-components/Chat/Chat/pagePreview/PagePreviewViewport.d.ts +37 -0
  59. package/esm/src/book-components/Chat/Chat/pagePreview/createPagePreviewSessionId.d.ts +20 -0
  60. package/esm/src/book-components/Chat/Chat/pagePreview/normalizePagePreviewInputEvent.d.ts +13 -0
  61. package/esm/src/book-components/Chat/Chat/pagePreview/normalizePagePreviewInputEvent.test.d.ts +1 -0
  62. package/esm/src/book-components/Chat/Chat/resolveChatRatingMessageKey.d.ts +8 -0
  63. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
  64. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
  65. package/esm/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +2 -0
  66. package/esm/src/book-components/Chat/SourceChip/SourceChip.test.d.ts +2 -0
  67. package/esm/src/book-components/Chat/hooks/useResolvedCitationLabel.test.d.ts +2 -0
  68. package/esm/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
  69. package/esm/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
  70. package/esm/src/book-components/Chat/utils/renderMarkdown.d.ts +78 -0
  71. package/esm/src/book-components/Chat/utils/resolveCitationSourceDisplay.d.ts +149 -0
  72. package/esm/src/book-components/Chat/utils/thinkingMessageVariants.d.ts +9 -0
  73. package/esm/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +2 -2
  74. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
  75. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
  76. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
  77. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
  78. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
  79. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
  80. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
  81. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
  82. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
  83. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
  84. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
  85. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
  86. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
  87. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
  88. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
  89. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
  90. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
  91. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
  92. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
  93. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
  94. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
  95. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
  96. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
  97. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
  98. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
  99. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
  100. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
  101. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
  102. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
  103. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
  104. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
  105. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
  106. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
  107. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
  108. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
  109. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +17 -0
  110. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.test.d.ts +1 -0
  111. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
  112. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
  113. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
  114. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
  115. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
  116. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
  117. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
  118. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
  119. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
  120. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
  121. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
  122. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
  123. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
  124. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
  125. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
  126. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
  127. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
  128. package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
  129. package/esm/src/cli/cli-commands/coder/add.d.ts +36 -0
  130. package/esm/src/cli/cli-commands/coder/add.test.d.ts +1 -0
  131. package/esm/src/cli/cli-commands/coder/boilerplateTemplates.d.ts +24 -0
  132. package/esm/src/cli/cli-commands/coder.d.ts +1 -0
  133. package/esm/src/cli/cli-commands/common/createNonNegativeIntegerOptionParser.d.ts +10 -0
  134. package/esm/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.d.ts +9 -0
  135. package/esm/src/cli/cli-commands/common/harness/$askForHarnessInstallationApproval.d.ts +9 -0
  136. package/esm/src/cli/cli-commands/common/harness/$checkHarnessInstallation.d.ts +10 -0
  137. package/esm/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +13 -0
  138. package/esm/src/cli/cli-commands/common/harness/$installHarness.d.ts +13 -0
  139. package/esm/src/cli/cli-commands/common/harness/$resolveInstalledHarnessVersion.d.ts +10 -0
  140. package/esm/src/cli/cli-commands/common/harness/$resolveLatestHarnessVersion.d.ts +10 -0
  141. package/esm/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +40 -0
  142. package/esm/src/cli/cli-commands/common/harness/HarnessDefinition.test.d.ts +1 -0
  143. package/esm/src/cli/cli-commands/common/harness/HarnessInstallationStatus.d.ts +35 -0
  144. package/esm/src/cli/cli-commands/common/harness/buildHarnessInstallCommand.d.ts +10 -0
  145. package/esm/src/cli/cli-commands/common/harness/extractHarnessVersionFromOutput.d.ts +11 -0
  146. package/esm/src/cli/cli-commands/common/harness/extractHarnessVersionFromOutput.test.d.ts +1 -0
  147. package/esm/src/cli/cli-commands/common/harness/formatHarnessInstallationWarning.d.ts +7 -0
  148. package/esm/src/cli/cli-commands/common/harness/isHarnessVersionOutdated.d.ts +9 -0
  149. package/esm/src/cli/cli-commands/common/harness/isHarnessVersionOutdated.test.d.ts +1 -0
  150. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
  151. package/esm/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
  152. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/buildAgentNameOrPermanentIdFilter.d.ts +18 -0
  153. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/buildAgentNameOrPermanentIdFilter.test.d.ts +1 -0
  154. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
  155. package/esm/src/commitments/META/META.d.ts +4 -2
  156. package/esm/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
  157. package/esm/src/commitments/META_THINKING_MESSAGE/META_THINKING_MESSAGE.d.ts +26 -0
  158. package/esm/src/commitments/index.d.ts +2 -1
  159. package/esm/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
  160. package/esm/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
  161. package/esm/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
  162. package/esm/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
  163. package/esm/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
  164. package/esm/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
  165. package/esm/src/execution/utils/formatUsagePrice.d.ts +12 -0
  166. package/esm/src/execution/utils/formatUsagePrice.test.d.ts +1 -0
  167. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
  168. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
  169. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
  170. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
  171. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
  172. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
  173. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
  174. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  175. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
  176. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
  177. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
  178. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
  179. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
  180. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
  181. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
  182. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  183. package/esm/src/utils/agent-message-runtime/agentMessageRuntimePaths.d.ts +24 -0
  184. package/esm/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.d.ts +16 -0
  185. package/esm/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.test.d.ts +1 -0
  186. package/esm/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
  187. package/esm/src/utils/agents/terminalAgentAvatarVisual.d.ts +104 -0
  188. package/esm/src/utils/agents/terminalAgentAvatarVisual.test.d.ts +1 -0
  189. package/esm/src/utils/color/Color.d.ts +1 -1
  190. package/esm/src/utils/html/escapeHtml.d.ts +9 -0
  191. package/esm/src/utils/markdown/shiftMarkdownHeadingLevels.d.ts +15 -0
  192. package/esm/src/version.d.ts +1 -1
  193. package/package.json +2 -2
  194. package/umd/index.umd.js +1196 -1084
  195. package/umd/index.umd.js.map +1 -1
  196. package/umd/src/_packages/components.index.d.ts +8 -0
  197. package/umd/src/_packages/core.index.d.ts +4 -0
  198. package/umd/src/_packages/types.index.d.ts +14 -2
  199. package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +24 -1
  200. package/umd/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
  201. package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +7 -0
  202. package/umd/src/book-2.0/agent-source/parseAgentSource/ParsedAgentProfile.d.ts +1 -1
  203. package/umd/src/book-2.0/book-language-documentation/BookLanguageDocumentationExample.d.ts +5 -13
  204. package/umd/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.d.ts +195 -0
  205. package/umd/src/book-2.0/book-language-documentation/bookLanguageDocumentationExamples.d.ts +2 -1
  206. package/umd/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.d.ts +43 -1
  207. package/umd/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.test.d.ts +1 -0
  208. package/umd/src/book-2.0/book-language-documentation/czechBookLanguageManualDictionary.d.ts +10 -0
  209. package/umd/src/book-2.0/book-language-documentation/englishBookLanguageManualDictionary.d.ts +10 -0
  210. package/umd/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.d.ts +33 -0
  211. package/umd/src/book-2.0/book-language-documentation/getBookLanguageManualDictionary.d.ts +15 -0
  212. package/umd/src/book-2.0/book-language-documentation/getSafeCodeBlock.d.ts +10 -0
  213. package/umd/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.d.ts +30 -0
  214. package/umd/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.d.ts +2 -1
  215. package/umd/src/book-2.0/book-language-documentation/toStableAnchorId.d.ts +12 -0
  216. package/umd/src/book-3.0/AgentMessageRunReport.d.ts +78 -0
  217. package/umd/src/book-3.0/AgentMessageRunReport.test.d.ts +1 -0
  218. package/umd/src/book-3.0/agentFolderPaths.d.ts +9 -0
  219. package/umd/src/book-3.0/codexLoginMethod.d.ts +38 -0
  220. package/umd/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
  221. package/umd/src/book-components/BookEditor/BookEditorSyntaxTokenStyles.d.ts +39 -0
  222. package/umd/src/book-components/BookEditor/createBookSourceHighlightStyles.d.ts +12 -0
  223. package/umd/src/book-components/BookEditor/highlightBookSourceToHtml.d.ts +20 -0
  224. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
  225. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
  226. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
  227. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
  228. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
  229. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
  230. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
  231. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
  232. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
  233. package/umd/src/book-components/Chat/Chat/ChatCitationModal.d.ts +5 -0
  234. package/umd/src/book-components/Chat/Chat/ChatCitationModal.test.d.ts +2 -0
  235. package/umd/src/book-components/Chat/Chat/ChatFeedbackStar.d.ts +37 -0
  236. package/umd/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
  237. package/umd/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
  238. package/umd/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
  239. package/umd/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
  240. package/umd/src/book-components/Chat/Chat/ChatMessageList.d.ts +5 -0
  241. package/umd/src/book-components/Chat/Chat/ChatMessageRichContent.d.ts +5 -0
  242. package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +21 -0
  243. package/umd/src/book-components/Chat/Chat/ChatRatingModal.test.d.ts +2 -0
  244. package/umd/src/book-components/Chat/Chat/CitationIframePreview.d.ts +25 -2
  245. package/umd/src/book-components/Chat/Chat/pagePreview/LiveBrowserPreview.d.ts +39 -0
  246. package/umd/src/book-components/Chat/Chat/pagePreview/LiveBrowserPreview.test.d.ts +2 -0
  247. package/umd/src/book-components/Chat/Chat/pagePreview/LiveBrowserPreviewToolbar.d.ts +71 -0
  248. package/umd/src/book-components/Chat/Chat/pagePreview/PagePreviewInputEvent.d.ts +72 -0
  249. package/umd/src/book-components/Chat/Chat/pagePreview/PagePreviewInputQueue.d.ts +64 -0
  250. package/umd/src/book-components/Chat/Chat/pagePreview/PagePreviewInputQueue.test.d.ts +1 -0
  251. package/umd/src/book-components/Chat/Chat/pagePreview/PagePreviewSessionState.d.ts +14 -0
  252. package/umd/src/book-components/Chat/Chat/pagePreview/PagePreviewViewport.d.ts +37 -0
  253. package/umd/src/book-components/Chat/Chat/pagePreview/createPagePreviewSessionId.d.ts +20 -0
  254. package/umd/src/book-components/Chat/Chat/pagePreview/normalizePagePreviewInputEvent.d.ts +13 -0
  255. package/umd/src/book-components/Chat/Chat/pagePreview/normalizePagePreviewInputEvent.test.d.ts +1 -0
  256. package/umd/src/book-components/Chat/Chat/resolveChatRatingMessageKey.d.ts +8 -0
  257. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
  258. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
  259. package/umd/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +2 -0
  260. package/umd/src/book-components/Chat/SourceChip/SourceChip.test.d.ts +2 -0
  261. package/umd/src/book-components/Chat/hooks/useResolvedCitationLabel.test.d.ts +2 -0
  262. package/umd/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
  263. package/umd/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
  264. package/umd/src/book-components/Chat/utils/renderMarkdown.d.ts +78 -0
  265. package/umd/src/book-components/Chat/utils/resolveCitationSourceDisplay.d.ts +149 -0
  266. package/umd/src/book-components/Chat/utils/thinkingMessageVariants.d.ts +9 -0
  267. package/umd/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +2 -2
  268. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
  269. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
  270. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
  271. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
  272. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
  273. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
  274. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
  275. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
  276. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
  277. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
  278. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
  279. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
  280. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
  281. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
  282. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
  283. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
  284. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
  285. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
  286. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
  287. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
  288. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
  289. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
  290. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
  291. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
  292. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
  293. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
  294. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
  295. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
  296. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
  297. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
  298. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
  299. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
  300. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
  301. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
  302. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
  303. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +17 -0
  304. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.test.d.ts +1 -0
  305. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
  306. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
  307. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
  308. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
  309. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
  310. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
  311. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
  312. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
  313. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
  314. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
  315. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
  316. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
  317. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
  318. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
  319. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
  320. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
  321. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
  322. package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
  323. package/umd/src/cli/cli-commands/coder/add.d.ts +36 -0
  324. package/umd/src/cli/cli-commands/coder/add.test.d.ts +1 -0
  325. package/umd/src/cli/cli-commands/coder/boilerplateTemplates.d.ts +24 -0
  326. package/umd/src/cli/cli-commands/coder.d.ts +1 -0
  327. package/umd/src/cli/cli-commands/common/createNonNegativeIntegerOptionParser.d.ts +10 -0
  328. package/umd/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.d.ts +9 -0
  329. package/umd/src/cli/cli-commands/common/harness/$askForHarnessInstallationApproval.d.ts +9 -0
  330. package/umd/src/cli/cli-commands/common/harness/$checkHarnessInstallation.d.ts +10 -0
  331. package/umd/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +13 -0
  332. package/umd/src/cli/cli-commands/common/harness/$installHarness.d.ts +13 -0
  333. package/umd/src/cli/cli-commands/common/harness/$resolveInstalledHarnessVersion.d.ts +10 -0
  334. package/umd/src/cli/cli-commands/common/harness/$resolveLatestHarnessVersion.d.ts +10 -0
  335. package/umd/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +40 -0
  336. package/umd/src/cli/cli-commands/common/harness/HarnessDefinition.test.d.ts +1 -0
  337. package/umd/src/cli/cli-commands/common/harness/HarnessInstallationStatus.d.ts +35 -0
  338. package/umd/src/cli/cli-commands/common/harness/buildHarnessInstallCommand.d.ts +10 -0
  339. package/umd/src/cli/cli-commands/common/harness/extractHarnessVersionFromOutput.d.ts +11 -0
  340. package/umd/src/cli/cli-commands/common/harness/extractHarnessVersionFromOutput.test.d.ts +1 -0
  341. package/umd/src/cli/cli-commands/common/harness/formatHarnessInstallationWarning.d.ts +7 -0
  342. package/umd/src/cli/cli-commands/common/harness/isHarnessVersionOutdated.d.ts +9 -0
  343. package/umd/src/cli/cli-commands/common/harness/isHarnessVersionOutdated.test.d.ts +1 -0
  344. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
  345. package/umd/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
  346. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/buildAgentNameOrPermanentIdFilter.d.ts +18 -0
  347. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/buildAgentNameOrPermanentIdFilter.test.d.ts +1 -0
  348. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
  349. package/umd/src/commitments/META/META.d.ts +4 -2
  350. package/umd/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
  351. package/umd/src/commitments/META_THINKING_MESSAGE/META_THINKING_MESSAGE.d.ts +26 -0
  352. package/umd/src/commitments/index.d.ts +2 -1
  353. package/umd/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
  354. package/umd/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
  355. package/umd/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
  356. package/umd/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
  357. package/umd/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
  358. package/umd/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
  359. package/umd/src/execution/utils/formatUsagePrice.d.ts +12 -0
  360. package/umd/src/execution/utils/formatUsagePrice.test.d.ts +1 -0
  361. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
  362. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
  363. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
  364. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
  365. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
  366. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
  367. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
  368. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  369. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
  370. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
  371. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
  372. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
  373. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
  374. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
  375. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
  376. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  377. package/umd/src/utils/agent-message-runtime/agentMessageRuntimePaths.d.ts +24 -0
  378. package/umd/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.d.ts +16 -0
  379. package/umd/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.test.d.ts +1 -0
  380. package/umd/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
  381. package/umd/src/utils/agents/terminalAgentAvatarVisual.d.ts +104 -0
  382. package/umd/src/utils/agents/terminalAgentAvatarVisual.test.d.ts +1 -0
  383. package/umd/src/utils/color/Color.d.ts +1 -1
  384. package/umd/src/utils/html/escapeHtml.d.ts +9 -0
  385. package/umd/src/utils/markdown/shiftMarkdownHeadingLevels.d.ts +15 -0
  386. package/umd/src/version.d.ts +1 -1
  387. package/esm/src/book-2.0/book-language-documentation/bookLanguageCommonPitfalls.d.ts +0 -25
  388. package/esm/src/book-components/_common/react-utils/escapeHtml.d.ts +0 -6
  389. package/umd/src/book-2.0/book-language-documentation/bookLanguageCommonPitfalls.d.ts +0 -25
  390. package/umd/src/book-components/_common/react-utils/escapeHtml.d.ts +0 -6
  391. /package/esm/src/{executables/browsers/locateInternetExplorer.test.d.ts → book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.test.d.ts} +0 -0
  392. /package/{umd/src/executables/browsers/locateInternetExplorer.test.d.ts → esm/src/book-3.0/AgentMessageRunReport.test.d.ts} +0 -0
package/umd/index.umd.js CHANGED
@@ -52,7 +52,7 @@
52
52
  * @generated
53
53
  * @see https://github.com/webgptorg/promptbook
54
54
  */
55
- const PROMPTBOOK_ENGINE_VERSION = '0.113.0-8';
55
+ const PROMPTBOOK_ENGINE_VERSION = '0.114.0-0';
56
56
  /**
57
57
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
58
58
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -129,6 +129,127 @@
129
129
  });
130
130
  }
131
131
 
132
+ /**
133
+ * Validates that a channel value is a valid number within the range of 0 to 255.
134
+ * Throws an error if the value is not valid.
135
+ *
136
+ * @param channelName - The name of the channel being validated.
137
+ * @param value - The value of the channel to validate.
138
+ * @throws Will throw an error if the value is not a valid channel number.
139
+ *
140
+ * @private util of `@promptbook/color`
141
+ */
142
+ function checkChannelValue(channelName, value) {
143
+ if (typeof value !== 'number') {
144
+ throw new Error(`${channelName} channel value is not number but ${typeof value}`);
145
+ }
146
+ if (isNaN(value)) {
147
+ throw new Error(`${channelName} channel value is NaN`);
148
+ }
149
+ if (Math.round(value) !== value) {
150
+ throw new Error(`${channelName} channel is not whole number, it is ${value}`);
151
+ }
152
+ if (value < 0) {
153
+ throw new Error(`${channelName} channel is lower than 0, it is ${value}`);
154
+ }
155
+ if (value > 255) {
156
+ throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Shared immutable channel storage and serialization helpers for `Color`.
162
+ *
163
+ * @private base class of Color
164
+ */
165
+ class ColorValue {
166
+ constructor(red, green, blue, alpha = 255) {
167
+ this.red = red;
168
+ this.green = green;
169
+ this.blue = blue;
170
+ this.alpha = alpha;
171
+ checkChannelValue('Red', red);
172
+ checkChannelValue('Green', green);
173
+ checkChannelValue('Blue', blue);
174
+ checkChannelValue('Alpha', alpha);
175
+ }
176
+ /**
177
+ * Shortcut for `red` property
178
+ * Number from 0 to 255
179
+ * @alias red
180
+ */
181
+ get r() {
182
+ return this.red;
183
+ }
184
+ /**
185
+ * Shortcut for `green` property
186
+ * Number from 0 to 255
187
+ * @alias green
188
+ */
189
+ get g() {
190
+ return this.green;
191
+ }
192
+ /**
193
+ * Shortcut for `blue` property
194
+ * Number from 0 to 255
195
+ * @alias blue
196
+ */
197
+ get b() {
198
+ return this.blue;
199
+ }
200
+ /**
201
+ * Shortcut for `alpha` property
202
+ * Number from 0 (transparent) to 255 (opaque)
203
+ * @alias alpha
204
+ */
205
+ get a() {
206
+ return this.alpha;
207
+ }
208
+ /**
209
+ * Shortcut for `alpha` property
210
+ * Number from 0 (transparent) to 255 (opaque)
211
+ * @alias alpha
212
+ */
213
+ get opacity() {
214
+ return this.alpha;
215
+ }
216
+ /**
217
+ * Shortcut for 1-`alpha` property
218
+ */
219
+ get transparency() {
220
+ return 255 - this.alpha;
221
+ }
222
+ clone() {
223
+ return take(this.createColor(this.red, this.green, this.blue, this.alpha));
224
+ }
225
+ toString() {
226
+ return this.toHex();
227
+ }
228
+ toHex() {
229
+ if (this.alpha === 255) {
230
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
231
+ .toString(16)
232
+ .padStart(2, '0')}`;
233
+ }
234
+ else {
235
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
236
+ .toString(16)
237
+ .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
238
+ }
239
+ }
240
+ toRgb() {
241
+ if (this.alpha === 255) {
242
+ return `rgb(${this.red}, ${this.green}, ${this.blue})`;
243
+ }
244
+ else {
245
+ return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
246
+ }
247
+ }
248
+ toHsl() {
249
+ throw new Error(`Getting HSL is not implemented`);
250
+ }
251
+ }
252
+
132
253
  /**
133
254
  * 🎨 List of all 140 color names which are supported by CSS
134
255
  *
@@ -288,127 +409,6 @@
288
409
  };
289
410
  // Note: [💞] Ignore a discrepancy between file name and entity name
290
411
 
291
- /**
292
- * Validates that a channel value is a valid number within the range of 0 to 255.
293
- * Throws an error if the value is not valid.
294
- *
295
- * @param channelName - The name of the channel being validated.
296
- * @param value - The value of the channel to validate.
297
- * @throws Will throw an error if the value is not a valid channel number.
298
- *
299
- * @private util of `@promptbook/color`
300
- */
301
- function checkChannelValue(channelName, value) {
302
- if (typeof value !== 'number') {
303
- throw new Error(`${channelName} channel value is not number but ${typeof value}`);
304
- }
305
- if (isNaN(value)) {
306
- throw new Error(`${channelName} channel value is NaN`);
307
- }
308
- if (Math.round(value) !== value) {
309
- throw new Error(`${channelName} channel is not whole number, it is ${value}`);
310
- }
311
- if (value < 0) {
312
- throw new Error(`${channelName} channel is lower than 0, it is ${value}`);
313
- }
314
- if (value > 255) {
315
- throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
316
- }
317
- }
318
-
319
- /**
320
- * Shared immutable channel storage and serialization helpers for `Color`.
321
- *
322
- * @private base class of Color
323
- */
324
- class ColorValue {
325
- constructor(red, green, blue, alpha = 255) {
326
- this.red = red;
327
- this.green = green;
328
- this.blue = blue;
329
- this.alpha = alpha;
330
- checkChannelValue('Red', red);
331
- checkChannelValue('Green', green);
332
- checkChannelValue('Blue', blue);
333
- checkChannelValue('Alpha', alpha);
334
- }
335
- /**
336
- * Shortcut for `red` property
337
- * Number from 0 to 255
338
- * @alias red
339
- */
340
- get r() {
341
- return this.red;
342
- }
343
- /**
344
- * Shortcut for `green` property
345
- * Number from 0 to 255
346
- * @alias green
347
- */
348
- get g() {
349
- return this.green;
350
- }
351
- /**
352
- * Shortcut for `blue` property
353
- * Number from 0 to 255
354
- * @alias blue
355
- */
356
- get b() {
357
- return this.blue;
358
- }
359
- /**
360
- * Shortcut for `alpha` property
361
- * Number from 0 (transparent) to 255 (opaque)
362
- * @alias alpha
363
- */
364
- get a() {
365
- return this.alpha;
366
- }
367
- /**
368
- * Shortcut for `alpha` property
369
- * Number from 0 (transparent) to 255 (opaque)
370
- * @alias alpha
371
- */
372
- get opacity() {
373
- return this.alpha;
374
- }
375
- /**
376
- * Shortcut for 1-`alpha` property
377
- */
378
- get transparency() {
379
- return 255 - this.alpha;
380
- }
381
- clone() {
382
- return take(this.createColor(this.red, this.green, this.blue, this.alpha));
383
- }
384
- toString() {
385
- return this.toHex();
386
- }
387
- toHex() {
388
- if (this.alpha === 255) {
389
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
390
- .toString(16)
391
- .padStart(2, '0')}`;
392
- }
393
- else {
394
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
395
- .toString(16)
396
- .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
397
- }
398
- }
399
- toRgb() {
400
- if (this.alpha === 255) {
401
- return `rgb(${this.red}, ${this.green}, ${this.blue})`;
402
- }
403
- else {
404
- return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
405
- }
406
- }
407
- toHsl() {
408
- throw new Error(`Getting HSL is not implemented`);
409
- }
410
- }
411
-
412
412
  /**
413
413
  * Checks if the given value is a valid hex color string
414
414
  *
@@ -11477,140 +11477,10 @@
11477
11477
  // TODO: [🏛] Escape all
11478
11478
  // TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
11479
11479
 
11480
- /**
11481
- * Tests if given string is valid semantic version
11482
- *
11483
- * Note: There are two similar functions:
11484
- * - `isValidSemanticVersion` which tests any semantic version
11485
- * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
11486
- *
11487
- * @public exported from `@promptbook/utils`
11488
- */
11489
- function isValidSemanticVersion(version) {
11490
- if (typeof version !== 'string') {
11491
- return false;
11492
- }
11493
- if (version.startsWith('0.0.0')) {
11494
- return false;
11495
- }
11496
- return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
11497
- }
11498
-
11499
- /**
11500
- * Tests if given string is valid promptbook version
11501
- * It looks into list of known promptbook versions.
11502
- *
11503
- * Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
11504
- * Note: There are two similar functions:
11505
- * - `isValidSemanticVersion` which tests any semantic version
11506
- * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
11507
- *
11508
- * @see https://www.npmjs.com/package/promptbook?activeTab=versions
11509
- *
11510
- * @public exported from `@promptbook/utils`
11511
- */
11512
- function isValidPromptbookVersion(version) {
11513
- if (!isValidSemanticVersion(version)) {
11514
- return false;
11515
- }
11516
- if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
11517
- return false;
11518
- }
11519
- // <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
11520
- return true;
11521
- }
11522
-
11523
- /**
11524
- * Tests if given string is valid pipeline URL URL.
11525
- *
11526
- * Note: There are few similar functions:
11527
- * - `isValidUrl` which tests any URL
11528
- * - `isValidAgentUrl` which tests just agent URL
11529
- * - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
11530
- *
11531
- * @public exported from `@promptbook/utils`
11532
- */
11533
- function isValidPipelineUrl(url) {
11534
- if (!isValidUrl(url)) {
11535
- return false;
11536
- }
11537
- if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
11538
- return false;
11539
- }
11540
- if (url.includes('#')) {
11541
- // TODO: [🐠]
11542
- return false;
11543
- }
11544
- /*
11545
- Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
11546
- if (isUrlOnPrivateNetwork(url)) {
11547
- return false;
11548
- }
11549
- */
11550
- return true;
11551
- }
11552
- // TODO: [🐠] Maybe more info why the URL is invalid
11553
-
11554
- /**
11555
- * Validates PipelineJson if it is logically valid
11556
- *
11557
- * It checks:
11558
- * - if it has correct parameters dependency
11559
- *
11560
- * It does NOT check:
11561
- * - if it is valid json
11562
- * - if it is meaningful
11563
- *
11564
- * Note: [🔂] This function is idempotent.
11565
- *
11566
- * @param pipeline valid or invalid PipelineJson
11567
- * @returns the same pipeline if it is logically valid
11568
- * @throws {PipelineLogicError} on logical error in the pipeline
11569
- *
11570
- * @public exported from `@promptbook/core`
11571
- */
11572
- function validatePipeline(pipeline) {
11573
- if (IS_PIPELINE_LOGIC_VALIDATED) {
11574
- validatePipeline_InnerFunction(pipeline);
11575
- }
11576
- else {
11577
- try {
11578
- validatePipeline_InnerFunction(pipeline);
11579
- }
11580
- catch (error) {
11581
- if (!(error instanceof PipelineLogicError)) {
11582
- throw error;
11583
- }
11584
- console.error(_spaceTrim.spaceTrim((block) => `
11585
- Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
11586
-
11587
- ${block(error.message)}
11588
- `));
11589
- }
11590
- }
11591
- return pipeline;
11592
- }
11593
- /**
11594
- * Validates pipeline inner function.
11595
- *
11596
- * @private internal function for `validatePipeline`
11597
- */
11598
- function validatePipeline_InnerFunction(pipeline) {
11599
- // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
11600
- const context = createPipelineValidationContext(pipeline);
11601
- validatePipelineMetadata(context);
11602
- validatePipelineCollectionsStructure(context);
11603
- validatePipelineParameters(context);
11604
- validatePipelineTasks(context);
11605
- validatePipelineDependencyResolution(context);
11606
- // Note: Check that formfactor is corresponding to the pipeline interface
11607
- // TODO: !!6 Implement this
11608
- // pipeline.formfactorName
11609
- }
11610
11480
  /**
11611
11481
  * Creates the shared validation context for one pipeline.
11612
11482
  *
11613
- * @private internal utility of `validatePipeline`
11483
+ * @private function of `validatePipeline`
11614
11484
  */
11615
11485
  function createPipelineValidationContext(pipeline) {
11616
11486
  return {
@@ -11634,52 +11504,61 @@
11634
11504
  }
11635
11505
  return pipelineIdentificationParts.join('\n');
11636
11506
  }
11637
- /**
11638
- * Validates pipeline-level metadata fields.
11639
- *
11640
- * @private internal step of `validatePipeline`
11641
- */
11642
- function validatePipelineMetadata({ pipeline, pipelineIdentification }) {
11643
- validatePipelineUrl(pipeline, pipelineIdentification);
11644
- validatePipelineBookVersion(pipeline, pipelineIdentification);
11645
- }
11507
+
11646
11508
  /**
11647
11509
  * Validates that the expected top-level collections have array structure.
11648
11510
  *
11649
- * @private internal step of `validatePipeline`
11511
+ * @private function of `validatePipeline`
11650
11512
  */
11651
- function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification }) {
11513
+ function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification, }) {
11652
11514
  validatePipelineParametersCollection(pipeline, pipelineIdentification);
11653
11515
  validatePipelineTasksCollection(pipeline, pipelineIdentification);
11654
11516
  }
11655
11517
  /**
11656
- * Validates all pipeline parameter declarations.
11518
+ * Validates that `pipeline.parameters` is an array.
11657
11519
  *
11658
- * @private internal step of `validatePipeline`
11520
+ * @private internal utility of `validatePipelineCollectionsStructure`
11659
11521
  */
11660
- function validatePipelineParameters({ pipeline, pipelineIdentification }) {
11661
- for (const parameter of pipeline.parameters) {
11662
- validatePipelineParameter(parameter, pipeline, pipelineIdentification);
11522
+ function validatePipelineParametersCollection(pipeline, pipelineIdentification) {
11523
+ // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
11524
+ if (Array.isArray(pipeline.parameters)) {
11525
+ return;
11663
11526
  }
11527
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
11528
+ throw new ParseError(_spaceTrim.spaceTrim((block) => `
11529
+ Pipeline is valid JSON but with wrong structure
11530
+
11531
+ \`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
11532
+
11533
+ ${block(pipelineIdentification)}
11534
+ `));
11664
11535
  }
11665
11536
  /**
11666
- * Validates all pipeline tasks and their per-task invariants.
11537
+ * Validates that `pipeline.tasks` is an array.
11667
11538
  *
11668
- * @private internal step of `validatePipeline`
11539
+ * @private internal utility of `validatePipelineCollectionsStructure`
11669
11540
  */
11670
- function validatePipelineTasks({ pipeline, pipelineIdentification }) {
11671
- // Note: All input parameters are defined - so that they can be used as result of some task
11672
- const definedParameters = createInitiallyDefinedParameters(pipeline);
11673
- for (const task of pipeline.tasks) {
11674
- validatePipelineTask(task, definedParameters, pipelineIdentification);
11541
+ function validatePipelineTasksCollection(pipeline, pipelineIdentification) {
11542
+ // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
11543
+ if (Array.isArray(pipeline.tasks)) {
11544
+ return;
11675
11545
  }
11546
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
11547
+ throw new ParseError(_spaceTrim.spaceTrim((block) => `
11548
+ Pipeline is valid JSON but with wrong structure
11549
+
11550
+ \`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
11551
+
11552
+ ${block(pipelineIdentification)}
11553
+ `));
11676
11554
  }
11555
+
11677
11556
  /**
11678
11557
  * Validates that task dependencies can be resolved without cycles or missing definitions.
11679
11558
  *
11680
- * @private internal step of `validatePipeline`
11559
+ * @private function of `validatePipeline`
11681
11560
  */
11682
- function validatePipelineDependencyResolution({ pipeline, pipelineIdentification }) {
11561
+ function validatePipelineDependencyResolution({ pipeline, pipelineIdentification, }) {
11683
11562
  let dependencyResolutionState = createInitialDependencyResolutionState(pipeline);
11684
11563
  let loopLimit = LOOP_LIMIT;
11685
11564
  while (hasUnresolvedTasks(dependencyResolutionState)) {
@@ -11690,29 +11569,211 @@
11690
11569
  }
11691
11570
  }
11692
11571
  /**
11693
- * Validates one pipeline parameter declaration.
11572
+ * Collects the parameter names that are already resolvable before dependency traversal starts.
11694
11573
  *
11695
- * @private internal step of `validatePipeline`
11574
+ * @private internal utility of `validatePipelineDependencyResolution`
11696
11575
  */
11697
- function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
11698
- validateParameterDirection(parameter, pipelineIdentification);
11699
- validateParameterUsage(parameter, pipeline, pipelineIdentification);
11700
- validateParameterDefinition(parameter, pipeline, pipelineIdentification);
11576
+ function createInitialDependencyResolutionState(pipeline) {
11577
+ return {
11578
+ resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
11579
+ unresolvedTasks: [...pipeline.tasks],
11580
+ };
11701
11581
  }
11702
11582
  /**
11703
- * Validates one pipeline task and its invariants.
11583
+ * Checks whether dependency resolution still has tasks left to process.
11704
11584
  *
11705
- * @private internal step of `validatePipeline`
11585
+ * @private internal utility of `validatePipelineDependencyResolution`
11706
11586
  */
11707
- function validatePipelineTask(task, definedParameters, pipelineIdentification) {
11708
- validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
11709
- validateTaskJokers(task, pipelineIdentification);
11710
- validateTaskExpectations(task, pipelineIdentification);
11587
+ function hasUnresolvedTasks({ unresolvedTasks }) {
11588
+ return unresolvedTasks.length > 0;
11589
+ }
11590
+ /**
11591
+ * Resolves the next batch of currently satisfiable tasks.
11592
+ *
11593
+ * @private internal utility of `validatePipelineDependencyResolution`
11594
+ */
11595
+ function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
11596
+ const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
11597
+ if (currentlyResolvedTasks.length === 0) {
11598
+ throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
11599
+ }
11600
+ return {
11601
+ resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
11602
+ unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
11603
+ };
11604
+ }
11605
+ /**
11606
+ * Collects the parameter names that are already resolvable before dependency traversal starts.
11607
+ *
11608
+ * @private internal utility of `validatePipelineDependencyResolution`
11609
+ */
11610
+ function createInitiallyResolvedParameterNames(pipeline) {
11611
+ let resolvedParameterNames = pipeline.parameters
11612
+ .filter(({ isInput }) => isInput)
11613
+ .map(({ name }) => name);
11614
+ for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
11615
+ resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
11616
+ }
11617
+ return resolvedParameterNames;
11618
+ }
11619
+ /**
11620
+ * Adds newly resolved task outputs to the resolved parameter list.
11621
+ *
11622
+ * @private internal utility of `validatePipelineDependencyResolution`
11623
+ */
11624
+ function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
11625
+ return [
11626
+ ...resolvedParameterNames,
11627
+ ...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
11628
+ ];
11629
+ }
11630
+ /**
11631
+ * Selects tasks whose dependencies are already resolved.
11632
+ *
11633
+ * @private internal utility of `validatePipelineDependencyResolution`
11634
+ */
11635
+ function getCurrentlyResolvedTasks(unresolvedTasks, resolvedParameterNames) {
11636
+ return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
11637
+ }
11638
+ /**
11639
+ * Creates the unexpected loop-limit error for dependency resolution.
11640
+ *
11641
+ * @private internal utility of `validatePipelineDependencyResolution`
11642
+ */
11643
+ function createDependencyResolutionLoopLimitError(pipelineIdentification) {
11644
+ // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
11645
+ return new UnexpectedError(_spaceTrim.spaceTrim((block) => `
11646
+ Loop limit reached during detection of circular dependencies in \`validatePipeline\`
11647
+
11648
+ ${block(pipelineIdentification)}
11649
+ `));
11650
+ }
11651
+ /**
11652
+ * Creates the detailed error for unresolved or circular task dependencies.
11653
+ *
11654
+ * @private internal utility of `validatePipelineDependencyResolution`
11655
+ */
11656
+ function createUnresolvedTasksError(unresolvedTasks, resolvedParameterNames, pipelineIdentification) {
11657
+ return new PipelineLogicError(
11658
+ // TODO: [🐎] DRY
11659
+ _spaceTrim.spaceTrim((block) => `
11660
+
11661
+ Can not resolve some parameters:
11662
+ Either you are using a parameter that is not defined, or there are some circular dependencies.
11663
+
11664
+ ${block(pipelineIdentification)}
11665
+
11666
+ **Can not resolve:**
11667
+ ${block(unresolvedTasks
11668
+ .map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
11669
+ .map((dependentParameterName) => `\`{${dependentParameterName}}\``)
11670
+ .join(' and ')}`)
11671
+ .join('\n'))}
11672
+
11673
+ **Resolved:**
11674
+ ${block(resolvedParameterNames
11675
+ .filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
11676
+ .map((name) => `- Parameter \`{${name}}\``)
11677
+ .join('\n'))}
11678
+
11679
+
11680
+ **Reserved (which are available):**
11681
+ ${block(resolvedParameterNames
11682
+ .filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
11683
+ .map((name) => `- Parameter \`{${name}}\``)
11684
+ .join('\n'))}
11685
+
11686
+
11687
+ `));
11688
+ }
11689
+
11690
+ /**
11691
+ * Tests if given string is valid semantic version
11692
+ *
11693
+ * Note: There are two similar functions:
11694
+ * - `isValidSemanticVersion` which tests any semantic version
11695
+ * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
11696
+ *
11697
+ * @public exported from `@promptbook/utils`
11698
+ */
11699
+ function isValidSemanticVersion(version) {
11700
+ if (typeof version !== 'string') {
11701
+ return false;
11702
+ }
11703
+ if (version.startsWith('0.0.0')) {
11704
+ return false;
11705
+ }
11706
+ return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
11707
+ }
11708
+
11709
+ /**
11710
+ * Tests if given string is valid promptbook version
11711
+ * It looks into list of known promptbook versions.
11712
+ *
11713
+ * Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
11714
+ * Note: There are two similar functions:
11715
+ * - `isValidSemanticVersion` which tests any semantic version
11716
+ * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
11717
+ *
11718
+ * @see https://www.npmjs.com/package/promptbook?activeTab=versions
11719
+ *
11720
+ * @public exported from `@promptbook/utils`
11721
+ */
11722
+ function isValidPromptbookVersion(version) {
11723
+ if (!isValidSemanticVersion(version)) {
11724
+ return false;
11725
+ }
11726
+ if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
11727
+ return false;
11728
+ }
11729
+ // <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
11730
+ return true;
11731
+ }
11732
+
11733
+ /**
11734
+ * Tests if given string is valid pipeline URL URL.
11735
+ *
11736
+ * Note: There are few similar functions:
11737
+ * - `isValidUrl` which tests any URL
11738
+ * - `isValidAgentUrl` which tests just agent URL
11739
+ * - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
11740
+ *
11741
+ * @public exported from `@promptbook/utils`
11742
+ */
11743
+ function isValidPipelineUrl(url) {
11744
+ if (!isValidUrl(url)) {
11745
+ return false;
11746
+ }
11747
+ if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
11748
+ return false;
11749
+ }
11750
+ if (url.includes('#')) {
11751
+ // TODO: [🐠]
11752
+ return false;
11753
+ }
11754
+ /*
11755
+ Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
11756
+ if (isUrlOnPrivateNetwork(url)) {
11757
+ return false;
11758
+ }
11759
+ */
11760
+ return true;
11761
+ }
11762
+ // TODO: [🐠] Maybe more info why the URL is invalid
11763
+
11764
+ /**
11765
+ * Validates pipeline-level metadata fields.
11766
+ *
11767
+ * @private function of `validatePipeline`
11768
+ */
11769
+ function validatePipelineMetadata({ pipeline, pipelineIdentification }) {
11770
+ validatePipelineUrl(pipeline, pipelineIdentification);
11771
+ validatePipelineBookVersion(pipeline, pipelineIdentification);
11711
11772
  }
11712
11773
  /**
11713
11774
  * Validates the pipeline URL, when present.
11714
11775
  *
11715
- * @private internal utility of `validatePipeline`
11776
+ * @private internal utility of `validatePipelineMetadata`
11716
11777
  */
11717
11778
  function validatePipelineUrl(pipeline, pipelineIdentification) {
11718
11779
  if (pipeline.pipelineUrl === undefined || isValidPipelineUrl(pipeline.pipelineUrl)) {
@@ -11728,7 +11789,7 @@
11728
11789
  /**
11729
11790
  * Validates the Promptbook version, when present.
11730
11791
  *
11731
- * @private internal utility of `validatePipeline`
11792
+ * @private internal utility of `validatePipelineMetadata`
11732
11793
  */
11733
11794
  function validatePipelineBookVersion(pipeline, pipelineIdentification) {
11734
11795
  if (pipeline.bookVersion === undefined || isValidPromptbookVersion(pipeline.bookVersion)) {
@@ -11741,48 +11802,31 @@
11741
11802
  ${block(pipelineIdentification)}
11742
11803
  `));
11743
11804
  }
11805
+
11744
11806
  /**
11745
- * Validates that `pipeline.parameters` is an array.
11807
+ * Validates all pipeline parameter declarations.
11746
11808
  *
11747
- * @private internal utility of `validatePipeline`
11809
+ * @private function of `validatePipeline`
11748
11810
  */
11749
- function validatePipelineParametersCollection(pipeline, pipelineIdentification) {
11750
- // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
11751
- if (Array.isArray(pipeline.parameters)) {
11752
- return;
11811
+ function validatePipelineParameters({ pipeline, pipelineIdentification }) {
11812
+ for (const parameter of pipeline.parameters) {
11813
+ validatePipelineParameter(parameter, pipeline, pipelineIdentification);
11753
11814
  }
11754
- // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
11755
- throw new ParseError(_spaceTrim.spaceTrim((block) => `
11756
- Pipeline is valid JSON but with wrong structure
11757
-
11758
- \`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
11759
-
11760
- ${block(pipelineIdentification)}
11761
- `));
11762
11815
  }
11763
11816
  /**
11764
- * Validates that `pipeline.tasks` is an array.
11817
+ * Validates one pipeline parameter declaration.
11765
11818
  *
11766
- * @private internal utility of `validatePipeline`
11819
+ * @private internal utility of `validatePipelineParameters`
11767
11820
  */
11768
- function validatePipelineTasksCollection(pipeline, pipelineIdentification) {
11769
- // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
11770
- if (Array.isArray(pipeline.tasks)) {
11771
- return;
11772
- }
11773
- // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
11774
- throw new ParseError(_spaceTrim.spaceTrim((block) => `
11775
- Pipeline is valid JSON but with wrong structure
11776
-
11777
- \`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
11778
-
11779
- ${block(pipelineIdentification)}
11780
- `));
11821
+ function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
11822
+ validateParameterDirection(parameter, pipelineIdentification);
11823
+ validateParameterUsage(parameter, pipeline, pipelineIdentification);
11824
+ validateParameterDefinition(parameter, pipeline, pipelineIdentification);
11781
11825
  }
11782
11826
  /**
11783
11827
  * Validates that one parameter does not declare incompatible directions.
11784
11828
  *
11785
- * @private internal utility of `validatePipeline`
11829
+ * @private internal utility of `validatePipelineParameters`
11786
11830
  */
11787
11831
  function validateParameterDirection(parameter, pipelineIdentification) {
11788
11832
  if (!parameter.isInput || !parameter.isOutput) {
@@ -11799,7 +11843,7 @@
11799
11843
  /**
11800
11844
  * Validates that one intermediate parameter is actually consumed by at least one task.
11801
11845
  *
11802
- * @private internal utility of `validatePipeline`
11846
+ * @private internal utility of `validatePipelineParameters`
11803
11847
  */
11804
11848
  function validateParameterUsage(parameter, pipeline, pipelineIdentification) {
11805
11849
  if (parameter.isInput || parameter.isOutput || isParameterUsedByAnyTask(parameter, pipeline.tasks)) {
@@ -11818,7 +11862,7 @@
11818
11862
  /**
11819
11863
  * Validates that one non-input parameter is produced by at least one task.
11820
11864
  *
11821
- * @private internal utility of `validatePipeline`
11865
+ * @private internal utility of `validatePipelineParameters`
11822
11866
  */
11823
11867
  function validateParameterDefinition(parameter, pipeline, pipelineIdentification) {
11824
11868
  if (parameter.isInput || isParameterDefinedByAnyTask(parameter, pipeline.tasks)) {
@@ -11837,7 +11881,7 @@
11837
11881
  /**
11838
11882
  * Checks whether one parameter is consumed by at least one task dependency list.
11839
11883
  *
11840
- * @private internal utility of `validatePipeline`
11884
+ * @private internal utility of `validatePipelineParameters`
11841
11885
  */
11842
11886
  function isParameterUsedByAnyTask(parameter, tasks) {
11843
11887
  return tasks.some((task) => task.dependentParameterNames.includes(parameter.name));
@@ -11845,23 +11889,46 @@
11845
11889
  /**
11846
11890
  * Checks whether one parameter is produced by at least one task.
11847
11891
  *
11848
- * @private internal utility of `validatePipeline`
11892
+ * @private internal utility of `validatePipelineParameters`
11849
11893
  */
11850
11894
  function isParameterDefinedByAnyTask(parameter, tasks) {
11851
11895
  return tasks.some((task) => task.resultingParameterName === parameter.name);
11852
11896
  }
11897
+
11898
+ /**
11899
+ * Validates all pipeline tasks and their per-task invariants.
11900
+ *
11901
+ * @private function of `validatePipeline`
11902
+ */
11903
+ function validatePipelineTasks({ pipeline, pipelineIdentification }) {
11904
+ // Note: All input parameters are defined - so that they can be used as result of some task
11905
+ const definedParameters = createInitiallyDefinedParameters(pipeline);
11906
+ for (const task of pipeline.tasks) {
11907
+ validatePipelineTask(task, definedParameters, pipelineIdentification);
11908
+ }
11909
+ }
11853
11910
  /**
11854
11911
  * Collects the parameter names that are already defined before task validation starts.
11855
11912
  *
11856
- * @private internal utility of `validatePipeline`
11913
+ * @private internal utility of `validatePipelineTasks`
11857
11914
  */
11858
11915
  function createInitiallyDefinedParameters(pipeline) {
11859
11916
  return new Set(pipeline.parameters.filter(({ isInput }) => isInput).map(({ name }) => name));
11860
11917
  }
11918
+ /**
11919
+ * Validates one pipeline task and its invariants.
11920
+ *
11921
+ * @private internal utility of `validatePipelineTasks`
11922
+ */
11923
+ function validatePipelineTask(task, definedParameters, pipelineIdentification) {
11924
+ validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
11925
+ validateTaskJokers(task, pipelineIdentification);
11926
+ validateTaskExpectations(task, pipelineIdentification);
11927
+ }
11861
11928
  /**
11862
11929
  * Validates one task result parameter declaration and marks it as defined.
11863
11930
  *
11864
- * @private internal utility of `validatePipeline`
11931
+ * @private internal utility of `validatePipelineTasks`
11865
11932
  */
11866
11933
  function validateTaskResultingParameter(task, definedParameters, pipelineIdentification) {
11867
11934
  if (definedParameters.has(task.resultingParameterName)) {
@@ -11883,7 +11950,7 @@
11883
11950
  /**
11884
11951
  * Validates joker parameters for one task.
11885
11952
  *
11886
- * @private internal utility of `validatePipeline`
11953
+ * @private internal utility of `validatePipelineTasks`
11887
11954
  */
11888
11955
  function validateTaskJokers(task, pipelineIdentification) {
11889
11956
  if (!hasTaskJokers(task)) {
@@ -11895,7 +11962,7 @@
11895
11962
  /**
11896
11963
  * Checks whether one task declares any joker parameters.
11897
11964
  *
11898
- * @private internal utility of `validatePipeline`
11965
+ * @private internal utility of `validatePipelineTasks`
11899
11966
  */
11900
11967
  function hasTaskJokers(task) {
11901
11968
  return !!task.jokerParameterNames && task.jokerParameterNames.length > 0;
@@ -11903,7 +11970,7 @@
11903
11970
  /**
11904
11971
  * Validates that a task has the required supporting features when using jokers.
11905
11972
  *
11906
- * @private internal utility of `validatePipeline`
11973
+ * @private internal utility of `validatePipelineTasks`
11907
11974
  */
11908
11975
  function validateTaskSupportsJokers(task, pipelineIdentification) {
11909
11976
  if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
@@ -11918,7 +11985,7 @@
11918
11985
  /**
11919
11986
  * Validates that every joker parameter is also listed among task dependencies.
11920
11987
  *
11921
- * @private internal utility of `validatePipeline`
11988
+ * @private internal utility of `validatePipelineTasks`
11922
11989
  */
11923
11990
  function validateTaskJokerDependencies(task, pipelineIdentification) {
11924
11991
  for (const joker of task.jokerParameterNames) {
@@ -11935,7 +12002,7 @@
11935
12002
  /**
11936
12003
  * Validates all expectation bounds configured on one task.
11937
12004
  *
11938
- * @private internal utility of `validatePipeline`
12005
+ * @private internal utility of `validatePipelineTasks`
11939
12006
  */
11940
12007
  function validateTaskExpectations(task, pipelineIdentification) {
11941
12008
  if (!task.expectations) {
@@ -11950,7 +12017,7 @@
11950
12017
  /**
11951
12018
  * Validates the minimum and maximum expectation ordering for one unit.
11952
12019
  *
11953
- * @private internal utility of `validatePipeline`
12020
+ * @private internal utility of `validatePipelineTasks`
11954
12021
  */
11955
12022
  function validateTaskExpectationRange(unit, min, max, pipelineIdentification) {
11956
12023
  if (min === undefined || max === undefined || min <= max) {
@@ -11965,7 +12032,7 @@
11965
12032
  /**
11966
12033
  * Validates the minimum expectation bound for one unit.
11967
12034
  *
11968
- * @private internal utility of `validatePipeline`
12035
+ * @private internal utility of `validatePipelineTasks`
11969
12036
  */
11970
12037
  function validateTaskExpectationMin(unit, min, pipelineIdentification) {
11971
12038
  if (min === undefined || min >= 0) {
@@ -11980,7 +12047,7 @@
11980
12047
  /**
11981
12048
  * Validates the maximum expectation bound for one unit.
11982
12049
  *
11983
- * @private internal utility of `validatePipeline`
12050
+ * @private internal utility of `validatePipelineTasks`
11984
12051
  */
11985
12052
  function validateTaskExpectationMax(unit, max, pipelineIdentification) {
11986
12053
  if (max === undefined || max > 0) {
@@ -11992,123 +12059,62 @@
11992
12059
  ${block(pipelineIdentification)}
11993
12060
  `));
11994
12061
  }
12062
+
11995
12063
  /**
11996
- * Collects the parameter names that are already resolvable before dependency traversal starts.
11997
- *
11998
- * @private internal utility of `validatePipeline`
11999
- */
12000
- function createInitialDependencyResolutionState(pipeline) {
12001
- return {
12002
- resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
12003
- unresolvedTasks: [...pipeline.tasks],
12004
- };
12005
- }
12006
- /**
12007
- * Checks whether dependency resolution still has tasks left to process.
12008
- *
12009
- * @private internal utility of `validatePipeline`
12010
- */
12011
- function hasUnresolvedTasks({ unresolvedTasks }) {
12012
- return unresolvedTasks.length > 0;
12013
- }
12014
- /**
12015
- * Resolves the next batch of currently satisfiable tasks.
12064
+ * Validates PipelineJson if it is logically valid
12016
12065
  *
12017
- * @private internal utility of `validatePipeline`
12018
- */
12019
- function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
12020
- const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
12021
- if (currentlyResolvedTasks.length === 0) {
12022
- throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
12023
- }
12024
- return {
12025
- resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
12026
- unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
12027
- };
12028
- }
12029
- /**
12030
- * Collects the parameter names that are already resolvable before dependency traversal starts.
12066
+ * It checks:
12067
+ * - if it has correct parameters dependency
12031
12068
  *
12032
- * @private internal utility of `validatePipeline`
12033
- */
12034
- function createInitiallyResolvedParameterNames(pipeline) {
12035
- let resolvedParameterNames = pipeline.parameters
12036
- .filter(({ isInput }) => isInput)
12037
- .map(({ name }) => name);
12038
- for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
12039
- resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
12040
- }
12041
- return resolvedParameterNames;
12042
- }
12043
- /**
12044
- * Adds newly resolved task outputs to the resolved parameter list.
12069
+ * It does NOT check:
12070
+ * - if it is valid json
12071
+ * - if it is meaningful
12045
12072
  *
12046
- * @private internal utility of `validatePipeline`
12047
- */
12048
- function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
12049
- return [
12050
- ...resolvedParameterNames,
12051
- ...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
12052
- ];
12053
- }
12054
- /**
12055
- * Selects tasks whose dependencies are already resolved.
12073
+ * Note: [🔂] This function is idempotent.
12056
12074
  *
12057
- * @private internal utility of `validatePipeline`
12058
- */
12059
- function getCurrentlyResolvedTasks(unresolvedTasks, resolvedParameterNames) {
12060
- return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
12061
- }
12062
- /**
12063
- * Creates the unexpected loop-limit error for dependency resolution.
12075
+ * @param pipeline valid or invalid PipelineJson
12076
+ * @returns the same pipeline if it is logically valid
12077
+ * @throws {PipelineLogicError} on logical error in the pipeline
12064
12078
  *
12065
- * @private internal utility of `validatePipeline`
12079
+ * @public exported from `@promptbook/core`
12066
12080
  */
12067
- function createDependencyResolutionLoopLimitError(pipelineIdentification) {
12068
- // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
12069
- return new UnexpectedError(_spaceTrim.spaceTrim((block) => `
12070
- Loop limit reached during detection of circular dependencies in \`validatePipeline\`
12081
+ function validatePipeline(pipeline) {
12082
+ if (IS_PIPELINE_LOGIC_VALIDATED) {
12083
+ validatePipeline_InnerFunction(pipeline);
12084
+ }
12085
+ else {
12086
+ try {
12087
+ validatePipeline_InnerFunction(pipeline);
12088
+ }
12089
+ catch (error) {
12090
+ if (!(error instanceof PipelineLogicError)) {
12091
+ throw error;
12092
+ }
12093
+ console.error(_spaceTrim.spaceTrim((block) => `
12094
+ Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
12071
12095
 
12072
- ${block(pipelineIdentification)}
12073
- `));
12096
+ ${block(error.message)}
12097
+ `));
12098
+ }
12099
+ }
12100
+ return pipeline;
12074
12101
  }
12075
12102
  /**
12076
- * Creates the detailed error for unresolved or circular task dependencies.
12103
+ * Validates pipeline inner function.
12077
12104
  *
12078
- * @private internal utility of `validatePipeline`
12105
+ * @private internal function for `validatePipeline`
12079
12106
  */
12080
- function createUnresolvedTasksError(unresolvedTasks, resolvedParameterNames, pipelineIdentification) {
12081
- return new PipelineLogicError(
12082
- // TODO: [🐎] DRY
12083
- _spaceTrim.spaceTrim((block) => `
12084
-
12085
- Can not resolve some parameters:
12086
- Either you are using a parameter that is not defined, or there are some circular dependencies.
12087
-
12088
- ${block(pipelineIdentification)}
12089
-
12090
- **Can not resolve:**
12091
- ${block(unresolvedTasks
12092
- .map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
12093
- .map((dependentParameterName) => `\`{${dependentParameterName}}\``)
12094
- .join(' and ')}`)
12095
- .join('\n'))}
12096
-
12097
- **Resolved:**
12098
- ${block(resolvedParameterNames
12099
- .filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
12100
- .map((name) => `- Parameter \`{${name}}\``)
12101
- .join('\n'))}
12102
-
12103
-
12104
- **Reserved (which are available):**
12105
- ${block(resolvedParameterNames
12106
- .filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
12107
- .map((name) => `- Parameter \`{${name}}\``)
12108
- .join('\n'))}
12109
-
12110
-
12111
- `));
12107
+ function validatePipeline_InnerFunction(pipeline) {
12108
+ // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
12109
+ const context = createPipelineValidationContext(pipeline);
12110
+ validatePipelineMetadata(context);
12111
+ validatePipelineCollectionsStructure(context);
12112
+ validatePipelineParameters(context);
12113
+ validatePipelineTasks(context);
12114
+ validatePipelineDependencyResolution(context);
12115
+ // Note: Check that formfactor is corresponding to the pipeline interface
12116
+ // TODO: !!6 Implement this
12117
+ // pipeline.formfactorName
12112
12118
  }
12113
12119
  /**
12114
12120
  * TODO: [🧞‍♀️] Do not allow joker + foreach
@@ -20766,13 +20772,14 @@
20766
20772
  * META commitment definition
20767
20773
  *
20768
20774
  * The META commitment handles all meta-information about the agent such as:
20769
- * - META AVATAR: Sets the agent's built-in default avatar visual
20775
+ * - META AVATAR / META VISUAL: Sets the agent's built-in default avatar visual
20770
20776
  * - META IMAGE: Sets the agent's avatar/profile image URL
20771
20777
  * - META LINK: Provides profile/source links for the person the agent models
20772
20778
  * - META DOMAIN: Sets the canonical custom domain/host of the agent
20773
20779
  * - META TITLE: Sets the agent's display title
20774
20780
  * - META DESCRIPTION: Sets the agent's description
20775
20781
  * - META INPUT PLACEHOLDER: Sets chat input placeholder text
20782
+ * - META THINKING MESSAGE: Adds custom thinking placeholder variants
20776
20783
  * - META [ANYTHING]: Any other meta information in uppercase format
20777
20784
  *
20778
20785
  * These commitments are special because they don't affect the system message,
@@ -20781,13 +20788,14 @@
20781
20788
  * Example usage in agent source:
20782
20789
  *
20783
20790
  * ```book
20784
- * META AVATAR pixel-art
20791
+ * META VISUAL pixel-art
20785
20792
  * META IMAGE https://example.com/avatar.jpg
20786
20793
  * META LINK https://twitter.com/username
20787
20794
  * META DOMAIN my-agent.com
20788
20795
  * META TITLE Professional Assistant
20789
20796
  * META DESCRIPTION An AI assistant specialized in business tasks
20790
20797
  * META INPUT PLACEHOLDER Write a message...
20798
+ * META THINKING MESSAGE Thinking...
20791
20799
  * META AUTHOR John Doe
20792
20800
  * META VERSION 1.0
20793
20801
  * ```
@@ -20821,13 +20829,14 @@
20821
20829
 
20822
20830
  ## Supported META types
20823
20831
 
20824
- - **META AVATAR** - Sets the agent's built-in default avatar visual
20832
+ - **META AVATAR** / **META VISUAL** - Sets the agent's built-in default avatar visual
20825
20833
  - **META IMAGE** - Sets the agent's avatar/profile image URL
20826
20834
  - **META LINK** - Provides profile/source links for the person the agent models
20827
20835
  - **META DOMAIN** - Sets the canonical custom domain/host of the agent
20828
20836
  - **META TITLE** - Sets the agent's display title
20829
20837
  - **META DESCRIPTION** - Sets the agent's description
20830
20838
  - **META INPUT PLACEHOLDER** - Sets chat input placeholder text
20839
+ - **META THINKING MESSAGE** - Adds custom thinking placeholder variants
20831
20840
  - **META [ANYTHING]** - Any other meta information in uppercase format
20832
20841
 
20833
20842
  ## Key aspects
@@ -20836,6 +20845,7 @@
20836
20845
  - Used for visual representation and attribution in user interfaces
20837
20846
  - Multiple META commitments of different types can be used
20838
20847
  - Multiple META LINK commitments can be used for different social profiles
20848
+ - Multiple META THINKING MESSAGE commitments can be used for different thinking placeholder variants
20839
20849
  - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
20840
20850
 
20841
20851
  ## Examples
@@ -20845,7 +20855,7 @@
20845
20855
  \`\`\`book
20846
20856
  Professional Assistant
20847
20857
 
20848
- META AVATAR octopus3
20858
+ META VISUAL octopus3
20849
20859
  META IMAGE https://example.com/professional-avatar.jpg
20850
20860
  META TITLE Senior Business Consultant
20851
20861
  META DESCRIPTION Specialized in strategic planning and project management
@@ -24016,452 +24026,13 @@
24016
24026
  .padStart(2, '0');
24017
24027
  }
24018
24028
 
24019
- /* eslint-disable no-magic-numbers */
24020
- /**
24021
- * Light direction used by the organic 3D octopus shading.
24022
- *
24023
- * @private helper of `octopus3dAvatarVisual`
24024
- */
24025
- const LIGHT_DIRECTION$3 = normalizeVector3({
24026
- x: 0.48,
24027
- y: -0.62,
24028
- z: 0.94,
24029
- });
24030
- /**
24031
- * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
24032
- *
24033
- * @private helper of `octopus3dAvatarVisual`
24034
- */
24035
- const octopus3dStableStateCache = new WeakMap();
24036
- /**
24037
- * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
24038
- *
24039
- * @private helper of `octopus3dAvatarVisual`
24040
- */
24041
- function getOctopus3dStableState(createRandom) {
24042
- const cached = octopus3dStableStateCache.get(createRandom);
24043
- if (cached !== undefined) {
24044
- return cached;
24045
- }
24046
- const animationRandom = createRandom('octopus3d-animation-profile');
24047
- const eyeRandom = createRandom('octopus3d-eye-profile');
24048
- const leftEyePhaseOffset = eyeRandom() * 0.6;
24049
- const rightEyePhaseOffset = eyeRandom() * 0.6;
24050
- const state = {
24051
- morphologyProfile: createOctopus3MorphologyProfile(createRandom),
24052
- animationPhase: animationRandom() * Math.PI * 2,
24053
- leftEyePhaseOffset,
24054
- rightEyePhaseOffset,
24055
- };
24056
- octopus3dStableStateCache.set(createRandom, state);
24057
- return state;
24058
- }
24059
- /**
24060
- * Proper 3D Octopus visual built from projected organic meshes and tentacles.
24061
- *
24062
- * @private built-in avatar visual
24063
- */
24064
- const octopus3dAvatarVisual = {
24065
- id: 'octopus3d',
24066
- title: 'Octopus 3D',
24067
- description: 'Proper 3D octopus portrait with a turning silhouette, expressive eyes, and depth-sorted tentacles.',
24068
- isAnimated: true,
24069
- supportsPointerTracking: true,
24070
- render({ context, size, palette, createRandom, timeMs, interaction }) {
24071
- const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
24072
- const sceneCenterX = size * 0.5;
24073
- const sceneCenterY = size * 0.56;
24074
- const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
24075
- const mantleCenter = {
24076
- x: interaction.bodyOffsetX * size * 0.042 + size * morphologyProfile.body.centerXJitterRatio * 0.65,
24077
- y: -size * 0.09 + interaction.bodyOffsetY * size * 0.028 + bob,
24078
- z: interaction.intensity * size * 0.012,
24079
- };
24080
- const underbodyCenter = {
24081
- x: mantleCenter.x * 0.86,
24082
- y: mantleCenter.y + size * 0.168,
24083
- z: mantleCenter.z - size * 0.018,
24084
- };
24085
- const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
24086
- const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
24087
- const mantleRadiusZ = size *
24088
- morphologyProfile.body.bodyRadiusRatio *
24089
- (0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
24090
- const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
24091
- const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
24092
- const underbodyRadiusZ = mantleRadiusZ * 0.78;
24093
- const bodyYaw = -0.18 +
24094
- Math.sin(timeMs / 2400 + animationPhase) * 0.05 +
24095
- interaction.bodyOffsetX * 0.18 +
24096
- interaction.gazeX * 0.22;
24097
- const bodyPitch = -0.08 +
24098
- Math.cos(timeMs / 2700 + animationPhase * 0.6) * 0.025 -
24099
- interaction.bodyOffsetY * 0.08 -
24100
- interaction.gazeY * 0.08;
24101
- const headYaw = bodyYaw - 0.04 + interaction.gazeX * 0.56;
24102
- const headPitch = bodyPitch - 0.02 - interaction.gazeY * 0.32;
24103
- const mantlePatches = resolveVisibleEllipsoidPatches({
24104
- center: mantleCenter,
24105
- radiusX: mantleRadiusX,
24106
- radiusY: mantleRadiusY,
24107
- radiusZ: mantleRadiusZ,
24108
- rotationX: headPitch,
24109
- rotationY: headYaw,
24110
- sceneCenterX,
24111
- sceneCenterY,
24112
- size,
24113
- palette,
24114
- verticalColorBias: 0,
24115
- outlineColor: `${palette.highlight}7a`,
24116
- });
24117
- const underbodyPatches = resolveVisibleEllipsoidPatches({
24118
- center: underbodyCenter,
24119
- radiusX: underbodyRadiusX,
24120
- radiusY: underbodyRadiusY,
24121
- radiusZ: underbodyRadiusZ,
24122
- rotationX: bodyPitch,
24123
- rotationY: bodyYaw,
24124
- sceneCenterX,
24125
- sceneCenterY,
24126
- size,
24127
- palette,
24128
- verticalColorBias: 0.18,
24129
- outlineColor: `${palette.shadow}8f`,
24130
- });
24131
- const tentacleStrokes = createOctopusTentacleStrokes({
24132
- createRandom,
24133
- morphologyProfile,
24134
- timeMs,
24135
- size,
24136
- center: underbodyCenter,
24137
- radiusX: underbodyRadiusX,
24138
- radiusY: underbodyRadiusY,
24139
- radiusZ: underbodyRadiusZ,
24140
- rotationX: bodyPitch,
24141
- rotationY: bodyYaw,
24142
- sceneCenterX,
24143
- sceneCenterY,
24144
- animationPhase,
24145
- });
24146
- const faceEyeSpacing = size * morphologyProfile.face.eyeSpacingRatio * 0.92;
24147
- const faceEyeYOffset = size * morphologyProfile.face.eyeCenterYOffsetRatio - mantleRadiusY * 0.02;
24148
- const faceEyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.82;
24149
- const faceEyeRadiusY = faceEyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.96;
24150
- const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio * 0.92;
24151
- const mouthY = size * morphologyProfile.face.mouthYOffsetRatio + mantleRadiusY * 0.08;
24152
- drawAvatarFrame(context, size, palette);
24153
- drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
24154
- drawOctopus3dShadow(context, size, palette, interaction, timeMs);
24155
- for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => !candidateTentacleStroke.isFrontFacing)) {
24156
- drawTentacleStroke(context, tentacleStroke, palette);
24157
- }
24158
- for (const surfacePatch of [...mantlePatches, ...underbodyPatches].sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
24159
- drawSurfacePatch(context, surfacePatch);
24160
- }
24161
- for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
24162
- drawTentacleStroke(context, tentacleStroke, palette);
24163
- }
24164
- drawProjectedOrganicEye(context, {
24165
- x: -faceEyeSpacing,
24166
- y: faceEyeYOffset,
24167
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
24168
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
24169
- drawProjectedOrganicEye(context, {
24170
- x: faceEyeSpacing,
24171
- y: faceEyeYOffset,
24172
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
24173
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
24174
- drawProjectedOrganicMouth(context, [
24175
- {
24176
- x: -mouthHalfWidth,
24177
- y: mouthY,
24178
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
24179
- },
24180
- {
24181
- x: size * morphologyProfile.face.mouthCenterOffsetRatio,
24182
- y: mouthY +
24183
- size * morphologyProfile.face.mouthCurveDepthRatio * 0.38 +
24184
- Math.sin(timeMs / 760 + animationPhase) * size * 0.01 +
24185
- interaction.gazeY * size * 0.01,
24186
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
24187
- },
24188
- {
24189
- x: mouthHalfWidth,
24190
- y: mouthY,
24191
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
24192
- },
24193
- ], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
24194
- },
24195
- };
24196
- /**
24197
- * Draws the atmospheric underwater glow behind the octopus mesh.
24198
- *
24199
- * @private helper of `octopus3dAvatarVisual`
24200
- */
24201
- function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
24202
- const glowGradient = context.createRadialGradient(sceneCenterX + interaction.gazeX * size * 0.1, sceneCenterY - size * 0.2 + interaction.gazeY * size * 0.05, size * 0.04, sceneCenterX, sceneCenterY - size * 0.04, size * 0.62);
24203
- glowGradient.addColorStop(0, `${palette.highlight}5c`);
24204
- glowGradient.addColorStop(0.36, `${palette.accent}24`);
24205
- glowGradient.addColorStop(1, `${palette.highlight}00`);
24206
- context.fillStyle = glowGradient;
24207
- context.fillRect(0, 0, size, size);
24208
- const lowerGradient = context.createRadialGradient(sceneCenterX + Math.sin(timeMs / 1700) * size * 0.05, sceneCenterY + size * 0.23, size * 0.08, sceneCenterX, sceneCenterY + size * 0.28, size * 0.5);
24209
- lowerGradient.addColorStop(0, `${palette.secondary}1d`);
24210
- lowerGradient.addColorStop(1, `${palette.secondary}00`);
24211
- context.fillStyle = lowerGradient;
24212
- context.fillRect(0, 0, size, size);
24213
- }
24214
- /**
24215
- * Draws the soft ground shadow below the octopus.
24216
- *
24217
- * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
24218
- * blurry ellipse without triggering a costly software rasterization pass on every frame.
24219
- *
24220
- * @private helper of `octopus3dAvatarVisual`
24221
- */
24222
- function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
24223
- const cx = size * 0.5 + interaction.gazeX * size * 0.04;
24224
- const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
24225
- const rx = size * (0.18 + interaction.intensity * 0.02);
24226
- const ry = size * 0.06;
24227
- context.save();
24228
- context.translate(cx, cy);
24229
- context.scale(1, ry / rx);
24230
- const blurRadius = rx * 1.4;
24231
- const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
24232
- shadowGradient.addColorStop(0, `${palette.shadow}7a`);
24233
- shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
24234
- shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
24235
- shadowGradient.addColorStop(1, `${palette.shadow}00`);
24236
- context.fillStyle = shadowGradient;
24237
- context.beginPath();
24238
- context.arc(0, 0, blurRadius, 0, Math.PI * 2);
24239
- context.fill();
24240
- context.restore();
24241
- }
24242
- /**
24243
- * Resolves visible projected patches for one rotated ellipsoid mesh.
24244
- *
24245
- * @private helper of `octopus3dAvatarVisual`
24246
- */
24247
- function resolveVisibleEllipsoidPatches(options) {
24248
- const { center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, verticalColorBias, outlineColor, } = options;
24249
- const latitudePatchCount = 10;
24250
- const longitudePatchCount = 18;
24251
- const surfacePatches = [];
24252
- for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
24253
- const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
24254
- const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
24255
- const verticalProgress = (latitudeIndex + 0.5) / latitudePatchCount;
24256
- for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
24257
- const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
24258
- const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
24259
- const localCorners = [
24260
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, startLongitude),
24261
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, endLongitude),
24262
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, endLongitude),
24263
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, startLongitude),
24264
- ];
24265
- const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
24266
- const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
24267
- if (surfaceNormal.z <= 0.01) {
24268
- continue;
24269
- }
24270
- const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
24271
- surfacePatches.push({
24272
- corners: projectedCorners,
24273
- averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
24274
- transformedCorners.length,
24275
- lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$3), -1, 1),
24276
- fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
24277
- outlineColor,
24278
- });
24279
- }
24280
- }
24281
- return surfacePatches;
24282
- }
24283
- /**
24284
- * Samples one point on an ellipsoid aligned to the local axes.
24285
- *
24286
- * @private helper of `octopus3dAvatarVisual`
24287
- */
24288
- function sampleEllipsoidPoint(radiusX, radiusY, radiusZ, latitude, longitude) {
24289
- const cosineLatitude = Math.cos(latitude);
24290
- return {
24291
- x: Math.sin(longitude) * cosineLatitude * radiusX,
24292
- y: Math.sin(latitude) * radiusY,
24293
- z: Math.cos(longitude) * cosineLatitude * radiusZ,
24294
- };
24295
- }
24296
- /**
24297
- * Resolves one base fill tone for a surface patch across the octopus body.
24298
- *
24299
- * @private helper of `octopus3dAvatarVisual`
24300
- */
24301
- function resolveSurfacePatchFillStyle(palette, verticalProgress) {
24302
- const clampedVerticalProgress = clampNumber$1(verticalProgress, 0, 1);
24303
- if (clampedVerticalProgress < 0.2) {
24304
- return palette.highlight;
24305
- }
24306
- if (clampedVerticalProgress < 0.45) {
24307
- return palette.secondary;
24308
- }
24309
- if (clampedVerticalProgress < 0.8) {
24310
- return palette.primary;
24311
- }
24312
- return `${palette.shadow}f2`;
24313
- }
24314
- /**
24315
- * Draws one projected mesh patch with organic shading.
24316
- *
24317
- * @private helper of `octopus3dAvatarVisual`
24318
- */
24319
- function drawSurfacePatch(context, surfacePatch) {
24320
- drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
24321
- if (surfacePatch.lightIntensity > 0) {
24322
- drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.15 * surfacePatch.lightIntensity})`);
24323
- }
24324
- else if (surfacePatch.lightIntensity < 0) {
24325
- drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
24326
- }
24327
- context.save();
24328
- context.beginPath();
24329
- context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
24330
- for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
24331
- context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
24332
- }
24333
- context.closePath();
24334
- context.strokeStyle = surfacePatch.outlineColor;
24335
- context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0044);
24336
- context.lineJoin = 'round';
24337
- context.stroke();
24338
- context.restore();
24339
- }
24340
- /**
24341
- * Creates the projected 3D tentacle strokes orbiting around the lower octopus body.
24342
- *
24343
- * @private helper of `octopus3dAvatarVisual`
24344
- */
24345
- function createOctopusTentacleStrokes(options) {
24346
- const { createRandom, morphologyProfile, timeMs, size, center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, animationPhase, } = options;
24347
- return Array.from({ length: morphologyProfile.tentacles.count }, (_, tentacleIndex) => {
24348
- const tentacleRandom = createRandom(`octopus3d-tentacle-${tentacleIndex}`);
24349
- const spreadProgress = morphologyProfile.tentacles.count === 1 ? 0.5 : tentacleIndex / (morphologyProfile.tentacles.count - 1);
24350
- const orbitAngle = -Math.PI * 0.92 + spreadProgress * Math.PI * 1.84 + (tentacleRandom() - 0.5) * 0.16;
24351
- const flowLength = size * (0.19 + morphologyProfile.tentacles.flowLengthScale * 0.075 + tentacleRandom() * 0.018);
24352
- const lateralReach = size *
24353
- (0.08 + morphologyProfile.tentacles.lateralReachScale * 0.05 + Math.abs(Math.sin(orbitAngle)) * 0.018);
24354
- const depthReach = size * (0.028 + morphologyProfile.tentacles.tipReachScale * 0.032);
24355
- const sway = Math.sin(timeMs / (760 + tentacleIndex * 36) + animationPhase + tentacleRandom() * Math.PI * 2);
24356
- const anchorPoint = {
24357
- x: Math.sin(orbitAngle) * radiusX * (0.84 + tentacleRandom() * 0.08),
24358
- y: radiusY * (0.22 + tentacleRandom() * 0.18),
24359
- z: Math.cos(orbitAngle) * radiusZ * (0.72 + tentacleRandom() * 0.12),
24360
- };
24361
- const controlPointOne = {
24362
- x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * 0.44,
24363
- y: anchorPoint.y + flowLength * 0.26,
24364
- z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
24365
- };
24366
- const controlPointTwo = {
24367
- x: anchorPoint.x +
24368
- Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
24369
- y: anchorPoint.y + flowLength * 0.66,
24370
- z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
24371
- };
24372
- const endPoint = {
24373
- x: anchorPoint.x +
24374
- Math.sin(orbitAngle) * lateralReach * (1.02 + morphologyProfile.tentacles.tipWidthScale * 0.12) +
24375
- sway * size * 0.028,
24376
- y: anchorPoint.y + flowLength,
24377
- z: anchorPoint.z + Math.cos(orbitAngle) * depthReach + sway * size * 0.016,
24378
- };
24379
- const scenePoints = Array.from({ length: 12 }, (_, sampleIndex) => transformScenePoint(sampleCubicBezierPoint3D(anchorPoint, controlPointOne, controlPointTwo, endPoint, sampleIndex / 11), center, rotationX, rotationY));
24380
- const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
24381
- const averageDepth = scenePoints.reduce((depthSum, scenePoint) => depthSum + scenePoint.z, 0) / scenePoints.length;
24382
- return {
24383
- projectedPoints,
24384
- averageDepth,
24385
- isFrontFacing: averageDepth >= center.z - size * 0.006,
24386
- baseWidth: size *
24387
- (0.019 +
24388
- morphologyProfile.tentacles.baseWidthScale * 0.007 +
24389
- tentacleRandom() * 0.003 +
24390
- Math.abs(Math.sin(orbitAngle)) * 0.002),
24391
- tipWidth: size * (0.0046 + morphologyProfile.tentacles.tipWidthScale * 0.0018),
24392
- colorBias: tentacleRandom(),
24393
- };
24394
- });
24395
- }
24396
- /**
24397
- * Samples one point on a cubic Bezier curve in 3D.
24398
- *
24399
- * @private helper of `octopus3dAvatarVisual`
24400
- */
24401
- function sampleCubicBezierPoint3D(startPoint, controlPointOne, controlPointTwo, endPoint, progress) {
24402
- const inverseProgress = 1 - progress;
24403
- return {
24404
- x: inverseProgress * inverseProgress * inverseProgress * startPoint.x +
24405
- 3 * inverseProgress * inverseProgress * progress * controlPointOne.x +
24406
- 3 * inverseProgress * progress * progress * controlPointTwo.x +
24407
- progress * progress * progress * endPoint.x,
24408
- y: inverseProgress * inverseProgress * inverseProgress * startPoint.y +
24409
- 3 * inverseProgress * inverseProgress * progress * controlPointOne.y +
24410
- 3 * inverseProgress * progress * progress * controlPointTwo.y +
24411
- progress * progress * progress * endPoint.y,
24412
- z: inverseProgress * inverseProgress * inverseProgress * startPoint.z +
24413
- 3 * inverseProgress * inverseProgress * progress * controlPointOne.z +
24414
- 3 * inverseProgress * progress * progress * controlPointTwo.z +
24415
- progress * progress * progress * endPoint.z,
24416
- };
24417
- }
24418
- /**
24419
- * Draws one projected tentacle stroke with a slim highlight ridge.
24420
- *
24421
- * @private helper of `octopus3dAvatarVisual`
24422
- */
24423
- function drawTentacleStroke(context, tentacleStroke, palette) {
24424
- const projectedSegments = tentacleStroke.projectedPoints.length - 1;
24425
- for (let segmentIndex = 0; segmentIndex < projectedSegments; segmentIndex++) {
24426
- const startPoint = tentacleStroke.projectedPoints[segmentIndex];
24427
- const endPoint = tentacleStroke.projectedPoints[segmentIndex + 1];
24428
- const progress = segmentIndex / projectedSegments;
24429
- const width = tentacleStroke.baseWidth + (tentacleStroke.tipWidth - tentacleStroke.baseWidth) * progress;
24430
- context.beginPath();
24431
- context.moveTo(startPoint.x, startPoint.y);
24432
- context.lineTo(endPoint.x, endPoint.y);
24433
- context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
24434
- context.lineWidth = width;
24435
- context.lineCap = 'round';
24436
- context.stroke();
24437
- context.beginPath();
24438
- context.moveTo(startPoint.x, startPoint.y);
24439
- context.lineTo(endPoint.x, endPoint.y);
24440
- context.strokeStyle = tentacleStroke.isFrontFacing ? `${palette.highlight}80` : `${palette.highlight}40`;
24441
- context.lineWidth = Math.max(1, width * 0.34);
24442
- context.lineCap = 'round';
24443
- context.stroke();
24444
- }
24445
- }
24446
- /**
24447
- * Resolves the front surface depth on an ellipsoid for one local face point.
24448
- *
24449
- * @private helper of `octopus3dAvatarVisual`
24450
- */
24451
- function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
24452
- const normalizedX = x / radiusX;
24453
- const normalizedY = y / radiusY;
24454
- const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
24455
- return Math.sqrt(remainingDepthRatio) * radiusZ;
24456
- }
24457
-
24458
24029
  /* eslint-disable no-magic-numbers */
24459
24030
  /**
24460
24031
  * Light direction used by the single-mesh octopus shading.
24461
24032
  *
24462
24033
  * @private helper of `octopus3d2AvatarVisual`
24463
24034
  */
24464
- const LIGHT_DIRECTION$2 = normalizeVector3({
24035
+ const LIGHT_DIRECTION$3 = normalizeVector3({
24465
24036
  x: 0.38,
24466
24037
  y: -0.6,
24467
24038
  z: 0.98,
@@ -24700,7 +24271,7 @@
24700
24271
  transformedCorners[2].z +
24701
24272
  transformedCorners[3].z) /
24702
24273
  4,
24703
- lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$2), -1, 1),
24274
+ lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$3), -1, 1),
24704
24275
  fillStyle: resolveBlobbySurfacePatchFillStyle$1(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
24705
24276
  outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
24706
24277
  });
@@ -24815,7 +24386,7 @@
24815
24386
  *
24816
24387
  * @private helper of `octopus3d3AvatarVisual`
24817
24388
  */
24818
- const LIGHT_DIRECTION$1 = normalizeVector3({
24389
+ const LIGHT_DIRECTION$2 = normalizeVector3({
24819
24390
  x: 0.34,
24820
24391
  y: -0.62,
24821
24392
  z: 1,
@@ -25122,7 +24693,7 @@
25122
24693
  transformedCorners[2].z +
25123
24694
  transformedCorners[3].z) /
25124
24695
  4,
25125
- lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
24696
+ lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$2), -1, 1),
25126
24697
  fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, cachedCosByPatchCenterLongitude[longitudeIndex], cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex].core, cachedLobeWavesByPatchCenterLongitude[longitudeIndex]),
25127
24698
  outlineColor: verticalProgress < 0.54 ? `${palette.highlight}69` : `${palette.shadow}78`,
25128
24699
  });
@@ -25437,7 +25008,7 @@
25437
25008
  *
25438
25009
  * @private helper of `octopus3d4AvatarVisual`
25439
25010
  */
25440
- const LIGHT_DIRECTION = normalizeVector3({
25011
+ const LIGHT_DIRECTION$1 = normalizeVector3({
25441
25012
  x: 0.32,
25442
25013
  y: -0.66,
25443
25014
  z: 1,
@@ -25783,7 +25354,7 @@
25783
25354
  projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
25784
25355
  projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
25785
25356
  ];
25786
- const lightIntensity = clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1);
25357
+ const lightIntensity = clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1);
25787
25358
  const rimLightIntensity = Math.pow(clampNumber$1(dotProduct3D(surfaceNormal, RIM_LIGHT_DIRECTION), 0, 1), 2.6);
25788
25359
  surfacePatches.push({
25789
25360
  corners: projectedCorners,
@@ -26182,6 +25753,445 @@
26182
25753
  .padStart(2, '0');
26183
25754
  }
26184
25755
 
25756
+ /* eslint-disable no-magic-numbers */
25757
+ /**
25758
+ * Light direction used by the organic 3D octopus shading.
25759
+ *
25760
+ * @private helper of `octopus3dAvatarVisual`
25761
+ */
25762
+ const LIGHT_DIRECTION = normalizeVector3({
25763
+ x: 0.48,
25764
+ y: -0.62,
25765
+ z: 0.94,
25766
+ });
25767
+ /**
25768
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
25769
+ *
25770
+ * @private helper of `octopus3dAvatarVisual`
25771
+ */
25772
+ const octopus3dStableStateCache = new WeakMap();
25773
+ /**
25774
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
25775
+ *
25776
+ * @private helper of `octopus3dAvatarVisual`
25777
+ */
25778
+ function getOctopus3dStableState(createRandom) {
25779
+ const cached = octopus3dStableStateCache.get(createRandom);
25780
+ if (cached !== undefined) {
25781
+ return cached;
25782
+ }
25783
+ const animationRandom = createRandom('octopus3d-animation-profile');
25784
+ const eyeRandom = createRandom('octopus3d-eye-profile');
25785
+ const leftEyePhaseOffset = eyeRandom() * 0.6;
25786
+ const rightEyePhaseOffset = eyeRandom() * 0.6;
25787
+ const state = {
25788
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
25789
+ animationPhase: animationRandom() * Math.PI * 2,
25790
+ leftEyePhaseOffset,
25791
+ rightEyePhaseOffset,
25792
+ };
25793
+ octopus3dStableStateCache.set(createRandom, state);
25794
+ return state;
25795
+ }
25796
+ /**
25797
+ * Proper 3D Octopus visual built from projected organic meshes and tentacles.
25798
+ *
25799
+ * @private built-in avatar visual
25800
+ */
25801
+ const octopus3dAvatarVisual = {
25802
+ id: 'octopus3d',
25803
+ title: 'Octopus 3D',
25804
+ description: 'Proper 3D octopus portrait with a turning silhouette, expressive eyes, and depth-sorted tentacles.',
25805
+ isAnimated: true,
25806
+ supportsPointerTracking: true,
25807
+ render({ context, size, palette, createRandom, timeMs, interaction }) {
25808
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
25809
+ const sceneCenterX = size * 0.5;
25810
+ const sceneCenterY = size * 0.56;
25811
+ const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
25812
+ const mantleCenter = {
25813
+ x: interaction.bodyOffsetX * size * 0.042 + size * morphologyProfile.body.centerXJitterRatio * 0.65,
25814
+ y: -size * 0.09 + interaction.bodyOffsetY * size * 0.028 + bob,
25815
+ z: interaction.intensity * size * 0.012,
25816
+ };
25817
+ const underbodyCenter = {
25818
+ x: mantleCenter.x * 0.86,
25819
+ y: mantleCenter.y + size * 0.168,
25820
+ z: mantleCenter.z - size * 0.018,
25821
+ };
25822
+ const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
25823
+ const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
25824
+ const mantleRadiusZ = size *
25825
+ morphologyProfile.body.bodyRadiusRatio *
25826
+ (0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
25827
+ const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
25828
+ const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
25829
+ const underbodyRadiusZ = mantleRadiusZ * 0.78;
25830
+ const bodyYaw = -0.18 +
25831
+ Math.sin(timeMs / 2400 + animationPhase) * 0.05 +
25832
+ interaction.bodyOffsetX * 0.18 +
25833
+ interaction.gazeX * 0.22;
25834
+ const bodyPitch = -0.08 +
25835
+ Math.cos(timeMs / 2700 + animationPhase * 0.6) * 0.025 -
25836
+ interaction.bodyOffsetY * 0.08 -
25837
+ interaction.gazeY * 0.08;
25838
+ const headYaw = bodyYaw - 0.04 + interaction.gazeX * 0.56;
25839
+ const headPitch = bodyPitch - 0.02 - interaction.gazeY * 0.32;
25840
+ const mantlePatches = resolveVisibleEllipsoidPatches({
25841
+ center: mantleCenter,
25842
+ radiusX: mantleRadiusX,
25843
+ radiusY: mantleRadiusY,
25844
+ radiusZ: mantleRadiusZ,
25845
+ rotationX: headPitch,
25846
+ rotationY: headYaw,
25847
+ sceneCenterX,
25848
+ sceneCenterY,
25849
+ size,
25850
+ palette,
25851
+ verticalColorBias: 0,
25852
+ outlineColor: `${palette.highlight}7a`,
25853
+ });
25854
+ const underbodyPatches = resolveVisibleEllipsoidPatches({
25855
+ center: underbodyCenter,
25856
+ radiusX: underbodyRadiusX,
25857
+ radiusY: underbodyRadiusY,
25858
+ radiusZ: underbodyRadiusZ,
25859
+ rotationX: bodyPitch,
25860
+ rotationY: bodyYaw,
25861
+ sceneCenterX,
25862
+ sceneCenterY,
25863
+ size,
25864
+ palette,
25865
+ verticalColorBias: 0.18,
25866
+ outlineColor: `${palette.shadow}8f`,
25867
+ });
25868
+ const tentacleStrokes = createOctopusTentacleStrokes({
25869
+ createRandom,
25870
+ morphologyProfile,
25871
+ timeMs,
25872
+ size,
25873
+ center: underbodyCenter,
25874
+ radiusX: underbodyRadiusX,
25875
+ radiusY: underbodyRadiusY,
25876
+ radiusZ: underbodyRadiusZ,
25877
+ rotationX: bodyPitch,
25878
+ rotationY: bodyYaw,
25879
+ sceneCenterX,
25880
+ sceneCenterY,
25881
+ animationPhase,
25882
+ });
25883
+ const faceEyeSpacing = size * morphologyProfile.face.eyeSpacingRatio * 0.92;
25884
+ const faceEyeYOffset = size * morphologyProfile.face.eyeCenterYOffsetRatio - mantleRadiusY * 0.02;
25885
+ const faceEyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.82;
25886
+ const faceEyeRadiusY = faceEyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.96;
25887
+ const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio * 0.92;
25888
+ const mouthY = size * morphologyProfile.face.mouthYOffsetRatio + mantleRadiusY * 0.08;
25889
+ drawAvatarFrame(context, size, palette);
25890
+ drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
25891
+ drawOctopus3dShadow(context, size, palette, interaction, timeMs);
25892
+ for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => !candidateTentacleStroke.isFrontFacing)) {
25893
+ drawTentacleStroke(context, tentacleStroke, palette);
25894
+ }
25895
+ for (const surfacePatch of [...mantlePatches, ...underbodyPatches].sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
25896
+ drawSurfacePatch(context, surfacePatch);
25897
+ }
25898
+ for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
25899
+ drawTentacleStroke(context, tentacleStroke, palette);
25900
+ }
25901
+ drawProjectedOrganicEye(context, {
25902
+ x: -faceEyeSpacing,
25903
+ y: faceEyeYOffset,
25904
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
25905
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
25906
+ drawProjectedOrganicEye(context, {
25907
+ x: faceEyeSpacing,
25908
+ y: faceEyeYOffset,
25909
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
25910
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
25911
+ drawProjectedOrganicMouth(context, [
25912
+ {
25913
+ x: -mouthHalfWidth,
25914
+ y: mouthY,
25915
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
25916
+ },
25917
+ {
25918
+ x: size * morphologyProfile.face.mouthCenterOffsetRatio,
25919
+ y: mouthY +
25920
+ size * morphologyProfile.face.mouthCurveDepthRatio * 0.38 +
25921
+ Math.sin(timeMs / 760 + animationPhase) * size * 0.01 +
25922
+ interaction.gazeY * size * 0.01,
25923
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
25924
+ },
25925
+ {
25926
+ x: mouthHalfWidth,
25927
+ y: mouthY,
25928
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
25929
+ },
25930
+ ], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
25931
+ },
25932
+ };
25933
+ /**
25934
+ * Draws the atmospheric underwater glow behind the octopus mesh.
25935
+ *
25936
+ * @private helper of `octopus3dAvatarVisual`
25937
+ */
25938
+ function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
25939
+ const glowGradient = context.createRadialGradient(sceneCenterX + interaction.gazeX * size * 0.1, sceneCenterY - size * 0.2 + interaction.gazeY * size * 0.05, size * 0.04, sceneCenterX, sceneCenterY - size * 0.04, size * 0.62);
25940
+ glowGradient.addColorStop(0, `${palette.highlight}5c`);
25941
+ glowGradient.addColorStop(0.36, `${palette.accent}24`);
25942
+ glowGradient.addColorStop(1, `${palette.highlight}00`);
25943
+ context.fillStyle = glowGradient;
25944
+ context.fillRect(0, 0, size, size);
25945
+ const lowerGradient = context.createRadialGradient(sceneCenterX + Math.sin(timeMs / 1700) * size * 0.05, sceneCenterY + size * 0.23, size * 0.08, sceneCenterX, sceneCenterY + size * 0.28, size * 0.5);
25946
+ lowerGradient.addColorStop(0, `${palette.secondary}1d`);
25947
+ lowerGradient.addColorStop(1, `${palette.secondary}00`);
25948
+ context.fillStyle = lowerGradient;
25949
+ context.fillRect(0, 0, size, size);
25950
+ }
25951
+ /**
25952
+ * Draws the soft ground shadow below the octopus.
25953
+ *
25954
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
25955
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
25956
+ *
25957
+ * @private helper of `octopus3dAvatarVisual`
25958
+ */
25959
+ function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
25960
+ const cx = size * 0.5 + interaction.gazeX * size * 0.04;
25961
+ const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
25962
+ const rx = size * (0.18 + interaction.intensity * 0.02);
25963
+ const ry = size * 0.06;
25964
+ context.save();
25965
+ context.translate(cx, cy);
25966
+ context.scale(1, ry / rx);
25967
+ const blurRadius = rx * 1.4;
25968
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
25969
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
25970
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
25971
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
25972
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
25973
+ context.fillStyle = shadowGradient;
25974
+ context.beginPath();
25975
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
25976
+ context.fill();
25977
+ context.restore();
25978
+ }
25979
+ /**
25980
+ * Resolves visible projected patches for one rotated ellipsoid mesh.
25981
+ *
25982
+ * @private helper of `octopus3dAvatarVisual`
25983
+ */
25984
+ function resolveVisibleEllipsoidPatches(options) {
25985
+ const { center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, verticalColorBias, outlineColor, } = options;
25986
+ const latitudePatchCount = 10;
25987
+ const longitudePatchCount = 18;
25988
+ const surfacePatches = [];
25989
+ for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
25990
+ const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
25991
+ const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
25992
+ const verticalProgress = (latitudeIndex + 0.5) / latitudePatchCount;
25993
+ for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
25994
+ const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
25995
+ const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
25996
+ const localCorners = [
25997
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, startLongitude),
25998
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, endLongitude),
25999
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, endLongitude),
26000
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, startLongitude),
26001
+ ];
26002
+ const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
26003
+ const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
26004
+ if (surfaceNormal.z <= 0.01) {
26005
+ continue;
26006
+ }
26007
+ const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
26008
+ surfacePatches.push({
26009
+ corners: projectedCorners,
26010
+ averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
26011
+ transformedCorners.length,
26012
+ lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
26013
+ fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
26014
+ outlineColor,
26015
+ });
26016
+ }
26017
+ }
26018
+ return surfacePatches;
26019
+ }
26020
+ /**
26021
+ * Samples one point on an ellipsoid aligned to the local axes.
26022
+ *
26023
+ * @private helper of `octopus3dAvatarVisual`
26024
+ */
26025
+ function sampleEllipsoidPoint(radiusX, radiusY, radiusZ, latitude, longitude) {
26026
+ const cosineLatitude = Math.cos(latitude);
26027
+ return {
26028
+ x: Math.sin(longitude) * cosineLatitude * radiusX,
26029
+ y: Math.sin(latitude) * radiusY,
26030
+ z: Math.cos(longitude) * cosineLatitude * radiusZ,
26031
+ };
26032
+ }
26033
+ /**
26034
+ * Resolves one base fill tone for a surface patch across the octopus body.
26035
+ *
26036
+ * @private helper of `octopus3dAvatarVisual`
26037
+ */
26038
+ function resolveSurfacePatchFillStyle(palette, verticalProgress) {
26039
+ const clampedVerticalProgress = clampNumber$1(verticalProgress, 0, 1);
26040
+ if (clampedVerticalProgress < 0.2) {
26041
+ return palette.highlight;
26042
+ }
26043
+ if (clampedVerticalProgress < 0.45) {
26044
+ return palette.secondary;
26045
+ }
26046
+ if (clampedVerticalProgress < 0.8) {
26047
+ return palette.primary;
26048
+ }
26049
+ return `${palette.shadow}f2`;
26050
+ }
26051
+ /**
26052
+ * Draws one projected mesh patch with organic shading.
26053
+ *
26054
+ * @private helper of `octopus3dAvatarVisual`
26055
+ */
26056
+ function drawSurfacePatch(context, surfacePatch) {
26057
+ drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
26058
+ if (surfacePatch.lightIntensity > 0) {
26059
+ drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.15 * surfacePatch.lightIntensity})`);
26060
+ }
26061
+ else if (surfacePatch.lightIntensity < 0) {
26062
+ drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
26063
+ }
26064
+ context.save();
26065
+ context.beginPath();
26066
+ context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
26067
+ for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
26068
+ context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
26069
+ }
26070
+ context.closePath();
26071
+ context.strokeStyle = surfacePatch.outlineColor;
26072
+ context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0044);
26073
+ context.lineJoin = 'round';
26074
+ context.stroke();
26075
+ context.restore();
26076
+ }
26077
+ /**
26078
+ * Creates the projected 3D tentacle strokes orbiting around the lower octopus body.
26079
+ *
26080
+ * @private helper of `octopus3dAvatarVisual`
26081
+ */
26082
+ function createOctopusTentacleStrokes(options) {
26083
+ const { createRandom, morphologyProfile, timeMs, size, center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, animationPhase, } = options;
26084
+ return Array.from({ length: morphologyProfile.tentacles.count }, (_, tentacleIndex) => {
26085
+ const tentacleRandom = createRandom(`octopus3d-tentacle-${tentacleIndex}`);
26086
+ const spreadProgress = morphologyProfile.tentacles.count === 1 ? 0.5 : tentacleIndex / (morphologyProfile.tentacles.count - 1);
26087
+ const orbitAngle = -Math.PI * 0.92 + spreadProgress * Math.PI * 1.84 + (tentacleRandom() - 0.5) * 0.16;
26088
+ const flowLength = size * (0.19 + morphologyProfile.tentacles.flowLengthScale * 0.075 + tentacleRandom() * 0.018);
26089
+ const lateralReach = size *
26090
+ (0.08 + morphologyProfile.tentacles.lateralReachScale * 0.05 + Math.abs(Math.sin(orbitAngle)) * 0.018);
26091
+ const depthReach = size * (0.028 + morphologyProfile.tentacles.tipReachScale * 0.032);
26092
+ const sway = Math.sin(timeMs / (760 + tentacleIndex * 36) + animationPhase + tentacleRandom() * Math.PI * 2);
26093
+ const anchorPoint = {
26094
+ x: Math.sin(orbitAngle) * radiusX * (0.84 + tentacleRandom() * 0.08),
26095
+ y: radiusY * (0.22 + tentacleRandom() * 0.18),
26096
+ z: Math.cos(orbitAngle) * radiusZ * (0.72 + tentacleRandom() * 0.12),
26097
+ };
26098
+ const controlPointOne = {
26099
+ x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * 0.44,
26100
+ y: anchorPoint.y + flowLength * 0.26,
26101
+ z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
26102
+ };
26103
+ const controlPointTwo = {
26104
+ x: anchorPoint.x +
26105
+ Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
26106
+ y: anchorPoint.y + flowLength * 0.66,
26107
+ z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
26108
+ };
26109
+ const endPoint = {
26110
+ x: anchorPoint.x +
26111
+ Math.sin(orbitAngle) * lateralReach * (1.02 + morphologyProfile.tentacles.tipWidthScale * 0.12) +
26112
+ sway * size * 0.028,
26113
+ y: anchorPoint.y + flowLength,
26114
+ z: anchorPoint.z + Math.cos(orbitAngle) * depthReach + sway * size * 0.016,
26115
+ };
26116
+ const scenePoints = Array.from({ length: 12 }, (_, sampleIndex) => transformScenePoint(sampleCubicBezierPoint3D(anchorPoint, controlPointOne, controlPointTwo, endPoint, sampleIndex / 11), center, rotationX, rotationY));
26117
+ const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
26118
+ const averageDepth = scenePoints.reduce((depthSum, scenePoint) => depthSum + scenePoint.z, 0) / scenePoints.length;
26119
+ return {
26120
+ projectedPoints,
26121
+ averageDepth,
26122
+ isFrontFacing: averageDepth >= center.z - size * 0.006,
26123
+ baseWidth: size *
26124
+ (0.019 +
26125
+ morphologyProfile.tentacles.baseWidthScale * 0.007 +
26126
+ tentacleRandom() * 0.003 +
26127
+ Math.abs(Math.sin(orbitAngle)) * 0.002),
26128
+ tipWidth: size * (0.0046 + morphologyProfile.tentacles.tipWidthScale * 0.0018),
26129
+ colorBias: tentacleRandom(),
26130
+ };
26131
+ });
26132
+ }
26133
+ /**
26134
+ * Samples one point on a cubic Bezier curve in 3D.
26135
+ *
26136
+ * @private helper of `octopus3dAvatarVisual`
26137
+ */
26138
+ function sampleCubicBezierPoint3D(startPoint, controlPointOne, controlPointTwo, endPoint, progress) {
26139
+ const inverseProgress = 1 - progress;
26140
+ return {
26141
+ x: inverseProgress * inverseProgress * inverseProgress * startPoint.x +
26142
+ 3 * inverseProgress * inverseProgress * progress * controlPointOne.x +
26143
+ 3 * inverseProgress * progress * progress * controlPointTwo.x +
26144
+ progress * progress * progress * endPoint.x,
26145
+ y: inverseProgress * inverseProgress * inverseProgress * startPoint.y +
26146
+ 3 * inverseProgress * inverseProgress * progress * controlPointOne.y +
26147
+ 3 * inverseProgress * progress * progress * controlPointTwo.y +
26148
+ progress * progress * progress * endPoint.y,
26149
+ z: inverseProgress * inverseProgress * inverseProgress * startPoint.z +
26150
+ 3 * inverseProgress * inverseProgress * progress * controlPointOne.z +
26151
+ 3 * inverseProgress * progress * progress * controlPointTwo.z +
26152
+ progress * progress * progress * endPoint.z,
26153
+ };
26154
+ }
26155
+ /**
26156
+ * Draws one projected tentacle stroke with a slim highlight ridge.
26157
+ *
26158
+ * @private helper of `octopus3dAvatarVisual`
26159
+ */
26160
+ function drawTentacleStroke(context, tentacleStroke, palette) {
26161
+ const projectedSegments = tentacleStroke.projectedPoints.length - 1;
26162
+ for (let segmentIndex = 0; segmentIndex < projectedSegments; segmentIndex++) {
26163
+ const startPoint = tentacleStroke.projectedPoints[segmentIndex];
26164
+ const endPoint = tentacleStroke.projectedPoints[segmentIndex + 1];
26165
+ const progress = segmentIndex / projectedSegments;
26166
+ const width = tentacleStroke.baseWidth + (tentacleStroke.tipWidth - tentacleStroke.baseWidth) * progress;
26167
+ context.beginPath();
26168
+ context.moveTo(startPoint.x, startPoint.y);
26169
+ context.lineTo(endPoint.x, endPoint.y);
26170
+ context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
26171
+ context.lineWidth = width;
26172
+ context.lineCap = 'round';
26173
+ context.stroke();
26174
+ context.beginPath();
26175
+ context.moveTo(startPoint.x, startPoint.y);
26176
+ context.lineTo(endPoint.x, endPoint.y);
26177
+ context.strokeStyle = tentacleStroke.isFrontFacing ? `${palette.highlight}80` : `${palette.highlight}40`;
26178
+ context.lineWidth = Math.max(1, width * 0.34);
26179
+ context.lineCap = 'round';
26180
+ context.stroke();
26181
+ }
26182
+ }
26183
+ /**
26184
+ * Resolves the front surface depth on an ellipsoid for one local face point.
26185
+ *
26186
+ * @private helper of `octopus3dAvatarVisual`
26187
+ */
26188
+ function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
26189
+ const normalizedX = x / radiusX;
26190
+ const normalizedY = y / radiusY;
26191
+ const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
26192
+ return Math.sqrt(remainingDepthRatio) * radiusZ;
26193
+ }
26194
+
26185
26195
  /* eslint-disable no-magic-numbers */
26186
26196
  /**
26187
26197
  * Octopus avatar visual.
@@ -27002,14 +27012,14 @@
27002
27012
  /**
27003
27013
  * META AVATAR commitment definition
27004
27014
  *
27005
- * The `META AVATAR` commitment sets the built-in default avatar visual used when
27006
- * the agent does not provide an explicit `META IMAGE`.
27015
+ * The `META AVATAR` and `META VISUAL` commitments set the built-in default avatar visual
27016
+ * used when the agent does not provide an explicit `META IMAGE`.
27007
27017
  *
27008
27018
  * @private [🪔] Maybe export the commitments through some package
27009
27019
  */
27010
27020
  class MetaAvatarCommitmentDefinition extends BaseCommitmentDefinition {
27011
- constructor() {
27012
- super('META AVATAR');
27021
+ constructor(type = 'META AVATAR') {
27022
+ super(type);
27013
27023
  }
27014
27024
  /**
27015
27025
  * Short one-line description of META AVATAR.
@@ -27029,14 +27039,15 @@
27029
27039
  get documentation() {
27030
27040
  const supportedVisuals = AVATAR_VISUALS.map((avatarVisual) => `\`${avatarVisual.id}\``).join(', ');
27031
27041
  return _spaceTrim.spaceTrim(`
27032
- # META AVATAR
27042
+ # ${this.type}
27033
27043
 
27034
27044
  Sets the built-in avatar visual used for the agent when no explicit \`META IMAGE\` is provided.
27045
+ \`META AVATAR\` and \`META VISUAL\` are equivalent.
27035
27046
 
27036
27047
  ## Key aspects
27037
27048
 
27038
27049
  - Does not modify the agent's behavior or responses.
27039
- - Only one \`META AVATAR\` should be used per agent.
27050
+ - Only one \`META AVATAR\` or \`META VISUAL\` should be used per agent.
27040
27051
  - If multiple are specified, the last one takes precedence.
27041
27052
  - Values are matched case-insensitively and spaces, hyphens, and underscores are normalized.
27042
27053
  - Supported visuals are derived from the shared avatar registry: ${supportedVisuals}.
@@ -27051,15 +27062,15 @@
27051
27062
  \`\`\`
27052
27063
 
27053
27064
  \`\`\`book
27054
- Orb Assistant
27065
+ Minecraft Assistant
27055
27066
 
27056
- META AVATAR orb
27067
+ META VISUAL Minecraft2
27057
27068
  GOAL Answer in a calm and focused way.
27058
27069
  \`\`\`
27059
27070
  `);
27060
27071
  }
27061
27072
  applyToAgentModelRequirements(requirements, content) {
27062
- // META AVATAR doesn't modify the system message or model requirements.
27073
+ // META AVATAR and META VISUAL don't modify the system message or model requirements.
27063
27074
  // It's handled separately in the parsing logic for profile avatar resolution.
27064
27075
  return requirements;
27065
27076
  }
@@ -27633,6 +27644,68 @@
27633
27644
  }
27634
27645
  // Note: [💞] Ignore a discrepancy between file name and entity name
27635
27646
 
27647
+ /**
27648
+ * META THINKING MESSAGE commitment definition.
27649
+ *
27650
+ * The `META THINKING MESSAGE` commitment adds one custom thinking placeholder
27651
+ * variant used by chat UIs while an agent is composing a reply.
27652
+ *
27653
+ * @private Metadata-only commitment used by Agents Server chat UIs.
27654
+ */
27655
+ class MetaThinkingMessageCommitmentDefinition extends BaseCommitmentDefinition {
27656
+ constructor() {
27657
+ super('META THINKING MESSAGE');
27658
+ }
27659
+ /**
27660
+ * Short one-line description of META THINKING MESSAGE.
27661
+ */
27662
+ get description() {
27663
+ return 'Add a custom thinking placeholder shown while the agent replies.';
27664
+ }
27665
+ /**
27666
+ * Icon for this commitment.
27667
+ */
27668
+ get icon() {
27669
+ return '💭';
27670
+ }
27671
+ /**
27672
+ * Markdown documentation for META THINKING MESSAGE commitment.
27673
+ */
27674
+ get documentation() {
27675
+ return _spaceTrim.spaceTrim(`
27676
+ # META THINKING MESSAGE
27677
+
27678
+ Adds one custom placeholder variant shown while the agent is composing a reply.
27679
+
27680
+ ## Key aspects
27681
+
27682
+ - Does not modify model behavior, system message, or tools.
27683
+ - Multiple \`META THINKING MESSAGE\` commitments define multiple variants.
27684
+ - Chat UIs randomly rotate between the configured variants while the reply is running.
27685
+ - When no non-empty variants are configured, the server-level \`THINKING_MESSAGES\` metadata is used.
27686
+ - Supports multiline markdown content.
27687
+
27688
+ ## Example
27689
+
27690
+ \`\`\`book
27691
+ Helpful Assistant
27692
+
27693
+ META THINKING MESSAGE Thinking...
27694
+ META THINKING MESSAGE Processing...
27695
+ META THINKING MESSAGE
27696
+
27697
+ Doing
27698
+ extra **hard** work
27699
+ \`\`\`
27700
+ `);
27701
+ }
27702
+ applyToAgentModelRequirements(requirements, content) {
27703
+ // META THINKING MESSAGE is metadata only and does not alter model requirements.
27704
+ return requirements;
27705
+ }
27706
+ }
27707
+ // Note: [💞] Ignore a discrepancy between file name and entity name
27708
+
27636
27709
  /**
27637
27710
  * META VISIBILITY commitment definition.
27638
27711
  *
@@ -29711,6 +29784,7 @@
29711
29784
  1. **One-shot URL fetching**: Simple function to fetch and scrape URL content (active)
29712
29785
  2. **Running browser**: For complex tasks like scrolling, clicking, form filling, etc. (runtime-dependent)
29713
29786
  - The actual browser tool usage is handled by the agent runtime
29787
+ - On the Agents Server, every agent browses in its own persistent isolated browser profile, so cookies and logged-in sessions survive across chats (the profile is linked from the agent wallet)
29714
29788
  - Allows the agent to fetch current information from websites and documents
29715
29789
  - Useful for research tasks, fact-checking, and accessing dynamic content
29716
29790
  - Supports various content types including HTML pages and PDF documents
@@ -36200,6 +36274,7 @@
36200
36274
  new ActionCommitmentDefinition('ACTIONS'),
36201
36275
  new ComponentCommitmentDefinition(),
36202
36276
  new MetaAvatarCommitmentDefinition(),
36277
+ new MetaAvatarCommitmentDefinition('META VISUAL'),
36203
36278
  new MetaImageCommitmentDefinition(),
36204
36279
  new MetaColorCommitmentDefinition(),
36205
36280
  new MetaFontCommitmentDefinition(),
@@ -36207,6 +36282,7 @@
36207
36282
  new MetaDomainCommitmentDefinition(),
36208
36283
  new MetaDisclaimerCommitmentDefinition(),
36209
36284
  new MetaInputPlaceholderCommitmentDefinition(),
36285
+ new MetaThinkingMessageCommitmentDefinition(),
36210
36286
  new MetaVisibilityCommitmentDefinition(),
36211
36287
  new MetaCommitmentDefinition(),
36212
36288
  new MetaVoiceCommitmentDefinition(),
@@ -37551,12 +37627,14 @@
37551
37627
  */
37552
37628
  const META_COMMITMENT_APPLIERS = {
37553
37629
  'META AVATAR': applyMetaAvatarContent,
37630
+ 'META VISUAL': applyMetaAvatarContent,
37554
37631
  'META LINK': applyMetaLinkContent,
37555
37632
  'META DOMAIN': applyMetaDomainContent,
37556
37633
  'META IMAGE': applyMetaImageContent,
37557
37634
  'META DESCRIPTION': applyMetaDescriptionContent,
37558
37635
  'META DISCLAIMER': applyMetaDisclaimerContent,
37559
37636
  'META INPUT PLACEHOLDER': applyMetaInputPlaceholderContent,
37637
+ 'META THINKING MESSAGE': applyMetaThinkingMessageContent,
37560
37638
  'MESSAGE SUFFIX': applyMessageSuffixContent,
37561
37639
  'META COLOR': applyMetaColorContent,
37562
37640
  'META FONT': applyMetaFontContent,
@@ -37599,7 +37677,7 @@
37599
37677
  state.meta[metaType] = metaValue;
37600
37678
  }
37601
37679
  /**
37602
- * Applies META AVATAR content into the canonical `meta.avatar` field.
37680
+ * Applies META AVATAR / META VISUAL content into the canonical `meta.avatar` field.
37603
37681
  */
37604
37682
  function applyMetaAvatarContent(state, content) {
37605
37683
  const avatarVisualId = resolveAvatarVisualId(content);
@@ -37647,6 +37725,16 @@
37647
37725
  function applyMetaInputPlaceholderContent(state, content) {
37648
37726
  state.meta.inputPlaceholder = _spaceTrim.spaceTrim(content);
37649
37727
  }
37728
+ /**
37729
+ * Applies one META THINKING MESSAGE content block into the custom thinking-message variants.
37730
+ */
37731
+ function applyMetaThinkingMessageContent(state, content) {
37732
+ const thinkingMessage = _spaceTrim.spaceTrim(content);
37733
+ if (!thinkingMessage) {
37734
+ return;
37735
+ }
37736
+ state.thinkingMessages = [...(state.thinkingMessages || []), thinkingMessage];
37737
+ }
37650
37738
  /**
37651
37739
  * Applies MESSAGE SUFFIX content into the canonical `meta.messageSuffix` field.
37652
37740
  */
@@ -38015,6 +38103,7 @@
38015
38103
  capabilities: [],
38016
38104
  samples: [],
38017
38105
  knowledgeSources: [],
38106
+ thinkingMessages: [],
38018
38107
  pendingUserMessage: null,
38019
38108
  knownKnowledgeSourceUrls: new Set(),
38020
38109
  };
@@ -38027,6 +38116,7 @@
38027
38116
  capabilities: state.capabilities,
38028
38117
  samples: state.samples,
38029
38118
  knowledgeSources: state.knowledgeSources,
38119
+ thinkingMessages: state.thinkingMessages,
38030
38120
  };
38031
38121
  }
38032
38122
  /**
@@ -38066,6 +38156,7 @@
38066
38156
  permanentId: parsedProfile.meta.id,
38067
38157
  personaDescription,
38068
38158
  initialMessage,
38159
+ thinkingMessages: parsedProfile.thinkingMessages,
38069
38160
  meta: parsedProfile.meta,
38070
38161
  links: parsedProfile.links,
38071
38162
  parameters: parseParameters(agentSource),
@@ -40995,7 +41086,7 @@
40995
41086
  *
40996
41087
  * @private within the repository
40997
41088
  */
40998
- function locateApp(options) {
41089
+ async function locateApp(options) {
40999
41090
  if (!$isRunningInNode()) {
41000
41091
  throw new EnvironmentMismatchError('Locating apps works only in Node.js environment');
41001
41092
  }
@@ -41140,61 +41231,41 @@
41140
41231
  */
41141
41232
  let $usedEnvFilename = null;
41142
41233
  /**
41143
- * Pass the `.env` file which was used to configure LLM tools
41144
- *
41145
- * Note: `$` is used to indicate that this variable is making side effect
41234
+ * Shared state for the `.env` file used to configure LLM tools.
41146
41235
  *
41147
- * @private internal log of `$provideLlmToolsConfigurationFromEnv` and `$registeredLlmToolsMessage`
41236
+ * @private internal state of `$registeredLlmToolsMessage`
41148
41237
  */
41149
- function $setUsedEnvFilename(filepath) {
41150
- $usedEnvFilename = filepath;
41151
- }
41152
- /**
41153
- * Creates a message with all registered LLM tools
41154
- *
41155
- * Note: This function is used to create a (error) message when there is no constructor for some LLM provider
41156
- *
41157
- * @private internal function of `createLlmToolsFromConfiguration` and `$provideLlmToolsFromEnv`
41158
- */
41159
- function $registeredLlmToolsMessage() {
41160
- const registeredLlmToolsMessageContext = createRegisteredLlmToolsMessageContext();
41161
- if (registeredLlmToolsMessageContext.llmToolStatuses.length === 0) {
41162
- return renderNoRegisteredLlmToolsMessage(registeredLlmToolsMessageContext.usedEnvMessage);
41163
- }
41164
- return renderRegisteredLlmToolsMessage(registeredLlmToolsMessageContext);
41165
- }
41166
- /**
41167
- * Collects all state needed to render the provider summary.
41168
- *
41169
- * @private internal function of `$registeredLlmToolsMessage`
41170
- */
41171
- function createRegisteredLlmToolsMessageContext() {
41172
- const isRunningInNode = $isRunningInNode();
41173
- const env = getAvailableEnvironmentVariables(isRunningInNode);
41174
- const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
41175
- return {
41176
- env,
41177
- llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
41178
- usedEnvMessage: createUsedEnvMessage(),
41179
- isRunningInNode,
41180
- };
41181
- }
41238
+ const USED_ENV_FILENAME = {
41239
+ set(filepath) {
41240
+ $usedEnvFilename = filepath;
41241
+ },
41242
+ createMessage() {
41243
+ return $usedEnvFilename === null
41244
+ ? `Unknown \`.env\` file`
41245
+ : _spaceTrim.spaceTrim(`
41246
+ Used \`.env\` file:
41247
+ ${$usedEnvFilename}
41248
+ `);
41249
+ },
41250
+ };
41251
+
41182
41252
  /**
41183
41253
  * Reads environment variables relevant for provider configuration.
41184
41254
  *
41185
- * @private internal function of `$registeredLlmToolsMessage`
41255
+ * @private function of `$registeredLlmToolsMessage`
41186
41256
  */
41187
- function getAvailableEnvironmentVariables(isRunningInNode) {
41257
+ function getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode) {
41188
41258
  if (isRunningInNode) {
41189
41259
  return process.env;
41190
41260
  // <- TODO: [⚛] Some DRY way how to get to `process.env` and pass it into functions - ACRY search for `env`
41191
41261
  }
41192
41262
  return {};
41193
41263
  }
41264
+
41194
41265
  /**
41195
41266
  * Takes stable snapshots of both LLM provider registers.
41196
41267
  *
41197
- * @private internal function of `$registeredLlmToolsMessage`
41268
+ * @private function of `$registeredLlmToolsMessage`
41198
41269
  */
41199
41270
  function getRegisteredLlmToolRegisters() {
41200
41271
  return {
@@ -41202,62 +41273,30 @@
41202
41273
  registeredTools: $llmToolsRegister.list(),
41203
41274
  };
41204
41275
  }
41205
- /**
41206
- * Lists provider entries enriched with installation and configuration state.
41207
- *
41208
- * @private internal function of `$registeredLlmToolsMessage`
41209
- */
41210
- function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
41211
- return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
41212
- }
41213
- /**
41214
- * Merges provider entries from the metadata and constructor registers.
41215
- *
41216
- * @private internal function of `$registeredLlmToolsMessage`
41217
- */
41218
- function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
41219
- const registeredLlmToolEntries = new Map();
41220
- for (const { title, packageName, className, envVariables } of registeredMetadata) {
41221
- addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
41222
- }
41223
- for (const { packageName, className } of registeredTools) {
41224
- addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
41225
- }
41226
- return [...registeredLlmToolEntries.values()];
41227
- }
41228
- /**
41229
- * Adds a provider entry only when the provider is not already present.
41230
- *
41231
- * @private internal function of `$registeredLlmToolsMessage`
41232
- */
41233
- function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
41234
- const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
41235
- if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
41236
- return;
41237
- }
41238
- registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
41239
- }
41276
+
41240
41277
  /**
41241
41278
  * Creates a deduplication key for a provider entry.
41242
41279
  *
41243
- * @private internal function of `$registeredLlmToolsMessage`
41280
+ * @private function of `$registeredLlmToolsMessage`
41244
41281
  */
41245
41282
  function createRegisteredLlmToolEntryKey({ packageName, className }) {
41246
41283
  return `${packageName}::${className}`;
41247
41284
  }
41285
+
41248
41286
  /**
41249
41287
  * Checks whether the given provider entry already exists in the target register list.
41250
41288
  *
41251
- * @private internal function of `$registeredLlmToolsMessage`
41289
+ * @private function of `$registeredLlmToolsMessage`
41252
41290
  */
41253
41291
  function hasRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
41254
41292
  const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
41255
41293
  return registeredLlmToolEntries.some((listedRegisteredLlmToolEntry) => createRegisteredLlmToolEntryKey(listedRegisteredLlmToolEntry) === registeredLlmToolEntryKey);
41256
41294
  }
41295
+
41257
41296
  /**
41258
41297
  * Builds the runtime status for one provider entry.
41259
41298
  *
41260
- * @private internal function of `$registeredLlmToolsMessage`
41299
+ * @private function of `$registeredLlmToolsMessage`
41261
41300
  */
41262
41301
  function createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env, }) {
41263
41302
  const availabilityStatus = createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools);
@@ -41271,7 +41310,7 @@
41271
41310
  /**
41272
41311
  * Resolves whether the provider has metadata and a registered constructor.
41273
41312
  *
41274
- * @private internal function of `$registeredLlmToolsMessage`
41313
+ * @private function of `$registeredLlmToolsMessage`
41275
41314
  */
41276
41315
  function createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools) {
41277
41316
  return {
@@ -41282,7 +41321,7 @@
41282
41321
  /**
41283
41322
  * Resolves whether the provider has enough environment variables to be configured.
41284
41323
  *
41285
- * @private internal function of `$registeredLlmToolsMessage`
41324
+ * @private function of `$registeredLlmToolsMessage`
41286
41325
  */
41287
41326
  function createRegisteredLlmToolConfigurationStatus({ envVariables }, env) {
41288
41327
  return {
@@ -41293,7 +41332,7 @@
41293
41332
  /**
41294
41333
  * Checks whether all required environment variables are present for a provider.
41295
41334
  *
41296
- * @private internal function of `$registeredLlmToolsMessage`
41335
+ * @private function of `$registeredLlmToolsMessage`
41297
41336
  */
41298
41337
  function isRegisteredLlmToolFullyConfigured(envVariables, env) {
41299
41338
  if (envVariables === undefined || envVariables === null) {
@@ -41304,7 +41343,7 @@
41304
41343
  /**
41305
41344
  * Checks whether at least one required environment variable is present for a provider.
41306
41345
  *
41307
- * @private internal function of `$registeredLlmToolsMessage`
41346
+ * @private function of `$registeredLlmToolsMessage`
41308
41347
  */
41309
41348
  function isRegisteredLlmToolPartiallyConfigured(envVariables, env) {
41310
41349
  if (envVariables === undefined || envVariables === null) {
@@ -41312,109 +41351,128 @@
41312
41351
  }
41313
41352
  return envVariables.some((envVariableName) => env[envVariableName] !== undefined);
41314
41353
  }
41354
+
41315
41355
  /**
41316
- * Renders the fallback message for environments with no registered providers.
41356
+ * Merges provider entries from the metadata and constructor registers.
41317
41357
  *
41318
- * @private internal function of `$registeredLlmToolsMessage`
41358
+ * @private function of `$registeredLlmToolsMessage`
41319
41359
  */
41320
- function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
41321
- return _spaceTrim.spaceTrim((block) => `
41322
- No LLM providers are available.
41323
-
41324
- ${block(usedEnvMessage)}
41325
- `);
41360
+ function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
41361
+ const registeredLlmToolEntries = new Map();
41362
+ for (const { title, packageName, className, envVariables } of registeredMetadata) {
41363
+ addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
41364
+ }
41365
+ for (const { packageName, className } of registeredTools) {
41366
+ addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
41367
+ }
41368
+ return [...registeredLlmToolEntries.values()];
41326
41369
  }
41327
41370
  /**
41328
- * Renders the full provider status summary.
41371
+ * Adds a provider entry only when the provider is not already present.
41329
41372
  *
41330
- * @private internal function of `$registeredLlmToolsMessage`
41373
+ * @private function of `$registeredLlmToolsMessage`
41331
41374
  */
41332
- function renderRegisteredLlmToolsMessage({ env, llmToolStatuses, usedEnvMessage, isRunningInNode, }) {
41333
- return _spaceTrim.spaceTrim((block) => `
41334
-
41335
- ${block(usedEnvMessage)}
41336
-
41337
- Relevant environment variables:
41338
- ${block(renderRelevantEnvironmentVariables(env, llmToolStatuses))}
41339
-
41340
- Available LLM providers are:
41341
- ${block(renderAvailableProviders(llmToolStatuses, env, isRunningInNode))}
41342
- `);
41375
+ function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
41376
+ const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
41377
+ if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
41378
+ return;
41379
+ }
41380
+ registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
41343
41381
  }
41382
+
41344
41383
  /**
41345
- * Renders the list of environment variables used by at least one registered provider.
41384
+ * Lists provider entries enriched with installation and configuration state.
41346
41385
  *
41347
- * @private internal function of `$registeredLlmToolsMessage`
41386
+ * @private function of `$registeredLlmToolsMessage`
41348
41387
  */
41349
- function renderRelevantEnvironmentVariables(env, llmToolStatuses) {
41350
- return listRelevantEnvironmentVariables(env, llmToolStatuses)
41351
- .map((envVariableName) => `- \`${envVariableName}\``)
41352
- .join('\n');
41388
+ function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
41389
+ return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
41353
41390
  }
41391
+
41354
41392
  /**
41355
- * Lists environment variables that are both present and used by at least one provider.
41393
+ * Collects all state needed to render the provider summary.
41356
41394
  *
41357
- * @private internal function of `$registeredLlmToolsMessage`
41395
+ * @private function of `$registeredLlmToolsMessage`
41358
41396
  */
41359
- function listRelevantEnvironmentVariables(env, llmToolStatuses) {
41360
- return Object.keys(env).filter((envVariableName) => llmToolStatuses.some(({ envVariables }) => envVariables === null || envVariables === void 0 ? void 0 : envVariables.includes(envVariableName)));
41397
+ function createRegisteredLlmToolsMessageContext() {
41398
+ const isRunningInNode = $isRunningInNode();
41399
+ const env = getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode);
41400
+ const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
41401
+ return {
41402
+ env,
41403
+ llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
41404
+ usedEnvMessage: USED_ENV_FILENAME.createMessage(),
41405
+ isRunningInNode,
41406
+ };
41361
41407
  }
41408
+
41362
41409
  /**
41363
- * Renders all provider lines in the status summary.
41410
+ * Renders the fallback message for environments with no registered providers.
41364
41411
  *
41365
- * @private internal function of `$registeredLlmToolsMessage`
41412
+ * @private function of `$registeredLlmToolsMessage`
41366
41413
  */
41367
- function renderAvailableProviders(llmToolStatuses, env, isRunningInNode) {
41368
- return llmToolStatuses
41369
- .map((llmToolStatus, index) => renderAvailableProvider(llmToolStatus, index, env, isRunningInNode))
41370
- .join('\n');
41414
+ function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
41415
+ return _spaceTrim.spaceTrim((block) => `
41416
+ No LLM providers are available.
41417
+
41418
+ ${block(usedEnvMessage)}
41419
+ `);
41371
41420
  }
41421
+
41372
41422
  /**
41373
- * Renders one provider line in the status summary.
41423
+ * Creates the configuration-status sentence for one provider.
41374
41424
  *
41375
- * @private internal function of `$registeredLlmToolsMessage`
41425
+ * @private function of `$registeredLlmToolsMessage`
41376
41426
  */
41377
- function renderAvailableProvider(llmToolStatus, index, env, isRunningInNode) {
41378
- const providerMessage = createAvailableProviderMessage(llmToolStatus, index, env);
41379
- if (!isRunningInNode) {
41380
- return providerMessage;
41427
+ function createRegisteredLlmToolConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
41428
+ if (isFullyConfigured) {
41429
+ return `Configured`;
41430
+ }
41431
+ if (isPartiallyConfigured) {
41432
+ return createPartiallyConfiguredStatusMessage(envVariables, env);
41381
41433
  }
41382
- return colorizeAvailableProviderMessage(providerMessage, llmToolStatus);
41434
+ if (envVariables !== null) {
41435
+ return createNotConfiguredStatusMessage(envVariables);
41436
+ }
41437
+ return `Not configured`;
41438
+ // <- Note: Can not be configured via environment variables
41383
41439
  }
41384
41440
  /**
41385
- * Creates the plain-text provider line before optional colorization.
41441
+ * Creates the partial-configuration sentence including missing variables.
41386
41442
  *
41387
- * @private internal function of `$registeredLlmToolsMessage`
41443
+ * @private function of `$registeredLlmToolsMessage`
41388
41444
  */
41389
- function createAvailableProviderMessage(llmToolStatus, index, env) {
41390
- const { title, packageName, className } = llmToolStatus;
41391
- const providerStatusMessages = createProviderStatusMessages(llmToolStatus, env);
41392
- return _spaceTrim.spaceTrim(`
41393
- ${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
41394
- ${providerStatusMessages.join('; ')}
41395
- `);
41445
+ function createPartiallyConfiguredStatusMessage(envVariables, env) {
41446
+ return `Partially confugured, missing ${listMissingEnvironmentVariables(envVariables, env).join(' + ')}`;
41396
41447
  }
41397
41448
  /**
41398
- * Creates the install and configuration fragments for one provider line.
41449
+ * Creates the not-configured sentence including the expected environment variables.
41399
41450
  *
41400
- * @private internal function of `$registeredLlmToolsMessage`
41451
+ * @private function of `$registeredLlmToolsMessage`
41401
41452
  */
41402
- function createProviderStatusMessages(llmToolStatus, env) {
41403
- return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
41453
+ function createNotConfiguredStatusMessage(envVariables) {
41454
+ return `Not configured, to configure set env ${envVariables === null || envVariables === void 0 ? void 0 : envVariables.join(' + ')}`;
41404
41455
  }
41456
+ /**
41457
+ * Lists environment variables that are required but currently missing.
41458
+ *
41459
+ * @private function of `$registeredLlmToolsMessage`
41460
+ */
41461
+ function listMissingEnvironmentVariables(envVariables, env) {
41462
+ return (envVariables === null || envVariables === void 0 ? void 0 : envVariables.filter((envVariable) => env[envVariable] === undefined)) || [];
41463
+ }
41464
+
41405
41465
  /**
41406
41466
  * Creates the installation-status sentence for one provider.
41407
41467
  *
41408
- * @private internal function of `$registeredLlmToolsMessage`
41468
+ * @private function of `$registeredLlmToolsMessage`
41409
41469
  */
41410
- function createInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
41411
- const installationStatusKey = createInstallationStatusKey(isMetadataAvailable, isInstalled);
41470
+ function createRegisteredLlmToolInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
41471
+ const installationStatusKey = createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled);
41412
41472
  switch (installationStatusKey) {
41413
41473
  case 'missing-metadata-and-installation':
41414
- // TODO: [�][�] Maybe do allow to do auto-install if package not registered and not found
41415
41474
  return `Not installed and no metadata, looks like a unexpected behavior`;
41416
41475
  case 'metadata-without-installation':
41417
- // TODO: [�][�]
41418
41476
  return `Not installed`;
41419
41477
  case 'installation-without-metadata':
41420
41478
  return `No metadata but installed, looks like a unexpected behavior`;
@@ -41427,9 +41485,9 @@
41427
41485
  /**
41428
41486
  * Creates a stable installation-state key from metadata and constructor availability.
41429
41487
  *
41430
- * @private internal function of `$registeredLlmToolsMessage`
41488
+ * @private function of `$registeredLlmToolsMessage`
41431
41489
  */
41432
- function createInstallationStatusKey(isMetadataAvailable, isInstalled) {
41490
+ function createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled) {
41433
41491
  if (!isMetadataAvailable && !isInstalled) {
41434
41492
  return 'missing-metadata-and-installation';
41435
41493
  }
@@ -41444,54 +41502,59 @@
41444
41502
  }
41445
41503
  return 'unknown';
41446
41504
  }
41505
+
41447
41506
  /**
41448
- * Creates the configuration-status sentence for one provider.
41507
+ * Renders all provider lines in the status summary.
41449
41508
  *
41450
- * @private internal function of `$registeredLlmToolsMessage`
41509
+ * @private function of `$registeredLlmToolsMessage`
41451
41510
  */
41452
- function createConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
41453
- if (isFullyConfigured) {
41454
- return `Configured`;
41455
- }
41456
- if (isPartiallyConfigured) {
41457
- return createPartiallyConfiguredStatusMessage(envVariables, env);
41458
- }
41459
- if (envVariables !== null) {
41460
- return createNotConfiguredStatusMessage(envVariables);
41461
- }
41462
- return `Not configured`;
41463
- // <- Note: Can not be configured via environment variables
41511
+ function renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode) {
41512
+ return llmToolStatuses
41513
+ .map((llmToolStatus, index) => renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode))
41514
+ .join('\n');
41464
41515
  }
41465
41516
  /**
41466
- * Creates the partial-configuration sentence including missing variables.
41517
+ * Renders one provider line in the status summary.
41467
41518
  *
41468
- * @private internal function of `$registeredLlmToolsMessage`
41519
+ * @private function of `$registeredLlmToolsMessage`
41469
41520
  */
41470
- function createPartiallyConfiguredStatusMessage(envVariables, env) {
41471
- return `Partially confugured, missing ${listMissingEnvironmentVariables(envVariables, env).join(' + ')}`;
41521
+ function renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode) {
41522
+ const providerMessage = createAvailableRegisteredLlmToolMessage(llmToolStatus, index, env);
41523
+ if (!isRunningInNode) {
41524
+ return providerMessage;
41525
+ }
41526
+ return colorizeAvailableRegisteredLlmToolMessage(providerMessage, llmToolStatus);
41472
41527
  }
41473
41528
  /**
41474
- * Creates the not-configured sentence including the expected environment variables.
41529
+ * Creates the plain-text provider line before optional colorization.
41475
41530
  *
41476
- * @private internal function of `$registeredLlmToolsMessage`
41531
+ * @private function of `$registeredLlmToolsMessage`
41477
41532
  */
41478
- function createNotConfiguredStatusMessage(envVariables) {
41479
- return `Not configured, to configure set env ${envVariables === null || envVariables === void 0 ? void 0 : envVariables.join(' + ')}`;
41533
+ function createAvailableRegisteredLlmToolMessage(llmToolStatus, index, env) {
41534
+ const { title, packageName, className } = llmToolStatus;
41535
+ const providerStatusMessages = createRegisteredLlmToolStatusMessages(llmToolStatus, env);
41536
+ return _spaceTrim.spaceTrim(`
41537
+ ${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
41538
+ ${providerStatusMessages.join('; ')}
41539
+ `);
41480
41540
  }
41481
41541
  /**
41482
- * Lists environment variables that are required but currently missing.
41542
+ * Creates the install and configuration fragments for one provider line.
41483
41543
  *
41484
- * @private internal function of `$registeredLlmToolsMessage`
41544
+ * @private function of `$registeredLlmToolsMessage`
41485
41545
  */
41486
- function listMissingEnvironmentVariables(envVariables, env) {
41487
- return (envVariables === null || envVariables === void 0 ? void 0 : envVariables.filter((envVariable) => env[envVariable] === undefined)) || [];
41546
+ function createRegisteredLlmToolStatusMessages(llmToolStatus, env) {
41547
+ return [
41548
+ createRegisteredLlmToolInstallationStatusMessage(llmToolStatus),
41549
+ createRegisteredLlmToolConfigurationStatusMessage(llmToolStatus, env),
41550
+ ];
41488
41551
  }
41489
41552
  /**
41490
41553
  * Applies the same terminal coloring rules as the original summary renderer.
41491
41554
  *
41492
- * @private internal function of `$registeredLlmToolsMessage`
41555
+ * @private function of `$registeredLlmToolsMessage`
41493
41556
  */
41494
- function colorizeAvailableProviderMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
41557
+ function colorizeAvailableRegisteredLlmToolMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
41495
41558
  if (isInstalled && isFullyConfigured) {
41496
41559
  return colors__default["default"].green(providerMessage);
41497
41560
  }
@@ -41500,18 +41563,67 @@
41500
41563
  }
41501
41564
  return colors__default["default"].gray(providerMessage);
41502
41565
  }
41566
+
41503
41567
  /**
41504
- * Creates the `.env` origin sentence used in the summary header.
41568
+ * Renders the list of environment variables used by at least one registered provider.
41505
41569
  *
41506
- * @private internal function of `$registeredLlmToolsMessage`
41570
+ * @private function of `$registeredLlmToolsMessage`
41507
41571
  */
41508
- function createUsedEnvMessage() {
41509
- return $usedEnvFilename === null
41510
- ? `Unknown \`.env\` file`
41511
- : _spaceTrim.spaceTrim(`
41512
- Used \`.env\` file:
41513
- ${$usedEnvFilename}
41514
- `);
41572
+ function renderRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses) {
41573
+ return listRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses)
41574
+ .map((envVariableName) => `- \`${envVariableName}\``)
41575
+ .join('\n');
41576
+ }
41577
+ /**
41578
+ * Lists environment variables that are both present and used by at least one provider.
41579
+ *
41580
+ * @private function of `$registeredLlmToolsMessage`
41581
+ */
41582
+ function listRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses) {
41583
+ return Object.keys(env).filter((envVariableName) => llmToolStatuses.some(({ envVariables }) => envVariables === null || envVariables === void 0 ? void 0 : envVariables.includes(envVariableName)));
41584
+ }
41585
+
41586
+ /**
41587
+ * Renders the full provider status summary.
41588
+ *
41589
+ * @private function of `$registeredLlmToolsMessage`
41590
+ */
41591
+ function renderRegisteredLlmToolsMessage({ env, llmToolStatuses, usedEnvMessage, isRunningInNode, }) {
41592
+ return _spaceTrim.spaceTrim((block) => `
41593
+
41594
+ ${block(usedEnvMessage)}
41595
+
41596
+ Relevant environment variables:
41597
+ ${block(renderRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses))}
41598
+
41599
+ Available LLM providers are:
41600
+ ${block(renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode))}
41601
+ `);
41602
+ }
41603
+
41604
+ /**
41605
+ * Pass the `.env` file which was used to configure LLM tools
41606
+ *
41607
+ * Note: `$` is used to indicate that this variable is making side effect
41608
+ *
41609
+ * @private internal log of `$provideLlmToolsConfigurationFromEnv` and `$registeredLlmToolsMessage`
41610
+ */
41611
+ function $setUsedEnvFilename(filepath) {
41612
+ USED_ENV_FILENAME.set(filepath);
41613
+ }
41614
+ /**
41615
+ * Creates a message with all registered LLM tools
41616
+ *
41617
+ * Note: This function is used to create a (error) message when there is no constructor for some LLM provider
41618
+ *
41619
+ * @private internal function of `createLlmToolsFromConfiguration` and `$provideLlmToolsFromEnv`
41620
+ */
41621
+ function $registeredLlmToolsMessage() {
41622
+ const registeredLlmToolsMessageContext = createRegisteredLlmToolsMessageContext();
41623
+ if (registeredLlmToolsMessageContext.llmToolStatuses.length === 0) {
41624
+ return renderNoRegisteredLlmToolsMessage(registeredLlmToolsMessageContext.usedEnvMessage);
41625
+ }
41626
+ return renderRegisteredLlmToolsMessage(registeredLlmToolsMessageContext);
41515
41627
  }
41516
41628
  // TODO: [®] DRY Register logic
41517
41629
  // TODO: [🧠][⚛] Maybe pass env as argument