@promptbook/core 0.113.0-1 → 0.113.0-11

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 (248) hide show
  1. package/README.md +1 -17
  2. package/esm/index.es.js +1105 -1069
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/src/_packages/types.index.d.ts +2 -2
  5. package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +98 -0
  6. package/esm/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
  7. package/esm/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
  8. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
  9. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
  10. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
  11. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
  12. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
  13. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
  14. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
  15. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
  16. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
  17. package/esm/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
  18. package/esm/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
  19. package/esm/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
  20. package/esm/src/book-components/Chat/Chat/ChatMessageItem.d.ts +1 -1
  21. package/esm/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
  22. package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +8 -0
  23. package/esm/src/book-components/Chat/Chat/CitationIframePreview.d.ts +1 -1
  24. package/esm/src/book-components/Chat/Chat/CitationIframePreview.test.d.ts +2 -0
  25. package/esm/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  26. package/esm/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  27. package/esm/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  28. package/esm/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  29. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
  30. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
  31. package/esm/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
  32. package/esm/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
  33. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
  34. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
  35. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
  36. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
  37. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
  38. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
  39. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
  40. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
  41. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
  42. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
  43. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
  44. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
  45. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
  46. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
  47. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
  48. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
  49. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
  50. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
  51. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
  52. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
  53. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
  54. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
  55. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
  56. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
  57. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
  58. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
  59. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
  60. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
  61. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
  62. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
  63. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
  64. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
  65. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
  66. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
  67. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
  68. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +16 -0
  69. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
  70. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
  71. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
  72. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
  73. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
  74. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
  75. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
  76. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
  77. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
  78. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
  79. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
  80. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
  81. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
  82. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
  83. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
  84. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
  85. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
  86. package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
  87. package/esm/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  88. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
  89. package/esm/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
  90. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
  91. package/esm/src/commitments/META/META.d.ts +2 -2
  92. package/esm/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
  93. package/esm/src/commitments/index.d.ts +1 -1
  94. package/esm/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
  95. package/esm/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
  96. package/esm/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
  97. package/esm/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
  98. package/esm/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
  99. package/esm/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
  100. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
  101. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
  102. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
  103. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
  104. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
  105. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
  106. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
  107. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  108. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
  109. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
  110. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
  111. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
  112. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
  113. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
  114. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
  115. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  116. package/esm/src/utils/agent-message-runtime/agentMessageRuntimePaths.d.ts +24 -0
  117. package/esm/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
  118. package/esm/src/utils/agents/terminalAgentAvatarVisual.d.ts +94 -0
  119. package/esm/src/utils/agents/terminalAgentAvatarVisual.test.d.ts +1 -0
  120. package/esm/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
  121. package/esm/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
  122. package/esm/src/utils/color/Color.d.ts +1 -1
  123. package/esm/src/version.d.ts +1 -1
  124. package/package.json +1 -1
  125. package/umd/index.umd.js +1105 -1069
  126. package/umd/index.umd.js.map +1 -1
  127. package/umd/src/_packages/types.index.d.ts +2 -2
  128. package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +98 -0
  129. package/umd/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
  130. package/umd/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
  131. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
  132. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
  133. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
  134. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
  135. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
  136. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
  137. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
  138. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
  139. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
  140. package/umd/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
  141. package/umd/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
  142. package/umd/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
  143. package/umd/src/book-components/Chat/Chat/ChatMessageItem.d.ts +1 -1
  144. package/umd/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
  145. package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +8 -0
  146. package/umd/src/book-components/Chat/Chat/CitationIframePreview.d.ts +1 -1
  147. package/umd/src/book-components/Chat/Chat/CitationIframePreview.test.d.ts +2 -0
  148. package/umd/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  149. package/umd/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  150. package/umd/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  151. package/umd/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  152. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
  153. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
  154. package/umd/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
  155. package/umd/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
  156. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
  157. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
  158. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
  159. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
  160. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
  161. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
  162. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
  163. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
  164. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
  165. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
  166. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
  167. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
  168. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
  169. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
  170. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
  171. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
  172. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
  173. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
  174. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
  175. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
  176. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
  177. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
  178. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
  179. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
  180. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
  181. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
  182. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
  183. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
  184. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
  185. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
  186. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
  187. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
  188. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
  189. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
  190. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
  191. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +16 -0
  192. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
  193. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
  194. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
  195. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
  196. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
  197. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
  198. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
  199. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
  200. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
  201. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
  202. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
  203. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
  204. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
  205. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
  206. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
  207. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
  208. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
  209. package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
  210. package/umd/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  211. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
  212. package/umd/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
  213. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
  214. package/umd/src/commitments/META/META.d.ts +2 -2
  215. package/umd/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
  216. package/umd/src/commitments/index.d.ts +1 -1
  217. package/umd/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
  218. package/umd/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
  219. package/umd/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
  220. package/umd/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
  221. package/umd/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
  222. package/umd/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
  223. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
  224. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
  225. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
  226. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
  227. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
  228. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
  229. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
  230. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  231. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
  232. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
  233. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
  234. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
  235. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
  236. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
  237. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
  238. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  239. package/umd/src/utils/agent-message-runtime/agentMessageRuntimePaths.d.ts +24 -0
  240. package/umd/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
  241. package/umd/src/utils/agents/terminalAgentAvatarVisual.d.ts +94 -0
  242. package/umd/src/utils/agents/terminalAgentAvatarVisual.test.d.ts +1 -0
  243. package/umd/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
  244. package/umd/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
  245. package/umd/src/utils/color/Color.d.ts +1 -1
  246. package/umd/src/version.d.ts +1 -1
  247. package/esm/src/book-components/Chat/utils/livePagePreviewConstants.d.ts +0 -12
  248. package/umd/src/book-components/Chat/utils/livePagePreviewConstants.d.ts +0 -12
package/umd/index.umd.js CHANGED
@@ -29,7 +29,7 @@
29
29
  * @generated
30
30
  * @see https://github.com/webgptorg/promptbook
31
31
  */
32
- const PROMPTBOOK_ENGINE_VERSION = '0.113.0-1';
32
+ const PROMPTBOOK_ENGINE_VERSION = '0.113.0-11';
33
33
  /**
34
34
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
35
35
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -281,6 +281,127 @@
281
281
  });
282
282
  }
283
283
 
284
+ /**
285
+ * Validates that a channel value is a valid number within the range of 0 to 255.
286
+ * Throws an error if the value is not valid.
287
+ *
288
+ * @param channelName - The name of the channel being validated.
289
+ * @param value - The value of the channel to validate.
290
+ * @throws Will throw an error if the value is not a valid channel number.
291
+ *
292
+ * @private util of `@promptbook/color`
293
+ */
294
+ function checkChannelValue(channelName, value) {
295
+ if (typeof value !== 'number') {
296
+ throw new Error(`${channelName} channel value is not number but ${typeof value}`);
297
+ }
298
+ if (isNaN(value)) {
299
+ throw new Error(`${channelName} channel value is NaN`);
300
+ }
301
+ if (Math.round(value) !== value) {
302
+ throw new Error(`${channelName} channel is not whole number, it is ${value}`);
303
+ }
304
+ if (value < 0) {
305
+ throw new Error(`${channelName} channel is lower than 0, it is ${value}`);
306
+ }
307
+ if (value > 255) {
308
+ throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Shared immutable channel storage and serialization helpers for `Color`.
314
+ *
315
+ * @private base class of Color
316
+ */
317
+ class ColorValue {
318
+ constructor(red, green, blue, alpha = 255) {
319
+ this.red = red;
320
+ this.green = green;
321
+ this.blue = blue;
322
+ this.alpha = alpha;
323
+ checkChannelValue('Red', red);
324
+ checkChannelValue('Green', green);
325
+ checkChannelValue('Blue', blue);
326
+ checkChannelValue('Alpha', alpha);
327
+ }
328
+ /**
329
+ * Shortcut for `red` property
330
+ * Number from 0 to 255
331
+ * @alias red
332
+ */
333
+ get r() {
334
+ return this.red;
335
+ }
336
+ /**
337
+ * Shortcut for `green` property
338
+ * Number from 0 to 255
339
+ * @alias green
340
+ */
341
+ get g() {
342
+ return this.green;
343
+ }
344
+ /**
345
+ * Shortcut for `blue` property
346
+ * Number from 0 to 255
347
+ * @alias blue
348
+ */
349
+ get b() {
350
+ return this.blue;
351
+ }
352
+ /**
353
+ * Shortcut for `alpha` property
354
+ * Number from 0 (transparent) to 255 (opaque)
355
+ * @alias alpha
356
+ */
357
+ get a() {
358
+ return this.alpha;
359
+ }
360
+ /**
361
+ * Shortcut for `alpha` property
362
+ * Number from 0 (transparent) to 255 (opaque)
363
+ * @alias alpha
364
+ */
365
+ get opacity() {
366
+ return this.alpha;
367
+ }
368
+ /**
369
+ * Shortcut for 1-`alpha` property
370
+ */
371
+ get transparency() {
372
+ return 255 - this.alpha;
373
+ }
374
+ clone() {
375
+ return take(this.createColor(this.red, this.green, this.blue, this.alpha));
376
+ }
377
+ toString() {
378
+ return this.toHex();
379
+ }
380
+ toHex() {
381
+ if (this.alpha === 255) {
382
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
383
+ .toString(16)
384
+ .padStart(2, '0')}`;
385
+ }
386
+ else {
387
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
388
+ .toString(16)
389
+ .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
390
+ }
391
+ }
392
+ toRgb() {
393
+ if (this.alpha === 255) {
394
+ return `rgb(${this.red}, ${this.green}, ${this.blue})`;
395
+ }
396
+ else {
397
+ return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
398
+ }
399
+ }
400
+ toHsl() {
401
+ throw new Error(`Getting HSL is not implemented`);
402
+ }
403
+ }
404
+
284
405
  /**
285
406
  * 🎨 List of all 140 color names which are supported by CSS
286
407
  *
@@ -440,127 +561,6 @@
440
561
  };
441
562
  // Note: [💞] Ignore a discrepancy between file name and entity name
442
563
 
443
- /**
444
- * Validates that a channel value is a valid number within the range of 0 to 255.
445
- * Throws an error if the value is not valid.
446
- *
447
- * @param channelName - The name of the channel being validated.
448
- * @param value - The value of the channel to validate.
449
- * @throws Will throw an error if the value is not a valid channel number.
450
- *
451
- * @private util of `@promptbook/color`
452
- */
453
- function checkChannelValue(channelName, value) {
454
- if (typeof value !== 'number') {
455
- throw new Error(`${channelName} channel value is not number but ${typeof value}`);
456
- }
457
- if (isNaN(value)) {
458
- throw new Error(`${channelName} channel value is NaN`);
459
- }
460
- if (Math.round(value) !== value) {
461
- throw new Error(`${channelName} channel is not whole number, it is ${value}`);
462
- }
463
- if (value < 0) {
464
- throw new Error(`${channelName} channel is lower than 0, it is ${value}`);
465
- }
466
- if (value > 255) {
467
- throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
468
- }
469
- }
470
-
471
- /**
472
- * Shared immutable channel storage and serialization helpers for `Color`.
473
- *
474
- * @private base class of Color
475
- */
476
- class ColorValue {
477
- constructor(red, green, blue, alpha = 255) {
478
- this.red = red;
479
- this.green = green;
480
- this.blue = blue;
481
- this.alpha = alpha;
482
- checkChannelValue('Red', red);
483
- checkChannelValue('Green', green);
484
- checkChannelValue('Blue', blue);
485
- checkChannelValue('Alpha', alpha);
486
- }
487
- /**
488
- * Shortcut for `red` property
489
- * Number from 0 to 255
490
- * @alias red
491
- */
492
- get r() {
493
- return this.red;
494
- }
495
- /**
496
- * Shortcut for `green` property
497
- * Number from 0 to 255
498
- * @alias green
499
- */
500
- get g() {
501
- return this.green;
502
- }
503
- /**
504
- * Shortcut for `blue` property
505
- * Number from 0 to 255
506
- * @alias blue
507
- */
508
- get b() {
509
- return this.blue;
510
- }
511
- /**
512
- * Shortcut for `alpha` property
513
- * Number from 0 (transparent) to 255 (opaque)
514
- * @alias alpha
515
- */
516
- get a() {
517
- return this.alpha;
518
- }
519
- /**
520
- * Shortcut for `alpha` property
521
- * Number from 0 (transparent) to 255 (opaque)
522
- * @alias alpha
523
- */
524
- get opacity() {
525
- return this.alpha;
526
- }
527
- /**
528
- * Shortcut for 1-`alpha` property
529
- */
530
- get transparency() {
531
- return 255 - this.alpha;
532
- }
533
- clone() {
534
- return take(this.createColor(this.red, this.green, this.blue, this.alpha));
535
- }
536
- toString() {
537
- return this.toHex();
538
- }
539
- toHex() {
540
- if (this.alpha === 255) {
541
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
542
- .toString(16)
543
- .padStart(2, '0')}`;
544
- }
545
- else {
546
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
547
- .toString(16)
548
- .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
549
- }
550
- }
551
- toRgb() {
552
- if (this.alpha === 255) {
553
- return `rgb(${this.red}, ${this.green}, ${this.blue})`;
554
- }
555
- else {
556
- return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
557
- }
558
- }
559
- toHsl() {
560
- throw new Error(`Getting HSL is not implemented`);
561
- }
562
- }
563
-
564
564
  /**
565
565
  * Checks if the given value is a valid hex color string
566
566
  *
@@ -2302,6 +2302,95 @@
2302
2302
  // TODO: [🏛] Escape all
2303
2303
  // TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
2304
2304
 
2305
+ /**
2306
+ * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
2307
+ *
2308
+ * @public exported from `@promptbook/core`
2309
+ */
2310
+ class PipelineLogicError extends Error {
2311
+ constructor(message) {
2312
+ super(message);
2313
+ this.name = 'PipelineLogicError';
2314
+ Object.setPrototypeOf(this, PipelineLogicError.prototype);
2315
+ }
2316
+ }
2317
+
2318
+ /**
2319
+ * Creates the shared validation context for one pipeline.
2320
+ *
2321
+ * @private function of `validatePipeline`
2322
+ */
2323
+ function createPipelineValidationContext(pipeline) {
2324
+ return {
2325
+ pipeline,
2326
+ pipelineIdentification: getPipelineIdentification$1(pipeline),
2327
+ };
2328
+ }
2329
+ /**
2330
+ * Builds a short file/url identification block for validation errors.
2331
+ *
2332
+ * @private internal utility of `validatePipeline`
2333
+ */
2334
+ function getPipelineIdentification$1(pipeline) {
2335
+ // Note: This is a 😐 implementation of [🚞]
2336
+ const pipelineIdentificationParts = [];
2337
+ if (pipeline.sourceFile !== undefined) {
2338
+ pipelineIdentificationParts.push(`File: ${pipeline.sourceFile}`);
2339
+ }
2340
+ if (pipeline.pipelineUrl !== undefined) {
2341
+ pipelineIdentificationParts.push(`Url: ${pipeline.pipelineUrl}`);
2342
+ }
2343
+ return pipelineIdentificationParts.join('\n');
2344
+ }
2345
+
2346
+ /**
2347
+ * Validates that the expected top-level collections have array structure.
2348
+ *
2349
+ * @private function of `validatePipeline`
2350
+ */
2351
+ function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification, }) {
2352
+ validatePipelineParametersCollection(pipeline, pipelineIdentification);
2353
+ validatePipelineTasksCollection(pipeline, pipelineIdentification);
2354
+ }
2355
+ /**
2356
+ * Validates that `pipeline.parameters` is an array.
2357
+ *
2358
+ * @private internal utility of `validatePipelineCollectionsStructure`
2359
+ */
2360
+ function validatePipelineParametersCollection(pipeline, pipelineIdentification) {
2361
+ // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
2362
+ if (Array.isArray(pipeline.parameters)) {
2363
+ return;
2364
+ }
2365
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
2366
+ throw new ParseError(spacetrim.spaceTrim((block) => `
2367
+ Pipeline is valid JSON but with wrong structure
2368
+
2369
+ \`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
2370
+
2371
+ ${block(pipelineIdentification)}
2372
+ `));
2373
+ }
2374
+ /**
2375
+ * Validates that `pipeline.tasks` is an array.
2376
+ *
2377
+ * @private internal utility of `validatePipelineCollectionsStructure`
2378
+ */
2379
+ function validatePipelineTasksCollection(pipeline, pipelineIdentification) {
2380
+ // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
2381
+ if (Array.isArray(pipeline.tasks)) {
2382
+ return;
2383
+ }
2384
+ // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
2385
+ throw new ParseError(spacetrim.spaceTrim((block) => `
2386
+ Pipeline is valid JSON but with wrong structure
2387
+
2388
+ \`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
2389
+
2390
+ ${block(pipelineIdentification)}
2391
+ `));
2392
+ }
2393
+
2305
2394
  /**
2306
2395
  * Orders JSON object by keys
2307
2396
  *
@@ -2842,16 +2931,137 @@
2842
2931
  // Note: [💞] Ignore a discrepancy between file name and entity name
2843
2932
 
2844
2933
  /**
2845
- * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
2934
+ * Validates that task dependencies can be resolved without cycles or missing definitions.
2846
2935
  *
2847
- * @public exported from `@promptbook/core`
2936
+ * @private function of `validatePipeline`
2848
2937
  */
