@promptbook/wizard 0.113.0-0 → 0.113.0-10

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