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