2849
- class PipelineLogicError extends Error {
2850
- constructor(message) {
2851
- super(message);
2852
- this.name = 'PipelineLogicError';
2853
- Object.setPrototypeOf(this, PipelineLogicError.prototype);
2938
+ function validatePipelineDependencyResolution({ pipeline, pipelineIdentification, }) {
2939
+ let dependencyResolutionState = createInitialDependencyResolutionState(pipeline);
2940
+ let loopLimit = LOOP_LIMIT;
2941
+ while (hasUnresolvedTasks(dependencyResolutionState)) {
2942
+ if (loopLimit-- < 0) {
2943
+ throw createDependencyResolutionLoopLimitError(pipelineIdentification);
2944
+ }
2945
+ dependencyResolutionState = resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification);
2946
+ }
2947
+ }
2948
+ /**
2949
+ * Collects the parameter names that are already resolvable before dependency traversal starts.
2950
+ *
2951
+ * @private internal utility of `validatePipelineDependencyResolution`
2952
+ */
2953
+ function createInitialDependencyResolutionState(pipeline) {
2954
+ return {
2955
+ resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
2956
+ unresolvedTasks: [...pipeline.tasks],
2957
+ };
2958
+ }
2959
+ /**
2960
+ * Checks whether dependency resolution still has tasks left to process.
2961
+ *
2962
+ * @private internal utility of `validatePipelineDependencyResolution`
2963
+ */
2964
+ function hasUnresolvedTasks({ unresolvedTasks }) {
2965
+ return unresolvedTasks.length > 0;
2966
+ }
2967
+ /**
2968
+ * Resolves the next batch of currently satisfiable tasks.
2969
+ *
2970
+ * @private internal utility of `validatePipelineDependencyResolution`
2971
+ */
2972
+ function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
2973
+ const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
2974
+ if (currentlyResolvedTasks.length === 0) {
2975
+ throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
2854
2976
  }
2977
+ return {
2978
+ resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
2979
+ unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
2980
+ };
2981
+ }
2982
+ /**
2983
+ * Collects the parameter names that are already resolvable before dependency traversal starts.
2984
+ *
2985
+ * @private internal utility of `validatePipelineDependencyResolution`
2986
+ */
2987
+ function createInitiallyResolvedParameterNames(pipeline) {
2988
+ let resolvedParameterNames = pipeline.parameters
2989
+ .filter(({ isInput }) => isInput)
2990
+ .map(({ name }) => name);
2991
+ for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
2992
+ resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
2993
+ }
2994
+ return resolvedParameterNames;
2995
+ }
2996
+ /**
2997
+ * Adds newly resolved task outputs to the resolved parameter list.
2998
+ *
2999
+ * @private internal utility of `validatePipelineDependencyResolution`
3000
+ */
3001
+ function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
3002
+ return [
3003
+ ...resolvedParameterNames,
3004
+ ...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
3005
+ ];
3006
+ }
3007
+ /**
3008
+ * Selects tasks whose dependencies are already resolved.
3009
+ *
3010
+ * @private internal utility of `validatePipelineDependencyResolution`
3011
+ */
3012
+ function getCurrentlyResolvedTasks(unresolvedTasks, resolvedParameterNames) {
3013
+ return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
3014
+ }
3015
+ /**
3016
+ * Creates the unexpected loop-limit error for dependency resolution.
3017
+ *
3018
+ * @private internal utility of `validatePipelineDependencyResolution`
3019
+ */
3020
+ function createDependencyResolutionLoopLimitError(pipelineIdentification) {
3021
+ // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
3022
+ return new UnexpectedError(spacetrim.spaceTrim((block) => `
3023
+ Loop limit reached during detection of circular dependencies in \`validatePipeline\`
3024
+
3025
+ ${block(pipelineIdentification)}
3026
+ `));
3027
+ }
3028
+ /**
3029
+ * Creates the detailed error for unresolved or circular task dependencies.
3030
+ *
3031
+ * @private internal utility of `validatePipelineDependencyResolution`
3032
+ */
3033
+ function createUnresolvedTasksError(unresolvedTasks, resolvedParameterNames, pipelineIdentification) {
3034
+ return new PipelineLogicError(
3035
+ // TODO: [🐎] DRY
3036
+ spacetrim.spaceTrim((block) => `
3037
+
3038
+ Can not resolve some parameters:
3039
+ Either you are using a parameter that is not defined, or there are some circular dependencies.
3040
+
3041
+ ${block(pipelineIdentification)}
3042
+
3043
+ **Can not resolve:**
3044
+ ${block(unresolvedTasks
3045
+ .map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
3046
+ .map((dependentParameterName) => `\`{${dependentParameterName}}\``)
3047
+ .join(' and ')}`)
3048
+ .join('\n'))}
3049
+
3050
+ **Resolved:**
3051
+ ${block(resolvedParameterNames
3052
+ .filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
3053
+ .map((name) => `- Parameter \`{${name}}\``)
3054
+ .join('\n'))}
3055
+
3056
+
3057
+ **Reserved (which are available):**
3058
+ ${block(resolvedParameterNames
3059
+ .filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
3060
+ .map((name) => `- Parameter \`{${name}}\``)
3061
+ .join('\n'))}
3062
+
3063
+
3064
+ `));
2855
3065
  }
2856
3066
 
2857
3067
  /**
@@ -2928,168 +3138,19 @@
2928
3138
  }
2929
3139
  // TODO: [🐠] Maybe more info why the URL is invalid
2930
3140
 
2931
- /**
2932
- * Validates PipelineJson if it is logically valid
2933
- *
2934
- * It checks:
2935
- * - if it has correct parameters dependency
2936
- *
2937
- * It does NOT check:
2938
- * - if it is valid json
2939
- * - if it is meaningful
2940
- *
2941
- * Note: [🔂] This function is idempotent.
2942
- *
2943
- * @param pipeline valid or invalid PipelineJson
2944
- * @returns the same pipeline if it is logically valid
2945
- * @throws {PipelineLogicError} on logical error in the pipeline
2946
- *
2947
- * @public exported from `@promptbook/core`
2948
- */
2949
- function validatePipeline(pipeline) {
2950
- if (IS_PIPELINE_LOGIC_VALIDATED) {
2951
- validatePipeline_InnerFunction(pipeline);
2952
- }
2953
- else {
2954
- try {
2955
- validatePipeline_InnerFunction(pipeline);
2956
- }
2957
- catch (error) {
2958
- if (!(error instanceof PipelineLogicError)) {
2959
- throw error;
2960
- }
2961
- console.error(spacetrim.spaceTrim((block) => `
2962
- Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
2963
-
2964
- ${block(error.message)}
2965
- `));
2966
- }
2967
- }
2968
- return pipeline;
2969
- }
2970
- /**
2971
- * Validates pipeline inner function.
2972
- *
2973
- * @private internal function for `validatePipeline`
2974
- */
2975
- function validatePipeline_InnerFunction(pipeline) {
2976
- // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
2977
- const context = createPipelineValidationContext(pipeline);
2978
- validatePipelineMetadata(context);
2979
- validatePipelineCollectionsStructure(context);
2980
- validatePipelineParameters(context);
2981
- validatePipelineTasks(context);
2982
- validatePipelineDependencyResolution(context);
2983
- // Note: Check that formfactor is corresponding to the pipeline interface
2984
- // TODO: !!6 Implement this
2985
- // pipeline.formfactorName
2986
- }
2987
- /**
2988
- * Creates the shared validation context for one pipeline.
2989
- *
2990
- * @private internal utility of `validatePipeline`
2991
- */
2992
- function createPipelineValidationContext(pipeline) {
2993
- return {
2994
- pipeline,
2995
- pipelineIdentification: getPipelineIdentification$1(pipeline),
2996
- };
2997
- }
2998
- /**
2999
- * Builds a short file/url identification block for validation errors.
3000
- *
3001
- * @private internal utility of `validatePipeline`
3002
- */
3003
- function getPipelineIdentification$1(pipeline) {
3004
- // Note: This is a 😐 implementation of [🚞]
3005
- const pipelineIdentificationParts = [];
3006
- if (pipeline.sourceFile !== undefined) {
3007
- pipelineIdentificationParts.push(`File: ${pipeline.sourceFile}`);
3008
- }
3009
- if (pipeline.pipelineUrl !== undefined) {
3010
- pipelineIdentificationParts.push(`Url: ${pipeline.pipelineUrl}`);
3011
- }
3012
- return pipelineIdentificationParts.join('\n');
3013
- }
3014
3141
  /**
3015
3142
  * Validates pipeline-level metadata fields.
3016
3143
  *
3017
- * @private internal step of `validatePipeline`
3144
+ * @private function of `validatePipeline`
3018
3145
  */
3019
3146
  function validatePipelineMetadata({ pipeline, pipelineIdentification }) {
3020
3147
  validatePipelineUrl(pipeline, pipelineIdentification);
3021
3148
  validatePipelineBookVersion(pipeline, pipelineIdentification);
3022
3149
  }
3023
- /**
3024
- * Validates that the expected top-level collections have array structure.
3025
- *
3026
- * @private internal step of `validatePipeline`
3027
- */
3028
- function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification }) {
3029
- validatePipelineParametersCollection(pipeline, pipelineIdentification);
3030
- validatePipelineTasksCollection(pipeline, pipelineIdentification);
3031
- }
3032
- /**
3033
- * Validates all pipeline parameter declarations.
3034
- *
3035
- * @private internal step of `validatePipeline`
3036
- */
3037
- function validatePipelineParameters({ pipeline, pipelineIdentification }) {
3038
- for (const parameter of pipeline.parameters) {
3039
- validatePipelineParameter(parameter, pipeline, pipelineIdentification);
3040
- }
3041
- }
3042
- /**
3043
- * Validates all pipeline tasks and their per-task invariants.
3044
- *
3045
- * @private internal step of `validatePipeline`
3046
- */
3047
- function validatePipelineTasks({ pipeline, pipelineIdentification }) {
3048
- // Note: All input parameters are defined - so that they can be used as result of some task
3049
- const definedParameters = createInitiallyDefinedParameters(pipeline);
3050
- for (const task of pipeline.tasks) {
3051
- validatePipelineTask(task, definedParameters, pipelineIdentification);
3052
- }
3053
- }
3054
- /**
3055
- * Validates that task dependencies can be resolved without cycles or missing definitions.
3056
- *
3057
- * @private internal step of `validatePipeline`
3058
- */
3059
- function validatePipelineDependencyResolution({ pipeline, pipelineIdentification }) {
3060
- let dependencyResolutionState = createInitialDependencyResolutionState(pipeline);
3061
- let loopLimit = LOOP_LIMIT;
3062
- while (hasUnresolvedTasks(dependencyResolutionState)) {
3063
- if (loopLimit-- < 0) {
3064
- throw createDependencyResolutionLoopLimitError(pipelineIdentification);
3065
- }
3066
- dependencyResolutionState = resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification);
3067
- }
3068
- }
3069
- /**
3070
- * Validates one pipeline parameter declaration.
3071
- *
3072
- * @private internal step of `validatePipeline`
3073
- */
3074
- function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
3075
- validateParameterDirection(parameter, pipelineIdentification);
3076
- validateParameterUsage(parameter, pipeline, pipelineIdentification);
3077
- validateParameterDefinition(parameter, pipeline, pipelineIdentification);
3078
- }
3079
- /**
3080
- * Validates one pipeline task and its invariants.
3081
- *
3082
- * @private internal step of `validatePipeline`
3083
- */
3084
- function validatePipelineTask(task, definedParameters, pipelineIdentification) {
3085
- validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
3086
- validateTaskJokers(task, pipelineIdentification);
3087
- validateTaskExpectations(task, pipelineIdentification);
3088
- }
3089
3150
  /**
3090
3151
  * Validates the pipeline URL, when present.
3091
3152
  *
3092
- * @private internal utility of `validatePipeline`
3153
+ * @private internal utility of `validatePipelineMetadata`
3093
3154
  */
3094
3155
  function validatePipelineUrl(pipeline, pipelineIdentification) {
3095
3156
  if (pipeline.pipelineUrl === undefined || isValidPipelineUrl(pipeline.pipelineUrl)) {
@@ -3105,7 +3166,7 @@
3105
3166
  /**
3106
3167
  * Validates the Promptbook version, when present.
3107
3168
  *
3108
- * @private internal utility of `validatePipeline`
3169
+ * @private internal utility of `validatePipelineMetadata`
3109
3170
  */
3110
3171
  function validatePipelineBookVersion(pipeline, pipelineIdentification) {
3111
3172
  if (pipeline.bookVersion === undefined || isValidPromptbookVersion(pipeline.bookVersion)) {
@@ -3118,48 +3179,31 @@
3118
3179
  ${block(pipelineIdentification)}
3119
3180
  `));
3120
3181
  }
3182
+
3121
3183
  /**
3122
- * Validates that `pipeline.parameters` is an array.
3184
+ * Validates all pipeline parameter declarations.
3123
3185
  *
3124
- * @private internal utility of `validatePipeline`
3186
+ * @private function of `validatePipeline`
3125
3187
  */
