@promptbook/core 0.103.0-45 → 0.103.0-47

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 (59) hide show
  1. package/esm/index.es.js +362 -276
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/servers.d.ts +1 -7
  4. package/esm/typings/src/_packages/components.index.d.ts +4 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +16 -14
  6. package/esm/typings/src/_packages/types.index.d.ts +12 -6
  7. package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +6 -1
  8. package/esm/typings/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +1 -1
  9. package/esm/typings/src/book-2.0/agent-source/createCommitmentRegex.d.ts +1 -1
  10. package/esm/typings/src/book-2.0/agent-source/padBook.d.ts +2 -0
  11. package/esm/typings/src/book-2.0/agent-source/string_book.d.ts +2 -0
  12. package/esm/typings/src/book-components/Chat/AgentChat/AgentChat.d.ts +14 -0
  13. package/esm/typings/src/book-components/Chat/AgentChat/AgentChat.test.d.ts +1 -0
  14. package/esm/typings/src/book-components/Chat/AgentChat/AgentChatProps.d.ts +13 -0
  15. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +5 -60
  16. package/esm/typings/src/{book-2.0/commitments → commitments}/ACTION/ACTION.d.ts +1 -1
  17. package/esm/typings/src/{book-2.0/commitments → commitments}/DELETE/DELETE.d.ts +1 -1
  18. package/esm/typings/src/{book-2.0/commitments → commitments}/FORMAT/FORMAT.d.ts +1 -1
  19. package/esm/typings/src/{book-2.0/commitments → commitments}/GOAL/GOAL.d.ts +1 -1
  20. package/esm/typings/src/{book-2.0/commitments → commitments}/KNOWLEDGE/KNOWLEDGE.d.ts +1 -5
  21. package/esm/typings/src/{book-2.0/commitments → commitments}/MEMORY/MEMORY.d.ts +1 -1
  22. package/esm/typings/src/{book-2.0/commitments → commitments}/MESSAGE/MESSAGE.d.ts +1 -1
  23. package/esm/typings/src/{book-2.0/commitments → commitments}/META/META.d.ts +1 -1
  24. package/esm/typings/src/{book-2.0/commitments → commitments}/META_IMAGE/META_IMAGE.d.ts +1 -1
  25. package/esm/typings/src/{book-2.0/commitments → commitments}/META_LINK/META_LINK.d.ts +1 -1
  26. package/esm/typings/src/{book-2.0/commitments → commitments}/MODEL/MODEL.d.ts +1 -1
  27. package/esm/typings/src/{book-2.0/commitments → commitments}/NOTE/NOTE.d.ts +1 -1
  28. package/esm/typings/src/{book-2.0/commitments → commitments}/PERSONA/PERSONA.d.ts +1 -1
  29. package/esm/typings/src/{book-2.0/commitments → commitments}/RULE/RULE.d.ts +1 -1
  30. package/esm/typings/src/{book-2.0/commitments → commitments}/SAMPLE/SAMPLE.d.ts +1 -1
  31. package/esm/typings/src/{book-2.0/commitments → commitments}/SCENARIO/SCENARIO.d.ts +1 -1
  32. package/esm/typings/src/{book-2.0/commitments → commitments}/STYLE/STYLE.d.ts +1 -1
  33. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/BaseCommitmentDefinition.d.ts +1 -1
  34. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/CommitmentDefinition.d.ts +1 -1
  35. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/NotYetImplementedCommitmentDefinition.d.ts +1 -1
  36. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/createEmptyAgentModelRequirements.d.ts +1 -1
  37. package/esm/typings/src/conversion/validation/validatePipeline.d.ts +2 -0
  38. package/esm/typings/src/execution/LlmExecutionTools.d.ts +1 -1
  39. package/esm/typings/src/execution/utils/validatePromptResult.d.ts +2 -0
  40. package/esm/typings/src/llm-providers/agent/Agent.d.ts +3 -7
  41. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +1 -1
  42. package/esm/typings/src/llm-providers/agent/CreateAgentLlmExecutionToolsOptions.d.ts +1 -1
  43. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +32 -0
  44. package/esm/typings/src/llm-providers/agent/RemoteAgentOptions.d.ts +11 -0
  45. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +5 -1
  46. package/esm/typings/src/pipeline/validatePipelineString.d.ts +2 -0
  47. package/esm/typings/src/storage/_common/PromptbookStorage.d.ts +1 -0
  48. package/esm/typings/src/types/typeAliases.d.ts +6 -0
  49. package/esm/typings/src/utils/color/internal-utils/checkChannelValue.d.ts +0 -3
  50. package/esm/typings/src/utils/random/$generateBookBoilerplate.d.ts +2 -2
  51. package/esm/typings/src/utils/random/$randomFullnameWithColor.d.ts +1 -1
  52. package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +2 -0
  53. package/esm/typings/src/version.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/umd/index.umd.js +362 -275
  56. package/umd/index.umd.js.map +1 -1
  57. /package/esm/typings/src/{book-2.0/commitments → commitments}/_base/BookCommitment.d.ts +0 -0
  58. /package/esm/typings/src/{book-2.0/commitments → commitments}/_base/ParsedCommitment.d.ts +0 -0
  59. /package/esm/typings/src/{book-2.0/commitments → commitments}/index.d.ts +0 -0
package/umd/index.umd.js CHANGED
@@ -28,7 +28,7 @@
28
28
  * @generated
29
29
  * @see https://github.com/webgptorg/promptbook
30
30
  */
31
- const PROMPTBOOK_ENGINE_VERSION = '0.103.0-45';
31
+ const PROMPTBOOK_ENGINE_VERSION = '0.103.0-47';
32
32
  /**
33
33
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
34
34
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -160,15 +160,20 @@
160
160
  */
