@promptbook/node 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
@@ -48,7 +48,7 @@
48
48
  * @generated
49
49
  * @see https://github.com/webgptorg/promptbook
50
50
  */
51
- const PROMPTBOOK_ENGINE_VERSION = '0.110.0';
51
+ const PROMPTBOOK_ENGINE_VERSION = '0.111.0-0';
52
52
  /**
53
53
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
54
54
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -11280,6 +11280,36 @@
11280
11280
  * Note: [💞] Ignore a discrepancy between file name and entity name
11281
11281
  */
11282
11282
 
11283
+ /**
11284
+ * HTTP header used by Promptbook clients to advertise their release version.
11285
+ *
11286
+ * @public exported from `@promptbook/utils`
11287
+ */
11288
+ const CLIENT_VERSION_HEADER = 'x-promptbook-client-version';
11289
+ /**
11290
+ * The latest client (engine) version that the server expects.
11291
+ *
11292
+ * @public exported from `@promptbook/utils`
11293
+ */
11294
+ const CLIENT_LATEST_VERSION = PROMPTBOOK_ENGINE_VERSION;
11295
+ /**
11296
+ * Creates a headers object that includes the client version header.
11297
+ *
11298
+ * @param headers - Optional base headers to clone.
11299
+ * @returns New headers object augmented with `CLIENT_VERSION_HEADER`.
11300
+ *
11301
+ * @public exported from `@promptbook/utils`
11302
+ */
11303
+ function attachClientVersionHeader(headers) {
11304
+ return {
11305
+ ...(headers !== null && headers !== void 0 ? headers : {}),
11306
+ [CLIENT_VERSION_HEADER]: CLIENT_LATEST_VERSION,
11307
+ };
11308
+ }
11309
+ /**
11310
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11311
+ */
11312
+
11283
11313
  /**
11284
11314
  * Detects if the code is running in a browser environment in main thread (Not in a web worker)
11285
11315
  *
@@ -14569,28 +14599,14 @@
14569
14599
  * Note: [💞] Ignore a discrepancy between file name and entity name
14570
14600
  */
14571
14601
 
14572
- /**
14573
- * @@@
14574
- *
14575
- * @private thing of inline knowledge
14576
- */
14602
+ /** @private The default base name for inline knowledge files when the content lacks identifying text */
14577
14603
  const INLINE_KNOWLEDGE_BASE_NAME = 'inline-knowledge';
14578
- /**
14579
- * @@@
14580
- *
14581
- * @private thing of inline knowledge
14582
- */
14604
+ /** @private The default file extension used for inline knowledge uploads */
14583
14605
  const INLINE_KNOWLEDGE_EXTENSION = '.txt';
14584
- /**
14585
- * @@@
14586
- *
14587
- * @private thing of inline knowledge
14588
- */
14606
+ /** @private Prefix that identifies base64 data URLs */
14589
14607
  const DATA_URL_PREFIX = 'data:';
14590
14608
  /**
14591
- * @@@
14592
- *
14593
- * @private thing of inline knowledge
14609
+ * @private Retrieves the first meaningful line from the inline content.
14594
14610
  */
14595
14611
  function getFirstNonEmptyLine(content) {
14596
14612
  const lines = content.split(/\r?\n/);
@@ -14603,9 +14619,7 @@
14603
14619
  return null;
14604
14620
  }
14605
14621
  /**
14606
- * @@@
14607
- *
14608
- * @private thing of inline knowledge
14622
+ * @private Determines the base file name by normalizing the first non-empty line.
14609
14623
  */
14610
14624
  function deriveBaseFilename(content) {
14611
14625
  const firstLine = getFirstNonEmptyLine(content);
@@ -14616,22 +14630,18 @@
14616
14630
  return normalized || INLINE_KNOWLEDGE_BASE_NAME;
14617
14631
  }
14618
14632
  /**
14619
- * Creates a data URL that represents the inline knowledge content as a text file.
14620
- *
14621
- * @private thing of inline knowledge
14633
+ * @private Converts inline knowledge into the internal metadata form used for uploads.
14622
14634
  */
