@promptbook/wizard 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
@@ -49,7 +49,7 @@
49
49
  * @generated
50
50
  * @see https://github.com/webgptorg/promptbook
51
51
  */
52
- const PROMPTBOOK_ENGINE_VERSION = '0.110.0';
52
+ const PROMPTBOOK_ENGINE_VERSION = '0.111.0-0';
53
53
  /**
54
54
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
55
55
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -6578,6 +6578,36 @@
6578
6578
  * Note: [💞] Ignore a discrepancy between file name and entity name
6579
6579
  */
6580
6580
 
6581
+ /**
6582
+ * HTTP header used by Promptbook clients to advertise their release version.
6583
+ *
6584
+ * @public exported from `@promptbook/utils`
6585
+ */
6586
+ const CLIENT_VERSION_HEADER = 'x-promptbook-client-version';
6587
+ /**
6588
+ * The latest client (engine) version that the server expects.
6589
+ *
6590
+ * @public exported from `@promptbook/utils`
6591
+ */
6592
+ const CLIENT_LATEST_VERSION = PROMPTBOOK_ENGINE_VERSION;
6593
+ /**
6594
+ * Creates a headers object that includes the client version header.
6595
+ *
6596
+ * @param headers - Optional base headers to clone.
6597
+ * @returns New headers object augmented with `CLIENT_VERSION_HEADER`.
6598
+ *
6599
+ * @public exported from `@promptbook/utils`
6600
+ */
6601
+ function attachClientVersionHeader(headers) {
6602
+ return {
6603
+ ...(headers !== null && headers !== void 0 ? headers : {}),
6604
+ [CLIENT_VERSION_HEADER]: CLIENT_LATEST_VERSION,
6605
+ };
6606
+ }
6607
+ /**
6608
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6609
+ */
6610
+
6581
6611
  /**
6582
6612
  * Detects if the code is running in a Node.js environment
6583
6613
  *
@@ -8686,6 +8716,83 @@
8686
8716
  }));
8687
8717
  }
8688
8718
 
8719
+ /**
8720
+ * Prompt parameter key used to pass hidden runtime context to tool execution.
8721
+ *
8722
+ * @private internal runtime wiring for commitment tools
8723
+ */
8724
+ const TOOL_RUNTIME_CONTEXT_PARAMETER = 'promptbookToolRuntimeContext';
8725
+ /**
8726
+ * Hidden argument key used to pass runtime context into individual tool calls.
8727
+ *
8728
+ * @private internal runtime wiring for commitment tools
8729
+ */
8730
+ const TOOL_RUNTIME_CONTEXT_ARGUMENT = '__promptbookToolRuntimeContext';
8731
+ /**
8732
+ * Parses unknown runtime context payload into a normalized object.
8733
+ *
8734
+ * @private internal runtime wiring for commitment tools
8735
+ */
8736
+ function parseToolRuntimeContext(rawValue) {
8737
+ if (!rawValue) {
8738
+ return null;
8739
+ }
8740
+ let parsed = rawValue;
8741
+ if (typeof rawValue === 'string') {
8742
+ try {
8743
+ parsed = JSON.parse(rawValue);
8744
+ }
8745
+ catch (_a) {
8746
+ return null;
8747
+ }
8748
+ }
8749
+ if (!parsed || typeof parsed !== 'object') {
8750
+ return null;
8751
+ }
8752
+ return parsed;
8753
+ }
8754
+ /**
8755
+ * Reads runtime context attached to tool call arguments.
8756
+ *
8757
+ * @private internal runtime wiring for commitment tools
8758
+ */
8759
+ function readToolRuntimeContextFromToolArgs(args) {
8760
+ return parseToolRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]);
8761
+ }
8762
+ /**
8763
+ * Serializes runtime context for prompt parameters.
8764
+ *
8765
+ * @private internal runtime wiring for commitment tools
8766
+ */
8767
+ function serializeToolRuntimeContext(context) {
8768
+ return JSON.stringify(context);
8769
+ }
8770
+ /**
8771
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8772
+ */
8773
+
8774
+ /**
8775
+ * Builds a tool invocation script that injects hidden runtime context into tool args.
8776
+ *
8777
+ * @private utility of OpenAI tool execution wrappers
8778
+ */
8779
+ function buildToolInvocationScript(options) {
8780
+ const { functionName, functionArgsExpression } = options;
8781
+ return `
8782
+ const args = ${functionArgsExpression};
8783
+ const runtimeContextRaw =
8784
+ typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
8785
+ ? undefined
8786
+ : ${TOOL_RUNTIME_CONTEXT_PARAMETER};
8787
+
8788
+ if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
8789
+ args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
8790
+ }
8791
+
8792
+ return await ${functionName}(args);
8793
+ `;
8794
+ }
8795
+
8689
8796
  /**
8690
8797
  * Parses an OpenAI error message to identify which parameter is unsupported
8691
8798
  *
@@ -9039,10 +9146,10 @@
9039
9146
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
9040
9147
  functionResponse = await scriptTool.execute({
9041
9148
  scriptLanguage: 'javascript',
9042
- script: `
9043
- const args = ${functionArgs};
9044
- return await ${functionName}(args);
9045
- `,
9149
+ script: buildToolInvocationScript({
9150
+ functionName,
9151
+ functionArgsExpression: functionArgs,
9152
+ }),
9046
9153
  parameters: prompt.parameters,
9047
9154
  });
9048
9155
  }
@@ -10224,28 +10331,14 @@
10224
10331
  }
10225
10332
  }
10226
10333
 
10227
- /**
10228
- * @@@
10229
- *
10230
- * @private thing of inline knowledge
10231
- */
10334
+ /** @private The default base name for inline knowledge files when the content lacks identifying text */
10232
10335
  const INLINE_KNOWLEDGE_BASE_NAME = 'inline-knowledge';