3126
- function validatePipelineParametersCollection(pipeline, pipelineIdentification) {
3127
- // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
3128
- if (Array.isArray(pipeline.parameters)) {
3129
- return;
3188
+ function validatePipelineParameters({ pipeline, pipelineIdentification }) {
3189
+ for (const parameter of pipeline.parameters) {
3190
+ validatePipelineParameter(parameter, pipeline, pipelineIdentification);
3130
3191
  }
3131
- // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
3132
- throw new ParseError(spacetrim.spaceTrim((block) => `
3133
- Pipeline is valid JSON but with wrong structure
3134
-
3135
- \`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
3136
-
3137
- ${block(pipelineIdentification)}
3138
- `));
3139
3192
  }
3140
3193
  /**
3141
- * Validates that `pipeline.tasks` is an array.
3194
+ * Validates one pipeline parameter declaration.
3142
3195
  *
3143
- * @private internal utility of `validatePipeline`
3196
+ * @private internal utility of `validatePipelineParameters`
3144
3197
  */
3145
- function validatePipelineTasksCollection(pipeline, pipelineIdentification) {
3146
- // TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
3147
- if (Array.isArray(pipeline.tasks)) {
3148
- return;
3149
- }
3150
- // TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
3151
- throw new ParseError(spacetrim.spaceTrim((block) => `
3152
- Pipeline is valid JSON but with wrong structure
3153
-
3154
- \`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
3155
-
3156
- ${block(pipelineIdentification)}
3157
- `));
3198
+ function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
3199
+ validateParameterDirection(parameter, pipelineIdentification);
3200
+ validateParameterUsage(parameter, pipeline, pipelineIdentification);
3201
+ validateParameterDefinition(parameter, pipeline, pipelineIdentification);
3158
3202
  }
3159
3203
  /**
3160
3204
  * Validates that one parameter does not declare incompatible directions.
3161
3205
  *
3162
- * @private internal utility of `validatePipeline`
3206
+ * @private internal utility of `validatePipelineParameters`
3163
3207
  */
3164
3208
  function validateParameterDirection(parameter, pipelineIdentification) {
3165
3209
  if (!parameter.isInput || !parameter.isOutput) {
@@ -3176,7 +3220,7 @@
3176
3220
  /**
3177
3221
  * Validates that one intermediate parameter is actually consumed by at least one task.
3178
3222
  *
3179
- * @private internal utility of `validatePipeline`
3223
+ * @private internal utility of `validatePipelineParameters`
3180
3224
  */
3181
3225
  function validateParameterUsage(parameter, pipeline, pipelineIdentification) {
3182
3226
  if (parameter.isInput || parameter.isOutput || isParameterUsedByAnyTask(parameter, pipeline.tasks)) {
@@ -3195,7 +3239,7 @@
3195
3239
  /**
3196
3240
  * Validates that one non-input parameter is produced by at least one task.
3197
3241
  *
3198
- * @private internal utility of `validatePipeline`
3242
+ * @private internal utility of `validatePipelineParameters`
3199
3243
  */
3200
3244
  function validateParameterDefinition(parameter, pipeline, pipelineIdentification) {
3201
3245
  if (parameter.isInput || isParameterDefinedByAnyTask(parameter, pipeline.tasks)) {
@@ -3214,7 +3258,7 @@
3214
3258
  /**
3215
3259
  * Checks whether one parameter is consumed by at least one task dependency list.
3216
3260
  *
3217
- * @private internal utility of `validatePipeline`
3261
+ * @private internal utility of `validatePipelineParameters`
3218
3262
  */
3219
3263
  function isParameterUsedByAnyTask(parameter, tasks) {
3220
3264
  return tasks.some((task) => task.dependentParameterNames.includes(parameter.name));
@@ -3222,23 +3266,46 @@
3222
3266
  /**
3223
3267
  * Checks whether one parameter is produced by at least one task.
3224
3268
  *
3225
- * @private internal utility of `validatePipeline`
3269
+ * @private internal utility of `validatePipelineParameters`
3226
3270
  */
3227
3271
  function isParameterDefinedByAnyTask(parameter, tasks) {
3228
3272
  return tasks.some((task) => task.resultingParameterName === parameter.name);
3229
3273
  }
3274
+
3275
+ /**
3276
+ * Validates all pipeline tasks and their per-task invariants.
3277
+ *
3278
+ * @private function of `validatePipeline`
3279
+ */
3280
+ function validatePipelineTasks({ pipeline, pipelineIdentification }) {
3281
+ // Note: All input parameters are defined - so that they can be used as result of some task
3282
+ const definedParameters = createInitiallyDefinedParameters(pipeline);
3283
+ for (const task of pipeline.tasks) {
3284
+ validatePipelineTask(task, definedParameters, pipelineIdentification);
3285
+ }
3286
+ }
3230
3287
  /**
3231
3288
  * Collects the parameter names that are already defined before task validation starts.
3232
3289
  *
3233
- * @private internal utility of `validatePipeline`
3290
+ * @private internal utility of `validatePipelineTasks`
3234
3291
  */
3235
3292
  function createInitiallyDefinedParameters(pipeline) {
3236
3293
  return new Set(pipeline.parameters.filter(({ isInput }) => isInput).map(({ name }) => name));
3237
3294
  }
3295
+ /**
3296
+ * Validates one pipeline task and its invariants.
3297
+ *
3298
+ * @private internal utility of `validatePipelineTasks`
3299
+ */
3300
+ function validatePipelineTask(task, definedParameters, pipelineIdentification) {
3301
+ validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
3302
+ validateTaskJokers(task, pipelineIdentification);
3303
+ validateTaskExpectations(task, pipelineIdentification);
3304
+ }
3238
3305
  /**
3239
3306
  * Validates one task result parameter declaration and marks it as defined.
3240
3307
  *
3241
- * @private internal utility of `validatePipeline`
3308
+ * @private internal utility of `validatePipelineTasks`
3242
3309
  */
3243
3310
  function validateTaskResultingParameter(task, definedParameters, pipelineIdentification) {
3244
3311
  if (definedParameters.has(task.resultingParameterName)) {
@@ -3260,7 +3327,7 @@
3260
3327
  /**
3261
3328
  * Validates joker parameters for one task.
3262
3329
  *
3263
- * @private internal utility of `validatePipeline`
3330
+ * @private internal utility of `validatePipelineTasks`
3264
3331
  */
3265
3332
  function validateTaskJokers(task, pipelineIdentification) {
3266
3333
  if (!hasTaskJokers(task)) {
@@ -3272,7 +3339,7 @@
3272
3339
  /**
3273
3340
  * Checks whether one task declares any joker parameters.
3274
3341
  *
3275
- * @private internal utility of `validatePipeline`
3342
+ * @private internal utility of `validatePipelineTasks`
3276
3343
  */
3277
3344
  function hasTaskJokers(task) {
3278
3345
  return !!task.jokerParameterNames && task.jokerParameterNames.length > 0;
@@ -3280,7 +3347,7 @@
3280
3347
  /**
3281
3348
  * Validates that a task has the required supporting features when using jokers.
3282
3349
  *
3283
- * @private internal utility of `validatePipeline`
3350
+ * @private internal utility of `validatePipelineTasks`
3284
3351
  */
3285
3352
  function validateTaskSupportsJokers(task, pipelineIdentification) {
3286
3353
  if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
@@ -3295,7 +3362,7 @@
3295
3362
  /**
3296
3363
  * Validates that every joker parameter is also listed among task dependencies.
3297
3364
  *
3298
- * @private internal utility of `validatePipeline`
3365
+ * @private internal utility of `validatePipelineTasks`
3299
3366
  */
3300
3367
  function validateTaskJokerDependencies(task, pipelineIdentification) {
3301
3368
  for (const joker of task.jokerParameterNames) {
@@ -3312,7 +3379,7 @@
3312
3379
  /**
3313
3380
  * Validates all expectation bounds configured on one task.
3314
3381
  *
3315
- * @private internal utility of `validatePipeline`
3382
+ * @private internal utility of `validatePipelineTasks`
3316
3383
  */
3317
3384
  function validateTaskExpectations(task, pipelineIdentification) {
3318
3385
  if (!task.expectations) {
@@ -3327,7 +3394,7 @@
3327
3394
  /**
3328
3395
  * Validates the minimum and maximum expectation ordering for one unit.
3329
3396
  *
3330
- * @private internal utility of `validatePipeline`
3397
+ * @private internal utility of `validatePipelineTasks`
3331
3398
  */
3332
3399
  function validateTaskExpectationRange(unit, min, max, pipelineIdentification) {
3333
3400
  if (min === undefined || max === undefined || min <= max) {
@@ -3342,7 +3409,7 @@
3342
3409
  /**
3343
3410
  * Validates the minimum expectation bound for one unit.
3344
3411
  *
3345
- * @private internal utility of `validatePipeline`
3412
+ * @private internal utility of `validatePipelineTasks`
3346
3413
  */
3347
3414
  function validateTaskExpectationMin(unit, min, pipelineIdentification) {
3348
3415
  if (min === undefined || min >= 0) {
@@ -3357,7 +3424,7 @@
3357
3424
  /**
3358
3425
  * Validates the maximum expectation bound for one unit.
3359
3426
  *
3360
- * @private internal utility of `validatePipeline`
3427
+ * @private internal utility of `validatePipelineTasks`
3361
3428
  */
3362
3429
  function validateTaskExpectationMax(unit, max, pipelineIdentification) {
3363
3430
  if (max === undefined || max > 0) {
@@ -3369,123 +3436,62 @@
3369
3436
  ${block(pipelineIdentification)}
3370
3437
  `));
3371
3438
  }
3439
+
3372
3440
  /**
3373
- * Collects the parameter names that are already resolvable before dependency traversal starts.
3374
- *
3375
- * @private internal utility of `validatePipeline`
3376
- */
3377
- function createInitialDependencyResolutionState(pipeline) {
3378
- return {
3379
- resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
3380
- unresolvedTasks: [...pipeline.tasks],
3381
- };
3382
- }
3383
- /**
3384
- * Checks whether dependency resolution still has tasks left to process.
3385
- *
3386
- * @private internal utility of `validatePipeline`
3387
- */
3388
- function hasUnresolvedTasks({ unresolvedTasks }) {
3389
- return unresolvedTasks.length > 0;
3390
- }
3391
- /**
3392
- * Resolves the next batch of currently satisfiable tasks.
3441
+ * Validates PipelineJson if it is logically valid
3393
3442
  *
3394
- * @private internal utility of `validatePipeline`
3395
- */
3396
- function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
3397
- const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
3398
- if (currentlyResolvedTasks.length === 0) {
3399
- throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
3400
- }
3401
- return {
3402
- resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
3403
- unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
3404
- };
3405
- }
3406
- /**
3407
- * Collects the parameter names that are already resolvable before dependency traversal starts.
3443
+ * It checks:
3444
+ * - if it has correct parameters dependency
3408
3445
  *
3409
- * @private internal utility of `validatePipeline`
3410
- */
3411
- function createInitiallyResolvedParameterNames(pipeline) {
3412
- let resolvedParameterNames = pipeline.parameters
3413
- .filter(({ isInput }) => isInput)
3414
- .map(({ name }) => name);
3415
- for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
3416
- resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
3417
- }
3418
- return resolvedParameterNames;
3419
- }
3420
- /**
3421
- * Adds newly resolved task outputs to the resolved parameter list.
3446
+ * It does NOT check:
3447
+ * - if it is valid json
3448
+ * - if it is meaningful
3422
3449
  *
3423
- * @private internal utility of `validatePipeline`
3424
- */
3425
- function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
3426
- return [
3427
- ...resolvedParameterNames,
3428
- ...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
3429
- ];
3430
- }
3431
- /**
3432
- * Selects tasks whose dependencies are already resolved.
3450
+ * Note: [🔂] This function is idempotent.
3433
3451
  *
3434
- * @private internal utility of `validatePipeline`
3435
- */
3436
- function getCurrentlyResolvedTasks(unresolvedTasks, resolvedParameterNames) {
3437
- return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
3438
- }
3439
- /**
3440
- * Creates the unexpected loop-limit error for dependency resolution.
3452
+ * @param pipeline valid or invalid PipelineJson
3453
+ * @returns the same pipeline if it is logically valid
3454
+ * @throws {PipelineLogicError} on logical error in the pipeline
3441
3455
  *
3442
- * @private internal utility of `validatePipeline`
3456
+ * @public exported from `@promptbook/core`
3443
3457
  */
3444
- function createDependencyResolutionLoopLimitError(pipelineIdentification) {
3445
- // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
3446
- return new UnexpectedError(spacetrim.spaceTrim((block) => `
3447
- Loop limit reached during detection of circular dependencies in \`validatePipeline\`
3458
+ function validatePipeline(pipeline) {
3459
+ if (IS_PIPELINE_LOGIC_VALIDATED) {
3460
+ validatePipeline_InnerFunction(pipeline);
3461
+ }
3462
+ else {
3463
+ try {
3464
+ validatePipeline_InnerFunction(pipeline);
3465
+ }
3466
+ catch (error) {
3467
+ if (!(error instanceof PipelineLogicError)) {
3468
+ throw error;
3469
+ }
3470
+ console.error(spacetrim.spaceTrim((block) => `
3471
+ Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
3448
3472
 
3449
- ${block(pipelineIdentification)}
3450
- `));
3473
+ ${block(error.message)}
3474
+ `));
3475
+ }
3476
+ }
3477
+ return pipeline;
3451
3478
  }
3452
3479
  /**
3453
- * Creates the detailed error for unresolved or circular task dependencies.
3480
+ * Validates pipeline inner function.
3454
3481
  *
3455
- * @private internal utility of `validatePipeline`
3482
+ * @private internal function for `validatePipeline`
3456
3483
  */
3457
- function createUnresolvedTasksError(unresolvedTasks, resolvedParameterNames, pipelineIdentification) {
3458
- return new PipelineLogicError(
3459
- // TODO: [🐎] DRY
3460
- spacetrim.spaceTrim((block) => `
3461
-
3462
- Can not resolve some parameters:
3463
- Either you are using a parameter that is not defined, or there are some circular dependencies.
3464
-
3465
- ${block(pipelineIdentification)}
3466
-
3467
- **Can not resolve:**
3468
- ${block(unresolvedTasks
3469
- .map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
3470
- .map((dependentParameterName) => `\`{${dependentParameterName}}\``)
3471
- .join(' and ')}`)
3472
- .join('\n'))}
3473
-
3474
- **Resolved:**
3475
- ${block(resolvedParameterNames
3476
- .filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
3477
- .map((name) => `- Parameter \`{${name}}\``)
3478
- .join('\n'))}
3479
-
3480
-
3481
- **Reserved (which are available):**
3482
- ${block(resolvedParameterNames
3483
- .filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
3484
- .map((name) => `- Parameter \`{${name}}\``)
3485
- .join('\n'))}
3486
-
3487
-
3488
- `));
3484
+ function validatePipeline_InnerFunction(pipeline) {
3485
+ // TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
3486
+ const context = createPipelineValidationContext(pipeline);
3487
+ validatePipelineMetadata(context);
3488
+ validatePipelineCollectionsStructure(context);
3489
+ validatePipelineParameters(context);
3490
+ validatePipelineTasks(context);
3491
+ validatePipelineDependencyResolution(context);
3492
+ // Note: Check that formfactor is corresponding to the pipeline interface
3493
+ // TODO: !!6 Implement this
3494
+ // pipeline.formfactorName
3489
3495
  }
3490
3496
  /**
3491
3497
  * TODO: [🧞‍♀️] Do not allow joker + foreach
@@ -11894,7 +11900,7 @@
11894
11900
  * META commitment definition
11895
11901
  *
11896
11902
  * The META commitment handles all meta-information about the agent such as:
11897
- * - META AVATAR: Sets the agent's built-in default avatar visual
11903
+ * - META AVATAR / META VISUAL: Sets the agent's built-in default avatar visual
11898
11904
  * - META IMAGE: Sets the agent's avatar/profile image URL
11899
11905
  * - META LINK: Provides profile/source links for the person the agent models
11900
11906
  * - META DOMAIN: Sets the canonical custom domain/host of the agent
@@ -11909,7 +11915,7 @@
11909
11915
  * Example usage in agent source:
11910
11916
  *
11911
11917
  * ```book
11912
- * META AVATAR pixel-art
11918
+ * META VISUAL pixel-art
11913
11919
  * META IMAGE https://example.com/avatar.jpg
11914
11920
  * META LINK https://twitter.com/username
11915
11921
  * META DOMAIN my-agent.com
@@ -11949,7 +11955,7 @@
11949
11955
 
11950
11956
  ## Supported META types
11951
11957
 
11952
- - **META AVATAR** - Sets the agent's built-in default avatar visual
11958
+ - **META AVATAR** / **META VISUAL** - Sets the agent's built-in default avatar visual
11953
11959
  - **META IMAGE** - Sets the agent's avatar/profile image URL
11954
11960
  - **META LINK** - Provides profile/source links for the person the agent models
11955
11961
  - **META DOMAIN** - Sets the canonical custom domain/host of the agent
@@ -11973,7 +11979,7 @@
11973
11979
  \`\`\`book
11974
11980
  Professional Assistant
11975
11981
 
11976
- META AVATAR octopus3
11982
+ META VISUAL octopus3
11977
11983
  META IMAGE https://example.com/professional-avatar.jpg
11978
11984
  META TITLE Senior Business Consultant
11979
11985
  META DESCRIPTION Specialized in strategic planning and project management
@@ -15144,452 +15150,13 @@
15144
15150
  .padStart(2, '0');
15145
15151
  }
15146
15152
 
15147
- /* eslint-disable no-magic-numbers */
15148
- /**
15149
- * Light direction used by the organic 3D octopus shading.
15150
- *
15151
- * @private helper of `octopus3dAvatarVisual`
15152
- */
15153
- const LIGHT_DIRECTION$3 = normalizeVector3({
15154
- x: 0.48,
15155
- y: -0.62,
15156
- z: 0.94,
15157
- });
15158
- /**
15159
- * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
15160
- *
15161
- * @private helper of `octopus3dAvatarVisual`
15162
- */
15163
- const octopus3dStableStateCache = new WeakMap();
15164
- /**
15165
- * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
15166
- *
15167
- * @private helper of `octopus3dAvatarVisual`
15168
- */
15169
- function getOctopus3dStableState(createRandom) {
15170
- const cached = octopus3dStableStateCache.get(createRandom);
15171
- if (cached !== undefined) {
15172
- return cached;
15173
- }
15174
- const animationRandom = createRandom('octopus3d-animation-profile');
15175
- const eyeRandom = createRandom('octopus3d-eye-profile');
15176
- const leftEyePhaseOffset = eyeRandom() * 0.6;
15177
- const rightEyePhaseOffset = eyeRandom() * 0.6;
15178
- const state = {
15179
- morphologyProfile: createOctopus3MorphologyProfile(createRandom),
15180
- animationPhase: animationRandom() * Math.PI * 2,
15181
- leftEyePhaseOffset,
15182
- rightEyePhaseOffset,
15183
- };
15184
- octopus3dStableStateCache.set(createRandom, state);
15185
- return state;
15186
- }
15187
- /**
15188
- * Proper 3D Octopus visual built from projected organic meshes and tentacles.
15189
- *
15190
- * @private built-in avatar visual
15191
- */
15192
- const octopus3dAvatarVisual = {
15193
- id: 'octopus3d',
15194
- title: 'Octopus 3D',
15195
- description: 'Proper 3D octopus portrait with a turning silhouette, expressive eyes, and depth-sorted tentacles.',
15196
- isAnimated: true,
15197
- supportsPointerTracking: true,
15198
- render({ context, size, palette, createRandom, timeMs, interaction }) {
15199
- const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
15200
- const sceneCenterX = size * 0.5;
15201
- const sceneCenterY = size * 0.56;
15202
- const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
15203
- const mantleCenter = {
15204
- x: interaction.bodyOffsetX * size * 0.042 + size * morphologyProfile.body.centerXJitterRatio * 0.65,
15205
- y: -size * 0.09 + interaction.bodyOffsetY * size * 0.028 + bob,
15206
- z: interaction.intensity * size * 0.012,
15207
- };
15208
- const underbodyCenter = {
15209
- x: mantleCenter.x * 0.86,
15210
- y: mantleCenter.y + size * 0.168,
15211
- z: mantleCenter.z - size * 0.018,
15212
- };
15213
- const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
15214
- const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
15215
- const mantleRadiusZ = size *
15216
- morphologyProfile.body.bodyRadiusRatio *
15217
- (0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
15218
- const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
15219
- const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
15220
- const underbodyRadiusZ = mantleRadiusZ * 0.78;
15221
- const bodyYaw = -0.18 +
15222
- Math.sin(timeMs / 2400 + animationPhase) * 0.05 +
15223
- interaction.bodyOffsetX * 0.18 +
15224
- interaction.gazeX * 0.22;
15225
- const bodyPitch = -0.08 +
15226
- Math.cos(timeMs / 2700 + animationPhase * 0.6) * 0.025 -
15227
- interaction.bodyOffsetY * 0.08 -
15228
- interaction.gazeY * 0.08;
15229
- const headYaw = bodyYaw - 0.04 + interaction.gazeX * 0.56;
15230
- const headPitch = bodyPitch - 0.02 - interaction.gazeY * 0.32;
15231
- const mantlePatches = resolveVisibleEllipsoidPatches({
15232
- center: mantleCenter,
15233
- radiusX: mantleRadiusX,
15234
- radiusY: mantleRadiusY,
15235
- radiusZ: mantleRadiusZ,
15236
- rotationX: headPitch,
15237
- rotationY: headYaw,
15238
- sceneCenterX,
15239
- sceneCenterY,
15240
- size,
15241
- palette,
15242
- verticalColorBias: 0,
15243
- outlineColor: `${palette.highlight}7a`,
15244
- });
15245
- const underbodyPatches = resolveVisibleEllipsoidPatches({
15246
- center: underbodyCenter,
15247
- radiusX: underbodyRadiusX,
15248
- radiusY: underbodyRadiusY,
15249
- radiusZ: underbodyRadiusZ,
15250
- rotationX: bodyPitch,
15251
- rotationY: bodyYaw,
15252
- sceneCenterX,
15253
- sceneCenterY,
15254
- size,
15255
- palette,
15256
- verticalColorBias: 0.18,
15257
- outlineColor: `${palette.shadow}8f`,
15258
- });
15259
- const tentacleStrokes = createOctopusTentacleStrokes({
15260
- createRandom,
15261
- morphologyProfile,
15262
- timeMs,
15263
- size,
15264
- center: underbodyCenter,
15265
- radiusX: underbodyRadiusX,
15266
- radiusY: underbodyRadiusY,
15267
- radiusZ: underbodyRadiusZ,
15268
- rotationX: bodyPitch,
15269
- rotationY: bodyYaw,
15270
- sceneCenterX,
15271
- sceneCenterY,
15272
- animationPhase,
15273
- });
15274
- const faceEyeSpacing = size * morphologyProfile.face.eyeSpacingRatio * 0.92;
15275
- const faceEyeYOffset = size * morphologyProfile.face.eyeCenterYOffsetRatio - mantleRadiusY * 0.02;
15276
- const faceEyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.82;
15277
- const faceEyeRadiusY = faceEyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.96;
15278
- const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio * 0.92;
15279
- const mouthY = size * morphologyProfile.face.mouthYOffsetRatio + mantleRadiusY * 0.08;
15280
- drawAvatarFrame(context, size, palette);
15281
- drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
15282
- drawOctopus3dShadow(context, size, palette, interaction, timeMs);
15283
- for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => !candidateTentacleStroke.isFrontFacing)) {
15284
- drawTentacleStroke(context, tentacleStroke, palette);
15285
- }
15286
- for (const surfacePatch of [...mantlePatches, ...underbodyPatches].sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
15287
- drawSurfacePatch(context, surfacePatch);
15288
- }
15289
- for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
15290
- drawTentacleStroke(context, tentacleStroke, palette);
15291
- }
15292
- drawProjectedOrganicEye(context, {
15293
- x: -faceEyeSpacing,
15294
- y: faceEyeYOffset,
15295
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
15296
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
15297
- drawProjectedOrganicEye(context, {
15298
- x: faceEyeSpacing,
15299
- y: faceEyeYOffset,
15300
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
15301
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
15302
- drawProjectedOrganicMouth(context, [
15303
- {
15304
- x: -mouthHalfWidth,
15305
- y: mouthY,
15306
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
15307
- },
15308
- {
15309
- x: size * morphologyProfile.face.mouthCenterOffsetRatio,
15310
- y: mouthY +
15311
- size * morphologyProfile.face.mouthCurveDepthRatio * 0.38 +
15312
- Math.sin(timeMs / 760 + animationPhase) * size * 0.01 +
15313
- interaction.gazeY * size * 0.01,
15314
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
15315
- },
15316
- {
15317
- x: mouthHalfWidth,
15318
- y: mouthY,
15319
- z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
15320
- },
15321
- ], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
15322
- },
15323
- };
15324
- /**
15325
- * Draws the atmospheric underwater glow behind the octopus mesh.
15326
- *
15327
- * @private helper of `octopus3dAvatarVisual`
15328
- */
15329
- function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
15330
- 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);
15331
- glowGradient.addColorStop(0, `${palette.highlight}5c`);
15332
- glowGradient.addColorStop(0.36, `${palette.accent}24`);
15333
- glowGradient.addColorStop(1, `${palette.highlight}00`);
15334
- context.fillStyle = glowGradient;
15335
- context.fillRect(0, 0, size, size);
15336
- 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);
15337
- lowerGradient.addColorStop(0, `${palette.secondary}1d`);
15338
- lowerGradient.addColorStop(1, `${palette.secondary}00`);
15339
- context.fillStyle = lowerGradient;
15340
- context.fillRect(0, 0, size, size);
15341
- }
15342
- /**
15343
- * Draws the soft ground shadow below the octopus.
15344
- *
15345
- * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
15346
- * blurry ellipse without triggering a costly software rasterization pass on every frame.
15347
- *
15348
- * @private helper of `octopus3dAvatarVisual`
15349
- */
15350
- function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
15351
- const cx = size * 0.5 + interaction.gazeX * size * 0.04;
15352
- const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
15353
- const rx = size * (0.18 + interaction.intensity * 0.02);
15354
- const ry = size * 0.06;
15355
- context.save();
15356
- context.translate(cx, cy);
15357
- context.scale(1, ry / rx);
15358
- const blurRadius = rx * 1.4;
15359
- const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
15360
- shadowGradient.addColorStop(0, `${palette.shadow}7a`);
15361
- shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
15362
- shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
15363
- shadowGradient.addColorStop(1, `${palette.shadow}00`);
15364
- context.fillStyle = shadowGradient;
15365
- context.beginPath();
15366
- context.arc(0, 0, blurRadius, 0, Math.PI * 2);
15367
- context.fill();
15368
- context.restore();
15369
- }
15370
- /**
15371
- * Resolves visible projected patches for one rotated ellipsoid mesh.
15372
- *
15373
- * @private helper of `octopus3dAvatarVisual`
15374
- */
15375
- function resolveVisibleEllipsoidPatches(options) {
15376
- const { center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, verticalColorBias, outlineColor, } = options;
15377
- const latitudePatchCount = 10;
15378
- const longitudePatchCount = 18;
15379
- const surfacePatches = [];
15380
- for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
15381
- const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
15382
- const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
15383
- const verticalProgress = (latitudeIndex + 0.5) / latitudePatchCount;
15384
- for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
15385
- const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
15386
- const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
15387
- const localCorners = [
15388
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, startLongitude),
15389
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, endLongitude),
15390
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, endLongitude),
15391
- sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, startLongitude),
15392
- ];
15393
- const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
15394
- const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
15395
- if (surfaceNormal.z <= 0.01) {
15396
- continue;
15397
- }
15398
- const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
15399
- surfacePatches.push({
15400
- corners: projectedCorners,
15401
- averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
15402
- transformedCorners.length,
15403
- lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$3), -1, 1),
15404
- fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
15405
- outlineColor,
15406
- });
15407
- }
15408
- }
15409
- return surfacePatches;
15410
- }
15411
- /**
15412
- * Samples one point on an ellipsoid aligned to the local axes.
15413
- *
15414
- * @private helper of `octopus3dAvatarVisual`
15415
- */
15416
- function sampleEllipsoidPoint(radiusX, radiusY, radiusZ, latitude, longitude) {
15417
- const cosineLatitude = Math.cos(latitude);
15418
- return {
15419
- x: Math.sin(longitude) * cosineLatitude * radiusX,
15420
- y: Math.sin(latitude) * radiusY,
15421
- z: Math.cos(longitude) * cosineLatitude * radiusZ,
15422
- };
15423
- }
15424
- /**
15425
- * Resolves one base fill tone for a surface patch across the octopus body.
15426
- *
15427
- * @private helper of `octopus3dAvatarVisual`
15428
- */
15429
- function resolveSurfacePatchFillStyle(palette, verticalProgress) {
15430
- const clampedVerticalProgress = clampNumber$1(verticalProgress, 0, 1);
15431
- if (clampedVerticalProgress < 0.2) {
15432
- return palette.highlight;
15433
- }
15434
- if (clampedVerticalProgress < 0.45) {
15435
- return palette.secondary;
15436
- }
15437
- if (clampedVerticalProgress < 0.8) {
15438
- return palette.primary;
15439
- }
15440
- return `${palette.shadow}f2`;
15441
- }
15442
- /**
15443
- * Draws one projected mesh patch with organic shading.
15444
- *
15445
- * @private helper of `octopus3dAvatarVisual`
15446
- */
15447
- function drawSurfacePatch(context, surfacePatch) {
15448
- drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
15449
- if (surfacePatch.lightIntensity > 0) {
15450
- drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.15 * surfacePatch.lightIntensity})`);
15451
- }
15452
- else if (surfacePatch.lightIntensity < 0) {
15453
- drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
15454
- }
15455
- context.save();
15456
- context.beginPath();
15457
- context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
15458
- for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
15459
- context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
15460
- }
15461
- context.closePath();
15462
- context.strokeStyle = surfacePatch.outlineColor;
15463
- context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0044);
15464
- context.lineJoin = 'round';
15465
- context.stroke();
15466
- context.restore();
15467
- }
15468
- /**
15469
- * Creates the projected 3D tentacle strokes orbiting around the lower octopus body.
15470
- *
15471
- * @private helper of `octopus3dAvatarVisual`
15472
- */
15473
- function createOctopusTentacleStrokes(options) {
15474
- const { createRandom, morphologyProfile, timeMs, size, center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, animationPhase, } = options;
15475
- return Array.from({ length: morphologyProfile.tentacles.count }, (_, tentacleIndex) => {
15476
- const tentacleRandom = createRandom(`octopus3d-tentacle-${tentacleIndex}`);
15477
- const spreadProgress = morphologyProfile.tentacles.count === 1 ? 0.5 : tentacleIndex / (morphologyProfile.tentacles.count - 1);
15478
- const orbitAngle = -Math.PI * 0.92 + spreadProgress * Math.PI * 1.84 + (tentacleRandom() - 0.5) * 0.16;
15479
- const flowLength = size * (0.19 + morphologyProfile.tentacles.flowLengthScale * 0.075 + tentacleRandom() * 0.018);
15480
- const lateralReach = size *
15481
- (0.08 + morphologyProfile.tentacles.lateralReachScale * 0.05 + Math.abs(Math.sin(orbitAngle)) * 0.018);
15482
- const depthReach = size * (0.028 + morphologyProfile.tentacles.tipReachScale * 0.032);
15483
- const sway = Math.sin(timeMs / (760 + tentacleIndex * 36) + animationPhase + tentacleRandom() * Math.PI * 2);
15484
- const anchorPoint = {
15485
- x: Math.sin(orbitAngle) * radiusX * (0.84 + tentacleRandom() * 0.08),
15486
- y: radiusY * (0.22 + tentacleRandom() * 0.18),
15487
- z: Math.cos(orbitAngle) * radiusZ * (0.72 + tentacleRandom() * 0.12),
15488
- };
15489
- const controlPointOne = {
15490
- x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * 0.44,
15491
- y: anchorPoint.y + flowLength * 0.26,
15492
- z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
15493
- };
15494
- const controlPointTwo = {
15495
- x: anchorPoint.x +
15496
- Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
15497
- y: anchorPoint.y + flowLength * 0.66,
15498
- z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
15499
- };
15500
- const endPoint = {
15501
- x: anchorPoint.x +
15502
- Math.sin(orbitAngle) * lateralReach * (1.02 + morphologyProfile.tentacles.tipWidthScale * 0.12) +
15503
- sway * size * 0.028,
15504
- y: anchorPoint.y + flowLength,
15505
- z: anchorPoint.z + Math.cos(orbitAngle) * depthReach + sway * size * 0.016,
15506
- };
15507
- const scenePoints = Array.from({ length: 12 }, (_, sampleIndex) => transformScenePoint(sampleCubicBezierPoint3D(anchorPoint, controlPointOne, controlPointTwo, endPoint, sampleIndex / 11), center, rotationX, rotationY));
15508
- const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
15509
- const averageDepth = scenePoints.reduce((depthSum, scenePoint) => depthSum + scenePoint.z, 0) / scenePoints.length;
15510
- return {
15511
- projectedPoints,
15512
- averageDepth,
15513
- isFrontFacing: averageDepth >= center.z - size * 0.006,
15514
- baseWidth: size *
15515
- (0.019 +
15516
- morphologyProfile.tentacles.baseWidthScale * 0.007 +
15517
- tentacleRandom() * 0.003 +
15518
- Math.abs(Math.sin(orbitAngle)) * 0.002),
15519
- tipWidth: size * (0.0046 + morphologyProfile.tentacles.tipWidthScale * 0.0018),
15520
- colorBias: tentacleRandom(),
15521
- };
15522
- });
15523
- }
15524
- /**
15525
- * Samples one point on a cubic Bezier curve in 3D.
15526
- *
15527
- * @private helper of `octopus3dAvatarVisual`
15528
- */
15529
- function sampleCubicBezierPoint3D(startPoint, controlPointOne, controlPointTwo, endPoint, progress) {
15530
- const inverseProgress = 1 - progress;
15531
- return {
15532
- x: inverseProgress * inverseProgress * inverseProgress * startPoint.x +
15533
- 3 * inverseProgress * inverseProgress * progress * controlPointOne.x +
15534
- 3 * inverseProgress * progress * progress * controlPointTwo.x +
15535
- progress * progress * progress * endPoint.x,
15536
- y: inverseProgress * inverseProgress * inverseProgress * startPoint.y +
15537
- 3 * inverseProgress * inverseProgress * progress * controlPointOne.y +
15538
- 3 * inverseProgress * progress * progress * controlPointTwo.y +
15539
- progress * progress * progress * endPoint.y,
15540
- z: inverseProgress * inverseProgress * inverseProgress * startPoint.z +
15541
- 3 * inverseProgress * inverseProgress * progress * controlPointOne.z +
15542
- 3 * inverseProgress * progress * progress * controlPointTwo.z +
15543
- progress * progress * progress * endPoint.z,
15544
- };
15545
- }
15546
- /**
15547
- * Draws one projected tentacle stroke with a slim highlight ridge.
15548
- *
15549
- * @private helper of `octopus3dAvatarVisual`
15550
- */
15551
- function drawTentacleStroke(context, tentacleStroke, palette) {
15552
- const projectedSegments = tentacleStroke.projectedPoints.length - 1;
15553
- for (let segmentIndex = 0; segmentIndex < projectedSegments; segmentIndex++) {
15554
- const startPoint = tentacleStroke.projectedPoints[segmentIndex];
15555
- const endPoint = tentacleStroke.projectedPoints[segmentIndex + 1];
15556
- const progress = segmentIndex / projectedSegments;
15557
- const width = tentacleStroke.baseWidth + (tentacleStroke.tipWidth - tentacleStroke.baseWidth) * progress;
15558
- context.beginPath();
15559
- context.moveTo(startPoint.x, startPoint.y);
15560
- context.lineTo(endPoint.x, endPoint.y);
15561
- context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
15562
- context.lineWidth = width;
15563
- context.lineCap = 'round';
15564
- context.stroke();
15565
- context.beginPath();
15566
- context.moveTo(startPoint.x, startPoint.y);
15567
- context.lineTo(endPoint.x, endPoint.y);
15568
- context.strokeStyle = tentacleStroke.isFrontFacing ? `${palette.highlight}80` : `${palette.highlight}40`;
15569
- context.lineWidth = Math.max(1, width * 0.34);
15570
- context.lineCap = 'round';
15571
- context.stroke();
15572
- }
15573
- }
15574
- /**
15575
- * Resolves the front surface depth on an ellipsoid for one local face point.
15576
- *
15577
- * @private helper of `octopus3dAvatarVisual`
15578
- */
15579
- function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
15580
- const normalizedX = x / radiusX;
15581
- const normalizedY = y / radiusY;
15582
- const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
15583
- return Math.sqrt(remainingDepthRatio) * radiusZ;
15584
- }
15585
-
15586
15153
  /* eslint-disable no-magic-numbers */
15587
15154
  /**
15588
15155
  * Light direction used by the single-mesh octopus shading.
15589
15156
  *
15590
15157
  * @private helper of `octopus3d2AvatarVisual`
15591
15158
  */
15592
- const LIGHT_DIRECTION$2 = normalizeVector3({
15159
+ const LIGHT_DIRECTION$3 = normalizeVector3({
15593
15160
  x: 0.38,
15594
15161
  y: -0.6,
15595
15162
  z: 0.98,
@@ -15828,7 +15395,7 @@
15828
15395
  transformedCorners[2].z +
15829
15396
  transformedCorners[3].z) /
15830
15397
  4,
15831
- lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$2), -1, 1),
15398
+ lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$3), -1, 1),
15832
15399
  fillStyle: resolveBlobbySurfacePatchFillStyle$1(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
15833
15400
  outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
15834
15401
  });
@@ -15943,7 +15510,7 @@
15943
15510
  *
15944
15511
  * @private helper of `octopus3d3AvatarVisual`
15945
15512
  */
15946
- const LIGHT_DIRECTION$1 = normalizeVector3({
15513
+ const LIGHT_DIRECTION$2 = normalizeVector3({
15947
15514
  x: 0.34,
15948
15515
  y: -0.62,
15949
15516
  z: 1,
@@ -16250,7 +15817,7 @@
16250
15817
  transformedCorners[2].z +
16251
15818
  transformedCorners[3].z) /
16252
15819
  4,
16253
- lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
15820
+ lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$2), -1, 1),
16254
15821
  fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, cachedCosByPatchCenterLongitude[longitudeIndex], cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex].core, cachedLobeWavesByPatchCenterLongitude[longitudeIndex]),
16255
15822
  outlineColor: verticalProgress < 0.54 ? `${palette.highlight}69` : `${palette.shadow}78`,
16256
15823
  });
@@ -16565,7 +16132,7 @@
16565
16132
  *
16566
16133
  * @private helper of `octopus3d4AvatarVisual`
16567
16134
  */
16568
- const LIGHT_DIRECTION = normalizeVector3({
16135
+ const LIGHT_DIRECTION$1 = normalizeVector3({
16569
16136
  x: 0.32,
16570
16137
  y: -0.66,
16571
16138
  z: 1,
@@ -16636,7 +16203,7 @@
16636
16203
  isAnimated: true,
16637
16204
  supportsPointerTracking: true,
16638
16205
  render({ context, size, palette, createRandom, timeMs, interaction }) {
16639
- const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots } = getOctopus3d4StableState(createRandom);
16206
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots, } = getOctopus3d4StableState(createRandom);
16640
16207
  const sceneCenterX = size * 0.5;
16641
16208
  const sceneCenterY = size * 0.535;
16642
16209
  const bob = Math.sin(timeMs / 980 + animationPhase) * size * 0.013;
@@ -16911,7 +16478,7 @@
16911
16478
  projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
16912
16479
  projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
16913
16480
  ];
16914
- const lightIntensity = clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1);
16481
+ const lightIntensity = clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1);
16915
16482
  const rimLightIntensity = Math.pow(clampNumber$1(dotProduct3D(surfaceNormal, RIM_LIGHT_DIRECTION), 0, 1), 2.6);
16916
16483
  surfacePatches.push({
16917
16484
  corners: projectedCorners,
@@ -16984,10 +16551,7 @@
16984
16551
  Math.max(0, Math.cos(effectiveLongitude)) * 0.12 +
16985
16552
  lowerBlend * tentacleInfluence.core * (0.12 + tentacleInfluence.depthScale * 0.07) -
16986
16553
  Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
16987
- const tentacleTubeRadius = lowerBlend *
16988
- tentacleInfluence.core *
16989
- (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) *
16990
- radiusX;
16554
+ const tentacleTubeRadius = lowerBlend * tentacleInfluence.core * (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) * radiusX;
16991
16555
  const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
16992
16556
  const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.74;
16993
16557
  const lowerDrop = lowerBlend *
@@ -16999,9 +16563,7 @@
16999
16563
  (morphologyProfile.tentacles.flowLengthScale - 1) * 0.1));
17000
16564
  const combinedTentacleSway = (primaryTentacleWave + secondaryTentacleWave) * radiusX * (0.06 + tipBlend * 0.06);
17001
16565
  return {
17002
- x: Math.sin(effectiveLongitude) * planarRadiusX +
17003
- combinedTentacleSway +
17004
- tentacleCurl * radiusX * 0.18,
16566
+ x: Math.sin(effectiveLongitude) * planarRadiusX + combinedTentacleSway + tentacleCurl * radiusX * 0.18,
17005
16567
  y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
17006
16568
  upperBlend * radiusY * 0.12 +
17007
16569
  lowerDrop +
@@ -17315,6 +16877,445 @@
17315
16877
  .padStart(2, '0');
17316
16878
  }
17317
16879
 
16880
+ /* eslint-disable no-magic-numbers */
16881
+ /**
16882
+ * Light direction used by the organic 3D octopus shading.
16883
+ *
16884
+ * @private helper of `octopus3dAvatarVisual`
16885
+ */
16886
+ const LIGHT_DIRECTION = normalizeVector3({
16887
+ x: 0.48,
16888
+ y: -0.62,
16889
+ z: 0.94,
16890
+ });
16891
+ /**
16892
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
16893
+ *
16894
+ * @private helper of `octopus3dAvatarVisual`
16895
+ */
16896
+ const octopus3dStableStateCache = new WeakMap();
16897
+ /**
16898
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
16899
+ *
16900
+ * @private helper of `octopus3dAvatarVisual`
16901
+ */
16902
+ function getOctopus3dStableState(createRandom) {
16903
+ const cached = octopus3dStableStateCache.get(createRandom);
16904
+ if (cached !== undefined) {
16905
+ return cached;
16906
+ }
16907
+ const animationRandom = createRandom('octopus3d-animation-profile');
16908
+ const eyeRandom = createRandom('octopus3d-eye-profile');
16909
+ const leftEyePhaseOffset = eyeRandom() * 0.6;
16910
+ const rightEyePhaseOffset = eyeRandom() * 0.6;
16911
+ const state = {
16912
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
16913
+ animationPhase: animationRandom() * Math.PI * 2,
16914
+ leftEyePhaseOffset,
16915
+ rightEyePhaseOffset,
16916
+ };
16917
+ octopus3dStableStateCache.set(createRandom, state);
16918
+ return state;
16919
+ }
16920
+ /**
16921
+ * Proper 3D Octopus visual built from projected organic meshes and tentacles.
16922
+ *
16923
+ * @private built-in avatar visual
16924
+ */
16925
+ const octopus3dAvatarVisual = {
16926
+ id: 'octopus3d',
16927
+ title: 'Octopus 3D',
16928
+ description: 'Proper 3D octopus portrait with a turning silhouette, expressive eyes, and depth-sorted tentacles.',
16929
+ isAnimated: true,
16930
+ supportsPointerTracking: true,
16931
+ render({ context, size, palette, createRandom, timeMs, interaction }) {
16932
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
16933
+ const sceneCenterX = size * 0.5;
16934
+ const sceneCenterY = size * 0.56;
16935
+ const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
16936
+ const mantleCenter = {
16937
+ x: interaction.bodyOffsetX * size * 0.042 + size * morphologyProfile.body.centerXJitterRatio * 0.65,
16938
+ y: -size * 0.09 + interaction.bodyOffsetY * size * 0.028 + bob,
16939
+ z: interaction.intensity * size * 0.012,
16940
+ };
16941
+ const underbodyCenter = {
16942
+ x: mantleCenter.x * 0.86,
16943
+ y: mantleCenter.y + size * 0.168,
16944
+ z: mantleCenter.z - size * 0.018,
16945
+ };
16946
+ const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
16947
+ const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
16948
+ const mantleRadiusZ = size *
16949
+ morphologyProfile.body.bodyRadiusRatio *
16950
+ (0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
16951
+ const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
16952
+ const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
16953
+ const underbodyRadiusZ = mantleRadiusZ * 0.78;
16954
+ const bodyYaw = -0.18 +
16955
+ Math.sin(timeMs / 2400 + animationPhase) * 0.05 +
16956
+ interaction.bodyOffsetX * 0.18 +
16957
+ interaction.gazeX * 0.22;
16958
+ const bodyPitch = -0.08 +
16959
+ Math.cos(timeMs / 2700 + animationPhase * 0.6) * 0.025 -
16960
+ interaction.bodyOffsetY * 0.08 -
16961
+ interaction.gazeY * 0.08;
16962
+ const headYaw = bodyYaw - 0.04 + interaction.gazeX * 0.56;
16963
+ const headPitch = bodyPitch - 0.02 - interaction.gazeY * 0.32;
16964
+ const mantlePatches = resolveVisibleEllipsoidPatches({
16965
+ center: mantleCenter,
16966
+ radiusX: mantleRadiusX,
16967
+ radiusY: mantleRadiusY,
16968
+ radiusZ: mantleRadiusZ,
16969
+ rotationX: headPitch,
16970
+ rotationY: headYaw,
16971
+ sceneCenterX,
16972
+ sceneCenterY,
16973
+ size,
16974
+ palette,
16975
+ verticalColorBias: 0,
16976
+ outlineColor: `${palette.highlight}7a`,
16977
+ });
16978
+ const underbodyPatches = resolveVisibleEllipsoidPatches({
16979
+ center: underbodyCenter,
16980
+ radiusX: underbodyRadiusX,
16981
+ radiusY: underbodyRadiusY,
16982
+ radiusZ: underbodyRadiusZ,
16983
+ rotationX: bodyPitch,
16984
+ rotationY: bodyYaw,
16985
+ sceneCenterX,
16986
+ sceneCenterY,
16987
+ size,
16988
+ palette,
16989
+ verticalColorBias: 0.18,
16990
+ outlineColor: `${palette.shadow}8f`,
16991
+ });
16992
+ const tentacleStrokes = createOctopusTentacleStrokes({
16993
+ createRandom,
16994
+ morphologyProfile,
16995
+ timeMs,
16996
+ size,
16997
+ center: underbodyCenter,
16998
+ radiusX: underbodyRadiusX,
16999
+ radiusY: underbodyRadiusY,
17000
+ radiusZ: underbodyRadiusZ,
17001
+ rotationX: bodyPitch,
17002
+ rotationY: bodyYaw,
17003
+ sceneCenterX,
17004
+ sceneCenterY,
17005
+ animationPhase,
17006
+ });
17007
+ const faceEyeSpacing = size * morphologyProfile.face.eyeSpacingRatio * 0.92;
17008
+ const faceEyeYOffset = size * morphologyProfile.face.eyeCenterYOffsetRatio - mantleRadiusY * 0.02;
17009
+ const faceEyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.82;
17010
+ const faceEyeRadiusY = faceEyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.96;
17011
+ const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio * 0.92;
17012
+ const mouthY = size * morphologyProfile.face.mouthYOffsetRatio + mantleRadiusY * 0.08;
17013
+ drawAvatarFrame(context, size, palette);
17014
+ drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
17015
+ drawOctopus3dShadow(context, size, palette, interaction, timeMs);
17016
+ for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => !candidateTentacleStroke.isFrontFacing)) {
17017
+ drawTentacleStroke(context, tentacleStroke, palette);
17018
+ }
17019
+ for (const surfacePatch of [...mantlePatches, ...underbodyPatches].sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
17020
+ drawSurfacePatch(context, surfacePatch);
17021
+ }
17022
+ for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
17023
+ drawTentacleStroke(context, tentacleStroke, palette);
17024
+ }
17025
+ drawProjectedOrganicEye(context, {
17026
+ x: -faceEyeSpacing,
17027
+ y: faceEyeYOffset,
17028
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
17029
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
17030
+ drawProjectedOrganicEye(context, {
17031
+ x: faceEyeSpacing,
17032
+ y: faceEyeYOffset,
17033
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
17034
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
17035
+ drawProjectedOrganicMouth(context, [
17036
+ {
17037
+ x: -mouthHalfWidth,
17038
+ y: mouthY,
17039
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
17040
+ },
17041
+ {
17042
+ x: size * morphologyProfile.face.mouthCenterOffsetRatio,
17043
+ y: mouthY +
17044
+ size * morphologyProfile.face.mouthCurveDepthRatio * 0.38 +
17045
+ Math.sin(timeMs / 760 + animationPhase) * size * 0.01 +
17046
+ interaction.gazeY * size * 0.01,
17047
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
17048
+ },
17049
+ {
17050
+ x: mouthHalfWidth,
17051
+ y: mouthY,
17052
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
17053
+ },
17054
+ ], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
17055
+ },
17056
+ };
17057
+ /**
17058
+ * Draws the atmospheric underwater glow behind the octopus mesh.
17059
+ *
17060
+ * @private helper of `octopus3dAvatarVisual`
17061
+ */
17062
+ function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
17063
+ 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);
17064
+ glowGradient.addColorStop(0, `${palette.highlight}5c`);
17065
+ glowGradient.addColorStop(0.36, `${palette.accent}24`);
17066
+ glowGradient.addColorStop(1, `${palette.highlight}00`);
17067
+ context.fillStyle = glowGradient;
17068
+ context.fillRect(0, 0, size, size);
17069
+ 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);
17070
+ lowerGradient.addColorStop(0, `${palette.secondary}1d`);
17071
+ lowerGradient.addColorStop(1, `${palette.secondary}00`);
17072
+ context.fillStyle = lowerGradient;
17073
+ context.fillRect(0, 0, size, size);
17074
+ }
17075
+ /**
17076
+ * Draws the soft ground shadow below the octopus.
17077
+ *
17078
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
17079
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
17080
+ *
17081
+ * @private helper of `octopus3dAvatarVisual`
17082
+ */
17083
+ function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
17084
+ const cx = size * 0.5 + interaction.gazeX * size * 0.04;
17085
+ const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
17086
+ const rx = size * (0.18 + interaction.intensity * 0.02);
17087
+ const ry = size * 0.06;
17088
+ context.save();
17089
+ context.translate(cx, cy);
17090
+ context.scale(1, ry / rx);
17091
+ const blurRadius = rx * 1.4;
17092
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
17093
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
17094
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
17095
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
17096
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
17097
+ context.fillStyle = shadowGradient;
17098
+ context.beginPath();
17099
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
17100
+ context.fill();
17101
+ context.restore();
17102
+ }
17103
+ /**
17104
+ * Resolves visible projected patches for one rotated ellipsoid mesh.
17105
+ *
17106
+ * @private helper of `octopus3dAvatarVisual`
17107
+ */
17108
+ function resolveVisibleEllipsoidPatches(options) {
17109
+ const { center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, verticalColorBias, outlineColor, } = options;
17110
+ const latitudePatchCount = 10;
17111
+ const longitudePatchCount = 18;
17112
+ const surfacePatches = [];
17113
+ for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
17114
+ const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
17115
+ const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
17116
+ const verticalProgress = (latitudeIndex + 0.5) / latitudePatchCount;
17117
+ for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
17118
+ const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
17119
+ const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
17120
+ const localCorners = [
17121
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, startLongitude),
17122
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, endLongitude),
17123
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, endLongitude),
17124
+ sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, startLongitude),
17125
+ ];
17126
+ const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
17127
+ const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
17128
+ if (surfaceNormal.z <= 0.01) {
17129
+ continue;
17130
+ }
17131
+ const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
17132
+ surfacePatches.push({
17133
+ corners: projectedCorners,
17134
+ averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
17135
+ transformedCorners.length,
17136
+ lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
17137
+ fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
17138
+ outlineColor,
17139
+ });
17140
+ }
17141
+ }
17142
+ return surfacePatches;
17143
+ }
17144
+ /**
17145
+ * Samples one point on an ellipsoid aligned to the local axes.
17146
+ *
17147
+ * @private helper of `octopus3dAvatarVisual`
17148
+ */
17149
+ function sampleEllipsoidPoint(radiusX, radiusY, radiusZ, latitude, longitude) {
17150
+ const cosineLatitude = Math.cos(latitude);
17151
+ return {
17152
+ x: Math.sin(longitude) * cosineLatitude * radiusX,
17153
+ y: Math.sin(latitude) * radiusY,
17154
+ z: Math.cos(longitude) * cosineLatitude * radiusZ,
17155
+ };
17156
+ }
17157
+ /**
17158
+ * Resolves one base fill tone for a surface patch across the octopus body.
17159
+ *
17160
+ * @private helper of `octopus3dAvatarVisual`
17161
+ */
17162
+ function resolveSurfacePatchFillStyle(palette, verticalProgress) {
17163
+ const clampedVerticalProgress = clampNumber$1(verticalProgress, 0, 1);
17164
+ if (clampedVerticalProgress < 0.2) {
17165
+ return palette.highlight;
17166
+ }
17167
+ if (clampedVerticalProgress < 0.45) {
17168
+ return palette.secondary;
17169
+ }
17170
+ if (clampedVerticalProgress < 0.8) {
17171
+ return palette.primary;
17172
+ }
17173
+ return `${palette.shadow}f2`;
17174
+ }
17175
+ /**
17176
+ * Draws one projected mesh patch with organic shading.
17177
+ *
17178
+ * @private helper of `octopus3dAvatarVisual`
17179
+ */
17180
+ function drawSurfacePatch(context, surfacePatch) {
17181
+ drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
17182
+ if (surfacePatch.lightIntensity > 0) {
17183
+ drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.15 * surfacePatch.lightIntensity})`);
17184
+ }
17185
+ else if (surfacePatch.lightIntensity < 0) {
17186
+ drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
17187
+ }
17188
+ context.save();
17189
+ context.beginPath();
17190
+ context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
17191
+ for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
17192
+ context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
17193
+ }
17194
+ context.closePath();
17195
+ context.strokeStyle = surfacePatch.outlineColor;
17196
+ context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0044);
17197
+ context.lineJoin = 'round';
17198
+ context.stroke();
17199
+ context.restore();
17200
+ }
17201
+ /**
17202
+ * Creates the projected 3D tentacle strokes orbiting around the lower octopus body.
17203
+ *
17204
+ * @private helper of `octopus3dAvatarVisual`
17205
+ */
17206
+ function createOctopusTentacleStrokes(options) {
17207
+ const { createRandom, morphologyProfile, timeMs, size, center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, animationPhase, } = options;
17208
+ return Array.from({ length: morphologyProfile.tentacles.count }, (_, tentacleIndex) => {
17209
+ const tentacleRandom = createRandom(`octopus3d-tentacle-${tentacleIndex}`);
17210
+ const spreadProgress = morphologyProfile.tentacles.count === 1 ? 0.5 : tentacleIndex / (morphologyProfile.tentacles.count - 1);
17211
+ const orbitAngle = -Math.PI * 0.92 + spreadProgress * Math.PI * 1.84 + (tentacleRandom() - 0.5) * 0.16;
17212
+ const flowLength = size * (0.19 + morphologyProfile.tentacles.flowLengthScale * 0.075 + tentacleRandom() * 0.018);
17213
+ const lateralReach = size *
17214
+ (0.08 + morphologyProfile.tentacles.lateralReachScale * 0.05 + Math.abs(Math.sin(orbitAngle)) * 0.018);
17215
+ const depthReach = size * (0.028 + morphologyProfile.tentacles.tipReachScale * 0.032);
17216
+ const sway = Math.sin(timeMs / (760 + tentacleIndex * 36) + animationPhase + tentacleRandom() * Math.PI * 2);
17217
+ const anchorPoint = {
17218
+ x: Math.sin(orbitAngle) * radiusX * (0.84 + tentacleRandom() * 0.08),
17219
+ y: radiusY * (0.22 + tentacleRandom() * 0.18),
17220
+ z: Math.cos(orbitAngle) * radiusZ * (0.72 + tentacleRandom() * 0.12),
17221
+ };
17222
+ const controlPointOne = {
17223
+ x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * 0.44,
17224
+ y: anchorPoint.y + flowLength * 0.26,
17225
+ z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
17226
+ };
17227
+ const controlPointTwo = {
17228
+ x: anchorPoint.x +
17229
+ Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
17230
+ y: anchorPoint.y + flowLength * 0.66,
17231
+ z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
17232
+ };
17233
+ const endPoint = {
17234
+ x: anchorPoint.x +
17235
+ Math.sin(orbitAngle) * lateralReach * (1.02 + morphologyProfile.tentacles.tipWidthScale * 0.12) +
17236
+ sway * size * 0.028,
17237
+ y: anchorPoint.y + flowLength,
17238
+ z: anchorPoint.z + Math.cos(orbitAngle) * depthReach + sway * size * 0.016,
17239
+ };
17240
+ const scenePoints = Array.from({ length: 12 }, (_, sampleIndex) => transformScenePoint(sampleCubicBezierPoint3D(anchorPoint, controlPointOne, controlPointTwo, endPoint, sampleIndex / 11), center, rotationX, rotationY));
17241
+ const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
17242
+ const averageDepth = scenePoints.reduce((depthSum, scenePoint) => depthSum + scenePoint.z, 0) / scenePoints.length;
17243
+ return {
17244
+ projectedPoints,
17245
+ averageDepth,
17246
+ isFrontFacing: averageDepth >= center.z - size * 0.006,
17247
+ baseWidth: size *
17248
+ (0.019 +
17249
+ morphologyProfile.tentacles.baseWidthScale * 0.007 +
17250
+ tentacleRandom() * 0.003 +
17251
+ Math.abs(Math.sin(orbitAngle)) * 0.002),
17252
+ tipWidth: size * (0.0046 + morphologyProfile.tentacles.tipWidthScale * 0.0018),
17253
+ colorBias: tentacleRandom(),
17254
+ };
17255
+ });
17256
+ }
17257
+ /**
17258
+ * Samples one point on a cubic Bezier curve in 3D.
17259
+ *
17260
+ * @private helper of `octopus3dAvatarVisual`
17261
+ */
17262
+ function sampleCubicBezierPoint3D(startPoint, controlPointOne, controlPointTwo, endPoint, progress) {
17263
+ const inverseProgress = 1 - progress;
17264
+ return {
17265
+ x: inverseProgress * inverseProgress * inverseProgress * startPoint.x +
17266
+ 3 * inverseProgress * inverseProgress * progress * controlPointOne.x +
17267
+ 3 * inverseProgress * progress * progress * controlPointTwo.x +
17268
+ progress * progress * progress * endPoint.x,
17269
+ y: inverseProgress * inverseProgress * inverseProgress * startPoint.y +
17270
+ 3 * inverseProgress * inverseProgress * progress * controlPointOne.y +
17271
+ 3 * inverseProgress * progress * progress * controlPointTwo.y +
17272
+ progress * progress * progress * endPoint.y,
17273
+ z: inverseProgress * inverseProgress * inverseProgress * startPoint.z +
17274
+ 3 * inverseProgress * inverseProgress * progress * controlPointOne.z +
17275
+ 3 * inverseProgress * progress * progress * controlPointTwo.z +
17276
+ progress * progress * progress * endPoint.z,
17277
+ };
17278
+ }
17279
+ /**
17280
+ * Draws one projected tentacle stroke with a slim highlight ridge.
17281
+ *
17282
+ * @private helper of `octopus3dAvatarVisual`
17283
+ */
17284
+ function drawTentacleStroke(context, tentacleStroke, palette) {
17285
+ const projectedSegments = tentacleStroke.projectedPoints.length - 1;
17286
+ for (let segmentIndex = 0; segmentIndex < projectedSegments; segmentIndex++) {
17287
+ const startPoint = tentacleStroke.projectedPoints[segmentIndex];
17288
+ const endPoint = tentacleStroke.projectedPoints[segmentIndex + 1];
17289
+ const progress = segmentIndex / projectedSegments;
17290
+ const width = tentacleStroke.baseWidth + (tentacleStroke.tipWidth - tentacleStroke.baseWidth) * progress;
17291
+ context.beginPath();
17292
+ context.moveTo(startPoint.x, startPoint.y);
17293
+ context.lineTo(endPoint.x, endPoint.y);
17294
+ context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
17295
+ context.lineWidth = width;
17296
+ context.lineCap = 'round';
17297
+ context.stroke();
17298
+ context.beginPath();
17299
+ context.moveTo(startPoint.x, startPoint.y);
17300
+ context.lineTo(endPoint.x, endPoint.y);
17301
+ context.strokeStyle = tentacleStroke.isFrontFacing ? `${palette.highlight}80` : `${palette.highlight}40`;
17302
+ context.lineWidth = Math.max(1, width * 0.34);
17303
+ context.lineCap = 'round';
17304
+ context.stroke();
17305
+ }
17306
+ }
17307
+ /**
17308
+ * Resolves the front surface depth on an ellipsoid for one local face point.
17309
+ *
17310
+ * @private helper of `octopus3dAvatarVisual`
17311
+ */
17312
+ function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
17313
+ const normalizedX = x / radiusX;
17314
+ const normalizedY = y / radiusY;
17315
+ const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
17316
+ return Math.sqrt(remainingDepthRatio) * radiusZ;
17317
+ }
17318
+
17318
17319
  /* eslint-disable no-magic-numbers */
17319
17320
  /**
17320
17321
  * Octopus avatar visual.
@@ -18135,14 +18136,14 @@
18135
18136
  /**
18136
18137
  * META AVATAR commitment definition
18137
18138
  *
18138
- * The `META AVATAR` commitment sets the built-in default avatar visual used when
18139
- * the agent does not provide an explicit `META IMAGE`.
18139
+ * The `META AVATAR` and `META VISUAL` commitments set the built-in default avatar visual
18140
+ * used when the agent does not provide an explicit `META IMAGE`.
18140
18141
  *
18141
18142
  * @private [🪔] Maybe export the commitments through some package
18142
18143
  */
18143
18144
  class MetaAvatarCommitmentDefinition extends BaseCommitmentDefinition {
18144
- constructor() {
18145
- super('META AVATAR');
18145
+ constructor(type = 'META AVATAR') {
18146
+ super(type);
18146
18147
  }
18147
18148
  /**
18148
18149
  * Short one-line description of META AVATAR.
@@ -18162,14 +18163,15 @@
18162
18163
  get documentation() {
18163
18164
  const supportedVisuals = AVATAR_VISUALS.map((avatarVisual) => `\`${avatarVisual.id}\``).join(', ');
