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