@memberjunction/ai-agents 6.1.4 → 6.2.0-edge.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.
Files changed (147) hide show
  1. package/README.md +25 -0
  2. package/dist/AgentDataPreloader.d.ts +4 -0
  3. package/dist/AgentDataPreloader.d.ts.map +1 -1
  4. package/dist/AgentDataPreloader.js +10 -2
  5. package/dist/AgentDataPreloader.js.map +1 -1
  6. package/dist/AgentRunner.d.ts +9 -4
  7. package/dist/AgentRunner.d.ts.map +1 -1
  8. package/dist/AgentRunner.js +39 -27
  9. package/dist/AgentRunner.js.map +1 -1
  10. package/dist/ArtifactToolManager.d.ts +4 -4
  11. package/dist/ArtifactToolManager.js +10 -10
  12. package/dist/ConversationToolManager.d.ts +16 -3
  13. package/dist/ConversationToolManager.d.ts.map +1 -1
  14. package/dist/ConversationToolManager.js +28 -5
  15. package/dist/ConversationToolManager.js.map +1 -1
  16. package/dist/PayloadChangeAnalyzer.d.ts +4 -0
  17. package/dist/PayloadChangeAnalyzer.d.ts.map +1 -1
  18. package/dist/PayloadChangeAnalyzer.js +10 -2
  19. package/dist/PayloadChangeAnalyzer.js.map +1 -1
  20. package/dist/PayloadFeedbackManager.d.ts +8 -0
  21. package/dist/PayloadFeedbackManager.d.ts.map +1 -1
  22. package/dist/PayloadFeedbackManager.js +20 -4
  23. package/dist/PayloadFeedbackManager.js.map +1 -1
  24. package/dist/PayloadManager.d.ts +27 -0
  25. package/dist/PayloadManager.d.ts.map +1 -1
  26. package/dist/PayloadManager.js +47 -15
  27. package/dist/PayloadManager.js.map +1 -1
  28. package/dist/agent-types/base-agent-type.d.ts +16 -0
  29. package/dist/agent-types/base-agent-type.d.ts.map +1 -1
  30. package/dist/agent-types/base-agent-type.js +20 -1
  31. package/dist/agent-types/base-agent-type.js.map +1 -1
  32. package/dist/agent-types/flow-agent-type.d.ts +9 -0
  33. package/dist/agent-types/flow-agent-type.d.ts.map +1 -1
  34. package/dist/agent-types/flow-agent-type.js +18 -5
  35. package/dist/agent-types/flow-agent-type.js.map +1 -1
  36. package/dist/agent-types/loop-agent-prompt-params.d.ts +74 -0
  37. package/dist/agent-types/loop-agent-prompt-params.d.ts.map +1 -1
  38. package/dist/agent-types/loop-agent-prompt-params.js +2 -0
  39. package/dist/agent-types/loop-agent-prompt-params.js.map +1 -1
  40. package/dist/artifact-target-plan.d.ts +2 -0
  41. package/dist/artifact-target-plan.d.ts.map +1 -1
  42. package/dist/artifact-target-plan.js +5 -1
  43. package/dist/artifact-target-plan.js.map +1 -1
  44. package/dist/base-agent.d.ts +408 -3
  45. package/dist/base-agent.d.ts.map +1 -1
  46. package/dist/base-agent.js +924 -78
  47. package/dist/base-agent.js.map +1 -1
  48. package/dist/constants.d.ts +57 -0
  49. package/dist/constants.d.ts.map +1 -0
  50. package/dist/constants.js +70 -0
  51. package/dist/constants.js.map +1 -0
  52. package/dist/index.d.ts +3 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +3 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/memory-manager-agent.d.ts +12 -12
  57. package/dist/memory-manager-agent.js +65 -65
  58. package/dist/native-tools/action-tool-builder.d.ts +8 -0
  59. package/dist/native-tools/action-tool-builder.d.ts.map +1 -1
  60. package/dist/native-tools/action-tool-builder.js +22 -6
  61. package/dist/native-tools/action-tool-builder.js.map +1 -1
  62. package/dist/native-tools/control-tools.d.ts +8 -0
  63. package/dist/native-tools/control-tools.d.ts.map +1 -1
  64. package/dist/native-tools/control-tools.js +25 -9
  65. package/dist/native-tools/control-tools.js.map +1 -1
  66. package/dist/native-tools/dual-channel.d.ts +2 -0
  67. package/dist/native-tools/dual-channel.d.ts.map +1 -1
  68. package/dist/native-tools/dual-channel.js +5 -1
  69. package/dist/native-tools/dual-channel.js.map +1 -1
  70. package/dist/native-tools/tool-result-turns.d.ts +9 -0
  71. package/dist/native-tools/tool-result-turns.d.ts.map +1 -1
  72. package/dist/native-tools/tool-result-turns.js +15 -3
  73. package/dist/native-tools/tool-result-turns.js.map +1 -1
  74. package/dist/pipeline/coerce.d.ts +14 -0
  75. package/dist/pipeline/coerce.d.ts.map +1 -1
  76. package/dist/pipeline/coerce.js +37 -9
  77. package/dist/pipeline/coerce.js.map +1 -1
  78. package/dist/pipeline/jsonpath-eval.d.ts +4 -0
  79. package/dist/pipeline/jsonpath-eval.d.ts.map +1 -1
  80. package/dist/pipeline/jsonpath-eval.js +10 -2
  81. package/dist/pipeline/jsonpath-eval.js.map +1 -1
  82. package/dist/pipeline/operators.js +16 -16
  83. package/dist/pipeline/path.d.ts +6 -0
  84. package/dist/pipeline/path.d.ts.map +1 -1
  85. package/dist/pipeline/path.js +17 -5
  86. package/dist/pipeline/path.js.map +1 -1
  87. package/dist/pipeline/pipeline-executor.js +10 -10
  88. package/dist/pipeline/predicate.d.ts +4 -0
  89. package/dist/pipeline/predicate.d.ts.map +1 -1
  90. package/dist/pipeline/predicate.js +15 -7
  91. package/dist/pipeline/predicate.js.map +1 -1
  92. package/dist/pipeline/providers/action-provider.js +2 -2
  93. package/dist/pipeline/providers/artifact-tool-provider.js +2 -2
  94. package/dist/pipeline/providers/serialize.d.ts +4 -0
  95. package/dist/pipeline/providers/serialize.d.ts.map +1 -1
  96. package/dist/pipeline/providers/serialize.js +10 -2
  97. package/dist/pipeline/providers/serialize.js.map +1 -1
  98. package/dist/pipeline/template.d.ts +4 -0
  99. package/dist/pipeline/template.d.ts.map +1 -1
  100. package/dist/pipeline/template.js +15 -7
  101. package/dist/pipeline/template.js.map +1 -1
  102. package/dist/realtime/agent-media-library.d.ts +10 -0
  103. package/dist/realtime/agent-media-library.d.ts.map +1 -1
  104. package/dist/realtime/agent-media-library.js +29 -9
  105. package/dist/realtime/agent-media-library.js.map +1 -1
  106. package/dist/realtime/media-channel-server.js +2 -2
  107. package/dist/realtime/meeting-controls-state.d.ts +2 -0
  108. package/dist/realtime/meeting-controls-state.d.ts.map +1 -1
  109. package/dist/realtime/meeting-controls-state.js +6 -2
  110. package/dist/realtime/meeting-controls-state.js.map +1 -1
  111. package/dist/realtime/realtime-channel-server-data-context.d.ts +2 -0
  112. package/dist/realtime/realtime-channel-server-data-context.d.ts.map +1 -1
  113. package/dist/realtime/realtime-channel-server-data-context.js +5 -1
  114. package/dist/realtime/realtime-channel-server-data-context.js.map +1 -1
  115. package/dist/realtime/realtime-channel-server-host.js +2 -2
  116. package/dist/realtime/realtime-client-session-service.d.ts +4 -0
  117. package/dist/realtime/realtime-client-session-service.d.ts.map +1 -1
  118. package/dist/realtime/realtime-client-session-service.js +15 -6
  119. package/dist/realtime/realtime-client-session-service.js.map +1 -1
  120. package/dist/realtime/realtime-coagent-config.d.ts +2 -0
  121. package/dist/realtime/realtime-coagent-config.d.ts.map +1 -1
  122. package/dist/realtime/realtime-coagent-config.js +6 -2
  123. package/dist/realtime/realtime-coagent-config.js.map +1 -1
  124. package/dist/realtime/realtime-recording-store.d.ts +15 -0
  125. package/dist/realtime/realtime-recording-store.d.ts.map +1 -1
  126. package/dist/realtime/realtime-recording-store.js +31 -7
  127. package/dist/realtime/realtime-recording-store.js.map +1 -1
  128. package/dist/realtime/realtime-session-runner.d.ts +4 -4
  129. package/dist/realtime/realtime-session-runner.js +9 -9
  130. package/dist/realtime/realtime-session-runner.js.map +1 -1
  131. package/dist/runtime-state-fragment.d.ts +101 -0
  132. package/dist/runtime-state-fragment.d.ts.map +1 -0
  133. package/dist/runtime-state-fragment.js +173 -0
  134. package/dist/runtime-state-fragment.js.map +1 -0
  135. package/dist/types/payload-operations.d.ts +8 -0
  136. package/dist/types/payload-operations.d.ts.map +1 -1
  137. package/dist/types/payload-operations.js +21 -5
  138. package/dist/types/payload-operations.js.map +1 -1
  139. package/dist/utils/ConversationMessageResolver.d.ts +4 -0
  140. package/dist/utils/ConversationMessageResolver.d.ts.map +1 -1
  141. package/dist/utils/ConversationMessageResolver.js +10 -2
  142. package/dist/utils/ConversationMessageResolver.js.map +1 -1
  143. package/dist/volatile-child-prompt.d.ts +33 -0
  144. package/dist/volatile-child-prompt.d.ts.map +1 -0
  145. package/dist/volatile-child-prompt.js +76 -0
  146. package/dist/volatile-child-prompt.js.map +1 -0
  147. package/package.json +20 -18