14623
14635
  function createInlineKnowledgeSourceFile(content) {
14624
14636
  const trimmedContent = content.trim();
14625
14637
  const baseName = deriveBaseFilename(trimmedContent);
14626
14638
  const filename = `${baseName}${INLINE_KNOWLEDGE_EXTENSION}`;
14627
14639
  const mimeType = 'text/plain';
14628
- const base64 = Buffer.from(trimmedContent, 'utf-8').toString('base64');
14629
- const encodedFilename = encodeURIComponent(filename);
14630
- const url = `${DATA_URL_PREFIX}${mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
14640
+ const buffer = Buffer.from(trimmedContent, 'utf-8');
14631
14641
  return {
14632
14642
  filename,
14633
14643
  mimeType,
14634
- url,
14644
+ buffer,
14635
14645
  };
14636
14646
  }
14637
14647
  /**
@@ -14642,10 +14652,18 @@
14642
14652
  function isDataUrlKnowledgeSource(source) {
14643
14653
  return typeof source === 'string' && source.startsWith(DATA_URL_PREFIX);
14644
14654
  }
14655
+ /**
14656
+ * @private Converts a stored inline knowledge file into a data URL for backwards compatibility.
14657
+ */
14658
+ function inlineKnowledgeSourceToDataUrl(source) {
14659
+ const base64 = source.buffer.toString('base64');
14660
+ const encodedFilename = encodeURIComponent(source.filename);
14661
+ return `${DATA_URL_PREFIX}${source.mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
14662
+ }
14645
14663
  /**
14646
14664
  * Parses a data URL-based knowledge source into its raw buffer, filename, and MIME type.
14647
14665
  *
14648
- * @private thing of inline knowledge
14666
+ * @private utility of inline knowledge processing
14649
14667
  */
14650
14668
  function parseDataUrlKnowledgeSource(source) {
14651
14669
  if (!isDataUrlKnowledgeSource(source)) {
@@ -14778,6 +14796,7 @@
14778
14796
  `);
14779
14797
  }
14780
14798
  applyToAgentModelRequirements(requirements, content) {
14799
+ var _a;
14781
14800
  const trimmedContent = content.trim();
14782
14801
  if (!trimmedContent) {
14783
14802
  return requirements;
@@ -14798,9 +14817,13 @@
14798
14817
  }
14799
14818
  else {
14800
14819
  const inlineSource = createInlineKnowledgeSourceFile(trimmedContent);
14820
+ const existingInlineSources = (((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.inlineKnowledgeSources) || []).slice();
14801
14821
  const updatedRequirements = {
14802
14822
  ...requirements,
14803
- knowledgeSources: [...(requirements.knowledgeSources || []), inlineSource.url],
14823
+ _metadata: {
14824
+ ...requirements._metadata,
14825
+ inlineKnowledgeSources: [...existingInlineSources, inlineSource],
14826
+ },
14804
14827
  };
14805
14828
  const knowledgeInfo = `Knowledge Source Inline: ${inlineSource.filename} (derived from inline content and processed for retrieval during chat)`;
14806
14829
  return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
@@ -14882,6 +14905,237 @@
14882
14905
  * Note: [💞] Ignore a discrepancy between file name and entity name
14883
14906
  */
14884
14907
 
14908
+ /**
14909
+ * @@@
14910
+ *
14911
+ * @private utility for commitments
14912
+ */
14913
+ function formatOptionalInstructionBlock(label, content) {
14914
+ const trimmedContent = spaceTrim$1.spaceTrim(content);
14915
+ if (!trimmedContent) {
14916
+ return '';
14917
+ }
14918
+ return spaceTrim$1.spaceTrim((block) => `
14919
+ - ${label}:
14920
+ ${block(trimmedContent
14921
+ .split(/\r?\n/)
14922
+ .map((line) => `- ${line}`)
14923
+ .join('\n'))}
14924
+ `);
14925
+ }
14926
+
14927
+ /**
14928
+ * Prompt parameter key used to pass hidden runtime context to tool execution.
14929
+ *
14930
+ * @private internal runtime wiring for commitment tools
14931
+ */
14932
+ const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
14933
+ /**
14934
+ * Hidden argument key used to pass runtime context into individual tool calls.
14935
+ *
14936
+ * @private internal runtime wiring for commitment tools
14937
+ */
14938
+ const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
14939
+ /**
14940
+ * Parses unknown runtime context payload into a normalized object.
14941
+ *
14942
+ * @private internal runtime wiring for commitment tools
14943
+ */
14944
+ function parseToolRuntimeContext(rawValue) {
14945
+ if (!rawValue) {
14946
+ return null;
14947
+ }
14948
+ let parsed = rawValue;
14949
+ if (typeof rawValue === 'string') {
14950
+ try {
14951
+ parsed = JSON.parse(rawValue);
14952
+ }
14953
+ catch (_a) {
14954
+ return null;
14955
+ }
14956
+ }
14957
+ if (!parsed || typeof parsed !== 'object') {
14958
+ return null;
14959
+ }
14960
+ return parsed;
14961
+ }
14962
+ /**
14963
+ * Reads runtime context attached to tool call arguments.
14964
+ *
14965
+ * @private internal runtime wiring for commitment tools
14966
+ */
14967
+ function readToolRuntimeContextFromToolArgs(args) {
14968
+ return parseToolRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]);
14969
+ }
14970
+ /**
14971
+ * Serializes runtime context for prompt parameters.
14972
+ *
14973
+ * @private internal runtime wiring for commitment tools
14974
+ */
14975
+ function serializeToolRuntimeContext(context) {
14976
+ return JSON.stringify(context);
14977
+ }
14978
+ /**
14979
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14980
+ */
14981
+
14982
+ /**
14983
+ * Tool name used to retrieve persisted user memory.
14984
+ *
14985
+ * @private internal MEMORY commitment constant
14986
+ */
14987
+ const RETRIEVE_USER_MEMORY_TOOL_NAME = 'retrieve_user_memory';
14988
+ /**
14989
+ * Tool name used to store persisted user memory.
14990
+ *
14991
+ * @private internal MEMORY commitment constant
14992
+ */
14993
+ const STORE_USER_MEMORY_TOOL_NAME = 'store_user_memory';
14994
+ const UPDATE_USER_MEMORY_TOOL_NAME = 'update_user_memory';
14995
+ const DELETE_USER_MEMORY_TOOL_NAME = 'delete_user_memory';
14996
+ /**
14997
+ * Resolves runtime context from hidden tool arguments.
14998
+ *
14999
+ * @private utility of MEMORY commitment
15000
+ */
15001
+ function resolveMemoryRuntimeContext(args) {
15002
+ const runtimeContext = readToolRuntimeContextFromToolArgs(args);
15003
+ const memoryContext = runtimeContext === null || runtimeContext === void 0 ? void 0 : runtimeContext.memory;
15004
+ return {
15005
+ enabled: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.enabled) === true,
15006
+ userId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.userId,
15007
+ username: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.username,
15008
+ agentId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentId,
15009
+ agentName: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentName,
15010
+ isTeamConversation: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.isTeamConversation) === true,
15011
+ };
15012
+ }
15013
+ /**
15014
+ * Builds a disabled memory-tool response payload.
15015
+ *
15016
+ * @private utility of MEMORY commitment
15017
+ */
15018
+ function createDisabledMemoryResult(action, message) {
15019
+ if (action === 'retrieve') {
15020
+ return {
15021
+ action,
15022
+ status: 'disabled',
15023
+ memories: [],
15024
+ message,
15025
+ };
15026
+ }
15027
+ if (action === 'store') {
15028
+ return {
15029
+ action,
15030
+ status: 'disabled',
15031
+ message,
15032
+ };
15033
+ }
15034
+ if (action === 'update') {
15035
+ return {
15036
+ action,
15037
+ status: 'disabled',
15038
+ message,
15039
+ };
15040
+ }
15041
+ if (action === 'delete') {
15042
+ return {
15043
+ action,
15044
+ status: 'disabled',
15045
+ message,
15046
+ };
15047
+ }
15048
+ throw new Error(`Unsupported memory tool action: ${action}`);
15049
+ }
15050
+ /**
15051
+ * Gets the runtime adapter and returns a disabled result when unavailable.
15052
+ *
15053
+ * @private utility of MEMORY commitment
15054
+ */
15055
+ function getRuntimeAdapterOrDisabledResult(action, runtimeContext) {
15056
+ if (!runtimeContext.enabled || runtimeContext.isTeamConversation) {
15057
+ return {
15058
+ adapter: null,
15059
+ disabledResult: createDisabledMemoryResult(action, runtimeContext.isTeamConversation
15060
+ ? 'Memory is disabled for TEAM conversations.'
15061
+ : 'Memory is disabled for unauthenticated users.'),
15062
+ };
15063
+ }
15064
+ {
15065
+ return {
15066
+ adapter: null,
15067
+ disabledResult: createDisabledMemoryResult(action, 'Memory runtime is not available in this environment.'),
15068
+ };
15069
+ }
15070
+ }
15071
+ /**
15072
+ * Parses retrieve memory arguments.
15073
+ *
15074
+ * @private utility of MEMORY commitment
15075
+ */
15076
+ function parseRetrieveMemoryArgs(args) {
15077
+ const query = typeof args.query === 'string' ? args.query.trim() : undefined;
15078
+ const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? Math.floor(args.limit) : undefined;
15079
+ return {
15080
+ query: query && query.length > 0 ? query : undefined,
15081
+ limit: limit && limit > 0 ? Math.min(limit, 20) : undefined,
15082
+ };
15083
+ }
15084
+ /**
15085
+ * Parses store memory arguments.
15086
+ *
15087
+ * @private utility of MEMORY commitment
15088
+ */
15089
+ function parseStoreMemoryArgs(args) {
15090
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
15091
+ if (!content) {
15092
+ throw new Error('Memory content is required.');
15093
+ }
15094
+ return {
15095
+ content,
15096
+ isGlobal: args.isGlobal === true,
15097
+ };
15098
+ }
15099
+ /**
15100
+ * Parses a memory identifier argument shared across MEMORY tools.
15101
+ *
15102
+ * @private utility of MEMORY commitment
15103
+ */
15104
+ function parseMemoryIdArg(value) {
15105
+ const memoryId = typeof value === 'string' ? value.trim() : '';
15106
+ if (!memoryId) {
15107
+ throw new Error('Memory id is required.');
15108
+ }
15109
+ return memoryId;
15110
+ }
15111
+ /**
15112
+ * Parses update memory arguments.
15113
+ *
15114
+ * @private utility of MEMORY commitment
15115
+ */
15116
+ function parseUpdateMemoryArgs(args) {
15117
+ const memoryId = parseMemoryIdArg(args.memoryId);
15118
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
15119
+ if (!content) {
15120
+ throw new Error('Memory content is required.');
15121
+ }
15122
+ const isGlobal = typeof args.isGlobal === 'boolean' ? args.isGlobal : undefined;
15123
+ return {
15124
+ memoryId,
15125
+ content,
15126
+ isGlobal,
15127
+ };
15128
+ }
15129
+ /**
15130
+ * Parses delete memory arguments.
15131
+ *
15132
+ * @private utility of MEMORY commitment
15133
+ */
15134
+ function parseDeleteMemoryArgs(args) {
15135
+ return {
15136
+ memoryId: parseMemoryIdArg(args.memoryId),
15137
+ };
15138
+ }
14885
15139
  /**
14886
15140
  * MEMORY commitment definition
14887
15141
  *
@@ -14903,6 +15157,9 @@
14903
15157
  constructor(type = 'MEMORY') {
14904
15158
  super(type);
14905
15159
  }
15160
+ get requiresContent() {
15161
+ return false;
15162
+ }
14906
15163
  /**
14907
15164
  * Short one-line description of MEMORY.
14908
15165
  */
@@ -14922,21 +15179,14 @@
14922
15179
  return spaceTrim$1.spaceTrim(`
14923
15180
  # ${this.type}
14924
15181
 
14925
- 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.
15182
+ Enables persistent user memory for the current agent. The memory is stored by the runtime and can be retrieved in future conversations.
14926
15183
 
14927
15184
  ## Key aspects
14928
15185
 
14929
- - Both terms work identically and can be used interchangeably.
14930
- - Focuses on user-specific information and interaction history.
14931
- - Helps personalize responses based on past interactions.
14932
- - Maintains continuity across conversations.
14933
-
14934
- ## Differences from KNOWLEDGE
14935
-
14936
- - \`KNOWLEDGE\` is for domain expertise and factual information
14937
- - \`MEMORY\` is for user-specific context and preferences
14938
- - \`MEMORY\` creates more personalized interactions
14939
- - \`MEMORY\` often includes temporal or preference-based information
15186
+ - Both \`MEMORY\` and \`MEMORIES\` work identically.
15187
+ - Stores user-specific details through runtime tools.
15188
+ - Retrieves relevant memories for personalized responses.
15189
+ - Supports optional extra instructions in the commitment content.
14940
15190
 
14941
15191
  ## Examples
14942
15192
 
@@ -14944,10 +15194,7 @@
14944
15194
  Personal Assistant
14945
15195
 
14946
15196
  PERSONA You are a personal productivity assistant
14947
- MEMORY User is a software developer working in JavaScript/React
14948
- MEMORY User prefers morning work sessions and afternoon meetings
14949
- MEMORY Previously helped with project planning for mobile apps
14950
- MEMORY User timezone: UTC-8 (Pacific Time)
15197
+ MEMORY Remember user projects and long-term preferences.
14951
15198
  GOAL Help optimize daily productivity and workflow
14952
15199
  \`\`\`
14953
15200
 
@@ -14955,10 +15202,7 @@
14955
15202
  Learning Companion
14956
15203
 
14957
15204
  PERSONA You are an educational companion for programming students
14958
- MEMORY Student is learning Python as their first programming language
14959
- MEMORY Previous topics covered: variables, loops, functions
14960
- MEMORY Student learns best with practical examples and exercises
14961
- MEMORY Last session: working on list comprehensions
15205
+ MEMORY Remember only the student's learning progress and preferred study style.
14962
15206
  GOAL Provide progressive learning experiences tailored to student's pace
14963
15207
  \`\`\`
14964
15208
 
@@ -14966,23 +15210,245 @@
14966
15210
  Customer Support Agent
14967
15211
 
14968
15212
  PERSONA You are a customer support representative
14969
- MEMORY Customer has premium subscription since 2023
14970
- MEMORY Previous issue: billing question resolved last month
14971
- MEMORY Customer prefers email communication over phone calls
14972
- MEMORY Account shows frequent use of advanced features
15213
+ MEMORY Remember only important support history and communication preferences.
14973
15214
  GOAL Provide personalized support based on customer history
14974
15215
  \`\`\`
14975
15216
  `);
14976
15217
  }
14977
15218
  applyToAgentModelRequirements(requirements, content) {
14978
- const trimmedContent = content.trim();
14979
- if (!trimmedContent) {
14980
- return requirements;
15219
+ const extraInstructions = formatOptionalInstructionBlock('Memory instructions', content);
15220
+ const existingTools = requirements.tools || [];
15221
+ const tools = [...existingTools];
15222
+ if (!tools.some((tool) => tool.name === RETRIEVE_USER_MEMORY_TOOL_NAME)) {
15223
+ tools.push({
15224
+ name: RETRIEVE_USER_MEMORY_TOOL_NAME,
15225
+ description: spaceTrim$1.spaceTrim(`
15226
+ Retrieve previously stored user memories relevant to the current conversation.
15227
+ Use this before responding when user context can improve the answer.
15228
+ `),
15229
+ parameters: {
15230
+ type: 'object',
15231
+ properties: {
15232
+ query: {
15233
+ type: 'string',
15234
+ description: 'Optional query used to filter relevant memories.',
15235
+ },
15236
+ limit: {
15237
+ type: 'integer',
15238
+ description: 'Optional maximum number of memories to return (default 5, max 20).',
15239
+ },
15240
+ },
15241
+ },
15242
+ });
14981
15243
  }
14982
- // Create memory section for system message
14983
- const memorySection = `Memory: ${trimmedContent}`;
14984
- // Memory information is contextual and should be included in the system message
14985
- return this.appendToSystemMessage(requirements, memorySection, '\n\n');
15244
+ if (!tools.some((tool) => tool.name === STORE_USER_MEMORY_TOOL_NAME)) {
15245
+ tools.push({
15246
+ name: STORE_USER_MEMORY_TOOL_NAME,
15247
+ description: spaceTrim$1.spaceTrim(`
15248
+ Store a durable user memory that should be remembered in future conversations.
15249
+ Store only stable and useful user-specific facts or preferences.
15250
+ `),
15251
+ parameters: {
15252
+ type: 'object',
15253
+ properties: {
15254
+ content: {
15255
+ type: 'string',
15256
+ description: 'Memory text to store.',
15257
+ },
15258
+ isGlobal: {
15259
+ type: 'boolean',
15260
+ description: 'Set true to make this memory global across all user agents.',
15261
+ },
15262
+ },
15263
+ required: ['content'],
15264
+ },
15265
+ });
15266
+ }
15267
+ if (!tools.some((tool) => tool.name === UPDATE_USER_MEMORY_TOOL_NAME)) {
15268
+ tools.push({
15269
+ name: UPDATE_USER_MEMORY_TOOL_NAME,
15270
+ description: spaceTrim$1.spaceTrim(`
15271
+ Update an existing user memory after retrieving it, so the stored fact stays accurate.
15272
+ Always pass the memory id you retrieved along with the new content.
15273
+ `),
15274
+ parameters: {
15275
+ type: 'object',
15276
+ properties: {
15277
+ memoryId: {
15278
+ type: 'string',
15279
+ description: 'Unique identifier of the memory entry to update.',
15280
+ },
15281
+ content: {
15282
+ type: 'string',
15283
+ description: 'Updated memory text.',
15284
+ },
15285
+ isGlobal: {
15286
+ type: 'boolean',
15287
+ description: 'Set true to keep the fact global; omit or false to keep it agent-scoped.',
15288
+ },
15289
+ },
15290
+ required: ['memoryId', 'content'],
15291
+ },
15292
+ });
15293
+ }
15294
+ if (!tools.some((tool) => tool.name === DELETE_USER_MEMORY_TOOL_NAME)) {
15295
+ tools.push({
15296
+ name: DELETE_USER_MEMORY_TOOL_NAME,
15297
+ description: spaceTrim$1.spaceTrim(`
15298
+ Delete a user memory that is no longer relevant. Deletions are soft so the record is hidden from future queries.
15299
+ `),
15300
+ parameters: {
15301
+ type: 'object',
15302
+ properties: {
15303
+ memoryId: {
15304
+ type: 'string',
15305
+ description: 'Unique identifier of the memory entry to delete.',
15306
+ },
15307
+ },
15308
+ required: ['memoryId'],
15309
+ },
15310
+ });
15311
+ }
15312
+ return this.appendToSystemMessage({
15313
+ ...requirements,
15314
+ tools,
15315
+ _metadata: {
15316
+ ...requirements._metadata,
15317
+ useMemory: content || true,
15318
+ },
15319
+ }, spaceTrim$1.spaceTrim((block) => `
15320
+ Memory:
15321
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
15322
+ - You can use persistent user memory tools.
15323
+ - Use "${RETRIEVE_USER_MEMORY_TOOL_NAME}" to load relevant memory before answering.
15324
+ - Use "${STORE_USER_MEMORY_TOOL_NAME}" to save stable user-specific facts that improve future help.
15325
+ - Use "${UPDATE_USER_MEMORY_TOOL_NAME}" to refresh an existing memory when the content changes.
15326
+ - Use "${DELETE_USER_MEMORY_TOOL_NAME}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
15327
+ - Store concise memory items and avoid duplicates.
15328
+ - Never claim memory was saved or loaded unless the tool confirms it.
15329
+ ${block(extraInstructions)}
15330
+ `));
15331
+ }
15332
+ /**
15333
+ * Gets human-readable titles for MEMORY tool functions.
15334
+ */
15335
+ getToolTitles() {
15336
+ return {
15337
+ [RETRIEVE_USER_MEMORY_TOOL_NAME]: 'User memory',
15338
+ [STORE_USER_MEMORY_TOOL_NAME]: 'Store user memory',
15339
+ [UPDATE_USER_MEMORY_TOOL_NAME]: 'Update user memory',
15340
+ [DELETE_USER_MEMORY_TOOL_NAME]: 'Delete user memory',
15341
+ };
15342
+ }
15343
+ /**
15344
+ * Gets MEMORY tool function implementations.
15345
+ */
15346
+ getToolFunctions() {
15347
+ return {
15348
+ async [RETRIEVE_USER_MEMORY_TOOL_NAME](args) {
15349
+ const runtimeContext = resolveMemoryRuntimeContext(args);
15350
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('retrieve', runtimeContext);
15351
+ if (!adapter || disabledResult) {
15352
+ return JSON.stringify(disabledResult);
15353
+ }
15354
+ const parsedArgs = parseRetrieveMemoryArgs(args);
15355
+ try {
15356
+ const memories = await adapter.retrieveMemories(parsedArgs, runtimeContext);
15357
+ const result = {
15358
+ action: 'retrieve',
15359
+ status: 'ok',
15360
+ query: parsedArgs.query,
15361
+ memories,
15362
+ };
15363
+ return JSON.stringify(result);
15364
+ }
15365
+ catch (error) {
15366
+ const result = {
15367
+ action: 'retrieve',
15368
+ status: 'error',
15369
+ query: parsedArgs.query,
15370
+ memories: [],
15371
+ message: error instanceof Error ? error.message : String(error),
15372
+ };
15373
+ return JSON.stringify(result);
15374
+ }
15375
+ },
15376
+ async [STORE_USER_MEMORY_TOOL_NAME](args) {
15377
+ const runtimeContext = resolveMemoryRuntimeContext(args);
15378
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('store', runtimeContext);
15379
+ if (!adapter || disabledResult) {
15380
+ return JSON.stringify(disabledResult);
15381
+ }
15382
+ try {
15383
+ const parsedArgs = parseStoreMemoryArgs(args);
15384
+ const memory = await adapter.storeMemory(parsedArgs, runtimeContext);
15385
+ const result = {
15386
+ action: 'store',
15387
+ status: 'stored',
15388
+ memory,
15389
+ };
15390
+ return JSON.stringify(result);
15391
+ }
15392
+ catch (error) {
15393
+ const result = {
15394
+ action: 'store',
15395
+ status: 'error',
15396
+ message: error instanceof Error ? error.message : String(error),
15397
+ };
15398
+ return JSON.stringify(result);
15399
+ }
15400
+ },
15401
+ async [UPDATE_USER_MEMORY_TOOL_NAME](args) {
15402
+ const runtimeContext = resolveMemoryRuntimeContext(args);
15403
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('update', runtimeContext);
15404
+ if (!adapter || disabledResult) {
15405
+ return JSON.stringify(disabledResult);
15406
+ }
15407
+ try {
15408
+ const parsedArgs = parseUpdateMemoryArgs(args);
15409
+ const memory = await adapter.updateMemory(parsedArgs, runtimeContext);
15410
+ const result = {
15411
+ action: 'update',
15412
+ status: 'updated',
15413
+ memory,
15414
+ };
15415
+ return JSON.stringify(result);
15416
+ }
15417
+ catch (error) {
15418
+ const result = {
15419
+ action: 'update',
15420
+ status: 'error',
15421
+ message: error instanceof Error ? error.message : String(error),
15422
+ };
15423
+ return JSON.stringify(result);
15424
+ }
15425
+ },
15426
+ async [DELETE_USER_MEMORY_TOOL_NAME](args) {
15427
+ const runtimeContext = resolveMemoryRuntimeContext(args);
15428
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('delete', runtimeContext);
15429
+ if (!adapter || disabledResult) {
15430
+ return JSON.stringify(disabledResult);
15431
+ }
15432
+ try {
15433
+ const parsedArgs = parseDeleteMemoryArgs(args);
15434
+ const deleted = await adapter.deleteMemory(parsedArgs, runtimeContext);
15435
+ const result = {
15436
+ action: 'delete',
15437
+ status: 'deleted',
15438
+ memoryId: deleted.id,
15439
+ };
15440
+ return JSON.stringify(result);
15441
+ }
15442
+ catch (error) {
15443
+ const result = {
15444
+ action: 'delete',
15445
+ status: 'error',
15446
+ message: error instanceof Error ? error.message : String(error),
15447
+ };
15448
+ return JSON.stringify(result);
15449
+ }
15450
+ },
15451
+ };
14986
15452
  }
14987
15453
  }
14988
15454
  /**
@@ -17095,14 +17561,30 @@
17095
17561
  /**
17096
17562
  * Builds a minimal chat prompt for teammate calls.
17097
17563
  */
17098
- function buildTeammatePrompt(request) {
17564
+ function buildTeammatePrompt(request, runtimeContext) {
17099
17565
  return {
17100
17566
  title: 'Teammate consultation',
17101
17567
  modelRequirements: {
17102
17568
  modelVariant: 'CHAT',
17103
17569
  },
17104
17570
  content: request,
17105
- parameters: {},
17571
+ parameters: {
17572
+ [TOOL_RUNTIME_CONTEXT_PARAMETER]: serializeToolRuntimeContext(runtimeContext),
17573
+ },
17574
+ };
17575
+ }
17576
+ /**
17577
+ * Creates teammate runtime context and marks conversation as team-only memory-disabled.
17578
+ */
17579
+ function createTeamConversationRuntimeContext(value) {
17580
+ const runtimeContext = parseToolRuntimeContext(value) || {};
17581
+ return {
17582
+ ...runtimeContext,
17583
+ memory: {
17584
+ ...(runtimeContext.memory || {}),
17585
+ enabled: false,
17586
+ isTeamConversation: true,
17587
+ },
17106
17588
  };
17107
17589
  }
17108
17590
  /**
@@ -17146,7 +17628,7 @@
17146
17628
  let toolCalls;
17147
17629
  try {
17148
17630
  const remoteAgent = await getRemoteTeammateAgent(entry.teammate.url);
17149
- const prompt = buildTeammatePrompt(request);
17631
+ const prompt = buildTeammatePrompt(request, createTeamConversationRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]));
17150
17632
  const teammateResult = await remoteAgent.callChatModel(prompt);
17151
17633
  response = teammateResult.content || '';
17152
17634
  toolCalls =
@@ -17696,25 +18178,6 @@
17696
18178
  * Note: [💞] Ignore a discrepancy between file name and entity name
17697
18179
  */
17698
18180
 
17699
- /**
17700
- * @@@
17701
- *
17702
- * @private utility for commitments
17703
- */
17704
- function formatOptionalInstructionBlock(label, content) {
17705
- const trimmedContent = spaceTrim$1.spaceTrim(content);
17706
- if (!trimmedContent) {
17707
- return '';
17708
- }
17709
- return spaceTrim$1.spaceTrim((block) => `
17710
- - ${label}:
17711
- ${block(trimmedContent
17712
- .split(/\r?\n/)
17713
- .map((line) => `- ${line}`)
17714
- .join('\n'))}
17715
- `);
17716
- }
17717
-
17718
18181
  /**
17719
18182
  * Client-side safe wrapper for sending emails.
17720
18183
  *
@@ -21516,6 +21979,7 @@
21516
21979
  systemMessage: requirements.systemMessage + '\n\n' + exampleInteractionsContent,
21517
21980
  };
21518
21981
  }
21982
+ requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
21519
21983
  // Remove comment lines (lines starting with #) from the final system message
21520
21984
  // while preserving the original content with comments in metadata
21521
21985
  const cleanedSystemMessage = removeCommentsFromSystemMessage(requirements.systemMessage);
@@ -21524,6 +21988,54 @@
21524
21988
  systemMessage: cleanedSystemMessage,
21525
21989
  };
21526
21990
  }
21991
+ /**
21992
+ * @private Attempts to upload inline knowledge entries, falling back to legacy data URLs when the upload fails or is not configured.
21993
+ */
21994
+ async function applyPendingInlineKnowledgeSources(requirements, uploader) {
21995
+ var _a;
21996
+ const inlineSources = extractInlineKnowledgeSources(requirements._metadata);
21997
+ if (inlineSources.length === 0) {
21998
+ return requirements;
21999
+ }
22000
+ const knowledgeSources = [...((_a = requirements.knowledgeSources) !== null && _a !== void 0 ? _a : [])];
22001
+ for (const inlineSource of inlineSources) {
22002
+ const url = uploader
22003
+ ? await uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader)
22004
+ : inlineKnowledgeSourceToDataUrl(inlineSource);
22005
+ knowledgeSources.push(url);
22006
+ }
22007
+ return {
22008
+ ...requirements,
22009
+ knowledgeSources,
22010
+ _metadata: stripInlineKnowledgeMetadata(requirements._metadata),
22011
+ };
22012
+ }
22013
+ async function uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader) {
22014
+ try {
22015
+ return await uploader(inlineSource);
22016
+ }
22017
+ catch (error) {
22018
+ console.error('[inline-knowledge] Failed to upload inline source', {
22019
+ filename: inlineSource.filename,
22020
+ error,
22021
+ });
22022
+ return inlineKnowledgeSourceToDataUrl(inlineSource);
22023
+ }
22024
+ }
22025
+ function extractInlineKnowledgeSources(metadata) {
22026
+ if (!metadata) {
22027
+ return [];
22028
+ }
22029
+ const value = metadata.inlineKnowledgeSources;
22030
+ return Array.isArray(value) ? value : [];
22031
+ }
22032
+ function stripInlineKnowledgeMetadata(metadata) {
22033
+ if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, 'inlineKnowledgeSources')) {
22034
+ return metadata;
22035
+ }
22036
+ const { inlineKnowledgeSources: _unusedInlineKnowledgeSources, ...rest } = metadata;
22037
+ return Object.keys(rest).length > 0 ? rest : undefined;
22038
+ }
21527
22039
  /**
21528
22040
  * Mocked security check for imported files
21529
22041
  *
@@ -22583,6 +23095,28 @@
22583
23095
  }));
22584
23096
  }
22585
23097
 
23098
+ /**
23099
+ * Builds a tool invocation script that injects hidden runtime context into tool args.
23100
+ *
23101
+ * @private utility of OpenAI tool execution wrappers
23102
+ */
23103
+ function buildToolInvocationScript(options) {
23104
+ const { functionName, functionArgsExpression } = options;
23105
+ return `
23106
+ const args = ${functionArgsExpression};
23107
+ const runtimeContextRaw =
23108
+ typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
23109
+ ? undefined
23110
+ : ${TOOL_RUNTIME_CONTEXT_PARAMETER};
23111
+
23112
+ if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
23113
+ args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
23114
+ }
23115
+
23116
+ return await ${functionName}(args);
23117
+ `;
23118
+ }
23119
+
22586
23120
  /**
22587
23121
  * Parses an OpenAI error message to identify which parameter is unsupported
22588
23122
  *
@@ -22936,10 +23470,10 @@
22936
23470
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
22937
23471
  functionResponse = await scriptTool.execute({
22938
23472
  scriptLanguage: 'javascript',
22939
- script: `
22940
- const args = ${functionArgs};
22941
- return await ${functionName}(args);
22942
- `,
23473
+ script: buildToolInvocationScript({
23474
+ functionName,
23475
+ functionArgsExpression: functionArgs,
23476
+ }),
22943
23477
  parameters: prompt.parameters,
22944
23478
  });
22945
23479
  }
@@ -24641,10 +25175,10 @@
24641
25175
  try {
24642
25176
  return await scriptTool.execute({
24643
25177
  scriptLanguage: 'javascript',
24644
- script: `
24645
- const args = ${JSON.stringify(functionArgs)};
24646
- return await ${functionName}(args);
24647
- `,
25178
+ script: buildToolInvocationScript({
25179
+ functionName,
25180
+ functionArgsExpression: JSON.stringify(functionArgs),
25181
+ }),
24648
25182
  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 : {},
24649
25183
  });
24650
25184
  }
@@ -25097,10 +25631,10 @@
25097
25631
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
25098
25632
  functionResponse = await scriptTool.execute({
25099
25633
  scriptLanguage: 'javascript',
25100
- script: `
25101
- const args = ${JSON.stringify(functionArgs)};
25102
- return await ${functionName}(args);
25103
- `,
25634
+ script: buildToolInvocationScript({
25635
+ functionName,
25636
+ functionArgsExpression: JSON.stringify(functionArgs),
25637
+ }),
25104
25638
  parameters: prompt.parameters,
25105
25639
  });
25106
25640
  if (this.options.isVerbose) {
@@ -26316,6 +26850,20 @@
26316
26850
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
26317
26851
  */
