@promptbook/browser 0.110.0-9 → 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 (45) hide show
  1. package/esm/index.es.js +709 -109
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/src/_packages/components.index.d.ts +4 -0
  4. package/esm/typings/src/_packages/core.index.d.ts +2 -2
  5. package/esm/typings/src/_packages/types.index.d.ts +6 -0
  6. package/esm/typings/src/_packages/utils.index.d.ts +12 -0
  7. package/esm/typings/src/book-2.0/agent-source/AgentReferenceResolver.d.ts +18 -0
  8. package/esm/typings/src/book-2.0/agent-source/BookEditable.d.ts +41 -0
  9. package/esm/typings/src/book-2.0/agent-source/CreateAgentModelRequirementsOptions.d.ts +17 -0
  10. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +8 -2
  11. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.agentReferenceResolver.test.d.ts +1 -0
  12. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.d.ts +4 -5
  13. package/esm/typings/src/book-components/BookEditor/BookEditor.d.ts +42 -0
  14. package/esm/typings/src/book-components/Chat/Chat/ChatActionsBar.d.ts +0 -2
  15. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +11 -0
  16. package/esm/typings/src/book-components/Chat/Chat/ChatSoundToggle.d.ts +12 -0
  17. package/esm/typings/src/book-components/Chat/Chat/ImagePromptRenderer.d.ts +21 -0
  18. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  19. package/esm/typings/src/book-components/Chat/LlmChat/defaults.d.ts +9 -0
  20. package/esm/typings/src/book-components/Chat/hooks/useChatRatings.d.ts +24 -2
  21. package/esm/typings/src/book-components/Chat/save/_common/ChatSaveFormatDefinition.d.ts +7 -1
  22. package/esm/typings/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +6 -5
  23. package/esm/typings/src/book-components/Chat/save/index.d.ts +3 -3
  24. package/esm/typings/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +11 -0
  25. package/esm/typings/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
  26. package/esm/typings/src/book-components/Chat/utils/getToolCallChipletInfo.d.ts +2 -10
  27. package/esm/typings/src/book-components/Chat/utils/parseCitationMarker.d.ts +75 -0
  28. package/esm/typings/src/book-components/Chat/utils/parseCitationsFromContent.d.ts +3 -1
  29. package/esm/typings/src/book-components/Chat/utils/parseCitationsFromContent.test.d.ts +1 -0
  30. package/esm/typings/src/book-components/Chat/utils/parseImagePrompts.d.ts +42 -0
  31. package/esm/typings/src/book-components/Chat/utils/parseImagePrompts.test.d.ts +1 -0
  32. package/esm/typings/src/book-components/icons/ArrowIcon.d.ts +17 -4
  33. package/esm/typings/src/commitments/MEMORY/MEMORY.d.ts +67 -0
  34. package/esm/typings/src/commitments/MEMORY/MEMORY.test.d.ts +1 -0
  35. package/esm/typings/src/commitments/_common/toolRuntimeContext.d.ts +49 -0
  36. package/esm/typings/src/constants/streaming.d.ts +20 -0
  37. package/esm/typings/src/llm-providers/openai/utils/buildToolInvocationScript.d.ts +9 -0
  38. package/esm/typings/src/utils/clientVersion.d.ts +51 -0
  39. package/esm/typings/src/utils/knowledge/inlineKnowledgeSource.d.ts +13 -9
  40. package/esm/typings/src/utils/normalization/constructImageFilename.d.ts +18 -0
  41. package/esm/typings/src/utils/normalization/constructImageFilename.test.d.ts +1 -0
  42. package/esm/typings/src/version.d.ts +1 -1
  43. package/package.json +2 -2
  44. package/umd/index.umd.js +709 -109
  45. 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-9';
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
+ });
6872
+ }
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
+ });
6610
6895
  }
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');
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
  /**
@@ -8597,7 +9063,8 @@ class TeamCommitmentDefinition extends BaseCommitmentDefinition {
8597
9063
  if (!trimmedContent) {
8598
9064
  return requirements;
8599
9065
  }
8600
- const teammates = parseTeamCommitmentContent(trimmedContent, { strict: true });
9066
+ // Keep TEAM resilient: unresolved/malformed teammate entries are skipped, valid ones are still registered.
9067
+ const teammates = parseTeamCommitmentContent(trimmedContent, { strict: false });
8601
9068
  if (teammates.length === 0) {
8602
9069
  return requirements;
8603
9070
  }
@@ -8723,14 +9190,30 @@ function buildTeammateRequest(message, context) {
8723
9190
  /**
8724
9191
  * Builds a minimal chat prompt for teammate calls.
8725
9192
  */
