@promptbook/wizard 0.113.0-7 → 0.113.0-9

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 (221) hide show
  1. package/esm/index.es.js +1113 -1083
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/src/_packages/types.index.d.ts +2 -2
  4. package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +24 -1
  5. package/esm/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
  6. package/esm/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
  7. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
  8. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
  9. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
  10. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
  11. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
  12. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
  13. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
  14. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
  15. package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
  16. package/esm/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
  17. package/esm/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
  18. package/esm/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
  19. package/esm/src/book-components/Chat/Chat/ChatMessageItem.d.ts +1 -1
  20. package/esm/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
  21. package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +8 -0
  22. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
  23. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
  24. package/esm/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
  25. package/esm/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
  26. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
  27. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
  28. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
  29. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
  30. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
  31. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
  32. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
  33. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
  34. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
  35. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
  36. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
  37. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
  38. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
  39. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
  40. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
  41. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
  42. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
  43. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
  44. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
  45. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
  46. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
  47. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
  48. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
  49. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
  50. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
  51. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
  52. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
  53. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
  54. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
  55. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
  56. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
  57. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
  58. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
  59. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
  60. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
  61. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +16 -0
  62. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
  63. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
  64. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
  65. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
  66. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
  67. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
  68. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
  69. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
  70. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
  71. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
  72. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
  73. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
  74. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
  75. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
  76. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
  77. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
  78. package/esm/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
  79. package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
  80. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
  81. package/esm/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
  82. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
  83. package/esm/src/commitments/META/META.d.ts +2 -2
  84. package/esm/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
  85. package/esm/src/commitments/index.d.ts +1 -1
  86. package/esm/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
  87. package/esm/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
  88. package/esm/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
  89. package/esm/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
  90. package/esm/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
  91. package/esm/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
  92. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
  93. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
  94. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
  95. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
  96. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
  97. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
  98. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
  99. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  100. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
  101. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
  102. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
  103. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
  104. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
  105. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
  106. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
  107. package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  108. package/esm/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
  109. package/esm/src/utils/color/Color.d.ts +1 -1
  110. package/esm/src/version.d.ts +1 -1
  111. package/package.json +2 -2
  112. package/umd/index.umd.js +1113 -1083
  113. package/umd/index.umd.js.map +1 -1
  114. package/umd/src/_packages/types.index.d.ts +2 -2
  115. package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +24 -1
  116. package/umd/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
  117. package/umd/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
  118. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
  119. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
  120. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
  121. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
  122. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
  123. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
  124. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
  125. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
  126. package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
  127. package/umd/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
  128. package/umd/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
  129. package/umd/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
  130. package/umd/src/book-components/Chat/Chat/ChatMessageItem.d.ts +1 -1
  131. package/umd/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
  132. package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +8 -0
  133. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
  134. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
  135. package/umd/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
  136. package/umd/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
  137. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
  138. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
  139. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
  140. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
  141. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
  142. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
  143. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
  144. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
  145. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
  146. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
  147. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
  148. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
  149. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
  150. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
  151. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
  152. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
  153. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
  154. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
  155. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
  156. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
  157. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
  158. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
  159. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
  160. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
  161. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
  162. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
  163. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
  164. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
  165. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
  166. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
  167. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
  168. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
  169. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
  170. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
  171. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
  172. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +16 -0
  173. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
  174. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
  175. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
  176. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
  177. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
  178. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
  179. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
  180. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
  181. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
  182. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
  183. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
  184. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
  185. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
  186. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
  187. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
  188. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
  189. package/umd/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
  190. package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
  191. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
  192. package/umd/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
  193. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
  194. package/umd/src/commitments/META/META.d.ts +2 -2
  195. package/umd/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
  196. package/umd/src/commitments/index.d.ts +1 -1
  197. package/umd/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
  198. package/umd/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
  199. package/umd/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
  200. package/umd/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
  201. package/umd/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
  202. package/umd/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
  203. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
  204. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
  205. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
  206. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
  207. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
  208. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
  209. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
  210. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  211. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
  212. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
  213. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
  214. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
  215. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
  216. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
  217. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
  218. package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
  219. package/umd/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
  220. package/umd/src/utils/color/Color.d.ts +1 -1
  221. 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-7';
