@promptbook/remote-server 0.113.0-8 → 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.
- package/esm/index.es.js +1100 -1060
- package/esm/index.es.js.map +1 -1
- package/esm/src/_packages/types.index.d.ts +2 -2
- package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +24 -1
- package/esm/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
- package/esm/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
- package/esm/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
- package/esm/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
- package/esm/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
- package/esm/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
- package/esm/src/book-components/Chat/Chat/ChatMessageItem.d.ts +1 -1
- package/esm/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
- package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +8 -0
- package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
- package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
- package/esm/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
- package/esm/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
- package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
- package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +16 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
- package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
- package/esm/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
- package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
- package/esm/src/commitments/META/META.d.ts +2 -2
- package/esm/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
- package/esm/src/commitments/index.d.ts +1 -1
- package/esm/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
- package/esm/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
- package/esm/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
- package/esm/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
- package/esm/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
- package/esm/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
- package/esm/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
- package/esm/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
- package/esm/src/utils/color/Color.d.ts +1 -1
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +1100 -1060
- package/umd/index.umd.js.map +1 -1
- package/umd/src/_packages/types.index.d.ts +2 -2
- package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +24 -1
- package/umd/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +1 -1
- package/umd/src/book-components/BookEditor/BookEditorMonacoUploadPanel.d.ts +1 -1
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/bookEditorMonacoUploadTypes.d.ts +120 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/clearScheduledTimer.d.ts +6 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/enqueueFilesForUpload.d.ts +26 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadEditorSync.d.ts +23 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadItemsState.d.ts +21 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadProgressQueue.d.ts +12 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useBookEditorMonacoUploadQueue.d.ts +27 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads/useCompletedUploadsAutoClear.d.ts +12 -0
- package/umd/src/book-components/BookEditor/useBookEditorMonacoUploads.d.ts +5 -58
- package/umd/src/book-components/Chat/Chat/ChatImageAttachmentModal.d.ts +25 -0
- package/umd/src/book-components/Chat/Chat/ChatInputArea.d.ts +3 -0
- package/umd/src/book-components/Chat/Chat/ChatMessageAttachments.d.ts +27 -0
- package/umd/src/book-components/Chat/Chat/ChatMessageItem.d.ts +1 -1
- package/umd/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
- package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +8 -0
- package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +12 -0
- package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.draftMessage.test.d.ts +2 -0
- package/umd/src/book-components/Chat/utils/isVisibleChatToolCall.d.ts +1 -1
- package/umd/src/book-components/Chat/utils/parseMessageButtons.d.ts +16 -2
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_FILENAME.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_BUILD_CACHE_VERSION.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AGENTS_SERVER_NEXT_BUILD_ID_FILENAME.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCache.d.ts +10 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/AgentsServerBuildCacheOptions.d.ts +10 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/NODE_MODULES_DIRECTORY_NAME.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/PreparedAgentsServerRuntime.d.ts +18 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerBuildSourceFingerprint.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +28 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.d.ts +19 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/getAgentsServerBuildInputRelativePaths.d.ts +11 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerAppPathMaterialized.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildCacheCurrent.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isAgentsServerBuildInputTestFile.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputDirectoryName.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerBuildInputPath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isExcludedAgentsServerRuntimeSourcePath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isFile.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/isPathInsideNodeModules.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/normalizeAgentsServerBuildInputPath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/prepareAgentsServerRuntime.d.ts +9 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/readAgentsServerBuildCache.d.ts +8 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerAppPath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildAppPath.d.ts +9 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveAgentsServerBuildOutputPath.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNextCliPath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/resolveNodeModulesPath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/runNextBuild.d.ts +12 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/shouldCopyAgentsServerRuntimePath.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/synchronizeMaterializedAgentsServerRuntime.d.ts +11 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/writeAgentsServerBuildCache.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +8 -109
- package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +1 -1
- package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +1 -1
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerChildEnvironment.d.ts +16 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerLogStreams.d.ts +30 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerRuntimePaths.d.ts +19 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/AgentsServerSupervisorState.d.ts +37 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/LocalAgentRunnerLimits.d.ts +9 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/PreparedAgentsServerLaunch.d.ts +13 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/StartAgentsServerOptions.d.ts +24 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createInternalRouteErrorMessage.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.d.ts +9 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/forwardChildOutput.d.ts +13 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/loadAgentsServerProjectEnvironment.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/prepareAgentsServerLaunch.d.ts +18 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/readInternalRouteErrorDetails.d.ts +6 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/resolveAgentsServerChildHostname.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startNextServer.d.ts +20 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/startUserChatJobWorkerPump.d.ts +15 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/stopChildProcess.d.ts +8 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer/waitForLocalAgentRunnerLimits.d.ts +16 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -30
- package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +1 -1
- package/umd/src/collection/agent-collection/CreateAgentInput.d.ts +1 -1
- package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +1 -1
- package/umd/src/commitments/META/META.d.ts +2 -2
- package/umd/src/commitments/META_AVATAR/META_AVATAR.d.ts +9 -4
- package/umd/src/commitments/index.d.ts +1 -1
- package/umd/src/conversion/validation/validatePipeline/createPipelineValidationContext.d.ts +16 -0
- package/umd/src/conversion/validation/validatePipeline/validatePipelineCollectionsStructure.d.ts +7 -0
- package/umd/src/conversion/validation/validatePipeline/validatePipelineDependencyResolution.d.ts +7 -0
- package/umd/src/conversion/validation/validatePipeline/validatePipelineMetadata.d.ts +7 -0
- package/umd/src/conversion/validation/validatePipeline/validatePipelineParameters.d.ts +7 -0
- package/umd/src/conversion/validation/validatePipeline/validatePipelineTasks.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/RegisteredLlmToolsMessageContext.d.ts +46 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/USED_ENV_FILENAME.d.ts +11 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolConfigurationStatusMessage.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolEntryKey.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolInstallationStatusMessage.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolStatus.d.ts +14 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/createRegisteredLlmToolsMessageContext.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getAvailableRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/getRegisteredLlmToolRegisters.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/hasRegisteredLlmToolEntry.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolEntries.d.ts +9 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/listRegisteredLlmToolStatuses.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderAvailableRegisteredLlmTools.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderNoRegisteredLlmToolsMessage.d.ts +7 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRegisteredLlmToolsMessage.d.ts +8 -0
- package/umd/src/llm-providers/_common/register/$registeredLlmToolsMessage/renderRelevantRegisteredLlmToolsEnvironmentVariables.d.ts +7 -0
- package/umd/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +2 -2
- package/umd/src/utils/color/Color.d.ts +1 -1
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
40
40
|
* @generated
|
|
41
41
|
* @see https://github.com/webgptorg/promptbook
|
|
42
42
|
*/
|
|
43
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.113.0-
|
|
43
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.113.0-9';
|
|
44
44
|
/**
|
|
45
45
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
46
46
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -103,6 +103,127 @@ function take(initialValue) {
|
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Validates that a channel value is a valid number within the range of 0 to 255.
|
|
108
|
+
* Throws an error if the value is not valid.
|
|
109
|
+
*
|
|
110
|
+
* @param channelName - The name of the channel being validated.
|
|
111
|
+
* @param value - The value of the channel to validate.
|
|
112
|
+
* @throws Will throw an error if the value is not a valid channel number.
|
|
113
|
+
*
|
|
114
|
+
* @private util of `@promptbook/color`
|
|
115
|
+
*/
|
|
116
|
+
function checkChannelValue(channelName, value) {
|
|
117
|
+
if (typeof value !== 'number') {
|
|
118
|
+
throw new Error(`${channelName} channel value is not number but ${typeof value}`);
|
|
119
|
+
}
|
|
120
|
+
if (isNaN(value)) {
|
|
121
|
+
throw new Error(`${channelName} channel value is NaN`);
|
|
122
|
+
}
|
|
123
|
+
if (Math.round(value) !== value) {
|
|
124
|
+
throw new Error(`${channelName} channel is not whole number, it is ${value}`);
|
|
125
|
+
}
|
|
126
|
+
if (value < 0) {
|
|
127
|
+
throw new Error(`${channelName} channel is lower than 0, it is ${value}`);
|
|
128
|
+
}
|
|
129
|
+
if (value > 255) {
|
|
130
|
+
throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
136
|
+
*
|
|
137
|
+
* @private base class of Color
|
|
138
|
+
*/
|
|
139
|
+
class ColorValue {
|
|
140
|
+
constructor(red, green, blue, alpha = 255) {
|
|
141
|
+
this.red = red;
|
|
142
|
+
this.green = green;
|
|
143
|
+
this.blue = blue;
|
|
144
|
+
this.alpha = alpha;
|
|
145
|
+
checkChannelValue('Red', red);
|
|
146
|
+
checkChannelValue('Green', green);
|
|
147
|
+
checkChannelValue('Blue', blue);
|
|
148
|
+
checkChannelValue('Alpha', alpha);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Shortcut for `red` property
|
|
152
|
+
* Number from 0 to 255
|
|
153
|
+
* @alias red
|
|
154
|
+
*/
|
|
155
|
+
get r() {
|
|
156
|
+
return this.red;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Shortcut for `green` property
|
|
160
|
+
* Number from 0 to 255
|
|
161
|
+
* @alias green
|
|
162
|
+
*/
|
|
163
|
+
get g() {
|
|
164
|
+
return this.green;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Shortcut for `blue` property
|
|
168
|
+
* Number from 0 to 255
|
|
169
|
+
* @alias blue
|
|
170
|
+
*/
|
|
171
|
+
get b() {
|
|
172
|
+
return this.blue;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Shortcut for `alpha` property
|
|
176
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
177
|
+
* @alias alpha
|
|
178
|
+
*/
|
|
179
|
+
get a() {
|
|
180
|
+
return this.alpha;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Shortcut for `alpha` property
|
|
184
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
185
|
+
* @alias alpha
|
|
186
|
+
*/
|
|
187
|
+
get opacity() {
|
|
188
|
+
return this.alpha;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Shortcut for 1-`alpha` property
|
|
192
|
+
*/
|
|
193
|
+
get transparency() {
|
|
194
|
+
return 255 - this.alpha;
|
|
195
|
+
}
|
|
196
|
+
clone() {
|
|
197
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
198
|
+
}
|
|
199
|
+
toString() {
|
|
200
|
+
return this.toHex();
|
|
201
|
+
}
|
|
202
|
+
toHex() {
|
|
203
|
+
if (this.alpha === 255) {
|
|
204
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
205
|
+
.toString(16)
|
|
206
|
+
.padStart(2, '0')}`;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
210
|
+
.toString(16)
|
|
211
|
+
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
toRgb() {
|
|
215
|
+
if (this.alpha === 255) {
|
|
216
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
toHsl() {
|
|
223
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
106
227
|
/**
|
|
107
228
|
* 🎨 List of all 140 color names which are supported by CSS
|
|
108
229
|
*
|
|
@@ -262,127 +383,6 @@ const CSS_COLORS = {
|
|
|
262
383
|
};
|
|
263
384
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
264
385
|
|
|
265
|
-
/**
|
|
266
|
-
* Validates that a channel value is a valid number within the range of 0 to 255.
|
|
267
|
-
* Throws an error if the value is not valid.
|
|
268
|
-
*
|
|
269
|
-
* @param channelName - The name of the channel being validated.
|
|
270
|
-
* @param value - The value of the channel to validate.
|
|
271
|
-
* @throws Will throw an error if the value is not a valid channel number.
|
|
272
|
-
*
|
|
273
|
-
* @private util of `@promptbook/color`
|
|
274
|
-
*/
|
|
275
|
-
function checkChannelValue(channelName, value) {
|
|
276
|
-
if (typeof value !== 'number') {
|
|
277
|
-
throw new Error(`${channelName} channel value is not number but ${typeof value}`);
|
|
278
|
-
}
|
|
279
|
-
if (isNaN(value)) {
|
|
280
|
-
throw new Error(`${channelName} channel value is NaN`);
|
|
281
|
-
}
|
|
282
|
-
if (Math.round(value) !== value) {
|
|
283
|
-
throw new Error(`${channelName} channel is not whole number, it is ${value}`);
|
|
284
|
-
}
|
|
285
|
-
if (value < 0) {
|
|
286
|
-
throw new Error(`${channelName} channel is lower than 0, it is ${value}`);
|
|
287
|
-
}
|
|
288
|
-
if (value > 255) {
|
|
289
|
-
throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
295
|
-
*
|
|
296
|
-
* @private base class of Color
|
|
297
|
-
*/
|
|
298
|
-
class ColorValue {
|
|
299
|
-
constructor(red, green, blue, alpha = 255) {
|
|
300
|
-
this.red = red;
|
|
301
|
-
this.green = green;
|
|
302
|
-
this.blue = blue;
|
|
303
|
-
this.alpha = alpha;
|
|
304
|
-
checkChannelValue('Red', red);
|
|
305
|
-
checkChannelValue('Green', green);
|
|
306
|
-
checkChannelValue('Blue', blue);
|
|
307
|
-
checkChannelValue('Alpha', alpha);
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Shortcut for `red` property
|
|
311
|
-
* Number from 0 to 255
|
|
312
|
-
* @alias red
|
|
313
|
-
*/
|
|
314
|
-
get r() {
|
|
315
|
-
return this.red;
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Shortcut for `green` property
|
|
319
|
-
* Number from 0 to 255
|
|
320
|
-
* @alias green
|
|
321
|
-
*/
|
|
322
|
-
get g() {
|
|
323
|
-
return this.green;
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Shortcut for `blue` property
|
|
327
|
-
* Number from 0 to 255
|
|
328
|
-
* @alias blue
|
|
329
|
-
*/
|
|
330
|
-
get b() {
|
|
331
|
-
return this.blue;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Shortcut for `alpha` property
|
|
335
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
336
|
-
* @alias alpha
|
|
337
|
-
*/
|
|
338
|
-
get a() {
|
|
339
|
-
return this.alpha;
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Shortcut for `alpha` property
|
|
343
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
344
|
-
* @alias alpha
|
|
345
|
-
*/
|
|
346
|
-
get opacity() {
|
|
347
|
-
return this.alpha;
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Shortcut for 1-`alpha` property
|
|
351
|
-
*/
|
|
352
|
-
get transparency() {
|
|
353
|
-
return 255 - this.alpha;
|
|
354
|
-
}
|
|
355
|
-
clone() {
|
|
356
|
-
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
357
|
-
}
|
|
358
|
-
toString() {
|
|
359
|
-
return this.toHex();
|
|
360
|
-
}
|
|
361
|
-
toHex() {
|
|
362
|
-
if (this.alpha === 255) {
|
|
363
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
364
|
-
.toString(16)
|
|
365
|
-
.padStart(2, '0')}`;
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
369
|
-
.toString(16)
|
|
370
|
-
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
toRgb() {
|
|
374
|
-
if (this.alpha === 255) {
|
|
375
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
toHsl() {
|
|
382
|
-
throw new Error(`Getting HSL is not implemented`);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
386
|
/**
|
|
387
387
|
* Checks if the given value is a valid hex color string
|
|
388
388
|
*
|
|
@@ -2150,6 +2150,82 @@ function resolveBookPipelineUrl(request, pipelines) {
|
|
|
2150
2150
|
return pipelines.find((pipelineUrl) => pipelineUrl.endsWith(request.originalUrl)) || fullUrl;
|
|
2151
2151
|
}
|
|
2152
2152
|
|
|
2153
|
+
/**
|
|
2154
|
+
* Creates the shared validation context for one pipeline.
|
|
2155
|
+
*
|
|
2156
|
+
* @private function of `validatePipeline`
|
|
2157
|
+
*/
|
|
2158
|
+
function createPipelineValidationContext(pipeline) {
|
|
2159
|
+
return {
|
|
2160
|
+
pipeline,
|
|
2161
|
+
pipelineIdentification: getPipelineIdentification(pipeline),
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
/**
|
|
2165
|
+
* Builds a short file/url identification block for validation errors.
|
|
2166
|
+
*
|
|
2167
|
+
* @private internal utility of `validatePipeline`
|
|
2168
|
+
*/
|
|
2169
|
+
function getPipelineIdentification(pipeline) {
|
|
2170
|
+
// Note: This is a 😐 implementation of [🚞]
|
|
2171
|
+
const pipelineIdentificationParts = [];
|
|
2172
|
+
if (pipeline.sourceFile !== undefined) {
|
|
2173
|
+
pipelineIdentificationParts.push(`File: ${pipeline.sourceFile}`);
|
|
2174
|
+
}
|
|
2175
|
+
if (pipeline.pipelineUrl !== undefined) {
|
|
2176
|
+
pipelineIdentificationParts.push(`Url: ${pipeline.pipelineUrl}`);
|
|
2177
|
+
}
|
|
2178
|
+
return pipelineIdentificationParts.join('\n');
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
/**
|
|
2182
|
+
* Validates that the expected top-level collections have array structure.
|
|
2183
|
+
*
|
|
2184
|
+
* @private function of `validatePipeline`
|
|
2185
|
+
*/
|
|
2186
|
+
function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification, }) {
|
|
2187
|
+
validatePipelineParametersCollection(pipeline, pipelineIdentification);
|
|
2188
|
+
validatePipelineTasksCollection(pipeline, pipelineIdentification);
|
|
2189
|
+
}
|
|
2190
|
+
/**
|
|
2191
|
+
* Validates that `pipeline.parameters` is an array.
|
|
2192
|
+
*
|
|
2193
|
+
* @private internal utility of `validatePipelineCollectionsStructure`
|
|
2194
|
+
*/
|
|
2195
|
+
function validatePipelineParametersCollection(pipeline, pipelineIdentification) {
|
|
2196
|
+
// TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
|
|
2197
|
+
if (Array.isArray(pipeline.parameters)) {
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
2201
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
2202
|
+
Pipeline is valid JSON but with wrong structure
|
|
2203
|
+
|
|
2204
|
+
\`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
|
|
2205
|
+
|
|
2206
|
+
${block(pipelineIdentification)}
|
|
2207
|
+
`));
|
|
2208
|
+
}
|
|
2209
|
+
/**
|
|
2210
|
+
* Validates that `pipeline.tasks` is an array.
|
|
2211
|
+
*
|
|
2212
|
+
* @private internal utility of `validatePipelineCollectionsStructure`
|
|
2213
|
+
*/
|
|
2214
|
+
function validatePipelineTasksCollection(pipeline, pipelineIdentification) {
|
|
2215
|
+
// TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
|
|
2216
|
+
if (Array.isArray(pipeline.tasks)) {
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
2220
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
2221
|
+
Pipeline is valid JSON but with wrong structure
|
|
2222
|
+
|
|
2223
|
+
\`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
|
|
2224
|
+
|
|
2225
|
+
${block(pipelineIdentification)}
|
|
2226
|
+
`));
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2153
2229
|
/**
|
|
2154
2230
|
* Orders JSON object by keys
|
|
2155
2231
|
*
|
|
@@ -2563,6 +2639,140 @@ const LIMITS = {
|
|
|
2563
2639
|
};
|
|
2564
2640
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2565
2641
|
|
|
2642
|
+
/**
|
|
2643
|
+
* Validates that task dependencies can be resolved without cycles or missing definitions.
|
|
2644
|
+
*
|
|
2645
|
+
* @private function of `validatePipeline`
|
|
2646
|
+
*/
|
|
2647
|
+
function validatePipelineDependencyResolution({ pipeline, pipelineIdentification, }) {
|
|
2648
|
+
let dependencyResolutionState = createInitialDependencyResolutionState(pipeline);
|
|
2649
|
+
let loopLimit = LOOP_LIMIT;
|
|
2650
|
+
while (hasUnresolvedTasks(dependencyResolutionState)) {
|
|
2651
|
+
if (loopLimit-- < 0) {
|
|
2652
|
+
throw createDependencyResolutionLoopLimitError(pipelineIdentification);
|
|
2653
|
+
}
|
|
2654
|
+
dependencyResolutionState = resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
/**
|
|
2658
|
+
* Collects the parameter names that are already resolvable before dependency traversal starts.
|
|
2659
|
+
*
|
|
2660
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2661
|
+
*/
|
|
2662
|
+
function createInitialDependencyResolutionState(pipeline) {
|
|
2663
|
+
return {
|
|
2664
|
+
resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
|
|
2665
|
+
unresolvedTasks: [...pipeline.tasks],
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Checks whether dependency resolution still has tasks left to process.
|
|
2670
|
+
*
|
|
2671
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2672
|
+
*/
|
|
2673
|
+
function hasUnresolvedTasks({ unresolvedTasks }) {
|
|
2674
|
+
return unresolvedTasks.length > 0;
|
|
2675
|
+
}
|
|
2676
|
+
/**
|
|
2677
|
+
* Resolves the next batch of currently satisfiable tasks.
|
|
2678
|
+
*
|
|
2679
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2680
|
+
*/
|
|
2681
|
+
function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
|
|
2682
|
+
const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
|
|
2683
|
+
if (currentlyResolvedTasks.length === 0) {
|
|
2684
|
+
throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
|
|
2685
|
+
}
|
|
2686
|
+
return {
|
|
2687
|
+
resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
|
|
2688
|
+
unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
/**
|
|
2692
|
+
* Collects the parameter names that are already resolvable before dependency traversal starts.
|
|
2693
|
+
*
|
|
2694
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2695
|
+
*/
|
|
2696
|
+
function createInitiallyResolvedParameterNames(pipeline) {
|
|
2697
|
+
let resolvedParameterNames = pipeline.parameters
|
|
2698
|
+
.filter(({ isInput }) => isInput)
|
|
2699
|
+
.map(({ name }) => name);
|
|
2700
|
+
for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
|
|
2701
|
+
resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
|
|
2702
|
+
}
|
|
2703
|
+
return resolvedParameterNames;
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Adds newly resolved task outputs to the resolved parameter list.
|
|
2707
|
+
*
|
|
2708
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2709
|
+
*/
|
|
2710
|
+
function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
|
|
2711
|
+
return [
|
|
2712
|
+
...resolvedParameterNames,
|
|
2713
|
+
...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
|
|
2714
|
+
];
|
|
2715
|
+
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Selects tasks whose dependencies are already resolved.
|
|
2718
|
+
*
|
|
2719
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2720
|
+
*/
|
|
2721
|
+
function getCurrentlyResolvedTasks(unresolvedTasks, resolvedParameterNames) {
|
|
2722
|
+
return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
|
|
2723
|
+
}
|
|
2724
|
+
/**
|
|
2725
|
+
* Creates the unexpected loop-limit error for dependency resolution.
|
|
2726
|
+
*
|
|
2727
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2728
|
+
*/
|
|
2729
|
+
function createDependencyResolutionLoopLimitError(pipelineIdentification) {
|
|
2730
|
+
// Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
|
|
2731
|
+
return new UnexpectedError(spaceTrim$1((block) => `
|
|
2732
|
+
Loop limit reached during detection of circular dependencies in \`validatePipeline\`
|
|
2733
|
+
|
|
2734
|
+
${block(pipelineIdentification)}
|
|
2735
|
+
`));
|
|
2736
|
+
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Creates the detailed error for unresolved or circular task dependencies.
|
|
2739
|
+
*
|
|
2740
|
+
* @private internal utility of `validatePipelineDependencyResolution`
|
|
2741
|
+
*/
|
|
2742
|
+
function createUnresolvedTasksError(unresolvedTasks, resolvedParameterNames, pipelineIdentification) {
|
|
2743
|
+
return new PipelineLogicError(
|
|
2744
|
+
// TODO: [🐎] DRY
|
|
2745
|
+
spaceTrim$1((block) => `
|
|
2746
|
+
|
|
2747
|
+
Can not resolve some parameters:
|
|
2748
|
+
Either you are using a parameter that is not defined, or there are some circular dependencies.
|
|
2749
|
+
|
|
2750
|
+
${block(pipelineIdentification)}
|
|
2751
|
+
|
|
2752
|
+
**Can not resolve:**
|
|
2753
|
+
${block(unresolvedTasks
|
|
2754
|
+
.map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
|
|
2755
|
+
.map((dependentParameterName) => `\`{${dependentParameterName}}\``)
|
|
2756
|
+
.join(' and ')}`)
|
|
2757
|
+
.join('\n'))}
|
|
2758
|
+
|
|
2759
|
+
**Resolved:**
|
|
2760
|
+
${block(resolvedParameterNames
|
|
2761
|
+
.filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
|
|
2762
|
+
.map((name) => `- Parameter \`{${name}}\``)
|
|
2763
|
+
.join('\n'))}
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
**Reserved (which are available):**
|
|
2767
|
+
${block(resolvedParameterNames
|
|
2768
|
+
.filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
|
|
2769
|
+
.map((name) => `- Parameter \`{${name}}\``)
|
|
2770
|
+
.join('\n'))}
|
|
2771
|
+
|
|
2772
|
+
|
|
2773
|
+
`));
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2566
2776
|
/**
|
|
2567
2777
|
* Tests if given string is valid semantic version
|
|
2568
2778
|
*
|
|
@@ -2668,168 +2878,19 @@ function isValidPipelineUrl(url) {
|
|
|
2668
2878
|
}
|
|
2669
2879
|
// TODO: [🐠] Maybe more info why the URL is invalid
|
|
2670
2880
|
|
|
2671
|
-
/**
|
|
2672
|
-
* Validates PipelineJson if it is logically valid
|
|
2673
|
-
*
|
|
2674
|
-
* It checks:
|
|
2675
|
-
* - if it has correct parameters dependency
|
|
2676
|
-
*
|
|
2677
|
-
* It does NOT check:
|
|
2678
|
-
* - if it is valid json
|
|
2679
|
-
* - if it is meaningful
|
|
2680
|
-
*
|
|
2681
|
-
* Note: [🔂] This function is idempotent.
|
|
2682
|
-
*
|
|
2683
|
-
* @param pipeline valid or invalid PipelineJson
|
|
2684
|
-
* @returns the same pipeline if it is logically valid
|
|
2685
|
-
* @throws {PipelineLogicError} on logical error in the pipeline
|
|
2686
|
-
*
|
|
2687
|
-
* @public exported from `@promptbook/core`
|
|
2688
|
-
*/
|
|
2689
|
-
function validatePipeline(pipeline) {
|
|
2690
|
-
if (IS_PIPELINE_LOGIC_VALIDATED) {
|
|
2691
|
-
validatePipeline_InnerFunction(pipeline);
|
|
2692
|
-
}
|
|
2693
|
-
else {
|
|
2694
|
-
try {
|
|
2695
|
-
validatePipeline_InnerFunction(pipeline);
|
|
2696
|
-
}
|
|
2697
|
-
catch (error) {
|
|
2698
|
-
if (!(error instanceof PipelineLogicError)) {
|
|
2699
|
-
throw error;
|
|
2700
|
-
}
|
|
2701
|
-
console.error(spaceTrim$1((block) => `
|
|
2702
|
-
Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
|
|
2703
|
-
|
|
2704
|
-
${block(error.message)}
|
|
2705
|
-
`));
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
return pipeline;
|
|
2709
|
-
}
|
|
2710
|
-
/**
|
|
2711
|
-
* Validates pipeline inner function.
|
|
2712
|
-
*
|
|
2713
|
-
* @private internal function for `validatePipeline`
|
|
2714
|
-
*/
|
|
2715
|
-
function validatePipeline_InnerFunction(pipeline) {
|
|
2716
|
-
// TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
|
|
2717
|
-
const context = createPipelineValidationContext(pipeline);
|
|
2718
|
-
validatePipelineMetadata(context);
|
|
2719
|
-
validatePipelineCollectionsStructure(context);
|
|
2720
|
-
validatePipelineParameters(context);
|
|
2721
|
-
validatePipelineTasks(context);
|
|
2722
|
-
validatePipelineDependencyResolution(context);
|
|
2723
|
-
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
2724
|
-
// TODO: !!6 Implement this
|
|
2725
|
-
// pipeline.formfactorName
|
|
2726
|
-
}
|
|
2727
|
-
/**
|
|
2728
|
-
* Creates the shared validation context for one pipeline.
|
|
2729
|
-
*
|
|
2730
|
-
* @private internal utility of `validatePipeline`
|
|
2731
|
-
*/
|
|
2732
|
-
function createPipelineValidationContext(pipeline) {
|
|
2733
|
-
return {
|
|
2734
|
-
pipeline,
|
|
2735
|
-
pipelineIdentification: getPipelineIdentification(pipeline),
|
|
2736
|
-
};
|
|
2737
|
-
}
|
|
2738
|
-
/**
|
|
2739
|
-
* Builds a short file/url identification block for validation errors.
|
|
2740
|
-
*
|
|
2741
|
-
* @private internal utility of `validatePipeline`
|
|
2742
|
-
*/
|
|
2743
|
-
function getPipelineIdentification(pipeline) {
|
|
2744
|
-
// Note: This is a 😐 implementation of [🚞]
|
|
2745
|
-
const pipelineIdentificationParts = [];
|
|
2746
|
-
if (pipeline.sourceFile !== undefined) {
|
|
2747
|
-
pipelineIdentificationParts.push(`File: ${pipeline.sourceFile}`);
|
|
2748
|
-
}
|
|
2749
|
-
if (pipeline.pipelineUrl !== undefined) {
|
|
2750
|
-
pipelineIdentificationParts.push(`Url: ${pipeline.pipelineUrl}`);
|
|
2751
|
-
}
|
|
2752
|
-
return pipelineIdentificationParts.join('\n');
|
|
2753
|
-
}
|
|
2754
2881
|
/**
|
|
2755
2882
|
* Validates pipeline-level metadata fields.
|
|
2756
2883
|
*
|
|
2757
|
-
* @private
|
|
2884
|
+
* @private function of `validatePipeline`
|
|
2758
2885
|
*/
|
|
2759
2886
|
function validatePipelineMetadata({ pipeline, pipelineIdentification }) {
|
|
2760
2887
|
validatePipelineUrl(pipeline, pipelineIdentification);
|
|
2761
2888
|
validatePipelineBookVersion(pipeline, pipelineIdentification);
|
|
2762
2889
|
}
|
|
2763
|
-
/**
|
|
2764
|
-
* Validates that the expected top-level collections have array structure.
|
|
2765
|
-
*
|
|
2766
|
-
* @private internal step of `validatePipeline`
|
|
2767
|
-
*/
|
|
2768
|
-
function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification }) {
|
|
2769
|
-
validatePipelineParametersCollection(pipeline, pipelineIdentification);
|
|
2770
|
-
validatePipelineTasksCollection(pipeline, pipelineIdentification);
|
|
2771
|
-
}
|
|
2772
|
-
/**
|
|
2773
|
-
* Validates all pipeline parameter declarations.
|
|
2774
|
-
*
|
|
2775
|
-
* @private internal step of `validatePipeline`
|
|
2776
|
-
*/
|
|
2777
|
-
function validatePipelineParameters({ pipeline, pipelineIdentification }) {
|
|
2778
|
-
for (const parameter of pipeline.parameters) {
|
|
2779
|
-
validatePipelineParameter(parameter, pipeline, pipelineIdentification);
|
|
2780
|
-
}
|
|
2781
|
-
}
|
|
2782
|
-
/**
|
|
2783
|
-
* Validates all pipeline tasks and their per-task invariants.
|
|
2784
|
-
*
|
|
2785
|
-
* @private internal step of `validatePipeline`
|
|
2786
|
-
*/
|
|
2787
|
-
function validatePipelineTasks({ pipeline, pipelineIdentification }) {
|
|
2788
|
-
// Note: All input parameters are defined - so that they can be used as result of some task
|
|
2789
|
-
const definedParameters = createInitiallyDefinedParameters(pipeline);
|
|
2790
|
-
for (const task of pipeline.tasks) {
|
|
2791
|
-
validatePipelineTask(task, definedParameters, pipelineIdentification);
|
|
2792
|
-
}
|
|
2793
|
-
}
|
|
2794
|
-
/**
|
|
2795
|
-
* Validates that task dependencies can be resolved without cycles or missing definitions.
|
|
2796
|
-
*
|
|
2797
|
-
* @private internal step of `validatePipeline`
|
|
2798
|
-
*/
|
|
2799
|
-
function validatePipelineDependencyResolution({ pipeline, pipelineIdentification }) {
|
|
2800
|
-
let dependencyResolutionState = createInitialDependencyResolutionState(pipeline);
|
|
2801
|
-
let loopLimit = LOOP_LIMIT;
|
|
2802
|
-
while (hasUnresolvedTasks(dependencyResolutionState)) {
|
|
2803
|
-
if (loopLimit-- < 0) {
|
|
2804
|
-
throw createDependencyResolutionLoopLimitError(pipelineIdentification);
|
|
2805
|
-
}
|
|
2806
|
-
dependencyResolutionState = resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification);
|
|
2807
|
-
}
|
|
2808
|
-
}
|
|
2809
|
-
/**
|
|
2810
|
-
* Validates one pipeline parameter declaration.
|
|
2811
|
-
*
|
|
2812
|
-
* @private internal step of `validatePipeline`
|
|
2813
|
-
*/
|
|
2814
|
-
function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
|
|
2815
|
-
validateParameterDirection(parameter, pipelineIdentification);
|
|
2816
|
-
validateParameterUsage(parameter, pipeline, pipelineIdentification);
|
|
2817
|
-
validateParameterDefinition(parameter, pipeline, pipelineIdentification);
|
|
2818
|
-
}
|
|
2819
|
-
/**
|
|
2820
|
-
* Validates one pipeline task and its invariants.
|
|
2821
|
-
*
|
|
2822
|
-
* @private internal step of `validatePipeline`
|
|
2823
|
-
*/
|
|
2824
|
-
function validatePipelineTask(task, definedParameters, pipelineIdentification) {
|
|
2825
|
-
validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
|
|
2826
|
-
validateTaskJokers(task, pipelineIdentification);
|
|
2827
|
-
validateTaskExpectations(task, pipelineIdentification);
|
|
2828
|
-
}
|
|
2829
2890
|
/**
|
|
2830
2891
|
* Validates the pipeline URL, when present.
|
|
2831
2892
|
*
|
|
2832
|
-
* @private internal utility of `
|
|
2893
|
+
* @private internal utility of `validatePipelineMetadata`
|
|
2833
2894
|
*/
|
|
2834
2895
|
function validatePipelineUrl(pipeline, pipelineIdentification) {
|
|
2835
2896
|
if (pipeline.pipelineUrl === undefined || isValidPipelineUrl(pipeline.pipelineUrl)) {
|
|
@@ -2845,7 +2906,7 @@ function validatePipelineUrl(pipeline, pipelineIdentification) {
|
|
|
2845
2906
|
/**
|
|
2846
2907
|
* Validates the Promptbook version, when present.
|
|
2847
2908
|
*
|
|
2848
|
-
* @private internal utility of `
|
|
2909
|
+
* @private internal utility of `validatePipelineMetadata`
|
|
2849
2910
|
*/
|
|
2850
2911
|
function validatePipelineBookVersion(pipeline, pipelineIdentification) {
|
|
2851
2912
|
if (pipeline.bookVersion === undefined || isValidPromptbookVersion(pipeline.bookVersion)) {
|
|
@@ -2858,48 +2919,31 @@ function validatePipelineBookVersion(pipeline, pipelineIdentification) {
|
|
|
2858
2919
|
${block(pipelineIdentification)}
|
|
2859
2920
|
`));
|
|
2860
2921
|
}
|
|
2922
|
+
|
|
2861
2923
|
/**
|
|
2862
|
-
* Validates
|
|
2924
|
+
* Validates all pipeline parameter declarations.
|
|
2863
2925
|
*
|
|
2864
|
-
* @private
|
|
2926
|
+
* @private function of `validatePipeline`
|
|
2865
2927
|
*/
|
|
2866
|
-
function
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
return;
|
|
2928
|
+
function validatePipelineParameters({ pipeline, pipelineIdentification }) {
|
|
2929
|
+
for (const parameter of pipeline.parameters) {
|
|
2930
|
+
validatePipelineParameter(parameter, pipeline, pipelineIdentification);
|
|
2870
2931
|
}
|
|
2871
|
-
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
2872
|
-
throw new ParseError(spaceTrim$1((block) => `
|
|
2873
|
-
Pipeline is valid JSON but with wrong structure
|
|
2874
|
-
|
|
2875
|
-
\`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
|
|
2876
|
-
|
|
2877
|
-
${block(pipelineIdentification)}
|
|
2878
|
-
`));
|
|
2879
2932
|
}
|
|
2880
2933
|
/**
|
|
2881
|
-
* Validates
|
|
2934
|
+
* Validates one pipeline parameter declaration.
|
|
2882
2935
|
*
|
|
2883
|
-
* @private internal utility of `
|
|
2936
|
+
* @private internal utility of `validatePipelineParameters`
|
|
2884
2937
|
*/
|
|
2885
|
-
function
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
}
|
|
2890
|
-
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
2891
|
-
throw new ParseError(spaceTrim$1((block) => `
|
|
2892
|
-
Pipeline is valid JSON but with wrong structure
|
|
2893
|
-
|
|
2894
|
-
\`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
|
|
2895
|
-
|
|
2896
|
-
${block(pipelineIdentification)}
|
|
2897
|
-
`));
|
|
2938
|
+
function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
|
|
2939
|
+
validateParameterDirection(parameter, pipelineIdentification);
|
|
2940
|
+
validateParameterUsage(parameter, pipeline, pipelineIdentification);
|
|
2941
|
+
validateParameterDefinition(parameter, pipeline, pipelineIdentification);
|
|
2898
2942
|
}
|
|
2899
2943
|
/**
|
|
2900
2944
|
* Validates that one parameter does not declare incompatible directions.
|
|
2901
2945
|
*
|
|
2902
|
-
* @private internal utility of `
|
|
2946
|
+
* @private internal utility of `validatePipelineParameters`
|
|
2903
2947
|
*/
|
|
2904
2948
|
function validateParameterDirection(parameter, pipelineIdentification) {
|
|
2905
2949
|
if (!parameter.isInput || !parameter.isOutput) {
|
|
@@ -2916,7 +2960,7 @@ function validateParameterDirection(parameter, pipelineIdentification) {
|
|
|
2916
2960
|
/**
|
|
2917
2961
|
* Validates that one intermediate parameter is actually consumed by at least one task.
|
|
2918
2962
|
*
|
|
2919
|
-
* @private internal utility of `
|
|
2963
|
+
* @private internal utility of `validatePipelineParameters`
|
|
2920
2964
|
*/
|
|
2921
2965
|
function validateParameterUsage(parameter, pipeline, pipelineIdentification) {
|
|
2922
2966
|
if (parameter.isInput || parameter.isOutput || isParameterUsedByAnyTask(parameter, pipeline.tasks)) {
|
|
@@ -2935,7 +2979,7 @@ function validateParameterUsage(parameter, pipeline, pipelineIdentification) {
|
|
|
2935
2979
|
/**
|
|
2936
2980
|
* Validates that one non-input parameter is produced by at least one task.
|
|
2937
2981
|
*
|
|
2938
|
-
* @private internal utility of `
|
|
2982
|
+
* @private internal utility of `validatePipelineParameters`
|
|
2939
2983
|
*/
|
|
2940
2984
|
function validateParameterDefinition(parameter, pipeline, pipelineIdentification) {
|
|
2941
2985
|
if (parameter.isInput || isParameterDefinedByAnyTask(parameter, pipeline.tasks)) {
|
|
@@ -2954,7 +2998,7 @@ function validateParameterDefinition(parameter, pipeline, pipelineIdentification
|
|
|
2954
2998
|
/**
|
|
2955
2999
|
* Checks whether one parameter is consumed by at least one task dependency list.
|
|
2956
3000
|
*
|
|
2957
|
-
* @private internal utility of `
|
|
3001
|
+
* @private internal utility of `validatePipelineParameters`
|
|
2958
3002
|
*/
|
|
2959
3003
|
function isParameterUsedByAnyTask(parameter, tasks) {
|
|
2960
3004
|
return tasks.some((task) => task.dependentParameterNames.includes(parameter.name));
|
|
@@ -2962,23 +3006,46 @@ function isParameterUsedByAnyTask(parameter, tasks) {
|
|
|
2962
3006
|
/**
|
|
2963
3007
|
* Checks whether one parameter is produced by at least one task.
|
|
2964
3008
|
*
|
|
2965
|
-
* @private internal utility of `
|
|
3009
|
+
* @private internal utility of `validatePipelineParameters`
|
|
2966
3010
|
*/
|
|
2967
3011
|
function isParameterDefinedByAnyTask(parameter, tasks) {
|
|
2968
3012
|
return tasks.some((task) => task.resultingParameterName === parameter.name);
|
|
2969
3013
|
}
|
|
3014
|
+
|
|
3015
|
+
/**
|
|
3016
|
+
* Validates all pipeline tasks and their per-task invariants.
|
|
3017
|
+
*
|
|
3018
|
+
* @private function of `validatePipeline`
|
|
3019
|
+
*/
|
|
3020
|
+
function validatePipelineTasks({ pipeline, pipelineIdentification }) {
|
|
3021
|
+
// Note: All input parameters are defined - so that they can be used as result of some task
|
|
3022
|
+
const definedParameters = createInitiallyDefinedParameters(pipeline);
|
|
3023
|
+
for (const task of pipeline.tasks) {
|
|
3024
|
+
validatePipelineTask(task, definedParameters, pipelineIdentification);
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
2970
3027
|
/**
|
|
2971
3028
|
* Collects the parameter names that are already defined before task validation starts.
|
|
2972
3029
|
*
|
|
2973
|
-
* @private internal utility of `
|
|
3030
|
+
* @private internal utility of `validatePipelineTasks`
|
|
2974
3031
|
*/
|
|
2975
3032
|
function createInitiallyDefinedParameters(pipeline) {
|
|
2976
3033
|
return new Set(pipeline.parameters.filter(({ isInput }) => isInput).map(({ name }) => name));
|
|
2977
3034
|
}
|
|
3035
|
+
/**
|
|
3036
|
+
* Validates one pipeline task and its invariants.
|
|
3037
|
+
*
|
|
3038
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3039
|
+
*/
|
|
3040
|
+
function validatePipelineTask(task, definedParameters, pipelineIdentification) {
|
|
3041
|
+
validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
|
|
3042
|
+
validateTaskJokers(task, pipelineIdentification);
|
|
3043
|
+
validateTaskExpectations(task, pipelineIdentification);
|
|
3044
|
+
}
|
|
2978
3045
|
/**
|
|
2979
3046
|
* Validates one task result parameter declaration and marks it as defined.
|
|
2980
3047
|
*
|
|
2981
|
-
* @private internal utility of `
|
|
3048
|
+
* @private internal utility of `validatePipelineTasks`
|
|
2982
3049
|
*/
|
|
2983
3050
|
function validateTaskResultingParameter(task, definedParameters, pipelineIdentification) {
|
|
2984
3051
|
if (definedParameters.has(task.resultingParameterName)) {
|
|
@@ -3000,7 +3067,7 @@ function validateTaskResultingParameter(task, definedParameters, pipelineIdentif
|
|
|
3000
3067
|
/**
|
|
3001
3068
|
* Validates joker parameters for one task.
|
|
3002
3069
|
*
|
|
3003
|
-
* @private internal utility of `
|
|
3070
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3004
3071
|
*/
|
|
3005
3072
|
function validateTaskJokers(task, pipelineIdentification) {
|
|
3006
3073
|
if (!hasTaskJokers(task)) {
|
|
@@ -3012,7 +3079,7 @@ function validateTaskJokers(task, pipelineIdentification) {
|
|
|
3012
3079
|
/**
|
|
3013
3080
|
* Checks whether one task declares any joker parameters.
|
|
3014
3081
|
*
|
|
3015
|
-
* @private internal utility of `
|
|
3082
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3016
3083
|
*/
|
|
3017
3084
|
function hasTaskJokers(task) {
|
|
3018
3085
|
return !!task.jokerParameterNames && task.jokerParameterNames.length > 0;
|
|
@@ -3020,7 +3087,7 @@ function hasTaskJokers(task) {
|
|
|
3020
3087
|
/**
|
|
3021
3088
|
* Validates that a task has the required supporting features when using jokers.
|
|
3022
3089
|
*
|
|
3023
|
-
* @private internal utility of `
|
|
3090
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3024
3091
|
*/
|
|
3025
3092
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
3026
3093
|
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
@@ -3035,7 +3102,7 @@ function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
|
3035
3102
|
/**
|
|
3036
3103
|
* Validates that every joker parameter is also listed among task dependencies.
|
|
3037
3104
|
*
|
|
3038
|
-
* @private internal utility of `
|
|
3105
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3039
3106
|
*/
|
|
3040
3107
|
function validateTaskJokerDependencies(task, pipelineIdentification) {
|
|
3041
3108
|
for (const joker of task.jokerParameterNames) {
|
|
@@ -3052,7 +3119,7 @@ function validateTaskJokerDependencies(task, pipelineIdentification) {
|
|
|
3052
3119
|
/**
|
|
3053
3120
|
* Validates all expectation bounds configured on one task.
|
|
3054
3121
|
*
|
|
3055
|
-
* @private internal utility of `
|
|
3122
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3056
3123
|
*/
|
|
3057
3124
|
function validateTaskExpectations(task, pipelineIdentification) {
|
|
3058
3125
|
if (!task.expectations) {
|
|
@@ -3067,7 +3134,7 @@ function validateTaskExpectations(task, pipelineIdentification) {
|
|
|
3067
3134
|
/**
|
|
3068
3135
|
* Validates the minimum and maximum expectation ordering for one unit.
|
|
3069
3136
|
*
|
|
3070
|
-
* @private internal utility of `
|
|
3137
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3071
3138
|
*/
|
|
3072
3139
|
function validateTaskExpectationRange(unit, min, max, pipelineIdentification) {
|
|
3073
3140
|
if (min === undefined || max === undefined || min <= max) {
|
|
@@ -3082,7 +3149,7 @@ function validateTaskExpectationRange(unit, min, max, pipelineIdentification) {
|
|
|
3082
3149
|
/**
|
|
3083
3150
|
* Validates the minimum expectation bound for one unit.
|
|
3084
3151
|
*
|
|
3085
|
-
* @private internal utility of `
|
|
3152
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3086
3153
|
*/
|
|
3087
3154
|
function validateTaskExpectationMin(unit, min, pipelineIdentification) {
|
|
3088
3155
|
if (min === undefined || min >= 0) {
|
|
@@ -3097,7 +3164,7 @@ function validateTaskExpectationMin(unit, min, pipelineIdentification) {
|
|
|
3097
3164
|
/**
|
|
3098
3165
|
* Validates the maximum expectation bound for one unit.
|
|
3099
3166
|
*
|
|
3100
|
-
* @private internal utility of `
|
|
3167
|
+
* @private internal utility of `validatePipelineTasks`
|
|
3101
3168
|
*/
|
|
3102
3169
|
function validateTaskExpectationMax(unit, max, pipelineIdentification) {
|
|
3103
3170
|
if (max === undefined || max > 0) {
|
|
@@ -3109,123 +3176,62 @@ function validateTaskExpectationMax(unit, max, pipelineIdentification) {
|
|
|
3109
3176
|
${block(pipelineIdentification)}
|
|
3110
3177
|
`));
|
|
3111
3178
|
}
|
|
3179
|
+
|
|
3112
3180
|
/**
|
|
3113
|
-
*
|
|
3114
|
-
*
|
|
3115
|
-
* @private internal utility of `validatePipeline`
|
|
3116
|
-
*/
|
|
3117
|
-
function createInitialDependencyResolutionState(pipeline) {
|
|
3118
|
-
return {
|
|
3119
|
-
resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
|
|
3120
|
-
unresolvedTasks: [...pipeline.tasks],
|
|
3121
|
-
};
|
|
3122
|
-
}
|
|
3123
|
-
/**
|
|
3124
|
-
* Checks whether dependency resolution still has tasks left to process.
|
|
3125
|
-
*
|
|
3126
|
-
* @private internal utility of `validatePipeline`
|
|
3127
|
-
*/
|
|
3128
|
-
function hasUnresolvedTasks({ unresolvedTasks }) {
|
|
3129
|
-
return unresolvedTasks.length > 0;
|
|
3130
|
-
}
|
|
3131
|
-
/**
|
|
3132
|
-
* Resolves the next batch of currently satisfiable tasks.
|
|
3181
|
+
* Validates PipelineJson if it is logically valid
|
|
3133
3182
|
*
|
|
3134
|
-
*
|
|
3135
|
-
|
|
3136
|
-
function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
|
|
3137
|
-
const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
|
|
3138
|
-
if (currentlyResolvedTasks.length === 0) {
|
|
3139
|
-
throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
|
|
3140
|
-
}
|
|
3141
|
-
return {
|
|
3142
|
-
resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
|
|
3143
|
-
unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
|
|
3144
|
-
};
|
|
3145
|
-
}
|
|
3146
|
-
/**
|
|
3147
|
-
* Collects the parameter names that are already resolvable before dependency traversal starts.
|
|
3183
|
+
* It checks:
|
|
3184
|
+
* - if it has correct parameters dependency
|
|
3148
3185
|
*
|
|
3149
|
-
*
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
let resolvedParameterNames = pipeline.parameters
|
|
3153
|
-
.filter(({ isInput }) => isInput)
|
|
3154
|
-
.map(({ name }) => name);
|
|
3155
|
-
for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
|
|
3156
|
-
resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
|
|
3157
|
-
}
|
|
3158
|
-
return resolvedParameterNames;
|
|
3159
|
-
}
|
|
3160
|
-
/**
|
|
3161
|
-
* Adds newly resolved task outputs to the resolved parameter list.
|
|
3186
|
+
* It does NOT check:
|
|
3187
|
+
* - if it is valid json
|
|
3188
|
+
* - if it is meaningful
|
|
3162
3189
|
*
|
|
3163
|
-
*
|
|
3164
|
-
*/
|
|
3165
|
-
function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
|
|
3166
|
-
return [
|
|
3167
|
-
...resolvedParameterNames,
|
|
3168
|
-
...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
|
|
3169
|
-
];
|
|
3170
|
-
}
|
|
3171
|
-
/**
|
|
3172
|
-
* Selects tasks whose dependencies are already resolved.
|
|
3190
|
+
* Note: [🔂] This function is idempotent.
|
|
3173
3191
|
*
|
|
3174
|
-
* @
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
|
|
3178
|
-
}
|
|
3179
|
-
/**
|
|
3180
|
-
* Creates the unexpected loop-limit error for dependency resolution.
|
|
3192
|
+
* @param pipeline valid or invalid PipelineJson
|
|
3193
|
+
* @returns the same pipeline if it is logically valid
|
|
3194
|
+
* @throws {PipelineLogicError} on logical error in the pipeline
|
|
3181
3195
|
*
|
|
3182
|
-
* @
|
|
3196
|
+
* @public exported from `@promptbook/core`
|
|
3183
3197
|
*/
|
|
3184
|
-
function
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3198
|
+
function validatePipeline(pipeline) {
|
|
3199
|
+
if (IS_PIPELINE_LOGIC_VALIDATED) {
|
|
3200
|
+
validatePipeline_InnerFunction(pipeline);
|
|
3201
|
+
}
|
|
3202
|
+
else {
|
|
3203
|
+
try {
|
|
3204
|
+
validatePipeline_InnerFunction(pipeline);
|
|
3205
|
+
}
|
|
3206
|
+
catch (error) {
|
|
3207
|
+
if (!(error instanceof PipelineLogicError)) {
|
|
3208
|
+
throw error;
|
|
3209
|
+
}
|
|
3210
|
+
console.error(spaceTrim$1((block) => `
|
|
3211
|
+
Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
|
|
3188
3212
|
|
|
3189
|
-
|
|
3190
|
-
|
|
3213
|
+
${block(error.message)}
|
|
3214
|
+
`));
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
return pipeline;
|
|
3191
3218
|
}
|
|
3192
3219
|
/**
|
|
3193
|
-
*
|
|
3220
|
+
* Validates pipeline inner function.
|
|
3194
3221
|
*
|
|
3195
|
-
* @private internal
|
|
3222
|
+
* @private internal function for `validatePipeline`
|
|
3196
3223
|
*/
|
|
3197
|
-
function
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
${block(unresolvedTasks
|
|
3209
|
-
.map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
|
|
3210
|
-
.map((dependentParameterName) => `\`{${dependentParameterName}}\``)
|
|
3211
|
-
.join(' and ')}`)
|
|
3212
|
-
.join('\n'))}
|
|
3213
|
-
|
|
3214
|
-
**Resolved:**
|
|
3215
|
-
${block(resolvedParameterNames
|
|
3216
|
-
.filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
|
|
3217
|
-
.map((name) => `- Parameter \`{${name}}\``)
|
|
3218
|
-
.join('\n'))}
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
**Reserved (which are available):**
|
|
3222
|
-
${block(resolvedParameterNames
|
|
3223
|
-
.filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
|
|
3224
|
-
.map((name) => `- Parameter \`{${name}}\``)
|
|
3225
|
-
.join('\n'))}
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
`));
|
|
3224
|
+
function validatePipeline_InnerFunction(pipeline) {
|
|
3225
|
+
// TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
|
|
3226
|
+
const context = createPipelineValidationContext(pipeline);
|
|
3227
|
+
validatePipelineMetadata(context);
|
|
3228
|
+
validatePipelineCollectionsStructure(context);
|
|
3229
|
+
validatePipelineParameters(context);
|
|
3230
|
+
validatePipelineTasks(context);
|
|
3231
|
+
validatePipelineDependencyResolution(context);
|
|
3232
|
+
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
3233
|
+
// TODO: !!6 Implement this
|
|
3234
|
+
// pipeline.formfactorName
|
|
3229
3235
|
}
|
|
3230
3236
|
/**
|
|
3231
3237
|
* TODO: [🧞♀️] Do not allow joker + foreach
|
|
@@ -8891,63 +8897,59 @@ const $llmToolsRegister = new $Register('llm_execution_tools_constructors');
|
|
|
8891
8897
|
// TODO: [®] DRY Register logic
|
|
8892
8898
|
|
|
8893
8899
|
/**
|
|
8894
|
-
*
|
|
8895
|
-
*
|
|
8896
|
-
* Note: `$` is used to indicate that this interacts with the global scope
|
|
8897
|
-
*
|
|
8898
|
-
* @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
|
|
8900
|
+
* Path to the `.env` file which was used to configure LLM tools
|
|
8899
8901
|
*
|
|
8900
|
-
*
|
|
8902
|
+
* Note: `$` is used to indicate that this variable is changed by side effect in `$provideLlmToolsConfigurationFromEnv` through `$setUsedEnvFilename`
|
|
8901
8903
|
*/
|
|
8902
|
-
|
|
8903
|
-
// TODO: [®] DRY Register logic
|
|
8904
|
-
|
|
8904
|
+
let $usedEnvFilename = null;
|
|
8905
8905
|
/**
|
|
8906
|
-
*
|
|
8907
|
-
*
|
|
8908
|
-
* Note: This function is used to create a (error) message when there is no constructor for some LLM provider
|
|
8906
|
+
* Shared state for the `.env` file used to configure LLM tools.
|
|
8909
8907
|
*
|
|
8910
|
-
* @private internal
|
|
8908
|
+
* @private internal state of `$registeredLlmToolsMessage`
|
|
8911
8909
|
*/
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
const env = getAvailableEnvironmentVariables(isRunningInNode);
|
|
8927
|
-
const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
|
|
8928
|
-
return {
|
|
8929
|
-
env,
|
|
8930
|
-
llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
|
|
8931
|
-
usedEnvMessage: createUsedEnvMessage(),
|
|
8932
|
-
isRunningInNode,
|
|
8933
|
-
};
|
|
8934
|
-
}
|
|
8910
|
+
const USED_ENV_FILENAME = {
|
|
8911
|
+
set(filepath) {
|
|
8912
|
+
$usedEnvFilename = filepath;
|
|
8913
|
+
},
|
|
8914
|
+
createMessage() {
|
|
8915
|
+
return $usedEnvFilename === null
|
|
8916
|
+
? `Unknown \`.env\` file`
|
|
8917
|
+
: spaceTrim$1(`
|
|
8918
|
+
Used \`.env\` file:
|
|
8919
|
+
${$usedEnvFilename}
|
|
8920
|
+
`);
|
|
8921
|
+
},
|
|
8922
|
+
};
|
|
8923
|
+
|
|
8935
8924
|
/**
|
|
8936
8925
|
* Reads environment variables relevant for provider configuration.
|
|
8937
8926
|
*
|
|
8938
|
-
* @private
|
|
8927
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
8939
8928
|
*/
|
|
8940
|
-
function
|
|
8929
|
+
function getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode) {
|
|
8941
8930
|
if (isRunningInNode) {
|
|
8942
8931
|
return process.env;
|
|
8943
8932
|
// <- TODO: [⚛] Some DRY way how to get to `process.env` and pass it into functions - ACRY search for `env`
|
|
8944
8933
|
}
|
|
8945
8934
|
return {};
|
|
8946
8935
|
}
|
|
8936
|
+
|
|
8937
|
+
/**
|
|
8938
|
+
* Register for LLM tools metadata.
|
|
8939
|
+
*
|
|
8940
|
+
* Note: `$` is used to indicate that this interacts with the global scope
|
|
8941
|
+
*
|
|
8942
|
+
* @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
|
|
8943
|
+
*
|
|
8944
|
+
* @public exported from `@promptbook/core`
|
|
8945
|
+
*/
|
|
8946
|
+
const $llmToolsMetadataRegister = new $Register('llm_tools_metadata');
|
|
8947
|
+
// TODO: [®] DRY Register logic
|
|
8948
|
+
|
|
8947
8949
|
/**
|
|
8948
8950
|
* Takes stable snapshots of both LLM provider registers.
|
|
8949
8951
|
*
|
|
8950
|
-
* @private
|
|
8952
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
8951
8953
|
*/
|
|
8952
8954
|
function getRegisteredLlmToolRegisters() {
|
|
8953
8955
|
return {
|
|
@@ -8955,62 +8957,30 @@ function getRegisteredLlmToolRegisters() {
|
|
|
8955
8957
|
registeredTools: $llmToolsRegister.list(),
|
|
8956
8958
|
};
|
|
8957
8959
|
}
|
|
8958
|
-
|
|
8959
|
-
* Lists provider entries enriched with installation and configuration state.
|
|
8960
|
-
*
|
|
8961
|
-
* @private internal function of `$registeredLlmToolsMessage`
|
|
8962
|
-
*/
|
|
8963
|
-
function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
|
|
8964
|
-
return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
|
|
8965
|
-
}
|
|
8966
|
-
/**
|
|
8967
|
-
* Merges provider entries from the metadata and constructor registers.
|
|
8968
|
-
*
|
|
8969
|
-
* @private internal function of `$registeredLlmToolsMessage`
|
|
8970
|
-
*/
|
|
8971
|
-
function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
|
|
8972
|
-
const registeredLlmToolEntries = new Map();
|
|
8973
|
-
for (const { title, packageName, className, envVariables } of registeredMetadata) {
|
|
8974
|
-
addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
|
|
8975
|
-
}
|
|
8976
|
-
for (const { packageName, className } of registeredTools) {
|
|
8977
|
-
addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
|
|
8978
|
-
}
|
|
8979
|
-
return [...registeredLlmToolEntries.values()];
|
|
8980
|
-
}
|
|
8981
|
-
/**
|
|
8982
|
-
* Adds a provider entry only when the provider is not already present.
|
|
8983
|
-
*
|
|
8984
|
-
* @private internal function of `$registeredLlmToolsMessage`
|
|
8985
|
-
*/
|
|
8986
|
-
function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
|
|
8987
|
-
const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
|
|
8988
|
-
if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
|
|
8989
|
-
return;
|
|
8990
|
-
}
|
|
8991
|
-
registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
|
|
8992
|
-
}
|
|
8960
|
+
|
|
8993
8961
|
/**
|
|
8994
8962
|
* Creates a deduplication key for a provider entry.
|
|
8995
8963
|
*
|
|
8996
|
-
* @private
|
|
8964
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
8997
8965
|
*/
|
|
8998
8966
|
function createRegisteredLlmToolEntryKey({ packageName, className }) {
|
|
8999
8967
|
return `${packageName}::${className}`;
|
|
9000
8968
|
}
|
|
8969
|
+
|
|
9001
8970
|
/**
|
|
9002
8971
|
* Checks whether the given provider entry already exists in the target register list.
|
|
9003
8972
|
*
|
|
9004
|
-
* @private
|
|
8973
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9005
8974
|
*/
|
|
9006
8975
|
function hasRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
|
|
9007
8976
|
const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
|
|
9008
8977
|
return registeredLlmToolEntries.some((listedRegisteredLlmToolEntry) => createRegisteredLlmToolEntryKey(listedRegisteredLlmToolEntry) === registeredLlmToolEntryKey);
|
|
9009
8978
|
}
|
|
8979
|
+
|
|
9010
8980
|
/**
|
|
9011
8981
|
* Builds the runtime status for one provider entry.
|
|
9012
8982
|
*
|
|
9013
|
-
* @private
|
|
8983
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9014
8984
|
*/
|
|
9015
8985
|
function createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env, }) {
|
|
9016
8986
|
const availabilityStatus = createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools);
|
|
@@ -9024,7 +8994,7 @@ function createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetad
|
|
|
9024
8994
|
/**
|
|
9025
8995
|
* Resolves whether the provider has metadata and a registered constructor.
|
|
9026
8996
|
*
|
|
9027
|
-
* @private
|
|
8997
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9028
8998
|
*/
|
|
9029
8999
|
function createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, registeredMetadata, registeredTools) {
|
|
9030
9000
|
return {
|
|
@@ -9035,7 +9005,7 @@ function createRegisteredLlmToolAvailabilityStatus(registeredLlmToolEntry, regis
|
|
|
9035
9005
|
/**
|
|
9036
9006
|
* Resolves whether the provider has enough environment variables to be configured.
|
|
9037
9007
|
*
|
|
9038
|
-
* @private
|
|
9008
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9039
9009
|
*/
|
|
9040
9010
|
function createRegisteredLlmToolConfigurationStatus({ envVariables }, env) {
|
|
9041
9011
|
return {
|
|
@@ -9046,7 +9016,7 @@ function createRegisteredLlmToolConfigurationStatus({ envVariables }, env) {
|
|
|
9046
9016
|
/**
|
|
9047
9017
|
* Checks whether all required environment variables are present for a provider.
|
|
9048
9018
|
*
|
|
9049
|
-
* @private
|
|
9019
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9050
9020
|
*/
|
|
9051
9021
|
function isRegisteredLlmToolFullyConfigured(envVariables, env) {
|
|
9052
9022
|
if (envVariables === undefined || envVariables === null) {
|
|
@@ -9057,7 +9027,7 @@ function isRegisteredLlmToolFullyConfigured(envVariables, env) {
|
|
|
9057
9027
|
/**
|
|
9058
9028
|
* Checks whether at least one required environment variable is present for a provider.
|
|
9059
9029
|
*
|
|
9060
|
-
* @private
|
|
9030
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9061
9031
|
*/
|
|
9062
9032
|
function isRegisteredLlmToolPartiallyConfigured(envVariables, env) {
|
|
9063
9033
|
if (envVariables === undefined || envVariables === null) {
|
|
@@ -9065,109 +9035,128 @@ function isRegisteredLlmToolPartiallyConfigured(envVariables, env) {
|
|
|
9065
9035
|
}
|
|
9066
9036
|
return envVariables.some((envVariableName) => env[envVariableName] !== undefined);
|
|
9067
9037
|
}
|
|
9038
|
+
|
|
9068
9039
|
/**
|
|
9069
|
-
*
|
|
9040
|
+
* Merges provider entries from the metadata and constructor registers.
|
|
9070
9041
|
*
|
|
9071
|
-
* @private
|
|
9042
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9072
9043
|
*/
|
|
9073
|
-
function
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9044
|
+
function listRegisteredLlmToolEntries(registeredMetadata, registeredTools) {
|
|
9045
|
+
const registeredLlmToolEntries = new Map();
|
|
9046
|
+
for (const { title, packageName, className, envVariables } of registeredMetadata) {
|
|
9047
|
+
addRegisteredLlmToolEntry(registeredLlmToolEntries, { title, packageName, className, envVariables });
|
|
9048
|
+
}
|
|
9049
|
+
for (const { packageName, className } of registeredTools) {
|
|
9050
|
+
addRegisteredLlmToolEntry(registeredLlmToolEntries, { packageName, className });
|
|
9051
|
+
}
|
|
9052
|
+
return [...registeredLlmToolEntries.values()];
|
|
9079
9053
|
}
|
|
9080
9054
|
/**
|
|
9081
|
-
*
|
|
9055
|
+
* Adds a provider entry only when the provider is not already present.
|
|
9082
9056
|
*
|
|
9083
|
-
* @private
|
|
9057
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9084
9058
|
*/
|
|
9085
|
-
function
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
${block(renderRelevantEnvironmentVariables(env, llmToolStatuses))}
|
|
9092
|
-
|
|
9093
|
-
Available LLM providers are:
|
|
9094
|
-
${block(renderAvailableProviders(llmToolStatuses, env, isRunningInNode))}
|
|
9095
|
-
`);
|
|
9059
|
+
function addRegisteredLlmToolEntry(registeredLlmToolEntries, registeredLlmToolEntry) {
|
|
9060
|
+
const registeredLlmToolEntryKey = createRegisteredLlmToolEntryKey(registeredLlmToolEntry);
|
|
9061
|
+
if (registeredLlmToolEntries.has(registeredLlmToolEntryKey)) {
|
|
9062
|
+
return;
|
|
9063
|
+
}
|
|
9064
|
+
registeredLlmToolEntries.set(registeredLlmToolEntryKey, registeredLlmToolEntry);
|
|
9096
9065
|
}
|
|
9066
|
+
|
|
9097
9067
|
/**
|
|
9098
|
-
*
|
|
9068
|
+
* Lists provider entries enriched with installation and configuration state.
|
|
9099
9069
|
*
|
|
9100
|
-
* @private
|
|
9070
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9101
9071
|
*/
|
|
9102
|
-
function
|
|
9103
|
-
return
|
|
9104
|
-
.map((envVariableName) => `- \`${envVariableName}\``)
|
|
9105
|
-
.join('\n');
|
|
9072
|
+
function listRegisteredLlmToolStatuses({ registeredMetadata, registeredTools }, env) {
|
|
9073
|
+
return listRegisteredLlmToolEntries(registeredMetadata, registeredTools).map((registeredLlmToolEntry) => createRegisteredLlmToolStatus({ registeredLlmToolEntry, registeredMetadata, registeredTools, env }));
|
|
9106
9074
|
}
|
|
9075
|
+
|
|
9107
9076
|
/**
|
|
9108
|
-
*
|
|
9077
|
+
* Collects all state needed to render the provider summary.
|
|
9109
9078
|
*
|
|
9110
|
-
* @private
|
|
9079
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9111
9080
|
*/
|
|
9112
|
-
function
|
|
9113
|
-
|
|
9081
|
+
function createRegisteredLlmToolsMessageContext() {
|
|
9082
|
+
const isRunningInNode = $isRunningInNode();
|
|
9083
|
+
const env = getAvailableRegisteredLlmToolsEnvironmentVariables(isRunningInNode);
|
|
9084
|
+
const registeredLlmToolRegisters = getRegisteredLlmToolRegisters();
|
|
9085
|
+
return {
|
|
9086
|
+
env,
|
|
9087
|
+
llmToolStatuses: listRegisteredLlmToolStatuses(registeredLlmToolRegisters, env),
|
|
9088
|
+
usedEnvMessage: USED_ENV_FILENAME.createMessage(),
|
|
9089
|
+
isRunningInNode,
|
|
9090
|
+
};
|
|
9114
9091
|
}
|
|
9092
|
+
|
|
9115
9093
|
/**
|
|
9116
|
-
* Renders
|
|
9094
|
+
* Renders the fallback message for environments with no registered providers.
|
|
9117
9095
|
*
|
|
9118
|
-
* @private
|
|
9096
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9119
9097
|
*/
|
|
9120
|
-
function
|
|
9121
|
-
return
|
|
9122
|
-
|
|
9123
|
-
|
|
9098
|
+
function renderNoRegisteredLlmToolsMessage(usedEnvMessage) {
|
|
9099
|
+
return spaceTrim$1((block) => `
|
|
9100
|
+
No LLM providers are available.
|
|
9101
|
+
|
|
9102
|
+
${block(usedEnvMessage)}
|
|
9103
|
+
`);
|
|
9124
9104
|
}
|
|
9105
|
+
|
|
9125
9106
|
/**
|
|
9126
|
-
*
|
|
9107
|
+
* Creates the configuration-status sentence for one provider.
|
|
9127
9108
|
*
|
|
9128
|
-
* @private
|
|
9109
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9129
9110
|
*/
|
|
9130
|
-
function
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
return providerMessage;
|
|
9111
|
+
function createRegisteredLlmToolConfigurationStatusMessage({ envVariables, isFullyConfigured, isPartiallyConfigured }, env) {
|
|
9112
|
+
if (isFullyConfigured) {
|
|
9113
|
+
return `Configured`;
|
|
9134
9114
|
}
|
|
9135
|
-
|
|
9115
|
+
if (isPartiallyConfigured) {
|
|
9116
|
+
return createPartiallyConfiguredStatusMessage(envVariables, env);
|
|
9117
|
+
}
|
|
9118
|
+
if (envVariables !== null) {
|
|
9119
|
+
return createNotConfiguredStatusMessage(envVariables);
|
|
9120
|
+
}
|
|
9121
|
+
return `Not configured`;
|
|
9122
|
+
// <- Note: Can not be configured via environment variables
|
|
9136
9123
|
}
|
|
9137
9124
|
/**
|
|
9138
|
-
* Creates the
|
|
9125
|
+
* Creates the partial-configuration sentence including missing variables.
|
|
9139
9126
|
*
|
|
9140
|
-
* @private
|
|
9127
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9141
9128
|
*/
|
|
9142
|
-
function
|
|
9143
|
-
|
|
9144
|
-
const providerStatusMessages = createProviderStatusMessages(llmToolStatus, env);
|
|
9145
|
-
return spaceTrim$1(`
|
|
9146
|
-
${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
|
|
9147
|
-
${providerStatusMessages.join('; ')}
|
|
9148
|
-
`);
|
|
9129
|
+
function createPartiallyConfiguredStatusMessage(envVariables, env) {
|
|
9130
|
+
return `Partially confugured, missing ${listMissingEnvironmentVariables(envVariables, env).join(' + ')}`;
|
|
9149
9131
|
}
|
|
9150
9132
|
/**
|
|
9151
|
-
* Creates the
|
|
9133
|
+
* Creates the not-configured sentence including the expected environment variables.
|
|
9152
9134
|
*
|
|
9153
|
-
* @private
|
|
9135
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9154
9136
|
*/
|
|
9155
|
-
function
|
|
9156
|
-
return
|
|
9137
|
+
function createNotConfiguredStatusMessage(envVariables) {
|
|
9138
|
+
return `Not configured, to configure set env ${envVariables === null || envVariables === void 0 ? void 0 : envVariables.join(' + ')}`;
|
|
9157
9139
|
}
|
|
9140
|
+
/**
|
|
9141
|
+
* Lists environment variables that are required but currently missing.
|
|
9142
|
+
*
|
|
9143
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9144
|
+
*/
|
|
9145
|
+
function listMissingEnvironmentVariables(envVariables, env) {
|
|
9146
|
+
return (envVariables === null || envVariables === void 0 ? void 0 : envVariables.filter((envVariable) => env[envVariable] === undefined)) || [];
|
|
9147
|
+
}
|
|
9148
|
+
|
|
9158
9149
|
/**
|
|
9159
9150
|
* Creates the installation-status sentence for one provider.
|
|
9160
9151
|
*
|
|
9161
|
-
* @private
|
|
9152
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9162
9153
|
*/
|
|
9163
|
-
function
|
|
9164
|
-
const installationStatusKey =
|
|
9154
|
+
function createRegisteredLlmToolInstallationStatusMessage({ isMetadataAvailable, isInstalled, }) {
|
|
9155
|
+
const installationStatusKey = createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled);
|
|
9165
9156
|
switch (installationStatusKey) {
|
|
9166
9157
|
case 'missing-metadata-and-installation':
|
|
9167
|
-
// TODO: [�][�] Maybe do allow to do auto-install if package not registered and not found
|
|
9168
9158
|
return `Not installed and no metadata, looks like a unexpected behavior`;
|
|
9169
9159
|
case 'metadata-without-installation':
|
|
9170
|
-
// TODO: [�][�]
|
|
9171
9160
|
return `Not installed`;
|
|
9172
9161
|
case 'installation-without-metadata':
|
|
9173
9162
|
return `No metadata but installed, looks like a unexpected behavior`;
|
|
@@ -9180,9 +9169,9 @@ function createInstallationStatusMessage({ isMetadataAvailable, isInstalled, })
|
|
|
9180
9169
|
/**
|
|
9181
9170
|
* Creates a stable installation-state key from metadata and constructor availability.
|
|
9182
9171
|
*
|
|
9183
|
-
* @private
|
|
9172
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9184
9173
|
*/
|
|
9185
|
-
function
|
|
9174
|
+
function createRegisteredLlmToolInstallationStatusKey(isMetadataAvailable, isInstalled) {
|
|
9186
9175
|
if (!isMetadataAvailable && !isInstalled) {
|
|
9187
9176
|
return 'missing-metadata-and-installation';
|
|
9188
9177
|
}
|
|
@@ -9197,54 +9186,59 @@ function createInstallationStatusKey(isMetadataAvailable, isInstalled) {
|
|
|
9197
9186
|
}
|
|
9198
9187
|
return 'unknown';
|
|
9199
9188
|
}
|
|
9189
|
+
|
|
9200
9190
|
/**
|
|
9201
|
-
*
|
|
9191
|
+
* Renders all provider lines in the status summary.
|
|
9202
9192
|
*
|
|
9203
|
-
* @private
|
|
9193
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9204
9194
|
*/
|
|
9205
|
-
function
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
if (isPartiallyConfigured) {
|
|
9210
|
-
return createPartiallyConfiguredStatusMessage(envVariables, env);
|
|
9211
|
-
}
|
|
9212
|
-
if (envVariables !== null) {
|
|
9213
|
-
return createNotConfiguredStatusMessage(envVariables);
|
|
9214
|
-
}
|
|
9215
|
-
return `Not configured`;
|
|
9216
|
-
// <- Note: Can not be configured via environment variables
|
|
9195
|
+
function renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode) {
|
|
9196
|
+
return llmToolStatuses
|
|
9197
|
+
.map((llmToolStatus, index) => renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode))
|
|
9198
|
+
.join('\n');
|
|
9217
9199
|
}
|
|
9218
9200
|
/**
|
|
9219
|
-
*
|
|
9201
|
+
* Renders one provider line in the status summary.
|
|
9220
9202
|
*
|
|
9221
|
-
* @private
|
|
9203
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9222
9204
|
*/
|
|
9223
|
-
function
|
|
9224
|
-
|
|
9205
|
+
function renderAvailableRegisteredLlmTool(llmToolStatus, index, env, isRunningInNode) {
|
|
9206
|
+
const providerMessage = createAvailableRegisteredLlmToolMessage(llmToolStatus, index, env);
|
|
9207
|
+
if (!isRunningInNode) {
|
|
9208
|
+
return providerMessage;
|
|
9209
|
+
}
|
|
9210
|
+
return colorizeAvailableRegisteredLlmToolMessage(providerMessage, llmToolStatus);
|
|
9225
9211
|
}
|
|
9226
9212
|
/**
|
|
9227
|
-
* Creates the
|
|
9213
|
+
* Creates the plain-text provider line before optional colorization.
|
|
9228
9214
|
*
|
|
9229
|
-
* @private
|
|
9215
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9230
9216
|
*/
|
|
9231
|
-
function
|
|
9232
|
-
|
|
9217
|
+
function createAvailableRegisteredLlmToolMessage(llmToolStatus, index, env) {
|
|
9218
|
+
const { title, packageName, className } = llmToolStatus;
|
|
9219
|
+
const providerStatusMessages = createRegisteredLlmToolStatusMessages(llmToolStatus, env);
|
|
9220
|
+
return spaceTrim$1(`
|
|
9221
|
+
${index + 1}) **${title}** \`${className}\` from \`${packageName}\`
|
|
9222
|
+
${providerStatusMessages.join('; ')}
|
|
9223
|
+
`);
|
|
9233
9224
|
}
|
|
9234
9225
|
/**
|
|
9235
|
-
*
|
|
9226
|
+
* Creates the install and configuration fragments for one provider line.
|
|
9236
9227
|
*
|
|
9237
|
-
* @private
|
|
9228
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9238
9229
|
*/
|
|
9239
|
-
function
|
|
9240
|
-
return
|
|
9230
|
+
function createRegisteredLlmToolStatusMessages(llmToolStatus, env) {
|
|
9231
|
+
return [
|
|
9232
|
+
createRegisteredLlmToolInstallationStatusMessage(llmToolStatus),
|
|
9233
|
+
createRegisteredLlmToolConfigurationStatusMessage(llmToolStatus, env),
|
|
9234
|
+
];
|
|
9241
9235
|
}
|
|
9242
9236
|
/**
|
|
9243
9237
|
* Applies the same terminal coloring rules as the original summary renderer.
|
|
9244
9238
|
*
|
|
9245
|
-
* @private
|
|
9239
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9246
9240
|
*/
|
|
9247
|
-
function
|
|
9241
|
+
function colorizeAvailableRegisteredLlmToolMessage(providerMessage, { isInstalled, isFullyConfigured, isPartiallyConfigured }) {
|
|
9248
9242
|
if (isInstalled && isFullyConfigured) {
|
|
9249
9243
|
return colors.green(providerMessage);
|
|
9250
9244
|
}
|
|
@@ -9253,14 +9247,57 @@ function colorizeAvailableProviderMessage(providerMessage, { isInstalled, isFull
|
|
|
9253
9247
|
}
|
|
9254
9248
|
return colors.gray(providerMessage);
|
|
9255
9249
|
}
|
|
9250
|
+
|
|
9251
|
+
/**
|
|
9252
|
+
* Renders the list of environment variables used by at least one registered provider.
|
|
9253
|
+
*
|
|
9254
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9255
|
+
*/
|
|
9256
|
+
function renderRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses) {
|
|
9257
|
+
return listRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses)
|
|
9258
|
+
.map((envVariableName) => `- \`${envVariableName}\``)
|
|
9259
|
+
.join('\n');
|
|
9260
|
+
}
|
|
9256
9261
|
/**
|
|
9257
|
-
*
|
|
9262
|
+
* Lists environment variables that are both present and used by at least one provider.
|
|
9263
|
+
*
|
|
9264
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9265
|
+
*/
|
|
9266
|
+
function listRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses) {
|
|
9267
|
+
return Object.keys(env).filter((envVariableName) => llmToolStatuses.some(({ envVariables }) => envVariables === null || envVariables === void 0 ? void 0 : envVariables.includes(envVariableName)));
|
|
9268
|
+
}
|
|
9269
|
+
|
|
9270
|
+
/**
|
|
9271
|
+
* Renders the full provider status summary.
|
|
9258
9272
|
*
|
|
9259
|
-
* @private
|
|
9273
|
+
* @private function of `$registeredLlmToolsMessage`
|
|
9260
9274
|
*/
|
|
9261
|
-
function
|
|
9262
|
-
return
|
|
9263
|
-
|
|
9275
|
+
function renderRegisteredLlmToolsMessage({ env, llmToolStatuses, usedEnvMessage, isRunningInNode, }) {
|
|
9276
|
+
return spaceTrim$1((block) => `
|
|
9277
|
+
|
|
9278
|
+
${block(usedEnvMessage)}
|
|
9279
|
+
|
|
9280
|
+
Relevant environment variables:
|
|
9281
|
+
${block(renderRelevantRegisteredLlmToolsEnvironmentVariables(env, llmToolStatuses))}
|
|
9282
|
+
|
|
9283
|
+
Available LLM providers are:
|
|
9284
|
+
${block(renderAvailableRegisteredLlmTools(llmToolStatuses, env, isRunningInNode))}
|
|
9285
|
+
`);
|
|
9286
|
+
}
|
|
9287
|
+
|
|
9288
|
+
/**
|
|
9289
|
+
* Creates a message with all registered LLM tools
|
|
9290
|
+
*
|
|
9291
|
+
* Note: This function is used to create a (error) message when there is no constructor for some LLM provider
|
|
9292
|
+
*
|
|
9293
|
+
* @private internal function of `createLlmToolsFromConfiguration` and `$provideLlmToolsFromEnv`
|
|
9294
|
+
*/
|
|
9295
|
+
function $registeredLlmToolsMessage() {
|
|
9296
|
+
const registeredLlmToolsMessageContext = createRegisteredLlmToolsMessageContext();
|
|
9297
|
+
if (registeredLlmToolsMessageContext.llmToolStatuses.length === 0) {
|
|
9298
|
+
return renderNoRegisteredLlmToolsMessage(registeredLlmToolsMessageContext.usedEnvMessage);
|
|
9299
|
+
}
|
|
9300
|
+
return renderRegisteredLlmToolsMessage(registeredLlmToolsMessageContext);
|
|
9264
9301
|
}
|
|
9265
9302
|
// TODO: [®] DRY Register logic
|
|
9266
9303
|
// TODO: [🧠][⚛] Maybe pass env as argument
|
|
@@ -12896,7 +12933,7 @@ class MessageSuffixCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
12896
12933
|
* META commitment definition
|
|
12897
12934
|
*
|
|
12898
12935
|
* The META commitment handles all meta-information about the agent such as:
|
|
12899
|
-
* - META AVATAR: Sets the agent's built-in default avatar visual
|
|
12936
|
+
* - META AVATAR / META VISUAL: Sets the agent's built-in default avatar visual
|
|
12900
12937
|
* - META IMAGE: Sets the agent's avatar/profile image URL
|
|
12901
12938
|
* - META LINK: Provides profile/source links for the person the agent models
|
|
12902
12939
|
* - META DOMAIN: Sets the canonical custom domain/host of the agent
|
|
@@ -12911,7 +12948,7 @@ class MessageSuffixCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
12911
12948
|
* Example usage in agent source:
|
|
12912
12949
|
*
|
|
12913
12950
|
* ```book
|
|
12914
|
-
* META
|
|
12951
|
+
* META VISUAL pixel-art
|
|
12915
12952
|
* META IMAGE https://example.com/avatar.jpg
|
|
12916
12953
|
* META LINK https://twitter.com/username
|
|
12917
12954
|
* META DOMAIN my-agent.com
|
|
@@ -12951,7 +12988,7 @@ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
12951
12988
|
|
|
12952
12989
|
## Supported META types
|
|
12953
12990
|
|
|
12954
|
-
- **META AVATAR** - Sets the agent's built-in default avatar visual
|
|
12991
|
+
- **META AVATAR** / **META VISUAL** - Sets the agent's built-in default avatar visual
|
|
12955
12992
|
- **META IMAGE** - Sets the agent's avatar/profile image URL
|
|
12956
12993
|
- **META LINK** - Provides profile/source links for the person the agent models
|
|
12957
12994
|
- **META DOMAIN** - Sets the canonical custom domain/host of the agent
|
|
@@ -12975,7 +13012,7 @@ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
12975
13012
|
\`\`\`book
|
|
12976
13013
|
Professional Assistant
|
|
12977
13014
|
|
|
12978
|
-
META
|
|
13015
|
+
META VISUAL octopus3
|
|
12979
13016
|
META IMAGE https://example.com/professional-avatar.jpg
|
|
12980
13017
|
META TITLE Senior Business Consultant
|
|
12981
13018
|
META DESCRIPTION Specialized in strategic planning and project management
|
|
@@ -16146,452 +16183,13 @@ function formatAlphaHex$1(opacity) {
|
|
|
16146
16183
|
.padStart(2, '0');
|
|
16147
16184
|
}
|
|
16148
16185
|
|
|
16149
|
-
/* eslint-disable no-magic-numbers */
|
|
16150
|
-
/**
|
|
16151
|
-
* Light direction used by the organic 3D octopus shading.
|
|
16152
|
-
*
|
|
16153
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16154
|
-
*/
|
|
16155
|
-
const LIGHT_DIRECTION$3 = normalizeVector3({
|
|
16156
|
-
x: 0.48,
|
|
16157
|
-
y: -0.62,
|
|
16158
|
-
z: 0.94,
|
|
16159
|
-
});
|
|
16160
|
-
/**
|
|
16161
|
-
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
16162
|
-
*
|
|
16163
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16164
|
-
*/
|
|
16165
|
-
const octopus3dStableStateCache = new WeakMap();
|
|
16166
|
-
/**
|
|
16167
|
-
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
16168
|
-
*
|
|
16169
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16170
|
-
*/
|
|
16171
|
-
function getOctopus3dStableState(createRandom) {
|
|
16172
|
-
const cached = octopus3dStableStateCache.get(createRandom);
|
|
16173
|
-
if (cached !== undefined) {
|
|
16174
|
-
return cached;
|
|
16175
|
-
}
|
|
16176
|
-
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
16177
|
-
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
16178
|
-
const leftEyePhaseOffset = eyeRandom() * 0.6;
|
|
16179
|
-
const rightEyePhaseOffset = eyeRandom() * 0.6;
|
|
16180
|
-
const state = {
|
|
16181
|
-
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
16182
|
-
animationPhase: animationRandom() * Math.PI * 2,
|
|
16183
|
-
leftEyePhaseOffset,
|
|
16184
|
-
rightEyePhaseOffset,
|
|
16185
|
-
};
|
|
16186
|
-
octopus3dStableStateCache.set(createRandom, state);
|
|
16187
|
-
return state;
|
|
16188
|
-
}
|
|
16189
|
-
/**
|
|
16190
|
-
* Proper 3D Octopus visual built from projected organic meshes and tentacles.
|
|
16191
|
-
*
|
|
16192
|
-
* @private built-in avatar visual
|
|
16193
|
-
*/
|
|
16194
|
-
const octopus3dAvatarVisual = {
|
|
16195
|
-
id: 'octopus3d',
|
|
16196
|
-
title: 'Octopus 3D',
|
|
16197
|
-
description: 'Proper 3D octopus portrait with a turning silhouette, expressive eyes, and depth-sorted tentacles.',
|
|
16198
|
-
isAnimated: true,
|
|
16199
|
-
supportsPointerTracking: true,
|
|
16200
|
-
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
16201
|
-
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
|
|
16202
|
-
const sceneCenterX = size * 0.5;
|
|
16203
|
-
const sceneCenterY = size * 0.56;
|
|
16204
|
-
const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
|
|
16205
|
-
const mantleCenter = {
|
|
16206
|
-
x: interaction.bodyOffsetX * size * 0.042 + size * morphologyProfile.body.centerXJitterRatio * 0.65,
|
|
16207
|
-
y: -size * 0.09 + interaction.bodyOffsetY * size * 0.028 + bob,
|
|
16208
|
-
z: interaction.intensity * size * 0.012,
|
|
16209
|
-
};
|
|
16210
|
-
const underbodyCenter = {
|
|
16211
|
-
x: mantleCenter.x * 0.86,
|
|
16212
|
-
y: mantleCenter.y + size * 0.168,
|
|
16213
|
-
z: mantleCenter.z - size * 0.018,
|
|
16214
|
-
};
|
|
16215
|
-
const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
|
|
16216
|
-
const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
|
|
16217
|
-
const mantleRadiusZ = size *
|
|
16218
|
-
morphologyProfile.body.bodyRadiusRatio *
|
|
16219
|
-
(0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
|
|
16220
|
-
const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
|
|
16221
|
-
const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
|
|
16222
|
-
const underbodyRadiusZ = mantleRadiusZ * 0.78;
|
|
16223
|
-
const bodyYaw = -0.18 +
|
|
16224
|
-
Math.sin(timeMs / 2400 + animationPhase) * 0.05 +
|
|
16225
|
-
interaction.bodyOffsetX * 0.18 +
|
|
16226
|
-
interaction.gazeX * 0.22;
|
|
16227
|
-
const bodyPitch = -0.08 +
|
|
16228
|
-
Math.cos(timeMs / 2700 + animationPhase * 0.6) * 0.025 -
|
|
16229
|
-
interaction.bodyOffsetY * 0.08 -
|
|
16230
|
-
interaction.gazeY * 0.08;
|
|
16231
|
-
const headYaw = bodyYaw - 0.04 + interaction.gazeX * 0.56;
|
|
16232
|
-
const headPitch = bodyPitch - 0.02 - interaction.gazeY * 0.32;
|
|
16233
|
-
const mantlePatches = resolveVisibleEllipsoidPatches({
|
|
16234
|
-
center: mantleCenter,
|
|
16235
|
-
radiusX: mantleRadiusX,
|
|
16236
|
-
radiusY: mantleRadiusY,
|
|
16237
|
-
radiusZ: mantleRadiusZ,
|
|
16238
|
-
rotationX: headPitch,
|
|
16239
|
-
rotationY: headYaw,
|
|
16240
|
-
sceneCenterX,
|
|
16241
|
-
sceneCenterY,
|
|
16242
|
-
size,
|
|
16243
|
-
palette,
|
|
16244
|
-
verticalColorBias: 0,
|
|
16245
|
-
outlineColor: `${palette.highlight}7a`,
|
|
16246
|
-
});
|
|
16247
|
-
const underbodyPatches = resolveVisibleEllipsoidPatches({
|
|
16248
|
-
center: underbodyCenter,
|
|
16249
|
-
radiusX: underbodyRadiusX,
|
|
16250
|
-
radiusY: underbodyRadiusY,
|
|
16251
|
-
radiusZ: underbodyRadiusZ,
|
|
16252
|
-
rotationX: bodyPitch,
|
|
16253
|
-
rotationY: bodyYaw,
|
|
16254
|
-
sceneCenterX,
|
|
16255
|
-
sceneCenterY,
|
|
16256
|
-
size,
|
|
16257
|
-
palette,
|
|
16258
|
-
verticalColorBias: 0.18,
|
|
16259
|
-
outlineColor: `${palette.shadow}8f`,
|
|
16260
|
-
});
|
|
16261
|
-
const tentacleStrokes = createOctopusTentacleStrokes({
|
|
16262
|
-
createRandom,
|
|
16263
|
-
morphologyProfile,
|
|
16264
|
-
timeMs,
|
|
16265
|
-
size,
|
|
16266
|
-
center: underbodyCenter,
|
|
16267
|
-
radiusX: underbodyRadiusX,
|
|
16268
|
-
radiusY: underbodyRadiusY,
|
|
16269
|
-
radiusZ: underbodyRadiusZ,
|
|
16270
|
-
rotationX: bodyPitch,
|
|
16271
|
-
rotationY: bodyYaw,
|
|
16272
|
-
sceneCenterX,
|
|
16273
|
-
sceneCenterY,
|
|
16274
|
-
animationPhase,
|
|
16275
|
-
});
|
|
16276
|
-
const faceEyeSpacing = size * morphologyProfile.face.eyeSpacingRatio * 0.92;
|
|
16277
|
-
const faceEyeYOffset = size * morphologyProfile.face.eyeCenterYOffsetRatio - mantleRadiusY * 0.02;
|
|
16278
|
-
const faceEyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.82;
|
|
16279
|
-
const faceEyeRadiusY = faceEyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.96;
|
|
16280
|
-
const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio * 0.92;
|
|
16281
|
-
const mouthY = size * morphologyProfile.face.mouthYOffsetRatio + mantleRadiusY * 0.08;
|
|
16282
|
-
drawAvatarFrame(context, size, palette);
|
|
16283
|
-
drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
16284
|
-
drawOctopus3dShadow(context, size, palette, interaction, timeMs);
|
|
16285
|
-
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => !candidateTentacleStroke.isFrontFacing)) {
|
|
16286
|
-
drawTentacleStroke(context, tentacleStroke, palette);
|
|
16287
|
-
}
|
|
16288
|
-
for (const surfacePatch of [...mantlePatches, ...underbodyPatches].sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
16289
|
-
drawSurfacePatch(context, surfacePatch);
|
|
16290
|
-
}
|
|
16291
|
-
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
16292
|
-
drawTentacleStroke(context, tentacleStroke, palette);
|
|
16293
|
-
}
|
|
16294
|
-
drawProjectedOrganicEye(context, {
|
|
16295
|
-
x: -faceEyeSpacing,
|
|
16296
|
-
y: faceEyeYOffset,
|
|
16297
|
-
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
16298
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
16299
|
-
drawProjectedOrganicEye(context, {
|
|
16300
|
-
x: faceEyeSpacing,
|
|
16301
|
-
y: faceEyeYOffset,
|
|
16302
|
-
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
16303
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
16304
|
-
drawProjectedOrganicMouth(context, [
|
|
16305
|
-
{
|
|
16306
|
-
x: -mouthHalfWidth,
|
|
16307
|
-
y: mouthY,
|
|
16308
|
-
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
|
|
16309
|
-
},
|
|
16310
|
-
{
|
|
16311
|
-
x: size * morphologyProfile.face.mouthCenterOffsetRatio,
|
|
16312
|
-
y: mouthY +
|
|
16313
|
-
size * morphologyProfile.face.mouthCurveDepthRatio * 0.38 +
|
|
16314
|
-
Math.sin(timeMs / 760 + animationPhase) * size * 0.01 +
|
|
16315
|
-
interaction.gazeY * size * 0.01,
|
|
16316
|
-
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
|
|
16317
|
-
},
|
|
16318
|
-
{
|
|
16319
|
-
x: mouthHalfWidth,
|
|
16320
|
-
y: mouthY,
|
|
16321
|
-
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
|
|
16322
|
-
},
|
|
16323
|
-
], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
|
|
16324
|
-
},
|
|
16325
|
-
};
|
|
16326
|
-
/**
|
|
16327
|
-
* Draws the atmospheric underwater glow behind the octopus mesh.
|
|
16328
|
-
*
|
|
16329
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16330
|
-
*/
|
|
16331
|
-
function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
16332
|
-
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);
|
|
16333
|
-
glowGradient.addColorStop(0, `${palette.highlight}5c`);
|
|
16334
|
-
glowGradient.addColorStop(0.36, `${palette.accent}24`);
|
|
16335
|
-
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
16336
|
-
context.fillStyle = glowGradient;
|
|
16337
|
-
context.fillRect(0, 0, size, size);
|
|
16338
|
-
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);
|
|
16339
|
-
lowerGradient.addColorStop(0, `${palette.secondary}1d`);
|
|
16340
|
-
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
16341
|
-
context.fillStyle = lowerGradient;
|
|
16342
|
-
context.fillRect(0, 0, size, size);
|
|
16343
|
-
}
|
|
16344
|
-
/**
|
|
16345
|
-
* Draws the soft ground shadow below the octopus.
|
|
16346
|
-
*
|
|
16347
|
-
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
16348
|
-
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
16349
|
-
*
|
|
16350
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16351
|
-
*/
|
|
16352
|
-
function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
|
|
16353
|
-
const cx = size * 0.5 + interaction.gazeX * size * 0.04;
|
|
16354
|
-
const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
|
|
16355
|
-
const rx = size * (0.18 + interaction.intensity * 0.02);
|
|
16356
|
-
const ry = size * 0.06;
|
|
16357
|
-
context.save();
|
|
16358
|
-
context.translate(cx, cy);
|
|
16359
|
-
context.scale(1, ry / rx);
|
|
16360
|
-
const blurRadius = rx * 1.4;
|
|
16361
|
-
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
16362
|
-
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
16363
|
-
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
16364
|
-
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
16365
|
-
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
16366
|
-
context.fillStyle = shadowGradient;
|
|
16367
|
-
context.beginPath();
|
|
16368
|
-
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
16369
|
-
context.fill();
|
|
16370
|
-
context.restore();
|
|
16371
|
-
}
|
|
16372
|
-
/**
|
|
16373
|
-
* Resolves visible projected patches for one rotated ellipsoid mesh.
|
|
16374
|
-
*
|
|
16375
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16376
|
-
*/
|
|
16377
|
-
function resolveVisibleEllipsoidPatches(options) {
|
|
16378
|
-
const { center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, verticalColorBias, outlineColor, } = options;
|
|
16379
|
-
const latitudePatchCount = 10;
|
|
16380
|
-
const longitudePatchCount = 18;
|
|
16381
|
-
const surfacePatches = [];
|
|
16382
|
-
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
16383
|
-
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
16384
|
-
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
16385
|
-
const verticalProgress = (latitudeIndex + 0.5) / latitudePatchCount;
|
|
16386
|
-
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
16387
|
-
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
16388
|
-
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
16389
|
-
const localCorners = [
|
|
16390
|
-
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, startLongitude),
|
|
16391
|
-
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, endLongitude),
|
|
16392
|
-
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, endLongitude),
|
|
16393
|
-
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, startLongitude),
|
|
16394
|
-
];
|
|
16395
|
-
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
16396
|
-
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
16397
|
-
if (surfaceNormal.z <= 0.01) {
|
|
16398
|
-
continue;
|
|
16399
|
-
}
|
|
16400
|
-
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
16401
|
-
surfacePatches.push({
|
|
16402
|
-
corners: projectedCorners,
|
|
16403
|
-
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
16404
|
-
transformedCorners.length,
|
|
16405
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$3), -1, 1),
|
|
16406
|
-
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
16407
|
-
outlineColor,
|
|
16408
|
-
});
|
|
16409
|
-
}
|
|
16410
|
-
}
|
|
16411
|
-
return surfacePatches;
|
|
16412
|
-
}
|
|
16413
|
-
/**
|
|
16414
|
-
* Samples one point on an ellipsoid aligned to the local axes.
|
|
16415
|
-
*
|
|
16416
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16417
|
-
*/
|
|
16418
|
-
function sampleEllipsoidPoint(radiusX, radiusY, radiusZ, latitude, longitude) {
|
|
16419
|
-
const cosineLatitude = Math.cos(latitude);
|
|
16420
|
-
return {
|
|
16421
|
-
x: Math.sin(longitude) * cosineLatitude * radiusX,
|
|
16422
|
-
y: Math.sin(latitude) * radiusY,
|
|
16423
|
-
z: Math.cos(longitude) * cosineLatitude * radiusZ,
|
|
16424
|
-
};
|
|
16425
|
-
}
|
|
16426
|
-
/**
|
|
16427
|
-
* Resolves one base fill tone for a surface patch across the octopus body.
|
|
16428
|
-
*
|
|
16429
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16430
|
-
*/
|
|
16431
|
-
function resolveSurfacePatchFillStyle(palette, verticalProgress) {
|
|
16432
|
-
const clampedVerticalProgress = clampNumber$1(verticalProgress, 0, 1);
|
|
16433
|
-
if (clampedVerticalProgress < 0.2) {
|
|
16434
|
-
return palette.highlight;
|
|
16435
|
-
}
|
|
16436
|
-
if (clampedVerticalProgress < 0.45) {
|
|
16437
|
-
return palette.secondary;
|
|
16438
|
-
}
|
|
16439
|
-
if (clampedVerticalProgress < 0.8) {
|
|
16440
|
-
return palette.primary;
|
|
16441
|
-
}
|
|
16442
|
-
return `${palette.shadow}f2`;
|
|
16443
|
-
}
|
|
16444
|
-
/**
|
|
16445
|
-
* Draws one projected mesh patch with organic shading.
|
|
16446
|
-
*
|
|
16447
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16448
|
-
*/
|
|
16449
|
-
function drawSurfacePatch(context, surfacePatch) {
|
|
16450
|
-
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
16451
|
-
if (surfacePatch.lightIntensity > 0) {
|
|
16452
|
-
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.15 * surfacePatch.lightIntensity})`);
|
|
16453
|
-
}
|
|
16454
|
-
else if (surfacePatch.lightIntensity < 0) {
|
|
16455
|
-
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
16456
|
-
}
|
|
16457
|
-
context.save();
|
|
16458
|
-
context.beginPath();
|
|
16459
|
-
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
16460
|
-
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
16461
|
-
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
16462
|
-
}
|
|
16463
|
-
context.closePath();
|
|
16464
|
-
context.strokeStyle = surfacePatch.outlineColor;
|
|
16465
|
-
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0044);
|
|
16466
|
-
context.lineJoin = 'round';
|
|
16467
|
-
context.stroke();
|
|
16468
|
-
context.restore();
|
|
16469
|
-
}
|
|
16470
|
-
/**
|
|
16471
|
-
* Creates the projected 3D tentacle strokes orbiting around the lower octopus body.
|
|
16472
|
-
*
|
|
16473
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16474
|
-
*/
|
|
16475
|
-
function createOctopusTentacleStrokes(options) {
|
|
16476
|
-
const { createRandom, morphologyProfile, timeMs, size, center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, animationPhase, } = options;
|
|
16477
|
-
return Array.from({ length: morphologyProfile.tentacles.count }, (_, tentacleIndex) => {
|
|
16478
|
-
const tentacleRandom = createRandom(`octopus3d-tentacle-${tentacleIndex}`);
|
|
16479
|
-
const spreadProgress = morphologyProfile.tentacles.count === 1 ? 0.5 : tentacleIndex / (morphologyProfile.tentacles.count - 1);
|
|
16480
|
-
const orbitAngle = -Math.PI * 0.92 + spreadProgress * Math.PI * 1.84 + (tentacleRandom() - 0.5) * 0.16;
|
|
16481
|
-
const flowLength = size * (0.19 + morphologyProfile.tentacles.flowLengthScale * 0.075 + tentacleRandom() * 0.018);
|
|
16482
|
-
const lateralReach = size *
|
|
16483
|
-
(0.08 + morphologyProfile.tentacles.lateralReachScale * 0.05 + Math.abs(Math.sin(orbitAngle)) * 0.018);
|
|
16484
|
-
const depthReach = size * (0.028 + morphologyProfile.tentacles.tipReachScale * 0.032);
|
|
16485
|
-
const sway = Math.sin(timeMs / (760 + tentacleIndex * 36) + animationPhase + tentacleRandom() * Math.PI * 2);
|
|
16486
|
-
const anchorPoint = {
|
|
16487
|
-
x: Math.sin(orbitAngle) * radiusX * (0.84 + tentacleRandom() * 0.08),
|
|
16488
|
-
y: radiusY * (0.22 + tentacleRandom() * 0.18),
|
|
16489
|
-
z: Math.cos(orbitAngle) * radiusZ * (0.72 + tentacleRandom() * 0.12),
|
|
16490
|
-
};
|
|
16491
|
-
const controlPointOne = {
|
|
16492
|
-
x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * 0.44,
|
|
16493
|
-
y: anchorPoint.y + flowLength * 0.26,
|
|
16494
|
-
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
|
|
16495
|
-
};
|
|
16496
|
-
const controlPointTwo = {
|
|
16497
|
-
x: anchorPoint.x +
|
|
16498
|
-
Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
|
|
16499
|
-
y: anchorPoint.y + flowLength * 0.66,
|
|
16500
|
-
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
|
|
16501
|
-
};
|
|
16502
|
-
const endPoint = {
|
|
16503
|
-
x: anchorPoint.x +
|
|
16504
|
-
Math.sin(orbitAngle) * lateralReach * (1.02 + morphologyProfile.tentacles.tipWidthScale * 0.12) +
|
|
16505
|
-
sway * size * 0.028,
|
|
16506
|
-
y: anchorPoint.y + flowLength,
|
|
16507
|
-
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach + sway * size * 0.016,
|
|
16508
|
-
};
|
|
16509
|
-
const scenePoints = Array.from({ length: 12 }, (_, sampleIndex) => transformScenePoint(sampleCubicBezierPoint3D(anchorPoint, controlPointOne, controlPointTwo, endPoint, sampleIndex / 11), center, rotationX, rotationY));
|
|
16510
|
-
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
16511
|
-
const averageDepth = scenePoints.reduce((depthSum, scenePoint) => depthSum + scenePoint.z, 0) / scenePoints.length;
|
|
16512
|
-
return {
|
|
16513
|
-
projectedPoints,
|
|
16514
|
-
averageDepth,
|
|
16515
|
-
isFrontFacing: averageDepth >= center.z - size * 0.006,
|
|
16516
|
-
baseWidth: size *
|
|
16517
|
-
(0.019 +
|
|
16518
|
-
morphologyProfile.tentacles.baseWidthScale * 0.007 +
|
|
16519
|
-
tentacleRandom() * 0.003 +
|
|
16520
|
-
Math.abs(Math.sin(orbitAngle)) * 0.002),
|
|
16521
|
-
tipWidth: size * (0.0046 + morphologyProfile.tentacles.tipWidthScale * 0.0018),
|
|
16522
|
-
colorBias: tentacleRandom(),
|
|
16523
|
-
};
|
|
16524
|
-
});
|
|
16525
|
-
}
|
|
16526
|
-
/**
|
|
16527
|
-
* Samples one point on a cubic Bezier curve in 3D.
|
|
16528
|
-
*
|
|
16529
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16530
|
-
*/
|
|
16531
|
-
function sampleCubicBezierPoint3D(startPoint, controlPointOne, controlPointTwo, endPoint, progress) {
|
|
16532
|
-
const inverseProgress = 1 - progress;
|
|
16533
|
-
return {
|
|
16534
|
-
x: inverseProgress * inverseProgress * inverseProgress * startPoint.x +
|
|
16535
|
-
3 * inverseProgress * inverseProgress * progress * controlPointOne.x +
|
|
16536
|
-
3 * inverseProgress * progress * progress * controlPointTwo.x +
|
|
16537
|
-
progress * progress * progress * endPoint.x,
|
|
16538
|
-
y: inverseProgress * inverseProgress * inverseProgress * startPoint.y +
|
|
16539
|
-
3 * inverseProgress * inverseProgress * progress * controlPointOne.y +
|
|
16540
|
-
3 * inverseProgress * progress * progress * controlPointTwo.y +
|
|
16541
|
-
progress * progress * progress * endPoint.y,
|
|
16542
|
-
z: inverseProgress * inverseProgress * inverseProgress * startPoint.z +
|
|
16543
|
-
3 * inverseProgress * inverseProgress * progress * controlPointOne.z +
|
|
16544
|
-
3 * inverseProgress * progress * progress * controlPointTwo.z +
|
|
16545
|
-
progress * progress * progress * endPoint.z,
|
|
16546
|
-
};
|
|
16547
|
-
}
|
|
16548
|
-
/**
|
|
16549
|
-
* Draws one projected tentacle stroke with a slim highlight ridge.
|
|
16550
|
-
*
|
|
16551
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16552
|
-
*/
|
|
16553
|
-
function drawTentacleStroke(context, tentacleStroke, palette) {
|
|
16554
|
-
const projectedSegments = tentacleStroke.projectedPoints.length - 1;
|
|
16555
|
-
for (let segmentIndex = 0; segmentIndex < projectedSegments; segmentIndex++) {
|
|
16556
|
-
const startPoint = tentacleStroke.projectedPoints[segmentIndex];
|
|
16557
|
-
const endPoint = tentacleStroke.projectedPoints[segmentIndex + 1];
|
|
16558
|
-
const progress = segmentIndex / projectedSegments;
|
|
16559
|
-
const width = tentacleStroke.baseWidth + (tentacleStroke.tipWidth - tentacleStroke.baseWidth) * progress;
|
|
16560
|
-
context.beginPath();
|
|
16561
|
-
context.moveTo(startPoint.x, startPoint.y);
|
|
16562
|
-
context.lineTo(endPoint.x, endPoint.y);
|
|
16563
|
-
context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
|
|
16564
|
-
context.lineWidth = width;
|
|
16565
|
-
context.lineCap = 'round';
|
|
16566
|
-
context.stroke();
|
|
16567
|
-
context.beginPath();
|
|
16568
|
-
context.moveTo(startPoint.x, startPoint.y);
|
|
16569
|
-
context.lineTo(endPoint.x, endPoint.y);
|
|
16570
|
-
context.strokeStyle = tentacleStroke.isFrontFacing ? `${palette.highlight}80` : `${palette.highlight}40`;
|
|
16571
|
-
context.lineWidth = Math.max(1, width * 0.34);
|
|
16572
|
-
context.lineCap = 'round';
|
|
16573
|
-
context.stroke();
|
|
16574
|
-
}
|
|
16575
|
-
}
|
|
16576
|
-
/**
|
|
16577
|
-
* Resolves the front surface depth on an ellipsoid for one local face point.
|
|
16578
|
-
*
|
|
16579
|
-
* @private helper of `octopus3dAvatarVisual`
|
|
16580
|
-
*/
|
|
16581
|
-
function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
|
|
16582
|
-
const normalizedX = x / radiusX;
|
|
16583
|
-
const normalizedY = y / radiusY;
|
|
16584
|
-
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
16585
|
-
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
16586
|
-
}
|
|
16587
|
-
|
|
16588
16186
|
/* eslint-disable no-magic-numbers */
|
|
16589
16187
|
/**
|
|
16590
16188
|
* Light direction used by the single-mesh octopus shading.
|
|
16591
16189
|
*
|
|
16592
16190
|
* @private helper of `octopus3d2AvatarVisual`
|
|
16593
16191
|
*/
|
|
16594
|
-
const LIGHT_DIRECTION$
|
|
16192
|
+
const LIGHT_DIRECTION$3 = normalizeVector3({
|
|
16595
16193
|
x: 0.38,
|
|
16596
16194
|
y: -0.6,
|
|
16597
16195
|
z: 0.98,
|
|
@@ -16830,7 +16428,7 @@ function resolveVisibleBlobbyOctopusPatches(options) {
|
|
|
16830
16428
|
transformedCorners[2].z +
|
|
16831
16429
|
transformedCorners[3].z) /
|
|
16832
16430
|
4,
|
|
16833
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$
|
|
16431
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$3), -1, 1),
|
|
16834
16432
|
fillStyle: resolveBlobbySurfacePatchFillStyle$1(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
16835
16433
|
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
16836
16434
|
});
|
|
@@ -16945,7 +16543,7 @@ function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
|
16945
16543
|
*
|
|
16946
16544
|
* @private helper of `octopus3d3AvatarVisual`
|
|
16947
16545
|
*/
|
|
16948
|
-
const LIGHT_DIRECTION$
|
|
16546
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
16949
16547
|
x: 0.34,
|
|
16950
16548
|
y: -0.62,
|
|
16951
16549
|
z: 1,
|
|
@@ -17252,7 +16850,7 @@ function resolveVisibleContinuousOctopusPatches(options) {
|
|
|
17252
16850
|
transformedCorners[2].z +
|
|
17253
16851
|
transformedCorners[3].z) /
|
|
17254
16852
|
4,
|
|
17255
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$
|
|
16853
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
17256
16854
|
fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, cachedCosByPatchCenterLongitude[longitudeIndex], cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex].core, cachedLobeWavesByPatchCenterLongitude[longitudeIndex]),
|
|
17257
16855
|
outlineColor: verticalProgress < 0.54 ? `${palette.highlight}69` : `${palette.shadow}78`,
|
|
17258
16856
|
});
|
|
@@ -17567,7 +17165,7 @@ function smoothStep$1(edgeStart, edgeEnd, value) {
|
|
|
17567
17165
|
*
|
|
17568
17166
|
* @private helper of `octopus3d4AvatarVisual`
|
|
17569
17167
|
*/
|
|
17570
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
17168
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
17571
17169
|
x: 0.32,
|
|
17572
17170
|
y: -0.66,
|
|
17573
17171
|
z: 1,
|
|
@@ -17913,7 +17511,7 @@ function resolveVisibleBlobbyContinuousPatches(options) {
|
|
|
17913
17511
|
projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
|
|
17914
17512
|
projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
|
|
17915
17513
|
];
|
|
17916
|
-
const lightIntensity = clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1);
|
|
17514
|
+
const lightIntensity = clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1);
|
|
17917
17515
|
const rimLightIntensity = Math.pow(clampNumber$1(dotProduct3D(surfaceNormal, RIM_LIGHT_DIRECTION), 0, 1), 2.6);
|
|
17918
17516
|
surfacePatches.push({
|
|
17919
17517
|
corners: projectedCorners,
|
|
@@ -18312,6 +17910,445 @@ function formatAlphaHex(opacity) {
|
|
|
18312
17910
|
.padStart(2, '0');
|
|
18313
17911
|
}
|
|
18314
17912
|
|
|
17913
|
+
/* eslint-disable no-magic-numbers */
|
|
17914
|
+
/**
|
|
17915
|
+
* Light direction used by the organic 3D octopus shading.
|
|
17916
|
+
*
|
|
17917
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
17918
|
+
*/
|
|
17919
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
17920
|
+
x: 0.48,
|
|
17921
|
+
y: -0.62,
|
|
17922
|
+
z: 0.94,
|
|
17923
|
+
});
|
|
17924
|
+
/**
|
|
17925
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
17926
|
+
*
|
|
17927
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
17928
|
+
*/
|
|
17929
|
+
const octopus3dStableStateCache = new WeakMap();
|
|
17930
|
+
/**
|
|
17931
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
17932
|
+
*
|
|
17933
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
17934
|
+
*/
|
|
17935
|
+
function getOctopus3dStableState(createRandom) {
|
|
17936
|
+
const cached = octopus3dStableStateCache.get(createRandom);
|
|
17937
|
+
if (cached !== undefined) {
|
|
17938
|
+
return cached;
|
|
17939
|
+
}
|
|
17940
|
+
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
17941
|
+
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
17942
|
+
const leftEyePhaseOffset = eyeRandom() * 0.6;
|
|
17943
|
+
const rightEyePhaseOffset = eyeRandom() * 0.6;
|
|
17944
|
+
const state = {
|
|
17945
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
17946
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
17947
|
+
leftEyePhaseOffset,
|
|
17948
|
+
rightEyePhaseOffset,
|
|
17949
|
+
};
|
|
17950
|
+
octopus3dStableStateCache.set(createRandom, state);
|
|
17951
|
+
return state;
|
|
17952
|
+
}
|
|
17953
|
+
/**
|
|
17954
|
+
* Proper 3D Octopus visual built from projected organic meshes and tentacles.
|
|
17955
|
+
*
|
|
17956
|
+
* @private built-in avatar visual
|
|
17957
|
+
*/
|
|
17958
|
+
const octopus3dAvatarVisual = {
|
|
17959
|
+
id: 'octopus3d',
|
|
17960
|
+
title: 'Octopus 3D',
|
|
17961
|
+
description: 'Proper 3D octopus portrait with a turning silhouette, expressive eyes, and depth-sorted tentacles.',
|
|
17962
|
+
isAnimated: true,
|
|
17963
|
+
supportsPointerTracking: true,
|
|
17964
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
17965
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
|
|
17966
|
+
const sceneCenterX = size * 0.5;
|
|
17967
|
+
const sceneCenterY = size * 0.56;
|
|
17968
|
+
const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
|
|
17969
|
+
const mantleCenter = {
|
|
17970
|
+
x: interaction.bodyOffsetX * size * 0.042 + size * morphologyProfile.body.centerXJitterRatio * 0.65,
|
|
17971
|
+
y: -size * 0.09 + interaction.bodyOffsetY * size * 0.028 + bob,
|
|
17972
|
+
z: interaction.intensity * size * 0.012,
|
|
17973
|
+
};
|
|
17974
|
+
const underbodyCenter = {
|
|
17975
|
+
x: mantleCenter.x * 0.86,
|
|
17976
|
+
y: mantleCenter.y + size * 0.168,
|
|
17977
|
+
z: mantleCenter.z - size * 0.018,
|
|
17978
|
+
};
|
|
17979
|
+
const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
|
|
17980
|
+
const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
|
|
17981
|
+
const mantleRadiusZ = size *
|
|
17982
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
17983
|
+
(0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
|
|
17984
|
+
const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
|
|
17985
|
+
const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
|
|
17986
|
+
const underbodyRadiusZ = mantleRadiusZ * 0.78;
|
|
17987
|
+
const bodyYaw = -0.18 +
|
|
17988
|
+
Math.sin(timeMs / 2400 + animationPhase) * 0.05 +
|
|
17989
|
+
interaction.bodyOffsetX * 0.18 +
|
|
17990
|
+
interaction.gazeX * 0.22;
|
|
17991
|
+
const bodyPitch = -0.08 +
|
|
17992
|
+
Math.cos(timeMs / 2700 + animationPhase * 0.6) * 0.025 -
|
|
17993
|
+
interaction.bodyOffsetY * 0.08 -
|
|
17994
|
+
interaction.gazeY * 0.08;
|
|
17995
|
+
const headYaw = bodyYaw - 0.04 + interaction.gazeX * 0.56;
|
|
17996
|
+
const headPitch = bodyPitch - 0.02 - interaction.gazeY * 0.32;
|
|
17997
|
+
const mantlePatches = resolveVisibleEllipsoidPatches({
|
|
17998
|
+
center: mantleCenter,
|
|
17999
|
+
radiusX: mantleRadiusX,
|
|
18000
|
+
radiusY: mantleRadiusY,
|
|
18001
|
+
radiusZ: mantleRadiusZ,
|
|
18002
|
+
rotationX: headPitch,
|
|
18003
|
+
rotationY: headYaw,
|
|
18004
|
+
sceneCenterX,
|
|
18005
|
+
sceneCenterY,
|
|
18006
|
+
size,
|
|
18007
|
+
palette,
|
|
18008
|
+
verticalColorBias: 0,
|
|
18009
|
+
outlineColor: `${palette.highlight}7a`,
|
|
18010
|
+
});
|
|
18011
|
+
const underbodyPatches = resolveVisibleEllipsoidPatches({
|
|
18012
|
+
center: underbodyCenter,
|
|
18013
|
+
radiusX: underbodyRadiusX,
|
|
18014
|
+
radiusY: underbodyRadiusY,
|
|
18015
|
+
radiusZ: underbodyRadiusZ,
|
|
18016
|
+
rotationX: bodyPitch,
|
|
18017
|
+
rotationY: bodyYaw,
|
|
18018
|
+
sceneCenterX,
|
|
18019
|
+
sceneCenterY,
|
|
18020
|
+
size,
|
|
18021
|
+
palette,
|
|
18022
|
+
verticalColorBias: 0.18,
|
|
18023
|
+
outlineColor: `${palette.shadow}8f`,
|
|
18024
|
+
});
|
|
18025
|
+
const tentacleStrokes = createOctopusTentacleStrokes({
|
|
18026
|
+
createRandom,
|
|
18027
|
+
morphologyProfile,
|
|
18028
|
+
timeMs,
|
|
18029
|
+
size,
|
|
18030
|
+
center: underbodyCenter,
|
|
18031
|
+
radiusX: underbodyRadiusX,
|
|
18032
|
+
radiusY: underbodyRadiusY,
|
|
18033
|
+
radiusZ: underbodyRadiusZ,
|
|
18034
|
+
rotationX: bodyPitch,
|
|
18035
|
+
rotationY: bodyYaw,
|
|
18036
|
+
sceneCenterX,
|
|
18037
|
+
sceneCenterY,
|
|
18038
|
+
animationPhase,
|
|
18039
|
+
});
|
|
18040
|
+
const faceEyeSpacing = size * morphologyProfile.face.eyeSpacingRatio * 0.92;
|
|
18041
|
+
const faceEyeYOffset = size * morphologyProfile.face.eyeCenterYOffsetRatio - mantleRadiusY * 0.02;
|
|
18042
|
+
const faceEyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.82;
|
|
18043
|
+
const faceEyeRadiusY = faceEyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.96;
|
|
18044
|
+
const mouthHalfWidth = size * morphologyProfile.face.mouthWidthRatio * 0.92;
|
|
18045
|
+
const mouthY = size * morphologyProfile.face.mouthYOffsetRatio + mantleRadiusY * 0.08;
|
|
18046
|
+
drawAvatarFrame(context, size, palette);
|
|
18047
|
+
drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
18048
|
+
drawOctopus3dShadow(context, size, palette, interaction, timeMs);
|
|
18049
|
+
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => !candidateTentacleStroke.isFrontFacing)) {
|
|
18050
|
+
drawTentacleStroke(context, tentacleStroke, palette);
|
|
18051
|
+
}
|
|
18052
|
+
for (const surfacePatch of [...mantlePatches, ...underbodyPatches].sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
18053
|
+
drawSurfacePatch(context, surfacePatch);
|
|
18054
|
+
}
|
|
18055
|
+
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
18056
|
+
drawTentacleStroke(context, tentacleStroke, palette);
|
|
18057
|
+
}
|
|
18058
|
+
drawProjectedOrganicEye(context, {
|
|
18059
|
+
x: -faceEyeSpacing,
|
|
18060
|
+
y: faceEyeYOffset,
|
|
18061
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
18062
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
18063
|
+
drawProjectedOrganicEye(context, {
|
|
18064
|
+
x: faceEyeSpacing,
|
|
18065
|
+
y: faceEyeYOffset,
|
|
18066
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
18067
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
18068
|
+
drawProjectedOrganicMouth(context, [
|
|
18069
|
+
{
|
|
18070
|
+
x: -mouthHalfWidth,
|
|
18071
|
+
y: mouthY,
|
|
18072
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
|
|
18073
|
+
},
|
|
18074
|
+
{
|
|
18075
|
+
x: size * morphologyProfile.face.mouthCenterOffsetRatio,
|
|
18076
|
+
y: mouthY +
|
|
18077
|
+
size * morphologyProfile.face.mouthCurveDepthRatio * 0.38 +
|
|
18078
|
+
Math.sin(timeMs / 760 + animationPhase) * size * 0.01 +
|
|
18079
|
+
interaction.gazeY * size * 0.01,
|
|
18080
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
|
|
18081
|
+
},
|
|
18082
|
+
{
|
|
18083
|
+
x: mouthHalfWidth,
|
|
18084
|
+
y: mouthY,
|
|
18085
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
|
|
18086
|
+
},
|
|
18087
|
+
], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
|
|
18088
|
+
},
|
|
18089
|
+
};
|
|
18090
|
+
/**
|
|
18091
|
+
* Draws the atmospheric underwater glow behind the octopus mesh.
|
|
18092
|
+
*
|
|
18093
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18094
|
+
*/
|
|
18095
|
+
function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
18096
|
+
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);
|
|
18097
|
+
glowGradient.addColorStop(0, `${palette.highlight}5c`);
|
|
18098
|
+
glowGradient.addColorStop(0.36, `${palette.accent}24`);
|
|
18099
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
18100
|
+
context.fillStyle = glowGradient;
|
|
18101
|
+
context.fillRect(0, 0, size, size);
|
|
18102
|
+
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);
|
|
18103
|
+
lowerGradient.addColorStop(0, `${palette.secondary}1d`);
|
|
18104
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
18105
|
+
context.fillStyle = lowerGradient;
|
|
18106
|
+
context.fillRect(0, 0, size, size);
|
|
18107
|
+
}
|
|
18108
|
+
/**
|
|
18109
|
+
* Draws the soft ground shadow below the octopus.
|
|
18110
|
+
*
|
|
18111
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
18112
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
18113
|
+
*
|
|
18114
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18115
|
+
*/
|
|
18116
|
+
function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
|
|
18117
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.04;
|
|
18118
|
+
const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
|
|
18119
|
+
const rx = size * (0.18 + interaction.intensity * 0.02);
|
|
18120
|
+
const ry = size * 0.06;
|
|
18121
|
+
context.save();
|
|
18122
|
+
context.translate(cx, cy);
|
|
18123
|
+
context.scale(1, ry / rx);
|
|
18124
|
+
const blurRadius = rx * 1.4;
|
|
18125
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
18126
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
18127
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
18128
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
18129
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
18130
|
+
context.fillStyle = shadowGradient;
|
|
18131
|
+
context.beginPath();
|
|
18132
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
18133
|
+
context.fill();
|
|
18134
|
+
context.restore();
|
|
18135
|
+
}
|
|
18136
|
+
/**
|
|
18137
|
+
* Resolves visible projected patches for one rotated ellipsoid mesh.
|
|
18138
|
+
*
|
|
18139
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18140
|
+
*/
|
|
18141
|
+
function resolveVisibleEllipsoidPatches(options) {
|
|
18142
|
+
const { center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, verticalColorBias, outlineColor, } = options;
|
|
18143
|
+
const latitudePatchCount = 10;
|
|
18144
|
+
const longitudePatchCount = 18;
|
|
18145
|
+
const surfacePatches = [];
|
|
18146
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
18147
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
18148
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
18149
|
+
const verticalProgress = (latitudeIndex + 0.5) / latitudePatchCount;
|
|
18150
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
18151
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
18152
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
18153
|
+
const localCorners = [
|
|
18154
|
+
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, startLongitude),
|
|
18155
|
+
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, startLatitude, endLongitude),
|
|
18156
|
+
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, endLongitude),
|
|
18157
|
+
sampleEllipsoidPoint(radiusX, radiusY, radiusZ, endLatitude, startLongitude),
|
|
18158
|
+
];
|
|
18159
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
18160
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
18161
|
+
if (surfaceNormal.z <= 0.01) {
|
|
18162
|
+
continue;
|
|
18163
|
+
}
|
|
18164
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
18165
|
+
surfacePatches.push({
|
|
18166
|
+
corners: projectedCorners,
|
|
18167
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
18168
|
+
transformedCorners.length,
|
|
18169
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
18170
|
+
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
18171
|
+
outlineColor,
|
|
18172
|
+
});
|
|
18173
|
+
}
|
|
18174
|
+
}
|
|
18175
|
+
return surfacePatches;
|
|
18176
|
+
}
|
|
18177
|
+
/**
|
|
18178
|
+
* Samples one point on an ellipsoid aligned to the local axes.
|
|
18179
|
+
*
|
|
18180
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18181
|
+
*/
|
|
18182
|
+
function sampleEllipsoidPoint(radiusX, radiusY, radiusZ, latitude, longitude) {
|
|
18183
|
+
const cosineLatitude = Math.cos(latitude);
|
|
18184
|
+
return {
|
|
18185
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX,
|
|
18186
|
+
y: Math.sin(latitude) * radiusY,
|
|
18187
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ,
|
|
18188
|
+
};
|
|
18189
|
+
}
|
|
18190
|
+
/**
|
|
18191
|
+
* Resolves one base fill tone for a surface patch across the octopus body.
|
|
18192
|
+
*
|
|
18193
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18194
|
+
*/
|
|
18195
|
+
function resolveSurfacePatchFillStyle(palette, verticalProgress) {
|
|
18196
|
+
const clampedVerticalProgress = clampNumber$1(verticalProgress, 0, 1);
|
|
18197
|
+
if (clampedVerticalProgress < 0.2) {
|
|
18198
|
+
return palette.highlight;
|
|
18199
|
+
}
|
|
18200
|
+
if (clampedVerticalProgress < 0.45) {
|
|
18201
|
+
return palette.secondary;
|
|
18202
|
+
}
|
|
18203
|
+
if (clampedVerticalProgress < 0.8) {
|
|
18204
|
+
return palette.primary;
|
|
18205
|
+
}
|
|
18206
|
+
return `${palette.shadow}f2`;
|
|
18207
|
+
}
|
|
18208
|
+
/**
|
|
18209
|
+
* Draws one projected mesh patch with organic shading.
|
|
18210
|
+
*
|
|
18211
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18212
|
+
*/
|
|
18213
|
+
function drawSurfacePatch(context, surfacePatch) {
|
|
18214
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
18215
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
18216
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.15 * surfacePatch.lightIntensity})`);
|
|
18217
|
+
}
|
|
18218
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
18219
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
18220
|
+
}
|
|
18221
|
+
context.save();
|
|
18222
|
+
context.beginPath();
|
|
18223
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
18224
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
18225
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
18226
|
+
}
|
|
18227
|
+
context.closePath();
|
|
18228
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
18229
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0044);
|
|
18230
|
+
context.lineJoin = 'round';
|
|
18231
|
+
context.stroke();
|
|
18232
|
+
context.restore();
|
|
18233
|
+
}
|
|
18234
|
+
/**
|
|
18235
|
+
* Creates the projected 3D tentacle strokes orbiting around the lower octopus body.
|
|
18236
|
+
*
|
|
18237
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18238
|
+
*/
|
|
18239
|
+
function createOctopusTentacleStrokes(options) {
|
|
18240
|
+
const { createRandom, morphologyProfile, timeMs, size, center, radiusX, radiusY, radiusZ, rotationX, rotationY, sceneCenterX, sceneCenterY, animationPhase, } = options;
|
|
18241
|
+
return Array.from({ length: morphologyProfile.tentacles.count }, (_, tentacleIndex) => {
|
|
18242
|
+
const tentacleRandom = createRandom(`octopus3d-tentacle-${tentacleIndex}`);
|
|
18243
|
+
const spreadProgress = morphologyProfile.tentacles.count === 1 ? 0.5 : tentacleIndex / (morphologyProfile.tentacles.count - 1);
|
|
18244
|
+
const orbitAngle = -Math.PI * 0.92 + spreadProgress * Math.PI * 1.84 + (tentacleRandom() - 0.5) * 0.16;
|
|
18245
|
+
const flowLength = size * (0.19 + morphologyProfile.tentacles.flowLengthScale * 0.075 + tentacleRandom() * 0.018);
|
|
18246
|
+
const lateralReach = size *
|
|
18247
|
+
(0.08 + morphologyProfile.tentacles.lateralReachScale * 0.05 + Math.abs(Math.sin(orbitAngle)) * 0.018);
|
|
18248
|
+
const depthReach = size * (0.028 + morphologyProfile.tentacles.tipReachScale * 0.032);
|
|
18249
|
+
const sway = Math.sin(timeMs / (760 + tentacleIndex * 36) + animationPhase + tentacleRandom() * Math.PI * 2);
|
|
18250
|
+
const anchorPoint = {
|
|
18251
|
+
x: Math.sin(orbitAngle) * radiusX * (0.84 + tentacleRandom() * 0.08),
|
|
18252
|
+
y: radiusY * (0.22 + tentacleRandom() * 0.18),
|
|
18253
|
+
z: Math.cos(orbitAngle) * radiusZ * (0.72 + tentacleRandom() * 0.12),
|
|
18254
|
+
};
|
|
18255
|
+
const controlPointOne = {
|
|
18256
|
+
x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * 0.44,
|
|
18257
|
+
y: anchorPoint.y + flowLength * 0.26,
|
|
18258
|
+
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
|
|
18259
|
+
};
|
|
18260
|
+
const controlPointTwo = {
|
|
18261
|
+
x: anchorPoint.x +
|
|
18262
|
+
Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
|
|
18263
|
+
y: anchorPoint.y + flowLength * 0.66,
|
|
18264
|
+
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
|
|
18265
|
+
};
|
|
18266
|
+
const endPoint = {
|
|
18267
|
+
x: anchorPoint.x +
|
|
18268
|
+
Math.sin(orbitAngle) * lateralReach * (1.02 + morphologyProfile.tentacles.tipWidthScale * 0.12) +
|
|
18269
|
+
sway * size * 0.028,
|
|
18270
|
+
y: anchorPoint.y + flowLength,
|
|
18271
|
+
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach + sway * size * 0.016,
|
|
18272
|
+
};
|
|
18273
|
+
const scenePoints = Array.from({ length: 12 }, (_, sampleIndex) => transformScenePoint(sampleCubicBezierPoint3D(anchorPoint, controlPointOne, controlPointTwo, endPoint, sampleIndex / 11), center, rotationX, rotationY));
|
|
18274
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
18275
|
+
const averageDepth = scenePoints.reduce((depthSum, scenePoint) => depthSum + scenePoint.z, 0) / scenePoints.length;
|
|
18276
|
+
return {
|
|
18277
|
+
projectedPoints,
|
|
18278
|
+
averageDepth,
|
|
18279
|
+
isFrontFacing: averageDepth >= center.z - size * 0.006,
|
|
18280
|
+
baseWidth: size *
|
|
18281
|
+
(0.019 +
|
|
18282
|
+
morphologyProfile.tentacles.baseWidthScale * 0.007 +
|
|
18283
|
+
tentacleRandom() * 0.003 +
|
|
18284
|
+
Math.abs(Math.sin(orbitAngle)) * 0.002),
|
|
18285
|
+
tipWidth: size * (0.0046 + morphologyProfile.tentacles.tipWidthScale * 0.0018),
|
|
18286
|
+
colorBias: tentacleRandom(),
|
|
18287
|
+
};
|
|
18288
|
+
});
|
|
18289
|
+
}
|
|
18290
|
+
/**
|
|
18291
|
+
* Samples one point on a cubic Bezier curve in 3D.
|
|
18292
|
+
*
|
|
18293
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18294
|
+
*/
|
|
18295
|
+
function sampleCubicBezierPoint3D(startPoint, controlPointOne, controlPointTwo, endPoint, progress) {
|
|
18296
|
+
const inverseProgress = 1 - progress;
|
|
18297
|
+
return {
|
|
18298
|
+
x: inverseProgress * inverseProgress * inverseProgress * startPoint.x +
|
|
18299
|
+
3 * inverseProgress * inverseProgress * progress * controlPointOne.x +
|
|
18300
|
+
3 * inverseProgress * progress * progress * controlPointTwo.x +
|
|
18301
|
+
progress * progress * progress * endPoint.x,
|
|
18302
|
+
y: inverseProgress * inverseProgress * inverseProgress * startPoint.y +
|
|
18303
|
+
3 * inverseProgress * inverseProgress * progress * controlPointOne.y +
|
|
18304
|
+
3 * inverseProgress * progress * progress * controlPointTwo.y +
|
|
18305
|
+
progress * progress * progress * endPoint.y,
|
|
18306
|
+
z: inverseProgress * inverseProgress * inverseProgress * startPoint.z +
|
|
18307
|
+
3 * inverseProgress * inverseProgress * progress * controlPointOne.z +
|
|
18308
|
+
3 * inverseProgress * progress * progress * controlPointTwo.z +
|
|
18309
|
+
progress * progress * progress * endPoint.z,
|
|
18310
|
+
};
|
|
18311
|
+
}
|
|
18312
|
+
/**
|
|
18313
|
+
* Draws one projected tentacle stroke with a slim highlight ridge.
|
|
18314
|
+
*
|
|
18315
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18316
|
+
*/
|
|
18317
|
+
function drawTentacleStroke(context, tentacleStroke, palette) {
|
|
18318
|
+
const projectedSegments = tentacleStroke.projectedPoints.length - 1;
|
|
18319
|
+
for (let segmentIndex = 0; segmentIndex < projectedSegments; segmentIndex++) {
|
|
18320
|
+
const startPoint = tentacleStroke.projectedPoints[segmentIndex];
|
|
18321
|
+
const endPoint = tentacleStroke.projectedPoints[segmentIndex + 1];
|
|
18322
|
+
const progress = segmentIndex / projectedSegments;
|
|
18323
|
+
const width = tentacleStroke.baseWidth + (tentacleStroke.tipWidth - tentacleStroke.baseWidth) * progress;
|
|
18324
|
+
context.beginPath();
|
|
18325
|
+
context.moveTo(startPoint.x, startPoint.y);
|
|
18326
|
+
context.lineTo(endPoint.x, endPoint.y);
|
|
18327
|
+
context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
|
|
18328
|
+
context.lineWidth = width;
|
|
18329
|
+
context.lineCap = 'round';
|
|
18330
|
+
context.stroke();
|
|
18331
|
+
context.beginPath();
|
|
18332
|
+
context.moveTo(startPoint.x, startPoint.y);
|
|
18333
|
+
context.lineTo(endPoint.x, endPoint.y);
|
|
18334
|
+
context.strokeStyle = tentacleStroke.isFrontFacing ? `${palette.highlight}80` : `${palette.highlight}40`;
|
|
18335
|
+
context.lineWidth = Math.max(1, width * 0.34);
|
|
18336
|
+
context.lineCap = 'round';
|
|
18337
|
+
context.stroke();
|
|
18338
|
+
}
|
|
18339
|
+
}
|
|
18340
|
+
/**
|
|
18341
|
+
* Resolves the front surface depth on an ellipsoid for one local face point.
|
|
18342
|
+
*
|
|
18343
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
18344
|
+
*/
|
|
18345
|
+
function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
|
|
18346
|
+
const normalizedX = x / radiusX;
|
|
18347
|
+
const normalizedY = y / radiusY;
|
|
18348
|
+
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
18349
|
+
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
18350
|
+
}
|
|
18351
|
+
|
|
18315
18352
|
/* eslint-disable no-magic-numbers */
|
|
18316
18353
|
/**
|
|
18317
18354
|
* Octopus avatar visual.
|
|
@@ -19132,14 +19169,14 @@ function resolveAvatarVisualId(value) {
|
|
|
19132
19169
|
/**
|
|
19133
19170
|
* META AVATAR commitment definition
|
|
19134
19171
|
*
|
|
19135
|
-
* The `META AVATAR`
|
|
19136
|
-
* the agent does not provide an explicit `META IMAGE`.
|
|
19172
|
+
* The `META AVATAR` and `META VISUAL` commitments set the built-in default avatar visual
|
|
19173
|
+
* used when the agent does not provide an explicit `META IMAGE`.
|
|
19137
19174
|
*
|
|
19138
19175
|
* @private [🪔] Maybe export the commitments through some package
|
|
19139
19176
|
*/
|
|
19140
19177
|
class MetaAvatarCommitmentDefinition extends BaseCommitmentDefinition {
|
|
19141
|
-
constructor() {
|
|
19142
|
-
super(
|
|
19178
|
+
constructor(type = 'META AVATAR') {
|
|
19179
|
+
super(type);
|
|
19143
19180
|
}
|
|
19144
19181
|
/**
|
|
19145
19182
|
* Short one-line description of META AVATAR.
|
|
@@ -19159,14 +19196,15 @@ class MetaAvatarCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19159
19196
|
get documentation() {
|
|
19160
19197
|
const supportedVisuals = AVATAR_VISUALS.map((avatarVisual) => `\`${avatarVisual.id}\``).join(', ');
|
|
19161
19198
|
return spaceTrim$1(`
|
|
19162
|
-
#
|
|
19199
|
+
# ${this.type}
|
|
19163
19200
|
|
|
19164
19201
|
Sets the built-in avatar visual used for the agent when no explicit \`META IMAGE\` is provided.
|
|
19202
|
+
\`META AVATAR\` and \`META VISUAL\` are equivalent.
|
|
19165
19203
|
|
|
19166
19204
|
## Key aspects
|
|
19167
19205
|
|
|
19168
19206
|
- Does not modify the agent's behavior or responses.
|
|
19169
|
-
- Only one \`META AVATAR\` should be used per agent.
|
|
19207
|
+
- Only one \`META AVATAR\` or \`META VISUAL\` should be used per agent.
|
|
19170
19208
|
- If multiple are specified, the last one takes precedence.
|
|
19171
19209
|
- Values are matched case-insensitively and spaces, hyphens, and underscores are normalized.
|
|
19172
19210
|
- Supported visuals are derived from the shared avatar registry: ${supportedVisuals}.
|
|
@@ -19181,15 +19219,15 @@ class MetaAvatarCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19181
19219
|
\`\`\`
|
|
19182
19220
|
|
|
19183
19221
|
\`\`\`book
|
|
19184
|
-
|
|
19222
|
+
Minecraft Assistant
|
|
19185
19223
|
|
|
19186
|
-
META
|
|
19224
|
+
META VISUAL Minecraft2
|
|
19187
19225
|
GOAL Answer in a calm and focused way.
|
|
19188
19226
|
\`\`\`
|
|
19189
19227
|
`);
|
|
19190
19228
|
}
|
|
19191
19229
|
applyToAgentModelRequirements(requirements, content) {
|
|
19192
|
-
// META AVATAR
|
|
19230
|
+
// META AVATAR and META VISUAL don't modify the system message or model requirements.
|
|
19193
19231
|
// It's handled separately in the parsing logic for profile avatar resolution.
|
|
19194
19232
|
return requirements;
|
|
19195
19233
|
}
|
|
@@ -28540,6 +28578,7 @@ const COMMITMENT_REGISTRY = [
|
|
|
28540
28578
|
new ActionCommitmentDefinition('ACTIONS'),
|
|
28541
28579
|
new ComponentCommitmentDefinition(),
|
|
28542
28580
|
new MetaAvatarCommitmentDefinition(),
|
|
28581
|
+
new MetaAvatarCommitmentDefinition('META VISUAL'),
|
|
28543
28582
|
new MetaImageCommitmentDefinition(),
|
|
28544
28583
|
new MetaColorCommitmentDefinition(),
|
|
28545
28584
|
new MetaFontCommitmentDefinition(),
|
|
@@ -33580,6 +33619,7 @@ function hasHttpProtocol(value) {
|
|
|
33580
33619
|
*/
|
|
33581
33620
|
const META_COMMITMENT_APPLIERS = {
|
|
33582
33621
|
'META AVATAR': applyMetaAvatarContent,
|
|
33622
|
+
'META VISUAL': applyMetaAvatarContent,
|
|
33583
33623
|
'META LINK': applyMetaLinkContent,
|
|
33584
33624
|
'META DOMAIN': applyMetaDomainContent,
|
|
33585
33625
|
'META IMAGE': applyMetaImageContent,
|
|
@@ -33628,7 +33668,7 @@ function applyGenericMetaCommitment(state, content) {
|
|
|
33628
33668
|
state.meta[metaType] = metaValue;
|
|
33629
33669
|
}
|
|
33630
33670
|
/**
|
|
33631
|
-
* Applies META AVATAR content into the canonical `meta.avatar` field.
|
|
33671
|
+
* Applies META AVATAR / META VISUAL content into the canonical `meta.avatar` field.
|
|
33632
33672
|
*/
|
|
33633
33673
|
function applyMetaAvatarContent(state, content) {
|
|
33634
33674
|
const avatarVisualId = resolveAvatarVisualId(content);
|