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