@promptbook/remote-client 0.89.0-8 → 0.89.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +9 -11
  2. package/esm/index.es.js +173 -52
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/servers.d.ts +40 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +12 -4
  6. package/esm/typings/src/_packages/remote-client.index.d.ts +6 -6
  7. package/esm/typings/src/_packages/remote-server.index.d.ts +6 -6
  8. package/esm/typings/src/_packages/types.index.d.ts +24 -14
  9. package/esm/typings/src/_packages/utils.index.d.ts +4 -0
  10. package/esm/typings/src/cli/cli-commands/login.d.ts +0 -1
  11. package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +16 -3
  12. package/esm/typings/src/cli/test/ptbk.d.ts +1 -1
  13. package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +2 -0
  14. package/esm/typings/src/config.d.ts +10 -19
  15. package/esm/typings/src/errors/0-index.d.ts +8 -2
  16. package/esm/typings/src/errors/PipelineExecutionError.d.ts +1 -1
  17. package/esm/typings/src/errors/PromptbookFetchError.d.ts +9 -0
  18. package/esm/typings/src/errors/WrappedError.d.ts +10 -0
  19. package/esm/typings/src/errors/assertsError.d.ts +11 -0
  20. package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
  21. package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +9 -0
  22. package/esm/typings/src/formats/csv/utils/isValidCsvString.test.d.ts +1 -0
  23. package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +3 -0
  24. package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +9 -0
  25. package/esm/typings/src/formats/xml/utils/isValidXmlString.test.d.ts +1 -0
  26. package/esm/typings/src/llm-providers/_common/register/$provideEnvFilename.d.ts +12 -0
  27. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +2 -8
  28. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +2 -0
  29. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizzardOrCli.d.ts +15 -4
  30. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -0
  31. package/esm/typings/src/remote-server/openapi-types.d.ts +284 -0
  32. package/esm/typings/src/remote-server/openapi.d.ts +187 -0
  33. package/esm/typings/src/remote-server/socket-types/_subtypes/{PromptbookServer_Identification.d.ts → Identification.d.ts} +9 -3
  34. package/esm/typings/src/remote-server/socket-types/_subtypes/identificationToPromptbookToken.d.ts +11 -0
  35. package/esm/typings/src/remote-server/socket-types/_subtypes/promptbookTokenToIdentification.d.ts +10 -0
  36. package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Request.d.ts +2 -2
  37. package/esm/typings/src/remote-server/socket-types/prepare/PromptbookServer_PreparePipeline_Request.d.ts +2 -2
  38. package/esm/typings/src/remote-server/socket-types/prompt/PromptbookServer_Prompt_Request.d.ts +2 -2
  39. package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -2
  40. package/esm/typings/src/remote-server/types/RemoteClientOptions.d.ts +2 -2
  41. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +57 -38
  42. package/esm/typings/src/scrapers/_common/utils/{scraperFetch.d.ts → promptbookFetch.d.ts} +2 -2
  43. package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +40 -0
  44. package/esm/typings/src/types/typeAliases.d.ts +26 -0
  45. package/package.json +7 -3
  46. package/umd/index.umd.js +173 -52
  47. package/umd/index.umd.js.map +1 -1
  48. package/esm/typings/src/cli/test/ptbk2.d.ts +0 -5
  49. package/esm/typings/src/playground/BrjappConnector.d.ts +0 -67
  50. package/esm/typings/src/playground/brjapp-api-schema.d.ts +0 -12879
@@ -3,13 +3,15 @@ import type { Promisable } from 'type-fest';
3
3
  import type { PipelineCollection } from '../../collection/PipelineCollection';
4
4
  import { AuthenticationError } from '../../errors/AuthenticationError';
5
5
  import type { CommonToolsOptions } from '../../execution/CommonToolsOptions';
6
+ import type { ExecutionTools } from '../../execution/ExecutionTools';
6
7
  import type { LlmExecutionTools } from '../../execution/LlmExecutionTools';
7
8
  import type { string_app_id } from '../../types/typeAliases';
8
9
  import type { string_email } from '../../types/typeAliases';
9
10
  import type { string_password } from '../../types/typeAliases';