161
161
  const REMOTE_SERVER_URLS = [
162
162
  {
163
- title: 'Promptbook',
164
- description: `Servers of Promptbook.studio`,
163
+ title: 'Promptbook.Studio',
164
+ description: `Server of Promptbook.studio`,
165
165
  owner: 'AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)',
166
- isAnonymousModeAllowed: true,
167
166
  urls: [
168
167
  'https://promptbook.s5.ptbk.io/',
169
168
  // Note: Servers 1-4 are not running
170
169
  ],
171
170
  },
171
+ {
172
+ title: 'Testing Agents',
173
+ description: `Testing Agents server on Vercel`,
174
+ owner: 'AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)',
175
+ urls: ['https://s6.ptbk.io/'],
176
+ },
172
177
  /*
173
178
  Note: Working on older version of Promptbook and not supported anymore
174
179
  {
@@ -413,9 +418,6 @@
413
418
  throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
414
419
  }
415
420
  }
416
- /**
417
- * TODO: [🧠][🚓] Is/which combination it better to use asserts/check, validate or is utility function?
418
- */
419
421
 
420
422
  /**
421
423
  * Color object represents an RGB color with alpha channel
@@ -1543,6 +1545,8 @@
1543
1545
  * Function `validatePipelineString` will validate the if the string is a valid pipeline string
1544
1546
  * It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
1545
1547
  *
1548
+ * Note: [🔂] This function is idempotent.
1549
+ *
1546
1550
  * @param {string} pipelineString the candidate for a pipeline string
1547
1551
  * @returns {PipelineString} the same string as input, but validated as valid
1548
1552
  * @throws {ParseError} if the string is not a valid pipeline string
@@ -2174,6 +2178,8 @@
2174
2178
  * - if it is valid json
2175
2179
  * - if it is meaningful
2176
2180
  *
2181
+ * Note: [🔂] This function is idempotent.
2182
+ *
2177
2183
  * @param pipeline valid or invalid PipelineJson
2178
2184
  * @returns the same pipeline if it is logically valid
2179
2185
  * @throws {PipelineLogicError} on logical error in the pipeline
@@ -6031,6 +6037,8 @@
6031
6037
  * This function provides a common abstraction for result validation that can be used
6032
6038
  * by both execution logic and caching logic to ensure consistency.
6033
6039
  *
6040
+ * Note: [🔂] This function is idempotent.
6041
+ *
6034
6042
  * @param options - The validation options including result string, expectations, and format
6035
6043
  * @returns Validation result with processed string and validity status
6036
6044
  * @private internal function of `createPipelineExecutor` and `cacheLlmTools`
@@ -7385,40 +7393,6 @@
7385
7393
  * TODO: [🏢] Check validity of `temperature` in pipeline
7386
7394
  */
7387
7395
 
7388
- /**
7389
- * Creates an empty/basic agent model requirements object
7390
- * This serves as the starting point for the reduce-like pattern
7391
- * where each commitment applies its changes to build the final requirements
7392
- *
7393
- * @public exported from `@promptbook/core`
7394
- */
7395
- function createEmptyAgentModelRequirements() {
7396
- return {
7397
- systemMessage: '',
7398
- // modelName: 'gpt-5',
7399
- modelName: 'gemini-2.5-flash-lite',
7400
- temperature: 0.7,
7401
- topP: 0.9,
7402
- topK: 50,
7403
- };
7404
- }
7405
- /**
7406
- * Creates a basic agent model requirements with just the agent name
7407
- * This is used when we have an agent name but no commitments
7408
- *
7409
- * @public exported from `@promptbook/core`
7410
- */
7411
- function createBasicAgentModelRequirements(agentName) {
7412
- const empty = createEmptyAgentModelRequirements();
7413
- return {
7414
- ...empty,
7415
- systemMessage: `You are ${agentName || 'AI Agent'}`,
7416
- };
7417
- }
7418
- /**
7419
- * TODO: [🐤] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
7420
- */
7421
-
7422
7396
  /**
7423
7397
  * Generates a regex pattern to match a specific commitment
7424
7398
  *
@@ -7952,23 +7926,19 @@
7952
7926
  `);
7953
7927
  }
7954
7928
  applyToAgentModelRequirements(requirements, content) {
7955
- var _a;
7956
7929
  const trimmedContent = content.trim();
7957
7930
  if (!trimmedContent) {
7958
7931
  return requirements;
7959
7932
  }
7960
7933
  // Check if content is a URL (external knowledge source)
7961
- if (this.isUrl(trimmedContent)) {
7934
+ if (isValidUrl(trimmedContent)) {
7962
7935
  // Store the URL for later async processing
7963
7936
  const updatedRequirements = {
7964
7937
  ...requirements,
7965
- metadata: {
7966
- ...requirements.metadata,
7967
- knowledgeSources: [
7968
- ...(((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.knowledgeSources) || []),
7969
- trimmedContent,
7970
- ],
7971
- },
7938
+ knowledgeSources: [
7939
+ ...(requirements.knowledgeSources || []),
7940
+ trimmedContent,
7941
+ ],
7972
7942
  };
7973
7943
  // Add placeholder information about knowledge sources to system message
7974
7944
  const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
@@ -7980,18 +7950,6 @@
7980
7950
  return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
7981
7951
  }
7982
7952
  }
7983
- /**
7984
- * Check if content is a URL
7985
- */
7986
- isUrl(content) {
7987
- try {
7988
- new URL(content);
7989
- return true;
7990
- }
7991
- catch (_a) {
7992
- return false;
7993
- }
7994
- }
7995
7953
  }
7996
7954
  /**
7997
7955
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -9317,6 +9275,40 @@
9317
9275
  * Note: [💞] Ignore a discrepancy between file name and entity name
9318
9276
  */
