@promptbook/browser 0.110.0 → 0.111.0-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 (29) hide show
  1. package/README.md +4 -0
  2. package/esm/index.es.js +654 -99
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/utils.index.d.ts +12 -0
  5. package/esm/typings/src/book-2.0/agent-source/BookEditable.d.ts +41 -0
  6. package/esm/typings/src/book-2.0/agent-source/CreateAgentModelRequirementsOptions.d.ts +5 -0
  7. package/esm/typings/src/book-components/Chat/Chat/ImagePromptRenderer.d.ts +21 -0
  8. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  9. package/esm/typings/src/book-components/Chat/LlmChat/defaults.d.ts +9 -0
  10. package/esm/typings/src/book-components/Chat/save/_common/ChatSaveFormatDefinition.d.ts +7 -1
  11. package/esm/typings/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +6 -5
  12. package/esm/typings/src/book-components/Chat/save/index.d.ts +3 -3
  13. package/esm/typings/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +11 -0
  14. package/esm/typings/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
  15. package/esm/typings/src/book-components/Chat/utils/parseImagePrompts.d.ts +42 -0
  16. package/esm/typings/src/book-components/Chat/utils/parseImagePrompts.test.d.ts +1 -0
  17. package/esm/typings/src/commitments/MEMORY/MEMORY.d.ts +67 -0
  18. package/esm/typings/src/commitments/MEMORY/MEMORY.test.d.ts +1 -0
  19. package/esm/typings/src/commitments/_common/toolRuntimeContext.d.ts +49 -0
  20. package/esm/typings/src/constants/streaming.d.ts +20 -0
  21. package/esm/typings/src/llm-providers/openai/utils/buildToolInvocationScript.d.ts +9 -0
  22. package/esm/typings/src/utils/clientVersion.d.ts +51 -0
  23. package/esm/typings/src/utils/knowledge/inlineKnowledgeSource.d.ts +13 -9
  24. package/esm/typings/src/utils/normalization/constructImageFilename.d.ts +18 -0
  25. package/esm/typings/src/utils/normalization/constructImageFilename.test.d.ts +1 -0
  26. package/esm/typings/src/version.d.ts +1 -1
  27. package/package.json +2 -2
  28. package/umd/index.umd.js +654 -99
  29. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -29,7 +29,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
29
29
  * @generated
30
30
  * @see https://github.com/webgptorg/promptbook
31
31
  */
32
- const PROMPTBOOK_ENGINE_VERSION = '0.110.0';
32
+ const PROMPTBOOK_ENGINE_VERSION = '0.111.0-0';
33
33
  /**
34
34
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
35
35
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -3860,6 +3860,36 @@ function prompt(strings, ...values) {
3860
3860
  * Note: [💞] Ignore a discrepancy between file name and entity name
3861
3861
  */
3862
3862
 
3863
+ /**
3864
+ * HTTP header used by Promptbook clients to advertise their release version.
3865
+ *
3866
+ * @public exported from `@promptbook/utils`
3867
+ */
3868
+ const CLIENT_VERSION_HEADER = 'x-promptbook-client-version';
3869
+ /**
3870
+ * The latest client (engine) version that the server expects.
3871
+ *
3872
+ * @public exported from `@promptbook/utils`
3873
+ */
3874
+ const CLIENT_LATEST_VERSION = PROMPTBOOK_ENGINE_VERSION;
3875
+ /**
3876
+ * Creates a headers object that includes the client version header.
3877
+ *
3878
+ * @param headers - Optional base headers to clone.
3879
+ * @returns New headers object augmented with `CLIENT_VERSION_HEADER`.
3880
+ *
3881
+ * @public exported from `@promptbook/utils`
3882
+ */
3883
+ function attachClientVersionHeader(headers) {
3884
+ return {
3885
+ ...(headers !== null && headers !== void 0 ? headers : {}),
3886
+ [CLIENT_VERSION_HEADER]: CLIENT_LATEST_VERSION,
3887
+ };
3888
+ }
3889
+ /**
3890
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3891
+ */
3892
+
3863
3893
  /**
3864
3894
  * Detects if the code is running in a browser environment in main thread (Not in a web worker)
3865
3895
  *
@@ -6198,28 +6228,14 @@ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
6198
6228
  * Note: [💞] Ignore a discrepancy between file name and entity name
6199
6229
  */
6200
6230
 
6201
- /**
6202
- * @@@
6203
- *
6204
- * @private thing of inline knowledge
6205
- */
6231
+ /** @private The default base name for inline knowledge files when the content lacks identifying text */
6206
6232
  const INLINE_KNOWLEDGE_BASE_NAME = 'inline-knowledge';
6207
- /**
6208
- * @@@
6209
- *
6210
- * @private thing of inline knowledge
6211
- */
6233
+ /** @private The default file extension used for inline knowledge uploads */
6212
6234
  const INLINE_KNOWLEDGE_EXTENSION = '.txt';
6213
- /**
6214
- * @@@
6215
- *
6216
- * @private thing of inline knowledge
6217
- */
6235
+ /** @private Prefix that identifies base64 data URLs */
6218
6236
  const DATA_URL_PREFIX = 'data:';
6219
6237
  /**
6220
- * @@@
6221
- *
6222
- * @private thing of inline knowledge
6238
+ * @private Retrieves the first meaningful line from the inline content.
6223
6239
  */