10233
- /**
10234
- * @@@
10235
- *
10236
- * @private thing of inline knowledge
10237
- */
10336
+ /** @private The default file extension used for inline knowledge uploads */
10238
10337
  const INLINE_KNOWLEDGE_EXTENSION = '.txt';
10239
- /**
10240
- * @@@
10241
- *
10242
- * @private thing of inline knowledge
10243
- */
10338
+ /** @private Prefix that identifies base64 data URLs */
10244
10339
  const DATA_URL_PREFIX = 'data:';
10245
10340
  /**
10246
- * @@@
10247
- *
10248
- * @private thing of inline knowledge
10341
+ * @private Retrieves the first meaningful line from the inline content.
10249
10342
  */
10250
10343
  function getFirstNonEmptyLine(content) {
10251
10344
  const lines = content.split(/\r?\n/);
@@ -10258,9 +10351,7 @@
10258
10351
  return null;
10259
10352
  }
10260
10353
  /**
10261
- * @@@
10262
- *
10263
- * @private thing of inline knowledge
10354
+ * @private Determines the base file name by normalizing the first non-empty line.
10264
10355
  */
10265
10356
  function deriveBaseFilename(content) {
10266
10357
  const firstLine = getFirstNonEmptyLine(content);
@@ -10271,22 +10362,18 @@
10271
10362
  return normalized || INLINE_KNOWLEDGE_BASE_NAME;
10272
10363
  }
10273
10364
  /**
10274
- * Creates a data URL that represents the inline knowledge content as a text file.
10275
- *
10276
- * @private thing of inline knowledge
10365
+ * @private Converts inline knowledge into the internal metadata form used for uploads.
10277
10366
  */
