@compilr-dev/agents 0.5.2 → 0.5.3
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.d.ts +2 -2
- package/dist/agent.js +25 -9
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/observation-masker.d.ts +17 -2
- package/dist/context/observation-masker.js +65 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/providers/claude.js +9 -0
- package/dist/providers/gemini-native.js +9 -0
- package/dist/providers/openai-compatible.js +18 -2
- package/dist/providers/types.d.ts +17 -1
- package/dist/tools/types.d.ts +13 -0
- package/package.json +1 -1
package/dist/agent.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent - The main class for running AI agents with tool use
|
|
3
3
|
*/
|
|
4
|
-
import type { LLMProvider, Message, ChatOptions, StreamChunk } from './providers/types.js';
|
|
4
|
+
import type { LLMProvider, Message, ChatOptions, StreamChunk, ContentBlock } from './providers/types.js';
|
|
5
5
|
import type { Tool, ToolDefinition, ToolRegistry, ToolExecutionResult, ToolExecutionContext } from './tools/types.js';
|
|
6
6
|
import type { ContextStats, VerbosityLevel, SmartCompactionResult } from './context/types.js';
|
|
7
7
|
import type { AgentState, Checkpointer, SessionMetadata } from './state/types.js';
|
|
@@ -1650,7 +1650,7 @@ export declare class Agent {
|
|
|
1650
1650
|
/**
|
|
1651
1651
|
* Run the agent with a user message
|
|
1652
1652
|
*/
|
|
1653
|
-
run(userMessage: string, options?: RunOptions): Promise<AgentRunResult>;
|
|
1653
|
+
run(userMessage: string | ContentBlock[], options?: RunOptions): Promise<AgentRunResult>;
|
|
1654
1654
|
/**
|
|
1655
1655
|
* Stream the agent's response with full tool use support
|
|
1656
1656
|
*
|
package/dist/agent.js
CHANGED
|
@@ -2091,18 +2091,33 @@ export class Agent {
|
|
|
2091
2091
|
const finalTokens = this.contextManager.estimateTokens(toolResultContent);
|
|
2092
2092
|
this.contextManager.addToCategory('toolResults', finalTokens);
|
|
2093
2093
|
}
|
|
2094
|
+
// Build content blocks: tool_result + optional image blocks
|
|
2095
|
+
const contentBlocks = [
|
|
2096
|
+
{
|
|
2097
|
+
type: 'tool_result',
|
|
2098
|
+
toolUseId: toolUse.id,
|
|
2099
|
+
content: toolResultContent,
|
|
2100
|
+
isError: !result.success,
|
|
2101
|
+
},
|
|
2102
|
+
];
|
|
2103
|
+
// Inject image blocks from tool result (e.g., view_image tool)
|
|
2104
|
+
if (result.imageBlocks?.length) {
|
|
2105
|
+
for (const img of result.imageBlocks) {
|
|
2106
|
+
contentBlocks.push({
|
|
2107
|
+
type: 'image',
|
|
2108
|
+
data: img.data,
|
|
2109
|
+
mediaType: img.mediaType,
|
|
2110
|
+
filename: img.filename,
|
|
2111
|
+
width: img.width,
|
|
2112
|
+
height: img.height,
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2094
2116
|
return {
|
|
2095
2117
|
result,
|
|
2096
2118
|
toolResultMsg: {
|
|
2097
2119
|
role: 'user',
|
|
2098
|
-
content:
|
|
2099
|
-
{
|
|
2100
|
-
type: 'tool_result',
|
|
2101
|
-
toolUseId: toolUse.id,
|
|
2102
|
-
content: toolResultContent,
|
|
2103
|
-
isError: !result.success,
|
|
2104
|
-
},
|
|
2105
|
-
],
|
|
2120
|
+
content: contentBlocks,
|
|
2106
2121
|
},
|
|
2107
2122
|
skipped: false,
|
|
2108
2123
|
aborted: false,
|
|
@@ -2352,8 +2367,9 @@ export class Agent {
|
|
|
2352
2367
|
// Context management: increment turn count and update token count
|
|
2353
2368
|
if (this.contextManager) {
|
|
2354
2369
|
this.contextManager.incrementTurn();
|
|
2355
|
-
// Observation masking: mask old
|
|
2370
|
+
// Observation masking: stamp new images, then mask old results + images
|
|
2356
2371
|
if (this.observationMasker) {
|
|
2372
|
+
this.observationMasker.stampImages(messages, this.contextManager.getTurnCount());
|
|
2357
2373
|
this.observationMasker.maskHistory(messages, this.contextManager.getTurnCount());
|
|
2358
2374
|
}
|
|
2359
2375
|
// Dead message pruning: prune superseded errors and permission exchanges
|
package/dist/context/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export type { ToolResultDelegatorOptions } from './tool-result-delegator.js';
|
|
|
21
21
|
export { DEFAULT_DELEGATION_CONFIG } from './delegation-types.js';
|
|
22
22
|
export type { DelegationConfig, StoredResult, DelegationEvent } from './delegation-types.js';
|
|
23
23
|
export { compactToolResult } from './result-compactor.js';
|
|
24
|
-
export { ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, } from './observation-masker.js';
|
|
24
|
+
export { ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, maskImageBlock, } from './observation-masker.js';
|
|
25
25
|
export type { InputCompactionRule, ObservationMaskConfig, MaskResult, ObservationMaskStats, } from './observation-masker.js';
|
|
26
26
|
export { DeadMessagePruner, DEFAULT_PRUNE_CONFIG, isPruned } from './dead-message-pruner.js';
|
|
27
27
|
export type { PruneConfig, PruneResult, PruneStats } from './dead-message-pruner.js';
|
package/dist/context/index.js
CHANGED
|
@@ -18,7 +18,7 @@ export { DEFAULT_DELEGATION_CONFIG } from './delegation-types.js';
|
|
|
18
18
|
// Compact Tool Result Formatting (Phase 2 Token Optimization)
|
|
19
19
|
export { compactToolResult } from './result-compactor.js';
|
|
20
20
|
// Observation Masking (Phase 1 Token Optimization) + Tool Input Compaction (Phase 1b)
|
|
21
|
-
export { ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, } from './observation-masker.js';
|
|
21
|
+
export { ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, maskImageBlock, } from './observation-masker.js';
|
|
22
22
|
// Dead Message Pruning (Phase 4 Token Optimization)
|
|
23
23
|
export { DeadMessagePruner, DEFAULT_PRUNE_CONFIG, isPruned } from './dead-message-pruner.js';
|
|
24
24
|
// Smart Windowing (Programmatic Context Compaction)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Strategy: In-place masking of conversationHistory after N turns.
|
|
9
9
|
* The agent can re-read from the environment if needed (files, git, etc.).
|
|
10
10
|
*/
|
|
11
|
-
import type { Message } from '../providers/types.js';
|
|
11
|
+
import type { Message, ImageBlock, TextBlock } from '../providers/types.js';
|
|
12
12
|
/**
|
|
13
13
|
* Defines which input fields to keep when compacting a tool_use input.
|
|
14
14
|
* All other fields are removed.
|
|
@@ -62,6 +62,8 @@ export declare class ObservationMasker {
|
|
|
62
62
|
private readonly stamps;
|
|
63
63
|
private readonly config;
|
|
64
64
|
private stats;
|
|
65
|
+
/** Tracks which image blocks have been stamped (by identity) to avoid re-stamping */
|
|
66
|
+
private readonly stampedImages;
|
|
65
67
|
constructor(config?: Partial<ObservationMaskConfig>);
|
|
66
68
|
/**
|
|
67
69
|
* Register a tool result with its turn number and input context.
|
|
@@ -69,8 +71,16 @@ export declare class ObservationMasker {
|
|
|
69
71
|
*/
|
|
70
72
|
stamp(toolUseId: string, toolName: string, input: Record<string, unknown>, contentLength: number, turn: number): void;
|
|
71
73
|
/**
|
|
72
|
-
*
|
|
74
|
+
* Stamp all image blocks in a message array with the current turn.
|
|
75
|
+
* Call this after adding user messages that may contain images.
|
|
76
|
+
*/
|
|
77
|
+
stampImages(messages: Message[], turn: number): void;
|
|
78
|
+
/** Turn at which each image block was first seen */
|
|
79
|
+
private readonly imageStamps;
|
|
80
|
+
/**
|
|
81
|
+
* Mask old tool results, images, and compact old tool_use inputs in-place.
|
|
73
82
|
* - tool_result: replaces content with compact mask text (Phase 1)
|
|
83
|
+
* - image: replaces with text placeholder after maskAfterTurns (Phase 2)
|
|
74
84
|
* - tool_use input: strips large fields, keeping only identifying fields (Phase 1b)
|
|
75
85
|
*/
|
|
76
86
|
maskHistory(messages: Message[], currentTurn: number): MaskResult;
|
|
@@ -101,4 +111,9 @@ export declare function buildMaskText(stamp: TurnStamp): string;
|
|
|
101
111
|
* Check if a tool result content string is already masked.
|
|
102
112
|
*/
|
|
103
113
|
export declare function isMasked(content: string): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Replace an image content block with a text placeholder.
|
|
116
|
+
* Preserves filename and dimensions for context.
|
|
117
|
+
*/
|
|
118
|
+
export declare function maskImageBlock(block: ImageBlock, turn: number): TextBlock;
|
|
104
119
|
export {};
|
|
@@ -26,6 +26,8 @@ export class ObservationMasker {
|
|
|
26
26
|
stamps = new Map();
|
|
27
27
|
config;
|
|
28
28
|
stats = { maskedCount: 0, tokensSaved: 0, inputsCompacted: 0 };
|
|
29
|
+
/** Tracks which image blocks have been stamped (by identity) to avoid re-stamping */
|
|
30
|
+
stampedImages = new WeakSet();
|
|
29
31
|
constructor(config) {
|
|
30
32
|
this.config = { ...DEFAULT_MASK_CONFIG, ...config };
|
|
31
33
|
}
|
|
@@ -45,11 +47,33 @@ export class ObservationMasker {
|
|
|
45
47
|
});
|
|
46
48
|
}
|
|
47
49
|
// ----------------------------------------------------------
|
|
50
|
+
// Image stamping — called when messages with images are added
|
|
51
|
+
// ----------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Stamp all image blocks in a message array with the current turn.
|
|
54
|
+
* Call this after adding user messages that may contain images.
|
|
55
|
+
*/
|
|
56
|
+
stampImages(messages, turn) {
|
|
57
|
+
for (const msg of messages) {
|
|
58
|
+
if (typeof msg.content === 'string')
|
|
59
|
+
continue;
|
|
60
|
+
for (const block of msg.content) {
|
|
61
|
+
if (block.type === 'image' && !this.stampedImages.has(block)) {
|
|
62
|
+
this.imageStamps.set(block, turn);
|
|
63
|
+
this.stampedImages.add(block);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Turn at which each image block was first seen */
|
|
69
|
+
imageStamps = new WeakMap();
|
|
70
|
+
// ----------------------------------------------------------
|
|
48
71
|
// Masking — called after incrementTurn()
|
|
49
72
|
// ----------------------------------------------------------
|
|
50
73
|
/**
|
|
51
|
-
* Mask old tool results and compact old tool_use inputs in-place.
|
|
74
|
+
* Mask old tool results, images, and compact old tool_use inputs in-place.
|
|
52
75
|
* - tool_result: replaces content with compact mask text (Phase 1)
|
|
76
|
+
* - image: replaces with text placeholder after maskAfterTurns (Phase 2)
|
|
53
77
|
* - tool_use input: strips large fields, keeping only identifying fields (Phase 1b)
|
|
54
78
|
*/
|
|
55
79
|
maskHistory(messages, currentTurn) {
|
|
@@ -90,6 +114,34 @@ export class ObservationMasker {
|
|
|
90
114
|
this.stamps.delete(block.toolUseId);
|
|
91
115
|
}
|
|
92
116
|
}
|
|
117
|
+
// Phase 2: Replace old image blocks with text placeholders
|
|
118
|
+
const contentArr = msg.content;
|
|
119
|
+
for (let i = 0; i < contentArr.length; i++) {
|
|
120
|
+
const block = contentArr[i];
|
|
121
|
+
if (block.type !== 'image')
|
|
122
|
+
continue;
|
|
123
|
+
// Stamp if not already stamped (images added before stampImages existed)
|
|
124
|
+
if (!this.stampedImages.has(block)) {
|
|
125
|
+
this.imageStamps.set(block, currentTurn);
|
|
126
|
+
this.stampedImages.add(block);
|
|
127
|
+
continue; // Don't mask on the same turn we stamp
|
|
128
|
+
}
|
|
129
|
+
const imageTurn = this.imageStamps.get(block);
|
|
130
|
+
if (imageTurn === undefined)
|
|
131
|
+
continue;
|
|
132
|
+
const age = currentTurn - imageTurn;
|
|
133
|
+
if (age < this.config.maskAfterTurns)
|
|
134
|
+
continue;
|
|
135
|
+
// Replace image block with text placeholder
|
|
136
|
+
const placeholder = maskImageBlock(block, imageTurn);
|
|
137
|
+
contentArr[i] = placeholder;
|
|
138
|
+
// Estimate tokens saved: base64 image data is ~4 chars per 3 bytes
|
|
139
|
+
// A typical image is 1000-5000 tokens; the placeholder is ~20 tokens
|
|
140
|
+
const imageTokens = Math.ceil(block.data.length / 4);
|
|
141
|
+
const savedTokens = Math.max(0, imageTokens - 20);
|
|
142
|
+
tokensSaved += savedTokens;
|
|
143
|
+
maskedCount++;
|
|
144
|
+
}
|
|
93
145
|
// Phase 1b: Compact old tool_use inputs in assistant messages
|
|
94
146
|
if (msg.role === 'assistant') {
|
|
95
147
|
for (const block of msg.content) {
|
|
@@ -252,3 +304,15 @@ export function buildMaskText(stamp) {
|
|
|
252
304
|
export function isMasked(content) {
|
|
253
305
|
return content.startsWith('[') && content.endsWith(']') && content.includes('@turn:');
|
|
254
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Replace an image content block with a text placeholder.
|
|
309
|
+
* Preserves filename and dimensions for context.
|
|
310
|
+
*/
|
|
311
|
+
export function maskImageBlock(block, turn) {
|
|
312
|
+
const name = block.filename ?? 'image';
|
|
313
|
+
const dims = block.width && block.height ? `, ${String(block.width)}x${String(block.height)}` : '';
|
|
314
|
+
return {
|
|
315
|
+
type: 'text',
|
|
316
|
+
text: `[Image: ${name}${dims}, sent@turn:${String(turn)}]`,
|
|
317
|
+
};
|
|
318
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export type { ToolPairingValidation } from './messages/index.js';
|
|
|
39
39
|
export { generateId, sleep, retry, truncate, withRetryGenerator, calculateBackoffDelay, DEFAULT_RETRY_CONFIG, countTokens, countMessageTokens, } from './utils/index.js';
|
|
40
40
|
export type { RetryConfig as LLMRetryConfig, WithRetryOptions } from './utils/index.js';
|
|
41
41
|
export { AgentError, ProviderError, ToolError, ToolTimeoutError, ToolLoopError, ValidationError, MaxIterationsError, AbortError, ContextOverflowError, isAgentError, isProviderError, isToolError, isToolTimeoutError, isToolLoopError, isContextOverflowError, wrapError, } from './errors.js';
|
|
42
|
-
export { ContextManager, DEFAULT_CONTEXT_CONFIG, FileAccessTracker, createFileTrackingHook, TRACKED_TOOLS, DelegatedResultStore, ToolResultDelegator, DELEGATION_SYSTEM_PROMPT, DEFAULT_DELEGATION_CONFIG, compactToolResult, ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, DeadMessagePruner, DEFAULT_PRUNE_CONFIG, isPruned, } from './context/index.js';
|
|
42
|
+
export { ContextManager, DEFAULT_CONTEXT_CONFIG, FileAccessTracker, createFileTrackingHook, TRACKED_TOOLS, DelegatedResultStore, ToolResultDelegator, DELEGATION_SYSTEM_PROMPT, DEFAULT_DELEGATION_CONFIG, compactToolResult, ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, maskImageBlock, DeadMessagePruner, DEFAULT_PRUNE_CONFIG, isPruned, } from './context/index.js';
|
|
43
43
|
export type { ContextManagerOptions, ContextCategory, BudgetAllocation, CategoryBudgetInfo, PreflightResult, VerbosityLevel, VerbosityConfig, ContextConfig, FilteringConfig, CompactionConfig, SummarizationConfig, CompactionResult, SummarizationResult, FilteringResult, ContextEvent, ContextEventHandler, ContextStats, FileAccessType, FileAccess, FileAccessTrackerOptions, FormatHintsOptions, FileAccessStats, RestorationHintMessage, DelegatedResultStoreStats, ToolResultDelegatorOptions, DelegationConfig, StoredResult, DelegationEvent, InputCompactionRule, ObservationMaskConfig, MaskResult, ObservationMaskStats, PruneConfig, PruneResult, PruneStats, WindowingConfig, WindowingResult, ImportanceLevel, } from './context/index.js';
|
|
44
44
|
export { SkillRegistry, defineSkill, createSkillRegistry, builtinSkills, getDefaultSkillRegistry, resetDefaultSkillRegistry, } from './skills/index.js';
|
|
45
45
|
export type { Skill, SkillInvocationResult, SkillInvokeOptions } from './skills/index.js';
|
package/dist/index.js
CHANGED
|
@@ -51,7 +51,7 @@ DelegatedResultStore, ToolResultDelegator, DELEGATION_SYSTEM_PROMPT, DEFAULT_DEL
|
|
|
51
51
|
// Compact tool result formatting (Phase 2 Token Optimization)
|
|
52
52
|
compactToolResult,
|
|
53
53
|
// Observation masking (Phase 1 Token Optimization) + Tool Input Compaction (Phase 1b)
|
|
54
|
-
ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked,
|
|
54
|
+
ObservationMasker, DEFAULT_MASK_CONFIG, DEFAULT_INPUT_COMPACTION, extractInputSummary, buildMaskText, isMasked, maskImageBlock,
|
|
55
55
|
// Dead message pruning (Phase 4 Token Optimization)
|
|
56
56
|
DeadMessagePruner, DEFAULT_PRUNE_CONFIG, isPruned, } from './context/index.js';
|
|
57
57
|
// Skills system
|
package/dist/providers/claude.js
CHANGED
|
@@ -228,6 +228,15 @@ export class ClaudeProvider {
|
|
|
228
228
|
// Thinking blocks are passed through as text for now
|
|
229
229
|
// The API expects thinking in a specific format during beta
|
|
230
230
|
return { type: 'text', text: `<thinking>${block.thinking}</thinking>` };
|
|
231
|
+
case 'image':
|
|
232
|
+
return {
|
|
233
|
+
type: 'image',
|
|
234
|
+
source: {
|
|
235
|
+
type: 'base64',
|
|
236
|
+
media_type: block.mediaType,
|
|
237
|
+
data: block.data,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
231
240
|
default: {
|
|
232
241
|
// Exhaustive check - this should never happen
|
|
233
242
|
const _exhaustive = block;
|
|
@@ -232,6 +232,15 @@ export class GeminiNativeProvider {
|
|
|
232
232
|
// They are internal model reasoning. Only the signature on function calls matters.
|
|
233
233
|
// Skip - do not add to parts.
|
|
234
234
|
break;
|
|
235
|
+
case 'image':
|
|
236
|
+
// Convert to Gemini's inlineData format
|
|
237
|
+
parts.push({
|
|
238
|
+
inlineData: {
|
|
239
|
+
mimeType: block.mediaType,
|
|
240
|
+
data: block.data,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
break;
|
|
235
244
|
default: {
|
|
236
245
|
// Exhaustive check
|
|
237
246
|
const _exhaustive = block;
|
|
@@ -221,12 +221,20 @@ export class OpenAICompatibleProvider {
|
|
|
221
221
|
else if (Array.isArray(msg.content)) {
|
|
222
222
|
// Handle content blocks
|
|
223
223
|
const blocks = msg.content;
|
|
224
|
-
const
|
|
224
|
+
const contentParts = [];
|
|
225
225
|
const toolCallsList = [];
|
|
226
226
|
const toolResults = [];
|
|
227
|
+
let hasImages = false;
|
|
227
228
|
for (const block of blocks) {
|
|
228
229
|
if (block.type === 'text') {
|
|
229
|
-
|
|
230
|
+
contentParts.push({ type: 'text', text: block.text });
|
|
231
|
+
}
|
|
232
|
+
else if (block.type === 'image') {
|
|
233
|
+
contentParts.push({
|
|
234
|
+
type: 'image_url',
|
|
235
|
+
image_url: { url: `data:${block.mediaType};base64,${block.data}` },
|
|
236
|
+
});
|
|
237
|
+
hasImages = true;
|
|
230
238
|
}
|
|
231
239
|
else if (block.type === 'tool_use') {
|
|
232
240
|
toolCallsList.push({
|
|
@@ -247,6 +255,7 @@ export class OpenAICompatibleProvider {
|
|
|
247
255
|
}
|
|
248
256
|
// Note: 'thinking' blocks are ignored (Claude-specific)
|
|
249
257
|
}
|
|
258
|
+
const textParts = contentParts.filter((p) => p.type === 'text').map((p) => p.text ?? '');
|
|
250
259
|
// Handle tool results - each needs its own message
|
|
251
260
|
if (toolResults.length > 0) {
|
|
252
261
|
for (const tr of toolResults) {
|
|
@@ -265,6 +274,13 @@ export class OpenAICompatibleProvider {
|
|
|
265
274
|
tool_calls: toolCallsList,
|
|
266
275
|
});
|
|
267
276
|
}
|
|
277
|
+
else if (hasImages) {
|
|
278
|
+
// Message with images — send as content parts array
|
|
279
|
+
result.push({
|
|
280
|
+
role: this.mapRole(msg.role),
|
|
281
|
+
content: contentParts,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
268
284
|
else if (textParts.length > 0) {
|
|
269
285
|
// Regular text message
|
|
270
286
|
result.push({
|
|
@@ -51,10 +51,26 @@ export interface ThinkingBlock {
|
|
|
51
51
|
*/
|
|
52
52
|
signature?: string;
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Image content block (user-attached or tool-provided image for vision)
|
|
56
|
+
*/
|
|
57
|
+
export interface ImageBlock {
|
|
58
|
+
type: 'image';
|
|
59
|
+
/** Base64-encoded image data */
|
|
60
|
+
data: string;
|
|
61
|
+
/** MIME type: image/png, image/jpeg, image/webp, image/gif */
|
|
62
|
+
mediaType: string;
|
|
63
|
+
/** Original filename (for display and observation masking placeholder) */
|
|
64
|
+
filename?: string;
|
|
65
|
+
/** Image width in pixels */
|
|
66
|
+
width?: number;
|
|
67
|
+
/** Image height in pixels */
|
|
68
|
+
height?: number;
|
|
69
|
+
}
|
|
54
70
|
/**
|
|
55
71
|
* Union of all content block types
|
|
56
72
|
*/
|
|
57
|
-
export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock;
|
|
73
|
+
export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock | ImageBlock;
|
|
58
74
|
/**
|
|
59
75
|
* A message in a conversation
|
|
60
76
|
*/
|
package/dist/tools/types.d.ts
CHANGED
|
@@ -24,6 +24,19 @@ export interface ToolExecutionResult {
|
|
|
24
24
|
success: boolean;
|
|
25
25
|
result?: unknown;
|
|
26
26
|
error?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Optional image blocks to inject alongside the tool result.
|
|
29
|
+
* When present, these are added as sibling content blocks in the
|
|
30
|
+
* tool result message, enabling vision-capable LLMs to see images.
|
|
31
|
+
* Used by tools like view_image that return visual content.
|
|
32
|
+
*/
|
|
33
|
+
imageBlocks?: Array<{
|
|
34
|
+
data: string;
|
|
35
|
+
mediaType: string;
|
|
36
|
+
filename?: string;
|
|
37
|
+
width?: number;
|
|
38
|
+
height?: number;
|
|
39
|
+
}>;
|
|
27
40
|
}
|
|
28
41
|
/**
|
|
29
42
|
* Context passed to tool execution for streaming output
|