@promptbook/cli 0.103.0-46 → 0.103.0-48

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 (109) hide show
  1. package/apps/agents-server/TODO.txt +2 -2
  2. package/apps/agents-server/config.ts.todo +5 -279
  3. package/apps/agents-server/next.config.ts +3 -0
  4. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +1 -1
  5. package/apps/agents-server/src/app/agents/[agentName]/api/book/test.http +2 -2
  6. package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +13 -5
  7. package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/TODO.txt +1 -0
  8. package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/route.ts +53 -0
  9. package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/systemMessage/route.ts +45 -0
  10. package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +54 -0
  11. package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +84 -18
  12. package/apps/agents-server/src/app/agents/[agentName]/book/page.tsx +9 -5
  13. package/apps/agents-server/src/app/agents/[agentName]/book+chat/{SelfLearningBook.tsx → AgentBookAndChatComponent.tsx} +5 -48
  14. package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx +7 -4
  15. package/apps/agents-server/src/app/agents/[agentName]/chat/AgentChatWrapper.tsx +38 -0
  16. package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +23 -0
  17. package/apps/agents-server/src/app/agents/[agentName]/page.tsx +8 -6
  18. package/apps/agents-server/src/app/agents/page.tsx +11 -0
  19. package/apps/agents-server/src/app/api/chat/route.ts +1 -1
  20. package/apps/agents-server/src/app/api/chat-streaming/route.ts +5 -1
  21. package/apps/agents-server/src/app/api/upload/route.ts +71 -0
  22. package/apps/agents-server/src/{supabase/getSupabase.ts → database/$provideSupabase.ts} +11 -7
  23. package/apps/agents-server/src/{supabase/getSupabaseForBrowser.ts → database/$provideSupabaseForBrowser.ts} +9 -5
  24. package/apps/agents-server/src/{supabase/getSupabaseForServer.ts → database/$provideSupabaseForServer.ts} +4 -4
  25. package/apps/agents-server/src/{supabase/getSupabaseForWorker.ts → database/$provideSupabaseForWorker.ts} +5 -4
  26. package/apps/agents-server/src/database/schema.sql +131 -0
  27. package/apps/agents-server/src/database/schema.ts +217 -0
  28. package/apps/agents-server/src/tools/$provideAgentCollectionForServer.ts +3 -2
  29. package/apps/agents-server/src/tools/$provideCdnForServer.ts +28 -0
  30. package/apps/agents-server/src/tools/$provideOpenAiAssistantExecutionToolsForServer.ts +1 -1
  31. package/apps/agents-server/src/utils/cdn/classes/DigitalOceanSpaces.ts +119 -0
  32. package/apps/agents-server/src/utils/cdn/interfaces/IFilesStorage.ts +32 -0
  33. package/apps/agents-server/src/utils/cdn/interfaces/IStorage.ts +14 -0
  34. package/apps/agents-server/src/utils/cdn/utils/getUserFileCdnKey.ts +28 -0
  35. package/apps/agents-server/src/utils/cdn/utils/nameToSubfolderPath.ts +9 -0
  36. package/apps/agents-server/src/utils/cdn/utils/nextRequestToNodeRequest.ts +27 -0
  37. package/apps/agents-server/src/utils/validators/validateMimeType.ts +24 -0
  38. package/apps/agents-server/tsconfig.json +1 -1
  39. package/esm/index.es.js +319 -181
  40. package/esm/index.es.js.map +1 -1
  41. package/esm/typings/servers.d.ts +1 -7
  42. package/esm/typings/src/_packages/components.index.d.ts +4 -0
  43. package/esm/typings/src/_packages/core.index.d.ts +22 -14
  44. package/esm/typings/src/_packages/types.index.d.ts +14 -6
  45. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +7 -3
  46. package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +6 -1
  47. package/esm/typings/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +3 -2
  48. package/esm/typings/src/book-2.0/agent-source/computeAgentHash.d.ts +8 -0
  49. package/esm/typings/src/book-2.0/agent-source/computeAgentHash.test.d.ts +1 -0
  50. package/esm/typings/src/book-2.0/agent-source/createCommitmentRegex.d.ts +1 -1
  51. package/esm/typings/src/book-2.0/agent-source/createDefaultAgentName.d.ts +8 -0
  52. package/esm/typings/src/book-2.0/agent-source/normalizeAgentName.d.ts +9 -0
  53. package/esm/typings/src/book-2.0/agent-source/normalizeAgentName.test.d.ts +1 -0
  54. package/esm/typings/src/book-2.0/agent-source/parseAgentSourceWithCommitments.d.ts +1 -1
  55. package/esm/typings/src/book-components/Chat/AgentChat/AgentChat.d.ts +14 -0
  56. package/esm/typings/src/book-components/Chat/AgentChat/AgentChat.test.d.ts +1 -0
  57. package/esm/typings/src/book-components/Chat/AgentChat/AgentChatProps.d.ts +13 -0
  58. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +1 -60
  59. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +57 -32
  60. package/esm/typings/src/{book-2.0/commitments → commitments}/ACTION/ACTION.d.ts +1 -1
  61. package/esm/typings/src/{book-2.0/commitments → commitments}/DELETE/DELETE.d.ts +1 -1
  62. package/esm/typings/src/{book-2.0/commitments → commitments}/FORMAT/FORMAT.d.ts +1 -1
  63. package/esm/typings/src/{book-2.0/commitments → commitments}/GOAL/GOAL.d.ts +1 -1
  64. package/esm/typings/src/{book-2.0/commitments → commitments}/KNOWLEDGE/KNOWLEDGE.d.ts +1 -5
  65. package/esm/typings/src/{book-2.0/commitments → commitments}/MEMORY/MEMORY.d.ts +1 -1
  66. package/esm/typings/src/{book-2.0/commitments → commitments}/MESSAGE/MESSAGE.d.ts +1 -1
  67. package/esm/typings/src/{book-2.0/commitments → commitments}/META/META.d.ts +1 -1
  68. package/esm/typings/src/{book-2.0/commitments → commitments}/META_IMAGE/META_IMAGE.d.ts +1 -1
  69. package/esm/typings/src/{book-2.0/commitments → commitments}/META_LINK/META_LINK.d.ts +1 -1
  70. package/esm/typings/src/{book-2.0/commitments → commitments}/MODEL/MODEL.d.ts +1 -1
  71. package/esm/typings/src/{book-2.0/commitments → commitments}/NOTE/NOTE.d.ts +1 -1
  72. package/esm/typings/src/{book-2.0/commitments → commitments}/PERSONA/PERSONA.d.ts +1 -1
  73. package/esm/typings/src/{book-2.0/commitments → commitments}/RULE/RULE.d.ts +1 -1
  74. package/esm/typings/src/{book-2.0/commitments → commitments}/SAMPLE/SAMPLE.d.ts +1 -1
  75. package/esm/typings/src/{book-2.0/commitments → commitments}/SCENARIO/SCENARIO.d.ts +1 -1
  76. package/esm/typings/src/{book-2.0/commitments → commitments}/STYLE/STYLE.d.ts +1 -1
  77. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/BaseCommitmentDefinition.d.ts +1 -1
  78. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/CommitmentDefinition.d.ts +1 -1
  79. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/NotYetImplementedCommitmentDefinition.d.ts +1 -1
  80. package/esm/typings/src/{book-2.0/commitments → commitments}/_base/createEmptyAgentModelRequirements.d.ts +1 -1
  81. package/esm/typings/src/execution/LlmExecutionTools.d.ts +1 -1
  82. package/esm/typings/src/llm-providers/_common/utils/assertUniqueModels.d.ts +12 -0
  83. package/esm/typings/src/llm-providers/agent/Agent.d.ts +10 -9
  84. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +5 -1
  85. package/esm/typings/src/llm-providers/agent/CreateAgentLlmExecutionToolsOptions.d.ts +1 -1
  86. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +32 -0
  87. package/esm/typings/src/llm-providers/agent/RemoteAgentOptions.d.ts +11 -0
  88. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +29 -4
  89. package/esm/typings/src/llm-providers/openai/openai-models.test.d.ts +4 -0
  90. package/esm/typings/src/remote-server/startAgentServer.d.ts +1 -1
  91. package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -2
  92. package/esm/typings/src/storage/_common/PromptbookStorage.d.ts +1 -0
  93. package/esm/typings/src/transpilers/openai-sdk/register.d.ts +1 -1
  94. package/esm/typings/src/types/typeAliases.d.ts +12 -0
  95. package/esm/typings/src/utils/color/internal-utils/checkChannelValue.d.ts +0 -3
  96. package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +2 -0
  97. package/esm/typings/src/utils/normalization/normalizeTo_PascalCase.d.ts +3 -0
  98. package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +2 -0
  99. package/esm/typings/src/utils/normalization/titleToName.d.ts +2 -0
  100. package/esm/typings/src/utils/random/$generateBookBoilerplate.d.ts +2 -2
  101. package/esm/typings/src/utils/random/$randomFullnameWithColor.d.ts +1 -1
  102. package/esm/typings/src/version.d.ts +1 -1
  103. package/package.json +1 -1
  104. package/umd/index.umd.js +320 -182
  105. package/umd/index.umd.js.map +1 -1
  106. package/apps/agents-server/src/supabase/TODO.txt +0 -1
  107. /package/esm/typings/src/{book-2.0/commitments → commitments}/_base/BookCommitment.d.ts +0 -0
  108. /package/esm/typings/src/{book-2.0/commitments → commitments}/_base/ParsedCommitment.d.ts +0 -0
  109. /package/esm/typings/src/{book-2.0/commitments → commitments}/index.d.ts +0 -0
