@rynx-ai/runtime 0.1.11-beta.48 → 0.1.11-beta.49
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.
|
@@ -32,19 +32,24 @@ function strippedImagePlaceholder(source) {
|
|
|
32
32
|
* history. A Read image result can contain a full-resolution base64 payload;
|
|
33
33
|
* replaying it as text only bloats the transcript, while the model cannot use
|
|
34
34
|
* those encoded bytes as text. Keep a small, human-readable marker instead. */
|
|
35
|
-
function stripInlineImageData(value) {
|
|
35
|
+
function stripInlineImageData(value, preview) {
|
|
36
36
|
if (Array.isArray(value))
|
|
37
|
-
return value.map(stripInlineImageData);
|
|
37
|
+
return value.map((part) => stripInlineImageData(part, preview));
|
|
38
38
|
if (!isObject(value))
|
|
39
39
|
return value;
|
|
40
40
|
const source = isObject(value.source) ? value.source : undefined;
|
|
41
41
|
if (value.type === "image" && source) {
|
|
42
|
-
return {
|
|
42
|
+
return {
|
|
43
|
+
type: "text",
|
|
44
|
+
text: value === preview
|
|
45
|
+
? `[${source.media_type} image attached]`
|
|
46
|
+
: strippedImagePlaceholder(source),
|
|
47
|
+
};
|
|
43
48
|
}
|
|
44
|
-
return Object.fromEntries(Object.entries(value).map(([key, nested]) => [key, stripInlineImageData(nested)]));
|
|
49
|
+
return Object.fromEntries(Object.entries(value).map(([key, nested]) => [key, stripInlineImageData(nested, preview)]));
|
|
45
50
|
}
|
|
46
|
-
function stringifyToolContent(content) {
|
|
47
|
-
const stripped = stripInlineImageData(content);
|
|
51
|
+
function stringifyToolContent(content, preview) {
|
|
52
|
+
const stripped = stripInlineImageData(content, preview);
|
|
48
53
|
if (typeof stripped === "string")
|
|
49
54
|
return stripped;
|
|
50
55
|
if (Array.isArray(stripped)) {
|
|
@@ -58,6 +63,25 @@ function stringifyToolContent(content) {
|
|
|
58
63
|
}
|
|
59
64
|
return stripped == null ? "" : JSON.stringify(stripped);
|
|
60
65
|
}
|
|
66
|
+
/** Native Read returns inline image bytes, sometimes transcoded from the file.
|
|
67
|
+
* Reuse the tool-image resource pipeline so the preview preserves those bytes
|
|
68
|
+
* while the canonical output text stays small. Remaining images keep markers
|
|
69
|
+
* until the shared tool-output contract supports more than one preview. */
|
|
70
|
+
function inlineImagePreview(content) {
|
|
71
|
+
if (!Array.isArray(content))
|
|
72
|
+
return undefined;
|
|
73
|
+
for (const block of content) {
|
|
74
|
+
if (!isObject(block) || block.type !== "image" || !isObject(block.source))
|
|
75
|
+
continue;
|
|
76
|
+
const { type, media_type: mediaType, data } = block.source;
|
|
77
|
+
if (type === "base64" &&
|
|
78
|
+
typeof mediaType === "string" && /^image\/[a-z0-9+.-]+$/i.test(mediaType) &&
|
|
79
|
+
typeof data === "string" && /^[A-Za-z0-9+/]+={0,2}$/.test(data)) {
|
|
80
|
+
return { block, result: `data:${mediaType};base64,${data}` };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
61
85
|
const BASH_INPUT_RE = /<bash-input>([\s\S]*?)<\/bash-input>/;
|
|
62
86
|
const BASH_STDOUT_RE = /<bash-stdout>([\s\S]*?)<\/bash-stdout>/;
|
|
63
87
|
const BASH_STDERR_RE = /<bash-stderr>([\s\S]*?)<\/bash-stderr>/;
|
|
@@ -188,14 +212,16 @@ export function parseTranscriptRecord(record, opts) {
|
|
|
188
212
|
return [];
|
|
189
213
|
for (const block of message.content) {
|
|
190
214
|
if (block.type === "tool_result") {
|
|
215
|
+
const preview = block.is_error ? undefined : inlineImagePreview(block.content);
|
|
191
216
|
out.push({
|
|
192
217
|
type: "tool",
|
|
193
218
|
event: "on_tool_end",
|
|
194
219
|
output: {
|
|
195
220
|
id: block.tool_use_id,
|
|
196
221
|
status: block.is_error ? "failed" : "completed",
|
|
197
|
-
aggregatedOutput: stringifyToolContent(block.content),
|
|
222
|
+
aggregatedOutput: stringifyToolContent(block.content, preview?.block),
|
|
198
223
|
exitCode: null,
|
|
224
|
+
...(preview ? { generatedImage: { result: preview.result } } : {}),
|
|
199
225
|
},
|
|
200
226
|
...(block.is_error ? { error: "tool_error" } : {}),
|
|
201
227
|
data: { tool_use_id: block.tool_use_id, itemStatus: "completed" },
|
|
@@ -249,6 +249,28 @@ export function mapCodexItem(method, item) {
|
|
|
249
249
|
});
|
|
250
250
|
return { events };
|
|
251
251
|
}
|
|
252
|
+
case "imageView": {
|
|
253
|
+
const image = item;
|
|
254
|
+
if (typeof image.id !== "string" || !image.id ||
|
|
255
|
+
typeof image.path !== "string" || !image.path)
|
|
256
|
+
return { events };
|
|
257
|
+
events.push({
|
|
258
|
+
type: "tool",
|
|
259
|
+
event: isStart ? "on_tool_start" : "on_tool_end",
|
|
260
|
+
name: "view_image",
|
|
261
|
+
// Image views may arrive only as completed items, including backfill.
|
|
262
|
+
input: isStart || isEnd ? { id: image.id, path: image.path } : undefined,
|
|
263
|
+
output: isEnd
|
|
264
|
+
? {
|
|
265
|
+
id: image.id,
|
|
266
|
+
aggregatedOutput: `Viewed image at ${image.path}`,
|
|
267
|
+
generatedImage: { savedPath: image.path },
|
|
268
|
+
}
|
|
269
|
+
: undefined,
|
|
270
|
+
data: { method, item },
|
|
271
|
+
});
|
|
272
|
+
return { events };
|
|
273
|
+
}
|
|
252
274
|
case "imageGeneration": {
|
|
253
275
|
const image = item;
|
|
254
276
|
events.push({
|
|
@@ -298,7 +298,11 @@ export interface ImageGenerationItem extends ThreadItemBase {
|
|
|
298
298
|
/** Codex App Server guarantees this is absolute when present. */
|
|
299
299
|
savedPath?: string;
|
|
300
300
|
}
|
|
301
|
-
export
|
|
301
|
+
export interface ImageViewItem extends ThreadItemBase {
|
|
302
|
+
type: "imageView";
|
|
303
|
+
path: string;
|
|
304
|
+
}
|
|
305
|
+
export type ThreadItem = UserMessageItem | AgentMessageItem | ReasoningItem | PlanItem | CommandExecutionItem | FileChangeItem | McpToolCallItem | DynamicToolCallItem | WebSearchItem | ImageGenerationItem | ImageViewItem | (ThreadItemBase & Record<string, unknown>);
|
|
302
306
|
export interface ThreadSummary {
|
|
303
307
|
id?: string;
|
|
304
308
|
threadId?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/runtime",
|
|
3
|
-
"version": "0.1.11-beta.
|
|
3
|
+
"version": "0.1.11-beta.49",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"smol-toml": "1.7.1",
|
|
28
28
|
"ws": "^8.21.0",
|
|
29
|
-
"@rynx-ai/core": "0.1.11-beta.
|
|
29
|
+
"@rynx-ai/core": "0.1.11-beta.49"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/ws": "^8.18.1"
|