@@ -10,9 +10,9 @@
10
10
  * @author MemberJunction.com
11
11
  * @since 2.49.0
12
12
  */
13
- import { MJAIAgentTypeEntity, MJTemplateParamEntity, MJAIAgentRelationshipEntity, MJAIAgentNoteEntity, MJAIAgentExampleEntity, MJAISkillEntity } from '@memberjunction/core-entities';
13
+ import { MJAIAgentTypeEntity, MJTemplateParamEntity, MJAIAgentRelationshipEntity, MJAIAgentNoteEntity, MJAIAgentExampleEntity, MJAISkillEntity, MJAIVendorEntity } from '@memberjunction/core-entities';
14
14
  import { type NativeToolBinding } from './native-tools/control-tools.js';
15
- import { MJAIAgentRunEntityExtended, MJAIAgentRunStepEntityExtended, MJAIPromptEntityExtended, MJAIAgentEntityExtended, MJAIPromptRunEntityExtended } from "@memberjunction/ai-core-plus";
15
+ import { MJAIAgentRunEntityExtended, MJAIAgentRunStepEntityExtended, MJAIPromptEntityExtended, MJAIAgentEntityExtended, MJAIModelEntityExtended, MJAIPromptRunEntityExtended } from "@memberjunction/ai-core-plus";
16
16
  import { UserInfo, IMetadataProvider } from '@memberjunction/core';
17
17
  import { ChatMessage, ChatMessageContent, BaseRealtimeModel, IRealtimeSession, ChatToolChoice } from '@memberjunction/ai';
