@promptbook/documents 0.112.0-40 β†’ 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/umd/index.umd.js CHANGED
@@ -24,7 +24,7 @@
24
24
  * @generated
25
25
  * @see https://github.com/webgptorg/promptbook
26
26
  */
27
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-40';
27
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-41';
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
@@ -6281,317 +6281,511 @@
6281
6281
  * @private internal utility of `createPipelineExecutor`
6282
6282
  */
6283
6283
  async function executeAttempts(options) {
6284
- const { jokerParameterNames, priority, maxAttempts, // <- Note: [πŸ’‚]
6285
- preparedContent, parameters, task, preparedPipeline, tools, $executionReport, pipelineIdentification, maxExecutionAttempts, onProgress, logLlmCall, } = options;
6286
- const $ongoingTaskResult = {
6284
+ const $ongoingTaskResult = createOngoingTaskResult();
6285
+ const llmTools = getSingleLlmExecutionTools(options.tools.llm);
6286
+ attempts: for (let attemptIndex = -options.jokerParameterNames.length; attemptIndex < options.maxAttempts; attemptIndex++) {
6287
+ const attempt = createAttemptDescriptor({
6288
+ attemptIndex,
6289
+ jokerParameterNames: options.jokerParameterNames,
6290
+ pipelineIdentification: options.pipelineIdentification,
6291
+ });
6292
+ resetAttemptExecutionState($ongoingTaskResult);
6293
+ try {
6294
+ await executeSingleAttempt({
6295
+ attempt,
6296
+ options,
6297
+ llmTools,
6298
+ $ongoingTaskResult,
6299
+ });
6300
+ break attempts;
6301
+ }
6302
+ catch (error) {
6303
+ if (!(error instanceof ExpectError)) {
6304
+ throw error;
6305
+ }
6306
+ recordFailedAttempt({
6307
+ error,
6308
+ attemptIndex,
6309
+ onProgress: options.onProgress,
6310
+ $ongoingTaskResult,
6311
+ });
6312
+ }
6313
+ finally {
6314
+ reportPromptExecution({
6315
+ attempt,
6316
+ task: options.task,
6317
+ $executionReport: options.$executionReport,
6318
+ logLlmCall: options.logLlmCall,
6319
+ $ongoingTaskResult,
6320
+ });
6321
+ }
6322
+ throwIfFinalAttemptFailed({
6323
+ attemptIndex,
6324
+ maxAttempts: options.maxAttempts,
6325
+ maxExecutionAttempts: options.maxExecutionAttempts,
6326
+ pipelineIdentification: options.pipelineIdentification,
6327
+ $ongoingTaskResult,
6328
+ });
6329
+ }
6330
+ return getSuccessfulResultString({
6331
+ pipelineIdentification: options.pipelineIdentification,
6332
+ $ongoingTaskResult,
6333
+ });
6334
+ }
6335
+ /**
6336
+ * Creates mutable attempt state for one task execution lifecycle.
6337
+ */
6338
+ function createOngoingTaskResult() {
6339
+ return {
6287
6340
  $result: null,
6288
6341
  $resultString: null,
6289
6342
  $expectError: null,
6290
6343
  $scriptPipelineExecutionErrors: [],
6291
- $failedResults: [], // Track all failed attempts
6344
+ $failedResults: [],
6292
6345
  };
6293
- const llmTools = getSingleLlmExecutionTools(tools.llm);
6294
- attempts: for (let attemptIndex = -jokerParameterNames.length; attemptIndex < maxAttempts; attemptIndex++) {
6295
- const isJokerAttempt = attemptIndex < 0;
6296
- const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attemptIndex];
6297
- // TODO: [🧠][🍭] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
6298
- if (isJokerAttempt && !jokerParameterName) {
6299
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
6300
- Joker not found in attempt ${attemptIndex}
6346
+ }
6347
+ /**
6348
+ * Resolves the bookkeeping for one loop iteration, including joker lookup.
6349
+ */
6350
+ function createAttemptDescriptor(options) {
6351
+ const { attemptIndex, jokerParameterNames, pipelineIdentification } = options;
6352
+ const isJokerAttempt = attemptIndex < 0;
6353
+ const jokerParameterName = isJokerAttempt
6354
+ ? jokerParameterNames[jokerParameterNames.length + attemptIndex]
6355
+ : undefined;
6356
+ if (isJokerAttempt && !jokerParameterName) {
6357
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
6358
+ Joker not found in attempt ${attemptIndex}
6301
6359
 
6302
- ${block(pipelineIdentification)}
6360
+ ${block(pipelineIdentification)}
6361
+ `));
6362
+ }
6363
+ return {
6364
+ attemptIndex,
6365
+ isJokerAttempt,
6366
+ jokerParameterName,
6367
+ };
6368
+ }
6369
+ /**
6370
+ * Clears the per-attempt result slots while preserving cumulative failure history.
6371
+ */
6372
+ function resetAttemptExecutionState($ongoingTaskResult) {
6373
+ $ongoingTaskResult.$result = null;
6374
+ $ongoingTaskResult.$resultString = null;
6375
+ $ongoingTaskResult.$expectError = null;
6376
+ }
6377
+ /**
6378
+ * Executes one loop iteration, from joker resolution or task execution through validation.
6379
+ */
6380
+ async function executeSingleAttempt(options) {
6381
+ const { attempt, options: executeAttemptsOptions, llmTools, $ongoingTaskResult } = options;
6382
+ if (attempt.isJokerAttempt) {
6383
+ resolveJokerAttemptResult({
6384
+ jokerParameterName: attempt.jokerParameterName,
6385
+ parameters: executeAttemptsOptions.parameters,
6386
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6387
+ $ongoingTaskResult,
6388
+ });
6389
+ }
6390
+ else {
6391
+ await executeTaskAttempt({
6392
+ options: executeAttemptsOptions,
6393
+ llmTools,
6394
+ $ongoingTaskResult,
6395
+ });
6396
+ await applyPostprocessingFunctions({
6397
+ task: executeAttemptsOptions.task,
6398
+ tools: executeAttemptsOptions.tools,
6399
+ $ongoingTaskResult,
6400
+ });
6401
+ }
6402
+ validateAttemptResult({
6403
+ task: executeAttemptsOptions.task,
6404
+ $ongoingTaskResult,
6405
+ });
6406
+ }
6407
+ /**
6408
+ * Resolves the shortcut value used by a joker attempt.
6409
+ */
6410
+ function resolveJokerAttemptResult(options) {
6411
+ const { jokerParameterName, parameters, pipelineIdentification, $ongoingTaskResult } = options;
6412
+ if (parameters[jokerParameterName] === undefined) {
6413
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6414
+ Joker parameter {${jokerParameterName}} not defined
6415
+
6416
+ ${block(pipelineIdentification)}
6417
+ `));
6418
+ // <- TODO: This is maybe `PipelineLogicError` which should be detected in `validatePipeline` and here just thrown as `UnexpectedError`
6419
+ }
6420
+ $ongoingTaskResult.$resultString = parameters[jokerParameterName];
6421
+ }
6422
+ /**
6423
+ * Dispatches non-joker execution to the handler for the current task type.
6424
+ */
6425
+ async function executeTaskAttempt(options) {
6426
+ const { options: executeAttemptsOptions, llmTools, $ongoingTaskResult } = options;
6427
+ const { task } = executeAttemptsOptions;
6428
+ switch (task.taskType) {
6429
+ case 'SIMPLE_TASK':
6430
+ executeSimpleTaskAttempt({
6431
+ preparedContent: executeAttemptsOptions.preparedContent,
6432
+ parameters: executeAttemptsOptions.parameters,
6433
+ $ongoingTaskResult,
6434
+ });
6435
+ return;
6436
+ case 'PROMPT_TASK':
6437
+ await executePromptTaskAttempt({
6438
+ preparedPipeline: executeAttemptsOptions.preparedPipeline,
6439
+ task,
6440
+ parameters: executeAttemptsOptions.parameters,
6441
+ preparedContent: executeAttemptsOptions.preparedContent,
6442
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6443
+ llmTools,
6444
+ $ongoingTaskResult,
6445
+ });
6446
+ return;
6447
+ case 'SCRIPT_TASK':
6448
+ await executeScriptTaskAttempt({
6449
+ tools: executeAttemptsOptions.tools,
6450
+ task,
6451
+ preparedContent: executeAttemptsOptions.preparedContent,
6452
+ parameters: executeAttemptsOptions.parameters,
6453
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6454
+ $ongoingTaskResult,
6455
+ });
6456
+ return;
6457
+ case 'DIALOG_TASK':
6458
+ await executeDialogTaskAttempt({
6459
+ tools: executeAttemptsOptions.tools,
6460
+ task,
6461
+ parameters: executeAttemptsOptions.parameters,
6462
+ preparedContent: executeAttemptsOptions.preparedContent,
6463
+ priority: executeAttemptsOptions.priority,
6464
+ pipelineIdentification: executeAttemptsOptions.pipelineIdentification,
6465
+ $ongoingTaskResult,
6466
+ });
6467
+ return;
6468
+ default:
6469
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6470
+ Unknown execution type "${task.taskType}"
6471
+
6472
+ ${block(executeAttemptsOptions.pipelineIdentification)}
6303
6473
  `));
6304
- }
6305
- $ongoingTaskResult.$result = null;
6306
- $ongoingTaskResult.$resultString = null;
6307
- $ongoingTaskResult.$expectError = null;
6308
- if (isJokerAttempt) {
6309
- if (parameters[jokerParameterName] === undefined) {
6310
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6311
- Joker parameter {${jokerParameterName}} not defined
6474
+ }
6475
+ }
6476
+ /**
6477
+ * Executes a simple templated task with no external tools.
6478
+ */
6479
+ function executeSimpleTaskAttempt(options) {
6480
+ const { preparedContent, parameters, $ongoingTaskResult } = options;
6481
+ $ongoingTaskResult.$resultString = templateParameters(preparedContent, parameters);
6482
+ }
6483
+ /**
6484
+ * Builds the prompt for a prompt task and calls the appropriate LLM variant.
6485
+ */
6486
+ async function executePromptTaskAttempt(options) {
6487
+ const { preparedPipeline, task, parameters, preparedContent, pipelineIdentification, llmTools, $ongoingTaskResult, } = options;
6488
+ const modelRequirements = {
6489
+ modelVariant: 'CHAT',
6490
+ ...(preparedPipeline.defaultModelRequirements || {}),
6491
+ ...(task.modelRequirements || {}),
6492
+ }; /* <- Note: [πŸ€›] */
6493
+ $ongoingTaskResult.$prompt = {
6494
+ title: task.title,
6495
+ pipelineUrl: `${preparedPipeline.pipelineUrl ? preparedPipeline.pipelineUrl : 'anonymous'}#${task.name
6496
+ // <- TODO: Here should be maybe also subformat index to distinguish between same task with different subformat values
6497
+ }`,
6498
+ parameters,
6499
+ content: preparedContent,
6500
+ modelRequirements,
6501
+ expectations: {
6502
+ ...(preparedPipeline.personas.find(({ name }) => name === task.personaName) || {}),
6503
+ ...task.expectations,
6504
+ },
6505
+ format: task.format,
6506
+ postprocessingFunctionNames: task.postprocessingFunctionNames,
6507
+ }; // <- TODO: Not very good type guard
6508
+ switch (modelRequirements.modelVariant) {
6509
+ case 'CHAT':
6510
+ $ongoingTaskResult.$chatResult = await llmTools.callChatModel(
6511
+ // <- TODO: [🧁] Check that `callChatModel` is defined
6512
+ $deepFreeze($ongoingTaskResult.$prompt));
6513
+ // TODO: [🍬] Destroy chatThread
6514
+ $ongoingTaskResult.$result = $ongoingTaskResult.$chatResult;
6515
+ $ongoingTaskResult.$resultString = $ongoingTaskResult.$chatResult.content;
6516
+ return;
6517
+ case 'COMPLETION':
6518
+ $ongoingTaskResult.$completionResult = await llmTools.callCompletionModel(
6519
+ // <- TODO: [🧁] Check that `callCompletionModel` is defined
6520
+ $deepFreeze($ongoingTaskResult.$prompt));
6521
+ $ongoingTaskResult.$result = $ongoingTaskResult.$completionResult;
6522
+ $ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
6523
+ return;
6524
+ case 'EMBEDDING':
6525
+ case 'IMAGE_GENERATION':
6526
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6527
+ ${modelRequirements.modelVariant} model can not be used in pipeline
6312
6528
 
6313
- ${block(pipelineIdentification)}
6314
- `));
6315
- // <- TODO: This is maybe `PipelineLogicError` which should be detected in `validatePipeline` and here just thrown as `UnexpectedError`
6316
- }
6317
- else {
6318
- $ongoingTaskResult.$resultString = parameters[jokerParameterName];
6319
- }
6320
- }
6321
- try {
6322
- if (!isJokerAttempt) {
6323
- taskType: switch (task.taskType) {
6324
- case 'SIMPLE_TASK':
6325
- $ongoingTaskResult.$resultString = templateParameters(preparedContent, parameters);
6326
- break taskType;
6327
- case 'PROMPT_TASK':
6328
- {
6329
- const modelRequirements = {
6330
- modelVariant: 'CHAT',
6331
- ...(preparedPipeline.defaultModelRequirements || {}),
6332
- ...(task.modelRequirements || {}),
6333
- }; /* <- Note: [πŸ€›] */
6334
- $ongoingTaskResult.$prompt = {
6335
- title: task.title,
6336
- pipelineUrl: `${preparedPipeline.pipelineUrl
6337
- ? preparedPipeline.pipelineUrl
6338
- : 'anonymous' /* <- TODO: [🧠] How to deal with anonymous pipelines, do here some auto-url like SHA-256 based ad-hoc identifier? */}#${task.name
6339
- // <- TODO: Here should be maybe also subformat index to distinguish between same task with different subformat values
6340
- }`,
6341
- parameters,
6342
- content: preparedContent,
6343
- modelRequirements,
6344
- expectations: {
6345
- ...(preparedPipeline.personas.find(({ name }) => name === task.personaName) || {}),
6346
- ...task.expectations,
6347
- },
6348
- format: task.format,
6349
- postprocessingFunctionNames: task.postprocessingFunctionNames,
6350
- }; // <- TODO: Not very good type guard
6351
- variant: switch (modelRequirements.modelVariant) {
6352
- case 'CHAT':
6353
- $ongoingTaskResult.$chatResult = await llmTools.callChatModel(
6354
- // <- TODO: [🧁] Check that `callChatModel` is defined
6355
- $deepFreeze($ongoingTaskResult.$prompt));
6356
- // TODO: [🍬] Destroy chatThread
6357
- $ongoingTaskResult.$result = $ongoingTaskResult.$chatResult;
6358
- $ongoingTaskResult.$resultString = $ongoingTaskResult.$chatResult.content;
6359
- break variant;
6360
- case 'COMPLETION':
6361
- $ongoingTaskResult.$completionResult = await llmTools.callCompletionModel(
6362
- // <- TODO: [🧁] Check that `callCompletionModel` is defined
6363
- $deepFreeze($ongoingTaskResult.$prompt));
6364
- $ongoingTaskResult.$result = $ongoingTaskResult.$completionResult;
6365
- $ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
6366
- break variant;
6367
- case 'EMBEDDING':
6368
- case 'IMAGE_GENERATION':
6369
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6370
- ${modelRequirements.modelVariant} model can not be used in pipeline
6371
-
6372
- This should be catched during parsing
6373
-
6374
- ${block(pipelineIdentification)}
6375
-
6376
- `));
6377
- break variant;
6378
- // <- case [πŸ€–]:
6379
- default:
6380
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6381
- Unknown model variant "${task.modelRequirements.modelVariant}"
6382
-
6383
- ${block(pipelineIdentification)}
6384
-
6385
- `));
6386
- }
6387
- }
6388
- break;
6389
- case 'SCRIPT_TASK':
6390
- if (arrayableToArray(tools.script).length === 0) {
6391
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6392
- No script execution tools are available
6529
+ This should be catched during parsing
6393
6530
 
6394
- ${block(pipelineIdentification)}
6395
- `));
6396
- }
6397
- if (!task.contentLanguage) {
6398
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6399
- Script language is not defined for SCRIPT TASK "${task.name}"
6531
+ ${block(pipelineIdentification)}
6400
6532
 
6401
- ${block(pipelineIdentification)}
6402
- `));
6403
- }
6404
- // TODO: DRY [☯]
6405
- scripts: for (const scriptTools of arrayableToArray(tools.script)) {
6406
- try {
6407
- $ongoingTaskResult.$resultString = await scriptTools.execute($deepFreeze({
6408
- scriptLanguage: task.contentLanguage,
6409
- script: preparedContent,
6410
- parameters,
6411
- }));
6412
- break scripts;
6413
- }
6414
- catch (error) {
6415
- assertsError(error);
6416
- if (error instanceof UnexpectedError) {
6417
- throw error;
6418
- }
6419
- $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6420
- }
6421
- }
6422
- if ($ongoingTaskResult.$resultString !== null) {
6423
- break taskType;
6424
- }
6425
- if ($ongoingTaskResult.$scriptPipelineExecutionErrors.length === 1) {
6426
- throw $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
6427
- }
6428
- else {
6429
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6430
- Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
6533
+ `));
6534
+ // <- case [πŸ€–]:
6535
+ default:
6536
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6537
+ Unknown model variant "${task.modelRequirements.modelVariant}"
6431
6538
 
6432
- ${block(pipelineIdentification)}
6539
+ ${block(pipelineIdentification)}
6433
6540
 
6434
- ${block($ongoingTaskResult.$scriptPipelineExecutionErrors
6435
- .map((error) => '- ' + error.message)
6436
- .join('\n\n'))}
6437
- `));
6438
- }
6439
- // Note: This line is unreachable because of the break taskType above
6440
- break taskType;
6441
- case 'DIALOG_TASK':
6442
- if (tools.userInterface === undefined) {
6443
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6444
- User interface tools are not available
6541
+ `));
6542
+ }
6543
+ }
6544
+ /**
6545
+ * Executes a script task with the first script tool that succeeds.
6546
+ */
6547
+ async function executeScriptTaskAttempt(options) {
6548
+ const { tools, task, preparedContent, parameters, pipelineIdentification, $ongoingTaskResult } = options;
6549
+ const scriptExecutionTools = arrayableToArray(tools.script);
6550
+ if (scriptExecutionTools.length === 0) {
6551
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6552
+ No script execution tools are available
6445
6553
 
6446
- ${block(pipelineIdentification)}
6447
- `));
6448
- }
6449
- // TODO: [🌹] When making next attempt for `DIALOG TASK`, preserve the previous user input
6450
- $ongoingTaskResult.$resultString = await tools.userInterface.promptDialog($deepFreeze({
6451
- promptTitle: task.title,
6452
- promptMessage: templateParameters(task.description || '', parameters),
6453
- defaultValue: templateParameters(preparedContent, parameters),
6454
- // TODO: [🧠] Figure out how to define placeholder in .book.md file
6455
- placeholder: undefined,
6456
- priority,
6457
- }));
6458
- break taskType;
6459
- // <- case: [πŸ…±]
6460
- default:
6461
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6462
- Unknown execution type "${task.taskType}"
6554
+ ${block(pipelineIdentification)}
6555
+ `));
6556
+ }
6557
+ if (!task.contentLanguage) {
6558
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6559
+ Script language is not defined for SCRIPT TASK "${task.name}"
6463
6560
 
6464
- ${block(pipelineIdentification)}
6465
- `));
6466
- }
6467
- }
6468
- if (!isJokerAttempt && task.postprocessingFunctionNames) {
6469
- for (const functionName of task.postprocessingFunctionNames) {
6470
- let postprocessingError = null;
6471
- scripts: for (const scriptTools of arrayableToArray(tools.script)) {
6472
- try {
6473
- $ongoingTaskResult.$resultString = await scriptTools.execute({
6474
- scriptLanguage: `javascript` /* <- TODO: Try it in each languages; In future allow postprocessing with arbitrary combination of languages to combine */,
6475
- script: `${functionName}(resultString)`,
6476
- parameters: {
6477
- resultString: $ongoingTaskResult.$resultString || '',
6478
- // Note: No ...parametersForTask, because working with result only
6479
- },
6480
- });
6481
- postprocessingError = null;
6482
- break scripts;
6483
- }
6484
- catch (error) {
6485
- assertsError(error);
6486
- if (error instanceof UnexpectedError) {
6487
- throw error;
6488
- }
6489
- postprocessingError = error;
6490
- $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6491
- }
6492
- }
6493
- if (postprocessingError) {
6494
- throw postprocessingError;
6495
- }
6496
- }
6497
- }
6498
- // TODO: [πŸ’] Unite object for expecting amount and format
6499
- // Use the common validation function for both format and expectations
6500
- if (task.format || task.expectations) {
6501
- const validationResult = validatePromptResult({
6502
- resultString: $ongoingTaskResult.$resultString || '',
6503
- expectations: task.expectations,
6504
- format: task.format,
6505
- });
6506
- if (!validationResult.isValid) {
6507
- throw validationResult.error;
6508
- }
6509
- // Update the result string in case format processing modified it (e.g., JSON extraction)
6510
- $ongoingTaskResult.$resultString = validationResult.processedResultString;
6511
- }
6512
- break attempts;
6561
+ ${block(pipelineIdentification)}
6562
+ `));
6563
+ }
6564
+ for (const scriptTools of scriptExecutionTools) {
6565
+ try {
6566
+ $ongoingTaskResult.$resultString = await scriptTools.execute($deepFreeze({
6567
+ scriptLanguage: task.contentLanguage,
6568
+ script: preparedContent,
6569
+ parameters,
6570
+ }));
6571
+ return;
6513
6572
  }
6514
6573
  catch (error) {
6515
- if (!(error instanceof ExpectError)) {
6574
+ assertsError(error);
6575
+ if (error instanceof UnexpectedError) {
6516
6576
  throw error;
6517
6577
  }
6518
- $ongoingTaskResult.$expectError = error;
6519
- // Store each failed attempt
6520
- if (!Array.isArray($ongoingTaskResult.$failedResults)) {
6521
- $ongoingTaskResult.$failedResults = [];
6522
- }
6523
- $ongoingTaskResult.$failedResults.push({
6524
- attemptIndex,
6525
- result: $ongoingTaskResult.$resultString,
6526
- error: error,
6527
- });
6528
- // Report failed attempt
6529
- onProgress({
6530
- errors: [error],
6578
+ $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6579
+ }
6580
+ }
6581
+ throw createScriptExecutionFailure({
6582
+ pipelineIdentification,
6583
+ $ongoingTaskResult,
6584
+ });
6585
+ }
6586
+ /**
6587
+ * Creates the final script-task error after all script tools have failed.
6588
+ */
6589
+ function createScriptExecutionFailure(options) {
6590
+ const { pipelineIdentification, $ongoingTaskResult } = options;
6591
+ if ($ongoingTaskResult.$scriptPipelineExecutionErrors.length === 1) {
6592
+ return $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
6593
+ }
6594
+ return new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6595
+ Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
6596
+
6597
+ ${block(pipelineIdentification)}
6598
+
6599
+ ${block($ongoingTaskResult.$scriptPipelineExecutionErrors.map((error) => '- ' + error.message).join('\n\n'))}
6600
+ `));
6601
+ }
6602
+ /**
6603
+ * Executes a dialog task through the configured user-interface tools.
6604
+ */
6605
+ async function executeDialogTaskAttempt(options) {
6606
+ const { tools, task, parameters, preparedContent, priority, pipelineIdentification, $ongoingTaskResult } = options;
6607
+ if (tools.userInterface === undefined) {
6608
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => `
6609
+ User interface tools are not available
6610
+
6611
+ ${block(pipelineIdentification)}
6612
+ `));
6613
+ }
6614
+ // TODO: [🌹] When making next attempt for `DIALOG TASK`, preserve the previous user input
6615
+ $ongoingTaskResult.$resultString = await tools.userInterface.promptDialog($deepFreeze({
6616
+ promptTitle: task.title,
6617
+ promptMessage: templateParameters(task.description || '', parameters),
6618
+ defaultValue: templateParameters(preparedContent, parameters),
6619
+ // TODO: [🧠] Figure out how to define placeholder in .book.md file
6620
+ placeholder: undefined,
6621
+ priority,
6622
+ }));
6623
+ }
6624
+ /**
6625
+ * Runs all configured postprocessing functions in order.
6626
+ */
6627
+ async function applyPostprocessingFunctions(options) {
6628
+ const { task } = options;
6629
+ if (!task.postprocessingFunctionNames) {
6630
+ return;
6631
+ }
6632
+ for (const functionName of task.postprocessingFunctionNames) {
6633
+ await executePostprocessingFunction({
6634
+ functionName,
6635
+ tools: options.tools,
6636
+ $ongoingTaskResult: options.$ongoingTaskResult,
6637
+ });
6638
+ }
6639
+ }
6640
+ /**
6641
+ * Executes one postprocessing function against the current result string.
6642
+ */
6643
+ async function executePostprocessingFunction(options) {
6644
+ const { functionName, tools, $ongoingTaskResult } = options;
6645
+ let postprocessingError = null;
6646
+ for (const scriptTools of arrayableToArray(tools.script)) {
6647
+ try {
6648
+ $ongoingTaskResult.$resultString = await scriptTools.execute({
6649
+ scriptLanguage: `javascript` /* <- TODO: Try it in each languages; In future allow postprocessing with arbitrary combination of languages to combine */,
6650
+ script: `${functionName}(resultString)`,
6651
+ parameters: {
6652
+ resultString: $ongoingTaskResult.$resultString || '',
6653
+ // Note: No ...parametersForTask, because working with result only
6654
+ },
6531
6655
  });
6656
+ postprocessingError = null;
6657
+ return;
6532
6658
  }
6533
- finally {
6534
- if (!isJokerAttempt && task.taskType === 'PROMPT_TASK' && $ongoingTaskResult.$prompt) {
6535
- // Note: [2] When some expected parameter is not defined, error will occur in templateParameters
6536
- // In that case we don’t want to make a report about it because it’s not a llm execution error
6537
- const executionPromptReport = {
6538
- prompt: {
6539
- ...$ongoingTaskResult.$prompt,
6540
- // <- TODO: [🧠] How to pick everyhing except `pipelineUrl`
6541
- },
6542
- result: $ongoingTaskResult.$result || undefined,
6543
- error: $ongoingTaskResult.$expectError === null
6544
- ? undefined
6545
- : serializeError($ongoingTaskResult.$expectError),
6546
- };
6547
- $executionReport.promptExecutions.push(executionPromptReport);
6548
- if (logLlmCall) {
6549
- logLlmCall({
6550
- modelName: 'model' /* <- TODO: How to get model name from the report */,
6551
- report: executionPromptReport,
6552
- });
6553
- }
6659
+ catch (error) {
6660
+ assertsError(error);
6661
+ if (error instanceof UnexpectedError) {
6662
+ throw error;
6554
6663
  }
6664
+ postprocessingError = error;
6665
+ $ongoingTaskResult.$scriptPipelineExecutionErrors.push(error);
6555
6666
  }
6556
- if ($ongoingTaskResult.$expectError !== null && attemptIndex === maxAttempts - 1) {
6557
- // Note: Create a summary of all failures
6558
- const failuresSummary = $ongoingTaskResult.$failedResults
6559
- .map((failure) => spacetrim.spaceTrim((block) => {
6560
- var _a, _b;
6561
- return `
6562
- Attempt ${failure.attemptIndex + 1}:
6563
- Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
6564
- ${block((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message.split(/\r?\n/).map((line) => `> ${line}`).join('\n'))}
6565
-
6566
- Result:
6567
- ${block(failure.result === null
6568
- ? 'null'
6569
- : spacetrim.spaceTrim(failure.result)
6570
- .split(/\r?\n/)
6571
- .map((line) => `> ${line}`)
6572
- .join('\n'))}
6573
- `;
6574
- }))
6575
- .join('\n\n---\n\n');
6576
- throw new PipelineExecutionError(spacetrim.spaceTrim((block) => {
6577
- var _a;
6578
- return `
6579
- LLM execution failed ${maxExecutionAttempts}x
6667
+ }
6668
+ if (postprocessingError) {
6669
+ throw postprocessingError;
6670
+ }
6671
+ }
6672
+ /**
6673
+ * Validates the current result string against expectations and format constraints.
6674
+ */
6675
+ function validateAttemptResult(options) {
6676
+ const { task, $ongoingTaskResult } = options;
6677
+ if (!task.format && !task.expectations) {
6678
+ return;
6679
+ }
6680
+ // TODO: [πŸ’] Unite object for expecting amount and format
6681
+ // Use the common validation function for both format and expectations
6682
+ const validationResult = validatePromptResult({
6683
+ resultString: $ongoingTaskResult.$resultString || '',
6684
+ expectations: task.expectations,
6685
+ format: task.format,
6686
+ });
6687
+ if (!validationResult.isValid) {
6688
+ throw validationResult.error;
6689
+ }
6690
+ // Update the result string in case format processing modified it (e.g., JSON extraction)
6691
+ $ongoingTaskResult.$resultString = validationResult.processedResultString;
6692
+ }
6693
+ /**
6694
+ * Stores one failed attempt and reports the expectation error upstream.
6695
+ */
6696
+ function recordFailedAttempt(options) {
6697
+ const { error, attemptIndex, onProgress, $ongoingTaskResult } = options;
6698
+ $ongoingTaskResult.$expectError = error;
6699
+ $ongoingTaskResult.$failedResults.push({
6700
+ attemptIndex,
6701
+ result: $ongoingTaskResult.$resultString,
6702
+ error,
6703
+ });
6704
+ onProgress({
6705
+ errors: [error],
6706
+ });
6707
+ }
6708
+ /**
6709
+ * Appends the prompt execution report for prompt-task attempts.
6710
+ */
6711
+ function reportPromptExecution(options) {
6712
+ const { attempt, task, $executionReport, logLlmCall, $ongoingTaskResult } = options;
6713
+ if (attempt.isJokerAttempt || task.taskType !== 'PROMPT_TASK' || !$ongoingTaskResult.$prompt) {
6714
+ return;
6715
+ }
6716
+ // Note: [2] When some expected parameter is not defined, error will occur in templateParameters
6717
+ // In that case we don’t want to make a report about it because it’s not a llm execution error
6718
+ const executionPromptReport = {
6719
+ prompt: {
6720
+ ...$ongoingTaskResult.$prompt,
6721
+ // <- TODO: [🧠] How to pick everyhing except `pipelineUrl`
6722
+ },
6723
+ result: $ongoingTaskResult.$result || undefined,
6724
+ error: $ongoingTaskResult.$expectError === null ? undefined : serializeError($ongoingTaskResult.$expectError),
6725
+ };
6726
+ $executionReport.promptExecutions.push(executionPromptReport);
6727
+ if (logLlmCall) {
6728
+ logLlmCall({
6729
+ modelName: 'model' /* <- TODO: How to get model name from the report */,
6730
+ report: executionPromptReport,
6731
+ });
6732
+ }
6733
+ }
6734
+ /**
6735
+ * Throws the aggregated retry error after the last regular attempt fails expectations.
6736
+ */
6737
+ function throwIfFinalAttemptFailed(options) {
6738
+ const { attemptIndex, maxAttempts, maxExecutionAttempts, pipelineIdentification, $ongoingTaskResult } = options;
6739
+ if ($ongoingTaskResult.$expectError === null || attemptIndex !== maxAttempts - 1) {
6740
+ return;
6741
+ }
6742
+ throw new PipelineExecutionError(spacetrim.spaceTrim((block) => {
6743
+ var _a;
6744
+ return `
6745
+ LLM execution failed ${maxExecutionAttempts}x
6580
6746
 
6581
- ${block(pipelineIdentification)}
6747
+ ${block(pipelineIdentification)}
6582
6748
 
6583
- The Prompt:
6584
- ${block((((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || '')
6585
- .split(/\r?\n/)
6586
- .map((line) => `> ${line}`)
6587
- .join('\n'))}
6749
+ The Prompt:
6750
+ ${block(quoteMultilineText(((_a = $ongoingTaskResult.$prompt) === null || _a === void 0 ? void 0 : _a.content) || ''))}
6588
6751
 
6589
- All Failed Attempts:
6590
- ${block(failuresSummary)}
6591
- `;
6592
- }));
6593
- }
6594
- }
6752
+ All Failed Attempts:
6753
+ ${block(createFailuresSummary($ongoingTaskResult.$failedResults))}
6754
+ `;
6755
+ }));
6756
+ }
6757
+ /**
6758
+ * Renders the retry history into the aggregated final error body.
6759
+ */
6760
+ function createFailuresSummary($failedResults) {
6761
+ return $failedResults
6762
+ .map((failure) => spacetrim.spaceTrim((block) => {
6763
+ var _a, _b;
6764
+ return `
6765
+ Attempt ${failure.attemptIndex + 1}:
6766
+ Error ${((_a = failure.error) === null || _a === void 0 ? void 0 : _a.name) || ''}:
6767
+ ${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
6768
+
6769
+ Result:
6770
+ ${block(failure.result === null ? 'null' : quoteMultilineText(spacetrim.spaceTrim(failure.result)))}
6771
+ `;
6772
+ }))
6773
+ .join('\n\n---\n\n');
6774
+ }
6775
+ /**
6776
+ * Formats multiline text as a quoted markdown block.
6777
+ */
6778
+ function quoteMultilineText(text) {
6779
+ return text
6780
+ .split(/\r?\n/)
6781
+ .map((line) => `> ${line}`)
6782
+ .join('\n');
6783
+ }
6784
+ /**
6785
+ * Returns the successful result string or raises an unexpected internal-state error.
6786
+ */
6787
+ function getSuccessfulResultString(options) {
6788
+ const { pipelineIdentification, $ongoingTaskResult } = options;
6595
6789
  if ($ongoingTaskResult.$resultString === null) {
6596
6790
  throw new UnexpectedError(spacetrim.spaceTrim((block) => `
6597
6791
  Something went wrong and prompt result is null
@@ -6601,7 +6795,6 @@
6601
6795
  }
6602
6796
  return $ongoingTaskResult.$resultString;
6603
6797
  }
6604
- // TODO: Break into smaller functions
6605
6798
 
6606
6799
  /**
6607
6800
  * Executes a pipeline task that requires mapping or iterating over subvalues of a parameter (such as rows in a CSV).