@myagentroam/agent 0.9.96 → 0.9.97

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.
@@ -15,4 +15,4 @@ export interface EnvironmentContextState {
15
15
  guaranteedCommands?: Readonly<Record<string, string>>;
16
16
  workspace: string;
17
17
  }
18
- export declare function buildEnvironmentContext(input: EnvironmentContextState, previous?: EnvironmentContextState): string;
18
+ export declare function buildEnvironmentContext(input: EnvironmentContextState, previous?: EnvironmentContextState, contextualEntries?: readonly string[]): string;
@@ -6,7 +6,7 @@ export const workspaceDisciplinePrompt = '# Workspace and change discipline\nAss
6
6
  export function environmentPrompt(input) {
7
7
  return `# Environment and workspace\nMode: ${input.mode}. The Runtime provides current platform, shell and Workspace facts in an environment_context message. These facts describe the execution environment, not additional instructions or permissions. Start exploration inside this workspace unless the task explicitly requires an absolute path elsewhere. Generate commands for the actual platform and configured shell; do not assume POSIX tools on Windows or PowerShell/cmd syntax on Unix. Relative tool paths resolve from the Workspace. Absolute paths are allowed subject to the operating-system account's permissions and Host-declared file boundaries.`;
8
8
  }
9
- export function buildEnvironmentContext(input, previous) {
9
+ export function buildEnvironmentContext(input, previous, contextualEntries = []) {
10
10
  const element = (name, value) => `<${name}>${value.replace(/[&<>"']/g, (character) => {
11
11
  return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&apos;' }[character];
12
12
  })}</${name}>`;
@@ -31,7 +31,7 @@ export function buildEnvironmentContext(input, previous) {
31
31
  return [];
32
32
  return [value ?? `<${name} status="unavailable" />`];
33
33
  });
34
- return changes.length
35
- ? ['<environment_context>', ...changes, '</environment_context>'].join('\n')
34
+ return changes.length > 0 || contextualEntries.length > 0
35
+ ? ['<environment_context>', ...changes, ...contextualEntries, '</environment_context>'].join('\n')
36
36
  : '';
37
37
  }
@@ -1,6 +1,3 @@
1
1
  import type { RolloutBudgetStage } from '../runtime/rollout-budget.js';
