@promptbook/website-crawler 0.112.0-39 β†’ 0.112.0-41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +23 -21
  2. package/esm/index.es.js +481 -288
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.d.ts +8 -2
  5. package/esm/src/book-components/Chat/Chat/ChatInputArea.d.ts +0 -10
  6. package/esm/src/book-components/Chat/Chat/ChatInputUploadedFile.d.ts +10 -0
  7. package/esm/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +46 -0
  8. package/esm/src/book-components/Chat/Chat/resolveRunBrowserToolCallDetailsState.d.ts +146 -0
  9. package/esm/src/book-components/Chat/Chat/useChatInputAreaAttachments.d.ts +1 -1
  10. package/esm/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +39 -0
  11. package/esm/src/book-components/Chat/Chat/useChatPostprocessedMessages.d.ts +17 -0
  12. package/esm/src/book-components/Chat/Chat/useChatScrollState.d.ts +34 -0
  13. package/esm/src/book-components/Chat/Chat/useChatToolCallModalState.d.ts +61 -0
  14. package/esm/src/book-components/Chat/Chat/useChatToolCallState.d.ts +35 -0
  15. package/esm/src/book-components/Chat/LlmChat/useLlmChatMessageHandler.d.ts +58 -0
  16. package/esm/src/book-components/Chat/LlmChat/useLlmChatMessages.d.ts +29 -0
  17. package/esm/src/book-components/Chat/LlmChat/useLlmChatState.d.ts +53 -0
  18. package/esm/src/collection/pipeline-collection/constructors/createPipelineCollectionFromDirectory.d.ts +7 -1
  19. package/esm/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +52 -0
  20. package/esm/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +128 -0
  21. package/esm/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +3 -3
  22. package/esm/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +54 -0
  23. package/esm/src/llm-providers/openai/utils/OpenAiCompatibleUnsupportedParameterRetrier.d.ts +29 -0
  24. package/esm/src/llm-providers/openai/utils/callOpenAiCompatibleChatModel.d.ts +28 -0
  25. package/esm/src/types/number_usd.d.ts +1 -1
  26. package/esm/src/types/string_parameter_name.d.ts +2 -2
  27. package/esm/src/types/typeAliases.d.ts +2 -2
  28. package/esm/src/version.d.ts +1 -1
  29. package/package.json +2 -2
  30. package/umd/index.umd.js +481 -288
  31. package/umd/index.umd.js.map +1 -1
  32. package/umd/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.d.ts +8 -2
  33. package/umd/src/book-components/Chat/Chat/ChatInputArea.d.ts +0 -10
  34. package/umd/src/book-components/Chat/Chat/ChatInputUploadedFile.d.ts +10 -0
  35. package/umd/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +46 -0
  36. package/umd/src/book-components/Chat/Chat/resolveRunBrowserToolCallDetailsState.d.ts +146 -0
  37. package/umd/src/book-components/Chat/Chat/useChatInputAreaAttachments.d.ts +1 -1
  38. package/umd/src/book-components/Chat/Chat/useChatInputAreaComposer.d.ts +39 -0
  39. package/umd/src/book-components/Chat/Chat/useChatPostprocessedMessages.d.ts +17 -0
  40. package/umd/src/book-components/Chat/Chat/useChatScrollState.d.ts +34 -0
  41. package/umd/src/book-components/Chat/Chat/useChatToolCallModalState.d.ts +61 -0
  42. package/umd/src/book-components/Chat/Chat/useChatToolCallState.d.ts +35 -0
  43. package/umd/src/book-components/Chat/LlmChat/useLlmChatMessageHandler.d.ts +58 -0
  44. package/umd/src/book-components/Chat/LlmChat/useLlmChatMessages.d.ts +29 -0
  45. package/umd/src/book-components/Chat/LlmChat/useLlmChatState.d.ts +53 -0
  46. package/umd/src/collection/pipeline-collection/constructors/createPipelineCollectionFromDirectory.d.ts +7 -1
  47. package/umd/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +52 -0
  48. package/umd/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +128 -0
  49. package/umd/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +3 -3
  50. package/umd/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +54 -0
  51. package/umd/src/llm-providers/openai/utils/OpenAiCompatibleUnsupportedParameterRetrier.d.ts +29 -0
  52. package/umd/src/llm-providers/openai/utils/callOpenAiCompatibleChatModel.d.ts +28 -0
  53. package/umd/src/types/number_usd.d.ts +1 -1
  54. package/umd/src/types/string_parameter_name.d.ts +2 -2
  55. package/umd/src/types/typeAliases.d.ts +2 -2
  56. package/umd/src/version.d.ts +1 -1
package/esm/index.es.js CHANGED
@@ -27,7 +27,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
27
27
  * @generated
28
28
  * @see https://github.com/webgptorg/promptbook
29
29
  */
30
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-39';
30
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-41';
31
31
  /**
32
32
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
33
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
@@ -6128,317 +6128,511 @@ function validatePromptResult(options) {
6128
6128
  * @private internal utility of `createPipelineExecutor`
6129
6129
  */