18164
18165
  return spacetrim.spaceTrim(`
18165
- # META AVATAR
18166
+ # ${this.type}
18166
18167
 
18167
18168
  Sets the built-in avatar visual used for the agent when no explicit \`META IMAGE\` is provided.
18169
+ \`META AVATAR\` and \`META VISUAL\` are equivalent.
18168
18170
 
18169
18171
  ## Key aspects
18170
18172
 
18171
18173
  - Does not modify the agent's behavior or responses.
18172
- - Only one \`META AVATAR\` should be used per agent.
18174
+ - Only one \`META AVATAR\` or \`META VISUAL\` should be used per agent.
18173
18175
  - If multiple are specified, the last one takes precedence.
18174
18176
  - Values are matched case-insensitively and spaces, hyphens, and underscores are normalized.
18175
18177
  - Supported visuals are derived from the shared avatar registry: ${supportedVisuals}.
@@ -18184,15 +18186,15 @@
18184
18186
  \`\`\`
18185
18187
 
18186
18188
  \`\`\`book
18187
- Orb Assistant
18189
+ Minecraft Assistant
18188
18190
 
18189
- META AVATAR orb
18191
+ META VISUAL Minecraft2
18190
18192
  GOAL Answer in a calm and focused way.
18191
18193
  \`\`\`
18192
18194
  `);
