@myagentroam/agent 0.9.168 → 0.9.170
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 +25 -0
- package/dist/agent-core/extensions/compaction.js +55 -0
- package/dist/agent-core/extensions/contracts.d.ts +5 -0
- package/dist/agent-core/model/anthropic-messages.js +13 -9
- package/dist/agent-core/runtime/compaction/operation.d.ts +2 -0
- package/dist/agent-core/runtime/compaction/operation.js +20 -0
- package/dist/agent-core/sdk/session.js +53 -5
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/shared/model-text.d.ts +16 -0
- package/dist/shared/model-text.js +43 -0
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ModelMessage, ModelUsage } from '../model/contracts.js';
|
|
2
|
+
export interface CoreCompactMessage {
|
|
3
|
+
readonly role: 'user' | 'assistant' | 'tool' | 'tool_call';
|
|
4
|
+
readonly content: string;
|
|
5
|
+
readonly callId?: string;
|
|
6
|
+
readonly name?: string;
|
|
7
|
+
readonly arguments?: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface CoreCompactContext {
|
|
10
|
+
readonly operationId: string;
|
|
11
|
+
readonly reason: 'manual' | 'automatic';
|
|
12
|
+
readonly messages: readonly CoreCompactMessage[];
|
|
13
|
+
readonly focus?: string;
|
|
14
|
+
readonly summaryTokenBudget: number;
|
|
15
|
+
/** Return the Core compaction contract selected for this operation's main model snapshot. */
|
|
16
|
+
readonly getPrompt: () => string;
|
|
17
|
+
}
|
|
18
|
+
export interface CoreCompactResult {
|
|
19
|
+
readonly summary: string;
|
|
20
|
+
readonly usage?: Readonly<ModelUsage>;
|
|
21
|
+
}
|
|
22
|
+
/** Copy only neutral evidence; a hook never receives provider payloads or history ownership. */
|
|
23
|
+
export declare function compactExtensionMessages(messages: readonly ModelMessage[]): readonly CoreCompactMessage[];
|
|
24
|
+
/** Invalid plugin results decline generation rather than altering the checkpoint contract. */
|
|
25
|
+
export declare function compactExtensionResult(value: unknown, budget: number): CoreCompactResult | undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { countModelTokens } from '../runtime/token-budget.js';
|
|
2
|
+
/** Copy only neutral evidence; a hook never receives provider payloads or history ownership. */
|
|
3
|
+
export function compactExtensionMessages(messages) {
|
|
4
|
+
return freeze(messages
|
|
5
|
+
.filter((message) => message.role !== 'provider' && message.contextKind === undefined)
|
|
6
|
+
.map((message) => ({
|
|
7
|
+
role: message.role,
|
|
8
|
+
content: message.content,
|
|
9
|
+
...(message.callId === undefined ? {} : { callId: message.callId }),
|
|
10
|
+
...(message.name === undefined ? {} : { name: message.name }),
|
|
11
|
+
...(message.arguments === undefined
|
|
12
|
+
? {}
|
|
13
|
+
: { arguments: structuredClone(message.arguments) })
|
|
14
|
+
})));
|
|
15
|
+
}
|
|
16
|
+
const usageKeys = new Set([
|
|
17
|
+
'inputTokens',
|
|
18
|
+
'contextInputTokens',
|
|
19
|
+
'outputTokens',
|
|
20
|
+
'cacheReadTokens',
|
|
21
|
+
'cacheWriteTokens',
|
|
22
|
+
'rolloutBudgetUnits',
|
|
23
|
+
'hostedSearches',
|
|
24
|
+
'hostedFetches'
|
|
25
|
+
]);
|
|
26
|
+
/** Invalid plugin results decline generation rather than altering the checkpoint contract. */
|
|
27
|
+
export function compactExtensionResult(value, budget) {
|
|
28
|
+
if (value === null ||
|
|
29
|
+
typeof value !== 'object' ||
|
|
30
|
+
!('summary' in value) ||
|
|
31
|
+
typeof value.summary !== 'string')
|
|
32
|
+
return undefined;
|
|
33
|
+
const summary = value.summary.trim();
|
|
34
|
+
if (!summary || countModelTokens(summary) > budget)
|
|
35
|
+
return undefined;
|
|
36
|
+
if (!('usage' in value) || value.usage === undefined)
|
|
37
|
+
return { summary };
|
|
38
|
+
if (value.usage === null || typeof value.usage !== 'object' || Array.isArray(value.usage))
|
|
39
|
+
return undefined;
|
|
40
|
+
const usage = {};
|
|
41
|
+
for (const [key, amount] of Object.entries(value.usage)) {
|
|
42
|
+
if (!usageKeys.has(key) || typeof amount !== 'number' || !Number.isFinite(amount) || amount < 0)
|
|
43
|
+
return undefined;
|
|
44
|
+
Object.assign(usage, { [key]: amount });
|
|
45
|
+
}
|
|
46
|
+
return { summary, usage };
|
|
47
|
+
}
|
|
48
|
+
function freeze(value) {
|
|
49
|
+
if (value !== null && typeof value === 'object') {
|
|
50
|
+
for (const child of Object.values(value))
|
|
51
|
+
freeze(child);
|
|
52
|
+
Object.freeze(value);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CoreModelRequest } from './model-request.js';
|
|
2
|
+
import type { CoreCompactContext, CoreCompactResult } from './compaction.js';
|
|
2
3
|
import type { CorePromptInput, CorePromptResult } from './prompt-input.js';
|
|
3
4
|
import type { CoreModelEvent } from './model-stream.js';
|
|
4
5
|
import type { CorePromptComposition, CorePromptSectionInput } from './prompt-composition.js';
|
|
@@ -115,6 +116,10 @@ export interface CoreDomainOperations extends CoreFileOperations {
|
|
|
115
116
|
input: CoreCompactInput;
|
|
116
117
|
output: CoreSessionActionResult;
|
|
117
118
|
};
|
|
119
|
+
'compact.generate': {
|
|
120
|
+
input: CoreCompactContext;
|
|
121
|
+
output: CoreCompactResult | undefined;
|
|
122
|
+
};
|
|
118
123
|
}
|
|
119
124
|
export interface CoreDomainFacts {
|
|
120
125
|
'session.ending': {
|
|
@@ -117,9 +117,9 @@ export class AnthropicMessagesAdapter {
|
|
|
117
117
|
responseId = text(message.id) ?? responseId;
|
|
118
118
|
yield { type: 'response.started', responseId };
|
|
119
119
|
const usage = record(message.usage);
|
|
120
|
-
const inputTokens =
|
|
121
|
-
const cacheReadTokens =
|
|
122
|
-
const cacheWriteTokens =
|
|
120
|
+
const inputTokens = inputTokenCount(usage.input_tokens);
|
|
121
|
+
const cacheReadTokens = inputTokenCount(usage.cache_read_input_tokens);
|
|
122
|
+
const cacheWriteTokens = inputTokenCount(usage.cache_creation_input_tokens);
|
|
123
123
|
latestInputUsage = inputUsage(inputTokens, cacheReadTokens, cacheWriteTokens);
|
|
124
124
|
yield {
|
|
125
125
|
type: 'usage',
|
|
@@ -334,12 +334,13 @@ export class AnthropicMessagesAdapter {
|
|
|
334
334
|
}
|
|
335
335
|
pendingTextBlocks.clear();
|
|
336
336
|
const usage = record(event.usage);
|
|
337
|
-
const inputTokens =
|
|
338
|
-
const cacheReadTokens =
|
|
339
|
-
const cacheWriteTokens =
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
337
|
+
const inputTokens = inputTokenCount(usage.input_tokens);
|
|
338
|
+
const cacheReadTokens = inputTokenCount(usage.cache_read_input_tokens);
|
|
339
|
+
const cacheWriteTokens = inputTokenCount(usage.cache_creation_input_tokens);
|
|
340
|
+
// Some compatible gateways emit a complete all-zero input placeholder at the end.
|
|
341
|
+
const zeroPlaceholder = inputTokens === 0 && cacheReadTokens === 0 && cacheWriteTokens === 0;
|
|
342
|
+
if (!zeroPlaceholder)
|
|
343
|
+
latestInputUsage = inputUsage(inputTokens ?? latestInputUsage?.inputTokens, cacheReadTokens ?? latestInputUsage?.cacheReadTokens, cacheWriteTokens ?? latestInputUsage?.cacheWriteTokens);
|
|
343
344
|
yield {
|
|
344
345
|
type: 'usage',
|
|
345
346
|
usage: {
|
|
@@ -439,6 +440,9 @@ function retryAfter(error) {
|
|
|
439
440
|
const value = error.details?.retryAfter;
|
|
440
441
|
return typeof value === 'string' ? value : null;
|
|
441
442
|
}
|
|
443
|
+
function inputTokenCount(value) {
|
|
444
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
445
|
+
}
|
|
442
446
|
function inputUsage(inputTokens, cacheReadTokens, cacheWriteTokens) {
|
|
443
447
|
return {
|
|
444
448
|
inputTokens,
|
|
@@ -17,6 +17,8 @@ export declare class CompactionOperation {
|
|
|
17
17
|
readonly signal: AbortSignal;
|
|
18
18
|
constructor(parent: AbortSignal, record: (progress: CompactionProgress) => void | Promise<void>);
|
|
19
19
|
start(model: Pick<ModelTurnSession, 'start'>, request: ModelRequest): AsyncIterable<ModelEvent>;
|
|
20
|
+
/** External generation shares this operation's deadline, including the default fallback. */
|
|
21
|
+
generate<T>(run: (signal: AbortSignal) => Promise<T>): Promise<T>;
|
|
20
22
|
dispose(): Promise<void>;
|
|
21
23
|
private report;
|
|
22
24
|
}
|
|
@@ -61,6 +61,26 @@ export class CompactionOperation {
|
|
|
61
61
|
throw error;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
+
/** External generation shares this operation's deadline, including the default fallback. */
|
|
65
|
+
async generate(run) {
|
|
66
|
+
this.signal.throwIfAborted();
|
|
67
|
+
let abort;
|
|
68
|
+
try {
|
|
69
|
+
return await Promise.race([
|
|
70
|
+
Promise.resolve().then(() => run(this.signal)),
|
|
71
|
+
new Promise((_resolve, reject) => {
|
|
72
|
+
abort = () => reject(this.signal.reason);
|
|
73
|
+
this.signal.addEventListener('abort', abort, { once: true });
|
|
74
|
+
if (this.signal.aborted)
|
|
75
|
+
abort();
|
|
76
|
+
})
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
if (abort)
|
|
81
|
+
this.signal.removeEventListener('abort', abort);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
64
84
|
async dispose() {
|
|
65
85
|
if (this.#closed)
|
|
66
86
|
return;
|
|
@@ -11,6 +11,7 @@ import { discoveredMcpToolNames, rebindMcpToolSearchOutputs } from '../tools/mcp
|
|
|
11
11
|
import { currentExecutionImages } from '../tools/output-projection.js';
|
|
12
12
|
import { createHash, randomUUID } from 'node:crypto';
|
|
13
13
|
import { ExecutionToolSources } from './extension-tools.js';
|
|
14
|
+
import { compactExtensionMessages, compactExtensionResult } from '../extensions/compaction.js';
|
|
14
15
|
import { ExtensionRequestBridge, ExtensionRequestSnapshots } from '../extensions/model-request.js';
|
|
15
16
|
import { normalizeSessionMessagesInput, sessionMessagesPage } from '../extensions/session-messages.js';
|
|
16
17
|
import { transformCoreModelStream } from '../extensions/model-stream.js';
|
|
@@ -1013,7 +1014,37 @@ export function createSessionOpener(services) {
|
|
|
1013
1014
|
: buildExecutionSystemPrompt();
|
|
1014
1015
|
let useManualCompactionFallback;
|
|
1015
1016
|
const manualAppendBoundary = pendingAppends.length;
|
|
1016
|
-
|
|
1017
|
+
const generateCompactExtension = async (history, reason, focus, compaction) => {
|
|
1018
|
+
if (!coreExtensions.hooks.hasInterceptors('compact.generate'))
|
|
1019
|
+
return undefined;
|
|
1020
|
+
const summaryTokenBudget = Math.min(10_000, selectedModel.maxOutputTokens, Math.max(1, Math.floor(selectedModel.contextWindowTokens / 4)));
|
|
1021
|
+
const highDensityCompaction = selectedModel.highDensityCompaction;
|
|
1022
|
+
try {
|
|
1023
|
+
const result = await compaction.generate((signal) => operation((call) => coreExtensions.hooks.invoke('compact.generate', Object.freeze({
|
|
1024
|
+
operationId: call.operationId,
|
|
1025
|
+
reason,
|
|
1026
|
+
messages: compactExtensionMessages(history),
|
|
1027
|
+
...(focus === undefined ? {} : { focus }),
|
|
1028
|
+
summaryTokenBudget,
|
|
1029
|
+
getPrompt: () => buildCompactionMessages('', highDensityCompaction)[1].content
|
|
1030
|
+
}), Object.freeze({ ...call, signal }), async () => undefined)));
|
|
1031
|
+
compaction.signal.throwIfAborted();
|
|
1032
|
+
return compactExtensionResult(result, summaryTokenBudget);
|
|
1033
|
+
}
|
|
1034
|
+
catch {
|
|
1035
|
+
compaction.signal.throwIfAborted();
|
|
1036
|
+
return undefined;
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
let manualExtension;
|
|
1040
|
+
if (mode === 'compact' && coreExtensions.hooks.hasInterceptors('compact.generate')) {
|
|
1041
|
+
manualCompactionStarted = true;
|
|
1042
|
+
manualCompaction = createCompactionOperation(manualCompactionId, compactSignal);
|
|
1043
|
+
await emit({ type: 'context.compacting', compactionId: manualCompactionId });
|
|
1044
|
+
rolloutBudget?.assertAvailable();
|
|
1045
|
+
manualExtension = await generateCompactExtension(messages, 'manual', compactFocus, manualCompaction);
|
|
1046
|
+
}
|
|
1047
|
+
if (mode === 'compact' && manualExtension === undefined) {
|
|
1017
1048
|
const compactSystemPrompt = initialSystemPrompt;
|
|
1018
1049
|
const compactHistory = [...messages];
|
|
1019
1050
|
const projectedHistory = normalizeMessagesForModel(insertContextualWorldState(compactHistory, contextualWorldState.entries), { supportsImages: false });
|
|
@@ -1079,8 +1110,6 @@ export function createSessionOpener(services) {
|
|
|
1079
1110
|
});
|
|
1080
1111
|
const compactOverheadTokens = estimatedRequestTokens(compactSystemPrompt, buildCompactionMessages('', selectedModel.highDensityCompaction), executionTools);
|
|
1081
1112
|
const compactInputTokens = Math.max(0, selectedModel.contextWindowTokens - compactOverheadTokens);
|
|
1082
|
-
if (compactInputTokens === 0)
|
|
1083
|
-
throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'Compaction prompt exceeds the selected model context window.');
|
|
1084
1113
|
let usingNativeMessages = shouldUseNativeCompaction({
|
|
1085
1114
|
estimatedRequestTokens: estimatedRequestTokens(compactSystemPrompt, nativeCompactMessages, executionTools),
|
|
1086
1115
|
contextWindowTokens: selectedModel.contextWindowTokens,
|
|
@@ -1101,7 +1130,16 @@ export function createSessionOpener(services) {
|
|
|
1101
1130
|
const compactionRetryState = { attempts: 0 };
|
|
1102
1131
|
const compaction = createCompactionOperation(compactionId, signal);
|
|
1103
1132
|
try {
|
|
1104
|
-
|
|
1133
|
+
const extensionResult = await generateCompactExtension(compactHistory, 'automatic', input.focus, compaction);
|
|
1134
|
+
if (extensionResult) {
|
|
1135
|
+
compactSummary = extensionResult.summary;
|
|
1136
|
+
latestUsage = extensionResult.usage;
|
|
1137
|
+
if (latestUsage)
|
|
1138
|
+
await emit({ type: 'usage.updated', ...publicModelUsage(latestUsage) });
|
|
1139
|
+
}
|
|
1140
|
+
while (extensionResult === undefined) {
|
|
1141
|
+
if (compactInputTokens === 0)
|
|
1142
|
+
throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'Compaction prompt exceeds the selected model context window.');
|
|
1105
1143
|
compactSummary = '';
|
|
1106
1144
|
latestUsage = undefined;
|
|
1107
1145
|
try {
|
|
@@ -1172,6 +1210,7 @@ export function createSessionOpener(services) {
|
|
|
1172
1210
|
}, options);
|
|
1173
1211
|
messages.splice(0, messages.length, environmentContextUpdate(executionEnvironment), ...compactedHistoryMessages(replacementHistory), ...retainedModelContext);
|
|
1174
1212
|
pendingAppends.length = 0;
|
|
1213
|
+
selected.resetContinuation?.();
|
|
1175
1214
|
return record;
|
|
1176
1215
|
});
|
|
1177
1216
|
contextGc.reset();
|
|
@@ -1385,7 +1424,15 @@ export function createSessionOpener(services) {
|
|
|
1385
1424
|
}
|
|
1386
1425
|
}
|
|
1387
1426
|
});
|
|
1388
|
-
|
|
1427
|
+
if (manualExtension) {
|
|
1428
|
+
rolloutBudget?.recordUsage(manualExtension.usage);
|
|
1429
|
+
rolloutBudget?.assertAvailable();
|
|
1430
|
+
if (manualExtension.usage)
|
|
1431
|
+
await emit({ type: 'usage.updated', ...publicModelUsage(manualExtension.usage) });
|
|
1432
|
+
}
|
|
1433
|
+
const completed = manualExtension
|
|
1434
|
+
? { finalAnswer: manualExtension.summary, usage: manualExtension.usage }
|
|
1435
|
+
: await executionLoop.run();
|
|
1389
1436
|
finalAnswer = completed.finalAnswer;
|
|
1390
1437
|
const compactSummary = mode === 'compact' ? finalAnswer.trim() : '';
|
|
1391
1438
|
if (manualCompaction) {
|
|
@@ -1410,6 +1457,7 @@ export function createSessionOpener(services) {
|
|
|
1410
1457
|
}, options);
|
|
1411
1458
|
messages.splice(0, messages.length, ...compactedHistoryMessages(replacementHistory), ...retainedModelContext);
|
|
1412
1459
|
pendingAppends.length = 0;
|
|
1460
|
+
selected.resetContinuation?.();
|
|
1413
1461
|
return record;
|
|
1414
1462
|
});
|
|
1415
1463
|
if (mode === 'compact' && manualCompactionId !== undefined)
|
package/dist/index.d.ts
CHANGED
|
@@ -8,10 +8,14 @@ export { testMarAgentModelTransport } from './agent-core/model/transport-test.js
|
|
|
8
8
|
export type { AccessMode, ExecutionMode, ExecutionResult, MarAgentImageMetadata, RolloutBudgetOptions, RunInput, RunInputImage } from './agent-core/runtime/contracts.js';
|
|
9
9
|
export type { MarAgentEvent } from './agent-core/runtime/events.js';
|
|
10
10
|
export { createMarAgent } from './agent-core/sdk/agent.js';
|
|
11
|
+
export { generateModelText, type GenerateModelTextInput } from './shared/model-text.js';
|
|
11
12
|
export type { CoreAgentExtensionContext, CoreSessionExtensionContext, CoreRuntimeExtension, CoreExtensionSnapshot, CoreExtensionSource, CoreExtensionDiagnostic, CoreDomainOperations, CoreDomainFacts, CoreHookRegistrar, CoreCapabilitySnapshot, CoreCommandSpec, CorePromptSection, CoreServiceDeclaration, CoreServiceDependency } from './agent-core/extensions/contracts.js';
|
|
12
13
|
export type { CoreDisposer, CoreResourceRegistration, CoreResourceScope } from './agent-core/extensions/resources.js';
|
|
13
14
|
export type { CoreHookOptions, CoreInterceptor } from './agent-core/extensions/hooks.js';
|
|
14
15
|
export type { CoreOperationContext } from './agent-core/extensions/operation.js';
|
|
16
|
+
export type { CoreCompactContext, CoreCompactMessage, CoreCompactResult } from './agent-core/extensions/compaction.js';
|
|
17
|
+
export { buildCompactionInput as buildCompactEvidence } from './agent-core/runtime/compaction/history.js';
|
|
18
|
+
export { countModelTokens } from './agent-core/runtime/token-budget.js';
|
|
15
19
|
export type { CoreServiceKey, CoreServiceRegistry } from './agent-core/extensions/services.js';
|
|
16
20
|
export type { CoreToolSpec, CoreToolRef, CoreToolInvocation, CoreToolCheck, CoreToolAttempt, CoreToolCompletion, CoreToolFailure } from './agent-core/extensions/tools.js';
|
|
17
21
|
export type { CoreModelMessage, CoreModelRequest, CoreRequestSnapshot } from './agent-core/extensions/model-request.js';
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,9 @@ export { LocalAgentHost, selectExecutionShell } from './agent-core/host/local-ag
|
|
|
4
4
|
export { SecretValue, marAgentReasoningEffortSchema, parseModelCatalog, resolveModelDefaultReasoningEffort } from './agent-core/model/configuration.js';
|
|
5
5
|
export { testMarAgentModelTransport } from './agent-core/model/transport-test.js';
|
|
6
6
|
export { createMarAgent } from './agent-core/sdk/agent.js';
|
|
7
|
+
export { generateModelText } from './shared/model-text.js';
|
|
8
|
+
export { buildCompactionInput as buildCompactEvidence } from './agent-core/runtime/compaction/history.js';
|
|
9
|
+
export { countModelTokens } from './agent-core/runtime/token-budget.js';
|
|
7
10
|
export { generateSessionTitle } from './shared/auto-title.js';
|
|
8
11
|
export { openMarAgentSessionCatalog } from './agent-core/session/catalog.js';
|
|
9
12
|
export { MCP_DEFINITION_LIMITS, assertMcpToolCatalog, assertMcpToolDefinition } from './agent-core/tools/mcp/catalog.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type MarAgentModelConfiguration, type MarAgentReasoningEffort } from '../agent-core/model/configuration.js';
|
|
2
|
+
import type { ModelUsage } from '../agent-core/model/contracts.js';
|
|
3
|
+
import type { CoreCompactMessage } from '../agent-core/extensions/compaction.js';
|
|
4
|
+
export interface GenerateModelTextInput {
|
|
5
|
+
readonly model: MarAgentModelConfiguration;
|
|
6
|
+
readonly system: string;
|
|
7
|
+
readonly messages: readonly CoreCompactMessage[];
|
|
8
|
+
readonly reasoningEffort?: MarAgentReasoningEffort;
|
|
9
|
+
readonly outputLimit?: number;
|
|
10
|
+
readonly signal: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
/** One tool-free request using the SDK transports. Credential providers remain caller-owned. */
|
|
13
|
+
export declare function generateModelText(input: GenerateModelTextInput): Promise<{
|
|
14
|
+
text: string;
|
|
15
|
+
usage?: ModelUsage;
|
|
16
|
+
} | undefined>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { MarAgentError } from '../agent-core/error.js';
|
|
2
|
+
import { AnthropicMessagesAdapter } from '../agent-core/model/anthropic-messages.js';
|
|
3
|
+
import { OpenAiResponsesAdapter } from '../agent-core/model/openai-responses.js';
|
|
4
|
+
import { resolveModelDefaultReasoningEffort } from '../agent-core/model/configuration.js';
|
|
5
|
+
/** One tool-free request using the SDK transports. Credential providers remain caller-owned. */
|
|
6
|
+
export async function generateModelText(input) {
|
|
7
|
+
input.signal.throwIfAborted();
|
|
8
|
+
if (!input.model.enabled)
|
|
9
|
+
return undefined;
|
|
10
|
+
const adapter = input.model.protocol === 'OPENAI_RESPONSES'
|
|
11
|
+
? new OpenAiResponsesAdapter(input.model)
|
|
12
|
+
: new AnthropicMessagesAdapter(input.model);
|
|
13
|
+
let text = '';
|
|
14
|
+
let completed = false;
|
|
15
|
+
let usage;
|
|
16
|
+
try {
|
|
17
|
+
for await (const event of adapter.start({
|
|
18
|
+
retryState: { attempts: 0, maxAttempts: 1 },
|
|
19
|
+
system: input.system,
|
|
20
|
+
messages: input.messages,
|
|
21
|
+
tools: [],
|
|
22
|
+
allowTools: false,
|
|
23
|
+
toolChoice: 'none',
|
|
24
|
+
reasoningEffort: input.reasoningEffort ?? resolveModelDefaultReasoningEffort(input.model),
|
|
25
|
+
...(input.outputLimit === undefined ? {} : { outputLimit: input.outputLimit })
|
|
26
|
+
}, input.signal)) {
|
|
27
|
+
input.signal.throwIfAborted();
|
|
28
|
+
if (event.type === 'text.completed' && (event.phase ?? 'final_answer') === 'final_answer')
|
|
29
|
+
text = event.text.trim();
|
|
30
|
+
else if (event.type === 'usage')
|
|
31
|
+
usage = event.usage;
|
|
32
|
+
else if (event.type === 'completed')
|
|
33
|
+
completed = event.reason === 'completed';
|
|
34
|
+
else if (event.type === 'client_tool.call')
|
|
35
|
+
throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Text generation returned a tool call while tools were disabled.');
|
|
36
|
+
}
|
|
37
|
+
input.signal.throwIfAborted();
|
|
38
|
+
return completed && text ? { text, ...(usage === undefined ? {} : { usage }) } : undefined;
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await adapter.close?.();
|
|
42
|
+
}
|
|
43
|
+
}
|