@promptbook/core 0.112.0-70 → 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.
- package/esm/index.es.js +1240 -1095
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-3.0/Book.d.ts +6 -0
- package/esm/src/book-components/Chat/utils/getToolCallChipletInfo.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +12 -2
- package/esm/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -0
- package/esm/src/cli/cli-commands/run/prepareRunCommandResources.d.ts +20 -0
- package/esm/src/cli/cli-commands/run/resolveRunInputParameters.d.ts +12 -0
- package/esm/src/cli/cli-commands/run/runCommandAction.d.ts +21 -0
- package/esm/src/cli/cli-commands/run/runPipelineExecution.d.ts +14 -0
- package/esm/src/cli/cli-commands/run.d.ts +1 -1
- package/esm/src/conversion/parsePipeline/applyPipelineHead.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/createInitialPipelineJson.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/createUniqueSectionNameResolver.d.ts +14 -0
- package/esm/src/conversion/parsePipeline/defineParameter.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/extractPipelineDescription.d.ts +6 -0
- package/esm/src/conversion/parsePipeline/finalizeParsedPipeline.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/getPipelineIdentification.d.ts +7 -0
- package/esm/src/conversion/parsePipeline/parsePreparedPipelineSections.d.ts +18 -0
- package/esm/src/conversion/parsePipeline/preparePipelineString.d.ts +8 -0
- package/esm/src/conversion/parsePipeline/processPipelineSection.d.ts +9 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +1240 -1095
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-3.0/Book.d.ts +6 -0
- package/umd/src/book-components/Chat/utils/getToolCallChipletInfo.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/agent/agentRunCliOptions.d.ts +12 -2
- package/umd/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -0
- package/umd/src/cli/cli-commands/run/prepareRunCommandResources.d.ts +20 -0
- package/umd/src/cli/cli-commands/run/resolveRunInputParameters.d.ts +12 -0
- package/umd/src/cli/cli-commands/run/runCommandAction.d.ts +21 -0
- package/umd/src/cli/cli-commands/run/runPipelineExecution.d.ts +14 -0
- package/umd/src/cli/cli-commands/run.d.ts +1 -1
- package/umd/src/conversion/parsePipeline/applyPipelineHead.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/createInitialPipelineJson.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/createUniqueSectionNameResolver.d.ts +14 -0
- package/umd/src/conversion/parsePipeline/defineParameter.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/extractPipelineDescription.d.ts +6 -0
- package/umd/src/conversion/parsePipeline/finalizeParsedPipeline.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/getPipelineIdentification.d.ts +7 -0
- package/umd/src/conversion/parsePipeline/parsePreparedPipelineSections.d.ts +18 -0
- package/umd/src/conversion/parsePipeline/preparePipelineString.d.ts +8 -0
- package/umd/src/conversion/parsePipeline/processPipelineSection.d.ts +9 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -28,7 +28,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
28
28
|
* @generated
|
|
29
29
|
* @see https://github.com/webgptorg/promptbook
|
|
30
30
|
*/
|
|
31
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
31
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-72';
|
|
32
32
|
/**
|
|
33
33
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
34
34
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -14124,7 +14124,9 @@ const octopus3dAvatarVisual = {
|
|
|
14124
14124
|
};
|
|
14125
14125
|
const mantleRadiusX = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch;
|
|
14126
14126
|
const mantleRadiusY = size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.1;
|
|
14127
|
-
const mantleRadiusZ = size *
|
|
14127
|
+
const mantleRadiusZ = size *
|
|
14128
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
14129
|
+
(0.9 + (morphologyProfile.body.horizontalStretch - 1) * 0.3);
|
|
14128
14130
|
const underbodyRadiusX = mantleRadiusX * (0.9 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.08);
|
|
14129
14131
|
const underbodyRadiusY = mantleRadiusY * (0.44 + morphologyProfile.body.lowerDropRatio * 3.1);
|
|
14130
14132
|
const underbodyRadiusZ = mantleRadiusZ * 0.78;
|
|
@@ -14210,7 +14212,11 @@ const octopus3dAvatarVisual = {
|
|
|
14210
14212
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
14211
14213
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
14212
14214
|
drawProjectedMouth(context, [
|
|
14213
|
-
{
|
|
14215
|
+
{
|
|
14216
|
+
x: -mouthHalfWidth,
|
|
14217
|
+
y: mouthY,
|
|
14218
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -mouthHalfWidth, mouthY),
|
|
14219
|
+
},
|
|
14214
14220
|
{
|
|
14215
14221
|
x: size * morphologyProfile.face.mouthCenterOffsetRatio,
|
|
14216
14222
|
y: mouthY +
|
|
@@ -14219,7 +14225,11 @@ const octopus3dAvatarVisual = {
|
|
|
14219
14225
|
interaction.gazeY * size * 0.01,
|
|
14220
14226
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, size * morphologyProfile.face.mouthCenterOffsetRatio, mouthY),
|
|
14221
14227
|
},
|
|
14222
|
-
{
|
|
14228
|
+
{
|
|
14229
|
+
x: mouthHalfWidth,
|
|
14230
|
+
y: mouthY,
|
|
14231
|
+
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, mouthHalfWidth, mouthY),
|
|
14232
|
+
},
|
|
14223
14233
|
], mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, palette, size);
|
|
14224
14234
|
},
|
|
14225
14235
|
};
|
|
@@ -14380,7 +14390,8 @@ function createOctopusTentacleStrokes(options) {
|
|
|
14380
14390
|
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.3 + sway * size * 0.012,
|
|
14381
14391
|
};
|
|
14382
14392
|
const controlPointTwo = {
|
|
14383
|
-
x: anchorPoint.x +
|
|
14393
|
+
x: anchorPoint.x +
|
|
14394
|
+
Math.sin(orbitAngle) * lateralReach * (0.82 + morphologyProfile.tentacles.swayScale * 0.12),
|
|
14384
14395
|
y: anchorPoint.y + flowLength * 0.66,
|
|
14385
14396
|
z: anchorPoint.z + Math.cos(orbitAngle) * depthReach * 0.72 + sway * size * 0.02,
|
|
14386
14397
|
};
|
|
@@ -14445,8 +14456,7 @@ function drawTentacleStroke(context, tentacleStroke, palette) {
|
|
|
14445
14456
|
context.beginPath();
|
|
14446
14457
|
context.moveTo(startPoint.x, startPoint.y);
|
|
14447
14458
|
context.lineTo(endPoint.x, endPoint.y);
|
|
14448
|
-
context.strokeStyle =
|
|
14449
|
-
tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
|
|
14459
|
+
context.strokeStyle = tentacleStroke.colorBias > 0.6 ? `${palette.secondary}f0` : `${palette.primary}f0`;
|
|
14450
14460
|
context.lineWidth = width;
|
|
14451
14461
|
context.lineCap = 'round';
|
|
14452
14462
|
context.stroke();
|
|
@@ -22478,6 +22488,212 @@ const DEFAULT_LIST_TIMEOUTS_LIMIT = 20;
|
|
|
22478
22488
|
* @private internal USE TIMEOUT constant
|
|
22479
22489
|
*/
|
|
22480
22490
|
const MAX_LIST_TIMEOUTS_LIMIT = 100;
|
|
22491
|
+
/**
|
|
22492
|
+
* Creates one formatted timeout-argument validation error.
|
|
22493
|
+
*
|
|
22494
|
+
* @private internal utility of USE TIMEOUT
|
|
22495
|
+
*/
|
|
22496
|
+
function createTimeoutToolArgsError(message) {
|
|
22497
|
+
return new PipelineExecutionError(spaceTrim$1(`
|
|
22498
|
+
${message}
|
|
22499
|
+
`));
|
|
22500
|
+
}
|
|
22501
|
+
/**
|
|
22502
|
+
* Normalizes one optional timeout id string.
|
|
22503
|
+
*
|
|
22504
|
+
* @private internal utility of USE TIMEOUT
|
|
22505
|
+
*/
|
|
22506
|
+
function normalizeOptionalTimeoutId(value) {
|
|
22507
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
22508
|
+
}
|
|
22509
|
+
/**
|
|
22510
|
+
* Parses timeout target selection for tools that accept either `timeoutId` or `allActive: true`.
|
|
22511
|
+
*
|
|
22512
|
+
* @private internal utility of USE TIMEOUT
|
|
22513
|
+
*/
|
|
22514
|
+
function parseTimeoutTargetSelection(args, options) {
|
|
22515
|
+
const timeoutId = normalizeOptionalTimeoutId(args.timeoutId);
|
|
22516
|
+
const allActive = args.allActive === true;
|
|
22517
|
+
if (timeoutId && allActive) {
|
|
22518
|
+
throw createTimeoutToolArgsError(options.bothMessage);
|
|
22519
|
+
}
|
|
22520
|
+
if (allActive) {
|
|
22521
|
+
return { allActive: true };
|
|
22522
|
+
}
|
|
22523
|
+
if (!timeoutId) {
|
|
22524
|
+
throw createTimeoutToolArgsError(options.missingMessage);
|
|
22525
|
+
}
|
|
22526
|
+
return {
|
|
22527
|
+
timeoutId,
|
|
22528
|
+
allActive: false,
|
|
22529
|
+
};
|
|
22530
|
+
}
|
|
22531
|
+
/**
|
|
22532
|
+
* Parses one explicit `dueAt` update value.
|
|
22533
|
+
*
|
|
22534
|
+
* @private internal utility of USE TIMEOUT
|
|
22535
|
+
*/
|
|
22536
|
+
function parseOptionalTimeoutDueAt(value) {
|
|
22537
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
22538
|
+
return undefined;
|
|
22539
|
+
}
|
|
22540
|
+
const normalizedDueAt = value.trim();
|
|
22541
|
+
const dueAtTimestamp = Date.parse(normalizedDueAt);
|
|
22542
|
+
if (!Number.isFinite(dueAtTimestamp)) {
|
|
22543
|
+
throw createTimeoutToolArgsError('Timeout `dueAt` must be one valid ISO timestamp.');
|
|
22544
|
+
}
|
|
22545
|
+
return new Date(dueAtTimestamp).toISOString();
|
|
22546
|
+
}
|
|
22547
|
+
/**
|
|
22548
|
+
* Parses one explicit `extendByMs` update value.
|
|
22549
|
+
*
|
|
22550
|
+
* @private internal utility of USE TIMEOUT
|
|
22551
|
+
*/
|
|
22552
|
+
function parseOptionalTimeoutExtendByMs(value) {
|
|
22553
|
+
if (typeof value !== 'number') {
|
|
22554
|
+
return undefined;
|
|
22555
|
+
}
|
|
22556
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
22557
|
+
throw createTimeoutToolArgsError('Timeout `extendByMs` must be a positive number of milliseconds.');
|
|
22558
|
+
}
|
|
22559
|
+
return Math.floor(value);
|
|
22560
|
+
}
|
|
22561
|
+
/**
|
|
22562
|
+
* Parses one explicit `recurrenceIntervalMs` update value.
|
|
22563
|
+
*
|
|
22564
|
+
* @private internal utility of USE TIMEOUT
|
|
22565
|
+
*/
|
|
22566
|
+
function parseOptionalTimeoutRecurrenceInterval(value) {
|
|
22567
|
+
if (value === null) {
|
|
22568
|
+
return null;
|
|
22569
|
+
}
|
|
22570
|
+
if (typeof value !== 'number') {
|
|
22571
|
+
return undefined;
|
|
22572
|
+
}
|
|
22573
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
22574
|
+
throw createTimeoutToolArgsError('Timeout `recurrenceIntervalMs` must be a positive number of milliseconds or `null`.');
|
|
22575
|
+
}
|
|
22576
|
+
return Math.floor(value);
|
|
22577
|
+
}
|
|
22578
|
+
/**
|
|
22579
|
+
* Parses one explicit `message` update value.
|
|
22580
|
+
*
|
|
22581
|
+
* @private internal utility of USE TIMEOUT
|
|
22582
|
+
*/
|
|
22583
|
+
function parseOptionalTimeoutMessage(value) {
|
|
22584
|
+
if (value === null) {
|
|
22585
|
+
return null;
|
|
22586
|
+
}
|
|
22587
|
+
if (typeof value !== 'string') {
|
|
22588
|
+
return undefined;
|
|
22589
|
+
}
|
|
22590
|
+
const normalizedMessage = value.trim();
|
|
22591
|
+
return normalizedMessage.length > 0 ? normalizedMessage : null;
|
|
22592
|
+
}
|
|
22593
|
+
/**
|
|
22594
|
+
* Parses one explicit `parameters` update value.
|
|
22595
|
+
*
|
|
22596
|
+
* @private internal utility of USE TIMEOUT
|
|
22597
|
+
*/
|
|
22598
|
+
function parseOptionalTimeoutParameters(value) {
|
|
22599
|
+
if (value === undefined) {
|
|
22600
|
+
return undefined;
|
|
22601
|
+
}
|
|
22602
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
22603
|
+
throw createTimeoutToolArgsError('Timeout `parameters` must be one JSON object.');
|
|
22604
|
+
}
|
|
22605
|
+
return value;
|
|
22606
|
+
}
|
|
22607
|
+
/**
|
|
22608
|
+
* Parses one explicit `paused` update value.
|
|
22609
|
+
*
|
|
22610
|
+
* @private internal utility of USE TIMEOUT
|
|
22611
|
+
*/
|
|
22612
|
+
function parseOptionalTimeoutPaused(value) {
|
|
22613
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
22614
|
+
}
|
|
22615
|
+
/**
|
|
22616
|
+
* Parses patch fields for `update_timeout`.
|
|
22617
|
+
*
|
|
22618
|
+
* @private internal utility of USE TIMEOUT
|
|
22619
|
+
*/
|
|
22620
|
+
function parseTimeoutUpdatePatch(args) {
|
|
22621
|
+
const patch = {};
|
|
22622
|
+
const dueAt = parseOptionalTimeoutDueAt(args.dueAt);
|
|
22623
|
+
const extendByMs = parseOptionalTimeoutExtendByMs(args.extendByMs);
|
|
22624
|
+
const recurrenceIntervalMs = parseOptionalTimeoutRecurrenceInterval(args.recurrenceIntervalMs);
|
|
22625
|
+
const message = parseOptionalTimeoutMessage(args.message);
|
|
22626
|
+
const parameters = parseOptionalTimeoutParameters(args.parameters);
|
|
22627
|
+
const paused = parseOptionalTimeoutPaused(args.paused);
|
|
22628
|
+
if (dueAt !== undefined) {
|
|
22629
|
+
patch.dueAt = dueAt;
|
|
22630
|
+
}
|
|
22631
|
+
if (extendByMs !== undefined) {
|
|
22632
|
+
patch.extendByMs = extendByMs;
|
|
22633
|
+
}
|
|
22634
|
+
if (patch.dueAt !== undefined && patch.extendByMs !== undefined) {
|
|
22635
|
+
throw createTimeoutToolArgsError('Timeout update cannot include both `dueAt` and `extendByMs`.');
|
|
22636
|
+
}
|
|
22637
|
+
if (recurrenceIntervalMs !== undefined) {
|
|
22638
|
+
patch.recurrenceIntervalMs = recurrenceIntervalMs;
|
|
22639
|
+
}
|
|
22640
|
+
if (message !== undefined) {
|
|
22641
|
+
patch.message = message;
|
|
22642
|
+
}
|
|
22643
|
+
if (parameters !== undefined) {
|
|
22644
|
+
patch.parameters = parameters;
|
|
22645
|
+
}
|
|
22646
|
+
if (paused !== undefined) {
|
|
22647
|
+
patch.paused = paused;
|
|
22648
|
+
}
|
|
22649
|
+
return patch;
|
|
22650
|
+
}
|
|
22651
|
+
/**
|
|
22652
|
+
* Determines whether the patch contains fields that are only supported for single-timeout updates.
|
|
22653
|
+
*
|
|
22654
|
+
* @private internal utility of USE TIMEOUT
|
|
22655
|
+
*/
|
|
22656
|
+
function hasSingleTimeoutOnlyPatchFields(patch) {
|
|
22657
|
+
return (patch.dueAt !== undefined ||
|
|
22658
|
+
patch.extendByMs !== undefined ||
|
|
22659
|
+
patch.recurrenceIntervalMs !== undefined ||
|
|
22660
|
+
patch.message !== undefined ||
|
|
22661
|
+
patch.parameters !== undefined);
|
|
22662
|
+
}
|
|
22663
|
+
/**
|
|
22664
|
+
* Parses bulk timeout update arguments.
|
|
22665
|
+
*
|
|
22666
|
+
* @private internal utility of USE TIMEOUT
|
|
22667
|
+
*/
|
|
22668
|
+
function parseBulkTimeoutUpdateArgs(patch) {
|
|
22669
|
+
if (patch.paused === undefined) {
|
|
22670
|
+
throw createTimeoutToolArgsError('Bulk timeout update with `allActive: true` requires `paused` to be explicitly set.');
|
|
22671
|
+
}
|
|
22672
|
+
if (hasSingleTimeoutOnlyPatchFields(patch)) {
|
|
22673
|
+
throw createTimeoutToolArgsError('Bulk timeout update only supports the `paused` field.');
|
|
22674
|
+
}
|
|
22675
|
+
return {
|
|
22676
|
+
allActive: true,
|
|
22677
|
+
paused: patch.paused,
|
|
22678
|
+
};
|
|
22679
|
+
}
|
|
22680
|
+
/**
|
|
22681
|
+
* Parses single-timeout update arguments.
|
|
22682
|
+
*
|
|
22683
|
+
* @private internal utility of USE TIMEOUT
|
|
22684
|
+
*/
|
|
22685
|
+
function parseSingleTimeoutUpdateArgs(timeoutId, patch) {
|
|
22686
|
+
if (!timeoutId) {
|
|
22687
|
+
throw createTimeoutToolArgsError('Timeout `timeoutId` is required for single-timeout updates.');
|
|
22688
|
+
}
|
|
22689
|
+
if (Object.keys(patch).length === 0) {
|
|
22690
|
+
throw createTimeoutToolArgsError('Timeout update must include at least one editable field.');
|
|
22691
|
+
}
|
|
22692
|
+
return {
|
|
22693
|
+
timeoutId,
|
|
22694
|
+
patch,
|
|
22695
|
+
};
|
|
22696
|
+
}
|
|
22481
22697
|
/**
|
|
22482
22698
|
* Parses and validates `USE TIMEOUT` tool arguments.
|
|
22483
22699
|
*
|
|
@@ -22504,22 +22720,14 @@ const parseTimeoutToolArgs = {
|
|
|
22504
22720
|
* Parses `cancel_timeout` input.
|
|
22505
22721
|
*/
|
|
22506
22722
|
cancel(args) {
|
|
22507
|
-
const
|
|
22508
|
-
|
|
22509
|
-
|
|
22510
|
-
|
|
22511
|
-
|
|
22512
|
-
`));
|
|
22513
|
-
}
|
|
22514
|
-
if (allActive) {
|
|
22723
|
+
const target = parseTimeoutTargetSelection(args, {
|
|
22724
|
+
bothMessage: 'Timeout cancellation must target either one `timeoutId` or `allActive: true`, not both.',
|
|
22725
|
+
missingMessage: 'Timeout `timeoutId` is required unless you pass `allActive: true`.',
|
|
22726
|
+
});
|
|
22727
|
+
if (target.allActive) {
|
|
22515
22728
|
return { allActive: true };
|
|
22516
22729
|
}
|
|
22517
|
-
|
|
22518
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22519
|
-
Timeout \`timeoutId\` is required unless you pass \`allActive: true\`.
|
|
22520
|
-
`));
|
|
22521
|
-
}
|
|
22522
|
-
return { timeoutId };
|
|
22730
|
+
return { timeoutId: target.timeoutId };
|
|
22523
22731
|
},
|
|
22524
22732
|
/**
|
|
22525
22733
|
* Parses `list_timeouts` input.
|
|
@@ -22550,106 +22758,14 @@ const parseTimeoutToolArgs = {
|
|
|
22550
22758
|
* Parses `update_timeout` input.
|
|
22551
22759
|
*/
|
|
22552
22760
|
update(args) {
|
|
22553
|
-
const
|
|
22554
|
-
|
|
22555
|
-
|
|
22556
|
-
|
|
22557
|
-
|
|
22558
|
-
|
|
22559
|
-
|
|
22560
|
-
|
|
22561
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22562
|
-
Timeout update requires one \`timeoutId\` or \`allActive: true\`.
|
|
22563
|
-
`));
|
|
22564
|
-
}
|
|
22565
|
-
const patch = {};
|
|
22566
|
-
if (typeof args.dueAt === 'string' && args.dueAt.trim().length > 0) {
|
|
22567
|
-
const normalizedDueAt = args.dueAt.trim();
|
|
22568
|
-
const dueAtTimestamp = Date.parse(normalizedDueAt);
|
|
22569
|
-
if (!Number.isFinite(dueAtTimestamp)) {
|
|
22570
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22571
|
-
Timeout \`dueAt\` must be one valid ISO timestamp.
|
|
22572
|
-
`));
|
|
22573
|
-
}
|
|
22574
|
-
patch.dueAt = new Date(dueAtTimestamp).toISOString();
|
|
22575
|
-
}
|
|
22576
|
-
if (typeof args.extendByMs === 'number') {
|
|
22577
|
-
if (!Number.isFinite(args.extendByMs) || args.extendByMs <= 0) {
|
|
22578
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22579
|
-
Timeout \`extendByMs\` must be a positive number of milliseconds.
|
|
22580
|
-
`));
|
|
22581
|
-
}
|
|
22582
|
-
patch.extendByMs = Math.floor(args.extendByMs);
|
|
22583
|
-
}
|
|
22584
|
-
if (patch.dueAt !== undefined && patch.extendByMs !== undefined) {
|
|
22585
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22586
|
-
Timeout update cannot include both \`dueAt\` and \`extendByMs\`.
|
|
22587
|
-
`));
|
|
22588
|
-
}
|
|
22589
|
-
if (args.recurrenceIntervalMs === null) {
|
|
22590
|
-
patch.recurrenceIntervalMs = null;
|
|
22591
|
-
}
|
|
22592
|
-
else if (typeof args.recurrenceIntervalMs === 'number') {
|
|
22593
|
-
if (!Number.isFinite(args.recurrenceIntervalMs) || args.recurrenceIntervalMs <= 0) {
|
|
22594
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22595
|
-
Timeout \`recurrenceIntervalMs\` must be a positive number of milliseconds or \`null\`.
|
|
22596
|
-
`));
|
|
22597
|
-
}
|
|
22598
|
-
patch.recurrenceIntervalMs = Math.floor(args.recurrenceIntervalMs);
|
|
22599
|
-
}
|
|
22600
|
-
if (args.message === null) {
|
|
22601
|
-
patch.message = null;
|
|
22602
|
-
}
|
|
22603
|
-
else if (typeof args.message === 'string') {
|
|
22604
|
-
const normalizedMessage = args.message.trim();
|
|
22605
|
-
patch.message = normalizedMessage.length > 0 ? normalizedMessage : null;
|
|
22606
|
-
}
|
|
22607
|
-
if (args.parameters !== undefined) {
|
|
22608
|
-
if (!args.parameters || typeof args.parameters !== 'object' || Array.isArray(args.parameters)) {
|
|
22609
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22610
|
-
Timeout \`parameters\` must be one JSON object.
|
|
22611
|
-
`));
|
|
22612
|
-
}
|
|
22613
|
-
patch.parameters = args.parameters;
|
|
22614
|
-
}
|
|
22615
|
-
if (typeof args.paused === 'boolean') {
|
|
22616
|
-
patch.paused = args.paused;
|
|
22617
|
-
}
|
|
22618
|
-
if (allActive) {
|
|
22619
|
-
if (patch.paused === undefined) {
|
|
22620
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22621
|
-
Bulk timeout update with \`allActive: true\` requires \`paused\` to be explicitly set.
|
|
22622
|
-
`));
|
|
22623
|
-
}
|
|
22624
|
-
const hasSingleOnlyPatch = patch.dueAt !== undefined ||
|
|
22625
|
-
patch.extendByMs !== undefined ||
|
|
22626
|
-
patch.recurrenceIntervalMs !== undefined ||
|
|
22627
|
-
patch.message !== undefined ||
|
|
22628
|
-
patch.parameters !== undefined;
|
|
22629
|
-
if (hasSingleOnlyPatch) {
|
|
22630
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22631
|
-
Bulk timeout update only supports the \`paused\` field.
|
|
22632
|
-
`));
|
|
22633
|
-
}
|
|
22634
|
-
return {
|
|
22635
|
-
allActive: true,
|
|
22636
|
-
paused: patch.paused,
|
|
22637
|
-
};
|
|
22638
|
-
}
|
|
22639
|
-
if (!timeoutId) {
|
|
22640
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22641
|
-
Timeout \`timeoutId\` is required for single-timeout updates.
|
|
22642
|
-
`));
|
|
22643
|
-
}
|
|
22644
|
-
if (Object.keys(patch).length === 0) {
|
|
22645
|
-
throw new PipelineExecutionError(spaceTrim$1(`
|
|
22646
|
-
Timeout update must include at least one editable field.
|
|
22647
|
-
`));
|
|
22648
|
-
}
|
|
22649
|
-
return {
|
|
22650
|
-
timeoutId,
|
|
22651
|
-
patch,
|
|
22652
|
-
};
|
|
22761
|
+
const target = parseTimeoutTargetSelection(args, {
|
|
22762
|
+
bothMessage: 'Timeout update must target either one `timeoutId` or `allActive: true`, not both.',
|
|
22763
|
+
missingMessage: 'Timeout update requires one `timeoutId` or `allActive: true`.',
|
|
22764
|
+
});
|
|
22765
|
+
const patch = parseTimeoutUpdatePatch(args);
|
|
22766
|
+
return target.allActive
|
|
22767
|
+
? parseBulkTimeoutUpdateArgs(patch)
|
|
22768
|
+
: parseSingleTimeoutUpdateArgs(target.timeoutId, patch);
|
|
22653
22769
|
},
|
|
22654
22770
|
};
|
|
22655
22771
|
|
|
@@ -27391,6 +27507,20 @@ class Book {
|
|
|
27391
27507
|
isComplete: true,
|
|
27392
27508
|
}));
|
|
27393
27509
|
}
|
|
27510
|
+
/**
|
|
27511
|
+
* Gets the newest parsed chat message written by the given sender.
|
|
27512
|
+
*
|
|
27513
|
+
* @public exported from `@promptbook/core`
|
|
27514
|
+
*/
|
|
27515
|
+
getLatestMessageBySender(sender) {
|
|
27516
|
+
const normalizedSender = normalizeChatMessageSender(sender);
|
|
27517
|
+
for (const message of [...this.getMessages()].reverse()) {
|
|
27518
|
+
if (message.sender === normalizedSender) {
|
|
27519
|
+
return message;
|
|
27520
|
+
}
|
|
27521
|
+
}
|
|
27522
|
+
return null;
|
|
27523
|
+
}
|
|
27394
27524
|
}
|
|
27395
27525
|
/**
|
|
27396
27526
|
* Normalizes one raw Book source to LF line endings.
|
|
@@ -28218,118 +28348,75 @@ function isCommitmentSupported(type) {
|
|
|
28218
28348
|
}
|
|
28219
28349
|
|
|
28220
28350
|
/**
|
|
28221
|
-
*
|
|
28222
|
-
*
|
|
28223
|
-
* There is is distinction between task types and section types
|
|
28224
|
-
* - Every section in markdown has its SectionType
|
|
28225
|
-
* - Some sections are tasks but other can be non-task sections
|
|
28226
|
-
*
|
|
28227
|
-
* @public exported from `@promptbook/core`
|
|
28228
|
-
*/
|
|
28229
|
-
const TaskTypes = [
|
|
28230
|
-
'PROMPT',
|
|
28231
|
-
'SIMPLE',
|
|
28232
|
-
'SCRIPT',
|
|
28233
|
-
'DIALOG',
|
|
28234
|
-
// <- [🅱]
|
|
28235
|
-
];
|
|
28236
|
-
|
|
28237
|
-
/**
|
|
28238
|
-
* All available sections which are not tasks
|
|
28239
|
-
*
|
|
28240
|
-
* @public exported from `@promptbook/core`
|
|
28241
|
-
*/
|
|
28242
|
-
const NonTaskSectionTypes = ['EXAMPLE', 'KNOWLEDGE', 'INSTRUMENT', 'ACTION'];
|
|
28243
|
-
/**
|
|
28244
|
-
* All available section types
|
|
28245
|
-
*
|
|
28246
|
-
* There is is distinction between task types and section types
|
|
28247
|
-
* - Every section in markdown has its SectionType
|
|
28248
|
-
* - Some sections are tasks but other can be non-task sections
|
|
28351
|
+
* Parses the boilerplate command
|
|
28249
28352
|
*
|
|
28250
|
-
*
|
|
28251
|
-
*/
|
|
28252
|
-
const SectionTypes = [
|
|
28253
|
-
...TaskTypes.map((TaskType) => `${TaskType}_TASK`),
|
|
28254
|
-
...NonTaskSectionTypes,
|
|
28255
|
-
];
|
|
28256
|
-
|
|
28257
|
-
/**
|
|
28258
|
-
* Parses the knowledge command
|
|
28353
|
+
* Note: @@ This command is used as boilerplate for new commands - it should NOT be used in any `.book` file
|
|
28259
28354
|
*
|
|
28260
28355
|
* @see `documentationUrl` for more details
|
|
28261
28356
|
*
|
|
28262
|
-
* @
|
|
28357
|
+
* @private within the commands folder
|
|
28263
28358
|
*/
|
|
28264
|
-
const
|
|
28359
|
+
const boilerplateCommandParser = {
|
|
28265
28360
|
/**
|
|
28266
28361
|
* Name of the command
|
|
28267
28362
|
*/
|
|
28268
|
-
name: '
|
|
28363
|
+
name: 'BOILERPLATE',
|
|
28364
|
+
/**
|
|
28365
|
+
* Aliases for the BOILERPLATE command
|
|
28366
|
+
*/
|
|
28367
|
+
aliasNames: ['BP'],
|
|
28269
28368
|
/**
|
|
28270
28369
|
* BOILERPLATE command can be used in:
|
|
28271
28370
|
*/
|
|
28272
28371
|
isUsedInPipelineHead: true,
|
|
28273
|
-
isUsedInPipelineTask:
|
|
28372
|
+
isUsedInPipelineTask: true,
|
|
28274
28373
|
/**
|
|
28275
|
-
* Description of the
|
|
28374
|
+
* Description of the BOILERPLATE command
|
|
28276
28375
|
*/
|
|
28277
|
-
description:
|
|
28376
|
+
description: `@@`,
|
|
28278
28377
|
/**
|
|
28279
28378
|
* Link to documentation
|
|
28280
28379
|
*/
|
|
28281
|
-
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions
|
|
28380
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
28282
28381
|
/**
|
|
28283
|
-
* Example usages of the
|
|
28382
|
+
* Example usages of the BOILERPLATE command
|
|
28284
28383
|
*/
|
|
28285
|
-
examples: [
|
|
28286
|
-
'KNOWLEDGE https://www.pavolhejny.com/',
|
|
28287
|
-
'KNOWLEDGE ./hejny-cv.txt',
|
|
28288
|
-
'KNOWLEDGE ./hejny-cv.md',
|
|
28289
|
-
'KNOWLEDGE ./hejny-cv.pdf',
|
|
28290
|
-
'KNOWLEDGE ./hejny-cv.docx',
|
|
28291
|
-
// <- TODO: [😿] Allow ONLY files scoped in the (sub)directory NOT ../ and test it
|
|
28292
|
-
],
|
|
28384
|
+
examples: ['BOILERPLATE foo', 'BOILERPLATE bar', 'BP foo', 'BP bar'],
|
|
28293
28385
|
/**
|
|
28294
|
-
* Parses the
|
|
28386
|
+
* Parses the BOILERPLATE command
|
|
28295
28387
|
*/
|
|
28296
28388
|
parse(input) {
|
|
28297
28389
|
const { args } = input;
|
|
28298
|
-
|
|
28299
|
-
|
|
28300
|
-
throw new ParseError(`Source is not defined`);
|
|
28390
|
+
if (args.length !== 1) {
|
|
28391
|
+
throw new ParseError(`BOILERPLATE command requires exactly one argument`);
|
|
28301
28392
|
}
|
|
28302
|
-
|
|
28303
|
-
if (
|
|
28304
|
-
throw new ParseError(`
|
|
28305
|
-
}
|
|
28306
|
-
if (!(isValidFilePath(knowledgeSourceContent) || isValidUrl(knowledgeSourceContent))) {
|
|
28307
|
-
throw new ParseError(`Source not valid`);
|
|
28308
|
-
}
|
|
28309
|
-
if (knowledgeSourceContent.startsWith('../') ||
|
|
28310
|
-
knowledgeSourceContent.startsWith('/') ||
|
|
28311
|
-
/^[A-Z]:[\\/]+/i.test(knowledgeSourceContent)) {
|
|
28312
|
-
throw new ParseError(`Source cannot be outside of the .book.md folder`);
|
|
28393
|
+
const value = args[0].toLowerCase();
|
|
28394
|
+
if (value.includes('brr')) {
|
|
28395
|
+
throw new ParseError(`BOILERPLATE value can not contain brr`);
|
|
28313
28396
|
}
|
|
28314
28397
|
return {
|
|
28315
|
-
type: '
|
|
28316
|
-
|
|
28398
|
+
type: 'BOILERPLATE',
|
|
28399
|
+
value,
|
|
28317
28400
|
};
|
|
28318
28401
|
},
|
|
28319
28402
|
/**
|
|
28320
|
-
* Apply the
|
|
28403
|
+
* Apply the BOILERPLATE command to the `pipelineJson`
|
|
28321
28404
|
*
|
|
28322
28405
|
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
28323
28406
|
*/
|
|
28324
28407
|
$applyToPipelineJson(command, $pipelineJson) {
|
|
28325
|
-
|
|
28326
|
-
$pipelineJson.knowledgeSources.push({
|
|
28327
|
-
name: knowledgeSourceContentToName(knowledgeSourceContent),
|
|
28328
|
-
knowledgeSourceContent,
|
|
28329
|
-
});
|
|
28408
|
+
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28330
28409
|
},
|
|
28331
28410
|
/**
|
|
28332
|
-
*
|
|
28411
|
+
* Apply the BOILERPLATE command to the `pipelineJson`
|
|
28412
|
+
*
|
|
28413
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
28414
|
+
*/
|
|
28415
|
+
$applyToTaskJson(command, $taskJson, $pipelineJson) {
|
|
28416
|
+
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28417
|
+
},
|
|
28418
|
+
/**
|
|
28419
|
+
* Converts the BOILERPLATE command back to string
|
|
28333
28420
|
*
|
|
28334
28421
|
* Note: This is used in `pipelineJsonToString` utility
|
|
28335
28422
|
*/
|
|
@@ -28337,179 +28424,84 @@ const knowledgeCommandParser = {
|
|
|
28337
28424
|
return `---`; // <- TODO: [🛋] Implement
|
|
28338
28425
|
},
|
|
28339
28426
|
/**
|
|
28340
|
-
* Reads the
|
|
28427
|
+
* Reads the BOILERPLATE command from the `PipelineJson`
|
|
28341
28428
|
*
|
|
28342
28429
|
* Note: This is used in `pipelineJsonToString` utility
|
|
28343
28430
|
*/
|
|
28344
28431
|
takeFromPipelineJson(pipelineJson) {
|
|
28345
|
-
throw new
|
|
28432
|
+
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28433
|
+
},
|
|
28434
|
+
/**
|
|
28435
|
+
* Reads the BOILERPLATE command from the `TaskJson`
|
|
28436
|
+
*
|
|
28437
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
28438
|
+
*/
|
|
28439
|
+
takeFromTaskJson($taskJson) {
|
|
28440
|
+
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28346
28441
|
},
|
|
28347
28442
|
};
|
|
28348
|
-
// Note: [⛱] There are two types of KNOWLEDGE commands *...(read more in [⛱])*
|
|
28349
28443
|
|
|
28350
28444
|
/**
|
|
28351
|
-
* Parses the
|
|
28445
|
+
* Parses the BOOK_VERSION command
|
|
28352
28446
|
*
|
|
28353
28447
|
* @see `documentationUrl` for more details
|
|
28354
28448
|
*
|
|
28355
28449
|
* @public exported from `@promptbook/editable`
|
|
28356
28450
|
*/
|
|
28357
|
-
const
|
|
28451
|
+
const bookVersionCommandParser = {
|
|
28358
28452
|
/**
|
|
28359
28453
|
* Name of the command
|
|
28360
28454
|
*/
|
|
28361
|
-
name: '
|
|
28362
|
-
|
|
28363
|
-
* Aliases for the SECTION command
|
|
28364
|
-
*/
|
|
28365
|
-
aliasNames: [
|
|
28366
|
-
'PROMPT',
|
|
28367
|
-
'SIMPLE',
|
|
28368
|
-
'SCRIPT',
|
|
28369
|
-
'DIALOG',
|
|
28370
|
-
'SAMPLE',
|
|
28371
|
-
'EXAMPLE',
|
|
28372
|
-
'KNOWLEDGE',
|
|
28373
|
-
'INSTRUMENT',
|
|
28374
|
-
'ACTION', // <- Note: [⛱]
|
|
28375
|
-
],
|
|
28376
|
-
/**
|
|
28377
|
-
* Aliases for the SECTION command
|
|
28378
|
-
*/
|
|
28379
|
-
deprecatedNames: ['TEMPLATE', 'BLOCK', 'EXECUTE'],
|
|
28455
|
+
name: 'BOOK_VERSION',
|
|
28456
|
+
aliasNames: ['PTBK_VERSION', 'PROMPTBOOK_VERSION', 'BOOK'],
|
|
28380
28457
|
/**
|
|
28381
28458
|
* BOILERPLATE command can be used in:
|
|
28382
28459
|
*/
|
|
28383
|
-
isUsedInPipelineHead:
|
|
28384
|
-
isUsedInPipelineTask:
|
|
28460
|
+
isUsedInPipelineHead: true,
|
|
28461
|
+
isUsedInPipelineTask: false,
|
|
28385
28462
|
/**
|
|
28386
|
-
* Description of the
|
|
28463
|
+
* Description of the BOOK_VERSION command
|
|
28387
28464
|
*/
|
|
28388
|
-
description: `
|
|
28465
|
+
description: `Which version of the Book language is the .book.md using`,
|
|
28389
28466
|
/**
|
|
28390
28467
|
* Link to documentation
|
|
28391
28468
|
*/
|
|
28392
|
-
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/
|
|
28469
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/69',
|
|
28393
28470
|
/**
|
|
28394
|
-
* Example usages of the
|
|
28471
|
+
* Example usages of the BOOK_VERSION command
|
|
28395
28472
|
*/
|
|
28396
|
-
examples: [
|
|
28397
|
-
// Short form:
|
|
28398
|
-
'PROMPT',
|
|
28399
|
-
'SIMPLE',
|
|
28400
|
-
'SCRIPT',
|
|
28401
|
-
'DIALOG',
|
|
28402
|
-
// <- [🅱]
|
|
28403
|
-
'EXAMPLE',
|
|
28404
|
-
'KNOWLEDGE',
|
|
28405
|
-
'INSTRUMENT',
|
|
28406
|
-
'ACTION',
|
|
28407
|
-
// -----------------
|
|
28408
|
-
// Recommended (reversed) form:
|
|
28409
|
-
'PROMPT SECTION',
|
|
28410
|
-
'SIMPLE SECTION',
|
|
28411
|
-
'SCRIPT SECTION',
|
|
28412
|
-
'DIALOG SECTION',
|
|
28413
|
-
// <- [🅱]
|
|
28414
|
-
'EXAMPLE SECTION',
|
|
28415
|
-
'KNOWLEDGE SECTION',
|
|
28416
|
-
'INSTRUMENT SECTION',
|
|
28417
|
-
'ACTION SECTION',
|
|
28418
|
-
// -----------------
|
|
28419
|
-
// Standard form:
|
|
28420
|
-
'SECTION PROMPT',
|
|
28421
|
-
'SECTION SIMPLE',
|
|
28422
|
-
'SECTION SCRIPT',
|
|
28423
|
-
'SECTION DIALOG',
|
|
28424
|
-
// <- [🅱]
|
|
28425
|
-
'SECTION EXAMPLE',
|
|
28426
|
-
'SECTION KNOWLEDGE',
|
|
28427
|
-
'SECTION INSTRUMENT',
|
|
28428
|
-
'SECTION ACTION',
|
|
28429
|
-
],
|
|
28430
|
-
// TODO: [♓️] order: -10 /* <- Note: Putting before other commands */
|
|
28473
|
+
examples: [`BOOK VERSION ${BOOK_LANGUAGE_VERSION}`, `BOOK ${BOOK_LANGUAGE_VERSION}`],
|
|
28431
28474
|
/**
|
|
28432
|
-
* Parses the
|
|
28475
|
+
* Parses the BOOK_VERSION command
|
|
28433
28476
|
*/
|
|
28434
28477
|
parse(input) {
|
|
28435
|
-
|
|
28436
|
-
|
|
28437
|
-
|
|
28438
|
-
|
|
28439
|
-
|
|
28440
|
-
if (
|
|
28441
|
-
throw new ParseError(
|
|
28442
|
-
|
|
28443
|
-
|
|
28444
|
-
|
|
28445
|
-
${block(SectionTypes.join(', '))}
|
|
28446
|
-
`));
|
|
28478
|
+
const { args } = input;
|
|
28479
|
+
const bookVersion = args.pop();
|
|
28480
|
+
if (bookVersion === undefined) {
|
|
28481
|
+
throw new ParseError(`Version is required`);
|
|
28482
|
+
}
|
|
28483
|
+
if (!isValidPromptbookVersion(bookVersion)) {
|
|
28484
|
+
throw new ParseError(`Invalid Promptbook version "${bookVersion}"`);
|
|
28485
|
+
}
|
|
28486
|
+
if (args.length > 0 && !(((args.length === 1 && args[0]) || '').toUpperCase() === 'VERSION')) {
|
|
28487
|
+
throw new ParseError(`Can not have more than one Promptbook version`);
|
|
28447
28488
|
}
|
|
28448
|
-
const taskType = taskTypes[0];
|
|
28449
28489
|
return {
|
|
28450
|
-
type: '
|
|
28451
|
-
|
|
28490
|
+
type: 'BOOK_VERSION',
|
|
28491
|
+
bookVersion: bookVersion,
|
|
28452
28492
|
};
|
|
28453
28493
|
},
|
|
28454
28494
|
/**
|
|
28455
|
-
* Apply the
|
|
28495
|
+
* Apply the BOOK_VERSION command to the `pipelineJson`
|
|
28456
28496
|
*
|
|
28457
|
-
* Note: `$` is used to indicate that this function mutates given `
|
|
28497
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
28458
28498
|
*/
|
|
28459
|
-
$
|
|
28460
|
-
if
|
|
28461
|
-
|
|
28462
|
-
Section type is already defined in the section.
|
|
28463
|
-
It can be defined only once.
|
|
28464
|
-
`));
|
|
28465
|
-
}
|
|
28466
|
-
$taskJson.isSectionTypeSet = true;
|
|
28467
|
-
// TODO: [🍧][💩] Rearrange better - but at bottom and unwrap from function
|
|
28468
|
-
const expectResultingParameterName = () => {
|
|
28469
|
-
if ($taskJson.resultingParameterName) {
|
|
28470
|
-
return;
|
|
28471
|
-
}
|
|
28472
|
-
throw new ParseError(`Task section and example section must end with return statement -> {parameterName}`);
|
|
28473
|
-
};
|
|
28474
|
-
if ($taskJson.content === undefined) {
|
|
28475
|
-
throw new UnexpectedError(`Content is missing in the taskJson - probably commands are applied in wrong order`);
|
|
28476
|
-
}
|
|
28477
|
-
if (command.taskType === 'EXAMPLE') {
|
|
28478
|
-
expectResultingParameterName();
|
|
28479
|
-
const parameter = $pipelineJson.parameters.find((param) => param.name === $taskJson.resultingParameterName);
|
|
28480
|
-
if (parameter === undefined) {
|
|
28481
|
-
// TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
|
|
28482
|
-
throw new ParseError(`Parameter \`{${$taskJson.resultingParameterName}}\` is not defined so can not define example value of it`);
|
|
28483
|
-
}
|
|
28484
|
-
parameter.exampleValues = parameter.exampleValues || [];
|
|
28485
|
-
parameter.exampleValues.push($taskJson.content);
|
|
28486
|
-
$taskJson.isTask = false;
|
|
28487
|
-
return;
|
|
28488
|
-
}
|
|
28489
|
-
if (command.taskType === 'KNOWLEDGE') {
|
|
28490
|
-
knowledgeCommandParser.$applyToPipelineJson({
|
|
28491
|
-
type: 'KNOWLEDGE',
|
|
28492
|
-
knowledgeSourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
|
|
28493
|
-
}, $pipelineJson);
|
|
28494
|
-
$taskJson.isTask = false;
|
|
28495
|
-
return;
|
|
28496
|
-
}
|
|
28497
|
-
if (command.taskType === 'ACTION') {
|
|
28498
|
-
console.error(new NotYetImplementedError('Actions are not implemented yet'));
|
|
28499
|
-
$taskJson.isTask = false;
|
|
28500
|
-
return;
|
|
28501
|
-
}
|
|
28502
|
-
if (command.taskType === 'INSTRUMENT') {
|
|
28503
|
-
console.error(new NotYetImplementedError('Instruments are not implemented yet'));
|
|
28504
|
-
$taskJson.isTask = false;
|
|
28505
|
-
return;
|
|
28506
|
-
}
|
|
28507
|
-
expectResultingParameterName();
|
|
28508
|
-
$taskJson.taskType = command.taskType;
|
|
28509
|
-
$taskJson.isTask = true;
|
|
28499
|
+
$applyToPipelineJson(command, $pipelineJson) {
|
|
28500
|
+
// TODO: Warn if the version is overridden
|
|
28501
|
+
$pipelineJson.bookVersion = command.bookVersion;
|
|
28510
28502
|
},
|
|
28511
28503
|
/**
|
|
28512
|
-
* Converts the
|
|
28504
|
+
* Converts the BOOK_VERSION command back to string
|
|
28513
28505
|
*
|
|
28514
28506
|
* Note: This is used in `pipelineJsonToString` utility
|
|
28515
28507
|
*/
|
|
@@ -28517,218 +28509,36 @@ const sectionCommandParser = {
|
|
|
28517
28509
|
return `---`; // <- TODO: [🛋] Implement
|
|
28518
28510
|
},
|
|
28519
28511
|
/**
|
|
28520
|
-
* Reads the
|
|
28512
|
+
* Reads the BOOK_VERSION command from the `PipelineJson`
|
|
28521
28513
|
*
|
|
28522
28514
|
* Note: This is used in `pipelineJsonToString` utility
|
|
28523
28515
|
*/
|
|
28524
|
-
|
|
28516
|
+
takeFromPipelineJson(pipelineJson) {
|
|
28525
28517
|
throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
|
|
28526
28518
|
},
|
|
28527
28519
|
};
|
|
28520
|
+
|
|
28528
28521
|
/**
|
|
28529
|
-
*
|
|
28530
|
-
* 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
|
|
28531
|
-
* - KNOWLEDGE Look at https://en.wikipedia.org/wiki/Artificial_intelligence
|
|
28532
|
-
* 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
|
|
28533
|
-
* - KNOWLEDGE SECTION
|
|
28522
|
+
* Units of text measurement
|
|
28534
28523
|
*
|
|
28535
|
-
*
|
|
28536
|
-
*
|
|
28537
|
-
*
|
|
28524
|
+
* @see https://github.com/webgptorg/promptbook/discussions/30
|
|
28525
|
+
*
|
|
28526
|
+
* @public exported from `@promptbook/core`
|
|
28538
28527
|
*/
|
|
28528
|
+
const EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'LINES', 'PARAGRAPHS', 'PAGES'];
|
|
28529
|
+
// TODO: [💝] Unite object for expecting amount and format - remove format
|
|
28539
28530
|
|
|
28540
28531
|
/**
|
|
28541
|
-
*
|
|
28532
|
+
* Function parseNumber will parse number from string
|
|
28542
28533
|
*
|
|
28543
|
-
* Note:
|
|
28534
|
+
* Note: [🔂] This function is idempotent.
|
|
28535
|
+
* Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
|
|
28536
|
+
* Note: it also works only with decimal numbers
|
|
28544
28537
|
*
|
|
28545
|
-
* @
|
|
28538
|
+
* @returns parsed number
|
|
28539
|
+
* @throws {ParseError} if the value is not a number
|
|
28546
28540
|
*
|
|
28547
|
-
* @
|
|
28548
|
-
*/
|
|
28549
|
-
const boilerplateCommandParser = {
|
|
28550
|
-
/**
|
|
28551
|
-
* Name of the command
|
|
28552
|
-
*/
|
|
28553
|
-
name: 'BOILERPLATE',
|
|
28554
|
-
/**
|
|
28555
|
-
* Aliases for the BOILERPLATE command
|
|
28556
|
-
*/
|
|
28557
|
-
aliasNames: ['BP'],
|
|
28558
|
-
/**
|
|
28559
|
-
* BOILERPLATE command can be used in:
|
|
28560
|
-
*/
|
|
28561
|
-
isUsedInPipelineHead: true,
|
|
28562
|
-
isUsedInPipelineTask: true,
|
|
28563
|
-
/**
|
|
28564
|
-
* Description of the BOILERPLATE command
|
|
28565
|
-
*/
|
|
28566
|
-
description: `@@`,
|
|
28567
|
-
/**
|
|
28568
|
-
* Link to documentation
|
|
28569
|
-
*/
|
|
28570
|
-
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
|
|
28571
|
-
/**
|
|
28572
|
-
* Example usages of the BOILERPLATE command
|
|
28573
|
-
*/
|
|
28574
|
-
examples: ['BOILERPLATE foo', 'BOILERPLATE bar', 'BP foo', 'BP bar'],
|
|
28575
|
-
/**
|
|
28576
|
-
* Parses the BOILERPLATE command
|
|
28577
|
-
*/
|
|
28578
|
-
parse(input) {
|
|
28579
|
-
const { args } = input;
|
|
28580
|
-
if (args.length !== 1) {
|
|
28581
|
-
throw new ParseError(`BOILERPLATE command requires exactly one argument`);
|
|
28582
|
-
}
|
|
28583
|
-
const value = args[0].toLowerCase();
|
|
28584
|
-
if (value.includes('brr')) {
|
|
28585
|
-
throw new ParseError(`BOILERPLATE value can not contain brr`);
|
|
28586
|
-
}
|
|
28587
|
-
return {
|
|
28588
|
-
type: 'BOILERPLATE',
|
|
28589
|
-
value,
|
|
28590
|
-
};
|
|
28591
|
-
},
|
|
28592
|
-
/**
|
|
28593
|
-
* Apply the BOILERPLATE command to the `pipelineJson`
|
|
28594
|
-
*
|
|
28595
|
-
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
28596
|
-
*/
|
|
28597
|
-
$applyToPipelineJson(command, $pipelineJson) {
|
|
28598
|
-
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28599
|
-
},
|
|
28600
|
-
/**
|
|
28601
|
-
* Apply the BOILERPLATE command to the `pipelineJson`
|
|
28602
|
-
*
|
|
28603
|
-
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
28604
|
-
*/
|
|
28605
|
-
$applyToTaskJson(command, $taskJson, $pipelineJson) {
|
|
28606
|
-
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28607
|
-
},
|
|
28608
|
-
/**
|
|
28609
|
-
* Converts the BOILERPLATE command back to string
|
|
28610
|
-
*
|
|
28611
|
-
* Note: This is used in `pipelineJsonToString` utility
|
|
28612
|
-
*/
|
|
28613
|
-
stringify(command) {
|
|
28614
|
-
return `---`; // <- TODO: [🛋] Implement
|
|
28615
|
-
},
|
|
28616
|
-
/**
|
|
28617
|
-
* Reads the BOILERPLATE command from the `PipelineJson`
|
|
28618
|
-
*
|
|
28619
|
-
* Note: This is used in `pipelineJsonToString` utility
|
|
28620
|
-
*/
|
|
28621
|
-
takeFromPipelineJson(pipelineJson) {
|
|
28622
|
-
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28623
|
-
},
|
|
28624
|
-
/**
|
|
28625
|
-
* Reads the BOILERPLATE command from the `TaskJson`
|
|
28626
|
-
*
|
|
28627
|
-
* Note: This is used in `pipelineJsonToString` utility
|
|
28628
|
-
*/
|
|
28629
|
-
takeFromTaskJson($taskJson) {
|
|
28630
|
-
throw new ParseError(`BOILERPLATE command is only for testing purposes and should not be used in the .book.md file`);
|
|
28631
|
-
},
|
|
28632
|
-
};
|
|
28633
|
-
|
|
28634
|
-
/**
|
|
28635
|
-
* Parses the BOOK_VERSION command
|
|
28636
|
-
*
|
|
28637
|
-
* @see `documentationUrl` for more details
|
|
28638
|
-
*
|
|
28639
|
-
* @public exported from `@promptbook/editable`
|
|
28640
|
-
*/
|
|
28641
|
-
const bookVersionCommandParser = {
|
|
28642
|
-
/**
|
|
28643
|
-
* Name of the command
|
|
28644
|
-
*/
|
|
28645
|
-
name: 'BOOK_VERSION',
|
|
28646
|
-
aliasNames: ['PTBK_VERSION', 'PROMPTBOOK_VERSION', 'BOOK'],
|
|
28647
|
-
/**
|
|
28648
|
-
* BOILERPLATE command can be used in:
|
|
28649
|
-
*/
|
|
28650
|
-
isUsedInPipelineHead: true,
|
|
28651
|
-
isUsedInPipelineTask: false,
|
|
28652
|
-
/**
|
|
28653
|
-
* Description of the BOOK_VERSION command
|
|
28654
|
-
*/
|
|
28655
|
-
description: `Which version of the Book language is the .book.md using`,
|
|
28656
|
-
/**
|
|
28657
|
-
* Link to documentation
|
|
28658
|
-
*/
|
|
28659
|
-
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/69',
|
|
28660
|
-
/**
|
|
28661
|
-
* Example usages of the BOOK_VERSION command
|
|
28662
|
-
*/
|
|
28663
|
-
examples: [`BOOK VERSION ${BOOK_LANGUAGE_VERSION}`, `BOOK ${BOOK_LANGUAGE_VERSION}`],
|
|
28664
|
-
/**
|
|
28665
|
-
* Parses the BOOK_VERSION command
|
|
28666
|
-
*/
|
|
28667
|
-
parse(input) {
|
|
28668
|
-
const { args } = input;
|
|
28669
|
-
const bookVersion = args.pop();
|
|
28670
|
-
if (bookVersion === undefined) {
|
|
28671
|
-
throw new ParseError(`Version is required`);
|
|
28672
|
-
}
|
|
28673
|
-
if (!isValidPromptbookVersion(bookVersion)) {
|
|
28674
|
-
throw new ParseError(`Invalid Promptbook version "${bookVersion}"`);
|
|
28675
|
-
}
|
|
28676
|
-
if (args.length > 0 && !(((args.length === 1 && args[0]) || '').toUpperCase() === 'VERSION')) {
|
|
28677
|
-
throw new ParseError(`Can not have more than one Promptbook version`);
|
|
28678
|
-
}
|
|
28679
|
-
return {
|
|
28680
|
-
type: 'BOOK_VERSION',
|
|
28681
|
-
bookVersion: bookVersion,
|
|
28682
|
-
};
|
|
28683
|
-
},
|
|
28684
|
-
/**
|
|
28685
|
-
* Apply the BOOK_VERSION command to the `pipelineJson`
|
|
28686
|
-
*
|
|
28687
|
-
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
28688
|
-
*/
|
|
28689
|
-
$applyToPipelineJson(command, $pipelineJson) {
|
|
28690
|
-
// TODO: Warn if the version is overridden
|
|
28691
|
-
$pipelineJson.bookVersion = command.bookVersion;
|
|
28692
|
-
},
|
|
28693
|
-
/**
|
|
28694
|
-
* Converts the BOOK_VERSION command back to string
|
|
28695
|
-
*
|
|
28696
|
-
* Note: This is used in `pipelineJsonToString` utility
|
|
28697
|
-
*/
|
|
28698
|
-
stringify(command) {
|
|
28699
|
-
return `---`; // <- TODO: [🛋] Implement
|
|
28700
|
-
},
|
|
28701
|
-
/**
|
|
28702
|
-
* Reads the BOOK_VERSION command from the `PipelineJson`
|
|
28703
|
-
*
|
|
28704
|
-
* Note: This is used in `pipelineJsonToString` utility
|
|
28705
|
-
*/
|
|
28706
|
-
takeFromPipelineJson(pipelineJson) {
|
|
28707
|
-
throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
|
|
28708
|
-
},
|
|
28709
|
-
};
|
|
28710
|
-
|
|
28711
|
-
/**
|
|
28712
|
-
* Units of text measurement
|
|
28713
|
-
*
|
|
28714
|
-
* @see https://github.com/webgptorg/promptbook/discussions/30
|
|
28715
|
-
*
|
|
28716
|
-
* @public exported from `@promptbook/core`
|
|
28717
|
-
*/
|
|
28718
|
-
const EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'LINES', 'PARAGRAPHS', 'PAGES'];
|
|
28719
|
-
// TODO: [💝] Unite object for expecting amount and format - remove format
|
|
28720
|
-
|
|
28721
|
-
/**
|
|
28722
|
-
* Function parseNumber will parse number from string
|
|
28723
|
-
*
|
|
28724
|
-
* Note: [🔂] This function is idempotent.
|
|
28725
|
-
* Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
|
|
28726
|
-
* Note: it also works only with decimal numbers
|
|
28727
|
-
*
|
|
28728
|
-
* @returns parsed number
|
|
28729
|
-
* @throws {ParseError} if the value is not a number
|
|
28730
|
-
*
|
|
28731
|
-
* @public exported from `@promptbook/utils`
|
|
28541
|
+
* @public exported from `@promptbook/utils`
|
|
28732
28542
|
*/
|
|
28733
28543
|
function parseNumber(value) {
|
|
28734
28544
|
if (value === null || value === undefined) {
|
|
@@ -29713,6 +29523,99 @@ const jokerCommandParser = {
|
|
|
29713
29523
|
},
|
|
29714
29524
|
};
|
|
29715
29525
|
|
|
29526
|
+
/**
|
|
29527
|
+
* Parses the knowledge command
|
|
29528
|
+
*
|
|
29529
|
+
* @see `documentationUrl` for more details
|
|
29530
|
+
*
|
|
29531
|
+
* @public exported from `@promptbook/editable`
|
|
29532
|
+
*/
|
|
29533
|
+
const knowledgeCommandParser = {
|
|
29534
|
+
/**
|
|
29535
|
+
* Name of the command
|
|
29536
|
+
*/
|
|
29537
|
+
name: 'KNOWLEDGE',
|
|
29538
|
+
/**
|
|
29539
|
+
* BOILERPLATE command can be used in:
|
|
29540
|
+
*/
|
|
29541
|
+
isUsedInPipelineHead: true,
|
|
29542
|
+
isUsedInPipelineTask: false,
|
|
29543
|
+
/**
|
|
29544
|
+
* Description of the KNOWLEDGE command
|
|
29545
|
+
*/
|
|
29546
|
+
description: `Tells promptbook which external knowledge to use`,
|
|
29547
|
+
/**
|
|
29548
|
+
* Link to documentation
|
|
29549
|
+
*/
|
|
29550
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/41',
|
|
29551
|
+
/**
|
|
29552
|
+
* Example usages of the KNOWLEDGE command
|
|
29553
|
+
*/
|
|
29554
|
+
examples: [
|
|
29555
|
+
'KNOWLEDGE https://www.pavolhejny.com/',
|
|
29556
|
+
'KNOWLEDGE ./hejny-cv.txt',
|
|
29557
|
+
'KNOWLEDGE ./hejny-cv.md',
|
|
29558
|
+
'KNOWLEDGE ./hejny-cv.pdf',
|
|
29559
|
+
'KNOWLEDGE ./hejny-cv.docx',
|
|
29560
|
+
// <- TODO: [😿] Allow ONLY files scoped in the (sub)directory NOT ../ and test it
|
|
29561
|
+
],
|
|
29562
|
+
/**
|
|
29563
|
+
* Parses the KNOWLEDGE command
|
|
29564
|
+
*/
|
|
29565
|
+
parse(input) {
|
|
29566
|
+
const { args } = input;
|
|
29567
|
+
const knowledgeSourceContent = spaceTrim$1(args[0] || '');
|
|
29568
|
+
if (knowledgeSourceContent === '') {
|
|
29569
|
+
throw new ParseError(`Source is not defined`);
|
|
29570
|
+
}
|
|
29571
|
+
// TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
|
|
29572
|
+
if (knowledgeSourceContent.startsWith('http://')) {
|
|
29573
|
+
throw new ParseError(`Source is not secure`);
|
|
29574
|
+
}
|
|
29575
|
+
if (!(isValidFilePath(knowledgeSourceContent) || isValidUrl(knowledgeSourceContent))) {
|
|
29576
|
+
throw new ParseError(`Source not valid`);
|
|
29577
|
+
}
|
|
29578
|
+
if (knowledgeSourceContent.startsWith('../') ||
|
|
29579
|
+
knowledgeSourceContent.startsWith('/') ||
|
|
29580
|
+
/^[A-Z]:[\\/]+/i.test(knowledgeSourceContent)) {
|
|
29581
|
+
throw new ParseError(`Source cannot be outside of the .book.md folder`);
|
|
29582
|
+
}
|
|
29583
|
+
return {
|
|
29584
|
+
type: 'KNOWLEDGE',
|
|
29585
|
+
knowledgeSourceContent,
|
|
29586
|
+
};
|
|
29587
|
+
},
|
|
29588
|
+
/**
|
|
29589
|
+
* Apply the KNOWLEDGE command to the `pipelineJson`
|
|
29590
|
+
*
|
|
29591
|
+
* Note: `$` is used to indicate that this function mutates given `pipelineJson`
|
|
29592
|
+
*/
|
|
29593
|
+
$applyToPipelineJson(command, $pipelineJson) {
|
|
29594
|
+
const { knowledgeSourceContent } = command;
|
|
29595
|
+
$pipelineJson.knowledgeSources.push({
|
|
29596
|
+
name: knowledgeSourceContentToName(knowledgeSourceContent),
|
|
29597
|
+
knowledgeSourceContent,
|
|
29598
|
+
});
|
|
29599
|
+
},
|
|
29600
|
+
/**
|
|
29601
|
+
* Converts the KNOWLEDGE command back to string
|
|
29602
|
+
*
|
|
29603
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
29604
|
+
*/
|
|
29605
|
+
stringify(command) {
|
|
29606
|
+
return `---`; // <- TODO: [🛋] Implement
|
|
29607
|
+
},
|
|
29608
|
+
/**
|
|
29609
|
+
* Reads the KNOWLEDGE command from the `PipelineJson`
|
|
29610
|
+
*
|
|
29611
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
29612
|
+
*/
|
|
29613
|
+
takeFromPipelineJson(pipelineJson) {
|
|
29614
|
+
throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
|
|
29615
|
+
},
|
|
29616
|
+
};
|
|
29617
|
+
// Note: [⛱] There are two types of KNOWLEDGE commands *...(read more in [⛱])*
|
|
29618
|
+
|
|
29716
29619
|
/**
|
|
29717
29620
|
* Constant for model variants.
|
|
29718
29621
|
*
|
|
@@ -30247,7 +30150,234 @@ const postprocessCommandParser = {
|
|
|
30247
30150
|
};
|
|
30248
30151
|
|
|
30249
30152
|
/**
|
|
30250
|
-
*
|
|
30153
|
+
* All available task types
|
|
30154
|
+
*
|
|
30155
|
+
* There is is distinction between task types and section types
|
|
30156
|
+
* - Every section in markdown has its SectionType
|
|
30157
|
+
* - Some sections are tasks but other can be non-task sections
|
|
30158
|
+
*
|
|
30159
|
+
* @public exported from `@promptbook/core`
|
|
30160
|
+
*/
|
|
30161
|
+
const TaskTypes = [
|
|
30162
|
+
'PROMPT',
|
|
30163
|
+
'SIMPLE',
|
|
30164
|
+
'SCRIPT',
|
|
30165
|
+
'DIALOG',
|
|
30166
|
+
// <- [🅱]
|
|
30167
|
+
];
|
|
30168
|
+
|
|
30169
|
+
/**
|
|
30170
|
+
* All available sections which are not tasks
|
|
30171
|
+
*
|
|
30172
|
+
* @public exported from `@promptbook/core`
|
|
30173
|
+
*/
|
|
30174
|
+
const NonTaskSectionTypes = ['EXAMPLE', 'KNOWLEDGE', 'INSTRUMENT', 'ACTION'];
|
|
30175
|
+
/**
|
|
30176
|
+
* All available section types
|
|
30177
|
+
*
|
|
30178
|
+
* There is is distinction between task types and section types
|
|
30179
|
+
* - Every section in markdown has its SectionType
|
|
30180
|
+
* - Some sections are tasks but other can be non-task sections
|
|
30181
|
+
*
|
|
30182
|
+
* @public exported from `@promptbook/core`
|
|
30183
|
+
*/
|
|
30184
|
+
const SectionTypes = [
|
|
30185
|
+
...TaskTypes.map((TaskType) => `${TaskType}_TASK`),
|
|
30186
|
+
...NonTaskSectionTypes,
|
|
30187
|
+
];
|
|
30188
|
+
|
|
30189
|
+
/**
|
|
30190
|
+
* Parses the section command
|
|
30191
|
+
*
|
|
30192
|
+
* @see `documentationUrl` for more details
|
|
30193
|
+
*
|
|
30194
|
+
* @public exported from `@promptbook/editable`
|
|
30195
|
+
*/
|
|
30196
|
+
const sectionCommandParser = {
|
|
30197
|
+
/**
|
|
30198
|
+
* Name of the command
|
|
30199
|
+
*/
|
|
30200
|
+
name: 'SECTION',
|
|
30201
|
+
/**
|
|
30202
|
+
* Aliases for the SECTION command
|
|
30203
|
+
*/
|
|
30204
|
+
aliasNames: [
|
|
30205
|
+
'PROMPT',
|
|
30206
|
+
'SIMPLE',
|
|
30207
|
+
'SCRIPT',
|
|
30208
|
+
'DIALOG',
|
|
30209
|
+
'SAMPLE',
|
|
30210
|
+
'EXAMPLE',
|
|
30211
|
+
'KNOWLEDGE',
|
|
30212
|
+
'INSTRUMENT',
|
|
30213
|
+
'ACTION', // <- Note: [⛱]
|
|
30214
|
+
],
|
|
30215
|
+
/**
|
|
30216
|
+
* Aliases for the SECTION command
|
|
30217
|
+
*/
|
|
30218
|
+
deprecatedNames: ['TEMPLATE', 'BLOCK', 'EXECUTE'],
|
|
30219
|
+
/**
|
|
30220
|
+
* BOILERPLATE command can be used in:
|
|
30221
|
+
*/
|
|
30222
|
+
isUsedInPipelineHead: false,
|
|
30223
|
+
isUsedInPipelineTask: true,
|
|
30224
|
+
/**
|
|
30225
|
+
* Description of the SECTION command
|
|
30226
|
+
*/
|
|
30227
|
+
description: `Defines the purpose of the markdown section - if its a task and which type or something else`,
|
|
30228
|
+
/**
|
|
30229
|
+
* Link to documentation
|
|
30230
|
+
*/
|
|
30231
|
+
documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/64',
|
|
30232
|
+
/**
|
|
30233
|
+
* Example usages of the SECTION command
|
|
30234
|
+
*/
|
|
30235
|
+
examples: [
|
|
30236
|
+
// Short form:
|
|
30237
|
+
'PROMPT',
|
|
30238
|
+
'SIMPLE',
|
|
30239
|
+
'SCRIPT',
|
|
30240
|
+
'DIALOG',
|
|
30241
|
+
// <- [🅱]
|
|
30242
|
+
'EXAMPLE',
|
|
30243
|
+
'KNOWLEDGE',
|
|
30244
|
+
'INSTRUMENT',
|
|
30245
|
+
'ACTION',
|
|
30246
|
+
// -----------------
|
|
30247
|
+
// Recommended (reversed) form:
|
|
30248
|
+
'PROMPT SECTION',
|
|
30249
|
+
'SIMPLE SECTION',
|
|
30250
|
+
'SCRIPT SECTION',
|
|
30251
|
+
'DIALOG SECTION',
|
|
30252
|
+
// <- [🅱]
|
|
30253
|
+
'EXAMPLE SECTION',
|
|
30254
|
+
'KNOWLEDGE SECTION',
|
|
30255
|
+
'INSTRUMENT SECTION',
|
|
30256
|
+
'ACTION SECTION',
|
|
30257
|
+
// -----------------
|
|
30258
|
+
// Standard form:
|
|
30259
|
+
'SECTION PROMPT',
|
|
30260
|
+
'SECTION SIMPLE',
|
|
30261
|
+
'SECTION SCRIPT',
|
|
30262
|
+
'SECTION DIALOG',
|
|
30263
|
+
// <- [🅱]
|
|
30264
|
+
'SECTION EXAMPLE',
|
|
30265
|
+
'SECTION KNOWLEDGE',
|
|
30266
|
+
'SECTION INSTRUMENT',
|
|
30267
|
+
'SECTION ACTION',
|
|
30268
|
+
],
|
|
30269
|
+
// TODO: [♓️] order: -10 /* <- Note: Putting before other commands */
|
|
30270
|
+
/**
|
|
30271
|
+
* Parses the SECTION command
|
|
30272
|
+
*/
|
|
30273
|
+
parse(input) {
|
|
30274
|
+
let { normalized } = input;
|
|
30275
|
+
normalized = normalized.split('SAMPLE').join('EXAMPLE');
|
|
30276
|
+
normalized = normalized.split('EXECUTE_').join('');
|
|
30277
|
+
normalized = normalized.split('DIALOGUE').join('DIALOG');
|
|
30278
|
+
const taskTypes = SectionTypes.filter((sectionType) => normalized.includes(sectionType.split('_TASK').join('')));
|
|
30279
|
+
if (taskTypes.length !== 1) {
|
|
30280
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
30281
|
+
Unknown section type "${normalized}"
|
|
30282
|
+
|
|
30283
|
+
Supported section types are:
|
|
30284
|
+
${block(SectionTypes.join(', '))}
|
|
30285
|
+
`));
|
|
30286
|
+
}
|
|
30287
|
+
const taskType = taskTypes[0];
|
|
30288
|
+
return {
|
|
30289
|
+
type: 'SECTION',
|
|
30290
|
+
taskType,
|
|
30291
|
+
};
|
|
30292
|
+
},
|
|
30293
|
+
/**
|
|
30294
|
+
* Apply the SECTION command to the `pipelineJson`
|
|
30295
|
+
*
|
|
30296
|
+
* Note: `$` is used to indicate that this function mutates given `taskJson`
|
|
30297
|
+
*/
|
|
30298
|
+
$applyToTaskJson(command, $taskJson, $pipelineJson) {
|
|
30299
|
+
if ($taskJson.isSectionTypeSet === true) {
|
|
30300
|
+
throw new ParseError(spaceTrim$1(`
|
|
30301
|
+
Section type is already defined in the section.
|
|
30302
|
+
It can be defined only once.
|
|
30303
|
+
`));
|
|
30304
|
+
}
|
|
30305
|
+
$taskJson.isSectionTypeSet = true;
|
|
30306
|
+
// TODO: [🍧][💩] Rearrange better - but at bottom and unwrap from function
|
|
30307
|
+
const expectResultingParameterName = () => {
|
|
30308
|
+
if ($taskJson.resultingParameterName) {
|
|
30309
|
+
return;
|
|
30310
|
+
}
|
|
30311
|
+
throw new ParseError(`Task section and example section must end with return statement -> {parameterName}`);
|
|
30312
|
+
};
|
|
30313
|
+
if ($taskJson.content === undefined) {
|
|
30314
|
+
throw new UnexpectedError(`Content is missing in the taskJson - probably commands are applied in wrong order`);
|
|
30315
|
+
}
|
|
30316
|
+
if (command.taskType === 'EXAMPLE') {
|
|
30317
|
+
expectResultingParameterName();
|
|
30318
|
+
const parameter = $pipelineJson.parameters.find((param) => param.name === $taskJson.resultingParameterName);
|
|
30319
|
+
if (parameter === undefined) {
|
|
30320
|
+
// TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
|
|
30321
|
+
throw new ParseError(`Parameter \`{${$taskJson.resultingParameterName}}\` is not defined so can not define example value of it`);
|
|
30322
|
+
}
|
|
30323
|
+
parameter.exampleValues = parameter.exampleValues || [];
|
|
30324
|
+
parameter.exampleValues.push($taskJson.content);
|
|
30325
|
+
$taskJson.isTask = false;
|
|
30326
|
+
return;
|
|
30327
|
+
}
|
|
30328
|
+
if (command.taskType === 'KNOWLEDGE') {
|
|
30329
|
+
knowledgeCommandParser.$applyToPipelineJson({
|
|
30330
|
+
type: 'KNOWLEDGE',
|
|
30331
|
+
knowledgeSourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
|
|
30332
|
+
}, $pipelineJson);
|
|
30333
|
+
$taskJson.isTask = false;
|
|
30334
|
+
return;
|
|
30335
|
+
}
|
|
30336
|
+
if (command.taskType === 'ACTION') {
|
|
30337
|
+
console.error(new NotYetImplementedError('Actions are not implemented yet'));
|
|
30338
|
+
$taskJson.isTask = false;
|
|
30339
|
+
return;
|
|
30340
|
+
}
|
|
30341
|
+
if (command.taskType === 'INSTRUMENT') {
|
|
30342
|
+
console.error(new NotYetImplementedError('Instruments are not implemented yet'));
|
|
30343
|
+
$taskJson.isTask = false;
|
|
30344
|
+
return;
|
|
30345
|
+
}
|
|
30346
|
+
expectResultingParameterName();
|
|
30347
|
+
$taskJson.taskType = command.taskType;
|
|
30348
|
+
$taskJson.isTask = true;
|
|
30349
|
+
},
|
|
30350
|
+
/**
|
|
30351
|
+
* Converts the SECTION command back to string
|
|
30352
|
+
*
|
|
30353
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
30354
|
+
*/
|
|
30355
|
+
stringify(command) {
|
|
30356
|
+
return `---`; // <- TODO: [🛋] Implement
|
|
30357
|
+
},
|
|
30358
|
+
/**
|
|
30359
|
+
* Reads the SECTION command from the `TaskJson`
|
|
30360
|
+
*
|
|
30361
|
+
* Note: This is used in `pipelineJsonToString` utility
|
|
30362
|
+
*/
|
|
30363
|
+
takeFromTaskJson($taskJson) {
|
|
30364
|
+
throw new NotYetImplementedError(`[🛋] Not implemented yet`); // <- TODO: [🛋] Implement
|
|
30365
|
+
},
|
|
30366
|
+
};
|
|
30367
|
+
/**
|
|
30368
|
+
* Note: [⛱] There are two types of KNOWLEDGE, ACTION and INSTRUMENT commands:
|
|
30369
|
+
* 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
|
|
30370
|
+
* - KNOWLEDGE Look at https://en.wikipedia.org/wiki/Artificial_intelligence
|
|
30371
|
+
* 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
|
|
30372
|
+
* - KNOWLEDGE SECTION
|
|
30373
|
+
*
|
|
30374
|
+
* ```
|
|
30375
|
+
* Look at https://en.wikipedia.org/wiki/Artificial_intelligence
|
|
30376
|
+
* ```
|
|
30377
|
+
*/
|
|
30378
|
+
|
|
30379
|
+
/**
|
|
30380
|
+
* Parses the url command
|
|
30251
30381
|
*
|
|
30252
30382
|
* @see `documentationUrl` for more details
|
|
30253
30383
|
*
|
|
@@ -30700,29 +30830,265 @@ function parseCommandVariant(input) {
|
|
|
30700
30830
|
}
|
|
30701
30831
|
|
|
30702
30832
|
/**
|
|
30703
|
-
*
|
|
30833
|
+
* Utility function to extract all list items from markdown
|
|
30704
30834
|
*
|
|
30705
|
-
*
|
|
30706
|
-
*
|
|
30835
|
+
* Note: It works with both ul and ol
|
|
30836
|
+
* Note: It omits list items in code blocks
|
|
30837
|
+
* Note: It flattens nested lists
|
|
30838
|
+
* Note: It can not work with html syntax and comments
|
|
30707
30839
|
*
|
|
30708
|
-
* @
|
|
30840
|
+
* @param markdown any valid markdown
|
|
30841
|
+
* @returns An array of strings, each representing an individual list item found in the markdown
|
|
30842
|
+
*
|
|
30843
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
30709
30844
|
*/
|
|
30710
|
-
function
|
|
30711
|
-
const
|
|
30712
|
-
|
|
30713
|
-
|
|
30714
|
-
|
|
30715
|
-
|
|
30716
|
-
|
|
30717
|
-
|
|
30718
|
-
|
|
30719
|
-
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
}
|
|
30723
|
-
}
|
|
30724
|
-
|
|
30725
|
-
|
|
30845
|
+
function extractAllListItemsFromMarkdown(markdown) {
|
|
30846
|
+
const lines = markdown.split(/\r?\n/);
|
|
30847
|
+
const listItems = [];
|
|
30848
|
+
let isInCodeBlock = false;
|
|
30849
|
+
for (const line of lines) {
|
|
30850
|
+
const trimmedLine = line.trim();
|
|
30851
|
+
if (trimmedLine.startsWith('```')) {
|
|
30852
|
+
isInCodeBlock = !isInCodeBlock;
|
|
30853
|
+
}
|
|
30854
|
+
if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
|
|
30855
|
+
const listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
|
|
30856
|
+
listItems.push(listItem);
|
|
30857
|
+
}
|
|
30858
|
+
}
|
|
30859
|
+
return listItems;
|
|
30860
|
+
}
|
|
30861
|
+
|
|
30862
|
+
/**
|
|
30863
|
+
* Builds a short file/url identification block for parse errors.
|
|
30864
|
+
*
|
|
30865
|
+
* @private internal utility of `parsePipeline`
|
|
30866
|
+
*/
|
|
30867
|
+
function getPipelineIdentification($pipelineJson) {
|
|
30868
|
+
// Note: This is a 😐 implementation of [🚞]
|
|
30869
|
+
const pipelineIdentificationParts = [];
|
|
30870
|
+
if ($pipelineJson.sourceFile !== undefined) {
|
|
30871
|
+
pipelineIdentificationParts.push(`File: ${$pipelineJson.sourceFile}`);
|
|
30872
|
+
}
|
|
30873
|
+
if ($pipelineJson.pipelineUrl !== undefined) {
|
|
30874
|
+
pipelineIdentificationParts.push(`Url: ${$pipelineJson.pipelineUrl}`);
|
|
30875
|
+
}
|
|
30876
|
+
return pipelineIdentificationParts.join('\n');
|
|
30877
|
+
}
|
|
30878
|
+
|
|
30879
|
+
/**
|
|
30880
|
+
* Merges one parameter declaration into the mutable pipeline parameter list.
|
|
30881
|
+
*
|
|
30882
|
+
* @private internal utility of `parsePipeline`
|
|
30883
|
+
*/
|
|
30884
|
+
function defineParameter($pipelineJson, parameterCommand) {
|
|
30885
|
+
const { parameterName, parameterDescription, isInput, isOutput } = parameterCommand;
|
|
30886
|
+
if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
|
|
30887
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
30888
|
+
Parameter name {${parameterName}} is reserved and cannot be used as resulting parameter name
|
|
30889
|
+
|
|
30890
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
30891
|
+
`) /* <- TODO: [🚞] */);
|
|
30892
|
+
}
|
|
30893
|
+
const existingParameter = $pipelineJson.parameters.find((parameter) => parameter.name === parameterName);
|
|
30894
|
+
if (existingParameter &&
|
|
30895
|
+
existingParameter.description &&
|
|
30896
|
+
existingParameter.description !== parameterDescription &&
|
|
30897
|
+
parameterDescription) {
|
|
30898
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
30899
|
+
Parameter \`{${parameterName}}\` is defined multiple times with different description:
|
|
30900
|
+
|
|
30901
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
30902
|
+
|
|
30903
|
+
First definition:
|
|
30904
|
+
${block(existingParameter.description || '[undefined]')}
|
|
30905
|
+
|
|
30906
|
+
Second definition:
|
|
30907
|
+
${block(parameterDescription || '[undefined]')}
|
|
30908
|
+
`));
|
|
30909
|
+
}
|
|
30910
|
+
if (existingParameter) {
|
|
30911
|
+
if (parameterDescription) {
|
|
30912
|
+
existingParameter.description = parameterDescription;
|
|
30913
|
+
}
|
|
30914
|
+
existingParameter.isInput = existingParameter.isInput || isInput;
|
|
30915
|
+
existingParameter.isOutput = existingParameter.isOutput || isOutput;
|
|
30916
|
+
return;
|
|
30917
|
+
}
|
|
30918
|
+
$pipelineJson.parameters.push({
|
|
30919
|
+
name: parameterName,
|
|
30920
|
+
description: parameterDescription || undefined,
|
|
30921
|
+
isInput,
|
|
30922
|
+
isOutput,
|
|
30923
|
+
});
|
|
30924
|
+
}
|
|
30925
|
+
|
|
30926
|
+
/**
|
|
30927
|
+
* Removes fenced code blocks when deriving human-readable section descriptions.
|
|
30928
|
+
*
|
|
30929
|
+
* @private internal utility of `extractPipelineDescription`
|
|
30930
|
+
*/
|
|
30931
|
+
const DESCRIPTION_CODE_BLOCK_REGEXP = /^```.*^```/gms;
|
|
30932
|
+
/**
|
|
30933
|
+
* Removes blockquote lines when deriving human-readable section descriptions.
|
|
30934
|
+
*
|
|
30935
|
+
* @private internal utility of `extractPipelineDescription`
|
|
30936
|
+
*/
|
|
30937
|
+
const DESCRIPTION_BLOCKQUOTE_REGEXP = /^>.*$/gm;
|
|
30938
|
+
/**
|
|
30939
|
+
* Removes list items and return statements when deriving human-readable section descriptions.
|
|
30940
|
+
*
|
|
30941
|
+
* @private internal utility of `extractPipelineDescription`
|
|
30942
|
+
*/
|
|
30943
|
+
const DESCRIPTION_LIST_ITEM_REGEXP = /^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm;
|
|
30944
|
+
/**
|
|
30945
|
+
* Extracts the plain-text description from a head or task section body.
|
|
30946
|
+
*
|
|
30947
|
+
* @private internal utility of `parsePipeline`
|
|
30948
|
+
*/
|
|
30949
|
+
function extractPipelineDescription(sectionContent) {
|
|
30950
|
+
let description = sectionContent;
|
|
30951
|
+
description = description.split(DESCRIPTION_CODE_BLOCK_REGEXP).join('');
|
|
30952
|
+
description = description.split(DESCRIPTION_BLOCKQUOTE_REGEXP).join('');
|
|
30953
|
+
description = description.split(DESCRIPTION_LIST_ITEM_REGEXP).join('');
|
|
30954
|
+
description = spaceTrim$1(description);
|
|
30955
|
+
if (description === '') {
|
|
30956
|
+
return undefined;
|
|
30957
|
+
}
|
|
30958
|
+
return description;
|
|
30959
|
+
}
|
|
30960
|
+
|
|
30961
|
+
/**
|
|
30962
|
+
* Applies the pipeline head title, description, and head-level commands.
|
|
30963
|
+
*
|
|
30964
|
+
* @private internal utility of `parsePipeline`
|
|
30965
|
+
*/
|
|
30966
|
+
function applyPipelineHead(pipelineHead, $pipelineJson) {
|
|
30967
|
+
$pipelineJson.title = pipelineHead.title;
|
|
30968
|
+
$pipelineJson.description = extractPipelineDescription(pipelineHead.content);
|
|
30969
|
+
for (const listItem of extractAllListItemsFromMarkdown(pipelineHead.content)) {
|
|
30970
|
+
applyPipelineHeadCommand(listItem, $pipelineJson);
|
|
30971
|
+
}
|
|
30972
|
+
}
|
|
30973
|
+
/**
|
|
30974
|
+
* Parses and applies one command declared in the pipeline head.
|
|
30975
|
+
*
|
|
30976
|
+
* @private internal utility of `applyPipelineHead`
|
|
30977
|
+
*/
|
|
30978
|
+
function applyPipelineHeadCommand(listItem, $pipelineJson) {
|
|
30979
|
+
const command = parseCommand(listItem, 'PIPELINE_HEAD');
|
|
30980
|
+
const commandParser = getParserForCommand(command);
|
|
30981
|
+
if (commandParser.isUsedInPipelineHead !== true /* <- Note: [🦦][4] */) {
|
|
30982
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
30983
|
+
Command \`${command.type}\` is not allowed in the head of the pipeline ONLY at the pipeline task
|
|
30984
|
+
|
|
30985
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
30986
|
+
`)); // <- TODO: [🚞]
|
|
30987
|
+
}
|
|
30988
|
+
try {
|
|
30989
|
+
commandParser.$applyToPipelineJson(command, $pipelineJson);
|
|
30990
|
+
// <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitly
|
|
30991
|
+
}
|
|
30992
|
+
catch (error) {
|
|
30993
|
+
if (!(error instanceof ParseError)) {
|
|
30994
|
+
throw error;
|
|
30995
|
+
}
|
|
30996
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
30997
|
+
Command ${command.type} failed to apply to the pipeline
|
|
30998
|
+
|
|
30999
|
+
The error:
|
|
31000
|
+
${block(error.message)}
|
|
31001
|
+
|
|
31002
|
+
Raw command:
|
|
31003
|
+
- ${listItem}
|
|
31004
|
+
|
|
31005
|
+
Usage of ${command.type}:
|
|
31006
|
+
${block(commandParser.examples.map((example) => `- ${example}`).join('\n'))}
|
|
31007
|
+
|
|
31008
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
31009
|
+
`)); // <- TODO: [🚞]
|
|
31010
|
+
}
|
|
31011
|
+
if (command.type === 'PARAMETER') {
|
|
31012
|
+
defineParameter($pipelineJson, command);
|
|
31013
|
+
// <- Note: [🍣]
|
|
31014
|
+
}
|
|
31015
|
+
}
|
|
31016
|
+
|
|
31017
|
+
/**
|
|
31018
|
+
* Creates the mutable pipeline JSON structure used throughout parsing.
|
|
31019
|
+
*
|
|
31020
|
+
* @private internal utility of `parsePipeline`
|
|
31021
|
+
*/
|
|
31022
|
+
function createInitialPipelineJson(pipelineString) {
|
|
31023
|
+
return {
|
|
31024
|
+
title: DEFAULT_BOOK_TITLE,
|
|
31025
|
+
parameters: [],
|
|
31026
|
+
tasks: [],
|
|
31027
|
+
knowledgeSources: [],
|
|
31028
|
+
knowledgePieces: [],
|
|
31029
|
+
personas: [],
|
|
31030
|
+
preparations: [],
|
|
31031
|
+
sources: [
|
|
31032
|
+
{
|
|
31033
|
+
type: 'BOOK',
|
|
31034
|
+
path: null,
|
|
31035
|
+
// <- TODO: !!6 Pass here path of the file
|
|
31036
|
+
content: pipelineString,
|
|
31037
|
+
},
|
|
31038
|
+
],
|
|
31039
|
+
};
|
|
31040
|
+
}
|
|
31041
|
+
|
|
31042
|
+
/**
|
|
31043
|
+
* Creates stable unique task names for duplicate section titles.
|
|
31044
|
+
*
|
|
31045
|
+
* @private internal utility of `parsePipeline`
|
|
31046
|
+
*/
|
|
31047
|
+
function createUniqueSectionNameResolver(pipelineSections) {
|
|
31048
|
+
const sectionCounts = {};
|
|
31049
|
+
for (const pipelineSection of pipelineSections) {
|
|
31050
|
+
const sectionName = titleToName(pipelineSection.title);
|
|
31051
|
+
if (sectionCounts[sectionName] === undefined) {
|
|
31052
|
+
sectionCounts[sectionName] = { count: 0, currentIndex: 0 };
|
|
31053
|
+
}
|
|
31054
|
+
sectionCounts[sectionName].count++;
|
|
31055
|
+
}
|
|
31056
|
+
return (title) => {
|
|
31057
|
+
const sectionName = titleToName(title);
|
|
31058
|
+
const sectionCount = sectionCounts[sectionName];
|
|
31059
|
+
if (sectionCount.count === 1) {
|
|
31060
|
+
return sectionName;
|
|
31061
|
+
}
|
|
31062
|
+
const nameWithSuffix = `${sectionName}-${sectionCount.currentIndex}`;
|
|
31063
|
+
sectionCount.currentIndex++;
|
|
31064
|
+
return nameWithSuffix;
|
|
31065
|
+
};
|
|
31066
|
+
}
|
|
31067
|
+
|
|
31068
|
+
/**
|
|
31069
|
+
* Extracts the interface (input and output parameters) from a pipeline.
|
|
31070
|
+
*
|
|
31071
|
+
* @deprecated https://github.com/webgptorg/promptbook/pull/186
|
|
31072
|
+
* @see https://github.com/webgptorg/promptbook/discussions/171
|
|
31073
|
+
*
|
|
31074
|
+
* @public exported from `@promptbook/core`
|
|
31075
|
+
*/
|
|
31076
|
+
function getPipelineInterface(pipeline) {
|
|
31077
|
+
const pipelineInterface = {
|
|
31078
|
+
inputParameters: [],
|
|
31079
|
+
outputParameters: [],
|
|
31080
|
+
};
|
|
31081
|
+
for (const parameter of pipeline.parameters) {
|
|
31082
|
+
const { isInput, isOutput } = parameter;
|
|
31083
|
+
if (isInput) {
|
|
31084
|
+
pipelineInterface.inputParameters.push(deepClone(parameter));
|
|
31085
|
+
}
|
|
31086
|
+
if (isOutput) {
|
|
31087
|
+
pipelineInterface.outputParameters.push(deepClone(parameter));
|
|
31088
|
+
}
|
|
31089
|
+
}
|
|
31090
|
+
for (const key of ['inputParameters', 'outputParameters']) {
|
|
31091
|
+
pipelineInterface[key].sort(({ name: name1 }, { name: name2 }) => name1.localeCompare(name2));
|
|
30726
31092
|
}
|
|
30727
31093
|
return exportJson({
|
|
30728
31094
|
name: `pipelineInterface`,
|
|
@@ -30960,157 +31326,125 @@ const HIGH_LEVEL_ABSTRACTIONS = [
|
|
|
30960
31326
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
30961
31327
|
|
|
30962
31328
|
/**
|
|
30963
|
-
*
|
|
31329
|
+
* Applies postprocessing and exports the parsed pipeline JSON.
|
|
30964
31330
|
*
|
|
30965
|
-
* @private internal
|
|
31331
|
+
* @private internal utility of `parsePipeline`
|
|
30966
31332
|
*/
|
|
30967
|
-
|
|
30968
|
-
|
|
30969
|
-
|
|
31333
|
+
function finalizeParsedPipeline($pipelineJson) {
|
|
31334
|
+
applyImplicitParameterDirections($pipelineJson);
|
|
31335
|
+
removeUndefinedValuesFromPipeline($pipelineJson);
|
|
31336
|
+
applySyncHighLevelAbstractions($pipelineJson);
|
|
31337
|
+
ensurePipelineFormfactor($pipelineJson);
|
|
31338
|
+
return exportParsedPipelineJson($pipelineJson);
|
|
31339
|
+
}
|
|
30970
31340
|
/**
|
|
30971
|
-
*
|
|
30972
|
-
*
|
|
30973
|
-
* @param {string} content - The string to remove comments from.
|
|
30974
|
-
* @returns {string} The input string with all comments removed.
|
|
31341
|
+
* Applies default INPUT/OUTPUT flags when the author did not specify them explicitly.
|
|
30975
31342
|
*
|
|
30976
|
-
* @
|
|
31343
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
30977
31344
|
*/
|
|
30978
|
-
function
|
|
30979
|
-
|
|
31345
|
+
function applyImplicitParameterDirections($pipelineJson) {
|
|
31346
|
+
markImplicitInputParameters($pipelineJson);
|
|
31347
|
+
markImplicitOutputParameters($pipelineJson);
|
|
30980
31348
|
}
|
|
30981
|
-
|
|
30982
31349
|
/**
|
|
30983
|
-
*
|
|
30984
|
-
* A flat pipeline is a simple text without proper structure (headers, blocks, etc).
|
|
31350
|
+
* Marks non-result parameters as pipeline inputs when no input was declared.
|
|
30985
31351
|
*
|
|
30986
|
-
* @
|
|
31352
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
30987
31353
|
*/
|
|
30988
|
-
function
|
|
30989
|
-
|
|
30990
|
-
|
|
30991
|
-
|
|
30992
|
-
|
|
30993
|
-
|
|
30994
|
-
|
|
30995
|
-
|
|
30996
|
-
|
|
30997
|
-
|
|
30998
|
-
|
|
30999
|
-
|
|
31000
|
-
|
|
31001
|
-
|
|
31354
|
+
function markImplicitInputParameters($pipelineJson) {
|
|
31355
|
+
if ($pipelineJson.parameters.some((parameter) => parameter.isInput)) {
|
|
31356
|
+
return;
|
|
31357
|
+
}
|
|
31358
|
+
for (const parameter of $pipelineJson.parameters) {
|
|
31359
|
+
const isThisParameterResulting = $pipelineJson.tasks.some((task) => task.resultingParameterName === parameter.name);
|
|
31360
|
+
if (!isThisParameterResulting) {
|
|
31361
|
+
parameter.isInput = true;
|
|
31362
|
+
// <- TODO: [💔] Why this is making typescript error in vscode but not in cli
|
|
31363
|
+
// > Type 'true' is not assignable to type 'false'.ts(2322)
|
|
31364
|
+
// > (property) isInput: false
|
|
31365
|
+
// > The parameter is input of the pipeline The parameter is NOT input of the pipeline
|
|
31366
|
+
}
|
|
31367
|
+
}
|
|
31002
31368
|
}
|
|
31003
|
-
|
|
31004
31369
|
/**
|
|
31005
|
-
*
|
|
31006
|
-
*
|
|
31007
|
-
* Transforms a flat, simple pipeline into a properly formatted pipeline string
|
|
31008
|
-
* with sections for title, prompt, and return statement.
|
|
31370
|
+
* Marks every non-input parameter as output when no output was declared.
|
|
31009
31371
|
*
|
|
31010
|
-
* @
|
|
31372
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
31011
31373
|
*/
|
|
31012
|
-
function
|
|
31013
|
-
if (
|
|
31014
|
-
return
|
|
31015
|
-
}
|
|
31016
|
-
pipelineString = spaceTrim$1(pipelineString);
|
|
31017
|
-
const pipelineStringLines = pipelineString.split(/\r?\n/);
|
|
31018
|
-
const potentialReturnStatement = pipelineStringLines.pop();
|
|
31019
|
-
let returnStatement;
|
|
31020
|
-
if (/(-|=)>\s*\{.*\}/.test(potentialReturnStatement)) {
|
|
31021
|
-
// Note: Last line is return statement
|
|
31022
|
-
returnStatement = potentialReturnStatement;
|
|
31023
|
-
}
|
|
31024
|
-
else {
|
|
31025
|
-
// Note: Last line is not a return statement
|
|
31026
|
-
returnStatement = `-> {${DEFAULT_BOOK_OUTPUT_PARAMETER_NAME}}`;
|
|
31027
|
-
pipelineStringLines.push(potentialReturnStatement);
|
|
31028
|
-
}
|
|
31029
|
-
const prompt = spaceTrim$1(pipelineStringLines.join('\n'));
|
|
31030
|
-
let quotedPrompt;
|
|
31031
|
-
if (prompt.split(/\r?\n/).length <= 1) {
|
|
31032
|
-
quotedPrompt = `> ${prompt}`;
|
|
31374
|
+
function markImplicitOutputParameters($pipelineJson) {
|
|
31375
|
+
if ($pipelineJson.parameters.some((parameter) => parameter.isOutput)) {
|
|
31376
|
+
return;
|
|
31033
31377
|
}
|
|
31034
|
-
|
|
31035
|
-
|
|
31036
|
-
|
|
31037
|
-
|
|
31038
|
-
|
|
31039
|
-
`);
|
|
31378
|
+
for (const parameter of $pipelineJson.parameters) {
|
|
31379
|
+
if (!parameter.isInput) {
|
|
31380
|
+
parameter.isOutput = true;
|
|
31381
|
+
// <- TODO: [💔]
|
|
31382
|
+
}
|
|
31040
31383
|
}
|
|
31041
|
-
pipelineString = validatePipelineString(spaceTrim$1((block) => `
|
|
31042
|
-
# ${DEFAULT_BOOK_TITLE}
|
|
31043
|
-
|
|
31044
|
-
## Prompt
|
|
31045
|
-
|
|
31046
|
-
${block(quotedPrompt)}
|
|
31047
|
-
|
|
31048
|
-
${returnStatement}
|
|
31049
|
-
`));
|
|
31050
|
-
// <- TODO: Maybe use book` notation
|
|
31051
|
-
return padBook(pipelineString);
|
|
31052
31384
|
}
|
|
31053
|
-
// TODO: Unit test
|
|
31054
|
-
|
|
31055
31385
|
/**
|
|
31056
|
-
*
|
|
31057
|
-
*
|
|
31058
|
-
* Note: It works with both ul and ol
|
|
31059
|
-
* Note: It omits list items in code blocks
|
|
31060
|
-
* Note: It flattens nested lists
|
|
31061
|
-
* Note: It can not work with html syntax and comments
|
|
31386
|
+
* Removes `undefined` properties from serialized tasks and parameters.
|
|
31062
31387
|
*
|
|
31063
|
-
* @
|
|
31064
|
-
|
|
31388
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
31389
|
+
*/
|
|
31390
|
+
function removeUndefinedValuesFromPipeline($pipelineJson) {
|
|
31391
|
+
$pipelineJson.tasks.forEach(removeUndefinedProperties);
|
|
31392
|
+
$pipelineJson.parameters.forEach(removeUndefinedProperties);
|
|
31393
|
+
}
|
|
31394
|
+
/**
|
|
31395
|
+
* Deletes all own properties with `undefined` values from a mutable JSON entity.
|
|
31065
31396
|
*
|
|
31066
|
-
* @
|
|
31397
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
31067
31398
|
*/
|
|
31068
|
-
function
|
|
31069
|
-
const
|
|
31070
|
-
|
|
31071
|
-
|
|
31072
|
-
for (const line of lines) {
|
|
31073
|
-
const trimmedLine = line.trim();
|
|
31074
|
-
if (trimmedLine.startsWith('```')) {
|
|
31075
|
-
isInCodeBlock = !isInCodeBlock;
|
|
31076
|
-
}
|
|
31077
|
-
if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
|
|
31078
|
-
const listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
|
|
31079
|
-
listItems.push(listItem);
|
|
31399
|
+
function removeUndefinedProperties(entity) {
|
|
31400
|
+
for (const [key, value] of Object.entries(entity)) {
|
|
31401
|
+
if (value === undefined) {
|
|
31402
|
+
delete entity[key];
|
|
31080
31403
|
}
|
|
31081
31404
|
}
|
|
31082
|
-
return listItems;
|
|
31083
31405
|
}
|
|
31084
|
-
|
|
31085
31406
|
/**
|
|
31086
|
-
*
|
|
31087
|
-
*
|
|
31088
|
-
* - When there are multiple or no code blocks the function throws a `ParseError`
|
|
31089
|
-
*
|
|
31090
|
-
* Note: There are multiple similar functions:
|
|
31091
|
-
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
31092
|
-
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
31093
|
-
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
31094
|
-
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
31407
|
+
* Applies all sync-only high-level abstractions after parsing.
|
|
31095
31408
|
*
|
|
31096
|
-
* @
|
|
31097
|
-
|
|
31098
|
-
|
|
31409
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
31410
|
+
*/
|
|
31411
|
+
function applySyncHighLevelAbstractions($pipelineJson) {
|
|
31412
|
+
for (const highLevelAbstraction of HIGH_LEVEL_ABSTRACTIONS.filter(({ type }) => type === 'SYNC')) {
|
|
31413
|
+
highLevelAbstraction.$applyToPipelineJson($pipelineJson);
|
|
31414
|
+
}
|
|
31415
|
+
}
|
|
31416
|
+
/**
|
|
31417
|
+
* Ensures parsed pipelines always have the default `GENERIC` formfactor.
|
|
31099
31418
|
*
|
|
31100
|
-
* @
|
|
31419
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
31101
31420
|
*/
|
|
31102
|
-
function
|
|
31103
|
-
|
|
31104
|
-
if (
|
|
31105
|
-
|
|
31106
|
-
There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
|
|
31107
|
-
|
|
31108
|
-
${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
|
|
31109
|
-
`));
|
|
31421
|
+
function ensurePipelineFormfactor($pipelineJson) {
|
|
31422
|
+
// Note: [🔆] If formfactor is still not set, set it to 'GENERIC'
|
|
31423
|
+
if ($pipelineJson.formfactorName === undefined) {
|
|
31424
|
+
$pipelineJson.formfactorName = 'GENERIC';
|
|
31110
31425
|
}
|
|
31111
|
-
return codeBlocks[0];
|
|
31112
31426
|
}
|
|
31113
|
-
|
|
31427
|
+
/**
|
|
31428
|
+
* Finalizes ordering and exports the parsed pipeline JSON.
|
|
31429
|
+
*
|
|
31430
|
+
* @private internal utility of `finalizeParsedPipeline`
|
|
31431
|
+
*/
|
|
31432
|
+
function exportParsedPipelineJson($pipelineJson) {
|
|
31433
|
+
return exportJson({
|
|
31434
|
+
name: 'pipelineJson',
|
|
31435
|
+
message: `Result of \`parsePipeline\``,
|
|
31436
|
+
order: ORDER_OF_PIPELINE_JSON,
|
|
31437
|
+
value: {
|
|
31438
|
+
formfactorName: 'GENERIC',
|
|
31439
|
+
// <- Note: [🔆] Setting `formfactorName` is redundant to satisfy the typescript
|
|
31440
|
+
...$pipelineJson,
|
|
31441
|
+
},
|
|
31442
|
+
});
|
|
31443
|
+
}
|
|
31444
|
+
// TODO: Use spaceTrim more effectively
|
|
31445
|
+
// TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
|
|
31446
|
+
// TODO: [♈] Probably move expectations from tasks to parameters
|
|
31447
|
+
// TODO: [🍙] Make some standard order of json properties
|
|
31114
31448
|
|
|
31115
31449
|
/**
|
|
31116
31450
|
* Parses markdown section to title its level and content
|
|
@@ -31201,151 +31535,188 @@ function splitMarkdownIntoSections(markdown) {
|
|
|
31201
31535
|
*/
|
|
31202
31536
|
|
|
31203
31537
|
/**
|
|
31204
|
-
*
|
|
31538
|
+
* Splits the prepared markdown into the pipeline head and task sections.
|
|
31205
31539
|
*
|
|
31206
|
-
*
|
|
31207
|
-
|
|
31540
|
+
* @private internal utility of `parsePipeline`
|
|
31541
|
+
*/
|
|
31542
|
+
function parsePreparedPipelineSections(pipelineString, $pipelineJson) {
|
|
31543
|
+
const [pipelineHead, ...pipelineSections] = splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection); /* <- Note: [🥞] */
|
|
31544
|
+
assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson);
|
|
31545
|
+
return {
|
|
31546
|
+
pipelineHead,
|
|
31547
|
+
pipelineSections,
|
|
31548
|
+
};
|
|
31549
|
+
}
|
|
31550
|
+
/**
|
|
31551
|
+
* Ensures the flattened markdown has exactly one h1 head followed by only h2 sections.
|
|
31208
31552
|
*
|
|
31209
|
-
* @
|
|
31553
|
+
* @private internal utility of `parsePreparedPipelineSections`
|
|
31210
31554
|
*/
|
|
31211
|
-
function
|
|
31212
|
-
|
|
31213
|
-
|
|
31214
|
-
|
|
31215
|
-
|
|
31216
|
-
|
|
31217
|
-
|
|
31218
|
-
|
|
31219
|
-
|
|
31220
|
-
flattenedMarkdown += `# ${firstSection.title}` + `\n\n`;
|
|
31221
|
-
flattenedMarkdown += firstSection.content + `\n\n`; // <- [🧠] Maybe 3 new lines?
|
|
31555
|
+
function assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson) {
|
|
31556
|
+
if (pipelineHead === undefined) {
|
|
31557
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
31558
|
+
Pipeline head is not defined
|
|
31559
|
+
|
|
31560
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
31561
|
+
|
|
31562
|
+
This should never happen, because the pipeline already flattened
|
|
31563
|
+
`));
|
|
31222
31564
|
}
|
|
31223
|
-
|
|
31224
|
-
|
|
31225
|
-
|
|
31565
|
+
if (pipelineHead.level !== 1) {
|
|
31566
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
31567
|
+
Pipeline head is not h1
|
|
31568
|
+
|
|
31569
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
31570
|
+
|
|
31571
|
+
This should never happen, because the pipeline already flattened
|
|
31572
|
+
`));
|
|
31226
31573
|
}
|
|
31227
|
-
|
|
31228
|
-
|
|
31229
|
-
|
|
31574
|
+
if (!pipelineSections.every((pipelineSection) => pipelineSection.level === 2)) {
|
|
31575
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
31576
|
+
Not every pipeline section is h2
|
|
31577
|
+
|
|
31578
|
+
${block(getPipelineIdentification($pipelineJson))}
|
|
31579
|
+
|
|
31580
|
+
This should never happen, because the pipeline already flattened
|
|
31581
|
+
`));
|
|
31230
31582
|
}
|
|
31231
|
-
return spaceTrim$1(flattenedMarkdown);
|
|
31232
31583
|
}
|
|
31233
|
-
/**
|
|
31234
|
-
* TODO: [🏛] This can be part of markdown builder
|
|
31235
|
-
* Note: [🕞] In past (commit 42086e1603cbed506482997c00a8ee979af0a247) there was much more
|
|
31236
|
-
* sophisticated implementation of this function through parsing markdown into JSON structure
|
|
31237
|
-
* and flattening the actual structure
|
|
31238
|
-
* NOW we are working just with markdown string and its good enough
|
|
31239
|
-
*/
|
|
31240
31584
|
|
|
31241
31585
|
/**
|
|
31242
|
-
*
|
|
31243
|
-
*
|
|
31244
|
-
* @private internal utility of `parsePipeline`
|
|
31245
|
-
*/
|
|
31246
|
-
const INLINE_CODE_PARAMETER_REGEXP = /`\{(?<parameterName>[a-z0-9_]+)\}`/gi;
|
|
31247
|
-
/**
|
|
31248
|
-
* Normalizes inline return statements wrapped in code spans before markdown flattening.
|
|
31586
|
+
* Removes Markdown (or HTML) comments
|
|
31249
31587
|
*
|
|
31250
|
-
* @
|
|
31251
|
-
|
|
31252
|
-
const INLINE_CODE_RETURN_PARAMETER_REGEXP = /`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi;
|
|
31253
|
-
/**
|
|
31254
|
-
* Matches the trailing return statement of a task section.
|
|
31588
|
+
* @param {string} content - The string to remove comments from.
|
|
31589
|
+
* @returns {string} The input string with all comments removed.
|
|
31255
31590
|
*
|
|
31256
|
-
* @
|
|
31591
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
31257
31592
|
*/
|
|
31258
|
-
|
|
31593
|
+
function removeMarkdownComments(content) {
|
|
31594
|
+
return spaceTrim$1(content.replace(/<!--(.*?)-->/gs, ''));
|
|
31595
|
+
}
|
|
31596
|
+
|
|
31259
31597
|
/**
|
|
31260
|
-
*
|
|
31598
|
+
* Utility to determine if a pipeline string is in flat format.
|
|
31599
|
+
* A flat pipeline is a simple text without proper structure (headers, blocks, etc).
|
|
31261
31600
|
*
|
|
31262
|
-
* @
|
|
31601
|
+
* @public exported from `@promptbook/editable`
|
|
31263
31602
|
*/
|
|
31264
|
-
|
|
31603
|
+
function isFlatPipeline(pipelineString) {
|
|
31604
|
+
pipelineString = removeMarkdownComments(pipelineString);
|
|
31605
|
+
pipelineString = spaceTrim$1(pipelineString);
|
|
31606
|
+
const isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
|
|
31607
|
+
//const isLastLineReturnStatement = pipelineString.split(/\r?\n/).pop()!.split('`').join('').startsWith('->');
|
|
31608
|
+
const isBacktickBlockUsed = pipelineString.includes('```');
|
|
31609
|
+
const isQuoteBlocksUsed = /^>\s+/m.test(pipelineString);
|
|
31610
|
+
const isBlocksUsed = isBacktickBlockUsed || isQuoteBlocksUsed;
|
|
31611
|
+
// TODO: [🧉] Also (double)check
|
|
31612
|
+
// > const usedCommands
|
|
31613
|
+
// > const isBlocksUsed
|
|
31614
|
+
// > const returnStatementCount
|
|
31615
|
+
const isFlat = !isMarkdownBeginningWithHeadline && !isBlocksUsed; /* && isLastLineReturnStatement */
|
|
31616
|
+
return isFlat;
|
|
31617
|
+
}
|
|
31618
|
+
|
|
31265
31619
|
/**
|
|
31266
|
-
*
|
|
31620
|
+
* Converts a pipeline structure to its string representation.
|
|
31267
31621
|
*
|
|
31268
|
-
*
|
|
31269
|
-
|
|
31270
|
-
const DESCRIPTION_BLOCKQUOTE_REGEXP = /^>.*$/gm;
|
|
31271
|
-
/**
|
|
31272
|
-
* Removes list items and return statements when deriving human-readable section descriptions.
|
|
31622
|
+
* Transforms a flat, simple pipeline into a properly formatted pipeline string
|
|
31623
|
+
* with sections for title, prompt, and return statement.
|
|
31273
31624
|
*
|
|
31274
|
-
* @
|
|
31625
|
+
* @public exported from `@promptbook/editable`
|
|
31275
31626
|
*/
|
|
31276
|
-
|
|
31627
|
+
function deflatePipeline(pipelineString) {
|
|
31628
|
+
if (!isFlatPipeline(pipelineString)) {
|
|
31629
|
+
return pipelineString;
|
|
31630
|
+
}
|
|
31631
|
+
pipelineString = spaceTrim$1(pipelineString);
|
|
31632
|
+
const pipelineStringLines = pipelineString.split(/\r?\n/);
|
|
31633
|
+
const potentialReturnStatement = pipelineStringLines.pop();
|
|
31634
|
+
let returnStatement;
|
|
31635
|
+
if (/(-|=)>\s*\{.*\}/.test(potentialReturnStatement)) {
|
|
31636
|
+
// Note: Last line is return statement
|
|
31637
|
+
returnStatement = potentialReturnStatement;
|
|
31638
|
+
}
|
|
31639
|
+
else {
|
|
31640
|
+
// Note: Last line is not a return statement
|
|
31641
|
+
returnStatement = `-> {${DEFAULT_BOOK_OUTPUT_PARAMETER_NAME}}`;
|
|
31642
|
+
pipelineStringLines.push(potentialReturnStatement);
|
|
31643
|
+
}
|
|
31644
|
+
const prompt = spaceTrim$1(pipelineStringLines.join('\n'));
|
|
31645
|
+
let quotedPrompt;
|
|
31646
|
+
if (prompt.split(/\r?\n/).length <= 1) {
|
|
31647
|
+
quotedPrompt = `> ${prompt}`;
|
|
31648
|
+
}
|
|
31649
|
+
else {
|
|
31650
|
+
quotedPrompt = spaceTrim$1((block) => `
|
|
31651
|
+
\`\`\`
|
|
31652
|
+
${block(prompt.split('`').join('\\`'))}
|
|
31653
|
+
\`\`\`
|
|
31654
|
+
`);
|
|
31655
|
+
}
|
|
31656
|
+
pipelineString = validatePipelineString(spaceTrim$1((block) => `
|
|
31657
|
+
# ${DEFAULT_BOOK_TITLE}
|
|
31658
|
+
|
|
31659
|
+
## Prompt
|
|
31660
|
+
|
|
31661
|
+
${block(quotedPrompt)}
|
|
31662
|
+
|
|
31663
|
+
${returnStatement}
|
|
31664
|
+
`));
|
|
31665
|
+
// <- TODO: Maybe use book` notation
|
|
31666
|
+
return padBook(pipelineString);
|
|
31667
|
+
}
|
|
31668
|
+
// TODO: Unit test
|
|
31669
|
+
|
|
31277
31670
|
/**
|
|
31278
|
-
*
|
|
31279
|
-
*
|
|
31280
|
-
* Note: There are 3 similar functions:
|
|
31281
|
-
* - `compilePipeline` **(preferred)** - which properly compiles the promptbook and uses embedding for external knowledge
|
|
31282
|
-
* - `parsePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
|
|
31283
|
-
* - `preparePipeline` - just one step in the compilation process
|
|
31284
|
-
*
|
|
31285
|
-
* Note: This function does not validate logic of the pipeline only the parsing
|
|
31286
|
-
* Note: This function acts as compilation process
|
|
31671
|
+
* Normalizes the markdown by flattening the structure
|
|
31287
31672
|
*
|
|
31288
|
-
*
|
|
31289
|
-
*
|
|
31290
|
-
* @throws {ParseError} if the promptbook string is not valid
|
|
31673
|
+
* - It always have h1 - if there is no h1 in the markdown, it will be added `DEFAULT_BOOK_TITLE`
|
|
31674
|
+
* - All other headings are normalized to h2
|
|
31291
31675
|
*
|
|
31292
|
-
* @public exported from `@promptbook/
|
|
31676
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
31293
31677
|
*/
|
|
31294
|
-
function
|
|
31295
|
-
const
|
|
31296
|
-
|
|
31297
|
-
|
|
31298
|
-
const getUniqueSectionName = createUniqueSectionNameResolver(pipelineSections);
|
|
31299
|
-
applyPipelineHead(pipelineHead, $pipelineJson);
|
|
31300
|
-
for (const pipelineSection of pipelineSections) {
|
|
31301
|
-
processPipelineSection(pipelineSection, $pipelineJson, getUniqueSectionName);
|
|
31678
|
+
function flattenMarkdown(markdown) {
|
|
31679
|
+
const sections = splitMarkdownIntoSections(markdown);
|
|
31680
|
+
if (sections.length === 0) {
|
|
31681
|
+
return `# ${DEFAULT_BOOK_TITLE}`;
|
|
31302
31682
|
}
|
|
31303
|
-
|
|
31304
|
-
|
|
31305
|
-
|
|
31306
|
-
|
|
31307
|
-
|
|
31683
|
+
let flattenedMarkdown = '';
|
|
31684
|
+
const parsedSections = sections.map(parseMarkdownSection);
|
|
31685
|
+
const firstSection = parsedSections.shift();
|
|
31686
|
+
if (firstSection.level === 1) {
|
|
31687
|
+
flattenedMarkdown += `# ${firstSection.title}` + `\n\n`;
|
|
31688
|
+
flattenedMarkdown += firstSection.content + `\n\n`; // <- [🧠] Maybe 3 new lines?
|
|
31689
|
+
}
|
|
31690
|
+
else {
|
|
31691
|
+
parsedSections.unshift(firstSection);
|
|
31692
|
+
flattenedMarkdown += `# ${DEFAULT_BOOK_TITLE}` + `\n\n`; // <- [🧠] Maybe 3 new lines?
|
|
31693
|
+
}
|
|
31694
|
+
for (const { title, content } of parsedSections) {
|
|
31695
|
+
flattenedMarkdown += `## ${title}` + `\n\n`;
|
|
31696
|
+
flattenedMarkdown += content + `\n\n`; // <- [🧠] Maybe 3 new lines?
|
|
31697
|
+
}
|
|
31698
|
+
return spaceTrim$1(flattenedMarkdown);
|
|
31308
31699
|
}
|
|
31309
31700
|
/**
|
|
31310
|
-
*
|
|
31701
|
+
* TODO: [🏛] This can be part of markdown builder
|
|
31702
|
+
* Note: [🕞] In past (commit 42086e1603cbed506482997c00a8ee979af0a247) there was much more
|
|
31703
|
+
* sophisticated implementation of this function through parsing markdown into JSON structure
|
|
31704
|
+
* and flattening the actual structure
|
|
31705
|
+
* NOW we are working just with markdown string and its good enough
|
|
31706
|
+
*/
|
|
31707
|
+
|
|
31708
|
+
/**
|
|
31709
|
+
* Normalizes inline parameter mentions wrapped in code spans before markdown flattening.
|
|
31311
31710
|
*
|
|
31312
|
-
* @private internal utility of `
|
|
31711
|
+
* @private internal utility of `preparePipelineString`
|
|
31313
31712
|
*/
|
|
31314
|
-
|
|
31315
|
-
return {
|
|
31316
|
-
title: DEFAULT_BOOK_TITLE,
|
|
31317
|
-
parameters: [],
|
|
31318
|
-
tasks: [],
|
|
31319
|
-
knowledgeSources: [],
|
|
31320
|
-
knowledgePieces: [],
|
|
31321
|
-
personas: [],
|
|
31322
|
-
preparations: [],
|
|
31323
|
-
sources: [
|
|
31324
|
-
{
|
|
31325
|
-
type: 'BOOK',
|
|
31326
|
-
path: null,
|
|
31327
|
-
// <- TODO: !!6 Pass here path of the file
|
|
31328
|
-
content: pipelineString,
|
|
31329
|
-
},
|
|
31330
|
-
],
|
|
31331
|
-
};
|
|
31332
|
-
}
|
|
31713
|
+
const INLINE_CODE_PARAMETER_REGEXP = /`\{(?<parameterName>[a-z0-9_]+)\}`/gi;
|
|
31333
31714
|
/**
|
|
31334
|
-
*
|
|
31715
|
+
* Normalizes inline return statements wrapped in code spans before markdown flattening.
|
|
31335
31716
|
*
|
|
31336
|
-
* @private internal utility of `
|
|
31717
|
+
* @private internal utility of `preparePipelineString`
|
|
31337
31718
|
*/
|
|
31338
|
-
|
|
31339
|
-
// Note: This is a 😐 implementation of [🚞]
|
|
31340
|
-
const pipelineIdentificationParts = [];
|
|
31341
|
-
if ($pipelineJson.sourceFile !== undefined) {
|
|
31342
|
-
pipelineIdentificationParts.push(`File: ${$pipelineJson.sourceFile}`);
|
|
31343
|
-
}
|
|
31344
|
-
if ($pipelineJson.pipelineUrl !== undefined) {
|
|
31345
|
-
pipelineIdentificationParts.push(`Url: ${$pipelineJson.pipelineUrl}`);
|
|
31346
|
-
}
|
|
31347
|
-
return pipelineIdentificationParts.join('\n');
|
|
31348
|
-
}
|
|
31719
|
+
const INLINE_CODE_RETURN_PARAMETER_REGEXP = /`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi;
|
|
31349
31720
|
/**
|
|
31350
31721
|
* Removes shebang/comments and normalizes markdown into a parseable pipeline form.
|
|
31351
31722
|
*
|
|
@@ -31362,222 +31733,78 @@ function preparePipelineString(pipelineString, $pipelineJson) {
|
|
|
31362
31733
|
pipelineString = pipelineString.replaceAll(INLINE_CODE_RETURN_PARAMETER_REGEXP, '-> {$<parameterName>}');
|
|
31363
31734
|
return pipelineString;
|
|
31364
31735
|
}
|
|
31365
|
-
/**
|
|
31366
|
-
* Validates and removes the optional `#!` shebang line for `.book` files.
|
|
31367
|
-
*
|
|
31368
|
-
* @private internal utility of `
|
|
31369
|
-
*/
|
|
31370
|
-
function removePipelineShebang(pipelineString, $pipelineJson) {
|
|
31371
|
-
if (!pipelineString.startsWith('#!')) {
|
|
31372
|
-
return pipelineString;
|
|
31373
|
-
}
|
|
31374
|
-
const [shebangLine, ...restLines] = pipelineString.split(/\r?\n/);
|
|
31375
|
-
const isBookShebang = (shebangLine || '').includes('ptbk');
|
|
31376
|
-
if (!isBookShebang) {
|
|
31377
|
-
throw new ParseError(spaceTrim$1((block) => `
|
|
31378
|
-
It seems that you try to parse a book file which has non-standard shebang line for book files:
|
|
31379
|
-
Shebang line must contain 'ptbk'
|
|
31380
|
-
|
|
31381
|
-
You have:
|
|
31382
|
-
${block(shebangLine || '(empty line)')}
|
|
31383
|
-
|
|
31384
|
-
It should look like this:
|
|
31385
|
-
#!/usr/bin/env ptbk
|
|
31386
|
-
|
|
31387
|
-
${block(getPipelineIdentification($pipelineJson))}
|
|
31388
|
-
`));
|
|
31389
|
-
}
|
|
31390
|
-
return validatePipelineString(restLines.join('\n'));
|
|
31391
|
-
}
|
|
31392
|
-
/**
|
|
31393
|
-
* Splits the prepared markdown into the pipeline head and task sections.
|
|
31394
|
-
*
|
|
31395
|
-
* @private internal utility of `parsePipeline`
|
|
31396
|
-
*/
|
|
31397
|
-
function parsePreparedPipelineSections(pipelineString, $pipelineJson) {
|
|
31398
|
-
const [pipelineHead, ...pipelineSections] = splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection); /* <- Note: [🥞] */
|
|
31399
|
-
assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson);
|
|
31400
|
-
return {
|
|
31401
|
-
pipelineHead,
|
|
31402
|
-
pipelineSections,
|
|
31403
|
-
};
|
|
31404
|
-
}
|
|
31405
|
-
/**
|
|
31406
|
-
* Ensures the flattened markdown has exactly one h1 head followed by only h2 sections.
|
|
31407
|
-
*
|
|
31408
|
-
* @private internal utility of `parsePipeline`
|
|
31409
|
-
*/
|
|
31410
|
-
function assertPipelineSectionsStructure(pipelineHead, pipelineSections, $pipelineJson) {
|
|
31411
|
-
if (pipelineHead === undefined) {
|
|
31412
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
31413
|
-
Pipeline head is not defined
|
|
31414
|
-
|
|
31415
|
-
${block(getPipelineIdentification($pipelineJson))}
|
|
31416
|
-
|
|
31417
|
-
This should never happen, because the pipeline already flattened
|
|
31418
|
-
`));
|
|
31419
|
-
}
|
|
31420
|
-
if (pipelineHead.level !== 1) {
|
|
31421
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
31422
|
-
Pipeline head is not h1
|
|
31423
|
-
|
|
31424
|
-
${block(getPipelineIdentification($pipelineJson))}
|
|
31425
|
-
|
|
31426
|
-
This should never happen, because the pipeline already flattened
|
|
31427
|
-
`));
|
|
31428
|
-
}
|
|
31429
|
-
if (!pipelineSections.every((pipelineSection) => pipelineSection.level === 2)) {
|
|
31430
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
31431
|
-
Not every pipeline section is h2
|
|
31432
|
-
|
|
31433
|
-
${block(getPipelineIdentification($pipelineJson))}
|
|
31434
|
-
|
|
31435
|
-
This should never happen, because the pipeline already flattened
|
|
31436
|
-
`));
|
|
31437
|
-
}
|
|
31438
|
-
}
|
|
31439
|
-
/**
|
|
31440
|
-
* Applies the pipeline head title, description, and head-level commands.
|
|
31441
|
-
*
|
|
31442
|
-
* @private internal utility of `parsePipeline`
|
|
31443
|
-
*/
|
|
31444
|
-
function applyPipelineHead(pipelineHead, $pipelineJson) {
|
|
31445
|
-
$pipelineJson.title = pipelineHead.title;
|
|
31446
|
-
$pipelineJson.description = extractPipelineDescription(pipelineHead.content);
|
|
31447
|
-
for (const listItem of extractAllListItemsFromMarkdown(pipelineHead.content)) {
|
|
31448
|
-
applyPipelineHeadCommand(listItem, $pipelineJson);
|
|
31449
|
-
}
|
|
31450
|
-
}
|
|
31451
|
-
/**
|
|
31452
|
-
* Extracts the plain-text description from a head or task section body.
|
|
31453
|
-
*
|
|
31454
|
-
* @private internal utility of `parsePipeline`
|
|
31455
|
-
*/
|
|
31456
|
-
function extractPipelineDescription(sectionContent) {
|
|
31457
|
-
let description = sectionContent;
|
|
31458
|
-
description = description.split(DESCRIPTION_CODE_BLOCK_REGEXP).join('');
|
|
31459
|
-
description = description.split(DESCRIPTION_BLOCKQUOTE_REGEXP).join('');
|
|
31460
|
-
description = description.split(DESCRIPTION_LIST_ITEM_REGEXP).join('');
|
|
31461
|
-
description = spaceTrim$1(description);
|
|
31462
|
-
if (description === '') {
|
|
31463
|
-
return undefined;
|
|
31464
|
-
}
|
|
31465
|
-
return description;
|
|
31466
|
-
}
|
|
31467
|
-
/**
|
|
31468
|
-
* Parses and applies one command declared in the pipeline head.
|
|
31469
|
-
*
|
|
31470
|
-
* @private internal utility of `parsePipeline`
|
|
31471
|
-
*/
|
|
31472
|
-
function applyPipelineHeadCommand(listItem, $pipelineJson) {
|
|
31473
|
-
const command = parseCommand(listItem, 'PIPELINE_HEAD');
|
|
31474
|
-
const commandParser = getParserForCommand(command);
|
|
31475
|
-
if (commandParser.isUsedInPipelineHead !== true /* <- Note: [🦦][4] */) {
|
|
31476
|
-
throw new ParseError(spaceTrim$1((block) => `
|
|
31477
|
-
Command \`${command.type}\` is not allowed in the head of the pipeline ONLY at the pipeline task
|
|
31478
|
-
|
|
31479
|
-
${block(getPipelineIdentification($pipelineJson))}
|
|
31480
|
-
`)); // <- TODO: [🚞]
|
|
31481
|
-
}
|
|
31482
|
-
try {
|
|
31483
|
-
commandParser.$applyToPipelineJson(command, $pipelineJson);
|
|
31484
|
-
// <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitly
|
|
31736
|
+
/**
|
|
31737
|
+
* Validates and removes the optional `#!` shebang line for `.book` files.
|
|
31738
|
+
*
|
|
31739
|
+
* @private internal utility of `preparePipelineString`
|
|
31740
|
+
*/
|
|
31741
|
+
function removePipelineShebang(pipelineString, $pipelineJson) {
|
|
31742
|
+
if (!pipelineString.startsWith('#!')) {
|
|
31743
|
+
return pipelineString;
|
|
31485
31744
|
}
|
|
31486
|
-
|
|
31487
|
-
|
|
31488
|
-
|
|
31489
|
-
}
|
|
31745
|
+
const [shebangLine, ...restLines] = pipelineString.split(/\r?\n/);
|
|
31746
|
+
const isBookShebang = (shebangLine || '').includes('ptbk');
|
|
31747
|
+
if (!isBookShebang) {
|
|
31490
31748
|
throw new ParseError(spaceTrim$1((block) => `
|
|
31491
|
-
|
|
31492
|
-
|
|
31493
|
-
The error:
|
|
31494
|
-
${block(error.message)}
|
|
31749
|
+
It seems that you try to parse a book file which has non-standard shebang line for book files:
|
|
31750
|
+
Shebang line must contain 'ptbk'
|
|
31495
31751
|
|
|
31496
|
-
|
|
31497
|
-
|
|
31752
|
+
You have:
|
|
31753
|
+
${block(shebangLine || '(empty line)')}
|
|
31498
31754
|
|
|
31499
|
-
|
|
31500
|
-
|
|
31755
|
+
It should look like this:
|
|
31756
|
+
#!/usr/bin/env ptbk
|
|
31501
31757
|
|
|
31502
31758
|
${block(getPipelineIdentification($pipelineJson))}
|
|
31503
|
-
|
|
31504
|
-
}
|
|
31505
|
-
if (command.type === 'PARAMETER') {
|
|
31506
|
-
defineParameter($pipelineJson, command);
|
|
31507
|
-
// <- Note: [🍣]
|
|
31759
|
+
`));
|
|
31508
31760
|
}
|
|
31761
|
+
return validatePipelineString(restLines.join('\n'));
|
|
31509
31762
|
}
|
|
31763
|
+
|
|
31510
31764
|
/**
|
|
31511
|
-
*
|
|
31765
|
+
* Supported script languages
|
|
31512
31766
|
*
|
|
31513
|
-
* @private internal
|
|
31767
|
+
* @private internal base for `ScriptLanguage`
|
|
31514
31768
|
*/
|
|
31515
|
-
|
|
31516
|
-
|
|
31517
|
-
if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
|
|
31518
|
-
throw new ParseError(spaceTrim$1((block) => `
|
|
31519
|
-
Parameter name {${parameterName}} is reserved and cannot be used as resulting parameter name
|
|
31769
|
+
const SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
|
|
31770
|
+
// <- TODO: [🏥] DRY
|
|
31520
31771
|
|
|
31521
|
-
|
|
31522
|
-
|
|
31523
|
-
|
|
31524
|
-
|
|
31525
|
-
|
|
31526
|
-
|
|
31527
|
-
|
|
31528
|
-
|
|
31772
|
+
/**
|
|
31773
|
+
* Extracts exactly ONE code block from markdown.
|
|
31774
|
+
*
|
|
31775
|
+
* - When there are multiple or no code blocks the function throws a `ParseError`
|
|
31776
|
+
*
|
|
31777
|
+
* Note: There are multiple similar functions:
|
|
31778
|
+
* - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
|
|
31779
|
+
* - `extractJsonBlock` extracts exactly one valid JSON code block
|
|
31780
|
+
* - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
|
|
31781
|
+
* - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
|
|
31782
|
+
*
|
|
31783
|
+
* @param markdown any valid markdown
|
|
31784
|
+
* @returns code block with language and content
|
|
31785
|
+
* @throws {ParseError} if there is not exactly one code block in the markdown
|
|
31786
|
+
*
|
|
31787
|
+
* @public exported from `@promptbook/markdown-utils`
|
|
31788
|
+
*/
|
|
31789
|
+
function extractOneBlockFromMarkdown(markdown) {
|
|
31790
|
+
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
31791
|
+
if (codeBlocks.length !== 1) {
|
|
31529
31792
|
throw new ParseError(spaceTrim$1((block) => `
|
|
31530
|
-
|
|
31531
|
-
|
|
31532
|
-
${block(getPipelineIdentification($pipelineJson))}
|
|
31533
|
-
|
|
31534
|
-
First definition:
|
|
31535
|
-
${block(existingParameter.description || '[undefined]')}
|
|
31793
|
+
There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
|
|
31536
31794
|
|
|
31537
|
-
|
|
31538
|
-
${block(parameterDescription || '[undefined]')}
|
|
31795
|
+
${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
|
|
31539
31796
|
`));
|
|
31540
31797
|
}
|
|
31541
|
-
|
|
31542
|
-
if (parameterDescription) {
|
|
31543
|
-
existingParameter.description = parameterDescription;
|
|
31544
|
-
}
|
|
31545
|
-
existingParameter.isInput = existingParameter.isInput || isInput;
|
|
31546
|
-
existingParameter.isOutput = existingParameter.isOutput || isOutput;
|
|
31547
|
-
return;
|
|
31548
|
-
}
|
|
31549
|
-
$pipelineJson.parameters.push({
|
|
31550
|
-
name: parameterName,
|
|
31551
|
-
description: parameterDescription || undefined,
|
|
31552
|
-
isInput,
|
|
31553
|
-
isOutput,
|
|
31554
|
-
});
|
|
31798
|
+
return codeBlocks[0];
|
|
31555
31799
|
}
|
|
31800
|
+
// TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
|
|
31801
|
+
|
|
31556
31802
|
/**
|
|
31557
|
-
*
|
|
31803
|
+
* Matches the trailing return statement of a task section.
|
|
31558
31804
|
*
|
|
31559
|
-
* @private internal utility of `
|
|
31805
|
+
* @private internal utility of `processPipelineSection`
|
|
31560
31806
|
*/
|
|
31561
|
-
|
|
31562
|
-
const sectionCounts = {};
|
|
31563
|
-
for (const pipelineSection of pipelineSections) {
|
|
31564
|
-
const sectionName = titleToName(pipelineSection.title);
|
|
31565
|
-
if (sectionCounts[sectionName] === undefined) {
|
|
31566
|
-
sectionCounts[sectionName] = { count: 0, currentIndex: 0 };
|
|
31567
|
-
}
|
|
31568
|
-
sectionCounts[sectionName].count++;
|
|
31569
|
-
}
|
|
31570
|
-
return (title) => {
|
|
31571
|
-
const sectionName = titleToName(title);
|
|
31572
|
-
const sectionCount = sectionCounts[sectionName];
|
|
31573
|
-
if (sectionCount.count === 1) {
|
|
31574
|
-
return sectionName;
|
|
31575
|
-
}
|
|
31576
|
-
const nameWithSuffix = `${sectionName}-${sectionCount.currentIndex}`;
|
|
31577
|
-
sectionCount.currentIndex++;
|
|
31578
|
-
return nameWithSuffix;
|
|
31579
|
-
};
|
|
31580
|
-
}
|
|
31807
|
+
const RESULTING_PARAMETER_LINE_REGEXP = /^->\s*\{(?<resultingParamName>[a-z0-9_]+)\}/im;
|
|
31581
31808
|
/**
|
|
31582
31809
|
* Parses, applies, and persists one h2 task section.
|
|
31583
31810
|
*
|
|
@@ -31597,7 +31824,7 @@ function processPipelineSection(pipelineSection, $pipelineJson, getUniqueSection
|
|
|
31597
31824
|
/**
|
|
31598
31825
|
* Creates the mutable task JSON shell from one markdown section.
|
|
31599
31826
|
*
|
|
31600
|
-
* @private internal utility of `
|
|
31827
|
+
* @private internal utility of `processPipelineSection`
|
|
31601
31828
|
*/
|
|
31602
31829
|
function createTaskJsonFromSection(pipelineSection, getUniqueSectionName) {
|
|
31603
31830
|
const { language, content } = extractOneBlockFromMarkdown(pipelineSection.content);
|
|
@@ -31625,7 +31852,7 @@ function createTaskJsonFromSection(pipelineSection, getUniqueSectionName) {
|
|
|
31625
31852
|
/**
|
|
31626
31853
|
* Extracts the optional trailing `-> {parameter}` statement from a section body.
|
|
31627
31854
|
*
|
|
31628
|
-
* @private internal utility of `
|
|
31855
|
+
* @private internal utility of `processPipelineSection`
|
|
31629
31856
|
*/
|
|
31630
31857
|
function extractResultingParameterName(sectionContent) {
|
|
31631
31858
|
var _a;
|
|
@@ -31636,7 +31863,7 @@ function extractResultingParameterName(sectionContent) {
|
|
|
31636
31863
|
/**
|
|
31637
31864
|
* Parses all list-item commands declared inside one task section.
|
|
31638
31865
|
*
|
|
31639
|
-
* @private internal utility of `
|
|
31866
|
+
* @private internal utility of `processPipelineSection`
|
|
31640
31867
|
*/
|
|
31641
31868
|
function parsePipelineTaskCommands(sectionContent) {
|
|
31642
31869
|
return extractAllListItemsFromMarkdown(sectionContent).map((listItem) => ({
|
|
@@ -31647,7 +31874,7 @@ function parsePipelineTaskCommands(sectionContent) {
|
|
|
31647
31874
|
/**
|
|
31648
31875
|
* Applies the implicit default `PROMPT_TASK` section type when no SECTION command is present.
|
|
31649
31876
|
*
|
|
31650
|
-
* @private internal utility of `
|
|
31877
|
+
* @private internal utility of `processPipelineSection`
|
|
31651
31878
|
*/
|
|
31652
31879
|
function applyDefaultTaskSectionType($taskJson, commands, $pipelineJson) {
|
|
31653
31880
|
const isSectionCommandPresent = commands.some(({ command }) => command.type === 'SECTION');
|
|
@@ -31659,7 +31886,7 @@ function applyDefaultTaskSectionType($taskJson, commands, $pipelineJson) {
|
|
|
31659
31886
|
/**
|
|
31660
31887
|
* Parses and applies one command declared inside a task section.
|
|
31661
31888
|
*
|
|
31662
|
-
* @private internal utility of `
|
|
31889
|
+
* @private internal utility of `processPipelineSection`
|
|
31663
31890
|
*/
|
|
31664
31891
|
function applyPipelineTaskCommand(commandItem, $taskJson, $pipelineJson) {
|
|
31665
31892
|
const { listItem, command } = commandItem;
|
|
@@ -31710,7 +31937,7 @@ function applyPipelineTaskCommand(commandItem, $taskJson, $pipelineJson) {
|
|
|
31710
31937
|
/**
|
|
31711
31938
|
* Validates and stores the language for SCRIPT tasks.
|
|
31712
31939
|
*
|
|
31713
|
-
* @private internal utility of `
|
|
31940
|
+
* @private internal utility of `processPipelineSection`
|
|
31714
31941
|
*/
|
|
31715
31942
|
function applyScriptTaskLanguage($taskJson, language, $pipelineJson) {
|
|
31716
31943
|
const isScriptTask = $taskJson.taskType === 'SCRIPT_TASK';
|
|
@@ -31727,7 +31954,6 @@ function applyScriptTaskLanguage($taskJson, language, $pipelineJson) {
|
|
|
31727
31954
|
if (!SUPPORTED_SCRIPT_LANGUAGES.includes(language)) {
|
|
31728
31955
|
throw new ParseError(spaceTrim$1((block) => `
|
|
31729
31956
|
Script language ${language} is not supported.
|
|
31730
|
-
|
|
31731
31957
|
Supported languages are:
|
|
31732
31958
|
${block(SUPPORTED_SCRIPT_LANGUAGES.join(', '))}
|
|
31733
31959
|
|
|
@@ -31738,7 +31964,7 @@ function applyScriptTaskLanguage($taskJson, language, $pipelineJson) {
|
|
|
31738
31964
|
/**
|
|
31739
31965
|
* Extracts task dependencies and ensures referenced parameters exist.
|
|
31740
31966
|
*
|
|
31741
|
-
* @private internal utility of `
|
|
31967
|
+
* @private internal utility of `processPipelineSection`
|
|
31742
31968
|
*/
|
|
31743
31969
|
function registerTaskDependentParameters($taskJson, $pipelineJson) {
|
|
31744
31970
|
$taskJson.dependentParameterNames = Array.from(extractParameterNamesFromTask($taskJson));
|
|
@@ -31756,7 +31982,7 @@ function registerTaskDependentParameters($taskJson, $pipelineJson) {
|
|
|
31756
31982
|
/**
|
|
31757
31983
|
* Removes transient parsing flags and persists real tasks into the pipeline JSON.
|
|
31758
31984
|
*
|
|
31759
|
-
* @private internal utility of `
|
|
31985
|
+
* @private internal utility of `processPipelineSection`
|
|
31760
31986
|
*/
|
|
31761
31987
|
function persistTaskIfNeeded($taskJson, $pipelineJson) {
|
|
31762
31988
|
/*
|
|
@@ -31785,119 +32011,38 @@ function persistTaskIfNeeded($taskJson, $pipelineJson) {
|
|
|
31785
32011
|
// TODO: [🍙] Maybe do reorder of `$taskJson` here
|
|
31786
32012
|
$pipelineJson.tasks.push($taskJson);
|
|
31787
32013
|
}
|
|
32014
|
+
|
|
31788
32015
|
/**
|
|
31789
|
-
*
|
|
31790
|
-
*
|
|
31791
|
-
* @private internal utility of `parsePipeline`
|
|
31792
|
-
*/
|
|
31793
|
-
function applyImplicitParameterDirections($pipelineJson) {
|
|
31794
|
-
markImplicitInputParameters($pipelineJson);
|
|
31795
|
-
markImplicitOutputParameters($pipelineJson);
|
|
31796
|
-
}
|
|
31797
|
-
/**
|
|
31798
|
-
* Marks non-result parameters as pipeline inputs when no input was declared.
|
|
31799
|
-
*
|
|
31800
|
-
* @private internal utility of `parsePipeline`
|
|
31801
|
-
*/
|
|
31802
|
-
function markImplicitInputParameters($pipelineJson) {
|
|
31803
|
-
if ($pipelineJson.parameters.some((parameter) => parameter.isInput)) {
|
|
31804
|
-
return;
|
|
31805
|
-
}
|
|
31806
|
-
for (const parameter of $pipelineJson.parameters) {
|
|
31807
|
-
const isThisParameterResulting = $pipelineJson.tasks.some((task) => task.resultingParameterName === parameter.name);
|
|
31808
|
-
if (!isThisParameterResulting) {
|
|
31809
|
-
parameter.isInput = true;
|
|
31810
|
-
// <- TODO: [💔] Why this is making typescript error in vscode but not in cli
|
|
31811
|
-
// > Type 'true' is not assignable to type 'false'.ts(2322)
|
|
31812
|
-
// > (property) isInput: false
|
|
31813
|
-
// > The parameter is input of the pipeline The parameter is NOT input of the pipeline
|
|
31814
|
-
}
|
|
31815
|
-
}
|
|
31816
|
-
}
|
|
31817
|
-
/**
|
|
31818
|
-
* Marks every non-input parameter as output when no output was declared.
|
|
31819
|
-
*
|
|
31820
|
-
* @private internal utility of `parsePipeline`
|
|
31821
|
-
*/
|
|
31822
|
-
function markImplicitOutputParameters($pipelineJson) {
|
|
31823
|
-
if ($pipelineJson.parameters.some((parameter) => parameter.isOutput)) {
|
|
31824
|
-
return;
|
|
31825
|
-
}
|
|
31826
|
-
for (const parameter of $pipelineJson.parameters) {
|
|
31827
|
-
if (!parameter.isInput) {
|
|
31828
|
-
parameter.isOutput = true;
|
|
31829
|
-
// <- TODO: [💔]
|
|
31830
|
-
}
|
|
31831
|
-
}
|
|
31832
|
-
}
|
|
31833
|
-
/**
|
|
31834
|
-
* Removes `undefined` properties from serialized tasks and parameters.
|
|
32016
|
+
* Compile pipeline from string (markdown) format to JSON format synchronously
|
|
31835
32017
|
*
|
|
31836
|
-
*
|
|
31837
|
-
|
|
31838
|
-
|
|
31839
|
-
|
|
31840
|
-
$pipelineJson.parameters.forEach(removeUndefinedProperties);
|
|
31841
|
-
}
|
|
31842
|
-
/**
|
|
31843
|
-
* Deletes all own properties with `undefined` values from a mutable JSON entity.
|
|
32018
|
+
* Note: There are 3 similar functions:
|
|
32019
|
+
* - `compilePipeline` **(preferred)** - which properly compiles the promptbook and uses embedding for external knowledge
|
|
32020
|
+
* - `parsePipeline` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
|
|
32021
|
+
* - `preparePipeline` - just one step in the compilation process
|
|
31844
32022
|
*
|
|
31845
|
-
*
|
|
31846
|
-
|
|
31847
|
-
function removeUndefinedProperties(entity) {
|
|
31848
|
-
for (const [key, value] of Object.entries(entity)) {
|
|
31849
|
-
if (value === undefined) {
|
|
31850
|
-
delete entity[key];
|
|
31851
|
-
}
|
|
31852
|
-
}
|
|
31853
|
-
}
|
|
31854
|
-
/**
|
|
31855
|
-
* Applies all sync-only high-level abstractions after parsing.
|
|
32023
|
+
* Note: This function does not validate logic of the pipeline only the parsing
|
|
32024
|
+
* Note: This function acts as compilation process
|
|
31856
32025
|
*
|
|
31857
|
-
* @
|
|
31858
|
-
|
|
31859
|
-
|
|
31860
|
-
for (const highLevelAbstraction of HIGH_LEVEL_ABSTRACTIONS.filter(({ type }) => type === 'SYNC')) {
|
|
31861
|
-
highLevelAbstraction.$applyToPipelineJson($pipelineJson);
|
|
31862
|
-
}
|
|
31863
|
-
}
|
|
31864
|
-
/**
|
|
31865
|
-
* Ensures parsed pipelines always have the default `GENERIC` formfactor.
|
|
32026
|
+
* @param pipelineString {Promptbook} in string markdown format (.book.md)
|
|
32027
|
+
* @returns {Promptbook} compiled in JSON format (.bookc)
|
|
32028
|
+
* @throws {ParseError} if the promptbook string is not valid
|
|
31866
32029
|
*
|
|
31867
|
-
* @
|
|
32030
|
+
* @public exported from `@promptbook/core`
|
|
31868
32031
|
*/
|
|
31869
|
-
function
|
|
31870
|
-
|
|
31871
|
-
|
|
31872
|
-
|
|
32032
|
+
function parsePipeline(pipelineString) {
|
|
32033
|
+
const $pipelineJson = createInitialPipelineJson(pipelineString);
|
|
32034
|
+
const preparedPipelineString = preparePipelineString(pipelineString, $pipelineJson);
|
|
32035
|
+
const { pipelineHead, pipelineSections } = parsePreparedPipelineSections(preparedPipelineString, $pipelineJson);
|
|
32036
|
+
const getUniqueSectionName = createUniqueSectionNameResolver(pipelineSections);
|
|
32037
|
+
applyPipelineHead(pipelineHead, $pipelineJson);
|
|
32038
|
+
for (const pipelineSection of pipelineSections) {
|
|
32039
|
+
processPipelineSection(pipelineSection, $pipelineJson, getUniqueSectionName);
|
|
31873
32040
|
}
|
|
31874
|
-
|
|
31875
|
-
/**
|
|
31876
|
-
* Finalizes ordering and exports the parsed pipeline JSON.
|
|
31877
|
-
*
|
|
31878
|
-
* @private internal utility of `parsePipeline`
|
|
31879
|
-
*/
|
|
31880
|
-
function exportParsedPipelineJson($pipelineJson) {
|
|
31881
|
-
return exportJson({
|
|
31882
|
-
name: 'pipelineJson',
|
|
31883
|
-
message: `Result of \`parsePipeline\``,
|
|
31884
|
-
order: ORDER_OF_PIPELINE_JSON,
|
|
31885
|
-
value: {
|
|
31886
|
-
formfactorName: 'GENERIC',
|
|
31887
|
-
// <- Note: [🔆] Setting `formfactorName` is redundant to satisfy the typescript
|
|
31888
|
-
...$pipelineJson,
|
|
31889
|
-
},
|
|
31890
|
-
});
|
|
32041
|
+
return finalizeParsedPipeline($pipelineJson);
|
|
31891
32042
|
}
|
|
31892
32043
|
// TODO: [🧠] Maybe more things here can be refactored as high-level abstractions
|
|
31893
32044
|
// TODO: [main] !!4 Warn if used only sync version
|
|
31894
32045
|
// TODO: [🚞] Report here line/column of error
|
|
31895
|
-
// TODO: Use spaceTrim more effectively
|
|
31896
|
-
// TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
|
|
31897
|
-
// TODO: [🥞] Not optimal parsing because `splitMarkdownIntoSections` is executed twice with same string, once through `flattenMarkdown` and second directly here
|
|
31898
|
-
// TODO: [♈] Probably move expectations from tasks to parameters
|
|
31899
|
-
// TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
|
|
31900
|
-
// TODO: [🍙] Make some standard order of json properties
|
|
31901
32046
|
|
|
31902
32047
|
/**
|
|
31903
32048
|
* Compile pipeline from string (markdown) format to JSON format
|