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