@promptbook/wizard 0.112.0-71 → 0.112.0-72

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 (45) hide show
  1. package/esm/index.es.js +1085 -954
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/src/book-3.0/Book.d.ts +6 -0
  4. package/esm/src/book-components/Chat/utils/getToolCallChipletInfo.test.d.ts +1 -0
  5. package/esm/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +12 -2
  6. package/esm/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -0
  7. package/esm/src/cli/cli-commands/run/prepareRunCommandResources.d.ts +20 -0
  8. package/esm/src/cli/cli-commands/run/resolveRunInputParameters.d.ts +12 -0
  9. package/esm/src/cli/cli-commands/run/runCommandAction.d.ts +21 -0
  10. package/esm/src/cli/cli-commands/run/runPipelineExecution.d.ts +14 -0
  11. package/esm/src/cli/cli-commands/run.d.ts +1 -1
  12. package/esm/src/conversion/parsePipeline/applyPipelineHead.d.ts +8 -0
  13. package/esm/src/conversion/parsePipeline/createInitialPipelineJson.d.ts +8 -0
  14. package/esm/src/conversion/parsePipeline/createUniqueSectionNameResolver.d.ts +14 -0
  15. package/esm/src/conversion/parsePipeline/defineParameter.d.ts +8 -0
  16. package/esm/src/conversion/parsePipeline/extractPipelineDescription.d.ts +6 -0
  17. package/esm/src/conversion/parsePipeline/finalizeParsedPipeline.d.ts +8 -0
  18. package/esm/src/conversion/parsePipeline/getPipelineIdentification.d.ts +7 -0
  19. package/esm/src/conversion/parsePipeline/parsePreparedPipelineSections.d.ts +18 -0
  20. package/esm/src/conversion/parsePipeline/preparePipelineString.d.ts +8 -0
  21. package/esm/src/conversion/parsePipeline/processPipelineSection.d.ts +9 -0
  22. package/esm/src/version.d.ts +1 -1
  23. package/package.json +2 -2
  24. package/umd/index.umd.js +1085 -954
  25. package/umd/index.umd.js.map +1 -1
  26. package/umd/src/book-3.0/Book.d.ts +6 -0
  27. package/umd/src/book-components/Chat/utils/getToolCallChipletInfo.test.d.ts +1 -0
  28. package/umd/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +12 -2
  29. package/umd/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -0
  30. package/umd/src/cli/cli-commands/run/prepareRunCommandResources.d.ts +20 -0
  31. package/umd/src/cli/cli-commands/run/resolveRunInputParameters.d.ts +12 -0
  32. package/umd/src/cli/cli-commands/run/runCommandAction.d.ts +21 -0
  33. package/umd/src/cli/cli-commands/run/runPipelineExecution.d.ts +14 -0
  34. package/umd/src/cli/cli-commands/run.d.ts +1 -1
  35. package/umd/src/conversion/parsePipeline/applyPipelineHead.d.ts +8 -0
  36. package/umd/src/conversion/parsePipeline/createInitialPipelineJson.d.ts +8 -0
  37. package/umd/src/conversion/parsePipeline/createUniqueSectionNameResolver.d.ts +14 -0
  38. package/umd/src/conversion/parsePipeline/defineParameter.d.ts +8 -0
  39. package/umd/src/conversion/parsePipeline/extractPipelineDescription.d.ts +6 -0
  40. package/umd/src/conversion/parsePipeline/finalizeParsedPipeline.d.ts +8 -0
  41. package/umd/src/conversion/parsePipeline/getPipelineIdentification.d.ts +7 -0
  42. package/umd/src/conversion/parsePipeline/parsePreparedPipelineSections.d.ts +18 -0
  43. package/umd/src/conversion/parsePipeline/preparePipelineString.d.ts +8 -0
  44. package/umd/src/conversion/parsePipeline/processPipelineSection.d.ts +9 -0
  45. package/umd/src/version.d.ts +1 -1
package/esm/index.es.js CHANGED
@@ -38,7 +38,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
38
38
  * @generated
39
39
  * @see https://github.com/webgptorg/promptbook
40
40
  */
41
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-71';
41
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-72';
42
42
  /**
43
43
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
44
44
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -22859,7 +22859,9 @@ const octopus3dAvatarVisual = {
22859
22859
  };
22860
22860
  const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
22861
22861
  const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
22862
- const mantleRadiusZ = size * morphologyProfile.body.bodyRadiusRatio * (0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
22862
+ const mantleRadiusZ = size *
22863
+ morphologyProfile.body.bodyRadiusRatio *
22864
+ (0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
22863
22865
  const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
22864
22866
  const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
22865
22867
  const underbodyRadiusZ = mantleRadiusZ * 0.78;
@@ -22945,7 +22947,11 @@ const octopus3dAvatarVisual = {
22945
22947
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
22946
22948
  }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
22947
22949
  drawProjectedMouth(context, [
22948
- { x: -mouthHalfWidth, y: mouthY, z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY) },
22950
+ {
22951
+ x: -mouthHalfWidth,
22952
+ y: mouthY,
22953
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
22954
+ },
22949
22955
  {
22950
22956
  x: size * morphologyProfile.face.mouthCenterOffsetRatio,
22951
22957
  y: mouthY +
@@ -22954,7 +22960,11 @@ const octopus3dAvatarVisual = {
22954
22960
  interaction.gazeY * size * 0.01,
22955
22961
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
22956
22962
  },
22957
- { x: mouthHalfWidth, y: mouthY, z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY) },
22963
+ {
22964
+ x: mouthHalfWidth,
22965
+ y: mouthY,
22966
+ z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
22967
+ },
22958
22968
  ], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
22959
22969
  },
22960
22970
  };
@@ -23115,7 +23125,8 @@ function createOctopusTentacleStrokes(options) {
23115
23125
  z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
23116
23126
  };
23117
23127
  const controlPointTwo = {
23118
- x: anchorPoint.x + Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
23128
+ x: anchorPoint.x +
23129
+ Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
23119
23130
  y: anchorPoint.y + flowLength * 0.66,
23120
23131
  z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
23121
23132
  };
@@ -23180,8 +23191,7 @@ function drawTentacleStroke(context, tentacleStroke, palette) {
23180
23191
  context.beginPath();
23181
23192
  context.moveTo(startPoint.x, startPoint.y);
23182
23193
  context.lineTo(endPoint.x, endPoint.y);
23183
- context.strokeStyle =
23184
- tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
23194
+ context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
23185
23195
  context.lineWidth = width;
23186
23196
  context.lineCap = 'round';
23187
23197
  context.stroke();
@@ -31166,6 +31176,212 @@ const DEFAULT_LIST_TIMEOUTS_LIMIT = 20;
31166
31176
  * @private internal USE TIMEOUT constant
31167
31177
  */
31168
31178
  const MAX_LIST_TIMEOUTS_LIMIT = 100;
31179
+ /**
31180
+ * Creates one formatted timeout-argument validation error.
31181
+ *
31182
+ * @private internal utility of USE TIMEOUT
31183
+ */
31184
+ function createTimeoutToolArgsError(message) {
31185
+ return new PipelineExecutionError(spaceTrim$1(`
31186
+ ${message}
31187
+ `));
31188
+ }
31189
+ /**
31190
+ * Normalizes one optional timeout id string.
31191
+ *
31192
+ * @private internal utility of USE TIMEOUT
31193
+ */
31194
+ function normalizeOptionalTimeoutId(value) {
31195
+ return typeof value === 'string' ? value.trim() : '';
31196
+ }
31197
+ /**
31198
+ * Parses timeout target selection for tools that accept either `timeoutId` or `allActive: true`.
31199
+ *
31200
+ * @private internal utility of USE TIMEOUT
31201
+ */
31202
+ function parseTimeoutTargetSelection(args, options) {
31203
+ const timeoutId = normalizeOptionalTimeoutId(args.timeoutId);
31204
+ const allActive = args.allActive === true;
31205
+ if (timeoutId && allActive) {
31206
+ throw createTimeoutToolArgsError(options.bothMessage);
31207
+ }
31208
+ if (allActive) {
31209
+ return { allActive: true };
31210
+ }
31211
+ if (!timeoutId) {
31212
+ throw createTimeoutToolArgsError(options.missingMessage);
31213
+ }
31214
+ return {
31215
+ timeoutId,
31216
+ allActive: false,
31217
+ };
31218
+ }
31219
+ /**
31220
+ * Parses one explicit `dueAt` update value.
31221
+ *
31222
+ * @private internal utility of USE TIMEOUT
31223
+ */
31224
+ function parseOptionalTimeoutDueAt(value) {
31225
+ if (typeof value !== 'string' || value.trim().length === 0) {
31226
+ return undefined;
31227
+ }
31228
+ const normalizedDueAt = value.trim();
31229
+ const dueAtTimestamp = Date.parse(normalizedDueAt);
31230
+ if (!Number.isFinite(dueAtTimestamp)) {
31231
+ throw createTimeoutToolArgsError('Timeout `dueAt` must be one valid ISO timestamp.');
31232
+ }
31233
+ return new Date(dueAtTimestamp).toISOString();
31234
+ }
31235
+ /**
31236
+ * Parses one explicit `extendByMs` update value.
31237
+ *
31238
+ * @private internal utility of USE TIMEOUT
31239
+ */
31240
+ function parseOptionalTimeoutExtendByMs(value) {
31241
+ if (typeof value !== 'number') {
31242
+ return undefined;
31243
+ }
31244
+ if (!Number.isFinite(value) || value <= 0) {
31245
+ throw createTimeoutToolArgsError('Timeout `extendByMs` must be a positive number of milliseconds.');
31246
+ }
31247
+ return Math.floor(value);
31248
+ }
31249
+ /**
31250
+ * Parses one explicit `recurrenceIntervalMs` update value.
31251
+ *
31252
+ * @private internal utility of USE TIMEOUT
31253
+ */
31254
+ function parseOptionalTimeoutRecurrenceInterval(value) {
31255
+ if (value === null) {
31256
+ return null;
31257
+ }
31258
+ if (typeof value !== 'number') {
31259
+ return undefined;
31260
+ }
31261
+ if (!Number.isFinite(value) || value <= 0) {
31262
+ throw createTimeoutToolArgsError('Timeout `recurrenceIntervalMs` must be a positive number of milliseconds or `null`.');
31263
+ }
31264
+ return Math.floor(value);
31265
+ }
31266
+ /**
31267
+ * Parses one explicit `message` update value.
31268
+ *
31269
+ * @private internal utility of USE TIMEOUT
31270
+ */
31271
+ function parseOptionalTimeoutMessage(value) {
31272
+ if (value === null) {
31273
+ return null;
31274
+ }
31275
+ if (typeof value !== 'string') {
31276
+ return undefined;
31277
+ }
31278
+ const normalizedMessage = value.trim();
31279
+ return normalizedMessage.length > 0 ? normalizedMessage : null;
31280
+ }
31281
+ /**
31282
+ * Parses one explicit `parameters` update value.
31283
+ *
31284
+ * @private internal utility of USE TIMEOUT
31285
+ */
31286
+ function parseOptionalTimeoutParameters(value) {
31287
+ if (value === undefined) {
31288
+ return undefined;
31289
+ }
31290
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
31291
+ throw createTimeoutToolArgsError('Timeout `parameters` must be one JSON object.');
31292
+ }
31293
+ return value;
31294
+ }
31295
+ /**
31296
+ * Parses one explicit `paused` update value.
31297
+ *
31298
+ * @private internal utility of USE TIMEOUT
31299
+ */
31300
+ function parseOptionalTimeoutPaused(value) {
31301
+ return typeof value === 'boolean' ? value : undefined;
31302
+ }
31303
+ /**
31304
+ * Parses patch fields for `update_timeout`.
31305
+ *
31306
+ * @private internal utility of USE TIMEOUT
31307
+ */
31308
+ function parseTimeoutUpdatePatch(args) {
31309
+ const patch = {};
31310
+ const dueAt = parseOptionalTimeoutDueAt(args.dueAt);
31311
+ const extendByMs = parseOptionalTimeoutExtendByMs(args.extendByMs);
31312
+ const recurrenceIntervalMs = parseOptionalTimeoutRecurrenceInterval(args.recurrenceIntervalMs);
31313
+ const message = parseOptionalTimeoutMessage(args.message);
31314
+ const parameters = parseOptionalTimeoutParameters(args.parameters);
31315
+ const paused = parseOptionalTimeoutPaused(args.paused);
31316
+ if (dueAt !== undefined) {
31317
+ patch.dueAt = dueAt;
31318
+ }
31319
+ if (extendByMs !== undefined) {
31320
+ patch.extendByMs = extendByMs;
31321
+ }
31322
+ if (patch.dueAt !== undefined && patch.extendByMs !== undefined) {
31323
+ throw createTimeoutToolArgsError('Timeout update cannot include both `dueAt` and `extendByMs`.');
31324
+ }
31325
+ if (recurrenceIntervalMs !== undefined) {
31326
+ patch.recurrenceIntervalMs = recurrenceIntervalMs;
31327
+ }
31328
+ if (message !== undefined) {
31329
+ patch.message = message;
31330
+ }
31331
+ if (parameters !== undefined) {
31332
+ patch.parameters = parameters;
31333
+ }
31334
+ if (paused !== undefined) {
31335
+ patch.paused = paused;
31336
+ }
31337
+ return patch;
31338
+ }
31339
+ /**
31340
+ * Determines whether the patch contains fields that are only supported for single-timeout updates.
31341
+ *
31342
+ * @private internal utility of USE TIMEOUT
31343
+ */
31344
+ function hasSingleTimeoutOnlyPatchFields(patch) {
31345
+ return (patch.dueAt !== undefined ||
31346
+ patch.extendByMs !== undefined ||
31347
+ patch.recurrenceIntervalMs !== undefined ||
31348
+ patch.message !== undefined ||
31349
+ patch.parameters !== undefined);
31350
+ }
31351
+ /**
31352
+ * Parses bulk timeout update arguments.
31353
+ *
31354
+ * @private internal utility of USE TIMEOUT
31355
+ */
31356
+ function parseBulkTimeoutUpdateArgs(patch) {
31357
+ if (patch.paused === undefined) {
31358
+ throw createTimeoutToolArgsError('Bulk timeout update with `allActive: true` requires `paused` to be explicitly set.');
31359
+ }
31360
+ if (hasSingleTimeoutOnlyPatchFields(patch)) {
31361
+ throw createTimeoutToolArgsError('Bulk timeout update only supports the `paused` field.');
31362
+ }
31363
+ return {
31364
+ allActive: true,
31365
+ paused: patch.paused,
31366
+ };
31367
+ }
31368
+ /**
31369
+ * Parses single-timeout update arguments.
31370
+ *
31371
+ * @private internal utility of USE TIMEOUT
31372
+ */
31373
+ function parseSingleTimeoutUpdateArgs(timeoutId, patch) {
31374
+ if (!timeoutId) {
31375
+ throw createTimeoutToolArgsError('Timeout `timeoutId` is required for single-timeout updates.');
31376
+ }
31377
+ if (Object.keys(patch).length === 0) {
31378
+ throw createTimeoutToolArgsError('Timeout update must include at least one editable field.');
31379
+ }
31380
+ return {
31381
+ timeoutId,
31382
+ patch,
31383
+ };
31384
+ }
31169
31385
  /**
31170
31386
  * Parses and validates `USE TIMEOUT` tool arguments.
31171
31387
  *
@@ -31192,22 +31408,14 @@ const parseTimeoutToolArgs = {
31192
31408
  * Parses `cancel_timeout` input.
31193
31409
  */