package/umd/index.umd.js CHANGED
@@ -56,7 +56,7 @@
56
56
  * @generated
57
57
  * @see https://github.com/webgptorg/promptbook
58
58
  */
59
- const PROMPTBOOK_ENGINE_VERSION = '0.103.0-46';
59
+ const PROMPTBOOK_ENGINE_VERSION = '0.103.0-48';
60
60
  /**
61
61
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
62
62
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -69,15 +69,20 @@
69
69
  */
70
70
  const REMOTE_SERVER_URLS = [
71
71
  {
72
- title: 'Promptbook',
73
- description: `Servers of Promptbook.studio`,
72
+ title: 'Promptbook.Studio',
73
+ description: `Server of Promptbook.studio`,
74
74
  owner: 'AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)',
75
- isAnonymousModeAllowed: true,
76
75
  urls: [
77
76
  'https://promptbook.s5.ptbk.io/',
78
77
  // Note: Servers 1-4 are not running
79
78
  ],
80
79
  },
80
+ {
81
+ title: 'Testing Agents',
82
+ description: `Testing Agents server on Vercel`,
83
+ owner: 'AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)',
84
+ urls: ['https://s6.ptbk.io/'],
85
+ },
81
86
  /*
82
87
  Note: Working on older version of Promptbook and not supported anymore
83
88
  {
@@ -335,9 +340,6 @@
335
340
  throw new Error(`${channelName} channel is greater than 255, it is ${value}`);
336
341
  }
337
342
  }
338
- /**
339
- * TODO: [🧠][🚓] Is/which combination it better to use asserts/check, validate or is utility function?
340
- */
341
343
 
342
344
  /**
343
345
  * Color object represents an RGB color with alpha channel
@@ -2945,6 +2947,8 @@
2945
2947
  /**
2946
2948
  * Converts a given text to kebab-case format.
2947
2949
  *
2950
+ * Note: [🔂] This function is idempotent.
2951
+ *
2948
2952
  * @param text The text to be converted.
2949
2953
  * @returns The kebab-case formatted string.
2950
2954
  * @example 'hello-world'
@@ -3014,6 +3018,8 @@
3014
3018
  /**
3015
3019
  * Converts a title string into a normalized name.
3016
3020
  *
3021
+ * Note: [🔂] This function is idempotent.
3022
+ *
3017
3023
  * @param value The title string to be converted to a name.
3018
3024
  * @returns A normalized name derived from the input title.
3019
3025
  * @example 'Hello World!' -> 'hello-world'
@@ -10024,6 +10030,8 @@
10024
10030
  /**
10025
10031
  * Normalizes a given text to camelCase format.
10026
10032
  *
10033
+ * Note: [🔂] This function is idempotent.
10034
+ *
10027
10035
  * @param text The text to be normalized.
10028
10036
  * @param _isFirstLetterCapital Whether the first letter should be capitalized.
10029
10037
  * @returns The camelCase formatted string.
@@ -13032,6 +13040,9 @@
13032
13040
  }
13033
13041
 
13034
13042
  /**
13043
+ * Normalizes a given text to PascalCase format.
13044
+ *
13045
+ * Note: [🔂] This function is idempotent.
13035
13046
  *
13036
13047
  * @param text @public exported from `@promptbook/utils`
13037
13048
  * @returns
@@ -15089,16 +15100,18 @@
15089
15100
  *
15090
15101
  * @see https://github.com/webgptorg/promptbook#remote-server
15091
15102
  * @public exported from `@promptbook/remote-server`
15092
- * <- TODO: !!!! Maybe change to `@promptbook/agent-server`
15103
+ * <- TODO: !!!! Change to `@promptbook/agent-server`
15093
15104
  */
15094
15105
  async function startAgentServer(options) {
15095
15106
  const { port = 4440 } = options;
15096
15107
  // TODO: !!!! [🌕]
15108
+ const agentsServerRoot = path.join(__dirname, '../apps/agents-server');
15097
15109
  console.trace(`!!! Starting agents server on port ${port}...`);
15098
15110
  console.log(`!!! cwd`, process.cwd());
15099
15111
  console.log(`!!! __dirname`, __dirname);
15112
+ console.log(`!!! agentsServerRoot`, agentsServerRoot);
15100
15113
  await $execCommand({
15101
- cwd: './apps/agents-server',
15114
+ cwd: agentsServerRoot,
15102
15115
  command: `next dev --port ${port} `,
15103
15116
  isVerbose: true,
15104
15117
  });
@@ -16399,8 +16412,7 @@
16399
16412
  };
16400
16413
  }
