@myagentroam/agent 0.12.2 → 0.12.3
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.
|
@@ -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
|
])
|
|
@@ -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. */
|
package/dist/tools/runtime.js
CHANGED
|
@@ -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,
|