@memberjunction/ai-agents 3.0.0 → 3.1.1
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/dist/AgentRunner.d.ts +4 -1
- package/dist/AgentRunner.d.ts.map +1 -1
- package/dist/AgentRunner.js +169 -0
- package/dist/AgentRunner.js.map +1 -1
- package/dist/base-agent.d.ts +10 -1
- package/dist/base-agent.d.ts.map +1 -1
- package/dist/base-agent.js +197 -7
- package/dist/base-agent.js.map +1 -1
- package/package.json +11 -11
- package/dist/services/AgentEmbeddingService.d.ts +0 -16
- package/dist/services/AgentEmbeddingService.d.ts.map +0 -1
- package/dist/services/AgentEmbeddingService.js +0 -158
- package/dist/services/AgentEmbeddingService.js.map +0 -1
- package/dist/types/AgentMatchResult.d.ts +0 -18
- package/dist/types/AgentMatchResult.d.ts.map +0 -1
- package/dist/types/AgentMatchResult.js +0 -3
- package/dist/types/AgentMatchResult.js.map +0 -1
package/dist/base-agent.js
CHANGED
|
@@ -52,6 +52,7 @@ class BaseAgent {
|
|
|
52
52
|
this._parentStepCounts = [];
|
|
53
53
|
this._allProgressSteps = [];
|
|
54
54
|
this._subAgentRuns = [];
|
|
55
|
+
this._mediaOutputs = [];
|
|
55
56
|
this._payloadManager = new PayloadManager_1.PayloadManager();
|
|
56
57
|
this._effectiveActions = [];
|
|
57
58
|
this._dynamicActionLimits = {};
|
|
@@ -82,6 +83,163 @@ class BaseAgent {
|
|
|
82
83
|
}
|
|
83
84
|
return aiengine_1.AIEngine.Instance.GetDefaultAgentConfigurationPreset(agentId);
|
|
84
85
|
}
|
|
86
|
+
promoteMediaOutputs(mediaOutputs) {
|
|
87
|
+
if (mediaOutputs && mediaOutputs.length > 0) {
|
|
88
|
+
this._mediaOutputs.push(...mediaOutputs);
|
|
89
|
+
this.logStatus(`📎 Promoted ${mediaOutputs.length} media output(s) to agent results`, true);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
get MediaOutputs() {
|
|
93
|
+
return [...this._mediaOutputs];
|
|
94
|
+
}
|
|
95
|
+
interceptLargeBinaryContent(actionParams, actionEntity) {
|
|
96
|
+
if (!actionParams || actionParams.length === 0) {
|
|
97
|
+
return actionParams;
|
|
98
|
+
}
|
|
99
|
+
const sanitizedParams = [];
|
|
100
|
+
for (const param of actionParams) {
|
|
101
|
+
if (param.Type !== 'Output' && param.Type !== 'Both') {
|
|
102
|
+
sanitizedParams.push(param);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const paramMetadata = actionEntity?.Params?.find(p => p.Name === param.Name);
|
|
106
|
+
const valueType = paramMetadata?.ValueType;
|
|
107
|
+
const isMediaOutputParam = valueType === 'MediaOutput';
|
|
108
|
+
if (isMediaOutputParam && Array.isArray(param.Value)) {
|
|
109
|
+
const mediaItems = param.Value;
|
|
110
|
+
const references = [];
|
|
111
|
+
let extractedCount = 0;
|
|
112
|
+
for (let i = 0; i < mediaItems.length; i++) {
|
|
113
|
+
const media = mediaItems[i];
|
|
114
|
+
if (media.data && media.data.length > BaseAgent.LARGE_BINARY_THRESHOLD) {
|
|
115
|
+
const refId = `media-${Date.now().toString(36)}-${i}-${Math.random().toString(36).substring(2, 8)}`;
|
|
116
|
+
this._mediaOutputs.push({
|
|
117
|
+
...media,
|
|
118
|
+
refId,
|
|
119
|
+
persist: false
|
|
120
|
+
});
|
|
121
|
+
references.push(`\${media:${refId}}`);
|
|
122
|
+
extractedCount++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (extractedCount > 0) {
|
|
126
|
+
sanitizedParams.push({
|
|
127
|
+
Name: param.Name,
|
|
128
|
+
Type: param.Type,
|
|
129
|
+
Value: {
|
|
130
|
+
mediaReferences: references,
|
|
131
|
+
count: mediaItems.length,
|
|
132
|
+
note: `${extractedCount} media item(s) extracted. Use placeholder syntax in your response: <img src="${references[0]}" alt="description" />`
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
this.logStatus(`📦 Extracted ${extractedCount} ${param.Name} item(s) to media references`, true);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (typeof param.Value === 'string' && param.Value.length > BaseAgent.LARGE_BINARY_THRESHOLD) {
|
|
140
|
+
const base64Pattern = /^[A-Za-z0-9+/]+=*$/;
|
|
141
|
+
if (isMediaOutputParam || base64Pattern.test(param.Value.substring(0, 1000))) {
|
|
142
|
+
const refId = `data-${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 8)}`;
|
|
143
|
+
this._mediaOutputs.push({
|
|
144
|
+
modality: 'Image',
|
|
145
|
+
mimeType: 'application/octet-stream',
|
|
146
|
+
data: param.Value,
|
|
147
|
+
label: `Media data from ${param.Name}`,
|
|
148
|
+
refId,
|
|
149
|
+
persist: false
|
|
150
|
+
});
|
|
151
|
+
sanitizedParams.push({
|
|
152
|
+
Name: param.Name,
|
|
153
|
+
Type: param.Type,
|
|
154
|
+
Value: `\${media:${refId}}`
|
|
155
|
+
});
|
|
156
|
+
this.logStatus(`📦 Extracted large binary content from '${param.Name}' to media reference`, true);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
sanitizedParams.push(param);
|
|
161
|
+
}
|
|
162
|
+
return sanitizedParams;
|
|
163
|
+
}
|
|
164
|
+
resolveMediaPlaceholdersInString(text) {
|
|
165
|
+
const hasRefIds = this._mediaOutputs.some(m => m.refId);
|
|
166
|
+
if (!text || !hasRefIds) {
|
|
167
|
+
return text;
|
|
168
|
+
}
|
|
169
|
+
const placeholderRegex = /\$\{media:([a-z0-9-]+)\}/g;
|
|
170
|
+
return text.replace(placeholderRegex, (match, refId) => {
|
|
171
|
+
const media = this._mediaOutputs.find(m => m.refId === refId);
|
|
172
|
+
if (media?.data) {
|
|
173
|
+
media.persist = true;
|
|
174
|
+
return `data:${media.mimeType};base64,${media.data}`;
|
|
175
|
+
}
|
|
176
|
+
this.logStatus(`⚠️ Media reference '${refId}' not found in registry`, true);
|
|
177
|
+
return match;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
resolveMediaPlaceholdersInPayload(payload) {
|
|
181
|
+
const hasRefIds = this._mediaOutputs.some(m => m.refId);
|
|
182
|
+
if (!hasRefIds) {
|
|
183
|
+
return payload;
|
|
184
|
+
}
|
|
185
|
+
const unpersisted = this._mediaOutputs.filter(m => m.refId && m.persist === false).length;
|
|
186
|
+
const resolved = this.resolveMediaPlaceholdersRecursive(payload);
|
|
187
|
+
const persistedAfter = this._mediaOutputs.filter(m => m.refId && m.persist === true).length;
|
|
188
|
+
const resolvedCount = persistedAfter - (unpersisted - this._mediaOutputs.filter(m => m.refId && m.persist === false).length);
|
|
189
|
+
if (resolvedCount > 0) {
|
|
190
|
+
this.logStatus(`✅ Resolved ${resolvedCount} media placeholder(s) in final payload`, true);
|
|
191
|
+
}
|
|
192
|
+
return resolved;
|
|
193
|
+
}
|
|
194
|
+
resolveMediaPlaceholdersRecursive(value) {
|
|
195
|
+
if (value === null || value === undefined) {
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
if (typeof value === 'string') {
|
|
199
|
+
return this.resolveMediaPlaceholdersInString(value);
|
|
200
|
+
}
|
|
201
|
+
if (Array.isArray(value)) {
|
|
202
|
+
return value.map(item => this.resolveMediaPlaceholdersRecursive(item));
|
|
203
|
+
}
|
|
204
|
+
if (typeof value === 'object') {
|
|
205
|
+
const result = {};
|
|
206
|
+
for (const key of Object.keys(value)) {
|
|
207
|
+
result[key] = this.resolveMediaPlaceholdersRecursive(value[key]);
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
return value;
|
|
212
|
+
}
|
|
213
|
+
processMessageMediaPlaceholders(message) {
|
|
214
|
+
if (!message) {
|
|
215
|
+
return message;
|
|
216
|
+
}
|
|
217
|
+
const hasRefIds = this._mediaOutputs.some(m => m.refId);
|
|
218
|
+
if (!hasRefIds) {
|
|
219
|
+
return message;
|
|
220
|
+
}
|
|
221
|
+
const placeholderRegex = /\$\{media:([a-zA-Z0-9_-]+)\}/g;
|
|
222
|
+
let match;
|
|
223
|
+
let promotedCount = 0;
|
|
224
|
+
while ((match = placeholderRegex.exec(message)) !== null) {
|
|
225
|
+
const refId = match[1];
|
|
226
|
+
const media = this._mediaOutputs.find(m => m.refId === refId);
|
|
227
|
+
if (media && media.persist !== true) {
|
|
228
|
+
media.persist = true;
|
|
229
|
+
promotedCount++;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (promotedCount > 0) {
|
|
233
|
+
this.logStatus(`📎 Auto-promoted ${promotedCount} media output(s) from message placeholders`, true);
|
|
234
|
+
}
|
|
235
|
+
let cleanedMessage = message
|
|
236
|
+
.replace(/<img[^>]*src=["']\$\{media:[^}]+\}["'][^>]*\/?>/gi, '')
|
|
237
|
+
.replace(/<audio[^>]*src=["']\$\{media:[^}]+\}["'][^>]*>.*?<\/audio>/gi, '')
|
|
238
|
+
.replace(/<video[^>]*src=["']\$\{media:[^}]+\}["'][^>]*>.*?<\/video>/gi, '')
|
|
239
|
+
.replace(/\n\s*\n\s*\n/g, '\n\n')
|
|
240
|
+
.trim();
|
|
241
|
+
return cleanedMessage;
|
|
242
|
+
}
|
|
85
243
|
get ValidationRetryCount() {
|
|
86
244
|
return this._validationRetryCount;
|
|
87
245
|
}
|
|
@@ -241,6 +399,7 @@ class BaseAgent {
|
|
|
241
399
|
this._contextRecoveryAttempts = 0;
|
|
242
400
|
this._effectiveActions = [];
|
|
243
401
|
this._dynamicActionLimits = {};
|
|
402
|
+
this._mediaOutputs = [];
|
|
244
403
|
this._messageLifecycleCallback = params.onMessageLifecycle;
|
|
245
404
|
await this.initializeEngines(params.contextUser);
|
|
246
405
|
if (params.cancellationToken?.aborted) {
|
|
@@ -321,6 +480,9 @@ class BaseAgent {
|
|
|
321
480
|
this.logStatus(`🔄 Executing step ${stepCount + 1} for agent '${params.agent.Name}'`, true, params);
|
|
322
481
|
const nextStep = await this.executeNextStep(params, config, currentNextStep, stepCount);
|
|
323
482
|
stepCount++;
|
|
483
|
+
if (nextStep.promoteMediaOutputs && nextStep.promoteMediaOutputs.length > 0) {
|
|
484
|
+
this.promoteMediaOutputs(nextStep.promoteMediaOutputs);
|
|
485
|
+
}
|
|
324
486
|
if (nextStep.terminate) {
|
|
325
487
|
continueExecution = false;
|
|
326
488
|
this.logStatus(`🏁 Agent '${params.agent.Name}' terminating after ${stepCount} steps with result: ${nextStep.step}`, true, params);
|
|
@@ -2822,6 +2984,13 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
2822
2984
|
throw new Error('Cancelled during sub-agent execution');
|
|
2823
2985
|
}
|
|
2824
2986
|
this._subAgentRuns.push(subAgentResult);
|
|
2987
|
+
if (subAgentResult.mediaOutputs?.length) {
|
|
2988
|
+
this._mediaOutputs.push(...subAgentResult.mediaOutputs);
|
|
2989
|
+
const refCount = subAgentResult.mediaOutputs.filter(m => m.refId).length;
|
|
2990
|
+
if (refCount > 0) {
|
|
2991
|
+
this.logStatus(`📦 Collected ${refCount} media reference(s) from sub-agent '${subAgentRequest.name}'`, true);
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2825
2994
|
const shouldTerminate = subAgentRequest.terminateAfter;
|
|
2826
2995
|
const outputData = {
|
|
2827
2996
|
subAgentResult: {
|
|
@@ -3006,6 +3175,13 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
3006
3175
|
(0, core_1.LogStatus)(`Related sub-agent '${subAgentRequest.name}' receiving context from paths: ${contextPaths.join(', ')}`);
|
|
3007
3176
|
}
|
|
3008
3177
|
const subAgentResult = await this.ExecuteSubAgent(params, subAgentRequest, subAgentEntity, stepEntity, initialSubAgentPayload, contextMessage, stepCount);
|
|
3178
|
+
if (subAgentResult.mediaOutputs?.length) {
|
|
3179
|
+
this._mediaOutputs.push(...subAgentResult.mediaOutputs);
|
|
3180
|
+
const refCount = subAgentResult.mediaOutputs.filter(m => m.refId).length;
|
|
3181
|
+
if (refCount > 0) {
|
|
3182
|
+
this.logStatus(`📦 Collected ${refCount} media reference(s) from related sub-agent '${subAgentRequest.name}'`, true);
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3009
3185
|
let mergedPayload = previousDecision.newPayload;
|
|
3010
3186
|
let currentStepPayloadChangeResult = undefined;
|
|
3011
3187
|
if (subAgentResult.success && relationship.SubAgentOutputMapping) {
|
|
@@ -3367,10 +3543,12 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
3367
3543
|
}
|
|
3368
3544
|
const actionSummaries = actionResults.map(result => {
|
|
3369
3545
|
const actionResult = result.success ? result.result : null;
|
|
3546
|
+
const outputParams = result.result?.Params?.filter(p => p.Type === 'Both' || p.Type === 'Output') || [];
|
|
3547
|
+
const sanitizedParams = this.interceptLargeBinaryContent(outputParams, result.actionEntity);
|
|
3370
3548
|
return {
|
|
3371
3549
|
actionName: result.action.name,
|
|
3372
3550
|
success: result.success,
|
|
3373
|
-
params:
|
|
3551
|
+
params: sanitizedParams,
|
|
3374
3552
|
resultCode: actionResult?.Result?.ResultCode || (result.success ? 'SUCCESS' : 'ERROR'),
|
|
3375
3553
|
message: result.success ? actionResult?.Message || 'Action completed' : result.error
|
|
3376
3554
|
};
|
|
@@ -3914,6 +4092,13 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
3914
4092
|
};
|
|
3915
4093
|
}
|
|
3916
4094
|
async finalizeAgentRun(finalStep, payload, contextUser) {
|
|
4095
|
+
const isRootAgent = this._depth === 0;
|
|
4096
|
+
const resolvedPayload = (payload && isRootAgent)
|
|
4097
|
+
? this.resolveMediaPlaceholdersInPayload(payload)
|
|
4098
|
+
: payload;
|
|
4099
|
+
const processedMessage = (finalStep.message && isRootAgent)
|
|
4100
|
+
? this.processMessageMediaPlaceholders(finalStep.message)
|
|
4101
|
+
: finalStep.message;
|
|
3917
4102
|
if (this._agentRun) {
|
|
3918
4103
|
this._agentRun.CompletedAt = new Date();
|
|
3919
4104
|
this._agentRun.Success = finalStep.step === 'Success' || finalStep.step === 'Chat';
|
|
@@ -3929,11 +4114,11 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
3929
4114
|
else {
|
|
3930
4115
|
this._agentRun.Status = 'Completed';
|
|
3931
4116
|
}
|
|
3932
|
-
this._agentRun.Result =
|
|
4117
|
+
this._agentRun.Result = resolvedPayload ? JSON.stringify(resolvedPayload) : null;
|
|
3933
4118
|
this._agentRun.FinalStep = finalStep.step;
|
|
3934
|
-
this._agentRun.Message =
|
|
3935
|
-
this._agentRun.FinalPayloadObject =
|
|
3936
|
-
this._agentRun.FinalPayload =
|
|
4119
|
+
this._agentRun.Message = processedMessage;
|
|
4120
|
+
this._agentRun.FinalPayloadObject = resolvedPayload;
|
|
4121
|
+
this._agentRun.FinalPayload = resolvedPayload ? JSON.stringify(resolvedPayload) : null;
|
|
3937
4122
|
const tokenStats = this.calculateTokenStats();
|
|
3938
4123
|
this._agentRun.TotalTokensUsed = tokenStats.totalTokens;
|
|
3939
4124
|
this._agentRun.TotalPromptTokensUsed = tokenStats.promptTokens;
|
|
@@ -3944,16 +4129,20 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
3944
4129
|
(0, core_1.LogError)(`Failed to finalize agent run ${this._agentRun.ID}`);
|
|
3945
4130
|
}
|
|
3946
4131
|
}
|
|
4132
|
+
if (finalStep.promoteMediaOutputs && finalStep.promoteMediaOutputs.length > 0) {
|
|
4133
|
+
this.promoteMediaOutputs(finalStep.promoteMediaOutputs);
|
|
4134
|
+
}
|
|
3947
4135
|
return {
|
|
3948
4136
|
success: finalStep.step === 'Success' || finalStep.step === 'Chat',
|
|
3949
|
-
payload,
|
|
4137
|
+
payload: resolvedPayload,
|
|
3950
4138
|
agentRun: this._agentRun,
|
|
3951
4139
|
responseForm: finalStep.responseForm,
|
|
3952
4140
|
actionableCommands: finalStep.actionableCommands,
|
|
3953
4141
|
automaticCommands: finalStep.automaticCommands,
|
|
3954
4142
|
memoryContext: this._injectedMemory.notes.length > 0 || this._injectedMemory.examples.length > 0
|
|
3955
4143
|
? this._injectedMemory
|
|
3956
|
-
: undefined
|
|
4144
|
+
: undefined,
|
|
4145
|
+
mediaOutputs: this._mediaOutputs.length > 0 ? this._mediaOutputs : undefined
|
|
3957
4146
|
};
|
|
3958
4147
|
}
|
|
3959
4148
|
calculateTokenStats() {
|
|
@@ -4378,4 +4567,5 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
4378
4567
|
}
|
|
4379
4568
|
exports.BaseAgent = BaseAgent;
|
|
4380
4569
|
BaseAgent.MAX_VALIDATION_RETRIES = 10;
|
|
4570
|
+
BaseAgent.LARGE_BINARY_THRESHOLD = 10000;
|
|
4381
4571
|
//# sourceMappingURL=base-agent.js.map
|