16401
16414
  /**
16402
- * TODO !!!! Add agent
16403
- * TODO: !!!! Allow to chat with agents directly via remote server
16415
+
16404
16416
  * TODO: [🕋] Use here `aboutPromptbookInformation`
16405
16417
  * TODO: [🌡] Add CORS and security - probably via `helmet`
16406
16418
  * TODO: Split this file into multiple functions - handler for each request
@@ -17521,17 +17533,17 @@
17521
17533
  },
17522
17534
  /**/
17523
17535
  /*/
17524
- {
17525
- modelTitle: 'tts-1-hd-1106',
17526
- modelName: 'tts-1-hd-1106',
17527
- },
17528
- /**/
17536
+ {
17537
+ modelTitle: 'tts-1-hd-1106',
17538
+ modelName: 'tts-1-hd-1106',
17539
+ },
17540
+ /**/
17529
17541
  /*/
17530
- {
17531
- modelTitle: 'tts-1-hd',
17532
- modelName: 'tts-1-hd',
17533
- },
17534
- /**/
17542
+ {
17543
+ modelTitle: 'tts-1-hd',
17544
+ modelName: 'tts-1-hd',
17545
+ },
17546
+ /**/
17535
17547
  /**/
17536
17548
  {
17537
17549
  modelVariant: 'CHAT',
@@ -18851,26 +18863,6 @@
18851
18863
  output: pricing(`$0.45 / 1M tokens`),
18852
18864
  },
18853
18865
  },
