@promptbook/remote-server 0.100.0 โ†’ 0.100.2

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 CHANGED
@@ -9,7 +9,7 @@ import { forTime } from 'waitasecond';
9
9
  import { randomBytes } from 'crypto';
10
10
  import { spawn } from 'child_process';
11
11
  import { stat, access, constants, readFile, writeFile, readdir, mkdir } from 'fs/promises';
12
- import { join, basename, dirname } from 'path';
12
+ import { join, basename, dirname, isAbsolute } from 'path';
13
13
  import { Subject } from 'rxjs';
14
14
  import parserHtml from 'prettier/parser-html';
15
15
  import parserMarkdown from 'prettier/parser-markdown';
@@ -34,7 +34,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
34
34
  * @generated
35
35
  * @see https://github.com/webgptorg/promptbook
36
36
  */
37
- const PROMPTBOOK_ENGINE_VERSION = '0.100.0';
37
+ const PROMPTBOOK_ENGINE_VERSION = '0.100.2';
38
38
  /**
39
39
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
40
40
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
@@ -2280,7 +2280,7 @@ function isValidEmail(email) {
2280
2280
  }
2281
2281
 
2282
2282
  /**
2283
- * Tests if given string is valid URL.
2283
+ * Tests if given string is valid file path.
2284
2284
  *
2285
2285
  * Note: This does not check if the file exists only if the path is valid
2286
2286
  * @public exported from `@promptbook/utils`
@@ -2292,18 +2292,25 @@ function isValidFilePath(filename) {
2292
2292
  if (filename.split('\n').length > 1) {
2293
2293
  return false;
2294
2294
  }
2295
- if (filename.split(' ').length >
2296
- 5 /* <- TODO: [๐Ÿง ][๐Ÿˆท] Make some better non-arbitrary way how to distinct filenames from informational texts */) {
2295
+ // Normalize slashes early so heuristics can detect path-like inputs
2296
+ const filenameSlashes = filename.replace(/\\/g, '/');
2297
+ // Reject strings that look like sentences (informational text)
2298
+ // Heuristic: contains multiple spaces and ends with a period, or contains typical sentence punctuation
2299
+ // But skip this heuristic if the string looks like a path (contains '/' or starts with a drive letter)
2300
+ if (filename.trim().length > 60 && // long enough to be a sentence
2301
+ /[.!?]/.test(filename) && // contains sentence punctuation
2302
+ filename.split(' ').length > 8 && // has many words
2303
+ !/\/|^[A-Z]:/i.test(filenameSlashes) // do NOT treat as sentence if looks like a path
2304
+ ) {
2297
2305
  return false;
2298
2306
  }
2299
- const filenameSlashes = filename.split('\\').join('/');
2300
2307
  // Absolute Unix path: /hello.txt
2301
2308
  if (/^(\/)/i.test(filenameSlashes)) {
2302
2309
  // console.log(filename, 'Absolute Unix path: /hello.txt');
2303
2310
  return true;
2304
2311
  }
2305
- // Absolute Windows path: /hello.txt
2306
- if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
2312
+ // Absolute Windows path: C:/ or C:\ (allow spaces and multiple dots in filename)
2313
+ if (/^[A-Z]:\/.+$/i.test(filenameSlashes)) {
2307
2314
  // console.log(filename, 'Absolute Windows path: /hello.txt');
2308
2315
  return true;
2309
2316
  }
@@ -2925,7 +2932,7 @@ const LLM_PROVIDER_PROFILES = {
2925
2932
  };
2926
2933
  /**
2927
2934
  * TODO: Refactor this - each profile must be alongside the provider definition
2928
- * TODO: Unite `AvatarProfileProps` and `ChatParticipant`
2935
+ * TODO: [๐Ÿ•›] Unite `AvatarProfileProps`, `ChatParticipant`, `LlmExecutionTools` + `LlmToolsMetadata`
2929
2936
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
2930
2937
  */
2931
2938
 
@@ -3949,9 +3956,15 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
3949
3956
  }
