@promptbook/remote-server 0.110.0 → 0.111.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +4 -0
  2. package/esm/index.es.js +654 -99
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/utils.index.d.ts +12 -0
  5. package/esm/typings/src/book-2.0/agent-source/BookEditable.d.ts +41 -0
  6. package/esm/typings/src/book-2.0/agent-source/CreateAgentModelRequirementsOptions.d.ts +5 -0
  7. package/esm/typings/src/book-components/Chat/Chat/ImagePromptRenderer.d.ts +21 -0
  8. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  9. package/esm/typings/src/book-components/Chat/LlmChat/defaults.d.ts +9 -0
  10. package/esm/typings/src/book-components/Chat/save/_common/ChatSaveFormatDefinition.d.ts +7 -1
  11. package/esm/typings/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +6 -5
  12. package/esm/typings/src/book-components/Chat/save/index.d.ts +3 -3
  13. package/esm/typings/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +11 -0
  14. package/esm/typings/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +2 -2
  15. package/esm/typings/src/book-components/Chat/utils/parseImagePrompts.d.ts +42 -0
  16. package/esm/typings/src/book-components/Chat/utils/parseImagePrompts.test.d.ts +1 -0
  17. package/esm/typings/src/commitments/MEMORY/MEMORY.d.ts +67 -0
  18. package/esm/typings/src/commitments/MEMORY/MEMORY.test.d.ts +1 -0
  19. package/esm/typings/src/commitments/_common/toolRuntimeContext.d.ts +49 -0
  20. package/esm/typings/src/constants/streaming.d.ts +20 -0
  21. package/esm/typings/src/llm-providers/openai/utils/buildToolInvocationScript.d.ts +9 -0
  22. package/esm/typings/src/utils/clientVersion.d.ts +51 -0
  23. package/esm/typings/src/utils/knowledge/inlineKnowledgeSource.d.ts +13 -9
  24. package/esm/typings/src/utils/normalization/constructImageFilename.d.ts +18 -0
  25. package/esm/typings/src/utils/normalization/constructImageFilename.test.d.ts +1 -0
  26. package/esm/typings/src/version.d.ts +1 -1
  27. package/package.json +2 -2
  28. package/umd/index.umd.js +654 -99
  29. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
40
40
  * @generated
41
41
  * @see https://github.com/webgptorg/promptbook
42
42
  */
43
- const PROMPTBOOK_ENGINE_VERSION = '0.110.0';
43
+ const PROMPTBOOK_ENGINE_VERSION = '0.111.0-0';
44
44
  /**
45
45
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
46
46
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -8447,6 +8447,36 @@ function prompt(strings, ...values) {
8447
8447
  * Note: [💞] Ignore a discrepancy between file name and entity name
8448
8448
  */
8449
8449
 
8450
+ /**
8451
+ * HTTP header used by Promptbook clients to advertise their release version.
8452
+ *
8453
+ * @public exported from `@promptbook/utils`
8454
+ */
8455
+ const CLIENT_VERSION_HEADER = 'x-promptbook-client-version';
8456
+ /**
8457
+ * The latest client (engine) version that the server expects.
8458
+ *
8459
+ * @public exported from `@promptbook/utils`
8460
+ */
8461
+ const CLIENT_LATEST_VERSION = PROMPTBOOK_ENGINE_VERSION;
8462
+ /**
8463
+ * Creates a headers object that includes the client version header.
8464
+ *
8465
+ * @param headers - Optional base headers to clone.
8466
+ * @returns New headers object augmented with `CLIENT_VERSION_HEADER`.
8467
+ *
8468
+ * @public exported from `@promptbook/utils`
8469
+ */
8470
+ function attachClientVersionHeader(headers) {
8471
+ return {
8472
+ ...(headers !== null && headers !== void 0 ? headers : {}),
8473
+ [CLIENT_VERSION_HEADER]: CLIENT_LATEST_VERSION,
8474
+ };
8475
+ }
8476
+ /**
8477
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8478
+ */
8479
+
8450
8480
  /**
8451
8481
  * Computes SHA-256 hash of the given object
8452
8482
  *
@@ -11647,28 +11677,14 @@ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
11647
11677
  * Note: [💞] Ignore a discrepancy between file name and entity name
11648
11678
  */
11649
11679
 
11650
- /**
11651
- * @@@
11652
- *
11653
- * @private thing of inline knowledge
11654
- */
11680
+ /** @private The default base name for inline knowledge files when the content lacks identifying text */
11655
11681
  const INLINE_KNOWLEDGE_BASE_NAME = 'inline-knowledge';
11656
- /**
11657
- * @@@
11658
- *
11659
- * @private thing of inline knowledge
11660
- */
11682
+ /** @private The default file extension used for inline knowledge uploads */
11661
11683
  const INLINE_KNOWLEDGE_EXTENSION = '.txt';
11662
- /**
11663
- * @@@
11664
- *
11665
- * @private thing of inline knowledge
11666
- */
11684
+ /** @private Prefix that identifies base64 data URLs */
11667
11685
  const DATA_URL_PREFIX = 'data:';
11668
11686
  /**
11669
- * @@@
11670
- *
11671
- * @private thing of inline knowledge
11687
+ * @private Retrieves the first meaningful line from the inline content.
11672
11688
  */
