@myagentroam/agent 0.9.159 → 0.9.160
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/agents.d.ts +69 -0
- package/dist/agent-core/extensions/agents.js +160 -0
- package/dist/agent-core/extensions/contracts.d.ts +260 -0
- package/dist/agent-core/extensions/contracts.js +1 -0
- package/dist/agent-core/extensions/data.d.ts +84 -0
- package/dist/agent-core/extensions/data.js +83 -0
- package/dist/agent-core/extensions/environment.d.ts +27 -0
- package/dist/agent-core/extensions/environment.js +52 -0
- package/dist/agent-core/extensions/files.d.ts +64 -0
- package/dist/agent-core/extensions/files.js +26 -0
- package/dist/agent-core/extensions/hooks.d.ts +32 -0
- package/dist/agent-core/extensions/hooks.js +135 -0
- package/dist/agent-core/extensions/manager.d.ts +39 -0
- package/dist/agent-core/extensions/manager.js +458 -0
- package/dist/agent-core/extensions/mcp.d.ts +99 -0
- package/dist/agent-core/extensions/mcp.js +433 -0
- package/dist/agent-core/extensions/model-request.d.ts +60 -0
- package/dist/agent-core/extensions/model-request.js +167 -0
- package/dist/agent-core/extensions/model-stream.d.ts +9 -0
- package/dist/agent-core/extensions/model-stream.js +101 -0
- package/dist/agent-core/extensions/models.d.ts +43 -0
- package/dist/agent-core/extensions/models.js +1 -0
- package/dist/agent-core/extensions/network.d.ts +32 -0
- package/dist/agent-core/extensions/network.js +97 -0
- package/dist/agent-core/extensions/operation.d.ts +29 -0
- package/dist/agent-core/extensions/operation.js +98 -0
- package/dist/agent-core/extensions/processes.d.ts +52 -0
- package/dist/agent-core/extensions/processes.js +283 -0
- package/dist/agent-core/extensions/prompt-composition.d.ts +24 -0
- package/dist/agent-core/extensions/prompt-composition.js +106 -0
- package/dist/agent-core/extensions/prompt-input.d.ts +23 -0
- package/dist/agent-core/extensions/prompt-input.js +46 -0
- package/dist/agent-core/extensions/resources.d.ts +27 -0
- package/dist/agent-core/extensions/resources.js +221 -0
- package/dist/agent-core/extensions/services.d.ts +31 -0
- package/dist/agent-core/extensions/services.js +61 -0
- package/dist/agent-core/extensions/session-input.d.ts +151 -0
- package/dist/agent-core/extensions/session-input.js +351 -0
- package/dist/agent-core/extensions/session-messages.d.ts +41 -0
- package/dist/agent-core/extensions/session-messages.js +76 -0
- package/dist/agent-core/extensions/session.d.ts +68 -0
- package/dist/agent-core/extensions/session.js +593 -0
- package/dist/agent-core/extensions/settings.d.ts +59 -0
- package/dist/agent-core/extensions/settings.js +115 -0
- package/dist/agent-core/extensions/store.d.ts +10 -0
- package/dist/agent-core/extensions/store.js +131 -0
- package/dist/agent-core/extensions/tools.d.ts +61 -0
- package/dist/agent-core/extensions/tools.js +266 -0
- package/dist/agent-core/host/contracts.d.ts +25 -0
- package/dist/agent-core/host/local-agent-host.d.ts +10 -1
- package/dist/agent-core/host/local-agent-host.js +132 -20
- package/dist/agent-core/host/local-file-access.d.ts +30 -0
- package/dist/agent-core/host/local-file-access.js +107 -0
- package/dist/agent-core/host/local-network-access.d.ts +6 -0
- package/dist/agent-core/host/local-network-access.js +97 -0
- package/dist/agent-core/host/local-process-executor.d.ts +5 -1
- package/dist/agent-core/host/local-session-environment.d.ts +18 -0
- package/dist/agent-core/host/local-session-environment.js +102 -0
- package/dist/agent-core/model/anthropic-messages.js +73 -23
- package/dist/agent-core/model/contracts.d.ts +12 -0
- package/dist/agent-core/model/openai-responses.js +73 -12
- package/dist/agent-core/model/text-blocks.d.ts +7 -0
- package/dist/agent-core/model/text-blocks.js +40 -0
- package/dist/agent-core/prompts/index.d.ts +6 -2
- package/dist/agent-core/prompts/index.js +38 -24
- package/dist/agent-core/runtime/context/gc-tokens.js +6 -1
- package/dist/agent-core/runtime/context/normalize.js +21 -1
- package/dist/agent-core/runtime/context/projection.js +35 -1
- package/dist/agent-core/runtime/context/request-budget.js +5 -2
- package/dist/agent-core/runtime/context/restore.d.ts +5 -0
- package/dist/agent-core/runtime/context/restore.js +47 -4
- package/dist/agent-core/runtime/context/usage.js +2 -3
- package/dist/agent-core/runtime/contracts.d.ts +2 -0
- package/dist/agent-core/runtime/execution.js +5 -2
- package/dist/agent-core/sdk/agent.js +177 -40
- package/dist/agent-core/sdk/extension-agents.d.ts +9 -0
- package/dist/agent-core/sdk/extension-agents.js +51 -0
- package/dist/agent-core/sdk/extension-models.d.ts +13 -0
- package/dist/agent-core/sdk/extension-models.js +128 -0
- package/dist/agent-core/sdk/extension-session.d.ts +30 -0
- package/dist/agent-core/sdk/extension-session.js +103 -0
- package/dist/agent-core/sdk/extension-tools.d.ts +16 -0
- package/dist/agent-core/sdk/extension-tools.js +126 -0
- package/dist/agent-core/sdk/session.d.ts +26 -2
- package/dist/agent-core/sdk/session.js +1215 -506
- package/dist/agent-core/sdk/types.d.ts +3 -0
- package/dist/agent-core/session/context-gc-checkpoint.js +1 -1
- package/dist/agent-core/session/jsonl-store.d.ts +28 -8
- package/dist/agent-core/session/jsonl-store.js +124 -84
- package/dist/agent-core/session/types.d.ts +4 -1
- package/dist/agent-core/storage/file-lock.d.ts +4 -0
- package/dist/agent-core/storage/file-lock.js +83 -0
- package/dist/agent-core/subagent/contracts.d.ts +11 -1
- package/dist/agent-core/subagent/scheduler.d.ts +8 -0
- package/dist/agent-core/subagent/session-controller.d.ts +22 -1
- package/dist/agent-core/subagent/session-controller.js +355 -98
- package/dist/agent-core/tools/agent/agent-start.d.ts +1 -1
- package/dist/agent-core/tools/code-mode/cells.js +5 -15
- package/dist/agent-core/tools/code-mode/dispatch.d.ts +1 -0
- package/dist/agent-core/tools/code-mode/dispatch.js +13 -1
- package/dist/agent-core/tools/code-mode/index.js +1 -2
- package/dist/agent-core/tools/code-mode/observations.d.ts +5 -0
- package/dist/agent-core/tools/code-mode/observations.js +16 -5
- package/dist/agent-core/tools/code-mode/quickjs-engine.js +10 -5
- package/dist/agent-core/tools/execution.d.ts +11 -2
- package/dist/agent-core/tools/execution.js +58 -21
- package/dist/agent-core/tools/input.d.ts +2 -0
- package/dist/agent-core/tools/input.js +36 -0
- package/dist/agent-core/tools/local/apply-patch.js +21 -17
- package/dist/agent-core/tools/local/exec.d.ts +4 -4
- package/dist/agent-core/tools/local/exec.js +234 -62
- package/dist/agent-core/tools/local/registry.d.ts +6 -0
- package/dist/agent-core/tools/local/registry.js +60 -9
- package/dist/agent-core/tools/mcp/catalog.d.ts +6 -2
- package/dist/agent-core/tools/mcp/catalog.js +4 -4
- package/dist/agent-core/tools/mcp/history.js +2 -2
- package/dist/agent-core/tools/mcp/tool-search.d.ts +3 -1
- package/dist/agent-core/tools/mcp/tool-search.js +2 -2
- package/dist/agent-core/tools/output-projection.d.ts +3 -1
- package/dist/agent-core/tools/output-projection.js +11 -2
- package/dist/agent-core/tools/runtime-context.d.ts +1 -0
- package/dist/agent-core/tools/runtime.d.ts +3 -1
- package/dist/agent-core/tools/runtime.js +22 -7
- package/dist/agent-core/tools/scheduler.d.ts +2 -0
- package/dist/agent-core/tools/scheduler.js +43 -6
- package/dist/index.d.ts +21 -0
- package/dist/sandbox/linux/bubblewrap-sandbox-executor.js +5 -2
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import { resolveModelDefaultReasoningEffort } from './configuration.js';
|
|
|
5
5
|
import { isRetryableUpstreamOverloadCode, number, parseSse, record, text, observeModelStreamEvent, modelStreamEventObservedAt } from './sse.js';
|
|
6
6
|
import { fetchModelResponse, modelRetryMaxAttempts, isRetryableModelRequestError, isRetryableModelTransportError, waitForModelRetry } from './http.js';
|
|
7
7
|
import { anthropicThinkingBlock, assertAnthropicThinkingBudget } from './anthropic-thinking.js';
|
|
8
|
+
import { resolveModelTextBlocks } from './text-blocks.js';
|
|
8
9
|
export class AnthropicMessagesAdapter {
|
|
9
10
|
configuration;
|
|
10
11
|
constructor(configuration) {
|
|
@@ -74,20 +75,25 @@ export class AnthropicMessagesAdapter {
|
|
|
74
75
|
},
|
|
75
76
|
body: JSON.stringify({
|
|
76
77
|
model: this.configuration.modelId,
|
|
77
|
-
system:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
system: request.systemBlocks !== undefined
|
|
79
|
+
? anthropicTextBlocks(request.system, request.systemBlocks)
|
|
80
|
+
: request.system
|
|
81
|
+
? [
|
|
82
|
+
{
|
|
83
|
+
type: 'text',
|
|
84
|
+
text: request.system,
|
|
85
|
+
cache_control: { type: 'ephemeral' }
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
: [],
|
|
89
|
+
messages: anthropicMessages(request.messages, request.images, request.tools, this.configuration.id, request.systemBlocks === undefined &&
|
|
90
|
+
request.messages.every((message) => message.textBlocks === undefined), request.cachePrefixMessages),
|
|
85
91
|
tools,
|
|
86
92
|
...(request.toolChoice === undefined
|
|
87
93
|
? {}
|
|
88
94
|
: { tool_choice: { type: request.toolChoice } }),
|
|
89
95
|
stream: true,
|
|
90
|
-
max_tokens: this.configuration.maxOutputTokens,
|
|
96
|
+
max_tokens: Math.min(request.outputLimit ?? this.configuration.maxOutputTokens, this.configuration.maxOutputTokens),
|
|
91
97
|
output_config: {
|
|
92
98
|
effort: request.reasoningEffort?.trim() ||
|
|
93
99
|
resolveModelDefaultReasoningEffort(this.configuration)
|
|
@@ -452,12 +458,20 @@ function boundedError(value, maximum) {
|
|
|
452
458
|
return undefined;
|
|
453
459
|
return [...normalized].slice(0, maximum).join('');
|
|
454
460
|
}
|
|
455
|
-
function anthropicMessages(messages, images, tools = [], modelId) {
|
|
461
|
+
function anthropicMessages(messages, images, tools = [], modelId, automaticCache = true, cachePrefixMessages) {
|
|
462
|
+
if (cachePrefixMessages !== undefined &&
|
|
463
|
+
(!Number.isSafeInteger(cachePrefixMessages) ||
|
|
464
|
+
cachePrefixMessages < 0 ||
|
|
465
|
+
cachePrefixMessages > messages.length))
|
|
466
|
+
throw new MarAgentError('MAR_AGENT_MODEL_REQUEST_INVALID', 'The captured cache prefix is invalid.');
|
|
456
467
|
const imageMessage = messages.findLastIndex((message) => message.role === 'user');
|
|
457
468
|
const toolDefinitions = new Map(tools.map((tool) => [tool.name, tool]));
|
|
458
469
|
const result = [];
|
|
459
470
|
let thinkingBytes = 0;
|
|
460
471
|
for (const [index, message] of messages.entries()) {
|
|
472
|
+
if (index === cachePrefixMessages)
|
|
473
|
+
for (const prior of result.slice(-2))
|
|
474
|
+
prior.content = withCacheBreakpoint(prior.content);
|
|
461
475
|
const userImages = message.role === 'user'
|
|
462
476
|
? uniqueModelImages(message.images, index === imageMessage ? images : undefined)
|
|
463
477
|
: [];
|
|
@@ -494,6 +508,7 @@ function anthropicMessages(messages, images, tools = [], modelId) {
|
|
|
494
508
|
const block = {
|
|
495
509
|
type: 'tool_result',
|
|
496
510
|
tool_use_id: message.callId,
|
|
511
|
+
...(message.isError === undefined ? {} : { is_error: message.isError }),
|
|
497
512
|
content: observationModelParts(message)?.map((part) => part.type === 'text'
|
|
498
513
|
? { type: 'text', text: part.text }
|
|
499
514
|
: {
|
|
@@ -504,10 +519,10 @@ function anthropicMessages(messages, images, tools = [], modelId) {
|
|
|
504
519
|
data: part.image.dataBase64
|
|
505
520
|
}
|
|
506
521
|
}) ??
|
|
507
|
-
(message.
|
|
522
|
+
(message.textBlocks !== undefined
|
|
508
523
|
? [
|
|
509
|
-
|
|
510
|
-
...message.images.map((image) => ({
|
|
524
|
+
...anthropicTextBlocks(message.content, message.textBlocks),
|
|
525
|
+
...(message.images ?? []).map((image) => ({
|
|
511
526
|
type: 'image',
|
|
512
527
|
source: {
|
|
513
528
|
type: 'base64',
|
|
@@ -516,7 +531,19 @@ function anthropicMessages(messages, images, tools = [], modelId) {
|
|
|
516
531
|
}
|
|
517
532
|
}))
|
|
518
533
|
]
|
|
519
|
-
: message.
|
|
534
|
+
: message.images?.length
|
|
535
|
+
? [
|
|
536
|
+
{ type: 'text', text: message.content },
|
|
537
|
+
...message.images.map((image) => ({
|
|
538
|
+
type: 'image',
|
|
539
|
+
source: {
|
|
540
|
+
type: 'base64',
|
|
541
|
+
media_type: image.mimeType,
|
|
542
|
+
data: image.dataBase64
|
|
543
|
+
}
|
|
544
|
+
}))
|
|
545
|
+
]
|
|
546
|
+
: message.content)
|
|
520
547
|
};
|
|
521
548
|
const previous = result.at(-1);
|
|
522
549
|
if (previous?.role === 'user' && Array.isArray(previous.content))
|
|
@@ -526,19 +553,21 @@ function anthropicMessages(messages, images, tools = [], modelId) {
|
|
|
526
553
|
continue;
|
|
527
554
|
}
|
|
528
555
|
if (message.role === 'assistant') {
|
|
529
|
-
if (!message.content)
|
|
556
|
+
if (!message.content && message.textBlocks === undefined)
|
|
530
557
|
continue;
|
|
531
|
-
const
|
|
558
|
+
const blocks = message.textBlocks !== undefined
|
|
559
|
+
? anthropicTextBlocks(message.content, message.textBlocks)
|
|
560
|
+
: [{ type: 'text', text: message.content }];
|
|
532
561
|
const previous = result.at(-1);
|
|
533
562
|
if (previous?.role === 'assistant' && Array.isArray(previous.content))
|
|
534
|
-
previous.content.push(
|
|
563
|
+
previous.content.push(...blocks);
|
|
535
564
|
else
|
|
536
|
-
result.push({ role: 'assistant', content:
|
|
565
|
+
result.push({ role: 'assistant', content: blocks });
|
|
537
566
|
continue;
|
|
538
567
|
}
|
|
539
568
|
result.push({
|
|
540
569
|
role: message.role,
|
|
541
|
-
content:
|
|
570
|
+
content: message.textBlocks !== undefined
|
|
542
571
|
? [
|
|
543
572
|
...userImages.map((image) => ({
|
|
544
573
|
type: 'image',
|
|
@@ -548,15 +577,36 @@ function anthropicMessages(messages, images, tools = [], modelId) {
|
|
|
548
577
|
data: image.dataBase64
|
|
549
578
|
}
|
|
550
579
|
})),
|
|
551
|
-
|
|
580
|
+
...anthropicTextBlocks(message.content, message.textBlocks)
|
|
552
581
|
]
|
|
553
|
-
:
|
|
582
|
+
: userImages.length > 0
|
|
583
|
+
? [
|
|
584
|
+
...userImages.map((image) => ({
|
|
585
|
+
type: 'image',
|
|
586
|
+
source: {
|
|
587
|
+
type: 'base64',
|
|
588
|
+
media_type: image.mimeType,
|
|
589
|
+
data: image.dataBase64
|
|
590
|
+
}
|
|
591
|
+
})),
|
|
592
|
+
{ type: 'text', text: message.content }
|
|
593
|
+
]
|
|
594
|
+
: message.content
|
|
554
595
|
});
|
|
555
596
|
}
|
|
556
|
-
|
|
557
|
-
|
|
597
|
+
if (cachePrefixMessages === messages.length ||
|
|
598
|
+
(cachePrefixMessages === undefined && automaticCache))
|
|
599
|
+
for (const message of result.slice(-2))
|
|
600
|
+
message.content = withCacheBreakpoint(message.content);
|
|
558
601
|
return result;
|
|
559
602
|
}
|
|
603
|
+
function anthropicTextBlocks(text, blocks) {
|
|
604
|
+
return resolveModelTextBlocks(text, blocks).map((block) => ({
|
|
605
|
+
type: 'text',
|
|
606
|
+
text: block.text,
|
|
607
|
+
...(block.cache ? { cache_control: { type: 'ephemeral' } } : {})
|
|
608
|
+
}));
|
|
609
|
+
}
|
|
560
610
|
function uniqueModelImages(...groups) {
|
|
561
611
|
const seen = new Set();
|
|
562
612
|
return groups.flatMap((group) => (group ?? []).flatMap((image) => {
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { ClientToolDefinition } from '../tools/contracts.js';
|
|
2
2
|
import type { MarAgentModelConfiguration, MarAgentReasoningEffort, ModelCredentialAcquireReason } from './configuration.js';
|
|
3
3
|
export type { ClientToolDefinition, ToolCaller } from '../tools/contracts.js';
|
|
4
|
+
export interface ModelTextBlock {
|
|
5
|
+
readonly text: string;
|
|
6
|
+
readonly cache?: true;
|
|
7
|
+
}
|
|
4
8
|
export interface ModelMessage {
|
|
9
|
+
/** Model-facing tool-result status; independent of the actual execution outcome. */
|
|
10
|
+
isError?: boolean;
|
|
5
11
|
calls?: readonly import('../tools/code-mode/observations.js').CodeToolCallRecord[];
|
|
6
12
|
role: 'user' | 'assistant' | 'tool' | 'tool_call' | 'provider';
|
|
7
13
|
content: string;
|
|
14
|
+
textBlocks?: readonly ModelTextBlock[];
|
|
8
15
|
contextKind?: 'environment' | 'private';
|
|
9
16
|
callId?: string;
|
|
10
17
|
name?: string;
|
|
@@ -64,8 +71,13 @@ export interface ModelRequest {
|
|
|
64
71
|
/** Shared local attempt accounting across Adapter retries and Runtime continuation. Never sent upstream. */
|
|
65
72
|
retryState?: ModelRetryState;
|
|
66
73
|
system: string;
|
|
74
|
+
systemBlocks?: readonly ModelTextBlock[];
|
|
75
|
+
/** Retain the automatic cache boundary of an actual captured prefix, excluding a fork tail. */
|
|
76
|
+
cachePrefixMessages?: number;
|
|
67
77
|
messages: readonly ModelMessage[];
|
|
68
78
|
tools: readonly ClientToolDefinition[];
|
|
79
|
+
/** Optional per-request cap; adapters never exceed their configured output ceiling. */
|
|
80
|
+
outputLimit?: number;
|
|
69
81
|
allowTools?: boolean;
|
|
70
82
|
/** Preserve the visible tool catalog while controlling whether the model may call it. */
|
|
71
83
|
toolChoice?: 'auto' | 'none';
|
|
@@ -7,6 +7,7 @@ import WebSocket from 'ws';
|
|
|
7
7
|
import { isRetryableUpstreamOverloadCode, number, parseSse, record, text, observeModelStreamEvent, modelStreamEventObservedAt } from './sse.js';
|
|
8
8
|
import { connectSocks5Target, fetchModelResponse, isRetryableModelHttpStatus, isRetryableModelTransportError, modelRetryMaxAttempts, isRetryableModelRequestError, modelRetryDelay, waitForModelRetry } from './http.js';
|
|
9
9
|
import { acquireModelCredential, appendModelCredentialHeaders } from './runtime-credential.js';
|
|
10
|
+
import { resolveModelTextBlocks } from './text-blocks.js';
|
|
10
11
|
const WEBSOCKET_IDLE_TIMEOUT_MS = 300_000;
|
|
11
12
|
const WEBSOCKET_SEND_FRAME_BYTES = 1024 * 1024;
|
|
12
13
|
export const OPENAI_RESPONSES_EARLY_EOF_REASON = 'OPENAI_RESPONSES_EARLY_EOF';
|
|
@@ -861,6 +862,11 @@ function isLocalContinuationReset(error) {
|
|
|
861
862
|
return error instanceof MarAgentError && error.code === 'MAR_AGENT_RESPONSES_CONTINUATION_RESET';
|
|
862
863
|
}
|
|
863
864
|
function responsesRequestBody(configuration, request, messages) {
|
|
865
|
+
if ((request.systemBlocks !== undefined &&
|
|
866
|
+
resolveModelTextBlocks(request.system, request.systemBlocks).some((block) => block.cache)) ||
|
|
867
|
+
messages.some((message) => message.textBlocks !== undefined &&
|
|
868
|
+
resolveModelTextBlocks(message.content, message.textBlocks).some((block) => block.cache)))
|
|
869
|
+
throw new MarAgentError('MAR_AGENT_MODEL_CAPABILITY_UNAVAILABLE', 'This model protocol does not support explicit text-block cache markers.');
|
|
864
870
|
const tools = request.allowTools === false
|
|
865
871
|
? []
|
|
866
872
|
: request.tools.map((tool) => tool.nativeType === 'tool_search'
|
|
@@ -887,14 +893,27 @@ function responsesRequestBody(configuration, request, messages) {
|
|
|
887
893
|
tools.push({ type: 'web_search' });
|
|
888
894
|
const toolChoice = request.toolChoice ?? 'auto';
|
|
889
895
|
const input = openAiInput(messages, request.images, configuration.id, true, usesResponsesConfigurationUpdates(configuration));
|
|
896
|
+
if (request.systemBlocks !== undefined && (request.systemBlocks.length || request.system.length))
|
|
897
|
+
input.unshift({
|
|
898
|
+
role: 'developer',
|
|
899
|
+
content: resolveModelTextBlocks(request.system, request.systemBlocks).map((block) => ({
|
|
900
|
+
type: 'input_text',
|
|
901
|
+
text: block.text
|
|
902
|
+
}))
|
|
903
|
+
});
|
|
890
904
|
return {
|
|
891
905
|
model: configuration.modelId,
|
|
906
|
+
...(request.outputLimit === undefined
|
|
907
|
+
? {}
|
|
908
|
+
: {
|
|
909
|
+
max_output_tokens: Math.min(request.outputLimit, configuration.maxOutputTokens)
|
|
910
|
+
}),
|
|
892
911
|
...(configuration.serviceTier !== undefined
|
|
893
912
|
? { service_tier: configuration.serviceTier }
|
|
894
913
|
: configuration.fastMode === true
|
|
895
914
|
? { service_tier: 'priority' }
|
|
896
915
|
: {}),
|
|
897
|
-
instructions: request.system,
|
|
916
|
+
instructions: request.systemBlocks === undefined ? request.system : '',
|
|
898
917
|
tools,
|
|
899
918
|
tool_choice: toolChoice,
|
|
900
919
|
input,
|
|
@@ -939,6 +958,7 @@ function responsesContinuationPropertiesMatch(previous, current) {
|
|
|
939
958
|
'instructions',
|
|
940
959
|
'tools',
|
|
941
960
|
'tool_choice',
|
|
961
|
+
'max_output_tokens',
|
|
942
962
|
'parallel_tool_calls',
|
|
943
963
|
'reasoning',
|
|
944
964
|
'store',
|
|
@@ -1687,8 +1707,8 @@ function strictFunctionSchema(value, optional = false) {
|
|
|
1687
1707
|
return value;
|
|
1688
1708
|
const schema = value;
|
|
1689
1709
|
const supportedSchema = Object.fromEntries(Object.entries(schema).filter(([keyword]) => keyword !== 'propertyNames'));
|
|
1690
|
-
if (schema.type === 'object'
|
|
1691
|
-
const properties = schema.properties;
|
|
1710
|
+
if (schema.type === 'object') {
|
|
1711
|
+
const properties = record(schema.properties);
|
|
1692
1712
|
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
1693
1713
|
return {
|
|
1694
1714
|
...supportedSchema,
|
|
@@ -1861,40 +1881,81 @@ function openAiInputItem(message, images, customCallIds = new Set(), functionCal
|
|
|
1861
1881
|
type: 'input_image',
|
|
1862
1882
|
image_url: `data:${part.image.mimeType};base64,${part.image.dataBase64}`
|
|
1863
1883
|
}) ??
|
|
1864
|
-
(message.
|
|
1884
|
+
(message.textBlocks !== undefined
|
|
1865
1885
|
? [
|
|
1866
|
-
|
|
1867
|
-
|
|
1886
|
+
...resolveModelTextBlocks(message.content, message.textBlocks).map((block) => ({
|
|
1887
|
+
type: 'input_text',
|
|
1888
|
+
text: block.text
|
|
1889
|
+
})),
|
|
1890
|
+
...(message.images ?? []).map((image) => ({
|
|
1868
1891
|
type: 'input_image',
|
|
1869
1892
|
image_url: `data:${image.mimeType};base64,${image.dataBase64}`
|
|
1870
1893
|
}))
|
|
1871
1894
|
]
|
|
1872
|
-
: message.
|
|
1895
|
+
: message.images?.length
|
|
1896
|
+
? [
|
|
1897
|
+
{ type: 'input_text', text: message.content },
|
|
1898
|
+
...message.images.map((image) => ({
|
|
1899
|
+
type: 'input_image',
|
|
1900
|
+
image_url: `data:${image.mimeType};base64,${image.dataBase64}`
|
|
1901
|
+
}))
|
|
1902
|
+
]
|
|
1903
|
+
: message.content)
|
|
1873
1904
|
};
|
|
1874
1905
|
return {
|
|
1875
1906
|
role: message.role,
|
|
1876
|
-
content:
|
|
1907
|
+
content: message.textBlocks !== undefined
|
|
1877
1908
|
? [
|
|
1878
|
-
|
|
1909
|
+
...resolveModelTextBlocks(message.content, message.textBlocks).map((block) => ({
|
|
1910
|
+
type: message.role === 'assistant' ? 'output_text' : 'input_text',
|
|
1911
|
+
text: block.text
|
|
1912
|
+
})),
|
|
1879
1913
|
...userImages.map((image) => ({
|
|
1880
1914
|
type: 'input_image',
|
|
1881
1915
|
image_url: `data:${image.mimeType};base64,${image.dataBase64}`
|
|
1882
1916
|
}))
|
|
1883
1917
|
]
|
|
1884
|
-
:
|
|
1918
|
+
: userImages.length > 0
|
|
1919
|
+
? [
|
|
1920
|
+
{ type: 'input_text', text: message.content },
|
|
1921
|
+
...userImages.map((image) => ({
|
|
1922
|
+
type: 'input_image',
|
|
1923
|
+
image_url: `data:${image.mimeType};base64,${image.dataBase64}`
|
|
1924
|
+
}))
|
|
1925
|
+
]
|
|
1926
|
+
: message.content
|
|
1885
1927
|
};
|
|
1886
1928
|
}
|
|
1887
1929
|
function responsesFunctionTool(tool) {
|
|
1930
|
+
const strict = !hasOpenFunctionObject(tool.inputSchema);
|
|
1888
1931
|
return tool.inputMode === 'freeform'
|
|
1889
1932
|
? { type: 'custom', name: tool.name, description: tool.description }
|
|
1890
1933
|
: {
|
|
1891
1934
|
type: 'function',
|
|
1892
1935
|
name: tool.name,
|
|
1893
1936
|
description: tool.description,
|
|
1894
|
-
parameters: strictFunctionSchema(tool.inputSchema),
|
|
1895
|
-
strict
|
|
1937
|
+
parameters: strict ? strictFunctionSchema(tool.inputSchema) : tool.inputSchema,
|
|
1938
|
+
strict
|
|
1896
1939
|
};
|
|
1897
1940
|
}
|
|
1941
|
+
function hasOpenFunctionObject(value) {
|
|
1942
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
1943
|
+
return false;
|
|
1944
|
+
const schema = record(value);
|
|
1945
|
+
if ((schema.type === 'object' || (Array.isArray(schema.type) && schema.type.includes('object'))) &&
|
|
1946
|
+
(schema.additionalProperties === true ||
|
|
1947
|
+
(schema.additionalProperties !== null && typeof schema.additionalProperties === 'object') ||
|
|
1948
|
+
(schema.properties === undefined && schema.additionalProperties !== false)))
|
|
1949
|
+
return true;
|
|
1950
|
+
const children = [
|
|
1951
|
+
...Object.values(record(schema.properties)),
|
|
1952
|
+
...Object.values(record(schema.$defs)),
|
|
1953
|
+
...Object.values(record(schema.definitions)),
|
|
1954
|
+
schema.items,
|
|
1955
|
+
...[schema.anyOf, schema.oneOf, schema.allOf].flatMap((items) => Array.isArray(items) ? items : [])
|
|
1956
|
+
];
|
|
1957
|
+
return children.some(hasOpenFunctionObject);
|
|
1958
|
+
}
|
|
1898
1959
|
function uniqueModelImages(...groups) {
|
|
1899
1960
|
const seen = new Set();
|
|
1900
1961
|
return groups.flatMap((group) => (group ?? []).flatMap((image) => {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ModelTextBlock } from './contracts.js';
|
|
2
|
+
/** Preserve explicit blocks only while their complete texts still match the actual prefix. */
|
|
3
|
+
export declare function resolveModelTextBlocks(text: string, blocks: readonly ModelTextBlock[]): readonly ModelTextBlock[];
|
|
4
|
+
export declare function modelTextInput(value: string | readonly ModelTextBlock[]): {
|
|
5
|
+
text: string;
|
|
6
|
+
blocks?: readonly ModelTextBlock[];
|
|
7
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MarAgentError } from '../error.js';
|
|
2
|
+
/** Preserve explicit blocks only while their complete texts still match the actual prefix. */
|
|
3
|
+
export function resolveModelTextBlocks(text, blocks) {
|
|
4
|
+
if (typeof text !== 'string' || !Array.isArray(blocks))
|
|
5
|
+
throw invalid();
|
|
6
|
+
const copied = blocks.map((block) => {
|
|
7
|
+
if (!block ||
|
|
8
|
+
typeof block !== 'object' ||
|
|
9
|
+
typeof block.text !== 'string' ||
|
|
10
|
+
(block.cache !== undefined && block.cache !== true))
|
|
11
|
+
throw invalid();
|
|
12
|
+
return { text: block.text, ...(block.cache === true ? { cache: true } : {}) };
|
|
13
|
+
});
|
|
14
|
+
let offset = 0;
|
|
15
|
+
const result = [];
|
|
16
|
+
for (const block of copied) {
|
|
17
|
+
if (!text.startsWith(block.text, offset))
|
|
18
|
+
break;
|
|
19
|
+
result.push(block);
|
|
20
|
+
offset += block.text.length;
|
|
21
|
+
}
|
|
22
|
+
if (offset < text.length)
|
|
23
|
+
result.push({ text: text.slice(offset) });
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
export function modelTextInput(value) {
|
|
27
|
+
if (typeof value === 'string')
|
|
28
|
+
return { text: value };
|
|
29
|
+
if (!Array.isArray(value))
|
|
30
|
+
throw invalid();
|
|
31
|
+
for (const block of value) {
|
|
32
|
+
if (!block || typeof block !== 'object' || typeof block.text !== 'string')
|
|
33
|
+
throw invalid();
|
|
34
|
+
}
|
|
35
|
+
const text = value.map((block) => block.text).join('');
|
|
36
|
+
return { text, blocks: resolveModelTextBlocks(text, value) };
|
|
37
|
+
}
|
|
38
|
+
function invalid() {
|
|
39
|
+
return new MarAgentError('MAR_AGENT_MODEL_TEXT_BLOCK_INVALID', 'Model text blocks are invalid.');
|
|
40
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ExecutionMode } from '../runtime/contracts.js';
|
|
2
|
+
import { type CorePromptPart } from '../extensions/prompt-composition.js';
|
|
2
3
|
export declare const MAR_AGENT_PROMPT_VERSION = "1.60";
|
|
3
|
-
|
|
4
|
+
interface SystemPromptInput {
|
|
4
5
|
mode: ExecutionMode;
|
|
5
6
|
platform: string;
|
|
6
7
|
architecture?: string;
|
|
@@ -14,4 +15,7 @@ export declare function buildSystemPrompt(input: {
|
|
|
14
15
|
directTools?: readonly string[];
|
|
15
16
|
highDensityCompaction?: boolean;
|
|
16
17
|
extension?: string | undefined;
|
|
17
|
-
}
|
|
18
|
+
}
|
|
19
|
+
export declare function buildSystemPrompt(input: SystemPromptInput): string;
|
|
20
|
+
export declare function buildSystemPromptSections(input: SystemPromptInput): readonly CorePromptPart[];
|
|
21
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { renderPromptSections } from '../extensions/prompt-composition.js';
|
|
1
2
|
import { compactionPrompt, highDensityCompactionPrompt } from './compact.js';
|
|
2
3
|
import { environmentPrompt, identityPrompt, instructionPriorityPrompt, workspaceDisciplinePrompt } from './core.js';
|
|
3
4
|
import { modePrompt } from './modes.js';
|
|
@@ -6,6 +7,9 @@ import { subagentPrompt } from './subagent.js';
|
|
|
6
7
|
import { interactionPrompt, longRunningPrompt, safetyPrompt, toolUsagePrompt, workflowPrompt } from './workflow.js';
|
|
7
8
|
export const MAR_AGENT_PROMPT_VERSION = '1.60';
|
|
8
9
|
export function buildSystemPrompt(input) {
|
|
10
|
+
return renderPromptSections(buildSystemPromptSections(input));
|
|
11
|
+
}
|
|
12
|
+
export function buildSystemPromptSections(input) {
|
|
9
13
|
const toolNames = new Set(input.tools);
|
|
10
14
|
const hasLongRunningCapability = [
|
|
11
15
|
'exec',
|
|
@@ -15,28 +19,38 @@ export function buildSystemPrompt(input) {
|
|
|
15
19
|
'agent_wait',
|
|
16
20
|
'agent_cancel'
|
|
17
21
|
].some((name) => toolNames.has(name));
|
|
18
|
-
|
|
19
|
-
identityPrompt(),
|
|
20
|
-
instructionPriorityPrompt,
|
|
21
|
-
workspaceDisciplinePrompt,
|
|
22
|
-
workflowPrompt,
|
|
23
|
-
interactionPrompt,
|
|
24
|
-
safetyPrompt,
|
|
25
|
-
outputStylePrompt,
|
|
26
|
-
environmentPrompt(input),
|
|
27
|
-
input.tools.length > 0 ? toolUsagePrompt(input.tools, input.directTools) : '',
|
|
28
|
-
hasLongRunningCapability ? longRunningPrompt(input.tools) : '',
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
22
|
+
const values = [
|
|
23
|
+
['identity', identityPrompt()],
|
|
24
|
+
['instruction-priority', instructionPriorityPrompt],
|
|
25
|
+
['workspace-discipline', workspaceDisciplinePrompt],
|
|
26
|
+
['workflow', workflowPrompt],
|
|
27
|
+
['interaction', interactionPrompt],
|
|
28
|
+
['safety', safetyPrompt],
|
|
29
|
+
['output-style', outputStylePrompt],
|
|
30
|
+
['environment-rules', environmentPrompt(input)],
|
|
31
|
+
['tools', input.tools.length > 0 ? toolUsagePrompt(input.tools, input.directTools) : ''],
|
|
32
|
+
['long-running', hasLongRunningCapability ? longRunningPrompt(input.tools) : ''],
|
|
33
|
+
[
|
|
34
|
+
'mode',
|
|
35
|
+
modePrompt(input.mode, {
|
|
36
|
+
questionAvailable: toolNames.has('question')
|
|
37
|
+
})
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
'compaction',
|
|
41
|
+
input.mode === 'compact'
|
|
42
|
+
? input.highDensityCompaction
|
|
43
|
+
? highDensityCompactionPrompt()
|
|
44
|
+
: compactionPrompt()
|
|
45
|
+
: ''
|
|
46
|
+
],
|
|
47
|
+
['subagent', toolNames.has('agent_start') ? subagentPrompt : ''],
|
|
48
|
+
[
|
|
49
|
+
'caller-instructions',
|
|
50
|
+
input.extension
|
|
51
|
+
? `# Caller, project, and selected Skill instructions\n${input.extension}`
|
|
52
|
+
: ''
|
|
53
|
+
]
|
|
54
|
+
];
|
|
55
|
+
return Object.freeze(values.map(([id, text]) => Object.freeze({ id: `core:${id}`, text: text || null })));
|
|
42
56
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { openAiInput } from '../../model/openai-responses.js';
|
|
2
2
|
import { countModelTokens } from '../token-budget.js';
|
|
3
|
+
import { observationModelText } from '../../tools/code-mode/observations.js';
|
|
3
4
|
export { MODEL_TOKEN_ESTIMATOR as CONTEXT_GC_TOKEN_ESTIMATOR } from '../token-budget.js';
|
|
4
5
|
/** Uses Responses lowering, including native alias and cross-model filtering. */
|
|
5
6
|
export function contextGcTokenEntries(input, messages) {
|
|
@@ -17,7 +18,11 @@ function serializedEntries(input, messages) {
|
|
|
17
18
|
: messages
|
|
18
19
|
.filter((message) => message.role !== 'provider' ||
|
|
19
20
|
(message.provider === 'ANTHROPIC_MESSAGES' && message.providerModelId === input.modelId))
|
|
20
|
-
.map((
|
|
21
|
+
.map((original) => {
|
|
22
|
+
const { observations: _observations, observationId: _observationId, ...message } = original;
|
|
23
|
+
const content = original.role === 'tool' ? observationModelText(original) : undefined;
|
|
24
|
+
return content === undefined ? message : { ...message, content };
|
|
25
|
+
});
|
|
21
26
|
return values.map((value, index) => {
|
|
22
27
|
const item = value;
|
|
23
28
|
const callId = item.call_id ?? item.callId;
|
|
@@ -18,7 +18,27 @@ export function normalizeMessagesForModel(messages, input) {
|
|
|
18
18
|
content: `[tool result unavailable for call ${callId}: the execution was interrupted before the result was recorded]`
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
// A record committed during tool execution may precede its results in physical history.
|
|
22
|
+
// Delay only user rows in the request projection; never reorder persisted events.
|
|
23
|
+
const projected = [];
|
|
24
|
+
const deferred = [];
|
|
25
|
+
const pending = new Set();
|
|
26
|
+
for (const message of result) {
|
|
27
|
+
if (message.role === 'user' && pending.size) {
|
|
28
|
+
deferred.push(message);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
projected.push(message);
|
|
32
|
+
const callId = pendingToolCallId(message);
|
|
33
|
+
if (callId)
|
|
34
|
+
pending.add(callId);
|
|
35
|
+
if (message.role === 'tool' && message.callId)
|
|
36
|
+
pending.delete(message.callId);
|
|
37
|
+
if (!pending.size && deferred.length)
|
|
38
|
+
projected.push(...deferred.splice(0));
|
|
39
|
+
}
|
|
40
|
+
projected.push(...deferred);
|
|
41
|
+
return projected;
|
|
22
42
|
}
|
|
23
43
|
function pendingToolCallId(message) {
|
|
24
44
|
if (message.role === 'tool_call')
|
|
@@ -74,7 +74,9 @@ export function applyContextGcReplacementsToMessages(messages, messageSources, r
|
|
|
74
74
|
next = {
|
|
75
75
|
...next,
|
|
76
76
|
observations,
|
|
77
|
-
content:
|
|
77
|
+
content: next.textBlocks === undefined
|
|
78
|
+
? renderObservationResult(observations, next.content)
|
|
79
|
+
: next.content
|
|
78
80
|
};
|
|
79
81
|
}
|
|
80
82
|
if (replacement && target && targetMatchesReplacement(target, replacement.target)) {
|
|
@@ -94,6 +96,11 @@ export function applyContextGcReplacementsToMessages(messages, messageSources, r
|
|
|
94
96
|
next.role === 'tool')
|
|
95
97
|
next = { ...next, content: replacement.replacementContent };
|
|
96
98
|
}
|
|
99
|
+
if (next.textBlocks !== undefined && next.content !== message.content)
|
|
100
|
+
next = {
|
|
101
|
+
...next,
|
|
102
|
+
textBlocks: [{ text: next.content }]
|
|
103
|
+
};
|
|
97
104
|
projected.push({ message: next, source });
|
|
98
105
|
}
|
|
99
106
|
return {
|
|
@@ -142,6 +149,19 @@ export function restoreModelContext(payload, providerModelId) {
|
|
|
142
149
|
const byteLimit = inputLimit === undefined ? MAX_MODEL_CONTEXT_BYTES : inputLimit * 6 + 4096;
|
|
143
150
|
if (Buffer.byteLength(JSON.stringify(payload)) > byteLimit)
|
|
144
151
|
return undefined;
|
|
152
|
+
if (payload.role === 'user' && typeof payload.content === 'string') {
|
|
153
|
+
const blocks = payload.textBlocks;
|
|
154
|
+
const textBlocks = Array.isArray(blocks) &&
|
|
155
|
+
Array.from(blocks).every((block) => block && typeof block.text === 'string') &&
|
|
156
|
+
blocks.map((block) => block.text).join('') === payload.content
|
|
157
|
+
? blocks.map((block) => ({ text: block.text }))
|
|
158
|
+
: undefined;
|
|
159
|
+
return {
|
|
160
|
+
role: 'user',
|
|
161
|
+
content: payload.content,
|
|
162
|
+
...(textBlocks === undefined ? {} : { textBlocks })
|
|
163
|
+
};
|
|
164
|
+
}
|
|
145
165
|
if (payload.role === 'tool' &&
|
|
146
166
|
typeof payload.content === 'string' &&
|
|
147
167
|
typeof payload.callId === 'string')
|
|
@@ -149,6 +169,20 @@ export function restoreModelContext(payload, providerModelId) {
|
|
|
149
169
|
role: 'tool',
|
|
150
170
|
content: payload.content,
|
|
151
171
|
callId: payload.callId,
|
|
172
|
+
...(typeof payload.name === 'string' ? { name: payload.name } : {}),
|
|
173
|
+
...(typeof payload.isError === 'boolean' ? { isError: payload.isError } : {}),
|
|
174
|
+
...(Array.isArray(payload.textBlocks) &&
|
|
175
|
+
payload.textBlocks.every((block) => block &&
|
|
176
|
+
typeof block.text === 'string' &&
|
|
177
|
+
(block.cache === undefined || block.cache === true)) &&
|
|
178
|
+
payload.textBlocks.map((block) => block.text).join('') === payload.content
|
|
179
|
+
? {
|
|
180
|
+
textBlocks: payload.textBlocks.map((block) => ({
|
|
181
|
+
text: block.text,
|
|
182
|
+
...(block.cache === true ? { cache: true } : {})
|
|
183
|
+
}))
|
|
184
|
+
}
|
|
185
|
+
: {}),
|
|
152
186
|
...(parseCodeCalls(payload.calls) ? { calls: parseCodeCalls(payload.calls) } : {}),
|
|
153
187
|
...(parseObservations(payload.observations)
|
|
154
188
|
? { observations: parseObservations(payload.observations) }
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { AGENT_EXECUTION_POLICY } from '../execution-policy.js';
|
|
2
2
|
import { countModelTokens } from '../token-budget.js';
|
|
3
|
+
import { observationModelText } from '../../tools/code-mode/observations.js';
|
|
3
4
|
export function estimatedRequestTokens(system, messages, tools, images) {
|
|
4
5
|
const transientImageCount = messages.reduce((total, message) => total + (message.images?.length ?? 0), images?.length ?? 0);
|
|
5
6
|
const textMessages = messages.map((message) => {
|
|
6
|
-
const
|
|
7
|
-
|
|
7
|
+
const { images: _images, observations: _observations, observationId: _observationId, ...textMessage } = message;
|
|
8
|
+
const content = message.role === 'tool' ? observationModelText(message) : undefined;
|
|
9
|
+
if (content !== undefined)
|
|
10
|
+
textMessage.content = content;
|
|
8
11
|
return textMessage;
|
|
9
12
|
});
|
|
10
13
|
return (countModelTokens(`${system}${stableJson(textMessages)}${stableJson(tools)}`) +
|