18
18
  import { BaseAgentType } from './agent-types/base-agent-type.js';
@@ -26,6 +26,7 @@ import { CarryForwardStepRecord } from './tool-result-format.js';
26
26
  import { AgentPreExecutionRAGResult } from './agent-pre-execution-rag.js';
27
27
  import { AIPromptParams, AIPromptRunResult, ExecuteAgentParams, AgentConfiguration, ExecuteAgentResult, AgentAction, AgentSubAgentRequest, BaseAgentNextStep, MessageLifecycleEvent, AgentChatMessage, AgentChatMessageMetadata, AIModelSelectionInfo, ActionChange, ActionChangeScope, SubAgentChange, MediaOutput, FileOutputRef, SecondaryScopeConfig, SecondaryScopeValue, AgentResponseForm, AgentPipelineRequest, AgentSkillActivationRequest, AgentSkillInvocation, SkillAvailabilityPurpose } from '@memberjunction/ai-core-plus';
28
28
  import { MJActionEntityExtended, ActionResult, ActionParam, AIDirective } from '@memberjunction/actions-base';
29
+ import { RuntimeStateDateTime, RuntimeStateScratchpad } from './runtime-state-fragment.js';
29
30
  import { ArtifactToolCall, StoredToolResult } from './ArtifactToolManager.js';
30
31
  import { MemoryWriteRequest, MemoryWriteResult } from './MemoryWriteManager.js';
31
32
  import { PipelineToolRegistry, PipelineExecutionResult } from './pipeline/index.js';
@@ -40,6 +41,8 @@ interface ActionResultSummary {
40
41
  resultCode: string;
41
42
  message: string;
42
43
  aiDirectives?: AIDirective[];
44
+ /** Set when the circuit breaker blocked the call without dispatching it. */
45
+ breakerReason?: ActionCircuitBreakerReason;
43
46
  }
44
47
  /**
45
48
  * Resolved per-run configuration for structurally compressing inline action-result
@@ -58,6 +61,47 @@ export interface ActionResultCrushConfig {
58
61
  */
59
62
  codeLang: CodeLang | undefined;
60
63
  }
64
+ /**
65
+ * Options for {@link BaseAgent.ExecuteSingleAction}.
66
+ */
67
+ export interface ExecuteSingleActionOptions {
68
+ /**
69
+ * When true, the run-scoped action circuit breaker is bypassed for this call: none of the
70
+ * pre-execution checks (fatal lockout, identical-arguments rule, consecutive-attempt budget)
71
+ * apply, and the outcome neither increments nor resets the failure history.
72
+ *
73
+ * Set by the pipeline registry and by the ForEach / While iteration paths. Those callers do
74
+ * their own per-element failure accounting and expect elements to be independent, and there
75
+ * is no model in the loop to act on the breaker's guidance, so counting those calls would let
76
+ * a run of bad elements block the rest of the batch and then block the model's next direct
77
+ * call too.
78
+ */
79
+ skipCircuitBreaker?: boolean;
80
+ }
81
+ /**
82
+ * Which circuit-breaker rule blocked an action call without dispatching it.
83
+ *
84
+ * - `'fatal'` — the action failed earlier in the run with a configuration or credential error and is
85
+ * locked out for the rest of the run.
86
+ * - `'identical-arguments'` — the action already failed {@link IDENTICAL_FAILURE_THRESHOLD} times
87
+ * with these exact arguments.
88
+ * - `'attempts-exhausted'` — the action has failed {@link ACTION_FAILURE_BUDGET} consecutive times
89
+ * across any arguments.
90
+ */
91
+ export type ActionCircuitBreakerReason = 'fatal' | 'identical-arguments' | 'attempts-exhausted';
92
+ /** Identical-arguments rule: this many failures with the same arguments block further identical calls. */
93
+ export declare const IDENTICAL_FAILURE_THRESHOLD = 2;
94
+ /** Attempt budget: this many consecutive failures, across any arguments, disable the action for the run. */
95
+ export declare const ACTION_FAILURE_BUDGET = 5;
96
+ /**
97
+ * The {@link ActionResult} returned when the run-scoped circuit breaker blocks a call before it
98
+ * reaches the action engine. Carries the rule that fired so the failure directive can name it
99
+ * directly instead of re-deriving it from the failure history, which a blocked call never updates.
100
+ */
101
+ export declare class CircuitBreakerActionResult extends ActionResult {
102
+ readonly Reason: ActionCircuitBreakerReason;
103
+ constructor(Reason: ActionCircuitBreakerReason);
104
+ }
61
105
  /**
62
106
  * The agent-invariant "base" catalog cached (process-wide) on AIEngine and reused across runs/steps.
63
107
  * Holds the resolved sub-agents + actions and their formatted markdown, plus the base merged
@@ -148,6 +192,138 @@ export declare class BaseAgent {
148
192
  * @private
149
193
  */
150
194
  private _lastModelSelectionInfo;
