@promptbook/pdf 0.112.0-71 → 0.112.0-73
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 +1409 -783
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-3.0/Book.d.ts +6 -0
- package/esm/src/book-components/Chat/save/_common/chatExportRendering.d.ts +28 -0
- package/esm/src/book-components/Chat/save/_common/getPromptbookExportBranding.d.ts +18 -0
- package/esm/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +1 -1
- package/esm/src/book-components/Chat/save/html/htmlSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/save/index.d.ts +4 -4
- package/esm/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +1 -1
- package/esm/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -2
- package/esm/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
- package/esm/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/save/react/reactSaveFormatDefinition.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/getToolCallChipletInfo.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/renderMarkdown.d.ts +26 -0
- package/esm/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +14 -2
- package/esm/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +2 -0
- package/esm/src/cli/cli-commands/common/handleActionErrors.d.ts +9 -4
- package/esm/src/cli/cli-commands/run/prepareRunCommandResources.d.ts +20 -0
- package/esm/src/cli/cli-commands/run/resolveRunInputParameters.d.ts +12 -0
- package/esm/src/cli/cli-commands/run/runCommandAction.d.ts +21 -0
- package/esm/src/cli/cli-commands/run/runPipelineExecution.d.ts +14 -0
- package/esm/src/cli/cli-commands/run.d.ts +1 -1
- package/esm/src/conversion/parsePipeline/applyPipelineHead.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/createInitialPipelineJson.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/createUniqueSectionNameResolver.d.ts +14 -0
- package/esm/src/conversion/parsePipeline/defineParameter.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/extractPipelineDescription.d.ts +6 -0
- package/esm/src/conversion/parsePipeline/finalizeParsedPipeline.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/getPipelineIdentification.d.ts +7 -0
- package/esm/src/conversion/parsePipeline/parsePreparedPipelineSections.d.ts +18 -0
- package/esm/src/conversion/parsePipeline/preparePipelineString.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/processPipelineSection.d.ts +9 -0
- package/esm/src/conversion/pipelineJsonToString/appendMarkdownBlock.d.ts +7 -0
- package/esm/src/conversion/pipelineJsonToString/createPipelineCommands.d.ts +7 -0
- package/esm/src/conversion/pipelineJsonToString/createPipelineIntroduction.d.ts +8 -0
- package/esm/src/conversion/pipelineJsonToString/createTaskSerialization.d.ts +23 -0
- package/esm/src/conversion/pipelineJsonToString/stringifyCommands.d.ts +7 -0
- package/esm/src/conversion/pipelineJsonToString/stringifyTask.d.ts +8 -0
- package/esm/src/conversion/pipelineJsonToString.test.d.ts +1 -0
- package/esm/src/execution/createPipelineExecutor/executeSingleAttempt.d.ts +31 -0
- package/esm/src/execution/createPipelineExecutor/handleAttemptFailure.d.ts +40 -0
- package/esm/src/execution/createPipelineExecutor/reportPromptExecution.d.ts +34 -0
- package/esm/src/execution/resolveTaskTldr.d.ts +32 -0
- package/esm/src/execution/resolveTaskTldr.test.d.ts +1 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +22 -63
- package/esm/src/llm-providers/agent/AgentLlmExecutionToolsAgentKitRunner.d.ts +51 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionToolsOpenAiAssistantRunner.d.ts +43 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionToolsPromptPreparer.d.ts +41 -0
- package/esm/src/llm-providers/agent/emitAgentLlmExecutionToolsAssistantPreparationProgress.d.ts +26 -0
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +16 -93
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsInputBuilder.d.ts +41 -0
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOutputTypeMapper.d.ts +56 -0
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.d.ts +99 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +24 -120
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsProgressReporter.d.ts +62 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsPromptBuilder.d.ts +29 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.d.ts +63 -0
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.d.ts +89 -0
- package/esm/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +9 -28
- package/esm/src/llm-providers/openai/OpenAiCompatibleModelCatalog.d.ts +31 -0
- package/esm/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.d.ts +57 -0
- package/esm/src/llm-providers/openai/OpenAiCompatibleRequestManager.d.ts +29 -0
- package/esm/src/llm-providers/openai/OpenAiVectorStoreFileBatchHandler.d.ts +51 -0
- package/esm/src/llm-providers/openai/OpenAiVectorStoreFileBatchPoller.d.ts +75 -0
- package/esm/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +1 -98
- package/esm/src/llm-providers/openai/OpenAiVectorStoreKnowledgeSourcePreparer.d.ts +44 -0
- package/esm/src/llm-providers/openai/utils/OpenAiCompatibleChatProgressReporter.d.ts +86 -0
- package/esm/src/llm-providers/openai/utils/OpenAiCompatibleChatPromptBuilder.d.ts +57 -0
- package/esm/src/llm-providers/openai/utils/OpenAiCompatibleChatToolCaller.d.ts +57 -0
- package/esm/src/remote-server/startRemoteServer/RemoteServerRuntime.d.ts +14 -0
- package/esm/src/remote-server/startRemoteServer/SocketResponse.d.ts +9 -0
- package/esm/src/remote-server/startRemoteServer/StartRemoteServerConfiguration.d.ts +18 -0
- package/esm/src/remote-server/startRemoteServer/createRemoteServerExpressApp.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/createRemoteServerHandle.d.ts +11 -0
- package/esm/src/remote-server/startRemoteServer/createSocketServer.d.ts +9 -0
- package/esm/src/remote-server/startRemoteServer/getExecutionToolsFromIdentification.d.ts +12 -0
- package/esm/src/remote-server/startRemoteServer/registerBookRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerExecutionRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerListModelsSocketHandler.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerLoginRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerNotFoundRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerOpenAiCompatibleChatCompletionsRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerOpenApiRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerPreparePipelineSocketHandler.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerPromptSocketHandler.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerRemoteServerHttpRoutes.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/registerRemoteServerSocketHandlers.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/registerServerIndexRoute.d.ts +7 -0
- package/esm/src/remote-server/startRemoteServer/resolveStartRemoteServerConfiguration.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/respondToSocketRequest.d.ts +8 -0
- package/esm/src/remote-server/startRemoteServer/startListening.d.ts +9 -0
- package/esm/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +14 -1
- package/esm/src/utils/serialization/serializeToPromptbookJavascript.d.ts +2 -0
- package/esm/src/utils/serialization/serializeToPromptbookJavascript.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +1409 -783
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-3.0/Book.d.ts +6 -0
- package/umd/src/book-components/Chat/save/_common/chatExportRendering.d.ts +28 -0
- package/umd/src/book-components/Chat/save/_common/getPromptbookExportBranding.d.ts +18 -0
- package/umd/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +1 -1
- package/umd/src/book-components/Chat/save/html/htmlSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/save/index.d.ts +4 -4
- package/umd/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +1 -1
- package/umd/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -2
- package/umd/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
- package/umd/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/save/react/reactSaveFormatDefinition.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/getToolCallChipletInfo.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/renderMarkdown.d.ts +26 -0
- package/umd/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +14 -2
- package/umd/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +2 -0
- package/umd/src/cli/cli-commands/common/handleActionErrors.d.ts +9 -4
- package/umd/src/cli/cli-commands/run/prepareRunCommandResources.d.ts +20 -0
- package/umd/src/cli/cli-commands/run/resolveRunInputParameters.d.ts +12 -0
- package/umd/src/cli/cli-commands/run/runCommandAction.d.ts +21 -0
- package/umd/src/cli/cli-commands/run/runPipelineExecution.d.ts +14 -0
- package/umd/src/cli/cli-commands/run.d.ts +1 -1
- package/umd/src/conversion/parsePipeline/applyPipelineHead.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/createInitialPipelineJson.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/createUniqueSectionNameResolver.d.ts +14 -0
- package/umd/src/conversion/parsePipeline/defineParameter.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/extractPipelineDescription.d.ts +6 -0
- package/umd/src/conversion/parsePipeline/finalizeParsedPipeline.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/getPipelineIdentification.d.ts +7 -0
- package/umd/src/conversion/parsePipeline/parsePreparedPipelineSections.d.ts +18 -0
- package/umd/src/conversion/parsePipeline/preparePipelineString.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/processPipelineSection.d.ts +9 -0
- package/umd/src/conversion/pipelineJsonToString/appendMarkdownBlock.d.ts +7 -0
- package/umd/src/conversion/pipelineJsonToString/createPipelineCommands.d.ts +7 -0
- package/umd/src/conversion/pipelineJsonToString/createPipelineIntroduction.d.ts +8 -0
- package/umd/src/conversion/pipelineJsonToString/createTaskSerialization.d.ts +23 -0
- package/umd/src/conversion/pipelineJsonToString/stringifyCommands.d.ts +7 -0
- package/umd/src/conversion/pipelineJsonToString/stringifyTask.d.ts +8 -0
- package/umd/src/conversion/pipelineJsonToString.test.d.ts +1 -0
- package/umd/src/execution/createPipelineExecutor/executeSingleAttempt.d.ts +31 -0
- package/umd/src/execution/createPipelineExecutor/handleAttemptFailure.d.ts +40 -0
- package/umd/src/execution/createPipelineExecutor/reportPromptExecution.d.ts +34 -0
- package/umd/src/execution/resolveTaskTldr.d.ts +32 -0
- package/umd/src/execution/resolveTaskTldr.test.d.ts +1 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +22 -63
- package/umd/src/llm-providers/agent/AgentLlmExecutionToolsAgentKitRunner.d.ts +51 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionToolsOpenAiAssistantRunner.d.ts +43 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionToolsPromptPreparer.d.ts +41 -0
- package/umd/src/llm-providers/agent/emitAgentLlmExecutionToolsAssistantPreparationProgress.d.ts +26 -0
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +16 -93
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsInputBuilder.d.ts +41 -0
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOutputTypeMapper.d.ts +56 -0
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.d.ts +99 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +24 -120
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsProgressReporter.d.ts +62 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsPromptBuilder.d.ts +29 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.d.ts +63 -0
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.d.ts +89 -0
- package/umd/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +9 -28
- package/umd/src/llm-providers/openai/OpenAiCompatibleModelCatalog.d.ts +31 -0
- package/umd/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.d.ts +57 -0
- package/umd/src/llm-providers/openai/OpenAiCompatibleRequestManager.d.ts +29 -0
- package/umd/src/llm-providers/openai/OpenAiVectorStoreFileBatchHandler.d.ts +51 -0
- package/umd/src/llm-providers/openai/OpenAiVectorStoreFileBatchPoller.d.ts +75 -0
- package/umd/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +1 -98
- package/umd/src/llm-providers/openai/OpenAiVectorStoreKnowledgeSourcePreparer.d.ts +44 -0
- package/umd/src/llm-providers/openai/utils/OpenAiCompatibleChatProgressReporter.d.ts +86 -0
- package/umd/src/llm-providers/openai/utils/OpenAiCompatibleChatPromptBuilder.d.ts +57 -0
- package/umd/src/llm-providers/openai/utils/OpenAiCompatibleChatToolCaller.d.ts +57 -0
- package/umd/src/remote-server/startRemoteServer/RemoteServerRuntime.d.ts +14 -0
- package/umd/src/remote-server/startRemoteServer/SocketResponse.d.ts +9 -0
- package/umd/src/remote-server/startRemoteServer/StartRemoteServerConfiguration.d.ts +18 -0
- package/umd/src/remote-server/startRemoteServer/createRemoteServerExpressApp.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/createRemoteServerHandle.d.ts +11 -0
- package/umd/src/remote-server/startRemoteServer/createSocketServer.d.ts +9 -0
- package/umd/src/remote-server/startRemoteServer/getExecutionToolsFromIdentification.d.ts +12 -0
- package/umd/src/remote-server/startRemoteServer/registerBookRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerExecutionRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerListModelsSocketHandler.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerLoginRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerNotFoundRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerOpenAiCompatibleChatCompletionsRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerOpenApiRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerPreparePipelineSocketHandler.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerPromptSocketHandler.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerRemoteServerHttpRoutes.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/registerRemoteServerSocketHandlers.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/registerServerIndexRoute.d.ts +7 -0
- package/umd/src/remote-server/startRemoteServer/resolveStartRemoteServerConfiguration.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/respondToSocketRequest.d.ts +8 -0
- package/umd/src/remote-server/startRemoteServer/startListening.d.ts +9 -0
- package/umd/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +14 -1
- package/umd/src/utils/serialization/serializeToPromptbookJavascript.d.ts +2 -0
- package/umd/src/utils/serialization/serializeToPromptbookJavascript.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -24,7 +24,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
24
24
|
* @generated
|
|
25
25
|
* @see https://github.com/webgptorg/promptbook
|
|
26
26
|
*/
|
|
27
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
27
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-73';
|
|
28
28
|
/**
|
|
29
29
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
30
30
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2046,6 +2046,60 @@ function validatePipelineString(pipelineString) {
|
|
|
2046
2046
|
}
|
|
2047
2047
|
// TODO: [🧠][🈴] Where is the best location for this file
|
|
2048
2048
|
|
|
2049
|
+
/**
|
|
2050
|
+
* Appends one markdown block to an existing markdown document.
|
|
2051
|
+
*
|
|
2052
|
+
* @private internal utility of `pipelineJsonToString`
|
|
2053
|
+
*/
|
|
2054
|
+
function appendMarkdownBlock(pipelineString, markdownBlock) {
|
|
2055
|
+
return spaceTrim$1((block) => `
|
|
2056
|
+
${block(pipelineString)}
|
|
2057
|
+
|
|
2058
|
+
${block(markdownBlock)}
|
|
2059
|
+
`);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
/**
|
|
2063
|
+
* Collects pipeline-level commands in the existing serialization order.
|
|
2064
|
+
*
|
|
2065
|
+
* @private internal utility of `pipelineJsonToString`
|
|
2066
|
+
*/
|
|
2067
|
+
function createPipelineCommands(pipelineJson) {
|
|
2068
|
+
const { pipelineUrl, bookVersion, parameters } = pipelineJson;
|
|
2069
|
+
const commands = [];
|
|
2070
|
+
if (pipelineUrl) {
|
|
2071
|
+
commands.push(`PIPELINE URL ${pipelineUrl}`);
|
|
2072
|
+
}
|
|
2073
|
+
if (bookVersion !== `undefined`) {
|
|
2074
|
+
commands.push(`BOOK VERSION ${bookVersion}`);
|
|
2075
|
+
}
|
|
2076
|
+
commands.push(...createParameterCommands(parameters, 'INPUT PARAMETER', ({ isInput }) => isInput));
|
|
2077
|
+
commands.push(...createParameterCommands(parameters, 'OUTPUT PARAMETER', ({ isOutput }) => isOutput));
|
|
2078
|
+
return commands;
|
|
2079
|
+
}
|
|
2080
|
+
/**
|
|
2081
|
+
* Builds one group of parameter commands while preserving the original parameter order.
|
|
2082
|
+
*
|
|
2083
|
+
* @private internal utility of `createPipelineCommands`
|
|
2084
|
+
*/
|
|
2085
|
+
function createParameterCommands(parameters, commandPrefix, isIncluded) {
|
|
2086
|
+
return parameters
|
|
2087
|
+
.filter((parameter) => isIncluded(parameter))
|
|
2088
|
+
.map((parameter) => `${commandPrefix} ${parameterJsonToString(parameter)}`);
|
|
2089
|
+
}
|
|
2090
|
+
/**
|
|
2091
|
+
* Converts one parameter JSON declaration to the serialized inline form.
|
|
2092
|
+
*
|
|
2093
|
+
* @private internal utility of `createPipelineCommands`
|
|
2094
|
+
*/
|
|
2095
|
+
function parameterJsonToString(parameterJson) {
|
|
2096
|
+
const { name, description } = parameterJson;
|
|
2097
|
+
if (!description) {
|
|
2098
|
+
return `{${name}}`;
|
|
2099
|
+
}
|
|
2100
|
+
return `{${name}} ${description}`;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2049
2103
|
/**
|
|
2050
2104
|
* Prettify the html code
|
|
2051
2105
|
*
|
|
@@ -2059,6 +2113,31 @@ function prettifyMarkdown(content) {
|
|
|
2059
2113
|
return (content + `\n\n<!-- Note: Prettier removed from Promptbook -->`);
|
|
2060
2114
|
}
|
|
2061
2115
|
|
|
2116
|
+
/**
|
|
2117
|
+
* Creates the initial markdown heading and description of a pipeline.
|
|
2118
|
+
*
|
|
2119
|
+
* @private internal utility of `pipelineJsonToString`
|
|
2120
|
+
*/
|
|
2121
|
+
function createPipelineIntroduction(pipelineJson) {
|
|
2122
|
+
const { title, description } = pipelineJson;
|
|
2123
|
+
const pipelineIntroduction = spaceTrim$1((block) => `
|
|
2124
|
+
# ${title}
|
|
2125
|
+
|
|
2126
|
+
${block(description || '')}
|
|
2127
|
+
`);
|
|
2128
|
+
// TODO: [main] !!5 This increases size of the bundle and is probably not necessary
|
|
2129
|
+
return prettifyMarkdown(pipelineIntroduction);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* Renders commands as markdown bullet items.
|
|
2134
|
+
*
|
|
2135
|
+
* @private internal utility of `pipelineJsonToString`
|
|
2136
|
+
*/
|
|
2137
|
+
function stringifyCommands(commands) {
|
|
2138
|
+
return commands.map((command) => `- ${command}`).join('\n');
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2062
2141
|
/**
|
|
2063
2142
|
* Makes first letter of a string uppercase
|
|
2064
2143
|
*
|
|
@@ -2071,141 +2150,186 @@ function capitalize(word) {
|
|
|
2071
2150
|
}
|
|
2072
2151
|
|
|
2073
2152
|
/**
|
|
2074
|
-
*
|
|
2153
|
+
* Collects all task-specific serialization details.
|
|
2075
2154
|
*
|
|
2076
|
-
* @
|
|
2077
|
-
|
|
2078
|
-
|
|
2155
|
+
* @private internal utility of `pipelineJsonToString`
|
|
2156
|
+
*/
|
|
2157
|
+
function createTaskSerialization(task) {
|
|
2158
|
+
const taskTypeSerialization = createTaskTypeSerialization(task);
|
|
2159
|
+
return {
|
|
2160
|
+
commands: [
|
|
2161
|
+
...taskTypeSerialization.commands,
|
|
2162
|
+
...createJokerCommands(task),
|
|
2163
|
+
...createPostprocessingCommands(task),
|
|
2164
|
+
...createExpectationCommands(task),
|
|
2165
|
+
...createFormatCommands(task),
|
|
2166
|
+
],
|
|
2167
|
+
contentLanguage: taskTypeSerialization.contentLanguage,
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* Collects commands and content language driven by the task type.
|
|
2079
2172
|
*
|
|
2080
|
-
* @
|
|
2173
|
+
* @private internal utility of `createTaskSerialization`
|
|
2081
2174
|
*/
|
|
2082
|
-
function
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2175
|
+
function createTaskTypeSerialization(task) {
|
|
2176
|
+
if (task.taskType === 'PROMPT_TASK') {
|
|
2177
|
+
return {
|
|
2178
|
+
commands: createPromptTaskCommands(task),
|
|
2179
|
+
contentLanguage: 'text',
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
if (task.taskType === 'SIMPLE_TASK') {
|
|
2183
|
+
return {
|
|
2184
|
+
commands: ['SIMPLE TEMPLATE'],
|
|
2185
|
+
contentLanguage: 'text',
|
|
2186
|
+
};
|
|
2187
|
+
}
|
|
2188
|
+
if (task.taskType === 'SCRIPT_TASK') {
|
|
2189
|
+
return {
|
|
2190
|
+
commands: ['SCRIPT'],
|
|
2191
|
+
contentLanguage: task.contentLanguage || '',
|
|
2192
|
+
};
|
|
2193
|
+
}
|
|
2194
|
+
if (task.taskType === 'DIALOG_TASK') {
|
|
2195
|
+
return {
|
|
2196
|
+
commands: ['DIALOG'],
|
|
2197
|
+
contentLanguage: 'text',
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
return {
|
|
2201
|
+
commands: [],
|
|
2202
|
+
contentLanguage: 'text',
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
/**
|
|
2206
|
+
* Collects prompt-task-specific commands.
|
|
2207
|
+
*
|
|
2208
|
+
* @private internal utility of `createTaskSerialization`
|
|
2209
|
+
*/
|
|
2210
|
+
function createPromptTaskCommands(task) {
|
|
2211
|
+
const { modelName, modelVariant } = task.modelRequirements || {};
|
|
2089
2212
|
const commands = [];
|
|
2090
|
-
|
|
2091
|
-
|
|
2213
|
+
// Note: Do nothing, it is default
|
|
2214
|
+
// commands.push(`PROMPT`);
|
|
2215
|
+
if (modelVariant) {
|
|
2216
|
+
commands.push(`MODEL VARIANT ${capitalize(modelVariant)}`);
|
|
2092
2217
|
}
|
|
2093
|
-
if (
|
|
2094
|
-
commands.push(`
|
|
2218
|
+
if (modelName) {
|
|
2219
|
+
commands.push(`MODEL NAME \`${modelName}\``);
|
|
2095
2220
|
}
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2221
|
+
return commands;
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Collects joker commands.
|
|
2225
|
+
*
|
|
2226
|
+
* @private internal utility of `createTaskSerialization`
|
|
2227
|
+
*/
|
|
2228
|
+
function createJokerCommands(task) {
|
|
2229
|
+
var _a;
|
|
2230
|
+
return ((_a = task.jokerParameterNames) === null || _a === void 0 ? void 0 : _a.map((joker) => `JOKER {${joker}}`)) || [];
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Collects postprocessing commands.
|
|
2234
|
+
*
|
|
2235
|
+
* @private internal utility of `createTaskSerialization`
|
|
2236
|
+
*/
|
|
2237
|
+
function createPostprocessingCommands(task) {
|
|
2238
|
+
var _a;
|
|
2239
|
+
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
2240
|
+
}
|
|
2241
|
+
/**
|
|
2242
|
+
* Collects expectation commands.
|
|
2243
|
+
*
|
|
2244
|
+
* @private internal utility of `createTaskSerialization`
|
|
2245
|
+
*/
|
|
2246
|
+
function createExpectationCommands(task) {
|
|
2247
|
+
if (!task.expectations) {
|
|
2248
|
+
return [];
|
|
2100
2249
|
}
|
|
2101
|
-
|
|
2102
|
-
|
|
2250
|
+
return Object.entries(task.expectations).flatMap(([unit, expectation]) => createExpectationCommandsForUnit(unit, expectation.min, expectation.max));
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Collects expectation commands for a single unit.
|
|
2254
|
+
*
|
|
2255
|
+
* @private internal utility of `createTaskSerialization`
|
|
2256
|
+
*/
|
|
2257
|
+
function createExpectationCommandsForUnit(unit, min, max) {
|
|
2258
|
+
if (min === max) {
|
|
2259
|
+
return [`EXPECT EXACTLY ${min} ${formatExpectationUnit(unit, min)}`];
|
|
2103
2260
|
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
else if (taskType === 'SCRIPT_TASK') {
|
|
2134
|
-
commands.push(`SCRIPT`);
|
|
2135
|
-
if (task.contentLanguage) {
|
|
2136
|
-
contentLanguage = task.contentLanguage;
|
|
2137
|
-
}
|
|
2138
|
-
else {
|
|
2139
|
-
contentLanguage = '';
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
else if (taskType === 'DIALOG_TASK') {
|
|
2143
|
-
commands.push(`DIALOG`);
|
|
2144
|
-
// Note: Nothing special here
|
|
2145
|
-
} // <- }else if([🅱]
|
|
2146
|
-
if (jokers) {
|
|
2147
|
-
for (const joker of jokers) {
|
|
2148
|
-
commands.push(`JOKER {${joker}}`);
|
|
2149
|
-
}
|
|
2150
|
-
} /* not else */
|
|
2151
|
-
if (postprocessing) {
|
|
2152
|
-
for (const postprocessingFunctionName of postprocessing) {
|
|
2153
|
-
commands.push(`POSTPROCESSING \`${postprocessingFunctionName}\``);
|
|
2154
|
-
}
|
|
2155
|
-
} /* not else */
|
|
2156
|
-
if (expectations) {
|
|
2157
|
-
for (const [unit, { min, max }] of Object.entries(expectations)) {
|
|
2158
|
-
if (min === max) {
|
|
2159
|
-
commands.push(`EXPECT EXACTLY ${min} ${capitalize(unit + (min > 1 ? 's' : ''))}`);
|
|
2160
|
-
}
|
|
2161
|
-
else {
|
|
2162
|
-
if (min !== undefined) {
|
|
2163
|
-
commands.push(`EXPECT MIN ${min} ${capitalize(unit + (min > 1 ? 's' : ''))}`);
|
|
2164
|
-
} /* not else */
|
|
2165
|
-
if (max !== undefined) {
|
|
2166
|
-
commands.push(`EXPECT MAX ${max} ${capitalize(unit + (max > 1 ? 's' : ''))}`);
|
|
2167
|
-
}
|
|
2168
|
-
}
|
|
2169
|
-
}
|
|
2170
|
-
} /* not else */
|
|
2171
|
-
if (format) {
|
|
2172
|
-
if (format === 'JSON') {
|
|
2173
|
-
// TODO: @deprecated remove
|
|
2174
|
-
commands.push(`FORMAT JSON`);
|
|
2175
|
-
}
|
|
2176
|
-
} /* not else */
|
|
2177
|
-
pipelineString = spaceTrim$1((block) => `
|
|
2178
|
-
${block(pipelineString)}
|
|
2261
|
+
const commands = [];
|
|
2262
|
+
if (min !== undefined) {
|
|
2263
|
+
commands.push(`EXPECT MIN ${min} ${formatExpectationUnit(unit, min)}`);
|
|
2264
|
+
}
|
|
2265
|
+
if (max !== undefined) {
|
|
2266
|
+
commands.push(`EXPECT MAX ${max} ${formatExpectationUnit(unit, max)}`);
|
|
2267
|
+
}
|
|
2268
|
+
return commands;
|
|
2269
|
+
}
|
|
2270
|
+
/**
|
|
2271
|
+
* Formats the expectation unit exactly as the legacy serializer does.
|
|
2272
|
+
*
|
|
2273
|
+
* @private internal utility of `createTaskSerialization`
|
|
2274
|
+
*/
|
|
2275
|
+
function formatExpectationUnit(unit, amount) {
|
|
2276
|
+
return capitalize(unit + (amount > 1 ? 's' : ''));
|
|
2277
|
+
}
|
|
2278
|
+
/**
|
|
2279
|
+
* Collects format commands.
|
|
2280
|
+
*
|
|
2281
|
+
* @private internal utility of `createTaskSerialization`
|
|
2282
|
+
*/
|
|
2283
|
+
function createFormatCommands(task) {
|
|
2284
|
+
if (task.format === 'JSON') {
|
|
2285
|
+
// TODO: @deprecated remove
|
|
2286
|
+
return ['FORMAT JSON'];
|
|
2287
|
+
}
|
|
2288
|
+
return [];
|
|
2289
|
+
}
|
|
2179
2290
|
|
|
2180
|
-
|
|
2291
|
+
/**
|
|
2292
|
+
* Stringifies one task section of the pipeline.
|
|
2293
|
+
*
|
|
2294
|
+
* @private internal utility of `pipelineJsonToString`
|
|
2295
|
+
*/
|
|
2296
|
+
function stringifyTask(task) {
|
|
2297
|
+
const { title, description, content, resultingParameterName } = task;
|
|
2298
|
+
const { commands, contentLanguage } = createTaskSerialization(task);
|
|
2299
|
+
return spaceTrim$1((block) => `
|
|
2300
|
+
## ${title}
|
|
2181
2301
|
|
|
2182
|
-
|
|
2302
|
+
${block(description || '')}
|
|
2183
2303
|
|
|
2184
|
-
|
|
2304
|
+
${block(stringifyCommands(commands))}
|
|
2185
2305
|
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2306
|
+
\`\`\`${contentLanguage}
|
|
2307
|
+
${block(spaceTrim$1(content))}
|
|
2308
|
+
\`\`\`
|
|
2189
2309
|
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
}
|
|
2195
|
-
return validatePipelineString(pipelineString);
|
|
2310
|
+
\`-> {${resultingParameterName}}\`
|
|
2311
|
+
`); // <- TODO: [main] !!3 If the parameter here has description, add it and use taskParameterJsonToString
|
|
2312
|
+
// <- TODO: [main] !!3 Escape
|
|
2313
|
+
// <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
|
|
2196
2314
|
}
|
|
2315
|
+
|
|
2197
2316
|
/**
|
|
2198
|
-
*
|
|
2317
|
+
* Converts promptbook in JSON format to string format
|
|
2199
2318
|
*
|
|
2200
|
-
* @
|
|
2319
|
+
* @deprecated TODO: [🥍][🧠] Backup original files in `PipelineJson` same as in Promptbook.studio
|
|
2320
|
+
* @param pipelineJson Promptbook in JSON format (.bookc)
|
|
2321
|
+
* @returns Promptbook in string format (.book.md)
|
|
2322
|
+
*
|
|
2323
|
+
* @public exported from `@promptbook/core`
|
|
2201
2324
|
*/
|
|
2202
|
-
function
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2325
|
+
function pipelineJsonToString(pipelineJson) {
|
|
2326
|
+
let pipelineString = createPipelineIntroduction(pipelineJson);
|
|
2327
|
+
const pipelineCommands = createPipelineCommands(pipelineJson);
|
|
2328
|
+
pipelineString = appendMarkdownBlock(pipelineString, stringifyCommands(pipelineCommands));
|
|
2329
|
+
for (const task of pipelineJson.tasks) {
|
|
2330
|
+
pipelineString = appendMarkdownBlock(pipelineString, stringifyTask(task));
|
|
2207
2331
|
}
|
|
2208
|
-
return
|
|
2332
|
+
return validatePipelineString(pipelineString);
|
|
2209
2333
|
}
|
|
2210
2334
|
// TODO: [🛋] Implement new features and commands into `pipelineJsonToString` + `taskParameterJsonToString` , use `stringifyCommand`
|
|
2211
2335
|
// TODO: [🧠] Is there a way to auto-detect missing features in pipelineJsonToString
|
|
@@ -2645,233 +2769,519 @@ function validatePipeline(pipeline) {
|
|
|
2645
2769
|
*/
|
|
2646
2770
|
function validatePipeline_InnerFunction(pipeline) {
|
|
2647
2771
|
// TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
|
|
2648
|
-
const
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2772
|
+
const context = createPipelineValidationContext(pipeline);
|
|
2773
|
+
validatePipelineMetadata(context);
|
|
2774
|
+
validatePipelineCollectionsStructure(context);
|
|
2775
|
+
validatePipelineParameters(context);
|
|
2776
|
+
validatePipelineTasks(context);
|
|
2777
|
+
validatePipelineDependencyResolution(context);
|
|
2778
|
+
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
2779
|
+
// TODO: !!6 Implement this
|
|
2780
|
+
// pipeline.formfactorName
|
|
2781
|
+
}
|
|
2782
|
+
/**
|
|
2783
|
+
* Creates the shared validation context for one pipeline.
|
|
2784
|
+
*
|
|
2785
|
+
* @private internal utility of `validatePipeline`
|
|
2786
|
+
*/
|
|
2787
|
+
function createPipelineValidationContext(pipeline) {
|
|
2788
|
+
return {
|
|
2789
|
+
pipeline,
|
|
2790
|
+
pipelineIdentification: getPipelineIdentification(pipeline),
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
/**
|
|
2794
|
+
* Builds a short file/url identification block for validation errors.
|
|
2795
|
+
*
|
|
2796
|
+
* @private internal utility of `validatePipeline`
|
|
2797
|
+
*/
|
|
2798
|
+
function getPipelineIdentification(pipeline) {
|
|
2799
|
+
// Note: This is a 😐 implementation of [🚞]
|
|
2800
|
+
const pipelineIdentificationParts = [];
|
|
2801
|
+
if (pipeline.sourceFile !== undefined) {
|
|
2802
|
+
pipelineIdentificationParts.push(`File: ${pipeline.sourceFile}`);
|
|
2803
|
+
}
|
|
2804
|
+
if (pipeline.pipelineUrl !== undefined) {
|
|
2805
|
+
pipelineIdentificationParts.push(`Url: ${pipeline.pipelineUrl}`);
|
|
2806
|
+
}
|
|
2807
|
+
return pipelineIdentificationParts.join('\n');
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* Validates pipeline-level metadata fields.
|
|
2811
|
+
*
|
|
2812
|
+
* @private internal step of `validatePipeline`
|
|
2813
|
+
*/
|
|
2814
|
+
function validatePipelineMetadata({ pipeline, pipelineIdentification }) {
|
|
2815
|
+
validatePipelineUrl(pipeline, pipelineIdentification);
|
|
2816
|
+
validatePipelineBookVersion(pipeline, pipelineIdentification);
|
|
2817
|
+
}
|
|
2818
|
+
/**
|
|
2819
|
+
* Validates that the expected top-level collections have array structure.
|
|
2820
|
+
*
|
|
2821
|
+
* @private internal step of `validatePipeline`
|
|
2822
|
+
*/
|
|
2823
|
+
function validatePipelineCollectionsStructure({ pipeline, pipelineIdentification }) {
|
|
2824
|
+
validatePipelineParametersCollection(pipeline, pipelineIdentification);
|
|
2825
|
+
validatePipelineTasksCollection(pipeline, pipelineIdentification);
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* Validates all pipeline parameter declarations.
|
|
2829
|
+
*
|
|
2830
|
+
* @private internal step of `validatePipeline`
|
|
2831
|
+
*/
|
|
2832
|
+
function validatePipelineParameters({ pipeline, pipelineIdentification }) {
|
|
2833
|
+
for (const parameter of pipeline.parameters) {
|
|
2834
|
+
validatePipelineParameter(parameter, pipeline, pipelineIdentification);
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
/**
|
|
2838
|
+
* Validates all pipeline tasks and their per-task invariants.
|
|
2839
|
+
*
|
|
2840
|
+
* @private internal step of `validatePipeline`
|
|
2841
|
+
*/
|
|
2842
|
+
function validatePipelineTasks({ pipeline, pipelineIdentification }) {
|
|
2843
|
+
// Note: All input parameters are defined - so that they can be used as result of some task
|
|
2844
|
+
const definedParameters = createInitiallyDefinedParameters(pipeline);
|
|
2845
|
+
for (const task of pipeline.tasks) {
|
|
2846
|
+
validatePipelineTask(task, definedParameters, pipelineIdentification);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* Validates that task dependencies can be resolved without cycles or missing definitions.
|
|
2851
|
+
*
|
|
2852
|
+
* @private internal step of `validatePipeline`
|
|
2853
|
+
*/
|
|
2854
|
+
function validatePipelineDependencyResolution({ pipeline, pipelineIdentification }) {
|
|
2855
|
+
let dependencyResolutionState = createInitialDependencyResolutionState(pipeline);
|
|
2856
|
+
let loopLimit = LOOP_LIMIT;
|
|
2857
|
+
while (hasUnresolvedTasks(dependencyResolutionState)) {
|
|
2858
|
+
if (loopLimit-- < 0) {
|
|
2859
|
+
throw createDependencyResolutionLoopLimitError(pipelineIdentification);
|
|
2656
2860
|
}
|
|
2657
|
-
|
|
2658
|
-
})();
|
|
2659
|
-
if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
|
|
2660
|
-
// <- Note: [🚲]
|
|
2661
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2662
|
-
Invalid promptbook URL "${pipeline.pipelineUrl}"
|
|
2663
|
-
|
|
2664
|
-
${block(pipelineIdentification)}
|
|
2665
|
-
`));
|
|
2861
|
+
dependencyResolutionState = resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification);
|
|
2666
2862
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2863
|
+
}
|
|
2864
|
+
/**
|
|
2865
|
+
* Validates one pipeline parameter declaration.
|
|
2866
|
+
*
|
|
2867
|
+
* @private internal step of `validatePipeline`
|
|
2868
|
+
*/
|
|
2869
|
+
function validatePipelineParameter(parameter, pipeline, pipelineIdentification) {
|
|
2870
|
+
validateParameterDirection(parameter, pipelineIdentification);
|
|
2871
|
+
validateParameterUsage(parameter, pipeline, pipelineIdentification);
|
|
2872
|
+
validateParameterDefinition(parameter, pipeline, pipelineIdentification);
|
|
2873
|
+
}
|
|
2874
|
+
/**
|
|
2875
|
+
* Validates one pipeline task and its invariants.
|
|
2876
|
+
*
|
|
2877
|
+
* @private internal step of `validatePipeline`
|
|
2878
|
+
*/
|
|
2879
|
+
function validatePipelineTask(task, definedParameters, pipelineIdentification) {
|
|
2880
|
+
validateTaskResultingParameter(task, definedParameters, pipelineIdentification);
|
|
2881
|
+
validateTaskJokers(task, pipelineIdentification);
|
|
2882
|
+
validateTaskExpectations(task, pipelineIdentification);
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Validates the pipeline URL, when present.
|
|
2886
|
+
*
|
|
2887
|
+
* @private internal utility of `validatePipeline`
|
|
2888
|
+
*/
|
|
2889
|
+
function validatePipelineUrl(pipeline, pipelineIdentification) {
|
|
2890
|
+
if (pipeline.pipelineUrl === undefined || isValidPipelineUrl(pipeline.pipelineUrl)) {
|
|
2891
|
+
return;
|
|
2892
|
+
}
|
|
2893
|
+
// <- Note: [🚲]
|
|
2894
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2895
|
+
Invalid promptbook URL "${pipeline.pipelineUrl}"
|
|
2671
2896
|
|
|
2672
|
-
|
|
2673
|
-
|
|
2897
|
+
${block(pipelineIdentification)}
|
|
2898
|
+
`));
|
|
2899
|
+
}
|
|
2900
|
+
/**
|
|
2901
|
+
* Validates the Promptbook version, when present.
|
|
2902
|
+
*
|
|
2903
|
+
* @private internal utility of `validatePipeline`
|
|
2904
|
+
*/
|
|
2905
|
+
function validatePipelineBookVersion(pipeline, pipelineIdentification) {
|
|
2906
|
+
if (pipeline.bookVersion === undefined || isValidPromptbookVersion(pipeline.bookVersion)) {
|
|
2907
|
+
return;
|
|
2674
2908
|
}
|
|
2909
|
+
// <- Note: [🚲]
|
|
2910
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2911
|
+
Invalid Promptbook Version "${pipeline.bookVersion}"
|
|
2912
|
+
|
|
2913
|
+
${block(pipelineIdentification)}
|
|
2914
|
+
`));
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* Validates that `pipeline.parameters` is an array.
|
|
2918
|
+
*
|
|
2919
|
+
* @private internal utility of `validatePipeline`
|
|
2920
|
+
*/
|
|
2921
|
+
function validatePipelineParametersCollection(pipeline, pipelineIdentification) {
|
|
2675
2922
|
// TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
|
|
2676
|
-
if (
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2923
|
+
if (Array.isArray(pipeline.parameters)) {
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
2927
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
2928
|
+
Pipeline is valid JSON but with wrong structure
|
|
2680
2929
|
|
|
2681
|
-
|
|
2930
|
+
\`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
|
|
2682
2931
|
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2932
|
+
${block(pipelineIdentification)}
|
|
2933
|
+
`));
|
|
2934
|
+
}
|
|
2935
|
+
/**
|
|
2936
|
+
* Validates that `pipeline.tasks` is an array.
|
|
2937
|
+
*
|
|
2938
|
+
* @private internal utility of `validatePipeline`
|
|
2939
|
+
*/
|
|
2940
|
+
function validatePipelineTasksCollection(pipeline, pipelineIdentification) {
|
|
2686
2941
|
// TODO: [🧠] Maybe do here some proper JSON-schema / ZOD checking
|
|
2687
|
-
if (
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2942
|
+
if (Array.isArray(pipeline.tasks)) {
|
|
2943
|
+
return;
|
|
2944
|
+
}
|
|
2945
|
+
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
2946
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
2947
|
+
Pipeline is valid JSON but with wrong structure
|
|
2691
2948
|
|
|
2692
|
-
|
|
2949
|
+
\`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
|
|
2693
2950
|
|
|
2694
|
-
|
|
2695
|
-
|
|
2951
|
+
${block(pipelineIdentification)}
|
|
2952
|
+
`));
|
|
2953
|
+
}
|
|
2954
|
+
/**
|
|
2955
|
+
* Validates that one parameter does not declare incompatible directions.
|
|
2956
|
+
*
|
|
2957
|
+
* @private internal utility of `validatePipeline`
|
|
2958
|
+
*/
|
|
2959
|
+
function validateParameterDirection(parameter, pipelineIdentification) {
|
|
2960
|
+
if (!parameter.isInput || !parameter.isOutput) {
|
|
2961
|
+
return;
|
|
2696
2962
|
}
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
// Note: Check that pipeline has some tasks
|
|
2700
|
-
if (pipeline.tasks.length === 0) {
|
|
2701
|
-
throw new PipelineLogicError(
|
|
2702
|
-
spaceTrim(
|
|
2703
|
-
(block) => `
|
|
2704
|
-
Pipeline must have at least one task
|
|
2963
|
+
const parameterName = parameter.name;
|
|
2964
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2705
2965
|
|
|
2706
|
-
|
|
2707
|
-
`,
|
|
2708
|
-
),
|
|
2709
|
-
);
|
|
2710
|
-
}
|
|
2711
|
-
*/
|
|
2712
|
-
// Note: Check each parameter individually
|
|
2713
|
-
for (const parameter of pipeline.parameters) {
|
|
2714
|
-
if (parameter.isInput && parameter.isOutput) {
|
|
2715
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2966
|
+
Parameter \`{${parameterName}}\` can not be both input and output
|
|
2716
2967
|
|
|
2717
|
-
|
|
2968
|
+
${block(pipelineIdentification)}
|
|
2969
|
+
`));
|
|
2970
|
+
}
|
|
2971
|
+
/**
|
|
2972
|
+
* Validates that one intermediate parameter is actually consumed by at least one task.
|
|
2973
|
+
*
|
|
2974
|
+
* @private internal utility of `validatePipeline`
|
|
2975
|
+
*/
|
|
2976
|
+
function validateParameterUsage(parameter, pipeline, pipelineIdentification) {
|
|
2977
|
+
if (parameter.isInput || parameter.isOutput || isParameterUsedByAnyTask(parameter, pipeline.tasks)) {
|
|
2978
|
+
return;
|
|
2979
|
+
}
|
|
2980
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2981
|
+
Parameter \`{${parameter.name}}\` is created but not used
|
|
2718
2982
|
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
}
|
|
2722
|
-
// Note: Testing that parameter is either intermediate or output BUT not created and unused
|
|
2723
|
-
if (!parameter.isInput &&
|
|
2724
|
-
!parameter.isOutput &&
|
|
2725
|
-
!pipeline.tasks.some((task) => task.dependentParameterNames.includes(parameter.name))) {
|
|
2726
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2727
|
-
Parameter \`{${parameter.name}}\` is created but not used
|
|
2983
|
+
You can declare {${parameter.name}} as output parameter by adding in the header:
|
|
2984
|
+
- OUTPUT PARAMETER \`{${parameter.name}}\` ${parameter.description || ''}
|
|
2728
2985
|
|
|
2729
|
-
|
|
2730
|
-
- OUTPUT PARAMETER \`{${parameter.name}}\` ${parameter.description || ''}
|
|
2986
|
+
${block(pipelineIdentification)}
|
|
2731
2987
|
|
|
2732
|
-
|
|
2988
|
+
`));
|
|
2989
|
+
}
|
|
2990
|
+
/**
|
|
2991
|
+
* Validates that one non-input parameter is produced by at least one task.
|
|
2992
|
+
*
|
|
2993
|
+
* @private internal utility of `validatePipeline`
|
|
2994
|
+
*/
|
|
2995
|
+
function validateParameterDefinition(parameter, pipeline, pipelineIdentification) {
|
|
2996
|
+
if (parameter.isInput || isParameterDefinedByAnyTask(parameter, pipeline.tasks)) {
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3000
|
+
Parameter \`{${parameter.name}}\` is declared but not defined
|
|
2733
3001
|
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
if (!parameter.isInput && !pipeline.tasks.some((task) => task.resultingParameterName === parameter.name)) {
|
|
2738
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2739
|
-
Parameter \`{${parameter.name}}\` is declared but not defined
|
|
3002
|
+
You can do one of these:
|
|
3003
|
+
1) Remove declaration of \`{${parameter.name}}\`
|
|
3004
|
+
2) Add task that results in \`-> {${parameter.name}}\`
|
|
2740
3005
|
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
3006
|
+
${block(pipelineIdentification)}
|
|
3007
|
+
`));
|
|
3008
|
+
}
|
|
3009
|
+
/**
|
|
3010
|
+
* Checks whether one parameter is consumed by at least one task dependency list.
|
|
3011
|
+
*
|
|
3012
|
+
* @private internal utility of `validatePipeline`
|
|
3013
|
+
*/
|
|
3014
|
+
function isParameterUsedByAnyTask(parameter, tasks) {
|
|
3015
|
+
return tasks.some((task) => task.dependentParameterNames.includes(parameter.name));
|
|
3016
|
+
}
|
|
3017
|
+
/**
|
|
3018
|
+
* Checks whether one parameter is produced by at least one task.
|
|
3019
|
+
*
|
|
3020
|
+
* @private internal utility of `validatePipeline`
|
|
3021
|
+
*/
|
|
3022
|
+
function isParameterDefinedByAnyTask(parameter, tasks) {
|
|
3023
|
+
return tasks.some((task) => task.resultingParameterName === parameter.name);
|
|
3024
|
+
}
|
|
3025
|
+
/**
|
|
3026
|
+
* Collects the parameter names that are already defined before task validation starts.
|
|
3027
|
+
*
|
|
3028
|
+
* @private internal utility of `validatePipeline`
|
|
3029
|
+
*/
|
|
3030
|
+
function createInitiallyDefinedParameters(pipeline) {
|
|
3031
|
+
return new Set(pipeline.parameters.filter(({ isInput }) => isInput).map(({ name }) => name));
|
|
3032
|
+
}
|
|
3033
|
+
/**
|
|
3034
|
+
* Validates one task result parameter declaration and marks it as defined.
|
|
3035
|
+
*
|
|
3036
|
+
* @private internal utility of `validatePipeline`
|
|
3037
|
+
*/
|
|
3038
|
+
function validateTaskResultingParameter(task, definedParameters, pipelineIdentification) {
|
|
3039
|
+
if (definedParameters.has(task.resultingParameterName)) {
|
|
3040
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3041
|
+
Parameter \`{${task.resultingParameterName}}\` is defined multiple times
|
|
2744
3042
|
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
}
|
|
3043
|
+
${block(pipelineIdentification)}
|
|
3044
|
+
`));
|
|
2748
3045
|
}
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
for (const task of pipeline.tasks) {
|
|
2753
|
-
if (definedParameters.has(task.resultingParameterName)) {
|
|
2754
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2755
|
-
Parameter \`{${task.resultingParameterName}}\` is defined multiple times
|
|
3046
|
+
if (RESERVED_PARAMETER_NAMES.includes(task.resultingParameterName)) {
|
|
3047
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3048
|
+
Parameter name {${task.resultingParameterName}} is reserved, please use different name
|
|
2756
3049
|
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
3050
|
+
${block(pipelineIdentification)}
|
|
3051
|
+
`));
|
|
3052
|
+
}
|
|
3053
|
+
definedParameters.add(task.resultingParameterName);
|
|
3054
|
+
}
|
|
3055
|
+
/**
|
|
3056
|
+
* Validates joker parameters for one task.
|
|
3057
|
+
*
|
|
3058
|
+
* @private internal utility of `validatePipeline`
|
|
3059
|
+
*/
|
|
3060
|
+
function validateTaskJokers(task, pipelineIdentification) {
|
|
3061
|
+
if (!hasTaskJokers(task)) {
|
|
3062
|
+
return;
|
|
3063
|
+
}
|
|
3064
|
+
validateTaskSupportsJokers(task, pipelineIdentification);
|
|
3065
|
+
validateTaskJokerDependencies(task, pipelineIdentification);
|
|
3066
|
+
}
|
|
3067
|
+
/**
|
|
3068
|
+
* Checks whether one task declares any joker parameters.
|
|
3069
|
+
*
|
|
3070
|
+
* @private internal utility of `validatePipeline`
|
|
3071
|
+
*/
|
|
3072
|
+
function hasTaskJokers(task) {
|
|
3073
|
+
return !!task.jokerParameterNames && task.jokerParameterNames.length > 0;
|
|
3074
|
+
}
|
|
3075
|
+
/**
|
|
3076
|
+
* Validates that a task has the required supporting features when using jokers.
|
|
3077
|
+
*
|
|
3078
|
+
* @private internal utility of `validatePipeline`
|
|
3079
|
+
*/
|
|
3080
|
+
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
3081
|
+
if (task.format ||
|
|
3082
|
+
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
3083
|
+
return;
|
|
3084
|
+
}
|
|
3085
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3086
|
+
Joker parameters are used for {${task.resultingParameterName}} but no expectations are defined
|
|
2763
3087
|
|
|
2764
|
-
|
|
2765
|
-
|
|
3088
|
+
${block(pipelineIdentification)}
|
|
3089
|
+
`));
|
|
3090
|
+
}
|
|
3091
|
+
/**
|
|
3092
|
+
* Validates that every joker parameter is also listed among task dependencies.
|
|
3093
|
+
*
|
|
3094
|
+
* @private internal utility of `validatePipeline`
|
|
3095
|
+
*/
|
|
3096
|
+
function validateTaskJokerDependencies(task, pipelineIdentification) {
|
|
3097
|
+
for (const joker of task.jokerParameterNames) {
|
|
3098
|
+
if (task.dependentParameterNames.includes(joker)) {
|
|
3099
|
+
continue;
|
|
2766
3100
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
if (!task.format &&
|
|
2770
|
-
!task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
2771
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2772
|
-
Joker parameters are used for {${task.resultingParameterName}} but no expectations are defined
|
|
2773
|
-
|
|
2774
|
-
${block(pipelineIdentification)}
|
|
2775
|
-
`));
|
|
2776
|
-
}
|
|
2777
|
-
for (const joker of task.jokerParameterNames) {
|
|
2778
|
-
if (!task.dependentParameterNames.includes(joker)) {
|
|
2779
|
-
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
2780
|
-
Parameter \`{${joker}}\` is used for {${task.resultingParameterName}} as joker but not in \`dependentParameterNames\`
|
|
3101
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3102
|
+
Parameter \`{${joker}}\` is used for {${task.resultingParameterName}} as joker but not in \`dependentParameterNames\`
|
|
2781
3103
|
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
3104
|
+
${block(pipelineIdentification)}
|
|
3105
|
+
`));
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
/**
|
|
3109
|
+
* Validates all expectation bounds configured on one task.
|
|
3110
|
+
*
|
|
3111
|
+
* @private internal utility of `validatePipeline`
|
|
3112
|
+
*/
|
|
3113
|
+
function validateTaskExpectations(task, pipelineIdentification) {
|
|
3114
|
+
if (!task.expectations) {
|
|
3115
|
+
return;
|
|
3116
|
+
}
|
|
3117
|
+
for (const [unit, { min, max }] of Object.entries(task.expectations)) {
|
|
3118
|
+
validateTaskExpectationRange(unit, min, max, pipelineIdentification);
|
|
3119
|
+
validateTaskExpectationMin(unit, min, pipelineIdentification);
|
|
3120
|
+
validateTaskExpectationMax(unit, max, pipelineIdentification);
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
/**
|
|
3124
|
+
* Validates the minimum and maximum expectation ordering for one unit.
|
|
3125
|
+
*
|
|
3126
|
+
* @private internal utility of `validatePipeline`
|
|
3127
|
+
*/
|
|
3128
|
+
function validateTaskExpectationRange(unit, min, max, pipelineIdentification) {
|
|
3129
|
+
if (min === undefined || max === undefined || min <= max) {
|
|
3130
|
+
return;
|
|
3131
|
+
}
|
|
3132
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3133
|
+
Min expectation (=${min}) of ${unit} is higher than max expectation (=${max})
|
|
2792
3134
|
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
3135
|
+
${block(pipelineIdentification)}
|
|
3136
|
+
`));
|
|
3137
|
+
}
|
|
3138
|
+
/**
|
|
3139
|
+
* Validates the minimum expectation bound for one unit.
|
|
3140
|
+
*
|
|
3141
|
+
* @private internal utility of `validatePipeline`
|
|
3142
|
+
*/
|
|
3143
|
+
function validateTaskExpectationMin(unit, min, pipelineIdentification) {
|
|
3144
|
+
if (min === undefined || min >= 0) {
|
|
3145
|
+
return;
|
|
3146
|
+
}
|
|
3147
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3148
|
+
Min expectation of ${unit} must be zero or positive
|
|
2799
3149
|
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
3150
|
+
${block(pipelineIdentification)}
|
|
3151
|
+
`));
|
|
3152
|
+
}
|
|
3153
|
+
/**
|
|
3154
|
+
* Validates the maximum expectation bound for one unit.
|
|
3155
|
+
*
|
|
3156
|
+
* @private internal utility of `validatePipeline`
|
|
3157
|
+
*/
|
|
3158
|
+
function validateTaskExpectationMax(unit, max, pipelineIdentification) {
|
|
3159
|
+
if (max === undefined || max > 0) {
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
3163
|
+
Max expectation of ${unit} must be positive
|
|
2806
3164
|
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
3165
|
+
${block(pipelineIdentification)}
|
|
3166
|
+
`));
|
|
3167
|
+
}
|
|
3168
|
+
/**
|
|
3169
|
+
* Collects the parameter names that are already resolvable before dependency traversal starts.
|
|
3170
|
+
*
|
|
3171
|
+
* @private internal utility of `validatePipeline`
|
|
3172
|
+
*/
|
|
3173
|
+
function createInitialDependencyResolutionState(pipeline) {
|
|
3174
|
+
return {
|
|
3175
|
+
resolvedParameterNames: createInitiallyResolvedParameterNames(pipeline),
|
|
3176
|
+
unresolvedTasks: [...pipeline.tasks],
|
|
3177
|
+
};
|
|
3178
|
+
}
|
|
3179
|
+
/**
|
|
3180
|
+
* Checks whether dependency resolution still has tasks left to process.
|
|
3181
|
+
*
|
|
3182
|
+
* @private internal utility of `validatePipeline`
|
|
3183
|
+
*/
|
|
3184
|
+
function hasUnresolvedTasks({ unresolvedTasks }) {
|
|
3185
|
+
return unresolvedTasks.length > 0;
|
|
3186
|
+
}
|
|
3187
|
+
/**
|
|
3188
|
+
* Resolves the next batch of currently satisfiable tasks.
|
|
3189
|
+
*
|
|
3190
|
+
* @private internal utility of `validatePipeline`
|
|
3191
|
+
*/
|
|
3192
|
+
function resolveNextDependencyResolutionState(dependencyResolutionState, pipelineIdentification) {
|
|
3193
|
+
const currentlyResolvedTasks = getCurrentlyResolvedTasks(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames);
|
|
3194
|
+
if (currentlyResolvedTasks.length === 0) {
|
|
3195
|
+
throw createUnresolvedTasksError(dependencyResolutionState.unresolvedTasks, dependencyResolutionState.resolvedParameterNames, pipelineIdentification);
|
|
2812
3196
|
}
|
|
2813
|
-
|
|
2814
|
-
|
|
3197
|
+
return {
|
|
3198
|
+
resolvedParameterNames: appendResolvedTaskParameterNames(dependencyResolutionState.resolvedParameterNames, currentlyResolvedTasks),
|
|
3199
|
+
unresolvedTasks: dependencyResolutionState.unresolvedTasks.filter((task) => !currentlyResolvedTasks.includes(task)),
|
|
3200
|
+
};
|
|
3201
|
+
}
|
|
3202
|
+
/**
|
|
3203
|
+
* Collects the parameter names that are already resolvable before dependency traversal starts.
|
|
3204
|
+
*
|
|
3205
|
+
* @private internal utility of `validatePipeline`
|
|
3206
|
+
*/
|
|
3207
|
+
function createInitiallyResolvedParameterNames(pipeline) {
|
|
3208
|
+
let resolvedParameterNames = pipeline.parameters
|
|
2815
3209
|
.filter(({ isInput }) => isInput)
|
|
2816
3210
|
.map(({ name }) => name);
|
|
2817
|
-
// Note: All reserved parameters are resolved
|
|
2818
3211
|
for (const reservedParameterName of RESERVED_PARAMETER_NAMES) {
|
|
2819
|
-
|
|
3212
|
+
resolvedParameterNames = [...resolvedParameterNames, reservedParameterName];
|
|
2820
3213
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
3214
|
+
return resolvedParameterNames;
|
|
3215
|
+
}
|
|
3216
|
+
/**
|
|
3217
|
+
* Adds newly resolved task outputs to the resolved parameter list.
|
|
3218
|
+
*
|
|
3219
|
+
* @private internal utility of `validatePipeline`
|
|
3220
|
+
*/
|
|
3221
|
+
function appendResolvedTaskParameterNames(resolvedParameterNames, currentlyResolvedTasks) {
|
|
3222
|
+
return [
|
|
3223
|
+
...resolvedParameterNames,
|
|
3224
|
+
...currentlyResolvedTasks.map(({ resultingParameterName }) => resultingParameterName),
|
|
3225
|
+
];
|
|
3226
|
+
}
|
|
3227
|
+
/**
|
|
3228
|
+
* Selects tasks whose dependencies are already resolved.
|
|
3229
|
+
*
|
|
3230
|
+
* @private internal utility of `validatePipeline`
|
|
3231
|
+
*/
|
|
3232
|
+
function getCurrentlyResolvedTasks(unresolvedTasks, resolvedParameterNames) {
|
|
3233
|
+
return unresolvedTasks.filter((task) => task.dependentParameterNames.every((name) => resolvedParameterNames.includes(name)));
|
|
3234
|
+
}
|
|
3235
|
+
/**
|
|
3236
|
+
* Creates the unexpected loop-limit error for dependency resolution.
|
|
3237
|
+
*
|
|
3238
|
+
* @private internal utility of `validatePipeline`
|
|
3239
|
+
*/
|
|
3240
|
+
function createDependencyResolutionLoopLimitError(pipelineIdentification) {
|
|
3241
|
+
// Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
|
|
3242
|
+
return new UnexpectedError(spaceTrim$1((block) => `
|
|
3243
|
+
Loop limit reached during detection of circular dependencies in \`validatePipeline\`
|
|
2828
3244
|
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
3245
|
+
${block(pipelineIdentification)}
|
|
3246
|
+
`));
|
|
3247
|
+
}
|
|
3248
|
+
/**
|
|
3249
|
+
* Creates the detailed error for unresolved or circular task dependencies.
|
|
3250
|
+
*
|
|
3251
|
+
* @private internal utility of `validatePipeline`
|
|
3252
|
+
*/
|
|
3253
|
+
function createUnresolvedTasksError(unresolvedTasks, resolvedParameterNames, pipelineIdentification) {
|
|
3254
|
+
return new PipelineLogicError(
|
|
3255
|
+
// TODO: [🐎] DRY
|
|
3256
|
+
spaceTrim$1((block) => `
|
|
2837
3257
|
|
|
2838
|
-
|
|
2839
|
-
|
|
3258
|
+
Can not resolve some parameters:
|
|
3259
|
+
Either you are using a parameter that is not defined, or there are some circular dependencies.
|
|
2840
3260
|
|
|
2841
|
-
|
|
3261
|
+
${block(pipelineIdentification)}
|
|
2842
3262
|
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
3263
|
+
**Can not resolve:**
|
|
3264
|
+
${block(unresolvedTasks
|
|
3265
|
+
.map(({ resultingParameterName, dependentParameterNames }) => `- Parameter \`{${resultingParameterName}}\` which depends on ${dependentParameterNames
|
|
3266
|
+
.map((dependentParameterName) => `\`{${dependentParameterName}}\``)
|
|
3267
|
+
.join(' and ')}`)
|
|
3268
|
+
.join('\n'))}
|
|
2849
3269
|
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
3270
|
+
**Resolved:**
|
|
3271
|
+
${block(resolvedParameterNames
|
|
3272
|
+
.filter((name) => !RESERVED_PARAMETER_NAMES.includes(name))
|
|
3273
|
+
.map((name) => `- Parameter \`{${name}}\``)
|
|
3274
|
+
.join('\n'))}
|
|
2855
3275
|
|
|
2856
3276
|
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
3277
|
+
**Reserved (which are available):**
|
|
3278
|
+
${block(resolvedParameterNames
|
|
3279
|
+
.filter((name) => RESERVED_PARAMETER_NAMES.includes(name))
|
|
3280
|
+
.map((name) => `- Parameter \`{${name}}\``)
|
|
3281
|
+
.join('\n'))}
|
|
2862
3282
|
|
|
2863
3283
|
|
|
2864
|
-
|
|
2865
|
-
}
|
|
2866
|
-
resovedParameters = [
|
|
2867
|
-
...resovedParameters,
|
|
2868
|
-
...currentlyResovedTasks.map(({ resultingParameterName }) => resultingParameterName),
|
|
2869
|
-
];
|
|
2870
|
-
unresovedTasks = unresovedTasks.filter((task) => !currentlyResovedTasks.includes(task));
|
|
2871
|
-
}
|
|
2872
|
-
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
2873
|
-
// TODO: !!6 Implement this
|
|
2874
|
-
// pipeline.formfactorName
|
|
3284
|
+
`));
|
|
2875
3285
|
}
|
|
2876
3286
|
/**
|
|
2877
3287
|
* TODO: [🧞♀️] Do not allow joker + foreach
|
|
@@ -3567,77 +3977,288 @@ function assertsTaskSuccessful(executionResult) {
|
|
|
3567
3977
|
// TODO: [🧠] Can this return type be better typed than void
|
|
3568
3978
|
|
|
3569
3979
|
/**
|
|
3570
|
-
*
|
|
3980
|
+
* Resolves the short task summary shown in the UI.
|
|
3571
3981
|
*
|
|
3572
|
-
* @private internal helper function
|
|
3982
|
+
* @private internal helper function of `ExecutionTask`
|
|
3573
3983
|
*/
|
|
3574
|
-
function
|
|
3575
|
-
const {
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3984
|
+
function resolveTaskTldr(options) {
|
|
3985
|
+
const { customTldr } = options;
|
|
3986
|
+
if (customTldr) {
|
|
3987
|
+
return customTldr;
|
|
3988
|
+
}
|
|
3989
|
+
return {
|
|
3990
|
+
percent: resolveTaskPercent(options),
|
|
3991
|
+
message: `${resolveTaskMessage(options)} (!!!fallback)`,
|
|
3992
|
+
};
|
|
3993
|
+
}
|
|
3994
|
+
/**
|
|
3995
|
+
* Resolves the best progress percentage for the current task state.
|
|
3996
|
+
*
|
|
3997
|
+
* @private internal helper function of `ExecutionTask`
|
|
3998
|
+
*/
|
|
3999
|
+
function resolveTaskPercent(options) {
|
|
4000
|
+
const explicitPercent = getExplicitTaskPercent(options.currentValue);
|
|
4001
|
+
if (typeof explicitPercent === 'number') {
|
|
4002
|
+
return normalizeTaskPercent(explicitPercent);
|
|
4003
|
+
}
|
|
4004
|
+
return normalizeTaskPercent(calculateSimulatedTaskPercent(options));
|
|
4005
|
+
}
|
|
4006
|
+
/**
|
|
4007
|
+
* Picks a directly reported progress percentage from the task result snapshot.
|
|
4008
|
+
*
|
|
4009
|
+
* @private internal helper function of `ExecutionTask`
|
|
4010
|
+
*/
|
|
4011
|
+
function getExplicitTaskPercent(currentValue) {
|
|
4012
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4013
|
+
return ((_f = (_d = (_b = (_a = currentValue === null || currentValue === void 0 ? void 0 : currentValue.tldr) === null || _a === void 0 ? void 0 : _a.percent) !== null && _b !== void 0 ? _b : (_c = currentValue === null || currentValue === void 0 ? void 0 : currentValue.usage) === null || _c === void 0 ? void 0 : _c.percent) !== null && _d !== void 0 ? _d : (_e = currentValue === null || currentValue === void 0 ? void 0 : currentValue.progress) === null || _e === void 0 ? void 0 : _e.percent) !== null && _f !== void 0 ? _f : currentValue === null || currentValue === void 0 ? void 0 : currentValue.percent);
|
|
4014
|
+
}
|
|
4015
|
+
/**
|
|
4016
|
+
* Simulates progress when the task result does not expose an explicit percentage.
|
|
4017
|
+
*
|
|
4018
|
+
* @private internal helper function of `ExecutionTask`
|
|
4019
|
+
*/
|
|
4020
|
+
function calculateSimulatedTaskPercent(options) {
|
|
4021
|
+
const { currentValue, status, createdAt } = options;
|
|
4022
|
+
const elapsedMs = new Date().getTime() - createdAt.getTime();
|
|
4023
|
+
const timeProgress = Math.min(elapsedMs / DEFAULT_TASK_SIMULATED_DURATION_MS, 1);
|
|
4024
|
+
const { subtaskCount, completedSubtasks } = summarizeTaskSubtasks(currentValue);
|
|
4025
|
+
if (status === 'FINISHED') {
|
|
4026
|
+
return 1;
|
|
4027
|
+
}
|
|
4028
|
+
if (status === 'ERROR') {
|
|
4029
|
+
return 0;
|
|
4030
|
+
}
|
|
4031
|
+
return Math.min(completedSubtasks / subtaskCount + (1 / subtaskCount) * timeProgress, 1);
|
|
4032
|
+
}
|
|
4033
|
+
/**
|
|
4034
|
+
* Counts total and completed subtasks used by the fallback progress simulation.
|
|
4035
|
+
*
|
|
4036
|
+
* @private internal helper function of `ExecutionTask`
|
|
4037
|
+
*/
|
|
4038
|
+
function summarizeTaskSubtasks(currentValue) {
|
|
4039
|
+
if (!Array.isArray(currentValue === null || currentValue === void 0 ? void 0 : currentValue.subtasks)) {
|
|
4040
|
+
return { subtaskCount: 1, completedSubtasks: 0 };
|
|
4041
|
+
}
|
|
4042
|
+
return {
|
|
4043
|
+
subtaskCount: currentValue.subtasks.length || 1,
|
|
4044
|
+
completedSubtasks: currentValue.subtasks.filter(isTaskSubtaskCompleted).length,
|
|
4045
|
+
};
|
|
4046
|
+
}
|
|
4047
|
+
/**
|
|
4048
|
+
* Tells whether a task subtask is already finished.
|
|
4049
|
+
*
|
|
4050
|
+
* @private internal helper function of `ExecutionTask`
|
|
4051
|
+
*/
|
|
4052
|
+
function isTaskSubtaskCompleted(subtask) {
|
|
4053
|
+
return subtask.done || subtask.completed || false;
|
|
4054
|
+
}
|
|
4055
|
+
/**
|
|
4056
|
+
* Normalizes a progress percentage into the expected `0..1` range.
|
|
4057
|
+
*
|
|
4058
|
+
* @private internal helper function of `ExecutionTask`
|
|
4059
|
+
*/
|
|
4060
|
+
function normalizeTaskPercent(percentRaw) {
|
|
4061
|
+
let percent = Number(percentRaw) || 0;
|
|
4062
|
+
if (percent < 0) {
|
|
4063
|
+
percent = 0;
|
|
4064
|
+
}
|
|
4065
|
+
if (percent > 1) {
|
|
4066
|
+
percent = 1;
|
|
4067
|
+
}
|
|
4068
|
+
return percent;
|
|
4069
|
+
}
|
|
4070
|
+
/**
|
|
4071
|
+
* Resolves the best human-readable status message for the current task state.
|
|
4072
|
+
*
|
|
4073
|
+
* @private internal helper function of `ExecutionTask`
|
|
4074
|
+
*/
|
|
4075
|
+
function resolveTaskMessage(options) {
|
|
4076
|
+
return (getCurrentValueMessage(options.currentValue) ||
|
|
4077
|
+
getCurrentSubtaskMessage(options.currentValue) ||
|
|
4078
|
+
getLatestIssueMessage(options.errors, 'Error') ||
|
|
4079
|
+
getLatestIssueMessage(options.warnings, 'Warning') ||
|
|
4080
|
+
getStatusMessage(options.status));
|
|
4081
|
+
}
|
|
4082
|
+
/**
|
|
4083
|
+
* Picks a message already reported by the current task result snapshot.
|
|
4084
|
+
*
|
|
4085
|
+
* @private internal helper function of `ExecutionTask`
|
|
4086
|
+
*/
|
|
4087
|
+
function getCurrentValueMessage(currentValue) {
|
|
4088
|
+
var _a, _b, _c, _d;
|
|
4089
|
+
return (_d = (_c = (_b = (_a = currentValue === null || currentValue === void 0 ? void 0 : currentValue.tldr) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : currentValue === null || currentValue === void 0 ? void 0 : currentValue.message) !== null && _c !== void 0 ? _c : currentValue === null || currentValue === void 0 ? void 0 : currentValue.summary) !== null && _d !== void 0 ? _d : currentValue === null || currentValue === void 0 ? void 0 : currentValue.statusMessage;
|
|
4090
|
+
}
|
|
4091
|
+
/**
|
|
4092
|
+
* Builds a fallback message from the first unfinished subtask title.
|
|
4093
|
+
*
|
|
4094
|
+
* @private internal helper function of `ExecutionTask`
|
|
4095
|
+
*/
|
|
4096
|
+
function getCurrentSubtaskMessage(currentValue) {
|
|
4097
|
+
if (!Array.isArray(currentValue === null || currentValue === void 0 ? void 0 : currentValue.subtasks) || currentValue.subtasks.length === 0) {
|
|
4098
|
+
return undefined;
|
|
4099
|
+
}
|
|
4100
|
+
const currentSubtask = currentValue.subtasks.find((subtask) => !isTaskSubtaskCompleted(subtask));
|
|
4101
|
+
if (!(currentSubtask === null || currentSubtask === void 0 ? void 0 : currentSubtask.title)) {
|
|
4102
|
+
return undefined;
|
|
4103
|
+
}
|
|
4104
|
+
return `Working on ${currentSubtask.title}`;
|
|
4105
|
+
}
|
|
4106
|
+
/**
|
|
4107
|
+
* Picks the latest error or warning message, with the legacy generic fallback label.
|
|
4108
|
+
*
|
|
4109
|
+
* @private internal helper function of `ExecutionTask`
|
|
4110
|
+
*/
|
|
4111
|
+
function getLatestIssueMessage(issues, fallbackMessage) {
|
|
4112
|
+
if (issues.length === 0) {
|
|
4113
|
+
return undefined;
|
|
4114
|
+
}
|
|
4115
|
+
return issues[issues.length - 1].message || fallbackMessage;
|
|
4116
|
+
}
|
|
4117
|
+
/**
|
|
4118
|
+
* Builds the final status-based fallback message.
|
|
4119
|
+
*
|
|
4120
|
+
* @private internal helper function of `ExecutionTask`
|
|
4121
|
+
*/
|
|
4122
|
+
function getStatusMessage(status) {
|
|
4123
|
+
if (status === 'FINISHED') {
|
|
4124
|
+
return 'Finished';
|
|
4125
|
+
}
|
|
4126
|
+
if (status === 'ERROR') {
|
|
4127
|
+
return 'Error';
|
|
4128
|
+
}
|
|
4129
|
+
return 'Running';
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4132
|
+
/**
|
|
4133
|
+
* Creates the initial mutable state for a task.
|
|
4134
|
+
*
|
|
4135
|
+
* @private internal helper function
|
|
4136
|
+
*/
|
|
4137
|
+
function createTaskState(title, createdAt) {
|
|
4138
|
+
return {
|
|
4139
|
+
title,
|
|
4140
|
+
status: 'RUNNING',
|
|
4141
|
+
updatedAt: createdAt,
|
|
4142
|
+
errors: [],
|
|
4143
|
+
warnings: [],
|
|
4144
|
+
llmCalls: [],
|
|
4145
|
+
currentValue: {},
|
|
4146
|
+
customTldr: null,
|
|
4147
|
+
};
|
|
4148
|
+
}
|
|
4149
|
+
/**
|
|
4150
|
+
* Creates the partial-result updater passed into the task process callback.
|
|
4151
|
+
*
|
|
4152
|
+
* @private internal helper function
|
|
4153
|
+
*/
|
|
4154
|
+
function createOngoingResultUpdater(taskState, partialResultSubject) {
|
|
4155
|
+
return (newOngoingResult) => {
|
|
4156
|
+
if (newOngoingResult.title) {
|
|
4157
|
+
taskState.title = newOngoingResult.title;
|
|
4158
|
+
}
|
|
4159
|
+
taskState.updatedAt = new Date();
|
|
4160
|
+
Object.assign(taskState.currentValue, newOngoingResult);
|
|
4161
|
+
// <- TODO: assign deep
|
|
4162
|
+
partialResultSubject.next(newOngoingResult);
|
|
4163
|
+
};
|
|
4164
|
+
}
|
|
4165
|
+
/**
|
|
4166
|
+
* Creates the custom-TLDR updater passed into the task process callback.
|
|
4167
|
+
*
|
|
4168
|
+
* @private internal helper function
|
|
4169
|
+
*/
|
|
4170
|
+
function createTldrUpdater(taskState) {
|
|
4171
|
+
return (tldrInfo) => {
|
|
4172
|
+
taskState.customTldr = tldrInfo;
|
|
4173
|
+
taskState.updatedAt = new Date();
|
|
4174
|
+
};
|
|
4175
|
+
}
|
|
4176
|
+
/**
|
|
4177
|
+
* Creates the LLM call logger passed into the task process callback.
|
|
4178
|
+
*
|
|
4179
|
+
* @private internal helper function
|
|
4180
|
+
*/
|
|
4181
|
+
function createLlmCallLogger(taskState) {
|
|
4182
|
+
return (llmCall) => {
|
|
4183
|
+
taskState.llmCalls.push(llmCall);
|
|
4184
|
+
taskState.updatedAt = new Date();
|
|
4185
|
+
};
|
|
4186
|
+
}
|
|
4187
|
+
/**
|
|
4188
|
+
* Wires the task promise into the observable/error lifecycle.
|
|
4189
|
+
*
|
|
4190
|
+
* @private internal helper function
|
|
4191
|
+
*/
|
|
4192
|
+
function settleTaskPromise(finalResultPromise, taskState, partialResultSubject) {
|
|
4193
|
+
finalResultPromise
|
|
4194
|
+
.catch((error) => {
|
|
4195
|
+
taskState.errors.push(error);
|
|
4196
|
+
partialResultSubject.error(error);
|
|
4197
|
+
})
|
|
4198
|
+
.then((executionResult) => {
|
|
4199
|
+
if (executionResult) {
|
|
4200
|
+
try {
|
|
4201
|
+
finalizeTaskResult(executionResult, taskState, partialResultSubject);
|
|
4202
|
+
}
|
|
4203
|
+
catch (error) {
|
|
4204
|
+
failTaskResult(error, taskState, partialResultSubject);
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
partialResultSubject.complete();
|
|
4208
|
+
});
|
|
4209
|
+
}
|
|
4210
|
+
/**
|
|
4211
|
+
* Applies the final successful task result into the mutable task state.
|
|
4212
|
+
*
|
|
4213
|
+
* @private internal helper function
|
|
4214
|
+
*/
|
|
4215
|
+
function finalizeTaskResult(executionResult, taskState, partialResultSubject) {
|
|
4216
|
+
taskState.updatedAt = new Date();
|
|
4217
|
+
taskState.errors.push(...executionResult.errors);
|
|
4218
|
+
taskState.warnings.push(...executionResult.warnings);
|
|
4219
|
+
// <- TODO: [🌂] Only unique errors and warnings should be added (or filtered)
|
|
4220
|
+
// TODO: [🧠] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
|
|
4221
|
+
// Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
|
|
4222
|
+
// And delete `ExecutionTask.currentValue.preparedPipeline`
|
|
4223
|
+
assertsTaskSuccessful(executionResult);
|
|
4224
|
+
taskState.status = 'FINISHED';
|
|
4225
|
+
taskState.currentValue = jsonStringsToJsons(executionResult);
|
|
4226
|
+
// <- TODO: [🧠] Is this a good idea to convert JSON strins to JSONs?
|
|
4227
|
+
partialResultSubject.next(executionResult);
|
|
4228
|
+
}
|
|
4229
|
+
/**
|
|
4230
|
+
* Records a final-result failure after the task promise itself resolved.
|
|
4231
|
+
*
|
|
4232
|
+
* @private internal helper function
|
|
4233
|
+
*/
|
|
4234
|
+
function failTaskResult(error, taskState, partialResultSubject) {
|
|
4235
|
+
assertsError(error);
|
|
4236
|
+
taskState.status = 'ERROR';
|
|
4237
|
+
taskState.errors.push(error);
|
|
4238
|
+
partialResultSubject.error(error);
|
|
4239
|
+
}
|
|
4240
|
+
/**
|
|
4241
|
+
* Helper to create a new task
|
|
4242
|
+
*
|
|
4243
|
+
* @private internal helper function
|
|
4244
|
+
*/
|
|
4245
|
+
function createTask(options) {
|
|
4246
|
+
const { taskType, title, taskProcessCallback } = options;
|
|
4247
|
+
// TODO: [🐙] DRY
|
|
4248
|
+
const taskId = `${taskType.toLowerCase().substring(0, 4)}-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
|
|
4249
|
+
const createdAt = new Date();
|
|
4250
|
+
const taskState = createTaskState(title, createdAt);
|
|
4251
|
+
const partialResultSubject = new Subject();
|
|
4252
|
+
// <- Note: Not using `BehaviorSubject` because on error we can't access the last value
|
|
4253
|
+
const finalResultPromise = /* not await */ taskProcessCallback(createOngoingResultUpdater(taskState, partialResultSubject), createTldrUpdater(taskState), createLlmCallLogger(taskState));
|
|
4254
|
+
settleTaskPromise(finalResultPromise, taskState, partialResultSubject);
|
|
4255
|
+
async function asPromise(options) {
|
|
4256
|
+
const { isCrashedOnError = true } = options || {};
|
|
4257
|
+
const finalResult = await finalResultPromise;
|
|
4258
|
+
if (isCrashedOnError) {
|
|
4259
|
+
assertsTaskSuccessful(finalResult);
|
|
4260
|
+
}
|
|
4261
|
+
return finalResult;
|
|
3641
4262
|
}
|
|
3642
4263
|
return {
|
|
3643
4264
|
taskType,
|
|
@@ -3646,91 +4267,29 @@ function createTask(options) {
|
|
|
3646
4267
|
return PROMPTBOOK_ENGINE_VERSION;
|
|
3647
4268
|
},
|
|
3648
4269
|
get title() {
|
|
3649
|
-
return title;
|
|
4270
|
+
return taskState.title;
|
|
3650
4271
|
// <- Note: [1] These must be getters to allow changing the value in the future
|
|
3651
4272
|
},
|
|
3652
4273
|
get status() {
|
|
3653
|
-
return status;
|
|
4274
|
+
return taskState.status;
|
|
3654
4275
|
// <- Note: [1] --||--
|
|
3655
4276
|
},
|
|
3656
4277
|
get tldr() {
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
let percentRaw = (_f = (_d = (_b = (_a = cv === null || cv === void 0 ? void 0 : cv.tldr) === null || _a === void 0 ? void 0 : _a.percent) !== null && _b !== void 0 ? _b : (_c = cv === null || cv === void 0 ? void 0 : cv.usage) === null || _c === void 0 ? void 0 : _c.percent) !== null && _d !== void 0 ? _d : (_e = cv === null || cv === void 0 ? void 0 : cv.progress) === null || _e === void 0 ? void 0 : _e.percent) !== null && _f !== void 0 ? _f : cv === null || cv === void 0 ? void 0 : cv.percent;
|
|
3666
|
-
// Simulate progress if not provided
|
|
3667
|
-
if (typeof percentRaw !== 'number') {
|
|
3668
|
-
// Simulate progress: evenly split across subtasks, based on elapsed time
|
|
3669
|
-
const now = new Date();
|
|
3670
|
-
const elapsedMs = now.getTime() - createdAt.getTime();
|
|
3671
|
-
const totalMs = DEFAULT_TASK_SIMULATED_DURATION_MS;
|
|
3672
|
-
// If subtasks are defined, split progress evenly
|
|
3673
|
-
const subtaskCount = Array.isArray(cv === null || cv === void 0 ? void 0 : cv.subtasks) ? cv.subtasks.length : 1;
|
|
3674
|
-
const completedSubtasks = Array.isArray(cv === null || cv === void 0 ? void 0 : cv.subtasks)
|
|
3675
|
-
? cv.subtasks.filter((s) => s.done || s.completed).length
|
|
3676
|
-
: 0;
|
|
3677
|
-
// Progress from completed subtasks
|
|
3678
|
-
const subtaskProgress = subtaskCount > 0 ? completedSubtasks / subtaskCount : 0;
|
|
3679
|
-
// Progress from elapsed time for current subtask
|
|
3680
|
-
const timeProgress = Math.min(elapsedMs / totalMs, 1);
|
|
3681
|
-
// Combine: completed subtasks + time progress for current subtask
|
|
3682
|
-
percentRaw = Math.min(subtaskProgress + (1 / subtaskCount) * timeProgress, 1);
|
|
3683
|
-
if (status === 'FINISHED')
|
|
3684
|
-
percentRaw = 1;
|
|
3685
|
-
if (status === 'ERROR')
|
|
3686
|
-
percentRaw = 0;
|
|
3687
|
-
}
|
|
3688
|
-
// Clamp to [0,1]
|
|
3689
|
-
let percent = Number(percentRaw) || 0;
|
|
3690
|
-
if (percent < 0)
|
|
3691
|
-
percent = 0;
|
|
3692
|
-
if (percent > 1)
|
|
3693
|
-
percent = 1;
|
|
3694
|
-
// Build a short message: prefer explicit tldr.message, then common summary/message fields, then errors/warnings, then status
|
|
3695
|
-
const messageFromResult = (_k = (_j = (_h = (_g = cv === null || cv === void 0 ? void 0 : cv.tldr) === null || _g === void 0 ? void 0 : _g.message) !== null && _h !== void 0 ? _h : cv === null || cv === void 0 ? void 0 : cv.message) !== null && _j !== void 0 ? _j : cv === null || cv === void 0 ? void 0 : cv.summary) !== null && _k !== void 0 ? _k : cv === null || cv === void 0 ? void 0 : cv.statusMessage;
|
|
3696
|
-
let message = messageFromResult;
|
|
3697
|
-
if (!message) {
|
|
3698
|
-
// If subtasks, show current subtask
|
|
3699
|
-
if (Array.isArray(cv === null || cv === void 0 ? void 0 : cv.subtasks) && cv.subtasks.length > 0) {
|
|
3700
|
-
const current = cv.subtasks.find((s) => !s.done && !s.completed);
|
|
3701
|
-
if (current && current.title) {
|
|
3702
|
-
message = `Working on ${current.title}`;
|
|
3703
|
-
}
|
|
3704
|
-
}
|
|
3705
|
-
if (!message) {
|
|
3706
|
-
if (errors.length) {
|
|
3707
|
-
message = errors[errors.length - 1].message || 'Error';
|
|
3708
|
-
}
|
|
3709
|
-
else if (warnings.length) {
|
|
3710
|
-
message = warnings[warnings.length - 1].message || 'Warning';
|
|
3711
|
-
}
|
|
3712
|
-
else if (status === 'FINISHED') {
|
|
3713
|
-
message = 'Finished';
|
|
3714
|
-
}
|
|
3715
|
-
else if (status === 'ERROR') {
|
|
3716
|
-
message = 'Error';
|
|
3717
|
-
}
|
|
3718
|
-
else {
|
|
3719
|
-
message = 'Running';
|
|
3720
|
-
}
|
|
3721
|
-
}
|
|
3722
|
-
}
|
|
3723
|
-
return {
|
|
3724
|
-
percent: percent,
|
|
3725
|
-
message: message + ' (!!!fallback)',
|
|
3726
|
-
};
|
|
4278
|
+
return resolveTaskTldr({
|
|
4279
|
+
customTldr: taskState.customTldr,
|
|
4280
|
+
currentValue: taskState.currentValue,
|
|
4281
|
+
status: taskState.status,
|
|
4282
|
+
createdAt,
|
|
4283
|
+
errors: taskState.errors,
|
|
4284
|
+
warnings: taskState.warnings,
|
|
4285
|
+
});
|
|
3727
4286
|
},
|
|
3728
4287
|
get createdAt() {
|
|
3729
4288
|
return createdAt;
|
|
3730
4289
|
// <- Note: [1] --||--
|
|
3731
4290
|
},
|
|
3732
4291
|
get updatedAt() {
|
|
3733
|
-
return updatedAt;
|
|
4292
|
+
return taskState.updatedAt;
|
|
3734
4293
|
// <- Note: [1] --||--
|
|
3735
4294
|
},
|
|
3736
4295
|
asPromise,
|
|
@@ -3738,19 +4297,19 @@ function createTask(options) {
|
|
|
3738
4297
|
return partialResultSubject.asObservable();
|
|
3739
4298
|
},
|
|
3740
4299
|
get errors() {
|
|
3741
|
-
return errors;
|
|
4300
|
+
return taskState.errors;
|
|
3742
4301
|
// <- Note: [1] --||--
|
|
3743
4302
|
},
|
|
3744
4303
|
get warnings() {
|
|
3745
|
-
return warnings;
|
|
4304
|
+
return taskState.warnings;
|
|
3746
4305
|
// <- Note: [1] --||--
|
|
3747
4306
|
},
|
|
3748
4307
|
get llmCalls() {
|
|
3749
|
-
return [...llmCalls, { foo: '!!! bar' }];
|
|
4308
|
+
return [...taskState.llmCalls, { foo: '!!! bar' }];
|
|
3750
4309
|
// <- Note: [1] --||--
|
|
3751
4310
|
},
|
|
3752
4311
|
get currentValue() {
|
|
3753
|
-
return currentValue;
|
|
4312
|
+
return taskState.currentValue;
|
|
3754
4313
|
// <- Note: [1] --||--
|
|
3755
4314
|
},
|
|
3756
4315
|
};
|
|
@@ -4668,210 +5227,275 @@ const promptbookFetch = async (urlOrRequest, init) => {
|
|
|
4668
5227
|
* @public exported from `@promptbook/core`
|
|
4669
5228
|
*/
|
|
4670
5229
|
async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
5230
|
+
const { knowledgeSourceContent } = knowledgeSource;
|
|
5231
|
+
const name = knowledgeSource.name || knowledgeSourceContentToName(knowledgeSourceContent);
|
|
5232
|
+
const { rootDirname = null, isVerbose = DEFAULT_IS_VERBOSE } = options || {};
|
|
5233
|
+
if (isValidUrl(knowledgeSourceContent)) {
|
|
5234
|
+
return makeUrlKnowledgeSourceHandler(knowledgeSourceContent, name, tools, options, isVerbose);
|
|
5235
|
+
}
|
|
5236
|
+
if (isValidFilePath(knowledgeSourceContent)) {
|
|
5237
|
+
return makeFileKnowledgeSourceHandler(knowledgeSourceContent, name, tools, rootDirname, isVerbose);
|
|
5238
|
+
}
|
|
5239
|
+
return makeInlineTextKnowledgeSourceHandler(knowledgeSourceContent, name, isVerbose);
|
|
5240
|
+
}
|
|
5241
|
+
/**
|
|
5242
|
+
* Creates a source handler for URL-based knowledge.
|
|
5243
|
+
*
|
|
5244
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5245
|
+
*/
|
|
5246
|
+
async function makeUrlKnowledgeSourceHandler(url, name, tools, options, isVerbose) {
|
|
4671
5247
|
var _a;
|
|
4672
5248
|
const { fetch = promptbookFetch } = tools;
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
const { rootDirname = null,
|
|
4676
|
-
// <- TODO: process.cwd() if running in Node.js
|
|
4677
|
-
isVerbose = DEFAULT_IS_VERBOSE, } = options || {};
|
|
4678
|
-
if (!name) {
|
|
4679
|
-
name = knowledgeSourceContentToName(knowledgeSourceContent);
|
|
5249
|
+
if (isVerbose) {
|
|
5250
|
+
console.info(`📄 [1] "${name}" is available at "${url}"`);
|
|
4680
5251
|
}
|
|
4681
|
-
|
|
4682
|
-
|
|
5252
|
+
const response = await fetch(url); // <- TODO: [🧠] Scraping and fetch proxy
|
|
5253
|
+
const mimeType = ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0]) || 'text/html';
|
|
5254
|
+
if (tools.fs === undefined || !url.endsWith('.pdf' /* <- TODO: [💵] */)) {
|
|
5255
|
+
return makeRemoteResponseKnowledgeSourceHandler(name, url, mimeType, response, isVerbose);
|
|
5256
|
+
}
|
|
5257
|
+
return cachePdfKnowledgeSourceHandler(url, name, mimeType, response, tools, options, isVerbose);
|
|
5258
|
+
}
|
|
5259
|
+
/**
|
|
5260
|
+
* Creates a source handler that reads directly from a fetched response.
|
|
5261
|
+
*
|
|
5262
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5263
|
+
*/
|
|
5264
|
+
function makeRemoteResponseKnowledgeSourceHandler(name, url, mimeType, response, isVerbose) {
|
|
5265
|
+
if (isVerbose) {
|
|
5266
|
+
console.info(`📄 [2] "${name}" tools.fs is not available or URL is not a PDF.`);
|
|
5267
|
+
}
|
|
5268
|
+
return {
|
|
5269
|
+
source: name,
|
|
5270
|
+
filename: null,
|
|
5271
|
+
url,
|
|
5272
|
+
mimeType,
|
|
5273
|
+
/*
|
|
5274
|
+
TODO: [🥽]
|
|
5275
|
+
> async asBlob() {
|
|
5276
|
+
> // TODO: [👨🏻🤝👨🏻] This can be called multiple times BUT when called second time, response in already consumed
|
|
5277
|
+
> const content = await response.blob();
|
|
5278
|
+
> return content;
|
|
5279
|
+
> },
|
|
5280
|
+
*/
|
|
5281
|
+
async asJson() {
|
|
5282
|
+
// TODO: [👨🏻🤝👨🏻]
|
|
5283
|
+
const content = await response.json();
|
|
5284
|
+
return content;
|
|
5285
|
+
},
|
|
5286
|
+
async asText() {
|
|
5287
|
+
// TODO: [👨🏻🤝👨🏻]
|
|
5288
|
+
const content = await response.text();
|
|
5289
|
+
return content;
|
|
5290
|
+
},
|
|
5291
|
+
};
|
|
5292
|
+
}
|
|
5293
|
+
/**
|
|
5294
|
+
* Downloads a PDF knowledge source into cache when possible and falls back to in-memory content otherwise.
|
|
5295
|
+
*
|
|
5296
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5297
|
+
*/
|
|
5298
|
+
async function cachePdfKnowledgeSourceHandler(url, name, mimeType, response, tools, options, isVerbose) {
|
|
5299
|
+
const rootDirname = join(process.cwd(), DEFAULT_DOWNLOAD_CACHE_DIRNAME);
|
|
5300
|
+
const filepath = createDownloadedKnowledgeSourceFilepath(url, mimeType);
|
|
5301
|
+
const fullFilepath = join(rootDirname, filepath);
|
|
5302
|
+
await createCacheDirectoryIfPossible(name, fullFilepath, tools, isVerbose);
|
|
5303
|
+
const fileContent = Buffer.from(await response.arrayBuffer());
|
|
5304
|
+
if (fileContent.length > DEFAULT_MAX_FILE_SIZE /* <- TODO: Allow to pass different value to remote server */) {
|
|
5305
|
+
throw new LimitReachedError(`File is too large (${Math.round(fileContent.length / 1024 / 1024)}MB). Maximum allowed size is ${Math.round(DEFAULT_MAX_FILE_SIZE / 1024 / 1024)}MB.`);
|
|
5306
|
+
}
|
|
5307
|
+
const isCached = await writeCacheFileIfPossible(name, fullFilepath, fileContent, tools, isVerbose);
|
|
5308
|
+
if (!isCached) {
|
|
5309
|
+
return makeBufferedKnowledgeSourceHandler(name, url, mimeType, fileContent);
|
|
5310
|
+
}
|
|
5311
|
+
// TODO: [💵] Check the file security
|
|
5312
|
+
// TODO: [🧹][🧠] Delete the file after the scraping is done
|
|
5313
|
+
if (isVerbose) {
|
|
5314
|
+
console.info(`📄 [5] "${name}" cached at "${fullFilepath}"`);
|
|
5315
|
+
}
|
|
5316
|
+
return makeKnowledgeSourceHandler({ name, knowledgeSourceContent: filepath }, tools, {
|
|
5317
|
+
...options,
|
|
5318
|
+
rootDirname,
|
|
5319
|
+
});
|
|
5320
|
+
}
|
|
5321
|
+
/**
|
|
5322
|
+
* Builds a stable cache filepath for a downloaded knowledge source.
|
|
5323
|
+
*
|
|
5324
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5325
|
+
*/
|
|
5326
|
+
function createDownloadedKnowledgeSourceFilepath(url, mimeType) {
|
|
5327
|
+
const basename = url.split('/').pop() || titleToName(url);
|
|
5328
|
+
const hash = sha256(hexEncoder.parse(url)).toString( /* hex */);
|
|
5329
|
+
// <- TODO: [🥬] Encapsulate sha256 to some private utility function
|
|
5330
|
+
return join(...nameToSubfolderPath(hash /* <- TODO: [🎎] Maybe add some SHA256 prefix */), `${basename.substring(0, MAX_FILENAME_LENGTH)}.${mimeTypeToExtension(mimeType)}`);
|
|
5331
|
+
}
|
|
5332
|
+
/**
|
|
5333
|
+
* Tries to create the cache directory needed for a downloaded knowledge source.
|
|
5334
|
+
*
|
|
5335
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5336
|
+
*/
|
|
5337
|
+
async function createCacheDirectoryIfPossible(name, fullFilepath, tools, isVerbose) {
|
|
5338
|
+
try {
|
|
5339
|
+
await tools.fs.mkdir(dirname(fullFilepath), { recursive: true });
|
|
5340
|
+
}
|
|
5341
|
+
catch (error) {
|
|
4683
5342
|
if (isVerbose) {
|
|
4684
|
-
console.info(`📄 [
|
|
4685
|
-
}
|
|
4686
|
-
const response = await fetch(url); // <- TODO: [🧠] Scraping and fetch proxy
|
|
4687
|
-
const mimeType = ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0]) || 'text/html';
|
|
4688
|
-
if (tools.fs === undefined || !url.endsWith('.pdf' /* <- TODO: [💵] */)) {
|
|
4689
|
-
if (isVerbose) {
|
|
4690
|
-
console.info(`📄 [2] "${name}" tools.fs is not available or URL is not a PDF.`);
|
|
4691
|
-
}
|
|
4692
|
-
return {
|
|
4693
|
-
source: name,
|
|
4694
|
-
filename: null,
|
|
4695
|
-
url,
|
|
4696
|
-
mimeType,
|
|
4697
|
-
/*
|
|
4698
|
-
TODO: [🥽]
|
|
4699
|
-
> async asBlob() {
|
|
4700
|
-
> // TODO: [👨🏻🤝👨🏻] This can be called multiple times BUT when called second time, response in already consumed
|
|
4701
|
-
> const content = await response.blob();
|
|
4702
|
-
> return content;
|
|
4703
|
-
> },
|
|
4704
|
-
*/
|
|
4705
|
-
async asJson() {
|
|
4706
|
-
// TODO: [👨🏻🤝👨🏻]
|
|
4707
|
-
const content = await response.json();
|
|
4708
|
-
return content;
|
|
4709
|
-
},
|
|
4710
|
-
async asText() {
|
|
4711
|
-
// TODO: [👨🏻🤝👨🏻]
|
|
4712
|
-
const content = await response.text();
|
|
4713
|
-
return content;
|
|
4714
|
-
},
|
|
4715
|
-
};
|
|
4716
|
-
}
|
|
4717
|
-
const basename = url.split('/').pop() || titleToName(url);
|
|
4718
|
-
const hash = sha256(hexEncoder.parse(url)).toString( /* hex */);
|
|
4719
|
-
// <- TODO: [🥬] Encapsulate sha256 to some private utility function
|
|
4720
|
-
const rootDirname = join(process.cwd(), DEFAULT_DOWNLOAD_CACHE_DIRNAME);
|
|
4721
|
-
const filepath = join(...nameToSubfolderPath(hash /* <- TODO: [🎎] Maybe add some SHA256 prefix */), `${basename.substring(0, MAX_FILENAME_LENGTH)}.${mimeTypeToExtension(mimeType)}`);
|
|
4722
|
-
// Note: Try to create cache directory, but don't fail if filesystem has issues
|
|
4723
|
-
try {
|
|
4724
|
-
await tools.fs.mkdir(dirname(join(rootDirname, filepath)), { recursive: true });
|
|
4725
|
-
}
|
|
4726
|
-
catch (error) {
|
|
4727
|
-
if (isVerbose) {
|
|
4728
|
-
console.info(`📄 [3] "${name}" error creating cache directory`);
|
|
4729
|
-
}
|
|
4730
|
-
// Note: If we can't create cache directory, we'll handle it when trying to write the file
|
|
4731
|
-
// This handles read-only filesystems, permission issues, and missing parent directories
|
|
4732
|
-
if (error instanceof Error &&
|
|
4733
|
-
(error.message.includes('EROFS') ||
|
|
4734
|
-
error.message.includes('read-only') ||
|
|
4735
|
-
error.message.includes('EACCES') ||
|
|
4736
|
-
error.message.includes('EPERM') ||
|
|
4737
|
-
error.message.includes('ENOENT'))) ;
|
|
4738
|
-
else {
|
|
4739
|
-
// Re-throw other unexpected errors
|
|
4740
|
-
throw error;
|
|
4741
|
-
}
|
|
4742
|
-
}
|
|
4743
|
-
const fileContent = Buffer.from(await response.arrayBuffer());
|
|
4744
|
-
if (fileContent.length > DEFAULT_MAX_FILE_SIZE /* <- TODO: Allow to pass different value to remote server */) {
|
|
4745
|
-
throw new LimitReachedError(`File is too large (${Math.round(fileContent.length / 1024 / 1024)}MB). Maximum allowed size is ${Math.round(DEFAULT_MAX_FILE_SIZE / 1024 / 1024)}MB.`);
|
|
4746
|
-
}
|
|
4747
|
-
// Note: Try to cache the downloaded file, but don't fail if the filesystem is read-only
|
|
4748
|
-
try {
|
|
4749
|
-
await tools.fs.writeFile(join(rootDirname, filepath), fileContent);
|
|
4750
|
-
}
|
|
4751
|
-
catch (error) {
|
|
4752
|
-
if (isVerbose) {
|
|
4753
|
-
console.info(`📄 [4] "${name}" error writing cache file`);
|
|
4754
|
-
}
|
|
4755
|
-
// Note: If we can't write to cache, we'll process the file directly from memory
|
|
4756
|
-
// This handles read-only filesystems like Vercel
|
|
4757
|
-
if (error instanceof Error &&
|
|
4758
|
-
(error.message.includes('EROFS') ||
|
|
4759
|
-
error.message.includes('read-only') ||
|
|
4760
|
-
error.message.includes('EACCES') ||
|
|
4761
|
-
error.message.includes('EPERM') ||
|
|
4762
|
-
error.message.includes('ENOENT'))) {
|
|
4763
|
-
// Return a handler that works directly with the downloaded content
|
|
4764
|
-
return {
|
|
4765
|
-
source: name,
|
|
4766
|
-
filename: null,
|
|
4767
|
-
url,
|
|
4768
|
-
mimeType,
|
|
4769
|
-
async asJson() {
|
|
4770
|
-
return JSON.parse(fileContent.toString('utf-8'));
|
|
4771
|
-
},
|
|
4772
|
-
async asText() {
|
|
4773
|
-
return fileContent.toString('utf-8');
|
|
4774
|
-
},
|
|
4775
|
-
};
|
|
4776
|
-
}
|
|
4777
|
-
else {
|
|
4778
|
-
// Re-throw other unexpected errors
|
|
4779
|
-
throw error;
|
|
4780
|
-
}
|
|
5343
|
+
console.info(`📄 [3] "${name}" error creating cache directory`);
|
|
4781
5344
|
}
|
|
4782
|
-
//
|
|
4783
|
-
//
|
|
4784
|
-
if (
|
|
4785
|
-
|
|
5345
|
+
// Note: If we can't create cache directory, we'll handle it when trying to write the file
|
|
5346
|
+
// This handles read-only filesystems, permission issues, and missing parent directories
|
|
5347
|
+
if (!isIgnorableCacheFilesystemError(error)) {
|
|
5348
|
+
throw error;
|
|
4786
5349
|
}
|
|
4787
|
-
return makeKnowledgeSourceHandler({ name, knowledgeSourceContent: filepath }, tools, {
|
|
4788
|
-
...options,
|
|
4789
|
-
rootDirname,
|
|
4790
|
-
});
|
|
4791
5350
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
5351
|
+
}
|
|
5352
|
+
/**
|
|
5353
|
+
* Tries to write downloaded content into cache and reports whether the cache was usable.
|
|
5354
|
+
*
|
|
5355
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5356
|
+
*/
|
|
5357
|
+
async function writeCacheFileIfPossible(name, fullFilepath, fileContent, tools, isVerbose) {
|
|
5358
|
+
// Note: Try to cache the downloaded file, but don't fail if the filesystem is read-only
|
|
5359
|
+
try {
|
|
5360
|
+
await tools.fs.writeFile(fullFilepath, fileContent);
|
|
5361
|
+
return true;
|
|
5362
|
+
}
|
|
5363
|
+
catch (error) {
|
|
4804
5364
|
if (isVerbose) {
|
|
4805
|
-
console.info(`📄 [
|
|
5365
|
+
console.info(`📄 [4] "${name}" error writing cache file`);
|
|
4806
5366
|
}
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
if (
|
|
4810
|
-
|
|
4811
|
-
Can not make source handler for file which does not exist:
|
|
4812
|
-
|
|
4813
|
-
File:
|
|
4814
|
-
${block(knowledgeSourceContent)}
|
|
4815
|
-
|
|
4816
|
-
Full file path:
|
|
4817
|
-
${block(filename)}
|
|
4818
|
-
`));
|
|
5367
|
+
// Note: If we can't write to cache, we'll process the file directly from memory
|
|
5368
|
+
// This handles read-only filesystems like Vercel
|
|
5369
|
+
if (isIgnorableCacheFilesystemError(error)) {
|
|
5370
|
+
return false;
|
|
4819
5371
|
}
|
|
4820
|
-
|
|
4821
|
-
return {
|
|
4822
|
-
source: name,
|
|
4823
|
-
filename,
|
|
4824
|
-
url: null,
|
|
4825
|
-
mimeType,
|
|
4826
|
-
/*
|
|
4827
|
-
TODO: [🥽]
|
|
4828
|
-
> async asBlob() {
|
|
4829
|
-
> const content = await tools.fs!.readFile(filename);
|
|
4830
|
-
> return new Blob(
|
|
4831
|
-
> [
|
|
4832
|
-
> content,
|
|
4833
|
-
> // <- TODO: [🥽] This is NOT tested, test it
|
|
4834
|
-
> ],
|
|
4835
|
-
> { type: mimeType },
|
|
4836
|
-
> );
|
|
4837
|
-
> },
|
|
4838
|
-
*/
|
|
4839
|
-
async asJson() {
|
|
4840
|
-
return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
|
|
4841
|
-
},
|
|
4842
|
-
async asText() {
|
|
4843
|
-
return await tools.fs.readFile(filename, 'utf-8');
|
|
4844
|
-
},
|
|
4845
|
-
};
|
|
5372
|
+
throw error;
|
|
4846
5373
|
}
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
5374
|
+
}
|
|
5375
|
+
/**
|
|
5376
|
+
* Detects filesystem errors that should not fail optional caching.
|
|
5377
|
+
*
|
|
5378
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5379
|
+
*/
|
|
5380
|
+
function isIgnorableCacheFilesystemError(error) {
|
|
5381
|
+
return (error instanceof Error &&
|
|
5382
|
+
(error.message.includes('EROFS') ||
|
|
5383
|
+
error.message.includes('read-only') ||
|
|
5384
|
+
error.message.includes('EACCES') ||
|
|
5385
|
+
error.message.includes('EPERM') ||
|
|
5386
|
+
error.message.includes('ENOENT')));
|
|
5387
|
+
}
|
|
5388
|
+
/**
|
|
5389
|
+
* Creates a source handler backed by already downloaded file content kept in memory.
|
|
5390
|
+
*
|
|
5391
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5392
|
+
*/
|
|
5393
|
+
function makeBufferedKnowledgeSourceHandler(name, url, mimeType, fileContent) {
|
|
5394
|
+
return {
|
|
5395
|
+
source: name,
|
|
5396
|
+
filename: null,
|
|
5397
|
+
url,
|
|
5398
|
+
mimeType,
|
|
5399
|
+
async asJson() {
|
|
5400
|
+
return JSON.parse(fileContent.toString('utf-8'));
|
|
5401
|
+
},
|
|
5402
|
+
async asText() {
|
|
5403
|
+
return fileContent.toString('utf-8');
|
|
5404
|
+
},
|
|
5405
|
+
};
|
|
5406
|
+
}
|
|
5407
|
+
/**
|
|
5408
|
+
* Creates a source handler for file-based knowledge.
|
|
5409
|
+
*
|
|
5410
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5411
|
+
*/
|
|
5412
|
+
async function makeFileKnowledgeSourceHandler(knowledgeSourceContent, name, tools, rootDirname, isVerbose) {
|
|
5413
|
+
if (tools.fs === undefined) {
|
|
5414
|
+
throw new EnvironmentMismatchError('Can not import file knowledge without filesystem tools');
|
|
5415
|
+
// <- TODO: [🧠] What is the best error type here`
|
|
5416
|
+
}
|
|
5417
|
+
if (rootDirname === null) {
|
|
5418
|
+
throw new EnvironmentMismatchError('Can not import file knowledge in non-file pipeline');
|
|
5419
|
+
// <- TODO: [🧠] What is the best error type here`
|
|
5420
|
+
}
|
|
5421
|
+
const filename = isAbsolute(knowledgeSourceContent)
|
|
5422
|
+
? knowledgeSourceContent
|
|
5423
|
+
: join(rootDirname, knowledgeSourceContent).split('\\').join('/');
|
|
5424
|
+
if (isVerbose) {
|
|
5425
|
+
console.info(`📄 [6] "${name}" is a valid file "${filename}"`);
|
|
5426
|
+
}
|
|
5427
|
+
const fileExtension = getFileExtension(filename);
|
|
5428
|
+
const mimeType = extensionToMimeType(fileExtension || '');
|
|
5429
|
+
if (!(await isFileExisting(filename, tools.fs))) {
|
|
5430
|
+
throw new NotFoundError(spaceTrim$1((block) => `
|
|
5431
|
+
Can not make source handler for file which does not exist:
|
|
5432
|
+
|
|
5433
|
+
File:
|
|
5434
|
+
${block(knowledgeSourceContent)}
|
|
5435
|
+
|
|
5436
|
+
Full file path:
|
|
5437
|
+
${block(filename)}
|
|
5438
|
+
`));
|
|
5439
|
+
}
|
|
5440
|
+
// TODO: [🧠][😿] Test security file - file is scoped to the project (BUT maybe do this in `filesystemTools`)
|
|
5441
|
+
return {
|
|
5442
|
+
source: name,
|
|
5443
|
+
filename,
|
|
5444
|
+
url: null,
|
|
5445
|
+
mimeType,
|
|
5446
|
+
/*
|
|
5447
|
+
TODO: [🥽]
|
|
5448
|
+
> async asBlob() {
|
|
5449
|
+
> const content = await tools.fs!.readFile(filename);
|
|
5450
|
+
> return new Blob(
|
|
5451
|
+
> [
|
|
5452
|
+
> content,
|
|
5453
|
+
> // <- TODO: [🥽] This is NOT tested, test it
|
|
5454
|
+
> ],
|
|
5455
|
+
> { type: mimeType },
|
|
5456
|
+
> );
|
|
5457
|
+
> },
|
|
5458
|
+
*/
|
|
5459
|
+
async asJson() {
|
|
5460
|
+
return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
|
|
5461
|
+
},
|
|
5462
|
+
async asText() {
|
|
5463
|
+
return await tools.fs.readFile(filename, 'utf-8');
|
|
5464
|
+
},
|
|
5465
|
+
};
|
|
5466
|
+
}
|
|
5467
|
+
/**
|
|
5468
|
+
* Creates a source handler for inline text knowledge.
|
|
5469
|
+
*
|
|
5470
|
+
* @private internal utility of `makeKnowledgeSourceHandler`
|
|
5471
|
+
*/
|
|
5472
|
+
function makeInlineTextKnowledgeSourceHandler(knowledgeSourceContent, name, isVerbose) {
|
|
5473
|
+
if (isVerbose) {
|
|
5474
|
+
console.info(`📄 [7] "${name}" is just a explicit string text with a knowledge source`);
|
|
5475
|
+
console.info('---');
|
|
5476
|
+
console.info(knowledgeSourceContent);
|
|
5477
|
+
console.info('---');
|
|
4874
5478
|
}
|
|
5479
|
+
return {
|
|
5480
|
+
source: name,
|
|
5481
|
+
filename: null,
|
|
5482
|
+
url: null,
|
|
5483
|
+
mimeType: 'text/markdown',
|
|
5484
|
+
asText() {
|
|
5485
|
+
return knowledgeSourceContent;
|
|
5486
|
+
},
|
|
5487
|
+
asJson() {
|
|
5488
|
+
throw new UnexpectedError('Did not expect that `markdownScraper` would need to get the content `asJson`');
|
|
5489
|
+
},
|
|
5490
|
+
/*
|
|
5491
|
+
TODO: [🥽]
|
|
5492
|
+
> asBlob() {
|
|
5493
|
+
> throw new UnexpectedError(
|
|
5494
|
+
> 'Did not expect that `markdownScraper` would need to get the content `asBlob`',
|
|
5495
|
+
> );
|
|
5496
|
+
> },
|
|
5497
|
+
*/
|
|
5498
|
+
};
|
|
4875
5499
|
}
|
|
4876
5500
|
|
|
4877
5501
|
/**
|
|
@@ -6156,112 +6780,10 @@ function validatePromptResult(options) {
|
|
|
6156
6780
|
}
|
|
6157
6781
|
}
|
|
6158
6782
|
|
|
6159
|
-
/**
|
|
6160
|
-
* Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
|
|
6161
|
-
* (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
|
|
6162
|
-
* Throws errors if execution fails after all attempts.
|
|
6163
|
-
*
|
|
6164
|
-
* @param options - The options for execution, including task, parameters, pipeline, and configuration.
|
|
6165
|
-
* @returns The result string of the executed task.
|
|
6166
|
-
*
|
|
6167
|
-
* @private internal utility of `createPipelineExecutor`
|
|
6168
|
-
*/
|
|
6169
|
-
async function executeAttempts(options) {
|
|
6170
|
-
const $ongoingTaskResult = createOngoingTaskResult();
|
|
6171
|
-
const llmTools = getSingleLlmExecutionTools(options.tools.llm);
|
|
6172
|
-
attempts: for (let attemptIndex = -options.jokerParameterNames.length; attemptIndex < options.maxAttempts; attemptIndex++) {
|
|
6173
|
-
const attempt = createAttemptDescriptor({
|
|
6174
|
-
attemptIndex,
|
|
6175
|
-
jokerParameterNames: options.jokerParameterNames,
|
|
6176
|
-
pipelineIdentification: options.pipelineIdentification,
|
|
6177
|
-
});
|
|
6178
|
-
resetAttemptExecutionState($ongoingTaskResult);
|
|
6179
|
-
try {
|
|
6180
|
-
await executeSingleAttempt({
|
|
6181
|
-
attempt,
|
|
6182
|
-
options,
|
|
6183
|
-
llmTools,
|
|
6184
|
-
$ongoingTaskResult,
|
|
6185
|
-
});
|
|
6186
|
-
break attempts;
|
|
6187
|
-
}
|
|
6188
|
-
catch (error) {
|
|
6189
|
-
if (!(error instanceof ExpectError)) {
|
|
6190
|
-
throw error;
|
|
6191
|
-
}
|
|
6192
|
-
recordFailedAttempt({
|
|
6193
|
-
error,
|
|
6194
|
-
attemptIndex,
|
|
6195
|
-
onProgress: options.onProgress,
|
|
6196
|
-
$ongoingTaskResult,
|
|
6197
|
-
});
|
|
6198
|
-
}
|
|
6199
|
-
finally {
|
|
6200
|
-
reportPromptExecution({
|
|
6201
|
-
attempt,
|
|
6202
|
-
task: options.task,
|
|
6203
|
-
$executionReport: options.$executionReport,
|
|
6204
|
-
logLlmCall: options.logLlmCall,
|
|
6205
|
-
$ongoingTaskResult,
|
|
6206
|
-
});
|
|
6207
|
-
}
|
|
6208
|
-
throwIfFinalAttemptFailed({
|
|
6209
|
-
attemptIndex,
|
|
6210
|
-
maxAttempts: options.maxAttempts,
|
|
6211
|
-
maxExecutionAttempts: options.maxExecutionAttempts,
|
|
6212
|
-
pipelineIdentification: options.pipelineIdentification,
|
|
6213
|
-
$ongoingTaskResult,
|
|
6214
|
-
});
|
|
6215
|
-
}
|
|
6216
|
-
return getSuccessfulResultString({
|
|
6217
|
-
pipelineIdentification: options.pipelineIdentification,
|
|
6218
|
-
$ongoingTaskResult,
|
|
6219
|
-
});
|
|
6220
|
-
}
|
|
6221
|
-
/**
|
|
6222
|
-
* Creates mutable attempt state for one task execution lifecycle.
|
|
6223
|
-
*/
|
|
6224
|
-
function createOngoingTaskResult() {
|
|
6225
|
-
return {
|
|
6226
|
-
$result: null,
|
|
6227
|
-
$resultString: null,
|
|
6228
|
-
$expectError: null,
|
|
6229
|
-
$scriptPipelineExecutionErrors: [],
|
|
6230
|
-
$failedResults: [],
|
|
6231
|
-
};
|
|
6232
|
-
}
|
|
6233
|
-
/**
|
|
6234
|
-
* Resolves the bookkeeping for one loop iteration, including joker lookup.
|
|
6235
|
-
*/
|
|
6236
|
-
function createAttemptDescriptor(options) {
|
|
6237
|
-
const { attemptIndex, jokerParameterNames, pipelineIdentification } = options;
|
|
6238
|
-
const isJokerAttempt = attemptIndex < 0;
|
|
6239
|
-
const jokerParameterName = isJokerAttempt
|
|
6240
|
-
? jokerParameterNames[jokerParameterNames.length + attemptIndex]
|
|
6241
|
-
: undefined;
|
|
6242
|
-
if (isJokerAttempt && !jokerParameterName) {
|
|
6243
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
6244
|
-
Joker not found in attempt ${attemptIndex}
|
|
6245
|
-
|
|
6246
|
-
${block(pipelineIdentification)}
|
|
6247
|
-
`));
|
|
6248
|
-
}
|
|
6249
|
-
return {
|
|
6250
|
-
attemptIndex,
|
|
6251
|
-
isJokerAttempt,
|
|
6252
|
-
jokerParameterName,
|
|
6253
|
-
};
|
|
6254
|
-
}
|
|
6255
|
-
/**
|
|
6256
|
-
* Clears the per-attempt result slots while preserving cumulative failure history.
|
|
6257
|
-
*/
|
|
6258
|
-
function resetAttemptExecutionState($ongoingTaskResult) {
|
|
6259
|
-
$ongoingTaskResult.$result = null;
|
|
6260
|
-
$ongoingTaskResult.$resultString = null;
|
|
6261
|
-
$ongoingTaskResult.$expectError = null;
|
|
6262
|
-
}
|
|
6263
6783
|
/**
|
|
6264
6784
|
* Executes one loop iteration, from joker resolution or task execution through validation.
|
|
6785
|
+
*
|
|
6786
|
+
* @private function of `executeAttempts`
|
|
6265
6787
|
*/
|
|
6266
6788
|
async function executeSingleAttempt(options) {
|
|
6267
6789
|
const { attempt, options: executeAttemptsOptions, llmTools, $ongoingTaskResult } = options;
|
|
@@ -6576,11 +7098,15 @@ function validateAttemptResult(options) {
|
|
|
6576
7098
|
// Update the result string in case format processing modified it (e.g., JSON extraction)
|
|
6577
7099
|
$ongoingTaskResult.$resultString = validationResult.processedResultString;
|
|
6578
7100
|
}
|
|
7101
|
+
|
|
6579
7102
|
/**
|
|
6580
|
-
* Stores one failed attempt
|
|
7103
|
+
* Stores one failed attempt, reports the expectation error, and throws the aggregated retry error after the final
|
|
7104
|
+
* regular attempt.
|
|
7105
|
+
*
|
|
7106
|
+
* @private function of `executeAttempts`
|
|
6581
7107
|
*/
|
|
6582
|
-
function
|
|
6583
|
-
const { error, attemptIndex, onProgress, $ongoingTaskResult } = options;
|
|
7108
|
+
function handleAttemptFailure(options) {
|
|
7109
|
+
const { error, attemptIndex, maxAttempts, maxExecutionAttempts, onProgress, pipelineIdentification, $ongoingTaskResult, } = options;
|
|
6584
7110
|
$ongoingTaskResult.$expectError = error;
|
|
6585
7111
|
$ongoingTaskResult.$failedResults.push({
|
|
6586
7112
|
attemptIndex,
|
|
@@ -6590,39 +7116,7 @@ function recordFailedAttempt(options) {
|
|
|
6590
7116
|
onProgress({
|
|
6591
7117
|
errors: [error],
|
|
6592
7118
|
});
|
|
6593
|
-
|
|
6594
|
-
/**
|
|
6595
|
-
* Appends the prompt execution report for prompt-task attempts.
|
|
6596
|
-
*/
|
|
6597
|
-
function reportPromptExecution(options) {
|
|
6598
|
-
const { attempt, task, $executionReport, logLlmCall, $ongoingTaskResult } = options;
|
|
6599
|
-
if (attempt.isJokerAttempt || task.taskType !== 'PROMPT_TASK' || !$ongoingTaskResult.$prompt) {
|
|
6600
|
-
return;
|
|
6601
|
-
}
|
|
6602
|
-
// Note: [2] When some expected parameter is not defined, error will occur in templateParameters
|
|
6603
|
-
// In that case we don’t want to make a report about it because it’s not a llm execution error
|
|
6604
|
-
const executionPromptReport = {
|
|
6605
|
-
prompt: {
|
|
6606
|
-
...$ongoingTaskResult.$prompt,
|
|
6607
|
-
// <- TODO: [🧠] How to pick everyhing except `pipelineUrl`
|
|
6608
|
-
},
|
|
6609
|
-
result: $ongoingTaskResult.$result || undefined,
|
|
6610
|
-
error: $ongoingTaskResult.$expectError === null ? undefined : serializeError($ongoingTaskResult.$expectError),
|
|
6611
|
-
};
|
|
6612
|
-
$executionReport.promptExecutions.push(executionPromptReport);
|
|
6613
|
-
if (logLlmCall) {
|
|
6614
|
-
logLlmCall({
|
|
6615
|
-
modelName: 'model' /* <- TODO: How to get model name from the report */,
|
|
6616
|
-
report: executionPromptReport,
|
|
6617
|
-
});
|
|
6618
|
-
}
|
|
6619
|
-
}
|
|
6620
|
-
/**
|
|
6621
|
-
* Throws the aggregated retry error after the last regular attempt fails expectations.
|
|
6622
|
-
*/
|
|
6623
|
-
function throwIfFinalAttemptFailed(options) {
|
|
6624
|
-
const { attemptIndex, maxAttempts, maxExecutionAttempts, pipelineIdentification, $ongoingTaskResult } = options;
|
|
6625
|
-
if ($ongoingTaskResult.$expectError === null || attemptIndex !== maxAttempts - 1) {
|
|
7119
|
+
if (attemptIndex !== maxAttempts - 1) {
|
|
6626
7120
|
return;
|
|
6627
7121
|
}
|
|
6628
7122
|
throw new PipelineExecutionError(spaceTrim$1((block) => {
|
|
@@ -6653,7 +7147,9 @@ function createFailuresSummary($failedResults) {
|
|
|
6653
7147
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
6654
7148
|
|
|
6655
7149
|
Result:
|
|
6656
|
-
${block(failure.result === null
|
|
7150
|
+
${block(failure.result === null
|
|
7151
|
+
? 'null'
|
|
7152
|
+
: quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
6657
7153
|
`;
|
|
6658
7154
|
}))
|
|
6659
7155
|
.join('\n\n---\n\n');
|
|
@@ -6667,6 +7163,136 @@ function quoteMultilineText(text) {
|
|
|
6667
7163
|
.map((line) => `> ${line}`)
|
|
6668
7164
|
.join('\n');
|
|
6669
7165
|
}
|
|
7166
|
+
|
|
7167
|
+
/**
|
|
7168
|
+
* Appends the prompt execution report for prompt-task attempts.
|
|
7169
|
+
*
|
|
7170
|
+
* @private function of `executeAttempts`
|
|
7171
|
+
*/
|
|
7172
|
+
function reportPromptExecution(options) {
|
|
7173
|
+
const { attempt, task, $executionReport, logLlmCall, $ongoingTaskResult } = options;
|
|
7174
|
+
if (attempt.isJokerAttempt || task.taskType !== 'PROMPT_TASK' || !$ongoingTaskResult.$prompt) {
|
|
7175
|
+
return;
|
|
7176
|
+
}
|
|
7177
|
+
// Note: [2] When some expected parameter is not defined, error will occur in templateParameters
|
|
7178
|
+
// In that case we don’t want to make a report about it because it’s not a llm execution error
|
|
7179
|
+
const executionPromptReport = {
|
|
7180
|
+
prompt: {
|
|
7181
|
+
...$ongoingTaskResult.$prompt,
|
|
7182
|
+
// <- TODO: [🧠] How to pick everyhing except `pipelineUrl`
|
|
7183
|
+
},
|
|
7184
|
+
result: $ongoingTaskResult.$result || undefined,
|
|
7185
|
+
error: $ongoingTaskResult.$expectError === null ? undefined : serializeError($ongoingTaskResult.$expectError),
|
|
7186
|
+
};
|
|
7187
|
+
$executionReport.promptExecutions.push(executionPromptReport);
|
|
7188
|
+
if (logLlmCall) {
|
|
7189
|
+
logLlmCall({
|
|
7190
|
+
modelName: 'model' /* <- TODO: How to get model name from the report */,
|
|
7191
|
+
report: executionPromptReport,
|
|
7192
|
+
});
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
|
|
7196
|
+
/**
|
|
7197
|
+
* Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
|
|
7198
|
+
* (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
|
|
7199
|
+
* Throws errors if execution fails after all attempts.
|
|
7200
|
+
*
|
|
7201
|
+
* @param options - The options for execution, including task, parameters, pipeline, and configuration.
|
|
7202
|
+
* @returns The result string of the executed task.
|
|
7203
|
+
*
|
|
7204
|
+
* @private internal utility of `createPipelineExecutor`
|
|
7205
|
+
*/
|
|
7206
|
+
async function executeAttempts(options) {
|
|
7207
|
+
const $ongoingTaskResult = createOngoingTaskResult();
|
|
7208
|
+
const llmTools = getSingleLlmExecutionTools(options.tools.llm);
|
|
7209
|
+
attempts: for (let attemptIndex = -options.jokerParameterNames.length; attemptIndex < options.maxAttempts; attemptIndex++) {
|
|
7210
|
+
const attempt = createAttemptDescriptor({
|
|
7211
|
+
attemptIndex,
|
|
7212
|
+
jokerParameterNames: options.jokerParameterNames,
|
|
7213
|
+
pipelineIdentification: options.pipelineIdentification,
|
|
7214
|
+
});
|
|
7215
|
+
resetAttemptExecutionState($ongoingTaskResult);
|
|
7216
|
+
try {
|
|
7217
|
+
await executeSingleAttempt({
|
|
7218
|
+
attempt,
|
|
7219
|
+
options,
|
|
7220
|
+
llmTools,
|
|
7221
|
+
$ongoingTaskResult,
|
|
7222
|
+
});
|
|
7223
|
+
break attempts;
|
|
7224
|
+
}
|
|
7225
|
+
catch (error) {
|
|
7226
|
+
if (!(error instanceof ExpectError)) {
|
|
7227
|
+
throw error;
|
|
7228
|
+
}
|
|
7229
|
+
handleAttemptFailure({
|
|
7230
|
+
error,
|
|
7231
|
+
attemptIndex,
|
|
7232
|
+
maxAttempts: options.maxAttempts,
|
|
7233
|
+
maxExecutionAttempts: options.maxExecutionAttempts,
|
|
7234
|
+
onProgress: options.onProgress,
|
|
7235
|
+
pipelineIdentification: options.pipelineIdentification,
|
|
7236
|
+
$ongoingTaskResult,
|
|
7237
|
+
});
|
|
7238
|
+
}
|
|
7239
|
+
finally {
|
|
7240
|
+
reportPromptExecution({
|
|
7241
|
+
attempt,
|
|
7242
|
+
task: options.task,
|
|
7243
|
+
$executionReport: options.$executionReport,
|
|
7244
|
+
logLlmCall: options.logLlmCall,
|
|
7245
|
+
$ongoingTaskResult,
|
|
7246
|
+
});
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
return getSuccessfulResultString({
|
|
7250
|
+
pipelineIdentification: options.pipelineIdentification,
|
|
7251
|
+
$ongoingTaskResult,
|
|
7252
|
+
});
|
|
7253
|
+
}
|
|
7254
|
+
/**
|
|
7255
|
+
* Creates mutable attempt state for one task execution lifecycle.
|
|
7256
|
+
*/
|
|
7257
|
+
function createOngoingTaskResult() {
|
|
7258
|
+
return {
|
|
7259
|
+
$result: null,
|
|
7260
|
+
$resultString: null,
|
|
7261
|
+
$expectError: null,
|
|
7262
|
+
$scriptPipelineExecutionErrors: [],
|
|
7263
|
+
$failedResults: [],
|
|
7264
|
+
};
|
|
7265
|
+
}
|
|
7266
|
+
/**
|
|
7267
|
+
* Resolves the bookkeeping for one loop iteration, including joker lookup.
|
|
7268
|
+
*/
|
|
7269
|
+
function createAttemptDescriptor(options) {
|
|
7270
|
+
const { attemptIndex, jokerParameterNames, pipelineIdentification } = options;
|
|
7271
|
+
const isJokerAttempt = attemptIndex < 0;
|
|
7272
|
+
const jokerParameterName = isJokerAttempt
|
|
7273
|
+
? jokerParameterNames[jokerParameterNames.length + attemptIndex]
|
|
7274
|
+
: undefined;
|
|
7275
|
+
if (isJokerAttempt && !jokerParameterName) {
|
|
7276
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
7277
|
+
Joker not found in attempt ${attemptIndex}
|
|
7278
|
+
|
|
7279
|
+
${block(pipelineIdentification)}
|
|
7280
|
+
`));
|
|
7281
|
+
}
|
|
7282
|
+
return {
|
|
7283
|
+
attemptIndex,
|
|
7284
|
+
isJokerAttempt,
|
|
7285
|
+
jokerParameterName,
|
|
7286
|
+
};
|
|
7287
|
+
}
|
|
7288
|
+
/**
|
|
7289
|
+
* Clears the per-attempt result slots while preserving cumulative failure history.
|
|
7290
|
+
*/
|
|
7291
|
+
function resetAttemptExecutionState($ongoingTaskResult) {
|
|
7292
|
+
$ongoingTaskResult.$result = null;
|
|
7293
|
+
$ongoingTaskResult.$resultString = null;
|
|
7294
|
+
$ongoingTaskResult.$expectError = null;
|
|
7295
|
+
}
|
|
6670
7296
|
/**
|
|
6671
7297
|
* Returns the successful result string or raises an unexpected internal-state error.
|
|
6672
7298
|
*/
|