18854
- {
18855
- modelVariant: 'CHAT',
18856
- modelTitle: 'Gemini 2.0 Flash',
18857
- modelName: 'gemini-2.0-flash',
18858
- modelDescription: 'Fast, efficient model with 128K context window optimized for rapid response times. Balances performance and cost with 2x lower latency than Pro models while maintaining strong capabilities in text generation, code completion, and logical reasoning. Excellent for interactive applications, chatbots, and services requiring quick responses with good quality.',
18859
- pricing: {
18860
- prompt: pricing(`$0.35 / 1M tokens`),
18861
- output: pricing(`$1.05 / 1M tokens`),
18862
- },
18863
- },
18864
- {
18865
- modelVariant: 'CHAT',
18866
- modelTitle: 'Gemini 2.0 Flash Lite',
18867
- modelName: 'gemini-2.0-flash-lite',
18868
- modelDescription: 'Streamlined version of Gemini 2.0 Flash with 64K context window, designed for extremely low-latency applications. Features 40% smaller model size and 3x faster inference while retaining core capabilities for text and simple reasoning tasks. Perfect for mobile applications, edge deployments, and high-volume services with strict latency requirements.',
18869
- pricing: {
18870
- prompt: pricing(`$0.20 / 1M tokens`),
18871
- output: pricing(`$0.60 / 1M tokens`),
18872
- },
18873
- },
18874
18866
  {
18875
18867
  modelVariant: 'CHAT',
18876
18868
  modelTitle: 'Gemini 2.0 Flash Thinking',
@@ -20407,7 +20399,7 @@
20407
20399
  *
20408
20400
  * This is useful for calling OpenAI API with a single assistant, for more wide usage use `OpenAiExecutionTools`.
20409
20401
  *
20410
- * Note: [🦖] There are several different things in Promptbook:
20402
+ * !!! Note: [🦖] There are several different things in Promptbook:
20411
20403
  * - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
20412
20404
  * - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
20413
20405
  * - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
@@ -20513,17 +20505,21 @@
20513
20505
  console.info('connect', stream.currentEvent);
20514
20506
  }
20515
20507
  });
20508
+ /*
20516
20509
  stream.on('messageDelta', (messageDelta) => {
20517
- var _a;
20518
- if (this.options.isVerbose &&
20510
+ if (
20511
+ this.options.isVerbose &&
20519
20512
  messageDelta &&
20520
20513
  messageDelta.content &&
20521
20514
  messageDelta.content[0] &&
20522
- messageDelta.content[0].type === 'text') {
20523
- console.info('messageDelta', (_a = messageDelta.content[0].text) === null || _a === void 0 ? void 0 : _a.value);
20515
+ messageDelta.content[0].type === 'text'
20516
+ ) {
20517
+ console.info('messageDelta', messageDelta.content[0].text?.value);
20524
20518
  }
20519
+
20525
20520
  // <- TODO: [🐚] Make streaming and running tasks working
20526
20521
  });
20522
+ */
20527
20523
  stream.on('messageCreated', (message) => {
20528
20524
  if (this.options.isVerbose) {
20529
20525
  console.info('messageCreated', message);
@@ -20578,15 +20574,19 @@
20578
20574
  },
20579
20575
  });
20580
20576
  }