195
+ /**
196
+ * The volatile runtime state message generated for the most recent prompt execution.
197
+ * When append-only trailing state mode is used (e.g. OpenAI prompt caching), this fragment
198
+ * is retained in conversation history across turns to preserve a byte-exact prompt prefix.
199
+ * @private
200
+ */
201
+ private _lastVolatileStateMessage;
202
+ /**
203
+ * The trailing-state retention mode once it has been decided for this run, frozen at the first
204
+ * model selection so the layout never flips again mid-run. Undefined until then (turn 1 only).
205
+ * @private
206
+ */
207
+ private _resolvedTrailingStateMode;
208
+ /**
209
+ * Index in conversationMessages where this agent run began, used to accurately restore
210
+ * turn 1's trailing state message in append-only mode without corrupting prior chat turns.
211
+ * @private
212
+ */
213
+ private _turn1InsertionIndex;
214
+ /**
215
+ * Actions that have failed fatally (e.g., missing API key, unauthorized, or repeated unrecoverable errors)
216
+ * during the current agent run. Subsequent attempts to execute these actions are short-circuited in 0ms.
217
+ * @private
218
+ */
219
+ private _fatalActionFailures;
220
+ /**
221
+ * Parameter-aware failure tracking per action name for the current agent run.
222
+ * Differentiates identical retries (which trip quickly) from parameter modifications (which allow self-correction).
223
+ * @private
224
+ */
225
+ private _actionFailureHistory;
226
+ /**
227
+ * The identity of one action call's arguments, for the circuit breaker's identical-arguments
228
+ * rule: two calls with the same normalized string are "the same call", whatever order the model
229
+ * wrote the keys in.
230
+ *
231
+ * Algorithm, top to bottom:
232
+ * 1. Null, undefined or a non-object yields `''` (a call with no arguments).
233
+ * 2. The top-level keys are sorted, and each `(key, value)` pair passes through
234
+ * {@link normalizeActionParamEntry}, which may rename it, rewrite its value, or drop it.
235
+ * 3. Every value passes through {@link normalizeActionParamValue}: plain objects are rebuilt with
236
+ * sorted keys at EVERY depth, arrays keep their order but normalize each element, and
237
+ * anything else (strings, numbers, booleans, null, Dates, entity instances) is kept as is.
238
+ * 4. The result is serialized with `JSON.stringify`. Should that throw (a circular reference,
239
+ * a BigInt), the fallback is a sorted list of the top-level keys — still deterministic, still
240
+ * distinguishes differently-shaped calls, and never throws.
241
+ *
242
+ * Three protected layers so a subclass can change one part without re-implementing the rest:
243
+ * override {@link normalizeActionParamEntry} to ignore a key (a trace id, a timestamp the model
244
+ * regenerates on every call), or {@link normalizeActionParamValue} to canonicalize values
245
+ * (case-fold a search query, trim whitespace) so near-identical retries count as identical.
246
+ */
247
+ protected normalizeActionParams(params: Record<string, unknown> | null | undefined): string;
248
+ /**
249
+ * Normalizes one top-level `(key, value)` pair of an action's arguments. The default keeps the
250
+ * key and normalizes the value through {@link normalizeActionParamValue}. Return `null` to drop
251
+ * the pair from the call's identity — the seam for ignoring arguments that legitimately differ
252
+ * between otherwise identical retries.
253
+ */
254
+ protected normalizeActionParamEntry(key: string, value: unknown): {
255
+ key: string;
256
+ value: unknown;
257
+ } | null;
258
+ /**
259
+ * Normalizes one value, recursively: a plain object is rebuilt with its keys sorted, an array
260
+ * keeps its order with each element normalized, and any other value is returned unchanged. The
261
+ * seam for canonicalizing values before they are compared.
262
+ *
263
+ * "Plain" here is by prototype (`Object.prototype` or none), not the structural
264
+ * `IsPlainObject` from `@memberjunction/global`: a Date, Map or entity instance must pass through
265
+ * as an opaque leaf and serialize as itself, not be rebuilt as an empty bag of sorted keys.
266
+ */
267
+ protected normalizeActionParamValue(value: unknown): unknown;
268
+ /**
269
+ * Detects whether an action error message represents a fatal configuration or credential
270
+ * problem: the tool cannot work in this environment no matter what arguments it is given,
271
+ * so retrying is pointless and the action is locked out for the rest of the run.
272
+ *
273
+ * Deliberately NOT fatal: HTTP 401/403, "unauthorized" and "forbidden". Those are usually
274
+ * per-resource (one site blocking a fetch, one record the user cannot read) or transient
275
+ * (a search provider using 403 as a rate limit), so they fall through to the parameter-aware
276
+ * failure history where the identical-arguments rule and the consecutive-attempt budget
277
+ * bound them without disabling the tool for every other resource.
278
+ *
279
+ * Also NOT fatal, for the same reason: a failure the model can fix by changing its arguments.
280
+ * A message that names a parameter is treated as an argument problem whatever else it says,
281
+ * and a call that itself carried credential-shaped arguments (password, API key, token) is
282
+ * never fatal even on "authentication failed", because the credential came from the model,
283
+ * not the environment. Demoting a message from fatal costs at most the attempt budget.
284
+ *
285
+ * @param message The action's failure message.
286
+ * @param actionParams The arguments the call was made with, when known.
287
+ */
288
+ protected isFatalActionError(message: string | null | undefined, actionParams?: Record<string, unknown> | null): boolean;
289
+ /**
290
+ * True when any top-level argument name looks like a credential the model supplied itself
291
+ * (password, secret, credential, API key, or an access / auth / bearer / refresh / ID token).
292
+ * `maxTokens`-style names are deliberately not matched.
293
+ */
294
+ protected hasCredentialShapedArguments(actionParams?: Record<string, unknown> | null): boolean;
295
+ /**
296
+ * Records a non-successful outcome for the run-scoped action circuit breaker. A fatal
297
+ * configuration error locks the action out for the rest of the run; any other failure
298
+ * updates the parameter-aware history behind the identical-arguments rule and the
299
+ * consecutive-attempt budget.
300
+ */
301
+ protected recordActionFailure(action: AgentAction, actionEntity: MJActionEntityExtended | undefined, message: string | null | undefined, normalizedParams: string): void;
302
+ /**
303
+ * Clears the parameter-aware failure history for an action after it succeeds, so the
304
+ * identical-arguments rule and the consecutive-attempt budget start over.
305
+ */
306
+ protected clearActionFailureRecord(action: AgentAction, actionEntity: MJActionEntityExtended | undefined): void;
307
+ /**
308
+ * Applies the three circuit-breaker rules to a call that is about to be dispatched. Returns a
309
+ * blocked result, with the rule that fired, when the call must not go to the action engine;
310
+ * null when it may proceed. Rules are checked fatal → identical-arguments → budget.
311
+ */
312
+ protected checkActionCircuitBreaker(params: ExecuteAgentParams, action: AgentAction, actionEntity: MJActionEntityExtended, normalizedParams: string): CircuitBreakerActionResult | null;
313
+ /** The failed {@link ActionResult} a blocked call returns in place of dispatching. */
314
+ protected buildBlockedActionResult(actionEntity: MJActionEntityExtended, reason: ActionCircuitBreakerReason, message: string): CircuitBreakerActionResult;
315
+ /**
316
+ * Names the rule behind a failed action summary so the directive matches what actually
317
+ * happened. A blocked call reports the rule that blocked it. A dispatched failure is fatal if
318
+ * `recordActionFailure` locked the action out (the summary has no access to the call's
319
+ * arguments, so the decision is read back rather than re-derived from the message); otherwise
320
+ * the budget is checked BEFORE the identical-arguments rule, because once the budget is spent
321
+ * the action is blocked whatever the arguments are, and telling the model to change them
322
+ * would send it in circles.
323
+ */
324
+ protected classifyActionFailure(summary: ActionResultSummary): ActionCircuitBreakerReason | 'warning';
325
+ /** The guidance line appended to the history for one failed action. */
326
+ protected formatActionFailureDirective(summary: ActionResultSummary): string;
151
327
  /**
152
328
  * Returns the active metadata provider for this agent run. Subclasses MUST
153
329
  * use this getter (rather than `new Metadata()` or `Metadata.Provider`) so
@@ -300,6 +476,8 @@ export declare class BaseAgent {
300
476
  * }]);
301
477
  * ```
302
478
  */
