@promptbook/cli 0.110.0-1 → 0.110.0-10
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 +1778 -502
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +4 -0
- package/esm/typings/src/_packages/core.index.d.ts +2 -2
- package/esm/typings/src/_packages/openai.index.d.ts +8 -4
- package/esm/typings/src/_packages/types.index.d.ts +12 -4
- package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +22 -21
- package/esm/typings/src/book-2.0/agent-source/AgentReferenceResolver.d.ts +18 -0
- package/esm/typings/src/book-2.0/agent-source/CreateAgentModelRequirementsOptions.d.ts +12 -0
- package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +8 -2
- package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.agentReferenceResolver.test.d.ts +1 -0
- package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.d.ts +4 -5
- package/esm/typings/src/book-components/Chat/AgentChip/AgentChip.d.ts +5 -1
- package/esm/typings/src/book-components/Chat/Chat/ChatActionsBar.d.ts +4 -2
- package/esm/typings/src/book-components/Chat/Chat/ChatInputArea.d.ts +1 -0
- package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +4 -0
- package/esm/typings/src/book-components/Chat/Chat/ChatMessageList.d.ts +1 -0
- package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +15 -0
- package/esm/typings/src/book-components/Chat/Chat/ChatSoundToggle.d.ts +31 -0
- package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +10 -1
- package/esm/typings/src/book-components/Chat/SourceChip/SourceChip.d.ts +5 -1
- package/esm/typings/src/book-components/Chat/utils/collectTeamToolCallSummary.d.ts +69 -0
- package/esm/typings/src/book-components/Chat/utils/getToolCallChipletInfo.d.ts +13 -13
- package/esm/typings/src/book-components/Chat/utils/parseCitationsFromContent.d.ts +9 -0
- package/esm/typings/src/book-components/Chat/utils/toolCallParsing.d.ts +4 -0
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +0 -3
- package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +9 -0
- package/esm/typings/src/execution/LlmExecutionTools.d.ts +2 -1
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +1 -1
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +5 -1
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.test.d.ts +1 -0
- package/esm/typings/src/llm-providers/agent/AgentOptions.d.ts +10 -0
- package/esm/typings/src/llm-providers/agent/CreateAgentLlmExecutionToolsOptions.d.ts +13 -2
- package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +2 -1
- package/esm/typings/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +150 -0
- package/esm/typings/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOptions.d.ts +15 -0
- package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +3 -3
- package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionToolsOptions.d.ts +3 -4
- package/esm/typings/src/llm-providers/openai/OpenAiVectorStoreHandler.d.ts +135 -0
- package/esm/typings/src/llm-providers/openai/utils/mapToolsToOpenAi.d.ts +1 -1
- package/esm/typings/src/types/LlmToolDefinition.d.ts +1 -0
- package/esm/typings/src/types/ModelRequirements.d.ts +9 -0
- package/esm/typings/src/utils/DEFAULT_THINKING_MESSAGES.d.ts +8 -0
- package/esm/typings/src/utils/agents/resolveAgentAvatarImageUrl.d.ts +29 -0
- package/esm/typings/src/utils/knowledge/inlineKnowledgeSource.d.ts +38 -0
- package/esm/typings/src/utils/knowledge/inlineKnowledgeSource.test.d.ts +1 -0
- package/esm/typings/src/utils/language/getBrowserPreferredSpeechRecognitionLanguage.d.ts +35 -0
- package/esm/typings/src/utils/toolCalls/getToolCallIdentity.d.ts +10 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +6 -2
- package/umd/index.umd.js +1781 -506
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/llm-providers/openai/OpenAiAgentExecutionTools.d.ts +0 -43
- package/esm/typings/src/llm-providers/openai/createOpenAiAgentExecutionTools.d.ts +0 -11
package/esm/index.es.js
CHANGED
|
@@ -31,6 +31,7 @@ import { OpenAIClient, AzureKeyCredential } from '@azure/openai';
|
|
|
31
31
|
import { Subject, BehaviorSubject } from 'rxjs';
|
|
32
32
|
import { lookup, extension } from 'mime-types';
|
|
33
33
|
import { parse, unparse } from 'papaparse';
|
|
34
|
+
import { Agent as Agent$1, setDefaultOpenAIClient, setDefaultOpenAIKey, fileSearchTool, tool, run } from '@openai/agents';
|
|
34
35
|
import OpenAI from 'openai';
|
|
35
36
|
|
|
36
37
|
// ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
|
|
@@ -47,7 +48,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
47
48
|
* @generated
|
|
48
49
|
* @see https://github.com/webgptorg/promptbook
|
|
49
50
|
*/
|
|
50
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.110.0-
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.110.0-10';
|
|
51
52
|
/**
|
|
52
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
53
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -15827,6 +15828,28 @@ class BaseCommitmentDefinition {
|
|
|
15827
15828
|
return currentMessage + separator + content;
|
|
15828
15829
|
});
|
|
15829
15830
|
}
|
|
15831
|
+
/**
|
|
15832
|
+
* Helper method to create a new requirements object with updated prompt suffix
|
|
15833
|
+
*/
|
|
15834
|
+
updatePromptSuffix(requirements, contentUpdate) {
|
|
15835
|
+
const newSuffix = typeof contentUpdate === 'string' ? contentUpdate : contentUpdate(requirements.promptSuffix);
|
|
15836
|
+
return {
|
|
15837
|
+
...requirements,
|
|
15838
|
+
promptSuffix: newSuffix,
|
|
15839
|
+
};
|
|
15840
|
+
}
|
|
15841
|
+
/**
|
|
15842
|
+
* Helper method to append content to the prompt suffix
|
|
15843
|
+
* Default separator is a single newline for bullet lists.
|
|
15844
|
+
*/
|
|
15845
|
+
appendToPromptSuffix(requirements, content, separator = '\n') {
|
|
15846
|
+
return this.updatePromptSuffix(requirements, (currentSuffix) => {
|
|
15847
|
+
if (!currentSuffix.trim()) {
|
|
15848
|
+
return content;
|
|
15849
|
+
}
|
|
15850
|
+
return `${currentSuffix}${separator}${content}`;
|
|
15851
|
+
});
|
|
15852
|
+
}
|
|
15830
15853
|
/**
|
|
15831
15854
|
* Helper method to add a comment section to the system message
|
|
15832
15855
|
* Comments are lines starting with # that will be removed from the final system message
|
|
@@ -16004,13 +16027,9 @@ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
16004
16027
|
`);
|
|
16005
16028
|
}
|
|
16006
16029
|
applyToAgentModelRequirements(requirements, _content) {
|
|
16007
|
-
const updatedMetadata = {
|
|
16008
|
-
...requirements.metadata,
|
|
16009
|
-
isClosed: true,
|
|
16010
|
-
};
|
|
16011
16030
|
return {
|
|
16012
16031
|
...requirements,
|
|
16013
|
-
|
|
16032
|
+
isClosed: true,
|
|
16014
16033
|
};
|
|
16015
16034
|
}
|
|
16016
16035
|
}
|
|
@@ -16288,12 +16307,12 @@ class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
16288
16307
|
return requirements;
|
|
16289
16308
|
}
|
|
16290
16309
|
// Get existing dictionary entries from metadata
|
|
16291
|
-
const existingDictionary = ((_a = requirements.
|
|
16310
|
+
const existingDictionary = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
|
|
16292
16311
|
// Merge the new dictionary entry with existing entries
|
|
16293
16312
|
const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
|
|
16294
16313
|
// Store the merged dictionary in metadata for debugging and inspection
|
|
16295
16314
|
const updatedMetadata = {
|
|
16296
|
-
...requirements.
|
|
16315
|
+
...requirements._metadata,
|
|
16297
16316
|
DICTIONARY: mergedDictionary,
|
|
16298
16317
|
};
|
|
16299
16318
|
// Create the dictionary section for the system message
|
|
@@ -16301,7 +16320,7 @@ class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
16301
16320
|
const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
|
|
16302
16321
|
return {
|
|
16303
16322
|
...this.appendToSystemMessage(requirements, dictionarySection),
|
|
16304
|
-
|
|
16323
|
+
_metadata: updatedMetadata,
|
|
16305
16324
|
};
|
|
16306
16325
|
}
|
|
16307
16326
|
}
|
|
@@ -16441,10 +16460,7 @@ class FromCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
16441
16460
|
applyToAgentModelRequirements(requirements, content) {
|
|
16442
16461
|
const trimmedContent = content.trim();
|
|
16443
16462
|
if (!trimmedContent) {
|
|
16444
|
-
return
|
|
16445
|
-
...requirements,
|
|
16446
|
-
parentAgentUrl: undefined,
|
|
16447
|
-
};
|
|
16463
|
+
return requirements;
|
|
16448
16464
|
}
|
|
16449
16465
|
if (trimmedContent.toUpperCase() === 'VOID' ||
|
|
16450
16466
|
trimmedContent.toUpperCase() === 'NULL' ||
|
|
@@ -16658,6 +16674,136 @@ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
16658
16674
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
16659
16675
|
*/
|
|
16660
16676
|
|
|
16677
|
+
/**
|
|
16678
|
+
* @@@
|
|
16679
|
+
*
|
|
16680
|
+
* @private thing of inline knowledge
|
|
16681
|
+
*/
|
|
16682
|
+
const INLINE_KNOWLEDGE_BASE_NAME = 'inline-knowledge';
|
|
16683
|
+
/**
|
|
16684
|
+
* @@@
|
|
16685
|
+
*
|
|
16686
|
+
* @private thing of inline knowledge
|
|
16687
|
+
*/
|
|
16688
|
+
const INLINE_KNOWLEDGE_EXTENSION = '.txt';
|
|
16689
|
+
/**
|
|
16690
|
+
* @@@
|
|
16691
|
+
*
|
|
16692
|
+
* @private thing of inline knowledge
|
|
16693
|
+
*/
|
|
16694
|
+
const DATA_URL_PREFIX = 'data:';
|
|
16695
|
+
/**
|
|
16696
|
+
* @@@
|
|
16697
|
+
*
|
|
16698
|
+
* @private thing of inline knowledge
|
|
16699
|
+
*/
|
|
16700
|
+
function getFirstNonEmptyLine(content) {
|
|
16701
|
+
const lines = content.split(/\r?\n/);
|
|
16702
|
+
for (const line of lines) {
|
|
16703
|
+
const trimmed = line.trim();
|
|
16704
|
+
if (trimmed) {
|
|
16705
|
+
return trimmed;
|
|
16706
|
+
}
|
|
16707
|
+
}
|
|
16708
|
+
return null;
|
|
16709
|
+
}
|
|
16710
|
+
/**
|
|
16711
|
+
* @@@
|
|
16712
|
+
*
|
|
16713
|
+
* @private thing of inline knowledge
|
|
16714
|
+
*/
|
|
16715
|
+
function deriveBaseFilename(content) {
|
|
16716
|
+
const firstLine = getFirstNonEmptyLine(content);
|
|
16717
|
+
if (!firstLine) {
|
|
16718
|
+
return INLINE_KNOWLEDGE_BASE_NAME;
|
|
16719
|
+
}
|
|
16720
|
+
const normalized = normalizeToKebabCase(firstLine);
|
|
16721
|
+
return normalized || INLINE_KNOWLEDGE_BASE_NAME;
|
|
16722
|
+
}
|
|
16723
|
+
/**
|
|
16724
|
+
* Creates a data URL that represents the inline knowledge content as a text file.
|
|
16725
|
+
*
|
|
16726
|
+
* @private thing of inline knowledge
|
|
16727
|
+
*/
|
|
16728
|
+
function createInlineKnowledgeSourceFile(content) {
|
|
16729
|
+
const trimmedContent = content.trim();
|
|
16730
|
+
const baseName = deriveBaseFilename(trimmedContent);
|
|
16731
|
+
const filename = `${baseName}${INLINE_KNOWLEDGE_EXTENSION}`;
|
|
16732
|
+
const mimeType = 'text/plain';
|
|
16733
|
+
const base64 = Buffer.from(trimmedContent, 'utf-8').toString('base64');
|
|
16734
|
+
const encodedFilename = encodeURIComponent(filename);
|
|
16735
|
+
const url = `${DATA_URL_PREFIX}${mimeType};name=${encodedFilename};charset=utf-8;base64,${base64}`;
|
|
16736
|
+
return {
|
|
16737
|
+
filename,
|
|
16738
|
+
mimeType,
|
|
16739
|
+
url,
|
|
16740
|
+
};
|
|
16741
|
+
}
|
|
16742
|
+
/**
|
|
16743
|
+
* Checks whether the provided source string is a data URL that can be decoded.
|
|
16744
|
+
*
|
|
16745
|
+
* @private thing of inline knowledge
|
|
16746
|
+
*/
|
|
16747
|
+
function isDataUrlKnowledgeSource(source) {
|
|
16748
|
+
return typeof source === 'string' && source.startsWith(DATA_URL_PREFIX);
|
|
16749
|
+
}
|
|
16750
|
+
/**
|
|
16751
|
+
* Parses a data URL-based knowledge source into its raw buffer, filename, and MIME type.
|
|
16752
|
+
*
|
|
16753
|
+
* @private thing of inline knowledge
|
|
16754
|
+
*/
|
|
16755
|
+
function parseDataUrlKnowledgeSource(source) {
|
|
16756
|
+
if (!isDataUrlKnowledgeSource(source)) {
|
|
16757
|
+
return null;
|
|
16758
|
+
}
|
|
16759
|
+
const commaIndex = source.indexOf(',');
|
|
16760
|
+
if (commaIndex === -1) {
|
|
16761
|
+
return null;
|
|
16762
|
+
}
|
|
16763
|
+
const header = source.slice(DATA_URL_PREFIX.length, commaIndex);
|
|
16764
|
+
const payload = source.slice(commaIndex + 1);
|
|
16765
|
+
const tokens = header.split(';');
|
|
16766
|
+
const mediaType = tokens[0] || 'text/plain';
|
|
16767
|
+
let filename = `${INLINE_KNOWLEDGE_BASE_NAME}${INLINE_KNOWLEDGE_EXTENSION}`;
|
|
16768
|
+
let isBase64 = false;
|
|
16769
|
+
for (let i = 1; i < tokens.length; i++) {
|
|
16770
|
+
const token = tokens[i];
|
|
16771
|
+
if (!token) {
|
|
16772
|
+
continue;
|
|
16773
|
+
}
|
|
16774
|
+
if (token.toLowerCase() === 'base64') {
|
|
16775
|
+
isBase64 = true;
|
|
16776
|
+
continue;
|
|
16777
|
+
}
|
|
16778
|
+
const [key, value] = token.split('=');
|
|
16779
|
+
if (key === 'name' && value !== undefined) {
|
|
16780
|
+
try {
|
|
16781
|
+
filename = decodeURIComponent(value);
|
|
16782
|
+
}
|
|
16783
|
+
catch (_a) {
|
|
16784
|
+
filename = value;
|
|
16785
|
+
}
|
|
16786
|
+
}
|
|
16787
|
+
}
|
|
16788
|
+
if (!isBase64) {
|
|
16789
|
+
return null;
|
|
16790
|
+
}
|
|
16791
|
+
try {
|
|
16792
|
+
const buffer = Buffer.from(payload, 'base64');
|
|
16793
|
+
return {
|
|
16794
|
+
buffer,
|
|
16795
|
+
filename,
|
|
16796
|
+
mimeType: mediaType,
|
|
16797
|
+
};
|
|
16798
|
+
}
|
|
16799
|
+
catch (_b) {
|
|
16800
|
+
return null;
|
|
16801
|
+
}
|
|
16802
|
+
}
|
|
16803
|
+
/**
|
|
16804
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
16805
|
+
*/
|
|
16806
|
+
|
|
16661
16807
|
/**
|
|
16662
16808
|
* KNOWLEDGE commitment definition
|
|
16663
16809
|
*
|
|
@@ -16756,9 +16902,13 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
16756
16902
|
return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
|
|
16757
16903
|
}
|
|
16758
16904
|
else {
|
|
16759
|
-
|
|
16760
|
-
const
|
|
16761
|
-
|
|
16905
|
+
const inlineSource = createInlineKnowledgeSourceFile(trimmedContent);
|
|
16906
|
+
const updatedRequirements = {
|
|
16907
|
+
...requirements,
|
|
16908
|
+
knowledgeSources: [...(requirements.knowledgeSources || []), inlineSource.url],
|
|
16909
|
+
};
|
|
16910
|
+
const knowledgeInfo = `Knowledge Source Inline: ${inlineSource.filename} (derived from inline content and processed for retrieval during chat)`;
|
|
16911
|
+
return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
|
|
16762
16912
|
}
|
|
16763
16913
|
}
|
|
16764
16914
|
}
|
|
@@ -17005,16 +17155,16 @@ class AgentMessageCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
17005
17155
|
// and typically doesn't need to be added to the system prompt or model requirements directly.
|
|
17006
17156
|
// It is extracted separately for the chat interface.
|
|
17007
17157
|
var _a;
|
|
17008
|
-
const pendingUserMessage = (_a = requirements.
|
|
17158
|
+
const pendingUserMessage = (_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.pendingUserMessage;
|
|
17009
17159
|
if (pendingUserMessage) {
|
|
17010
17160
|
const newSample = { question: pendingUserMessage, answer: content };
|
|
17011
17161
|
const newSamples = [...(requirements.samples || []), newSample];
|
|
17012
|
-
const newMetadata = { ...requirements.
|
|
17162
|
+
const newMetadata = { ...requirements._metadata };
|
|
17013
17163
|
delete newMetadata.pendingUserMessage;
|
|
17014
17164
|
return {
|
|
17015
17165
|
...requirements,
|
|
17016
17166
|
samples: newSamples,
|
|
17017
|
-
|
|
17167
|
+
_metadata: newMetadata,
|
|
17018
17168
|
};
|
|
17019
17169
|
}
|
|
17020
17170
|
return requirements;
|
|
@@ -17262,8 +17412,8 @@ class UserMessageCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
17262
17412
|
applyToAgentModelRequirements(requirements, content) {
|
|
17263
17413
|
return {
|
|
17264
17414
|
...requirements,
|
|
17265
|
-
|
|
17266
|
-
...requirements.
|
|
17415
|
+
_metadata: {
|
|
17416
|
+
...requirements._metadata,
|
|
17267
17417
|
pendingUserMessage: content,
|
|
17268
17418
|
},
|
|
17269
17419
|
};
|
|
@@ -18121,11 +18271,7 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18121
18271
|
if (trimmedContent === '') {
|
|
18122
18272
|
return requirements;
|
|
18123
18273
|
}
|
|
18124
|
-
|
|
18125
|
-
return {
|
|
18126
|
-
...requirements,
|
|
18127
|
-
notes: [...(requirements.notes || []), trimmedContent],
|
|
18128
|
-
};
|
|
18274
|
+
return requirements;
|
|
18129
18275
|
}
|
|
18130
18276
|
}
|
|
18131
18277
|
/**
|
|
@@ -18187,12 +18333,12 @@ class OpenCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18187
18333
|
// Since OPEN is default, we can just ensure isClosed is false
|
|
18188
18334
|
// But to be explicit we can set it
|
|
18189
18335
|
const updatedMetadata = {
|
|
18190
|
-
...requirements.
|
|
18336
|
+
...requirements._metadata,
|
|
18191
18337
|
isClosed: false,
|
|
18192
18338
|
};
|
|
18193
18339
|
return {
|
|
18194
18340
|
...requirements,
|
|
18195
|
-
|
|
18341
|
+
_metadata: updatedMetadata,
|
|
18196
18342
|
};
|
|
18197
18343
|
}
|
|
18198
18344
|
}
|
|
@@ -18273,7 +18419,7 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18273
18419
|
return requirements;
|
|
18274
18420
|
}
|
|
18275
18421
|
// Get existing persona content from metadata
|
|
18276
|
-
const existingPersonaContent = ((_a = requirements.
|
|
18422
|
+
const existingPersonaContent = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
|
|
18277
18423
|
// Merge the new content with existing persona content
|
|
18278
18424
|
// When multiple PERSONA commitments exist, they are merged into one
|
|
18279
18425
|
const mergedPersonaContent = existingPersonaContent
|
|
@@ -18281,12 +18427,12 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18281
18427
|
: trimmedContent;
|
|
18282
18428
|
// Store the merged persona content in metadata for debugging and inspection
|
|
18283
18429
|
const updatedMetadata = {
|
|
18284
|
-
...requirements.
|
|
18430
|
+
...requirements._metadata,
|
|
18285
18431
|
PERSONA: mergedPersonaContent,
|
|
18286
18432
|
};
|
|
18287
18433
|
// Get the agent name from metadata (which should contain the first line of agent source)
|
|
18288
18434
|
// If not available, extract from current system message as fallback
|
|
18289
|
-
let agentName = (_b = requirements.
|
|
18435
|
+
let agentName = (_b = requirements._metadata) === null || _b === void 0 ? void 0 : _b.agentName;
|
|
18290
18436
|
if (!agentName) {
|
|
18291
18437
|
// Fallback: extract from current system message
|
|
18292
18438
|
const currentMessage = requirements.systemMessage.trim();
|
|
@@ -18333,7 +18479,7 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18333
18479
|
return {
|
|
18334
18480
|
...requirements,
|
|
18335
18481
|
systemMessage: newSystemMessage,
|
|
18336
|
-
|
|
18482
|
+
_metadata: updatedMetadata,
|
|
18337
18483
|
};
|
|
18338
18484
|
}
|
|
18339
18485
|
}
|
|
@@ -18416,7 +18562,16 @@ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18416
18562
|
}
|
|
18417
18563
|
// Add rule to the system message
|
|
18418
18564
|
const ruleSection = `Rule: ${trimmedContent}`;
|
|
18419
|
-
|
|
18565
|
+
const requirementsWithRule = this.appendToSystemMessage(requirements, ruleSection, '\n\n');
|
|
18566
|
+
const ruleLines = trimmedContent
|
|
18567
|
+
.split(/\r?\n/)
|
|
18568
|
+
.map((line) => line.trim())
|
|
18569
|
+
.filter(Boolean)
|
|
18570
|
+
.map((line) => `- ${line}`);
|
|
18571
|
+
if (ruleLines.length === 0) {
|
|
18572
|
+
return requirementsWithRule;
|
|
18573
|
+
}
|
|
18574
|
+
return this.appendToPromptSuffix(requirementsWithRule, ruleLines.join('\n'));
|
|
18420
18575
|
}
|
|
18421
18576
|
}
|
|
18422
18577
|
/**
|
|
@@ -18922,7 +19077,7 @@ class TeamCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18922
19077
|
if (teammates.length === 0) {
|
|
18923
19078
|
return requirements;
|
|
18924
19079
|
}
|
|
18925
|
-
const agentName = ((_a = requirements.
|
|
19080
|
+
const agentName = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.agentName) || 'Agent';
|
|
18926
19081
|
const teamEntries = teammates.map((teammate) => ({
|
|
18927
19082
|
toolName: createTeamToolName(teammate.url),
|
|
18928
19083
|
teammate,
|
|
@@ -18962,7 +19117,7 @@ class TeamCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18962
19117
|
},
|
|
18963
19118
|
});
|
|
18964
19119
|
}
|
|
18965
|
-
const existingTeammates = ((_b = requirements.
|
|
19120
|
+
const existingTeammates = ((_b = requirements._metadata) === null || _b === void 0 ? void 0 : _b.teammates) || [];
|
|
18966
19121
|
const updatedTeammates = [...existingTeammates];
|
|
18967
19122
|
for (const entry of teamEntries) {
|
|
18968
19123
|
if (updatedTeammates.some((existing) => existing.url === entry.teammate.url)) {
|
|
@@ -18991,8 +19146,8 @@ class TeamCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
18991
19146
|
return this.appendToSystemMessage({
|
|
18992
19147
|
...requirements,
|
|
18993
19148
|
tools: updatedTools,
|
|
18994
|
-
|
|
18995
|
-
...requirements.
|
|
19149
|
+
_metadata: {
|
|
19150
|
+
...requirements._metadata,
|
|
18996
19151
|
teammates: updatedTeammates,
|
|
18997
19152
|
},
|
|
18998
19153
|
}, teamSystemMessage);
|
|
@@ -19092,11 +19247,16 @@ function createTeamToolFunction(entry) {
|
|
|
19092
19247
|
const request = buildTeammateRequest(message, args.context);
|
|
19093
19248
|
let response = '';
|
|
19094
19249
|
let error = null;
|
|
19250
|
+
let toolCalls;
|
|
19095
19251
|
try {
|
|
19096
19252
|
const remoteAgent = await getRemoteTeammateAgent(entry.teammate.url);
|
|
19097
19253
|
const prompt = buildTeammatePrompt(request);
|
|
19098
19254
|
const teammateResult = await remoteAgent.callChatModel(prompt);
|
|
19099
19255
|
response = teammateResult.content || '';
|
|
19256
|
+
toolCalls =
|
|
19257
|
+
'toolCalls' in teammateResult && Array.isArray(teammateResult.toolCalls)
|
|
19258
|
+
? teammateResult.toolCalls
|
|
19259
|
+
: undefined;
|
|
19100
19260
|
}
|
|
19101
19261
|
catch (err) {
|
|
19102
19262
|
error = err instanceof Error ? err.message : String(err);
|
|
@@ -19106,6 +19266,7 @@ function createTeamToolFunction(entry) {
|
|
|
19106
19266
|
teammate: teammateMetadata,
|
|
19107
19267
|
request,
|
|
19108
19268
|
response: teammateReply,
|
|
19269
|
+
toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,
|
|
19109
19270
|
error,
|
|
19110
19271
|
conversation: [
|
|
19111
19272
|
{
|
|
@@ -19218,7 +19379,7 @@ class TemplateCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19218
19379
|
if (!trimmedContent) {
|
|
19219
19380
|
// Store template mode flag in metadata
|
|
19220
19381
|
const updatedMetadata = {
|
|
19221
|
-
...requirements.
|
|
19382
|
+
...requirements._metadata,
|
|
19222
19383
|
templateMode: true,
|
|
19223
19384
|
};
|
|
19224
19385
|
// Add a general instruction about using structured templates
|
|
@@ -19228,21 +19389,21 @@ class TemplateCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19228
19389
|
`);
|
|
19229
19390
|
return {
|
|
19230
19391
|
...this.appendToSystemMessage(requirements, templateModeInstruction, '\n\n'),
|
|
19231
|
-
|
|
19392
|
+
_metadata: updatedMetadata,
|
|
19232
19393
|
};
|
|
19233
19394
|
}
|
|
19234
19395
|
// If content is provided, add the specific template instructions
|
|
19235
19396
|
const templateSection = `Response Template: ${trimmedContent}`;
|
|
19236
19397
|
// Store the template in metadata for potential programmatic access
|
|
19237
|
-
const existingTemplates = ((_a = requirements.
|
|
19398
|
+
const existingTemplates = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.templates) || [];
|
|
19238
19399
|
const updatedMetadata = {
|
|
19239
|
-
...requirements.
|
|
19400
|
+
...requirements._metadata,
|
|
19240
19401
|
templates: [...existingTemplates, trimmedContent],
|
|
19241
19402
|
templateMode: true,
|
|
19242
19403
|
};
|
|
19243
19404
|
return {
|
|
19244
19405
|
...this.appendToSystemMessage(requirements, templateSection, '\n\n'),
|
|
19245
|
-
|
|
19406
|
+
_metadata: updatedMetadata,
|
|
19246
19407
|
};
|
|
19247
19408
|
}
|
|
19248
19409
|
}
|
|
@@ -19579,8 +19740,8 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19579
19740
|
return this.appendToSystemMessage({
|
|
19580
19741
|
...requirements,
|
|
19581
19742
|
tools: updatedTools,
|
|
19582
|
-
|
|
19583
|
-
...requirements.
|
|
19743
|
+
_metadata: {
|
|
19744
|
+
...requirements._metadata,
|
|
19584
19745
|
useBrowser: true,
|
|
19585
19746
|
},
|
|
19586
19747
|
}, spaceTrim$1(`
|
|
@@ -19809,8 +19970,8 @@ class UseEmailCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19809
19970
|
return this.appendToSystemMessage({
|
|
19810
19971
|
...requirements,
|
|
19811
19972
|
tools: updatedTools,
|
|
19812
|
-
|
|
19813
|
-
...requirements.
|
|
19973
|
+
_metadata: {
|
|
19974
|
+
...requirements._metadata,
|
|
19814
19975
|
useEmail: content || true,
|
|
19815
19976
|
},
|
|
19816
19977
|
}, spaceTrim$1((block) => `
|
|
@@ -19945,8 +20106,8 @@ class UseImageGeneratorCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
19945
20106
|
return this.appendToSystemMessage({
|
|
19946
20107
|
...requirements,
|
|
19947
20108
|
tools: updatedTools,
|
|
19948
|
-
|
|
19949
|
-
...requirements.
|
|
20109
|
+
_metadata: {
|
|
20110
|
+
...requirements._metadata,
|
|
19950
20111
|
useImageGenerator: content || true,
|
|
19951
20112
|
},
|
|
19952
20113
|
}, spaceTrim$1(`
|
|
@@ -20237,8 +20398,8 @@ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
20237
20398
|
return this.appendToSystemMessage({
|
|
20238
20399
|
...requirements,
|
|
20239
20400
|
tools: updatedTools,
|
|
20240
|
-
|
|
20241
|
-
...requirements.
|
|
20401
|
+
_metadata: {
|
|
20402
|
+
...requirements._metadata,
|
|
20242
20403
|
useSearchEngine: content || true,
|
|
20243
20404
|
},
|
|
20244
20405
|
}, spaceTrim$1((block) => `
|
|
@@ -20386,8 +20547,8 @@ class UseTimeCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
20386
20547
|
return this.appendToSystemMessage({
|
|
20387
20548
|
...requirements,
|
|
20388
20549
|
tools: updatedTools,
|
|
20389
|
-
|
|
20390
|
-
...requirements.
|
|
20550
|
+
_metadata: {
|
|
20551
|
+
...requirements._metadata,
|
|
20391
20552
|
},
|
|
20392
20553
|
}, spaceTrim$1((block) => `
|
|
20393
20554
|
Time and date context:
|
|
@@ -24965,6 +25126,66 @@ const OPENAI_MODELS = exportJson({
|
|
|
24965
25126
|
},
|
|
24966
25127
|
/**/
|
|
24967
25128
|
/**/
|
|
25129
|
+
{
|
|
25130
|
+
modelVariant: 'CHAT',
|
|
25131
|
+
modelTitle: 'gpt-5.2-codex',
|
|
25132
|
+
modelName: 'gpt-5.2-codex',
|
|
25133
|
+
modelDescription: 'High-capability Codex variant tuned for agentic code generation with large contexts and reasoning effort controls. Ideal for long-horizon coding workflows and multi-step reasoning.',
|
|
25134
|
+
pricing: {
|
|
25135
|
+
prompt: pricing(`$1.75 / 1M tokens`),
|
|
25136
|
+
output: pricing(`$14.00 / 1M tokens`),
|
|
25137
|
+
},
|
|
25138
|
+
},
|
|
25139
|
+
/**/
|
|
25140
|
+
/**/
|
|
25141
|
+
{
|
|
25142
|
+
modelVariant: 'CHAT',
|
|
25143
|
+
modelTitle: 'gpt-5.1-codex-max',
|
|
25144
|
+
modelName: 'gpt-5.1-codex-max',
|
|
25145
|
+
modelDescription: 'Premium GPT-5.1 Codex flavor that mirrors gpt-5.1 in capability and pricing while adding Codex tooling optimizations.',
|
|
25146
|
+
pricing: {
|
|
25147
|
+
prompt: pricing(`$1.25 / 1M tokens`),
|
|
25148
|
+
output: pricing(`$10.00 / 1M tokens`),
|
|
25149
|
+
},
|
|
25150
|
+
},
|
|
25151
|
+
/**/
|
|
25152
|
+
/**/
|
|
25153
|
+
{
|
|
25154
|
+
modelVariant: 'CHAT',
|
|
25155
|
+
modelTitle: 'gpt-5.1-codex',
|
|
25156
|
+
modelName: 'gpt-5.1-codex',
|
|
25157
|
+
modelDescription: 'Core GPT-5.1 Codex model focused on agentic coding tasks with a balanced trade-off between reasoning and cost.',
|
|
25158
|
+
pricing: {
|
|
25159
|
+
prompt: pricing(`$1.25 / 1M tokens`),
|
|
25160
|
+
output: pricing(`$10.00 / 1M tokens`),
|
|
25161
|
+
},
|
|
25162
|
+
},
|
|
25163
|
+
/**/
|
|
25164
|
+
/**/
|
|
25165
|
+
{
|
|
25166
|
+
modelVariant: 'CHAT',
|
|
25167
|
+
modelTitle: 'gpt-5.1-codex-mini',
|
|
25168
|
+
modelName: 'gpt-5.1-codex-mini',
|
|
25169
|
+
modelDescription: 'Compact, cost-effective GPT-5.1 Codex variant with a smaller context window ideal for cheap assistant iterations that still require coding awareness.',
|
|
25170
|
+
pricing: {
|
|
25171
|
+
prompt: pricing(`$0.25 / 1M tokens`),
|
|
25172
|
+
output: pricing(`$2.00 / 1M tokens`),
|
|
25173
|
+
},
|
|
25174
|
+
},
|
|
25175
|
+
/**/
|
|
25176
|
+
/**/
|
|
25177
|
+
{
|
|
25178
|
+
modelVariant: 'CHAT',
|
|
25179
|
+
modelTitle: 'gpt-5-codex',
|
|
25180
|
+
modelName: 'gpt-5-codex',
|
|
25181
|
+
modelDescription: 'Legacy GPT-5 Codex model built for agentic coding workloads with the same pricing as GPT-5 and a focus on stability.',
|
|
25182
|
+
pricing: {
|
|
25183
|
+
prompt: pricing(`$1.25 / 1M tokens`),
|
|
25184
|
+
output: pricing(`$10.00 / 1M tokens`),
|
|
25185
|
+
},
|
|
25186
|
+
},
|
|
25187
|
+
/**/
|
|
25188
|
+
/**/
|
|
24968
25189
|
{
|
|
24969
25190
|
modelVariant: 'CHAT',
|
|
24970
25191
|
modelTitle: 'gpt-5-mini',
|
|
@@ -26993,6 +27214,32 @@ function isUnsupportedParameterError(error) {
|
|
|
26993
27214
|
errorMessage.includes('does not support'));
|
|
26994
27215
|
}
|
|
26995
27216
|
|
|
27217
|
+
/**
|
|
27218
|
+
* Provides access to the structured clone implementation when available.
|
|
27219
|
+
*/
|
|
27220
|
+
function getStructuredCloneFunction() {
|
|
27221
|
+
return globalThis.structuredClone;
|
|
27222
|
+
}
|
|
27223
|
+
/**
|
|
27224
|
+
* Checks whether the prompt is a chat prompt that carries file attachments.
|
|
27225
|
+
*/
|
|
27226
|
+
function hasChatPromptFiles(prompt) {
|
|
27227
|
+
return 'files' in prompt && Array.isArray(prompt.files);
|
|
27228
|
+
}
|
|
27229
|
+
/**
|
|
27230
|
+
* Creates a deep copy of the prompt while keeping attached files intact when structured clone is not available.
|
|
27231
|
+
*/
|
|
27232
|
+
function clonePromptPreservingFiles(prompt) {
|
|
27233
|
+
const structuredCloneFn = getStructuredCloneFunction();
|
|
27234
|
+
if (typeof structuredCloneFn === 'function') {
|
|
27235
|
+
return structuredCloneFn(prompt);
|
|
27236
|
+
}
|
|
27237
|
+
const clonedPrompt = JSON.parse(JSON.stringify(prompt));
|
|
27238
|
+
if (hasChatPromptFiles(prompt)) {
|
|
27239
|
+
clonedPrompt.files = prompt.files;
|
|
27240
|
+
}
|
|
27241
|
+
return clonedPrompt;
|
|
27242
|
+
}
|
|
26996
27243
|
/**
|
|
26997
27244
|
* Execution Tools for calling OpenAI API or other OpenAI compatible provider
|
|
26998
27245
|
*
|
|
@@ -27022,16 +27269,11 @@ class OpenAiCompatibleExecutionTools {
|
|
|
27022
27269
|
const openAiOptions = { ...this.options };
|
|
27023
27270
|
delete openAiOptions.isVerbose;
|
|
27024
27271
|
delete openAiOptions.userId;
|
|
27025
|
-
// Enhanced configuration
|
|
27272
|
+
// Enhanced configuration with retries and timeouts.
|
|
27026
27273
|
const enhancedOptions = {
|
|
27027
27274
|
...openAiOptions,
|
|
27028
27275
|
timeout: API_REQUEST_TIMEOUT,
|
|
27029
27276
|
maxRetries: CONNECTION_RETRIES_LIMIT,
|
|
27030
|
-
defaultHeaders: {
|
|
27031
|
-
Connection: 'keep-alive',
|
|
27032
|
-
'Keep-Alive': 'timeout=30, max=100',
|
|
27033
|
-
...openAiOptions.defaultHeaders,
|
|
27034
|
-
},
|
|
27035
27277
|
};
|
|
27036
27278
|
this.client = new OpenAI(enhancedOptions);
|
|
27037
27279
|
}
|
|
@@ -27082,7 +27324,7 @@ class OpenAiCompatibleExecutionTools {
|
|
|
27082
27324
|
*/
|
|
27083
27325
|
async callChatModelStream(prompt, onProgress) {
|
|
27084
27326
|
// Deep clone prompt and modelRequirements to avoid mutation across calls
|
|
27085
|
-
const clonedPrompt =
|
|
27327
|
+
const clonedPrompt = clonePromptPreservingFiles(prompt);
|
|
27086
27328
|
// Use local Set for retried parameters to ensure independence and thread safety
|
|
27087
27329
|
const retriedUnsupportedParameters = new Set();
|
|
27088
27330
|
return this.callChatModelWithRetry(clonedPrompt, clonedPrompt.modelRequirements, [], retriedUnsupportedParameters, onProgress);
|
|
@@ -27109,7 +27351,10 @@ class OpenAiCompatibleExecutionTools {
|
|
|
27109
27351
|
// <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
|
|
27110
27352
|
// <- Note: [🧆]
|
|
27111
27353
|
}; // <- TODO: [💩] Guard here types better
|
|
27112
|
-
if (
|
|
27354
|
+
if (currentModelRequirements.responseFormat !== undefined) {
|
|
27355
|
+
modelSettings.response_format = currentModelRequirements.responseFormat;
|
|
27356
|
+
}
|
|
27357
|
+
else if (format === 'JSON') {
|
|
27113
27358
|
modelSettings.response_format = {
|
|
27114
27359
|
type: 'json_object',
|
|
27115
27360
|
};
|
|
@@ -28322,6 +28567,7 @@ const _OpenAiAssistantMetadataRegistration = $llmToolsMetadataRegister.register(
|
|
|
28322
28567
|
apiKey: 'sk-',
|
|
28323
28568
|
assistantId: 'asst_',
|
|
28324
28569
|
maxRequestsPerMinute: DEFAULT_MAX_REQUESTS_PER_MINUTE,
|
|
28570
|
+
isCreatingNewAssistantsAllowed: false,
|
|
28325
28571
|
},
|
|
28326
28572
|
};
|
|
28327
28573
|
},
|
|
@@ -28416,18 +28662,6 @@ class OpenAiExecutionTools extends OpenAiCompatibleExecutionTools {
|
|
|
28416
28662
|
get profile() {
|
|
28417
28663
|
return OPENAI_PROVIDER_PROFILE;
|
|
28418
28664
|
}
|
|
28419
|
-
/*
|
|
28420
|
-
Note: Commenting this out to avoid circular dependency
|
|
28421
|
-
/**
|
|
28422
|
-
* Create (sub)tools for calling OpenAI API Assistants
|
|
28423
|
-
*
|
|
28424
|
-
* @param assistantId Which assistant to use
|
|
28425
|
-
* @returns Tools for calling OpenAI API Assistants with same token
|
|
28426
|
-
* /
|
|
28427
|
-
public createAssistantSubtools(assistantId: string_token): OpenAiAssistantExecutionTools {
|
|
28428
|
-
return new OpenAiAssistantExecutionTools({ ...this.options, assistantId });
|
|
28429
|
-
}
|
|
28430
|
-
*/
|
|
28431
28665
|
/**
|
|
28432
28666
|
* List all available models (non dynamically)
|
|
28433
28667
|
*
|
|
@@ -28462,6 +28696,775 @@ class OpenAiExecutionTools extends OpenAiCompatibleExecutionTools {
|
|
|
28462
28696
|
}
|
|
28463
28697
|
}
|
|
28464
28698
|
|
|
28699
|
+
const DEFAULT_KNOWLEDGE_SOURCE_DOWNLOAD_TIMEOUT_MS = 30000;
|
|
28700
|
+
const DEFAULT_KNOWLEDGE_SOURCE_UPLOAD_TIMEOUT_MS = 900000;
|
|
28701
|
+
const VECTOR_STORE_PROGRESS_LOG_INTERVAL_MIN_MS = 15000;
|
|
28702
|
+
const VECTOR_STORE_STALL_LOG_THRESHOLD_MS = 30000;
|
|
28703
|
+
/**
|
|
28704
|
+
* Base class for OpenAI execution tools that need hosted vector stores.
|
|
28705
|
+
*
|
|
28706
|
+
* @public exported from `@promptbook/openai`
|
|
28707
|
+
*/
|
|
28708
|
+
class OpenAiVectorStoreHandler extends OpenAiExecutionTools {
|
|
28709
|
+
/**
|
|
28710
|
+
* Returns the per-knowledge-source download timeout in milliseconds.
|
|
28711
|
+
*/
|
|
28712
|
+
getKnowledgeSourceDownloadTimeoutMs() {
|
|
28713
|
+
var _a;
|
|
28714
|
+
return (_a = this.vectorStoreOptions.knowledgeSourceDownloadTimeoutMs) !== null && _a !== void 0 ? _a : DEFAULT_KNOWLEDGE_SOURCE_DOWNLOAD_TIMEOUT_MS;
|
|
28715
|
+
}
|
|
28716
|
+
/**
|
|
28717
|
+
* Returns the max concurrency for knowledge source uploads.
|
|
28718
|
+
*/
|
|
28719
|
+
getKnowledgeSourceUploadMaxConcurrency() {
|
|
28720
|
+
var _a;
|
|
28721
|
+
return (_a = this.vectorStoreOptions.knowledgeSourceUploadMaxConcurrency) !== null && _a !== void 0 ? _a : 5;
|
|
28722
|
+
}
|
|
28723
|
+
/**
|
|
28724
|
+
* Returns the polling interval in milliseconds for vector store uploads.
|
|
28725
|
+
*/
|
|
28726
|
+
getKnowledgeSourceUploadPollIntervalMs() {
|
|
28727
|
+
var _a;
|
|
28728
|
+
return (_a = this.vectorStoreOptions.knowledgeSourceUploadPollIntervalMs) !== null && _a !== void 0 ? _a : 5000;
|
|
28729
|
+
}
|
|
28730
|
+
/**
|
|
28731
|
+
* Returns the overall upload timeout in milliseconds for vector store uploads.
|
|
28732
|
+
*/
|
|
28733
|
+
getKnowledgeSourceUploadTimeoutMs() {
|
|
28734
|
+
var _a;
|
|
28735
|
+
return (_a = this.vectorStoreOptions.knowledgeSourceUploadTimeoutMs) !== null && _a !== void 0 ? _a : DEFAULT_KNOWLEDGE_SOURCE_UPLOAD_TIMEOUT_MS;
|
|
28736
|
+
}
|
|
28737
|
+
/**
|
|
28738
|
+
* Returns true if we should continue even if vector store ingestion stalls.
|
|
28739
|
+
*/
|
|
28740
|
+
shouldContinueOnVectorStoreStall() {
|
|
28741
|
+
var _a;
|
|
28742
|
+
return (_a = this.vectorStoreOptions.shouldContinueOnVectorStoreStall) !== null && _a !== void 0 ? _a : true;
|
|
28743
|
+
}
|
|
28744
|
+
/**
|
|
28745
|
+
* Returns vector-store-specific options with extended settings.
|
|
28746
|
+
*/
|
|
28747
|
+
get vectorStoreOptions() {
|
|
28748
|
+
return this.options;
|
|
28749
|
+
}
|
|
28750
|
+
/**
|
|
28751
|
+
* Returns the OpenAI vector stores API surface, supporting stable and beta SDKs.
|
|
28752
|
+
*/
|
|
28753
|
+
getVectorStoresApi(client) {
|
|
28754
|
+
var _a, _b;
|
|
28755
|
+
const vectorStores = (_a = client.vectorStores) !== null && _a !== void 0 ? _a : (_b = client.beta) === null || _b === void 0 ? void 0 : _b.vectorStores;
|
|
28756
|
+
if (!vectorStores) {
|
|
28757
|
+
throw new Error('OpenAI client does not support vector stores. Please ensure you are using a compatible version of the OpenAI SDK with vector store support.');
|
|
28758
|
+
}
|
|
28759
|
+
return vectorStores;
|
|
28760
|
+
}
|
|
28761
|
+
/**
|
|
28762
|
+
* Downloads a knowledge source URL into a File for vector store upload.
|
|
28763
|
+
*/
|
|
28764
|
+
async downloadKnowledgeSourceFile(options) {
|
|
28765
|
+
var _a;
|
|
28766
|
+
const { source, timeoutMs, logLabel } = options;
|
|
28767
|
+
const startedAtMs = Date.now();
|
|
28768
|
+
const controller = new AbortController();
|
|
28769
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
28770
|
+
if (this.options.isVerbose) {
|
|
28771
|
+
console.info('[🤰]', 'Downloading knowledge source', {
|
|
28772
|
+
source,
|
|
28773
|
+
timeoutMs,
|
|
28774
|
+
logLabel,
|
|
28775
|
+
});
|
|
28776
|
+
}
|
|
28777
|
+
try {
|
|
28778
|
+
const response = await fetch(source, { signal: controller.signal });
|
|
28779
|
+
const contentType = (_a = response.headers.get('content-type')) !== null && _a !== void 0 ? _a : undefined;
|
|
28780
|
+
if (!response.ok) {
|
|
28781
|
+
console.error('[🤰]', 'Failed to download knowledge source', {
|
|
28782
|
+
source,
|
|
28783
|
+
status: response.status,
|
|
28784
|
+
statusText: response.statusText,
|
|
28785
|
+
contentType,
|
|
28786
|
+
elapsedMs: Date.now() - startedAtMs,
|
|
28787
|
+
logLabel,
|
|
28788
|
+
});
|
|
28789
|
+
return null;
|
|
28790
|
+
}
|
|
28791
|
+
const buffer = await response.arrayBuffer();
|
|
28792
|
+
let filename = source.split('/').pop() || 'downloaded-file';
|
|
28793
|
+
try {
|
|
28794
|
+
const url = new URL(source);
|
|
28795
|
+
filename = url.pathname.split('/').pop() || filename;
|
|
28796
|
+
}
|
|
28797
|
+
catch (error) {
|
|
28798
|
+
// Keep default filename
|
|
28799
|
+
}
|
|
28800
|
+
const file = new File([buffer], filename, contentType ? { type: contentType } : undefined);
|
|
28801
|
+
const elapsedMs = Date.now() - startedAtMs;
|
|
28802
|
+
const sizeBytes = buffer.byteLength;
|
|
28803
|
+
if (this.options.isVerbose) {
|
|
28804
|
+
console.info('[🤰]', 'Downloaded knowledge source', {
|
|
28805
|
+
source,
|
|
28806
|
+
filename,
|
|
28807
|
+
sizeBytes,
|
|
28808
|
+
contentType,
|
|
28809
|
+
elapsedMs,
|
|
28810
|
+
logLabel,
|
|
28811
|
+
});
|
|
28812
|
+
}
|
|
28813
|
+
return { file, sizeBytes, filename, elapsedMs };
|
|
28814
|
+
}
|
|
28815
|
+
catch (error) {
|
|
28816
|
+
assertsError(error);
|
|
28817
|
+
console.error('[🤰]', 'Error downloading knowledge source', {
|
|
28818
|
+
source,
|
|
28819
|
+
elapsedMs: Date.now() - startedAtMs,
|
|
28820
|
+
logLabel,
|
|
28821
|
+
error: serializeError(error),
|
|
28822
|
+
});
|
|
28823
|
+
return null;
|
|
28824
|
+
}
|
|
28825
|
+
finally {
|
|
28826
|
+
clearTimeout(timeoutId);
|
|
28827
|
+
}
|
|
28828
|
+
}
|
|
28829
|
+
/**
|
|
28830
|
+
* Logs vector store file batch diagnostics to help trace ingestion stalls or failures.
|
|
28831
|
+
*/
|
|
28832
|
+
async logVectorStoreFileBatchDiagnostics(options) {
|
|
28833
|
+
var _a, _b, _c, _d, _e;
|
|
28834
|
+
const { client, vectorStoreId, batchId, uploadedFiles, logLabel, reason } = options;
|
|
28835
|
+
if (reason === 'stalled' && !this.options.isVerbose) {
|
|
28836
|
+
return;
|
|
28837
|
+
}
|
|
28838
|
+
if (!batchId.startsWith('vsfb_')) {
|
|
28839
|
+
console.error('[🤰]', 'Vector store file batch diagnostics skipped (invalid batch id)', {
|
|
28840
|
+
vectorStoreId,
|
|
28841
|
+
batchId,
|
|
28842
|
+
reason,
|
|
28843
|
+
logLabel,
|
|
28844
|
+
});
|
|
28845
|
+
return;
|
|
28846
|
+
}
|
|
28847
|
+
const fileIdToMetadata = new Map();
|
|
28848
|
+
for (const file of uploadedFiles) {
|
|
28849
|
+
fileIdToMetadata.set(file.fileId, file);
|
|
28850
|
+
}
|
|
28851
|
+
try {
|
|
28852
|
+
const vectorStores = this.getVectorStoresApi(client);
|
|
28853
|
+
const limit = Math.min(100, Math.max(10, uploadedFiles.length));
|
|
28854
|
+
const batchFilesPage = await vectorStores.fileBatches.listFiles(batchId, {
|
|
28855
|
+
vector_store_id: vectorStoreId,
|
|
28856
|
+
limit,
|
|
28857
|
+
});
|
|
28858
|
+
const batchFiles = (_a = batchFilesPage.data) !== null && _a !== void 0 ? _a : [];
|
|
28859
|
+
const statusCounts = {
|
|
28860
|
+
in_progress: 0,
|
|
28861
|
+
completed: 0,
|
|
28862
|
+
failed: 0,
|
|
28863
|
+
cancelled: 0,
|
|
28864
|
+
};
|
|
28865
|
+
const errorSamples = [];
|
|
28866
|
+
const inProgressSamples = [];
|
|
28867
|
+
const batchFileIds = new Set();
|
|
28868
|
+
for (const file of batchFiles) {
|
|
28869
|
+
const status = (_b = file.status) !== null && _b !== void 0 ? _b : 'unknown';
|
|
28870
|
+
statusCounts[status] = ((_c = statusCounts[status]) !== null && _c !== void 0 ? _c : 0) + 1;
|
|
28871
|
+
const vectorStoreFileId = file.id;
|
|
28872
|
+
const uploadedFileId = (_d = file.file_id) !== null && _d !== void 0 ? _d : file.fileId;
|
|
28873
|
+
const fileId = uploadedFileId !== null && uploadedFileId !== void 0 ? uploadedFileId : vectorStoreFileId;
|
|
28874
|
+
batchFileIds.add(fileId);
|
|
28875
|
+
const metadata = fileIdToMetadata.get(fileId);
|
|
28876
|
+
if (status === 'failed') {
|
|
28877
|
+
errorSamples.push({
|
|
28878
|
+
fileId,
|
|
28879
|
+
status,
|
|
28880
|
+
error: (_e = file.last_error) === null || _e === void 0 ? void 0 : _e.message,
|
|
28881
|
+
filename: metadata === null || metadata === void 0 ? void 0 : metadata.filename,
|
|
28882
|
+
vectorStoreFileId: uploadedFileId ? vectorStoreFileId : undefined,
|
|
28883
|
+
});
|
|
28884
|
+
}
|
|
28885
|
+
if (status === 'in_progress') {
|
|
28886
|
+
inProgressSamples.push({
|
|
28887
|
+
fileId,
|
|
28888
|
+
filename: metadata === null || metadata === void 0 ? void 0 : metadata.filename,
|
|
28889
|
+
vectorStoreFileId: uploadedFileId ? vectorStoreFileId : undefined,
|
|
28890
|
+
});
|
|
28891
|
+
}
|
|
28892
|
+
}
|
|
28893
|
+
const missingSamples = uploadedFiles
|
|
28894
|
+
.filter((file) => !batchFileIds.has(file.fileId))
|
|
28895
|
+
.slice(0, 5)
|
|
28896
|
+
.map((file) => ({
|
|
28897
|
+
fileId: file.fileId,
|
|
28898
|
+
filename: file.filename,
|
|
28899
|
+
sizeBytes: file.sizeBytes,
|
|
28900
|
+
}));
|
|
28901
|
+
const vectorStore = await vectorStores.retrieve(vectorStoreId);
|
|
28902
|
+
const logPayload = {
|
|
28903
|
+
vectorStoreId,
|
|
28904
|
+
batchId,
|
|
28905
|
+
reason,
|
|
28906
|
+
vectorStoreStatus: vectorStore.status,
|
|
28907
|
+
vectorStoreFileCounts: vectorStore.file_counts,
|
|
28908
|
+
vectorStoreUsageBytes: vectorStore.usage_bytes,
|
|
28909
|
+
batchFileCount: batchFiles.length,
|
|
28910
|
+
statusCounts,
|
|
28911
|
+
errorSamples: errorSamples.slice(0, 5),
|
|
28912
|
+
inProgressSamples,
|
|
28913
|
+
missingFileCount: uploadedFiles.length - batchFileIds.size,
|
|
28914
|
+
missingSamples,
|
|
28915
|
+
logLabel,
|
|
28916
|
+
};
|
|
28917
|
+
const logFunction = reason === 'stalled' ? console.info : console.error;
|
|
28918
|
+
logFunction('[🤰]', 'Vector store file batch diagnostics', logPayload);
|
|
28919
|
+
}
|
|
28920
|
+
catch (error) {
|
|
28921
|
+
assertsError(error);
|
|
28922
|
+
console.error('[🤰]', 'Vector store file batch diagnostics failed', {
|
|
28923
|
+
vectorStoreId,
|
|
28924
|
+
batchId,
|
|
28925
|
+
reason,
|
|
28926
|
+
logLabel,
|
|
28927
|
+
error: serializeError(error),
|
|
28928
|
+
});
|
|
28929
|
+
}
|
|
28930
|
+
}
|
|
28931
|
+
/**
|
|
28932
|
+
* Uploads knowledge source files to the vector store and polls until processing completes.
|
|
28933
|
+
*/
|
|
28934
|
+
async uploadKnowledgeSourceFilesToVectorStore(options) {
|
|
28935
|
+
var _a, _b, _c, _d, _e, _f;
|
|
28936
|
+
const { client, vectorStoreId, files, totalBytes, logLabel } = options;
|
|
28937
|
+
const vectorStores = this.getVectorStoresApi(client);
|
|
28938
|
+
const uploadStartedAtMs = Date.now();
|
|
28939
|
+
const maxConcurrency = Math.max(1, this.getKnowledgeSourceUploadMaxConcurrency());
|
|
28940
|
+
const pollIntervalMs = Math.max(1000, this.getKnowledgeSourceUploadPollIntervalMs());
|
|
28941
|
+
const uploadTimeoutMs = Math.max(1000, this.getKnowledgeSourceUploadTimeoutMs());
|
|
28942
|
+
if (this.options.isVerbose) {
|
|
28943
|
+
console.info('[🤰]', 'Uploading knowledge source files to OpenAI', {
|
|
28944
|
+
vectorStoreId,
|
|
28945
|
+
fileCount: files.length,
|
|
28946
|
+
totalBytes,
|
|
28947
|
+
maxConcurrency,
|
|
28948
|
+
pollIntervalMs,
|
|
28949
|
+
uploadTimeoutMs,
|
|
28950
|
+
logLabel,
|
|
28951
|
+
});
|
|
28952
|
+
}
|
|
28953
|
+
const fileTypeSummary = {};
|
|
28954
|
+
for (const file of files) {
|
|
28955
|
+
const filename = (_a = file.name) !== null && _a !== void 0 ? _a : '';
|
|
28956
|
+
const extension = filename.includes('.')
|
|
28957
|
+
? (_c = (_b = filename.split('.').pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase()) !== null && _c !== void 0 ? _c : 'unknown'
|
|
28958
|
+
: 'unknown';
|
|
28959
|
+
const sizeBytes = typeof file.size === 'number' ? file.size : 0;
|
|
28960
|
+
const summary = (_d = fileTypeSummary[extension]) !== null && _d !== void 0 ? _d : { count: 0, totalBytes: 0 };
|
|
28961
|
+
summary.count += 1;
|
|
28962
|
+
summary.totalBytes += sizeBytes;
|
|
28963
|
+
fileTypeSummary[extension] = summary;
|
|
28964
|
+
}
|
|
28965
|
+
if (this.options.isVerbose) {
|
|
28966
|
+
console.info('[🤰]', 'Knowledge source file summary', {
|
|
28967
|
+
vectorStoreId,
|
|
28968
|
+
fileCount: files.length,
|
|
28969
|
+
totalBytes,
|
|
28970
|
+
fileTypeSummary,
|
|
28971
|
+
logLabel,
|
|
28972
|
+
});
|
|
28973
|
+
}
|
|
28974
|
+
const fileEntries = files.map((file, index) => ({ file, index }));
|
|
28975
|
+
const fileIterator = fileEntries.values();
|
|
28976
|
+
const fileIds = [];
|
|
28977
|
+
const uploadedFiles = [];
|
|
28978
|
+
const failedUploads = [];
|
|
28979
|
+
let uploadedCount = 0;
|
|
28980
|
+
const processFiles = async (iterator) => {
|
|
28981
|
+
var _a, _b;
|
|
28982
|
+
for (const { file, index } of iterator) {
|
|
28983
|
+
const uploadIndex = index + 1;
|
|
28984
|
+
const filename = file.name || `knowledge-source-${uploadIndex}`;
|
|
28985
|
+
const extension = filename.includes('.')
|
|
28986
|
+
? (_b = (_a = filename.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'unknown'
|
|
28987
|
+
: 'unknown';
|
|
28988
|
+
const sizeBytes = typeof file.size === 'number' ? file.size : undefined;
|
|
28989
|
+
const fileUploadStartedAtMs = Date.now();
|
|
28990
|
+
if (this.options.isVerbose) {
|
|
28991
|
+
console.info('[🤰]', 'Uploading knowledge source file', {
|
|
28992
|
+
index: uploadIndex,
|
|
28993
|
+
total: files.length,
|
|
28994
|
+
filename,
|
|
28995
|
+
extension,
|
|
28996
|
+
sizeBytes,
|
|
28997
|
+
logLabel,
|
|
28998
|
+
});
|
|
28999
|
+
}
|
|
29000
|
+
try {
|
|
29001
|
+
const uploaded = await client.files.create({ file, purpose: 'assistants' });
|
|
29002
|
+
fileIds.push(uploaded.id);
|
|
29003
|
+
uploadedFiles.push({ fileId: uploaded.id, filename, sizeBytes });
|
|
29004
|
+
uploadedCount += 1;
|
|
29005
|
+
if (this.options.isVerbose) {
|
|
29006
|
+
console.info('[🤰]', 'Uploaded knowledge source file', {
|
|
29007
|
+
index: uploadIndex,
|
|
29008
|
+
total: files.length,
|
|
29009
|
+
filename,
|
|
29010
|
+
sizeBytes,
|
|
29011
|
+
fileId: uploaded.id,
|
|
29012
|
+
elapsedMs: Date.now() - fileUploadStartedAtMs,
|
|
29013
|
+
logLabel,
|
|
29014
|
+
});
|
|
29015
|
+
}
|
|
29016
|
+
}
|
|
29017
|
+
catch (error) {
|
|
29018
|
+
assertsError(error);
|
|
29019
|
+
const serializedError = serializeError(error);
|
|
29020
|
+
failedUploads.push({ index: uploadIndex, filename, error: serializedError });
|
|
29021
|
+
console.error('[🤰]', 'Failed to upload knowledge source file', {
|
|
29022
|
+
index: uploadIndex,
|
|
29023
|
+
total: files.length,
|
|
29024
|
+
filename,
|
|
29025
|
+
sizeBytes,
|
|
29026
|
+
elapsedMs: Date.now() - fileUploadStartedAtMs,
|
|
29027
|
+
logLabel,
|
|
29028
|
+
error: serializedError,
|
|
29029
|
+
});
|
|
29030
|
+
}
|
|
29031
|
+
}
|
|
29032
|
+
};
|
|
29033
|
+
const workerCount = Math.min(maxConcurrency, files.length);
|
|
29034
|
+
const workers = Array.from({ length: workerCount }, () => processFiles(fileIterator));
|
|
29035
|
+
await Promise.all(workers);
|
|
29036
|
+
if (this.options.isVerbose) {
|
|
29037
|
+
console.info('[🤰]', 'Finished uploading knowledge source files', {
|
|
29038
|
+
vectorStoreId,
|
|
29039
|
+
fileCount: files.length,
|
|
29040
|
+
uploadedCount,
|
|
29041
|
+
failedCount: failedUploads.length,
|
|
29042
|
+
elapsedMs: Date.now() - uploadStartedAtMs,
|
|
29043
|
+
failedSamples: failedUploads.slice(0, 3),
|
|
29044
|
+
logLabel,
|
|
29045
|
+
});
|
|
29046
|
+
}
|
|
29047
|
+
if (fileIds.length === 0) {
|
|
29048
|
+
console.error('[🤰]', 'No knowledge source files were uploaded', {
|
|
29049
|
+
vectorStoreId,
|
|
29050
|
+
fileCount: files.length,
|
|
29051
|
+
failedCount: failedUploads.length,
|
|
29052
|
+
logLabel,
|
|
29053
|
+
});
|
|
29054
|
+
return null;
|
|
29055
|
+
}
|
|
29056
|
+
const batch = await vectorStores.fileBatches.create(vectorStoreId, {
|
|
29057
|
+
file_ids: fileIds,
|
|
29058
|
+
});
|
|
29059
|
+
const expectedBatchId = batch.id;
|
|
29060
|
+
const expectedBatchIdValid = expectedBatchId.startsWith('vsfb_');
|
|
29061
|
+
if (!expectedBatchIdValid) {
|
|
29062
|
+
console.error('[🤰]', 'Vector store file batch id looks invalid', {
|
|
29063
|
+
vectorStoreId,
|
|
29064
|
+
batchId: expectedBatchId,
|
|
29065
|
+
batchVectorStoreId: batch.vector_store_id,
|
|
29066
|
+
logLabel,
|
|
29067
|
+
});
|
|
29068
|
+
}
|
|
29069
|
+
else if (batch.vector_store_id !== vectorStoreId) {
|
|
29070
|
+
console.error('[🤰]', 'Vector store file batch vector store id mismatch', {
|
|
29071
|
+
vectorStoreId,
|
|
29072
|
+
batchId: expectedBatchId,
|
|
29073
|
+
batchVectorStoreId: batch.vector_store_id,
|
|
29074
|
+
logLabel,
|
|
29075
|
+
});
|
|
29076
|
+
}
|
|
29077
|
+
if (this.options.isVerbose) {
|
|
29078
|
+
console.info('[🤰]', 'Created vector store file batch', {
|
|
29079
|
+
vectorStoreId,
|
|
29080
|
+
batchId: expectedBatchId,
|
|
29081
|
+
fileCount: fileIds.length,
|
|
29082
|
+
logLabel,
|
|
29083
|
+
});
|
|
29084
|
+
}
|
|
29085
|
+
const pollStartedAtMs = Date.now();
|
|
29086
|
+
const progressLogIntervalMs = Math.max(VECTOR_STORE_PROGRESS_LOG_INTERVAL_MIN_MS, pollIntervalMs);
|
|
29087
|
+
const diagnosticsIntervalMs = Math.max(60000, pollIntervalMs * 5);
|
|
29088
|
+
// let lastStatus: string | undefined;
|
|
29089
|
+
let lastCountsKey = '';
|
|
29090
|
+
let lastProgressKey = '';
|
|
29091
|
+
let lastLogAtMs = 0;
|
|
29092
|
+
let lastProgressAtMs = pollStartedAtMs;
|
|
29093
|
+
let lastDiagnosticsAtMs = pollStartedAtMs;
|
|
29094
|
+
let latestBatch = batch;
|
|
29095
|
+
let loggedBatchIdMismatch = false;
|
|
29096
|
+
let loggedBatchIdFallback = false;
|
|
29097
|
+
let loggedBatchIdInvalid = false;
|
|
29098
|
+
let shouldPoll = true;
|
|
29099
|
+
while (shouldPoll) {
|
|
29100
|
+
const nowMs = Date.now();
|
|
29101
|
+
// [🤰] Note: Sometimes OpenAI returns Vector Store object instead of Batch object, or IDs get swapped.
|
|
29102
|
+
const rawBatchId = typeof latestBatch.id === 'string' ? latestBatch.id : '';
|
|
29103
|
+
const rawVectorStoreId = latestBatch.vector_store_id;
|
|
29104
|
+
let returnedBatchId = rawBatchId;
|
|
29105
|
+
let returnedBatchIdValid = typeof returnedBatchId === 'string' && returnedBatchId.startsWith('vsfb_');
|
|
29106
|
+
if (!returnedBatchIdValid && expectedBatchIdValid) {
|
|
29107
|
+
if (!loggedBatchIdFallback) {
|
|
29108
|
+
console.error('[🤰]', 'Vector store file batch id missing from response; falling back to expected', {
|
|
29109
|
+
vectorStoreId,
|
|
29110
|
+
expectedBatchId,
|
|
29111
|
+
returnedBatchId,
|
|
29112
|
+
rawVectorStoreId,
|
|
29113
|
+
logLabel,
|
|
29114
|
+
});
|
|
29115
|
+
loggedBatchIdFallback = true;
|
|
29116
|
+
}
|
|
29117
|
+
returnedBatchId = expectedBatchId;
|
|
29118
|
+
returnedBatchIdValid = true;
|
|
29119
|
+
}
|
|
29120
|
+
if (!returnedBatchIdValid && !loggedBatchIdInvalid) {
|
|
29121
|
+
console.error('[🤰]', 'Vector store file batch id is invalid; stopping polling', {
|
|
29122
|
+
vectorStoreId,
|
|
29123
|
+
expectedBatchId,
|
|
29124
|
+
returnedBatchId,
|
|
29125
|
+
rawVectorStoreId,
|
|
29126
|
+
logLabel,
|
|
29127
|
+
});
|
|
29128
|
+
loggedBatchIdInvalid = true;
|
|
29129
|
+
}
|
|
29130
|
+
const batchIdMismatch = expectedBatchIdValid && returnedBatchIdValid && returnedBatchId !== expectedBatchId;
|
|
29131
|
+
if (batchIdMismatch && !loggedBatchIdMismatch) {
|
|
29132
|
+
console.error('[🤰]', 'Vector store file batch id mismatch', {
|
|
29133
|
+
vectorStoreId,
|
|
29134
|
+
expectedBatchId,
|
|
29135
|
+
returnedBatchId,
|
|
29136
|
+
logLabel,
|
|
29137
|
+
});
|
|
29138
|
+
loggedBatchIdMismatch = true;
|
|
29139
|
+
}
|
|
29140
|
+
if (returnedBatchIdValid) {
|
|
29141
|
+
latestBatch = await vectorStores.fileBatches.retrieve(returnedBatchId, {
|
|
29142
|
+
vector_store_id: vectorStoreId,
|
|
29143
|
+
});
|
|
29144
|
+
}
|
|
29145
|
+
else {
|
|
29146
|
+
shouldPoll = false;
|
|
29147
|
+
continue;
|
|
29148
|
+
}
|
|
29149
|
+
const status = (_e = latestBatch.status) !== null && _e !== void 0 ? _e : 'unknown';
|
|
29150
|
+
const fileCounts = (_f = latestBatch.file_counts) !== null && _f !== void 0 ? _f : {};
|
|
29151
|
+
const progressKey = JSON.stringify(fileCounts);
|
|
29152
|
+
const statusCountsKey = `${status}-${progressKey}`;
|
|
29153
|
+
const isProgressing = progressKey !== lastProgressKey;
|
|
29154
|
+
if (isProgressing) {
|
|
29155
|
+
lastProgressAtMs = nowMs;
|
|
29156
|
+
lastProgressKey = progressKey;
|
|
29157
|
+
}
|
|
29158
|
+
if (this.options.isVerbose &&
|
|
29159
|
+
(statusCountsKey !== lastCountsKey || nowMs - lastLogAtMs >= progressLogIntervalMs)) {
|
|
29160
|
+
console.info('[🤰]', 'Vector store file batch status', {
|
|
29161
|
+
vectorStoreId,
|
|
29162
|
+
batchId: returnedBatchId,
|
|
29163
|
+
status,
|
|
29164
|
+
fileCounts,
|
|
29165
|
+
elapsedMs: nowMs - pollStartedAtMs,
|
|
29166
|
+
logLabel,
|
|
29167
|
+
});
|
|
29168
|
+
lastCountsKey = statusCountsKey;
|
|
29169
|
+
lastLogAtMs = nowMs;
|
|
29170
|
+
}
|
|
29171
|
+
if (status === 'in_progress' &&
|
|
29172
|
+
nowMs - lastProgressAtMs >= VECTOR_STORE_STALL_LOG_THRESHOLD_MS &&
|
|
29173
|
+
nowMs - lastDiagnosticsAtMs >= diagnosticsIntervalMs) {
|
|
29174
|
+
lastDiagnosticsAtMs = nowMs;
|
|
29175
|
+
await this.logVectorStoreFileBatchDiagnostics({
|
|
29176
|
+
client,
|
|
29177
|
+
vectorStoreId,
|
|
29178
|
+
batchId: returnedBatchId,
|
|
29179
|
+
uploadedFiles,
|
|
29180
|
+
logLabel,
|
|
29181
|
+
reason: 'stalled',
|
|
29182
|
+
});
|
|
29183
|
+
}
|
|
29184
|
+
if (status === 'completed') {
|
|
29185
|
+
if (this.options.isVerbose) {
|
|
29186
|
+
console.info('[🤰]', 'Vector store file batch completed', {
|
|
29187
|
+
vectorStoreId,
|
|
29188
|
+
batchId: returnedBatchId,
|
|
29189
|
+
fileCounts,
|
|
29190
|
+
elapsedMs: nowMs - pollStartedAtMs,
|
|
29191
|
+
logLabel,
|
|
29192
|
+
});
|
|
29193
|
+
}
|
|
29194
|
+
shouldPoll = false;
|
|
29195
|
+
continue;
|
|
29196
|
+
}
|
|
29197
|
+
if (status === 'failed') {
|
|
29198
|
+
console.error('[🤰]', 'Vector store file batch completed with failures', {
|
|
29199
|
+
vectorStoreId,
|
|
29200
|
+
batchId: returnedBatchId,
|
|
29201
|
+
fileCounts,
|
|
29202
|
+
elapsedMs: nowMs - pollStartedAtMs,
|
|
29203
|
+
logLabel,
|
|
29204
|
+
});
|
|
29205
|
+
await this.logVectorStoreFileBatchDiagnostics({
|
|
29206
|
+
client,
|
|
29207
|
+
vectorStoreId,
|
|
29208
|
+
batchId: returnedBatchId,
|
|
29209
|
+
uploadedFiles,
|
|
29210
|
+
logLabel,
|
|
29211
|
+
reason: 'failed',
|
|
29212
|
+
});
|
|
29213
|
+
shouldPoll = false;
|
|
29214
|
+
continue;
|
|
29215
|
+
}
|
|
29216
|
+
if (status === 'cancelled') {
|
|
29217
|
+
console.error('[🤰]', 'Vector store file batch did not complete', {
|
|
29218
|
+
vectorStoreId,
|
|
29219
|
+
batchId: returnedBatchId,
|
|
29220
|
+
status,
|
|
29221
|
+
fileCounts,
|
|
29222
|
+
elapsedMs: nowMs - pollStartedAtMs,
|
|
29223
|
+
logLabel,
|
|
29224
|
+
});
|
|
29225
|
+
await this.logVectorStoreFileBatchDiagnostics({
|
|
29226
|
+
client,
|
|
29227
|
+
vectorStoreId,
|
|
29228
|
+
batchId: returnedBatchId,
|
|
29229
|
+
uploadedFiles,
|
|
29230
|
+
logLabel,
|
|
29231
|
+
reason: 'failed',
|
|
29232
|
+
});
|
|
29233
|
+
shouldPoll = false;
|
|
29234
|
+
continue;
|
|
29235
|
+
}
|
|
29236
|
+
if (nowMs - pollStartedAtMs >= uploadTimeoutMs) {
|
|
29237
|
+
console.error('[🤰]', 'Timed out waiting for vector store file batch', {
|
|
29238
|
+
vectorStoreId,
|
|
29239
|
+
batchId: returnedBatchId,
|
|
29240
|
+
fileCounts,
|
|
29241
|
+
elapsedMs: nowMs - pollStartedAtMs,
|
|
29242
|
+
uploadTimeoutMs,
|
|
29243
|
+
logLabel,
|
|
29244
|
+
});
|
|
29245
|
+
await this.logVectorStoreFileBatchDiagnostics({
|
|
29246
|
+
client,
|
|
29247
|
+
vectorStoreId,
|
|
29248
|
+
batchId: returnedBatchId,
|
|
29249
|
+
uploadedFiles,
|
|
29250
|
+
logLabel,
|
|
29251
|
+
reason: 'timeout',
|
|
29252
|
+
});
|
|
29253
|
+
if (this.shouldContinueOnVectorStoreStall()) {
|
|
29254
|
+
console.warn('[🤰]', 'Continuing despite vector store timeout as requested', {
|
|
29255
|
+
vectorStoreId,
|
|
29256
|
+
logLabel,
|
|
29257
|
+
});
|
|
29258
|
+
shouldPoll = false;
|
|
29259
|
+
continue;
|
|
29260
|
+
}
|
|
29261
|
+
try {
|
|
29262
|
+
const cancelBatchId = batchIdMismatch && returnedBatchId.startsWith('vsfb_') ? returnedBatchId : expectedBatchId;
|
|
29263
|
+
if (!cancelBatchId.startsWith('vsfb_')) {
|
|
29264
|
+
console.error('[🤰]', 'Skipping vector store file batch cancel (invalid batch id)', {
|
|
29265
|
+
vectorStoreId,
|
|
29266
|
+
batchId: cancelBatchId,
|
|
29267
|
+
logLabel,
|
|
29268
|
+
});
|
|
29269
|
+
}
|
|
29270
|
+
else {
|
|
29271
|
+
await vectorStores.fileBatches.cancel(cancelBatchId, {
|
|
29272
|
+
vector_store_id: vectorStoreId,
|
|
29273
|
+
});
|
|
29274
|
+
}
|
|
29275
|
+
if (this.options.isVerbose) {
|
|
29276
|
+
console.info('[🤰]', 'Cancelled vector store file batch after timeout', {
|
|
29277
|
+
vectorStoreId,
|
|
29278
|
+
batchId: batchIdMismatch && returnedBatchId.startsWith('vsfb_')
|
|
29279
|
+
? returnedBatchId
|
|
29280
|
+
: expectedBatchId,
|
|
29281
|
+
...(batchIdMismatch ? { returnedBatchId } : {}),
|
|
29282
|
+
logLabel,
|
|
29283
|
+
});
|
|
29284
|
+
}
|
|
29285
|
+
}
|
|
29286
|
+
catch (error) {
|
|
29287
|
+
assertsError(error);
|
|
29288
|
+
console.error('[🤰]', 'Failed to cancel vector store file batch after timeout', {
|
|
29289
|
+
vectorStoreId,
|
|
29290
|
+
batchId: expectedBatchId,
|
|
29291
|
+
...(batchIdMismatch ? { returnedBatchId } : {}),
|
|
29292
|
+
logLabel,
|
|
29293
|
+
error: serializeError(error),
|
|
29294
|
+
});
|
|
29295
|
+
}
|
|
29296
|
+
shouldPoll = false;
|
|
29297
|
+
continue;
|
|
29298
|
+
}
|
|
29299
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
29300
|
+
}
|
|
29301
|
+
return latestBatch;
|
|
29302
|
+
}
|
|
29303
|
+
/**
|
|
29304
|
+
* Creates a vector store and uploads knowledge sources, returning its ID.
|
|
29305
|
+
*/
|
|
29306
|
+
async createVectorStoreWithKnowledgeSources(options) {
|
|
29307
|
+
const { client, name, knowledgeSources, logLabel } = options;
|
|
29308
|
+
const vectorStores = this.getVectorStoresApi(client);
|
|
29309
|
+
const knowledgeSourcesCount = knowledgeSources.length;
|
|
29310
|
+
const downloadTimeoutMs = this.getKnowledgeSourceDownloadTimeoutMs();
|
|
29311
|
+
if (this.options.isVerbose) {
|
|
29312
|
+
console.info('[🤰]', 'Creating vector store with knowledge sources', {
|
|
29313
|
+
name,
|
|
29314
|
+
knowledgeSourcesCount,
|
|
29315
|
+
downloadTimeoutMs,
|
|
29316
|
+
logLabel,
|
|
29317
|
+
});
|
|
29318
|
+
}
|
|
29319
|
+
const vectorStore = await vectorStores.create({
|
|
29320
|
+
name: `${name} Knowledge Base`,
|
|
29321
|
+
});
|
|
29322
|
+
const vectorStoreId = vectorStore.id;
|
|
29323
|
+
if (this.options.isVerbose) {
|
|
29324
|
+
console.info('[🤰]', 'Vector store created', {
|
|
29325
|
+
vectorStoreId,
|
|
29326
|
+
logLabel,
|
|
29327
|
+
});
|
|
29328
|
+
}
|
|
29329
|
+
const fileStreams = [];
|
|
29330
|
+
const skippedSources = [];
|
|
29331
|
+
let totalBytes = 0;
|
|
29332
|
+
const processingStartedAtMs = Date.now();
|
|
29333
|
+
for (const [index, source] of knowledgeSources.entries()) {
|
|
29334
|
+
try {
|
|
29335
|
+
const isDataUrl = isDataUrlKnowledgeSource(source);
|
|
29336
|
+
const isHttp = source.startsWith('http://') || source.startsWith('https://');
|
|
29337
|
+
const sourceType = isDataUrl ? 'data_url' : isHttp ? 'url' : 'file';
|
|
29338
|
+
if (this.options.isVerbose) {
|
|
29339
|
+
console.info('[🤰]', 'Processing knowledge source', {
|
|
29340
|
+
index: index + 1,
|
|
29341
|
+
total: knowledgeSourcesCount,
|
|
29342
|
+
source,
|
|
29343
|
+
sourceType,
|
|
29344
|
+
logLabel,
|
|
29345
|
+
});
|
|
29346
|
+
}
|
|
29347
|
+
if (isDataUrl) {
|
|
29348
|
+
const parsed = parseDataUrlKnowledgeSource(source);
|
|
29349
|
+
if (!parsed) {
|
|
29350
|
+
skippedSources.push({ source, reason: 'invalid_data_url' });
|
|
29351
|
+
if (this.options.isVerbose) {
|
|
29352
|
+
console.info('[🤰]', 'Skipping knowledge source (invalid data URL)', {
|
|
29353
|
+
source,
|
|
29354
|
+
sourceType,
|
|
29355
|
+
logLabel,
|
|
29356
|
+
});
|
|
29357
|
+
}
|
|
29358
|
+
continue;
|
|
29359
|
+
}
|
|
29360
|
+
const dataUrlFile = new File([parsed.buffer], parsed.filename, {
|
|
29361
|
+
type: parsed.mimeType,
|
|
29362
|
+
});
|
|
29363
|
+
fileStreams.push(dataUrlFile);
|
|
29364
|
+
totalBytes += parsed.buffer.length;
|
|
29365
|
+
continue;
|
|
29366
|
+
}
|
|
29367
|
+
if (isHttp) {
|
|
29368
|
+
const downloadResult = await this.downloadKnowledgeSourceFile({
|
|
29369
|
+
source,
|
|
29370
|
+
timeoutMs: downloadTimeoutMs,
|
|
29371
|
+
logLabel,
|
|
29372
|
+
});
|
|
29373
|
+
if (downloadResult) {
|
|
29374
|
+
fileStreams.push(downloadResult.file);
|
|
29375
|
+
totalBytes += downloadResult.sizeBytes;
|
|
29376
|
+
}
|
|
29377
|
+
else {
|
|
29378
|
+
skippedSources.push({ source, reason: 'download_failed' });
|
|
29379
|
+
}
|
|
29380
|
+
}
|
|
29381
|
+
else {
|
|
29382
|
+
skippedSources.push({ source, reason: 'unsupported_source_type' });
|
|
29383
|
+
if (this.options.isVerbose) {
|
|
29384
|
+
console.info('[🤰]', 'Skipping knowledge source (unsupported type)', {
|
|
29385
|
+
source,
|
|
29386
|
+
sourceType,
|
|
29387
|
+
logLabel,
|
|
29388
|
+
});
|
|
29389
|
+
}
|
|
29390
|
+
/*
|
|
29391
|
+
TODO: [🤰] Resolve problem with browser environment
|
|
29392
|
+
// Assume it's a local file path
|
|
29393
|
+
// Note: This will work in Node.js environment
|
|
29394
|
+
// For browser environments, this would need different handling
|
|
29395
|
+
const fs = await import('fs');
|
|
29396
|
+
const fileStream = fs.createReadStream(source);
|
|
29397
|
+
fileStreams.push(fileStream);
|
|
29398
|
+
*/
|
|
29399
|
+
}
|
|
29400
|
+
}
|
|
29401
|
+
catch (error) {
|
|
29402
|
+
assertsError(error);
|
|
29403
|
+
skippedSources.push({ source, reason: 'processing_error' });
|
|
29404
|
+
console.error('[🤰]', 'Error processing knowledge source', {
|
|
29405
|
+
source,
|
|
29406
|
+
logLabel,
|
|
29407
|
+
error: serializeError(error),
|
|
29408
|
+
});
|
|
29409
|
+
}
|
|
29410
|
+
}
|
|
29411
|
+
if (this.options.isVerbose) {
|
|
29412
|
+
console.info('[🤰]', 'Finished processing knowledge sources', {
|
|
29413
|
+
total: knowledgeSourcesCount,
|
|
29414
|
+
downloadedCount: fileStreams.length,
|
|
29415
|
+
skippedCount: skippedSources.length,
|
|
29416
|
+
totalBytes,
|
|
29417
|
+
elapsedMs: Date.now() - processingStartedAtMs,
|
|
29418
|
+
skippedSamples: skippedSources.slice(0, 3),
|
|
29419
|
+
logLabel,
|
|
29420
|
+
});
|
|
29421
|
+
}
|
|
29422
|
+
if (fileStreams.length > 0) {
|
|
29423
|
+
if (this.options.isVerbose) {
|
|
29424
|
+
console.info('[🤰]', 'Uploading files to vector store', {
|
|
29425
|
+
vectorStoreId,
|
|
29426
|
+
fileCount: fileStreams.length,
|
|
29427
|
+
totalBytes,
|
|
29428
|
+
maxConcurrency: this.getKnowledgeSourceUploadMaxConcurrency(),
|
|
29429
|
+
pollIntervalMs: this.getKnowledgeSourceUploadPollIntervalMs(),
|
|
29430
|
+
uploadTimeoutMs: this.getKnowledgeSourceUploadTimeoutMs(),
|
|
29431
|
+
logLabel,
|
|
29432
|
+
});
|
|
29433
|
+
}
|
|
29434
|
+
try {
|
|
29435
|
+
await this.uploadKnowledgeSourceFilesToVectorStore({
|
|
29436
|
+
client,
|
|
29437
|
+
vectorStoreId,
|
|
29438
|
+
files: fileStreams,
|
|
29439
|
+
totalBytes,
|
|
29440
|
+
logLabel,
|
|
29441
|
+
});
|
|
29442
|
+
}
|
|
29443
|
+
catch (error) {
|
|
29444
|
+
assertsError(error);
|
|
29445
|
+
console.error('[🤰]', 'Error uploading files to vector store', {
|
|
29446
|
+
vectorStoreId,
|
|
29447
|
+
logLabel,
|
|
29448
|
+
error: serializeError(error),
|
|
29449
|
+
});
|
|
29450
|
+
}
|
|
29451
|
+
}
|
|
29452
|
+
else if (this.options.isVerbose) {
|
|
29453
|
+
console.info('[🤰]', 'No knowledge source files to upload', {
|
|
29454
|
+
vectorStoreId,
|
|
29455
|
+
skippedCount: skippedSources.length,
|
|
29456
|
+
logLabel,
|
|
29457
|
+
});
|
|
29458
|
+
}
|
|
29459
|
+
return {
|
|
29460
|
+
vectorStoreId,
|
|
29461
|
+
uploadedFileCount: fileStreams.length,
|
|
29462
|
+
skippedCount: skippedSources.length,
|
|
29463
|
+
totalBytes,
|
|
29464
|
+
};
|
|
29465
|
+
}
|
|
29466
|
+
}
|
|
29467
|
+
|
|
28465
29468
|
/**
|
|
28466
29469
|
* Uploads files to OpenAI and returns their IDs
|
|
28467
29470
|
*
|
|
@@ -28495,10 +29498,10 @@ async function uploadFilesToOpenAi(client, files) {
|
|
|
28495
29498
|
* - `OpenAiAssistantExecutionTools` - which is a specific implementation of `LlmExecutionTools` for OpenAI models with assistant capabilities, recommended for usage in `Agent` or `AgentLlmExecutionTools`
|
|
28496
29499
|
* - `RemoteAgent` - which is an `Agent` that connects to a Promptbook Agents Server
|
|
28497
29500
|
*
|
|
29501
|
+
* @deprecated Use `OpenAiAgentKitExecutionTools` instead.
|
|
28498
29502
|
* @public exported from `@promptbook/openai`
|
|
28499
|
-
* @deprecated Use `OpenAiAgentExecutionTools` instead which uses the new OpenAI Responses API
|
|
28500
29503
|
*/
|
|
28501
|
-
class OpenAiAssistantExecutionTools extends
|
|
29504
|
+
class OpenAiAssistantExecutionTools extends OpenAiVectorStoreHandler {
|
|
28502
29505
|
/**
|
|
28503
29506
|
* Creates OpenAI Execution Tools.
|
|
28504
29507
|
*
|
|
@@ -28627,8 +29630,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28627
29630
|
console.info(colors.bgWhite('rawRequest (non-streaming with tools)'), JSON.stringify(rawRequest, null, 4));
|
|
28628
29631
|
}
|
|
28629
29632
|
// Create thread and run
|
|
28630
|
-
|
|
28631
|
-
let run = threadAndRun;
|
|
29633
|
+
let run = (await client.beta.threads.createAndRun(rawRequest));
|
|
28632
29634
|
const completedToolCalls = [];
|
|
28633
29635
|
const toolCallStartedAt = new Map();
|
|
28634
29636
|
// Poll until run completes or requires action
|
|
@@ -28723,14 +29725,14 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28723
29725
|
}
|
|
28724
29726
|
}
|
|
28725
29727
|
// Submit tool outputs
|
|
28726
|
-
run = await client.beta.threads.runs.submitToolOutputs(run.thread_id, run.id, {
|
|
29728
|
+
run = (await client.beta.threads.runs.submitToolOutputs(run.thread_id, run.id, {
|
|
28727
29729
|
tool_outputs: toolOutputs,
|
|
28728
|
-
});
|
|
29730
|
+
}));
|
|
28729
29731
|
}
|
|
28730
29732
|
else {
|
|
28731
29733
|
// Wait a bit before polling again
|
|
28732
29734
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
28733
|
-
run = await client.beta.threads.runs.retrieve(run.thread_id, run.id);
|
|
29735
|
+
run = (await client.beta.threads.runs.retrieve(run.thread_id, run.id));
|
|
28734
29736
|
}
|
|
28735
29737
|
}
|
|
28736
29738
|
if (run.status !== 'completed') {
|
|
@@ -28929,6 +29931,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28929
29931
|
getAssistant(assistantId) {
|
|
28930
29932
|
return new OpenAiAssistantExecutionTools({
|
|
28931
29933
|
...this.options,
|
|
29934
|
+
isCreatingNewAssistantsAllowed: this.isCreatingNewAssistantsAllowed,
|
|
28932
29935
|
assistantId,
|
|
28933
29936
|
});
|
|
28934
29937
|
}
|
|
@@ -28954,88 +29957,13 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
28954
29957
|
let vectorStoreId;
|
|
28955
29958
|
// If knowledge sources are provided, create a vector store with them
|
|
28956
29959
|
if (knowledgeSources && knowledgeSources.length > 0) {
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
28960
|
-
|
|
28961
|
-
|
|
28962
|
-
}
|
|
28963
|
-
// Create a vector store
|
|
28964
|
-
const vectorStore = await client.beta.vectorStores.create({
|
|
28965
|
-
name: `${name} Knowledge Base`,
|
|
29960
|
+
const vectorStoreResult = await this.createVectorStoreWithKnowledgeSources({
|
|
29961
|
+
client,
|
|
29962
|
+
name,
|
|
29963
|
+
knowledgeSources,
|
|
29964
|
+
logLabel: 'assistant creation',
|
|
28966
29965
|
});
|
|
28967
|
-
vectorStoreId =
|
|
28968
|
-
if (this.options.isVerbose) {
|
|
28969
|
-
console.info('[🤰]', 'Vector store created', {
|
|
28970
|
-
vectorStoreId,
|
|
28971
|
-
});
|
|
28972
|
-
}
|
|
28973
|
-
// Upload files from knowledge sources to the vector store
|
|
28974
|
-
const fileStreams = [];
|
|
28975
|
-
for (const [index, source] of knowledgeSources.entries()) {
|
|
28976
|
-
try {
|
|
28977
|
-
if (this.options.isVerbose) {
|
|
28978
|
-
console.info('[🤰]', 'Processing knowledge source', {
|
|
28979
|
-
index: index + 1,
|
|
28980
|
-
total: knowledgeSources.length,
|
|
28981
|
-
source,
|
|
28982
|
-
sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
|
|
28983
|
-
});
|
|
28984
|
-
}
|
|
28985
|
-
// Check if it's a URL
|
|
28986
|
-
if (source.startsWith('http://') || source.startsWith('https://')) {
|
|
28987
|
-
// Download the file
|
|
28988
|
-
const response = await fetch(source);
|
|
28989
|
-
if (!response.ok) {
|
|
28990
|
-
console.error(`Failed to download ${source}: ${response.statusText}`);
|
|
28991
|
-
continue;
|
|
28992
|
-
}
|
|
28993
|
-
const buffer = await response.arrayBuffer();
|
|
28994
|
-
let filename = source.split('/').pop() || 'downloaded-file';
|
|
28995
|
-
try {
|
|
28996
|
-
const url = new URL(source);
|
|
28997
|
-
filename = url.pathname.split('/').pop() || filename;
|
|
28998
|
-
}
|
|
28999
|
-
catch (error) {
|
|
29000
|
-
// Keep default filename
|
|
29001
|
-
}
|
|
29002
|
-
const blob = new Blob([buffer]);
|
|
29003
|
-
const file = new File([blob], filename);
|
|
29004
|
-
fileStreams.push(file);
|
|
29005
|
-
}
|
|
29006
|
-
else {
|
|
29007
|
-
/*
|
|
29008
|
-
TODO: [🐱🚀] Resolve problem with browser environment
|
|
29009
|
-
// Assume it's a local file path
|
|
29010
|
-
// Note: This will work in Node.js environment
|
|
29011
|
-
// For browser environments, this would need different handling
|
|
29012
|
-
const fs = await import('fs');
|
|
29013
|
-
const fileStream = fs.createReadStream(source);
|
|
29014
|
-
fileStreams.push(fileStream);
|
|
29015
|
-
*/
|
|
29016
|
-
}
|
|
29017
|
-
}
|
|
29018
|
-
catch (error) {
|
|
29019
|
-
console.error(`Error processing knowledge source ${source}:`, error);
|
|
29020
|
-
}
|
|
29021
|
-
}
|
|
29022
|
-
// Batch upload files to the vector store
|
|
29023
|
-
if (fileStreams.length > 0) {
|
|
29024
|
-
try {
|
|
29025
|
-
await client.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, {
|
|
29026
|
-
files: fileStreams,
|
|
29027
|
-
});
|
|
29028
|
-
if (this.options.isVerbose) {
|
|
29029
|
-
console.info('[🤰]', 'Uploaded files to vector store', {
|
|
29030
|
-
vectorStoreId,
|
|
29031
|
-
fileCount: fileStreams.length,
|
|
29032
|
-
});
|
|
29033
|
-
}
|
|
29034
|
-
}
|
|
29035
|
-
catch (error) {
|
|
29036
|
-
console.error('Error uploading files to vector store:', error);
|
|
29037
|
-
}
|
|
29038
|
-
}
|
|
29966
|
+
vectorStoreId = vectorStoreResult.vectorStoreId;
|
|
29039
29967
|
}
|
|
29040
29968
|
// Create assistant with vector store attached
|
|
29041
29969
|
const assistantConfig = {
|
|
@@ -29102,91 +30030,14 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
29102
30030
|
const client = await this.getClient();
|
|
29103
30031
|
let vectorStoreId;
|
|
29104
30032
|
// If knowledge sources are provided, create a vector store with them
|
|
29105
|
-
// TODO: [🧠] Reuse vector store creation logic from createNewAssistant
|
|
29106
30033
|
if (knowledgeSources && knowledgeSources.length > 0) {
|
|
29107
|
-
|
|
29108
|
-
|
|
29109
|
-
|
|
29110
|
-
|
|
29111
|
-
|
|
29112
|
-
});
|
|
29113
|
-
}
|
|
29114
|
-
// Create a vector store
|
|
29115
|
-
const vectorStore = await client.beta.vectorStores.create({
|
|
29116
|
-
name: `${name} Knowledge Base`,
|
|
30034
|
+
const vectorStoreResult = await this.createVectorStoreWithKnowledgeSources({
|
|
30035
|
+
client,
|
|
30036
|
+
name: name !== null && name !== void 0 ? name : assistantId,
|
|
30037
|
+
knowledgeSources,
|
|
30038
|
+
logLabel: 'assistant update',
|
|
29117
30039
|
});
|
|
29118
|
-
vectorStoreId =
|
|
29119
|
-
if (this.options.isVerbose) {
|
|
29120
|
-
console.info('[🤰]', 'Vector store created for assistant update', {
|
|
29121
|
-
vectorStoreId,
|
|
29122
|
-
});
|
|
29123
|
-
}
|
|
29124
|
-
// Upload files from knowledge sources to the vector store
|
|
29125
|
-
const fileStreams = [];
|
|
29126
|
-
for (const [index, source] of knowledgeSources.entries()) {
|
|
29127
|
-
try {
|
|
29128
|
-
if (this.options.isVerbose) {
|
|
29129
|
-
console.info('[🤰]', 'Processing knowledge source for update', {
|
|
29130
|
-
index: index + 1,
|
|
29131
|
-
total: knowledgeSources.length,
|
|
29132
|
-
source,
|
|
29133
|
-
sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
|
|
29134
|
-
});
|
|
29135
|
-
}
|
|
29136
|
-
// Check if it's a URL
|
|
29137
|
-
if (source.startsWith('http://') || source.startsWith('https://')) {
|
|
29138
|
-
// Download the file
|
|
29139
|
-
const response = await fetch(source);
|
|
29140
|
-
if (!response.ok) {
|
|
29141
|
-
console.error(`Failed to download ${source}: ${response.statusText}`);
|
|
29142
|
-
continue;
|
|
29143
|
-
}
|
|
29144
|
-
const buffer = await response.arrayBuffer();
|
|
29145
|
-
let filename = source.split('/').pop() || 'downloaded-file';
|
|
29146
|
-
try {
|
|
29147
|
-
const url = new URL(source);
|
|
29148
|
-
filename = url.pathname.split('/').pop() || filename;
|
|
29149
|
-
}
|
|
29150
|
-
catch (error) {
|
|
29151
|
-
// Keep default filename
|
|
29152
|
-
}
|
|
29153
|
-
const blob = new Blob([buffer]);
|
|
29154
|
-
const file = new File([blob], filename);
|
|
29155
|
-
fileStreams.push(file);
|
|
29156
|
-
}
|
|
29157
|
-
else {
|
|
29158
|
-
/*
|
|
29159
|
-
TODO: [🐱🚀] Resolve problem with browser environment
|
|
29160
|
-
// Assume it's a local file path
|
|
29161
|
-
// Note: This will work in Node.js environment
|
|
29162
|
-
// For browser environments, this would need different handling
|
|
29163
|
-
const fs = await import('fs');
|
|
29164
|
-
const fileStream = fs.createReadStream(source);
|
|
29165
|
-
fileStreams.push(fileStream);
|
|
29166
|
-
*/
|
|
29167
|
-
}
|
|
29168
|
-
}
|
|
29169
|
-
catch (error) {
|
|
29170
|
-
console.error(`Error processing knowledge source ${source}:`, error);
|
|
29171
|
-
}
|
|
29172
|
-
}
|
|
29173
|
-
// Batch upload files to the vector store
|
|
29174
|
-
if (fileStreams.length > 0) {
|
|
29175
|
-
try {
|
|
29176
|
-
await client.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, {
|
|
29177
|
-
files: fileStreams,
|
|
29178
|
-
});
|
|
29179
|
-
if (this.options.isVerbose) {
|
|
29180
|
-
console.info('[🤰]', 'Uploaded files to vector store for update', {
|
|
29181
|
-
vectorStoreId,
|
|
29182
|
-
fileCount: fileStreams.length,
|
|
29183
|
-
});
|
|
29184
|
-
}
|
|
29185
|
-
}
|
|
29186
|
-
catch (error) {
|
|
29187
|
-
console.error('Error uploading files to vector store:', error);
|
|
29188
|
-
}
|
|
29189
|
-
}
|
|
30040
|
+
vectorStoreId = vectorStoreResult.vectorStoreId;
|
|
29190
30041
|
}
|
|
29191
30042
|
const assistantUpdate = {
|
|
29192
30043
|
name,
|
|
@@ -29229,7 +30080,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
29229
30080
|
* Discriminant for type guards
|
|
29230
30081
|
*/
|
|
29231
30082
|
get discriminant() {
|
|
29232
|
-
return DISCRIMINANT;
|
|
30083
|
+
return DISCRIMINANT$1;
|
|
29233
30084
|
}
|
|
29234
30085
|
/**
|
|
29235
30086
|
* Type guard to check if given `LlmExecutionTools` are instanceof `OpenAiAssistantExecutionTools`
|
|
@@ -29237,7 +30088,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
29237
30088
|
* Note: This is useful when you can possibly have multiple versions of `@promptbook/openai` installed
|
|
29238
30089
|
*/
|
|
29239
30090
|
static isOpenAiAssistantExecutionTools(llmExecutionTools) {
|
|
29240
|
-
return llmExecutionTools.discriminant === DISCRIMINANT;
|
|
30091
|
+
return llmExecutionTools.discriminant === DISCRIMINANT$1;
|
|
29241
30092
|
}
|
|
29242
30093
|
}
|
|
29243
30094
|
/**
|
|
@@ -29245,7 +30096,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
|
|
|
29245
30096
|
*
|
|
29246
30097
|
* @private const of `OpenAiAssistantExecutionTools`
|
|
29247
30098
|
*/
|
|
29248
|
-
const DISCRIMINANT = 'OPEN_AI_ASSISTANT_V1';
|
|
30099
|
+
const DISCRIMINANT$1 = 'OPEN_AI_ASSISTANT_V1';
|
|
29249
30100
|
/**
|
|
29250
30101
|
* TODO: !!!!! [✨🥚] Knowledge should work both with and without scrapers
|
|
29251
30102
|
* TODO: [🙎] In `OpenAiAssistantExecutionTools` Allow to create abstract assistants with `isCreatingNewAssistantsAllowed`
|
|
@@ -30398,11 +31249,14 @@ const _FormattedBookInMarkdownTranspilerRegistration = $bookTranspilersRegister.
|
|
|
30398
31249
|
function createEmptyAgentModelRequirements() {
|
|
30399
31250
|
return {
|
|
30400
31251
|
systemMessage: '',
|
|
31252
|
+
promptSuffix: '',
|
|
30401
31253
|
// modelName: 'gpt-5',
|
|
30402
31254
|
modelName: 'gemini-2.5-flash-lite',
|
|
30403
31255
|
temperature: 0.7,
|
|
30404
31256
|
topP: 0.9,
|
|
30405
31257
|
topK: 50,
|
|
31258
|
+
parentAgentUrl: null,
|
|
31259
|
+
isClosed: false,
|
|
30406
31260
|
};
|
|
30407
31261
|
}
|
|
30408
31262
|
/**
|
|
@@ -30792,14 +31646,26 @@ function removeCommentsFromSystemMessage(systemMessage) {
|
|
|
30792
31646
|
}
|
|
30793
31647
|
|
|
30794
31648
|
/**
|
|
30795
|
-
* Creates agent model requirements using the new commitment system
|
|
31649
|
+
* Creates agent model requirements using the new commitment system.
|
|
31650
|
+
*
|
|
30796
31651
|
* This function uses a reduce-like pattern where each commitment applies its changes
|
|
30797
|
-
* to build the final requirements starting from a basic empty model
|
|
31652
|
+
* to build the final requirements starting from a basic empty model.
|
|
30798
31653
|
*
|
|
30799
|
-
* @
|
|
31654
|
+
* @param agentSource - Agent source book to parse.
|
|
31655
|
+
* @param modelName - Optional override for the agent model name.
|
|
31656
|
+
* @param options - Additional options such as the agent reference resolver.
|
|
31657
|
+
*
|
|
31658
|
+
* @private @@@
|
|
31659
|
+
*/
|
|
31660
|
+
const COMMITMENTS_WITH_AGENT_REFERENCES = new Set(['FROM', 'IMPORT', 'IMPORTS', 'TEAM']);
|
|
31661
|
+
/**
|
|
31662
|
+
* @@@
|
|
31663
|
+
*
|
|
31664
|
+
* @private @@@
|
|
30800
31665
|
*/
|
|
30801
|
-
async function createAgentModelRequirementsWithCommitments(agentSource, modelName) {
|
|
31666
|
+
async function createAgentModelRequirementsWithCommitments(agentSource, modelName, options) {
|
|
30802
31667
|
var _a;
|
|
31668
|
+
const agentReferenceResolver = options === null || options === void 0 ? void 0 : options.agentReferenceResolver;
|
|
30803
31669
|
// Parse the agent source to extract commitments
|
|
30804
31670
|
const parseResult = parseAgentSourceWithCommitments(agentSource);
|
|
30805
31671
|
// Apply DELETE filtering: remove prior commitments tagged by parameters targeted by DELETE/CANCEL/DISCARD/REMOVE
|
|
@@ -30836,8 +31702,8 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
|
|
|
30836
31702
|
// Store the agent name in metadata so commitments can access it
|
|
30837
31703
|
requirements = {
|
|
30838
31704
|
...requirements,
|
|
30839
|
-
|
|
30840
|
-
...requirements.
|
|
31705
|
+
_metadata: {
|
|
31706
|
+
...requirements._metadata,
|
|
30841
31707
|
agentName: parseResult.agentName,
|
|
30842
31708
|
},
|
|
30843
31709
|
};
|
|
@@ -30851,6 +31717,11 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
|
|
|
30851
31717
|
// Apply each commitment in order using reduce-like pattern
|
|
30852
31718
|
for (let i = 0; i < filteredCommitments.length; i++) {
|
|
30853
31719
|
const commitment = filteredCommitments[i];
|
|
31720
|
+
const isReferenceCommitment = Boolean(agentReferenceResolver && COMMITMENTS_WITH_AGENT_REFERENCES.has(commitment.type));
|
|
31721
|
+
let commitmentContent = commitment.content;
|
|
31722
|
+
if (isReferenceCommitment && agentReferenceResolver) {
|
|
31723
|
+
commitmentContent = await agentReferenceResolver.resolveCommitmentContent(commitment.type, commitment.content);
|
|
31724
|
+
}
|
|
30854
31725
|
// CLOSED commitment should work only if its the last commitment in the book
|
|
30855
31726
|
if (commitment.type === 'CLOSED' && i !== filteredCommitments.length - 1) {
|
|
30856
31727
|
continue;
|
|
@@ -30858,7 +31729,7 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
|
|
|
30858
31729
|
const definition = getCommitmentDefinition(commitment.type);
|
|
30859
31730
|
if (definition) {
|
|
30860
31731
|
try {
|
|
30861
|
-
requirements = definition.applyToAgentModelRequirements(requirements,
|
|
31732
|
+
requirements = definition.applyToAgentModelRequirements(requirements, commitmentContent);
|
|
30862
31733
|
}
|
|
30863
31734
|
catch (error) {
|
|
30864
31735
|
console.warn(`Failed to apply commitment ${commitment.type}:`, error);
|
|
@@ -31317,23 +32188,28 @@ function normalizeSeparator(content) {
|
|
|
31317
32188
|
*/
|
|
31318
32189
|
|
|
31319
32190
|
/**
|
|
31320
|
-
* Creates model requirements for an agent based on its source
|
|
32191
|
+
* Creates model requirements for an agent based on its source.
|
|
31321
32192
|
*
|
|
31322
32193
|
* There are 2 similar functions:
|
|
31323
32194
|
* - `parseAgentSource` which is a lightweight parser for agent source, it parses basic information and its purpose is to be quick and synchronous. The commitments there are hardcoded.
|
|
31324
32195
|
* - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronous.
|
|
31325
32196
|
*
|
|
32197
|
+
* @param agentSource - Book describing the agent.
|
|
32198
|
+
* @param modelName - Optional override for the agent's model.
|
|
32199
|
+
* @param availableModels - Models that could fulfill the agent.
|
|
32200
|
+
* @param llmTools - Execution tools used when selecting a best model.
|
|
32201
|
+
* @param options - Optional hooks such as the agent reference resolver.
|
|
31326
32202
|
* @public exported from `@promptbook/core`
|
|
31327
32203
|
*/
|
|
31328
|
-
async function createAgentModelRequirements(agentSource, modelName, availableModels, llmTools) {
|
|
32204
|
+
async function createAgentModelRequirements(agentSource, modelName, availableModels, llmTools, options) {
|
|
31329
32205
|
// If availableModels are provided and no specific modelName is given,
|
|
31330
32206
|
// use preparePersona to select the best model
|
|
31331
32207
|
if (availableModels && !modelName && llmTools) {
|
|
31332
32208
|
const selectedModelName = await selectBestModelUsingPersona(agentSource, llmTools);
|
|
31333
|
-
return createAgentModelRequirementsWithCommitments(agentSource, selectedModelName);
|
|
32209
|
+
return createAgentModelRequirementsWithCommitments(agentSource, selectedModelName, options);
|
|
31334
32210
|
}
|
|
31335
32211
|
// Use the new commitment-based system with provided or default model
|
|
31336
|
-
return createAgentModelRequirementsWithCommitments(agentSource, modelName);
|
|
32212
|
+
return createAgentModelRequirementsWithCommitments(agentSource, modelName, options);
|
|
31337
32213
|
}
|
|
31338
32214
|
/**
|
|
31339
32215
|
* Selects the best model using the preparePersona function
|
|
@@ -31831,6 +32707,40 @@ function isAssistantPreparationToolCall(toolCall) {
|
|
|
31831
32707
|
return toolCall.name === ASSISTANT_PREPARATION_TOOL_CALL_NAME;
|
|
31832
32708
|
}
|
|
31833
32709
|
|
|
32710
|
+
/**
|
|
32711
|
+
* Builds a stable identity string for tool calls across partial updates.
|
|
32712
|
+
*
|
|
32713
|
+
* @param toolCall - Tool call entry to identify.
|
|
32714
|
+
* @returns Stable identity string for deduplication.
|
|
32715
|
+
*
|
|
32716
|
+
* @private function of <Chat/>
|
|
32717
|
+
*/
|
|
32718
|
+
function getToolCallIdentity(toolCall) {
|
|
32719
|
+
const rawToolCall = toolCall.rawToolCall;
|
|
32720
|
+
const rawId = (rawToolCall === null || rawToolCall === void 0 ? void 0 : rawToolCall.id) || (rawToolCall === null || rawToolCall === void 0 ? void 0 : rawToolCall.callId) || (rawToolCall === null || rawToolCall === void 0 ? void 0 : rawToolCall.call_id);
|
|
32721
|
+
if (rawId) {
|
|
32722
|
+
return `id:${rawId}`;
|
|
32723
|
+
}
|
|
32724
|
+
if (toolCall.createdAt) {
|
|
32725
|
+
return `time:${toolCall.createdAt}:${toolCall.name}`;
|
|
32726
|
+
}
|
|
32727
|
+
const argsKey = (() => {
|
|
32728
|
+
if (typeof toolCall.arguments === 'string') {
|
|
32729
|
+
return toolCall.arguments;
|
|
32730
|
+
}
|
|
32731
|
+
if (!toolCall.arguments) {
|
|
32732
|
+
return '';
|
|
32733
|
+
}
|
|
32734
|
+
try {
|
|
32735
|
+
return JSON.stringify(toolCall.arguments);
|
|
32736
|
+
}
|
|
32737
|
+
catch (_a) {
|
|
32738
|
+
return '';
|
|
32739
|
+
}
|
|
32740
|
+
})();
|
|
32741
|
+
return `fallback:${toolCall.name}:${argsKey}`;
|
|
32742
|
+
}
|
|
32743
|
+
|
|
31834
32744
|
/*! *****************************************************************************
|
|
31835
32745
|
Copyright (c) Microsoft Corporation.
|
|
31836
32746
|
|
|
@@ -32052,206 +32962,490 @@ function promptbookifyAiText(text) {
|
|
|
32052
32962
|
* TODO: [🧠][✌️] Make some Promptbook-native token system
|
|
32053
32963
|
*/
|
|
32054
32964
|
|
|
32965
|
+
const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5.2';
|
|
32966
|
+
const DEFAULT_JSON_SCHEMA_NAME = 'StructuredOutput';
|
|
32967
|
+
/*
|
|
32968
|
+
TODO: Use or remove
|
|
32969
|
+
const EMPTY_JSON_SCHEMA: JsonSchemaDefinition['schema'] = {
|
|
32970
|
+
type: 'object',
|
|
32971
|
+
properties: {},
|
|
32972
|
+
required: [],
|
|
32973
|
+
additionalProperties: true,
|
|
32974
|
+
};
|
|
32975
|
+
*/
|
|
32976
|
+
function buildJsonSchemaDefinition(jsonSchema) {
|
|
32977
|
+
var _a, _b, _c;
|
|
32978
|
+
const schema = (_a = jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.schema) !== null && _a !== void 0 ? _a : {};
|
|
32979
|
+
return {
|
|
32980
|
+
type: 'json_schema',
|
|
32981
|
+
name: (_b = jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.name) !== null && _b !== void 0 ? _b : DEFAULT_JSON_SCHEMA_NAME,
|
|
32982
|
+
strict: Boolean(jsonSchema === null || jsonSchema === void 0 ? void 0 : jsonSchema.strict),
|
|
32983
|
+
schema: {
|
|
32984
|
+
type: 'object',
|
|
32985
|
+
properties: ((_c = schema.properties) !== null && _c !== void 0 ? _c : {}),
|
|
32986
|
+
required: Array.isArray(schema.required) ? schema.required : [],
|
|
32987
|
+
additionalProperties: schema.additionalProperties === undefined ? true : Boolean(schema.additionalProperties),
|
|
32988
|
+
description: schema.description,
|
|
32989
|
+
},
|
|
32990
|
+
};
|
|
32991
|
+
}
|
|
32992
|
+
/**
|
|
32993
|
+
* Maps OpenAI `response_format` payloads to AgentKit output types so the runner can forward
|
|
32994
|
+
* structured-output preferences to OpenAI while still reusing the same AgentKit agent instance.
|
|
32995
|
+
*
|
|
32996
|
+
* @param responseFormat - The OpenAI `response_format` payload from the user request.
|
|
32997
|
+
* @returns An Agent output type compatible with the requested schema or `undefined` when no impact is required.
|
|
32998
|
+
* @private utility of Open AI
|
|
32999
|
+
*/
|
|
33000
|
+
function mapResponseFormatToAgentOutputType(responseFormat) {
|
|
33001
|
+
if (!responseFormat) {
|
|
33002
|
+
return undefined;
|
|
33003
|
+
}
|
|
33004
|
+
if (typeof responseFormat === 'string') {
|
|
33005
|
+
if (responseFormat === 'text') {
|
|
33006
|
+
return 'text';
|
|
33007
|
+
}
|
|
33008
|
+
if (responseFormat === 'json_schema' || responseFormat === 'json_object') {
|
|
33009
|
+
return buildJsonSchemaDefinition();
|
|
33010
|
+
}
|
|
33011
|
+
return 'text';
|
|
33012
|
+
}
|
|
33013
|
+
switch (responseFormat.type) {
|
|
33014
|
+
case 'text':
|
|
33015
|
+
return 'text';
|
|
33016
|
+
case 'json_schema':
|
|
33017
|
+
return buildJsonSchemaDefinition(responseFormat.json_schema);
|
|
33018
|
+
case 'json_object':
|
|
33019
|
+
return buildJsonSchemaDefinition();
|
|
33020
|
+
default:
|
|
33021
|
+
return undefined;
|
|
33022
|
+
}
|
|
33023
|
+
}
|
|
32055
33024
|
/**
|
|
32056
|
-
* Execution
|
|
33025
|
+
* Execution tools for OpenAI AgentKit (Agents SDK).
|
|
32057
33026
|
*
|
|
32058
33027
|
* @public exported from `@promptbook/openai`
|
|
32059
33028
|
*/
|
|
32060
|
-
class
|
|
33029
|
+
class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
33030
|
+
/**
|
|
33031
|
+
* Creates OpenAI AgentKit execution tools.
|
|
33032
|
+
*/
|
|
32061
33033
|
constructor(options) {
|
|
33034
|
+
var _a;
|
|
33035
|
+
if (options.isProxied) {
|
|
33036
|
+
throw new NotYetImplementedError(`Proxy mode is not yet implemented for OpenAI AgentKit`);
|
|
33037
|
+
}
|
|
32062
33038
|
super(options);
|
|
32063
|
-
this.
|
|
33039
|
+
this.preparedAgentKitAgent = null;
|
|
33040
|
+
this.agentKitModelName = (_a = options.agentKitModelName) !== null && _a !== void 0 ? _a : DEFAULT_AGENT_KIT_MODEL_NAME;
|
|
32064
33041
|
}
|
|
32065
33042
|
get title() {
|
|
32066
|
-
return 'OpenAI
|
|
33043
|
+
return 'OpenAI AgentKit';
|
|
32067
33044
|
}
|
|
32068
33045
|
get description() {
|
|
32069
|
-
return 'Use OpenAI
|
|
33046
|
+
return 'Use OpenAI AgentKit for agent-style chat with tools and knowledge';
|
|
32070
33047
|
}
|
|
32071
33048
|
/**
|
|
32072
|
-
* Calls OpenAI
|
|
33049
|
+
* Calls OpenAI AgentKit with a chat prompt (non-streaming).
|
|
33050
|
+
*/
|
|
33051
|
+
async callChatModel(prompt) {
|
|
33052
|
+
return this.callChatModelStream(prompt, () => { });
|
|
33053
|
+
}
|
|
33054
|
+
/**
|
|
33055
|
+
* Calls OpenAI AgentKit with a chat prompt (streaming).
|
|
32073
33056
|
*/
|
|
32074
33057
|
async callChatModelStream(prompt, onProgress) {
|
|
32075
|
-
if (this.options.isVerbose) {
|
|
32076
|
-
console.info('💬 OpenAI Agent callChatModel call', { prompt });
|
|
32077
|
-
}
|
|
32078
33058
|
const { content, parameters, modelRequirements } = prompt;
|
|
32079
|
-
const client = await this.getClient();
|
|
32080
33059
|
if (modelRequirements.modelVariant !== 'CHAT') {
|
|
32081
33060
|
throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
|
|
32082
33061
|
}
|
|
33062
|
+
for (const key of ['maxTokens', 'modelName', 'seed', 'temperature']) {
|
|
33063
|
+
if (modelRequirements[key] !== undefined) {
|
|
33064
|
+
throw new NotYetImplementedError(`In \`OpenAiAgentKitExecutionTools\` you cannot specify \`${key}\``);
|
|
33065
|
+
}
|
|
33066
|
+
}
|
|
32083
33067
|
const rawPromptContent = templateParameters(content, {
|
|
32084
33068
|
...parameters,
|
|
32085
|
-
modelName:
|
|
33069
|
+
modelName: this.agentKitModelName,
|
|
32086
33070
|
});
|
|
32087
|
-
|
|
32088
|
-
const
|
|
32089
|
-
|
|
32090
|
-
|
|
32091
|
-
|
|
32092
|
-
|
|
32093
|
-
content: msg.content,
|
|
32094
|
-
}));
|
|
32095
|
-
input.push(...previousMessages);
|
|
32096
|
-
}
|
|
32097
|
-
// Add current user message
|
|
32098
|
-
input.push({
|
|
32099
|
-
role: 'user',
|
|
32100
|
-
content: rawPromptContent,
|
|
33071
|
+
const responseFormatOutputType = mapResponseFormatToAgentOutputType(modelRequirements.responseFormat);
|
|
33072
|
+
const preparedAgentKitAgent = await this.prepareAgentKitAgent({
|
|
33073
|
+
name: (prompt.title || 'Agent'),
|
|
33074
|
+
instructions: modelRequirements.systemMessage || '',
|
|
33075
|
+
knowledgeSources: modelRequirements.knowledgeSources,
|
|
33076
|
+
tools: 'tools' in prompt && Array.isArray(prompt.tools) ? prompt.tools : modelRequirements.tools,
|
|
32101
33077
|
});
|
|
32102
|
-
|
|
32103
|
-
|
|
32104
|
-
|
|
32105
|
-
|
|
32106
|
-
|
|
32107
|
-
|
|
32108
|
-
|
|
32109
|
-
|
|
32110
|
-
|
|
32111
|
-
|
|
32112
|
-
|
|
32113
|
-
|
|
33078
|
+
return this.callChatModelStreamWithPreparedAgent({
|
|
33079
|
+
openAiAgentKitAgent: preparedAgentKitAgent.agent,
|
|
33080
|
+
prompt,
|
|
33081
|
+
rawPromptContent,
|
|
33082
|
+
onProgress,
|
|
33083
|
+
responseFormatOutputType,
|
|
33084
|
+
});
|
|
33085
|
+
}
|
|
33086
|
+
/**
|
|
33087
|
+
* Returns a prepared AgentKit agent when the server wants to manage caching externally.
|
|
33088
|
+
*/
|
|
33089
|
+
getPreparedAgentKitAgent() {
|
|
33090
|
+
return this.preparedAgentKitAgent;
|
|
33091
|
+
}
|
|
33092
|
+
/**
|
|
33093
|
+
* Stores a prepared AgentKit agent for later reuse by external cache managers.
|
|
33094
|
+
*/
|
|
33095
|
+
setPreparedAgentKitAgent(preparedAgent) {
|
|
33096
|
+
this.preparedAgentKitAgent = preparedAgent;
|
|
33097
|
+
}
|
|
33098
|
+
/**
|
|
33099
|
+
* Creates a new tools instance bound to a prepared AgentKit agent.
|
|
33100
|
+
*/
|
|
33101
|
+
getPreparedAgentTools(preparedAgent) {
|
|
33102
|
+
const tools = new OpenAiAgentKitExecutionTools(this.agentKitOptions);
|
|
33103
|
+
tools.setPreparedAgentKitAgent(preparedAgent);
|
|
33104
|
+
return tools;
|
|
33105
|
+
}
|
|
33106
|
+
/**
|
|
33107
|
+
* Prepares an AgentKit agent with optional knowledge sources and tool definitions.
|
|
33108
|
+
*/
|
|
33109
|
+
async prepareAgentKitAgent(options) {
|
|
33110
|
+
var _a, _b;
|
|
33111
|
+
const { name, instructions, knowledgeSources, tools, vectorStoreId: cachedVectorStoreId, storeAsPrepared, } = options;
|
|
33112
|
+
await this.ensureAgentKitDefaults();
|
|
33113
|
+
if (this.options.isVerbose) {
|
|
33114
|
+
console.info('[🤰]', 'Preparing OpenAI AgentKit agent', {
|
|
33115
|
+
name,
|
|
33116
|
+
instructionsLength: instructions.length,
|
|
33117
|
+
knowledgeSourcesCount: (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0,
|
|
33118
|
+
toolsCount: (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0,
|
|
33119
|
+
});
|
|
32114
33120
|
}
|
|
32115
|
-
|
|
32116
|
-
if (
|
|
32117
|
-
|
|
32118
|
-
|
|
32119
|
-
|
|
32120
|
-
|
|
32121
|
-
|
|
32122
|
-
|
|
33121
|
+
let vectorStoreId = cachedVectorStoreId;
|
|
33122
|
+
if (!vectorStoreId && knowledgeSources && knowledgeSources.length > 0) {
|
|
33123
|
+
const vectorStoreResult = await this.createVectorStoreWithKnowledgeSources({
|
|
33124
|
+
client: await this.getClient(),
|
|
33125
|
+
name,
|
|
33126
|
+
knowledgeSources,
|
|
33127
|
+
logLabel: 'agentkit preparation',
|
|
33128
|
+
});
|
|
33129
|
+
vectorStoreId = vectorStoreResult.vectorStoreId;
|
|
32123
33130
|
}
|
|
32124
|
-
|
|
32125
|
-
|
|
32126
|
-
|
|
32127
|
-
|
|
32128
|
-
|
|
32129
|
-
|
|
32130
|
-
|
|
32131
|
-
|
|
32132
|
-
|
|
32133
|
-
|
|
33131
|
+
else if (vectorStoreId && this.options.isVerbose) {
|
|
33132
|
+
console.info('[🤰]', 'Using cached vector store for AgentKit agent', {
|
|
33133
|
+
name,
|
|
33134
|
+
vectorStoreId,
|
|
33135
|
+
});
|
|
33136
|
+
}
|
|
33137
|
+
const agentKitTools = this.buildAgentKitTools({ tools, vectorStoreId });
|
|
33138
|
+
const openAiAgentKitAgent = new Agent$1({
|
|
33139
|
+
name,
|
|
33140
|
+
model: this.agentKitModelName,
|
|
33141
|
+
instructions: instructions || 'You are a helpful assistant.',
|
|
33142
|
+
tools: agentKitTools,
|
|
33143
|
+
});
|
|
33144
|
+
const preparedAgent = {
|
|
33145
|
+
agent: openAiAgentKitAgent,
|
|
33146
|
+
vectorStoreId,
|
|
32134
33147
|
};
|
|
32135
|
-
if (
|
|
32136
|
-
|
|
33148
|
+
if (storeAsPrepared) {
|
|
33149
|
+
this.setPreparedAgentKitAgent(preparedAgent);
|
|
32137
33150
|
}
|
|
32138
|
-
// Call Responses API
|
|
32139
|
-
// Note: Using any cast because types might not be updated yet
|
|
32140
|
-
const response = await client.responses.create(rawRequest);
|
|
32141
33151
|
if (this.options.isVerbose) {
|
|
32142
|
-
console.info(
|
|
33152
|
+
console.info('[🤰]', 'OpenAI AgentKit agent ready', {
|
|
33153
|
+
name,
|
|
33154
|
+
model: this.agentKitModelName,
|
|
33155
|
+
toolCount: agentKitTools.length,
|
|
33156
|
+
hasVectorStore: Boolean(vectorStoreId),
|
|
33157
|
+
});
|
|
32143
33158
|
}
|
|
32144
|
-
|
|
32145
|
-
|
|
32146
|
-
|
|
32147
|
-
|
|
32148
|
-
|
|
32149
|
-
|
|
32150
|
-
|
|
32151
|
-
|
|
32152
|
-
|
|
32153
|
-
|
|
32154
|
-
|
|
33159
|
+
return preparedAgent;
|
|
33160
|
+
}
|
|
33161
|
+
/**
|
|
33162
|
+
* Ensures the AgentKit SDK is wired to the OpenAI client and API key.
|
|
33163
|
+
*/
|
|
33164
|
+
async ensureAgentKitDefaults() {
|
|
33165
|
+
const client = await this.getClient();
|
|
33166
|
+
setDefaultOpenAIClient(client);
|
|
33167
|
+
const apiKey = this.agentKitOptions.apiKey;
|
|
33168
|
+
if (apiKey && typeof apiKey === 'string') {
|
|
33169
|
+
setDefaultOpenAIKey(apiKey);
|
|
33170
|
+
}
|
|
33171
|
+
}
|
|
33172
|
+
/**
|
|
33173
|
+
* Builds the tool list for AgentKit, including hosted file search when applicable.
|
|
33174
|
+
*/
|
|
33175
|
+
buildAgentKitTools(options) {
|
|
33176
|
+
var _a;
|
|
33177
|
+
const { tools, vectorStoreId } = options;
|
|
33178
|
+
const agentKitTools = [];
|
|
33179
|
+
if (vectorStoreId) {
|
|
33180
|
+
agentKitTools.push(fileSearchTool(vectorStoreId));
|
|
33181
|
+
}
|
|
33182
|
+
if (tools && tools.length > 0) {
|
|
33183
|
+
const scriptTools = this.resolveScriptTools();
|
|
33184
|
+
for (const toolDefinition of tools) {
|
|
33185
|
+
agentKitTools.push(tool({
|
|
33186
|
+
name: toolDefinition.name,
|
|
33187
|
+
description: toolDefinition.description,
|
|
33188
|
+
parameters: toolDefinition.parameters
|
|
33189
|
+
? {
|
|
33190
|
+
...toolDefinition.parameters,
|
|
33191
|
+
additionalProperties: false,
|
|
33192
|
+
required: (_a = toolDefinition.parameters.required) !== null && _a !== void 0 ? _a : [],
|
|
33193
|
+
}
|
|
33194
|
+
: undefined,
|
|
33195
|
+
strict: false,
|
|
33196
|
+
execute: async (input, runContext, details) => {
|
|
33197
|
+
var _a, _b, _c;
|
|
33198
|
+
const scriptTool = scriptTools[0];
|
|
33199
|
+
const functionName = toolDefinition.name;
|
|
33200
|
+
const calledAt = $getCurrentDate();
|
|
33201
|
+
const callId = (_a = details === null || details === void 0 ? void 0 : details.toolCall) === null || _a === void 0 ? void 0 : _a.callId;
|
|
33202
|
+
const functionArgs = input !== null && input !== void 0 ? input : {};
|
|
33203
|
+
if (this.options.isVerbose) {
|
|
33204
|
+
console.info('[🤰]', 'Executing AgentKit tool', {
|
|
33205
|
+
functionName,
|
|
33206
|
+
callId,
|
|
33207
|
+
calledAt,
|
|
33208
|
+
});
|
|
33209
|
+
}
|
|
33210
|
+
try {
|
|
33211
|
+
return await scriptTool.execute({
|
|
33212
|
+
scriptLanguage: 'javascript',
|
|
33213
|
+
script: `
|
|
33214
|
+
const args = ${JSON.stringify(functionArgs)};
|
|
33215
|
+
return await ${functionName}(args);
|
|
33216
|
+
`,
|
|
33217
|
+
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 : {},
|
|
33218
|
+
});
|
|
32155
33219
|
}
|
|
32156
|
-
|
|
32157
|
-
|
|
33220
|
+
catch (error) {
|
|
33221
|
+
assertsError(error);
|
|
33222
|
+
const serializedError = serializeError(error);
|
|
33223
|
+
const errorMessage = spaceTrim$2((block) => `
|
|
33224
|
+
|
|
33225
|
+
The invoked tool \`${functionName}\` failed with error:
|
|
33226
|
+
|
|
33227
|
+
\`\`\`json
|
|
33228
|
+
${block(JSON.stringify(serializedError, null, 4))}
|
|
33229
|
+
\`\`\`
|
|
33230
|
+
|
|
33231
|
+
`);
|
|
33232
|
+
console.error('[🤰]', 'AgentKit tool execution failed', {
|
|
33233
|
+
functionName,
|
|
33234
|
+
callId,
|
|
33235
|
+
error: serializedError,
|
|
33236
|
+
});
|
|
33237
|
+
return errorMessage;
|
|
32158
33238
|
}
|
|
33239
|
+
},
|
|
33240
|
+
}));
|
|
33241
|
+
}
|
|
33242
|
+
}
|
|
33243
|
+
return agentKitTools;
|
|
33244
|
+
}
|
|
33245
|
+
/**
|
|
33246
|
+
* Resolves the configured script tools for tool execution.
|
|
33247
|
+
*/
|
|
33248
|
+
resolveScriptTools() {
|
|
33249
|
+
const executionTools = this.options.executionTools;
|
|
33250
|
+
if (!executionTools || !executionTools.script) {
|
|
33251
|
+
throw new PipelineExecutionError(`Model requested tools but no executionTools.script were provided in OpenAiAgentKitExecutionTools options`);
|
|
33252
|
+
}
|
|
33253
|
+
return Array.isArray(executionTools.script) ? executionTools.script : [executionTools.script];
|
|
33254
|
+
}
|
|
33255
|
+
/**
|
|
33256
|
+
* Runs a prepared AgentKit agent and streams results back to the caller.
|
|
33257
|
+
*/
|
|
33258
|
+
async callChatModelStreamWithPreparedAgent(options) {
|
|
33259
|
+
var _a, _b, _c, _d;
|
|
33260
|
+
const { openAiAgentKitAgent, prompt, onProgress } = options;
|
|
33261
|
+
const rawPromptContent = (_a = options.rawPromptContent) !== null && _a !== void 0 ? _a : templateParameters(prompt.content, {
|
|
33262
|
+
...prompt.parameters,
|
|
33263
|
+
modelName: this.agentKitModelName,
|
|
33264
|
+
});
|
|
33265
|
+
const agentForRun = options.responseFormatOutputType !== undefined
|
|
33266
|
+
? openAiAgentKitAgent.clone({
|
|
33267
|
+
outputType: options.responseFormatOutputType,
|
|
33268
|
+
})
|
|
33269
|
+
: openAiAgentKitAgent;
|
|
33270
|
+
const start = $getCurrentDate();
|
|
33271
|
+
let latestContent = '';
|
|
33272
|
+
const toolCalls = [];
|
|
33273
|
+
const toolCallIndexById = new Map();
|
|
33274
|
+
const inputItems = await this.buildAgentKitInputItems(prompt, rawPromptContent);
|
|
33275
|
+
const rawRequest = {
|
|
33276
|
+
agentName: agentForRun.name,
|
|
33277
|
+
input: inputItems,
|
|
33278
|
+
};
|
|
33279
|
+
const streamResult = await run(agentForRun, inputItems, {
|
|
33280
|
+
stream: true,
|
|
33281
|
+
context: { parameters: prompt.parameters },
|
|
33282
|
+
});
|
|
33283
|
+
for await (const event of streamResult) {
|
|
33284
|
+
if (event.type === 'raw_model_stream_event' && ((_b = event.data) === null || _b === void 0 ? void 0 : _b.type) === 'output_text_delta') {
|
|
33285
|
+
latestContent += event.data.delta;
|
|
33286
|
+
onProgress({
|
|
33287
|
+
content: latestContent,
|
|
33288
|
+
modelName: this.agentKitModelName,
|
|
33289
|
+
timing: { start, complete: $getCurrentDate() },
|
|
33290
|
+
usage: UNCERTAIN_USAGE,
|
|
33291
|
+
rawPromptContent: rawPromptContent,
|
|
33292
|
+
rawRequest: null,
|
|
33293
|
+
rawResponse: {},
|
|
33294
|
+
});
|
|
33295
|
+
continue;
|
|
33296
|
+
}
|
|
33297
|
+
if (event.type === 'run_item_stream_event') {
|
|
33298
|
+
const rawItem = (_c = event.item) === null || _c === void 0 ? void 0 : _c.rawItem;
|
|
33299
|
+
if (event.name === 'tool_called' && (rawItem === null || rawItem === void 0 ? void 0 : rawItem.type) === 'function_call') {
|
|
33300
|
+
const toolCall = {
|
|
33301
|
+
name: rawItem.name,
|
|
33302
|
+
arguments: rawItem.arguments,
|
|
33303
|
+
rawToolCall: rawItem,
|
|
33304
|
+
createdAt: $getCurrentDate(),
|
|
33305
|
+
};
|
|
33306
|
+
toolCallIndexById.set(rawItem.callId, toolCalls.length);
|
|
33307
|
+
toolCalls.push(toolCall);
|
|
33308
|
+
onProgress({
|
|
33309
|
+
content: latestContent,
|
|
33310
|
+
modelName: this.agentKitModelName,
|
|
33311
|
+
timing: { start, complete: $getCurrentDate() },
|
|
33312
|
+
usage: UNCERTAIN_USAGE,
|
|
33313
|
+
rawPromptContent: rawPromptContent,
|
|
33314
|
+
rawRequest: null,
|
|
33315
|
+
rawResponse: {},
|
|
33316
|
+
toolCalls: [toolCall],
|
|
33317
|
+
});
|
|
33318
|
+
}
|
|
33319
|
+
if (event.name === 'tool_output' && (rawItem === null || rawItem === void 0 ? void 0 : rawItem.type) === 'function_call_result') {
|
|
33320
|
+
const index = toolCallIndexById.get(rawItem.callId);
|
|
33321
|
+
const result = this.formatAgentKitToolOutput(rawItem.output);
|
|
33322
|
+
if (index !== undefined) {
|
|
33323
|
+
const existingToolCall = toolCalls[index];
|
|
33324
|
+
const completedToolCall = {
|
|
33325
|
+
...existingToolCall,
|
|
33326
|
+
result,
|
|
33327
|
+
rawToolCall: rawItem,
|
|
33328
|
+
};
|
|
33329
|
+
toolCalls[index] = completedToolCall;
|
|
33330
|
+
onProgress({
|
|
33331
|
+
content: latestContent,
|
|
33332
|
+
modelName: this.agentKitModelName,
|
|
33333
|
+
timing: { start, complete: $getCurrentDate() },
|
|
33334
|
+
usage: UNCERTAIN_USAGE,
|
|
33335
|
+
rawPromptContent: rawPromptContent,
|
|
33336
|
+
rawRequest: null,
|
|
33337
|
+
rawResponse: {},
|
|
33338
|
+
toolCalls: [completedToolCall],
|
|
33339
|
+
});
|
|
32159
33340
|
}
|
|
32160
33341
|
}
|
|
32161
|
-
else if (item.type === 'function_call') ;
|
|
32162
33342
|
}
|
|
32163
33343
|
}
|
|
32164
|
-
|
|
32165
|
-
|
|
32166
|
-
|
|
32167
|
-
|
|
32168
|
-
|
|
32169
|
-
|
|
32170
|
-
content: resultContent,
|
|
32171
|
-
modelName: response.model || 'agent',
|
|
33344
|
+
await streamResult.completed;
|
|
33345
|
+
const complete = $getCurrentDate();
|
|
33346
|
+
const finalContent = ((_d = streamResult.finalOutput) !== null && _d !== void 0 ? _d : latestContent);
|
|
33347
|
+
const finalResult = {
|
|
33348
|
+
content: finalContent,
|
|
33349
|
+
modelName: this.agentKitModelName,
|
|
32172
33350
|
timing: { start, complete },
|
|
32173
33351
|
usage: UNCERTAIN_USAGE,
|
|
32174
|
-
rawPromptContent,
|
|
33352
|
+
rawPromptContent: rawPromptContent,
|
|
32175
33353
|
rawRequest,
|
|
32176
|
-
rawResponse:
|
|
32177
|
-
|
|
32178
|
-
|
|
32179
|
-
|
|
32180
|
-
|
|
32181
|
-
order: [],
|
|
32182
|
-
value: {
|
|
32183
|
-
content: resultContent,
|
|
32184
|
-
modelName: response.model || 'agent',
|
|
32185
|
-
timing: { start, complete },
|
|
32186
|
-
usage: UNCERTAIN_USAGE,
|
|
32187
|
-
rawPromptContent,
|
|
32188
|
-
rawRequest,
|
|
32189
|
-
rawResponse: response,
|
|
32190
|
-
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
32191
|
-
},
|
|
32192
|
-
});
|
|
33354
|
+
rawResponse: { runResult: streamResult },
|
|
33355
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
33356
|
+
};
|
|
33357
|
+
onProgress(finalResult);
|
|
33358
|
+
return finalResult;
|
|
32193
33359
|
}
|
|
32194
33360
|
/**
|
|
32195
|
-
*
|
|
33361
|
+
* Builds AgentKit input items from the prompt and optional thread.
|
|
32196
33362
|
*/
|
|
32197
|
-
|
|
32198
|
-
|
|
32199
|
-
const
|
|
32200
|
-
|
|
32201
|
-
|
|
32202
|
-
|
|
32203
|
-
|
|
32204
|
-
|
|
32205
|
-
|
|
32206
|
-
|
|
32207
|
-
|
|
32208
|
-
|
|
32209
|
-
|
|
32210
|
-
const response = await fetch(source);
|
|
32211
|
-
if (!response.ok) {
|
|
32212
|
-
console.error(`Failed to download ${source}: ${response.statusText}`);
|
|
32213
|
-
continue;
|
|
32214
|
-
}
|
|
32215
|
-
const buffer = await response.arrayBuffer();
|
|
32216
|
-
const filename = source.split('/').pop() || 'downloaded-file';
|
|
32217
|
-
const blob = new Blob([buffer]);
|
|
32218
|
-
const file = new File([blob], filename);
|
|
32219
|
-
fileStreams.push(file);
|
|
33363
|
+
async buildAgentKitInputItems(prompt, rawPromptContent) {
|
|
33364
|
+
var _a;
|
|
33365
|
+
const inputItems = [];
|
|
33366
|
+
if ('thread' in prompt && Array.isArray(prompt.thread)) {
|
|
33367
|
+
for (const message of prompt.thread) {
|
|
33368
|
+
const sender = message.sender;
|
|
33369
|
+
const content = (_a = message.content) !== null && _a !== void 0 ? _a : '';
|
|
33370
|
+
if (sender === 'assistant' || sender === 'agent') {
|
|
33371
|
+
inputItems.push({
|
|
33372
|
+
role: 'assistant',
|
|
33373
|
+
status: 'completed',
|
|
33374
|
+
content: [{ type: 'output_text', text: content }],
|
|
33375
|
+
});
|
|
32220
33376
|
}
|
|
32221
33377
|
else {
|
|
32222
|
-
|
|
33378
|
+
inputItems.push({
|
|
33379
|
+
role: 'user',
|
|
33380
|
+
content,
|
|
33381
|
+
});
|
|
32223
33382
|
}
|
|
32224
33383
|
}
|
|
32225
|
-
catch (error) {
|
|
32226
|
-
console.error(`Error processing knowledge source ${source}:`, error);
|
|
32227
|
-
}
|
|
32228
33384
|
}
|
|
32229
|
-
|
|
32230
|
-
|
|
32231
|
-
|
|
32232
|
-
|
|
32233
|
-
|
|
32234
|
-
|
|
32235
|
-
|
|
32236
|
-
|
|
32237
|
-
|
|
33385
|
+
const userContent = await this.buildAgentKitUserContent(prompt, rawPromptContent);
|
|
33386
|
+
inputItems.push({
|
|
33387
|
+
role: 'user',
|
|
33388
|
+
content: userContent,
|
|
33389
|
+
});
|
|
33390
|
+
return inputItems;
|
|
33391
|
+
}
|
|
33392
|
+
/**
|
|
33393
|
+
* Builds the user message content for AgentKit runs, including file inputs when provided.
|
|
33394
|
+
*/
|
|
33395
|
+
async buildAgentKitUserContent(prompt, rawPromptContent) {
|
|
33396
|
+
if ('files' in prompt && Array.isArray(prompt.files) && prompt.files.length > 0) {
|
|
33397
|
+
const fileItems = await Promise.all(prompt.files.map(async (file) => {
|
|
33398
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
33399
|
+
const base64 = Buffer.from(arrayBuffer).toString('base64');
|
|
33400
|
+
return {
|
|
33401
|
+
type: 'input_image',
|
|
33402
|
+
image: `data:${file.type};base64,${base64}`,
|
|
33403
|
+
};
|
|
33404
|
+
}));
|
|
33405
|
+
return [{ type: 'input_text', text: rawPromptContent }, ...fileItems];
|
|
33406
|
+
}
|
|
33407
|
+
return rawPromptContent;
|
|
33408
|
+
}
|
|
33409
|
+
/**
|
|
33410
|
+
* Normalizes AgentKit tool outputs into a string for Promptbook tool call results.
|
|
33411
|
+
*/
|
|
33412
|
+
formatAgentKitToolOutput(output) {
|
|
33413
|
+
if (typeof output === 'string') {
|
|
33414
|
+
return output;
|
|
33415
|
+
}
|
|
33416
|
+
if (output && typeof output === 'object') {
|
|
33417
|
+
const textOutput = output;
|
|
33418
|
+
if (textOutput.type === 'text' && typeof textOutput.text === 'string') {
|
|
33419
|
+
return textOutput.text;
|
|
32238
33420
|
}
|
|
32239
33421
|
}
|
|
32240
|
-
return
|
|
33422
|
+
return JSON.stringify(output !== null && output !== void 0 ? output : null);
|
|
32241
33423
|
}
|
|
32242
33424
|
/**
|
|
32243
|
-
*
|
|
33425
|
+
* Returns AgentKit-specific options.
|
|
33426
|
+
*/
|
|
33427
|
+
get agentKitOptions() {
|
|
33428
|
+
return this.options;
|
|
33429
|
+
}
|
|
33430
|
+
/**
|
|
33431
|
+
* Discriminant for type guards.
|
|
32244
33432
|
*/
|
|
32245
33433
|
get discriminant() {
|
|
32246
|
-
return
|
|
33434
|
+
return DISCRIMINANT;
|
|
32247
33435
|
}
|
|
32248
33436
|
/**
|
|
32249
|
-
* Type guard to check if given `LlmExecutionTools` are instanceof `
|
|
33437
|
+
* Type guard to check if given `LlmExecutionTools` are instanceof `OpenAiAgentKitExecutionTools`.
|
|
32250
33438
|
*/
|
|
32251
|
-
static
|
|
32252
|
-
return llmExecutionTools.discriminant ===
|
|
33439
|
+
static isOpenAiAgentKitExecutionTools(llmExecutionTools) {
|
|
33440
|
+
return llmExecutionTools.discriminant === DISCRIMINANT;
|
|
32253
33441
|
}
|
|
32254
33442
|
}
|
|
33443
|
+
/**
|
|
33444
|
+
* Discriminant for type guards.
|
|
33445
|
+
*
|
|
33446
|
+
* @private const of `OpenAiAgentKitExecutionTools`
|
|
33447
|
+
*/
|
|
33448
|
+
const DISCRIMINANT = 'OPEN_AI_AGENT_KIT_V1';
|
|
32255
33449
|
|
|
32256
33450
|
/**
|
|
32257
33451
|
* Emits a progress update to signal assistant preparation before long setup work.
|
|
@@ -32288,8 +33482,8 @@ function emitAssistantPreparationProgress(options) {
|
|
|
32288
33482
|
* - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
|
|
32289
33483
|
* - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
|
|
32290
33484
|
* - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
|
|
32291
|
-
* - `OpenAiAgentExecutionTools` - which is a specific implementation of `LlmExecutionTools` for OpenAI models with agent capabilities (using Responses API), recommended for usage in `Agent` or `AgentLlmExecutionTools`
|
|
32292
33485
|
* - `OpenAiAssistantExecutionTools` - (Deprecated) which is a specific implementation of `LlmExecutionTools` for OpenAI models with assistant capabilities
|
|
33486
|
+
* - `OpenAiAgentKitExecutionTools` - which is a specific implementation of `LlmExecutionTools` backed by OpenAI AgentKit
|
|
32293
33487
|
* - `RemoteAgent` - which is an `Agent` that connects to a Promptbook Agents Server
|
|
32294
33488
|
*
|
|
32295
33489
|
* @public exported from `@promptbook/core`
|
|
@@ -32424,97 +33618,129 @@ class AgentLlmExecutionTools {
|
|
|
32424
33618
|
* Calls the chat model with agent-specific system prompt and requirements with streaming
|
|
32425
33619
|
*/
|
|
32426
33620
|
async callChatModelStream(prompt, onProgress) {
|
|
33621
|
+
var _a, _b;
|
|
32427
33622
|
// Ensure we're working with a chat prompt
|
|
32428
33623
|
if (prompt.modelRequirements.modelVariant !== 'CHAT') {
|
|
32429
33624
|
throw new Error('AgentLlmExecutionTools only supports chat prompts');
|
|
32430
33625
|
}
|
|
32431
33626
|
const modelRequirements = await this.getModelRequirements();
|
|
33627
|
+
const { _metadata, promptSuffix, ...sanitizedRequirements } = modelRequirements;
|
|
32432
33628
|
const chatPrompt = prompt;
|
|
32433
33629
|
let underlyingLlmResult;
|
|
32434
|
-
|
|
33630
|
+
const chatPromptContentWithSuffix = promptSuffix
|
|
33631
|
+
? `${chatPrompt.content}\n\n${promptSuffix}`
|
|
33632
|
+
: chatPrompt.content;
|
|
32435
33633
|
const promptWithAgentModelRequirements = {
|
|
32436
33634
|
...chatPrompt,
|
|
33635
|
+
content: chatPromptContentWithSuffix,
|
|
32437
33636
|
modelRequirements: {
|
|
32438
33637
|
...chatPrompt.modelRequirements,
|
|
32439
|
-
...
|
|
33638
|
+
...sanitizedRequirements,
|
|
32440
33639
|
// Spread tools to convert readonly array to mutable
|
|
32441
|
-
tools:
|
|
33640
|
+
tools: sanitizedRequirements.tools
|
|
33641
|
+
? [...sanitizedRequirements.tools]
|
|
33642
|
+
: chatPrompt.modelRequirements.tools,
|
|
32442
33643
|
// Spread knowledgeSources to convert readonly array to mutable
|
|
32443
|
-
knowledgeSources:
|
|
32444
|
-
? [...
|
|
33644
|
+
knowledgeSources: sanitizedRequirements.knowledgeSources
|
|
33645
|
+
? [...sanitizedRequirements.knowledgeSources]
|
|
32445
33646
|
: undefined,
|
|
32446
33647
|
// Prepend agent system message to existing system message
|
|
32447
|
-
systemMessage:
|
|
33648
|
+
systemMessage: sanitizedRequirements.systemMessage +
|
|
32448
33649
|
(chatPrompt.modelRequirements.systemMessage
|
|
32449
33650
|
? `\n\n${chatPrompt.modelRequirements.systemMessage}`
|
|
32450
33651
|
: ''),
|
|
32451
33652
|
}, // Cast to avoid readonly mismatch from spread
|
|
32452
33653
|
};
|
|
32453
33654
|
console.log('!!!! promptWithAgentModelRequirements:', promptWithAgentModelRequirements);
|
|
32454
|
-
if (
|
|
32455
|
-
const requirementsHash = SHA256(JSON.stringify(
|
|
32456
|
-
const
|
|
32457
|
-
|
|
32458
|
-
|
|
33655
|
+
if (OpenAiAgentKitExecutionTools.isOpenAiAgentKitExecutionTools(this.options.llmTools)) {
|
|
33656
|
+
const requirementsHash = SHA256(JSON.stringify(sanitizedRequirements)).toString();
|
|
33657
|
+
const vectorStoreHash = SHA256(JSON.stringify((_a = sanitizedRequirements.knowledgeSources) !== null && _a !== void 0 ? _a : [])).toString();
|
|
33658
|
+
const cachedVectorStore = AgentLlmExecutionTools.vectorStoreCache.get(this.title);
|
|
33659
|
+
const cachedAgentKit = AgentLlmExecutionTools.agentKitAgentCache.get(this.title);
|
|
33660
|
+
let preparedAgentKit = this.options.assistantPreparationMode === 'external'
|
|
33661
|
+
? this.options.llmTools.getPreparedAgentKitAgent()
|
|
33662
|
+
: null;
|
|
33663
|
+
const vectorStoreId = (preparedAgentKit === null || preparedAgentKit === void 0 ? void 0 : preparedAgentKit.vectorStoreId) ||
|
|
33664
|
+
(cachedVectorStore && cachedVectorStore.requirementsHash === vectorStoreHash
|
|
33665
|
+
? cachedVectorStore.vectorStoreId
|
|
33666
|
+
: undefined);
|
|
33667
|
+
if (!preparedAgentKit && cachedAgentKit && cachedAgentKit.requirementsHash === requirementsHash) {
|
|
32459
33668
|
if (this.options.isVerbose) {
|
|
32460
|
-
console.
|
|
33669
|
+
console.info('[🤰]', 'Using cached OpenAI AgentKit agent', {
|
|
33670
|
+
agent: this.title,
|
|
33671
|
+
});
|
|
32461
33672
|
}
|
|
32462
|
-
|
|
32463
|
-
|
|
32464
|
-
|
|
32465
|
-
|
|
32466
|
-
// We can cast to access options if they were public, or use a method to clone.
|
|
32467
|
-
// OpenAiAgentExecutionTools doesn't have a clone method.
|
|
32468
|
-
// However, we can just assume the passed tool *might* not have the vector store yet, or we are replacing it.
|
|
32469
|
-
// Actually, if the passed tool IS OpenAiAgentExecutionTools, we should use it as a base.
|
|
32470
|
-
// TODO: [🧠] This is a bit hacky, accessing protected options or recreating tools.
|
|
32471
|
-
// Ideally OpenAiAgentExecutionTools should have a method `withVectorStoreId`.
|
|
32472
|
-
agentTools = new OpenAiAgentExecutionTools({
|
|
32473
|
-
...this.options.llmTools.options,
|
|
32474
|
-
vectorStoreId: cached.vectorStoreId,
|
|
32475
|
-
});
|
|
33673
|
+
preparedAgentKit = {
|
|
33674
|
+
agent: cachedAgentKit.agent,
|
|
33675
|
+
vectorStoreId: cachedAgentKit.vectorStoreId,
|
|
33676
|
+
};
|
|
32476
33677
|
}
|
|
32477
|
-
|
|
33678
|
+
if (!preparedAgentKit) {
|
|
32478
33679
|
if (this.options.isVerbose) {
|
|
32479
|
-
console.
|
|
32480
|
-
|
|
32481
|
-
|
|
32482
|
-
if (modelRequirements.knowledgeSources && modelRequirements.knowledgeSources.length > 0) {
|
|
32483
|
-
const client = await this.options.llmTools.getClient();
|
|
32484
|
-
vectorStoreId = await OpenAiAgentExecutionTools.createVectorStore(client, this.title, modelRequirements.knowledgeSources);
|
|
33680
|
+
console.info('[🤰]', 'Preparing OpenAI AgentKit agent', {
|
|
33681
|
+
agent: this.title,
|
|
33682
|
+
});
|
|
32485
33683
|
}
|
|
32486
|
-
if (vectorStoreId) {
|
|
32487
|
-
|
|
32488
|
-
|
|
32489
|
-
|
|
33684
|
+
if (!vectorStoreId && ((_b = sanitizedRequirements.knowledgeSources) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
33685
|
+
emitAssistantPreparationProgress({
|
|
33686
|
+
onProgress,
|
|
33687
|
+
prompt,
|
|
33688
|
+
modelName: this.modelName,
|
|
33689
|
+
phase: 'Creating knowledge base',
|
|
32490
33690
|
});
|
|
32491
33691
|
}
|
|
32492
|
-
|
|
32493
|
-
|
|
33692
|
+
emitAssistantPreparationProgress({
|
|
33693
|
+
onProgress,
|
|
33694
|
+
prompt,
|
|
33695
|
+
modelName: this.modelName,
|
|
33696
|
+
phase: 'Preparing AgentKit agent',
|
|
33697
|
+
});
|
|
33698
|
+
preparedAgentKit = await this.options.llmTools.prepareAgentKitAgent({
|
|
33699
|
+
name: this.title,
|
|
33700
|
+
instructions: sanitizedRequirements.systemMessage || '',
|
|
33701
|
+
knowledgeSources: sanitizedRequirements.knowledgeSources,
|
|
33702
|
+
tools: sanitizedRequirements.tools ? [...sanitizedRequirements.tools] : undefined,
|
|
32494
33703
|
vectorStoreId,
|
|
32495
33704
|
});
|
|
32496
33705
|
}
|
|
32497
|
-
|
|
32498
|
-
|
|
32499
|
-
|
|
32500
|
-
|
|
32501
|
-
|
|
32502
|
-
|
|
32503
|
-
|
|
32504
|
-
|
|
32505
|
-
|
|
32506
|
-
|
|
32507
|
-
|
|
32508
|
-
|
|
32509
|
-
|
|
32510
|
-
|
|
33706
|
+
if (preparedAgentKit.vectorStoreId) {
|
|
33707
|
+
AgentLlmExecutionTools.vectorStoreCache.set(this.title, {
|
|
33708
|
+
vectorStoreId: preparedAgentKit.vectorStoreId,
|
|
33709
|
+
requirementsHash: vectorStoreHash,
|
|
33710
|
+
});
|
|
33711
|
+
}
|
|
33712
|
+
AgentLlmExecutionTools.agentKitAgentCache.set(this.title, {
|
|
33713
|
+
agent: preparedAgentKit.agent,
|
|
33714
|
+
requirementsHash,
|
|
33715
|
+
vectorStoreId: preparedAgentKit.vectorStoreId,
|
|
33716
|
+
});
|
|
33717
|
+
const responseFormatOutputType = mapResponseFormatToAgentOutputType(promptWithAgentModelRequirements.modelRequirements.responseFormat);
|
|
33718
|
+
underlyingLlmResult = await this.options.llmTools.callChatModelStreamWithPreparedAgent({
|
|
33719
|
+
openAiAgentKitAgent: preparedAgentKit.agent,
|
|
33720
|
+
prompt: promptWithAgentModelRequirements,
|
|
33721
|
+
onProgress,
|
|
33722
|
+
responseFormatOutputType,
|
|
33723
|
+
});
|
|
32511
33724
|
}
|
|
32512
33725
|
else if (OpenAiAssistantExecutionTools.isOpenAiAssistantExecutionTools(this.options.llmTools)) {
|
|
32513
33726
|
// ... deprecated path ...
|
|
32514
|
-
const requirementsHash = SHA256(JSON.stringify(
|
|
33727
|
+
const requirementsHash = SHA256(JSON.stringify(sanitizedRequirements)).toString();
|
|
32515
33728
|
const cached = AgentLlmExecutionTools.assistantCache.get(this.title);
|
|
32516
33729
|
let assistant;
|
|
32517
|
-
if (
|
|
33730
|
+
if (this.options.assistantPreparationMode === 'external') {
|
|
33731
|
+
assistant = this.options.llmTools;
|
|
33732
|
+
if (this.options.isVerbose) {
|
|
33733
|
+
console.info('[🤰]', 'Using externally managed OpenAI Assistant', {
|
|
33734
|
+
agent: this.title,
|
|
33735
|
+
assistantId: assistant.assistantId,
|
|
33736
|
+
});
|
|
33737
|
+
}
|
|
33738
|
+
AgentLlmExecutionTools.assistantCache.set(this.title, {
|
|
33739
|
+
assistantId: assistant.assistantId,
|
|
33740
|
+
requirementsHash,
|
|
33741
|
+
});
|
|
33742
|
+
}
|
|
33743
|
+
else if (cached) {
|
|
32518
33744
|
if (cached.requirementsHash === requirementsHash) {
|
|
32519
33745
|
if (this.options.isVerbose) {
|
|
32520
33746
|
console.info('[🤰]', 'Using cached OpenAI Assistant', {
|
|
@@ -32540,9 +33766,9 @@ class AgentLlmExecutionTools {
|
|
|
32540
33766
|
assistant = await this.options.llmTools.updateAssistant({
|
|
32541
33767
|
assistantId: cached.assistantId,
|
|
32542
33768
|
name: this.title,
|
|
32543
|
-
instructions:
|
|
32544
|
-
knowledgeSources:
|
|
32545
|
-
tools:
|
|
33769
|
+
instructions: sanitizedRequirements.systemMessage,
|
|
33770
|
+
knowledgeSources: sanitizedRequirements.knowledgeSources,
|
|
33771
|
+
tools: sanitizedRequirements.tools ? [...sanitizedRequirements.tools] : undefined,
|
|
32546
33772
|
});
|
|
32547
33773
|
AgentLlmExecutionTools.assistantCache.set(this.title, {
|
|
32548
33774
|
assistantId: assistant.assistantId,
|
|
@@ -32565,9 +33791,9 @@ class AgentLlmExecutionTools {
|
|
|
32565
33791
|
});
|
|
32566
33792
|
assistant = await this.options.llmTools.createNewAssistant({
|
|
32567
33793
|
name: this.title,
|
|
32568
|
-
instructions:
|
|
32569
|
-
knowledgeSources:
|
|
32570
|
-
tools:
|
|
33794
|
+
instructions: sanitizedRequirements.systemMessage,
|
|
33795
|
+
knowledgeSources: sanitizedRequirements.knowledgeSources,
|
|
33796
|
+
tools: sanitizedRequirements.tools ? [...sanitizedRequirements.tools] : undefined,
|
|
32571
33797
|
/*
|
|
32572
33798
|
!!!
|
|
32573
33799
|
metadata: {
|
|
@@ -32609,18 +33835,28 @@ class AgentLlmExecutionTools {
|
|
|
32609
33835
|
}
|
|
32610
33836
|
}
|
|
32611
33837
|
let content = underlyingLlmResult.content;
|
|
32612
|
-
|
|
32613
|
-
|
|
32614
|
-
|
|
32615
|
-
|
|
33838
|
+
if (typeof content === 'string') {
|
|
33839
|
+
// Note: Cleanup the AI artifacts from the content
|
|
33840
|
+
content = humanizeAiText(content);
|
|
33841
|
+
// Note: Make sure the content is Promptbook-like
|
|
33842
|
+
content = promptbookifyAiText(content);
|
|
33843
|
+
}
|
|
33844
|
+
else {
|
|
33845
|
+
// TODO: Maybe deep `humanizeAiText` + `promptbookifyAiText` inside of the object
|
|
33846
|
+
content = JSON.stringify(content);
|
|
33847
|
+
}
|
|
32616
33848
|
const agentResult = {
|
|
32617
33849
|
...underlyingLlmResult,
|
|
32618
|
-
content,
|
|
33850
|
+
content: content,
|
|
32619
33851
|
modelName: this.modelName,
|
|
32620
33852
|
};
|
|
32621
33853
|
return agentResult;
|
|
32622
33854
|
}
|
|
32623
33855
|
}
|
|
33856
|
+
/**
|
|
33857
|
+
* Cached AgentKit agents to avoid rebuilding identical instances.
|
|
33858
|
+
*/
|
|
33859
|
+
AgentLlmExecutionTools.agentKitAgentCache = new Map();
|
|
32624
33860
|
/**
|
|
32625
33861
|
* Cache of OpenAI assistants to avoid creating duplicates
|
|
32626
33862
|
*/
|
|
@@ -32701,8 +33937,8 @@ function buildTeacherSummary(commitments, used) {
|
|
|
32701
33937
|
* - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
|
|
32702
33938
|
* - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
|
|
32703
33939
|
* - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
|
|
32704
|
-
* - `OpenAiAgentExecutionTools` - which is a specific implementation of `LlmExecutionTools` for OpenAI models with agent capabilities (using Responses API), recommended for usage in `Agent` or `AgentLlmExecutionTools`
|
|
32705
33940
|
* - `OpenAiAssistantExecutionTools` - (Deprecated) which is a specific implementation of `LlmExecutionTools` for OpenAI models with assistant capabilities
|
|
33941
|
+
* - `OpenAiAgentKitExecutionTools` - which is a specific implementation of `LlmExecutionTools` backed by OpenAI AgentKit
|
|
32706
33942
|
* - `RemoteAgent` - which is an `Agent` that connects to a Promptbook Agents Server
|
|
32707
33943
|
*
|
|
32708
33944
|
* @public exported from `@promptbook/core`
|
|
@@ -32733,6 +33969,7 @@ class Agent extends AgentLlmExecutionTools {
|
|
|
32733
33969
|
super({
|
|
32734
33970
|
isVerbose: options.isVerbose,
|
|
32735
33971
|
llmTools: getSingleLlmExecutionTools(options.executionTools.llm),
|
|
33972
|
+
assistantPreparationMode: options.assistantPreparationMode,
|
|
32736
33973
|
agentSource: agentSource.value, // <- TODO: [🐱🚀] Allow to pass BehaviorSubject<string_book> OR refresh llmExecutionTools.callChat on agentSource change
|
|
32737
33974
|
});
|
|
32738
33975
|
_Agent_instances.add(this);
|
|
@@ -32799,7 +34036,6 @@ class Agent extends AgentLlmExecutionTools {
|
|
|
32799
34036
|
* Note: This method also implements the learning mechanism
|
|
32800
34037
|
*/
|
|
32801
34038
|
async callChatModelStream(prompt, onProgress) {
|
|
32802
|
-
var _a;
|
|
32803
34039
|
// [1] Check if the user is asking the same thing as in the samples
|
|
32804
34040
|
const modelRequirements = await this.getModelRequirements();
|
|
32805
34041
|
if (modelRequirements.samples) {
|
|
@@ -32847,7 +34083,7 @@ class Agent extends AgentLlmExecutionTools {
|
|
|
32847
34083
|
if (result.rawResponse && 'sample' in result.rawResponse) {
|
|
32848
34084
|
return result;
|
|
32849
34085
|
}
|
|
32850
|
-
if (
|
|
34086
|
+
if (modelRequirements.isClosed) {
|
|
32851
34087
|
return result;
|
|
32852
34088
|
}
|
|
32853
34089
|
// Note: [0] Notify start of self-learning
|
|
@@ -33008,6 +34244,63 @@ async function _Agent_selfLearnTeacher(prompt, result) {
|
|
|
33008
34244
|
* TODO: [🧠][😰]Agent is not working with the parameters, should it be?
|
|
33009
34245
|
*/
|
|
33010
34246
|
|
|
34247
|
+
/**
|
|
34248
|
+
* Resolve a remote META IMAGE value into an absolute URL when possible.
|
|
34249
|
+
*/
|
|
34250
|
+
function resolveRemoteImageUrl(imageUrl, agentUrl) {
|
|
34251
|
+
if (!imageUrl) {
|
|
34252
|
+
return undefined;
|
|
34253
|
+
}
|
|
34254
|
+
if (imageUrl.startsWith('http://') ||
|
|
34255
|
+
imageUrl.startsWith('https://') ||
|
|
34256
|
+
imageUrl.startsWith('data:') ||
|
|
34257
|
+
imageUrl.startsWith('blob:')) {
|
|
34258
|
+
return imageUrl;
|
|
34259
|
+
}
|
|
34260
|
+
try {
|
|
34261
|
+
return new URL(imageUrl, agentUrl).href;
|
|
34262
|
+
}
|
|
34263
|
+
catch (_a) {
|
|
34264
|
+
return imageUrl;
|
|
34265
|
+
}
|
|
34266
|
+
}
|
|
34267
|
+
/**
|
|
34268
|
+
* Format a META commitment line when the value is provided.
|
|
34269
|
+
*/
|
|
34270
|
+
function formatMetaLine(label, value) {
|
|
34271
|
+
if (!value) {
|
|
34272
|
+
return null;
|
|
34273
|
+
}
|
|
34274
|
+
return `META ${label} ${value}`;
|
|
34275
|
+
}
|
|
34276
|
+
/**
|
|
34277
|
+
* Build a minimal agent source snapshot for remote agents.
|
|
34278
|
+
*/
|
|
34279
|
+
function buildRemoteAgentSource(profile, meta) {
|
|
34280
|
+
const metaLines = [
|
|
34281
|
+
formatMetaLine('FULLNAME', meta === null || meta === void 0 ? void 0 : meta.fullname),
|
|
34282
|
+
formatMetaLine('IMAGE', meta === null || meta === void 0 ? void 0 : meta.image),
|
|
34283
|
+
formatMetaLine('DESCRIPTION', meta === null || meta === void 0 ? void 0 : meta.description),
|
|
34284
|
+
formatMetaLine('COLOR', meta === null || meta === void 0 ? void 0 : meta.color),
|
|
34285
|
+
formatMetaLine('FONT', meta === null || meta === void 0 ? void 0 : meta.font),
|
|
34286
|
+
formatMetaLine('LINK', meta === null || meta === void 0 ? void 0 : meta.link),
|
|
34287
|
+
]
|
|
34288
|
+
.filter((line) => Boolean(line))
|
|
34289
|
+
.join('\n');
|
|
34290
|
+
const personaBlock = profile.personaDescription
|
|
34291
|
+
? spaceTrim$2((block) => `
|
|
34292
|
+
PERSONA
|
|
34293
|
+
${block(profile.personaDescription || '')}
|
|
34294
|
+
`)
|
|
34295
|
+
: '';
|
|
34296
|
+
return book `
|
|
34297
|
+
${profile.agentName}
|
|
34298
|
+
|
|
34299
|
+
${metaLines}
|
|
34300
|
+
|
|
34301
|
+
${personaBlock}
|
|
34302
|
+
`;
|
|
34303
|
+
}
|
|
33011
34304
|
/**
|
|
33012
34305
|
* Represents one AI Agent
|
|
33013
34306
|
*
|
|
@@ -33015,13 +34308,15 @@ async function _Agent_selfLearnTeacher(prompt, result) {
|
|
|
33015
34308
|
* - `Agent` - which represents an AI Agent with its source, memories, actions, etc. Agent is a higher-level abstraction which is internally using:
|
|
33016
34309
|
* - `LlmExecutionTools` - which wraps one or more LLM models and provides an interface to execute them
|
|
33017
34310
|
* - `AgentLlmExecutionTools` - which is a specific implementation of `LlmExecutionTools` that wraps another LlmExecutionTools and applies agent-specific system prompts and requirements
|
|
33018
|
-
* - `OpenAiAssistantExecutionTools` - which is a specific implementation of `LlmExecutionTools` for OpenAI models with assistant capabilities
|
|
34311
|
+
* - `OpenAiAssistantExecutionTools` - (Deprecated) which is a specific implementation of `LlmExecutionTools` for OpenAI models with assistant capabilities
|
|
34312
|
+
* - `OpenAiAgentKitExecutionTools` - which is a specific implementation of `LlmExecutionTools` backed by OpenAI AgentKit
|
|
33019
34313
|
* - `RemoteAgent` - which is an `Agent` that connects to a Promptbook Agents Server
|
|
33020
34314
|
*
|
|
33021
34315
|
* @public exported from `@promptbook/core`
|
|
33022
34316
|
*/
|
|
33023
34317
|
class RemoteAgent extends Agent {
|
|
33024
34318
|
static async connect(options) {
|
|
34319
|
+
var _a, _b, _c;
|
|
33025
34320
|
const agentProfileUrl = `${options.agentUrl}/api/profile`;
|
|
33026
34321
|
const profileResponse = await fetch(agentProfileUrl);
|
|
33027
34322
|
// <- TODO: [🐱🚀] What about closed-source agents?
|
|
@@ -33041,14 +34336,14 @@ class RemoteAgent extends Agent {
|
|
|
33041
34336
|
|
|
33042
34337
|
`));
|
|
33043
34338
|
}
|
|
33044
|
-
const profile = await profileResponse.json();
|
|
34339
|
+
const profile = (await profileResponse.json());
|
|
34340
|
+
const resolvedMeta = {
|
|
34341
|
+
...(profile.meta || {}),
|
|
34342
|
+
image: resolveRemoteImageUrl((_a = profile.meta) === null || _a === void 0 ? void 0 : _a.image, options.agentUrl),
|
|
34343
|
+
};
|
|
33045
34344
|
// Note: We are creating dummy agent source because we don't have the source from the remote agent
|
|
33046
34345
|
// But we populate the metadata from the profile
|
|
33047
|
-
const agentSource = new BehaviorSubject(
|
|
33048
|
-
${profile.agentName}
|
|
33049
|
-
|
|
33050
|
-
${profile.personaDescription}
|
|
33051
|
-
`);
|
|
34346
|
+
const agentSource = new BehaviorSubject(buildRemoteAgentSource(profile, resolvedMeta));
|
|
33052
34347
|
// <- TODO: [🐱🚀] createBookFromProfile
|
|
33053
34348
|
// <- TODO: [🐱🚀] Support updating and self-updating
|
|
33054
34349
|
const remoteAgent = new RemoteAgent({
|
|
@@ -33071,10 +34366,10 @@ class RemoteAgent extends Agent {
|
|
|
33071
34366
|
});
|
|
33072
34367
|
remoteAgent._remoteAgentName = profile.agentName;
|
|
33073
34368
|
remoteAgent._remoteAgentHash = profile.agentHash;
|
|
33074
|
-
remoteAgent.personaDescription = profile.personaDescription;
|
|
33075
|
-
remoteAgent.initialMessage = profile.initialMessage;
|
|
33076
|
-
remoteAgent.links = profile.links;
|
|
33077
|
-
remoteAgent.meta =
|
|
34369
|
+
remoteAgent.personaDescription = (_b = profile.personaDescription) !== null && _b !== void 0 ? _b : null;
|
|
34370
|
+
remoteAgent.initialMessage = (_c = profile.initialMessage) !== null && _c !== void 0 ? _c : null;
|
|
34371
|
+
remoteAgent.links = profile.links || [];
|
|
34372
|
+
remoteAgent.meta = resolvedMeta;
|
|
33078
34373
|
remoteAgent.capabilities = profile.capabilities || [];
|
|
33079
34374
|
remoteAgent.samples = profile.samples || [];
|
|
33080
34375
|
remoteAgent.toolTitles = profile.toolTitles || {};
|
|
@@ -33178,26 +34473,7 @@ class RemoteAgent extends Agent {
|
|
|
33178
34473
|
};
|
|
33179
34474
|
};
|
|
33180
34475
|
const getToolCallKey = (toolCall) => {
|
|
33181
|
-
|
|
33182
|
-
const rawId = (_a = toolCall.rawToolCall) === null || _a === void 0 ? void 0 : _a.id;
|
|
33183
|
-
if (rawId) {
|
|
33184
|
-
return `id:${rawId}`;
|
|
33185
|
-
}
|
|
33186
|
-
const argsKey = (() => {
|
|
33187
|
-
if (typeof toolCall.arguments === 'string') {
|
|
33188
|
-
return toolCall.arguments;
|
|
33189
|
-
}
|
|
33190
|
-
if (!toolCall.arguments) {
|
|
33191
|
-
return '';
|
|
33192
|
-
}
|
|
33193
|
-
try {
|
|
33194
|
-
return JSON.stringify(toolCall.arguments);
|
|
33195
|
-
}
|
|
33196
|
-
catch (_a) {
|
|
33197
|
-
return '';
|
|
33198
|
-
}
|
|
33199
|
-
})();
|
|
33200
|
-
return `${toolCall.name}:${toolCall.createdAt || ''}:${argsKey}`;
|
|
34476
|
+
return getToolCallIdentity(toolCall);
|
|
33201
34477
|
};
|
|
33202
34478
|
const mergeToolCall = (existing, incoming) => {
|
|
33203
34479
|
const incomingResult = incoming.result;
|