20581
- async playground() {
20577
+ /*
20578
+ public async playground() {
20582
20579
  const client = await this.getClient();
20580
+
20583
20581
  // List all assistants
20584
20582
  const assistants = await client.beta.assistants.list();
20585
20583
  console.log('!!! Assistants:', assistants);
20584
+
20586
20585
  // Get details of a specific assistant
20587
20586
  const assistantId = 'asst_MO8fhZf4dGloCfXSHeLcIik0';
20588
20587
  const assistant = await client.beta.assistants.retrieve(assistantId);
20589
20588
  console.log('!!! Assistant Details:', assistant);
20589
+
20590
20590
  // Update an assistant
20591
20591
  const updatedAssistant = await client.beta.assistants.update(assistantId, {
20592
20592
  name: assistant.name + '(M)',
@@ -20596,71 +20596,103 @@
20596
20596
  },
20597
20597
  });
20598
20598
  console.log('!!! Updated Assistant:', updatedAssistant);
20599
- await waitasecond.forEver();
20599
+
20600
+ await forEver();
20601
+ }
20602
+ */
20603
+ /**
20604
+ * Get an existing assistant tool wrapper
20605
+ */
20606
+ getAssistant(assistantId) {
20607
+ return new OpenAiAssistantExecutionTools({
20608
+ ...this.options,
20609
+ assistantId,
20610
+ });
20600
20611
  }
20601
20612
  async createNewAssistant(options) {
20602
20613
  if (!this.isCreatingNewAssistantsAllowed) {
20603
20614
  throw new NotAllowed(`Creating new assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
20604
20615
  }
20605
20616
  // await this.playground();
20606
- const { name, instructions } = options;
20617
+ const { name, instructions, knowledgeSources } = options;
20607
20618
  const client = await this.getClient();
20608
- /*/
20609
- //TODO: !!!
20610
- async function downloadFile(url: string, folder = './tmp'): Promise<string> {
20611
- const filename = path.basename(url.split('?')[0]);
20612
- const filepath = path.join(folder, filename);
20613
-
20614
- if (!fs.existsSync(folder)) fs.mkdirSync(folder);
20615
-
20616
- const res = await fetch(url);
20617
- if (!res.ok) throw new Error(`Download error: ${url}`);
20618
- const buffer = await res.arrayBuffer();
20619
- fs.writeFileSync(filepath, Buffer.from(buffer));
20620
- console.log(`📥 File downloaded: ${filename}`);
20621
-
20622
- return filepath;
20623
- }
20624
-
20625
- async function uploadFileToOpenAI(filepath: string) {
20626
- const file = await client.files.create({
20627
- file: fs.createReadStream(filepath),
20628
- purpose: 'assistants',
20619
+ let vectorStoreId;
20620
+ // If knowledge sources are provided, create a vector store with them
20621
+ if (knowledgeSources && knowledgeSources.length > 0) {
20622
+ if (this.options.isVerbose) {
20623
+ console.info(`📚 Creating vector store with ${knowledgeSources.length} knowledge sources...`);
20624
+ }
20625
+ // Create a vector store
20626
+ const vectorStore = await client.beta.vectorStores.create({
20627
+ name: `${name} Knowledge Base`,
20629
20628
  });
20630
- console.log(`⬆️ File uploaded to OpenAI: ${file.filename} (${file.id})`);
20631
- return file;
20632
- }
20633
-
20634
- // 🌐 URL addresses of files to upload
20635
- const fileUrls = [
20636
- 'https://raw.githubusercontent.com/vercel/next.js/canary/packages/next/README.md',
20637
- 'https://raw.githubusercontent.com/openai/openai-cookbook/main/examples/How_to_call_the_Assistants_API_with_Node.js.ipynb',
20638
- ];
20639
-
20640
- // 1️⃣ Download files from URL
20641
- const localFiles = [];
20642
- for (const url of fileUrls) {
20643
- const filepath = await downloadFile(url);
20644
- localFiles.push(filepath);
20645
- }
20646
-
20647
- // 2️⃣ Upload files to OpenAI
20648
- const uploadedFiles = [];
20649
- for (const filepath of localFiles) {
20650
- const file = await uploadFileToOpenAI(filepath);
20651
- uploadedFiles.push(file.id);
20629
+ vectorStoreId = vectorStore.id;
20630
+ if (this.options.isVerbose) {
20631
+ console.info(`✅ Vector store created: ${vectorStoreId}`);
20632
+ }
20633
+ // Upload files from knowledge sources to the vector store
20634
+ const fileStreams = [];
20635
+ for (const source of knowledgeSources) {
20636
+ try {
20637
+ // Check if it's a URL
20638
+ if (source.startsWith('http://') || source.startsWith('https://')) {
20639
+ // Download the file
20640
+ const response = await fetch(source);
20641
+ if (!response.ok) {
20642
+ console.error(`Failed to download ${source}: ${response.statusText}`);
20643
+ continue;
20644
+ }
20645
+ const buffer = await response.arrayBuffer();
20646
+ const filename = source.split('/').pop() || 'downloaded-file';
20647
+ const blob = new Blob([buffer]);
20648
+ const file = new File([blob], filename);
20649
+ fileStreams.push(file);
20650
+ }
20651
+ else {
20652
+ // Assume it's a local file path
20653
+ // Note: This will work in Node.js environment
20654
+ // For browser environments, this would need different handling
20655
+ const fs = await import('fs');
20656
+ const fileStream = fs.createReadStream(source);
20657
+ fileStreams.push(fileStream);
20658
+ }
20659
+ }
20660
+ catch (error) {
20661
+ console.error(`Error processing knowledge source ${source}:`, error);
20662
+ }
20663
+ }
20664
+ // Batch upload files to the vector store
20665
+ if (fileStreams.length > 0) {
20666
+ try {
20667
+ await client.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, {
20668
+ files: fileStreams,
20669
+ });
20670
+ if (this.options.isVerbose) {
20671
+ console.info(`✅ Uploaded ${fileStreams.length} files to vector store`);
20672
+ }
20673
+ }
20674
+ catch (error) {
20675
+ console.error('Error uploading files to vector store:', error);
20676
+ }
20677
+ }
20652
20678
  }
20653
- /**/
20654
- // alert('!!!! Creating new OpenAI assistant');
20655
- // 3️⃣ Create assistant with uploaded files
20656
- const assistant = await client.beta.assistants.create({
20679
+ // Create assistant with vector store attached
20680
+ const assistantConfig = {
20657
20681
  name,
20658
20682
  description: 'Assistant created via Promptbook',
20659
20683
  model: 'gpt-4o',
20660
20684
  instructions,
20661
20685
  tools: [/* TODO: [🧠] Maybe add { type: 'code_interpreter' }, */ { type: 'file_search' }],
20662
- // !!!! file_ids: uploadedFiles,
20663
- });
20686
+ };
20687
+ // Attach vector store if created
20688
+ if (vectorStoreId) {
20689
+ assistantConfig.tool_resources = {
20690
+ file_search: {
20691
+ vector_store_ids: [vectorStoreId],
20692
+ },
20693
+ };
20694
+ }
20695
+ const assistant = await client.beta.assistants.create(assistantConfig);
20664
20696
  console.log(`✅ Assistant created: ${assistant.id}`);
20665
20697
  // TODO: !!!! Try listing existing assistants
20666
20698
  // TODO: !!!! Try marking existing assistants by DISCRIMINANT
@@ -20671,6 +20703,95 @@
20671
20703
  assistantId: assistant.id,
20672
20704
  });
20673
20705
  }
20706
+ async updateAssistant(options) {
20707
+ if (!this.isCreatingNewAssistantsAllowed) {
20708
+ throw new NotAllowed(`Updating assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
20709
+ }
20710
+ const { assistantId, name, instructions, knowledgeSources } = options;
20711
+ const client = await this.getClient();
20712
+ let vectorStoreId;
20713
+ // If knowledge sources are provided, create a vector store with them
20714
+ // TODO: [🧠] Reuse vector store creation logic from createNewAssistant
20715
+ if (knowledgeSources && knowledgeSources.length > 0) {
20716
+ if (this.options.isVerbose) {
20717
+ console.info(`📚 Creating vector store for update with ${knowledgeSources.length} knowledge sources...`);
20718
+ }
20719
+ // Create a vector store
20720
+ const vectorStore = await client.beta.vectorStores.create({
20721
+ name: `${name} Knowledge Base`,
20722
+ });
20723
+ vectorStoreId = vectorStore.id;
20724
+ if (this.options.isVerbose) {
20725
+ console.info(`✅ Vector store created: ${vectorStoreId}`);
20726
+ }
20727
+ // Upload files from knowledge sources to the vector store
20728
+ const fileStreams = [];
20729
+ for (const source of knowledgeSources) {
20730
+ try {
20731
+ // Check if it's a URL
20732
+ if (source.startsWith('http://') || source.startsWith('https://')) {
20733
+ // Download the file
20734
+ const response = await fetch(source);
20735
+ if (!response.ok) {
20736
+ console.error(`Failed to download ${source}: ${response.statusText}`);
20737
+ continue;
20738
+ }
20739
+ const buffer = await response.arrayBuffer();
20740
+ const filename = source.split('/').pop() || 'downloaded-file';
20741
+ const blob = new Blob([buffer]);
20742
+ const file = new File([blob], filename);
20743
+ fileStreams.push(file);
20744
+ }
20745
+ else {
20746
+ // Assume it's a local file path
20747
+ // Note: This will work in Node.js environment
20748
+ // For browser environments, this would need different handling
20749
+ const fs = await import('fs');
20750
+ const fileStream = fs.createReadStream(source);
20751
+ fileStreams.push(fileStream);
20752
+ }
20753
+ }
20754
+ catch (error) {
20755
+ console.error(`Error processing knowledge source ${source}:`, error);
20756
+ }
20757
+ }
20758
+ // Batch upload files to the vector store
20759
+ if (fileStreams.length > 0) {
20760
+ try {
20761
+ await client.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, {
20762
+ files: fileStreams,
20763
+ });
20764
+ if (this.options.isVerbose) {
20765
+ console.info(`✅ Uploaded ${fileStreams.length} files to vector store`);
20766
+ }
20767
+ }
20768
+ catch (error) {
20769
+ console.error('Error uploading files to vector store:', error);
20770
+ }
20771
+ }
20772
+ }
20773
+ const assistantUpdate = {
20774
+ name,
20775
+ instructions,
20776
+ tools: [/* TODO: [🧠] Maybe add { type: 'code_interpreter' }, */ { type: 'file_search' }],
20777
+ };
20778
+ if (vectorStoreId) {
20779
+ assistantUpdate.tool_resources = {
20780
+ file_search: {
20781
+ vector_store_ids: [vectorStoreId],
20782
+ },
20783
+ };
20784
+ }
20785
+ const assistant = await client.beta.assistants.update(assistantId, assistantUpdate);
20786
+ if (this.options.isVerbose) {
20787
+ console.log(`✅ Assistant updated: ${assistant.id}`);
20788
+ }
20789
+ return new OpenAiAssistantExecutionTools({
20790
+ ...this.options,
20791
+ isCreatingNewAssistantsAllowed: false,
20792
+ assistantId: assistant.id,
20793
+ });
20794
+ }
20674
20795
  /**
20675
20796
  * Discriminant for type guards
20676
20797
  */
@@ -22234,40 +22355,6 @@
22234
22355
  * Note: [💞] Ignore a discrepancy between file name and entity name
22235
22356
  */
22236
22357
 
22237
- /**
22238
- * Creates an empty/basic agent model requirements object
22239
- * This serves as the starting point for the reduce-like pattern
22240
- * where each commitment applies its changes to build the final requirements
22241
- *
22242
- * @public exported from `@promptbook/core`
22243
- */
22244
- function createEmptyAgentModelRequirements() {
22245
- return {
22246
- systemMessage: '',
22247
- // modelName: 'gpt-5',
22248
- modelName: 'gemini-2.5-flash-lite',
22249
- temperature: 0.7,
22250
- topP: 0.9,
22251
- topK: 50,
22252
- };
22253
- }
22254
- /**
22255
- * Creates a basic agent model requirements with just the agent name
22256
- * This is used when we have an agent name but no commitments
22257
- *
22258
- * @public exported from `@promptbook/core`
22259
- */
22260
- function createBasicAgentModelRequirements(agentName) {
22261
- const empty = createEmptyAgentModelRequirements();
22262
- return {
22263
- ...empty,
22264
- systemMessage: `You are ${agentName || 'AI Agent'}`,
22265
- };
22266
- }
22267
- /**
22268
- * TODO: [🐤] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
22269
- */
22270
-
22271
22358
  /**
22272
22359
  * Generates a regex pattern to match a specific commitment
22273
22360
  *
@@ -22801,23 +22888,19 @@
22801
22888
  `);
22802
22889
  }
22803
22890
  applyToAgentModelRequirements(requirements, content) {
22804
- var _a;
22805
22891
  const trimmedContent = content.trim();
22806
22892
  if (!trimmedContent) {
22807
22893
  return requirements;
22808
22894
  }
22809
22895
  // Check if content is a URL (external knowledge source)
22810
- if (this.isUrl(trimmedContent)) {
22896
+ if (isValidUrl(trimmedContent)) {
22811
22897
  // Store the URL for later async processing
22812
22898
  const updatedRequirements = {
22813
22899
  ...requirements,
22814
- metadata: {
22815
- ...requirements.metadata,
22816
- knowledgeSources: [
22817
- ...(((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.knowledgeSources) || []),
22818
- trimmedContent,
22819
- ],
22820
- },
22900
+ knowledgeSources: [
22901
+ ...(requirements.knowledgeSources || []),
22902
+ trimmedContent,
22903
+ ],
22821
22904
  };
22822
22905
  // Add placeholder information about knowledge sources to system message
22823
22906
  const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
@@ -22829,18 +22912,6 @@
22829
22912
  return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
22830
22913
  }
22831
22914
  }
22832
- /**
22833
- * Check if content is a URL
22834
- */
22835
- isUrl(content) {
22836
- try {
22837
- new URL(content);
22838
- return true;
22839
- }
22840
- catch (_a) {
22841
- return false;
22842
- }
22843
- }
22844
22915
  }