11673
11689
  function getFirstNonEmptyLine(content) {
11674
11690
  const lines = content.split(/\r?\n/);
@@ -11681,9 +11697,7 @@ function getFirstNonEmptyLine(content) {
11681
11697
  return null;
11682
11698
  }
11683
11699
  /**
11684
- * @@@
11685
- *
11686
- * @private thing of inline knowledge
11700
+ * @private Determines the base file name by normalizing the first non-empty line.
11687
11701
  */
11688
11702
  function deriveBaseFilename(content) {
11689
11703
  const firstLine = getFirstNonEmptyLine(content);
@@ -11694,22 +11708,18 @@ function deriveBaseFilename(content) {
11694
11708
  return normalized || INLINE_KNOWLEDGE_BASE_NAME;
11695
11709
  }
11696
11710
  /**
11697
- * Creates a data URL that represents the inline knowledge content as a text file.
11698
- *
11699
- * @private thing of inline knowledge
11711
+ * @private Converts inline knowledge into the internal metadata form used for uploads.
11700
11712
  */
11701
11713
  function createInlineKnowledgeSourceFile(content) {
11702
11714
  const trimmedContent = content.trim();
11703
11715
  const baseName = deriveBaseFilename(trimmedContent);
11704
11716
  const filename = `${baseName}${INLINE_KNOWLEDGE_EXTENSION}`;
11705
11717
  const mimeType = 'text/plain';
11706
- const base64 = Buffer.from(trimmedContent, 'utf-8').toString('base64');
11707
- const encodedFilename = encodeURIComponent(filename);
11708
- const url = `${DATA_URL_PREFIX}${mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
11718
+ const buffer = Buffer.from(trimmedContent, 'utf-8');
11709
11719
  return {
11710
11720
  filename,
11711
11721
  mimeType,
11712
- url,
11722
+ buffer,
11713
11723
  };
11714
11724
  }
11715
11725
  /**
@@ -11720,10 +11730,18 @@ function createInlineKnowledgeSourceFile(content) {
11720
11730
  function isDataUrlKnowledgeSource(source) {
11721
11731
  return typeof source === 'string' && source.startsWith(DATA_URL_PREFIX);
11722
11732
  }
11733
+ /**
11734
+ * @private Converts a stored inline knowledge file into a data URL for backwards compatibility.
11735
+ */
11736
+ function inlineKnowledgeSourceToDataUrl(source) {
11737
+ const base64 = source.buffer.toString('base64');
11738
+ const encodedFilename = encodeURIComponent(source.filename);
11739
+ return `${DATA_URL_PREFIX}${source.mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
11740
+ }
11723
11741
  /**
11724
11742
  * Parses a data URL-based knowledge source into its raw buffer, filename, and MIME type.
11725
11743
  *
11726
- * @private thing of inline knowledge
11744
+ * @private utility of inline knowledge processing
11727
11745
  */
11728
11746
  function parseDataUrlKnowledgeSource(source) {
11729
11747
  if (!isDataUrlKnowledgeSource(source)) {
@@ -11856,6 +11874,7 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
11856
11874
  `);
11857
11875
  }
11858
11876
  applyToAgentModelRequirements(requirements, content) {
11877
+ var _a;
11859
11878
  const trimmedContent = content.trim();
11860
11879
  if (!trimmedContent) {
11861
11880
  return requirements;
@@ -11876,9 +11895,13 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
11876
11895
  }
11877
11896
  else {
11878
11897
  const inlineSource = createInlineKnowledgeSourceFile(trimmedContent);
11898
+ const existingInlineSources = (((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.inlineKnowledgeSources) || []).slice();
11879
11899
  const updatedRequirements = {
11880
11900
  ...requirements,
11881
- knowledgeSources: [...(requirements.knowledgeSources || []), inlineSource.url],
11901
+ _metadata: {
11902
+ ...requirements._metadata,
11903
+ inlineKnowledgeSources: [...existingInlineSources, inlineSource],
11904
+ },
11882
11905
  };
11883
11906
  const knowledgeInfo = `Knowledge Source Inline: ${inlineSource.filename} (derived from inline content and processed for retrieval during chat)`;
11884
11907
  return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
@@ -11960,6 +11983,237 @@ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
11960
11983
  * Note: [💞] Ignore a discrepancy between file name and entity name
11961
11984
  */
11962
11985
 
11986
+ /**
11987
+ * @@@
11988
+ *
11989
+ * @private utility for commitments
11990
+ */
11991
+ function formatOptionalInstructionBlock(label, content) {
11992
+ const trimmedContent = spaceTrim$1(content);
11993
+ if (!trimmedContent) {
11994
+ return '';
11995
+ }
11996
+ return spaceTrim$1((block) => `
11997
+ - ${label}:
11998
+ ${block(trimmedContent
11999
+ .split(/\r?\n/)
12000
+ .map((line) => `- ${line}`)
12001
+ .join('\n'))}
12002
+ `);
12003
+ }
12004
+
12005
+ /**
12006
+ * Prompt parameter key used to pass hidden runtime context to tool execution.
12007
+ *
12008
+ * @private internal runtime wiring for commitment tools
12009
+ */
12010
+ const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
12011
+ /**
12012
+ * Hidden argument key used to pass runtime context into individual tool calls.
12013
+ *
12014
+ * @private internal runtime wiring for commitment tools
12015
+ */
12016
+ const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
12017
+ /**
12018
+ * Parses unknown runtime context payload into a normalized object.
12019
+ *
12020
+ * @private internal runtime wiring for commitment tools
12021
+ */
12022
+ function parseToolRuntimeContext(rawValue) {
12023
+ if (!rawValue) {
12024
+ return null;
12025
+ }
12026
+ let parsed = rawValue;
12027
+ if (typeof rawValue === 'string') {
12028
+ try {
12029
+ parsed = JSON.parse(rawValue);
12030
+ }
12031
+ catch (_a) {
12032
+ return null;
12033
+ }
12034
+ }
12035
+ if (!parsed || typeof parsed !== 'object') {
12036
+ return null;
12037
+ }
12038
+ return parsed;
12039
+ }
12040
+ /**
12041
+ * Reads runtime context attached to tool call arguments.
12042
+ *
12043
+ * @private internal runtime wiring for commitment tools
12044
+ */
12045
+ function readToolRuntimeContextFromToolArgs(args) {
12046
+ return parseToolRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]);
12047
+ }
12048
+ /**
12049
+ * Serializes runtime context for prompt parameters.
12050
+ *
12051
+ * @private internal runtime wiring for commitment tools
12052
+ */
12053
+ function serializeToolRuntimeContext(context) {
12054
+ return JSON.stringify(context);
12055
+ }
12056
+ /**
12057
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12058
+ */
12059
+
12060
+ /**
12061
+ * Tool name used to retrieve persisted user memory.
12062
+ *
12063
+ * @private internal MEMORY commitment constant
12064
+ */
12065
+ const RETRIEVE_USER_MEMORY_TOOL_NAME = 'retrieve_user_memory';
12066
+ /**
12067
+ * Tool name used to store persisted user memory.
12068
+ *
12069
+ * @private internal MEMORY commitment constant
12070
+ */
12071
+ const STORE_USER_MEMORY_TOOL_NAME = 'store_user_memory';
12072
+ const UPDATE_USER_MEMORY_TOOL_NAME = 'update_user_memory';
12073
+ const DELETE_USER_MEMORY_TOOL_NAME = 'delete_user_memory';
12074
+ /**
12075
+ * Resolves runtime context from hidden tool arguments.
12076
+ *
12077
+ * @private utility of MEMORY commitment
12078
+ */
12079
+ function resolveMemoryRuntimeContext(args) {
12080
+ const runtimeContext = readToolRuntimeContextFromToolArgs(args);
12081
+ const memoryContext = runtimeContext === null || runtimeContext === void 0 ? void 0 : runtimeContext.memory;
12082
+ return {
12083
+ enabled: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.enabled) === true,
12084
+ userId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.userId,
12085
+ username: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.username,
12086
+ agentId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentId,
12087
+ agentName: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentName,
12088
+ isTeamConversation: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.isTeamConversation) === true,
12089
+ };
12090
+ }
12091
+ /**
12092
+ * Builds a disabled memory-tool response payload.
12093
+ *
12094
+ * @private utility of MEMORY commitment
12095
+ */
12096
+ function createDisabledMemoryResult(action, message) {
12097
+ if (action === 'retrieve') {
12098
+ return {
12099
+ action,
12100
+ status: 'disabled',
12101
+ memories: [],
12102
+ message,
12103
+ };
12104
+ }
12105
+ if (action === 'store') {
12106
+ return {
12107
+ action,
12108
+ status: 'disabled',
12109
+ message,
12110
+ };
12111
+ }
12112
+ if (action === 'update') {
12113
+ return {
12114
+ action,
12115
+ status: 'disabled',
12116
+ message,
12117
+ };
12118
+ }
12119
+ if (action === 'delete') {
12120
+ return {
12121
+ action,
12122
+ status: 'disabled',
12123
+ message,
12124
+ };
12125
+ }
12126
+ throw new Error(`Unsupported memory tool action: ${action}`);
12127
+ }
12128
+ /**
12129
+ * Gets the runtime adapter and returns a disabled result when unavailable.
12130
+ *
12131
+ * @private utility of MEMORY commitment
12132
+ */
12133
+ function getRuntimeAdapterOrDisabledResult(action, runtimeContext) {
12134
+ if (!runtimeContext.enabled || runtimeContext.isTeamConversation) {
12135
+ return {
12136
+ adapter: null,
12137
+ disabledResult: createDisabledMemoryResult(action, runtimeContext.isTeamConversation
12138
+ ? 'Memory is disabled for TEAM conversations.'
12139
+ : 'Memory is disabled for unauthenticated users.'),
12140
+ };
12141
+ }
12142
+ {
12143
+ return {
12144
+ adapter: null,
12145
+ disabledResult: createDisabledMemoryResult(action, 'Memory runtime is not available in this environment.'),
12146
+ };
12147
+ }
12148
+ }
12149
+ /**
12150
+ * Parses retrieve memory arguments.
12151
+ *
12152
+ * @private utility of MEMORY commitment
12153
+ */
12154
+ function parseRetrieveMemoryArgs(args) {
12155
+ const query = typeof args.query === 'string' ? args.query.trim() : undefined;
12156
+ const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? Math.floor(args.limit) : undefined;
12157
+ return {
12158
+ query: query && query.length > 0 ? query : undefined,
12159
+ limit: limit && limit > 0 ? Math.min(limit, 20) : undefined,
12160
+ };
12161
+ }
12162
+ /**
12163
+ * Parses store memory arguments.
12164
+ *
12165
+ * @private utility of MEMORY commitment
12166
+ */
12167
+ function parseStoreMemoryArgs(args) {
12168
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
12169
+ if (!content) {
12170
+ throw new Error('Memory content is required.');
12171
+ }
12172
+ return {
12173
+ content,
12174
+ isGlobal: args.isGlobal === true,
12175
+ };
12176
+ }
12177
+ /**
12178
+ * Parses a memory identifier argument shared across MEMORY tools.
12179
+ *
12180
+ * @private utility of MEMORY commitment
12181
+ */
12182
+ function parseMemoryIdArg(value) {
12183
+ const memoryId = typeof value === 'string' ? value.trim() : '';
12184
+ if (!memoryId) {
12185
+ throw new Error('Memory id is required.');
12186
+ }
12187
+ return memoryId;
12188
+ }
12189
+ /**
12190
+ * Parses update memory arguments.
12191
+ *
12192
+ * @private utility of MEMORY commitment
12193
+ */
12194
+ function parseUpdateMemoryArgs(args) {
12195
+ const memoryId = parseMemoryIdArg(args.memoryId);
12196
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
12197
+ if (!content) {
12198
+ throw new Error('Memory content is required.');
12199
+ }
12200
+ const isGlobal = typeof args.isGlobal === 'boolean' ? args.isGlobal : undefined;
12201
+ return {
12202
+ memoryId,
12203
+ content,
12204
+ isGlobal,
12205
+ };
12206
+ }
12207
+ /**
12208
+ * Parses delete memory arguments.
12209
+ *
12210
+ * @private utility of MEMORY commitment
12211
+ */
12212
+ function parseDeleteMemoryArgs(args) {
12213
+ return {
12214
+ memoryId: parseMemoryIdArg(args.memoryId),
12215
+ };
12216
+ }
11963
12217
  /**
11964
12218
  * MEMORY commitment definition
11965
12219
  *
@@ -11981,6 +12235,9 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
11981
12235
  constructor(type = 'MEMORY') {
11982
12236
  super(type);
11983
12237
  }
12238
+ get requiresContent() {
12239
+ return false;
12240
+ }
11984
12241
  /**
11985
12242
  * Short one-line description of MEMORY.
11986
12243
  */
@@ -12000,21 +12257,14 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
12000
12257
  return spaceTrim$1(`
12001
12258
  # ${this.type}
12002
12259
 
12003
- 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.
12260
+ Enables persistent user memory for the current agent. The memory is stored by the runtime and can be retrieved in future conversations.
12004
12261
 
12005
12262
  ## Key aspects
12006
12263
 
12007
- - Both terms work identically and can be used interchangeably.
12008
- - Focuses on user-specific information and interaction history.
12009
- - Helps personalize responses based on past interactions.
12010
- - Maintains continuity across conversations.
12011
-
12012
- ## Differences from KNOWLEDGE
12013
-
12014
- - \`KNOWLEDGE\` is for domain expertise and factual information
12015
- - \`MEMORY\` is for user-specific context and preferences
12016
- - \`MEMORY\` creates more personalized interactions
12017
- - \`MEMORY\` often includes temporal or preference-based information
12264
+ - Both \`MEMORY\` and \`MEMORIES\` work identically.
12265
+ - Stores user-specific details through runtime tools.
12266
+ - Retrieves relevant memories for personalized responses.
12267
+ - Supports optional extra instructions in the commitment content.
12018
12268
 
12019
12269
  ## Examples
12020
12270
 
@@ -12022,10 +12272,7 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
12022
12272
  Personal Assistant
12023
12273
 
12024
12274
  PERSONA You are a personal productivity assistant
12025
- MEMORY User is a software developer working in JavaScript/React
12026
- MEMORY User prefers morning work sessions and afternoon meetings
12027
- MEMORY Previously helped with project planning for mobile apps
12028
- MEMORY User timezone: UTC-8 (Pacific Time)
12275
+ MEMORY Remember user projects and long-term preferences.
12029
12276
  GOAL Help optimize daily productivity and workflow
12030
12277
  \`\`\`
12031
12278
 
@@ -12033,10 +12280,7 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
12033
12280
  Learning Companion
12034
12281
 
12035
12282
  PERSONA You are an educational companion for programming students
12036
- MEMORY Student is learning Python as their first programming language
12037
- MEMORY Previous topics covered: variables, loops, functions
12038
- MEMORY Student learns best with practical examples and exercises
12039
- MEMORY Last session: working on list comprehensions
12283
+ MEMORY Remember only the student's learning progress and preferred study style.
12040
12284
  GOAL Provide progressive learning experiences tailored to student's pace
12041
12285
  \`\`\`
12042
12286
 
@@ -12044,23 +12288,245 @@ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
12044
12288
  Customer Support Agent
12045
12289
 
12046
12290
  PERSONA You are a customer support representative
12047
- MEMORY Customer has premium subscription since 2023
12048
- MEMORY Previous issue: billing question resolved last month
12049
- MEMORY Customer prefers email communication over phone calls
12050
- MEMORY Account shows frequent use of advanced features
12291
+ MEMORY Remember only important support history and communication preferences.
12051
12292
  GOAL Provide personalized support based on customer history
12052
12293
  \`\`\`
12053
12294
  `);
12054
12295
  }
12055
12296
  applyToAgentModelRequirements(requirements, content) {
12056
- const trimmedContent = content.trim();
12057
- if (!trimmedContent) {
12058
- return requirements;
12297
+ const extraInstructions = formatOptionalInstructionBlock('Memory instructions', content);
12298
+ const existingTools = requirements.tools || [];
12299
+ const tools = [...existingTools];
12300
+ if (!tools.some((tool) => tool.name === RETRIEVE_USER_MEMORY_TOOL_NAME)) {
12301
+ tools.push({
12302
+ name: RETRIEVE_USER_MEMORY_TOOL_NAME,
12303
+ description: spaceTrim$1(`
12304
+ Retrieve previously stored user memories relevant to the current conversation.
12305
+ Use this before responding when user context can improve the answer.
12306
+ `),
12307
+ parameters: {
12308
+ type: 'object',
12309
+ properties: {
12310
+ query: {
12311
+ type: 'string',
12312
+ description: 'Optional query used to filter relevant memories.',
12313
+ },
12314
+ limit: {
12315
+ type: 'integer',
12316
+ description: 'Optional maximum number of memories to return (default 5, max 20).',
12317
+ },
12318
+ },
12319
+ },
12320
+ });
12321
+ }
12322
+ if (!tools.some((tool) => tool.name === STORE_USER_MEMORY_TOOL_NAME)) {
12323
+ tools.push({
12324
+ name: STORE_USER_MEMORY_TOOL_NAME,
12325
+ description: spaceTrim$1(`
12326
+ Store a durable user memory that should be remembered in future conversations.
12327
+ Store only stable and useful user-specific facts or preferences.
12328
+ `),
12329
+ parameters: {
12330
+ type: 'object',
12331
+ properties: {
12332
+ content: {
12333
+ type: 'string',
12334
+ description: 'Memory text to store.',
12335
+ },
12336
+ isGlobal: {
12337
+ type: 'boolean',
12338
+ description: 'Set true to make this memory global across all user agents.',
12339
+ },
12340
+ },
12341
+ required: ['content'],
12342
+ },
12343
+ });
12344
+ }
12345
+ if (!tools.some((tool) => tool.name === UPDATE_USER_MEMORY_TOOL_NAME)) {
12346
+ tools.push({
12347
+ name: UPDATE_USER_MEMORY_TOOL_NAME,
12348
+ description: spaceTrim$1(`
12349
+ Update an existing user memory after retrieving it, so the stored fact stays accurate.
12350
+ Always pass the memory id you retrieved along with the new content.
12351
+ `),
12352
+ parameters: {
12353
+ type: 'object',
12354
+ properties: {
12355
+ memoryId: {
12356
+ type: 'string',
12357
+ description: 'Unique identifier of the memory entry to update.',
12358
+ },
12359
+ content: {
12360
+ type: 'string',
12361
+ description: 'Updated memory text.',
12362
+ },
12363
+ isGlobal: {
12364
+ type: 'boolean',
12365
+ description: 'Set true to keep the fact global; omit or false to keep it agent-scoped.',
12366
+ },
12367
+ },
12368
+ required: ['memoryId', 'content'],
12369
+ },
12370
+ });
12371
+ }
12372
+ if (!tools.some((tool) => tool.name === DELETE_USER_MEMORY_TOOL_NAME)) {
12373
+ tools.push({
12374
+ name: DELETE_USER_MEMORY_TOOL_NAME,
12375
+ description: spaceTrim$1(`
12376
+ Delete a user memory that is no longer relevant. Deletions are soft so the record is hidden from future queries.
12377
+ `),
12378
+ parameters: {
12379
+ type: 'object',
12380
+ properties: {
12381
+ memoryId: {
12382
+ type: 'string',
12383
+ description: 'Unique identifier of the memory entry to delete.',
12384
+ },
12385
+ },
12386
+ required: ['memoryId'],
12387
+ },
12388
+ });
12059
12389
  }
12060
- // Create memory section for system message
12061
- const memorySection = `Memory: ${trimmedContent}`;
12062
- // Memory information is contextual and should be included in the system message
12063
- return this.appendToSystemMessage(requirements, memorySection, '\n\n');
12390
+ return this.appendToSystemMessage({
12391
+ ...requirements,
12392
+ tools,
12393
+ _metadata: {
12394
+ ...requirements._metadata,
12395
+ useMemory: content || true,
12396
+ },
12397
+ }, spaceTrim$1((block) => `
12398
+ Memory:
12399
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
12400
+ - You can use persistent user memory tools.
12401
+ - Use "${RETRIEVE_USER_MEMORY_TOOL_NAME}" to load relevant memory before answering.
12402
+ - Use "${STORE_USER_MEMORY_TOOL_NAME}" to save stable user-specific facts that improve future help.
12403
+ - Use "${UPDATE_USER_MEMORY_TOOL_NAME}" to refresh an existing memory when the content changes.
12404
+ - Use "${DELETE_USER_MEMORY_TOOL_NAME}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
12405
+ - Store concise memory items and avoid duplicates.
12406
+ - Never claim memory was saved or loaded unless the tool confirms it.
12407
+ ${block(extraInstructions)}
12408
+ `));
12409
+ }
12410
+ /**
12411
+ * Gets human-readable titles for MEMORY tool functions.
12412
+ */
12413
+ getToolTitles() {
12414
+ return {
12415
+ [RETRIEVE_USER_MEMORY_TOOL_NAME]: 'User memory',
12416
+ [STORE_USER_MEMORY_TOOL_NAME]: 'Store user memory',
12417
+ [UPDATE_USER_MEMORY_TOOL_NAME]: 'Update user memory',
12418
+ [DELETE_USER_MEMORY_TOOL_NAME]: 'Delete user memory',
12419
+ };
12420
+ }
12421
+ /**
12422
+ * Gets MEMORY tool function implementations.
12423
+ */
12424
+ getToolFunctions() {
12425
+ return {
12426
+ async [RETRIEVE_USER_MEMORY_TOOL_NAME](args) {
12427
+ const runtimeContext = resolveMemoryRuntimeContext(args);
12428
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('retrieve', runtimeContext);
12429
+ if (!adapter || disabledResult) {
12430
+ return JSON.stringify(disabledResult);
12431
+ }
12432
+ const parsedArgs = parseRetrieveMemoryArgs(args);
12433
+ try {
12434
+ const memories = await adapter.retrieveMemories(parsedArgs, runtimeContext);
12435
+ const result = {
12436
+ action: 'retrieve',
12437
+ status: 'ok',
12438
+ query: parsedArgs.query,
12439
+ memories,
12440
+ };
12441
+ return JSON.stringify(result);
12442
+ }
12443
+ catch (error) {
12444
+ const result = {
12445
+ action: 'retrieve',
12446
+ status: 'error',
12447
+ query: parsedArgs.query,
12448
+ memories: [],
12449
+ message: error instanceof Error ? error.message : String(error),
12450
+ };
12451
+ return JSON.stringify(result);
12452
+ }
12453
+ },
12454
+ async [STORE_USER_MEMORY_TOOL_NAME](args) {
12455
+ const runtimeContext = resolveMemoryRuntimeContext(args);
12456
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('store', runtimeContext);
12457
+ if (!adapter || disabledResult) {
12458
+ return JSON.stringify(disabledResult);
12459
+ }
12460
+ try {
12461
+ const parsedArgs = parseStoreMemoryArgs(args);
12462
+ const memory = await adapter.storeMemory(parsedArgs, runtimeContext);
12463
+ const result = {
12464
+ action: 'store',
12465
+ status: 'stored',
12466
+ memory,
12467
+ };
12468
+ return JSON.stringify(result);
12469
+ }
12470
+ catch (error) {
12471
+ const result = {
12472
+ action: 'store',
12473
+ status: 'error',
12474
+ message: error instanceof Error ? error.message : String(error),
12475
+ };
12476
+ return JSON.stringify(result);
12477
+ }
12478
+ },
12479
+ async [UPDATE_USER_MEMORY_TOOL_NAME](args) {
12480
+ const runtimeContext = resolveMemoryRuntimeContext(args);
12481
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('update', runtimeContext);
12482
+ if (!adapter || disabledResult) {
12483
+ return JSON.stringify(disabledResult);
12484
+ }
12485
+ try {
12486
+ const parsedArgs = parseUpdateMemoryArgs(args);
12487
+ const memory = await adapter.updateMemory(parsedArgs, runtimeContext);
12488
+ const result = {
12489
+ action: 'update',
12490
+ status: 'updated',
12491
+ memory,
12492
+ };
12493
+ return JSON.stringify(result);
12494
+ }
12495
+ catch (error) {
12496
+ const result = {
12497
+ action: 'update',
12498
+ status: 'error',
12499
+ message: error instanceof Error ? error.message : String(error),
12500
+ };
12501
+ return JSON.stringify(result);
12502
+ }
12503
+ },
12504
+ async [DELETE_USER_MEMORY_TOOL_NAME](args) {
12505
+ const runtimeContext = resolveMemoryRuntimeContext(args);
12506
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('delete', runtimeContext);
12507
+ if (!adapter || disabledResult) {
12508
+ return JSON.stringify(disabledResult);
12509
+ }
12510
+ try {
12511
+ const parsedArgs = parseDeleteMemoryArgs(args);
12512
+ const deleted = await adapter.deleteMemory(parsedArgs, runtimeContext);
12513
+ const result = {
12514
+ action: 'delete',
12515
+ status: 'deleted',
12516
+ memoryId: deleted.id,
12517
+ };
12518
+ return JSON.stringify(result);
12519
+ }
12520
+ catch (error) {
12521
+ const result = {
12522
+ action: 'delete',
12523
+ status: 'error',
12524
+ message: error instanceof Error ? error.message : String(error),
12525
+ };
12526
+ return JSON.stringify(result);
12527
+ }
12528
+ },
12529
+ };
12064
12530
  }
12065
12531
  }
12066
12532
  /**
@@ -14173,14 +14639,30 @@ function buildTeammateRequest(message, context) {
14173
14639
  /**
14174
14640
  * Builds a minimal chat prompt for teammate calls.
14175
14641
  */
14176
- function buildTeammatePrompt(request) {
14642
+ function buildTeammatePrompt(request, runtimeContext) {
14177
14643
  return {
14178
14644
  title: 'Teammate consultation',
14179
14645
  modelRequirements: {
14180
14646
  modelVariant: 'CHAT',
14181
14647
  },
14182
14648
  content: request,
14183
- parameters: {},
14649
+ parameters: {
14650
+ [TOOL_RUNTIME_CONTEXT_PARAMETER]: serializeToolRuntimeContext(runtimeContext),
14651
+ },
14652
+ };
14653
+ }
14654
+ /**
14655
+ * Creates teammate runtime context and marks conversation as team-only memory-disabled.
14656
+ */
14657
+ function createTeamConversationRuntimeContext(value) {
14658
+ const runtimeContext = parseToolRuntimeContext(value) || {};
14659
+ return {
14660
+ ...runtimeContext,
14661
+ memory: {
14662
+ ...(runtimeContext.memory || {}),
14663
+ enabled: false,
14664
+ isTeamConversation: true,
14665
+ },
14184
14666
  };
14185
14667
  }
14186
14668
  /**
@@ -14224,7 +14706,7 @@ function createTeamToolFunction(entry) {
14224
14706
  let toolCalls;
14225
14707
  try {
14226
14708
  const remoteAgent = await getRemoteTeammateAgent(entry.teammate.url);
14227
- const prompt = buildTeammatePrompt(request);
14709
+ const prompt = buildTeammatePrompt(request, createTeamConversationRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]));
14228
14710
  const teammateResult = await remoteAgent.callChatModel(prompt);
14229
14711
  response = teammateResult.content || '';
14230
14712
  toolCalls =
@@ -14774,25 +15256,6 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
14774
15256
  * Note: [💞] Ignore a discrepancy between file name and entity name
14775
15257
  */
14776
15258
 
14777
- /**
14778
- * @@@
14779
- *
14780
- * @private utility for commitments
14781
- */
14782
- function formatOptionalInstructionBlock(label, content) {
14783
- const trimmedContent = spaceTrim$1(content);
14784
- if (!trimmedContent) {
14785
- return '';
14786
- }
14787
- return spaceTrim$1((block) => `
14788
- - ${label}:
14789
- ${block(trimmedContent
14790
- .split(/\r?\n/)
14791
- .map((line) => `- ${line}`)
14792
- .join('\n'))}
14793
- `);
14794
- }
14795
-
14796
15259
  /**
14797
15260
  * Client-side safe wrapper for sending emails.
14798
15261
  *
@@ -18607,6 +19070,7 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
18607
19070
  systemMessage: requirements.systemMessage + '\n\n' + exampleInteractionsContent,
18608
19071
  };
18609
19072
  }
19073
+ requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
18610
19074
  // Remove comment lines (lines starting with #) from the final system message
18611
19075
  // while preserving the original content with comments in metadata
18612
19076
  const cleanedSystemMessage = removeCommentsFromSystemMessage(requirements.systemMessage);
@@ -18615,6 +19079,54 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
18615
19079
  systemMessage: cleanedSystemMessage,
18616
19080
  };
18617
19081
  }
19082
+ /**
19083
+ * @private Attempts to upload inline knowledge entries, falling back to legacy data URLs when the upload fails or is not configured.
19084
+ */
19085
+ async function applyPendingInlineKnowledgeSources(requirements, uploader) {
19086
+ var _a;
19087
+ const inlineSources = extractInlineKnowledgeSources(requirements._metadata);
19088
+ if (inlineSources.length === 0) {
19089
+ return requirements;
19090
+ }
19091
+ const knowledgeSources = [...((_a = requirements.knowledgeSources) !== null && _a !== void 0 ? _a : [])];
19092
+ for (const inlineSource of inlineSources) {
19093
+ const url = uploader
19094
+ ? await uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader)
19095
+ : inlineKnowledgeSourceToDataUrl(inlineSource);
19096
+ knowledgeSources.push(url);
19097
+ }
19098
+ return {
19099
+ ...requirements,
19100
+ knowledgeSources,
19101
+ _metadata: stripInlineKnowledgeMetadata(requirements._metadata),
19102
+ };
19103
+ }
19104
+ async function uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader) {
19105
+ try {
19106
+ return await uploader(inlineSource);
19107
+ }
19108
+ catch (error) {
19109
+ console.error('[inline-knowledge] Failed to upload inline source', {
19110
+ filename: inlineSource.filename,
19111
+ error,
19112
+ });
19113
+ return inlineKnowledgeSourceToDataUrl(inlineSource);
19114
+ }
19115
+ }
19116
+ function extractInlineKnowledgeSources(metadata) {
19117
+ if (!metadata) {
19118
+ return [];
19119
+ }
19120
+ const value = metadata.inlineKnowledgeSources;
19121
+ return Array.isArray(value) ? value : [];
19122
+ }
19123
+ function stripInlineKnowledgeMetadata(metadata) {
19124
+ if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, 'inlineKnowledgeSources')) {
19125
+ return metadata;
19126
+ }
19127
+ const { inlineKnowledgeSources: _unusedInlineKnowledgeSources, ...rest } = metadata;
19128
+ return Object.keys(rest).length > 0 ? rest : undefined;
19129
+ }
18618
19130
  /**
18619
19131
  * Mocked security check for imported files
18620
19132
  *
@@ -19674,6 +20186,28 @@ function mapToolsToOpenAi(tools) {
19674
20186
  }));
19675
20187
  }
19676
20188
 
20189
+ /**
20190
+ * Builds a tool invocation script that injects hidden runtime context into tool args.
20191
+ *
20192
+ * @private utility of OpenAI tool execution wrappers
20193
+ */
20194
+ function buildToolInvocationScript(options) {
20195
+ const { functionName, functionArgsExpression } = options;
20196
+ return `
20197
+ const args = ${functionArgsExpression};
20198
+ const runtimeContextRaw =
20199
+ typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
20200
+ ? undefined
20201
+ : ${TOOL_RUNTIME_CONTEXT_PARAMETER};
20202
+
20203
+ if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
20204
+ args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
20205
+ }
20206
+
20207
+ return await ${functionName}(args);
20208
+ `;
20209
+ }
20210
+
19677
20211
  /**
19678
20212
  * Parses an OpenAI error message to identify which parameter is unsupported
19679
20213
  *
@@ -20027,10 +20561,10 @@ class OpenAiCompatibleExecutionTools {
20027
20561
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
20028
20562
  functionResponse = await scriptTool.execute({
20029
20563
  scriptLanguage: 'javascript',
20030
- script: `
20031
- const args = ${functionArgs};
20032
- return await ${functionName}(args);
20033
- `,
20564
+ script: buildToolInvocationScript({
20565
+ functionName,
20566
+ functionArgsExpression: functionArgs,
20567
+ }),
20034
20568
  parameters: prompt.parameters,
20035
20569
  });
20036
20570
  }
@@ -21732,10 +22266,10 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
21732
22266
  try {
21733
22267
  return await scriptTool.execute({
21734
22268
  scriptLanguage: 'javascript',
21735
- script: `
21736
- const args = ${JSON.stringify(functionArgs)};
21737
- return await ${functionName}(args);
21738
- `,
22269
+ script: buildToolInvocationScript({
22270
+ functionName,
22271
+ functionArgsExpression: JSON.stringify(functionArgs),
22272
+ }),
21739
22273
  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 : {},
21740
22274
  });
21741
22275
  }
@@ -22188,10 +22722,10 @@ class OpenAiAssistantExecutionTools extends OpenAiVectorStoreHandler {
22188
22722
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
22189
22723
  functionResponse = await scriptTool.execute({
22190
22724
  scriptLanguage: 'javascript',
22191
- script: `
22192
- const args = ${JSON.stringify(functionArgs)};
22193
- return await ${functionName}(args);
22194
- `,
22725
+ script: buildToolInvocationScript({
22726
+ functionName,
22727
+ functionArgsExpression: JSON.stringify(functionArgs),
22728
+ }),
22195
22729
  parameters: prompt.parameters,
22196
22730
  });
22197
22731
  if (this.options.isVerbose) {
@@ -23407,6 +23941,20 @@ async function _Agent_selfLearnTeacher(prompt, result) {
23407
23941
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
23408
23942
  */