479
+ PromoteMediaOutputs(mediaOutputs: MediaOutput[]): void;
480
+ /** @deprecated Use {@link PromoteMediaOutputs}. */
303
481
  promoteMediaOutputs(mediaOutputs: MediaOutput[]): void;
304
482
  /**
305
483
  * Gets the currently accumulated media outputs for this agent run.
@@ -1384,6 +1562,151 @@ export declare class BaseAgent {
1384
1562
  */
1385
1563
  protected isFinalPermittedIteration(params: ExecuteAgentParams): boolean;
1386
1564
  protected preparePromptParams<P>(config: AgentConfiguration, payload: P, params: ExecuteAgentParams): Promise<AIPromptParams>;
1565
+ /**
1566
+ * In append-only mode, restores turn 1's volatile state fragment if mode resolution
1567
+ * was deferred until after turn 1 (e.g. dynamic model selection).
1568
+ *
1569
+ * Restores the fragment at the exact message boundary where turn 1 executed, ensuring
1570
+ * earlier turns in multi-turn conversations are not corrupted.
1571
+ *
1572
+ * This is only correct for a replace → append-only flip between turn 1 and turn 2, when
1573
+ * `_lastVolatileStateMessage` still holds turn 1's fragment. `shouldUseAppendOnlyTrailingState`
1574
+ * freezes the mode at the first model selection precisely so that no later flip can occur.
1575
+ */
1576
+ protected restoreTurn1VolatileStateIfNeeded(params: ExecuteAgentParams, isAppendOnly: boolean): void;
1577
+ /**
1578
+ * Whether THIS run has already placed a volatile-state fragment in the history, i.e. at or after
1579
+ * the turn-1 boundary. Fragments before the boundary belong to an earlier run whose history the
1580
+ * caller reused; they must not suppress this run's turn-1 restore.
1581
+ */
1582
+ protected runHasVolatileStateMessage(params: ExecuteAgentParams): boolean;
1583
+ /**
1584
+ * The message array sent for ONE request under `'trailingMessage'` placement: a copy of the history
1585
+ * with every non-system message's fragment tag literals escaped, then the real fragment last.
1586
+ *
1587
+ * Escaping at send time (rather than where text enters the history) covers every source at once —
1588
+ * user turns, action results, sub-agent results, skill activations — without rewriting stored data,
1589
+ * and it is deterministic, so the cached prefix stays byte-stable across iterations. System messages
1590
+ * and framework-authored volatile state messages are left alone.
1591
+ */
1592
+ protected assembleOutgoingMessages(history: ChatMessage[], fragment: AgentChatMessage, isAppendOnly?: boolean): ChatMessage[];
1593
+ /**
1594
+ * Determines whether the current prompt execution should use append-only trailing state retention.
1595
+ *
1596
+ * Why: OpenAI and xAI prompt caching operate on an exact byte prefix match from token 0. Replacing the
1597
+ * trailing runtime-state fragment turn-over-turn breaks the byte prefix after the system prompt,
1598
+ * dropping cache hit rates significantly. In append-only mode, prior runtime state messages are
1599
+ * retained in the message history so each turn is an exact prefix extension of the prior turn,
1600
+ * achieving ~93% cache hit rate. Providers with block-level or sliding caching (Gemini, Cerebras)
1601
+ * use replace-in-place to keep context compact.
1602
+ *
1603
+ * Which providers are which is METADATA, not code: the `PrefixPromptCache` flag in the model
1604
+ * catalog's `ModelConfiguration` cascade (Model Types < Models < Vendors' `Configuration.ModelDefaults`
1605
+ * < Model Vendors), read through {@link resolvePrefixPromptCache}. `true` means append-only;
1606
+ * anything else means replace.
1607
+ *
1608
+ * Decided ONCE per run. An explicit `trailingStateMode` or a runtime model override answers
1609
+ * immediately. Otherwise the answer is frozen at the first model selection and reused for every
1610
+ * later turn, so a failover to another vendor cannot flip the layout mid-run — a flip after turn 2
1611
+ * would leave stale fragments in the history or, worse, restore the wrong turn's fragment. On turn 1,
1612
+ * before any selection is known, the answer is replace-in-place: turn 1's fragment is kept and, if
1613
+ * turn 2 resolves to append-only, spliced back at the turn-1 boundary, which reproduces exactly the
1614
+ * bytes an append-only turn 1 would have sent. Nothing is lost by deferring, so the prompt's bound
1615
+ * models are deliberately NOT consulted — prompts commonly bind several vendors for failover, and
1616
+ * guessing from them mis-pins runs that end up selecting another vendor.
1617
+ */
1618
+ protected shouldUseAppendOnlyTrailingState(promptParams: AIPromptParams): boolean;
1619
+ /**
1620
+ * Whether a model, as served by a vendor, sits behind a byte-prefix prompt cache
1621
+ * (`LLM.PrefixPromptCache`), read from the model catalog's `ModelConfiguration` cascade —
1622
+ * `AIModelType < AIModel < AIVendor.Configuration.ModelDefaults < AIModelVendor` — via
1623
+ * `AIEngine.GetEffectiveModelConfiguration`. The most specific layer is the INFERENCE-PROVIDER
1624
+ * model-vendor row for `vendor`, whose vendor row supplies the host-wide default that beats the
1625
+ * model's own bag; when the vendor is unknown, or has no inference row for this model, the model
1626
+ * and type layers still answer. False when no layer declares it, which callers
1627
+ * treat as a block cache (replace-in-place).
1628
+ *
1629
+ * Extension point: a subclass with out-of-catalog knowledge (an OpenAI-compatible gateway whose
1630
+ * rows carry no flag, say) can override this rather than the mode decision above.
1631
+ */
1632
+ protected resolvePrefixPromptCache(model: MJAIModelEntityExtended | undefined, vendor: MJAIVendorEntity | undefined): boolean;
1633
+ /**
1634
+ * Builds the framework-authored `user` message that carries the loop agent's volatile state as the
1635
+ * final message of the request; returns null only when every block is turned off, or when the
1636
+ * system prompt template in this database has not yet synced and still embeds the state itself
1637
+ * (see the guard below). The blocks mirror the sections the template used to render (see
1638
+ * {@link RuntimeStateFragmentBuilder}), and each honors the same include flag the template did.
1639
+ *
1640
+ * Why this exists: provider prompt caching is a prefix match over tools → system → messages, so
1641
+ * state that changes every iteration INSIDE the system prompt invalidates the entire history each
1642
+ * call. Measured on Sage: 36% → 83% cached on Gemini 2.5 Flash, 12% → 96% on Claude Opus 5 (with the
1643
+ * Anthropic adapter placing its breakpoint before this message), output quality unchanged.
1644
+ *
1645
+ * The message carries STATE only — never rules. It is marked `metadata.volatileState` so adapters
1646
+ * can recognize it without depending on this package's tag names.
1647
+ */
1648
+ protected buildVolatileStateMessage<P>(params: ExecuteAgentParams, promptParams: AIPromptParams, payload: P, childPrompt: MJAIPromptEntityExtended | undefined, agentType: MJAIAgentTypeEntity, systemPrompt?: MJAIPromptEntityExtended): Promise<AgentChatMessage | null>;
1649
+ /**
1650
+ * Decides whether this run's specialization (child prompt) rides in the trailing message, and if so
1651
+ * pre-renders it and flags the template to render a stub in its place. Decided from the child
1652
+ * template's UNRENDERED text via {@link ResolveSpecializationPlacement}, so the answer is the same on
1653
+ * every iteration and the layout never flips mid-run. Returns the rendered specialization, or null
1654
+ * when it stays in the system prompt.
1655
+ */
1656
+ protected resolveRelocatedSpecialization(promptParams: AIPromptParams, childPrompt: MJAIPromptEntityExtended | undefined, agentType: MJAIAgentTypeEntity, contextUser: UserInfo): Promise<string | null>;
1657
+ /**
1658
+ * Decides, from the system prompt's UNRENDERED template text, whether the trailing runtime-state
1659
+ * fragment belongs on this request:
1660
+ *
1661
+ * - `'trailing'` — the template carries the `<mj-runtime-state>` pointer, so the model is told where
1662
+ * the state lives. The Loop agent system prompt.
1663
+ * - `'embedded'` — the template still renders the state blocks itself (an environment whose
1664
+ * TemplateContent has not synced the new Loop template, or the Flow template, which embeds the
1665
+ * payload). Emitting the fragment would deliver the same state twice.
1666
+ * - `'unsupported'` — the template has neither. The Harness system prompt, or a custom prompt run
1667
+ * without the Loop system prompt. The model would receive an unexplained block.
1668
+ * - `'unknown'` — no template text to inspect (no TemplateID, or the lookup failed). The caller
1669
+ * fails OPEN here: a Loop agent losing its payload from the model's view is far worse than a
1670
+ * non-Loop agent receiving an unexplained fragment, and in practice every agent type's system
1671
+ * prompt has a template, so this arises only from a lookup failure.
1672
+ */
1673
+ protected resolveRuntimeStateDelivery(systemPrompt: MJAIPromptEntityExtended | undefined, contextUser: UserInfo): Promise<'trailing' | 'embedded' | 'unsupported' | 'unknown'>;
1674
+ /**
1675
+ * The strings whose presence in a system prompt's unrendered template text means the template
1676
+ * still renders the volatile state itself, so the trailing fragment must be suppressed. Defaults
1677
+ * to {@link VOLATILE_TEMPLATE_MARKERS}: the three block headings plus the date and payload
1678
+ * placeholders. Extension point — an agent type whose template lays the state out under other
1679
+ * headings overrides this to return its own markers.
1680
+ */
1681
+ protected get volatileTemplateMarkers(): readonly string[];
1682
+ /**
1683
+ * True when unrendered template text contains any of {@link volatileTemplateMarkers} — the legacy
1684
+ * Loop layout, or any template that embeds the payload.
1685
+ */
1686
+ protected templateTextEmbedsVolatileState(templateText: string): boolean;
1687
+ /**
1688
+ * Raw template text (placeholders intact) for an AI prompt from the cached template engine.
1689
+ * Null when the prompt has no template or the lookup fails.
1690
+ */
1691
+ protected loadPromptTemplateText(prompt: MJAIPromptEntityExtended | undefined, contextUser: UserInfo): Promise<string | null>;
1692
+ /**
1693
+ * The child prompt's raw template text (placeholders intact), from the cached template engine.
1694
+ * Null when the prompt has no template or the lookup fails — which fails CLOSED: with no text to
1695
+ * inspect, {@link ResolveSpecializationPlacement} keeps the specialization in the system prompt.
1696
+ */
1697
+ protected loadChildPromptTemplateText(childPrompt: MJAIPromptEntityExtended, contextUser: UserInfo): Promise<string | null>;
1698
+ /**
1699
+ * The date/time strings exactly as the system placeholders would render them into the template.
1700
+ * Resolves only the three temporal placeholders (by name, through the same registry the template
1701
+ * uses, so a registered override applies here too) rather than every system placeholder — this runs
1702
+ * on every loop iteration.
1703
+ */
1704
+ protected resolveFragmentDateTime(promptParams: AIPromptParams): Promise<RuntimeStateDateTime | null>;
1705
+ /**
1706
+ * The scratchpad strings already placed in the template data by the prep step (so the fragment shows
1707
+ * exactly what the template would have). Null when the scratchpad is disabled or absent.
1708
+ */
1709
+ protected readScratchpadFromTemplateData(data: Record<string, unknown>): RuntimeStateScratchpad | null;
1387
1710
  /**
1388
1711
  * Executes the configured prompt. Always uses the attemptJSONRepair option to try to fix LLM
1389
1712
  * JSON syntax issues if they arise.
@@ -1624,6 +1947,32 @@ export declare class BaseAgent {
1624
1947
  * @protected
1625
1948
  */