22845
22916
  /**
22846
22917
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -23651,6 +23722,7 @@
23651
23722
  // Keep everything after the PERSONA section
23652
23723
  cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
23653
23724
  }
23725
+ // TODO: [🕛] There should be `agentFullname` not `agentName`
23654
23726
  // Create new system message with persona at the beginning
23655
23727
  // Format: "You are {agentName}\n{personaContent}"
23656
23728
  // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
@@ -24138,6 +24210,40 @@
24138
24210
  * Note: [💞] Ignore a discrepancy between file name and entity name
24139
24211
  */
24140
24212
 
24213
+ /**
24214
+ * Creates an empty/basic agent model requirements object
24215
+ * This serves as the starting point for the reduce-like pattern
24216
+ * where each commitment applies its changes to build the final requirements
24217
+ *
24218
+ * @public exported from `@promptbook/core`
24219
+ */
24220
+ function createEmptyAgentModelRequirements() {
24221
+ return {
24222
+ systemMessage: '',
24223
+ // modelName: 'gpt-5',
24224
+ modelName: 'gemini-2.5-flash-lite',
24225
+ temperature: 0.7,
24226
+ topP: 0.9,
24227
+ topK: 50,
24228
+ };
24229
+ }
24230
+ /**
24231
+ * Creates a basic agent model requirements with just the agent name
24232
+ * This is used when we have an agent name but no commitments
24233
+ *
24234
+ * @public exported from `@promptbook/core`
24235
+ */
24236
+ function createBasicAgentModelRequirements(agentName) {
24237
+ const empty = createEmptyAgentModelRequirements();
24238
+ return {
24239
+ ...empty,
24240
+ systemMessage: `You are ${agentName || 'AI Agent'}`,
24241
+ };
24242
+ }
24243
+ /**
24244
+ * TODO: [🐤] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
24245
+ */
24246
+
24141
24247
  /**
24142
24248
  * Parses agent source using the new commitment system with multiline support
24143
24249
  * This function replaces the hardcoded commitment parsing in the original parseAgentSource
@@ -24228,29 +24334,6 @@
24228
24334
  };
24229
24335
  }
24230
24336
 
24231
- /**
24232
- * Removes comment lines (lines starting with #) from a system message
24233
- * This is used to clean up the final system message before sending it to the AI model
24234
- * while preserving the original content with comments in metadata
24235
- *
24236
- * @param systemMessage The system message that may contain comment lines
24237
- * @returns The system message with comment lines removed
24238
- *
24239
- * @private - TODO: [🧠] Maybe should be public?
24240
- */
24241
- function removeCommentsFromSystemMessage(systemMessage) {
24242
- if (!systemMessage) {
24243
- return systemMessage;
24244
- }
24245
- const lines = systemMessage.split('\n');
24246
- const filteredLines = lines.filter((line) => {
24247
- const trimmedLine = line.trim();
24248
- // Remove lines that start with # (comments)
24249
- return !trimmedLine.startsWith('#');
24250
- });
24251
- return filteredLines.join('\n').trim();
24252
- }
24253
-
24254
24337
  /**
24255
24338
  * Parses parameters from text using both supported notations:
24256
24339
  * 1. @Parameter - single word parameter starting with @
@@ -24309,6 +24392,29 @@
24309
24392
  return uniqueParameters;
24310
24393
  }
24311
24394
 
24395
+ /**
24396
+ * Removes comment lines (lines starting with #) from a system message
24397
+ * This is used to clean up the final system message before sending it to the AI model
24398
+ * while preserving the original content with comments in metadata
24399
+ *
24400
+ * @param systemMessage The system message that may contain comment lines
24401
+ * @returns The system message with comment lines removed
24402
+ *
24403
+ * @private - TODO: [🧠] Maybe should be public?
24404
+ */
24405
+ function removeCommentsFromSystemMessage(systemMessage) {
24406
+ if (!systemMessage) {
24407
+ return systemMessage;
24408
+ }
24409
+ const lines = systemMessage.split('\n');
24410
+ const filteredLines = lines.filter((line) => {
24411
+ const trimmedLine = line.trim();
24412
+ // Remove lines that start with # (comments)
24413
+ return !trimmedLine.startsWith('#');
24414
+ });
24415
+ return filteredLines.join('\n').trim();
24416
+ }
24417
+
24312
24418
  /**
24313
24419
  * Creates agent model requirements using the new commitment system
24314
24420
  * This function uses a reduce-like pattern where each commitment applies its changes
@@ -24445,6 +24551,36 @@
24445
24551
  * TODO: [🤹] Figure out best placeholder image generator https://i.pravatar.cc/1000?u=568
24446
24552
  */