18193
18195
  }
18194
18196
  applyToAgentModelRequirements(requirements, content) {
18195
- // META AVATAR doesn't modify the system message or model requirements.
18197
+ // META AVATAR and META VISUAL don't modify the system message or model requirements.
18196
18198
  // It's handled separately in the parsing logic for profile avatar resolution.
18197
18199
  return requirements;
18198
18200
  }
@@ -20171,10 +20173,10 @@
20171
20173
  *
20172
20174
  * @private
20173
20175
  */
20174
- const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
20175
- '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
20176
- '- Do not ask the user for information that a listed teammate can provide directly.',
20177
- ];
20176
+ const TEAM_SYSTEM_MESSAGE_GUIDANCE = spacetrim.spaceTrim(`
20177
+ - If a teammate is relevant to the request, consult that teammate using the matching tool.
20178
+ - Do not ask the user for information that a listed teammate can provide directly.
20179
+ `);
20178
20180
  /**
20179
20181
  * Constant for remote agents by Url.
20180
20182
  */
@@ -20356,7 +20358,7 @@
20356
20358
  `);
20357
20359
  });
20358
20360
  return spacetrim.spaceTrim((block) => `
20359
- ${block(TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES.join('\n'))}
20361
+ ${block(TEAM_SYSTEM_MESSAGE_GUIDANCE)}
20360
20362
 