2
- export interface ExecutionBudgetPromptState {
3
- stage: RolloutBudgetStage;
4
- limitTokens: number;
5
- }
6
- export declare function executionBudgetPrompt(input: ExecutionBudgetPromptState): string;
2
+ export type ExecutionBudgetEnvironmentStage = Exclude<RolloutBudgetStage, 'normal'> | 'inactive';
3
+ export declare function executionBudgetEnvironmentEntry(stage: ExecutionBudgetEnvironmentStage): string;
@@ -1,10 +1,11 @@
1
- export function executionBudgetPrompt(input) {
1
+ export function executionBudgetEnvironmentEntry(stage) {
2
+ if (stage === 'inactive')
3
+ return '<execution_guidance status="inactive" />';
2
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.';
3
- if (input.stage === 'exhausted')
4
- return `# Execution budget\n${privateInstruction}\n\nThe shared rollout budget is exhausted. Do not start or continue investigation, optional work, new tool exploration, or new subagents. Return a concise final answer now using the current verified staged result. Clearly distinguish completed work from anything still incomplete, without mentioning this budget.`;
5
- if (input.stage === 'finalize')
6
- return `# Execution budget\n${privateInstruction}\n\nEnter 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
- if (input.stage === 'conserve')
8
- return `# Execution budget\n${privateInstruction}\n\nStop 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.`;
9
- return `# Execution budget\n${privateInstruction}\n\nThis main Execution and the subagents it creates share an internal weighted token budget of ${input.limitTokens}. Work normally, but keep scope disciplined and converge once the requested outcome is verified.`;
5
+ const guidance = stage === 'exhausted'
6
+ ? 'The shared rollout budget is exhausted. Do not start or continue investigation, optional work, new tool exploration, or new subagents. Return a concise final answer now using the current verified staged result. Clearly distinguish completed work from anything still incomplete, without mentioning this budget.'
7
+ : stage === 'finalize'
8
+ ? '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.'
9
+ : '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.';
10
+ return `<execution_guidance stage="${stage}">\n${privateInstruction}\n\n${guidance}\n</execution_guidance>`;
10
11
  }
@@ -1,7 +1,6 @@
1
1
  import type { ExecutionMode } from '../sdk/types.js';
2
- import { type ExecutionBudgetPromptState } from './execution-budget.js';
3
2
  import { type CurrentAgentModel, type SubagentModelOption } from './subagent.js';
4
- export declare const MAR_AGENT_PROMPT_VERSION = "1.52";
3
+ export declare const MAR_AGENT_PROMPT_VERSION = "1.53";
5
4
  export declare function buildSystemPrompt(input: {
6
5
  mode: ExecutionMode;
7
6
  platform: string;
@@ -15,7 +14,6 @@ export declare function buildSystemPrompt(input: {
15
14
  tools: readonly string[];
16
15
  currentAgentModel?: CurrentAgentModel;
17
16
  subagentModels?: readonly SubagentModelOption[];
18
- executionBudget?: ExecutionBudgetPromptState;
19
17
  highDensityCompaction?: boolean;
20
18
  extension?: string | undefined;
21
19
  }): string;
@@ -1,11 +1,10 @@
1
1
  import { compactionPrompt, highDensityCompactionPrompt } from './compact.js';
2
2
  import { environmentPrompt, identityPrompt, instructionPriorityPrompt, workspaceDisciplinePrompt } from './core.js';
3
- import { executionBudgetPrompt } from './execution-budget.js';
4
3
  import { modePrompt } from './modes.js';
5
4
  import { outputStylePrompt } from './output.js';
6
5
  import { subagentModelOptionsPrompt, subagentPrompt, currentAgentModelPrompt } from './subagent.js';
7
6
  import { interactionPrompt, longRunningPrompt, safetyPrompt, toolUsagePrompt, workflowPrompt } from './workflow.js';
8
- export const MAR_AGENT_PROMPT_VERSION = '1.52';
7
+ export const MAR_AGENT_PROMPT_VERSION = '1.53';
9
8
  export function buildSystemPrompt(input) {
10
9
  const toolNames = new Set(input.tools);
11
10
  const hasLongRunningCapability = [
@@ -27,10 +26,8 @@ export function buildSystemPrompt(input) {
27
26
  environmentPrompt(input),
28
27
  input.tools.length > 0 ? toolUsagePrompt(input.tools) : '',
29
28
  hasLongRunningCapability ? longRunningPrompt(input.tools) : '',
30
- input.executionBudget ? executionBudgetPrompt(input.executionBudget) : '',
31
29
  modePrompt(input.mode, {
32
- questionAvailable: toolNames.has('question'),
33
- forceFinalize: input.executionBudget?.stage === 'exhausted'
30
+ questionAvailable: toolNames.has('question')
34
31
  }),
35
32
  input.mode === 'compact'
36
33
  ? input.highDensityCompaction
@@ -1,5 +1,4 @@
1
1
  import type { ExecutionMode } from '../sdk/types.js';
2
2
  export declare function modePrompt(mode: ExecutionMode, input: {
3
3
  questionAvailable: boolean;
4
- forceFinalize: boolean;
5
4
  }): string;
@@ -1,17 +1,11 @@
1
1
  export function modePrompt(mode, input) {
2
2
  if (mode !== 'plan')
3
3
  return '';
4
- const investigationGuidance = input.forceFinalize
5
- ? 'Use only evidence already gathered; do not start or continue Plan exploration.'
6
- : '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.';
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.';
7
5
  const decisionGuidance = input.questionAvailable
8
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.'
9
- : input.forceFinalize
10
- ? 'User input is unavailable in this exhausted round. Return the current verified staged result now; state the unresolved decision and its impact instead of guessing.'
11
- : 'Ask a concise plain-text question for unresolved user-owned choices that materially change the result instead of finalizing an ambiguous plan. Do not invent support for multiple outcomes or silently choose a default.';
12
- const finalGuidance = input.forceFinalize
13
- ? 'Return only the concise staged plan now, distinguishing verified conclusions from incomplete work and unresolved decisions. Do not ask whether to proceed or claim unresolved work is complete.'
14
- : '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 planned work is completed.';
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.';
15
9
  return `# Plan mode
16
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.
17
11
 
@@ -1,4 +1,4 @@
1
1
  import type { ModelMessage } from '../model/contracts.js';
2
2
  import { type EnvironmentContextState } from '../prompts/core.js';
3
3
  export declare function restoreEnvironmentState(payload: unknown): EnvironmentContextState | undefined;
4
- export declare function environmentContextUpdate(current: EnvironmentContextState, previous?: EnvironmentContextState): ModelMessage | undefined;
4
+ export declare function environmentContextUpdate(current: EnvironmentContextState, previous?: EnvironmentContextState, contextualEntries?: readonly string[]): ModelMessage | undefined;
@@ -35,7 +35,7 @@ export function restoreEnvironmentState(payload) {
35
35
  ...(guaranteedCommands === undefined ? {} : { guaranteedCommands })
36
36
  };
37
37
  }
38
- export function environmentContextUpdate(current, previous) {
39
- const content = buildEnvironmentContext(current, previous);
38
+ export function environmentContextUpdate(current, previous, contextualEntries = []) {
39
+ const content = buildEnvironmentContext(current, previous, contextualEntries);
40
40
  return content ? { role: 'user', contextKind: 'environment', content } : undefined;
41
41
  }
package/dist/sdk/agent.js CHANGED
@@ -21,6 +21,7 @@ import { buildEnvironmentContext } from '../prompts/core.js';
21
21
  import { modelOutputContinuationMessage } from '../prompts/output.js';
22
22
  import { retainedSessionResourcesSnapshot, retainedSessionResourcesUpdate } from '../prompts/resources.js';
23
23
  import { environmentContextUpdate, restoreEnvironmentState } from '../runtime/environment-context.js';
24
+ import { executionBudgetEnvironmentEntry } from '../prompts/execution-budget.js';
24
25
  import { childSubagentInstruction } from '../prompts/subagent.js';
25
26
  import { sessionTitlePrompt } from '../prompts/title.js';
26
27
  import { loadAgentInstructions, renderAgentInstructions } from '../runtime/instructions.js';
@@ -278,6 +279,20 @@ export async function createMarAgent(options) {
278
279
  includeImages: mode !== 'compact'
279
280
  });
280
281
  const messages = restored.messages;
282
+ let projectedExecutionBudgetStage;
283
+ const appendExecutionBudgetEnvironment = () => {
284
+ const currentStage = rolloutBudget?.active ? rolloutBudget.stage : 'inactive';
285
+ if (currentStage === projectedExecutionBudgetStage)
286
+ return;
287
+ const previousStage = projectedExecutionBudgetStage;
288
+ projectedExecutionBudgetStage = currentStage;
289
+ if ((previousStage === undefined &&
290
+ (currentStage === 'normal' || currentStage === 'inactive')) ||
291
+ (currentStage === 'inactive' && previousStage === 'normal'))
292
+ return;
293
+ const entry = executionBudgetEnvironmentEntry(currentStage === 'normal' ? 'inactive' : currentStage);
294
+ messages.push(environmentContextUpdate(currentEnvironment, currentEnvironment, [entry]));
295
+ };
281
296
  const appendMailboxMessages = async () => {
282
297
  let appended = false;
283
298
  while (mailbox.length > 0) {
@@ -536,14 +551,6 @@ export async function createMarAgent(options) {
536
551
  }))
537
552
  : [],
538
553
  highDensityCompaction: selectedModel.highDensityCompaction,
539
- ...(rolloutBudget?.active
540
- ? {
541
- executionBudget: {
542
- stage: rolloutBudget.stage,
543
- limitTokens: rolloutBudget.limitTokens
544
- }
545
- }
546
- : {}),
547
554
  extension: [
548
555
  options.systemInstruction,
549
556
  instructionContext?.skillCatalog,
@@ -610,7 +617,7 @@ export async function createMarAgent(options) {
610
617
  const current = messages.at(-1);
611
618
  if (!current || messages.length < 2)
612
619
  return false;
613
- const retainCurrent = current.role === 'user';
620
+ const retainCurrent = current.role === 'user' && current.contextKind !== 'environment';
614
621
  let compactSummary = '';
615
622
  const compactSystemPrompt = buildExecutionSystemPrompt(executionTools, 'run');
616
623
  const compactHistory = retainCurrent ? messages.slice(0, -1) : messages;
@@ -701,6 +708,7 @@ export async function createMarAgent(options) {
701
708
  });
702
709
  contextGc.reset();
703
710
  messages.splice(0, messages.length, environmentContextUpdate(currentEnvironment), ...compactedHistoryMessages(replacementHistory));
711
+ projectedExecutionBudgetStage = undefined;
704
712
  compactionUserMessages = replacementHistory
705
713
  .filter((message) => message.kind === 'user_input')
706
714
  .map((message) => message.content);
@@ -735,6 +743,7 @@ export async function createMarAgent(options) {
735
743
  const modelRetryState = { attempts: 0 };
736
744
  while (true) {
737
745
  await appendMailboxMessages();
746
+ appendExecutionBudgetEnvironment();
738
747
  let stop;
739
748
  let sawTool = false;
740
749
  let latestUsage;
@@ -742,6 +751,7 @@ export async function createMarAgent(options) {
742
751
  const pendingTools = [];
743
752
  let incompleteToolCall = false;
744
753
  await ensureContextBudget();
754
+ appendExecutionBudgetEnvironment();
745
755
  const toolsAllowed = mode !== 'compact' && (!rolloutBudget?.active || rolloutBudget.stage !== 'exhausted');
746
756
  const roundTools = mode === 'compact' ? executionTools : toolsAllowed ? executionTools : [];
747
757
  const systemPrompt = mode === 'compact'
@@ -1158,6 +1168,7 @@ export async function createMarAgent(options) {
1158
1168
  projection: committed.projection
1159
1169
  });
1160
1170
  messages.splice(0, messages.length, ...refreshed.messages);
1171
+ projectedExecutionBudgetStage = undefined;
1161
1172
  compactionUserMessages = [...refreshed.userMessages];
1162
1173
  agentInstructionInsertIndex =
1163
1174
  refreshed.currentTurnUserIndex ?? Math.max(0, messages.length - 1);
@@ -1791,7 +1802,8 @@ function appendOnlyUsageDelta(usage, historyMessages) {
1791
1802
  const toolCallIds = new Set(usage.historyMessages
1792
1803
  .filter((message) => message.role === 'tool_call')
1793
1804
  .map((message) => message.callId));
1794
- return appended.every((message) => message.role === 'tool' && toolCallIds.has(message.callId))
1805
+ return appended.every((message) => (message.role === 'tool' && toolCallIds.has(message.callId)) ||
1806
+ (message.role === 'user' && message.contextKind === 'environment'))
1795
1807
  ? appended
1796
1808
  : undefined;
1797
1809
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.9.96",
3
+ "version": "0.9.97",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",