8726
- function buildTeammatePrompt(request) {
9193
+ function buildTeammatePrompt(request, runtimeContext) {
8727
9194
  return {
8728
9195
  title: 'Teammate consultation',
8729
9196
  modelRequirements: {
8730
9197
  modelVariant: 'CHAT',
8731
9198
  },
8732
9199
  content: request,
8733
- 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
+ },
8734
9217
  };
8735
9218
  }
8736
9219
  /**
@@ -8774,7 +9257,7 @@ function createTeamToolFunction(entry) {
8774
9257
  let toolCalls;
8775
9258
  try {
8776
9259
  const remoteAgent = await getRemoteTeammateAgent(entry.teammate.url);
8777
- const prompt = buildTeammatePrompt(request);
9260
+ const prompt = buildTeammatePrompt(request, createTeamConversationRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]));
8778
9261
  const teammateResult = await remoteAgent.callChatModel(prompt);
8779
9262
  response = teammateResult.content || '';
8780
9263
  toolCalls =
@@ -9324,25 +9807,6 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
9324
9807
  * Note: [💞] Ignore a discrepancy between file name and entity name
9325
9808
  */
9326
9809
 
9327
- /**
9328
- * @@@
9329
- *
9330
- * @private utility for commitments
9331
- */
9332
- function formatOptionalInstructionBlock(label, content) {
9333
- const trimmedContent = spaceTrim$1(content);
9334
- if (!trimmedContent) {
9335
- return '';
9336
- }
9337
- return spaceTrim$1((block) => `
9338
- - ${label}:
9339
- ${block(trimmedContent
9340
- .split(/\r?\n/)
9341
- .map((line) => `- ${line}`)
9342
- .join('\n'))}
9343
- `);
9344
- }
9345
-
9346
9810
  /**
9347
9811
  * Client-side safe wrapper for sending emails.
9348
9812
  *
@@ -15955,14 +16419,42 @@ function removeCommentsFromSystemMessage(systemMessage) {
15955
16419
  }
15956
16420
 
15957
16421
  /**
15958
- * Creates agent model requirements using the new commitment system
16422
+ * Creates agent model requirements using the new commitment system.
16423
+ *
15959
16424
  * This function uses a reduce-like pattern where each commitment applies its changes
15960
- * to build the final requirements starting from a basic empty model
16425
+ * to build the final requirements starting from a basic empty model.
15961
16426
  *
15962
- * @public exported from `@promptbook/core`
16427
+ * @param agentSource - Agent source book to parse.
16428
+ * @param modelName - Optional override for the agent model name.
16429
+ * @param options - Additional options such as the agent reference resolver.
16430
+ *
16431
+ * @private @@@
16432
+ */
16433
+ const COMMITMENTS_WITH_AGENT_REFERENCES = new Set(['FROM', 'IMPORT', 'IMPORTS', 'TEAM']);
16434
+ /**
16435
+ * Returns a safe fallback content when a resolver fails to transform a reference commitment.
16436
+ *
16437
+ * @param commitmentType - Commitment being resolved.
16438
+ * @param originalContent - Original unresolved commitment content.
16439
+ * @returns Fallback content that keeps requirement creation resilient.
15963
16440
  */