10
- import type { string_uri } from '../../types/typeAliases';
11
+ import type { string_token } from '../../types/typeAliases';
11
12
  import type { string_user_id } from '../../types/typeAliases';
12
- import type { PromptbookServer_Identification } from '../socket-types/_subtypes/PromptbookServer_Identification';
13
+ import type { ApplicationModeIdentification } from '../socket-types/_subtypes/Identification';
14
+ import type { Identification } from '../socket-types/_subtypes/Identification';
13
15
  /**
14
16
  * @@@
15
17
  *
@@ -29,14 +31,18 @@ export type RemoteServerOptions<TCustomOptions> = CommonToolsOptions & {
29
31
  */
30
32
  readonly port: number;
31
33
  /**
32
- * Root path of the server
34
+ * Creates execution tools the client
33
35
  *
34
- * Note: This is useful when you reverse proxy the server without changing the path
36
+ * This is relevant also in anonymous mode in oposition to `createLlmExecutionTools`
35
37
  *
36
- * @default '/'
37
- * @example '/api/promptbook/'
38
+ * Note: You can provide only some tools and leave the rest to the default ones also llm tools are created by `createLlmExecutionTools`
39
+ * Note: This is useful when you want to provide some custom restrictions for example:
40
+ * - Limit access to certain websites for some users
41
+ * - Bind user-interface tools to email agent
42
+ * - Allow / block script execution
43
+ * - And many more
38
44
  */
