@memberjunction/ai-agents 5.27.1 → 5.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/AgentRunner.d.ts +39 -0
  2. package/dist/AgentRunner.d.ts.map +1 -1
  3. package/dist/AgentRunner.js +300 -5
  4. package/dist/AgentRunner.js.map +1 -1
  5. package/dist/ArtifactToolManager.d.ts +165 -0
  6. package/dist/ArtifactToolManager.d.ts.map +1 -0
  7. package/dist/ArtifactToolManager.js +534 -0
  8. package/dist/ArtifactToolManager.js.map +1 -0
  9. package/dist/agent-types/loop-agent-prompt-params.d.ts +14 -0
  10. package/dist/agent-types/loop-agent-prompt-params.d.ts.map +1 -1
  11. package/dist/agent-types/loop-agent-prompt-params.js +3 -1
  12. package/dist/agent-types/loop-agent-prompt-params.js.map +1 -1
  13. package/dist/agent-types/loop-agent-response-type.d.ts +9 -1
  14. package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
  15. package/dist/agent-types/loop-agent-response-type.js.map +1 -1
  16. package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
  17. package/dist/agent-types/loop-agent-type.js +3 -0
  18. package/dist/agent-types/loop-agent-type.js.map +1 -1
  19. package/dist/artifact-tools/DataSnapshotToolLibrary.d.ts +18 -0
  20. package/dist/artifact-tools/DataSnapshotToolLibrary.d.ts.map +1 -0
  21. package/dist/artifact-tools/DataSnapshotToolLibrary.js +365 -0
  22. package/dist/artifact-tools/DataSnapshotToolLibrary.js.map +1 -0
  23. package/dist/artifact-tools/DocxToolLibrary.d.ts +15 -0
  24. package/dist/artifact-tools/DocxToolLibrary.d.ts.map +1 -0
  25. package/dist/artifact-tools/DocxToolLibrary.js +160 -0
  26. package/dist/artifact-tools/DocxToolLibrary.js.map +1 -0
  27. package/dist/artifact-tools/ExcelToolLibrary.d.ts +16 -0
  28. package/dist/artifact-tools/ExcelToolLibrary.d.ts.map +1 -0
  29. package/dist/artifact-tools/ExcelToolLibrary.js +300 -0
  30. package/dist/artifact-tools/ExcelToolLibrary.js.map +1 -0
  31. package/dist/artifact-tools/JSONToolLibrary.d.ts +18 -0
  32. package/dist/artifact-tools/JSONToolLibrary.d.ts.map +1 -0
  33. package/dist/artifact-tools/JSONToolLibrary.js +178 -0
  34. package/dist/artifact-tools/JSONToolLibrary.js.map +1 -0
  35. package/dist/artifact-tools/PDFToolLibrary.d.ts +14 -0
  36. package/dist/artifact-tools/PDFToolLibrary.d.ts.map +1 -0
  37. package/dist/artifact-tools/PDFToolLibrary.js +172 -0
  38. package/dist/artifact-tools/PDFToolLibrary.js.map +1 -0
  39. package/dist/artifact-tools/TextToolLibrary.d.ts +12 -0
  40. package/dist/artifact-tools/TextToolLibrary.d.ts.map +1 -0
  41. package/dist/artifact-tools/TextToolLibrary.js +82 -0
  42. package/dist/artifact-tools/TextToolLibrary.js.map +1 -0
  43. package/dist/base-agent.d.ts +5 -0
  44. package/dist/base-agent.d.ts.map +1 -1
  45. package/dist/base-agent.js +87 -6
  46. package/dist/base-agent.js.map +1 -1
  47. package/dist/file-input-resolver.d.ts +2 -0
  48. package/dist/file-input-resolver.d.ts.map +1 -0
  49. package/dist/file-input-resolver.js +4 -0
  50. package/dist/file-input-resolver.js.map +1 -0
  51. package/dist/index.d.ts +9 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +9 -1
  54. package/dist/index.js.map +1 -1
  55. package/package.json +18 -15
