@myagentroam/agent 0.11.6 → 0.11.8
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/model/anthropic-messages.js +6 -1
- package/dist/agent-core/model/contracts.d.ts +1 -0
- package/dist/agent-core/model/native-context.d.ts +3 -0
- package/dist/agent-core/model/native-context.js +44 -0
- package/dist/agent-core/model/request-configuration.d.ts +17 -0
- package/dist/agent-core/model/request-configuration.js +47 -0
- package/dist/agent-core/model/tool-declarations.d.ts +4 -0
- package/dist/agent-core/model/tool-declarations.js +6 -0
- package/dist/agent-core/runtime/context/projection.js +3 -29
- package/dist/agent-core/runtime/context/usage.d.ts +0 -1
- package/dist/agent-core/runtime/context/usage.js +0 -15
- package/dist/agent-core/runtime/execution.js +1 -3
- package/dist/agent-core/sdk/model-runtime.d.ts +5 -0
- package/dist/agent-core/sdk/model-runtime.js +28 -0
- package/dist/agent-core/sdk/request-preparation.d.ts +7 -0
- package/dist/agent-core/sdk/request-preparation.js +23 -0
- package/dist/agent-core/sdk/session.d.ts +1 -1
- package/dist/agent-core/sdk/session.js +38 -84
- package/package.json +1 -1
|
@@ -317,7 +317,12 @@ export class AnthropicMessagesAdapter {
|
|
|
317
317
|
throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Anthropic returned an invalid or oversized native thinking block.');
|
|
318
318
|
thinkingBytes += Buffer.byteLength(JSON.stringify(item));
|
|
319
319
|
assertAnthropicThinkingBudget(thinkingBytes);
|
|
320
|
-
yield observeModelStreamEvent({
|
|
320
|
+
yield observeModelStreamEvent({
|
|
321
|
+
type: 'response.item',
|
|
322
|
+
provider: 'ANTHROPIC_MESSAGES',
|
|
323
|
+
contextKind: 'private',
|
|
324
|
+
item
|
|
325
|
+
}, modelStreamEventObservedAt(raw));
|
|
321
326
|
}
|
|
322
327
|
if (block.type === 'thinking' && block.text.trim())
|
|
323
328
|
yield observeModelStreamEvent({
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ModelMessage } from './contracts.js';
|
|
2
|
+
/** Interpret only the existing native context record shapes and their model ownership. */
|
|
3
|
+
export declare function restoreNativeModelContext(payload: Record<string, unknown>, activeModelId?: string): ModelMessage | undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { anthropicThinkingBlock } from './anthropic-thinking.js';
|
|
2
|
+
/** Interpret only the existing native context record shapes and their model ownership. */
|
|
3
|
+
export function restoreNativeModelContext(payload, activeModelId) {
|
|
4
|
+
const modelId = typeof payload.providerModelId === 'string' && payload.providerModelId.length > 0
|
|
5
|
+
? payload.providerModelId
|
|
6
|
+
: undefined;
|
|
7
|
+
const contextKind = nativeContextKind(payload.contextKind);
|
|
8
|
+
if (payload.provider === 'ANTHROPIC_MESSAGES') {
|
|
9
|
+
const item = anthropicThinkingBlock(payload.item);
|
|
10
|
+
return item && modelId
|
|
11
|
+
? {
|
|
12
|
+
role: 'provider',
|
|
13
|
+
content: '',
|
|
14
|
+
provider: 'ANTHROPIC_MESSAGES',
|
|
15
|
+
providerModelId: modelId,
|
|
16
|
+
contextKind: contextKind ?? 'private',
|
|
17
|
+
item
|
|
18
|
+
}
|
|
19
|
+
: undefined;
|
|
20
|
+
}
|
|
21
|
+
if (payload.provider !== 'OPENAI_RESPONSES' ||
|
|
22
|
+
!payload.item ||
|
|
23
|
+
typeof payload.item !== 'object' ||
|
|
24
|
+
Array.isArray(payload.item))
|
|
25
|
+
return undefined;
|
|
26
|
+
const restoredModelId = modelId ?? activeModelId;
|
|
27
|
+
return {
|
|
28
|
+
role: 'provider',
|
|
29
|
+
content: '',
|
|
30
|
+
provider: 'OPENAI_RESPONSES',
|
|
31
|
+
...(restoredModelId === undefined ? {} : { providerModelId: restoredModelId }),
|
|
32
|
+
...(contextKind === undefined ? {} : { contextKind }),
|
|
33
|
+
item: payload.item
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function nativeContextKind(value) {
|
|
37
|
+
return value === 'environment' ||
|
|
38
|
+
value === 'private' ||
|
|
39
|
+
value === 'contextual' ||
|
|
40
|
+
value === 'summary' ||
|
|
41
|
+
value === 'compact_control'
|
|
42
|
+
? value
|
|
43
|
+
: undefined;
|
|
44
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type MarAgentModelConfiguration, type MarAgentReasoningEffort } from './configuration.js';
|
|
2
|
+
import type { ModelMessage } from './contracts.js';
|
|
3
|
+
/** Resolve request effort and native updates without owning their persistence or timing. */
|
|
4
|
+
export declare function prepareModelConfiguration(model: Pick<MarAgentModelConfiguration, 'id' | 'protocol' | 'responsesConfigurationUpdates' | 'codexCredential'>, effort: MarAgentReasoningEffort, context: {
|
|
5
|
+
readonly baselineEffort: MarAgentReasoningEffort | undefined;
|
|
6
|
+
readonly messages: readonly ModelMessage[];
|
|
7
|
+
readonly checkpointAdopted?: false;
|
|
8
|
+
} | {
|
|
9
|
+
readonly checkpointAdopted: true;
|
|
10
|
+
}): {
|
|
11
|
+
readonly requestReasoningEffort?: MarAgentReasoningEffort;
|
|
12
|
+
readonly updates: readonly ModelMessage[];
|
|
13
|
+
readonly contextProjection: {
|
|
14
|
+
readonly modelProtocol: MarAgentModelConfiguration['protocol'];
|
|
15
|
+
readonly responsesConfigurationUpdates: boolean;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { marAgentReasoningEffortSchema, usesResponsesConfigurationUpdates } from './configuration.js';
|
|
2
|
+
/** Resolve request effort and native updates without owning their persistence or timing. */
|
|
3
|
+
export function prepareModelConfiguration(model, effort, context) {
|
|
4
|
+
const useUpdates = usesResponsesConfigurationUpdates(model);
|
|
5
|
+
const contextProjection = {
|
|
6
|
+
modelProtocol: model.protocol,
|
|
7
|
+
responsesConfigurationUpdates: useUpdates
|
|
8
|
+
};
|
|
9
|
+
if (context.checkpointAdopted)
|
|
10
|
+
return { requestReasoningEffort: effort, updates: [], contextProjection };
|
|
11
|
+
if (!useUpdates)
|
|
12
|
+
return { updates: [], contextProjection };
|
|
13
|
+
const requestReasoningEffort = context.baselineEffort ?? effort;
|
|
14
|
+
const effectiveEffort = context.baselineEffort === undefined
|
|
15
|
+
? requestReasoningEffort
|
|
16
|
+
: (lastConfigurationEffort(context.messages, model.id) ?? requestReasoningEffort);
|
|
17
|
+
return {
|
|
18
|
+
requestReasoningEffort,
|
|
19
|
+
contextProjection,
|
|
20
|
+
updates: effectiveEffort === effort
|
|
21
|
+
? []
|
|
22
|
+
: [
|
|
23
|
+
{
|
|
24
|
+
role: 'provider',
|
|
25
|
+
content: '',
|
|
26
|
+
provider: 'OPENAI_RESPONSES',
|
|
27
|
+
providerModelId: model.id,
|
|
28
|
+
item: { type: 'configuration_update', reasoning: { effort } }
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function lastConfigurationEffort(messages, modelId) {
|
|
34
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
35
|
+
const message = messages[index];
|
|
36
|
+
if (message.role !== 'provider' ||
|
|
37
|
+
message.provider !== 'OPENAI_RESPONSES' ||
|
|
38
|
+
message.providerModelId !== modelId ||
|
|
39
|
+
message.item?.type !== 'configuration_update')
|
|
40
|
+
continue;
|
|
41
|
+
const reasoning = message.item.reasoning;
|
|
42
|
+
const effort = marAgentReasoningEffortSchema.safeParse(reasoning?.effort);
|
|
43
|
+
if (effort.success)
|
|
44
|
+
return effort.data;
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MarAgentModelConfiguration } from './configuration.js';
|
|
2
|
+
import type { ClientToolDefinition } from './contracts.js';
|
|
3
|
+
/** Native Responses discovery carries deferred definitions in history, not the top-level catalog. */
|
|
4
|
+
export declare function projectModelRequestTools(model: Pick<MarAgentModelConfiguration, 'protocol'>, tools: readonly ClientToolDefinition[], residentNames: ReadonlySet<string>): readonly ClientToolDefinition[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Native Responses discovery carries deferred definitions in history, not the top-level catalog. */
|
|
2
|
+
export function projectModelRequestTools(model, tools, residentNames) {
|
|
3
|
+
return model.protocol === 'OPENAI_RESPONSES'
|
|
4
|
+
? tools.filter((tool) => residentNames.has(tool.name))
|
|
5
|
+
: tools;
|
|
6
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { restoreNativeModelContext } from '../../model/native-context.js';
|
|
2
2
|
import { appliedInputRecord } from '../../session/deferred-input.js';
|
|
3
3
|
import { inputMetadataFromRecord } from '../../session/store/index.js';
|
|
4
4
|
import { contextGcTargetKey, latestValidContextGcCheckpoint } from '../../session/context-gc-checkpoint.js';
|
|
@@ -227,34 +227,8 @@ export function restoreModelContext(payload, providerModelId) {
|
|
|
227
227
|
? { inputMode: payload.inputMode }
|
|
228
228
|
: {})
|
|
229
229
|
};
|
|
230
|
-
if (payload.role === 'provider'
|
|
231
|
-
|
|
232
|
-
const modelId = modelIdFromPayload(payload, 'providerModelId');
|
|
233
|
-
return item && modelId
|
|
234
|
-
? {
|
|
235
|
-
role: 'provider',
|
|
236
|
-
provider: 'ANTHROPIC_MESSAGES',
|
|
237
|
-
providerModelId: modelId,
|
|
238
|
-
contextKind: 'private',
|
|
239
|
-
content: '',
|
|
240
|
-
item
|
|
241
|
-
}
|
|
242
|
-
: undefined;
|
|
243
|
-
}
|
|
244
|
-
if (payload.role === 'provider' &&
|
|
245
|
-
payload.provider === 'OPENAI_RESPONSES' &&
|
|
246
|
-
isRecord(payload.item)) {
|
|
247
|
-
const restoredProviderModelId = modelIdFromPayload(payload, 'providerModelId') ?? providerModelId;
|
|
248
|
-
return {
|
|
249
|
-
role: 'provider',
|
|
250
|
-
content: '',
|
|
251
|
-
provider: 'OPENAI_RESPONSES',
|
|
252
|
-
...(restoredProviderModelId === undefined
|
|
253
|
-
? {}
|
|
254
|
-
: { providerModelId: restoredProviderModelId }),
|
|
255
|
-
item: payload.item
|
|
256
|
-
};
|
|
257
|
-
}
|
|
230
|
+
if (payload.role === 'provider')
|
|
231
|
+
return restoreNativeModelContext(payload, providerModelId);
|
|
258
232
|
return undefined;
|
|
259
233
|
}
|
|
260
234
|
export function providerToolCallId(message) {
|
|
@@ -8,7 +8,6 @@ export interface AuthoritativeModelUsage {
|
|
|
8
8
|
}
|
|
9
9
|
export declare function latestModelUsage(records: readonly import('../../session/store/index.js').SessionRecord[], selectedModelId: string): AuthoritativeModelUsage | undefined;
|
|
10
10
|
export declare function reasoningEffortBaseline(records: readonly import('../../session/store/index.js').SessionRecord[], modelId: string): MarAgentReasoningEffort | undefined;
|
|
11
|
-
export declare function lastConfigurationEffort(messages: readonly ModelMessage[], modelId: string): MarAgentReasoningEffort | undefined;
|
|
12
11
|
export declare function shouldUseNativeCompaction(input: {
|
|
13
12
|
readonly estimatedRequestTokens: number;
|
|
14
13
|
readonly contextWindowTokens: number;
|
|
@@ -82,21 +82,6 @@ export function reasoningEffortBaseline(records, modelId) {
|
|
|
82
82
|
}
|
|
83
83
|
return baseline;
|
|
84
84
|
}
|
|
85
|
-
export function lastConfigurationEffort(messages, modelId) {
|
|
86
|
-
for (let index = messages.length - 1; index >= 0; index--) {
|
|
87
|
-
const message = messages[index];
|
|
88
|
-
if (message.role !== 'provider' ||
|
|
89
|
-
message.provider !== 'OPENAI_RESPONSES' ||
|
|
90
|
-
message.providerModelId !== modelId ||
|
|
91
|
-
message.item?.type !== 'configuration_update')
|
|
92
|
-
continue;
|
|
93
|
-
const reasoning = message.item.reasoning;
|
|
94
|
-
const effort = marAgentReasoningEffortSchema.safeParse(reasoning?.effort);
|
|
95
|
-
if (effort.success)
|
|
96
|
-
return effort.data;
|
|
97
|
-
}
|
|
98
|
-
return undefined;
|
|
99
|
-
}
|
|
100
85
|
export function shouldUseNativeCompaction(input) {
|
|
101
86
|
if (input.estimatedRequestTokens <= input.contextWindowTokens)
|
|
102
87
|
return true;
|
|
@@ -132,9 +132,7 @@ export class ExecutionLoop {
|
|
|
132
132
|
content: '',
|
|
133
133
|
provider: event.provider,
|
|
134
134
|
providerModelId: input.model.id,
|
|
135
|
-
...(event.
|
|
136
|
-
? { contextKind: 'private' }
|
|
137
|
-
: {}),
|
|
135
|
+
...(event.contextKind === undefined ? {} : { contextKind: event.contextKind }),
|
|
138
136
|
item: event.item
|
|
139
137
|
};
|
|
140
138
|
messages.push(message);
|
|
@@ -9,5 +9,10 @@ export declare function resolveAgentModels(configurations: readonly MarAgentMode
|
|
|
9
9
|
readonly credentialProviders: Set<ModelCredentialProvider>;
|
|
10
10
|
};
|
|
11
11
|
export declare function createModelTurnSession(adapter: ModelAdapter): ModelTurnSession;
|
|
12
|
+
/** Owns only one Execution's model turn and explicitly transferred adapters. */
|
|
13
|
+
export declare function createExecutionModelResources(activeAdapters: Set<ModelAdapter>): {
|
|
14
|
+
openTurn(adapter: ModelAdapter, ownsAdapter: boolean): ModelTurnSession;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
};
|
|
12
17
|
export declare function closeModelAdapters(adapters: Iterable<ModelAdapter>): Promise<void>;
|
|
13
18
|
export declare function addModelCredentialProviders(target: Set<ModelCredentialProvider>, configuration: MarAgentModelConfiguration): void;
|
|
@@ -51,6 +51,34 @@ export function createModelTurnSession(adapter) {
|
|
|
51
51
|
close: () => turn.close()
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
/** Owns only one Execution's model turn and explicitly transferred adapters. */
|
|
55
|
+
export function createExecutionModelResources(activeAdapters) {
|
|
56
|
+
let turn;
|
|
57
|
+
const ownedAdapters = new Set();
|
|
58
|
+
return {
|
|
59
|
+
openTurn(adapter, ownsAdapter) {
|
|
60
|
+
if (ownsAdapter) {
|
|
61
|
+
ownedAdapters.add(adapter);
|
|
62
|
+
activeAdapters.add(adapter);
|
|
63
|
+
}
|
|
64
|
+
turn = createModelTurnSession(adapter);
|
|
65
|
+
return turn;
|
|
66
|
+
},
|
|
67
|
+
async close() {
|
|
68
|
+
await turn?.close().catch(() => undefined);
|
|
69
|
+
try {
|
|
70
|
+
await closeModelAdapters(ownedAdapters);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Model cleanup must not replace the Execution result.
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
for (const adapter of ownedAdapters)
|
|
77
|
+
activeAdapters.delete(adapter);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
54
82
|
export async function closeModelAdapters(adapters) {
|
|
55
83
|
const results = await Promise.allSettled([...new Set(adapters)].flatMap((adapter) => adapter.close === undefined ? [] : [adapter.close()]));
|
|
56
84
|
const failure = results.find((result) => result.status === 'rejected');
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MarAgentModelConfiguration } from '../model/configuration.js';
|
|
2
|
+
import type { ClientToolDefinition, ModelMessage, ModelRequest } from '../model/contracts.js';
|
|
3
|
+
import { type ContextualWorldState } from '../runtime/context/world-state.js';
|
|
4
|
+
/** Assemble captured round values only. Admission, Hooks and publication belong to Session. */
|
|
5
|
+
export declare function prepareSessionModelRequest(candidate: ModelRequest, model: Pick<MarAgentModelConfiguration, 'protocol' | 'inputCapabilities'>, entries: ContextualWorldState['entries'], residentTools: readonly ClientToolDefinition[], autoPermission: boolean): ModelRequest;
|
|
6
|
+
/** The actual candidate and current Session view share the same side-effect-free projection. */
|
|
7
|
+
export declare function projectSessionRequestMessages(messages: readonly ModelMessage[], entries: ContextualWorldState['entries'], supportsImages: boolean, codeMode: boolean, autoPermission?: boolean): ModelMessage[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { projectModelRequestTools } from '../model/tool-declarations.js';
|
|
2
|
+
import { projectSmartCompactionMessage } from '../runtime/compaction/smart.js';
|
|
3
|
+
import { normalizeMessagesForModel } from '../runtime/context/normalize.js';
|
|
4
|
+
import { insertContextualWorldState } from '../runtime/context/world-state.js';
|
|
5
|
+
import { projectCodeModeSearchResult, projectCodeModeTools } from '../tools/code-mode/index.js';
|
|
6
|
+
import { projectPermissionTool } from '../tools/permissions.js';
|
|
7
|
+
/** Assemble captured round values only. Admission, Hooks and publication belong to Session. */
|
|
8
|
+
export function prepareSessionModelRequest(candidate, model, entries, residentTools, autoPermission) {
|
|
9
|
+
const codeMode = candidate.tools.some((tool) => tool.name === 'code_exec');
|
|
10
|
+
return {
|
|
11
|
+
...candidate,
|
|
12
|
+
messages: projectSessionRequestMessages(candidate.messages, entries, model.inputCapabilities.includes('IMAGE'), codeMode, autoPermission),
|
|
13
|
+
tools: projectModelRequestTools(model, projectCodeModeTools(candidate.tools, residentTools), new Set(residentTools.map((tool) => tool.name)))
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** The actual candidate and current Session view share the same side-effect-free projection. */
|
|
17
|
+
export function projectSessionRequestMessages(messages, entries, supportsImages, codeMode, autoPermission = false) {
|
|
18
|
+
return normalizeMessagesForModel(insertContextualWorldState(messages, entries), {
|
|
19
|
+
supportsImages
|
|
20
|
+
}).map((message) => projectCodeModeSearchResult(autoPermission && message.toolSearchTools
|
|
21
|
+
? { ...message, toolSearchTools: message.toolSearchTools.map(projectPermissionTool) }
|
|
22
|
+
: projectSmartCompactionMessage(message), codeMode));
|
|
23
|
+
}
|
|
@@ -7,7 +7,7 @@ import { ExtensionRequestSnapshots } from '../extensions/model-request.js';
|
|
|
7
7
|
import { SessionInputCoordinator, type CoreSessionBackend } from '../extensions/session-input.js';
|
|
8
8
|
import type { CoreAgentsBackend } from '../extensions/agents.js';
|
|
9
9
|
import type { HostDescription, MarAgentHost } from '../host/contracts.js';
|
|
10
|
-
import {
|
|
10
|
+
import type { MarAgentReasoningEffort } from '../model/configuration.js';
|
|
11
11
|
import type { ModelAdapter, ModelMessage } from '../model/contracts.js';
|
|
12
12
|
import { CompactRequests } from '../runtime/compaction/requests.js';
|
|
13
13
|
import { JsonlSessionStore } from '../session/store/index.js';
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { restoreMessages } from '../runtime/context/restore.js';
|
|
2
2
|
import { createNativeSteer } from './native-steer.js';
|
|
3
|
-
import {
|
|
3
|
+
import { latestModelUsage, reasoningEffortBaseline } from '../runtime/context/usage.js';
|
|
4
4
|
import { splitContextualPrompt } from '../runtime/context/contextual-blocks.js';
|
|
5
|
-
import { contextualInstructionInsertIndex,
|
|
5
|
+
import { contextualInstructionInsertIndex, latestContextualWorldStateGeneration, parsePersistedContextualWorldState, persistContextualWorldState, resetContextualWorldState, updateContextualWorldState, updatePromptWorldState } from '../runtime/context/world-state.js';
|
|
6
6
|
import { eventForPersistence, publicModelUsage } from '../runtime/event-projection.js';
|
|
7
7
|
import { ExecutionLoop } from '../runtime/execution.js';
|
|
8
|
-
import { closeModelAdapters, createModelTurnSession } from './model-runtime.js';
|
|
8
|
+
import { closeModelAdapters, createExecutionModelResources, createModelTurnSession } from './model-runtime.js';
|
|
9
|
+
import { prepareSessionModelRequest, projectSessionRequestMessages } from './request-preparation.js';
|
|
9
10
|
import { createSubagentBackend } from './subagent-backend.js';
|
|
10
11
|
import { ExecutionToolPermissions, projectPermissionTool, resolvePermissionMode, withToolPermissions } from '../tools/permissions.js';
|
|
11
12
|
import { createToolWaitInterrupt } from '../tools/wait.js';
|
|
@@ -24,7 +25,7 @@ import { createExtensionAgentsBackend } from './extension-agents.js';
|
|
|
24
25
|
import { coreMcpCatalog } from '../extensions/mcp.js';
|
|
25
26
|
import { isDeepStrictEqual } from 'node:util';
|
|
26
27
|
import { MarAgentError, describeMarAgentError } from '../error.js';
|
|
27
|
-
import {
|
|
28
|
+
import { prepareModelConfiguration } from '../model/request-configuration.js';
|
|
28
29
|
import { autoPermissionPrompt } from '../prompts/permissions.js';
|
|
29
30
|
import { MAR_AGENT_PROMPT_VERSION, buildSystemPromptSections } from '../prompts/index.js';
|
|
30
31
|
import { renderPromptSections } from '../extensions/prompt-composition.js';
|
|
@@ -43,12 +44,11 @@ import { ContextGcRuntime } from '../runtime/context/gc-runtime.js';
|
|
|
43
44
|
import { AGENT_EXECUTION_POLICY } from '../runtime/execution-policy.js';
|
|
44
45
|
import { loadAgentInstructions, renderAgentInstructions } from '../runtime/context/instructions.js';
|
|
45
46
|
import { normalizeMessagesForModel } from '../runtime/context/normalize.js';
|
|
46
|
-
import { latestSmartContextTokens,
|
|
47
|
+
import { latestSmartContextTokens, requestSmartCompaction } from '../runtime/compaction/smart.js';
|
|
47
48
|
import { compactSummaryFromCheckpoint, inputMetadataFromRecord } from '../session/store/index.js';
|
|
48
49
|
import { SubagentSessionController } from '../subagent/session-controller.js';
|
|
49
50
|
import { agentStartToolDefinitionWithModels } from '../tools/agent/agent-start.js';
|
|
50
51
|
import { allowsDirectTool, allowsToolCaller, toolCallers } from '../tools/callers.js';
|
|
51
|
-
import { projectCodeModeSearchResult, projectCodeModeTools } from '../tools/code-mode/index.js';
|
|
52
52
|
import { assertMcpToolCatalog } from '../tools/mcp/catalog.js';
|
|
53
53
|
import { BUILTIN_TOOL_DEFINITIONS } from '../tools/registry.js';
|
|
54
54
|
import { createSessionToolScheduler } from '../tools/scheduler.js';
|
|
@@ -362,10 +362,9 @@ export function createSessionOpener(services) {
|
|
|
362
362
|
let finalAnswer = '';
|
|
363
363
|
let executionLoop;
|
|
364
364
|
let executionToolSources;
|
|
365
|
-
let selectedTurn;
|
|
366
365
|
const contextGc = new ContextGcRuntime();
|
|
367
366
|
let selectedAdapter;
|
|
368
|
-
const
|
|
367
|
+
const modelResources = createExecutionModelResources(activeExecutionAdapters);
|
|
369
368
|
const subagents = sessionSource.type === 'user' ? sessionRuntime.subagents : undefined;
|
|
370
369
|
try {
|
|
371
370
|
controller.signal.throwIfAborted();
|
|
@@ -767,28 +766,11 @@ export function createSessionOpener(services) {
|
|
|
767
766
|
});
|
|
768
767
|
selectedAdapter = sessionAdapter(input.modelId ?? executionDefaultModelId, executionModels);
|
|
769
768
|
const selectedModel = executionModels.get(input.modelId ?? executionDefaultModelId);
|
|
770
|
-
|
|
771
|
-
executionScopedAdapters.add(selectedAdapter);
|
|
772
|
-
activeExecutionAdapters.add(selectedAdapter);
|
|
773
|
-
}
|
|
774
|
-
const selected = createModelTurnSession(selectedAdapter);
|
|
775
|
-
selectedTurn = selected;
|
|
769
|
+
const selected = modelResources.openTurn(selectedAdapter, services.hasCustomAdapters && selectedAdapter.createTurnSession === undefined);
|
|
776
770
|
let lastServerUsage = latestModelUsage(contextRecords, selectedModel.id);
|
|
777
771
|
let smartContextTokens = latestSmartContextTokens(contextRecords, selectedModel.id, selectedModel.contextWindowTokens);
|
|
778
772
|
const compactUserTokenLimit = Math.min(20_000, Math.floor(selectedModel.contextWindowTokens / 8));
|
|
779
773
|
const reasoningEffort = input.reasoningEffort ?? selectedModel.defaultReasoningEffort;
|
|
780
|
-
const useEffortUpdates = usesResponsesConfigurationUpdates(selectedModel);
|
|
781
|
-
const previousReasoningEffort = useEffortUpdates
|
|
782
|
-
? reasoningEffortBaseline(contextRecords, selectedModel.id)
|
|
783
|
-
: undefined;
|
|
784
|
-
let requestReasoningEffort = useEffortUpdates
|
|
785
|
-
? (previousReasoningEffort ?? reasoningEffort)
|
|
786
|
-
: undefined;
|
|
787
|
-
let effectiveReasoningEffort = useEffortUpdates
|
|
788
|
-
? previousReasoningEffort === undefined
|
|
789
|
-
? requestReasoningEffort
|
|
790
|
-
: (lastConfigurationEffort(messages, selectedModel.id) ?? requestReasoningEffort)
|
|
791
|
-
: undefined;
|
|
792
774
|
if (mode !== 'compact' && subagents)
|
|
793
775
|
await subagents.beginParentExecution({
|
|
794
776
|
executionId,
|
|
@@ -1310,25 +1292,21 @@ export function createSessionOpener(services) {
|
|
|
1310
1292
|
diagnose: () => coreExtensions.diagnose({ code: 'MAR_AGENT_STEER_POST_COMMIT_FAILED', sessionId })
|
|
1311
1293
|
});
|
|
1312
1294
|
}
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
turnId
|
|
1329
|
-
});
|
|
1330
|
-
effectiveReasoningEffort = reasoningEffort;
|
|
1331
|
-
}
|
|
1295
|
+
const modelConfiguration = prepareModelConfiguration(selectedModel, reasoningEffort, {
|
|
1296
|
+
baselineEffort: reasoningEffortBaseline(contextRecords, selectedModel.id),
|
|
1297
|
+
messages
|
|
1298
|
+
});
|
|
1299
|
+
let requestReasoningEffort = modelConfiguration.requestReasoningEffort;
|
|
1300
|
+
if (mode !== 'compact')
|
|
1301
|
+
for (const update of modelConfiguration.updates) {
|
|
1302
|
+
messages.push(update);
|
|
1303
|
+
await store.append(sessionId, {
|
|
1304
|
+
type: 'model.context',
|
|
1305
|
+
payload: update,
|
|
1306
|
+
executionId,
|
|
1307
|
+
turnId
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1332
1310
|
const runPreparedExecution = async (compactFocus = input.prompt, compactSignal = controller.signal) => {
|
|
1333
1311
|
const initialSystemPrompt = mode === 'compact'
|
|
1334
1312
|
? buildExecutionSystemPrompt(executionTools, 'run')
|
|
@@ -1403,8 +1381,9 @@ export function createSessionOpener(services) {
|
|
|
1403
1381
|
lastServerContextTokens = undefined;
|
|
1404
1382
|
lastServerUsage = undefined;
|
|
1405
1383
|
smartContextTokens = undefined;
|
|
1406
|
-
requestReasoningEffort = reasoningEffort
|
|
1407
|
-
|
|
1384
|
+
requestReasoningEffort = prepareModelConfiguration(selectedModel, reasoningEffort, {
|
|
1385
|
+
checkpointAdopted: true
|
|
1386
|
+
}).requestReasoningEffort;
|
|
1408
1387
|
};
|
|
1409
1388
|
const compactLeaf = async (input, signal, prepare, compactionId) => {
|
|
1410
1389
|
if (messages.length < 2)
|
|
@@ -1688,37 +1667,27 @@ export function createSessionOpener(services) {
|
|
|
1688
1667
|
executionEnvironment = { ...currentEnvironment, ...currentLocalTimeContext() };
|
|
1689
1668
|
await modelContext.recordEnvironment();
|
|
1690
1669
|
const { roundTools, roundBindings, toolScope, composeSystemPrompt } = captureRoundToolScope();
|
|
1691
|
-
const codeModeEnabled = roundTools.some((tool) => tool.name === 'code_exec');
|
|
1692
1670
|
const residentTools = projectTools(mcpRegistry.projectDirect(baseTools()));
|
|
1693
|
-
const requestTools = (() => {
|
|
1694
|
-
if (selectedModel.protocol !== 'OPENAI_RESPONSES')
|
|
1695
|
-
return projectCodeModeTools(roundTools, residentTools);
|
|
1696
|
-
const directNames = new Set(residentTools.map((tool) => tool.name));
|
|
1697
|
-
// Discovery and caller policy are independent: keep nested declarations for active tools.
|
|
1698
|
-
return projectCodeModeTools(roundTools, residentTools).filter((tool) => directNames.has(tool.name));
|
|
1699
|
-
})();
|
|
1700
1671
|
const requestContextMessages = pendingOutputContinuation === undefined
|
|
1701
1672
|
? messages
|
|
1702
1673
|
: [...messages, pendingOutputContinuation];
|
|
1703
1674
|
sources.bind(toolScope);
|
|
1704
1675
|
const composedSystem = splitContextualPrompt(await composeSystemPrompt());
|
|
1705
1676
|
const candidateWorld = updatePromptWorldState(modelContext.worldState, messages.length, composedSystem.parts);
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
const candidateRequest = {
|
|
1709
|
-
system: systemPrompt,
|
|
1677
|
+
const candidateRequest = prepareSessionModelRequest({
|
|
1678
|
+
system: composedSystem.system,
|
|
1710
1679
|
...(composedSystem.systemBlocks
|
|
1711
1680
|
? { systemBlocks: composedSystem.systemBlocks }
|
|
1712
1681
|
: {}),
|
|
1713
|
-
messages:
|
|
1714
|
-
tools:
|
|
1682
|
+
messages: requestContextMessages,
|
|
1683
|
+
tools: roundTools,
|
|
1715
1684
|
promptCacheKey: sessionId,
|
|
1716
1685
|
reasoningEffort,
|
|
1717
1686
|
...(requestReasoningEffort === undefined ? {} : { requestReasoningEffort }),
|
|
1718
1687
|
...(modelInputImages?.length ? { images: modelInputImages } : {}),
|
|
1719
1688
|
onAttemptDiagnostic: recordModelAttempt('EXECUTION')
|
|
1720
|
-
};
|
|
1721
|
-
preparingRequestMessages =
|
|
1689
|
+
}, selectedModel, candidateWorld.entries, residentTools, permissionPolicy.mode === 'auto');
|
|
1690
|
+
preparingRequestMessages = candidateRequest.messages;
|
|
1722
1691
|
preparingRequestBaseLength = messages.length;
|
|
1723
1692
|
let request;
|
|
1724
1693
|
try {
|
|
@@ -1803,8 +1772,7 @@ export function createSessionOpener(services) {
|
|
|
1803
1772
|
modelId: selectedModel.id,
|
|
1804
1773
|
contextWindowTokens: selectedModel.contextWindowTokens,
|
|
1805
1774
|
usage: latestUsage,
|
|
1806
|
-
|
|
1807
|
-
responsesConfigurationUpdates: usesResponsesConfigurationUpdates(selectedModel),
|
|
1775
|
+
...modelConfiguration.contextProjection,
|
|
1808
1776
|
workspace: logicalWorkspace,
|
|
1809
1777
|
platform: description.platform,
|
|
1810
1778
|
getActiveProcessIds: async () => {
|
|
@@ -1894,6 +1862,7 @@ export function createSessionOpener(services) {
|
|
|
1894
1862
|
};
|
|
1895
1863
|
}
|
|
1896
1864
|
finally {
|
|
1865
|
+
// Revoke this Execution's request and input bindings, not Session warm resources.
|
|
1897
1866
|
delete executionContext.requestMessages;
|
|
1898
1867
|
compactRequests.close(new MarAgentError('MAR_AGENT_CANCELLED', 'Execution ended.'));
|
|
1899
1868
|
if (executionContext.compactRequests === compactRequests)
|
|
@@ -1905,18 +1874,10 @@ export function createSessionOpener(services) {
|
|
|
1905
1874
|
if (executionContext.toolSources === executionToolSources)
|
|
1906
1875
|
delete executionContext.toolSources;
|
|
1907
1876
|
internal.signal?.removeEventListener('abort', abortSource);
|
|
1877
|
+
// Compact retains its existing owner, waiting and error propagation.
|
|
1908
1878
|
await compactCoordinator.close(controller.signal.reason ?? new MarAgentError('MAR_AGENT_CANCELLED', 'Execution ended.'));
|
|
1909
|
-
await
|
|
1910
|
-
|
|
1911
|
-
await closeModelAdapters(executionScopedAdapters);
|
|
1912
|
-
}
|
|
1913
|
-
catch {
|
|
1914
|
-
// Execution cleanup is best effort.
|
|
1915
|
-
}
|
|
1916
|
-
finally {
|
|
1917
|
-
for (const adapter of executionScopedAdapters)
|
|
1918
|
-
activeExecutionAdapters.delete(adapter);
|
|
1919
|
-
}
|
|
1879
|
+
await modelResources.close();
|
|
1880
|
+
// Ending the parent Execution does not destroy Session-owned child tasks.
|
|
1920
1881
|
subagents?.endParentExecution(executionId);
|
|
1921
1882
|
try {
|
|
1922
1883
|
await releaseSession?.();
|
|
@@ -1927,6 +1888,7 @@ export function createSessionOpener(services) {
|
|
|
1927
1888
|
throw error;
|
|
1928
1889
|
}
|
|
1929
1890
|
finally {
|
|
1891
|
+
// Writer release cannot skip owner-safe deactivation; the event stream closes last.
|
|
1930
1892
|
if (sessionRuntime.execution === executionContext)
|
|
1931
1893
|
delete sessionRuntime.execution;
|
|
1932
1894
|
active.delete(`${sessionId}:${executionId}`);
|
|
@@ -2262,14 +2224,6 @@ function modelAttemptFailureDiagnostic(diagnostic, summary) {
|
|
|
2262
2224
|
message: `${prefix}${[...diagnostic.message].slice(0, availableCharacters).join('')}`
|
|
2263
2225
|
};
|
|
2264
2226
|
}
|
|
2265
|
-
/** Shared, side-effect-free projection for the real request and current Session request view. */
|
|
2266
|
-
function projectSessionRequestMessages(messages, entries, supportsImages, codeMode, autoPermission = false) {
|
|
2267
|
-
return normalizeMessagesForModel(insertContextualWorldState(messages, entries), {
|
|
2268
|
-
supportsImages
|
|
2269
|
-
}).map((message) => projectCodeModeSearchResult(autoPermission && message.toolSearchTools
|
|
2270
|
-
? { ...message, toolSearchTools: message.toolSearchTools.map(projectPermissionTool) }
|
|
2271
|
-
: projectSmartCompactionMessage(message), codeMode));
|
|
2272
|
-
}
|
|
2273
2227
|
function projectAppendedModelMessage(input) {
|
|
2274
2228
|
if (input.visibility === 'transcript')
|
|
2275
2229
|
return undefined;
|