20361
20363
  ${block(teammateSections.join('\n\n'))}
20362
20364
  `);
@@ -27346,6 +27348,7 @@
27346
27348
  new ActionCommitmentDefinition('ACTIONS'),
27347
27349
  new ComponentCommitmentDefinition(),
27348
27350
  new MetaAvatarCommitmentDefinition(),
27351
+ new MetaAvatarCommitmentDefinition('META VISUAL'),
27349
27352
  new MetaImageCommitmentDefinition(),
27350
27353
  new MetaColorCommitmentDefinition(),
27351
27354
  new MetaFontCommitmentDefinition(),
@@ -28688,6 +28691,7 @@
28688
28691
  */
28689
28692
  const META_COMMITMENT_APPLIERS = {
28690
28693
  'META AVATAR': applyMetaAvatarContent,
28694
+ 'META VISUAL': applyMetaAvatarContent,
28691
28695
  'META LINK': applyMetaLinkContent,
28692
28696
  'META DOMAIN': applyMetaDomainContent,
28693
28697
  'META IMAGE': applyMetaImageContent,
@@ -28736,7 +28740,7 @@
28736
28740
  state.meta[metaType] = metaValue;
28737
28741
  }
28738
28742
  /**
28739
- * Applies META AVATAR content into the canonical `meta.avatar` field.
28743
+ * Applies META AVATAR / META VISUAL content into the canonical `meta.avatar` field.
28740
28744
  */
28741
28745
  function applyMetaAvatarContent(state, content) {
28742
28746
  const avatarVisualId = resolveAvatarVisualId(content);
@@ -29916,6 +29920,7 @@
29916
29920
  'PERSONAE',
29917
29921
  'META',
29918
29922
  'META AVATAR',
29923
+ 'META VISUAL',
29919
29924
  'META IMAGE',
29920
29925
  'META LINK',
29921
29926
  'META DOMAIN',
@@ -30175,7 +30180,7 @@
30175
30180
  4. **Add capabilities**
30176
30181
  Add only necessary \`USE*\` and/or \`MEMORY\` commitments.
30177
30182
  5. **Set profile metadata**
30178
- Add \`META DESCRIPTION\`, \`META AVATAR\` or \`META IMAGE\`, \`META INPUT PLACEHOLDER\`, and disclaimers if needed.
30183
+ Add \`META DESCRIPTION\`, \`META AVATAR\` / \`META VISUAL\` or \`META IMAGE\`, \`META INPUT PLACEHOLDER\`, and disclaimers if needed.
30179
30184
  6. **Add first interaction**
30180
30185
  Add \`INITIAL MESSAGE\` and optionally sample \`USER MESSAGE\` / \`AGENT MESSAGE\` pairs.
30181
30186
  7. **Close for deterministic behavior (optional)**
@@ -35972,51 +35977,47 @@
35972
35977
  // TODO: [🎺]
35973
35978
 
35974
35979
  /**
35975
- * Creates a message with all registered LLM tools
35980
+ * Path to the `.env` file which was used to configure LLM tools
35976
35981
  *
35977
- * Note: This function is used to create a (error) message when there is no constructor for some LLM provider
35978
- *
35979
- * @private internal function of `createLlmToolsFromConfiguration` and `$provideLlmToolsFromEnv`
35982
+ * Note: `$` is used to indicate that this variable is changed by side effect in `$provideLlmToolsConfigurationFromEnv` through `$setUsedEnvFilename`
35980
35983
  */
35981
- function $registeredLlmToolsMessage() {
35982
- const registeredLlmToolsMessageContext = createRegisteredLlmToolsMessageContext();
35983
- if (registeredLlmToolsMessageContext.llmToolStatuses.length === 0) {
35984
- return renderNoRegisteredLlmToolsMessage(registeredLlmToolsMessageContext.usedEnvMessage);
35985
- }
35986
- return renderRegisteredLlmToolsMessage(registeredLlmToolsMessageContext);
35987
- }
35984
+ let $usedEnvFilename = null;
35988
35985
  /**
35989
- * Collects all state needed to render the provider summary.
35986
+ * Shared state for the `.env` file used to configure LLM tools.
35990
35987
  *
35991
- * @private internal function of `$registeredLlmToolsMessage`
35988
+ * @private internal state of `$registeredLlmToolsMessage`
35992
35989
  */
35993
- function createRegisteredLlmToolsMessageContext() {
35994
- const isRunningInNode = $isRunningInNode();
35995
- const env = getAvailableEnvironmentVariables(isRunningInNode);
35996
- const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
35997
- return {
35998
- env,
35999
- llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
36000
- usedEnvMessage: createUsedEnvMessage(),
36001
- isRunningInNode,
36002
- };
36003
- }
35990
+ const USED_ENV_FILENAME = {
35991
+ set(filepath) {
35992
+ $usedEnvFilename = filepath;
35993
+ },
35994
+ createMessage() {
35995
+ return $usedEnvFilename === null
35996
+ ? `Unknown \`.env\` file`
35997
+ : spacetrim.spaceTrim(`
35998
+ Used \`.env\` file:
35999
+ ${$usedEnvFilename}
36000
+ `);
36001
+ },
36002
+ };
36003
+
36004
36004
  /**
36005
36005
  * Reads environment variables relevant for provider configuration.
36006
36006
  *
36007
- * @private internal function of `$registeredLlmToolsMessage`
36007
+ * @private function of `$registeredLlmToolsMessage`
36008
36008
  */