@@ -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().
@@ -908,8 +914,18 @@ export class BaseAgent {
908
914
  if (params.convertUIMarkupToPlainText !== false) {
909
915
  this.convertUIMarkupInMessages(wrappedParams.conversationMessages);
910
916
  }
911
- // Reset scratchpad for each new execution (ephemeral per run)
917
+ // Reset scratchpad and artifact tools for each new execution (ephemeral per run)
912
918
  this._scratchpadManager.Clear();
919
+ this._artifactToolManager.Clear();
920
+ // Initialize artifact tools with any input artifacts from the conversation
921
+ const inputArtifacts = wrappedParams.data?.__inputArtifacts;
922
+ if (inputArtifacts?.length) {
923
+ this._artifactToolManager.Initialize(inputArtifacts);
924
+ this.logStatus(`[ArtifactTools] Initialized with ${inputArtifacts.length} artifact(s): ${inputArtifacts.map(a => `${a.typeName}:"${a.name}"`).join(', ')}`, true, params);
925
+ }
926
+ else {
927
+ this.logStatus(`[ArtifactTools] No input artifacts found for this run`, true, params);
928
+ }
913
929
  // Initialize starting payload — must complete before AgentRun creation since the
914
930
  // run record stores the starting payload snapshot.
915
931
  await this.initializeStartingPayload(wrappedParams);
@@ -1636,6 +1652,26 @@ export class BaseAgent {
1636
1652
  promptParams.data['_SCRATCHPAD_TASKS'] = this._scratchpadManager.ToPromptString();
1637
1653
  promptParams.data['_SCRATCHPAD_TASK_SUMMARY'] = this._scratchpadManager.GetTaskSummary();
1638
1654
  }
1655
+ // Inject artifact tools template variables if enabled and artifacts are present
1656
+ const artifactToolsEnabled = agentTypePromptParams?.includeArtifactToolsDocs !== false;
1657
+ if (artifactToolsEnabled && this._artifactToolManager.HasArtifacts()) {
1658
+ promptParams.data['_ARTIFACT_MANIFEST'] = this._artifactToolManager.ToManifestString();
1659
+ promptParams.data['_ARTIFACT_TOOLS'] = this._artifactToolManager.GetToolDocumentation();
1660
+ promptParams.data['_ARTIFACT_TOOL_RESULTS'] = this._artifactToolManager.GetPendingResults();
1661
+ promptParams.data['_ARTIFACT_TOOL_SUMMARY'] = this._artifactToolManager.GetSummary();
1662
+ this.logStatus(`[ArtifactTools] Injected manifest into prompt: ${this._artifactToolManager.GetSummary()}`, true, params);
1663
+ }
1664
+ else if (this._artifactToolManager.HasArtifacts()) {
1665
+ this.logStatus(`[ArtifactTools] Artifacts present but tools disabled by agent config (includeArtifactToolsDocs=false)`, true, params);
1666
+ }
1667
+ // Pass file artifacts as candidate native file inputs.
1668
+ // The AIPromptRunner will check these against the resolved driver's
1669
+ // FileCapabilities and attach qualifying files as native content blocks.
1670
+ // When the driver doesn't support a file type, the runner falls back to
1671
+ // the pre-extracted TextContent on each candidate.
1672
+ if (this._artifactToolManager.HasArtifacts()) {
1673
+ promptParams.nativeFileInputs = await this._artifactToolManager.GetNativeFileInputCandidates();
1674
+ }
1639
1675
  }
1640
1676
  // Only set up child prompts if we have a system prompt
