@myagentroam/agent 0.11.21 → 0.11.23
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.
- package/dist/agent-core/error.d.ts +1 -1
- package/dist/agent-core/error.js +20 -14
- package/dist/agent-core/extensions/compaction.d.ts +6 -0
- package/dist/agent-core/extensions/compaction.js +16 -2
- package/dist/agent-core/extensions/model-request.d.ts +5 -9
- package/dist/agent-core/extensions/model-request.js +14 -3
- package/dist/agent-core/extensions/prompt-input.js +3 -1
- package/dist/agent-core/host/contracts.d.ts +8 -0
- package/dist/agent-core/host/local-agent-host.d.ts +2 -0
- package/dist/agent-core/host/local-agent-host.js +3 -0
- package/dist/agent-core/model/anthropic-messages.js +15 -26
- package/dist/agent-core/model/catalog-file.d.ts +2 -0
- package/dist/agent-core/model/configuration.d.ts +3 -1
- package/dist/agent-core/model/configuration.js +1 -0
- package/dist/agent-core/model/contracts.d.ts +5 -8
- package/dist/agent-core/model/image.d.ts +17 -0
- package/dist/agent-core/model/image.js +53 -0
- package/dist/agent-core/model/openai-responses.d.ts +7 -2
- package/dist/agent-core/model/openai-responses.js +81 -27
- package/dist/agent-core/runtime/compaction/retained-context.js +2 -9
- package/dist/agent-core/runtime/context/gc-runtime.d.ts +3 -1
- package/dist/agent-core/runtime/context/gc-runtime.js +17 -6
- package/dist/agent-core/runtime/context/gc-tokens.js +13 -0
- package/dist/agent-core/runtime/context/gc.d.ts +2 -1
- package/dist/agent-core/runtime/context/gc.js +78 -12
- package/dist/agent-core/runtime/context/projection.js +4 -0
- package/dist/agent-core/runtime/context/request-budget.d.ts +2 -4
- package/dist/agent-core/runtime/context/restore.d.ts +2 -0
- package/dist/agent-core/runtime/context/restore.js +19 -3
- package/dist/agent-core/runtime/contracts.d.ts +2 -3
- package/dist/agent-core/runtime/execution.d.ts +1 -1
- package/dist/agent-core/runtime/execution.js +10 -4
- package/dist/agent-core/runtime/resource-publication.d.ts +8 -0
- package/dist/agent-core/runtime/resource-publication.js +60 -0
- package/dist/agent-core/sdk/agent.js +16 -0
- package/dist/agent-core/sdk/model-runtime.js +2 -0
- package/dist/agent-core/sdk/resource-input.d.ts +31 -0
- package/dist/agent-core/sdk/resource-input.js +342 -0
- package/dist/agent-core/sdk/session.js +144 -39
- package/dist/agent-core/session/catalog.d.ts +4 -0
- package/dist/agent-core/session/catalog.js +4 -0
- package/dist/agent-core/session/context-gc-checkpoint.d.ts +6 -4
- package/dist/agent-core/session/context-gc-checkpoint.js +43 -16
- package/dist/agent-core/session/inline-media.d.ts +45 -0
- package/dist/agent-core/session/inline-media.js +163 -0
- package/dist/agent-core/session/store/contracts.d.ts +11 -0
- package/dist/agent-core/session/store/history.d.ts +1 -1
- package/dist/agent-core/session/store/history.js +26 -2
- package/dist/agent-core/session/store/images.d.ts +4 -6
- package/dist/agent-core/session/store/images.js +18 -111
- package/dist/agent-core/session/store/jsonl-store.d.ts +9 -0
- package/dist/agent-core/session/store/jsonl-store.js +100 -28
- package/dist/agent-core/session/store/resources.d.ts +26 -0
- package/dist/agent-core/session/store/resources.js +196 -0
- package/dist/agent-core/session/store/types.d.ts +7 -6
- package/dist/agent-core/session/transaction-recovery.js +1 -1
- package/dist/agent-core/tools/code-mode/cells.js +3 -4
- package/dist/agent-core/tools/code-mode/index.js +32 -8
- package/dist/agent-core/tools/code-mode/observations.d.ts +5 -16
- package/dist/agent-core/tools/code-mode/quickjs-engine.js +23 -26
- package/dist/agent-core/tools/contracts.d.ts +15 -5
- package/dist/agent-core/tools/execution-limits.d.ts +3 -1
- package/dist/agent-core/tools/execution-limits.js +3 -1
- package/dist/agent-core/tools/execution.d.ts +2 -1
- package/dist/agent-core/tools/execution.js +31 -4
- package/dist/agent-core/tools/input-diagnostics/source-preview.d.ts +10 -0
- package/dist/agent-core/tools/input-diagnostics/source-preview.js +64 -0
- package/dist/agent-core/tools/local/apply-patch-parser.js +2 -53
- package/dist/agent-core/tools/local/apply-patch.js +1 -1
- package/dist/agent-core/tools/local/image-processing.d.ts +25 -0
- package/dist/agent-core/tools/local/image-processing.js +146 -0
- package/dist/agent-core/tools/local/read.js +1 -1
- package/dist/agent-core/tools/local/view-image.d.ts +4 -0
- package/dist/agent-core/tools/local/view-image.js +154 -25
- package/dist/agent-core/tools/output-projection.d.ts +2 -4
- package/dist/agent-core/tools/output-projection.js +81 -10
- package/dist/agent-core/tools/runtime-context.d.ts +1 -0
- package/dist/agent-core/tools/runtime.js +20 -1
- package/dist/cli/main.js +2 -1
- package/dist/index.d.ts +1 -1
- package/package.json +2 -1
|
@@ -289,7 +289,7 @@ function readKey(input) {
|
|
|
289
289
|
}
|
|
290
290
|
function readError(path, error) {
|
|
291
291
|
if (error instanceof MarAgentError)
|
|
292
|
-
return { path, error: { code: error.code, message: error.
|
|
292
|
+
return { path, error: { code: error.code, message: error.publicMessage } };
|
|
293
293
|
const code = typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'
|
|
294
294
|
? error.code
|
|
295
295
|
: 'MAR_AGENT_TOOL_FAILED';
|
|
@@ -8,4 +8,8 @@ export declare class ViewImageTool {
|
|
|
8
8
|
constructor(paths: WorkspacePathResolver);
|
|
9
9
|
execute(arguments_: unknown, signal?: AbortSignal): Promise<ToolExecutionResult>;
|
|
10
10
|
}
|
|
11
|
+
/** Resolve Session-owned bytes without using the resource's public URL or original path. */
|
|
12
|
+
export declare function viewResourceImage(arguments_: unknown, readResource: (resourceId: string) => Promise<{
|
|
13
|
+
dataBase64: string;
|
|
14
|
+
} | undefined>, signal?: AbortSignal): Promise<ToolExecutionResult>;
|
|
11
15
|
export declare function detectImageMime(data: Buffer): ViewImageResult['mimeType'];
|
|
@@ -2,17 +2,39 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { open } from 'node:fs/promises';
|
|
3
3
|
import { MarAgentError } from '../../error.js';
|
|
4
4
|
import { TOOL_EXECUTION_LIMITS } from '../execution-limits.js';
|
|
5
|
+
import { processImage, readImageMetadata } from './image-processing.js';
|
|
5
6
|
export const viewImageToolDefinition = {
|
|
6
7
|
name: 'view_image',
|
|
7
8
|
allowedCallers: ['direct', 'programmatic'],
|
|
8
9
|
parallelSafety: 'safe',
|
|
9
|
-
description:
|
|
10
|
+
description: 'View a PNG, JPEG, or WebP image by path or Session resourceId. Relative paths use the workspace; absolute paths are allowed. Use this tool instead of converting images through exec.',
|
|
10
11
|
inputSchema: {
|
|
11
12
|
type: 'object',
|
|
12
13
|
properties: {
|
|
13
|
-
path: { type: 'string', description: 'Relative workspace path or absolute image path.' }
|
|
14
|
+
path: { type: 'string', description: 'Relative workspace path or absolute image path.' },
|
|
15
|
+
resourceId: { type: 'string', description: 'Session image resource ID, instead of path.' },
|
|
16
|
+
region: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
description: 'For close inspection of a specific area; coordinates use oriented source pixels.',
|
|
19
|
+
properties: {
|
|
20
|
+
x: { type: 'integer', minimum: 0 },
|
|
21
|
+
y: { type: 'integer', minimum: 0 },
|
|
22
|
+
width: { type: 'integer', minimum: 1 },
|
|
23
|
+
height: { type: 'integer', minimum: 1 }
|
|
24
|
+
},
|
|
25
|
+
required: ['x', 'y', 'width', 'height'],
|
|
26
|
+
additionalProperties: false
|
|
27
|
+
},
|
|
28
|
+
resize: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
description: 'For a smaller overview; fit the image or cropped region within these dimensions without enlargement.',
|
|
31
|
+
properties: {
|
|
32
|
+
maxWidth: { type: 'integer', minimum: 1 },
|
|
33
|
+
maxHeight: { type: 'integer', minimum: 1 }
|
|
34
|
+
},
|
|
35
|
+
additionalProperties: false
|
|
36
|
+
}
|
|
14
37
|
},
|
|
15
|
-
required: ['path'],
|
|
16
38
|
additionalProperties: false
|
|
17
39
|
}
|
|
18
40
|
};
|
|
@@ -23,6 +45,8 @@ export class ViewImageTool {
|
|
|
23
45
|
}
|
|
24
46
|
async execute(arguments_, signal) {
|
|
25
47
|
const input = parseViewImageInput(arguments_);
|
|
48
|
+
if (input.path === undefined)
|
|
49
|
+
return invalidInput();
|
|
26
50
|
signal?.throwIfAborted();
|
|
27
51
|
const path = await this.paths.resolve(input.path);
|
|
28
52
|
const handle = await open(path, 'r');
|
|
@@ -30,13 +54,22 @@ export class ViewImageTool {
|
|
|
30
54
|
const stat = await handle.stat({ bigint: true });
|
|
31
55
|
if (!stat.isFile())
|
|
32
56
|
throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Path is not a regular file.');
|
|
33
|
-
if (stat.size > BigInt(TOOL_EXECUTION_LIMITS.
|
|
34
|
-
throw new MarAgentError('MAR_AGENT_TOOL_OUTPUT_LIMIT', `Image exceeds the ${TOOL_EXECUTION_LIMITS.
|
|
57
|
+
if (stat.size > BigInt(TOOL_EXECUTION_LIMITS.viewImageMaxSourceBytes))
|
|
58
|
+
throw new MarAgentError('MAR_AGENT_TOOL_OUTPUT_LIMIT', `Image exceeds the ${TOOL_EXECUTION_LIMITS.viewImageMaxSourceBytes}-byte source limit. Use an external image tool to reduce it first.`);
|
|
59
|
+
const hasTransform = input.region !== undefined || input.resize !== undefined;
|
|
60
|
+
if (!hasTransform && stat.size > BigInt(TOOL_EXECUTION_LIMITS.viewImageMaxBytes))
|
|
61
|
+
throw imageOutputLimit('Image exceeds 3 MiB. Use resize or region.');
|
|
35
62
|
signal?.throwIfAborted();
|
|
36
|
-
const data =
|
|
63
|
+
const data = Buffer.allocUnsafe(Number(stat.size));
|
|
64
|
+
let offset = 0;
|
|
65
|
+
while (offset < data.byteLength) {
|
|
66
|
+
signal?.throwIfAborted();
|
|
67
|
+
const { bytesRead } = await handle.read(data, offset, data.byteLength - offset, offset);
|
|
68
|
+
if (bytesRead === 0)
|
|
69
|
+
incompleteImage();
|
|
70
|
+
offset += bytesRead;
|
|
71
|
+
}
|
|
37
72
|
signal?.throwIfAborted();
|
|
38
|
-
if (data.byteLength > TOOL_EXECUTION_LIMITS.viewImageMaxBytes)
|
|
39
|
-
throw new MarAgentError('MAR_AGENT_TOOL_OUTPUT_LIMIT', `Image exceeds the ${TOOL_EXECUTION_LIMITS.viewImageMaxBytes}-byte limit.`);
|
|
40
73
|
const after = await handle.stat({ bigint: true });
|
|
41
74
|
signal?.throwIfAborted();
|
|
42
75
|
if (stat.size !== after.size ||
|
|
@@ -44,34 +77,130 @@ export class ViewImageTool {
|
|
|
44
77
|
stat.mtimeNs !== after.mtimeNs ||
|
|
45
78
|
stat.ctimeNs !== after.ctimeNs)
|
|
46
79
|
return incompleteImage();
|
|
47
|
-
|
|
48
|
-
validateImageContainer(data, mimeType);
|
|
49
|
-
const metadata = {
|
|
50
|
-
path: input.path,
|
|
51
|
-
mimeType,
|
|
52
|
-
bytes: data.byteLength,
|
|
53
|
-
sha256: createHash('sha256').update(data).digest('hex')
|
|
54
|
-
};
|
|
55
|
-
return {
|
|
56
|
-
content: `Viewed image ${input.path} (${mimeType}, ${data.byteLength} bytes).`,
|
|
57
|
-
data: metadata,
|
|
58
|
-
images: [{ mimeType, dataBase64: data.toString('base64') }]
|
|
59
|
-
};
|
|
80
|
+
return await renderViewImage(data, input, signal);
|
|
60
81
|
}
|
|
61
82
|
finally {
|
|
62
83
|
await handle.close();
|
|
63
84
|
}
|
|
64
85
|
}
|
|
65
86
|
}
|
|
87
|
+
/** Resolve Session-owned bytes without using the resource's public URL or original path. */
|
|
88
|
+
export async function viewResourceImage(arguments_, readResource, signal) {
|
|
89
|
+
const input = parseViewImageInput(arguments_);
|
|
90
|
+
if (input.resourceId === undefined)
|
|
91
|
+
return invalidInput();
|
|
92
|
+
signal?.throwIfAborted();
|
|
93
|
+
const resource = await readResource(input.resourceId);
|
|
94
|
+
signal?.throwIfAborted();
|
|
95
|
+
if (!resource)
|
|
96
|
+
throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Image resource was not found in this Session.');
|
|
97
|
+
const data = Buffer.from(resource.dataBase64, 'base64');
|
|
98
|
+
if (data.length > TOOL_EXECUTION_LIMITS.viewImageMaxSourceBytes)
|
|
99
|
+
throw imageOutputLimit('Image exceeds the source limit.');
|
|
100
|
+
if (!input.region && !input.resize && data.length > TOOL_EXECUTION_LIMITS.viewImageMaxBytes)
|
|
101
|
+
throw imageOutputLimit('Image exceeds 3 MiB. Use resize or region.');
|
|
102
|
+
return renderViewImage(data, input, signal);
|
|
103
|
+
}
|
|
104
|
+
async function renderViewImage(data, input, signal) {
|
|
105
|
+
const mimeType = detectImageMime(data);
|
|
106
|
+
validateImageContainer(data, mimeType);
|
|
107
|
+
const sourceMetadata = await readImageMetadata(data, mimeType, signal);
|
|
108
|
+
if (input.region &&
|
|
109
|
+
(input.region.x > sourceMetadata.width ||
|
|
110
|
+
input.region.y > sourceMetadata.height ||
|
|
111
|
+
input.region.width > sourceMetadata.width - input.region.x ||
|
|
112
|
+
input.region.height > sourceMetadata.height - input.region.y))
|
|
113
|
+
throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Image region is outside the oriented source dimensions.');
|
|
114
|
+
const visual = input.region !== undefined || input.resize !== undefined
|
|
115
|
+
? await processImage(data, sourceMetadata, input, signal)
|
|
116
|
+
: {
|
|
117
|
+
bytes: data,
|
|
118
|
+
width: sourceMetadata.width,
|
|
119
|
+
height: sourceMetadata.height,
|
|
120
|
+
mimeType
|
|
121
|
+
};
|
|
122
|
+
signal?.throwIfAborted();
|
|
123
|
+
const resultMetadata = {
|
|
124
|
+
...(input.path ? { path: input.path } : { resourceId: input.resourceId }),
|
|
125
|
+
mimeType: visual.mimeType,
|
|
126
|
+
bytes: visual.bytes.byteLength,
|
|
127
|
+
width: visual.width,
|
|
128
|
+
height: visual.height,
|
|
129
|
+
...('sourceWidth' in visual && visual.sourceWidth !== undefined
|
|
130
|
+
? { sourceWidth: visual.sourceWidth, sourceHeight: visual.sourceHeight }
|
|
131
|
+
: {}),
|
|
132
|
+
...('region' in visual && visual.region ? { region: visual.region } : {}),
|
|
133
|
+
sha256: createHash('sha256').update(visual.bytes).digest('hex')
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
content: describeImageResult(resultMetadata),
|
|
137
|
+
data: resultMetadata,
|
|
138
|
+
images: [{ mimeType: visual.mimeType, dataBase64: visual.bytes.toString('base64') }]
|
|
139
|
+
};
|
|
140
|
+
}
|
|
66
141
|
function parseViewImageInput(value) {
|
|
67
142
|
if (!value || typeof value !== 'object')
|
|
68
143
|
return invalidInput();
|
|
69
144
|
const input = value;
|
|
70
|
-
if (Object.keys(input).some((key) =>
|
|
71
|
-
|
|
72
|
-
input.path.length === 0)
|
|
145
|
+
if (Object.keys(input).some((key) => !['path', 'resourceId', 'region', 'resize'].includes(key)) ||
|
|
146
|
+
(input.path == null) === (input.resourceId == null) ||
|
|
147
|
+
(input.path != null && (typeof input.path !== 'string' || input.path.length === 0)) ||
|
|
148
|
+
(input.resourceId != null &&
|
|
149
|
+
(typeof input.resourceId !== 'string' || input.resourceId.length === 0)))
|
|
150
|
+
return invalidInput();
|
|
151
|
+
return {
|
|
152
|
+
...(typeof input.path === 'string'
|
|
153
|
+
? { path: input.path }
|
|
154
|
+
: { resourceId: input.resourceId }),
|
|
155
|
+
...(input.region == null ? {} : { region: parseRegion(input.region) }),
|
|
156
|
+
...(input.resize == null ? {} : { resize: parseResize(input.resize) })
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function parseRegion(value) {
|
|
160
|
+
if (!isRecord(value) ||
|
|
161
|
+
Object.keys(value).some((key) => !['x', 'y', 'width', 'height'].includes(key)) ||
|
|
162
|
+
!Number.isSafeInteger(value.x) ||
|
|
163
|
+
value.x < 0 ||
|
|
164
|
+
!Number.isSafeInteger(value.y) ||
|
|
165
|
+
value.y < 0 ||
|
|
166
|
+
!isPositiveSafeInteger(value.width) ||
|
|
167
|
+
!isPositiveSafeInteger(value.height))
|
|
168
|
+
return invalidInput();
|
|
169
|
+
return {
|
|
170
|
+
x: value.x,
|
|
171
|
+
y: value.y,
|
|
172
|
+
width: value.width,
|
|
173
|
+
height: value.height
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function parseResize(value) {
|
|
177
|
+
if (!isRecord(value) ||
|
|
178
|
+
(value.maxWidth == null && value.maxHeight == null) ||
|
|
179
|
+
Object.keys(value).some((key) => key !== 'maxWidth' && key !== 'maxHeight') ||
|
|
180
|
+
(value.maxWidth != null && !isPositiveSafeInteger(value.maxWidth)) ||
|
|
181
|
+
(value.maxHeight != null && !isPositiveSafeInteger(value.maxHeight)))
|
|
73
182
|
return invalidInput();
|
|
74
|
-
return {
|
|
183
|
+
return {
|
|
184
|
+
...(value.maxWidth == null ? {} : { maxWidth: value.maxWidth }),
|
|
185
|
+
...(value.maxHeight == null ? {} : { maxHeight: value.maxHeight })
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function isRecord(value) {
|
|
189
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
190
|
+
}
|
|
191
|
+
function isPositiveSafeInteger(value) {
|
|
192
|
+
return Number.isSafeInteger(value) && value > 0;
|
|
193
|
+
}
|
|
194
|
+
function describeImageResult(result) {
|
|
195
|
+
const details = [`${result.width}×${result.height} px`, result.mimeType, `${result.bytes} bytes`];
|
|
196
|
+
if (result.sourceWidth !== undefined && result.sourceHeight !== undefined)
|
|
197
|
+
details.push(`source ${result.sourceWidth}×${result.sourceHeight} px`);
|
|
198
|
+
if (result.region)
|
|
199
|
+
details.push(`region ${result.region.x},${result.region.y} ${result.region.width}×${result.region.height} px`);
|
|
200
|
+
return `Viewed image ${result.path ?? result.resourceId} (${details.join(', ')}).`;
|
|
201
|
+
}
|
|
202
|
+
function imageOutputLimit(message) {
|
|
203
|
+
return new MarAgentError('MAR_AGENT_TOOL_OUTPUT_LIMIT', message);
|
|
75
204
|
}
|
|
76
205
|
export function detectImageMime(data) {
|
|
77
206
|
if (data.length >= 8 &&
|
|
@@ -3,10 +3,8 @@ import type { ApplyPatchResult, ApplyPatchPartialResult, CodeCellEventData, Exec
|
|
|
3
3
|
import type { ToolRuntimeImage } from './runtime-context.js';
|
|
4
4
|
import type { SleepResult } from './agent/sleep.js';
|
|
5
5
|
import { type PublicToolMetadata } from './public-metadata.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
readonly dataBase64: string;
|
|
9
|
-
}[] | undefined, toolImages: readonly ToolRuntimeImage[]): ToolRuntimeImage[];
|
|
6
|
+
import type { ModelImage } from '../model/image.js';
|
|
7
|
+
export declare function currentExecutionImages(modelInputImages: readonly ModelImage[] | undefined, toolImages: readonly ToolRuntimeImage[]): ToolRuntimeImage[];
|
|
10
8
|
export declare function boundedModelToolOutput(toolName: string, value: string, data: unknown): {
|
|
11
9
|
content: string;
|
|
12
10
|
truncated: boolean;
|
|
@@ -6,7 +6,9 @@ import { TOOL_EXECUTION_LIMITS } from './execution-limits.js';
|
|
|
6
6
|
import { publicToolMetadata } from './public-metadata.js';
|
|
7
7
|
export function currentExecutionImages(modelInputImages, toolImages) {
|
|
8
8
|
return [
|
|
9
|
-
...(modelInputImages ?? [])
|
|
9
|
+
...(modelInputImages ?? [])
|
|
10
|
+
.filter((image) => image.dataBase64 !== undefined)
|
|
11
|
+
.map((image) => ({
|
|
10
12
|
mimeType: image.mimeType,
|
|
11
13
|
data: Buffer.from(image.dataBase64, 'base64')
|
|
12
14
|
})),
|
|
@@ -148,15 +150,8 @@ export function structuredToolEventData(toolName, value) {
|
|
|
148
150
|
}))
|
|
149
151
|
};
|
|
150
152
|
}
|
|
151
|
-
if (toolName === 'view_image'
|
|
152
|
-
|
|
153
|
-
(value.mimeType === 'image/png' ||
|
|
154
|
-
value.mimeType === 'image/jpeg' ||
|
|
155
|
-
value.mimeType === 'image/webp') &&
|
|
156
|
-
isNonnegativeInteger(value.bytes) &&
|
|
157
|
-
typeof value.sha256 === 'string' &&
|
|
158
|
-
/^[a-f0-9]{64}$/u.test(value.sha256))
|
|
159
|
-
return value;
|
|
153
|
+
if (toolName === 'view_image')
|
|
154
|
+
return parseViewImageResult(value);
|
|
160
155
|
if ((toolName === 'exec' || toolName === 'exec_wait') &&
|
|
161
156
|
(value.status === 'running' || value.status === 'completed' || value.status === 'cancelled') &&
|
|
162
157
|
typeof value.stdout === 'string' &&
|
|
@@ -175,6 +170,82 @@ export function structuredToolEventData(toolName, value) {
|
|
|
175
170
|
return parseApplyPatchResult(value);
|
|
176
171
|
return undefined;
|
|
177
172
|
}
|
|
173
|
+
function parseViewImageResult(value) {
|
|
174
|
+
if (!((typeof value.path === 'string' && value.path.length > 0 && value.resourceId === undefined) ||
|
|
175
|
+
(typeof value.resourceId === 'string' &&
|
|
176
|
+
value.resourceId.length > 0 &&
|
|
177
|
+
value.path === undefined)) ||
|
|
178
|
+
(value.mimeType !== 'image/png' &&
|
|
179
|
+
value.mimeType !== 'image/jpeg' &&
|
|
180
|
+
value.mimeType !== 'image/webp') ||
|
|
181
|
+
!isPositiveSafeInteger(value.bytes) ||
|
|
182
|
+
value.bytes > TOOL_EXECUTION_LIMITS.viewImageMaxBytes ||
|
|
183
|
+
!isPositiveSafeInteger(value.width) ||
|
|
184
|
+
!isPositiveSafeInteger(value.height) ||
|
|
185
|
+
!withinImagePixelLimit(value.width, value.height) ||
|
|
186
|
+
typeof value.sha256 !== 'string' ||
|
|
187
|
+
!/^[a-f0-9]{64}$/u.test(value.sha256))
|
|
188
|
+
return undefined;
|
|
189
|
+
const hasSourceWidth = Object.hasOwn(value, 'sourceWidth');
|
|
190
|
+
const hasSourceHeight = Object.hasOwn(value, 'sourceHeight');
|
|
191
|
+
if (hasSourceWidth !== hasSourceHeight)
|
|
192
|
+
return undefined;
|
|
193
|
+
if (hasSourceWidth &&
|
|
194
|
+
(!isPositiveSafeInteger(value.sourceWidth) ||
|
|
195
|
+
!isPositiveSafeInteger(value.sourceHeight) ||
|
|
196
|
+
!withinImagePixelLimit(value.sourceWidth, value.sourceHeight) ||
|
|
197
|
+
value.width > value.sourceWidth ||
|
|
198
|
+
value.height > value.sourceHeight))
|
|
199
|
+
return undefined;
|
|
200
|
+
let region;
|
|
201
|
+
if (Object.hasOwn(value, 'region')) {
|
|
202
|
+
if (!isRecord(value.region))
|
|
203
|
+
return undefined;
|
|
204
|
+
const candidate = value.region;
|
|
205
|
+
if (Object.keys(candidate).some((key) => !['x', 'y', 'width', 'height'].includes(key)) ||
|
|
206
|
+
!isNonnegativeSafeInteger(candidate.x) ||
|
|
207
|
+
!isNonnegativeSafeInteger(candidate.y) ||
|
|
208
|
+
!isPositiveSafeInteger(candidate.width) ||
|
|
209
|
+
!isPositiveSafeInteger(candidate.height) ||
|
|
210
|
+
!hasSourceWidth ||
|
|
211
|
+
candidate.x > value.sourceWidth ||
|
|
212
|
+
candidate.y > value.sourceHeight ||
|
|
213
|
+
candidate.width > value.sourceWidth - candidate.x ||
|
|
214
|
+
candidate.height > value.sourceHeight - candidate.y ||
|
|
215
|
+
value.width > candidate.width ||
|
|
216
|
+
value.height > candidate.height)
|
|
217
|
+
return undefined;
|
|
218
|
+
region = {
|
|
219
|
+
x: candidate.x,
|
|
220
|
+
y: candidate.y,
|
|
221
|
+
width: candidate.width,
|
|
222
|
+
height: candidate.height
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
...(typeof value.path === 'string'
|
|
227
|
+
? { path: value.path }
|
|
228
|
+
: { resourceId: value.resourceId }),
|
|
229
|
+
mimeType: value.mimeType,
|
|
230
|
+
bytes: value.bytes,
|
|
231
|
+
width: value.width,
|
|
232
|
+
height: value.height,
|
|
233
|
+
...(hasSourceWidth
|
|
234
|
+
? { sourceWidth: value.sourceWidth, sourceHeight: value.sourceHeight }
|
|
235
|
+
: {}),
|
|
236
|
+
...(region ? { region } : {}),
|
|
237
|
+
sha256: value.sha256
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function withinImagePixelLimit(width, height) {
|
|
241
|
+
return width <= Math.floor(TOOL_EXECUTION_LIMITS.viewImageMaxPixels / height);
|
|
242
|
+
}
|
|
243
|
+
function isPositiveSafeInteger(value) {
|
|
244
|
+
return Number.isSafeInteger(value) && value > 0;
|
|
245
|
+
}
|
|
246
|
+
function isNonnegativeSafeInteger(value) {
|
|
247
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
248
|
+
}
|
|
178
249
|
/** Partial patch facts are allowlisted; arbitrary error details never become public event data. */
|
|
179
250
|
export function structuredToolFailureData(toolName, error) {
|
|
180
251
|
return toolName === 'apply_patch' &&
|
|
@@ -44,6 +44,7 @@ export interface ToolRuntimeImage {
|
|
|
44
44
|
}
|
|
45
45
|
export interface ToolRuntimeContext {
|
|
46
46
|
host: MarAgentHost;
|
|
47
|
+
imageStore?: import('../session/store/contracts.js').SessionStore;
|
|
47
48
|
todo: TodoStore;
|
|
48
49
|
requestSmartCompact?: () => void;
|
|
49
50
|
subagents?: SubagentController;
|
|
@@ -4,6 +4,7 @@ import { AGENT_TOOL_HANDLERS, BUILTIN_TOOL_DEFINITIONS } from './registry.js';
|
|
|
4
4
|
import { normalizeToolInput } from './input.js';
|
|
5
5
|
import { validateToolResult } from './output-projection.js';
|
|
6
6
|
import { withToolResultExtensions } from './result-extensions.js';
|
|
7
|
+
import { viewResourceImage } from './local/view-image.js';
|
|
7
8
|
export async function executeRegisteredTool(name, arguments_, callId, context, caller = 'direct') {
|
|
8
9
|
return withToolResultExtensions(context.writeToolResultResource, async () => {
|
|
9
10
|
if (context.invokeTool)
|
|
@@ -18,6 +19,17 @@ export async function executeCapturedTool(kind, call, context) {
|
|
|
18
19
|
: undefined;
|
|
19
20
|
if (definition)
|
|
20
21
|
call = { ...call, arguments: normalizeToolInput(call.arguments, definition.inputSchema) };
|
|
22
|
+
if (kind !== 'mcp' &&
|
|
23
|
+
call.name === 'view_image' &&
|
|
24
|
+
call.arguments !== null &&
|
|
25
|
+
typeof call.arguments === 'object' &&
|
|
26
|
+
'resourceId' in call.arguments &&
|
|
27
|
+
call.arguments.resourceId != null) {
|
|
28
|
+
const store = context.imageStore;
|
|
29
|
+
if (!store)
|
|
30
|
+
throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Session image resources are unavailable.');
|
|
31
|
+
return viewResourceImage(call.arguments, (resourceId) => store.readResource(context.sessionId, resourceId), context.signal);
|
|
32
|
+
}
|
|
21
33
|
if (kind === 'builtin') {
|
|
22
34
|
const handler = AGENT_TOOL_HANDLERS.get(call.name);
|
|
23
35
|
if (handler)
|
|
@@ -40,7 +52,14 @@ export async function executeCapturedTool(kind, call, context) {
|
|
|
40
52
|
sessionId: context.sessionId,
|
|
41
53
|
executionId: context.executionId,
|
|
42
54
|
...(context.modelId === undefined ? {} : { modelId: context.modelId }),
|
|
43
|
-
...(context.recentImages === undefined
|
|
55
|
+
...(context.recentImages === undefined
|
|
56
|
+
? {}
|
|
57
|
+
: {
|
|
58
|
+
recentImages: context.recentImages.map((image) => ({
|
|
59
|
+
...image,
|
|
60
|
+
data: Buffer.from(image.data)
|
|
61
|
+
}))
|
|
62
|
+
}),
|
|
44
63
|
...(context.codeMode === undefined ? {} : { codeMode: context.codeMode })
|
|
45
64
|
});
|
|
46
65
|
}
|
package/dist/cli/main.js
CHANGED
|
@@ -155,6 +155,7 @@ async function modelsCommand(home, arguments_, codexAuthFile) {
|
|
|
155
155
|
.map((effort) => parseReasoningEffort(effort, '--reasoning-efforts'));
|
|
156
156
|
const defaultReasoningEffortOption = option('--default-reasoning-effort');
|
|
157
157
|
const model = {
|
|
158
|
+
useResourceUrl: existing?.useResourceUrl ?? false,
|
|
158
159
|
id,
|
|
159
160
|
name: required(option('--name', existing?.name), '--name'),
|
|
160
161
|
protocol,
|
|
@@ -472,6 +473,6 @@ function parseExecutionInvocation(input) {
|
|
|
472
473
|
}
|
|
473
474
|
main().catch((error) => {
|
|
474
475
|
const diagnostic = describeMarAgentError(error, 'MAR_AGENT_CLI_FAILED', 'CLI command failed.');
|
|
475
|
-
process.stderr.write(`${diagnostic.message}\n`);
|
|
476
|
+
process.stderr.write(`${diagnostic.code}: ${diagnostic.message}\n`);
|
|
476
477
|
process.exitCode = cliExitCode(diagnostic.code);
|
|
477
478
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type { CoreProcessesApi, CoreProcessesBackend, CoreProcessInput, CoreProc
|
|
|
41
41
|
export type { CreateMarAgentOptions, CreateSessionInput, ExecutionHandle, CompactInput, SteerInput, SteerResult, MarAgent, MarAgentSession, SessionTitleUpdateInput } from './agent-core/sdk/types.js';
|
|
42
42
|
export { openMarAgentSessionCatalog, type MarAgentContextUsage, type MarAgentHistoryEntry, type MarAgentHistoryPage, type MarAgentSessionCatalog, type MarAgentSessionDeleteResult, type MarAgentSessionImage, type MarAgentSessionPage, type MarAgentSessionSummary } from './agent-core/session/catalog.js';
|
|
43
43
|
export type { SessionListInput, SessionSource } from './agent-core/session/types.js';
|
|
44
|
-
export type { SessionStore, SessionStoreMaintenance, SessionStoreSession, SessionRecordInput, SessionStoreCompactInput, SessionRecord, SessionExecutionState, CompactHistoryMessage, CompactUserInput, SessionInputImage, SessionInputImageMetadata, SessionInputImageData, RestoredSessionInputImage, CodeModeStateEntry, TodoSnapshot, TodoItem, CodeToolCallRecord, CodeObservation, ModelMessage, ModelUsage, ModelInputMetadata, ModelTextBlock, ModelContextualBlock, EnvironmentContextState, ContextGcCheckpointDraft, ContextGcBase, ContextGcPlatform, ContextGcEconomicsPolicy, ContextGcMetrics, ContextGcReplacement, ContextGcTarget, ContextGcReadItemReplacement, ContextGcWebToolName, ContextGcSubagentToolName, AvailableToolResultResource } from './agent-core/session/store/contracts.js';
|
|
44
|
+
export type { SessionStore, SessionResource, SessionStoreMaintenance, SessionStoreSession, SessionRecordInput, SessionStoreCompactInput, SessionRecord, SessionExecutionState, CompactHistoryMessage, CompactUserInput, SessionInputImage, SessionInputImageMetadata, SessionInputImageData, RestoredSessionInputImage, CodeModeStateEntry, TodoSnapshot, TodoItem, CodeToolCallRecord, CodeObservation, ModelMessage, ModelUsage, ModelInputMetadata, ModelTextBlock, ModelContextualBlock, EnvironmentContextState, ContextGcCheckpointDraft, ContextGcBase, ContextGcPlatform, ContextGcEconomicsPolicy, ContextGcMetrics, ContextGcReplacement, ContextGcTarget, ContextGcReadItemReplacement, ContextGcWebToolName, ContextGcSubagentToolName, AvailableToolResultResource } from './agent-core/session/store/contracts.js';
|
|
45
45
|
export type { OpenMarAgentSessionCatalogInput } from './agent-core/session/catalog.js';
|
|
46
46
|
export type { ApplyPatchFileResult, ApplyPatchResult, ApplyPatchPartialResult, ClientToolDefinition, MarAgentToolArtifact, MarAgentToolImageArtifact, McpCatalogTool, McpToolCallContext, McpToolCatalog, McpToolCatalogContext, ToolCall, ToolCaller, ToolExecutionContext, ToolExecutionResult } from './agent-core/tools/contracts.js';
|
|
47
47
|
export { MCP_DEFINITION_LIMITS, assertMcpToolCatalog, assertMcpToolDefinition } from './agent-core/tools/mcp/catalog.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/agent",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.23",
|
|
4
4
|
"description": "Embeddable MAR coding agent SDK and CLI.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@jitl/quickjs-wasmfile-release-sync": "0.32.0",
|
|
38
38
|
"quickjs-emscripten-core": "0.32.0",
|
|
39
|
+
"sharp": "0.35.5",
|
|
39
40
|
"undici": "7.29.0",
|
|
40
41
|
"ws": "8.21.3",
|
|
41
42
|
"zod": "4.4.3"
|