15964
- async function createAgentModelRequirementsWithCommitments(agentSource, modelName) {
16441
+ function getSafeReferenceCommitmentFallback(commitmentType, originalContent) {
16442
+ if (commitmentType === 'FROM') {
16443
+ return 'VOID';
16444
+ }
16445
+ if (commitmentType === 'IMPORT' || commitmentType === 'IMPORTS' || commitmentType === 'TEAM') {
16446
+ return '';
16447
+ }
16448
+ return originalContent;
16449
+ }
16450
+ /**
16451
+ * @@@
16452
+ *
16453
+ * @private @@@
16454
+ */
16455
+ async function createAgentModelRequirementsWithCommitments(agentSource, modelName, options) {
15965
16456
  var _a;
16457
+ const agentReferenceResolver = options === null || options === void 0 ? void 0 : options.agentReferenceResolver;
15966
16458
  // Parse the agent source to extract commitments
15967
16459
  const parseResult = parseAgentSourceWithCommitments(agentSource);
15968
16460
  // Apply DELETE filtering: remove prior commitments tagged by parameters targeted by DELETE/CANCEL/DISCARD/REMOVE
@@ -16014,6 +16506,17 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
16014
16506
  // Apply each commitment in order using reduce-like pattern
16015
16507
  for (let i = 0; i < filteredCommitments.length; i++) {
16016
16508
  const commitment = filteredCommitments[i];
16509
+ const isReferenceCommitment = Boolean(agentReferenceResolver && COMMITMENTS_WITH_AGENT_REFERENCES.has(commitment.type));
16510
+ let commitmentContent = commitment.content;
16511
+ if (isReferenceCommitment && agentReferenceResolver) {
16512
+ try {
16513
+ commitmentContent = await agentReferenceResolver.resolveCommitmentContent(commitment.type, commitment.content);
16514
+ }
16515
+ catch (error) {
16516
+ console.warn(`Failed to resolve commitment references for ${commitment.type}, falling back to safe defaults:`, error);
16517
+ commitmentContent = getSafeReferenceCommitmentFallback(commitment.type, commitment.content);
16518
+ }
16519
+ }
16017
16520
  // CLOSED commitment should work only if its the last commitment in the book
16018
16521
  if (commitment.type === 'CLOSED' && i !== filteredCommitments.length - 1) {
16019
16522
  continue;
@@ -16021,7 +16524,7 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
16021
16524
  const definition = getCommitmentDefinition(commitment.type);
16022
16525
  if (definition) {
16023
16526
  try {
16024
- requirements = definition.applyToAgentModelRequirements(requirements, commitment.content);
16527
+ requirements = definition.applyToAgentModelRequirements(requirements, commitmentContent);
16025
16528
  }
16026
16529
  catch (error) {
16027
16530
  console.warn(`Failed to apply commitment ${commitment.type}:`, error);
@@ -16129,6 +16632,7 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
16129
16632
  systemMessage: requirements.systemMessage + '\n\n' + exampleInteractionsContent,
16130
16633
  };
16131
16634
  }
16635
+ requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
16132
16636
  // Remove comment lines (lines starting with #) from the final system message
16133
16637
  // while preserving the original content with comments in metadata
16134
16638
  const cleanedSystemMessage = removeCommentsFromSystemMessage(requirements.systemMessage);
@@ -16137,6 +16641,54 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
16137
16641
  systemMessage: cleanedSystemMessage,
16138
16642
  };
16139
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
+ }
16140
16692
  /**
16141
16693
  * Mocked security check for imported files
16142
16694
  *
@@ -16169,23 +16721,28 @@ function isBinaryMimeType(mimeType) {
16169
16721
  }
16170
16722
 
16171
16723
  /**
16172
- * Creates model requirements for an agent based on its source
16724
+ * Creates model requirements for an agent based on its source.
16173
16725
  *
16174
16726
  * There are 2 similar functions:
16175
16727
  * - `parseAgentSource` which is a lightweight parser for agent source, it parses basic information and its purpose is to be quick and synchronous. The commitments there are hardcoded.
16176
16728
  * - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronous.
16177
16729
  *
16730
+ * @param agentSource - Book describing the agent.
16731
+ * @param modelName - Optional override for the agent's model.
16732
+ * @param availableModels - Models that could fulfill the agent.
16733
+ * @param llmTools - Execution tools used when selecting a best model.
16734
+ * @param options - Optional hooks such as the agent reference resolver.
16178
16735
  * @public exported from `@promptbook/core`
16179
16736
  */
16180
- async function createAgentModelRequirements(agentSource, modelName, availableModels, llmTools) {
16737
+ async function createAgentModelRequirements(agentSource, modelName, availableModels, llmTools, options) {
16181
16738
  // If availableModels are provided and no specific modelName is given,
16182
16739
  // use preparePersona to select the best model
16183
16740
  if (availableModels && !modelName && llmTools) {
16184
16741
  const selectedModelName = await selectBestModelUsingPersona(agentSource, llmTools);
16185
- return createAgentModelRequirementsWithCommitments(agentSource, selectedModelName);
16742
+ return createAgentModelRequirementsWithCommitments(agentSource, selectedModelName, options);
16186
16743
  }
16187
16744
  // Use the new commitment-based system with provided or default model
16188
- return createAgentModelRequirementsWithCommitments(agentSource, modelName);
16745
+ return createAgentModelRequirementsWithCommitments(agentSource, modelName, options);
16189
16746
  }
16190
16747
  /**
16191
16748
  * Selects the best model using the preparePersona function
@@ -17191,6 +17748,28 @@ function mapToolsToOpenAi(tools) {
17191
17748
  }));
17192
17749
  }
17193
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
+
17194
17773
  /**
17195
17774
  * Parses an OpenAI error message to identify which parameter is unsupported
17196
17775
  *
@@ -17544,10 +18123,10 @@ class OpenAiCompatibleExecutionTools {
17544
18123
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
17545
18124
  functionResponse = await scriptTool.execute({
17546
18125
  scriptLanguage: 'javascript',
17547
- script: `
17548
- const args = ${functionArgs};
17549
- return await ${functionName}(args);
17550
- `,
18126
+ script: buildToolInvocationScript({
18127
+ functionName,
18128
+ functionArgsExpression: functionArgs,
18129
+ }),
17551
18130
  parameters: prompt.parameters,
17552
18131
  });
17553
18132
  }
@@ -19249,10 +19828,10 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
19249
19828
  try {
19250
19829
  return await scriptTool.execute({
19251
19830
  scriptLanguage: 'javascript',
19252
- script: `
19253
- const args = ${JSON.stringify(functionArgs)};
19254
- return await ${functionName}(args);
19255
- `,
19831
+ script: buildToolInvocationScript({
19832
+ functionName,
19833
+ functionArgsExpression: JSON.stringify(functionArgs),
19834
+ }),
19256
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 : {},
19257
19836
  });
19258
19837
  }
@@ -19705,10 +20284,10 @@ class OpenAiAssistantExecutionTools extends OpenAiVectorStoreHandler {
19705
20284
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
19706
20285
  functionResponse = await scriptTool.execute({
19707
20286
  scriptLanguage: 'javascript',
19708
- script: `
19709
- const args = ${JSON.stringify(functionArgs)};
19710
- return await ${functionName}(args);
19711
- `,
20287
+ script: buildToolInvocationScript({
20288
+ functionName,
20289
+ functionArgsExpression: JSON.stringify(functionArgs),
20290
+ }),
19712
20291
  parameters: prompt.parameters,
19713
20292
  });
19714
20293
  if (this.options.isVerbose) {
@@ -20924,6 +21503,20 @@ async function _Agent_selfLearnTeacher(prompt, result) {
20924
21503
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
20925
21504
  */
20926
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
+
20927
21520
  /**
20928
21521
  * Resolve a remote META IMAGE value into an absolute URL when possible.
20929
21522
  */
@@ -20998,7 +21591,9 @@ class RemoteAgent extends Agent {
20998
21591
  static async connect(options) {
20999
21592
  var _a, _b, _c;
21000
21593
  const agentProfileUrl = `${options.agentUrl}/api/profile`;
21001
- const profileResponse = await fetch(agentProfileUrl);
21594
+ const profileResponse = await fetch(agentProfileUrl, {
21595
+ headers: attachClientVersionHeader(),
21596
+ });
21002
21597
  // <- TODO: [🐱‍🚀] What about closed-source agents?
21003
21598
  // <- TODO: [🐱‍🚀] Maybe use promptbookFetch
21004
21599
  if (!profileResponse.ok) {
@@ -21099,6 +21694,7 @@ class RemoteAgent extends Agent {
21099
21694
  }
21100
21695
  const response = await fetch(`${this.agentUrl}/api/voice`, {
21101
21696
  method: 'POST',
21697
+ headers: attachClientVersionHeader(),
21102
21698
  body: formData,
21103
21699
  });
21104
21700
  if (!response.ok) {
@@ -21128,13 +21724,14 @@ class RemoteAgent extends Agent {
21128
21724
  const chatPrompt = prompt;
21129
21725
  const bookResponse = await fetch(`${this.agentUrl}/api/chat`, {
21130
21726
  method: 'POST',
21131
- headers: {
21727
+ headers: attachClientVersionHeader({
21132
21728
  'Content-Type': 'application/json',
21133
- },
21729
+ }),
21134
21730
  body: JSON.stringify({
21135
21731
  message: prompt.content,
21136
21732
  thread: chatPrompt.thread,
21137
21733
  attachments: chatPrompt.attachments,
21734
+ parameters: chatPrompt.parameters,
21138
21735
  }),
21139
21736
  });
21140
21737
  // <- TODO: [🐱‍🚀] What about closed-source agents?
@@ -21216,6 +21813,9 @@ class RemoteAgent extends Agent {
21216
21813
  const lines = textChunk.split(/\r?\n/);
21217
21814
  for (const line of lines) {
21218
21815
  const trimmedLine = line.trim();
21816
+ if (trimmedLine === CHAT_STREAM_KEEP_ALIVE_TOKEN) {
21817
+ continue;
21818
+ }
21219
21819
  let isToolCallLine = false;
21220
21820
  if (trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
21221
21821
  try {