@promptbook/wizard 0.105.0-6 → 0.105.0-8

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.
package/esm/index.es.js CHANGED
@@ -36,7 +36,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
36
36
  * @generated
37
37
  * @see https://github.com/webgptorg/promptbook
38
38
  */
39
- const PROMPTBOOK_ENGINE_VERSION = '0.105.0-6';
39
+ const PROMPTBOOK_ENGINE_VERSION = '0.105.0-8';
40
40
  /**
41
41
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
42
42
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -7705,6 +7705,16 @@ function unwrapResult(text, options) {
7705
7705
  trimmedText = spaceTrim$1(trimmedText);
7706
7706
  }
7707
7707
  let processedText = trimmedText;
7708
+ // Check for markdown code block
7709
+ const codeBlockRegex = /^```[a-z]*\n([\s\S]*?)\n```\s*$/;
7710
+ const codeBlockMatch = processedText.match(codeBlockRegex);
7711
+ if (codeBlockMatch && codeBlockMatch[1] !== undefined) {
7712
+ // Check if there's only one code block
7713
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
7714
+ if (codeBlockCount === 1) {
7715
+ return unwrapResult(codeBlockMatch[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
7716
+ }
7717
+ }
7708
7718
  if (isIntroduceSentenceRemoved) {
7709
7719
  const introduceSentenceRegex = /^[a-zěščřžýáíéúů:\s]*:\s*/i;
7710
7720
  if (introduceSentenceRegex.test(text)) {
@@ -7712,6 +7722,14 @@ function unwrapResult(text, options) {
7712
7722
  processedText = processedText.replace(introduceSentenceRegex, '');
7713
7723
  }
7714
7724
  processedText = spaceTrim$1(processedText);
7725
+ // Check again for code block after removing introduce sentence
7726
+ const codeBlockMatch2 = processedText.match(codeBlockRegex);
7727
+ if (codeBlockMatch2 && codeBlockMatch2[1] !== undefined) {
7728
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
7729
+ if (codeBlockCount === 1) {
7730
+ return unwrapResult(codeBlockMatch2[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
7731
+ }
7732
+ }
7715
7733
  }
7716
7734
  if (processedText.length < 3) {
7717
7735
  return trimmedText;
@@ -17695,6 +17713,46 @@ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
17695
17713
  * Note: [💞] Ignore a discrepancy between file name and entity name
17696
17714
  */
17697
17715
 
17716
+ /**
17717
+ * A search engine implementation that uses the SerpApi to fetch Google search results.
17718
+ *
17719
+ * @private <- TODO: !!!! Export via some package
17720
+ */
17721
+ class SerpSearchEngine {
17722
+ get title() {
17723
+ return 'SerpApi Search Engine';
17724
+ }
17725
+ get description() {
17726
+ return 'Search engine that uses SerpApi to fetch Google search results';
17727
+ }
17728
+ checkConfiguration() {
17729
+ if (!process.env.SERP_API_KEY) {
17730
+ throw new Error('SERP_API_KEY is not configured');
17731
+ }
17732
+ }
17733
+ async search(query) {
17734
+ const apiKey = process.env.SERP_API_KEY;
17735
+ if (!apiKey) {
17736
+ throw new Error('SERP_API_KEY is not configured');
17737
+ }
17738
+ const url = new URL('https://serpapi.com/search');
17739
+ url.searchParams.set('q', query);
17740
+ url.searchParams.set('api_key', apiKey);
17741
+ url.searchParams.set('engine', 'google');
17742
+ const response = await fetch(url.toString());
17743
+ if (!response.ok) {
17744
+ const body = await response.text();
17745
+ throw new Error(`SerpApi failed with status ${response.status}: ${response.statusText}\n${body}`);
17746
+ }
17747
+ const data = (await response.json());
17748
+ return (data.organic_results || []).map((item) => ({
17749
+ title: item.title,
17750
+ url: item.link,
17751
+ snippet: item.snippet || '',
17752
+ }));
17753
+ }
17754
+ }
17755
+
17698
17756
  /**
17699
17757
  * USE SEARCH ENGINE commitment definition
17700
17758
  *
@@ -17771,18 +17829,13 @@ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
17771
17829
  ? existingTools
17772
17830
  : [
17773
17831
  ...existingTools,
17774
- { type: 'web_search' },
17775
- // <- Note: [🔰] This is just using simple native search tool by OpenAI @see https://platform.openai.com/docs/guides/tools-web-search
17776
- // In future we will use proper MCP search tool:
17777
- /*
17778
-
17779
17832
  {
17780
17833
  name: 'web_search',
17781
- description: spaceTrim(`
17782
- Search the internet for information.
17783
- Use this tool when you need to find up-to-date information or facts that you don't know.
17784
- ${!content ? '' : `Search scope / instructions: ${content}`}
17785
- `),
17834
+ description: spaceTrim$1(`
17835
+ Search the internet for information.
17836
+ Use this tool when you need to find up-to-date information or facts that you don't know.
17837
+ ${!content ? '' : `Search scope / instructions: ${content}`}
17838
+ `),
17786
17839
  parameters: {
17787
17840
  type: 'object',
17788
17841
  properties: {
@@ -17794,7 +17847,6 @@ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
17794
17847
  required: ['query'],
17795
17848
  },
17796
17849
  },
17797
- */
17798
17850
  ];
17799
17851
  // Return requirements with updated tools and metadata
17800
17852
  return {
@@ -17806,6 +17858,33 @@ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
17806
17858
  },
17807
17859
  };
17808
17860
  }