1626
1949
  protected serializePayloadAtEnd(payload: any): string | null;
1950
+ /**
1951
+ * Recovery Strategy 0: drop stale runtime-state fragments.
1952
+ *
1953
+ * Under append-only trailing-state retention (prefix-cache providers: OpenAI, xAI) every
1954
+ * iteration leaves its `<mj-runtime-state>` message in the history so the next request is an
1955
+ * exact prefix extension of the last. Those copies are cached tokens on the wire, but they are
1956
+ * context all the same, and they carry nothing the model needs: the CURRENT state always rides
1957
+ * as the fresh fragment appended to the outgoing request. So when the context overflows they
1958
+ * are the first thing to go, oldest first, all but the most recent. Keeping the newest one
1959
+ * matters for two reasons: it is the history's only fragment after this pass, so
1960
+ * {@link restoreTurn1VolatileStateIfNeeded} does not splice a turn-1 copy back in, and it
1961
+ * keeps the prefix intact from that point forward. The cost is one cache miss on the next call;
1962
+ * the alternative was a failed run.
1963
+ *
1964
+ * A no-op under replace-in-place retention, where the history never holds a fragment.
1965
+ *
1966
+ * @param params - Agent execution parameters
1967
+ * @param tokensToSave - Target number of tokens to free
1968
+ * @param currentStepCount - Current turn number, for the lifecycle event
1969
+ * @returns Result with tokens saved and strategy description
1970
+ * @protected
1971
+ */
1972
+ protected recoveryStrategy_DropStaleVolatileState(params: ExecuteAgentParams, tokensToSave: number, currentStepCount: number): {
1973
+ tokensSaved: number;
1974
+ strategyName: string;
1975
+ };
1627
1976
  /**
1628
1977
  * Recovery Strategy 1: Remove oldest tool-result messages.
1629
1978
  * Targets messages older than minAge turns for removal.
@@ -1728,6 +2077,8 @@ export declare class BaseAgent {
1728
2077
  * its direct predecessor's results, so context never compounds.
1729
2078
  *
1730
2079
  * Gated on conversationId + root depth — programmatic runs and sub-agents skip it.
2080
+ * Skipped under a history floor (`ConversationHistoryFrom`): the previous run's tool
2081
+ * results can quote messages from before the floor.
1731
2082
  * @protected
1732
2083
  */