24447
24553
 
24554
+ /**
24555
+ * Computes SHA-256 hash of the agent source
24556
+ *
24557
+ * @public exported from `@promptbook/core`
24558
+ */
24559
+ function computeAgentHash(agentSource) {
24560
+ return cryptoJs.SHA256(hexEncoder__default["default"].parse(agentSource /* <- TODO: !!!!! spaceTrim */)).toString( /* hex */);
24561
+ }
24562
+
24563
+ /**
24564
+ * Normalizes agent name from arbitrary string to valid agent name
24565
+ *
24566
+ * Note: [🔂] This function is idempotent.
24567
+ *
24568
+ * @public exported from `@promptbook/core`
24569
+ */
24570
+ function normalizeAgentName(rawAgentName) {
24571
+ return titleToName(spaceTrim__default["default"](rawAgentName));
24572
+ }
24573
+
24574
+ /**
24575
+ * Creates temporary default agent name based on agent source hash
24576
+ *
24577
+ * @public exported from `@promptbook/core`
24578
+ */
24579
+ function createDefaultAgentName(agentSource) {
24580
+ const agentHash = computeAgentHash(agentSource);
24581
+ return normalizeAgentName(`Agent ${agentHash.substring(0, 6)}`);
24582
+ }
24583
+
24448
24584
  /**
24449
24585
  * Parses basic information from agent source
24450
24586
  *
@@ -24487,8 +24623,10 @@
24487
24623
  // Parse parameters using unified approach - both @Parameter and {parameter} notations
24488
24624
  // are treated as the same syntax feature with unified representation
24489
24625
  const parameters = parseParameters(agentSource);
24626
+ const agentHash = computeAgentHash(agentSource);
24490
24627
  return {
24491
- agentName: parseResult.agentName,
24628
+ agentName: normalizeAgentName(parseResult.agentName || createDefaultAgentName(agentSource)),
24629
+ agentHash,
24492
24630
  personaDescription,
24493
24631
  meta,
24494
24632
  parameters,
@@ -24708,7 +24846,7 @@
24708
24846
  });
24709
24847
 
24710
24848
  const answer = response.choices[0].message.content;
24711
- console.log('\\n🧠 ${agentName}:', answer, '\\n');
24849
+ console.log('\\n🧠 ${agentName /* <- TODO: [🕛] There should be `agentFullname` not `agentName` */}:', answer, '\\n');
24712
24850
 