17861
+ /**
17862
+ * Gets the `web_search` tool function implementation.
17863
+ */
17864
+ getToolFunctions() {
17865
+ return {
17866
+ async web_search(args) {
17867
+ console.log('!!!! [Tool] web_search called', { args });
17868
+ const { query } = args;
17869
+ if (!query) {
17870
+ throw new Error('Search query is required');
17871
+ }
17872
+ const searchEngine = new SerpSearchEngine();
17873
+ const results = await searchEngine.search(query);
17874
+ return spaceTrim$1((block) => `
17875
+ Search results for "${query}":
17876
+
17877
+ ${block(results
17878
+ .map((result) => spaceTrim$1(`
17879
+ - **${result.title}**
17880
+ ${result.url}
17881
+ ${result.snippet}
17882
+ `))
17883
+ .join('\n\n'))}
17884
+ `);
17885
+ },
17886
+ };
17887
+ }
17809
17888
  }
17810
17889
  /**
17811
17890
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -18049,6 +18128,7 @@ const COMMITMENT_REGISTRY = [
18049
18128
  new NoteCommitmentDefinition('NOTES'),
18050
18129
  new NoteCommitmentDefinition('COMMENT'),
18051
18130
  new NoteCommitmentDefinition('NONCE'),
18131
+ new NoteCommitmentDefinition('TODO'),
18052
18132
  new GoalCommitmentDefinition('GOAL'),
18053
18133
  new GoalCommitmentDefinition('GOALS'),
18054
18134
  new InitialMessageCommitmentDefinition(),
@@ -20083,6 +20163,16 @@ function cacheLlmTools(llmTools, options = {}) {
20083
20163
  }
20084
20164
  }
20085
20165
  }
20166
+ if (shouldCache && promptResult.toolCalls !== undefined) {
20167
+ // Note: Do not cache results that contain tool calls because they are dynamic and should be always fresh
20168
+ // For example, it doesn't make sense to cache the message 'What time is it? 3:30 pm' because when the question is asked another time, it can be a different time.
20169
+ shouldCache = false;
20170
+ if (isVerbose) {
20171
+ console.info('Not caching result that contains tool calls for key:', key, {
20172
+ toolCalls: promptResult.toolCalls,
20173
+ });
20174
+ }
20175
+ }
20086
20176
  if (shouldCache) {
20087
20177
  await storage.setItem(key, {
20088
20178
  date: $getCurrentDate(),