@myagentroam/agent 0.10.7 → 0.10.9
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/extensions/compaction.d.ts +1 -0
- package/dist/agent-core/extensions/model-request.js +1 -1
- package/dist/agent-core/extensions/session-messages.d.ts +1 -1
- package/dist/agent-core/host/contracts.d.ts +2 -0
- package/dist/agent-core/host/local-agent-host.d.ts +2 -0
- package/dist/agent-core/host/local-agent-host.js +2 -0
- package/dist/agent-core/model/anthropic-messages.js +15 -23
- package/dist/agent-core/model/catalog-file.d.ts +14 -0
- package/dist/agent-core/model/configuration.d.ts +7 -0
- package/dist/agent-core/model/configuration.js +10 -0
- package/dist/agent-core/model/contracts.d.ts +8 -0
- package/dist/agent-core/model/openai-responses.d.ts +1 -1
- package/dist/agent-core/model/openai-responses.js +62 -29
- package/dist/agent-core/model/runtime-credential.d.ts +2 -0
- package/dist/agent-core/model/runtime-credential.js +15 -0
- package/dist/agent-core/model/sse.d.ts +1 -1
- package/dist/agent-core/model/sse.js +22 -4
- package/dist/agent-core/model/tool-input.d.ts +3 -0
- package/dist/agent-core/model/tool-input.js +18 -0
- package/dist/agent-core/model/usage-observer.d.ts +31 -0
- package/dist/agent-core/model/usage-observer.js +82 -0
- package/dist/agent-core/runtime/events.d.ts +2 -0
- package/dist/agent-core/sdk/agent.js +9 -1
- package/dist/agent-core/sdk/extension-models.d.ts +1 -1
- package/dist/agent-core/sdk/extension-models.js +9 -1
- package/dist/agent-core/sdk/session.js +31 -3
- package/dist/agent-core/session/catalog.d.ts +1 -0
- package/dist/agent-core/session/catalog.js +1 -0
- package/dist/agent-core/session/jsonl-store.d.ts +9 -0
- package/dist/agent-core/session/jsonl-store.js +24 -0
- package/dist/agent-core/session/tool-result-resources.d.ts +26 -0
- package/dist/agent-core/session/tool-result-resources.js +285 -0
- package/dist/agent-core/session/transaction-recovery.js +1 -1
- package/dist/agent-core/tools/code-mode/dispatch.js +5 -0
- package/dist/agent-core/tools/code-mode/index.js +8 -2
- package/dist/agent-core/tools/code-mode/observations.d.ts +1 -0
- package/dist/agent-core/tools/contracts.d.ts +2 -0
- package/dist/agent-core/tools/execution.js +11 -2
- package/dist/agent-core/tools/file-change-diff.d.ts +10 -0
- package/dist/agent-core/tools/file-change-diff.js +139 -0
- package/dist/agent-core/tools/local/apply-patch.js +19 -8
- package/dist/agent-core/tools/result-extensions.d.ts +46 -0
- package/dist/agent-core/tools/result-extensions.js +134 -0
- package/dist/agent-core/tools/runtime-context.d.ts +1 -0
- package/dist/agent-core/tools/runtime.js +6 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -0
- package/dist/shared/auto-title.d.ts +2 -0
- package/dist/shared/auto-title.js +6 -0
- package/dist/shared/model-text.d.ts +2 -0
- package/dist/shared/model-text.js +6 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { dirname, isAbsolute, parse, resolve } from 'node:path';
|
|
|
4
4
|
import { TextDecoder } from 'node:util';
|
|
5
5
|
import { MarAgentError } from '../../error.js';
|
|
6
6
|
import { TOOL_EXECUTION_LIMITS } from '../execution-limits.js';
|
|
7
|
+
import { captureFileChange, reserveFileChangePaths } from '../result-extensions.js';
|
|
7
8
|
export const applyPatchToolDefinition = {
|
|
8
9
|
name: 'apply_patch',
|
|
9
10
|
allowedCallers: ['direct', 'programmatic'],
|
|
@@ -70,6 +71,9 @@ export class ApplyPatchTool {
|
|
|
70
71
|
}
|
|
71
72
|
async execute(patch) {
|
|
72
73
|
const changes = parsePatch(patch);
|
|
74
|
+
reserveFileChangePaths(changes.flatMap((change) => change.kind === 'update' && change.targetPath
|
|
75
|
+
? [change.path, change.targetPath]
|
|
76
|
+
: [change.path]));
|
|
73
77
|
const resolvedChanges = await this.#resolveChanges(changes);
|
|
74
78
|
const results = [];
|
|
75
79
|
let totalBytes = 0;
|
|
@@ -149,7 +153,7 @@ export class ApplyPatchTool {
|
|
|
149
153
|
const targetStat = await optionalLstat(resolvedChange.target);
|
|
150
154
|
if (targetStat && !targetStat.isFile())
|
|
151
155
|
invalid('Patch targets must be regular files.');
|
|
152
|
-
const content = Buffer.from(`${change.lines.join('\n')}\n`);
|
|
156
|
+
const content = Buffer.from(change.lines.length ? `${change.lines.join('\n')}\n` : '');
|
|
153
157
|
const totalBytes = enforceContentLimits(content, currentTotalBytes);
|
|
154
158
|
return {
|
|
155
159
|
mutations: [
|
|
@@ -158,7 +162,8 @@ export class ApplyPatchTool {
|
|
|
158
162
|
target: resolvedChange.target,
|
|
159
163
|
content,
|
|
160
164
|
...(targetStat ? { mode: targetStat.mode & 0o7777 } : {}),
|
|
161
|
-
expectedExisting: targetStat !== undefined
|
|
165
|
+
expectedExisting: targetStat !== undefined,
|
|
166
|
+
...(targetStat ? { original: await readBoundedFile(resolvedChange.target) } : {})
|
|
162
167
|
}
|
|
163
168
|
],
|
|
164
169
|
result: {
|
|
@@ -178,7 +183,9 @@ export class ApplyPatchTool {
|
|
|
178
183
|
if (resolvedChange.kind === 'delete') {
|
|
179
184
|
const { change } = resolvedChange;
|
|
180
185
|
return {
|
|
181
|
-
mutations: [
|
|
186
|
+
mutations: [
|
|
187
|
+
{ path: change.path, target: resolvedChange.source, expectedExisting: true, original }
|
|
188
|
+
],
|
|
182
189
|
result: {
|
|
183
190
|
path: change.path,
|
|
184
191
|
operation: 'deleted',
|
|
@@ -204,13 +211,14 @@ export class ApplyPatchTool {
|
|
|
204
211
|
invalid('Patch targets must be regular files.');
|
|
205
212
|
return {
|
|
206
213
|
mutations: [
|
|
207
|
-
{ path: change.path, target: resolvedChange.source, expectedExisting: true },
|
|
214
|
+
{ path: change.path, target: resolvedChange.source, expectedExisting: true, original },
|
|
208
215
|
{
|
|
209
216
|
path: moveChange.targetPath,
|
|
210
217
|
target: resolvedChange.target,
|
|
211
218
|
content,
|
|
212
219
|
mode: (targetStat ?? sourceStat).mode & 0o7777,
|
|
213
|
-
expectedExisting: targetStat !== undefined
|
|
220
|
+
expectedExisting: targetStat !== undefined,
|
|
221
|
+
...(targetStat ? { original: await readBoundedFile(resolvedChange.target) } : {})
|
|
214
222
|
}
|
|
215
223
|
],
|
|
216
224
|
result: {
|
|
@@ -230,7 +238,8 @@ export class ApplyPatchTool {
|
|
|
230
238
|
target: resolvedChange.source,
|
|
231
239
|
content,
|
|
232
240
|
mode: sourceStat.mode & 0o7777,
|
|
233
|
-
expectedExisting: true
|
|
241
|
+
expectedExisting: true,
|
|
242
|
+
original
|
|
234
243
|
}
|
|
235
244
|
],
|
|
236
245
|
result: {
|
|
@@ -267,6 +276,8 @@ export class ApplyPatchTool {
|
|
|
267
276
|
const backup = `${mutation.target}.mar-patch-${randomUUID()}.bak`;
|
|
268
277
|
await this.#fileOperations.rename(mutation.target, backup);
|
|
269
278
|
backups.push({ target: mutation.target, backup });
|
|
279
|
+
if (mutation.original && !(await readBoundedFile(backup)).equals(mutation.original))
|
|
280
|
+
throw new MarAgentError('MAR_AGENT_PATCH_CONFLICT', 'A patch target changed after preflight.');
|
|
270
281
|
}
|
|
271
282
|
for (const item of staged) {
|
|
272
283
|
await this.#fileOperations.rename(item.temporary, item.target);
|
|
@@ -291,6 +302,8 @@ export class ApplyPatchTool {
|
|
|
291
302
|
throw error;
|
|
292
303
|
}
|
|
293
304
|
await Promise.all(backups.map((item) => this.#fileOperations.rm(item.backup, { force: true })));
|
|
305
|
+
for (const mutation of mutations)
|
|
306
|
+
await captureFileChange(mutation.path, mutation.original, mutation.content);
|
|
294
307
|
}
|
|
295
308
|
}
|
|
296
309
|
function parsePatch(patch) {
|
|
@@ -331,8 +344,6 @@ function parsePatch(patch) {
|
|
|
331
344
|
invalid('Added file lines must start with +.');
|
|
332
345
|
content.push(line.slice(1));
|
|
333
346
|
}
|
|
334
|
-
if (!content.length)
|
|
335
|
-
invalid('Added files must contain at least one patch line.');
|
|
336
347
|
changes.push({ kind: 'add', path, lines: content });
|
|
337
348
|
}
|
|
338
349
|
else if (header.startsWith('*** Delete File: ')) {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ToolExecutionResult } from './contracts.js';
|
|
3
|
+
export declare const fileChangesExtensionSchema: z.ZodObject<{
|
|
4
|
+
type: z.ZodLiteral<"file_changes">;
|
|
5
|
+
version: z.ZodLiteral<1>;
|
|
6
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
7
|
+
changeId: z.ZodString;
|
|
8
|
+
path: z.ZodString;
|
|
9
|
+
change: z.ZodEnum<{
|
|
10
|
+
added: "added";
|
|
11
|
+
modified: "modified";
|
|
12
|
+
deleted: "deleted";
|
|
13
|
+
}>;
|
|
14
|
+
additions: z.ZodNullable<z.ZodNumber>;
|
|
15
|
+
deletions: z.ZodNullable<z.ZodNumber>;
|
|
16
|
+
diff: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
|
+
status: z.ZodLiteral<"available">;
|
|
18
|
+
resourceRef: z.ZodString;
|
|
19
|
+
format: z.ZodLiteral<"unified-diff">;
|
|
20
|
+
byteSize: z.ZodNumber;
|
|
21
|
+
sha256: z.ZodString;
|
|
22
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
23
|
+
status: z.ZodLiteral<"unavailable">;
|
|
24
|
+
reason: z.ZodEnum<{
|
|
25
|
+
"unsupported-content": "unsupported-content";
|
|
26
|
+
"limit-exceeded": "limit-exceeded";
|
|
27
|
+
"capture-failed": "capture-failed";
|
|
28
|
+
"storage-failed": "storage-failed";
|
|
29
|
+
}>;
|
|
30
|
+
}, z.core.$strip>], "status">;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
export type ToolResultExtension = z.infer<typeof fileChangesExtensionSchema>;
|
|
34
|
+
export type FileChangeEvidence = ToolResultExtension['entries'][number];
|
|
35
|
+
export type AvailableToolResultResource = Extract<FileChangeEvidence['diff'], {
|
|
36
|
+
status: 'available';
|
|
37
|
+
}>;
|
|
38
|
+
export type ToolResultResourceWriter = (text: string) => Promise<AvailableToolResultResource>;
|
|
39
|
+
export declare function parseToolResultExtensions(value: unknown): ToolResultExtension[] | undefined;
|
|
40
|
+
export declare function failedToolResultExtensions(error: unknown): ToolResultExtension[] | undefined;
|
|
41
|
+
/** Reserve a complete invocation's descriptors before any leaf commits, including wrapped calls. */
|
|
42
|
+
export declare function reserveFileChangePaths(paths: readonly string[]): void;
|
|
43
|
+
/** Only the SDK's real file commit calls this producer; arbitrary result fields are ignored. */
|
|
44
|
+
export declare function captureFileChange(path: string, before?: Buffer, after?: Buffer): Promise<void>;
|
|
45
|
+
/** Own a physical invocation, including all real leaf effects retained across wrappers. */
|
|
46
|
+
export declare function withToolResultExtensions(write: ToolResultResourceWriter | undefined, run: () => Promise<ToolExecutionResult>): Promise<ToolExecutionResult>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { MarAgentError } from '../error.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { createFileDiff, FileDiffLimitError } from './file-change-diff.js';
|
|
6
|
+
const diffSchema = z.discriminatedUnion('status', [
|
|
7
|
+
z.object({
|
|
8
|
+
status: z.literal('available'),
|
|
9
|
+
resourceRef: z.string().uuid(),
|
|
10
|
+
format: z.literal('unified-diff'),
|
|
11
|
+
byteSize: z
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.nonnegative()
|
|
15
|
+
.max(16 * 1024 * 1024),
|
|
16
|
+
sha256: z.string().regex(/^[a-f0-9]{64}$/u)
|
|
17
|
+
}),
|
|
18
|
+
z.object({
|
|
19
|
+
status: z.literal('unavailable'),
|
|
20
|
+
reason: z.enum(['unsupported-content', 'limit-exceeded', 'capture-failed', 'storage-failed'])
|
|
21
|
+
})
|
|
22
|
+
]);
|
|
23
|
+
export const fileChangesExtensionSchema = z.object({
|
|
24
|
+
type: z.literal('file_changes'),
|
|
25
|
+
version: z.literal(1),
|
|
26
|
+
entries: z
|
|
27
|
+
.array(z.object({
|
|
28
|
+
changeId: z.string().uuid(),
|
|
29
|
+
path: z.string().min(1).max(8192),
|
|
30
|
+
change: z.enum(['added', 'modified', 'deleted']),
|
|
31
|
+
additions: z.number().int().nonnegative().nullable(),
|
|
32
|
+
deletions: z.number().int().nonnegative().nullable(),
|
|
33
|
+
diff: diffSchema
|
|
34
|
+
}))
|
|
35
|
+
.max(200)
|
|
36
|
+
});
|
|
37
|
+
export function parseToolResultExtensions(value) {
|
|
38
|
+
if (!Array.isArray(value) || value.length > 16)
|
|
39
|
+
return undefined;
|
|
40
|
+
const extensions = [];
|
|
41
|
+
const ids = new Set();
|
|
42
|
+
for (const input of value) {
|
|
43
|
+
const parsed = fileChangesExtensionSchema.safeParse(input);
|
|
44
|
+
if (!parsed.success || extensions.some((entry) => entry.type === parsed.data.type))
|
|
45
|
+
continue;
|
|
46
|
+
if (new Set(parsed.data.entries.map((entry) => entry.changeId)).size !==
|
|
47
|
+
parsed.data.entries.length ||
|
|
48
|
+
parsed.data.entries.some((entry) => ids.has(entry.changeId)))
|
|
49
|
+
continue;
|
|
50
|
+
parsed.data.entries.forEach((entry) => ids.add(entry.changeId));
|
|
51
|
+
extensions.push(parsed.data);
|
|
52
|
+
}
|
|
53
|
+
return extensions.length && Buffer.byteLength(JSON.stringify(extensions)) <= 1024 * 1024
|
|
54
|
+
? extensions
|
|
55
|
+
: undefined;
|
|
56
|
+
}
|
|
57
|
+
const capture = new AsyncLocalStorage();
|
|
58
|
+
const failures = new WeakMap();
|
|
59
|
+
export function failedToolResultExtensions(error) {
|
|
60
|
+
return error !== null && typeof error === 'object' ? failures.get(error) : undefined;
|
|
61
|
+
}
|
|
62
|
+
/** Reserve a complete invocation's descriptors before any leaf commits, including wrapped calls. */
|
|
63
|
+
export function reserveFileChangePaths(paths) {
|
|
64
|
+
const context = capture.getStore();
|
|
65
|
+
const entries = (context?.reservedEntries ?? 0) + paths.length;
|
|
66
|
+
const bytes = (context?.descriptorBytes ?? 256) +
|
|
67
|
+
paths.reduce((sum, path) => sum + Buffer.byteLength(JSON.stringify(path)) + 512, 0);
|
|
68
|
+
if (entries > 200 || bytes > 1024 * 1024 || paths.some((path) => path.length > 8192))
|
|
69
|
+
throw new MarAgentError('MAR_AGENT_TOOL_OUTPUT_LIMIT', 'Patch paths exceed the file evidence descriptor limit.');
|
|
70
|
+
if (context) {
|
|
71
|
+
context.reservedEntries = entries;
|
|
72
|
+
context.descriptorBytes = bytes;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Only the SDK's real file commit calls this producer; arbitrary result fields are ignored. */
|
|
76
|
+
export async function captureFileChange(path, before, after) {
|
|
77
|
+
const context = capture.getStore();
|
|
78
|
+
if (!context)
|
|
79
|
+
return;
|
|
80
|
+
const entry = {
|
|
81
|
+
changeId: randomUUID(),
|
|
82
|
+
path,
|
|
83
|
+
change: before === undefined ? 'added' : after === undefined ? 'deleted' : 'modified',
|
|
84
|
+
additions: null,
|
|
85
|
+
deletions: null,
|
|
86
|
+
diff: { status: 'unavailable', reason: 'capture-failed' }
|
|
87
|
+
};
|
|
88
|
+
context.entries.push(entry);
|
|
89
|
+
try {
|
|
90
|
+
const diff = createFileDiff(path, before, after);
|
|
91
|
+
if (!diff) {
|
|
92
|
+
entry.diff = { status: 'unavailable', reason: 'unsupported-content' };
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
entry.additions = diff.additions;
|
|
96
|
+
entry.deletions = diff.deletions;
|
|
97
|
+
context.bytes += Buffer.byteLength(diff.text);
|
|
98
|
+
if (context.bytes > 32 * 1024 * 1024)
|
|
99
|
+
entry.diff = { status: 'unavailable', reason: 'limit-exceeded' };
|
|
100
|
+
else if (context.write)
|
|
101
|
+
entry.diff = await context.write(diff.text);
|
|
102
|
+
else
|
|
103
|
+
entry.diff = { status: 'unavailable', reason: 'storage-failed' };
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
entry.diff = {
|
|
107
|
+
status: 'unavailable',
|
|
108
|
+
reason: error instanceof FileDiffLimitError ? 'limit-exceeded' : 'storage-failed'
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Own a physical invocation, including all real leaf effects retained across wrappers. */
|
|
113
|
+
export async function withToolResultExtensions(write, run) {
|
|
114
|
+
const context = {
|
|
115
|
+
entries: [],
|
|
116
|
+
bytes: 0,
|
|
117
|
+
reservedEntries: 0,
|
|
118
|
+
descriptorBytes: 256,
|
|
119
|
+
...(write ? { write } : {})
|
|
120
|
+
};
|
|
121
|
+
return capture.run(context, async () => {
|
|
122
|
+
const extensions = () => parseToolResultExtensions([{ type: 'file_changes', version: 1, entries: context.entries }]);
|
|
123
|
+
try {
|
|
124
|
+
const { resultExtensions: _ignored, ...result } = await run();
|
|
125
|
+
const resultExtensions = context.entries.length ? extensions() : undefined;
|
|
126
|
+
return resultExtensions ? { ...result, resultExtensions } : result;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (context.entries.length && error !== null && typeof error === 'object')
|
|
130
|
+
failures.set(error, extensions());
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -46,6 +46,7 @@ export interface ToolRuntimeContext {
|
|
|
46
46
|
executionId: string;
|
|
47
47
|
modelId?: string;
|
|
48
48
|
signal: AbortSignal;
|
|
49
|
+
writeToolResultResource?: import('./result-extensions.js').ToolResultResourceWriter;
|
|
49
50
|
codeMode?: import('./contracts.js').ToolExecutionContext['codeMode'];
|
|
50
51
|
skills: ReadonlyMap<string, AgentSkill>;
|
|
51
52
|
recentImages?: readonly ToolRuntimeImage[];
|
|
@@ -3,10 +3,13 @@ import { randomUUID } from 'node:crypto';
|
|
|
3
3
|
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
|
+
import { withToolResultExtensions } from './result-extensions.js';
|
|
6
7
|
export async function executeRegisteredTool(name, arguments_, callId, context, caller = 'direct') {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
return withToolResultExtensions(context.writeToolResultResource, async () => {
|
|
9
|
+
if (context.invokeTool)
|
|
10
|
+
return validateToolResult(await context.invokeTool({ name, arguments: arguments_, callId }, context, caller));
|
|
11
|
+
return validateToolResult(await executeCapturedTool(AGENT_TOOL_HANDLERS.has(name) ? 'builtin' : name.startsWith('mcp__') ? 'mcp' : 'host', { name, arguments: arguments_, callId }, context));
|
|
12
|
+
});
|
|
10
13
|
}
|
|
11
14
|
/** Invoke an already captured source; names never reselect a different backend. */
|
|
12
15
|
export async function executeCapturedTool(kind, call, context) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { MarAgentError } from './agent-core/error.js';
|
|
2
2
|
export { MAR_AGENT_HOST_API_VERSION, negotiateHost, type HostDescription, type MarAgentHostCapability } from './agent-core/host/contracts.js';
|
|
3
|
+
export type { ToolResultExtension, FileChangeEvidence } from './agent-core/tools/result-extensions.js';
|
|
4
|
+
export { parseToolResultExtensions } from './agent-core/tools/result-extensions.js';
|
|
5
|
+
export type { ToolResultResourceInput, ToolResultResourcePage } from './agent-core/session/tool-result-resources.js';
|
|
3
6
|
export type { HostExecutionExtensions, HostSessionResourceSnapshot, HostSkill, MarAgentHost } from './agent-core/host/contracts.js';
|
|
4
7
|
export { LocalAgentHost, selectExecutionShell, type LocalAgentExecutionExtensions, type LocalAgentExecutionMcpBinding, type LocalAgentMcpBinding } from './agent-core/host/local-agent-host.js';
|
|
5
8
|
export type { LocalProcessExecutor, LocalProcessSpawnRequest } from './agent-core/host/local-process-executor.js';
|
|
@@ -41,3 +44,4 @@ export type { ApplyPatchFileResult, ApplyPatchResult, ApplyPatchPartialResult, C
|
|
|
41
44
|
export { MCP_DEFINITION_LIMITS, assertMcpToolCatalog, assertMcpToolDefinition } from './agent-core/tools/mcp/catalog.js';
|
|
42
45
|
export type { WorkspacePathMount } from './agent-core/tools/shared/path-resolver.js';
|
|
43
46
|
export type { CodeModeEngine, CodeModeEngineFactory, CreateCodeModeEngine } from './agent-core/tools/code-mode/engine.js';
|
|
47
|
+
export type { ModelRequestUsage, ModelUsageObservation, ModelUsageObserver } from './agent-core/model/usage-observer.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { MarAgentError } from './agent-core/error.js';
|
|
2
2
|
export { MAR_AGENT_HOST_API_VERSION, negotiateHost } from './agent-core/host/contracts.js';
|
|
3
|
+
export { parseToolResultExtensions } from './agent-core/tools/result-extensions.js';
|
|
3
4
|
export { LocalAgentHost, selectExecutionShell } from './agent-core/host/local-agent-host.js';
|
|
4
5
|
export { SecretValue, marAgentReasoningEffortSchema, parseModelCatalog, resolveModelDefaultReasoningEffort } from './agent-core/model/configuration.js';
|
|
5
6
|
export { testMarAgentModelTransport } from './agent-core/model/transport-test.js';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type MarAgentModelConfiguration } from '../agent-core/model/configuration.js';
|
|
2
2
|
export interface GenerateSessionTitleInput {
|
|
3
|
+
readonly onModelUsage?: (usage: import('../agent-core/model/usage-observer.js').ModelRequestUsage) => Promise<void> | void;
|
|
4
|
+
readonly onModelUsageFailure?: () => void;
|
|
3
5
|
readonly models: readonly MarAgentModelConfiguration[];
|
|
4
6
|
readonly currentModelId: string;
|
|
5
7
|
readonly prompt: string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import { MarAgentError } from '../agent-core/error.js';
|
|
2
3
|
import { AnthropicMessagesAdapter } from '../agent-core/model/anthropic-messages.js';
|
|
3
4
|
import { resolveModelDefaultReasoningEffort } from '../agent-core/model/configuration.js';
|
|
@@ -38,6 +39,11 @@ export async function generateSessionTitle(input) {
|
|
|
38
39
|
try {
|
|
39
40
|
for await (const event of adapter.start({
|
|
40
41
|
retryState: { attempts: 0, maxAttempts: 1 },
|
|
42
|
+
usageRequestId: randomUUID(),
|
|
43
|
+
...(input.onModelUsage === undefined ? {} : { onModelUsage: input.onModelUsage }),
|
|
44
|
+
...(input.onModelUsageFailure === undefined
|
|
45
|
+
? {}
|
|
46
|
+
: { onModelUsageFailure: input.onModelUsageFailure }),
|
|
41
47
|
system: defaultLanguage
|
|
42
48
|
? `${sessionTitlePrompt}\n- If the user message does not establish a language, use ${JSON.stringify(defaultLanguage)} as the default language.`
|
|
43
49
|
: sessionTitlePrompt,
|
|
@@ -2,6 +2,8 @@ import { type MarAgentModelConfiguration, type MarAgentReasoningEffort } from '.
|
|
|
2
2
|
import type { ModelAttemptDiagnostic, ModelUsage } from '../agent-core/model/contracts.js';
|
|
3
3
|
import type { CoreCompactMessage } from '../agent-core/extensions/compaction.js';
|
|
4
4
|
export interface GenerateModelTextInput {
|
|
5
|
+
readonly onModelUsage?: (usage: import('../agent-core/model/usage-observer.js').ModelRequestUsage) => Promise<void> | void;
|
|
6
|
+
readonly onModelUsageFailure?: () => void;
|
|
5
7
|
readonly model: MarAgentModelConfiguration;
|
|
6
8
|
readonly system: string;
|
|
7
9
|
readonly messages: readonly CoreCompactMessage[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import { MarAgentError } from '../agent-core/error.js';
|
|
2
3
|
import { AnthropicMessagesAdapter } from '../agent-core/model/anthropic-messages.js';
|
|
3
4
|
import { OpenAiResponsesAdapter } from '../agent-core/model/openai-responses.js';
|
|
@@ -16,6 +17,11 @@ export async function generateModelText(input) {
|
|
|
16
17
|
try {
|
|
17
18
|
for await (const event of adapter.start({
|
|
18
19
|
retryState: { attempts: 0, maxAttempts: 1 },
|
|
20
|
+
usageRequestId: randomUUID(),
|
|
21
|
+
...(input.onModelUsage === undefined ? {} : { onModelUsage: input.onModelUsage }),
|
|
22
|
+
...(input.onModelUsageFailure === undefined
|
|
23
|
+
? {}
|
|
24
|
+
: { onModelUsageFailure: input.onModelUsageFailure }),
|
|
19
25
|
system: input.system,
|
|
20
26
|
messages: input.messages,
|
|
21
27
|
tools: [],
|