55
+ const PROMPTBOOK_ENGINE_VERSION = '0.113.0-9';
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,
@@ -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,
@@ -26182,6 +25749,445 @@
26182
25749
  .padStart(2, '0');
26183
25750
  }
26184
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
+
26185
26191
  /* eslint-disable no-magic-numbers */
26186
26192
  /**
26187
26193
  * Octopus avatar visual.
@@ -27002,14 +27008,14 @@
27002
27008
  /**
27003
27009
  * META AVATAR commitment definition
27004
27010
  *
27005
- * The `META AVATAR` commitment sets the built-in default avatar visual used when
27006
- * 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`.
27007
27013
  *
27008
27014
  * @private [🪔] Maybe export the commitments through some package
27009
27015
  */
27010
27016
  class MetaAvatarCommitmentDefinition extends BaseCommitmentDefinition {
27011
- constructor() {
27012
- super('META AVATAR');
27017
+ constructor(type = 'META AVATAR') {
27018
+ super(type);
27013
27019
  }
27014
27020
  /**
27015
27021
  * Short one-line description of META AVATAR.
@@ -27029,14 +27035,15 @@
27029
27035
  get documentation() {
27030
27036
  const supportedVisuals = AVATAR_VISUALS.map((avatarVisual) => `\`${avatarVisual.id}\``).join(', ');
27031
27037
  return _spaceTrim.spaceTrim(`
27032
- # META AVATAR
27038
+ # ${this.type}
27033
27039
 
27034
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.
27035
27042
 
27036
27043
  ## Key aspects
27037
27044
 
27038
27045
  - Does not modify the agent's behavior or responses.
27039
- - Only one \`META AVATAR\` should be used per agent.
27046
+ - Only one \`META AVATAR\` or \`META VISUAL\` should be used per agent.
27040
27047
  - If multiple are specified, the last one takes precedence.
27041
27048
  - Values are matched case-insensitively and spaces, hyphens, and underscores are normalized.
27042
27049
  - Supported visuals are derived from the shared avatar registry: ${supportedVisuals}.
@@ -27051,15 +27058,15 @@
27051
27058
  \`\`\`
27052
27059
 
27053
27060
  \`\`\`book
27054
- Orb Assistant
27061
+ Minecraft Assistant
27055
27062
 
27056
- META AVATAR orb
27063
+ META VISUAL Minecraft2
27057
27064
  GOAL Answer in a calm and focused way.
27058
27065
  \`\`\`
27059
27066
  `);
27060
27067
  }
27061
27068
  applyToAgentModelRequirements(requirements, content) {
27062
- // 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.
27063
27070
  // It's handled separately in the parsing logic for profile avatar resolution.
27064
27071
  return requirements;
27065
27072
  }
@@ -36200,6 +36207,7 @@
36200
36207
  new ActionCommitmentDefinition('ACTIONS'),
36201
36208
  new ComponentCommitmentDefinition(),
36202
36209
  new MetaAvatarCommitmentDefinition(),
36210
+ new MetaAvatarCommitmentDefinition('META VISUAL'),
36203
36211
  new MetaImageCommitmentDefinition(),
36204
36212
  new MetaColorCommitmentDefinition(),
36205
36213
  new MetaFontCommitmentDefinition(),
@@ -37551,6 +37559,7 @@
37551
37559
  */
37552
37560
  const META_COMMITMENT_APPLIERS = {
37553
37561
  'META AVATAR': applyMetaAvatarContent,
37562
+ 'META VISUAL': applyMetaAvatarContent,
37554
37563
  'META LINK': applyMetaLinkContent,
37555
37564
  'META DOMAIN': applyMetaDomainContent,
37556
37565
  'META IMAGE': applyMetaImageContent,
@@ -37599,7 +37608,7 @@
37599
37608
  state.meta[metaType] = metaValue;
37600
37609
  }
37601
37610
  /**
37602
- * Applies META AVATAR content into the canonical `meta.avatar` field.
37611
+ * Applies META AVATAR / META VISUAL content into the canonical `meta.avatar` field.
37603
37612
  */
37604
37613
  function applyMetaAvatarContent(state, content) {
37605
37614
  const avatarVisualId = resolveAvatarVisualId(content);
@@ -41140,61 +41149,41 @@
41140
41149
  */
41141
41150
  let $usedEnvFilename = null;
41142
41151
  /**
41143
- * Pass the `.env` file which was used to configure LLM tools
41144
- *
41145
- * Note: `$` is used to indicate that this variable is making side effect
41152
+ * Shared state for the `.env` file used to configure LLM tools.
41146
41153
  *
41147
- * @private internal log of `$provideLlmToolsConfigurationFromEnv` and `$registeredLlmToolsMessage`
41154
+ * @private internal state of `$registeredLlmToolsMessage`
41148
41155
  */
41149
- function $setUsedEnvFilename(filepath) {
41150
- $usedEnvFilename = filepath;
41151
- }
41152
- /**
41153
- * Creates a message with all registered LLM tools
41154
- *
41155
- * Note: This function is used to create a (error) message when there is no constructor for some LLM provider
41156
- *
41157
- * @private internal function of `createLlmToolsFromConfiguration` and `$provideLlmToolsFromEnv`
41158
- */
41159
- function $registeredLlmToolsMessage() {
41160
- const registeredLlmToolsMessageContext = createRegisteredLlmToolsMessageContext();
41161
- if (registeredLlmToolsMessageContext.llmToolStatuses.length === 0) {
41162
- return renderNoRegisteredLlmToolsMessage(registeredLlmToolsMessageContext.usedEnvMessage);
41163
- }
41164
- return renderRegisteredLlmToolsMessage(registeredLlmToolsMessageContext);
41165
- }
41166
- /**
41167
- * Collects all state needed to render the provider summary.
41168
- *
41169
- * @private internal function of `$registeredLlmToolsMessage`
41170
- */
41171
- function createRegisteredLlmToolsMessageContext() {
41172
- const isRunningInNode = $isRunningInNode();
41173
- const env = getAvailableEnvironmentVariables(isRunningInNode);
41174
- const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
41175
- return {
41176
- env,
41177
- llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
41178
- usedEnvMessage: createUsedEnvMessage(),
41179
- isRunningInNode,
41180
- };
41181
- }
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
+
41182
41170
  /**
41183
41171
  * Reads environment variables relevant for provider configuration.
41184
41172
  *
41185
- * @private internal function of `$registeredLlmToolsMessage`
41173
+ * @private function of `$registeredLlmToolsMessage`
41186
41174
  */
41187
- function getAvailableEnvironmentVariables(isRunningInNode) {
41175
+ function getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode) {
41188
41176
  if (isRunningInNode) {
41189
41177
  return process.env;
41190
41178
  // <- TODO: [⚛] Some DRY way how to get to `process.env` and pass it into functions - ACRY search for `env`
41191
41179
  }
41192
41180
  return {};
41193
41181
  }
41182
+
41194
41183
  /**
41195
41184
  * Takes stable snapshots of both LLM provider registers.
41196
41185
  *
41197
- * @private internal function of `$registeredLlmToolsMessage`
41186
+ * @private function of `$registeredLlmToolsMessage`
41198
41187
  */
41199
41188
  function getRegisteredLlmToolRegisters() {
41200
41189
  return {
@@ -41202,62 +41191,30 @@
41202
41191
  registeredTools: $llmToolsRegister.list(),
41203
41192
  };
41204
41193
  }
41205
- /**
41206
- * Lists provider entries enriched with installation and configuration state.
41207
- *
41208
- * @private internal function of `$registeredLlmToolsMessage`
41209
- */
41210
- function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
41211
- return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
41212
- }
41213
- /**
41214
- * Merges provider entries from the metadata and constructor registers.
41215
- *
41216
- * @private internal function of `$registeredLlmToolsMessage`
41217
- */
41218
- function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
41219
- const registeredLlmToolEntries = new Map();
41220
- for (const { title, packageName, className, envVariables } of registeredMetadata) {
41221
- addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
41222
- }
41223
- for (const { packageName, className } of registeredTools) {
41224
- addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
41225
- }
41226
- return [...registeredLlmToolEntries.values()];
41227
- }
41228
- /**
41229
- * Adds a provider entry only when the provider is not already present.
41230
- *
41231
- * @private internal function of `$registeredLlmToolsMessage`
41232
- */
41233
- function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
41234
- const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
41235
- if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
41236
- return;
41237
- }
41238
- registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
41239
- }
41194
+
41240
41195
  /**
41241
41196
  * Creates a deduplication key for a provider entry.
41242
41197
  *
41243
- * @private internal function of `$registeredLlmToolsMessage`
41198
+ * @private function of `$registeredLlmToolsMessage`
41244
41199
  */