9319
9277
 
9278
+ /**
9279
+ * Creates an empty/basic agent model requirements object
9280
+ * This serves as the starting point for the reduce-like pattern
9281
+ * where each commitment applies its changes to build the final requirements
9282
+ *
9283
+ * @public exported from `@promptbook/core`
9284
+ */
9285
+ function createEmptyAgentModelRequirements() {
9286
+ return {
9287
+ systemMessage: '',
9288
+ // modelName: 'gpt-5',
9289
+ modelName: 'gemini-2.5-flash-lite',
9290
+ temperature: 0.7,
9291
+ topP: 0.9,
9292
+ topK: 50,
9293
+ };
9294
+ }
9295
+ /**
9296
+ * Creates a basic agent model requirements with just the agent name
9297
+ * This is used when we have an agent name but no commitments
9298
+ *
9299
+ * @public exported from `@promptbook/core`
9300
+ */
9301
+ function createBasicAgentModelRequirements(agentName) {
9302
+ const empty = createEmptyAgentModelRequirements();
9303
+ return {
9304
+ ...empty,
9305
+ systemMessage: `You are ${agentName || 'AI Agent'}`,
9306
+ };
9307
+ }
9308
+ /**
9309
+ * TODO: [🐤] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
9310
+ */
9311
+
9320
9312
  /**
9321
9313
  * Parses agent source using the new commitment system with multiline support
9322
9314
  * This function replaces the hardcoded commitment parsing in the original parseAgentSource
@@ -9407,29 +9399,6 @@
9407
9399
  };
9408
9400
  }
9409
9401
 
9410
- /**
9411
- * Removes comment lines (lines starting with #) from a system message
9412
- * This is used to clean up the final system message before sending it to the AI model
9413
- * while preserving the original content with comments in metadata
9414
- *
9415
- * @param systemMessage The system message that may contain comment lines
9416
- * @returns The system message with comment lines removed
9417
- *
9418
- * @private - TODO: [🧠] Maybe should be public?
9419
- */
9420
- function removeCommentsFromSystemMessage(systemMessage) {
9421
- if (!systemMessage) {
9422
- return systemMessage;
9423
- }
9424
- const lines = systemMessage.split('\n');
9425
- const filteredLines = lines.filter((line) => {
9426
- const trimmedLine = line.trim();
9427
- // Remove lines that start with # (comments)
9428
- return !trimmedLine.startsWith('#');
9429
- });
9430
- return filteredLines.join('\n').trim();
9431
- }
9432
-
9433
9402
  /**
9434
9403
  * Parses parameters from text using both supported notations:
9435
9404
  * 1. @Parameter - single word parameter starting with @
@@ -9488,6 +9457,29 @@
9488
9457
  return uniqueParameters;
9489
9458
  }
9490
9459
 
9460
+ /**
9461
+ * Removes comment lines (lines starting with #) from a system message
9462
+ * This is used to clean up the final system message before sending it to the AI model
9463
+ * while preserving the original content with comments in metadata
9464
+ *
9465
+ * @param systemMessage The system message that may contain comment lines
9466
+ * @returns The system message with comment lines removed
9467
+ *
9468
+ * @private - TODO: [🧠] Maybe should be public?
9469
+ */
9470
+ function removeCommentsFromSystemMessage(systemMessage) {
9471
+ if (!systemMessage) {
9472
+ return systemMessage;
9473
+ }
9474
+ const lines = systemMessage.split('\n');
9475
+ const filteredLines = lines.filter((line) => {
9476
+ const trimmedLine = line.trim();
9477
+ // Remove lines that start with # (comments)
9478
+ return !trimmedLine.startsWith('#');
9479
+ });
9480
+ return filteredLines.join('\n').trim();
9481
+ }
9482
+
9491
9483
  /**
9492
9484
  * Creates agent model requirements using the new commitment system
9493
9485
  * This function uses a reduce-like pattern where each commitment applies its changes
@@ -9823,6 +9815,8 @@
9823
9815
  /**
9824
9816
  * A function that adds padding to the book content
9825
9817
  *
9818
+ * Note: [🔂] This function is idempotent.
9819
+ *
9826
9820
  * @public exported from `@promptbook/core`
9827
9821
  */
9828
9822
  function padBook(content) {
@@ -9868,6 +9862,8 @@
9868
9862
  * This function should be used when you have a string that you know represents agent source
9869
9863
  * but need to convert it to the branded type for type safety
9870
9864
  *
9865
+ * Note: [🔂] This function is idempotent.
9866
+ *
9871
9867
  * @public exported from `@promptbook/core`
9872
9868
  */
9873
9869
  function validateBook(source) {
@@ -9927,125 +9923,51 @@
9927
9923
  console.info(`Creating pipeline collection from supabase...`);
9928
9924
  }
9929
9925
  }
9930
- /**
9931
- * Cached defined execution tools
9932
- */
9933
- // !!! private _definedTools: ExecutionTools | null = null;
9934
- /*
9935
- TODO: !!! Use or remove
9936
- /**
9937
- * Gets or creates execution tools for the collection
9938
- * /
9939
- private async getTools(): Promise<ExecutionTools> {
9940
- if (this._definedTools !== null) {
9941
- return this._definedTools;
9942
- }
9943
-
9944
- this._definedTools = {
9945
- ...(this.tools === undefined || this.tools.fs === undefined ? await $provideExecutionToolsForNode() : {}),
9946
- ...this.tools,
9947
- };
9948
- return this._definedTools;
9949
- }
9950
- // <- TODO: [👪] Maybe create some common abstraction *(or parent abstract class)*
9951
- */
9952
9926
  /**
9953
9927
  * Gets all agents in the collection
9954
9928
  */