23409
23943
 
23944
+ /**
23945
+ * Keep-alive helpers used for streaming chat responses.
23946
+ *
23947
+ * These constants coordinate the signal sent by the Agents Server streaming
23948
+ * endpoint and the parser in the SDK so we can distinguish between
23949
+ * real content and occasional pings.
23950
+ *
23951
+ * @private internal streaming helper for Promptbook chat connections
23952
+ */
23953
+ const CHAT_STREAM_KEEP_ALIVE_TOKEN = 'STREAM_KEEP_ALIVE';
23954
+ /**
23955
+ * Note: [💞] Ignore a discrepancy between file name and entity name
23956
+ */
23957
+
23410
23958
  /**
23411
23959
  * Resolve a remote META IMAGE value into an absolute URL when possible.
23412
23960
  */
@@ -23481,7 +24029,9 @@ class RemoteAgent extends Agent {
23481
24029
  static async connect(options) {
23482
24030
  var _a, _b, _c;
23483
24031
  const agentProfileUrl = `${options.agentUrl}/api/profile`;
23484
- const profileResponse = await fetch(agentProfileUrl);
24032
+ const profileResponse = await fetch(agentProfileUrl, {
24033
+ headers: attachClientVersionHeader(),
24034
+ });
23485
24035
  // <- TODO: [🐱‍🚀] What about closed-source agents?
23486
24036
  // <- TODO: [🐱‍🚀] Maybe use promptbookFetch
23487
24037
  if (!profileResponse.ok) {
@@ -23582,6 +24132,7 @@ class RemoteAgent extends Agent {
23582
24132
  }
23583
24133
  const response = await fetch(`${this.agentUrl}/api/voice`, {
23584
24134
  method: 'POST',
24135
+ headers: attachClientVersionHeader(),
23585
24136
  body: formData,
23586
24137
  });
23587
24138
  if (!response.ok) {
@@ -23611,13 +24162,14 @@ class RemoteAgent extends Agent {
23611
24162
  const chatPrompt = prompt;
23612
24163
  const bookResponse = await fetch(`${this.agentUrl}/api/chat`, {
23613
24164
  method: 'POST',
23614
- headers: {
24165
+ headers: attachClientVersionHeader({
23615
24166
  'Content-Type': 'application/json',
23616
- },
24167
+ }),
23617
24168
  body: JSON.stringify({
23618
24169
  message: prompt.content,
23619
24170
  thread: chatPrompt.thread,
23620
24171
  attachments: chatPrompt.attachments,
24172
+ parameters: chatPrompt.parameters,
23621
24173
  }),
23622
24174
  });
23623
24175
  // <- TODO: [🐱‍🚀] What about closed-source agents?
@@ -23699,6 +24251,9 @@ class RemoteAgent extends Agent {
23699
24251
  const lines = textChunk.split(/\r?\n/);
23700
24252
  for (const line of lines) {
23701
24253
  const trimmedLine = line.trim();
24254
+ if (trimmedLine === CHAT_STREAM_KEEP_ALIVE_TOKEN) {
24255
+ continue;
24256
+ }
23702
24257
  let isToolCallLine = false;
23703
24258
  if (trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
23704
24259
  try {