6224
6240
  function getFirstNonEmptyLine(content) {
6225
6241
  const lines = content.split(/\r?\n/);
@@ -6232,9 +6248,7 @@ function getFirstNonEmptyLine(content) {
6232
6248
  return null;
6233
6249
  }
6234
6250
  /**
6235
- * @@@
6236
- *
6237
- * @private thing of inline knowledge
6251
+ * @private Determines the base file name by normalizing the first non-empty line.
6238
6252
  */
6239
6253
  function deriveBaseFilename(content) {
6240
6254
  const firstLine = getFirstNonEmptyLine(content);
@@ -6245,22 +6259,18 @@ function deriveBaseFilename(content) {
6245
6259
  return normalized || INLINE_KNOWLEDGE_BASE_NAME;
6246
6260
  }
6247
6261
  /**
6248
- * Creates a data URL that represents the inline knowledge content as a text file.
6249
- *
6250
- * @private thing of inline knowledge
6262
+ * @private Converts inline knowledge into the internal metadata form used for uploads.
6251
6263
  */
6252
6264
  function createInlineKnowledgeSourceFile(content) {
6253
6265
  const trimmedContent = content.trim();
6254
6266
  const baseName = deriveBaseFilename(trimmedContent);
6255
6267
  const filename = `${baseName}${INLINE_KNOWLEDGE_EXTENSION}`;
6256
6268
  const mimeType = 'text/plain';
6257
- const base64 = Buffer.from(trimmedContent, 'utf-8').toString('base64');
6258
- const encodedFilename = encodeURIComponent(filename);
6259
- const url = `${DATA_URL_PREFIX}${mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
6269
+ const buffer = Buffer.from(trimmedContent, 'utf-8');
6260
6270
  return {
6261
6271
  filename,
6262
6272
  mimeType,
6263
- url,
6273
+ buffer,
6264
6274
  };
6265
6275
  }
6266
6276
  /**
@@ -6271,10 +6281,18 @@ function createInlineKnowledgeSourceFile(content) {
6271
6281
  function isDataUrlKnowledgeSource(source) {
6272
6282
  return typeof source === 'string' && source.startsWith(DATA_URL_PREFIX);
6273
6283
  }
6284
+ /**
6285
+ * @private Converts a stored inline knowledge file into a data URL for backwards compatibility.
6286
+ */
6287
+ function inlineKnowledgeSourceToDataUrl(source) {
6288
+ const base64 = source.buffer.toString('base64');
6289
+ const encodedFilename = encodeURIComponent(source.filename);
6290
+ return `${DATA_URL_PREFIX}${source.mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
6291
+ }
6274
6292
  /**
6275
6293
  * Parses a data URL-based knowledge source into its raw buffer, filename, and MIME type.
6276
6294
  *
6277
- * @private thing of inline knowledge
6295
+ * @private utility of inline knowledge processing
6278
6296
  */
6279
6297
  function parseDataUrlKnowledgeSource(source) {
6280
6298
  if (!isDataUrlKnowledgeSource(source)) {
@@ -6407,6 +6425,7 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
6407
6425
  `);
6408
6426
  }
6409
6427
  applyToAgentModelRequirements(requirements, content) {
6428
+ var _a;
6410
6429
  const trimmedContent = content.trim();
6411
6430
  if (!trimmedContent) {
6412
6431
  return requirements;
@@ -6427,9 +6446,13 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
6427
6446
  }
6428
6447
  else {
6429
6448
  const inlineSource = createInlineKnowledgeSourceFile(trimmedContent);
6449
+ const existingInlineSources = (((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.inlineKnowledgeSources) || []).slice();
6430
6450
  const updatedRequirements = {
6431
6451
  ...requirements,
6432
- knowledgeSources: [...(requirements.knowledgeSources || []), inlineSource.url],
6452
+ _metadata: {
6453
+ ...requirements._metadata,
6454
+ inlineKnowledgeSources: [...existingInlineSources, inlineSource],
6455
+ },
6433
6456
  };
6434
6457
  const knowledgeInfo = `Knowledge Source Inline: ${inlineSource.filename} (derived from inline content and processed for retrieval during chat)`;
6435
6458
  return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
@@ -6511,6 +6534,237 @@ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
6511
6534
  * Note: [💞] Ignore a discrepancy between file name and entity name
6512
6535
  */
6513
6536
 
6537
+ /**
6538
+ * @@@
6539
+ *
6540
+ * @private utility for commitments
6541
+ */
6542
+ function formatOptionalInstructionBlock(label, content) {
6543
+ const trimmedContent = spaceTrim$1(content);
6544
+ if (!trimmedContent) {
6545
+ return '';
6546
+ }
6547
+ return spaceTrim$1((block) => `
6548
+ - ${label}:
6549
+ ${block(trimmedContent
6550
+ .split(/\r?\n/)
6551
+ .map((line) => `- ${line}`)
6552
+ .join('\n'))}
6553
+ `);
6554
+ }
6555
+
6556
+ /**
6557
+ * Prompt parameter key used to pass hidden runtime context to tool execution.
6558
+ *
6559
+ * @private internal runtime wiring for commitment tools
6560
+ */
6561
+ const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
6562
+ /**
6563
+ * Hidden argument key used to pass runtime context into individual tool calls.
6564
+ *
6565
+ * @private internal runtime wiring for commitment tools
6566
+ */
6567
+ const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
6568
+ /**
6569
+ * Parses unknown runtime context payload into a normalized object.
6570
+ *
6571
+ * @private internal runtime wiring for commitment tools
6572
+ */
6573
+ function parseToolRuntimeContext(rawValue) {
6574
+ if (!rawValue) {
6575
+ return null;
6576
+ }
6577
+ let parsed = rawValue;
6578
+ if (typeof rawValue === 'string') {
6579
+ try {
6580
+ parsed = JSON.parse(rawValue);
6581
+ }
6582
+ catch (_a) {
6583
+ return null;
6584
+ }
6585
+ }
6586
+ if (!parsed || typeof parsed !== 'object') {
6587
+ return null;
6588
+ }
6589
+ return parsed;
6590
+ }
6591
+ /**
6592
+ * Reads runtime context attached to tool call arguments.
6593
+ *
6594
+ * @private internal runtime wiring for commitment tools
6595
+ */
6596
+ function readToolRuntimeContextFromToolArgs(args) {
6597
+ return parseToolRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]);
6598
+ }
6599
+ /**
6600
+ * Serializes runtime context for prompt parameters.
6601
+ *
6602
+ * @private internal runtime wiring for commitment tools
6603
+ */
6604
+ function serializeToolRuntimeContext(context) {
6605
+ return JSON.stringify(context);
6606
+ }
6607
+ /**
6608
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6609
+ */
6610
+
6611
+ /**
6612
+ * Tool name used to retrieve persisted user memory.
6613
+ *
6614
+ * @private internal MEMORY commitment constant
6615
+ */
6616
+ const RETRIEVE_USER_MEMORY_TOOL_NAME = 'retrieve_user_memory';
6617
+ /**
6618
+ * Tool name used to store persisted user memory.
6619
+ *
6620
+ * @private internal MEMORY commitment constant
6621
+ */
6622
+ const STORE_USER_MEMORY_TOOL_NAME = 'store_user_memory';
6623
+ const UPDATE_USER_MEMORY_TOOL_NAME = 'update_user_memory';
6624
+ const DELETE_USER_MEMORY_TOOL_NAME = 'delete_user_memory';
6625
+ /**
6626
+ * Resolves runtime context from hidden tool arguments.
6627
+ *
6628
+ * @private utility of MEMORY commitment
6629
+ */
6630
+ function resolveMemoryRuntimeContext(args) {
6631
+ const runtimeContext = readToolRuntimeContextFromToolArgs(args);
6632
+ const memoryContext = runtimeContext === null || runtimeContext === void 0 ? void 0 : runtimeContext.memory;
6633
+ return {
6634
+ enabled: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.enabled) === true,
6635
+ userId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.userId,
6636
+ username: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.username,
6637
+ agentId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentId,
6638
+ agentName: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentName,
6639
+ isTeamConversation: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.isTeamConversation) === true,
6640
+ };
6641
+ }
6642
+ /**
6643
+ * Builds a disabled memory-tool response payload.
6644
+ *
6645
+ * @private utility of MEMORY commitment
6646
+ */
6647
+ function createDisabledMemoryResult(action, message) {
6648
+ if (action === 'retrieve') {
6649
+ return {
6650
+ action,
6651
+ status: 'disabled',
6652
+ memories: [],
6653
+ message,
6654
+ };
6655
+ }
6656
+ if (action === 'store') {
6657
+ return {
6658
+ action,
6659
+ status: 'disabled',
6660
+ message,
6661
+ };
6662
+ }
6663
+ if (action === 'update') {
6664
+ return {
6665
+ action,
6666
+ status: 'disabled',
6667
+ message,
6668
+ };
6669
+ }
6670
+ if (action === 'delete') {
6671
+ return {
6672
+ action,
6673
+ status: 'disabled',
6674
+ message,
6675
+ };
6676
+ }
6677
+ throw new Error(`Unsupported memory tool action: ${action}`);
6678
+ }
6679
+ /**
6680
+ * Gets the runtime adapter and returns a disabled result when unavailable.
6681
+ *
6682
+ * @private utility of MEMORY commitment
6683
+ */
6684
+ function getRuntimeAdapterOrDisabledResult(action, runtimeContext) {
6685
+ if (!runtimeContext.enabled || runtimeContext.isTeamConversation) {
6686
+ return {
6687
+ adapter: null,
6688
+ disabledResult: createDisabledMemoryResult(action, runtimeContext.isTeamConversation
6689
+ ? 'Memory is disabled for TEAM conversations.'
6690
+ : 'Memory is disabled for unauthenticated users.'),
6691
+ };
6692
+ }
6693
+ {
6694
+ return {
6695
+ adapter: null,
6696
+ disabledResult: createDisabledMemoryResult(action, 'Memory runtime is not available in this environment.'),
6697
+ };
6698
+ }
6699
+ }
6700
+ /**
6701
+ * Parses retrieve memory arguments.
6702
+ *
6703
+ * @private utility of MEMORY commitment
6704
+ */
6705
+ function parseRetrieveMemoryArgs(args) {
6706
+ const query = typeof args.query === 'string' ? args.query.trim() : undefined;
6707
+ const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? Math.floor(args.limit) : undefined;
6708
+ return {
6709
+ query: query && query.length > 0 ? query : undefined,
6710
+ limit: limit && limit > 0 ? Math.min(limit, 20) : undefined,
6711
+ };
6712
+ }
6713
+ /**
6714
+ * Parses store memory arguments.
6715
+ *
6716
+ * @private utility of MEMORY commitment
6717
+ */
6718
+ function parseStoreMemoryArgs(args) {
6719
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
6720
+ if (!content) {
6721
+ throw new Error('Memory content is required.');
6722
+ }
6723
+ return {
6724
+ content,
6725
+ isGlobal: args.isGlobal === true,
6726
+ };
6727
+ }
6728
+ /**
6729
+ * Parses a memory identifier argument shared across MEMORY tools.
6730
+ *
6731
+ * @private utility of MEMORY commitment
6732
+ */
6733
+ function parseMemoryIdArg(value) {
6734
+ const memoryId = typeof value === 'string' ? value.trim() : '';
6735
+ if (!memoryId) {
6736
+ throw new Error('Memory id is required.');
6737
+ }
6738
+ return memoryId;
6739
+ }
6740
+ /**
6741
+ * Parses update memory arguments.
6742
+ *
6743
+ * @private utility of MEMORY commitment
6744
+ */
6745
+ function parseUpdateMemoryArgs(args) {
6746
+ const memoryId = parseMemoryIdArg(args.memoryId);
6747
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
6748
+ if (!content) {
6749
+ throw new Error('Memory content is required.');
6750
+ }
6751
+ const isGlobal = typeof args.isGlobal === 'boolean' ? args.isGlobal : undefined;
6752
+ return {
6753
+ memoryId,
6754
+ content,
6755
+ isGlobal,
6756
+ };
6757
+ }
6758
+ /**
6759
+ * Parses delete memory arguments.
6760
+ *
6761
+ * @private utility of MEMORY commitment
6762
+ */
6763
+ function parseDeleteMemoryArgs(args) {
6764
+ return {
6765
+ memoryId: parseMemoryIdArg(args.memoryId),
6766
+ };
6767
+ }
6514
6768
  /**
6515
6769
  * MEMORY commitment definition
6516
6770
  *
@@ -6532,6 +6786,9 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
6532
6786
  constructor(type = 'MEMORY') {
6533
6787
  super(type);
6534
6788
  }
6789
+ get requiresContent() {
6790
+ return false;
6791
+ }
6535
6792
  /**
6536
6793
  * Short one-line description of MEMORY.
6537
6794
  */
@@ -6551,21 +6808,14 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
6551
6808
  return spaceTrim$1(`
6552
6809
  # ${this.type}
6553
6810
 
6554
- Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
6811
+ Enables persistent user memory for the current agent. The memory is stored by the runtime and can be retrieved in future conversations.
6555
6812
 
6556
6813
  ## Key aspects
6557
6814
 
6558
- - Both terms work identically and can be used interchangeably.
6559
- - Focuses on user-specific information and interaction history.
6560
- - Helps personalize responses based on past interactions.
6561
- - Maintains continuity across conversations.
6562
-
6563
- ## Differences from KNOWLEDGE
6564
-
6565
- - \`KNOWLEDGE\` is for domain expertise and factual information
6566
- - \`MEMORY\` is for user-specific context and preferences
6567
- - \`MEMORY\` creates more personalized interactions
6568
- - \`MEMORY\` often includes temporal or preference-based information
6815
+ - Both \`MEMORY\` and \`MEMORIES\` work identically.
6816
+ - Stores user-specific details through runtime tools.
6817
+ - Retrieves relevant memories for personalized responses.
6818
+ - Supports optional extra instructions in the commitment content.
6569
6819
 
6570
6820
  ## Examples
6571
6821
 
@@ -6573,10 +6823,7 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
6573
6823
  Personal Assistant
6574
6824
 
6575
6825
  PERSONA You are a personal productivity assistant
6576
- MEMORY User is a software developer working in JavaScript/React
6577
- MEMORY User prefers morning work sessions and afternoon meetings
6578
- MEMORY Previously helped with project planning for mobile apps
6579
- MEMORY User timezone: UTC-8 (Pacific Time)
6826
+ MEMORY Remember user projects and long-term preferences.
6580
6827
  GOAL Help optimize daily productivity and workflow
6581
6828
  \`\`\`
6582
6829
 
@@ -6584,10 +6831,7 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
6584
6831
  Learning Companion
6585
6832
 
6586
6833
  PERSONA You are an educational companion for programming students
6587
- MEMORY Student is learning Python as their first programming language
6588
- MEMORY Previous topics covered: variables, loops, functions
6589
- MEMORY Student learns best with practical examples and exercises
6590
- MEMORY Last session: working on list comprehensions
6834
+ MEMORY Remember only the student's learning progress and preferred study style.
6591
6835
  GOAL Provide progressive learning experiences tailored to student's pace
6592
6836
  \`\`\`
6593
6837
 
@@ -6595,23 +6839,245 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
6595
6839
  Customer Support Agent
6596
6840
 
6597
6841
  PERSONA You are a customer support representative
6598
- MEMORY Customer has premium subscription since 2023
6599
- MEMORY Previous issue: billing question resolved last month
6600
- MEMORY Customer prefers email communication over phone calls
6601
- MEMORY Account shows frequent use of advanced features
6842
+ MEMORY Remember only important support history and communication preferences.
6602
6843
  GOAL Provide personalized support based on customer history
6603
6844
  \`\`\`
6604
6845
  `);
6605
6846
  }
6606
6847
  applyToAgentModelRequirements(requirements, content) {
6607
- const trimmedContent = content.trim();
6608
- if (!trimmedContent) {
6609
- return requirements;
6848
+ const extraInstructions = formatOptionalInstructionBlock('Memory instructions', content);
6849
+ const existingTools = requirements.tools || [];
6850
+ const tools = [...existingTools];
6851
+ if (!tools.some((tool) => tool.name === RETRIEVE_USER_MEMORY_TOOL_NAME)) {
6852
+ tools.push({
6853
+ name: RETRIEVE_USER_MEMORY_TOOL_NAME,
6854
+ description: spaceTrim$1(`
6855
+ Retrieve previously stored user memories relevant to the current conversation.
6856
+ Use this before responding when user context can improve the answer.
6857
+ `),
6858
+ parameters: {
6859
+ type: 'object',
6860
+ properties: {
6861
+ query: {
6862
+ type: 'string',
6863
+ description: 'Optional query used to filter relevant memories.',
6864
+ },
6865
+ limit: {
6866
+ type: 'integer',
6867
+ description: 'Optional maximum number of memories to return (default 5, max 20).',
6868
+ },
6869
+ },
6870
+ },
6871
+ });
6610
6872
  }
6611
- // Create memory section for system message
6612
- const memorySection = `Memory: ${trimmedContent}`;
6613
- // Memory information is contextual and should be included in the system message
6614
- return this.appendToSystemMessage(requirements, memorySection, '\n\n');
6873
+ if (!tools.some((tool) => tool.name === STORE_USER_MEMORY_TOOL_NAME)) {
6874
+ tools.push({
6875
+ name: STORE_USER_MEMORY_TOOL_NAME,
6876
+ description: spaceTrim$1(`
6877
+ Store a durable user memory that should be remembered in future conversations.
6878
+ Store only stable and useful user-specific facts or preferences.
6879
+ `),
6880
+ parameters: {
6881
+ type: 'object',
6882
+ properties: {
6883
+ content: {
6884
+ type: 'string',
6885
+ description: 'Memory text to store.',
6886
+ },
6887
+ isGlobal: {
6888
+ type: 'boolean',
6889
+ description: 'Set true to make this memory global across all user agents.',
6890
+ },
6891
+ },
6892
+ required: ['content'],
6893
+ },
6894
+ });
6895
+ }
6896
+ if (!tools.some((tool) => tool.name === UPDATE_USER_MEMORY_TOOL_NAME)) {
6897
+ tools.push({
6898
+ name: UPDATE_USER_MEMORY_TOOL_NAME,
6899
+ description: spaceTrim$1(`
6900
+ Update an existing user memory after retrieving it, so the stored fact stays accurate.
6901
+ Always pass the memory id you retrieved along with the new content.
6902
+ `),
6903
+ parameters: {
6904
+ type: 'object',
6905
+ properties: {
6906
+ memoryId: {
6907
+ type: 'string',
6908
+ description: 'Unique identifier of the memory entry to update.',
6909
+ },
6910
+ content: {
6911
+ type: 'string',
6912
+ description: 'Updated memory text.',
6913
+ },
6914
+ isGlobal: {
6915
+ type: 'boolean',
6916
+ description: 'Set true to keep the fact global; omit or false to keep it agent-scoped.',
6917
+ },
6918
+ },
6919
+ required: ['memoryId', 'content'],
6920
+ },
6921
+ });
6922
+ }
6923
+ if (!tools.some((tool) => tool.name === DELETE_USER_MEMORY_TOOL_NAME)) {
6924
+ tools.push({
6925
+ name: DELETE_USER_MEMORY_TOOL_NAME,
6926
+ description: spaceTrim$1(`
6927
+ Delete a user memory that is no longer relevant. Deletions are soft so the record is hidden from future queries.
6928
+ `),
6929
+ parameters: {
6930
+ type: 'object',
6931
+ properties: {
6932
+ memoryId: {
6933
+ type: 'string',
6934
+ description: 'Unique identifier of the memory entry to delete.',
6935
+ },
6936
+ },
6937
+ required: ['memoryId'],
6938
+ },
6939
+ });
6940
+ }
6941
+ return this.appendToSystemMessage({
6942
+ ...requirements,
6943
+ tools,
6944
+ _metadata: {
6945
+ ...requirements._metadata,
6946
+ useMemory: content || true,
6947
+ },
6948
+ }, spaceTrim$1((block) => `
6949
+ Memory:
6950
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
6951
+ - You can use persistent user memory tools.
6952
+ - Use "${RETRIEVE_USER_MEMORY_TOOL_NAME}" to load relevant memory before answering.
6953
+ - Use "${STORE_USER_MEMORY_TOOL_NAME}" to save stable user-specific facts that improve future help.
6954
+ - Use "${UPDATE_USER_MEMORY_TOOL_NAME}" to refresh an existing memory when the content changes.
6955
+ - Use "${DELETE_USER_MEMORY_TOOL_NAME}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
6956
+ - Store concise memory items and avoid duplicates.
6957
+ - Never claim memory was saved or loaded unless the tool confirms it.
6958
+ ${block(extraInstructions)}
6959
+ `));
6960
+ }
6961
+ /**
6962
+ * Gets human-readable titles for MEMORY tool functions.
6963
+ */
6964
+ getToolTitles() {
6965
+ return {
6966
+ [RETRIEVE_USER_MEMORY_TOOL_NAME]: 'User memory',
6967
+ [STORE_USER_MEMORY_TOOL_NAME]: 'Store user memory',
6968
+ [UPDATE_USER_MEMORY_TOOL_NAME]: 'Update user memory',
6969
+ [DELETE_USER_MEMORY_TOOL_NAME]: 'Delete user memory',
6970
+ };
6971
+ }
6972
+ /**
6973
+ * Gets MEMORY tool function implementations.
6974
+ */
6975
+ getToolFunctions() {
6976
+ return {
6977
+ async [RETRIEVE_USER_MEMORY_TOOL_NAME](args) {
6978
+ const runtimeContext = resolveMemoryRuntimeContext(args);
6979
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('retrieve', runtimeContext);
6980
+ if (!adapter || disabledResult) {
6981
+ return JSON.stringify(disabledResult);
6982
+ }
6983
+ const parsedArgs = parseRetrieveMemoryArgs(args);
6984
+ try {
6985
+ const memories = await adapter.retrieveMemories(parsedArgs, runtimeContext);
6986
+ const result = {
6987
+ action: 'retrieve',
6988
+ status: 'ok',
6989
+ query: parsedArgs.query,
6990
+ memories,
6991
+ };
6992
+ return JSON.stringify(result);
6993
+ }
6994
+ catch (error) {
6995
+ const result = {
6996
+ action: 'retrieve',
6997
+ status: 'error',
6998
+ query: parsedArgs.query,
6999
+ memories: [],
7000
+ message: error instanceof Error ? error.message : String(error),
7001
+ };
7002
+ return JSON.stringify(result);
7003
+ }
7004
+ },
7005
+ async [STORE_USER_MEMORY_TOOL_NAME](args) {
7006
+ const runtimeContext = resolveMemoryRuntimeContext(args);
7007
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('store', runtimeContext);
7008
+ if (!adapter || disabledResult) {
7009
+ return JSON.stringify(disabledResult);
7010
+ }
7011
+ try {
7012
+ const parsedArgs = parseStoreMemoryArgs(args);
7013
+ const memory = await adapter.storeMemory(parsedArgs, runtimeContext);
7014
+ const result = {
7015
+ action: 'store',
7016
+ status: 'stored',
7017
+ memory,
7018
+ };
7019
+ return JSON.stringify(result);
7020
+ }
7021
+ catch (error) {
7022
+ const result = {
7023
+ action: 'store',
7024
+ status: 'error',
7025
+ message: error instanceof Error ? error.message : String(error),
7026
+ };
7027
+ return JSON.stringify(result);
7028
+ }
7029
+ },
7030
+ async [UPDATE_USER_MEMORY_TOOL_NAME](args) {
7031
+ const runtimeContext = resolveMemoryRuntimeContext(args);
7032
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('update', runtimeContext);
7033
+ if (!adapter || disabledResult) {
7034
+ return JSON.stringify(disabledResult);
7035
+ }
7036
+ try {
7037
+ const parsedArgs = parseUpdateMemoryArgs(args);
7038
+ const memory = await adapter.updateMemory(parsedArgs, runtimeContext);
7039
+ const result = {
7040
+ action: 'update',
7041
+ status: 'updated',
7042
+ memory,
7043
+ };
7044
+ return JSON.stringify(result);
7045
+ }
7046
+ catch (error) {
7047
+ const result = {
7048
+ action: 'update',
7049
+ status: 'error',
7050
+ message: error instanceof Error ? error.message : String(error),
7051
+ };
7052
+ return JSON.stringify(result);
7053
+ }
7054
+ },
7055
+ async [DELETE_USER_MEMORY_TOOL_NAME](args) {
7056
+ const runtimeContext = resolveMemoryRuntimeContext(args);
7057
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('delete', runtimeContext);
7058
+ if (!adapter || disabledResult) {
7059
+ return JSON.stringify(disabledResult);
7060
+ }
7061
+ try {
7062
+ const parsedArgs = parseDeleteMemoryArgs(args);
7063
+ const deleted = await adapter.deleteMemory(parsedArgs, runtimeContext);
7064
+ const result = {
7065
+ action: 'delete',
7066
+ status: 'deleted',
7067
+ memoryId: deleted.id,
7068
+ };
7069
+ return JSON.stringify(result);
7070
+ }
7071
+ catch (error) {
7072
+ const result = {
7073
+ action: 'delete',
7074
+ status: 'error',
7075
+ message: error instanceof Error ? error.message : String(error),
7076
+ };
7077
+ return JSON.stringify(result);
7078
+ }
7079
+ },
7080
+ };
6615
7081
  }
6616
7082
  }
6617
7083
  /**
@@ -8724,14 +9190,30 @@ function buildTeammateRequest(message, context) {
8724
9190
  /**
8725
9191
  * Builds a minimal chat prompt for teammate calls.
8726
9192
  */
8727
- function buildTeammatePrompt(request) {
9193
+ function buildTeammatePrompt(request, runtimeContext) {
8728
9194
  return {
8729
9195
  title: 'Teammate consultation',
8730
9196
  modelRequirements: {
8731
9197
  modelVariant: 'CHAT',
8732
9198
  },
8733
9199
  content: request,
8734
- parameters: {},
9200
+ parameters: {
9201
+ [TOOL_RUNTIME_CONTEXT_PARAMETER]: serializeToolRuntimeContext(runtimeContext),
9202
+ },
9203
+ };
9204
+ }
9205
+ /**
9206
+ * Creates teammate runtime context and marks conversation as team-only memory-disabled.
9207
+ */
9208
+ function createTeamConversationRuntimeContext(value) {
9209
+ const runtimeContext = parseToolRuntimeContext(value) || {};
9210
+ return {
9211
+ ...runtimeContext,
9212
+ memory: {
9213
+ ...(runtimeContext.memory || {}),
9214
+ enabled: false,
9215
+ isTeamConversation: true,
9216
+ },
8735
9217
  };
8736
9218
  }
8737
9219
  /**
@@ -8775,7 +9257,7 @@ function createTeamToolFunction(entry) {
8775
9257
  let toolCalls;
8776
9258
  try {
8777
9259
  const remoteAgent = await getRemoteTeammateAgent(entry.teammate.url);
8778
- const prompt = buildTeammatePrompt(request);
9260
+ const prompt = buildTeammatePrompt(request, createTeamConversationRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]));
8779
9261
  const teammateResult = await remoteAgent.callChatModel(prompt);
8780
9262
  response = teammateResult.content || '';
8781
9263
  toolCalls =
@@ -9325,25 +9807,6 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
9325
9807
  * Note: [💞] Ignore a discrepancy between file name and entity name
9326
9808
  */
9327
9809
 
9328
- /**
9329
- * @@@
9330
- *
9331
- * @private utility for commitments
9332
- */
9333
- function formatOptionalInstructionBlock(label, content) {
9334
- const trimmedContent = spaceTrim$1(content);
9335
- if (!trimmedContent) {
9336
- return '';
9337
- }
9338
- return spaceTrim$1((block) => `
9339
- - ${label}:
9340
- ${block(trimmedContent
9341
- .split(/\r?\n/)
9342
- .map((line) => `- ${line}`)
9343
- .join('\n'))}
9344
- `);
9345
- }
9346
-
9347
9810
  /**
9348
9811
  * Client-side safe wrapper for sending emails.
9349
9812
  *
@@ -16169,6 +16632,7 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
16169
16632
  systemMessage: requirements.systemMessage + '\n\n' + exampleInteractionsContent,
16170
16633
  };
16171
16634
  }
16635
+ requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
16172
16636
  // Remove comment lines (lines starting with #) from the final system message
16173
16637
  // while preserving the original content with comments in metadata
16174
16638
  const cleanedSystemMessage = removeCommentsFromSystemMessage(requirements.systemMessage);
@@ -16177,6 +16641,54 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
16177
16641
  systemMessage: cleanedSystemMessage,
16178
16642
  };
16179
16643
  }
16644
+ /**
16645
+ * @private Attempts to upload inline knowledge entries, falling back to legacy data URLs when the upload fails or is not configured.
16646
+ */
16647
+ async function applyPendingInlineKnowledgeSources(requirements, uploader) {
16648
+ var _a;
16649
+ const inlineSources = extractInlineKnowledgeSources(requirements._metadata);
16650
+ if (inlineSources.length === 0) {
16651
+ return requirements;
16652
+ }
16653
+ const knowledgeSources = [...((_a = requirements.knowledgeSources) !== null && _a !== void 0 ? _a : [])];
16654
+ for (const inlineSource of inlineSources) {
16655
+ const url = uploader
16656
+ ? await uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader)
16657
+ : inlineKnowledgeSourceToDataUrl(inlineSource);
16658
+ knowledgeSources.push(url);
16659
+ }
16660
+ return {
16661
+ ...requirements,
16662
+ knowledgeSources,
16663
+ _metadata: stripInlineKnowledgeMetadata(requirements._metadata),
16664
+ };
16665
+ }
16666
+ async function uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader) {
16667
+ try {
16668
+ return await uploader(inlineSource);
16669
+ }
16670
+ catch (error) {
16671
+ console.error('[inline-knowledge] Failed to upload inline source', {
16672
+ filename: inlineSource.filename,
16673
+ error,
16674
+ });
16675
+ return inlineKnowledgeSourceToDataUrl(inlineSource);
16676
+ }
16677
+ }
16678
+ function extractInlineKnowledgeSources(metadata) {
16679
+ if (!metadata) {
16680
+ return [];
16681
+ }
16682
+ const value = metadata.inlineKnowledgeSources;
16683
+ return Array.isArray(value) ? value : [];
16684
+ }
16685
+ function stripInlineKnowledgeMetadata(metadata) {
16686
+ if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, 'inlineKnowledgeSources')) {
16687
+ return metadata;
16688
+ }
16689
+ const { inlineKnowledgeSources: _unusedInlineKnowledgeSources, ...rest } = metadata;
16690
+ return Object.keys(rest).length > 0 ? rest : undefined;
16691
+ }
16180
16692
  /**
16181
16693
  * Mocked security check for imported files
16182
16694
  *
@@ -17236,6 +17748,28 @@ function mapToolsToOpenAi(tools) {
17236
17748
  }));
17237
17749
  }
17238
17750
 
17751
+ /**
17752
+ * Builds a tool invocation script that injects hidden runtime context into tool args.
17753
+ *
17754
+ * @private utility of OpenAI tool execution wrappers
17755
+ */
17756
+ function buildToolInvocationScript(options) {
17757
+ const { functionName, functionArgsExpression } = options;
17758
+ return `
17759
+ const args = ${functionArgsExpression};
17760
+ const runtimeContextRaw =
17761
+ typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
17762
+ ? undefined
17763
+ : ${TOOL_RUNTIME_CONTEXT_PARAMETER};
17764
+
17765
+ if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
17766
+ args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
17767
+ }
17768
+
17769
+ return await ${functionName}(args);
17770
+ `;
17771
+ }
17772
+
17239
17773
  /**
17240
17774
  * Parses an OpenAI error message to identify which parameter is unsupported
17241
17775
  *
@@ -17589,10 +18123,10 @@ class OpenAiCompatibleExecutionTools {
17589
18123
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
17590
18124
  functionResponse = await scriptTool.execute({
17591
18125
  scriptLanguage: 'javascript',
17592
- script: `
17593
- const args = ${functionArgs};
17594
- return await ${functionName}(args);
17595
- `,
18126
+ script: buildToolInvocationScript({
18127
+ functionName,
18128
+ functionArgsExpression: functionArgs,
18129
+ }),
17596
18130
  parameters: prompt.parameters,
17597
18131
  });
17598
18132
  }
@@ -19294,10 +19828,10 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
19294
19828
  try {
19295
19829
  return await scriptTool.execute({
19296
19830
  scriptLanguage: 'javascript',
19297
- script: `
19298
- const args = ${JSON.stringify(functionArgs)};
19299
- return await ${functionName}(args);
19300
- `,
19831
+ script: buildToolInvocationScript({
19832
+ functionName,
19833
+ functionArgsExpression: JSON.stringify(functionArgs),
19834
+ }),
19301
19835
  parameters: (_c = (_b = runContext === null || runContext === void 0 ? void 0 : runContext.context) === null || _b === void 0 ? void 0 : _b.parameters) !== null && _c !== void 0 ? _c : {},
19302
19836
  });
19303
19837
  }
@@ -19750,10 +20284,10 @@ class OpenAiAssistantExecutionTools extends OpenAiVectorStoreHandler {
19750
20284
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
19751
20285
  functionResponse = await scriptTool.execute({
19752
20286
  scriptLanguage: 'javascript',
19753
- script: `
19754
- const args = ${JSON.stringify(functionArgs)};
19755
- return await ${functionName}(args);
19756
- `,
20287
+ script: buildToolInvocationScript({
20288
+ functionName,
20289
+ functionArgsExpression: JSON.stringify(functionArgs),
20290
+ }),
19757
20291
  parameters: prompt.parameters,
19758
20292
  });
19759
20293
  if (this.options.isVerbose) {
@@ -20969,6 +21503,20 @@ async function _Agent_selfLearnTeacher(prompt, result) {
20969
21503
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
20970
21504
  */