6130
6130
  async function executeAttempts(options) {
6131
- const { jokerParameterNames, priority, maxAttempts, // <- Note: [πŸ’‚]
6132
- preparedContent, parameters, task, preparedPipeline, tools, $executionReport, pipelineIdentification, maxExecutionAttempts, onProgress, logLlmCall, } = options;
6133
- const $ongoingTaskResult = {
6131
+ const $ongoingTaskResult = createOngoingTaskResult();
6132
+ const llmTools = getSingleLlmExecutionTools(options.tools.llm);
6133
+ attempts: for (let attemptIndex = -options.jokerParameterNames.length; attemptIndex < options.maxAttempts; attemptIndex++) {
6134
+ const attempt = createAttemptDescriptor({
6135
+ attemptIndex,
6136
+ jokerParameterNames: options.jokerParameterNames,
6137
+ pipelineIdentification: options.pipelineIdentification,
6138
+ });
6139
+ resetAttemptExecutionState($ongoingTaskResult);
6140
+ try {
6141
+ await executeSingleAttempt({
6142
+ attempt,
6143
+ options,
6144
+ llmTools,
6145
+ $ongoingTaskResult,
6146
+ });
6147
+ break attempts;
6148
+ }
6149
+ catch (error) {
6150
+ if (!(error instanceof ExpectError)) {
6151
+ throw error;
6152
+ }
6153
+ recordFailedAttempt({
6154
+ error,
6155
+ attemptIndex,
6156
+ onProgress: options.onProgress,
6157
+ $ongoingTaskResult,
6158
+ });
6159
+ }
6160
+ finally {
6161
+ reportPromptExecution({
6162
+ attempt,
6163
+ task: options.task,
6164
+ $executionReport: options.$executionReport,
6165
+ logLlmCall: options.logLlmCall,
6166
+ $ongoingTaskResult,
6167
+ });
6168
+ }
6169
+ throwIfFinalAttemptFailed({
6170
+ attemptIndex,
6171
+ maxAttempts: options.maxAttempts,
6172
+ maxExecutionAttempts: options.maxExecutionAttempts,
6173
+ pipelineIdentification: options.pipelineIdentification,
6174
+ $ongoingTaskResult,
6175
+ });
6176
+ }
6177
+ return getSuccessfulResultString({
6178
+ pipelineIdentification: options.pipelineIdentification,
6179
+ $ongoingTaskResult,
6180
+ });
6181
+ }
6182
+ /**
6183
+ * Creates mutable attempt state for one task execution lifecycle.
6184
+ */
6185
+ function createOngoingTaskResult() {
6186
+ return {
6134
6187
  $result: null,
6135
6188
  $resultString: null,
6136
6189
  $expectError: null,
6137
6190
  $scriptPipelineExecutionErrors: [],
6138
- $failedResults: [], // Track all failed attempts
6191
+ $failedResults: [],
6139
6192
  };
6140
- const llmTools = getSingleLlmExecutionTools(tools.llm);
6141
- attempts: for (let attemptIndex = -jokerParameterNames.length; attemptIndex < maxAttempts; attemptIndex++) {
6142
- const isJokerAttempt = attemptIndex < 0;
6143
- const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attemptIndex];
6144
- // TODO: [🧠][🍭] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
6145
- if (isJokerAttempt && !jokerParameterName) {
6146
- throw new UnexpectedError(spaceTrim$1((block) => `
6147
- Joker not found in attempt ${attemptIndex}
6193
+ }
6194
+ /**
6195
+ * Resolves the bookkeeping for one loop iteration, including joker lookup.
6196
+ */
6197
+ function createAttemptDescriptor(options) {
6198
+ const { attemptIndex, jokerParameterNames, pipelineIdentification } = options;
6199
+ const isJokerAttempt = attemptIndex < 0;
6200
+ const jokerParameterName = isJokerAttempt
6201
+ ? jokerParameterNames[jokerParameterNames.length + attemptIndex]
6202
+ : undefined;
6203
+ if (isJokerAttempt && !jokerParameterName) {
6204
+ throw new UnexpectedError(spaceTrim$1((block) => `
6205
+ Joker not found in attempt ${attemptIndex}
6148
6206
 
6149
- ${block(pipelineIdentification)}
6207
+ ${block(pipelineIdentification)}
6208
+ `));
6209
+ }
6210
+ return {
6211
+ attemptIndex,
6212
+ isJokerAttempt,
6213
+ jokerParameterName,
6214
+ };
6215
+ }
6216
+ /**
6217
+ * Clears the per-attempt result slots while preserving cumulative failure history.
6218
+ */
6219
+ function resetAttemptExecutionState($ongoingTaskResult) {
6220
+ $ongoingTaskResult.$result = null;
6221
+ $ongoingTaskResult.$resultString = null;
6222
+ $ongoingTaskResult.$expectError = null;
6223
+ }
6224
+ /**
6225
+ * Executes one loop iteration, from joker resolution or task execution through validation.
6226
+ */
6227
+ async function executeSingleAttempt(options) {
6228
+ const { attempt, options: executeAttemptsOptions, llmTools, $ongoingTaskResult } = options;
6229
+ if (attempt.isJokerAttempt) {
6230
+ resolveJokerAttemptResult({
6231
+ jokerParameterName: attempt.jokerParameterName,
6232
+ parameters: executeAttemptsOptions.parameters,
6233
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6234
+ $ongoingTaskResult,
6235
+ });
6236
+ }
6237
+ else {
6238
+ await executeTaskAttempt({
6239
+ options: executeAttemptsOptions,
6240
+ llmTools,
6241
+ $ongoingTaskResult,
6242
+ });
6243
+ await applyPostprocessingFunctions({
6244
+ task: executeAttemptsOptions.task,
6245
+ tools: executeAttemptsOptions.tools,
6246
+ $ongoingTaskResult,
6247
+ });
6248
+ }
6249
+ validateAttemptResult({
6250
+ task: executeAttemptsOptions.task,
6251
+ $ongoingTaskResult,
6252
+ });
6253
+ }
6254
+ /**
6255
+ * Resolves the shortcut value used by a joker attempt.
6256
+ */
6257
+ function resolveJokerAttemptResult(options) {
6258
+ const { jokerParameterName, parameters, pipelineIdentification, $ongoingTaskResult } = options;
6259
+ if (parameters[jokerParameterName] === undefined) {
6260
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6261
+ Joker parameter {${jokerParameterName}} not defined
6262
+
6263
+ ${block(pipelineIdentification)}
6264
+ `));
6265
+ // <- TODO: This is maybe `PipelineLogicError` which should be detected in `validatePipeline` and here just thrown as `UnexpectedError`
6266
+ }
6267
+ $ongoingTaskResult.$resultString = parameters[jokerParameterName];
6268
+ }
6269
+ /**
6270
+ * Dispatches non-joker execution to the handler for the current task type.
6271
+ */
6272
+ async function executeTaskAttempt(options) {
6273
+ const { options: executeAttemptsOptions, llmTools, $ongoingTaskResult } = options;
6274
+ const { task } = executeAttemptsOptions;
6275
+ switch (task.taskType) {
6276
+ case 'SIMPLE_TASK':
6277
+ executeSimpleTaskAttempt({
6278
+ preparedContent: executeAttemptsOptions.preparedContent,
6279
+ parameters: executeAttemptsOptions.parameters,
6280
+ $ongoingTaskResult,
6281
+ });
6282
+ return;
6283
+ case 'PROMPT_TASK':
6284
+ await executePromptTaskAttempt({
6285
+ preparedPipeline: executeAttemptsOptions.preparedPipeline,
6286
+ task,
6287
+ parameters: executeAttemptsOptions.parameters,
6288
+ preparedContent: executeAttemptsOptions.preparedContent,
6289
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6290
+ llmTools,
6291
+ $ongoingTaskResult,
6292
+ });
6293
+ return;
6294
+ case 'SCRIPT_TASK':
6295
+ await executeScriptTaskAttempt({
6296
+ tools: executeAttemptsOptions.tools,
6297
+ task,
6298
+ preparedContent: executeAttemptsOptions.preparedContent,
6299
+ parameters: executeAttemptsOptions.parameters,
6300
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6301
+ $ongoingTaskResult,
6302
+ });
6303
+ return;
6304
+ case 'DIALOG_TASK':
6305
+ await executeDialogTaskAttempt({
6306
+ tools: executeAttemptsOptions.tools,
6307
+ task,
6308
+ parameters: executeAttemptsOptions.parameters,
6309
+ preparedContent: executeAttemptsOptions.preparedContent,
6310
+ priority: executeAttemptsOptions.priority,
6311
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6312
+ $ongoingTaskResult,
6313
+ });
6314
+ return;
6315
+ default:
6316
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6317
+ Unknown execution type "${task.taskType}"
6318
+
6319
+ ${block(executeAttemptsOptions.pipelineIdentification)}
6150
6320
  `));
6151
- }
6152
- $ongoingTaskResult.$result = null;
6153
- $ongoingTaskResult.$resultString = null;
6154
- $ongoingTaskResult.$expectError = null;
6155
- if (isJokerAttempt) {
6156
- if (parameters[jokerParameterName] === undefined) {
6157
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6158
- Joker parameter {${jokerParameterName}} not defined
6321
+ }
6322
+ }
6323
+ /**
6324
+ * Executes a simple templated task with no external tools.
6325
+ */
6326
+ function executeSimpleTaskAttempt(options) {
6327
+ const { preparedContent, parameters, $ongoingTaskResult } = options;
6328
+ $ongoingTaskResult.$resultString = templateParameters(preparedContent, parameters);
6329
+ }
6330
+ /**
6331
+ * Builds the prompt for a prompt task and calls the appropriate LLM variant.
6332
+ */
6333
+ async function executePromptTaskAttempt(options) {
6334
+ const { preparedPipeline, task, parameters, preparedContent, pipelineIdentification, llmTools, $ongoingTaskResult, } = options;
6335
+ const modelRequirements = {
6336
+ modelVariant: 'CHAT',
6337
+ ...(preparedPipeline.defaultModelRequirements || {}),
6338
+ ...(task.modelRequirements || {}),
6339
+ }; /* <- Note: [πŸ€›] */
6340
+ $ongoingTaskResult.$prompt = {
6341
+ title: task.title,
6342
+ pipelineUrl: `${preparedPipeline.pipelineUrl ? preparedPipeline.pipelineUrl : 'anonymous'}#${task.name
6343
+ // <- TODO: Here should be maybe also subformat index to distinguish between same task with different subformat values
6344
+ }`,
6345
+ parameters,
6346
+ content: preparedContent,
6347
+ modelRequirements,
6348
+ expectations: {
6349
+ ...(preparedPipeline.personas.find(({ name }) => name === task.personaName) || {}),
6350
+ ...task.expectations,
6351
+ },
6352
+ format: task.format,
6353
+ postprocessingFunctionNames: task.postprocessingFunctionNames,
6354
+ }; // <- TODO: Not very good type guard
6355
+ switch (modelRequirements.modelVariant) {
6356
+ case 'CHAT':
6357
+ $ongoingTaskResult.$chatResult = await llmTools.callChatModel(
6358
+ // <- TODO: [🧁] Check that `callChatModel` is defined
6359
+ $deepFreeze($ongoingTaskResult.$prompt));
6360
+ // TODO: [🍬] Destroy chatThread
6361
+ $ongoingTaskResult.$result = $ongoingTaskResult.$chatResult;
6362
+ $ongoingTaskResult.$resultString = $ongoingTaskResult.$chatResult.content;
6363
+ return;
6364
+ case 'COMPLETION':
6365
+ $ongoingTaskResult.$completionResult = await llmTools.callCompletionModel(
6366
+ // <- TODO: [🧁] Check that `callCompletionModel` is defined
6367
+ $deepFreeze($ongoingTaskResult.$prompt));
6368
+ $ongoingTaskResult.$result = $ongoingTaskResult.$completionResult;
6369
+ $ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
6370
+ return;
6371
+ case 'EMBEDDING':
6372
+ case 'IMAGE_GENERATION':
6373
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6374
+ ${modelRequirements.modelVariant} model can not be used in pipeline
6159
6375
 
6160
- ${block(pipelineIdentification)}
6161
- `));
6162
- // <- TODO: This is maybe `PipelineLogicError` which should be detected in `validatePipeline` and here just thrown as `UnexpectedError`
6163
- }
6164
- else {
6165
- $ongoingTaskResult.$resultString = parameters[jokerParameterName];
6166
- }
6167
- }
6168
- try {
6169
- if (!isJokerAttempt) {
6170
- taskType: switch (task.taskType) {
6171
- case 'SIMPLE_TASK':
6172
- $ongoingTaskResult.$resultString = templateParameters(preparedContent, parameters);
6173
- break taskType;
6174
- case 'PROMPT_TASK':
6175
- {
6176
- const modelRequirements = {
6177
- modelVariant: 'CHAT',
6178
- ...(preparedPipeline.defaultModelRequirements || {}),
6179
- ...(task.modelRequirements || {}),
6180
- }; /* <- Note: [πŸ€›] */
6181
- $ongoingTaskResult.$prompt = {
6182
- title: task.title,
6183
- pipelineUrl: `${preparedPipeline.pipelineUrl
6184
- ? preparedPipeline.pipelineUrl
6185
- : 'anonymous' /* <- TODO: [🧠] How to deal with anonymous pipelines, do here some auto-url like SHA-256 based ad-hoc identifier? */}#${task.name
6186
- // <- TODO: Here should be maybe also subformat index to distinguish between same task with different subformat values
6187
- }`,
6188
- parameters,
6189
- content: preparedContent,
6190
- modelRequirements,
6191
- expectations: {
6192
- ...(preparedPipeline.personas.find(({ name }) => name === task.personaName) || {}),
6193
- ...task.expectations,
6194
- },
6195
- format: task.format,
6196
- postprocessingFunctionNames: task.postprocessingFunctionNames,
6197
- }; // <- TODO: Not very good type guard
6198
- variant: switch (modelRequirements.modelVariant) {
6199
- case 'CHAT':
6200
- $ongoingTaskResult.$chatResult = await llmTools.callChatModel(
6201
- // <- TODO: [🧁] Check that `callChatModel` is defined
6202
- $deepFreeze($ongoingTaskResult.$prompt));
6203
- // TODO: [🍬] Destroy chatThread
6204
- $ongoingTaskResult.$result = $ongoingTaskResult.$chatResult;
6205
- $ongoingTaskResult.$resultString = $ongoingTaskResult.$chatResult.content;
6206
- break variant;
6207
- case 'COMPLETION':
6208
- $ongoingTaskResult.$completionResult = await llmTools.callCompletionModel(
6209
- // <- TODO: [🧁] Check that `callCompletionModel` is defined
6210
- $deepFreeze($ongoingTaskResult.$prompt));
6211
- $ongoingTaskResult.$result = $ongoingTaskResult.$completionResult;
6212
- $ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
6213
- break variant;
6214
- case 'EMBEDDING':
6215
- case 'IMAGE_GENERATION':
6216
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6217
- ${modelRequirements.modelVariant} model can not be used in pipeline
6218
-
6219
- This should be catched during parsing
6220
-
6221
- ${block(pipelineIdentification)}
6222
-
6223
- `));
6224
- break variant;
6225
- // <- case [πŸ€–]:
6226
- default:
6227
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6228
- Unknown model variant "${task.modelRequirements.modelVariant}"
6229
-
6230
- ${block(pipelineIdentification)}
6231
-
6232
- `));
6233
- }
6234
- }
6235
- break;
6236
- case 'SCRIPT_TASK':
6237
- if (arrayableToArray(tools.script).length === 0) {
6238
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6239
- No script execution tools are available
6376
+ This should be catched during parsing
6240
6377
 
6241
- ${block(pipelineIdentification)}
6242
- `));
6243
- }
6244
- if (!task.contentLanguage) {
6245
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6246
- Script language is not defined for SCRIPT TASK "${task.name}"
6378
+ ${block(pipelineIdentification)}
6247
6379
 
6248
- ${block(pipelineIdentification)}
6249
- `));
6250
- }
6251
- // TODO: DRY [☯]
6252
- scripts: for (const scriptTools of arrayableToArray(tools.script)) {
6253
- try {
6254
- $ongoingTaskResult.$resultString = await scriptTools.execute($deepFreeze({
6255
- scriptLanguage: task.contentLanguage,
6256
- script: preparedContent,
6257
- parameters,
6258
- }));
6259
- break scripts;
6260
- }
6261
- catch (error) {
6262
- assertsError(error);
6263
- if (error instanceof UnexpectedError) {
6264
- throw error;
6265
- }
6266
- $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6267
- }
6268
- }
6269
- if ($ongoingTaskResult.$resultString !== null) {
6270
- break taskType;
6271
- }
6272
- if ($ongoingTaskResult.$scriptPipelineExecutionErrors.length === 1) {
6273
- throw $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
6274
- }
6275
- else {
6276
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6277
- Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
6380
+ `));
6381
+ // <- case [πŸ€–]:
6382
+ default:
6383
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6384
+ Unknown model variant "${task.modelRequirements.modelVariant}"
6278
6385
 
6279
- ${block(pipelineIdentification)}
6386
+ ${block(pipelineIdentification)}
6280
6387
 
6281
- ${block($ongoingTaskResult.$scriptPipelineExecutionErrors
6282
- .map((error) => '- ' + error.message)
6283
- .join('\n\n'))}
6284
- `));
6285
- }
6286
- // Note: This line is unreachable because of the break taskType above
6287
- break taskType;
6288
- case 'DIALOG_TASK':
6289
- if (tools.userInterface === undefined) {
6290
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6291
- User interface tools are not available
6388
+ `));
6389
+ }
6390
+ }
6391
+ /**
6392
+ * Executes a script task with the first script tool that succeeds.
6393
+ */
6394
+ async function executeScriptTaskAttempt(options) {
6395
+ const { tools, task, preparedContent, parameters, pipelineIdentification, $ongoingTaskResult } = options;
6396
+ const scriptExecutionTools = arrayableToArray(tools.script);
6397
+ if (scriptExecutionTools.length === 0) {
6398
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6399
+ No script execution tools are available
6292
6400
 
6293
- ${block(pipelineIdentification)}
6294
- `));
6295
- }
6296
- // TODO: [🌹] When making next attempt for `DIALOG TASK`, preserve the previous user input
6297
- $ongoingTaskResult.$resultString = await tools.userInterface.promptDialog($deepFreeze({
6298
- promptTitle: task.title,
6299
- promptMessage: templateParameters(task.description || '', parameters),
6300
- defaultValue: templateParameters(preparedContent, parameters),
6301
- // TODO: [🧠] Figure out how to define placeholder in .book.md file
6302
- placeholder: undefined,
6303
- priority,
6304
- }));
6305
- break taskType;
6306
- // <- case: [πŸ…±]
6307
- default:
6308
- throw new PipelineExecutionError(spaceTrim$1((block) => `
6309
- Unknown execution type "${task.taskType}"
6401
+ ${block(pipelineIdentification)}
6402
+ `));
6403
+ }
6404
+ if (!task.contentLanguage) {
6405
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6406
+ Script language is not defined for SCRIPT TASK "${task.name}"
6310
6407
 
6311
- ${block(pipelineIdentification)}
6312
- `));
6313
- }
6314
- }
6315
- if (!isJokerAttempt && task.postprocessingFunctionNames) {
6316
- for (const functionName of task.postprocessingFunctionNames) {
6317
- let postprocessingError = null;
6318
- scripts: for (const scriptTools of arrayableToArray(tools.script)) {
6319
- try {
6320
- $ongoingTaskResult.$resultString = await scriptTools.execute({
6321
- scriptLanguage: `javascript` /* <- TODO: Try it in each languages; In future allow postprocessing with arbitrary combination of languages to combine */,
6322
- script: `${functionName}(resultString)`,
6323
- parameters: {
6324
- resultString: $ongoingTaskResult.$resultString || '',
6325
- // Note: No ...parametersForTask, because working with result only
6326
- },
6327
- });
6328
- postprocessingError = null;
6329
- break scripts;
6330
- }
6331
- catch (error) {
6332
- assertsError(error);
6333
- if (error instanceof UnexpectedError) {
6334
- throw error;
6335
- }
6336
- postprocessingError = error;
6337
- $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6338
- }
6339
- }
6340
- if (postprocessingError) {
6341
- throw postprocessingError;
6342
- }
6343
- }
6344
- }
6345
- // TODO: [πŸ’] Unite object for expecting amount and format
6346
- // Use the common validation function for both format and expectations
6347
- if (task.format || task.expectations) {
6348
- const validationResult = validatePromptResult({
6349
- resultString: $ongoingTaskResult.$resultString || '',
6350
- expectations: task.expectations,
6351
- format: task.format,
6352
- });
6353
- if (!validationResult.isValid) {
6354
- throw validationResult.error;
6355
- }
6356
- // Update the result string in case format processing modified it (e.g., JSON extraction)
6357
- $ongoingTaskResult.$resultString = validationResult.processedResultString;
6358
- }
6359
- break attempts;
6408
+ ${block(pipelineIdentification)}
6409
+ `));
6410
+ }
6411
+ for (const scriptTools of scriptExecutionTools) {
6412
+ try {
6413
+ $ongoingTaskResult.$resultString = await scriptTools.execute($deepFreeze({
6414
+ scriptLanguage: task.contentLanguage,
6415
+ script: preparedContent,
6416
+ parameters,
6417
+ }));
6418
+ return;
6360
6419
  }
6361
6420
  catch (error) {
6362
- if (!(error instanceof ExpectError)) {
6421
+ assertsError(error);
6422
+ if (error instanceof UnexpectedError) {
6363
6423
  throw error;
6364
6424
  }
6365
- $ongoingTaskResult.$expectError = error;
6366
- // Store each failed attempt
6367
- if (!Array.isArray($ongoingTaskResult.$failedResults)) {
6368
- $ongoingTaskResult.$failedResults = [];
6369
- }
6370
- $ongoingTaskResult.$failedResults.push({
6371
- attemptIndex,
6372
- result: $ongoingTaskResult.$resultString,
6373
- error: error,
6374
- });
6375
- // Report failed attempt
6376
- onProgress({
6377
- errors: [error],
6425
+ $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6426
+ }
6427
+ }
6428
+ throw createScriptExecutionFailure({
6429
+ pipelineIdentification,
6430
+ $ongoingTaskResult,
6431
+ });
6432
+ }
6433
+ /**
6434
+ * Creates the final script-task error after all script tools have failed.
6435
+ */
6436
+ function createScriptExecutionFailure(options) {
6437
+ const { pipelineIdentification, $ongoingTaskResult } = options;
6438
+ if ($ongoingTaskResult.$scriptPipelineExecutionErrors.length === 1) {
6439
+ return $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
6440
+ }
6441
+ return new PipelineExecutionError(spaceTrim$1((block) => `
6442
+ Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
6443
+
6444
+ ${block(pipelineIdentification)}
6445
+
6446
+ ${block($ongoingTaskResult.$scriptPipelineExecutionErrors.map((error) => '- ' + error.message).join('\n\n'))}
6447
+ `));
6448
+ }
6449
+ /**
6450
+ * Executes a dialog task through the configured user-interface tools.
6451
+ */
6452
+ async function executeDialogTaskAttempt(options) {
6453
+ const { tools, task, parameters, preparedContent, priority, pipelineIdentification, $ongoingTaskResult } = options;
6454
+ if (tools.userInterface === undefined) {
6455
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6456
+ User interface tools are not available
6457
+
6458
+ ${block(pipelineIdentification)}
6459
+ `));
6460
+ }
6461
+ // TODO: [🌹] When making next attempt for `DIALOG TASK`, preserve the previous user input
6462
+ $ongoingTaskResult.$resultString = await tools.userInterface.promptDialog($deepFreeze({
6463
+ promptTitle: task.title,
6464
+ promptMessage: templateParameters(task.description || '', parameters),
6465
+ defaultValue: templateParameters(preparedContent, parameters),
6466
+ // TODO: [🧠] Figure out how to define placeholder in .book.md file
6467
+ placeholder: undefined,
6468
+ priority,
6469
+ }));
6470
+ }
6471
+ /**
6472
+ * Runs all configured postprocessing functions in order.
6473
+ */
6474
+ async function applyPostprocessingFunctions(options) {
6475
+ const { task } = options;
6476
+ if (!task.postprocessingFunctionNames) {
6477
+ return;
6478
+ }
6479
+ for (const functionName of task.postprocessingFunctionNames) {
6480
+ await executePostprocessingFunction({
6481
+ functionName,
6482
+ tools: options.tools,
6483
+ $ongoingTaskResult: options.$ongoingTaskResult,
6484
+ });
6485
+ }
6486
+ }
6487
+ /**
6488
+ * Executes one postprocessing function against the current result string.
6489
+ */
6490
+ async function executePostprocessingFunction(options) {
6491
+ const { functionName, tools, $ongoingTaskResult } = options;
6492
+ let postprocessingError = null;
6493
+ for (const scriptTools of arrayableToArray(tools.script)) {
6494
+ try {
6495
+ $ongoingTaskResult.$resultString = await scriptTools.execute({
6496
+ scriptLanguage: `javascript` /* <- TODO: Try it in each languages; In future allow postprocessing with arbitrary combination of languages to combine */,
6497
+ script: `${functionName}(resultString)`,
6498
+ parameters: {
6499
+ resultString: $ongoingTaskResult.$resultString || '',
6500
+ // Note: No ...parametersForTask, because working with result only
6501
+ },
6378
6502
  });
6503
+ postprocessingError = null;
6504
+ return;
6379
6505
  }
6380
- finally {
6381
- if (!isJokerAttempt && task.taskType === 'PROMPT_TASK' && $ongoingTaskResult.$prompt) {
6382
- // Note: [2] When some expected parameter is not defined, error will occur in templateParameters
6383
- // In that case we don’t want to make a report about it because it’s not a llm execution error
6384
- const executionPromptReport = {
6385
- prompt: {
6386
- ...$ongoingTaskResult.$prompt,
6387
- // <- TODO: [🧠] How to pick everyhing except `pipelineUrl`
6388
- },
6389
- result: $ongoingTaskResult.$result || undefined,
6390
- error: $ongoingTaskResult.$expectError === null
6391
- ? undefined
6392
- : serializeError($ongoingTaskResult.$expectError),
6393
- };
6394
- $executionReport.promptExecutions.push(executionPromptReport);
6395
- if (logLlmCall) {
6396
- logLlmCall({
6397
- modelName: 'model' /* <- TODO: How to get model name from the report */,
6398
- report: executionPromptReport,
6399
- });
6400
- }
6506
+ catch (error) {
6507
+ assertsError(error);
6508
+ if (error instanceof UnexpectedError) {
6509
+ throw error;
6401
6510
  }
6511
+ postprocessingError = error;
6512
+ $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6402
6513
  }
6403
- if ($ongoingTaskResult.$expectError !== null && attemptIndex === maxAttempts - 1) {
6404
- // Note: Create a summary of all failures
6405
- const failuresSummary = $ongoingTaskResult.$failedResults
6406
- .map((failure) => spaceTrim$1((block) => {
6407
- var _a, _b;
6408
- return `
6409
- Attempt ${failure.attemptIndex + 1}:
6410
- Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
6411
- ${block((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message.split(/\r?\n/).map((line) => `> ${line}`).join('\n'))}
6412
-
6413
- Result:
6414
- ${block(failure.result === null
6415
- ? 'null'
6416
- : spaceTrim$1(failure.result)
6417
- .split(/\r?\n/)
6418
- .map((line) => `> ${line}`)
6419
- .join('\n'))}
6420
- `;
6421
- }))
6422
- .join('\n\n---\n\n');
6423
- throw new PipelineExecutionError(spaceTrim$1((block) => {
6424
- var _a;
6425
- return `
6426
- LLM execution failed ${maxExecutionAttempts}x
6514
+ }
6515
+ if (postprocessingError) {
6516
+ throw postprocessingError;
6517
+ }
6518
+ }
6519
+ /**
6520
+ * Validates the current result string against expectations and format constraints.
6521
+ */
6522
+ function validateAttemptResult(options) {
6523
+ const { task, $ongoingTaskResult } = options;
6524
+ if (!task.format && !task.expectations) {
6525
+ return;
6526
+ }
6527
+ // TODO: [πŸ’] Unite object for expecting amount and format
6528
+ // Use the common validation function for both format and expectations
6529
+ const validationResult = validatePromptResult({
6530
+ resultString: $ongoingTaskResult.$resultString || '',
6531
+ expectations: task.expectations,
6532
+ format: task.format,
6533
+ });
6534
+ if (!validationResult.isValid) {
6535
+ throw validationResult.error;
6536
+ }
6537
+ // Update the result string in case format processing modified it (e.g., JSON extraction)
6538
+ $ongoingTaskResult.$resultString = validationResult.processedResultString;
6539
+ }
6540
+ /**
6541
+ * Stores one failed attempt and reports the expectation error upstream.
6542
+ */
6543
+ function recordFailedAttempt(options) {
6544
+ const { error, attemptIndex, onProgress, $ongoingTaskResult } = options;
6545
+ $ongoingTaskResult.$expectError = error;
6546
+ $ongoingTaskResult.$failedResults.push({
6547
+ attemptIndex,
6548
+ result: $ongoingTaskResult.$resultString,
6549
+ error,
6550
+ });
6551
+ onProgress({
6552
+ errors: [error],
6553
+ });
6554
+ }
6555
+ /**
6556
+ * Appends the prompt execution report for prompt-task attempts.
6557
+ */
6558
+ function reportPromptExecution(options) {
6559
+ const { attempt, task, $executionReport, logLlmCall, $ongoingTaskResult } = options;
6560
+ if (attempt.isJokerAttempt || task.taskType !== 'PROMPT_TASK' || !$ongoingTaskResult.$prompt) {
6561
+ return;
6562
+ }
6563
+ // Note: [2] When some expected parameter is not defined, error will occur in templateParameters
6564
+ // In that case we don’t want to make a report about it because it’s not a llm execution error
6565
+ const executionPromptReport = {
6566
+ prompt: {
6567
+ ...$ongoingTaskResult.$prompt,
6568
+ // <- TODO: [🧠] How to pick everyhing except `pipelineUrl`
6569
+ },
6570
+ result: $ongoingTaskResult.$result || undefined,
6571
+ error: $ongoingTaskResult.$expectError === null ? undefined : serializeError($ongoingTaskResult.$expectError),
6572
+ };
6573
+ $executionReport.promptExecutions.push(executionPromptReport);
6574
+ if (logLlmCall) {
6575
+ logLlmCall({
6576
+ modelName: 'model' /* <- TODO: How to get model name from the report */,
6577
+ report: executionPromptReport,
6578
+ });
6579
+ }
6580
+ }
6581
+ /**
6582
+ * Throws the aggregated retry error after the last regular attempt fails expectations.
6583
+ */
6584
+ function throwIfFinalAttemptFailed(options) {
6585
+ const { attemptIndex, maxAttempts, maxExecutionAttempts, pipelineIdentification, $ongoingTaskResult } = options;
6586
+ if ($ongoingTaskResult.$expectError === null || attemptIndex !== maxAttempts - 1) {
6587
+ return;
6588
+ }
6589
+ throw new PipelineExecutionError(spaceTrim$1((block) => {
6590
+ var _a;
6591
+ return `
6592
+ LLM execution failed ${maxExecutionAttempts}x
6427
6593
 
6428
- ${block(pipelineIdentification)}
6594
+ ${block(pipelineIdentification)}
6429
6595
 
6430
- The Prompt:
6431
- ${block((((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || '')
6432
- .split(/\r?\n/)
6433
- .map((line) => `> ${line}`)
6434
- .join('\n'))}
6596
+ The Prompt:
6597
+ ${block(quoteMultilineText(((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || ''))}
6435
6598
 
6436
- All Failed Attempts:
6437
- ${block(failuresSummary)}
6438
- `;
6439
- }));
6440
- }
6441
- }
6599
+ All Failed Attempts:
6600
+ ${block(createFailuresSummary($ongoingTaskResult.$failedResults))}
6601
+ `;
6602
+ }));
6603
+ }
6604
+ /**
6605
+ * Renders the retry history into the aggregated final error body.
6606
+ */
6607
+ function createFailuresSummary($failedResults) {
6608
+ return $failedResults
6609
+ .map((failure) => spaceTrim$1((block) => {
6610
+ var _a, _b;
6611
+ return `
6612
+ Attempt ${failure.attemptIndex + 1}:
6613
+ Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
6614
+ ${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
6615
+
6616
+ Result:
6617
+ ${block(failure.result === null ? 'null' : quoteMultilineText(spaceTrim$1(failure.result)))}
6618
+ `;
6619
+ }))
6620
+ .join('\n\n---\n\n');
6621
+ }
6622
+ /**
6623
+ * Formats multiline text as a quoted markdown block.
6624
+ */
6625
+ function quoteMultilineText(text) {
6626
+ return text
6627
+ .split(/\r?\n/)
6628
+ .map((line) => `> ${line}`)
6629
+ .join('\n');
6630
+ }
6631
+ /**
6632
+ * Returns the successful result string or raises an unexpected internal-state error.
6633
+ */
6634
+ function getSuccessfulResultString(options) {
6635
+ const { pipelineIdentification, $ongoingTaskResult } = options;
6442
6636
  if ($ongoingTaskResult.$resultString === null) {
6443
6637
  throw new UnexpectedError(spaceTrim$1((block) => `
6444
6638
  Something went wrong and prompt result is null
@@ -6448,7 +6642,6 @@ async function executeAttempts(options) {
6448
6642
  }
6449
6643
  return $ongoingTaskResult.$resultString;
6450
6644
  }
6451
- // TODO: Break into smaller functions
6452
6645
 
6453
6646
  /**
6454
6647
  * Executes a pipeline task that requires mapping or iterating over subvalues of a parameter (such as rows in a CSV).