1733
2084
  protected injectPriorTurnToolResults(params: ExecuteAgentParams): Promise<void>;
@@ -2051,6 +2402,20 @@ export declare class BaseAgent {
2051
2402
  * @since 2.131.0
2052
2403
  */
2053
2404
  protected extractSchemaDefaults(schemaJson: string | null | undefined): Record<string, unknown>;
2405
+ /**
2406
+ * Whether THIS action may use the run's runtime API key for THIS driver class. The default is
2407
+ * yes: the run was started on those keys, and an action that calls a vendor on the user's behalf
2408
+ * (Generate Image) is doing what the prompts do. Override to narrow it — an agent that knows
2409
+ * which of its actions talk to which vendor can refuse everything else, and a refusal costs the
2410
+ * action nothing but the customer's key: it falls back to the platform key as if the run had none.
2411
+ */
2412
+ protected actionMayUseRuntimeAPIKey(action: MJActionEntityExtended, driverClass: string, params: ExecuteAgentParams): boolean;
2413
+ /**
2414
+ * The {@link RuntimeAPIKeyResolver} handed to one action dispatch: one driver class in, one key
2415
+ * out, the list itself never leaves this closure. Every answer is logged by action and driver
2416
+ * class (never the key), so a run's log shows which action drew which credential.
2417
+ */
2418
+ private buildRuntimeAPIKeyResolver;
2054
2419
  /**
2055
2420
  * This method executes one action using the MemberJunction Actions framework.
2056
2421
  * The full ActionResult objects are returned, allowing the caller to access result codes, output parameters,
@@ -2059,12 +2424,14 @@ export declare class BaseAgent {
2059
2424
  * @param {ExecuteAgentParams} params - Parameters from agent execution for context passing
2060
2425
  * @param {AgentAction} action - Action to execute
2061
2426
  * @param {UserInfo} [contextUser] - Optional user context for permissions
2427
+ * @param {ExecuteSingleActionOptions} [options] - `skipCircuitBreaker` bypasses the run-scoped
2428
+ * circuit breaker for callers that do their own failure accounting (the pipeline executor)
2062
2429
  *
2063
2430
  * @returns {Promise<ActionResult>} ActionResult object from the action execution
2064
2431
  *
2065
2432
  * @throws {Error} If the action fails to execute
2066
2433
  */
2067
- ExecuteSingleAction(params: ExecuteAgentParams, action: AgentAction, actionEntity: MJActionEntityExtended, contextUser?: UserInfo): Promise<ActionResult>;
2434
+ ExecuteSingleAction(params: ExecuteAgentParams, action: AgentAction, actionEntity: MJActionEntityExtended, contextUser?: UserInfo, options?: ExecuteSingleActionOptions): Promise<ActionResult>;
2068
2435
  /**
2069
2436
  * Makes a SLICED conversation window safe to send on its own.
2070
2437
  *
@@ -2095,6 +2462,13 @@ export declare class BaseAgent {
2095
2462
  * **Priority:** AIAgentRelationship.MessageMode takes precedence over AIAgent.MessageMode
2096
2463
  * to allow different parent agents to pass messages differently to the same sub-agent.
2097
2464
  *
2465
+ * **Runtime state never crosses the boundary.** The parent's trailing runtime-state messages
2466
+ * (`metadata.volatileState` — its payload, scratchpad and, when relocated, its specialization;
2467
+ * retained in the history under append-only mode) are dropped BEFORE any mode slices the
2468
+ * history, so a sub-agent never sees the parent's state, never has it counted against
2469
+ * `MaxMessages`, and never receives it unescaped when it builds no fragment of its own. The
2470
+ * sub-agent builds its own fragment at its prompt step.
2471
+ *
2098
2472
  * Subclasses can override this method to implement custom message preparation logic
2099
2473
  * specific to their domain (e.g., Skip agents adding special context).
2100
2474
  *
@@ -2847,6 +3221,13 @@ export declare class BaseAgent {
2847
3221
  * Supports both dot notation (obj.prop) and array indexing (arr[0]).
2848
3222
  *
2849
3223
 
3224
+ /**
3225
+ * The {@link ExecuteSingleActionOptions} the main loop passes for this run's agent type: the
3226
+ * circuit-breaker exemption when the type has opted out (`BaseAgentType.UsesActionCircuitBreaker`
3227
+ * is false — Flow), otherwise none. Kept as a seam so a subclass can widen or narrow the
3228
+ * exemption without touching the loop.
3229
+ */
3230
+ protected actionOptionsForAgentType(): ExecuteSingleActionOptions | undefined;
2850
3231
  /**
2851
3232
  * Executes actions step and tracks it.
2852
3233
  *
@@ -3280,6 +3661,23 @@ export declare class BaseAgent {
3280
3661
  * rather than being deleted after a single prompt turn.
3281
3662
  */
3282
3663
  private injectLoopResultsMessage;
3664
+ /**
3665
+ * Fails a loop that never ran an iteration, and tells the model why.
3666
+ *
3667
+ * A Loop agent answers a Failed step by prompting again (`HandleStepFallback` returns null), and
3668
+ * nothing on that path reads the step's `errorMessage`. Without the injected message the model
3669
+ * gets another turn with no idea its loop failed, and is likely to emit the same loop again.
3670
+ * Flow agents don't inject loop results, so for them this is just the Failed step.
3671
+ */
3672
+ private failLoopBeforeFirstIteration;
3673
+ /**
3674
+ * One loop error as readable text. Joining the error objects directly wrote "[object Object]"
3675
+ * into the step's ErrorMessage. Falls back to JSON when an iteration threw something with no
3676
+ * message (a thrown non-Error).
3677
+ */
3678
+ private describeLoopError;
3679
+ /** All loop errors as text for a step's ErrorMessage. */
3680
+ private formatLoopErrors;
3283
3681
  /**
3284
3682
  * Formats loop iteration results as markdown. Handles two distinct result shapes
3285
3683
  * depending on whether the loop body executed actions or sub-agents:
@@ -3442,6 +3840,8 @@ export declare class BaseAgent {
3442
3840
  * (agent or type ContextWindowMaxTokens) — before the first prompt the model is
3443
3841
  * unknown, and compacting against the conservative default would over-trigger on
3444
3842
  * large-context models. The post-turn hook (real model known) covers those.
3843
+ * Skipped under a history floor (`ConversationHistoryFrom`): a summary folds in the
3844
+ * conversation from its first message, which is what the floor excludes.
3445
3845
  * @protected
3446
3846
  */
3447
3847
  protected checkPreTurnCompaction(params: ExecuteAgentParams, config: AgentConfiguration | undefined): Promise<void>;
@@ -3453,6 +3853,11 @@ export declare class BaseAgent {
3453
3853
  * final step (→ AwaitingFeedback) is the NORMAL ending of a conversational turn;
3454
3854
  * gating on 'Completed' alone silently disabled post-turn compaction for exactly
3455
3855
  * the long-chat scenario this feature targets.
3856
+ *
3857
+ * Skipped under a history floor (`ConversationHistoryFrom`). A run with a floor must not
3858
+ * write the conversation's summary: the summary covers every row below its boundary, and
3859
+ * a run that may not read the rows before the floor can't produce that — nor, once reads
3860
+ * are narrowed to what the asker can see, can it tell which rows it was not shown.
3456
3861
  * @protected
3457
3862
  */
3458
3863
  protected startPostTurnCompaction(): void;