36009
- function getAvailableEnvironmentVariables(isRunningInNode) {
36009
+ function getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode) {
36010
36010
  if (isRunningInNode) {
36011
36011
  return process.env;
36012
36012
  // <- TODO: [⚛] Some DRY way how to get to `process.env` and pass it into functions - ACRY search for `env`
36013
36013
  }
36014
36014
  return {};
36015
36015
  }
36016
+
36016
36017
  /**
36017
36018
  * Takes stable snapshots of both LLM provider registers.
36018
36019
  *
36019
- * @private internal function of `$registeredLlmToolsMessage`
36020
+ * @private function of `$registeredLlmToolsMessage`
36020
36021
  */
36021
36022
  function getRegisteredLlmToolRegisters() {
36022
36023
  return {
@@ -36024,62 +36025,30 @@
36024
36025
  registeredTools: $llmToolsRegister.list(),
36025
36026
  };
36026
36027
  }
36027
- /**
36028
- * Lists provider entries enriched with installation and configuration state.
36029
- *
36030
- * @private internal function of `$registeredLlmToolsMessage`
36031
- */
36032
- function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
36033
- return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
36034
- }
36035
- /**
36036
- * Merges provider entries from the metadata and constructor registers.
36037
- *
36038
- * @private internal function of `$registeredLlmToolsMessage`
36039
- */
36040
- function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
36041
- const registeredLlmToolEntries = new Map();
36042
- for (const { title, packageName, className, envVariables } of registeredMetadata) {
36043
- addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
36044
- }
36045
- for (const { packageName, className } of registeredTools) {
36046
- addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
36047
- }
36048
- return [...registeredLlmToolEntries.values()];
36049
- }
36050
- /**
36051
- * Adds a provider entry only when the provider is not already present.
36052
- *
36053
- * @private internal function of `$registeredLlmToolsMessage`
36054
- */
36055
- function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
36056
- const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
36057
- if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
36058
- return;
36059
- }
36060
- registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
36061
- }
36028
+
36062
36029
  /**
36063
36030
  * Creates a deduplication key for a provider entry.
36064
36031
  *
36065
- * @private internal function of `$registeredLlmToolsMessage`
36032
+ * @private function of `$registeredLlmToolsMessage`
36066
36033
  */
36067
36034
  function createRegisteredLlmToolEntryKey({ packageName, className }) {
36068
36035
  return `${packageName}::${className}`;
36069
36036
  }
36037
+
36070
36038
  /**
36071
36039
  * Checks whether the given provider entry already exists in the target register list.
36072
36040
  *
36073
- * @private internal function of `$registeredLlmToolsMessage`
36041
+ * @private function of `$registeredLlmToolsMessage`
36074
36042
  */
36075
36043
  function hasRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
36076
36044
  const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
36077
36045
  return registeredLlmToolEntries.some((listedRegisteredLlmToolEntry) => createRegisteredLlmToolEntryKey(listedRegisteredLlmToolEntry) === registeredLlmToolEntryKey);
36078
36046
  }
36047
+
36079
36048
  /**
36080
36049
  * Builds the runtime status for one provider entry.
36081
36050
  *
36082
- * @private internal function of `$registeredLlmToolsMessage`
36051
+ * @private function of `$registeredLlmToolsMessage`
36083
36052
  */
36084
36053
  function createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env, }) {
36085
36054
  const availabilityStatus = createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools);
@@ -36093,7 +36062,7 @@
36093
36062
  /**
36094
36063
  * Resolves whether the provider has metadata and a registered constructor.
36095
36064
  *
36096
- * @private internal function of `$registeredLlmToolsMessage`
36065
+ * @private function of `$registeredLlmToolsMessage`
36097
36066
  */