9955
9929
  async listAgents( /* TODO: [🧠] Allow to pass some condition here */) {
9956
9930
  const { isVerbose = exports.DEFAULT_IS_VERBOSE } = this.options || {};
9957
- const result = await this.supabaseClient
9931
+ const selectResult = await this.supabaseClient
9958
9932
  .from('AgentCollection' /* <- TODO: !!!! Change to `Agent` */)
9959
9933
  .select('agentProfile');
9960
- if (result.error) {
9934
+ if (selectResult.error) {
9961
9935
  throw new DatabaseError(spaceTrim((block) => `
9962
9936
 
9963
9937
  Error fetching agents from Supabase:
9964
9938
 
9965
- ${block(result.error.message)}
9939
+ ${block(selectResult.error.message)}
9966
9940
  `));
9967
9941
  }
9968
9942
  if (isVerbose) {
9969
- console.info(`Found ${result.data.length} agents in directory`);
9943
+ console.info(`Found ${selectResult.data.length} agents in directory`);
9970
9944
  }
9971
- return result.data.map((row) => row.agentProfile);
9945
+ return selectResult.data.map((row) => row.agentProfile);
9972
9946
  }
9973
- /**
9974
- * !!!
9975
- * /
9976
- public async spawnAgent(agentName: string_agent_name): Promise<Agent> {
9977
-
9978
- // <- TODO: !!! ENOENT: no such file or directory, open 'C:\Users\me\work\ai\promptbook\agents\examples\Asistent pro LŠVP.book
9979
- const { isVerbose = DEFAULT_IS_VERBOSE } = this.options || {};
9980
- const tools = await this.getTools();
9981
-
9982
- const agentSourceValue = validateBook(await tools.fs!.readFile(agentSourcePath, 'utf-8'));
9983
- const agentSource = new BehaviorSubject(agentSourceValue);
9984
-
9985
- // Note: Write file whenever agent source changes
9986
- agentSource.subscribe(async (newSource) => {
9987
- if (isVerbose) {
9988
- console.info(colors.cyan(`Writing agent source to file ${agentSourcePath}`));
9989
- }
9990
- await forTime(500); // <- TODO: [🙌] !!! Remove
9991
- await tools.fs!.writeFile(agentSourcePath, newSource, 'utf-8');
9992
- });
9993
-
9994
- // Note: Watch file for external changes
9995
- for await (const event of tools.fs!.watch(agentSourcePath)) {
9996
- // <- TODO: !!!! Solve the memory freeing when the watching is no longer needed
9997
-
9998
- if (event.eventType !== 'change') {
9999
- continue;
10000
- }
10001
-
10002
- if (isVerbose) {
10003
- console.info(
10004
- colors.cyan(`Detected external change in agent source file ${agentSourcePath}, reloading`),
10005
- );
10006
- }
10007
- await forTime(500); // <- TODO: [🙌] !!! Remove
10008
- const newSource = validateBook(await tools.fs!.readFile(agentSourcePath, 'utf-8'));
10009
- agentSource.next(newSource);
10010
- }
10011
-
10012
- // TODO: [🙌] !!!! Debug the infinite loop when file is changed externally and agent source is updated which causes file to be written again
10013
-
10014
- const agent = new Agent({
10015
- ...this.options,
10016
- agentSource,
10017
- executionTools: this.tools || {},
10018
- });
10019
-
10020
- if (isVerbose) {
10021
- console.info(colors.cyan(`Created agent "${agent.agentName}" from source file ${agentSourcePath}`));
10022
- }
10023
-
10024
- return agent;
10025
- * /
10026
- }
10027
- */
10028
9947
  /**
10029
9948
  * !!!@@@
10030
9949
  */
10031
9950
  async getAgentSource(agentName) {
10032
- const result = await this.supabaseClient
9951
+ const selectResult = await this.supabaseClient
10033
9952
  .from('AgentCollection' /* <- TODO: !!!! Change to `Agent` */)
10034
9953
  .select('agentSource')
10035
9954
  .eq('agentName', agentName)
10036
9955
  .single();
10037
- if (result.error) {
9956
+ /*
9957
+ if (selectResult.data===null) {
9958
+ throw new NotFoundError(`Agent "${agentName}" not found`);
9959
+ }
9960
+ */
9961
+ if (selectResult.error) {
10038
9962
  throw new DatabaseError(spaceTrim((block) => `
10039
9963
 
10040
9964
  Error fetching agent "${agentName}" from Supabase:
10041
9965
 
10042
- ${block(result.error.message)}
9966
+ ${block(selectResult.error.message)}
10043
9967
  `));
10044
9968
  // <- TODO: !!! First check if the error is "not found" and throw `NotFoundError` instead then throw `DatabaseError`
10045
9969
  }
10046
- const agentSource = new rxjs.BehaviorSubject(result.data.agentSource);
10047
- // <- TODO: !!!! Dynamic updates
10048
- return agentSource;
9970
+ return selectResult.data.agentSource;
10049
9971
  }
10050
9972
  /**
10051
9973
  * Creates a new agent in the collection
@@ -10055,7 +9977,9 @@
10055
9977
  async createAgent(agentSource) {
10056
9978
  const agentProfile = parseAgentSource(agentSource);
10057
9979
  // <- TODO: [🕛]
10058
- const result = await this.supabaseClient.from('AgentCollection' /* <- TODO: !!!! Change to `Agent` */).insert({
9980
+ const selectResult = await this.supabaseClient
9981
+ .from('AgentCollection' /* <- TODO: !!!! Change to `Agent` */)
9982
+ .insert({
10059
9983
  agentName: agentProfile.agentName || '!!!!!' /* <- TODO: !!!! Remove */,
10060
9984
  agentProfile,
10061
9985
  createdAt: new Date().toISOString(),
@@ -10065,15 +9989,56 @@
10065
9989
  usage: ZERO_USAGE,
10066
9990
  agentSource: agentSource,
10067
9991
  });
10068
- if (result.error) {
9992
+ if (selectResult.error) {
10069
9993
  throw new DatabaseError(spaceTrim((block) => `
10070
9994
  Error creating agent "${agentProfile.agentName}" in Supabase:
10071
9995
 
10072
- ${block(result.error.message)}
9996
+ ${block(selectResult.error.message)}
10073
9997
  `));
10074
9998
  }
10075
9999
  return agentProfile;
10076
10000
  }
10001
+ /**
10002
+ * Updates an existing agent in the collection
10003
+ */
10004
+ async updateAgentSource(agentName, agentSource) {
10005
+ const selectResult = await this.supabaseClient
10006
+ .from('AgentCollection' /* <- TODO: !!!! Change to `Agent` */)
10007
+ .select('agentVersion')
10008
+ .eq('agentName', agentName)
10009
+ .single();
10010
+ if (!selectResult.data) {
10011
+ throw new NotFoundError(`Agent "${agentName}" not found`);
10012
+ }
10013
+ const agentProfile = parseAgentSource(agentSource);
10014
+ // TODO: !!!!!! What about agentName change
10015
+ console.log('!!! agentName', agentName);
10016
+ const oldAgentSource = await this.getAgentSource(agentName);
10017
+ const updateResult = await this.supabaseClient
10018
+ .from('AgentCollection' /* <- TODO: !!!! Change to `Agent` */)
10019
+ .update({
10020
+ // TODO: !!!! Compare not update> agentName: agentProfile.agentName || '!!!!!' /* <- TODO: !!!! Remove */,
10021
+ agentProfile,
10022
+ updatedAt: new Date().toISOString(),
10023
+ agentVersion: selectResult.data.agentVersion + 1,
10024
+ agentSource,
10025
+ promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
10026
+ })
10027
+ .eq('agentName', agentName);
10028
+ const newAgentSource = await this.getAgentSource(agentName);
10029
+ console.log('!!! updateAgent', updateResult);
10030
+ console.log('!!! old', oldAgentSource);
10031
+ console.log('!!! new', newAgentSource);
10032
+ if (updateResult.error) {
10033
+ throw new DatabaseError(spaceTrim((block) => `
10034
+ Error updating agent "${agentName}" in Supabase:
10035
+
10036
+ ${block(updateResult.error.message)}
10037
+ `));
10038
+ }
10039
+ }
10040
+ // TODO: !!!! public async getAgentSourceSubject(agentName: string_agent_name): Promise<BehaviorSubject<string_book>>
10041
+ // Use Supabase realtime logic
10077
10042
  /**
10078
10043
  * Deletes an agent from the collection
10079
10044
  */
@@ -10965,6 +10930,8 @@
10965
10930
  * Function `validateParameterName` will normalize and validate a parameter name for use in pipelines.
10966
10931
  * It removes diacritics, emojis, and quotes, normalizes to camelCase, and checks for reserved names and invalid characters.
10967
10932
  *
10933
+ * Note: [🔂] This function is idempotent.
10934
+ *
10968
10935
  * @param parameterName The parameter name to validate and normalize.
10969
10936
  * @returns The validated and normalized parameter name.
10970
10937
  * @throws {ParseError} If the parameter name is empty, reserved, or contains invalid characters.
@@ -16520,7 +16487,7 @@
16520
16487
  *
16521
16488
  * This is useful for calling OpenAI API with a single assistant, for more wide usage use `OpenAiExecutionTools`.
16522
16489
  *
16523
- * Note: [🦖] There are several different things in Promptbook:
16490
+ * !!! Note: [🦖] There are several different things in Promptbook:
16524
16491
  * - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
16525
16492
  * - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
16526
16493
  * - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
@@ -16626,17 +16593,21 @@
16626
16593
  console.info('connect', stream.currentEvent);
16627
16594
  }
16628
16595
  });