10278
10367
  function createInlineKnowledgeSourceFile(content) {
10279
10368
  const trimmedContent = content.trim();
10280
10369
  const baseName = deriveBaseFilename(trimmedContent);
10281
10370
  const filename = `${baseName}${INLINE_KNOWLEDGE_EXTENSION}`;
10282
10371
  const mimeType = 'text/plain';
10283
- const base64 = Buffer.from(trimmedContent, 'utf-8').toString('base64');
10284
- const encodedFilename = encodeURIComponent(filename);
10285
- const url = `${DATA_URL_PREFIX}${mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
10372
+ const buffer = Buffer.from(trimmedContent, 'utf-8');
10286
10373
  return {
10287
10374
  filename,
10288
10375
  mimeType,
10289
- url,
10376
+ buffer,
10290
10377
  };
10291
10378
  }
10292
10379
  /**
@@ -10297,10 +10384,18 @@
10297
10384
  function isDataUrlKnowledgeSource(source) {
10298
10385
  return typeof source === 'string' && source.startsWith(DATA_URL_PREFIX);
10299
10386
  }
10387
+ /**
10388
+ * @private Converts a stored inline knowledge file into a data URL for backwards compatibility.
10389
+ */
10390
+ function inlineKnowledgeSourceToDataUrl(source) {
10391
+ const base64 = source.buffer.toString('base64');
10392
+ const encodedFilename = encodeURIComponent(source.filename);
10393
+ return `${DATA_URL_PREFIX}${source.mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
10394
+ }
10300
10395
  /**
10301
10396
  * Parses a data URL-based knowledge source into its raw buffer, filename, and MIME type.
10302
10397
  *
10303
- * @private thing of inline knowledge
10398
+ * @private utility of inline knowledge processing
10304
10399
  */
10305
10400
  function parseDataUrlKnowledgeSource(source) {
10306
10401
  if (!isDataUrlKnowledgeSource(source)) {
@@ -11342,10 +11437,10 @@
11342
11437
  const scriptTool = scriptTools[0]; // <- TODO: [🧠] Which script tool to use?
11343
11438
  functionResponse = await scriptTool.execute({
11344
11439
  scriptLanguage: 'javascript',
11345
- script: `
11346
- const args = ${JSON.stringify(functionArgs)};
11347
- return await ${functionName}(args);
11348
- `,
11440
+ script: buildToolInvocationScript({
11441
+ functionName,
11442
+ functionArgsExpression: JSON.stringify(functionArgs),
11443
+ }),
11349
11444
  parameters: prompt.parameters,
11350
11445
  });
11351
11446
  if (this.options.isVerbose) {
@@ -18475,6 +18570,7 @@
18475
18570
  `);
18476
18571
  }
18477
18572
  applyToAgentModelRequirements(requirements, content) {
18573
+ var _a;
18478
18574
  const trimmedContent = content.trim();
18479
18575
  if (!trimmedContent) {
18480
18576
  return requirements;
@@ -18495,9 +18591,13 @@
18495
18591
  }
18496
18592
  else {
18497
18593
  const inlineSource = createInlineKnowledgeSourceFile(trimmedContent);
18594
+ const existingInlineSources = (((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.inlineKnowledgeSources) || []).slice();
18498
18595
  const updatedRequirements = {
18499
18596
  ...requirements,
18500
- knowledgeSources: [...(requirements.knowledgeSources || []), inlineSource.url],
18597
+ _metadata: {
18598
+ ...requirements._metadata,
18599
+ inlineKnowledgeSources: [...existingInlineSources, inlineSource],
18600
+ },
18501
18601
  };
18502
18602
  const knowledgeInfo = `Knowledge Source Inline: ${inlineSource.filename} (derived from inline content and processed for retrieval during chat)`;
18503
18603
  return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
@@ -18579,6 +18679,182 @@
18579
18679
  * Note: [💞] Ignore a discrepancy between file name and entity name
18580
18680
  */
18581
18681
 
18682
+ /**
18683
+ * @@@
18684
+ *
18685
+ * @private utility for commitments
18686
+ */
18687
+ function formatOptionalInstructionBlock(label, content) {
18688
+ const trimmedContent = spaceTrim$1.spaceTrim(content);
18689
+ if (!trimmedContent) {
18690
+ return '';
18691
+ }
18692
+ return spaceTrim$1.spaceTrim((block) => `
18693
+ - ${label}:
18694
+ ${block(trimmedContent
18695
+ .split(/\r?\n/)
18696
+ .map((line) => `- ${line}`)
18697
+ .join('\n'))}
18698
+ `);
18699
+ }
18700
+
18701
+ /**
18702
+ * Tool name used to retrieve persisted user memory.
18703
+ *
18704
+ * @private internal MEMORY commitment constant
18705
+ */
18706
+ const RETRIEVE_USER_MEMORY_TOOL_NAME = 'retrieve_user_memory';
18707
+ /**
18708
+ * Tool name used to store persisted user memory.
18709
+ *
18710
+ * @private internal MEMORY commitment constant
18711
+ */
18712
+ const STORE_USER_MEMORY_TOOL_NAME = 'store_user_memory';
18713
+ const UPDATE_USER_MEMORY_TOOL_NAME = 'update_user_memory';
18714
+ const DELETE_USER_MEMORY_TOOL_NAME = 'delete_user_memory';
18715
+ /**
18716
+ * Resolves runtime context from hidden tool arguments.
18717
+ *
18718
+ * @private utility of MEMORY commitment
18719
+ */
18720
+ function resolveMemoryRuntimeContext(args) {
18721
+ const runtimeContext = readToolRuntimeContextFromToolArgs(args);
18722
+ const memoryContext = runtimeContext === null || runtimeContext === void 0 ? void 0 : runtimeContext.memory;
18723
+ return {
18724
+ enabled: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.enabled) === true,
18725
+ userId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.userId,
18726
+ username: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.username,
18727
+ agentId: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentId,
18728
+ agentName: memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.agentName,
18729
+ isTeamConversation: (memoryContext === null || memoryContext === void 0 ? void 0 : memoryContext.isTeamConversation) === true,
18730
+ };
18731
+ }
18732
+ /**
18733
+ * Builds a disabled memory-tool response payload.
18734
+ *
18735
+ * @private utility of MEMORY commitment
18736
+ */
18737
+ function createDisabledMemoryResult(action, message) {
18738
+ if (action === 'retrieve') {
18739
+ return {
18740
+ action,
18741
+ status: 'disabled',
18742
+ memories: [],
18743
+ message,
18744
+ };
18745
+ }
18746
+ if (action === 'store') {
18747
+ return {
18748
+ action,
18749
+ status: 'disabled',
18750
+ message,
18751
+ };
18752
+ }
18753
+ if (action === 'update') {
18754
+ return {
18755
+ action,
18756
+ status: 'disabled',
18757
+ message,
18758
+ };
18759
+ }
18760
+ if (action === 'delete') {
18761
+ return {
18762
+ action,
18763
+ status: 'disabled',
18764
+ message,
18765
+ };
18766
+ }
18767
+ throw new Error(`Unsupported memory tool action: ${action}`);
18768
+ }
18769
+ /**
18770
+ * Gets the runtime adapter and returns a disabled result when unavailable.
18771
+ *
18772
+ * @private utility of MEMORY commitment
18773
+ */
18774
+ function getRuntimeAdapterOrDisabledResult(action, runtimeContext) {
18775
+ if (!runtimeContext.enabled || runtimeContext.isTeamConversation) {
18776
+ return {
18777
+ adapter: null,
18778
+ disabledResult: createDisabledMemoryResult(action, runtimeContext.isTeamConversation
18779
+ ? 'Memory is disabled for TEAM conversations.'
18780
+ : 'Memory is disabled for unauthenticated users.'),
18781
+ };
18782
+ }
18783
+ {
18784
+ return {
18785
+ adapter: null,
18786
+ disabledResult: createDisabledMemoryResult(action, 'Memory runtime is not available in this environment.'),
18787
+ };
18788
+ }
18789
+ }
18790
+ /**
18791
+ * Parses retrieve memory arguments.
18792
+ *
18793
+ * @private utility of MEMORY commitment
18794
+ */
18795
+ function parseRetrieveMemoryArgs(args) {
18796
+ const query = typeof args.query === 'string' ? args.query.trim() : undefined;
18797
+ const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) ? Math.floor(args.limit) : undefined;
18798
+ return {
18799
+ query: query && query.length > 0 ? query : undefined,
18800
+ limit: limit && limit > 0 ? Math.min(limit, 20) : undefined,
18801
+ };
18802
+ }
18803
+ /**
18804
+ * Parses store memory arguments.
18805
+ *
18806
+ * @private utility of MEMORY commitment
18807
+ */
18808
+ function parseStoreMemoryArgs(args) {
18809
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
18810
+ if (!content) {
18811
+ throw new Error('Memory content is required.');
18812
+ }
18813
+ return {
18814
+ content,
18815
+ isGlobal: args.isGlobal === true,
18816
+ };
18817
+ }
18818
+ /**
18819
+ * Parses a memory identifier argument shared across MEMORY tools.
18820
+ *
18821
+ * @private utility of MEMORY commitment
18822
+ */
18823
+ function parseMemoryIdArg(value) {
18824
+ const memoryId = typeof value === 'string' ? value.trim() : '';
18825
+ if (!memoryId) {
18826
+ throw new Error('Memory id is required.');
18827
+ }
18828
+ return memoryId;
18829
+ }
18830
+ /**
18831
+ * Parses update memory arguments.
18832
+ *
18833
+ * @private utility of MEMORY commitment
18834
+ */
18835
+ function parseUpdateMemoryArgs(args) {
18836
+ const memoryId = parseMemoryIdArg(args.memoryId);
18837
+ const content = typeof args.content === 'string' ? args.content.trim() : '';
18838
+ if (!content) {
18839
+ throw new Error('Memory content is required.');
18840
+ }
18841
+ const isGlobal = typeof args.isGlobal === 'boolean' ? args.isGlobal : undefined;
18842
+ return {
18843
+ memoryId,
18844
+ content,
18845
+ isGlobal,
18846
+ };
18847
+ }
18848
+ /**
18849
+ * Parses delete memory arguments.
18850
+ *
18851
+ * @private utility of MEMORY commitment
18852
+ */
18853
+ function parseDeleteMemoryArgs(args) {
18854
+ return {
18855
+ memoryId: parseMemoryIdArg(args.memoryId),
18856
+ };
18857
+ }
18582
18858
  /**
18583
18859
  * MEMORY commitment definition
18584
18860
  *
@@ -18600,6 +18876,9 @@
18600
18876
  constructor(type = 'MEMORY') {
18601
18877
  super(type);
18602
18878
  }
18879
+ get requiresContent() {
18880
+ return false;
18881
+ }
18603
18882
  /**
18604
18883
  * Short one-line description of MEMORY.
18605
18884
  */
@@ -18619,21 +18898,14 @@
18619
18898
  return spaceTrim$1.spaceTrim(`
18620
18899
  # ${this.type}
18621
18900
 
18622
- 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.
18901
+ Enables persistent user memory for the current agent. The memory is stored by the runtime and can be retrieved in future conversations.
18623
18902
 
18624
18903
  ## Key aspects
18625
18904
 
18626
- - Both terms work identically and can be used interchangeably.
18627
- - Focuses on user-specific information and interaction history.
18628
- - Helps personalize responses based on past interactions.
18629
- - Maintains continuity across conversations.
18630
-
18631
- ## Differences from KNOWLEDGE
18632
-
18633
- - \`KNOWLEDGE\` is for domain expertise and factual information
18634
- - \`MEMORY\` is for user-specific context and preferences
18635
- - \`MEMORY\` creates more personalized interactions
18636
- - \`MEMORY\` often includes temporal or preference-based information
18905
+ - Both \`MEMORY\` and \`MEMORIES\` work identically.
18906
+ - Stores user-specific details through runtime tools.
18907
+ - Retrieves relevant memories for personalized responses.
18908
+ - Supports optional extra instructions in the commitment content.
18637
18909
 
18638
18910
  ## Examples
18639
18911
 
@@ -18641,10 +18913,7 @@
18641
18913
  Personal Assistant
18642
18914
 
18643
18915
  PERSONA You are a personal productivity assistant
18644
- MEMORY User is a software developer working in JavaScript/React
18645
- MEMORY User prefers morning work sessions and afternoon meetings
18646
- MEMORY Previously helped with project planning for mobile apps
18647
- MEMORY User timezone: UTC-8 (Pacific Time)
18916
+ MEMORY Remember user projects and long-term preferences.
18648
18917
  GOAL Help optimize daily productivity and workflow
18649
18918
  \`\`\`
18650
18919
 
@@ -18652,10 +18921,7 @@
18652
18921
  Learning Companion
18653
18922
 
18654
18923
  PERSONA You are an educational companion for programming students
18655
- MEMORY Student is learning Python as their first programming language
18656
- MEMORY Previous topics covered: variables, loops, functions
18657
- MEMORY Student learns best with practical examples and exercises
18658
- MEMORY Last session: working on list comprehensions
18924
+ MEMORY Remember only the student's learning progress and preferred study style.
18659
18925
  GOAL Provide progressive learning experiences tailored to student's pace
18660
18926
  \`\`\`
18661
18927
 
@@ -18663,23 +18929,245 @@
18663
18929
  Customer Support Agent
18664
18930
 
18665
18931
  PERSONA You are a customer support representative
18666
- MEMORY Customer has premium subscription since 2023
18667
- MEMORY Previous issue: billing question resolved last month
18668
- MEMORY Customer prefers email communication over phone calls
18669
- MEMORY Account shows frequent use of advanced features
18932
+ MEMORY Remember only important support history and communication preferences.
18670
18933
  GOAL Provide personalized support based on customer history
18671
18934
  \`\`\`
18672
18935
  `);
18673
18936
  }
18674
18937
  applyToAgentModelRequirements(requirements, content) {
18675
- const trimmedContent = content.trim();
18676
- if (!trimmedContent) {
18677
- return requirements;
18938
+ const extraInstructions = formatOptionalInstructionBlock('Memory instructions', content);
18939
+ const existingTools = requirements.tools || [];
18940
+ const tools = [...existingTools];
18941
+ if (!tools.some((tool) => tool.name === RETRIEVE_USER_MEMORY_TOOL_NAME)) {
18942
+ tools.push({
18943
+ name: RETRIEVE_USER_MEMORY_TOOL_NAME,
18944
+ description: spaceTrim$1.spaceTrim(`
18945
+ Retrieve previously stored user memories relevant to the current conversation.
18946
+ Use this before responding when user context can improve the answer.
18947
+ `),
18948
+ parameters: {
18949
+ type: 'object',
18950
+ properties: {
18951
+ query: {
18952
+ type: 'string',
18953
+ description: 'Optional query used to filter relevant memories.',
18954
+ },
18955
+ limit: {
18956
+ type: 'integer',
18957
+ description: 'Optional maximum number of memories to return (default 5, max 20).',
18958
+ },
18959
+ },
18960
+ },
18961
+ });
18962
+ }
18963
+ if (!tools.some((tool) => tool.name === STORE_USER_MEMORY_TOOL_NAME)) {
18964
+ tools.push({
18965
+ name: STORE_USER_MEMORY_TOOL_NAME,
18966
+ description: spaceTrim$1.spaceTrim(`
18967
+ Store a durable user memory that should be remembered in future conversations.
18968
+ Store only stable and useful user-specific facts or preferences.
18969
+ `),
18970
+ parameters: {
18971
+ type: 'object',
18972
+ properties: {
18973
+ content: {
18974
+ type: 'string',
18975
+ description: 'Memory text to store.',
18976
+ },
18977
+ isGlobal: {
18978
+ type: 'boolean',
18979
+ description: 'Set true to make this memory global across all user agents.',
18980
+ },
18981
+ },
18982
+ required: ['content'],
18983
+ },
18984
+ });
18678
18985
  }
18679
- // Create memory section for system message
18680
- const memorySection = `Memory: ${trimmedContent}`;
18681
- // Memory information is contextual and should be included in the system message
18682
- return this.appendToSystemMessage(requirements, memorySection, '\n\n');
18986
+ if (!tools.some((tool) => tool.name === UPDATE_USER_MEMORY_TOOL_NAME)) {
18987
+ tools.push({
18988
+ name: UPDATE_USER_MEMORY_TOOL_NAME,
18989
+ description: spaceTrim$1.spaceTrim(`
18990
+ Update an existing user memory after retrieving it, so the stored fact stays accurate.
18991
+ Always pass the memory id you retrieved along with the new content.
18992
+ `),
18993
+ parameters: {
18994
+ type: 'object',
18995
+ properties: {
18996
+ memoryId: {
18997
+ type: 'string',
18998
+ description: 'Unique identifier of the memory entry to update.',
18999
+ },
19000
+ content: {
19001
+ type: 'string',
19002
+ description: 'Updated memory text.',
19003
+ },
19004
+ isGlobal: {
19005
+ type: 'boolean',
19006
+ description: 'Set true to keep the fact global; omit or false to keep it agent-scoped.',
19007
+ },
19008
+ },
19009
+ required: ['memoryId', 'content'],
19010
+ },
19011
+ });
19012
+ }
19013
+ if (!tools.some((tool) => tool.name === DELETE_USER_MEMORY_TOOL_NAME)) {
19014
+ tools.push({
19015
+ name: DELETE_USER_MEMORY_TOOL_NAME,
19016
+ description: spaceTrim$1.spaceTrim(`
19017
+ Delete a user memory that is no longer relevant. Deletions are soft so the record is hidden from future queries.
19018
+ `),
19019
+ parameters: {
19020
+ type: 'object',
19021
+ properties: {
19022
+ memoryId: {
19023
+ type: 'string',
19024
+ description: 'Unique identifier of the memory entry to delete.',
19025
+ },
19026
+ },
19027
+ required: ['memoryId'],
19028
+ },
19029
+ });
19030
+ }
19031
+ return this.appendToSystemMessage({
19032
+ ...requirements,
19033
+ tools,
19034
+ _metadata: {
19035
+ ...requirements._metadata,
19036
+ useMemory: content || true,
19037
+ },
19038
+ }, spaceTrim$1.spaceTrim((block) => `
19039
+ Memory:
19040
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
19041
+ - You can use persistent user memory tools.
19042
+ - Use "${RETRIEVE_USER_MEMORY_TOOL_NAME}" to load relevant memory before answering.
19043
+ - Use "${STORE_USER_MEMORY_TOOL_NAME}" to save stable user-specific facts that improve future help.
19044
+ - Use "${UPDATE_USER_MEMORY_TOOL_NAME}" to refresh an existing memory when the content changes.
19045
+ - Use "${DELETE_USER_MEMORY_TOOL_NAME}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
19046
+ - Store concise memory items and avoid duplicates.
19047
+ - Never claim memory was saved or loaded unless the tool confirms it.
19048
+ ${block(extraInstructions)}
19049
+ `));
19050
+ }
19051
+ /**
19052
+ * Gets human-readable titles for MEMORY tool functions.
19053
+ */
19054
+ getToolTitles() {
19055
+ return {
19056
+ [RETRIEVE_USER_MEMORY_TOOL_NAME]: 'User memory',
19057
+ [STORE_USER_MEMORY_TOOL_NAME]: 'Store user memory',
19058
+ [UPDATE_USER_MEMORY_TOOL_NAME]: 'Update user memory',
19059
+ [DELETE_USER_MEMORY_TOOL_NAME]: 'Delete user memory',
19060
+ };
19061
+ }
19062
+ /**
19063
+ * Gets MEMORY tool function implementations.
19064
+ */
19065
+ getToolFunctions() {
19066
+ return {
19067
+ async [RETRIEVE_USER_MEMORY_TOOL_NAME](args) {
19068
+ const runtimeContext = resolveMemoryRuntimeContext(args);
19069
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('retrieve', runtimeContext);
19070
+ if (!adapter || disabledResult) {
19071
+ return JSON.stringify(disabledResult);
19072
+ }
19073
+ const parsedArgs = parseRetrieveMemoryArgs(args);
19074
+ try {
19075
+ const memories = await adapter.retrieveMemories(parsedArgs, runtimeContext);
19076
+ const result = {
19077
+ action: 'retrieve',
19078
+ status: 'ok',
19079
+ query: parsedArgs.query,
19080
+ memories,
19081
+ };
19082
+ return JSON.stringify(result);
19083
+ }
19084
+ catch (error) {
19085
+ const result = {
19086
+ action: 'retrieve',
19087
+ status: 'error',
19088
+ query: parsedArgs.query,
19089
+ memories: [],
19090
+ message: error instanceof Error ? error.message : String(error),
19091
+ };
19092
+ return JSON.stringify(result);
19093
+ }
19094
+ },
19095
+ async [STORE_USER_MEMORY_TOOL_NAME](args) {
19096
+ const runtimeContext = resolveMemoryRuntimeContext(args);
19097
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('store', runtimeContext);
19098
+ if (!adapter || disabledResult) {
19099
+ return JSON.stringify(disabledResult);
19100
+ }
19101
+ try {
19102
+ const parsedArgs = parseStoreMemoryArgs(args);
19103
+ const memory = await adapter.storeMemory(parsedArgs, runtimeContext);
19104
+ const result = {
19105
+ action: 'store',
19106
+ status: 'stored',
19107
+ memory,
19108
+ };
19109
+ return JSON.stringify(result);
19110
+ }
19111
+ catch (error) {
19112
+ const result = {
19113
+ action: 'store',
19114
+ status: 'error',
19115
+ message: error instanceof Error ? error.message : String(error),
19116
+ };
19117
+ return JSON.stringify(result);
19118
+ }
19119
+ },
19120
+ async [UPDATE_USER_MEMORY_TOOL_NAME](args) {
19121
+ const runtimeContext = resolveMemoryRuntimeContext(args);
19122
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('update', runtimeContext);
19123
+ if (!adapter || disabledResult) {
19124
+ return JSON.stringify(disabledResult);
19125
+ }
19126
+ try {
19127
+ const parsedArgs = parseUpdateMemoryArgs(args);
19128
+ const memory = await adapter.updateMemory(parsedArgs, runtimeContext);
19129
+ const result = {
19130
+ action: 'update',
19131
+ status: 'updated',
19132
+ memory,
19133
+ };
19134
+ return JSON.stringify(result);
19135
+ }
19136
+ catch (error) {
19137
+ const result = {
19138
+ action: 'update',
19139
+ status: 'error',
19140
+ message: error instanceof Error ? error.message : String(error),
19141
+ };
19142
+ return JSON.stringify(result);
19143
+ }
19144
+ },
19145
+ async [DELETE_USER_MEMORY_TOOL_NAME](args) {
19146
+ const runtimeContext = resolveMemoryRuntimeContext(args);
19147
+ const { adapter, disabledResult } = getRuntimeAdapterOrDisabledResult('delete', runtimeContext);
19148
+ if (!adapter || disabledResult) {
19149
+ return JSON.stringify(disabledResult);
19150
+ }
19151
+ try {
19152
+ const parsedArgs = parseDeleteMemoryArgs(args);
19153
+ const deleted = await adapter.deleteMemory(parsedArgs, runtimeContext);
19154
+ const result = {
19155
+ action: 'delete',
19156
+ status: 'deleted',
19157
+ memoryId: deleted.id,
19158
+ };
19159
+ return JSON.stringify(result);
19160
+ }
19161
+ catch (error) {
19162
+ const result = {
19163
+ action: 'delete',
19164
+ status: 'error',
19165
+ message: error instanceof Error ? error.message : String(error),
19166
+ };
19167
+ return JSON.stringify(result);
19168
+ }
19169
+ },
19170
+ };
18683
19171
  }
18684
19172
  }
18685
19173
  /**
@@ -20792,14 +21280,30 @@
20792
21280
  /**
20793
21281
  * Builds a minimal chat prompt for teammate calls.
20794
21282
  */
20795
- function buildTeammatePrompt(request) {
21283
+ function buildTeammatePrompt(request, runtimeContext) {
20796
21284
  return {
20797
21285
  title: 'Teammate consultation',
20798
21286
  modelRequirements: {
20799
21287
  modelVariant: 'CHAT',
20800
21288
  },
20801
21289
  content: request,
20802
- parameters: {},
21290
+ parameters: {
21291
+ [TOOL_RUNTIME_CONTEXT_PARAMETER]: serializeToolRuntimeContext(runtimeContext),
21292
+ },
21293
+ };
21294
+ }
21295
+ /**
21296
+ * Creates teammate runtime context and marks conversation as team-only memory-disabled.
21297
+ */
21298
+ function createTeamConversationRuntimeContext(value) {
21299
+ const runtimeContext = parseToolRuntimeContext(value) || {};
21300
+ return {
21301
+ ...runtimeContext,
21302
+ memory: {
21303
+ ...(runtimeContext.memory || {}),
21304
+ enabled: false,
21305
+ isTeamConversation: true,
21306
+ },
20803
21307
  };
20804
21308
  }
20805
21309
  /**
@@ -20843,7 +21347,7 @@
20843
21347
  let toolCalls;
20844
21348
  try {
20845
21349
  const remoteAgent = await getRemoteTeammateAgent(entry.teammate.url);
20846
- const prompt = buildTeammatePrompt(request);
21350
+ const prompt = buildTeammatePrompt(request, createTeamConversationRuntimeContext(args[TOOL_RUNTIME_CONTEXT_ARGUMENT]));
20847
21351
  const teammateResult = await remoteAgent.callChatModel(prompt);
20848
21352
  response = teammateResult.content || '';
20849
21353
  toolCalls =
@@ -21393,25 +21897,6 @@
21393
21897
  * Note: [💞] Ignore a discrepancy between file name and entity name
21394
21898
  */
21395
21899
 
21396
- /**
21397
- * @@@
21398
- *
21399
- * @private utility for commitments
21400
- */
21401
- function formatOptionalInstructionBlock(label, content) {
21402
- const trimmedContent = spaceTrim$1.spaceTrim(content);
21403
- if (!trimmedContent) {
21404
- return '';
21405
- }
21406
- return spaceTrim$1.spaceTrim((block) => `
21407
- - ${label}:
21408
- ${block(trimmedContent
21409
- .split(/\r?\n/)
21410
- .map((line) => `- ${line}`)
21411
- .join('\n'))}
21412
- `);
21413
- }
21414
-
21415
21900
  /**
21416
21901
  * Client-side safe wrapper for sending emails.
21417
21902
  *
@@ -22938,6 +23423,7 @@
22938
23423
  systemMessage: requirements.systemMessage + '\n\n' + exampleInteractionsContent,
22939
23424
  };
22940
23425
  }
23426
+ requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
22941
23427
  // Remove comment lines (lines starting with #) from the final system message
22942
23428
  // while preserving the original content with comments in metadata
22943
23429
  const cleanedSystemMessage = removeCommentsFromSystemMessage(requirements.systemMessage);
@@ -22946,6 +23432,54 @@
22946
23432
  systemMessage: cleanedSystemMessage,
22947
23433
  };
22948
23434
  }
23435
+ /**
23436
+ * @private Attempts to upload inline knowledge entries, falling back to legacy data URLs when the upload fails or is not configured.
23437
+ */
23438
+ async function applyPendingInlineKnowledgeSources(requirements, uploader) {
23439
+ var _a;
23440
+ const inlineSources = extractInlineKnowledgeSources(requirements._metadata);
23441
+ if (inlineSources.length === 0) {
23442
+ return requirements;
23443
+ }
23444
+ const knowledgeSources = [...((_a = requirements.knowledgeSources) !== null && _a !== void 0 ? _a : [])];
23445
+ for (const inlineSource of inlineSources) {
23446
+ const url = uploader
23447
+ ? await uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader)
23448
+ : inlineKnowledgeSourceToDataUrl(inlineSource);
23449
+ knowledgeSources.push(url);
23450
+ }
23451
+ return {
23452
+ ...requirements,
23453
+ knowledgeSources,
23454
+ _metadata: stripInlineKnowledgeMetadata(requirements._metadata),
23455
+ };
23456
+ }
23457
+ async function uploadInlineKnowledgeSourceWithFallback(inlineSource, uploader) {
23458
+ try {
23459
+ return await uploader(inlineSource);
23460
+ }
23461
+ catch (error) {
23462
+ console.error('[inline-knowledge] Failed to upload inline source', {
23463
+ filename: inlineSource.filename,
23464
+ error,
23465
+ });
23466
+ return inlineKnowledgeSourceToDataUrl(inlineSource);
23467
+ }
23468
+ }
23469
+ function extractInlineKnowledgeSources(metadata) {
23470
+ if (!metadata) {
23471
+ return [];
23472
+ }
23473
+ const value = metadata.inlineKnowledgeSources;
23474
+ return Array.isArray(value) ? value : [];
23475
+ }
23476
+ function stripInlineKnowledgeMetadata(metadata) {
23477
+ if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, 'inlineKnowledgeSources')) {
23478
+ return metadata;
23479
+ }
23480
+ const { inlineKnowledgeSources: _unusedInlineKnowledgeSources, ...rest } = metadata;
23481
+ return Object.keys(rest).length > 0 ? rest : undefined;
23482
+ }
22949
23483
  /**
22950
23484
  * Mocked security check for imported files
22951
23485
  *
@@ -30110,10 +30644,10 @@
30110
30644
  try {
30111
30645
  return await scriptTool.execute({
30112
30646
  scriptLanguage: 'javascript',
30113
- script: `
30114
- const args = ${JSON.stringify(functionArgs)};
30115
- return await ${functionName}(args);
30116
- `,
30647
+ script: buildToolInvocationScript({
30648
+ functionName,
30649
+ functionArgsExpression: JSON.stringify(functionArgs),
30650
+ }),
30117
30651
  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 : {},
30118
30652
  });
30119
30653
  }
@@ -31144,6 +31678,20 @@
31144
31678
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?
31145
31679
  */