26318
26852
 
26853
+ /**
26854
+ * Keep-alive helpers used for streaming chat responses.
26855
+ *
26856
+ * These constants coordinate the signal sent by the Agents Server streaming
26857
+ * endpoint and the parser in the SDK so we can distinguish between
26858
+ * real content and occasional pings.
26859
+ *
26860
+ * @private internal streaming helper for Promptbook chat connections
26861
+ */
26862
+ const CHAT_STREAM_KEEP_ALIVE_TOKEN = 'STREAM_KEEP_ALIVE';
26863
+ /**
26864
+ * Note: [💞] Ignore a discrepancy between file name and entity name
26865
+ */
26866
+
26319
26867
  /**
26320
26868
  * Resolve a remote META IMAGE value into an absolute URL when possible.
26321
26869
  */
@@ -26390,7 +26938,9 @@
26390
26938
  static async connect(options) {
26391
26939
  var _a, _b, _c;
26392
26940
  const agentProfileUrl = `${options.agentUrl}/api/profile`;
26393
- const profileResponse = await fetch(agentProfileUrl);
26941
+ const profileResponse = await fetch(agentProfileUrl, {
26942
+ headers: attachClientVersionHeader(),
26943
+ });
26394
26944
  // <- TODO: [🐱‍🚀] What about closed-source agents?
26395
26945
  // <- TODO: [🐱‍🚀] Maybe use promptbookFetch
26396
26946
  if (!profileResponse.ok) {
@@ -26491,6 +27041,7 @@
26491
27041
  }
26492
27042
  const response = await fetch(`${this.agentUrl}/api/voice`, {
26493
27043
  method: 'POST',
27044
+ headers: attachClientVersionHeader(),
26494
27045
  body: formData,
26495
27046
  });
26496
27047
  if (!response.ok) {
@@ -26520,13 +27071,14 @@
26520
27071
  const chatPrompt = prompt;
26521
27072
  const bookResponse = await fetch(`${this.agentUrl}/api/chat`, {
26522
27073
  method: 'POST',
26523
- headers: {
27074
+ headers: attachClientVersionHeader({
26524
27075
  'Content-Type': 'application/json',
26525
- },
27076
+ }),
26526
27077
  body: JSON.stringify({
26527
27078
  message: prompt.content,
26528
27079
  thread: chatPrompt.thread,
26529
27080
  attachments: chatPrompt.attachments,
27081
+ parameters: chatPrompt.parameters,
26530
27082
  }),
26531
27083
  });
26532
27084
  // <- TODO: [🐱‍🚀] What about closed-source agents?
@@ -26608,6 +27160,9 @@
26608
27160
  const lines = textChunk.split(/\r?\n/);
26609
27161
  for (const line of lines) {
26610
27162
  const trimmedLine = line.trim();
27163
+ if (trimmedLine === CHAT_STREAM_KEEP_ALIVE_TOKEN) {
27164
+ continue;
27165
+ }
26611
27166
  let isToolCallLine = false;
26612
27167
  if (trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
26613
27168
  try {