@myagentroam/agent 0.12.2 → 0.12.4

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.
@@ -11,6 +11,8 @@ export interface ExtensionCompactMessage {
11
11
  export interface ExtensionCompactContext {
12
12
  readonly reportModelUsage?: ((usage: import('../model/usage-observer.js').ModelRequestUsage) => Promise<void> | void) | undefined;
13
13
  readonly operationId: string;
14
+ /** Actual execution model configuration ID, not the session default or summary model. */
15
+ readonly modelId?: string;
14
16
  readonly reason: 'manual' | 'automatic';
15
17
  readonly messages: readonly ExtensionCompactMessage[];
16
18
  readonly focus?: string;
@@ -1,5 +1,5 @@
1
1
  import { type LocalProcessExecutor } from './local-process-executor.js';
2
- import type { ExecOutputSnapshot, ExecResult } from '../tools/contracts.js';
2
+ import type { ExecOutputSnapshot, ExecResult, ExecutionSource } from '../tools/contracts.js';
3
3
  import { type ToolWaitInterrupt } from '../tools/wait.js';
4
4
  import { WorkspacePathResolver } from '../tools/shared/path-resolver.js';
5
5
  import { type ExtensionProcessInput, type ExtensionProcessHandle } from '../extensions/processes.js';
@@ -13,7 +13,7 @@ export declare class ExecTool {
13
13
  private readonly shell?;
14
14
  private readonly processExecutor;
15
15
  constructor(paths: WorkspacePathResolver, maxOutputBytes?: number, maxProcesses?: number, environment?: NodeJS.ProcessEnv, shell?: string | undefined, processExecutor?: LocalProcessExecutor);
16
- execute(arguments_: unknown, signal?: AbortSignal, owner?: NonNullable<import('./local-process-executor.js').LocalProcessSpawnRequest['owner']>, waitInterrupt?: ToolWaitInterrupt, onOutput?: (output: ExecOutputSnapshot) => Promise<void>): Promise<ExecResult>;
16
+ execute(arguments_: unknown, signal?: AbortSignal, owner?: NonNullable<import('./local-process-executor.js').LocalProcessSpawnRequest['owner']>, waitInterrupt?: ToolWaitInterrupt, onOutput?: (output: ExecOutputSnapshot) => Promise<void>, onExecutionSource?: (source: ExecutionSource) => Promise<void> | void): Promise<ExecResult>;
17
17
  spawn(input: ExtensionProcessInput, call: ExtensionOperationContext): Promise<ExtensionProcessHandle>;
18
18
  listSessionResources(sessionId: string): {
19
19
  processId: string;
@@ -6,6 +6,14 @@ import { TOOL_EXECUTION_LIMITS } from '../tools/execution-limits.js';
6
6
  import { waitForToolCondition, waitMetadata } from '../tools/wait.js';
7
7
  import { validateCoreProcessInput } from '../extensions/processes.js';
8
8
  import { parseExecInput } from '../tools/local/exec.js';
9
+ function processSource(process) {
10
+ return {
11
+ kind: 'SHELL',
12
+ text: process.command.slice(0, 10_000),
13
+ cwd: process.cwd.slice(0, 10_000),
14
+ truncated: process.command.length > 10_000 || process.cwd.length > 10_000
15
+ };
16
+ }
9
17
  export class ExecTool {
10
18
  paths;
11
19
  maxOutputBytes;
@@ -25,7 +33,7 @@ export class ExecTool {
25
33
  this.shell = shell;
26
34
  this.processExecutor = processExecutor;
27
35
  }
28
- async execute(arguments_, signal, owner, waitInterrupt, onOutput) {
36
+ async execute(arguments_, signal, owner, waitInterrupt, onOutput, onExecutionSource) {
29
37
  if (signal?.aborted)
30
38
  throw executionAbortReason(signal);
31
39
  const input = parseExecInput(arguments_);
@@ -36,6 +44,10 @@ export class ExecTool {
36
44
  if (completed) {
37
45
  if (owner !== undefined && completed.ownerSessionId !== owner.sessionId)
38
46
  throw new AgentError('MAR_AGENT_PROCESS_NOT_FOUND', 'Managed process was not found.');
47
+ if (onExecutionSource)
48
+ await onExecutionSource(processSource(completed));
49
+ if (signal?.aborted)
50
+ throw executionAbortReason(signal);
39
51
  if (input.action === 'write')
40
52
  throw new AgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Completed process cannot accept input.');
41
53
  if (input.action === 'cancel')
@@ -52,6 +64,10 @@ export class ExecTool {
52
64
  process.native ||
53
65
  (owner !== undefined && process.ownerSessionId !== owner.sessionId))
54
66
  throw new AgentError('MAR_AGENT_PROCESS_NOT_FOUND', 'Managed process was not found.');
67
+ if (onExecutionSource)
68
+ await onExecutionSource(processSource(process));
69
+ if (signal?.aborted)
70
+ throw executionAbortReason(signal);
55
71
  let outcome;
56
72
  if (input.action === 'poll' && input.yieldMs)
57
73
  outcome = await waitForProcessCompletion(input.processId, process, Math.min(Math.max(input.yieldMs, 0), TOOL_EXECUTION_LIMITS.execMaxPollYieldMs), signal, waitInterrupt, onOutput);
@@ -427,12 +443,7 @@ export class ExecTool {
427
443
  stdoutDroppedBytes: stdout.droppedBytes,
428
444
  stderrDroppedBytes: stderr.droppedBytes,
429
445
  displayOutput: displayOutput(process),
430
- executionSource: {
431
- kind: 'SHELL',
432
- text: process.command.slice(0, 10_000),
433
- cwd: process.cwd.slice(0, 10_000),
434
- truncated: process.command.length > 10_000 || process.cwd.length > 10_000
435
- }
446
+ executionSource: processSource(process)
436
447
  }
437
448
  });
438
449
  while (this.#completed.size > TOOL_EXECUTION_LIMITS.execMaxCompletedResults)
@@ -496,12 +507,7 @@ export class ExecTool {
496
507
  stdoutDroppedBytes: stdout.droppedBytes,
497
508
  stderrDroppedBytes: stderr.droppedBytes,
498
509
  displayOutput: displayOutput(process),
499
- executionSource: {
500
- kind: 'SHELL',
501
- text: process.command.slice(0, 10_000),
502
- cwd: process.cwd.slice(0, 10_000),
503
- truncated: process.command.length > 10_000 || process.cwd.length > 10_000
504
- }
510
+ executionSource: processSource(process)
505
511
  };
506
512
  }
507
513
  async dispose() {
@@ -98,7 +98,7 @@ export class LocalToolRegistry {
98
98
  ? {}
99
99
  : { ownerInstanceId: context.operation.ownerInstanceId })
100
100
  })
101
- }, context.waitInterrupt, context.onOutput);
101
+ }, context.waitInterrupt, context.onOutput, context.onExecutionSource);
102
102
  return formatExecResult(result);
103
103
  }
104
104
  ])