41245
41200
  function createRegisteredLlmToolEntryKey({ packageName, className }) {
41246
41201
  return `${packageName}::${className}`;
41247
41202
  }
41203
+
41248
41204
  /**
41249
41205
  * Checks whether the given provider entry already exists in the target register list.
41250
41206
  *
41251
- * @private internal function of `$registeredLlmToolsMessage`
41207
+ * @private function of `$registeredLlmToolsMessage`
41252
41208
  */
41253
41209
  function hasRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
41254
41210
  const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
41255
41211
  return registeredLlmToolEntries.some((listedRegisteredLlmToolEntry) => createRegisteredLlmToolEntryKey(listedRegisteredLlmToolEntry) === registeredLlmToolEntryKey);
41256
41212
  }
41213
+
41257
41214
  /**
41258
41215
  * Builds the runtime status for one provider entry.
41259
41216
  *
41260
- * @private internal function of `$registeredLlmToolsMessage`
41217
+ * @private function of `$registeredLlmToolsMessage`
41261
41218
  */
41262
41219
  function createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env, }) {
41263
41220
  const availabilityStatus = createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools);
@@ -41271,7 +41228,7 @@
41271
41228
  /**
41272
41229
  * Resolves whether the provider has metadata and a registered constructor.
41273
41230
  *
41274
- * @private internal function of `$registeredLlmToolsMessage`
41231
+ * @private function of `$registeredLlmToolsMessage`
41275
41232
  */