24713
24851
  chatHistory.push({ role: 'assistant', content: answer });
24714
24852
  promptUser();
@@ -24727,7 +24865,7 @@
24727
24865
 
24728
24866
  (async () => {
24729
24867
  await setupKnowledge();
24730
- console.log("🤖 Chat with ${agentName} (type 'exit' to quit)\\n");
24868
+ console.log("🤖 Chat with ${agentName /* <- TODO: [🕛] There should be `agentFullname` not `agentName` */} (type 'exit' to quit)\\n");
24731
24869
  promptUser();
24732
24870
  })();
24733
24871
  `);
@@ -24774,7 +24912,7 @@
24774
24912
  });
24775
24913
 
24776
24914
  const answer = response.choices[0].message.content;
24777
- console.log('\\n🧠 ${agentName}:', answer, '\\n');
24915
+ console.log('\\n🧠 ${agentName /* <- TODO: [🕛] There should be `agentFullname` not `agentName` */}:', answer, '\\n');
24778
24916
 
24779
24917
  chatHistory.push({ role: 'assistant', content: answer });
24780
24918
  promptUser();
@@ -24791,7 +24929,7 @@
24791
24929
  });
24792
24930
  }
24793
24931
 
24794
- console.log("🤖 Chat with ${agentName} (type 'exit' to quit)\\n");
24932
+ console.log("🤖 Chat with ${agentName /* <- TODO: [🕛] There should be `agentFullname` not `agentName` */} (type 'exit' to quit)\\n");
24795
24933
  promptUser();
24796
24934
 
24797
24935
  `);
@@ -24807,7 +24945,7 @@
24807
24945
  * @public exported from `@promptbook/wizard`
24808
24946
  * @public exported from `@promptbook/cli`
24809
24947
  *
24810
- * TODO: !!!! Which package should export this?
24948
+ * TODO: [🧠] Which package should export this?
24811
24949
  */
24812
24950
  const _OpenAiSdkTranspilerRegistration = $bookTranspilersRegister.register(OpenAiSdkTranspiler);
24813
24951
  /**