31194
31410
  cancel(args) {
31195
- const timeoutId = typeof args.timeoutId === 'string' ? args.timeoutId.trim() : '';
31196
- const allActive = args.allActive === true;
31197
- if (timeoutId && allActive) {
31198
- throw new PipelineExecutionError(spaceTrim$1(`
31199
- Timeout cancellation must target either one \`timeoutId\` or \`allActive: true\`, not both.
31200
- `));
31201
- }
31202
- if (allActive) {
31411
+ const target = parseTimeoutTargetSelection(args, {
31412
+ bothMessage: 'Timeout cancellation must target either one `timeoutId` or `allActive: true`, not both.',
31413
+ missingMessage: 'Timeout `timeoutId` is required unless you pass `allActive: true`.',
31414
+ });
31415
+ if (target.allActive) {
31203
31416
  return { allActive: true };
31204
31417
  }
31205
- if (!timeoutId) {
31206
- throw new PipelineExecutionError(spaceTrim$1(`
31207
- Timeout \`timeoutId\` is required unless you pass \`allActive: true\`.
31208
- `));
31209
- }
31210
- return { timeoutId };
31418
+ return { timeoutId: target.timeoutId };
31211
31419
  },
31212
31420
  /**
31213
31421
  * Parses `list_timeouts` input.
@@ -31238,106 +31446,14 @@ const parseTimeoutToolArgs = {
31238
31446
  * Parses `update_timeout` input.
31239
31447
  */
31240
31448
  update(args) {
31241
- const timeoutId = typeof args.timeoutId === 'string' ? args.timeoutId.trim() : '';
31242
- const allActive = args.allActive === true;
31243
- if (timeoutId && allActive) {
31244
- throw new PipelineExecutionError(spaceTrim$1(`
31245
- Timeout update must target either one \`timeoutId\` or \`allActive: true\`, not both.
31246
- `));
31247
- }
31248
- if (!timeoutId && !allActive) {
31249
- throw new PipelineExecutionError(spaceTrim$1(`
31250
- Timeout update requires one \`timeoutId\` or \`allActive: true\`.
31251
- `));
31252
- }
31253
- const patch = {};
31254
- if (typeof args.dueAt === 'string' && args.dueAt.trim().length > 0) {
31255
- const normalizedDueAt = args.dueAt.trim();
31256
- const dueAtTimestamp = Date.parse(normalizedDueAt);
31257
- if (!Number.isFinite(dueAtTimestamp)) {
31258
- throw new PipelineExecutionError(spaceTrim$1(`
31259
- Timeout \`dueAt\` must be one valid ISO timestamp.
31260
- `));
31261
- }
31262
- patch.dueAt = new Date(dueAtTimestamp).toISOString();
31263
- }
31264
- if (typeof args.extendByMs === 'number') {
31265
- if (!Number.isFinite(args.extendByMs) || args.extendByMs <= 0) {
31266
- throw new PipelineExecutionError(spaceTrim$1(`
31267
- Timeout \`extendByMs\` must be a positive number of milliseconds.
31268
- `));
31269
- }
31270
- patch.extendByMs = Math.floor(args.extendByMs);
31271
- }
31272
- if (patch.dueAt !== undefined && patch.extendByMs !== undefined) {
31273
- throw new PipelineExecutionError(spaceTrim$1(`
31274
- Timeout update cannot include both \`dueAt\` and \`extendByMs\`.
31275
- `));
31276
- }
31277
- if (args.recurrenceIntervalMs === null) {
31278
- patch.recurrenceIntervalMs = null;
31279
- }
31280
- else if (typeof args.recurrenceIntervalMs === 'number') {
31281
- if (!Number.isFinite(args.recurrenceIntervalMs) || args.recurrenceIntervalMs <= 0) {
31282
- throw new PipelineExecutionError(spaceTrim$1(`
31283
- Timeout \`recurrenceIntervalMs\` must be a positive number of milliseconds or \`null\`.
31284
- `));
31285
- }
31286
- patch.recurrenceIntervalMs = Math.floor(args.recurrenceIntervalMs);
31287
- }
31288
- if (args.message === null) {
31289
- patch.message = null;
31290
- }
31291
- else if (typeof args.message === 'string') {
31292
- const normalizedMessage = args.message.trim();
31293
- patch.message = normalizedMessage.length > 0 ? normalizedMessage : null;
31294
- }
31295
- if (args.parameters !== undefined) {
31296
- if (!args.parameters || typeof args.parameters !== 'object' || Array.isArray(args.parameters)) {
31297
- throw new PipelineExecutionError(spaceTrim$1(`
31298
- Timeout \`parameters\` must be one JSON object.
31299
- `));
31300
- }
31301
- patch.parameters = args.parameters;
31302
- }
31303
- if (typeof args.paused === 'boolean') {
31304
- patch.paused = args.paused;
31305
- }
31306
- if (allActive) {
31307
- if (patch.paused === undefined) {
31308
- throw new PipelineExecutionError(spaceTrim$1(`
31309
- Bulk timeout update with \`allActive: true\` requires \`paused\` to be explicitly set.
31310
- `));
31311
- }
31312
- const hasSingleOnlyPatch = patch.dueAt !== undefined ||
31313
- patch.extendByMs !== undefined ||
31314
- patch.recurrenceIntervalMs !== undefined ||
31315
- patch.message !== undefined ||
31316
- patch.parameters !== undefined;
31317
- if (hasSingleOnlyPatch) {
31318
- throw new PipelineExecutionError(spaceTrim$1(`
31319
- Bulk timeout update only supports the \`paused\` field.
31320
- `));
31321
- }
31322
- return {
31323
- allActive: true,
31324
- paused: patch.paused,
31325
- };
31326
- }
31327
- if (!timeoutId) {
31328
- throw new PipelineExecutionError(spaceTrim$1(`
31329
- Timeout \`timeoutId\` is required for single-timeout updates.
31330
- `));
31331
- }
31332
- if (Object.keys(patch).length === 0) {
31333
- throw new PipelineExecutionError(spaceTrim$1(`
31334
- Timeout update must include at least one editable field.
31335
- `));
31336
- }
31337
- return {
31338
- timeoutId,
31339
- patch,
31340
- };
31449
+ const target = parseTimeoutTargetSelection(args, {
31450
+ bothMessage: 'Timeout update must target either one `timeoutId` or `allActive: true`, not both.',
31451
+ missingMessage: 'Timeout update requires one `timeoutId` or `allActive: true`.',
31452
+ });
31453
+ const patch = parseTimeoutUpdatePatch(args);
31454
+ return target.allActive
31455
+ ? parseBulkTimeoutUpdateArgs(patch)
31456
+ : parseSingleTimeoutUpdateArgs(target.timeoutId, patch);
31341
31457
  },
31342
31458
  };
31343
31459
 
@@ -41443,326 +41559,6 @@ async function loadArchive(filePath, fs) {
41443
41559
  }
41444
41560
  // Note: [🟢] Code for Node archive helper [loadArchive](src/conversion/archive/loadArchive.ts) should never be published into packages that could be imported into browser environment
41445
41561
 