16596
+ /*
16629
16597
  stream.on('messageDelta', (messageDelta) => {
16630
- var _a;
16631
- if (this.options.isVerbose &&
16598
+ if (
16599
+ this.options.isVerbose &&
16632
16600
  messageDelta &&
16633
16601
  messageDelta.content &&
16634
16602
  messageDelta.content[0] &&
16635
- messageDelta.content[0].type === 'text') {
16636
- console.info('messageDelta', (_a = messageDelta.content[0].text) === null || _a === void 0 ? void 0 : _a.value);
16603
+ messageDelta.content[0].type === 'text'
16604
+ ) {
16605
+ console.info('messageDelta', messageDelta.content[0].text?.value);
16637
16606
  }
16607
+
16638
16608
  // <- TODO: [🐚] Make streaming and running tasks working
16639
16609
  });
16610
+ */
16640
16611
  stream.on('messageCreated', (message) => {
16641
16612
  if (this.options.isVerbose) {
16642
16613
  console.info('messageCreated', message);
@@ -16716,64 +16687,85 @@
16716
16687
  throw new NotAllowed(`Creating new assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
16717
16688
  }
16718
16689
  // await this.playground();
16719
- const { name, instructions } = options;
16690
+ const { name, instructions, knowledgeSources } = options;
16720
16691
  const client = await this.getClient();
16721
- /*/
16722
- //TODO: !!!
16723
- async function downloadFile(url: string, folder = './tmp'): Promise<string> {
16724
- const filename = path.basename(url.split('?')[0]);
16725
- const filepath = path.join(folder, filename);
16726
-
16727
- if (!fs.existsSync(folder)) fs.mkdirSync(folder);
16728
-
16729
- const res = await fetch(url);
16730
- if (!res.ok) throw new Error(`Download error: ${url}`);
16731
- const buffer = await res.arrayBuffer();
16732
- fs.writeFileSync(filepath, Buffer.from(buffer));
16733
- console.log(`📥 File downloaded: ${filename}`);
16734
-
16735
- return filepath;
16736
- }
16737
-
16738
- async function uploadFileToOpenAI(filepath: string) {
16739
- const file = await client.files.create({
16740
- file: fs.createReadStream(filepath),
16741
- purpose: 'assistants',
16692
+ let vectorStoreId;
16693
+ // If knowledge sources are provided, create a vector store with them
16694
+ if (knowledgeSources && knowledgeSources.length > 0) {
16695
+ if (this.options.isVerbose) {
16696
+ console.info(`📚 Creating vector store with ${knowledgeSources.length} knowledge sources...`);
16697
+ }
16698
+ // Create a vector store
16699
+ const vectorStore = await client.beta.vectorStores.create({
16700
+ name: `${name} Knowledge Base`,
16742
16701
  });
16743
- console.log(`⬆️ File uploaded to OpenAI: ${file.filename} (${file.id})`);
16744
- return file;
16745
- }
16746
-
16747
- // 🌐 URL addresses of files to upload
16748
- const fileUrls = [
16749
- 'https://raw.githubusercontent.com/vercel/next.js/canary/packages/next/README.md',
16750
- 'https://raw.githubusercontent.com/openai/openai-cookbook/main/examples/How_to_call_the_Assistants_API_with_Node.js.ipynb',
16751
- ];
16752
-
16753
- // 1️⃣ Download files from URL
16754
- const localFiles = [];
16755
- for (const url of fileUrls) {
16756
- const filepath = await downloadFile(url);
16757
- localFiles.push(filepath);
16758
- }
16759
-
16760
- // 2️⃣ Upload files to OpenAI
16761
- const uploadedFiles = [];
16762
- for (const filepath of localFiles) {
16763
- const file = await uploadFileToOpenAI(filepath);
16764
- uploadedFiles.push(file.id);
16702
+ vectorStoreId = vectorStore.id;
16703
+ if (this.options.isVerbose) {
16704
+ console.info(`✅ Vector store created: ${vectorStoreId}`);
16705
+ }
16706
+ // Upload files from knowledge sources to the vector store
16707
+ const fileStreams = [];
16708
+ for (const source of knowledgeSources) {
16709
+ try {
16710
+ // Check if it's a URL
16711
+ if (source.startsWith('http://') || source.startsWith('https://')) {
16712
+ // Download the file
16713
+ const response = await fetch(source);
16714
+ if (!response.ok) {
16715
+ console.error(`Failed to download ${source}: ${response.statusText}`);
16716
+ continue;
16717
+ }
16718
+ const buffer = await response.arrayBuffer();
16719
+ const filename = source.split('/').pop() || 'downloaded-file';
16720
+ const blob = new Blob([buffer]);
16721
+ const file = new File([blob], filename);
16722
+ fileStreams.push(file);
16723
+ }
16724
+ else {
16725
+ // Assume it's a local file path
16726
+ // Note: This will work in Node.js environment
16727
+ // For browser environments, this would need different handling
16728
+ const fs = await import('fs');
16729
+ const fileStream = fs.createReadStream(source);
16730
+ fileStreams.push(fileStream);
16731
+ }
16732
+ }
16733
+ catch (error) {
16734
+ console.error(`Error processing knowledge source ${source}:`, error);
16735
+ }
16736
+ }
16737
+ // Batch upload files to the vector store
16738
+ if (fileStreams.length > 0) {
16739
+ try {
16740
+ await client.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, {
16741
+ files: fileStreams,
16742
+ });
16743
+ if (this.options.isVerbose) {
16744
+ console.info(`✅ Uploaded ${fileStreams.length} files to vector store`);
16745
+ }
16746
+ }
16747
+ catch (error) {
16748
+ console.error('Error uploading files to vector store:', error);
16749
+ }
16750
+ }
16765
16751
  }
16766
- /**/
16767
- // alert('!!!! Creating new OpenAI assistant');
16768
- // 3️⃣ Create assistant with uploaded files
16769
- const assistant = await client.beta.assistants.create({
16752
+ // Create assistant with vector store attached
16753
+ const assistantConfig = {
16770
16754
  name,
16771
16755
  description: 'Assistant created via Promptbook',
16772
16756
  model: 'gpt-4o',
16773
16757
  instructions,
16774
16758
  tools: [/* TODO: [🧠] Maybe add { type: 'code_interpreter' }, */ { type: 'file_search' }],
16775
- // !!!! file_ids: uploadedFiles,
16776
- });
16759
+ };
16760
+ // Attach vector store if created
16761
+ if (vectorStoreId) {
16762
+ assistantConfig.tool_resources = {
16763
+ file_search: {
16764
+ vector_store_ids: [vectorStoreId],
16765
+ },
16766
+ };
16767
+ }
16768
+ const assistant = await client.beta.assistants.create(assistantConfig);
16777
16769
  console.log(`✅ Assistant created: ${assistant.id}`);
16778
16770
  // TODO: !!!! Try listing existing assistants
16779
16771
  // TODO: !!!! Try marking existing assistants by DISCRIMINANT
@@ -16816,7 +16808,7 @@
16816
16808
  * Execution Tools for calling LLM models with a predefined agent "soul"
16817
16809
  * This wraps underlying LLM execution tools and applies agent-specific system prompts and requirements
16818
16810
  *
16819
- * Note: [🦖] There are several different things in Promptbook:
16811
+ * !!! Note: [🦖] There are several different things in Promptbook:
16820
16812
  * - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
16821
16813
  * - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
16822
16814
  * - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
@@ -16932,6 +16924,7 @@
16932
16924
  const assistant = await this.options.llmTools.createNewAssistant({
16933
16925
  name: this.title,
16934
16926
  instructions: modelRequirements.systemMessage,
16927
+ knowledgeSources: modelRequirements.knowledgeSources,
16935
16928
  /*
16936
16929
  !!!
16937
16930
  metadata: {
@@ -16982,7 +16975,7 @@
16982
16975
  /**
16983
16976
  * Represents one AI Agent
16984
16977
  *
16985
- * Note: [🦖] There are several different things in Promptbook:
16978
+ * !!! Note: [🦖] There are several different things in Promptbook:
16986
16979
  * - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
16987
16980
  * - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
16988
16981
  * - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
@@ -16990,7 +16983,7 @@
16990
16983
  *
16991
16984
  * @public exported from `@promptbook/core`
16992
16985
  */
16993
- class Agent {
16986
+ class Agent extends AgentLlmExecutionTools {
16994
16987
  /**
16995
16988
  * Not used in Agent, always returns empty array
16996
16989
  */
@@ -17000,7 +16993,12 @@
17000
16993
  ];
17001
16994
  }
17002
16995
  constructor(options) {
17003
- this.options = options;
16996
+ const agentSource = asUpdatableSubject(options.agentSource);
16997
+ super({
16998
+ isVerbose: options.isVerbose,
16999
+ llmTools: getSingleLlmExecutionTools(options.executionTools.llm),
17000
+ agentSource: agentSource.value, // <- TODO: !!!! Allow to pass BehaviorSubject<string_book> OR refresh llmExecutionTools.callChat on agentSource change
17001
+ });
17004
17002
  /**
17005
17003
  * Name of the agent
17006
17004
  */
@@ -17013,7 +17011,9 @@
17013
17011
  * Metadata like image or color
17014
17012
  */
17015
17013
  this.meta = {};
17016
- this.agentSource = asUpdatableSubject(options.agentSource);
17014
+ // TODO: !!!! Add `Agent` simple "mocked" learning by appending to agent source
17015
+ // TODO: !!!! Add `Agent` learning by promptbookAgent
17016
+ this.agentSource = agentSource;
17017
17017
  this.agentSource.subscribe((source) => {
17018
17018
  const { agentName, personaDescription, meta } = parseAgentSource(source);
17019
17019
  this.agentName = agentName;
@@ -17021,19 +17021,6 @@
17021
17021
  this.meta = { ...this.meta, ...meta };
17022
17022
  });
17023
17023
  }
17024
- /**
17025
- * Creates LlmExecutionTools which exposes the agent as a model
17026
- */
17027
- getLlmExecutionTools() {
17028
- const llmTools = new AgentLlmExecutionTools({
17029
- isVerbose: this.options.isVerbose,
17030
- llmTools: getSingleLlmExecutionTools(this.options.executionTools.llm),
17031
- agentSource: this.agentSource.value, // <- TODO: !!!! Allow to pass BehaviorSubject<string_book> OR refresh llmExecutionTools.callChat on agentSource change
17032
- });
17033
- // TODO: !!!! Add `Agent` simple "mocked" learning by appending to agent source
17034
- // TODO: !!!! Add `Agent` learning by promptbookAgent
17035
- return llmTools;
17036
- }
17037
17024
  }
17038
17025
  /**
17039
17026
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
@@ -17100,6 +17087,106 @@
17100
17087
  * Note: [💞] Ignore a discrepancy between file name and entity name
17101
17088
  */
17102
17089
 
17090
+ /**
17091
+ * Represents one AI Agent
17092
+ *
17093
+ * !!! Note: [🦖] There are several different things in Promptbook:
17094
+ * - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
17095
+ * !!!! `RemoteAgent`
17096
+ * - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
17097
+ * - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
17098
+ * - `OpenAiAssistantExecutionTools` - which is a specific implementation of `LlmExecutionTools` for OpenAI models with assistant capabilities, recommended for usage in `Agent` or `AgentLlmExecutionTools`
17099
+ *
17100
+ * @public exported from `@promptbook/core`
17101
+ */
17102
+ class RemoteAgent extends Agent {
17103
+ static async connect(options) {
17104
+ console.log('!!!!!', `${options.agentUrl}/api/book`);
17105
+ const bookResponse = await fetch(`${options.agentUrl}/api/book`);
17106
+ // <- TODO: !!!! What about closed-source agents?
17107
+ // <- TODO: !!!! Maybe use promptbookFetch
17108
+ const agentSourceValue = (await bookResponse.text());
17109
+ const agentSource = new rxjs.BehaviorSubject(agentSourceValue);
17110
+ // <- TODO: !!!!!! Support updating
17111
+ return new RemoteAgent({
17112
+ ...options,
17113
+ executionTools: {
17114
+ /* Note: These tools are not used */
17115
+ // ---------------------------------------
17116
+ /*
17117
+ TODO: !!! Get rid of
17118
+
17119
+ > You have not provided any `LlmExecutionTools`
17120
+ > This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
17121
+ >
17122
+ > Technically, it's not an error, but it's probably not what you want because it does not make sense to use Promptbook without language models.
17123
+
17124
+ */
17125
+ },
17126
+ agentSource,
17127
+ });
17128
+ }
17129
+ constructor(options) {
17130
+ super(options);
17131
+ this.agentUrl = options.agentUrl;
17132
+ }
17133
+ /**
17134
+ * Calls the agent on agents remote server
17135
+ */
17136
+ async callChatModel(prompt) {
17137
+ // Ensure we're working with a chat prompt
17138
+ if (prompt.modelRequirements.modelVariant !== 'CHAT') {
17139
+ throw new Error('Agents only supports chat prompts');
17140
+ }
17141
+ const bookResponse = await fetch(`${this.agentUrl}/api/chat?message=${encodeURIComponent(prompt.content)}`);
17142
+ // <- TODO: !!!! What about closed-source agents?
17143
+ // <- TODO: !!!! Maybe use promptbookFetch
17144
+ let content = '';
17145
+ if (!bookResponse.body) {
17146
+ content = await bookResponse.text();
17147
+ }
17148
+ else {
17149
+ // Note: [🐚] Problem with streaming is not here but it is not implemented on server
17150
+ const decoder = new TextDecoder();
17151
+ // Web ReadableStream is not async-iterable in many runtimes; use a reader.
17152
+ const reader = bookResponse.body.getReader();
17153
+ try {
17154
+ let doneReading = false;
17155
+ while (!doneReading) {
17156
+ const { done, value } = await reader.read();
17157
+ doneReading = !!done;
17158
+ if (value) {
17159
+ const textChunk = decoder.decode(value, { stream: true });
17160
+ // console.debug('RemoteAgent chunk:', textChunk);
17161
+ content += textChunk;
17162
+ }
17163
+ }
17164
+ // Flush any remaining decoder internal state
17165
+ content += decoder.decode();
17166
+ }
17167
+ finally {
17168
+ reader.releaseLock();
17169
+ }
17170
+ }
17171
+ // <- TODO: !!!!!!!! Transfer metadata
17172
+ const agentResult = {
17173
+ content,
17174
+ modelName: this.modelName,
17175
+ timing: {},
17176
+ usage: {},
17177
+ rawPromptContent: {},
17178
+ rawRequest: {},
17179
+ rawResponse: {},
17180
+ // <- TODO: !!!!!!!! Transfer and proxy the metadata
17181
+ };
17182
+ return agentResult;
17183
+ }
17184
+ }
17185
+ /**
17186
+ * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
17187
+ * TODO: !!! Agent on remote server
17188
+ */
17189
+
17103
17190
  /**
17104
17191
  * Registration of LLM provider metadata
17105
17192
  *
@@ -18318,8 +18405,7 @@
18318
18405
 
18319
18406
  ## Servers
18320
18407
 
18321
- ${block(REMOTE_SERVER_URLS.map(({ title, urls, isAnonymousModeAllowed, description }, index) => `${index + 1}. ${title} ${description}
18322
- ${isAnonymousModeAllowed ? '🐱‍💻 ' : ''} ${urls.join(', ')}
18408
+ ${block(REMOTE_SERVER_URLS.map(({ title, urls, description }, index) => `${index + 1}. ${title} ${description} ${urls.join(', ')}
18323
18409
  `).join('\n'))}
18324
18410
  `);
18325
18411
  fullInfoPieces.push(serversInfo);
@@ -18362,6 +18448,30 @@
18362
18448
  * TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
18363
18449
  */
18364
18450
 
18451
+ const PERSONALITIES = [
18452
+ 'Friendly and helpful AI agent.',
18453
+ 'Professional and efficient virtual assistant.',
18454
+ 'Creative and imaginative digital companion.',
18455
+ 'Knowledgeable and informative AI guide.',
18456
+ 'Empathetic and understanding support bot.',
18457
+ 'Energetic and enthusiastic conversational partner.',
18458
+ 'Calm and patient virtual helper.',
18459
+ 'Curious and inquisitive AI explorer.',
18460
+ 'Witty and humorous digital friend.',
18461
+ 'Serious and focused AI consultant.',
18462
+ ];
18463
+ /**
18464
+ * @@@@
18465
+ *
18466
+ * @private internal helper function
18467
+ */
18468
+ function $randomAgentPersona() {
18469
+ return $randomItem(...PERSONALITIES);
18470
+ }
18471
+ /**
18472
+ * TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
18473
+ */
18474
+
18365
18475
  const FIRSTNAMES = [
18366
18476
  'Paul',
18367
18477
  'George',
@@ -18422,30 +18532,6 @@
18422
18532
  * TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
18423
18533
  */
18424
18534
 
18425
- const PERSONALITIES = [
18426
- 'Friendly and helpful AI agent.',
18427
- 'Professional and efficient virtual assistant.',
18428
- 'Creative and imaginative digital companion.',
18429
- 'Knowledgeable and informative AI guide.',
18430
- 'Empathetic and understanding support bot.',
18431
- 'Energetic and enthusiastic conversational partner.',
18432
- 'Calm and patient virtual helper.',
18433
- 'Curious and inquisitive AI explorer.',
18434
- 'Witty and humorous digital friend.',
18435
- 'Serious and focused AI consultant.',
18436
- ];
18437
- /**
18438
- * @@@@
18439
- *
18440
- * @private internal helper function
18441
- */
18442
- function $randomAgentPersona() {
18443
- return $randomItem(...PERSONALITIES);
18444
- }
18445
- /**
18446
- * TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
18447
- */
18448
-
18449
18535
  /**
18450
18536
  * Generates boilerplate for a new agent book
18451
18537
  *
@@ -18577,6 +18663,7 @@
18577
18663
  exports.PromptbookFetchError = PromptbookFetchError;
18578
18664
  exports.REMOTE_SERVER_URLS = REMOTE_SERVER_URLS;
18579
18665
  exports.RESERVED_PARAMETER_NAMES = RESERVED_PARAMETER_NAMES;
18666
+ exports.RemoteAgent = RemoteAgent;
18580
18667
  exports.SET_IS_VERBOSE = SET_IS_VERBOSE;
18581
18668
  exports.SectionTypes = SectionTypes;
18582
18669
  exports.SheetsFormfactorDefinition = SheetsFormfactorDefinition;