@memberjunction/ai-agents 5.28.0 → 5.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AgentRunner.d.ts +39 -0
- package/dist/AgentRunner.d.ts.map +1 -1
- package/dist/AgentRunner.js +301 -6
- package/dist/AgentRunner.js.map +1 -1
- package/dist/ArtifactToolManager.d.ts +165 -0
- package/dist/ArtifactToolManager.d.ts.map +1 -0
- package/dist/ArtifactToolManager.js +534 -0
- package/dist/ArtifactToolManager.js.map +1 -0
- package/dist/agent-types/loop-agent-prompt-params.d.ts +14 -0
- package/dist/agent-types/loop-agent-prompt-params.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-prompt-params.js +3 -1
- package/dist/agent-types/loop-agent-prompt-params.js.map +1 -1
- package/dist/agent-types/loop-agent-response-type.d.ts +9 -1
- package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-response-type.js.map +1 -1
- package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-type.js +3 -0
- package/dist/agent-types/loop-agent-type.js.map +1 -1
- package/dist/artifact-tools/DataSnapshotToolLibrary.d.ts +18 -0
- package/dist/artifact-tools/DataSnapshotToolLibrary.d.ts.map +1 -0
- package/dist/artifact-tools/DataSnapshotToolLibrary.js +365 -0
- package/dist/artifact-tools/DataSnapshotToolLibrary.js.map +1 -0
- package/dist/artifact-tools/DocxToolLibrary.d.ts +15 -0
- package/dist/artifact-tools/DocxToolLibrary.d.ts.map +1 -0
- package/dist/artifact-tools/DocxToolLibrary.js +160 -0
- package/dist/artifact-tools/DocxToolLibrary.js.map +1 -0
- package/dist/artifact-tools/ExcelToolLibrary.d.ts +16 -0
- package/dist/artifact-tools/ExcelToolLibrary.d.ts.map +1 -0
- package/dist/artifact-tools/ExcelToolLibrary.js +300 -0
- package/dist/artifact-tools/ExcelToolLibrary.js.map +1 -0
- package/dist/artifact-tools/JSONToolLibrary.d.ts +18 -0
- package/dist/artifact-tools/JSONToolLibrary.d.ts.map +1 -0
- package/dist/artifact-tools/JSONToolLibrary.js +178 -0
- package/dist/artifact-tools/JSONToolLibrary.js.map +1 -0
- package/dist/artifact-tools/PDFToolLibrary.d.ts +14 -0
- package/dist/artifact-tools/PDFToolLibrary.d.ts.map +1 -0
- package/dist/artifact-tools/PDFToolLibrary.js +172 -0
- package/dist/artifact-tools/PDFToolLibrary.js.map +1 -0
- package/dist/artifact-tools/TextToolLibrary.d.ts +12 -0
- package/dist/artifact-tools/TextToolLibrary.d.ts.map +1 -0
- package/dist/artifact-tools/TextToolLibrary.js +82 -0
- package/dist/artifact-tools/TextToolLibrary.js.map +1 -0
- package/dist/base-agent.d.ts +12 -0
- package/dist/base-agent.d.ts.map +1 -1
- package/dist/base-agent.js +155 -9
- package/dist/base-agent.js.map +1 -1
- package/dist/file-input-resolver.d.ts +2 -0
- package/dist/file-input-resolver.d.ts.map +1 -0
- package/dist/file-input-resolver.js +4 -0
- package/dist/file-input-resolver.js.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/memory-cleanup-agent.d.ts +10 -3
- package/dist/memory-cleanup-agent.d.ts.map +1 -1
- package/dist/memory-cleanup-agent.js +10 -3
- package/dist/memory-cleanup-agent.js.map +1 -1
- package/dist/memory-manager-agent.d.ts +341 -7
- package/dist/memory-manager-agent.d.ts.map +1 -1
- package/dist/memory-manager-agent.js +1723 -373
- package/dist/memory-manager-agent.js.map +1 -1
- package/package.json +18 -15
package/dist/base-agent.js
CHANGED
|
@@ -24,6 +24,7 @@ import { AIPromptParams, ChildPromptParam, ConversationUtility, ParseFileOutputR
|
|
|
24
24
|
import { AgentRunner } from './AgentRunner.js';
|
|
25
25
|
import { PayloadManager } from './PayloadManager.js';
|
|
26
26
|
import { ScratchpadManager } from './ScratchpadManager.js';
|
|
27
|
+
import { ArtifactToolManager } from './ArtifactToolManager.js';
|
|
27
28
|
import { AgentDataPreloader } from './AgentDataPreloader.js';
|
|
28
29
|
import { ClientToolRequestManager } from './ClientToolRequestManager.js';
|
|
29
30
|
import { ConversationMessageResolver } from './utils/ConversationMessageResolver.js';
|
|
@@ -184,6 +185,11 @@ export class BaseAgent {
|
|
|
184
185
|
* @since 2.46.0
|
|
185
186
|
*/
|
|
186
187
|
this._scratchpadManager = new ScratchpadManager();
|
|
188
|
+
/**
|
|
189
|
+
* Manages artifact tools for the current agent run.
|
|
190
|
+
* Allows agents to explore input artifacts on demand.
|
|
191
|
+
*/
|
|
192
|
+
this._artifactToolManager = new ArtifactToolManager();
|
|
187
193
|
/**
|
|
188
194
|
* Effective actions available to this agent after applying actionChanges.
|
|
189
195
|
* Populated during gatherPromptTemplateData() and used for validation in executeActionsStep().
|
|
@@ -863,10 +869,59 @@ export class BaseAgent {
|
|
|
863
869
|
* });
|
|
864
870
|
* ```
|
|
865
871
|
*/
|
|
872
|
+
/**
|
|
873
|
+
* Engine-default wall-clock timeout applied to any agent run whose
|
|
874
|
+
* `ExecuteAgentParams.maxExecutionTimeMs` is not set. Sub-classes can
|
|
875
|
+
* override to globally change the default. Intentionally generous
|
|
876
|
+
* (2 hours) — tighten per-run for interactive scenarios.
|
|
877
|
+
*/
|
|
878
|
+
get DefaultAgentTimeoutMS() {
|
|
879
|
+
return 2 * 60 * 60 * 1000;
|
|
880
|
+
}
|
|
866
881
|
async Execute(params) {
|
|
867
882
|
// Capture per-request provider for the duration of this execution so all entity
|
|
868
883
|
// saves go through the isolated provider, never the global singleton's transaction.
|
|
869
884
|
this._activeProvider = params.provider || Metadata.Provider;
|
|
885
|
+
// =====================================================================================
|
|
886
|
+
// UNIVERSAL WALL-CLOCK TIMEOUT
|
|
887
|
+
//
|
|
888
|
+
// We chain any caller-supplied `cancellationToken` with an internal
|
|
889
|
+
// AbortController that fires after `maxExecutionTimeMs` (falling back
|
|
890
|
+
// to `DefaultAgentTimeoutMS`). The chained signal replaces
|
|
891
|
+
// `params.cancellationToken` for the duration of the run, so every
|
|
892
|
+
// existing cancellation check in the body of Execute sees the merged
|
|
893
|
+
// abort condition — whether it came from the caller, the timeout, or
|
|
894
|
+
// both.
|
|
895
|
+
//
|
|
896
|
+
// Actions invoked from this agent carry their own AbortSignal on
|
|
897
|
+
// `RunActionParams.AbortSignal` (see ActionEngine.RunAction) and are
|
|
898
|
+
// unaffected by this wrapper — their timeout budget is independent.
|
|
899
|
+
// =====================================================================================
|
|
900
|
+
const agentTimeoutMS = params.maxExecutionTimeMs ?? this.DefaultAgentTimeoutMS;
|
|
901
|
+
const upstreamToken = params.cancellationToken;
|
|
902
|
+
const timeoutController = new AbortController();
|
|
903
|
+
const relayUpstreamAbort = () => {
|
|
904
|
+
if (!timeoutController.signal.aborted) {
|
|
905
|
+
timeoutController.abort(upstreamToken?.reason ?? 'upstream cancellation');
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
if (upstreamToken) {
|
|
909
|
+
if (upstreamToken.aborted) {
|
|
910
|
+
relayUpstreamAbort();
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
upstreamToken.addEventListener('abort', relayUpstreamAbort, { once: true });
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
const timeoutId = setTimeout(() => {
|
|
917
|
+
if (!timeoutController.signal.aborted) {
|
|
918
|
+
timeoutController.abort(`Agent '${params.agent.Name}' exceeded maxExecutionTimeMs (${agentTimeoutMS}ms)`);
|
|
919
|
+
}
|
|
920
|
+
}, agentTimeoutMS);
|
|
921
|
+
// Route the merged signal back through `params` so the existing body of
|
|
922
|
+
// Execute (and downstream sub-agent invocations that propagate
|
|
923
|
+
// `cancellationToken`) observe it.
|
|
924
|
+
params.cancellationToken = timeoutController.signal;
|
|
870
925
|
try {
|
|
871
926
|
this.logStatus(`🤖 Starting execution of agent '${params.agent.Name}'`, true, params);
|
|
872
927
|
// =====================================================================================
|
|
@@ -908,8 +963,18 @@ export class BaseAgent {
|
|
|
908
963
|
if (params.convertUIMarkupToPlainText !== false) {
|
|
909
964
|
this.convertUIMarkupInMessages(wrappedParams.conversationMessages);
|
|
910
965
|
}
|
|
911
|
-
// Reset scratchpad for each new execution (ephemeral per run)
|
|
966
|
+
// Reset scratchpad and artifact tools for each new execution (ephemeral per run)
|
|
912
967
|
this._scratchpadManager.Clear();
|
|
968
|
+
this._artifactToolManager.Clear();
|
|
969
|
+
// Initialize artifact tools with any input artifacts from the conversation
|
|
970
|
+
const inputArtifacts = wrappedParams.data?.__inputArtifacts;
|
|
971
|
+
if (inputArtifacts?.length) {
|
|
972
|
+
this._artifactToolManager.Initialize(inputArtifacts);
|
|
973
|
+
this.logStatus(`[ArtifactTools] Initialized with ${inputArtifacts.length} artifact(s): ${inputArtifacts.map(a => `${a.typeName}:"${a.name}"`).join(', ')}`, true, params);
|
|
974
|
+
}
|
|
975
|
+
else {
|
|
976
|
+
this.logStatus(`[ArtifactTools] No input artifacts found for this run`, true, params);
|
|
977
|
+
}
|
|
913
978
|
// Initialize starting payload — must complete before AgentRun creation since the
|
|
914
979
|
// run record stores the starting payload snapshot.
|
|
915
980
|
await this.initializeStartingPayload(wrappedParams);
|
|
@@ -1065,8 +1130,11 @@ export class BaseAgent {
|
|
|
1065
1130
|
catch (error) {
|
|
1066
1131
|
// Check if error is due to cancellation
|
|
1067
1132
|
if (params.cancellationToken?.aborted || error.message === 'Cancelled during execution') {
|
|
1068
|
-
|
|
1069
|
-
|
|
1133
|
+
const reason = typeof timeoutController.signal.reason === 'string'
|
|
1134
|
+
? timeoutController.signal.reason
|
|
1135
|
+
: error.message;
|
|
1136
|
+
this.logStatus(`⚠️ Agent '${params.agent.Name}' execution cancelled: ${reason}`, true, params);
|
|
1137
|
+
return await this.createCancelledResult(reason || 'Cancelled due to error during execution', params.contextUser);
|
|
1070
1138
|
}
|
|
1071
1139
|
this.logError(error, {
|
|
1072
1140
|
agent: params.agent,
|
|
@@ -1075,6 +1143,18 @@ export class BaseAgent {
|
|
|
1075
1143
|
});
|
|
1076
1144
|
return await this.createFailureResult(error.message, params.contextUser);
|
|
1077
1145
|
}
|
|
1146
|
+
finally {
|
|
1147
|
+
// Release timeout / upstream-abort listeners so we don't leak
|
|
1148
|
+
// handles when the run completes (success, failure, or cancel).
|
|
1149
|
+
clearTimeout(timeoutId);
|
|
1150
|
+
if (upstreamToken) {
|
|
1151
|
+
upstreamToken.removeEventListener('abort', relayUpstreamAbort);
|
|
1152
|
+
}
|
|
1153
|
+
// Restore the caller's original cancellationToken on `params` so
|
|
1154
|
+
// consumers that re-read `params` after the call see what they
|
|
1155
|
+
// passed in, not our chained signal.
|
|
1156
|
+
params.cancellationToken = upstreamToken;
|
|
1157
|
+
}
|
|
1078
1158
|
}
|
|
1079
1159
|
/**
|
|
1080
1160
|
* Sub-classes can override this method to perform any specialized initialization
|
|
@@ -1636,6 +1716,26 @@ export class BaseAgent {
|
|
|
1636
1716
|
promptParams.data['_SCRATCHPAD_TASKS'] = this._scratchpadManager.ToPromptString();
|
|
1637
1717
|
promptParams.data['_SCRATCHPAD_TASK_SUMMARY'] = this._scratchpadManager.GetTaskSummary();
|
|
1638
1718
|
}
|
|
1719
|
+
// Inject artifact tools template variables if enabled and artifacts are present
|
|
1720
|
+
const artifactToolsEnabled = agentTypePromptParams?.includeArtifactToolsDocs !== false;
|
|
1721
|
+
if (artifactToolsEnabled && this._artifactToolManager.HasArtifacts()) {
|
|
1722
|
+
promptParams.data['_ARTIFACT_MANIFEST'] = this._artifactToolManager.ToManifestString();
|
|
1723
|
+
promptParams.data['_ARTIFACT_TOOLS'] = this._artifactToolManager.GetToolDocumentation();
|
|
1724
|
+
promptParams.data['_ARTIFACT_TOOL_RESULTS'] = this._artifactToolManager.GetPendingResults();
|
|
1725
|
+
promptParams.data['_ARTIFACT_TOOL_SUMMARY'] = this._artifactToolManager.GetSummary();
|
|
1726
|
+
this.logStatus(`[ArtifactTools] Injected manifest into prompt: ${this._artifactToolManager.GetSummary()}`, true, params);
|
|
1727
|
+
}
|
|
1728
|
+
else if (this._artifactToolManager.HasArtifacts()) {
|
|
1729
|
+
this.logStatus(`[ArtifactTools] Artifacts present but tools disabled by agent config (includeArtifactToolsDocs=false)`, true, params);
|
|
1730
|
+
}
|
|
1731
|
+
// Pass file artifacts as candidate native file inputs.
|
|
1732
|
+
// The AIPromptRunner will check these against the resolved driver's
|
|
1733
|
+
// FileCapabilities and attach qualifying files as native content blocks.
|
|
1734
|
+
// When the driver doesn't support a file type, the runner falls back to
|
|
1735
|
+
// the pre-extracted TextContent on each candidate.
|
|
1736
|
+
if (this._artifactToolManager.HasArtifacts()) {
|
|
1737
|
+
promptParams.nativeFileInputs = await this._artifactToolManager.GetNativeFileInputCandidates();
|
|
1738
|
+
}
|
|
1639
1739
|
}
|
|
1640
1740
|
// Only set up child prompts if we have a system prompt
|
|
1641
1741
|
if (systemPrompt) {
|
|
@@ -2403,14 +2503,36 @@ export class BaseAgent {
|
|
|
2403
2503
|
* @protected
|
|
2404
2504
|
*/
|
|
2405
2505
|
isConfigurationError(errorMessage, config) {
|
|
2506
|
+
// Extract the property name from the error up front — used by the
|
|
2507
|
+
// narrowed classifier below to decide whether this is a genuine config
|
|
2508
|
+
// issue or a generic runtime exception that should bubble up normally.
|
|
2509
|
+
const propertyMatch = errorMessage.match(/reading '(\w+)'/i);
|
|
2510
|
+
const accessedProperty = propertyMatch ? propertyMatch[1].toLowerCase() : '';
|
|
2511
|
+
// Only `.map/.x on undefined` errors that reference config-related
|
|
2512
|
+
// properties are treated as configuration errors. Generic runtime
|
|
2513
|
+
// errors (e.g. a tool handler crashing on `rows.map`) should not
|
|
2514
|
+
// terminate the run as "unrecoverable config issue" — they should
|
|
2515
|
+
// fail the step and let the agent try to recover.
|
|
2516
|
+
const CONFIG_RELATED_PROPERTIES = new Set([
|
|
2517
|
+
'prompt', 'childprompt', 'systemprompt', 'prompts',
|
|
2518
|
+
'agent', 'agents', 'agenttype', 'agenttypes',
|
|
2519
|
+
'model', 'models', 'vendor', 'vendors',
|
|
2520
|
+
'template', 'templates',
|
|
2521
|
+
]);
|
|
2522
|
+
const isConfigRelatedProperty = accessedProperty !== ''
|
|
2523
|
+
&& CONFIG_RELATED_PROPERTIES.has(accessedProperty);
|
|
2406
2524
|
// Check for common configuration error patterns
|
|
2407
2525
|
const configErrorPatterns = [
|
|
2408
2526
|
{
|
|
2409
|
-
|
|
2527
|
+
// Only match when the accessed property is config-related.
|
|
2528
|
+
// Without this guard, any runtime `.map on undefined` (e.g.
|
|
2529
|
+
// in an artifact tool handler) gets misclassified as a fatal
|
|
2530
|
+
// configuration error and the agent run terminates.
|
|
2531
|
+
pattern: isConfigRelatedProperty
|
|
2532
|
+
? /cannot read propert(y|ies) of (undefined|null)/i
|
|
2533
|
+
: /__NEVER_MATCH_GENERIC_UNDEFINED_ACCESS__/,
|
|
2410
2534
|
getMessage: () => {
|
|
2411
|
-
|
|
2412
|
-
const propertyMatch = errorMessage.match(/reading '(\w+)'/i);
|
|
2413
|
-
const property = propertyMatch ? propertyMatch[1] : 'unknown property';
|
|
2535
|
+
const property = accessedProperty || 'unknown property';
|
|
2414
2536
|
let details = `Attempted to access property '${property}' on an undefined or null object.`;
|
|
2415
2537
|
// Provide specific guidance based on the property name
|
|
2416
2538
|
if (property.toLowerCase().includes('prompt')) {
|
|
@@ -3223,7 +3345,8 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
3223
3345
|
{ docsFlag: 'includeCommandDocs', responseTypeKey: 'commands' },
|
|
3224
3346
|
{ docsFlag: 'includeForEachDocs', responseTypeKey: 'forEach' },
|
|
3225
3347
|
{ docsFlag: 'includeWhileDocs', responseTypeKey: 'while' },
|
|
3226
|
-
{ docsFlag: 'includeScratchpadDocs', responseTypeKey: 'scratchpad' }
|
|
3348
|
+
{ docsFlag: 'includeScratchpadDocs', responseTypeKey: 'scratchpad' },
|
|
3349
|
+
{ docsFlag: 'includeArtifactToolsDocs', responseTypeKey: 'artifactToolCalls' }
|
|
3227
3350
|
];
|
|
3228
3351
|
for (const { docsFlag, responseTypeKey } of alignmentMappings) {
|
|
3229
3352
|
// Check if the user explicitly set this response type property
|
|
@@ -4080,7 +4203,8 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
4080
4203
|
}
|
|
4081
4204
|
this._agentRun.Status = 'Running';
|
|
4082
4205
|
this._agentRun.StartedAt = new Date();
|
|
4083
|
-
this._agentRun.UserID = params.contextUser?.ID || null;
|
|
4206
|
+
this._agentRun.UserID = params.userId || params.contextUser?.ID || null;
|
|
4207
|
+
this._agentRun.CompanyID = params.companyId || null;
|
|
4084
4208
|
// Resolve and save the effort level used (same precedence hierarchy as prompts)
|
|
4085
4209
|
if (params.effortLevel !== undefined && params.effortLevel !== null) {
|
|
4086
4210
|
this._agentRun.EffortLevel = params.effortLevel;
|
|
@@ -4780,6 +4904,16 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
4780
4904
|
LogStatus(`Scratchpad: pruned ${pruned} completed tasks (limit: ${maxTasks})`);
|
|
4781
4905
|
}
|
|
4782
4906
|
}
|
|
4907
|
+
// Execute artifact tool calls if provided (zero turn cost — processed inline)
|
|
4908
|
+
const artifactToolCalls = initialNextStep.artifactToolCalls;
|
|
4909
|
+
const artifactToolsExecutedThisTurn = !!(artifactToolCalls?.length);
|
|
4910
|
+
if (artifactToolsExecutedThisTurn) {
|
|
4911
|
+
this.logStatus(`[ArtifactTools] LLM requested ${artifactToolCalls.length} tool call(s): ${artifactToolCalls.map(c => `${c.artifactId}.${c.tool}`).join(', ')}`, true, params);
|
|
4912
|
+
await this._artifactToolManager.ExecuteToolCalls(artifactToolCalls);
|
|
4913
|
+
}
|
|
4914
|
+
else if (this._artifactToolManager.HasArtifacts()) {
|
|
4915
|
+
this.logStatus(`[ArtifactTools] LLM did not use artifact tools this turn (artifacts available but not accessed)`, true, params);
|
|
4916
|
+
}
|
|
4783
4917
|
// now that we have processed the payload, we can process the next step which does validation and changes the next step if
|
|
4784
4918
|
// validation fails
|
|
4785
4919
|
const updatedNextStep = await this.processNextStep(initialNextStep, params, config.agentType, promptResult, finalPayload, stepEntity);
|
|
@@ -4802,6 +4936,10 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
4802
4936
|
...(this._scratchpadManager.HasContent() && {
|
|
4803
4937
|
scratchpad: this._scratchpadManager.ToJSON()
|
|
4804
4938
|
}),
|
|
4939
|
+
// Include artifact tools snapshot for audit/training data
|
|
4940
|
+
...(this._artifactToolManager.HasArtifacts() && {
|
|
4941
|
+
artifactTools: this._artifactToolManager.ToJSON()
|
|
4942
|
+
}),
|
|
4805
4943
|
// Include memory attribution for observability
|
|
4806
4944
|
// This tracks which notes/examples were injected and influenced this step
|
|
4807
4945
|
...(this._injectedMemory && (this._injectedMemory.notes.length > 0 || this._injectedMemory.examples.length > 0) && {
|
|
@@ -4834,6 +4972,14 @@ The context is now within limits. Please retry your request with the recovered c
|
|
|
4834
4972
|
await this.finalizeStepEntity(stepEntity, promptResult.success, promptResult.success ? undefined : promptResult.errorMessage, outputData);
|
|
4835
4973
|
// Return based on next step
|
|
4836
4974
|
if (updatedNextStep.step === 'Chat') {
|
|
4975
|
+
// If artifact tools were called THIS turn, don't terminate yet — the LLM
|
|
4976
|
+
// needs one more turn to see the results and incorporate them into its response.
|
|
4977
|
+
// Without this, the tool results are wasted because the run exits before
|
|
4978
|
+
// the LLM ever sees them.
|
|
4979
|
+
if (artifactToolsExecutedThisTurn && this._artifactToolManager.HasArtifacts()) {
|
|
4980
|
+
this.logStatus(`[ArtifactTools] Chat step included tool calls — forcing one more turn so LLM can use results`, true, params);
|
|
4981
|
+
return { ...updatedNextStep, terminate: false, step: 'Retry' };
|
|
4982
|
+
}
|
|
4837
4983
|
// For root agents, create a persistent AIAgentRequest so the request is
|
|
4838
4984
|
// tracked in the dashboard and can be responded to outside a conversation.
|
|
4839
4985
|
// This is done here because Chat decisions from executePromptStep terminate
|