41446
- /**
41447
- * All available task types
41448
- *
41449
- * There is is distinction between task types and section types
41450
- * - Every section in markdown has its SectionType
41451
- * - Some sections are tasks but other can be non-task sections
41452
- *
41453
- * @public exported from `@promptbook/core`
41454
- */
41455
- const TaskTypes = [
41456
- 'PROMPT',
41457
- 'SIMPLE',
41458
- 'SCRIPT',
41459
- 'DIALOG',
41460
- // <- [🅱]
41461
- ];
41462
-
41463
- /**
41464
- * All available sections which are not tasks
41465
- *
41466
- * @public exported from `@promptbook/core`
41467
- */
41468
- const NonTaskSectionTypes = ['EXAMPLE', 'KNOWLEDGE', 'INSTRUMENT', 'ACTION'];
41469
- /**
41470
- * All available section types
41471
- *
41472
- * There is is distinction between task types and section types
41473
- * - Every section in markdown has its SectionType
41474
- * - Some sections are tasks but other can be non-task sections
41475
- *
41476
- * @public exported from `@promptbook/core`
41477
- */
41478
- const SectionTypes = [
41479
- ...TaskTypes.map((TaskType) => `${TaskType}_TASK`),
41480
- ...NonTaskSectionTypes,
41481
- ];
41482
-
41483
- /**
41484
- * Parses the knowledge command
41485
- *
41486
- * @see `documentationUrl` for more details
41487
- *
41488
- * @public exported from `@promptbook/editable`
41489
- */
41490
- const knowledgeCommandParser = {
41491
- /**
41492
- * Name of the command
41493
- */
41494
- name: 'KNOWLEDGE',
41495
- /**
41496
- * BOILERPLATE command can be used in:
41497
- */
41498
- isUsedInPipelineHead: true,
41499
- isUsedInPipelineTask: false,
41500
- /**
41501
- * Description of the KNOWLEDGE command
41502
- */
41503
- description: `Tells promptbook which external knowledge to use`,
41504
- /**
41505
- * Link to documentation
41506
- */
41507
- documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/41',
41508
- /**
41509
- * Example usages of the KNOWLEDGE command
41510
- */
41511
- examples: [
41512
- 'KNOWLEDGE https://www.pavolhejny.com/',
41513
- 'KNOWLEDGE ./hejny-cv.txt',
41514
- 'KNOWLEDGE ./hejny-cv.md',
41515
- 'KNOWLEDGE ./hejny-cv.pdf',
41516
- 'KNOWLEDGE ./hejny-cv.docx',
41517
- // <- TODO: [😿] Allow ONLY files scoped in the (sub)directory NOT ../ and test it
41518
- ],
41519
- /**
41520
- * Parses the KNOWLEDGE command
41521
- */
41522
- parse(input) {
41523
- const { args } = input;
41524
- const knowledgeSourceContent = spaceTrim$1(args[0] || '');
41525
- if (knowledgeSourceContent === '') {
41526
- throw new ParseError(`Source is not defined`);
41527
- }
41528
- // TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
41529
- if (knowledgeSourceContent.startsWith('http://')) {
41530
- throw new ParseError(`Source is not secure`);
41531
- }
41532
- if (!(isValidFilePath(knowledgeSourceContent) || isValidUrl(knowledgeSourceContent))) {
41533
- throw new ParseError(`Source not valid`);
41534
- }
41535
- if (knowledgeSourceContent.startsWith('../') ||
41536
- knowledgeSourceContent.startsWith('/') ||
41537
- /^[A-Z]:[\\/]+/i.test(knowledgeSourceContent)) {
41538
- throw new ParseError(`Source cannot be outside of the .book.md folder`);
41539
- }
41540
- return {
41541
- type: 'KNOWLEDGE',
41542
- knowledgeSourceContent,
41543
- };
41544
- },
41545
- /**
41546
- * Apply the KNOWLEDGE command to the `pipelineJson`
41547
- *
41548
- * Note: `$` is used to indicate that this function mutates given `pipelineJson`
41549
- */
41550
- $applyToPipelineJson(command, $pipelineJson) {
41551
- const { knowledgeSourceContent } = command;
41552
- $pipelineJson.knowledgeSources.push({
41553
- name: knowledgeSourceContentToName(knowledgeSourceContent),
41554
- knowledgeSourceContent,
41555
- });
41556
- },
41557
- /**
41558
- * Converts the KNOWLEDGE command back to string
41559
- *
41560
- * Note: This is used in `pipelineJsonToString` utility
41561
- */
41562
- stringify(command) {
41563
- return `---`; // <- TODO: [🛋] Implement
41564
- },
41565
- /**
41566
- * Reads the KNOWLEDGE command from the `PipelineJson`
41567
- *
41568
- * Note: This is used in `pipelineJsonToString` utility
41569
- */
41570
- takeFromPipelineJson(pipelineJson) {
41571
- throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
41572
- },
41573
- };
41574
- // Note: [⛱] There are two types of KNOWLEDGE commands *...(read more in [⛱])*
41575
-
41576
- /**
41577
- * Parses the section command
41578
- *
41579
- * @see `documentationUrl` for more details
41580
- *
41581
- * @public exported from `@promptbook/editable`
41582
- */
41583
- const sectionCommandParser = {
41584
- /**
41585
- * Name of the command
41586
- */
41587
- name: 'SECTION',
41588
- /**
41589
- * Aliases for the SECTION command
41590
- */
41591
- aliasNames: [
41592
- 'PROMPT',
41593
- 'SIMPLE',
41594
- 'SCRIPT',
41595
- 'DIALOG',
41596
- 'SAMPLE',
41597
- 'EXAMPLE',
41598
- 'KNOWLEDGE',
41599
- 'INSTRUMENT',
41600
- 'ACTION', // <- Note: [⛱]
41601
- ],
41602
- /**
41603
- * Aliases for the SECTION command
41604
- */
41605
- deprecatedNames: ['TEMPLATE', 'BLOCK', 'EXECUTE'],
41606
- /**
41607
- * BOILERPLATE command can be used in:
41608
- */
41609
- isUsedInPipelineHead: false,
41610
- isUsedInPipelineTask: true,
41611
- /**
41612
- * Description of the SECTION command
41613
- */
41614
- description: `Defines the purpose of the markdown section - if its a task and which type or something else`,
41615
- /**
41616
- * Link to documentation
41617
- */
41618
- documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/64',
41619
- /**
41620
- * Example usages of the SECTION command
41621
- */
41622
- examples: [
41623
- // Short form:
41624
- 'PROMPT',
41625
- 'SIMPLE',
41626
- 'SCRIPT',
41627
- 'DIALOG',
41628
- // <- [🅱]
41629
- 'EXAMPLE',
41630
- 'KNOWLEDGE',
41631
- 'INSTRUMENT',
41632
- 'ACTION',
41633
- // -----------------
41634
- // Recommended (reversed) form:
41635
- 'PROMPT SECTION',
41636
- 'SIMPLE SECTION',
41637
- 'SCRIPT SECTION',
41638
- 'DIALOG SECTION',
41639
- // <- [🅱]
41640
- 'EXAMPLE SECTION',
41641
- 'KNOWLEDGE SECTION',
41642
- 'INSTRUMENT SECTION',
41643
- 'ACTION SECTION',
41644
- // -----------------
41645
- // Standard form:
41646
- 'SECTION PROMPT',
41647
- 'SECTION SIMPLE',
41648
- 'SECTION SCRIPT',
41649
- 'SECTION DIALOG',
41650
- // <- [🅱]
41651
- 'SECTION EXAMPLE',
41652
- 'SECTION KNOWLEDGE',
41653
- 'SECTION INSTRUMENT',
41654
- 'SECTION ACTION',
41655
- ],
41656
- // TODO: [♓️] order: -10 /* <- Note: Putting before other commands */
41657
- /**
41658
- * Parses the SECTION command
41659
- */
41660
- parse(input) {
41661
- let { normalized } = input;
41662
- normalized = normalized.split('SAMPLE').join('EXAMPLE');
41663
- normalized = normalized.split('EXECUTE_').join('');
41664
- normalized = normalized.split('DIALOGUE').join('DIALOG');
41665
- const taskTypes = SectionTypes.filter((sectionType) => normalized.includes(sectionType.split('_TASK').join('')));
41666
- if (taskTypes.length !== 1) {
41667
- throw new ParseError(spaceTrim$1((block) => `
41668
- Unknown section type "${normalized}"
41669
-
41670
- Supported section types are:
41671
- ${block(SectionTypes.join(', '))}
41672
- `));
41673
- }
41674
- const taskType = taskTypes[0];
41675
- return {
41676
- type: 'SECTION',
41677
- taskType,
41678
- };
41679
- },
41680
- /**
41681
- * Apply the SECTION command to the `pipelineJson`
41682
- *
41683
- * Note: `$` is used to indicate that this function mutates given `taskJson`
41684
- */
41685
- $applyToTaskJson(command, $taskJson, $pipelineJson) {
41686
- if ($taskJson.isSectionTypeSet === true) {
41687
- throw new ParseError(spaceTrim$1(`
41688
- Section type is already defined in the section.
41689
- It can be defined only once.
41690
- `));
41691
- }
41692
- $taskJson.isSectionTypeSet = true;
41693
- // TODO: [🍧][💩] Rearrange better - but at bottom and unwrap from function
41694
- const expectResultingParameterName = () => {
41695
- if ($taskJson.resultingParameterName) {
41696
- return;
41697
- }
41698
- throw new ParseError(`Task section and example section must end with return statement -> {parameterName}`);
41699
- };
41700
- if ($taskJson.content === undefined) {
41701
- throw new UnexpectedError(`Content is missing in the taskJson - probably commands are applied in wrong order`);
41702
- }
41703
- if (command.taskType === 'EXAMPLE') {
41704
- expectResultingParameterName();
41705
- const parameter = $pipelineJson.parameters.find((param) => param.name === $taskJson.resultingParameterName);
41706
- if (parameter === undefined) {
41707
- // TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
41708
- throw new ParseError(`Parameter \`{${$taskJson.resultingParameterName}}\` is not defined so can not define example value of it`);
41709
- }
41710
- parameter.exampleValues = parameter.exampleValues || [];
41711
- parameter.exampleValues.push($taskJson.content);
41712
- $taskJson.isTask = false;
41713
- return;
41714
- }
41715
- if (command.taskType === 'KNOWLEDGE') {
41716
- knowledgeCommandParser.$applyToPipelineJson({
41717
- type: 'KNOWLEDGE',
41718
- knowledgeSourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
41719
- }, $pipelineJson);
41720
- $taskJson.isTask = false;
41721
- return;
41722
- }
41723
- if (command.taskType === 'ACTION') {
41724
- console.error(new NotYetImplementedError('Actions are not implemented yet'));
41725
- $taskJson.isTask = false;
41726
- return;
41727
- }
41728
- if (command.taskType === 'INSTRUMENT') {
41729
- console.error(new NotYetImplementedError('Instruments are not implemented yet'));
41730
- $taskJson.isTask = false;
41731
- return;
41732
- }
41733
- expectResultingParameterName();
41734
- $taskJson.taskType = command.taskType;
41735
- $taskJson.isTask = true;
41736
- },
41737
- /**
41738
- * Converts the SECTION command back to string
41739
- *
41740
- * Note: This is used in `pipelineJsonToString` utility
41741
- */
41742
- stringify(command) {
41743
- return `---`; // <- TODO: [🛋] Implement
41744
- },
41745
- /**
41746
- * Reads the SECTION command from the `TaskJson`
41747
- *
41748
- * Note: This is used in `pipelineJsonToString` utility
41749
- */
41750
- takeFromTaskJson($taskJson) {
41751
- throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
41752
- },
41753
- };
41754
- /**
41755
- * Note: [⛱] There are two types of KNOWLEDGE, ACTION and INSTRUMENT commands:
41756
- * 1) There are commands `KNOWLEDGE`, `ACTION` and `INSTRUMENT` used in the pipeline head, they just define the knowledge, action or instrument as single line after the command
41757
- * - KNOWLEDGE Look at https://en.wikipedia.org/wiki/Artificial_intelligence
41758
- * 2) `KNOWLEDGE SECTION` which has short form `KNOWLEDGE` is used in the sectiom, does not refer the line itself, but the content of the section block
41759
- * - KNOWLEDGE SECTION
41760
- *
41761
- * ```
41762
- * Look at https://en.wikipedia.org/wiki/Artificial_intelligence
41763
- * ```
41764
- */
41765
-
41766
41562
  /**
41767
41563
  * Parses the boilerplate command
41768
41564
  *
@@ -42844,6 +42640,99 @@ const jokerCommandParser = {
42844
42640
  },
42845
42641
  };
42846
42642
 
42643
+ /**
42644
+ * Parses the knowledge command
42645
+ *
42646
+ * @see `documentationUrl` for more details
42647
+ *
42648
+ * @public exported from `@promptbook/editable`
42649
+ */
42650
+ const knowledgeCommandParser = {
42651
+ /**
42652
+ * Name of the command
42653
+ */
42654
+ name: 'KNOWLEDGE',
42655
+ /**
42656
+ * BOILERPLATE command can be used in:
42657
+ */
42658
+ isUsedInPipelineHead: true,
42659
+ isUsedInPipelineTask: false,
42660
+ /**
42661
+ * Description of the KNOWLEDGE command
42662
+ */
42663
+ description: `Tells promptbook which external knowledge to use`,
42664
+ /**
42665
+ * Link to documentation
42666
+ */
42667
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/41',
42668
+ /**
42669
+ * Example usages of the KNOWLEDGE command
42670
+ */
42671
+ examples: [
42672
+ 'KNOWLEDGE https://www.pavolhejny.com/',
42673
+ 'KNOWLEDGE ./hejny-cv.txt',
42674
+ 'KNOWLEDGE ./hejny-cv.md',
42675
+ 'KNOWLEDGE ./hejny-cv.pdf',
42676
+ 'KNOWLEDGE ./hejny-cv.docx',
42677
+ // <- TODO: [😿] Allow ONLY files scoped in the (sub)directory NOT ../ and test it
42678
+ ],
42679
+ /**
42680
+ * Parses the KNOWLEDGE command
42681
+ */
42682
+ parse(input) {
42683
+ const { args } = input;
42684
+ const knowledgeSourceContent = spaceTrim$1(args[0] || '');
42685
+ if (knowledgeSourceContent === '') {
42686
+ throw new ParseError(`Source is not defined`);
42687
+ }
42688
+ // TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
42689
+ if (knowledgeSourceContent.startsWith('http://')) {
42690
+ throw new ParseError(`Source is not secure`);
42691
+ }
42692
+ if (!(isValidFilePath(knowledgeSourceContent) || isValidUrl(knowledgeSourceContent))) {
42693
+ throw new ParseError(`Source not valid`);
42694
+ }
42695
+ if (knowledgeSourceContent.startsWith('../') ||
42696
+ knowledgeSourceContent.startsWith('/') ||
42697
+ /^[A-Z]:[\\/]+/i.test(knowledgeSourceContent)) {
42698
+ throw new ParseError(`Source cannot be outside of the .book.md folder`);
42699
+ }
42700
+ return {
42701
+ type: 'KNOWLEDGE',
42702
+ knowledgeSourceContent,
42703
+ };
42704
+ },
42705
+ /**
42706
+ * Apply the KNOWLEDGE command to the `pipelineJson`
42707
+ *
42708
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
42709
+ */
42710
+ $applyToPipelineJson(command, $pipelineJson) {
42711
+ const { knowledgeSourceContent } = command;
42712
+ $pipelineJson.knowledgeSources.push({
42713
+ name: knowledgeSourceContentToName(knowledgeSourceContent),
42714
+ knowledgeSourceContent,
42715
+ });
42716
+ },
42717
+ /**
42718
+ * Converts the KNOWLEDGE command back to string
42719
+ *
42720
+ * Note: This is used in `pipelineJsonToString` utility
42721
+ */
42722
+ stringify(command) {
42723
+ return `---`; // <- TODO: [🛋] Implement
42724
+ },
42725
+ /**
42726
+ * Reads the KNOWLEDGE command from the `PipelineJson`
42727
+ *
42728
+ * Note: This is used in `pipelineJsonToString` utility
42729
+ */
42730
+ takeFromPipelineJson(pipelineJson) {
42731
+ throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
42732
+ },
42733
+ };
42734
+ // Note: [⛱] There are two types of KNOWLEDGE commands *...(read more in [⛱])*
42735
+
42847
42736
  /**
42848
42737
  * Constant for model variants.
42849
42738
  *
@@ -43362,6 +43251,233 @@ const postprocessCommandParser = {
43362
43251
  },
43363
43252
  };
43364
43253
 
43254
+ /**
43255
+ * All available task types
43256
+ *
43257
+ * There is is distinction between task types and section types
43258
+ * - Every section in markdown has its SectionType
43259
+ * - Some sections are tasks but other can be non-task sections
43260
+ *
43261
+ * @public exported from `@promptbook/core`
43262
+ */
43263
+ const TaskTypes = [
43264
+ 'PROMPT',
43265
+ 'SIMPLE',
43266
+ 'SCRIPT',
43267
+ 'DIALOG',
43268
+ // <- [🅱]
43269
+ ];
43270
+
43271
+ /**
43272
+ * All available sections which are not tasks
43273
+ *
43274
+ * @public exported from `@promptbook/core`
43275
+ */
43276
+ const NonTaskSectionTypes = ['EXAMPLE', 'KNOWLEDGE', 'INSTRUMENT', 'ACTION'];
43277
+ /**
43278
+ * All available section types
43279
+ *
43280
+ * There is is distinction between task types and section types
43281
+ * - Every section in markdown has its SectionType
43282
+ * - Some sections are tasks but other can be non-task sections
43283
+ *
43284
+ * @public exported from `@promptbook/core`
43285
+ */
43286
+ const SectionTypes = [
43287
+ ...TaskTypes.map((TaskType) => `${TaskType}_TASK`),
43288
+ ...NonTaskSectionTypes,
43289
+ ];
43290
+
43291
+ /**
43292
+ * Parses the section command
43293
+ *
43294
+ * @see `documentationUrl` for more details
43295
+ *
43296
+ * @public exported from `@promptbook/editable`
43297
+ */
43298
+ const sectionCommandParser = {
43299
+ /**
43300
+ * Name of the command
43301
+ */
43302
+ name: 'SECTION',
43303
+ /**
43304
+ * Aliases for the SECTION command
43305
+ */
43306
+ aliasNames: [
43307
+ 'PROMPT',
43308
+ 'SIMPLE',
43309
+ 'SCRIPT',
43310
+ 'DIALOG',
43311
+ 'SAMPLE',
43312
+ 'EXAMPLE',
43313
+ 'KNOWLEDGE',
43314
+ 'INSTRUMENT',
43315
+ 'ACTION', // <- Note: [⛱]
43316
+ ],
43317
+ /**
43318
+ * Aliases for the SECTION command
43319
+ */
43320
+ deprecatedNames: ['TEMPLATE', 'BLOCK', 'EXECUTE'],
43321
+ /**
43322
+ * BOILERPLATE command can be used in:
43323
+ */
43324
+ isUsedInPipelineHead: false,
43325
+ isUsedInPipelineTask: true,
43326
+ /**
43327
+ * Description of the SECTION command
43328
+ */
43329
+ description: `Defines the purpose of the markdown section - if its a task and which type or something else`,
43330
+ /**
43331
+ * Link to documentation
43332
+ */
43333
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/64',
43334
+ /**
43335
+ * Example usages of the SECTION command
43336
+ */
43337
+ examples: [
43338
+ // Short form:
43339
+ 'PROMPT',
43340
+ 'SIMPLE',
43341
+ 'SCRIPT',
43342
+ 'DIALOG',
43343
+ // <- [🅱]
43344
+ 'EXAMPLE',
43345
+ 'KNOWLEDGE',
43346
+ 'INSTRUMENT',
43347
+ 'ACTION',
43348
+ // -----------------
43349
+ // Recommended (reversed) form:
43350
+ 'PROMPT SECTION',
43351
+ 'SIMPLE SECTION',
43352
+ 'SCRIPT SECTION',
43353
+ 'DIALOG SECTION',
43354
+ // <- [🅱]
43355
+ 'EXAMPLE SECTION',
43356
+ 'KNOWLEDGE SECTION',
43357
+ 'INSTRUMENT SECTION',
43358
+ 'ACTION SECTION',
43359
+ // -----------------
43360
+ // Standard form:
43361
+ 'SECTION PROMPT',
43362
+ 'SECTION SIMPLE',
43363
+ 'SECTION SCRIPT',
43364
+ 'SECTION DIALOG',
43365
+ // <- [🅱]
43366
+ 'SECTION EXAMPLE',
43367
+ 'SECTION KNOWLEDGE',
43368
+ 'SECTION INSTRUMENT',
43369
+ 'SECTION ACTION',
43370
+ ],
43371
+ // TODO: [♓️] order: -10 /* <- Note: Putting before other commands */
43372
+ /**
43373
+ * Parses the SECTION command
43374
+ */
43375
+ parse(input) {
43376
+ let { normalized } = input;
43377
+ normalized = normalized.split('SAMPLE').join('EXAMPLE');
43378
+ normalized = normalized.split('EXECUTE_').join('');
43379
+ normalized = normalized.split('DIALOGUE').join('DIALOG');
43380
+ const taskTypes = SectionTypes.filter((sectionType) => normalized.includes(sectionType.split('_TASK').join('')));
43381
+ if (taskTypes.length !== 1) {
43382
+ throw new ParseError(spaceTrim$1((block) => `
43383
+ Unknown section type "${normalized}"
43384
+
43385
+ Supported section types are:
43386
+ ${block(SectionTypes.join(', '))}
43387
+ `));
43388
+ }
43389
+ const taskType = taskTypes[0];
43390
+ return {
43391
+ type: 'SECTION',
43392
+ taskType,
43393
+ };
43394
+ },
43395
+ /**
43396
+ * Apply the SECTION command to the `pipelineJson`
43397
+ *
43398
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
43399
+ */
43400
+ $applyToTaskJson(command, $taskJson, $pipelineJson) {
43401
+ if ($taskJson.isSectionTypeSet === true) {
43402
+ throw new ParseError(spaceTrim$1(`
43403
+ Section type is already defined in the section.
43404
+ It can be defined only once.
43405
+ `));
43406
+ }
43407
+ $taskJson.isSectionTypeSet = true;
43408
+ // TODO: [🍧][💩] Rearrange better - but at bottom and unwrap from function
43409
+ const expectResultingParameterName = () => {
43410
+ if ($taskJson.resultingParameterName) {
43411
+ return;
43412
+ }
43413
+ throw new ParseError(`Task section and example section must end with return statement -> {parameterName}`);
43414
+ };
43415
+ if ($taskJson.content === undefined) {
43416
+ throw new UnexpectedError(`Content is missing in the taskJson - probably commands are applied in wrong order`);
43417
+ }
43418
+ if (command.taskType === 'EXAMPLE') {
43419
+ expectResultingParameterName();
43420
+ const parameter = $pipelineJson.parameters.find((param) => param.name === $taskJson.resultingParameterName);
43421
+ if (parameter === undefined) {
43422
+ // TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
43423
+ throw new ParseError(`Parameter \`{${$taskJson.resultingParameterName}}\` is not defined so can not define example value of it`);
43424
+ }
43425
+ parameter.exampleValues = parameter.exampleValues || [];
43426
+ parameter.exampleValues.push($taskJson.content);
43427
+ $taskJson.isTask = false;
43428
+ return;
43429
+ }
43430
+ if (command.taskType === 'KNOWLEDGE') {
43431
+ knowledgeCommandParser.$applyToPipelineJson({
43432
+ type: 'KNOWLEDGE',
43433
+ knowledgeSourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
43434
+ }, $pipelineJson);
43435
+ $taskJson.isTask = false;
43436
+ return;
43437
+ }
43438
+ if (command.taskType === 'ACTION') {
43439
+ console.error(new NotYetImplementedError('Actions are not implemented yet'));
43440
+ $taskJson.isTask = false;
43441
+ return;
43442
+ }
43443
+ if (command.taskType === 'INSTRUMENT') {
43444
+ console.error(new NotYetImplementedError('Instruments are not implemented yet'));
43445
+ $taskJson.isTask = false;
43446
+ return;
43447
+ }
43448
+ expectResultingParameterName();
43449
+ $taskJson.taskType = command.taskType;
43450
+ $taskJson.isTask = true;
43451
+ },
43452
+ /**
43453
+ * Converts the SECTION command back to string
43454
+ *
43455
+ * Note: This is used in `pipelineJsonToString` utility
43456
+ */
43457
+ stringify(command) {
43458
+ return `---`; // <- TODO: [🛋] Implement
43459
+ },
43460
+ /**
43461
+ * Reads the SECTION command from the `TaskJson`
43462
+ *
43463
+ * Note: This is used in `pipelineJsonToString` utility
43464
+ */
43465
+ takeFromTaskJson($taskJson) {
43466
+ throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
43467
+ },
43468
+ };
43469
+ /**
43470
+ * Note: [⛱] There are two types of KNOWLEDGE, ACTION and INSTRUMENT commands:
43471
+ * 1) There are commands `KNOWLEDGE`, `ACTION` and `INSTRUMENT` used in the pipeline head, they just define the knowledge, action or instrument as single line after the command
43472
+ * - KNOWLEDGE Look at https://en.wikipedia.org/wiki/Artificial_intelligence
43473
+ * 2) `KNOWLEDGE SECTION` which has short form `KNOWLEDGE` is used in the sectiom, does not refer the line itself, but the content of the section block
43474
+ * - KNOWLEDGE SECTION
43475
+ *
43476
+ * ```
43477
+ * Look at https://en.wikipedia.org/wiki/Artificial_intelligence
43478
+ * ```
43479
+ */
43480
+
43365
43481
  /**
43366
43482
  * Parses the url command
43367
43483
  *
@@ -43815,6 +43931,242 @@ function parseCommandVariant(input) {
43815
43931
  return null;
43816
43932
  }
43817
43933
 
43934
+ /**
43935
+ * Utility function to extract all list items from markdown
43936
+ *
43937
+ * Note: It works with both ul and ol
43938
+ * Note: It omits list items in code blocks
43939
+ * Note: It flattens nested lists
43940
+ * Note: It can not work with html syntax and comments
43941
+ *
43942
+ * @param markdown any valid markdown
43943
+ * @returns An array of strings, each representing an individual list item found in the markdown
43944
+ *
43945
+ * @public exported from `@promptbook/markdown-utils`
43946
+ */
43947
+ function extractAllListItemsFromMarkdown(markdown) {
43948
+ const lines = markdown.split(/\r?\n/);
43949
+ const listItems = [];
43950
+ let isInCodeBlock = false;
43951
+ for (const line of lines) {
43952
+ const trimmedLine = line.trim();
43953
+ if (trimmedLine.startsWith('```')) {
43954
+ isInCodeBlock = !isInCodeBlock;
43955
+ }
43956
+ if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
43957
+ const listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
43958
+ listItems.push(listItem);
43959
+ }
43960
+ }
43961
+ return listItems;
43962
+ }
43963
+
43964
+ /**
43965
+ * Builds a short file/url identification block for parse errors.
43966
+ *
43967
+ * @private internal utility of `parsePipeline`
43968
+ */
43969
+ function getPipelineIdentification($pipelineJson) {
43970
+ // Note: This is a 😐 implementation of [🚞]
43971
+ const pipelineIdentificationParts = [];
43972
+ if ($pipelineJson.sourceFile !== undefined) {
43973
+ pipelineIdentificationParts.push(`File: ${$pipelineJson.sourceFile}`);
43974
+ }
43975
+ if ($pipelineJson.pipelineUrl !== undefined) {
43976
+ pipelineIdentificationParts.push(`Url: ${$pipelineJson.pipelineUrl}`);
43977
+ }
43978
+ return pipelineIdentificationParts.join('\n');
43979
+ }
43980
+
43981
+ /**
43982
+ * Merges one parameter declaration into the mutable pipeline parameter list.
43983
+ *
43984
+ * @private internal utility of `parsePipeline`
43985
+ */
43986
+ function defineParameter($pipelineJson, parameterCommand) {
43987
+ const { parameterName, parameterDescription, isInput, isOutput } = parameterCommand;
43988
+ if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
43989
+ throw new ParseError(spaceTrim$1((block) => `
43990
+ Parameter name {${parameterName}} is reserved and cannot be used as resulting parameter name
43991
+
43992
+ ${block(getPipelineIdentification($pipelineJson))}
43993
+ `) /* <- TODO: [🚞] */);
43994
+ }
43995
+ const existingParameter = $pipelineJson.parameters.find((parameter) => parameter.name === parameterName);
43996
+ if (existingParameter &&
43997
+ existingParameter.description &&
43998
+ existingParameter.description !== parameterDescription &&
43999
+ parameterDescription) {
44000
+ throw new ParseError(spaceTrim$1((block) => `
44001
+ Parameter \`{${parameterName}}\` is defined multiple times with different description:
44002
+
44003
+ ${block(getPipelineIdentification($pipelineJson))}
44004
+
44005
+ First definition:
44006
+ ${block(existingParameter.description || '[undefined]')}
44007
+
44008
+ Second definition:
44009
+ ${block(parameterDescription || '[undefined]')}
44010
+ `));
44011
+ }
44012
+ if (existingParameter) {
44013
+ if (parameterDescription) {
44014
+ existingParameter.description = parameterDescription;
44015
+ }
44016
+ existingParameter.isInput = existingParameter.isInput || isInput;
44017
+ existingParameter.isOutput = existingParameter.isOutput || isOutput;
44018
+ return;
44019
+ }
44020
+ $pipelineJson.parameters.push({
44021
+ name: parameterName,
44022
+ description: parameterDescription || undefined,
44023
+ isInput,
44024
+ isOutput,
44025
+ });
44026
+ }
44027
+
44028
+ /**
44029
+ * Removes fenced code blocks when deriving human-readable section descriptions.
44030
+ *
44031
+ * @private internal utility of `extractPipelineDescription`
44032
+ */
44033
+ const DESCRIPTION_CODE_BLOCK_REGEXP = /^```.*^```/gms;
44034
+ /**
44035
+ * Removes blockquote lines when deriving human-readable section descriptions.
44036
+ *
44037
+ * @private internal utility of `extractPipelineDescription`
44038
+ */
44039
+ const DESCRIPTION_BLOCKQUOTE_REGEXP = /^>.*$/gm;
44040
+ /**
44041
+ * Removes list items and return statements when deriving human-readable section descriptions.
44042
+ *
44043
+ * @private internal utility of `extractPipelineDescription`
44044
+ */
44045
+ const DESCRIPTION_LIST_ITEM_REGEXP = /^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm;
44046
+ /**
44047
+ * Extracts the plain-text description from a head or task section body.
44048
+ *
44049
+ * @private internal utility of `parsePipeline`
44050
+ */
44051
+ function extractPipelineDescription(sectionContent) {
44052
+ let description = sectionContent;
44053
+ description = description.split(DESCRIPTION_CODE_BLOCK_REGEXP).join('');
44054
+ description = description.split(DESCRIPTION_BLOCKQUOTE_REGEXP).join('');
44055
+ description = description.split(DESCRIPTION_LIST_ITEM_REGEXP).join('');
44056
+ description = spaceTrim$1(description);
44057
+ if (description === '') {
44058
+ return undefined;
44059
+ }
44060
+ return description;
44061
+ }
44062
+
44063
+ /**
44064
+ * Applies the pipeline head title, description, and head-level commands.
44065
+ *
44066
+ * @private internal utility of `parsePipeline`
44067
+ */
44068
+ function applyPipelineHead(pipelineHead, $pipelineJson) {
44069
+ $pipelineJson.title = pipelineHead.title;
44070
+ $pipelineJson.description = extractPipelineDescription(pipelineHead.content);
44071
+ for (const listItem of extractAllListItemsFromMarkdown(pipelineHead.content)) {
44072
+ applyPipelineHeadCommand(listItem, $pipelineJson);
44073
+ }
44074
+ }
44075
+ /**
44076
+ * Parses and applies one command declared in the pipeline head.
44077
+ *
44078
+ * @private internal utility of `applyPipelineHead`
44079
+ */
44080
+ function applyPipelineHeadCommand(listItem, $pipelineJson) {
44081
+ const command = parseCommand(listItem, 'PIPELINE_HEAD');
44082
+ const commandParser = getParserForCommand(command);
44083
+ if (commandParser.isUsedInPipelineHead !== true /* <- Note: [🦦][4] */) {
44084
+ throw new ParseError(spaceTrim$1((block) => `
44085
+ Command \`${command.type}\` is not allowed in the head of the pipeline ONLY at the pipeline task
44086
+
44087
+ ${block(getPipelineIdentification($pipelineJson))}
44088
+ `)); // <- TODO: [🚞]
44089
+ }
44090
+ try {
44091
+ commandParser.$applyToPipelineJson(command, $pipelineJson);
44092
+ // <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitly
44093
+ }
44094
+ catch (error) {
44095
+ if (!(error instanceof ParseError)) {
44096
+ throw error;
44097
+ }
44098
+ throw new ParseError(spaceTrim$1((block) => `
44099
+ Command ${command.type} failed to apply to the pipeline
44100
+
44101
+ The error:
44102
+ ${block(error.message)}
44103
+
44104
+ Raw command:
44105
+ - ${listItem}
44106
+
44107
+ Usage of ${command.type}:
44108
+ ${block(commandParser.examples.map((example) => `- ${example}`).join('\n'))}
44109
+
44110
+ ${block(getPipelineIdentification($pipelineJson))}
44111
+ `)); // <- TODO: [🚞]
44112
+ }
44113
+ if (command.type === 'PARAMETER') {
44114
+ defineParameter($pipelineJson, command);
44115
+ // <- Note: [🍣]
44116
+ }
44117
+ }
44118
+
44119
+ /**
44120
+ * Creates the mutable pipeline JSON structure used throughout parsing.
44121
+ *
44122
+ * @private internal utility of `parsePipeline`
44123
+ */
44124
+ function createInitialPipelineJson(pipelineString) {
44125
+ return {
44126
+ title: DEFAULT_BOOK_TITLE,
44127
+ parameters: [],
44128
+ tasks: [],
44129
+ knowledgeSources: [],
44130
+ knowledgePieces: [],
44131
+ personas: [],
44132
+ preparations: [],
44133
+ sources: [
44134
+ {
44135
+ type: 'BOOK',
44136
+ path: null,
44137
+ // <- TODO: !!6 Pass here path of the file
44138
+ content: pipelineString,
44139
+ },
44140
+ ],
44141
+ };
44142
+ }
44143
+
44144
+ /**
44145
+ * Creates stable unique task names for duplicate section titles.
44146
+ *
44147
+ * @private internal utility of `parsePipeline`
44148
+ */
44149
+ function createUniqueSectionNameResolver(pipelineSections) {
44150
+ const sectionCounts = {};
44151
+ for (const pipelineSection of pipelineSections) {
44152
+ const sectionName = titleToName(pipelineSection.title);
44153
+ if (sectionCounts[sectionName] === undefined) {
44154
+ sectionCounts[sectionName] = { count: 0, currentIndex: 0 };
44155
+ }
44156
+ sectionCounts[sectionName].count++;
44157
+ }
44158
+ return (title) => {
44159
+ const sectionName = titleToName(title);
44160
+ const sectionCount = sectionCounts[sectionName];
44161
+ if (sectionCount.count === 1) {
44162
+ return sectionName;
44163
+ }
44164
+ const nameWithSuffix = `${sectionName}-${sectionCount.currentIndex}`;
44165
+ sectionCount.currentIndex++;
44166
+ return nameWithSuffix;
44167
+ };
44168
+ }
44169
+
43818
44170
  /**
43819
44171
  * Extracts the interface (input and output parameters) from a pipeline.
43820
44172
  *
@@ -44076,12 +44428,261 @@ const HIGH_LEVEL_ABSTRACTIONS = [
44076
44428
  // Note: [💞] Ignore a discrepancy between file name and entity name
44077
44429
 
44078
44430
  /**
44079
- * Supported script languages
44431
+ * Applies postprocessing and exports the parsed pipeline JSON.
44080
44432
  *
44081
- * @private internal base for `ScriptLanguage`
44433
+ * @private internal utility of `parsePipeline`
44082
44434
  */