3950
3957
  if (isValidUrl(knowledgeSourceContent)) {
3951
3958
  const url = knowledgeSourceContent;
3959
+ if (isVerbose) {
3960
+ console.info(`๐Ÿ“„ [1] "${name}" is available at "${url}"`);
3961
+ }
3952
3962
  const response = await fetch(url); // <- TODO: [๐Ÿง ] Scraping and fetch proxy
3953
3963
  const mimeType = ((_a = response.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.split(';')[0]) || 'text/html';
3954
3964
  if (tools.fs === undefined || !url.endsWith('.pdf' /* <- TODO: [๐Ÿ’ต] */)) {
3965
+ if (isVerbose) {
3966
+ console.info(`๐Ÿ“„ [2] "${name}" tools.fs is not available or URL is not a PDF.`);
3967
+ }
3955
3968
  return {
3956
3969
  source: name,
3957
3970
  filename: null,
@@ -3987,13 +4000,17 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
3987
4000
  await tools.fs.mkdir(dirname(join(rootDirname, filepath)), { recursive: true });
3988
4001
  }
3989
4002
  catch (error) {
4003
+ if (isVerbose) {
4004
+ console.info(`๐Ÿ“„ [3] "${name}" error creating cache directory`);
4005
+ }
3990
4006
  // Note: If we can't create cache directory, we'll handle it when trying to write the file
3991
4007
  // This handles read-only filesystems, permission issues, and missing parent directories
3992
- if (error instanceof Error && (error.message.includes('EROFS') ||
3993
- error.message.includes('read-only') ||
3994
- error.message.includes('EACCES') ||
3995
- error.message.includes('EPERM') ||
3996
- error.message.includes('ENOENT'))) ;
4008
+ if (error instanceof Error &&
4009
+ (error.message.includes('EROFS') ||
4010
+ error.message.includes('read-only') ||
4011
+ error.message.includes('EACCES') ||
4012
+ error.message.includes('EPERM') ||
4013
+ error.message.includes('ENOENT'))) ;
3997
4014
  else {
3998
4015
  // Re-throw other unexpected errors
3999
4016
  throw error;
@@ -4008,13 +4025,17 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
4008
4025
  await tools.fs.writeFile(join(rootDirname, filepath), fileContent);
4009
4026
  }
4010
4027
  catch (error) {
4028
+ if (isVerbose) {
4029
+ console.info(`๐Ÿ“„ [4] "${name}" error writing cache file`);
4030
+ }
4011
4031
  // Note: If we can't write to cache, we'll process the file directly from memory
4012
4032
  // This handles read-only filesystems like Vercel
4013
- if (error instanceof Error && (error.message.includes('EROFS') ||
4014
- error.message.includes('read-only') ||
4015
- error.message.includes('EACCES') ||
4016
- error.message.includes('EPERM') ||
4017
- error.message.includes('ENOENT'))) {
4033
+ if (error instanceof Error &&
4034
+ (error.message.includes('EROFS') ||
4035
+ error.message.includes('read-only') ||
4036
+ error.message.includes('EACCES') ||
4037
+ error.message.includes('EPERM') ||
4038
+ error.message.includes('ENOENT'))) {
4018
4039
  // Return a handler that works directly with the downloaded content
4019
4040
  return {
4020
4041
  source: name,
@@ -4036,6 +4057,9 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
4036
4057
  }
4037
4058
  // TODO: [๐Ÿ’ต] Check the file security
4038
4059
  // TODO: [๐Ÿงน][๐Ÿง ] Delete the file after the scraping is done
4060
+ if (isVerbose) {
4061
+ console.info(`๐Ÿ“„ [5] "${name}" cached at "${join(rootDirname, filepath)}"`);
4062
+ }
4039
4063
  return makeKnowledgeSourceHandler({ name, knowledgeSourceContent: filepath }, tools, {
4040
4064
  ...options,
4041
4065
  rootDirname,
@@ -4050,7 +4074,12 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
4050
4074
  throw new EnvironmentMismatchError('Can not import file knowledge in non-file pipeline');
4051
4075
  // <- TODO: [๐Ÿง ] What is the best error type here`
4052
4076
  }
4053
- const filename = join(rootDirname, knowledgeSourceContent).split('\\').join('/');
4077
+ const filename = isAbsolute(knowledgeSourceContent)
4078
+ ? knowledgeSourceContent
4079
+ : join(rootDirname, knowledgeSourceContent).split('\\').join('/');
4080
+ if (isVerbose) {
4081
+ console.info(`๐Ÿ“„ [6] "${name}" is a valid file "${filename}"`);
4082
+ }
4054
4083
  const fileExtension = getFileExtension(filename);
4055
4084
  const mimeType = extensionToMimeType(fileExtension || '');
4056
4085
  if (!(await isFileExisting(filename, tools.fs))) {
@@ -4092,6 +4121,12 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
4092
4121
  };
4093
4122
  }
4094
4123
  else {
4124
+ if (isVerbose) {
4125
+ console.info(`๐Ÿ“„ [7] "${name}" is just a explicit string text with a knowledge source`);
4126
+ console.info('---');
4127
+ console.info(knowledgeSourceContent);
4128
+ console.info('---');
4129
+ }
4095
4130
  return {
4096
4131
  source: name,
4097
4132
  filename: null,