1641
1677
  if (systemPrompt) {
@@ -2403,14 +2439,36 @@ export class BaseAgent {
2403
2439
  * @protected
2404
2440
  */
2405
2441
  isConfigurationError(errorMessage, config) {
2442
+ // Extract the property name from the error up front — used by the
2443
+ // narrowed classifier below to decide whether this is a genuine config
2444
+ // issue or a generic runtime exception that should bubble up normally.
2445
+ const propertyMatch = errorMessage.match(/reading '(\w+)'/i);
2446
+ const accessedProperty = propertyMatch ? propertyMatch[1].toLowerCase() : '';
2447
+ // Only `.map/.x on undefined` errors that reference config-related
2448
+ // properties are treated as configuration errors. Generic runtime
2449
+ // errors (e.g. a tool handler crashing on `rows.map`) should not
2450
+ // terminate the run as "unrecoverable config issue" — they should
2451
+ // fail the step and let the agent try to recover.
2452
+ const CONFIG_RELATED_PROPERTIES = new Set([
2453
+ 'prompt', 'childprompt', 'systemprompt', 'prompts',
2454
+ 'agent', 'agents', 'agenttype', 'agenttypes',
2455
+ 'model', 'models', 'vendor', 'vendors',
2456
+ 'template', 'templates',
2457
+ ]);
2458
+ const isConfigRelatedProperty = accessedProperty !== ''
2459
+ && CONFIG_RELATED_PROPERTIES.has(accessedProperty);
2406
2460
  // Check for common configuration error patterns
2407
2461
  const configErrorPatterns = [
2408
2462
  {
2409
- pattern: /cannot read propert(y|ies) of (undefined|null)/i,
2463
+ // Only match when the accessed property is config-related.
2464
+ // Without this guard, any runtime `.map on undefined` (e.g.
2465
+ // in an artifact tool handler) gets misclassified as a fatal
2466
+ // configuration error and the agent run terminates.
2467
+ pattern: isConfigRelatedProperty
2468
+ ? /cannot read propert(y|ies) of (undefined|null)/i
2469
+ : /__NEVER_MATCH_GENERIC_UNDEFINED_ACCESS__/,
2410
2470
  getMessage: () => {
2411
- // Try to extract what property was being accessed
2412
- const propertyMatch = errorMessage.match(/reading '(\w+)'/i);
2413
- const property = propertyMatch ? propertyMatch[1] : 'unknown property';
2471
+ const property = accessedProperty || 'unknown property';
2414
2472
  let details = `Attempted to access property '${property}' on an undefined or null object.`;
2415
2473
  // Provide specific guidance based on the property name
2416
2474
  if (property.toLowerCase().includes('prompt')) {
@@ -3223,7 +3281,8 @@ The context is now within limits. Please retry your request with the recovered c
3223
3281
  { docsFlag: 'includeCommandDocs', responseTypeKey: 'commands' },
3224
3282
  { docsFlag: 'includeForEachDocs', responseTypeKey: 'forEach' },
3225
3283
  { docsFlag: 'includeWhileDocs', responseTypeKey: 'while' },
3226
- { docsFlag: 'includeScratchpadDocs', responseTypeKey: 'scratchpad' }
3284
+ { docsFlag: 'includeScratchpadDocs', responseTypeKey: 'scratchpad' },
3285
+ { docsFlag: 'includeArtifactToolsDocs', responseTypeKey: 'artifactToolCalls' }
3227
3286
  ];
3228
3287
  for (const { docsFlag, responseTypeKey } of alignmentMappings) {
3229
3288
  // Check if the user explicitly set this response type property
@@ -4780,6 +4839,16 @@ The context is now within limits. Please retry your request with the recovered c
4780
4839
  LogStatus(`Scratchpad: pruned ${pruned} completed tasks (limit: ${maxTasks})`);
4781
4840
  }
4782
4841
  }
4842
+ // Execute artifact tool calls if provided (zero turn cost — processed inline)
4843
+ const artifactToolCalls = initialNextStep.artifactToolCalls;
4844
+ const artifactToolsExecutedThisTurn = !!(artifactToolCalls?.length);
4845
+ if (artifactToolsExecutedThisTurn) {
4846
+ this.logStatus(`[ArtifactTools] LLM requested ${artifactToolCalls.length} tool call(s): ${artifactToolCalls.map(c => `${c.artifactId}.${c.tool}`).join(', ')}`, true, params);
4847
+ await this._artifactToolManager.ExecuteToolCalls(artifactToolCalls);
4848
+ }
4849
+ else if (this._artifactToolManager.HasArtifacts()) {
4850
+ this.logStatus(`[ArtifactTools] LLM did not use artifact tools this turn (artifacts available but not accessed)`, true, params);
4851
+ }
4783
4852
  // now that we have processed the payload, we can process the next step which does validation and changes the next step if
4784
4853
  // validation fails
4785
4854
  const updatedNextStep = await this.processNextStep(initialNextStep, params, config.agentType, promptResult, finalPayload, stepEntity);
@@ -4802,6 +4871,10 @@ The context is now within limits. Please retry your request with the recovered c
4802
4871
  ...(this._scratchpadManager.HasContent() && {
4803
4872
  scratchpad: this._scratchpadManager.ToJSON()
4804
4873
  }),
4874
+ // Include artifact tools snapshot for audit/training data
4875
+ ...(this._artifactToolManager.HasArtifacts() && {
4876
+ artifactTools: this._artifactToolManager.ToJSON()
4877
+ }),
4805
4878
  // Include memory attribution for observability
4806
4879
  // This tracks which notes/examples were injected and influenced this step
4807
4880
  ...(this._injectedMemory && (this._injectedMemory.notes.length > 0 || this._injectedMemory.examples.length > 0) && {
@@ -4834,6 +4907,14 @@ The context is now within limits. Please retry your request with the recovered c
4834
4907
  await this.finalizeStepEntity(stepEntity, promptResult.success, promptResult.success ? undefined : promptResult.errorMessage, outputData);
4835
4908
  // Return based on next step
4836
4909
  if (updatedNextStep.step === 'Chat') {
4910
+ // If artifact tools were called THIS turn, don't terminate yet — the LLM
4911
+ // needs one more turn to see the results and incorporate them into its response.
4912
+ // Without this, the tool results are wasted because the run exits before
4913
+ // the LLM ever sees them.
4914
+ if (artifactToolsExecutedThisTurn && this._artifactToolManager.HasArtifacts()) {
4915
+ this.logStatus(`[ArtifactTools] Chat step included tool calls — forcing one more turn so LLM can use results`, true, params);
4916
+ return { ...updatedNextStep, terminate: false, step: 'Retry' };
4917
+ }
4837
4918
  // For root agents, create a persistent AIAgentRequest so the request is
4838
4919
  // tracked in the dashboard and can be responded to outside a conversation.
4839
4920
  // This is done here because Chat decisions from executePromptStep terminate