@promptbook/wizard 0.100.0-1 → 0.100.0-11
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 +155 -78
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/config.d.ts +0 -10
- package/esm/typings/src/version.d.ts +1 -1
- package/esm/typings/src/wizard/wizard.d.ts +14 -4
- package/package.json +2 -2
- package/umd/index.umd.js +155 -78
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/remote-server/connection-improvements.test.d.ts +0 -1
- package/esm/typings/src/remote-server/utils/connectionProgress.d.ts +0 -72
package/esm/index.es.js
CHANGED
@@ -38,7 +38,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
38
38
|
* @generated
|
39
39
|
* @see https://github.com/webgptorg/promptbook
|
40
40
|
*/
|
41
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.100.0-
|
41
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.100.0-11';
|
42
42
|
/**
|
43
43
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
44
44
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
@@ -192,12 +192,9 @@ const SMALL_NUMBER = 0.001;
|
|
192
192
|
/**
|
193
193
|
* Timeout for the connections in milliseconds
|
194
194
|
*
|
195
|
-
* Note: Increased from 7 seconds to 30 seconds to accommodate OAuth flows
|
196
|
-
* like Facebook login which may require user interaction and redirects
|
197
|
-
*
|
198
195
|
* @private within the repository - too low-level in comparison with other `MAX_...`
|
199
196
|
*/
|
200
|
-
const CONNECTION_TIMEOUT_MS =
|
197
|
+
const CONNECTION_TIMEOUT_MS = 7 * 1000;
|
201
198
|
// <- TODO: [⏳] Standardize timeouts, Make DEFAULT_TIMEOUT_MS as global constant
|
202
199
|
/**
|
203
200
|
* How many times to retry the connections
|
@@ -1389,39 +1386,13 @@ async function createRemoteClient(options) {
|
|
1389
1386
|
transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
|
1390
1387
|
});
|
1391
1388
|
// console.log('Connecting to', this.options.remoteServerUrl.href, { socket });
|
1392
|
-
let isResolved = false;
|
1393
1389
|
socket.on('connect', () => {
|
1394
|
-
|
1395
|
-
isResolved = true;
|
1396
|
-
resolve(socket);
|
1397
|
-
}
|
1398
|
-
});
|
1399
|
-
socket.on('connect_error', (error) => {
|
1400
|
-
if (!isResolved) {
|
1401
|
-
isResolved = true;
|
1402
|
-
reject(new Error(`Failed to connect to ${remoteServerUrl}: ${error.message || error}`));
|
1403
|
-
}
|
1404
|
-
});
|
1405
|
-
socket.on('disconnect', (reason) => {
|
1406
|
-
if (!isResolved) {
|
1407
|
-
isResolved = true;
|
1408
|
-
reject(new Error(`Connection to ${remoteServerUrl} was disconnected: ${reason}`));
|
1409
|
-
}
|
1390
|
+
resolve(socket);
|
1410
1391
|
});
|
1411
|
-
// Better timeout handling
|
1412
|
-
|
1413
|
-
|
1414
|
-
isResolved = true;
|
1415
|
-
socket.disconnect();
|
1416
|
-
reject(new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS / 1000} seconds while connecting to ${remoteServerUrl}. ` +
|
1417
|
-
`This may indicate network issues or the server may be experiencing high load. ` +
|
1418
|
-
`For authentication flows like social login, ensure sufficient time is allowed for user interaction.`));
|
1419
|
-
}
|
1392
|
+
// TODO: [💩] Better timeout handling
|
1393
|
+
setTimeout(() => {
|
1394
|
+
reject(new Error(`Timeout while connecting to ${remoteServerUrl}`));
|
1420
1395
|
}, CONNECTION_TIMEOUT_MS);
|
1421
|
-
// Clean up timeout if connection succeeds
|
1422
|
-
socket.on('connect', () => {
|
1423
|
-
clearTimeout(timeoutId);
|
1424
|
-
});
|
1425
1396
|
});
|
1426
1397
|
}
|
1427
1398
|
|
@@ -1467,33 +1438,8 @@ class RemoteLlmExecutionTools {
|
|
1467
1438
|
* Check the configuration of all execution tools
|
1468
1439
|
*/
|
1469
1440
|
async checkConfiguration() {
|
1470
|
-
|
1471
|
-
|
1472
|
-
socket.disconnect();
|
1473
|
-
}
|
1474
|
-
catch (error) {
|
1475
|
-
if (error instanceof Error) {
|
1476
|
-
// Provide user-friendly error messages for common connection issues
|
1477
|
-
if (error.message.includes('timeout') || error.message.includes('Timeout')) {
|
1478
|
-
throw new Error(`Connection to Promptbook server timed out. This may happen during authentication flows like Facebook login. ` +
|
1479
|
-
`Please ensure: 1) Server is running at ${this.options.remoteServerUrl}, ` +
|
1480
|
-
`2) Network connection is stable, 3) Authentication process is completed within the timeout period. ` +
|
1481
|
-
`Original error: ${error.message}`);
|
1482
|
-
}
|
1483
|
-
if (error.message.includes('connect') || error.message.includes('ECONNREFUSED')) {
|
1484
|
-
throw new Error(`Cannot connect to Promptbook server at ${this.options.remoteServerUrl}. ` +
|
1485
|
-
`Please check if the server is running and accessible. ` +
|
1486
|
-
`Original error: ${error.message}`);
|
1487
|
-
}
|
1488
|
-
if (error.message.includes('authentication') || error.message.includes('auth')) {
|
1489
|
-
throw new Error(`Authentication failed when connecting to Promptbook server. ` +
|
1490
|
-
`This may happen if social login (like Facebook) was not completed properly. ` +
|
1491
|
-
`Please retry the authentication process. ` +
|
1492
|
-
`Original error: ${error.message}`);
|
1493
|
-
}
|
1494
|
-
}
|
1495
|
-
throw error; // Re-throw if not a recognized error pattern
|
1496
|
-
}
|
1441
|
+
const socket = await createRemoteClient(this.options);
|
1442
|
+
socket.disconnect();
|
1497
1443
|
// TODO: [main] !!3 Check version of the remote server and compatibility
|
1498
1444
|
// TODO: [🎍] Send checkConfiguration
|
1499
1445
|
}
|
@@ -6017,7 +5963,23 @@ async function getScraperIntermediateSource(source, options) {
|
|
6017
5963
|
.join('/') +
|
6018
5964
|
'.' +
|
6019
5965
|
extension;
|
6020
|
-
|
5966
|
+
// Note: Try to create cache directory, but don't fail if filesystem has issues
|
5967
|
+
try {
|
5968
|
+
await mkdir(dirname(cacheFilename), { recursive: true });
|
5969
|
+
}
|
5970
|
+
catch (error) {
|
5971
|
+
// Note: If we can't create cache directory, continue without it
|
5972
|
+
// This handles read-only filesystems, permission issues, and missing parent directories
|
5973
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
5974
|
+
error.message.includes('read-only') ||
|
5975
|
+
error.message.includes('EACCES') ||
|
5976
|
+
error.message.includes('EPERM') ||
|
5977
|
+
error.message.includes('ENOENT'))) ;
|
5978
|
+
else {
|
5979
|
+
// Re-throw other unexpected errors
|
5980
|
+
throw error;
|
5981
|
+
}
|
5982
|
+
}
|
6021
5983
|
let isDestroyed = true;
|
6022
5984
|
const fileHandler = {
|
6023
5985
|
filename: cacheFilename,
|
@@ -7781,12 +7743,58 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
7781
7743
|
// <- TODO: [🥬] Encapsulate sha256 to some private utility function
|
7782
7744
|
const rootDirname = join(process.cwd(), DEFAULT_DOWNLOAD_CACHE_DIRNAME);
|
7783
7745
|
const filepath = join(...nameToSubfolderPath(hash /* <- TODO: [🎎] Maybe add some SHA256 prefix */), `${basename.substring(0, MAX_FILENAME_LENGTH)}.${mimeTypeToExtension(mimeType)}`);
|
7784
|
-
|
7746
|
+
// Note: Try to create cache directory, but don't fail if filesystem has issues
|
7747
|
+
try {
|
7748
|
+
await tools.fs.mkdir(dirname(join(rootDirname, filepath)), { recursive: true });
|
7749
|
+
}
|
7750
|
+
catch (error) {
|
7751
|
+
// Note: If we can't create cache directory, we'll handle it when trying to write the file
|
7752
|
+
// This handles read-only filesystems, permission issues, and missing parent directories
|
7753
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
7754
|
+
error.message.includes('read-only') ||
|
7755
|
+
error.message.includes('EACCES') ||
|
7756
|
+
error.message.includes('EPERM') ||
|
7757
|
+
error.message.includes('ENOENT'))) ;
|
7758
|
+
else {
|
7759
|
+
// Re-throw other unexpected errors
|
7760
|
+
throw error;
|
7761
|
+
}
|
7762
|
+
}
|
7785
7763
|
const fileContent = Buffer.from(await response.arrayBuffer());
|
7786
7764
|
if (fileContent.length > DEFAULT_MAX_FILE_SIZE /* <- TODO: Allow to pass different value to remote server */) {
|
7787
7765
|
throw new LimitReachedError(`File is too large (${Math.round(fileContent.length / 1024 / 1024)}MB). Maximum allowed size is ${Math.round(DEFAULT_MAX_FILE_SIZE / 1024 / 1024)}MB.`);
|
7788
7766
|
}
|
7789
|
-
|
7767
|
+
// Note: Try to cache the downloaded file, but don't fail if the filesystem is read-only
|
7768
|
+
try {
|
7769
|
+
await tools.fs.writeFile(join(rootDirname, filepath), fileContent);
|
7770
|
+
}
|
7771
|
+
catch (error) {
|
7772
|
+
// Note: If we can't write to cache, we'll process the file directly from memory
|
7773
|
+
// This handles read-only filesystems like Vercel
|
7774
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
7775
|
+
error.message.includes('read-only') ||
|
7776
|
+
error.message.includes('EACCES') ||
|
7777
|
+
error.message.includes('EPERM') ||
|
7778
|
+
error.message.includes('ENOENT'))) {
|
7779
|
+
// Return a handler that works directly with the downloaded content
|
7780
|
+
return {
|
7781
|
+
source: name,
|
7782
|
+
filename: null,
|
7783
|
+
url,
|
7784
|
+
mimeType,
|
7785
|
+
async asJson() {
|
7786
|
+
return JSON.parse(fileContent.toString('utf-8'));
|
7787
|
+
},
|
7788
|
+
async asText() {
|
7789
|
+
return fileContent.toString('utf-8');
|
7790
|
+
},
|
7791
|
+
};
|
7792
|
+
}
|
7793
|
+
else {
|
7794
|
+
// Re-throw other unexpected errors
|
7795
|
+
throw error;
|
7796
|
+
}
|
7797
|
+
}
|
7790
7798
|
// TODO: [💵] Check the file security
|
7791
7799
|
// TODO: [🧹][🧠] Delete the file after the scraping is done
|
7792
7800
|
return makeKnowledgeSourceHandler({ name, knowledgeSourceContent: filepath }, tools, {
|
@@ -10864,7 +10872,23 @@ class MarkitdownScraper {
|
|
10864
10872
|
// <- TODO: [🍀] Make MarkitdownError
|
10865
10873
|
}
|
10866
10874
|
// console.log('!!', { result, cacheFilehandler });
|
10867
|
-
|
10875
|
+
// Note: Try to cache the converted content, but don't fail if the filesystem is read-only
|
10876
|
+
try {
|
10877
|
+
await this.tools.fs.writeFile(cacheFilehandler.filename, result.text_content);
|
10878
|
+
}
|
10879
|
+
catch (error) {
|
10880
|
+
// Note: If we can't write to cache, we'll continue without caching
|
10881
|
+
// This handles read-only filesystems like Vercel
|
10882
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
10883
|
+
error.message.includes('read-only') ||
|
10884
|
+
error.message.includes('EACCES') ||
|
10885
|
+
error.message.includes('EPERM') ||
|
10886
|
+
error.message.includes('ENOENT'))) ;
|
10887
|
+
else {
|
10888
|
+
// Re-throw other unexpected errors
|
10889
|
+
throw error;
|
10890
|
+
}
|
10891
|
+
}
|
10868
10892
|
}
|
10869
10893
|
return cacheFilehandler;
|
10870
10894
|
}
|
@@ -11152,7 +11176,23 @@ class WebsiteScraper {
|
|
11152
11176
|
extension: 'html',
|
11153
11177
|
isVerbose,
|
11154
11178
|
});
|
11155
|
-
|
11179
|
+
// Note: Try to cache the scraped content, but don't fail if the filesystem is read-only
|
11180
|
+
try {
|
11181
|
+
await this.tools.fs.writeFile(cacheFilehandler.filename, html, 'utf-8');
|
11182
|
+
}
|
11183
|
+
catch (error) {
|
11184
|
+
// Note: If we can't write to cache, we'll continue without caching
|
11185
|
+
// This handles read-only filesystems like Vercel
|
11186
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
11187
|
+
error.message.includes('read-only') ||
|
11188
|
+
error.message.includes('EACCES') ||
|
11189
|
+
error.message.includes('EPERM') ||
|
11190
|
+
error.message.includes('ENOENT'))) ;
|
11191
|
+
else {
|
11192
|
+
// Re-throw other unexpected errors
|
11193
|
+
throw error;
|
11194
|
+
}
|
11195
|
+
}
|
11156
11196
|
const markdown = this.showdownConverter.makeMarkdown(html, jsdom.window.document);
|
11157
11197
|
return { ...cacheFilehandler, markdown };
|
11158
11198
|
}
|
@@ -11893,8 +11933,27 @@ class FileCacheStorage {
|
|
11893
11933
|
throw new UnexpectedError(`The "${key}" you want to store in JSON file is not serializable as JSON`);
|
11894
11934
|
}
|
11895
11935
|
const fileContent = stringifyPipelineJson(value);
|
11896
|
-
|
11897
|
-
|
11936
|
+
// Note: Try to create cache directory and write file, but don't fail if filesystem is read-only or has permission issues
|
11937
|
+
try {
|
11938
|
+
await mkdir(dirname(filename), { recursive: true }); // <- [0]
|
11939
|
+
await writeFile(filename, fileContent, 'utf-8');
|
11940
|
+
}
|
11941
|
+
catch (error) {
|
11942
|
+
// Note: If we can't write to cache, silently ignore the error
|
11943
|
+
// This handles read-only filesystems, permission issues, and missing parent directories
|
11944
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
11945
|
+
error.message.includes('read-only') ||
|
11946
|
+
error.message.includes('EACCES') ||
|
11947
|
+
error.message.includes('EPERM') ||
|
11948
|
+
error.message.includes('ENOENT'))) {
|
11949
|
+
// Silently ignore filesystem errors - caching is optional
|
11950
|
+
return;
|
11951
|
+
}
|
11952
|
+
else {
|
11953
|
+
// Re-throw other unexpected errors
|
11954
|
+
throw error;
|
11955
|
+
}
|
11956
|
+
}
|
11898
11957
|
}
|
11899
11958
|
/**
|
11900
11959
|
* Removes the key/value pair with the given key from the storage, if a key/value pair with the given key exists.
|
@@ -16764,7 +16823,23 @@ async function $getCompiledBook(tools, pipelineSource, options) {
|
|
16764
16823
|
...options,
|
16765
16824
|
});
|
16766
16825
|
const compiledFilePath = filePath.replace('.book.md', '.book').replace('.book', '.bookc');
|
16767
|
-
|
16826
|
+
// Note: Try to save the compiled book to disk for caching, but don't fail if the filesystem is read-only
|
16827
|
+
try {
|
16828
|
+
await saveArchive(compiledFilePath, [pipelineJson], fs);
|
16829
|
+
}
|
16830
|
+
catch (error) {
|
16831
|
+
// Note: Ignore filesystem errors (like EROFS on read-only systems like Vercel)
|
16832
|
+
// The compiled book can still be used even if it can't be cached
|
16833
|
+
if (error instanceof Error && (error.message.includes('EROFS') ||
|
16834
|
+
error.message.includes('read-only') ||
|
16835
|
+
error.message.includes('EACCES') ||
|
16836
|
+
error.message.includes('EPERM') ||
|
16837
|
+
error.message.includes('ENOENT'))) ;
|
16838
|
+
else {
|
16839
|
+
// Re-throw other unexpected errors
|
16840
|
+
throw error;
|
16841
|
+
}
|
16842
|
+
}
|
16768
16843
|
return pipelineJson;
|
16769
16844
|
}
|
16770
16845
|
}
|
@@ -16886,14 +16961,14 @@ class Wizard {
|
|
16886
16961
|
*
|
16887
16962
|
* Note: This works similar to the `ptbk run` command
|
16888
16963
|
*/
|
16889
|
-
async execute(book, inputParameters) {
|
16964
|
+
async execute(book, inputParameters, options = {}) {
|
16890
16965
|
if (!$isRunningInNode()) {
|
16891
16966
|
throw new EnvironmentMismatchError('Wizard works only in Node.js environment');
|
16892
16967
|
}
|
16893
16968
|
// ▶ Get the tools
|
16894
|
-
const tools = await this.getExecutionTools();
|
16969
|
+
const tools = await this.getExecutionTools(options);
|
16895
16970
|
// ▶ Get the Pipeline
|
16896
|
-
const pipeline = await this.getCompiledBook(book);
|
16971
|
+
const pipeline = await this.getCompiledBook(book, options);
|
16897
16972
|
// ▶ Create executor - the function that will execute the Pipeline
|
16898
16973
|
const pipelineExecutor = createPipelineExecutor({ pipeline, tools });
|
16899
16974
|
// 🚀▶ Execute the Pipeline
|
@@ -16916,15 +16991,16 @@ class Wizard {
|
|
16916
16991
|
/**
|
16917
16992
|
* Provides the tools automatically for the Node.js environment
|
16918
16993
|
*
|
16919
|
-
* @param
|
16994
|
+
* @param options
|
16920
16995
|
*/
|
16921
|
-
async getExecutionTools() {
|
16996
|
+
async getExecutionTools(options = {}) {
|
16997
|
+
var _a;
|
16922
16998
|
if (this.executionTools !== null) {
|
16923
16999
|
return this.executionTools;
|
16924
17000
|
}
|
16925
17001
|
// TODO: DRY [◽]
|
16926
17002
|
const prepareAndScrapeOptions = {
|
16927
|
-
isVerbose: false,
|
17003
|
+
isVerbose: (_a = options.isVerbose) !== null && _a !== void 0 ? _a : false,
|
16928
17004
|
isCacheReloaded: false, // <- TODO: Allow to pass
|
16929
17005
|
}; /* <- TODO: ` satisfies PrepareAndScrapeOptions` */
|
16930
17006
|
const fs = $provideFilesystemForNode();
|
@@ -16954,9 +17030,10 @@ class Wizard {
|
|
16954
17030
|
* 3) As a string
|
16955
17031
|
*
|
16956
17032
|
* @param pipelineSource
|
17033
|
+
* @param options
|
16957
17034
|
*/
|
16958
|
-
async getCompiledBook(pipelineSource) {
|
16959
|
-
const tools = await this.getExecutionTools();
|
17035
|
+
async getCompiledBook(pipelineSource, options = {}) {
|
17036
|
+
const tools = await this.getExecutionTools(options);
|
16960
17037
|
return /* not await */ $getCompiledBook(tools, pipelineSource);
|
16961
17038
|
}
|
16962
17039
|
}
|