@myagentroam/agent 0.10.12 → 0.10.14

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.
@@ -949,7 +949,8 @@ function responsesRequestBody(configuration, request, messages) {
949
949
  ...(tools.length > 0 ? { tool_choice: toolChoice, parallel_tool_calls: true } : {}),
950
950
  input,
951
951
  stream: true,
952
- store: configuration.responsesTransport?.transport !== 'WEBSOCKET',
952
+ store: configuration.responsesPreviousResponseId === true &&
953
+ configuration.responsesTransport?.transport !== 'WEBSOCKET',
953
954
  ...(configuration.responsesOptionalParameters?.textVerbosity === false
954
955
  ? {}
955
956
  : { text: { verbosity: 'low' } }),
@@ -1,6 +1,6 @@
1
1
  import type { ExecutionMode } from '../runtime/contracts.js';
2
2
  import { type CorePromptPart } from '../extensions/prompt-composition.js';
3
- export declare const MAR_AGENT_PROMPT_VERSION = "1.63";
3
+ export declare const MAR_AGENT_PROMPT_VERSION = "1.64";
4
4
  interface SystemPromptInput {
5
5
  mode: ExecutionMode;
6
6
  platform: string;
@@ -5,7 +5,7 @@ import { modePrompt } from './modes.js';
5
5
  import { outputStylePrompt } from './output.js';
6
6
  import { subagentPrompt } from './subagent.js';
7
7
  import { interactionPrompt, longRunningPrompt, safetyPrompt, toolUsagePrompt, workflowPrompt } from './workflow.js';
8
- export const MAR_AGENT_PROMPT_VERSION = '1.63';
8
+ export const MAR_AGENT_PROMPT_VERSION = '1.64';
9
9
  export function buildSystemPrompt(input) {
10
10
  return renderPromptSections(buildSystemPromptSections(input));
11
11
  }
@@ -1,11 +1,11 @@
1
1
  export function modePrompt(mode, input) {
2
2
  if (mode !== 'plan')
3
3
  return '';
4
- const investigationGuidance = 'Resolve discoverable facts through targeted read-only investigation. Ask about user-owned preferences and tradeoffs early when they cannot be inferred from the request, conversation, or workspace evidence. If current environment guidance requires finalization, stop further exploration and use only evidence already gathered.';
4
+ const investigationGuidance = 'Resolve discoverable facts through targeted read-only investigation. Ask about user-owned preferences and tradeoffs early when they cannot be inferred from the request, conversation, or workspace evidence.';
5
5
  const decisionGuidance = input.questionAvailable
6
6
  ? 'Use question for unresolved choices that materially change the result; do not finalize the plan while such choices remain. Do not invent support for multiple outcomes or silently choose a default to avoid asking.'
7
- : 'Ask a concise plain-text question for unresolved user-owned choices that materially change the result instead of finalizing an ambiguous plan. When current environment guidance requires finalization and user input is unavailable, state the unresolved decision and its impact instead of guessing. Do not invent support for multiple outcomes or silently choose a default.';
8
- const finalGuidance = 'Once the plan is decision-complete, return only a concise, actionable plan. Break the work into meaningful, logically ordered deliverables that are easy to verify. Do not pad the plan with filler or obvious steps. Include the implementation and verification detail needed to execute it, without drafting the implementation itself. When current environment guidance requires finalization, return the concise verified staged plan and distinguish incomplete work or unresolved decisions. Do not ask whether to proceed or claim unresolved work is complete.';
7
+ : 'Ask a concise plain-text question for unresolved user-owned choices that materially change the result instead of finalizing an ambiguous plan. If user input is unavailable, state the unresolved decision and its impact instead of guessing. Do not invent support for multiple outcomes or silently choose a default.';
8
+ const finalGuidance = 'Once the plan is decision-complete, return only a concise, actionable plan. Break the work into meaningful, logically ordered deliverables that are easy to verify. Do not pad the plan with filler or obvious steps. Include the implementation and verification detail needed to execute it, without drafting the implementation itself. Do not ask whether to proceed or claim unresolved work is complete.';
9
9
  return `# Plan mode
10
10
  Use tools only for read-only investigation that reduces uncertainty and improves the plan. Do not create, modify, delete, rename, or move files, and do not run commands intended to mutate repository-tracked state or implement the requested work. This is behavioral guidance, not a security boundary; the normal tools and Host policies remain available.
11
11
 
@@ -30,6 +30,7 @@ export interface ExecutionResult {
30
30
  errorCode?: string;
31
31
  errorMessage?: string;
32
32
  }
33
+ /** @deprecated Execution token budgets are no longer enforced. */
33
34
  export interface RolloutBudgetOptions {
34
35
  limitTokens?: number;
35
36
  conserveAtRemainingTokens?: number;
@@ -1,10 +1,5 @@
1
1
  export declare const AGENT_EXECUTION_POLICY: Readonly<{
2
2
  subagentModelRounds: 32;
3
- rolloutBudgetTokens: 1250000;
4
- rolloutBudgetConserveRemainingTokens: 350000;
5
- rolloutBudgetFinalizeRemainingTokens: 200000;
6
- rolloutBudgetSamplingTokenWeight: 1;
7
- rolloutBudgetPrefillTokenWeight: 1;
8
3
  toolEventSummaryCharacters: 2000;
9
4
  modelToolOutputTokens: 10000;
10
5
  automaticCompactionPercent: 90;
@@ -1,10 +1,5 @@
1
1
  export const AGENT_EXECUTION_POLICY = Object.freeze({
2
2
  subagentModelRounds: 32,
3
- rolloutBudgetTokens: 1_250_000,
4
- rolloutBudgetConserveRemainingTokens: 350_000,
5
- rolloutBudgetFinalizeRemainingTokens: 200_000,
6
- rolloutBudgetSamplingTokenWeight: 1,
7
- rolloutBudgetPrefillTokenWeight: 1,
8
3
  toolEventSummaryCharacters: 2_000,
9
4
  modelToolOutputTokens: 10_000,
10
5
  automaticCompactionPercent: 90,
@@ -5,7 +5,6 @@ import type { ToolRuntimeImage } from '../tools/runtime-context.js';
5
5
  import type { AuthoritativeModelUsage } from './context/usage.js';
6
6
  import type { ExecutionMode } from './contracts.js';
7
7
  import type { EventPayload } from './events.js';
8
- import type { RolloutBudget } from './rollout-budget.js';
9
8
  export interface PreparedExecutionRound {
10
9
  readonly request: ModelRequest;
11
10
  readonly toolScope: RoundToolScope;
@@ -18,7 +17,6 @@ export interface ExecutionLoopInput {
18
17
  readonly model: Pick<MarAgentModelConfiguration, 'id' | 'name'>;
19
18
  readonly messages: ModelMessage[];
20
19
  readonly toolImages: ToolRuntimeImage[];
21
- readonly rolloutBudget: RolloutBudget | undefined;
22
20
  readonly publish: (event: EventPayload) => Promise<void>;
23
21
  readonly appendContext: (message: ModelMessage) => Promise<void>;
24
22
  readonly prepareRound: (continuation: ModelMessage | undefined) => Promise<PreparedExecutionRound>;
@@ -35,7 +35,6 @@ export class ExecutionLoop {
35
35
  const pendingTools = [];
36
36
  let incompleteToolCall = false;
37
37
  const round = await input.prepareRound(pendingOutputContinuation);
38
- input.rolloutBudget?.assertAvailable();
39
38
  let sawModelSemanticEvent = false;
40
39
  let requestStartedAt;
41
40
  let firstModelResponseAt;
@@ -340,9 +339,6 @@ export class ExecutionLoop {
340
339
  if (input.sourceType === 'subagent')
341
340
  this.finalAnswer = '';
342
341
  }
343
- input.rolloutBudget?.recordUsage(latestUsage);
344
- if (!input.signal.aborted)
345
- input.rolloutBudget?.assertAvailable();
346
342
  if (mode !== 'compact' && stop === 'max_output') {
347
343
  const needsContinuation = !sawTool || incompleteToolCall;
348
344
  if (needsContinuation) {
@@ -365,7 +361,6 @@ export class ExecutionLoop {
365
361
  const aborted = toolResults.find((result) => result.failed)?.error;
366
362
  throw aborted ?? new MarAgentError('MAR_AGENT_EXECUTION_CANCELLED', 'Execution cancelled.');
367
363
  }
368
- input.rolloutBudget?.assertAvailable();
369
364
  if (input.mailbox.hasPending() && (await input.mailbox.append())) {
370
365
  this.finalAnswer = '';
371
366
  continue;
@@ -7,7 +7,6 @@ import { negotiateHost } from '../host/contracts.js';
7
7
  import { toolCallers } from '../tools/callers.js';
8
8
  import { AnthropicMessagesAdapter } from '../model/anthropic-messages.js';
9
9
  import { OpenAiResponsesAdapter } from '../model/openai-responses.js';
10
- import { resolveRolloutBudgetOptions } from '../runtime/rollout-budget.js';
11
10
  import { JsonlSessionStore } from '../session/jsonl-store.js';
12
11
  /** Validate models before Host negotiation and expose only built-in protocol adapters. */
13
12
  export async function createMarAgent(options) {
@@ -17,7 +16,6 @@ export async function createMarAgent(options) {
17
16
  }
18
17
  /** Package-internal seam for deterministic adapter tests; not a package export. */
19
18
  export async function createMarAgentWithAdapter(options) {
20
- const rolloutBudgetOptions = resolveRolloutBudgetOptions(options.rolloutBudget);
21
19
  const resolvedModels = resolveAgentModels(options.models);
22
20
  let { models, defaultModelId } = resolvedModels;
23
21
  let modelGeneration = 0;
@@ -169,7 +167,6 @@ export async function createMarAgentWithAdapter(options) {
169
167
  sessionRuntimes,
170
168
  sessionWriterOwner
171
169
  },
172
- rolloutBudgetOptions,
173
170
  hasCustomAdapters: options.adapterFactory !== undefined,
174
171
  modelState: () => ({ models, defaultModelId, generation: modelGeneration }),
175
172
  createAdapter,
@@ -9,7 +9,6 @@ import type { CoreAgentsBackend } from '../extensions/agents.js';
9
9
  import type { HostDescription, MarAgentHost } from '../host/contracts.js';
10
10
  import { type MarAgentReasoningEffort } from '../model/configuration.js';
11
11
  import type { ModelAdapter, ModelMessage } from '../model/contracts.js';
12
- import { resolveRolloutBudgetOptions } from '../runtime/rollout-budget.js';
13
12
  import { JsonlSessionStore } from '../session/jsonl-store.js';
14
13
  import { SubagentSessionController, type SubagentMailboxMessage, type SubagentMessageDelivery, type SubagentTurnHandle } from '../subagent/session-controller.js';
15
14
  import { createSessionToolScheduler } from '../tools/scheduler.js';
@@ -69,7 +68,6 @@ interface SessionServices {
69
68
  readonly store: JsonlSessionStore;
70
69
  readonly extensions: ExtensionManager;
71
70
  readonly registry: AgentSessionRegistry;
72
- readonly rolloutBudgetOptions: ReturnType<typeof resolveRolloutBudgetOptions>;
73
71
  readonly hasCustomAdapters: boolean;
74
72
  readonly modelState: () => {
75
73
  readonly models: ReadonlyMap<string, ResolvedModelConfiguration>;
@@ -24,7 +24,6 @@ import { coreMcpCatalog } from '../extensions/mcp.js';
24
24
  import { isDeepStrictEqual } from 'node:util';
25
25
  import { MarAgentError, describeMarAgentError } from '../error.js';
26
26
  import { usesResponsesConfigurationUpdates } from '../model/configuration.js';
27
- import { executionBudgetEnvironmentEntry } from '../prompts/execution-budget.js';
28
27
  import { MAR_AGENT_PROMPT_VERSION, buildSystemPromptSections } from '../prompts/index.js';
29
28
  import { renderPromptSections } from '../extensions/prompt-composition.js';
30
29
  import { retainedSessionResourcesSnapshot } from '../prompts/resources.js';
@@ -37,7 +36,6 @@ import { ContextGcRuntime } from '../runtime/context/gc-runtime.js';
37
36
  import { AGENT_EXECUTION_POLICY } from '../runtime/execution-policy.js';
38
37
  import { loadAgentInstructions, renderAgentInstructions } from '../runtime/context/instructions.js';
39
38
  import { normalizeMessagesForModel } from '../runtime/context/normalize.js';
40
- import { RolloutBudget } from '../runtime/rollout-budget.js';
41
39
  import { compactSummaryFromCheckpoint, inputMetadataFromRecord } from '../session/jsonl-store.js';
42
40
  import { SubagentSessionController } from '../subagent/session-controller.js';
43
41
  import { agentStartToolDefinitionWithModels } from '../tools/agent/agent-start.js';
@@ -50,7 +48,7 @@ import { TodoStore } from '../tools/agent/todo.js';
50
48
  import { DeferredMcpRegistry } from '../tools/mcp/tool-search.js';
51
49
  /** SDK Session orchestration owns warm resources; Runtime owns only the model/tool loop. */
52
50
  export function createSessionOpener(services) {
53
- const { host, description, settings, store, rolloutBudgetOptions, createAdapter, activeAdaptersExcept } = services;
51
+ const { host, description, settings, store, createAdapter, activeAdaptersExcept } = services;
54
52
  const { active, activeExecutionAdapters, executionResults, sessionRuntimes, sessionWriterOwner } = services.registry;
55
53
  const openSession = async (sessionId, workspace) => {
56
54
  const storedSession = await store.getSession(sessionId);
@@ -327,9 +325,6 @@ export function createSessionOpener(services) {
327
325
  let finalAnswer = '';
328
326
  let executionLoop;
329
327
  let manualCompaction;
330
- const rolloutBudget = sessionSource.type === 'user' && rolloutBudgetOptions
331
- ? new RolloutBudget(rolloutBudgetOptions)
332
- : undefined;
333
328
  let releaseSession;
334
329
  let executionToolSources;
335
330
  let selectedTurn;
@@ -395,23 +390,6 @@ export function createSessionOpener(services) {
395
390
  pendingAppends.length = 0;
396
391
  immediateTarget = messages;
397
392
  let recordedEnvironment = restored.environmentState;
398
- let projectedExecutionBudgetStage;
399
- const appendExecutionBudgetEnvironment = () => {
400
- rolloutBudget?.assertAvailable();
401
- const currentStage = rolloutBudget?.active ? rolloutBudget.stage : 'inactive';
402
- if (currentStage === 'exhausted')
403
- return;
404
- if (currentStage === projectedExecutionBudgetStage)
405
- return;
406
- const previousStage = projectedExecutionBudgetStage;
407
- projectedExecutionBudgetStage = currentStage;
408
- if ((previousStage === undefined &&
409
- (currentStage === 'normal' || currentStage === 'inactive')) ||
410
- (currentStage === 'inactive' && previousStage === 'normal'))
411
- return;
412
- const entry = executionBudgetEnvironmentEntry(currentStage === 'normal' ? 'inactive' : currentStage);
413
- messages.push(environmentContextUpdate(executionEnvironment, executionEnvironment, [entry]));
414
- };
415
393
  let compactContext;
416
394
  const writeInputRecord = async (content, type, metadata, call, committed) => {
417
395
  call.signal.throwIfAborted();
@@ -1107,7 +1085,6 @@ export function createSessionOpener(services) {
1107
1085
  manualCompactionStarted = true;
1108
1086
  manualCompaction = createCompactionOperation(manualCompactionId, compactSignal);
1109
1087
  await emit({ type: 'context.compacting', compactionId: manualCompactionId });
1110
- rolloutBudget?.assertAvailable();
1111
1088
  manualExtension = await generateCompactExtension(messages, 'manual', compactFocus, manualCompaction);
1112
1089
  }
1113
1090
  if (mode === 'compact' && manualExtension === undefined) {
@@ -1259,7 +1236,6 @@ export function createSessionOpener(services) {
1259
1236
  }
1260
1237
  if (!compactSummary)
1261
1238
  throw new MarAgentError('MAR_AGENT_COMPACT_FAILED', 'Automatic compact failed.');
1262
- rolloutBudget?.recordUsage(latestUsage);
1263
1239
  let replacementHistory = buildCompactedHistory(compactSummary, retainCurrent ? compactionUserMessages.slice(0, -1) : compactionUserMessages, compactUserTokenLimit, retainCurrent
1264
1240
  ? {
1265
1241
  content: current.content,
@@ -1297,7 +1273,6 @@ export function createSessionOpener(services) {
1297
1273
  });
1298
1274
  contextGc.reset();
1299
1275
  restoreMcpDiscovery();
1300
- projectedExecutionBudgetStage = undefined;
1301
1276
  recordedEnvironment = executionEnvironment;
1302
1277
  compactionUserMessages = replacementHistory
1303
1278
  .filter((message) => message.kind !== 'summary')
@@ -1337,7 +1312,6 @@ export function createSessionOpener(services) {
1337
1312
  model: selectedModel,
1338
1313
  messages,
1339
1314
  toolImages: currentExecutionToolImages,
1340
- rolloutBudget,
1341
1315
  publish: emit,
1342
1316
  appendContext: (message) => withRecordProjection(async () => {
1343
1317
  await store.append(sessionId, {
@@ -1350,7 +1324,6 @@ export function createSessionOpener(services) {
1350
1324
  prepareRound: async (pendingOutputContinuation) => {
1351
1325
  if (mode !== 'compact')
1352
1326
  await appendMailboxMessages();
1353
- appendExecutionBudgetEnvironment();
1354
1327
  updateMcpRegistry();
1355
1328
  executionTools = mcpRegistry.project(baseTools());
1356
1329
  if (mode !== 'compact')
@@ -1358,7 +1331,6 @@ export function createSessionOpener(services) {
1358
1331
  await ensureContextBudget();
1359
1332
  if (mode !== 'compact')
1360
1333
  await syncMcpWorldState(messages.length);
1361
- appendExecutionBudgetEnvironment();
1362
1334
  if (mode !== 'compact') {
1363
1335
  executionEnvironment = { ...currentEnvironment, ...currentLocalTimeContext() };
1364
1336
  await recordEnvironment();
@@ -1491,7 +1463,6 @@ export function createSessionOpener(services) {
1491
1463
  .map((entry) => entry.message);
1492
1464
  messages.splice(0, messages.length, ...refreshed.messages, ...lateMessages);
1493
1465
  restoreMcpDiscovery();
1494
- projectedExecutionBudgetStage = undefined;
1495
1466
  recordedEnvironment = refreshed.environmentState;
1496
1467
  compactionUserMessages = [...refreshed.userMessages];
1497
1468
  agentInstructionInsertIndex = contextualInstructionInsertIndex(messages);
@@ -1512,8 +1483,6 @@ export function createSessionOpener(services) {
1512
1483
  }
1513
1484
  });
1514
1485
  if (manualExtension) {
1515
- rolloutBudget?.recordUsage(manualExtension.usage);
1516
- rolloutBudget?.assertAvailable();
1517
1486
  if (manualExtension.usage)
1518
1487
  await emit({ type: 'usage.updated', ...publicModelUsage(manualExtension.usage) });
1519
1488
  }
@@ -1602,7 +1571,6 @@ export function createSessionOpener(services) {
1602
1571
  if (sessionRuntime.toolSources === executionToolSources)
1603
1572
  delete sessionRuntime.toolSources;
1604
1573
  internal.signal?.removeEventListener('abort', abortSource);
1605
- rolloutBudget?.discard();
1606
1574
  await manualCompaction?.dispose();
1607
1575
  await selectedTurn?.close().catch(() => undefined);
1608
1576
  try {
@@ -60,6 +60,7 @@ export interface CreateMarAgentOptions {
60
60
  readonly logicalPath: string;
61
61
  readonly physicalPath: string;
62
62
  };
63
+ /** @deprecated Accepted for source compatibility and otherwise ignored. */
63
64
  rolloutBudget?: false | RolloutBudgetOptions;
64
65
  runtimeExtensions?: readonly CoreRuntimeExtension[] | CoreExtensionSource;
65
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.10.12",
3
+ "version": "0.10.14",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,3 +0,0 @@
1
- import type { RolloutBudgetStage } from '../runtime/rollout-budget.js';
2
- export type ExecutionBudgetEnvironmentStage = Exclude<RolloutBudgetStage, 'normal' | 'exhausted'> | 'inactive';
3
- export declare function executionBudgetEnvironmentEntry(stage: ExecutionBudgetEnvironmentStage): string;
@@ -1,9 +0,0 @@
1
- export function executionBudgetEnvironmentEntry(stage) {
2
- if (stage === 'inactive')
3
- return '<execution_guidance status="inactive" />';
4
- const privateInstruction = 'This is internal runtime guidance. Never mention the budget, thresholds, remaining amount, or budget stage in user-visible progress or the final answer.';
5
- const guidance = stage === 'finalize'
6
- ? 'Enter finalization now. Do not start new investigation or new subagents. Complete only the current atomic change, the minimum necessary verification, and the final answer as soon as possible.'
7
- : 'Stop expanding scope and stop optional work. Prefer completing the current objective with the evidence already gathered, and avoid new investigation unless it is strictly required for correctness.';
8
- return `<execution_guidance stage="${stage}">\n${privateInstruction}\n\n${guidance}\n</execution_guidance>`;
9
- }
@@ -1,25 +0,0 @@
1
- import type { ModelUsage } from '../model/contracts.js';
2
- import type { RolloutBudgetOptions } from './contracts.js';
3
- export type RolloutBudgetStage = 'normal' | 'conserve' | 'finalize' | 'exhausted';
4
- export interface ResolvedRolloutBudgetOptions {
5
- limitTokens: number;
6
- conserveAtRemainingTokens: number;
7
- finalizeAtRemainingTokens: number;
8
- samplingTokenWeight: number;
9
- prefillTokenWeight: number;
10
- }
11
- export declare class RolloutBudget {
12
- #private;
13
- readonly options: ResolvedRolloutBudgetOptions;
14
- constructor(options: ResolvedRolloutBudgetOptions);
15
- get active(): boolean;
16
- get limitTokens(): number;
17
- get spentTokens(): number;
18
- get remainingTokens(): number;
19
- get stage(): RolloutBudgetStage;
20
- recordUsage(usage: ModelUsage | undefined): number;
21
- discard(): void;
22
- assertAvailable(): void;
23
- }
24
- export declare function resolveRolloutBudgetOptions(options: false | RolloutBudgetOptions | undefined): ResolvedRolloutBudgetOptions | undefined;
25
- export declare function createRolloutBudget(options: false | RolloutBudgetOptions | undefined): RolloutBudget | undefined;
@@ -1,96 +0,0 @@
1
- import { MarAgentError } from '../error.js';
2
- import { AGENT_EXECUTION_POLICY } from './execution-policy.js';
3
- export class RolloutBudget {
4
- options;
5
- #spentTokens = 0;
6
- #active = true;
7
- constructor(options) {
8
- this.options = options;
9
- }
10
- get active() {
11
- return this.#active;
12
- }
13
- get limitTokens() {
14
- return this.options.limitTokens;
15
- }
16
- get spentTokens() {
17
- return this.#spentTokens;
18
- }
19
- get remainingTokens() {
20
- return Math.max(0, this.limitTokens - this.#spentTokens);
21
- }
22
- get stage() {
23
- if (!this.#active)
24
- return 'normal';
25
- const remaining = this.remainingTokens;
26
- if (remaining <= 0)
27
- return 'exhausted';
28
- if (remaining <= this.options.finalizeAtRemainingTokens)
29
- return 'finalize';
30
- if (remaining <= this.options.conserveAtRemainingTokens)
31
- return 'conserve';
32
- return 'normal';
33
- }
34
- recordUsage(usage) {
35
- if (!this.#active || !usage)
36
- return 0;
37
- const providerUnits = usage.rolloutBudgetUnits;
38
- if (providerUnits !== undefined && (!Number.isFinite(providerUnits) || providerUnits < 0))
39
- throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Provider rollout budget units are invalid.');
40
- const charged = providerUnits ??
41
- nonnegative(usage.outputTokens) * this.options.samplingTokenWeight +
42
- Math.max(nonnegative(usage.contextInputTokens ?? usage.inputTokens) -
43
- nonnegative(usage.cacheReadTokens), 0) *
44
- this.options.prefillTokenWeight;
45
- this.#spentTokens += charged;
46
- return charged;
47
- }
48
- discard() {
49
- this.#active = false;
50
- }
51
- assertAvailable() {
52
- if (this.stage === 'exhausted')
53
- throw new MarAgentError('MAR_AGENT_ROLLOUT_BUDGET_EXCEEDED', 'The execution token budget has been exhausted.');
54
- }
55
- }
56
- export function resolveRolloutBudgetOptions(options) {
57
- if (options === false)
58
- return undefined;
59
- const limitTokens = options?.limitTokens ?? AGENT_EXECUTION_POLICY.rolloutBudgetTokens;
60
- if (!Number.isSafeInteger(limitTokens) || limitTokens < 2)
61
- return invalid();
62
- const conserveAtRemainingTokens = options?.conserveAtRemainingTokens ??
63
- Math.min(AGENT_EXECUTION_POLICY.rolloutBudgetConserveRemainingTokens, Math.max(1, Math.floor(limitTokens * 0.28)));
64
- const finalizeAtRemainingTokens = options?.finalizeAtRemainingTokens ??
65
- Math.min(AGENT_EXECUTION_POLICY.rolloutBudgetFinalizeRemainingTokens, Math.max(0, Math.min(conserveAtRemainingTokens - 1, Math.floor(limitTokens * 0.16))));
66
- const samplingTokenWeight = options?.samplingTokenWeight ?? AGENT_EXECUTION_POLICY.rolloutBudgetSamplingTokenWeight;
67
- const prefillTokenWeight = options?.prefillTokenWeight ?? AGENT_EXECUTION_POLICY.rolloutBudgetPrefillTokenWeight;
68
- if (!Number.isSafeInteger(conserveAtRemainingTokens) ||
69
- conserveAtRemainingTokens < 0 ||
70
- conserveAtRemainingTokens >= limitTokens ||
71
- !Number.isSafeInteger(finalizeAtRemainingTokens) ||
72
- finalizeAtRemainingTokens < 0 ||
73
- finalizeAtRemainingTokens >= conserveAtRemainingTokens ||
74
- !Number.isFinite(samplingTokenWeight) ||
75
- samplingTokenWeight < 0 ||
76
- !Number.isFinite(prefillTokenWeight) ||
77
- prefillTokenWeight < 0)
78
- return invalid();
79
- return {
80
- limitTokens,
81
- conserveAtRemainingTokens,
82
- finalizeAtRemainingTokens,
83
- samplingTokenWeight,
84
- prefillTokenWeight
85
- };
86
- }
87
- export function createRolloutBudget(options) {
88
- const resolved = resolveRolloutBudgetOptions(options);
89
- return resolved ? new RolloutBudget(resolved) : undefined;
90
- }
91
- function nonnegative(value) {
92
- return value !== undefined && Number.isFinite(value) && value >= 0 ? value : 0;
93
- }
94
- function invalid() {
95
- throw new MarAgentError('MAR_AGENT_ROLLOUT_BUDGET_INVALID', 'Rollout budget configuration is invalid.');
96
- }