20971
21505
 
21506
+ /**
21507
+ * Keep-alive helpers used for streaming chat responses.
21508
+ *
21509
+ * These constants coordinate the signal sent by the Agents Server streaming
21510
+ * endpoint and the parser in the SDK so we can distinguish between
21511
+ * real content and occasional pings.
21512
+ *
21513
+ * @private internal streaming helper for Promptbook chat connections
21514
+ */
21515
+ const CHAT_STREAM_KEEP_ALIVE_TOKEN = 'STREAM_KEEP_ALIVE';
21516
+ /**
21517
+ * Note: [💞] Ignore a discrepancy between file name and entity name
21518
+ */
21519
+
20972
21520
  /**
20973
21521
  * Resolve a remote META IMAGE value into an absolute URL when possible.
20974
21522
  */
@@ -21043,7 +21591,9 @@ class RemoteAgent extends Agent {
21043
21591
  static async connect(options) {
21044
21592
  var _a, _b, _c;
21045
21593
  const agentProfileUrl = `${options.agentUrl}/api/profile`;
21046
- const profileResponse = await fetch(agentProfileUrl);
21594
+ const profileResponse = await fetch(agentProfileUrl, {
21595
+ headers: attachClientVersionHeader(),
21596
+ });
21047
21597
  // <- TODO: [🐱‍🚀] What about closed-source agents?
21048
21598
  // <- TODO: [🐱‍🚀] Maybe use promptbookFetch
21049
21599
  if (!profileResponse.ok) {
@@ -21144,6 +21694,7 @@ class RemoteAgent extends Agent {
21144
21694
  }
21145
21695
  const response = await fetch(`${this.agentUrl}/api/voice`, {
21146
21696
  method: 'POST',
21697
+ headers: attachClientVersionHeader(),
21147
21698
  body: formData,
21148
21699
  });
21149
21700
  if (!response.ok) {
@@ -21173,13 +21724,14 @@ class RemoteAgent extends Agent {
21173
21724
  const chatPrompt = prompt;
21174
21725
  const bookResponse = await fetch(`${this.agentUrl}/api/chat`, {
21175
21726
  method: 'POST',
21176
- headers: {
21727
+ headers: attachClientVersionHeader({
21177
21728
  'Content-Type': 'application/json',
21178
- },
21729
+ }),
21179
21730
  body: JSON.stringify({
21180
21731
  message: prompt.content,
21181
21732
  thread: chatPrompt.thread,
21182
21733
  attachments: chatPrompt.attachments,
21734
+ parameters: chatPrompt.parameters,
21183
21735
  }),
21184
21736
  });
21185
21737
  // <- TODO: [🐱‍🚀] What about closed-source agents?
@@ -21261,6 +21813,9 @@ class RemoteAgent extends Agent {
21261
21813
  const lines = textChunk.split(/\r?\n/);
21262
21814
  for (const line of lines) {
21263
21815
  const trimmedLine = line.trim();
21816
+ if (trimmedLine === CHAT_STREAM_KEEP_ALIVE_TOKEN) {
21817
+ continue;
21818
+ }
21264
21819
  let isToolCallLine = false;
21265
21820
  if (trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
21266
21821
  try {