39
- readonly rootPath?: string_uri;
45
+ createExecutionTools?(options: Identification<TCustomOptions>): Promisable<Partial<Omit<ExecutionTools, 'llm'>>>;
40
46
  } & ((AnonymousRemoteServerOptions & {
41
47
  readonly isApplicationModeAllowed?: false;
42
48
  }) | ({
@@ -70,36 +76,11 @@ export type ApplicationRemoteServerOptions<TCustomOptions> = {
70
76
  * Note: In most cases DO NOT THROW `AuthenticationError` but return `isSuccess: false` with message
71
77
  * @throws `AuthenticationError` if the user is not allowed to login for example because of invalid credentials
72
78
  */
73
- login(credentials: {
74
- /**
75
- * Identifier of the application you are using
76
- *
77
- * Note: This is usefull when you use Promptbook remote server for multiple apps/frontends, if its used just for single app, use here just "app" or "your-app-name"
78
- */
79
- readonly appId: string_app_id | null;
80
- /**
81
- * Username (for example email) of the user
82
- */
83
- readonly username: string_email | string;
84
- /**
85
- * Password of the user
86
- */
87
- readonly password: string_password;
88
- /**
89
- * Request object from express if you want to access some request data for example headers, IP address, etc.
90
- */
91
- readonly rawRequest: Request;
92
- /**
93
- * Response object from express if you want to add some custom headers.
94
- *
95
- * Note: It is not recommended to use this object to send body of the response because it can confuse the client
96
- */
97
- readonly rawResponse: Response;
98
- }): Promise<ApplicationRemoteServerOptionsLoginResponse<TCustomOptions>>;
79
+ login(loginRequest: LoginRequest): Promise<LoginResponse<TCustomOptions>>;
99
80
  /**
100
81
  * Creates llm execution tools for each client
101
82
  */
102
- createLlmExecutionTools(options: ApplicationRemoteServerClientOptions<TCustomOptions>): Promisable<LlmExecutionTools>;
83
+ createLlmExecutionTools(options: ApplicationModeIdentification<TCustomOptions>): Promisable<LlmExecutionTools>;
103
84
  };
104
85
  export type ApplicationRemoteServerClientOptions<TCustomOptions> = {
105
86
  /**
@@ -121,23 +102,61 @@ export type ApplicationRemoteServerClientOptions<TCustomOptions> = {
121
102
  *
122
103
  * Note: This is passed for example to `createLlmExecutionTools`
123
104
  */
124
- readonly userToken?: string_user_id;
105
+ readonly userToken?: string_token;
125
106
  /**
126
107
  * Additional arbitrary options to identify the client or to pass custom metadata
127
108
  */
128
109
  readonly customOptions?: TCustomOptions;
129
110
  };
130
- export type ApplicationRemoteServerOptionsLoginResponse<TCustomOptions> = {
111
+ /**
112
+ * Login request for the application mode
113
+ */
114
+ export type LoginRequest = {
115
+ /**
116
+ * Identifier of the application you are using
117
+ *
118
+ * Note: This is usefull when you use Promptbook remote server for multiple apps/frontends, if its used just for single app, use here just "app" or "your-app-name"
119
+ */
120
+ readonly appId: string_app_id | null;
121
+ /**
122
+ * Username (for example email) of the user
123
+ */
124
+ readonly username: string_email | string;
125
+ /**
126
+ * Password of the user
127
+ */
128
+ readonly password: string_password;
129
+ /**
130
+ * Request object from express if you want to access some request data for example headers, IP address, etc.
131
+ */
132
+ readonly rawRequest: Request;
133
+ /**
134
+ * Response object from express if you want to add some custom headers.
135
+ *
136
+ * Note: It is not recommended to use this object to send body of the response because it can confuse the client
137
+ */
138
+ readonly rawResponse: Response;
139
+ };
140
+ /**
141
+ * Login response for the application mode
142
+ */
143
+ export type LoginResponse<TCustomOptions> = {
131
144
  /**
132
145
  * Was the login successful
133
146
  */
134
147
  readonly isSuccess: boolean;
135
148
  /**
136
- *
149
+ * Message to display to the user, this message is always displayed
137
150
  */
138
151
  readonly message?: string;
152
+ /**
153
+ * Optional error if the login was not successful
154
+ */
139
155
  readonly error?: AuthenticationError;
140
- readonly identification?: PromptbookServer_Identification<TCustomOptions>;
156
+ /**
157
+ * Identification of the user to be used in the future requests
158
+ */
159
+ readonly identification?: Identification<TCustomOptions>;
141
160
  };
142
161
  /**
143
162
  * TODO: Constrain anonymous mode for specific models / providers
@@ -2,9 +2,9 @@ import type { PromptbookFetch } from '../../../execution/PromptbookFetch';
2
2
  /**
3
3
  * The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
4
4
  *
5
- * @private as default `fetch` function used in Promptbook scrapers
5
+ * @public exported from `@promptbook/core`
6
6
  */
7
- export declare const scraperFetch: PromptbookFetch;
7
+ export declare const promptbookFetch: PromptbookFetch;
8
8
  /**
9
9
  * TODO: [🧠] Maybe rename because it is not used only for scrapers but also in `$getCompiledBook`
10
10
  */
@@ -0,0 +1,40 @@
1
+ import type { PromptbookStorage } from '../_common/PromptbookStorage';
2
+ /**
3
+ * Stores data in .env variables
4
+ *
5
+ * Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file and also writes to `process.env`
6
+ *
7
+ * @private within the repository - for CLI utils
8
+ */
9
+ export declare class $EnvStorage<TItem> implements PromptbookStorage<TItem> {
10
+ private envFilename;
11
+ private $provideOrCreateEnvFile;
12
+ private transformKey;
13
+ /**
14
+ * Returns the number of key/value pairs currently present in the list associated with the object.
15
+ */
16
+ get length(): number;
17
+ /**
18
+ * Empties the list associated with the object of all key/value pairs, if there are any.
19
+ */
20
+ clear(): void;
21
+ /**
22
+ * Returns the current value associated with the given key, or null if the given key does not exist in the list associated with the object.
23
+ */
24
+ getItem(key: string): Promise<TItem | null>;
25
+ /**
26
+ * Returns the name of the nth key in the list, or null if n is greater than or equal to the number of key/value pairs in the object.
27
+ */
28
+ key(index: number): string | null;
29
+ /**
30
+ * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
31
+ */
32
+ setItem(key: string, value: TItem): Promise<void>;
33
+ /**
34
+ * Removes the key/value pair with the given key from the list associated with the object, if a key/value pair with the given key exists.
35
+ */
36
+ removeItem(key: string): void;
37
+ }
38
+ /**
39
+ * TODO: Write file more securely - ensure that there can be no accidental overwriting of existing variables and other content
40
+ */
@@ -325,6 +325,12 @@ export type string_css_selector = string;
325
325
  * For example `"https://collboard.com/9SeSQTupmQHwuSrLi"`
326
326
  */
327
327
  export type string_url = string;
328
+ /**
329
+ * Semantic helper
330
+ *
331
+ * For example `"https://s1.ptbk.io/promptbook"`
332
+ */
333
+ export type string_promptbook_server_url = string;
328
334
  /**
329
335
  * Semantic helper
330
336
  *
@@ -408,6 +414,13 @@ export type string_host = string;
408
414
  * Semantic helper
409
415
  */
410
416
  export type string_protocol = 'http:' | 'https:';
417
+ /**
418
+ * Semantic helper
419
+ *
420
+ * For example `"192.168.1.1"` (IPv4)
421
+ * For example `"2001:0db8:85a3:0000:0000:8a2e:0370:7334"` (IPv6)
422
+ */
423
+ export type string_ip_address = string;
411
424
  /**
412
425
  * Semantic helper
413
426
  *
@@ -521,6 +534,13 @@ export type string_person_profile = string;
521
534
  * For example `"MIT"`
522
535
  */
523
536
  export type string_license = string;
537
+ /**
538
+ * Semantic helper
539
+ *
540
+ * For example `"Pavol Hejný <pavol@ptbk.io> (https://www.pavolhejny.com/)"`
541
+ * For example `"AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)"`
542
+ */
543
+ export type string_legal_entity = string | string_person_profile | string_title;
524
544
  /**
525
545
  * Semantic helper for attributes
526
546
  *
@@ -570,6 +590,12 @@ export type string_postprocessing_function_name = string;
570
590
  export type id = string | number;
571
591
  export type task_id = string;
572
592
  export type string_token = string;
593
+ /**
594
+ * Semantic helper
595
+ *
596
+ * Made by `identificationToPromptbookToken` exported from `@promptbook/core`
597
+ */
598
+ export type string_promptbook_token = string_token;
573
599
  export type string_license_token = string_token;
574
600
  export type string_password = string;
575
601
  export type string_ssh_key = string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/remote-client",
3
- "version": "0.89.0-8",
3
+ "version": "0.89.0",
4
4
  "description": "It's time for a paradigm shift. The future of software in plain English, French or Latin",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -43,14 +43,18 @@
43
43
  "url": "https://github.com/webgptorg/promptbook/issues"
44
44
  },
45
45
  "homepage": "https://ptbk.io/",
46
+ "engines": {
47
+ "node": ">=16.0.0",
48
+ "npm": ">=8.0.0"
49
+ },
46
50
  "main": "./umd/index.umd.js",
47
51
  "module": "./esm/index.es.js",
48
52
  "typings": "./esm/typings/src/_packages/remote-client.index.d.ts",
49
53
  "peerDependencies": {
50
- "@promptbook/core": "0.89.0-8"
54
+ "@promptbook/core": "0.89.0"
51
55
  },
52
56
  "dependencies": {
53
- "crypto": "^1.0.1",
57
+ "crypto": "1.0.1",
54
58
  "crypto-js": "4.2.0",
55
59
  "papaparse": "5.4.1",
56
60
  "socket.io-client": "4.7.2",
package/umd/index.umd.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * @generated
24
24
  * @see https://github.com/webgptorg/promptbook
25
25
  */
26
- const PROMPTBOOK_ENGINE_VERSION = '0.89.0-8';
26
+ const PROMPTBOOK_ENGINE_VERSION = '0.89.0';
27
27
  /**
28
28
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
29
29
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -241,7 +241,7 @@
241
241
  }
242
242
  }
243
243
  /**
244
- * TODO: !!!!!! Add id to all errors
244
+ * TODO: [🧠][🌂] Add id to all errors
245
245
  */
246
246
 
247
247
  /**
@@ -270,6 +270,19 @@
270
270
  }
271
271
  }
272
272
 
273
+ /**
274
+ * Error thrown when a fetch request fails
275
+ *
276
+ * @public exported from `@promptbook/core`
277
+ */
278
+ class PromptbookFetchError extends Error {
279
+ constructor(message) {
280
+ super(message);
281
+ this.name = 'PromptbookFetchError';
282
+ Object.setPrototypeOf(this, PromptbookFetchError.prototype);
283
+ }
284
+ }
285
+
273
286
  /**
274
287
  * Returns the same value that is passed as argument.
275
288
  * No side effects.
@@ -310,6 +323,7 @@
310
323
  * @public exported from `@promptbook/core`
311
324
  */
312
325
  const ADMIN_GITHUB_NAME = 'hejny';
326
+ // <- TODO: [🐊] Pick the best claim
313
327
  /**
314
328
  * When the title is not provided, the default title is used
315
329
  *
@@ -433,6 +447,26 @@
433
447
  }
434
448
  }
435
449
 
450
+ /**
451
+ * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
452
+ *
453
+ * @public exported from `@promptbook/core`
454
+ */
455
+ class WrappedError extends Error {
456
+ constructor(whatWasThrown) {
457
+ const tag = `[🤮]`;
458
+ console.error(tag, whatWasThrown);
459
+ super(spaceTrim.spaceTrim(`
460
+ Non-Error object was thrown
461
+
462
+ Note: Look for ${tag} in the console for more details
463
+ Please report issue on ${ADMIN_EMAIL}
464
+ `));
465
+ this.name = 'WrappedError';
466
+ Object.setPrototypeOf(this, WrappedError.prototype);
467
+ }
468
+ }
469
+
436
470
  /**
437
471
  * Index of all custom errors
438
472
  *
@@ -453,7 +487,10 @@
453
487
  PipelineExecutionError,
454
488
  PipelineLogicError,
455
489
  PipelineUrlError,
490
+ AuthenticationError,
491
+ PromptbookFetchError,
456
492
  UnexpectedError,
493
+ WrappedError,
457
494
  // TODO: [🪑]> VersionMismatchError,
458
495
  };
459
496
  /**
@@ -470,7 +507,6 @@
470
507
  TypeError,
471
508
  URIError,
472
509
  AggregateError,
473
- AuthenticationError,
474
510
  /*
475
511
  Note: Not widely supported
476
512
  > InternalError,
@@ -519,6 +555,35 @@
519
555
  return deserializedError;
520
556
  }
521
557
 
558
+ /**
559
+ * Tests if given string is valid URL.
560
+ *
561
+ * Note: Dataurl are considered perfectly valid.
562
+ * Note: There are two simmilar functions:
563
+ * - `isValidUrl` which tests any URL
564
+ * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
565
+ *
566
+ * @public exported from `@promptbook/utils`
567
+ */
568
+ function isValidUrl(url) {
569
+ if (typeof url !== 'string') {
570
+ return false;
571
+ }
572
+ try {
573
+ if (url.startsWith('blob:')) {
574
+ url = url.replace(/^blob:/, '');
575
+ }
576
+ const urlObject = new URL(url /* because fail is handled */);
577
+ if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
578
+ return false;
579
+ }
580
+ return true;
581
+ }
582
+ catch (error) {
583
+ return false;
584
+ }
585
+ }
586
+
522
587
  /**
523
588
  * Creates a connection to the remote proxy server.
524
589
  *
@@ -528,17 +593,31 @@
528
593
  */
529
594
  async function createRemoteClient(options) {
530
595
  const { remoteServerUrl } = options;
531
- let path = new URL(remoteServerUrl).pathname;
532
- if (path.endsWith('/')) {
533
- path = path.slice(0, -1);
596
+ if (!isValidUrl(remoteServerUrl)) {
597
+ throw new Error(`Invalid \`remoteServerUrl\`: "${remoteServerUrl}"`);
598
+ }
599
+ const remoteServerUrlParsed = new URL(remoteServerUrl);
600
+ if (remoteServerUrlParsed.pathname !== '/' && remoteServerUrlParsed.pathname !== '') {
601
+ remoteServerUrlParsed.pathname = '/';
602
+ throw new Error(spaceTrim__default["default"]((block) => `
603
+ Remote server requires root url \`/\`
604
+
605
+ You have provided \`remoteServerUrl\`:
606
+ ${block(remoteServerUrl)}
607
+
608
+ But something like this is expected:
609
+ ${block(remoteServerUrlParsed.href)}
610
+
611
+ Note: If you need to run multiple services on the same server, use 3rd or 4th degree subdomain
612
+
613
+ `));
534
614
  }
535
- path = `${path}/socket.io`;
536
615
  return new Promise((resolve, reject) => {
537
616
  const socket = socket_ioClient.io(remoteServerUrl, {
538
617
  retries: CONNECTION_RETRIES_LIMIT,
539
618
  timeout: CONNECTION_TIMEOUT_MS,
540
- path,
541
- transports: [/*'websocket', <- TODO: [🌬] Make websocket transport work */ 'polling'],
619
+ path: '/socket.io',
620
+ transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
542
621
  });
543
622
  // console.log('Connecting to', this.options.remoteServerUrl.href, { socket });
544
623
  socket.on('connect', () => {
@@ -672,35 +751,6 @@
672
751
  * TODO: [🍏] Implement for MacOs
673
752
  */
674
753
 
675
- /**
676
- * Tests if given string is valid URL.
677
- *
678
- * Note: Dataurl are considered perfectly valid.
679
- * Note: There are two simmilar functions:
680
- * - `isValidUrl` which tests any URL
681
- * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
682
- *
683
- * @public exported from `@promptbook/utils`
684
- */
685
- function isValidUrl(url) {
686
- if (typeof url !== 'string') {
687
- return false;
688
- }
689
- try {
690
- if (url.startsWith('blob:')) {
691
- url = url.replace(/^blob:/, '');
692
- }
693
- const urlObject = new URL(url /* because fail is handled */);
694
- if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
695
- return false;
696
- }
697
- return true;
698
- }
699
- catch (error) {
700
- return false;
701
- }
702
- }
703
-
704
754
  const defaultDiacriticsRemovalMap = [
705
755
  {
706
756
  base: 'A',
@@ -1528,6 +1578,34 @@
1528
1578
  },
1529
1579
  };
1530
1580
 
1581
+ /**
1582
+ * Helper used in catch blocks to assert that the error is an instance of `Error`
1583
+ *
1584
+ * @param whatWasThrown Any object that was thrown
1585
+ * @returns Nothing if the error is an instance of `Error`
1586
+ * @throws `WrappedError` or `UnexpectedError` if the error is not standard
1587
+ *
1588
+ * @private within the repository
1589
+ */
1590
+ function assertsError(whatWasThrown) {
1591
+ // Case 1: Handle error which was rethrown as `WrappedError`
1592
+ if (whatWasThrown instanceof WrappedError) {
1593
+ const wrappedError = whatWasThrown;
1594
+ throw wrappedError;
1595
+ }
1596
+ // Case 2: Handle unexpected errors
1597
+ if (whatWasThrown instanceof UnexpectedError) {
1598
+ const unexpectedError = whatWasThrown;
1599
+ throw unexpectedError;
1600
+ }
1601
+ // Case 3: Handle standard errors - keep them up to consumer
1602
+ if (whatWasThrown instanceof Error) {
1603
+ return;
1604
+ }
1605
+ // Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
1606
+ throw new WrappedError(whatWasThrown);
1607
+ }
1608
+
1531
1609
  /**
1532
1610
  * Units of text measurement
1533
1611
  *
@@ -1608,6 +1686,8 @@
1608
1686
  */
1609
1687
 
1610
1688
  /**
1689
+ import { WrappedError } from '../../errors/WrappedError';
1690
+ import { assertsError } from '../../errors/assertsError';
1611
1691
  * Parses the expect command
1612
1692
  *
1613
1693
  * @see `documentationUrl` for more details
@@ -1699,9 +1779,7 @@
1699
1779
  };
1700
1780
  }
1701
1781
  catch (error) {
1702
- if (!(error instanceof Error)) {
1703
- throw error;
1704
- }
1782
+ assertsError(error);
1705
1783
  throw new ParseError(spaceTrim__default["default"]((block) => `
1706
1784
  Invalid FORMAT command
1707
1785
  ${block(error.message)}:
@@ -1759,6 +1837,28 @@
1759
1837
  // encoding: 'utf-8',
1760
1838
  });
1761
1839
 
1840
+ /**
1841
+ * Function to check if a string is valid CSV
1842
+ *
1843
+ * @param value The string to check
1844
+ * @returns True if the string is a valid CSV string, false otherwise
1845
+ *
1846
+ * @public exported from `@promptbook/utils`
1847
+ */
1848
+ function isValidCsvString(value) {
1849
+ try {
1850
+ // A simple check for CSV format: at least one comma and no invalid characters
1851
+ if (value.includes(',') && /^[\w\s,"']+$/.test(value)) {
1852
+ return true;
1853
+ }
1854
+ return false;
1855
+ }
1856
+ catch (error) {
1857
+ assertsError(error);
1858
+ return false;
1859
+ }
1860
+ }
1861
+
1762
1862
  /**
1763
1863
  * Definition for CSV spreadsheet
1764
1864
  *
@@ -1769,7 +1869,7 @@
1769
1869
  formatName: 'CSV',
1770
1870
  aliases: ['SPREADSHEET', 'TABLE'],
1771
1871
  isValid(value, settings, schema) {
1772
- return true;
1872
+ return isValidCsvString(value);
1773
1873
  },
1774
1874
  canBeValid(partialValue, settings, schema) {
1775
1875
  return true;
@@ -1850,6 +1950,9 @@
1850
1950
  /**
1851
1951
  * Function isValidJsonString will tell you if the string is valid JSON or not
1852
1952
  *
1953
+ * @param value The string to check
1954
+ * @returns True if the string is a valid JSON string, false otherwise
1955
+ *
1853
1956
  * @public exported from `@promptbook/utils`
1854
1957
  */
1855
1958
  function isValidJsonString(value /* <- [👨‍⚖️] */) {
@@ -1858,9 +1961,7 @@
1858
1961
  return true;
1859
1962
  }
1860
1963
  catch (error) {
1861
- if (!(error instanceof Error)) {
1862
- throw error;
1863
- }
1964
+ assertsError(error);
1864
1965
  if (error.message.includes('Unexpected token')) {
1865
1966
  return false;
1866
1967
  }
@@ -1944,6 +2045,30 @@
1944
2045
  * TODO: [🏢] Allow to expect something inside each item of list and other formats
1945
2046
  */
1946
2047
 
2048
+ /**
2049
+ * Function to check if a string is valid XML
2050
+ *
2051
+ * @param value
2052
+ * @returns True if the string is a valid XML string, false otherwise
2053
+ *
2054
+ * @public exported from `@promptbook/utils`
2055
+ */
2056
+ function isValidXmlString(value) {
2057
+ try {
2058
+ const parser = new DOMParser();
2059
+ const parsedDocument = parser.parseFromString(value, 'application/xml');
2060
+ const parserError = parsedDocument.getElementsByTagName('parsererror');
2061
+ if (parserError.length > 0) {
2062
+ return false;
2063
+ }
2064
+ return true;
2065
+ }
2066
+ catch (error) {
2067
+ assertsError(error);
2068
+ return false;
2069
+ }
2070
+ }
2071
+
1947
2072
  /**
1948
2073
  * Definition for XML format
1949
2074
  *
@@ -1953,7 +2078,7 @@
1953
2078
  formatName: 'XML',
1954
2079
  mimeType: 'application/xml',
1955
2080
  isValid(value, settings, schema) {
1956
- return true;
2081
+ return isValidXmlString(value);
1957
2082
  },
1958
2083
  canBeValid(partialValue, settings, schema) {
1959
2084
  return true;
@@ -2178,9 +2303,7 @@
2178
2303
  JSON.stringify(value); // <- TODO: [0]
2179
2304
  }
2180
2305
  catch (error) {
2181
- if (!(error instanceof Error)) {
2182
- throw error;
2183
- }
2306
+ assertsError(error);
2184
2307
  throw new UnexpectedError(spaceTrim__default["default"]((block) => `
2185
2308
  \`${name}\` is not serializable
2186
2309
 
@@ -4835,9 +4958,7 @@
4835
4958
  }
4836
4959
  }
4837
4960
  catch (error) {
4838
- if (!(error instanceof Error)) {
4839
- throw error;
4840
- }
4961
+ assertsError(error);
4841
4962
  throw new ParseError(spaceTrim.spaceTrim((block) => `
4842
4963
  Can not extract variables from the script
4843
4964
  ${block(error.stack || error.message)}