36098
36067
  function createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools) {
36099
36068
  return {
@@ -36104,7 +36073,7 @@
36104
36073
  /**
36105
36074
  * Resolves whether the provider has enough environment variables to be configured.
36106
36075
  *
36107
- * @private internal function of `$registeredLlmToolsMessage`
36076
+ * @private function of `$registeredLlmToolsMessage`
36108
36077
  */
36109
36078
  function createRegisteredLlmToolConfigurationStatus({ envVariables }, env) {
36110
36079
  return {
@@ -36115,7 +36084,7 @@
36115
36084
  /**
36116
36085
  * Checks whether all required environment variables are present for a provider.
36117
36086
  *
36118
- * @private internal function of `$registeredLlmToolsMessage`
36087
+ * @private function of `$registeredLlmToolsMessage`
36119
36088
  */
36120
36089
  function isRegisteredLlmToolFullyConfigured(envVariables, env) {
36121
36090
  if (envVariables === undefined || envVariables === null) {
@@ -36126,7 +36095,7 @@
36126
36095
  /**
36127
36096
  * Checks whether at least one required environment variable is present for a provider.
36128
36097
  *
36129
- * @private internal function of `$registeredLlmToolsMessage`
36098
+ * @private function of `$registeredLlmToolsMessage`
36130
36099
  */
36131
36100
  function isRegisteredLlmToolPartiallyConfigured(envVariables, env) {
36132
36101
  if (envVariables === undefined || envVariables === null) {
@@ -36134,109 +36103,128 @@
36134
36103
  }
36135
36104
  return envVariables.some((envVariableName) => env[envVariableName] !== undefined);
36136
36105
  }
36106
+
36137
36107
  /**
36138
- * Renders the fallback message for environments with no registered providers.
36108
+ * Merges provider entries from the metadata and constructor registers.
36139
36109
  *
36140
- * @private internal function of `$registeredLlmToolsMessage`
36110
+ * @private function of `$registeredLlmToolsMessage`
36141
36111
  */
36142
- function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
36143
- return spacetrim.spaceTrim((block) => `
36144
- No LLM providers are available.
36145
-
36146
- ${block(usedEnvMessage)}
36147
- `);
36112
+ function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
36113
+ const registeredLlmToolEntries = new Map();
36114
+ for (const { title, packageName, className, envVariables } of registeredMetadata) {
36115
+ addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
36116
+ }
36117
+ for (const { packageName, className } of registeredTools) {
36118
+ addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
36119
+ }
36120
+ return [...registeredLlmToolEntries.values()];
36148
36121
  }
36149
36122
  /**
36150
- * Renders the full provider status summary.
36123
+ * Adds a provider entry only when the provider is not already present.
36151
36124
  *
36152
- * @private internal function of `$registeredLlmToolsMessage`
36125
+ * @private function of `$registeredLlmToolsMessage`
36153
36126
  */
36154
- function renderRegisteredLlmToolsMessage({ env, llmToolStatuses, usedEnvMessage, isRunningInNode, }) {
36155
- return spacetrim.spaceTrim((block) => `
36156
-
36157
- ${block(usedEnvMessage)}
36158
-
36159
- Relevant environment variables:
36160
- ${block(renderRelevantEnvironmentVariables(env, llmToolStatuses))}
36161
-
36162
- Available LLM providers are:
36163
- ${block(renderAvailableProviders(llmToolStatuses, env, isRunningInNode))}
36164
- `);
36127
+ function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
36128
+ const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
36129
+ if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
36130
+ return;
36131
+ }
36132
+ registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
36165
36133
  }
36134
+
36166
36135
  /**
36167
- * Renders the list of environment variables used by at least one registered provider.
36136
+ * Lists provider entries enriched with installation and configuration state.
36168
36137
  *
36169
- * @private internal function of `$registeredLlmToolsMessage`
36138
+ * @private function of `$registeredLlmToolsMessage`
36170
36139
  */
36171
- function renderRelevantEnvironmentVariables(env, llmToolStatuses) {
36172
- return listRelevantEnvironmentVariables(env, llmToolStatuses)
36173
- .map((envVariableName) => `- \`${envVariableName}\``)
36174
- .join('\n');
36140
+ function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
36141
+ return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
36175
36142
  }
36143
+
36176
36144
  /**
36177
- * Lists environment variables that are both present and used by at least one provider.
36145
+ * Collects all state needed to render the provider summary.
36178
36146
  *
36179
- * @private internal function of `$registeredLlmToolsMessage`
36147
+ * @private function of `$registeredLlmToolsMessage`
36180
36148
  */
36181
- function listRelevantEnvironmentVariables(env, llmToolStatuses) {
36182
- return Object.keys(env).filter((envVariableName) => llmToolStatuses.some(({ envVariables }) => envVariables === null || envVariables === void 0 ? void 0 : envVariables.includes(envVariableName)));
36149
+ function createRegisteredLlmToolsMessageContext() {
36150
+ const isRunningInNode = $isRunningInNode();
36151
+ const env = getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode);
36152
+ const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
36153
+ return {
36154
+ env,
36155
+ llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
36156
+ usedEnvMessage: USED_ENV_FILENAME.createMessage(),
36157
+ isRunningInNode,
36158
+ };
36183
36159
  }
36160
+
36184
36161
  /**
36185
- * Renders all provider lines in the status summary.
36162
+ * Renders the fallback message for environments with no registered providers.
36186
36163
  *
36187
- * @private internal function of `$registeredLlmToolsMessage`
36164
+ * @private function of `$registeredLlmToolsMessage`
36188
36165
  */
36189
- function renderAvailableProviders(llmToolStatuses, env, isRunningInNode) {
36190
- return llmToolStatuses
36191
- .map((llmToolStatus, index) => renderAvailableProvider(llmToolStatus, index, env, isRunningInNode))
36192
- .join('\n');
36166
+ function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
36167
+ return spacetrim.spaceTrim((block) => `
36168
+ No LLM providers are available.
36169
+
36170
+ ${block(usedEnvMessage)}
36171
+ `);
36193
36172
  }
36173
+
36194
36174
  /**
36195
- * Renders one provider line in the status summary.
36175
+ * Creates the configuration-status sentence for one provider.
36196
36176
  *
36197
- * @private internal function of `$registeredLlmToolsMessage`
36177
+ * @private function of `$registeredLlmToolsMessage`
36198
36178
  */
36199
- function renderAvailableProvider(llmToolStatus, index, env, isRunningInNode) {
36200
- const providerMessage = createAvailableProviderMessage(llmToolStatus, index, env);
36201
- if (!isRunningInNode) {
36202
- return providerMessage;
36179
+ function createRegisteredLlmToolConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
36180
+ if (isFullyConfigured) {
36181
+ return `Configured`;
36203
36182
  }
36204
- return colorizeAvailableProviderMessage(providerMessage, llmToolStatus);
36183
+ if (isPartiallyConfigured) {
36184
+ return createPartiallyConfiguredStatusMessage(envVariables, env);
36185
+ }
36186
+ if (envVariables !== null) {
36187
+ return createNotConfiguredStatusMessage(envVariables);
36188
+ }
36189
+ return `Not configured`;
36190
+ // <- Note: Can not be configured via environment variables
36205
36191
  }
36206
36192
  /**
36207
- * Creates the plain-text provider line before optional colorization.
36193
+ * Creates the partial-configuration sentence including missing variables.
36208
36194
  *
36209
- * @private internal function of `$registeredLlmToolsMessage`
36195
+ * @private function of `$registeredLlmToolsMessage`
36210
36196
  */
36211
- function createAvailableProviderMessage(llmToolStatus, index, env) {
36212
- const { title, packageName, className } = llmToolStatus;
36213
- const providerStatusMessages = createProviderStatusMessages(llmToolStatus, env);
36214
- return spacetrim.spaceTrim(`
36215
- ${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
36216
- ${providerStatusMessages.join('; ')}
36217
- `);
36197
+ function createPartiallyConfiguredStatusMessage(envVariables, env) {
36198
+ return `Partially confugured, missing ${listMissingEnvironmentVariables(envVariables, env).join(' + ')}`;
36218
36199
  }
36219
36200
  /**
36220
- * Creates the install and configuration fragments for one provider line.
36201
+ * Creates the not-configured sentence including the expected environment variables.
36221
36202
  *
36222
- * @private internal function of `$registeredLlmToolsMessage`
36203
+ * @private function of `$registeredLlmToolsMessage`
36223
36204
  */
36224
- function createProviderStatusMessages(llmToolStatus, env) {
36225
- return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
36205
+ function createNotConfiguredStatusMessage(envVariables) {
36206
+ return `Not configured, to configure set env ${envVariables === null || envVariables === void 0 ? void 0 : envVariables.join(' + ')}`;
36226
36207
  }
36208
+ /**
36209
+ * Lists environment variables that are required but currently missing.
36210
+ *
36211
+ * @private function of `$registeredLlmToolsMessage`
36212
+ */
36213
+ function listMissingEnvironmentVariables(envVariables, env) {
36214
+ return (envVariables === null || envVariables === void 0 ? void 0 : envVariables.filter((envVariable) => env[envVariable] === undefined)) || [];
36215
+ }
36216
+
36227
36217
  /**
36228
36218
  * Creates the installation-status sentence for one provider.
36229
36219
  *
36230
- * @private internal function of `$registeredLlmToolsMessage`
36220
+ * @private function of `$registeredLlmToolsMessage`
36231
36221
  */
36232
- function createInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
36233
- const installationStatusKey = createInstallationStatusKey(isMetadataAvailable, isInstalled);
36222
+ function createRegisteredLlmToolInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
36223
+ const installationStatusKey = createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled);
36234
36224
  switch (installationStatusKey) {
36235
36225
  case 'missing-metadata-and-installation':
36236
- // TODO: [�][�] Maybe do allow to do auto-install if package not registered and not found
36237
36226
  return `Not installed and no metadata, looks like a unexpected behavior`;
36238
36227
  case 'metadata-without-installation':
36239
- // TODO: [�][�]
36240
36228
  return `Not installed`;
36241
36229
  case 'installation-without-metadata':
36242
36230
  return `No metadata but installed, looks like a unexpected behavior`;
@@ -36249,9 +36237,9 @@
36249
36237
  /**
36250
36238
  * Creates a stable installation-state key from metadata and constructor availability.
36251
36239
  *
36252
- * @private internal function of `$registeredLlmToolsMessage`
36240
+ * @private function of `$registeredLlmToolsMessage`
36253
36241
  */
36254
- function createInstallationStatusKey(isMetadataAvailable, isInstalled) {
36242
+ function createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled) {
36255
36243
  if (!isMetadataAvailable && !isInstalled) {
36256
36244
  return 'missing-metadata-and-installation';
36257
36245
  }
@@ -36266,54 +36254,59 @@
36266
36254
  }
36267
36255
  return 'unknown';
36268
36256
  }
36257
+
36269
36258
  /**
36270
- * Creates the configuration-status sentence for one provider.
36259
+ * Renders all provider lines in the status summary.
36271
36260
  *
36272
- * @private internal function of `$registeredLlmToolsMessage`
36261
+ * @private function of `$registeredLlmToolsMessage`
36273
36262
  */
36274
- function createConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
36275
- if (isFullyConfigured) {
36276
- return `Configured`;
36277
- }
36278
- if (isPartiallyConfigured) {
36279
- return createPartiallyConfiguredStatusMessage(envVariables, env);
36280
- }
36281
- if (envVariables !== null) {
36282
- return createNotConfiguredStatusMessage(envVariables);
36283
- }
36284
- return `Not configured`;
36285
- // <- Note: Can not be configured via environment variables
36263
+ function renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode) {
36264
+ return llmToolStatuses
36265
+ .map((llmToolStatus, index) => renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode))
36266
+ .join('\n');
36286
36267
  }
36287
36268
  /**
36288
- * Creates the partial-configuration sentence including missing variables.
36269
+ * Renders one provider line in the status summary.
36289
36270
  *
36290
- * @private internal function of `$registeredLlmToolsMessage`
36271
+ * @private function of `$registeredLlmToolsMessage`
36291
36272
  */
36292
- function createPartiallyConfiguredStatusMessage(envVariables, env) {
36293
- return `Partially confugured, missing ${listMissingEnvironmentVariables(envVariables, env).join(' + ')}`;
36273
+ function renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode) {
36274
+ const providerMessage = createAvailableRegisteredLlmToolMessage(llmToolStatus, index, env);
36275
+ if (!isRunningInNode) {
36276
+ return providerMessage;
36277
+ }
36278
+ return colorizeAvailableRegisteredLlmToolMessage(providerMessage, llmToolStatus);
36294
36279
  }
36295
36280
  /**
36296
- * Creates the not-configured sentence including the expected environment variables.
36281
+ * Creates the plain-text provider line before optional colorization.
36297
36282
  *
36298
- * @private internal function of `$registeredLlmToolsMessage`
36283
+ * @private function of `$registeredLlmToolsMessage`
36299
36284
  */
36300
- function createNotConfiguredStatusMessage(envVariables) {
36301
- return `Not configured, to configure set env ${envVariables === null || envVariables === void 0 ? void 0 : envVariables.join(' + ')}`;
36285
+ function createAvailableRegisteredLlmToolMessage(llmToolStatus, index, env) {
36286
+ const { title, packageName, className } = llmToolStatus;
36287
+ const providerStatusMessages = createRegisteredLlmToolStatusMessages(llmToolStatus, env);
36288
+ return spacetrim.spaceTrim(`
36289
+ ${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
36290
+ ${providerStatusMessages.join('; ')}
36291
+ `);
36302
36292
  }
36303
36293
  /**
36304
- * Lists environment variables that are required but currently missing.
36294
+ * Creates the install and configuration fragments for one provider line.
36305
36295
  *
36306
- * @private internal function of `$registeredLlmToolsMessage`
36296
+ * @private function of `$registeredLlmToolsMessage`
36307
36297
  */
36308
- function listMissingEnvironmentVariables(envVariables, env) {
36309
- return (envVariables === null || envVariables === void 0 ? void 0 : envVariables.filter((envVariable) => env[envVariable] === undefined)) || [];
36298
+ function createRegisteredLlmToolStatusMessages(llmToolStatus, env) {
36299
+ return [
36300
+ createRegisteredLlmToolInstallationStatusMessage(llmToolStatus),
36301
+ createRegisteredLlmToolConfigurationStatusMessage(llmToolStatus, env),
36302
+ ];
36310
36303
  }
36311
36304
  /**
36312
36305
  * Applies the same terminal coloring rules as the original summary renderer.
36313
36306
  *
36314
- * @private internal function of `$registeredLlmToolsMessage`
36307
+ * @private function of `$registeredLlmToolsMessage`
36315
36308
  */
36316
- function colorizeAvailableProviderMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
36309
+ function colorizeAvailableRegisteredLlmToolMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
36317
36310
  if (isInstalled && isFullyConfigured) {
36318
36311
  return colors__default["default"].green(providerMessage);
36319
36312
  }
@@ -36322,14 +36315,57 @@
36322
36315
  }
36323
36316
  return colors__default["default"].gray(providerMessage);
36324
36317
  }
36318
+
36319
+ /**
36320
+ * Renders the list of environment variables used by at least one registered provider.
36321
+ *
36322
+ * @private function of `$registeredLlmToolsMessage`
36323
+ */
36324
+ function renderRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses) {
36325
+ return listRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses)
36326
+ .map((envVariableName) => `- \`${envVariableName}\``)
36327
+ .join('\n');
36328
+ }
36329
+ /**
36330
+ * Lists environment variables that are both present and used by at least one provider.
36331
+ *
36332
+ * @private function of `$registeredLlmToolsMessage`
36333
+ */
36334
+ function listRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses) {
36335
+ return Object.keys(env).filter((envVariableName) => llmToolStatuses.some(({ envVariables }) => envVariables === null || envVariables === void 0 ? void 0 : envVariables.includes(envVariableName)));
36336
+ }
36337
+
36338
+ /**
36339
+ * Renders the full provider status summary.
36340
+ *
36341
+ * @private function of `$registeredLlmToolsMessage`
36342
+ */
36343
+ function renderRegisteredLlmToolsMessage({ env, llmToolStatuses, usedEnvMessage, isRunningInNode, }) {
36344
+ return spacetrim.spaceTrim((block) => `
36345
+
36346
+ ${block(usedEnvMessage)}
36347
+
36348
+ Relevant environment variables:
36349
+ ${block(renderRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses))}
36350
+
36351
+ Available LLM providers are:
36352
+ ${block(renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode))}
36353
+ `);
36354
+ }
36355
+
36325
36356
  /**
36326
- * Creates the `.env` origin sentence used in the summary header.
36357
+ * Creates a message with all registered LLM tools
36358
+ *
36359
+ * Note: This function is used to create a (error) message when there is no constructor for some LLM provider
36327
36360
  *
36328
- * @private internal function of `$registeredLlmToolsMessage`
36361
+ * @private internal function of `createLlmToolsFromConfiguration` and `$provideLlmToolsFromEnv`
36329
36362
  */
36330
- function createUsedEnvMessage() {
36331
- return `Unknown \`.env\` file`
36332
- ;
36363
+ function $registeredLlmToolsMessage() {
36364
+ const registeredLlmToolsMessageContext = createRegisteredLlmToolsMessageContext();
36365
+ if (registeredLlmToolsMessageContext.llmToolStatuses.length === 0) {
36366
+ return renderNoRegisteredLlmToolsMessage(registeredLlmToolsMessageContext.usedEnvMessage);
36367
+ }
36368
+ return renderRegisteredLlmToolsMessage(registeredLlmToolsMessageContext);
36333
36369
  }
36334
36370
  // TODO: [®] DRY Register logic
36335
36371
  // TODO: [🧠][⚛] Maybe pass env as argument