31146
31680
 
31681
+ /**
31682
+ * Keep-alive helpers used for streaming chat responses.
31683
+ *
31684
+ * These constants coordinate the signal sent by the Agents Server streaming
31685
+ * endpoint and the parser in the SDK so we can distinguish between
31686
+ * real content and occasional pings.
31687
+ *
31688
+ * @private internal streaming helper for Promptbook chat connections
31689
+ */
31690
+ const CHAT_STREAM_KEEP_ALIVE_TOKEN = 'STREAM_KEEP_ALIVE';
31691
+ /**
31692
+ * Note: [💞] Ignore a discrepancy between file name and entity name
31693
+ */
31694
+
31147
31695
  /**
31148
31696
  * Resolve a remote META IMAGE value into an absolute URL when possible.
31149
31697
  */
@@ -31218,7 +31766,9 @@
31218
31766
  static async connect(options) {
31219
31767
  var _a, _b, _c;
31220
31768
  const agentProfileUrl = `${options.agentUrl}/api/profile`;
31221
- const profileResponse = await fetch(agentProfileUrl);
31769
+ const profileResponse = await fetch(agentProfileUrl, {
31770
+ headers: attachClientVersionHeader(),
31771
+ });
31222
31772
  // <- TODO: [🐱‍🚀] What about closed-source agents?
31223
31773
  // <- TODO: [🐱‍🚀] Maybe use promptbookFetch
31224
31774
  if (!profileResponse.ok) {
@@ -31319,6 +31869,7 @@
31319
31869
  }
31320
31870
  const response = await fetch(`${this.agentUrl}/api/voice`, {
31321
31871
  method: 'POST',
31872
+ headers: attachClientVersionHeader(),
31322
31873
  body: formData,
31323
31874
  });
31324
31875
  if (!response.ok) {
@@ -31348,13 +31899,14 @@
31348
31899
  const chatPrompt = prompt;
31349
31900
  const bookResponse = await fetch(`${this.agentUrl}/api/chat`, {
31350
31901
  method: 'POST',
31351
- headers: {
31902
+ headers: attachClientVersionHeader({
31352
31903
  'Content-Type': 'application/json',
31353
- },
31904
+ }),
31354
31905
  body: JSON.stringify({
31355
31906
  message: prompt.content,
31356
31907
  thread: chatPrompt.thread,
31357
31908
  attachments: chatPrompt.attachments,
31909
+ parameters: chatPrompt.parameters,
31358
31910
  }),
31359
31911
  });
31360
31912
  // <- TODO: [🐱‍🚀] What about closed-source agents?
@@ -31436,6 +31988,9 @@
31436
31988
  const lines = textChunk.split(/\r?\n/);
31437
31989
  for (const line of lines) {
31438
31990
  const trimmedLine = line.trim();
31991
+ if (trimmedLine === CHAT_STREAM_KEEP_ALIVE_TOKEN) {
31992
+ continue;
31993
+ }
31439
31994
  let isToolCallLine = false;
31440
31995
  if (trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
31441
31996
  try {