@@ -4,6 +4,7 @@ import type { CompactionOperation } from '../runtime/compaction/operation.js';
4
4
  import type { ModelRequestUsage } from '../model/usage-observer.js';
5
5
  /** Bounds Extension diagnostics and validates its candidate before native fallback. */
6
6
  export declare function createExecutionCompactExtension(ports: {
7
+ readonly modelId: string;
7
8
  readonly contextWindowTokens: number;
8
9
  readonly maxOutputTokens: number;
9
10
  hasInterceptor(): boolean;
@@ -10,6 +10,7 @@ export function createExecutionCompactExtension(ports) {
10
10
  let acceptsDiagnostics = true;
11
11
  try {
12
12
  const result = await compaction.generate((signal) => ports.invoke(Object.freeze({
13
+ modelId: ports.modelId,
13
14
  reason,
14
15
  messages: compactExtensionMessages(history),
15
16
  ...(focus === undefined ? {} : { focus }),
@@ -530,6 +530,7 @@ export function createSessionExecutionFactory(ports) {
530
530
  ? buildExecutionSystemPrompt(toolCatalog.tools, 'run')
531
531
  : buildExecutionSystemPrompt();
532
532
  const generateCompactExtension = createExecutionCompactExtension({
533
+ modelId: selectedModel.id,
533
534
  contextWindowTokens: selectedModel.contextWindowTokens,
534
535
  maxOutputTokens: selectedModel.maxOutputTokens,
535
536
  hasInterceptor: () => coreExtensions.hooks.hasInterceptors('compact.generate'),
@@ -298,6 +298,9 @@ export class CodeCells {
298
298
  const cell = this.#cells.get(input.cellId);
299
299
  if (!cell || cell.sessionId !== context.sessionId)
300
300
  throw new AgentError('MAR_AGENT_CODE_CELL_NOT_FOUND', 'Code Exec cell is unavailable in this Session.');
301
+ if (context.onExecutionSource)
302
+ await context.onExecutionSource({ ...cell.source });
303
+ context.signal.throwIfAborted();
301
304
  if (input.action === 'cancel' && cell.status === 'running') {
302
305
  cell.controller.abort(new AgentError('MAR_AGENT_CODE_CANCELLED', 'Code Exec cell was terminated.'));
303
306
  await new Promise((resolve, reject) => {
@@ -33,6 +33,8 @@ export interface ToolExecutionContext {
33
33
  waitInterrupt?: import('./wait.js').ToolWaitInterrupt | undefined;
34
34
  /** Live-only process output; does not consume the eventual tool result. */
35
35
  onOutput?: (output: ExecOutputSnapshot) => Promise<void>;
36
+ /** Publish owner-confirmed source metadata before waiting, without consuming output. */
37
+ onExecutionSource?: (source: ExecutionSource) => Promise<void> | void;
36
38
  sessionId: string;
37
39
  executionId: string;
38
40
  /** Current model identity for neutral Host-owned tool policies. */
@@ -53,6 +53,13 @@ export async function executeCapturedTool(kind, call, context) {
53
53
  ...((name === 'exec' || name === 'exec_wait' || name === 'code_exec_wait') &&
54
54
  callId !== undefined
55
55
  ? {
56
+ onExecutionSource: (source) => context.emit({
57
+ type: 'tool.updated',
58
+ toolName: name,
59
+ callId,
60
+ ...(context.parentCallId === undefined ? {} : { parentCallId: context.parentCallId }),
61
+ data: { executionSource: source }
62
+ }),
56
63
  onOutput: (output) => context.emit({
57
64
  type: 'tool.output',
58
65
  toolName: name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",