41276
41233
  function createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools) {
41277
41234
  return {
@@ -41282,7 +41239,7 @@
41282
41239
  /**
41283
41240
  * Resolves whether the provider has enough environment variables to be configured.
41284
41241
  *
41285
- * @private internal function of `$registeredLlmToolsMessage`
41242
+ * @private function of `$registeredLlmToolsMessage`
41286
41243
  */
41287
41244
  function createRegisteredLlmToolConfigurationStatus({ envVariables }, env) {
41288
41245
  return {
@@ -41293,7 +41250,7 @@
41293
41250
  /**
41294
41251
  * Checks whether all required environment variables are present for a provider.
41295
41252
  *
41296
- * @private internal function of `$registeredLlmToolsMessage`
41253
+ * @private function of `$registeredLlmToolsMessage`
41297
41254
  */
41298
41255
  function isRegisteredLlmToolFullyConfigured(envVariables, env) {
41299
41256
  if (envVariables === undefined || envVariables === null) {
@@ -41304,7 +41261,7 @@
41304
41261
  /**
41305
41262
  * Checks whether at least one required environment variable is present for a provider.
41306
41263
  *
41307
- * @private internal function of `$registeredLlmToolsMessage`
41264
+ * @private function of `$registeredLlmToolsMessage`
41308
41265
  */
41309
41266
  function isRegisteredLlmToolPartiallyConfigured(envVariables, env) {
41310
41267
  if (envVariables === undefined || envVariables === null) {
@@ -41312,109 +41269,128 @@
41312
41269
  }
41313
41270
  return envVariables.some((envVariableName) => env[envVariableName] !== undefined);
41314
41271
  }
41272
+
41315
41273
  /**
41316
- * Renders the fallback message for environments with no registered providers.
41274
+ * Merges provider entries from the metadata and constructor registers.
41317
41275
  *
41318
- * @private internal function of `$registeredLlmToolsMessage`
41276
+ * @private function of `$registeredLlmToolsMessage`
41319
41277
  */
41320
- function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
41321
- return _spaceTrim.spaceTrim((block) => `
41322
- No LLM providers are available.
41323
-
41324
- ${block(usedEnvMessage)}
41325
- `);
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()];
41326
41287
  }
41327
41288
  /**
41328
- * Renders the full provider status summary.
41289
+ * Adds a provider entry only when the provider is not already present.
41329
41290
  *
41330
- * @private internal function of `$registeredLlmToolsMessage`
41291
+ * @private function of `$registeredLlmToolsMessage`
41331
41292
  */
41332
- function renderRegisteredLlmToolsMessage({ env, llmToolStatuses, usedEnvMessage, isRunningInNode, }) {
41333
- return _spaceTrim.spaceTrim((block) => `
41334
-
41335
- ${block(usedEnvMessage)}
41336
-
41337
- Relevant environment variables:
41338
- ${block(renderRelevantEnvironmentVariables(env, llmToolStatuses))}
41339
-
41340
- Available LLM providers are:
41341
- ${block(renderAvailableProviders(llmToolStatuses, env, isRunningInNode))}
41342
- `);
41293
+ function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
41294
+ const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
41295
+ if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
41296
+ return;
41297
+ }
41298
+ registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
41343
41299
  }
41300
+
41344
41301
  /**
41345
- * Renders the list of environment variables used by at least one registered provider.
41302
+ * Lists provider entries enriched with installation and configuration state.
41346
41303
  *
41347
- * @private internal function of `$registeredLlmToolsMessage`
41304
+ * @private function of `$registeredLlmToolsMessage`
41348
41305
  */
41349
- function renderRelevantEnvironmentVariables(env, llmToolStatuses) {
41350
- return listRelevantEnvironmentVariables(env, llmToolStatuses)
41351
- .map((envVariableName) => `- \`${envVariableName}\``)
41352
- .join('\n');
41306
+ function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
41307
+ return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
41353
41308
  }
41309
+
41354
41310
  /**
41355
- * Lists environment variables that are both present and used by at least one provider.
41311
+ * Collects all state needed to render the provider summary.
41356
41312
  *
41357
- * @private internal function of `$registeredLlmToolsMessage`
41313
+ * @private function of `$registeredLlmToolsMessage`
41358
41314
  */
41359
- function listRelevantEnvironmentVariables(env, llmToolStatuses) {
41360
- return Object.keys(env).filter((envVariableName) => llmToolStatuses.some(({ envVariables }) => envVariables === null || envVariables === void 0 ? void 0 : envVariables.includes(envVariableName)));
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
+ };
41361
41325
  }
41326
+
41362
41327
  /**
41363
- * Renders all provider lines in the status summary.
41328
+ * Renders the fallback message for environments with no registered providers.
41364
41329
  *
41365
- * @private internal function of `$registeredLlmToolsMessage`
41330
+ * @private function of `$registeredLlmToolsMessage`
41366
41331
  */
41367
- function renderAvailableProviders(llmToolStatuses, env, isRunningInNode) {
41368
- return llmToolStatuses
41369
- .map((llmToolStatus, index) => renderAvailableProvider(llmToolStatus, index, env, isRunningInNode))
41370
- .join('\n');
41332
+ function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
41333
+ return _spaceTrim.spaceTrim((block) => `
41334
+ No LLM providers are available.
41335
+
41336
+ ${block(usedEnvMessage)}
41337
+ `);
41371
41338
  }
41339
+
41372
41340
  /**
41373
- * Renders one provider line in the status summary.
41341
+ * Creates the configuration-status sentence for one provider.
41374
41342
  *
41375
- * @private internal function of `$registeredLlmToolsMessage`
41343
+ * @private function of `$registeredLlmToolsMessage`
41376
41344
  */
41377
- function renderAvailableProvider(llmToolStatus, index, env, isRunningInNode) {
41378
- const providerMessage = createAvailableProviderMessage(llmToolStatus, index, env);
41379
- if (!isRunningInNode) {
41380
- return providerMessage;
41345
+ function createRegisteredLlmToolConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
41346
+ if (isFullyConfigured) {
41347
+ return `Configured`;
41348
+ }
41349
+ if (isPartiallyConfigured) {
41350
+ return createPartiallyConfiguredStatusMessage(envVariables, env);
41381
41351
  }
41382
- 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
41383
41357
  }
41384
41358
  /**
41385
- * Creates the plain-text provider line before optional colorization.
41359
+ * Creates the partial-configuration sentence including missing variables.
41386
41360
  *
41387
- * @private internal function of `$registeredLlmToolsMessage`
41361
+ * @private function of `$registeredLlmToolsMessage`
41388
41362
  */
41389
- function createAvailableProviderMessage(llmToolStatus, index, env) {
41390
- const { title, packageName, className } = llmToolStatus;
41391
- const providerStatusMessages = createProviderStatusMessages(llmToolStatus, env);
41392
- return _spaceTrim.spaceTrim(`
41393
- ${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
41394
- ${providerStatusMessages.join('; ')}
41395
- `);
41363
+ function createPartiallyConfiguredStatusMessage(envVariables, env) {
41364
+ return `Partially confugured, missing ${listMissingEnvironmentVariables(envVariables, env).join(' + ')}`;
41396
41365
  }
41397
41366
  /**
41398
- * Creates the install and configuration fragments for one provider line.
41367
+ * Creates the not-configured sentence including the expected environment variables.
41399
41368
  *
41400
- * @private internal function of `$registeredLlmToolsMessage`
41369
+ * @private function of `$registeredLlmToolsMessage`
41401
41370
  */
41402
- function createProviderStatusMessages(llmToolStatus, env) {
41403
- 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(' + ')}`;
41404
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
+
41405
41383
  /**
41406
41384
  * Creates the installation-status sentence for one provider.
41407
41385
  *
41408
- * @private internal function of `$registeredLlmToolsMessage`
41386
+ * @private function of `$registeredLlmToolsMessage`
41409
41387
  */
41410
- function createInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
41411
- const installationStatusKey = createInstallationStatusKey(isMetadataAvailable, isInstalled);
41388
+ function createRegisteredLlmToolInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
41389
+ const installationStatusKey = createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled);
41412
41390
  switch (installationStatusKey) {
41413
41391
  case 'missing-metadata-and-installation':
41414
- // TODO: [�][�] Maybe do allow to do auto-install if package not registered and not found
41415
41392
  return `Not installed and no metadata, looks like a unexpected behavior`;
41416
41393
  case 'metadata-without-installation':
41417
- // TODO: [�][�]
41418
41394
  return `Not installed`;
41419
41395
  case 'installation-without-metadata':
41420
41396
  return `No metadata but installed, looks like a unexpected behavior`;
@@ -41427,9 +41403,9 @@
41427
41403
  /**
41428
41404
  * Creates a stable installation-state key from metadata and constructor availability.
41429
41405
  *
41430
- * @private internal function of `$registeredLlmToolsMessage`
41406
+ * @private function of `$registeredLlmToolsMessage`
41431
41407
  */
41432
- function createInstallationStatusKey(isMetadataAvailable, isInstalled) {
41408
+ function createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled) {
41433
41409
  if (!isMetadataAvailable && !isInstalled) {
41434
41410
  return 'missing-metadata-and-installation';
41435
41411
  }
@@ -41444,54 +41420,59 @@
41444
41420
  }
41445
41421
  return 'unknown';
41446
41422
  }
41423
+
41447
41424
  /**
41448
- * Creates the configuration-status sentence for one provider.
41425
+ * Renders all provider lines in the status summary.
41449
41426
  *
41450
- * @private internal function of `$registeredLlmToolsMessage`
41427
+ * @private function of `$registeredLlmToolsMessage`
41451
41428
  */
41452
- function createConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
41453
- if (isFullyConfigured) {
41454
- return `Configured`;
41455
- }
41456
- if (isPartiallyConfigured) {
41457
- return createPartiallyConfiguredStatusMessage(envVariables, env);
41458
- }
41459
- if (envVariables !== null) {
41460
- return createNotConfiguredStatusMessage(envVariables);
41461
- }
41462
- return `Not configured`;
41463
- // <- Note: Can not be configured via environment variables
41429
+ function renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode) {
41430
+ return llmToolStatuses
41431
+ .map((llmToolStatus, index) => renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode))
41432
+ .join('\n');
41464
41433
  }
41465
41434
  /**
41466
- * Creates the partial-configuration sentence including missing variables.
41435
+ * Renders one provider line in the status summary.
41467
41436
  *
41468
- * @private internal function of `$registeredLlmToolsMessage`
41437
+ * @private function of `$registeredLlmToolsMessage`
41469
41438
  */
41470
- function createPartiallyConfiguredStatusMessage(envVariables, env) {
41471
- 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);
41472
41445
  }
41473
41446
  /**
41474
- * Creates the not-configured sentence including the expected environment variables.
41447
+ * Creates the plain-text provider line before optional colorization.
41475
41448
  *
41476
- * @private internal function of `$registeredLlmToolsMessage`
41449
+ * @private function of `$registeredLlmToolsMessage`
41477
41450
  */
41478
- function createNotConfiguredStatusMessage(envVariables) {
41479
- 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
+ `);
41480
41458
  }
41481
41459
  /**
41482
- * Lists environment variables that are required but currently missing.
41460
+ * Creates the install and configuration fragments for one provider line.
41483
41461
  *
41484
- * @private internal function of `$registeredLlmToolsMessage`
41462
+ * @private function of `$registeredLlmToolsMessage`
41485
41463
  */
41486
- function listMissingEnvironmentVariables(envVariables, env) {
41487
- 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
+ ];
41488
41469
  }
41489
41470
  /**
41490
41471
  * Applies the same terminal coloring rules as the original summary renderer.
41491
41472
  *
41492
- * @private internal function of `$registeredLlmToolsMessage`
41473
+ * @private function of `$registeredLlmToolsMessage`
41493
41474
  */
41494
- function colorizeAvailableProviderMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
41475
+ function colorizeAvailableRegisteredLlmToolMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
41495
41476
  if (isInstalled && isFullyConfigured) {
41496
41477
  return colors__default["default"].green(providerMessage);
41497
41478
  }
@@ -41500,18 +41481,67 @@
41500
41481
  }
41501
41482
  return colors__default["default"].gray(providerMessage);
41502
41483
  }
41484
+
41503
41485
  /**
41504
- * Creates the `.env` origin sentence used in the summary header.
41486
+ * Renders the list of environment variables used by at least one registered provider.
41505
41487
  *
41506
- * @private internal function of `$registeredLlmToolsMessage`
41488
+ * @private function of `$registeredLlmToolsMessage`
41507
41489
  */
41508
- function createUsedEnvMessage() {
41509
- return $usedEnvFilename === null
41510
- ? `Unknown \`.env\` file`
41511
- : _spaceTrim.spaceTrim(`
41512
- Used \`.env\` file:
41513
- ${$usedEnvFilename}
41514
- `);
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);
41515
41545
  }
41516
41546
  // TODO: [®] DRY Register logic
41517
41547
  // TODO: [🧠][⚛] Maybe pass env as argument