44083
- const SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
44084
- // <- TODO: [🏥] DRY
44435
+ function finalizeParsedPipeline($pipelineJson) {
44436
+ applyImplicitParameterDirections($pipelineJson);
44437
+ removeUndefinedValuesFromPipeline($pipelineJson);
44438
+ applySyncHighLevelAbstractions($pipelineJson);
44439
+ ensurePipelineFormfactor($pipelineJson);
44440
+ return exportParsedPipelineJson($pipelineJson);
44441
+ }
44442
+ /**
44443
+ * Applies default INPUT/OUTPUT flags when the author did not specify them explicitly.
44444
+ *
44445
+ * @private internal utility of `finalizeParsedPipeline`
44446
+ */
44447
+ function applyImplicitParameterDirections($pipelineJson) {
44448
+ markImplicitInputParameters($pipelineJson);
44449
+ markImplicitOutputParameters($pipelineJson);
44450
+ }
44451
+ /**
44452
+ * Marks non-result parameters as pipeline inputs when no input was declared.
44453
+ *
44454
+ * @private internal utility of `finalizeParsedPipeline`
44455
+ */
44456
+ function markImplicitInputParameters($pipelineJson) {
44457
+ if ($pipelineJson.parameters.some((parameter) => parameter.isInput)) {
44458
+ return;
44459
+ }
44460
+ for (const parameter of $pipelineJson.parameters) {
44461
+ const isThisParameterResulting = $pipelineJson.tasks.some((task) => task.resultingParameterName === parameter.name);
44462
+ if (!isThisParameterResulting) {
44463
+ parameter.isInput = true;
44464
+ // <- TODO: [💔] Why this is making typescript error in vscode but not in cli
44465
+ // > Type 'true' is not assignable to type 'false'.ts(2322)
44466
+ // > (property) isInput: false
44467
+ // > The parameter is input of the pipeline The parameter is NOT input of the pipeline
44468
+ }
44469
+ }
44470
+ }
44471
+ /**
44472
+ * Marks every non-input parameter as output when no output was declared.
44473
+ *
44474
+ * @private internal utility of `finalizeParsedPipeline`
44475
+ */
44476
+ function markImplicitOutputParameters($pipelineJson) {
44477
+ if ($pipelineJson.parameters.some((parameter) => parameter.isOutput)) {
44478
+ return;
44479
+ }
44480
+ for (const parameter of $pipelineJson.parameters) {
44481
+ if (!parameter.isInput) {
44482
+ parameter.isOutput = true;
44483
+ // <- TODO: [💔]
44484
+ }
44485
+ }
44486
+ }
44487
+ /**
44488
+ * Removes `undefined` properties from serialized tasks and parameters.
44489
+ *
44490
+ * @private internal utility of `finalizeParsedPipeline`
44491
+ */
44492
+ function removeUndefinedValuesFromPipeline($pipelineJson) {
44493
+ $pipelineJson.tasks.forEach(removeUndefinedProperties);
44494
+ $pipelineJson.parameters.forEach(removeUndefinedProperties);
44495
+ }
44496
+ /**
44497
+ * Deletes all own properties with `undefined` values from a mutable JSON entity.
44498
+ *
44499
+ * @private internal utility of `finalizeParsedPipeline`
44500
+ */
44501
+ function removeUndefinedProperties(entity) {
44502
+ for (const [key, value] of Object.entries(entity)) {
44503
+ if (value === undefined) {
44504
+ delete entity[key];
44505
+ }
44506
+ }
44507
+ }
44508
+ /**
44509
+ * Applies all sync-only high-level abstractions after parsing.
44510
+ *
44511
+ * @private internal utility of `finalizeParsedPipeline`
44512
+ */
44513
+ function applySyncHighLevelAbstractions($pipelineJson) {
44514
+ for (const highLevelAbstraction of HIGH_LEVEL_ABSTRACTIONS.filter(({ type }) => type === 'SYNC')) {
44515
+ highLevelAbstraction.$applyToPipelineJson($pipelineJson);
44516
+ }
44517
+ }
44518
+ /**
44519
+ * Ensures parsed pipelines always have the default `GENERIC` formfactor.
44520
+ *
44521
+ * @private internal utility of `finalizeParsedPipeline`
44522
+ */
44523
+ function ensurePipelineFormfactor($pipelineJson) {
44524
+ // Note: [🔆] If formfactor is still not set, set it to 'GENERIC'
44525
+ if ($pipelineJson.formfactorName === undefined) {
44526
+ $pipelineJson.formfactorName = 'GENERIC';
44527
+ }
44528
+ }
44529
+ /**
44530
+ * Finalizes ordering and exports the parsed pipeline JSON.
44531
+ *
44532
+ * @private internal utility of `finalizeParsedPipeline`
44533
+ */
44534
+ function exportParsedPipelineJson($pipelineJson) {
44535
+ return exportJson({
44536
+ name: 'pipelineJson',
44537
+ message: `Result of \`parsePipeline\``,
44538
+ order: ORDER_OF_PIPELINE_JSON,
44539
+ value: {
44540
+ formfactorName: 'GENERIC',
44541
+ // <- Note: [🔆] Setting `formfactorName` is redundant to satisfy the typescript
44542
+ ...$pipelineJson,
44543
+ },
44544
+ });
44545
+ }
44546
+ // TODO: Use spaceTrim more effectively
44547
+ // TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
44548
+ // TODO: [♈] Probably move expectations from tasks to parameters
44549
+ // TODO: [🍙] Make some standard order of json properties
44550
+
44551
+ /**
44552
+ * Parses markdown section to title its level and content
44553
+ *
44554
+ * @public exported from `@promptbook/markdown-utils`
44555
+ */
44556
+ function parseMarkdownSection(value) {
44557
+ var _a, _b;
44558
+ const lines = value.split(/\r?\n/);
44559
+ if (!lines[0].startsWith('#')) {
44560
+ throw new ParseError('Markdown section must start with heading');
44561
+ }
44562
+ const title = lines[0].replace(/^#+\s*/, '');
44563
+ const level = (_b = (_a = lines[0].match(/^#+/)) === null || _a === void 0 ? void 0 : _a[0].length) !== null && _b !== void 0 ? _b : 0;
44564
+ const content = spaceTrim$1(lines.slice(1).join('\n'));
44565
+ if (level < 1 || level > 6) {
44566
+ throw new ParseError('Markdown section must have heading level between 1 and 6');
44567
+ }
44568
+ return { title, level: level, content };
44569
+ }
44570
+ /**
44571
+ * Note: [🕞] In past (commit 42086e1603cbed506482997c00a8ee979af0a247) there was much more
44572
+ * sophisticated implementation of this function through parsing markdown into JSON structure
44573
+ * and flattening the actual structure
44574
+ * NOW we are working just with markdown string and its good enough
44575
+ */
44576
+
44577
+ /**
44578
+ * Splits the markdown into sections by headings
44579
+ *
44580
+ * @public exported from `@promptbook/markdown-utils`
44581
+ */
44582
+ function splitMarkdownIntoSections(markdown) {
44583
+ const lines = markdown.split(/\r?\n/);
44584
+ const sections = [];
44585
+ // TODO: [🧽] DRY
44586
+ let currentType = 'MARKDOWN';
44587
+ let buffer = [];
44588
+ const finishSection = () => {
44589
+ if (buffer.length === 0) {
44590
+ return;
44591
+ }
44592
+ let section = spaceTrim$1(buffer.join('\n'));
44593
+ if (section === '') {
44594
+ return;
44595
+ }
44596
+ if (!section.startsWith('#')) {
44597
+ section = `# ${DEFAULT_BOOK_TITLE}\n\n${section}`;
44598
+ }
44599
+ sections.push(section);
44600
+ buffer = [];
44601
+ };
44602
+ for (const line of lines) {
44603
+ if (currentType === 'MARKDOWN') {
44604
+ if (line.startsWith('#')) {
44605
+ finishSection();
44606
+ }
44607
+ buffer.push(line);
44608
+ if (line.startsWith('```')) {
44609
+ currentType = 'CODE_BLOCK';
44610
+ }
44611
+ else if (line.includes('<!--')) {
44612
+ currentType = 'COMMENT';
44613
+ }
44614
+ }
44615
+ else if (currentType === 'CODE_BLOCK') {
44616
+ buffer.push(line);
44617
+ if (line.startsWith('```')) {
44618
+ currentType = 'MARKDOWN';
44619
+ }
44620
+ }
44621
+ else if (currentType === 'COMMENT') {
44622
+ buffer.push(line);
44623
+ if (line.includes('-->')) {
44624
+ currentType = 'MARKDOWN';
44625
+ }
44626
+ }
44627
+ }
44628
+ finishSection();
44629
+ return sections;
44630
+ }
44631
+ /**
44632
+ * TODO: [🏛] This can be part of markdown builder
44633
+ * Note: [🕞] In past (commit 42086e1603cbed506482997c00a8ee979af0a247) there was much more
44634
+ * sophisticated implementation of this function through parsing markdown into JSON structure
44635
+ * and flattening the actual structure
44636
+ * NOW we are working just with markdown string and its good enough
44637
+ */
44638
+
44639
+ /**
44640
+ * Splits the prepared markdown into the pipeline head and task sections.
44641
+ *
44642
+ * @private internal utility of `parsePipeline`
44643
+ */
44644
+ function parsePreparedPipelineSections(pipelineString, $pipelineJson) {
44645
+ const [pipelineHead, ...pipelineSections] = splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection); /* <- Note: [🥞] */
44646
+ assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson);
44647
+ return {
44648
+ pipelineHead,
44649
+ pipelineSections,
44650
+ };
44651
+ }
44652
+ /**
44653
+ * Ensures the flattened markdown has exactly one h1 head followed by only h2 sections.
44654
+ *
44655
+ * @private internal utility of `parsePreparedPipelineSections`
44656
+ */
44657
+ function assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson) {
44658
+ if (pipelineHead === undefined) {
44659
+ throw new UnexpectedError(spaceTrim$1((block) => `
44660
+ Pipeline head is not defined
44661
+
44662
+ ${block(getPipelineIdentification($pipelineJson))}
44663
+
44664
+ This should never happen, because the pipeline already flattened
44665
+ `));
44666
+ }
44667
+ if (pipelineHead.level !== 1) {
44668
+ throw new UnexpectedError(spaceTrim$1((block) => `
44669
+ Pipeline head is not h1
44670
+
44671
+ ${block(getPipelineIdentification($pipelineJson))}
44672
+
44673
+ This should never happen, because the pipeline already flattened
44674
+ `));
44675
+ }
44676
+ if (!pipelineSections.every((pipelineSection) => pipelineSection.level === 2)) {
44677
+ throw new UnexpectedError(spaceTrim$1((block) => `
44678
+ Not every pipeline section is h2
44679
+
44680
+ ${block(getPipelineIdentification($pipelineJson))}
44681
+
44682
+ This should never happen, because the pipeline already flattened
44683
+ `));
44684
+ }
44685
+ }
44085
44686
 
44086
44687
  /**
44087
44688
  * Number of padding lines to add at the end of the book content
@@ -44208,124 +44809,6 @@ function deflatePipeline(pipelineString) {
44208
44809
  }
44209
44810
  // TODO: Unit test
44210
44811
 
44211
- /**
44212
- * Utility function to extract all list items from markdown
44213
- *
44214
- * Note: It works with both ul and ol
44215
- * Note: It omits list items in code blocks
44216
- * Note: It flattens nested lists
44217
- * Note: It can not work with html syntax and comments
44218
- *
44219
- * @param markdown any valid markdown
44220
- * @returns An array of strings, each representing an individual list item found in the markdown
44221
- *
44222
- * @public exported from `@promptbook/markdown-utils`
44223
- */
44224
- function extractAllListItemsFromMarkdown(markdown) {
44225
- const lines = markdown.split(/\r?\n/);
44226
- const listItems = [];
44227
- let isInCodeBlock = false;
44228
- for (const line of lines) {
44229
- const trimmedLine = line.trim();
44230
- if (trimmedLine.startsWith('```')) {
44231
- isInCodeBlock = !isInCodeBlock;
44232
- }
44233
- if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
44234
- const listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
44235
- listItems.push(listItem);
44236
- }
44237
- }
44238
- return listItems;
44239
- }
44240
-
44241
- /**
44242
- * Parses markdown section to title its level and content
44243
- *
44244
- * @public exported from `@promptbook/markdown-utils`
44245
- */
44246
- function parseMarkdownSection(value) {
44247
- var _a, _b;
44248
- const lines = value.split(/\r?\n/);
44249
- if (!lines[0].startsWith('#')) {
44250
- throw new ParseError('Markdown section must start with heading');
44251
- }
44252
- const title = lines[0].replace(/^#+\s*/, '');
44253
- const level = (_b = (_a = lines[0].match(/^#+/)) === null || _a === void 0 ? void 0 : _a[0].length) !== null && _b !== void 0 ? _b : 0;
44254
- const content = spaceTrim$1(lines.slice(1).join('\n'));
44255
- if (level < 1 || level > 6) {
44256
- throw new ParseError('Markdown section must have heading level between 1 and 6');
44257
- }
44258
- return { title, level: level, content };
44259
- }
44260
- /**
44261
- * Note: [🕞] In past (commit 42086e1603cbed506482997c00a8ee979af0a247) there was much more
44262
- * sophisticated implementation of this function through parsing markdown into JSON structure
44263
- * and flattening the actual structure
44264
- * NOW we are working just with markdown string and its good enough
44265
- */
44266
-
44267
- /**
44268
- * Splits the markdown into sections by headings
44269
- *
44270
- * @public exported from `@promptbook/markdown-utils`
44271
- */
44272
- function splitMarkdownIntoSections(markdown) {
44273
- const lines = markdown.split(/\r?\n/);
44274
- const sections = [];
44275
- // TODO: [🧽] DRY
44276
- let currentType = 'MARKDOWN';
44277
- let buffer = [];
44278
- const finishSection = () => {
44279
- if (buffer.length === 0) {
44280
- return;
44281
- }
44282
- let section = spaceTrim$1(buffer.join('\n'));
44283
- if (section === '') {
44284
- return;
44285
- }
44286
- if (!section.startsWith('#')) {
44287
- section = `# ${DEFAULT_BOOK_TITLE}\n\n${section}`;
44288
- }
44289
- sections.push(section);
44290
- buffer = [];
44291
- };
44292
- for (const line of lines) {
44293
- if (currentType === 'MARKDOWN') {
44294
- if (line.startsWith('#')) {
44295
- finishSection();
44296
- }
44297
- buffer.push(line);
44298
- if (line.startsWith('```')) {
44299
- currentType = 'CODE_BLOCK';
44300
- }
44301
- else if (line.includes('<!--')) {
44302
- currentType = 'COMMENT';
44303
- }
44304
- }
44305
- else if (currentType === 'CODE_BLOCK') {
44306
- buffer.push(line);
44307
- if (line.startsWith('```')) {
44308
- currentType = 'MARKDOWN';
44309
- }
44310
- }
44311
- else if (currentType === 'COMMENT') {
44312
- buffer.push(line);
44313
- if (line.includes('-->')) {
44314
- currentType = 'MARKDOWN';
44315
- }
44316
- }
44317
- }
44318
- finishSection();
44319
- return sections;
44320
- }
44321
- /**
44322
- * TODO: [🏛] This can be part of markdown builder
44323
- * Note: [🕞] In past (commit 42086e1603cbed506482997c00a8ee979af0a247) there was much more
44324
- * sophisticated implementation of this function through parsing markdown into JSON structure
44325
- * and flattening the actual structure
44326
- * NOW we are working just with markdown string and its good enough
44327
- */
44328
-
44329
44812
  /**
44330
44813
  * Normalizes the markdown by flattening the structure
44331
44814
  *
@@ -44367,111 +44850,15 @@ function flattenMarkdown(markdown) {
44367
44850
  /**
44368
44851
  * Normalizes inline parameter mentions wrapped in code spans before markdown flattening.
44369
44852
  *
44370
- * @private internal utility of `parsePipeline`
44853
+ * @private internal utility of `preparePipelineString`
44371
44854
  */
44372
44855
  const INLINE_CODE_PARAMETER_REGEXP = /`\{(?<parameterName>[a-z0-9_]+)\}`/gi;
44373
44856
  /**
44374
44857
  * Normalizes inline return statements wrapped in code spans before markdown flattening.
44375
44858
  *
44376
- * @private internal utility of `parsePipeline`
44859
+ * @private internal utility of `preparePipelineString`
44377
44860
  */
44378
44861
  const INLINE_CODE_RETURN_PARAMETER_REGEXP = /`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi;
44379
- /**
44380
- * Matches the trailing return statement of a task section.
44381
- *
44382
- * @private internal utility of `parsePipeline`
44383
- */
44384
- const RESULTING_PARAMETER_LINE_REGEXP = /^->\s*\{(?<resultingParamName>[a-z0-9_]+)\}/im;
44385
- /**
44386
- * Removes fenced code blocks when deriving human-readable section descriptions.
44387
- *
44388
- * @private internal utility of `parsePipeline`
44389
- */
44390
- const DESCRIPTION_CODE_BLOCK_REGEXP = /^```.*^```/gms;
44391
- /**
44392
- * Removes blockquote lines when deriving human-readable section descriptions.
44393
- *
44394
- * @private internal utility of `parsePipeline`
44395
- */
44396
- const DESCRIPTION_BLOCKQUOTE_REGEXP = /^>.*$/gm;
44397
- /**
44398
- * Removes list items and return statements when deriving human-readable section descriptions.
44399
- *
44400
- * @private internal utility of `parsePipeline`
44401
- */
44402
- const DESCRIPTION_LIST_ITEM_REGEXP = /^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm;
44403
- /**
44404
- * Compile pipeline from string (markdown) format to JSON format synchronously
44405
- *
44406
- * Note: There are 3 similar functions:
44407
- * - `compilePipeline` **(preferred)** - which properly compiles the promptbook and uses embedding for external knowledge
44408
- * - `parsePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
44409
- * - `preparePipeline` - just one step in the compilation process
44410
- *
44411
- * Note: This function does not validate logic of the pipeline only the parsing
44412
- * Note: This function acts as compilation process
44413
- *
44414
- * @param pipelineString {Promptbook} in string markdown format (.book.md)
44415
- * @returns {Promptbook} compiled in JSON format (.bookc)
44416
- * @throws {ParseError} if the promptbook string is not valid
44417
- *
44418
- * @public exported from `@promptbook/core`
44419
- */
44420
- function parsePipeline(pipelineString) {
44421
- const $pipelineJson = createInitialPipelineJson(pipelineString);
44422
- const preparedPipelineString = preparePipelineString(pipelineString, $pipelineJson);
44423
- const { pipelineHead, pipelineSections } = parsePreparedPipelineSections(preparedPipelineString, $pipelineJson);
44424
- const getUniqueSectionName = createUniqueSectionNameResolver(pipelineSections);
44425
- applyPipelineHead(pipelineHead, $pipelineJson);
44426
- for (const pipelineSection of pipelineSections) {
44427
- processPipelineSection(pipelineSection, $pipelineJson, getUniqueSectionName);
44428
- }
44429
- applyImplicitParameterDirections($pipelineJson);
44430
- removeUndefinedValuesFromPipeline($pipelineJson);
44431
- applySyncHighLevelAbstractions($pipelineJson);
44432
- ensurePipelineFormfactor($pipelineJson);
44433
- return exportParsedPipelineJson($pipelineJson);
44434
- }
44435
- /**
44436
- * Creates the mutable pipeline JSON structure used throughout parsing.
44437
- *
44438
- * @private internal utility of `parsePipeline`
44439
- */
44440
- function createInitialPipelineJson(pipelineString) {
44441
- return {
44442
- title: DEFAULT_BOOK_TITLE,
44443
- parameters: [],
44444
- tasks: [],
44445
- knowledgeSources: [],
44446
- knowledgePieces: [],
44447
- personas: [],
44448
- preparations: [],
44449
- sources: [
44450
- {
44451
- type: 'BOOK',
44452
- path: null,
44453
- // <- TODO: !!6 Pass here path of the file
44454
- content: pipelineString,
44455
- },
44456
- ],
44457
- };
44458
- }
44459
- /**
44460
- * Builds a short file/url identification block for parse errors.
44461
- *
44462
- * @private internal utility of `parsePipeline`
44463
- */
44464
- function getPipelineIdentification($pipelineJson) {
44465
- // Note: This is a 😐 implementation of [🚞]
44466
- const pipelineIdentificationParts = [];
44467
- if ($pipelineJson.sourceFile !== undefined) {
44468
- pipelineIdentificationParts.push(`File: ${$pipelineJson.sourceFile}`);
44469
- }
44470
- if ($pipelineJson.pipelineUrl !== undefined) {
44471
- pipelineIdentificationParts.push(`Url: ${$pipelineJson.pipelineUrl}`);
44472
- }
44473
- return pipelineIdentificationParts.join('\n');
44474
- }
44475
44862
  /**
44476
44863
  * Removes shebang/comments and normalizes markdown into a parseable pipeline form.
44477
44864
  *
@@ -44491,7 +44878,7 @@ function preparePipelineString(pipelineString, $pipelineJson) {
44491
44878
  /**
44492
44879
  * Validates and removes the optional `#!` shebang line for `.book` files.
44493
44880
  *
44494
- * @private internal utility of `parsePipeline`
44881
+ * @private internal utility of `preparePipelineString`
44495
44882
  */
44496
44883
  function removePipelineShebang(pipelineString, $pipelineJson) {
44497
44884
  if (!pipelineString.startsWith('#!')) {
@@ -44515,195 +44902,21 @@ function removePipelineShebang(pipelineString, $pipelineJson) {
44515
44902
  }
44516
44903
  return validatePipelineString(restLines.join('\n'));
44517
44904
  }
44518
- /**
44519
- * Splits the prepared markdown into the pipeline head and task sections.
44520
- *
44521
- * @private internal utility of `parsePipeline`
44522
- */
44523
- function parsePreparedPipelineSections(pipelineString, $pipelineJson) {
44524
- const [pipelineHead, ...pipelineSections] = splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection); /* <- Note: [🥞] */
44525
- assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson);
44526
- return {
44527
- pipelineHead,
44528
- pipelineSections,
44529
- };
44530
- }
44531
- /**
44532
- * Ensures the flattened markdown has exactly one h1 head followed by only h2 sections.
44533
- *
44534
- * @private internal utility of `parsePipeline`
44535
- */
44536
- function assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson) {
44537
- if (pipelineHead === undefined) {
44538
- throw new UnexpectedError(spaceTrim$1((block) => `
44539
- Pipeline head is not defined
44540
-
44541
- ${block(getPipelineIdentification($pipelineJson))}
44542
-
44543
- This should never happen, because the pipeline already flattened
44544
- `));
44545
- }
44546
- if (pipelineHead.level !== 1) {
44547
- throw new UnexpectedError(spaceTrim$1((block) => `
44548
- Pipeline head is not h1
44549
-
44550
- ${block(getPipelineIdentification($pipelineJson))}
44551
-
44552
- This should never happen, because the pipeline already flattened
44553
- `));
44554
- }
44555
- if (!pipelineSections.every((pipelineSection) => pipelineSection.level === 2)) {
44556
- throw new UnexpectedError(spaceTrim$1((block) => `
44557
- Not every pipeline section is h2
44558
-
44559
- ${block(getPipelineIdentification($pipelineJson))}
44560
-
44561
- This should never happen, because the pipeline already flattened
44562
- `));
44563
- }
44564
- }
44565
- /**
44566
- * Applies the pipeline head title, description, and head-level commands.
44567
- *
44568
- * @private internal utility of `parsePipeline`
44569
- */
44570
- function applyPipelineHead(pipelineHead, $pipelineJson) {
44571
- $pipelineJson.title = pipelineHead.title;
44572
- $pipelineJson.description = extractPipelineDescription(pipelineHead.content);
44573
- for (const listItem of extractAllListItemsFromMarkdown(pipelineHead.content)) {
44574
- applyPipelineHeadCommand(listItem, $pipelineJson);
44575
- }
44576
- }
44577
- /**
44578
- * Extracts the plain-text description from a head or task section body.
44579
- *
44580
- * @private internal utility of `parsePipeline`
44581
- */
44582
- function extractPipelineDescription(sectionContent) {
44583
- let description = sectionContent;
44584
- description = description.split(DESCRIPTION_CODE_BLOCK_REGEXP).join('');
44585
- description = description.split(DESCRIPTION_BLOCKQUOTE_REGEXP).join('');
44586
- description = description.split(DESCRIPTION_LIST_ITEM_REGEXP).join('');
44587
- description = spaceTrim$1(description);
44588
- if (description === '') {
44589
- return undefined;
44590
- }
44591
- return description;
44592
- }
44593
- /**
44594
- * Parses and applies one command declared in the pipeline head.
44595
- *
44596
- * @private internal utility of `parsePipeline`
44597
- */
44598
- function applyPipelineHeadCommand(listItem, $pipelineJson) {
44599
- const command = parseCommand(listItem, 'PIPELINE_HEAD');
44600
- const commandParser = getParserForCommand(command);
44601
- if (commandParser.isUsedInPipelineHead !== true /* <- Note: [🦦][4] */) {
44602
- throw new ParseError(spaceTrim$1((block) => `
44603
- Command \`${command.type}\` is not allowed in the head of the pipeline ONLY at the pipeline task
44604
-
44605
- ${block(getPipelineIdentification($pipelineJson))}
44606
- `)); // <- TODO: [🚞]
44607
- }
44608
- try {
44609
- commandParser.$applyToPipelineJson(command, $pipelineJson);
44610
- // <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitly
44611
- }
44612
- catch (error) {
44613
- if (!(error instanceof ParseError)) {
44614
- throw error;
44615
- }
44616
- throw new ParseError(spaceTrim$1((block) => `
44617
- Command ${command.type} failed to apply to the pipeline
44618
-
44619
- The error:
44620
- ${block(error.message)}
44621
-
44622
- Raw command:
44623
- - ${listItem}
44624
-
44625
- Usage of ${command.type}:
44626
- ${block(commandParser.examples.map((example) => `- ${example}`).join('\n'))}
44627
44905
 
44628
- ${block(getPipelineIdentification($pipelineJson))}
44629
- `)); // <- TODO: [🚞]
44630
- }
44631
- if (command.type === 'PARAMETER') {
44632
- defineParameter($pipelineJson, command);
44633
- // <- Note: [🍣]
44634
- }
44635
- }
44636
44906
  /**
44637
- * Merges one parameter declaration into the mutable pipeline parameter list.
44907
+ * Supported script languages
44638
44908
  *
44639
- * @private internal utility of `parsePipeline`
44909
+ * @private internal base for `ScriptLanguage`
44640
44910
  */
44641
- function defineParameter($pipelineJson, parameterCommand) {
44642
- const { parameterName, parameterDescription, isInput, isOutput } = parameterCommand;
44643
- if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
44644
- throw new ParseError(spaceTrim$1((block) => `
44645
- Parameter name {${parameterName}} is reserved and cannot be used as resulting parameter name
44646
-
44647
- ${block(getPipelineIdentification($pipelineJson))}
44648
- `) /* <- TODO: [🚞] */);
44649
- }
44650
- const existingParameter = $pipelineJson.parameters.find((parameter) => parameter.name === parameterName);
44651
- if (existingParameter &&
44652
- existingParameter.description &&
44653
- existingParameter.description !== parameterDescription &&
44654
- parameterDescription) {
44655
- throw new ParseError(spaceTrim$1((block) => `
44656
- Parameter \`{${parameterName}}\` is defined multiple times with different description:
44657
-
44658
- ${block(getPipelineIdentification($pipelineJson))}
44659
-
44660
- First definition:
44661
- ${block(existingParameter.description || '[undefined]')}
44911
+ const SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
44912
+ // <- TODO: [🏥] DRY
44662
44913
 
44663
- Second definition:
44664
- ${block(parameterDescription || '[undefined]')}
44665
- `));
44666
- }
44667
- if (existingParameter) {
44668
- if (parameterDescription) {
44669
- existingParameter.description = parameterDescription;
44670
- }
44671
- existingParameter.isInput = existingParameter.isInput || isInput;
44672
- existingParameter.isOutput = existingParameter.isOutput || isOutput;
44673
- return;
44674
- }
44675
- $pipelineJson.parameters.push({
44676
- name: parameterName,
44677
- description: parameterDescription || undefined,
44678
- isInput,
44679
- isOutput,
44680
- });
44681
- }
44682
44914
  /**
44683
- * Creates stable unique task names for duplicate section titles.
44915
+ * Matches the trailing return statement of a task section.
44684
44916
  *
44685
- * @private internal utility of `parsePipeline`
44917
+ * @private internal utility of `processPipelineSection`
44686
44918
  */
44687
- function createUniqueSectionNameResolver(pipelineSections) {
44688
- const sectionCounts = {};
44689
- for (const pipelineSection of pipelineSections) {
44690
- const sectionName = titleToName(pipelineSection.title);
44691
- if (sectionCounts[sectionName] === undefined) {
44692
- sectionCounts[sectionName] = { count: 0, currentIndex: 0 };
44693
- }
44694
- sectionCounts[sectionName].count++;
44695
- }
44696
- return (title) => {
44697
- const sectionName = titleToName(title);
44698
- const sectionCount = sectionCounts[sectionName];
44699
- if (sectionCount.count === 1) {
44700
- return sectionName;
44701
- }
44702
- const nameWithSuffix = `${sectionName}-${sectionCount.currentIndex}`;
44703
- sectionCount.currentIndex++;
44704
- return nameWithSuffix;
44705
- };
44706
- }
44919
+ const RESULTING_PARAMETER_LINE_REGEXP = /^->\s*\{(?<resultingParamName>[a-z0-9_]+)\}/im;
44707
44920
  /**
44708
44921
  * Parses, applies, and persists one h2 task section.
44709
44922
  *
@@ -44723,7 +44936,7 @@ function processPipelineSection(pipelineSection, $pipelineJson, getUniqueSection
44723
44936
  /**
44724
44937
  * Creates the mutable task JSON shell from one markdown section.
44725
44938
  *
44726
- * @private internal utility of `parsePipeline`
44939
+ * @private internal utility of `processPipelineSection`
44727
44940
  */
44728
44941
  function createTaskJsonFromSection(pipelineSection, getUniqueSectionName) {
44729
44942
  const { language, content } = extractOneBlockFromMarkdown(pipelineSection.content);
@@ -44751,7 +44964,7 @@ function createTaskJsonFromSection(pipelineSection, getUniqueSectionName) {
44751
44964
  /**
44752
44965
  * Extracts the optional trailing `-> {parameter}` statement from a section body.
44753
44966
  *
44754
- * @private internal utility of `parsePipeline`
44967
+ * @private internal utility of `processPipelineSection`
44755
44968
  */
44756
44969
  function extractResultingParameterName(sectionContent) {
44757
44970
  var _a;
@@ -44762,7 +44975,7 @@ function extractResultingParameterName(sectionContent) {
44762
44975
  /**
44763
44976
  * Parses all list-item commands declared inside one task section.
44764
44977
  *
44765
- * @private internal utility of `parsePipeline`
44978
+ * @private internal utility of `processPipelineSection`
44766
44979
  */
44767
44980
  function parsePipelineTaskCommands(sectionContent) {
44768
44981
  return extractAllListItemsFromMarkdown(sectionContent).map((listItem) => ({
@@ -44773,7 +44986,7 @@ function parsePipelineTaskCommands(sectionContent) {
44773
44986
  /**
44774
44987
  * Applies the implicit default `PROMPT_TASK` section type when no SECTION command is present.
44775
44988
  *
44776
- * @private internal utility of `parsePipeline`
44989
+ * @private internal utility of `processPipelineSection`
44777
44990
  */
44778
44991
  function applyDefaultTaskSectionType($taskJson, commands, $pipelineJson) {
44779
44992
  const isSectionCommandPresent = commands.some(({ command }) => command.type === 'SECTION');
@@ -44785,7 +44998,7 @@ function applyDefaultTaskSectionType($taskJson, commands, $pipelineJson) {
44785
44998
  /**
44786
44999
  * Parses and applies one command declared inside a task section.
44787
45000
  *
44788
- * @private internal utility of `parsePipeline`
45001
+ * @private internal utility of `processPipelineSection`
44789
45002
  */
44790
45003
  function applyPipelineTaskCommand(commandItem, $taskJson, $pipelineJson) {
44791
45004
  const { listItem, command } = commandItem;
@@ -44836,7 +45049,7 @@ function applyPipelineTaskCommand(commandItem, $taskJson, $pipelineJson) {
44836
45049
  /**
44837
45050
  * Validates and stores the language for SCRIPT tasks.
44838
45051
  *
44839
- * @private internal utility of `parsePipeline`
45052
+ * @private internal utility of `processPipelineSection`
44840
45053
  */
44841
45054
  function applyScriptTaskLanguage($taskJson, language, $pipelineJson) {
44842
45055
  const isScriptTask = $taskJson.taskType === 'SCRIPT_TASK';
@@ -44853,7 +45066,6 @@ function applyScriptTaskLanguage($taskJson, language, $pipelineJson) {
44853
45066
  if (!SUPPORTED_SCRIPT_LANGUAGES.includes(language)) {
44854
45067
  throw new ParseError(spaceTrim$1((block) => `
44855
45068
  Script language ${language} is not supported.
44856
-
44857
45069
  Supported languages are:
44858
45070
  ${block(SUPPORTED_SCRIPT_LANGUAGES.join(', '))}
44859
45071
 
@@ -44864,7 +45076,7 @@ function applyScriptTaskLanguage($taskJson, language, $pipelineJson) {
44864
45076
  /**
44865
45077
  * Extracts task dependencies and ensures referenced parameters exist.
44866
45078
  *
44867
- * @private internal utility of `parsePipeline`
45079
+ * @private internal utility of `processPipelineSection`
44868
45080
  */
44869
45081
  function registerTaskDependentParameters($taskJson, $pipelineJson) {
44870
45082
  $taskJson.dependentParameterNames = Array.from(extractParameterNamesFromTask($taskJson));
@@ -44882,7 +45094,7 @@ function registerTaskDependentParameters($taskJson, $pipelineJson) {
44882
45094
  /**
44883
45095
  * Removes transient parsing flags and persists real tasks into the pipeline JSON.
44884
45096
  *
44885
- * @private internal utility of `parsePipeline`
45097
+ * @private internal utility of `processPipelineSection`
44886
45098
  */
44887
45099
  function persistTaskIfNeeded($taskJson, $pipelineJson) {
44888
45100
  /*
@@ -44911,119 +45123,38 @@ function persistTaskIfNeeded($taskJson, $pipelineJson) {
44911
45123
  // TODO: [🍙] Maybe do reorder of `$taskJson` here
44912
45124
  $pipelineJson.tasks.push($taskJson);
44913
45125
  }
45126
+
44914
45127
  /**
44915
- * Applies default INPUT/OUTPUT flags when the author did not specify them explicitly.
44916
- *
44917
- * @private internal utility of `parsePipeline`
44918
- */
44919
- function applyImplicitParameterDirections($pipelineJson) {
44920
- markImplicitInputParameters($pipelineJson);
44921
- markImplicitOutputParameters($pipelineJson);
44922
- }
44923
- /**
44924
- * Marks non-result parameters as pipeline inputs when no input was declared.
44925
- *
44926
- * @private internal utility of `parsePipeline`
44927
- */
44928
- function markImplicitInputParameters($pipelineJson) {
44929
- if ($pipelineJson.parameters.some((parameter) => parameter.isInput)) {
44930
- return;
44931
- }
44932
- for (const parameter of $pipelineJson.parameters) {
44933
- const isThisParameterResulting = $pipelineJson.tasks.some((task) => task.resultingParameterName === parameter.name);
44934
- if (!isThisParameterResulting) {
44935
- parameter.isInput = true;
44936
- // <- TODO: [💔] Why this is making typescript error in vscode but not in cli
44937
- // > Type 'true' is not assignable to type 'false'.ts(2322)
44938
- // > (property) isInput: false
44939
- // > The parameter is input of the pipeline The parameter is NOT input of the pipeline
44940
- }
44941
- }
44942
- }
44943
- /**
44944
- * Marks every non-input parameter as output when no output was declared.
44945
- *
44946
- * @private internal utility of `parsePipeline`
44947
- */
44948
- function markImplicitOutputParameters($pipelineJson) {
44949
- if ($pipelineJson.parameters.some((parameter) => parameter.isOutput)) {
44950
- return;
44951
- }
44952
- for (const parameter of $pipelineJson.parameters) {
44953
- if (!parameter.isInput) {
44954
- parameter.isOutput = true;
44955
- // <- TODO: [💔]
44956
- }
44957
- }
44958
- }
44959
- /**
44960
- * Removes `undefined` properties from serialized tasks and parameters.
45128
+ * Compile pipeline from string (markdown) format to JSON format synchronously
44961
45129
  *
44962
- * @private internal utility of `parsePipeline`
44963
- */
44964
- function removeUndefinedValuesFromPipeline($pipelineJson) {
44965
- $pipelineJson.tasks.forEach(removeUndefinedProperties);
44966
- $pipelineJson.parameters.forEach(removeUndefinedProperties);
44967
- }
44968
- /**
44969
- * Deletes all own properties with `undefined` values from a mutable JSON entity.
45130
+ * Note: There are 3 similar functions:
45131
+ * - `compilePipeline` **(preferred)** - which properly compiles the promptbook and uses embedding for external knowledge
45132
+ * - `parsePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
45133
+ * - `preparePipeline` - just one step in the compilation process
44970
45134
  *
44971
- * @private internal utility of `parsePipeline`
44972
- */
44973
- function removeUndefinedProperties(entity) {
44974
- for (const [key, value] of Object.entries(entity)) {
44975
- if (value === undefined) {
44976
- delete entity[key];
44977
- }
44978
- }
44979
- }
44980
- /**
44981
- * Applies all sync-only high-level abstractions after parsing.
45135
+ * Note: This function does not validate logic of the pipeline only the parsing
45136
+ * Note: This function acts as compilation process
44982
45137
  *
44983
- * @private internal utility of `parsePipeline`
44984
- */
44985
- function applySyncHighLevelAbstractions($pipelineJson) {
44986
- for (const highLevelAbstraction of HIGH_LEVEL_ABSTRACTIONS.filter(({ type }) => type === 'SYNC')) {
44987
- highLevelAbstraction.$applyToPipelineJson($pipelineJson);
44988
- }
44989
- }
44990
- /**
44991
- * Ensures parsed pipelines always have the default `GENERIC` formfactor.
45138
+ * @param pipelineString {Promptbook} in string markdown format (.book.md)
45139
+ * @returns {Promptbook} compiled in JSON format (.bookc)
45140
+ * @throws {ParseError} if the promptbook string is not valid
44992
45141
  *
44993
- * @private internal utility of `parsePipeline`
45142
+ * @public exported from `@promptbook/core`
44994
45143
  */
44995
- function ensurePipelineFormfactor($pipelineJson) {
44996
- // Note: [🔆] If formfactor is still not set, set it to 'GENERIC'
44997
- if ($pipelineJson.formfactorName === undefined) {
44998
- $pipelineJson.formfactorName = 'GENERIC';
45144
+ function parsePipeline(pipelineString) {
45145
+ const $pipelineJson = createInitialPipelineJson(pipelineString);
45146
+ const preparedPipelineString = preparePipelineString(pipelineString, $pipelineJson);
45147
+ const { pipelineHead, pipelineSections } = parsePreparedPipelineSections(preparedPipelineString, $pipelineJson);
45148
+ const getUniqueSectionName = createUniqueSectionNameResolver(pipelineSections);
45149
+ applyPipelineHead(pipelineHead, $pipelineJson);
45150
+ for (const pipelineSection of pipelineSections) {
45151
+ processPipelineSection(pipelineSection, $pipelineJson, getUniqueSectionName);
44999
45152
  }
45000
- }
45001
- /**
45002
- * Finalizes ordering and exports the parsed pipeline JSON.
45003
- *
45004
- * @private internal utility of `parsePipeline`
45005
- */
45006
- function exportParsedPipelineJson($pipelineJson) {
45007
- return exportJson({
45008
- name: 'pipelineJson',
45009
- message: `Result of \`parsePipeline\``,
45010
- order: ORDER_OF_PIPELINE_JSON,
45011
- value: {
45012
- formfactorName: 'GENERIC',
45013
- // <- Note: [🔆] Setting `formfactorName` is redundant to satisfy the typescript
45014
- ...$pipelineJson,
45015
- },
45016
- });
45153
+ return finalizeParsedPipeline($pipelineJson);
45017
45154
  }
45018
45155
  // TODO: [🧠] Maybe more things here can be refactored as high-level abstractions
45019
45156
  // TODO: [main] !!4 Warn if used only sync version
45020
45157
  // TODO: [🚞] Report here line/column of error
45021
- // TODO: Use spaceTrim more effectively
45022
- // TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
45023
- // TODO: [🥞] Not optimal parsing because `splitMarkdownIntoSections` is executed twice with same string, once through `flattenMarkdown` and second directly here
45024
- // TODO: [♈] Probably move expectations from tasks to parameters
45025
- // TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
45026
- // TODO: [🍙] Make some standard order of json properties
45027
45158
 
45028
45159
  /**
45029
45160
  * Compile pipeline from string (markdown) format to JSON format