@mcpmesh/sdk 0.9.12 → 1.0.0-beta.2
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/__tests__/llm-agent-media.test.d.ts +8 -0
- package/dist/__tests__/llm-agent-media.test.d.ts.map +1 -0
- package/dist/__tests__/llm-agent-media.test.js +167 -0
- package/dist/__tests__/llm-agent-media.test.js.map +1 -0
- package/dist/__tests__/media-helpers.test.d.ts +7 -0
- package/dist/__tests__/media-helpers.test.d.ts.map +1 -0
- package/dist/__tests__/media-helpers.test.js +60 -0
- package/dist/__tests__/media-helpers.test.js.map +1 -0
- package/dist/__tests__/media-param.test.d.ts +7 -0
- package/dist/__tests__/media-param.test.d.ts.map +1 -0
- package/dist/__tests__/media-param.test.js +104 -0
- package/dist/__tests__/media-param.test.js.map +1 -0
- package/dist/__tests__/media-resolver.test.d.ts +8 -0
- package/dist/__tests__/media-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/media-resolver.test.js +298 -0
- package/dist/__tests__/media-resolver.test.js.map +1 -0
- package/dist/__tests__/media-result.test.d.ts +5 -0
- package/dist/__tests__/media-result.test.d.ts.map +1 -0
- package/dist/__tests__/media-result.test.js +180 -0
- package/dist/__tests__/media-result.test.js.map +1 -0
- package/dist/__tests__/media-store.test.d.ts +7 -0
- package/dist/__tests__/media-store.test.d.ts.map +1 -0
- package/dist/__tests__/media-store.test.js +102 -0
- package/dist/__tests__/media-store.test.js.map +1 -0
- package/dist/__tests__/proxy-resource-link.test.d.ts +8 -0
- package/dist/__tests__/proxy-resource-link.test.d.ts.map +1 -0
- package/dist/__tests__/proxy-resource-link.test.js +175 -0
- package/dist/__tests__/proxy-resource-link.test.js.map +1 -0
- package/dist/agent.d.ts +1 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +76 -10
- package/dist/agent.js.map +1 -1
- package/dist/api-runtime.d.ts.map +1 -1
- package/dist/api-runtime.js +7 -1
- package/dist/api-runtime.js.map +1 -1
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -1
- package/dist/debug.d.ts +1 -1
- package/dist/debug.d.ts.map +1 -1
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +33 -18
- package/dist/express.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/llm-agent.d.ts.map +1 -1
- package/dist/llm-agent.js +44 -6
- package/dist/llm-agent.js.map +1 -1
- package/dist/llm-provider.d.ts +25 -7
- package/dist/llm-provider.d.ts.map +1 -1
- package/dist/llm-provider.js +104 -17
- package/dist/llm-provider.js.map +1 -1
- package/dist/media/index.d.ts +104 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +135 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/media-store.d.ts +75 -0
- package/dist/media/media-store.d.ts.map +1 -0
- package/dist/media/media-store.js +217 -0
- package/dist/media/media-store.js.map +1 -0
- package/dist/media/resolver.d.ts +67 -0
- package/dist/media/resolver.d.ts.map +1 -0
- package/dist/media/resolver.js +311 -0
- package/dist/media/resolver.js.map +1 -0
- package/dist/media-param.d.ts +17 -0
- package/dist/media-param.d.ts.map +1 -0
- package/dist/media-param.js +32 -0
- package/dist/media-param.js.map +1 -0
- package/dist/provider-handlers/provider-handler.d.ts.map +1 -1
- package/dist/provider-handlers/provider-handler.js +5 -4
- package/dist/provider-handlers/provider-handler.js.map +1 -1
- package/dist/proxy.d.ts +22 -1
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +65 -20
- package/dist/proxy.js.map +1 -1
- package/dist/tls-config.d.ts +31 -0
- package/dist/tls-config.d.ts.map +1 -0
- package/dist/tls-config.js +102 -0
- package/dist/tls-config.js.map +1 -0
- package/dist/types.d.ts +63 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +33 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MediaStore abstraction for multimodal content storage.
|
|
3
|
+
*
|
|
4
|
+
* Provides pluggable storage backends (local filesystem, S3) for
|
|
5
|
+
* binary media referenced by resource_link content items.
|
|
6
|
+
*/
|
|
7
|
+
import { resolveMediaConfig } from "../config.js";
|
|
8
|
+
/** Simple extension-to-MIME mapping for common types. */
|
|
9
|
+
const MIME_MAP = {
|
|
10
|
+
".png": "image/png",
|
|
11
|
+
".jpg": "image/jpeg",
|
|
12
|
+
".jpeg": "image/jpeg",
|
|
13
|
+
".gif": "image/gif",
|
|
14
|
+
".webp": "image/webp",
|
|
15
|
+
".svg": "image/svg+xml",
|
|
16
|
+
".mp3": "audio/mpeg",
|
|
17
|
+
".wav": "audio/wav",
|
|
18
|
+
".mp4": "video/mp4",
|
|
19
|
+
".webm": "video/webm",
|
|
20
|
+
".pdf": "application/pdf",
|
|
21
|
+
".json": "application/json",
|
|
22
|
+
".txt": "text/plain",
|
|
23
|
+
".html": "text/html",
|
|
24
|
+
".css": "text/css",
|
|
25
|
+
".csv": "text/csv",
|
|
26
|
+
".md": "text/markdown",
|
|
27
|
+
};
|
|
28
|
+
/** Guess MIME type from a filename extension. Falls back to application/octet-stream. */
|
|
29
|
+
export function guessMimeType(filename) {
|
|
30
|
+
const ext = filename.slice(filename.lastIndexOf(".")).toLowerCase();
|
|
31
|
+
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Local filesystem media store.
|
|
35
|
+
*
|
|
36
|
+
* Stores files under a configurable base path and returns `file://` URIs.
|
|
37
|
+
*/
|
|
38
|
+
export class LocalMediaStore {
|
|
39
|
+
basePath;
|
|
40
|
+
prefix;
|
|
41
|
+
constructor(basePath, prefix) {
|
|
42
|
+
const cfg = resolveMediaConfig();
|
|
43
|
+
this.basePath = basePath ?? cfg.storagePath;
|
|
44
|
+
this.prefix = prefix ?? cfg.storagePrefix;
|
|
45
|
+
}
|
|
46
|
+
async validatePath(filePath) {
|
|
47
|
+
const { resolve } = await import("node:path");
|
|
48
|
+
const resolved = resolve(filePath);
|
|
49
|
+
if (!resolved.startsWith(resolve(this.basePath))) {
|
|
50
|
+
throw new Error(`Invalid filename (path traversal): ${filePath}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async upload(data, filename, _mimeType) {
|
|
54
|
+
const { mkdir, writeFile } = await import("node:fs/promises");
|
|
55
|
+
const { join } = await import("node:path");
|
|
56
|
+
const dir = join(this.basePath, this.prefix);
|
|
57
|
+
await mkdir(dir, { recursive: true });
|
|
58
|
+
const filePath = join(dir, filename);
|
|
59
|
+
await this.validatePath(filePath);
|
|
60
|
+
await writeFile(filePath, data);
|
|
61
|
+
return `file://${filePath}`;
|
|
62
|
+
}
|
|
63
|
+
async fetch(uri) {
|
|
64
|
+
const { readFile } = await import("node:fs/promises");
|
|
65
|
+
const filePath = uri.startsWith("file://") ? uri.slice(7) : uri;
|
|
66
|
+
await this.validatePath(filePath);
|
|
67
|
+
const data = await readFile(filePath);
|
|
68
|
+
const mimeType = guessMimeType(filePath);
|
|
69
|
+
return { data: Buffer.from(data), mimeType };
|
|
70
|
+
}
|
|
71
|
+
async exists(uri) {
|
|
72
|
+
const { access } = await import("node:fs/promises");
|
|
73
|
+
const filePath = uri.startsWith("file://") ? uri.slice(7) : uri;
|
|
74
|
+
try {
|
|
75
|
+
await this.validatePath(filePath);
|
|
76
|
+
await access(filePath);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* S3-compatible media store.
|
|
86
|
+
*
|
|
87
|
+
* Uses lazy imports for @aws-sdk/client-s3 so it is only required
|
|
88
|
+
* when storage is configured as "s3".
|
|
89
|
+
*/
|
|
90
|
+
export class S3MediaStore {
|
|
91
|
+
bucket;
|
|
92
|
+
endpoint;
|
|
93
|
+
prefix;
|
|
94
|
+
// Lazily initialised S3 client
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
_client = null;
|
|
97
|
+
constructor(bucket, endpoint, prefix) {
|
|
98
|
+
const cfg = resolveMediaConfig();
|
|
99
|
+
this.bucket = bucket ?? cfg.storageBucket ?? "mcp-mesh-media";
|
|
100
|
+
this.endpoint = endpoint ?? cfg.storageEndpoint;
|
|
101
|
+
this.prefix = prefix ?? cfg.storagePrefix;
|
|
102
|
+
}
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
async getClient() {
|
|
105
|
+
if (this._client)
|
|
106
|
+
return this._client;
|
|
107
|
+
// Lazy import - @aws-sdk/client-s3 is NOT a required dependency.
|
|
108
|
+
// Uses variable to prevent TypeScript from resolving the module at compile time.
|
|
109
|
+
const s3ModuleName = "@aws-sdk/client-s3";
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
|
+
const s3Module = await import(/* webpackIgnore: true */ s3ModuleName);
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
113
|
+
const opts = {};
|
|
114
|
+
if (this.endpoint) {
|
|
115
|
+
opts.endpoint = this.endpoint;
|
|
116
|
+
opts.forcePathStyle = true;
|
|
117
|
+
}
|
|
118
|
+
this._client = new s3Module.S3Client(opts);
|
|
119
|
+
return this._client;
|
|
120
|
+
}
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
async loadS3Module() {
|
|
123
|
+
const name = "@aws-sdk/client-s3";
|
|
124
|
+
return import(/* webpackIgnore: true */ name);
|
|
125
|
+
}
|
|
126
|
+
async upload(data, filename, mimeType) {
|
|
127
|
+
const s3Module = await this.loadS3Module();
|
|
128
|
+
const client = await this.getClient();
|
|
129
|
+
const key = `${this.prefix}${filename}`;
|
|
130
|
+
await client.send(new s3Module.PutObjectCommand({
|
|
131
|
+
Bucket: this.bucket,
|
|
132
|
+
Key: key,
|
|
133
|
+
Body: data,
|
|
134
|
+
ContentType: mimeType,
|
|
135
|
+
}));
|
|
136
|
+
return `s3://${this.bucket}/${key}`;
|
|
137
|
+
}
|
|
138
|
+
async fetch(uri) {
|
|
139
|
+
const s3Module = await this.loadS3Module();
|
|
140
|
+
const client = await this.getClient();
|
|
141
|
+
const { bucket, key } = this.parseUri(uri);
|
|
142
|
+
const response = await client.send(new s3Module.GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
143
|
+
const body = await response.Body?.transformToByteArray();
|
|
144
|
+
if (!body)
|
|
145
|
+
throw new Error(`Empty body for ${uri}`);
|
|
146
|
+
return {
|
|
147
|
+
data: Buffer.from(body),
|
|
148
|
+
mimeType: response.ContentType ?? guessMimeType(key),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async exists(uri) {
|
|
152
|
+
const s3Module = await this.loadS3Module();
|
|
153
|
+
const client = await this.getClient();
|
|
154
|
+
const { bucket, key } = this.parseUri(uri);
|
|
155
|
+
try {
|
|
156
|
+
await client.send(new s3Module.HeadObjectCommand({ Bucket: bucket, Key: key }));
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
// Only treat "not found" as false; re-throw real errors
|
|
161
|
+
if (err instanceof Error &&
|
|
162
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
163
|
+
(err.name === "NotFound" || err.$metadata?.httpStatusCode === 404)) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
parseUri(uri) {
|
|
170
|
+
if (uri.startsWith("s3://")) {
|
|
171
|
+
const withoutScheme = uri.slice(5);
|
|
172
|
+
const slashIdx = withoutScheme.indexOf("/");
|
|
173
|
+
if (slashIdx === -1) {
|
|
174
|
+
return { bucket: withoutScheme, key: "" };
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
bucket: withoutScheme.slice(0, slashIdx),
|
|
178
|
+
key: withoutScheme.slice(slashIdx + 1),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// Assume key-only, use configured bucket
|
|
182
|
+
return { bucket: this.bucket, key: uri };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
// Singleton factory
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
let _instance = null;
|
|
189
|
+
/**
|
|
190
|
+
* Get (or create) the singleton MediaStore based on configuration.
|
|
191
|
+
*
|
|
192
|
+
* Reads `media_storage` config key (env: `MCP_MESH_MEDIA_STORAGE`).
|
|
193
|
+
* - `"local"` (default) -> LocalMediaStore
|
|
194
|
+
* - `"s3"` -> S3MediaStore
|
|
195
|
+
*/
|
|
196
|
+
export function getMediaStore() {
|
|
197
|
+
if (_instance)
|
|
198
|
+
return _instance;
|
|
199
|
+
const cfg = resolveMediaConfig();
|
|
200
|
+
switch (cfg.storage) {
|
|
201
|
+
case "s3":
|
|
202
|
+
_instance = new S3MediaStore();
|
|
203
|
+
break;
|
|
204
|
+
default:
|
|
205
|
+
_instance = new LocalMediaStore();
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
return _instance;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Reset the singleton (mainly for testing).
|
|
212
|
+
* @internal
|
|
213
|
+
*/
|
|
214
|
+
export function _resetMediaStore() {
|
|
215
|
+
_instance = null;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=media-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-store.js","sourceRoot":"","sources":["../../src/media/media-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve resource_link URIs to provider-native multimodal content.
|
|
3
|
+
*
|
|
4
|
+
* When an LLM provider calls a tool that returns a resource_link (e.g., an image URI),
|
|
5
|
+
* the LLM currently sees just a JSON string. This module resolves the URI to base64
|
|
6
|
+
* media in provider-native format so the LLM can actually "see" the image.
|
|
7
|
+
*
|
|
8
|
+
* Based on Python's resolver:
|
|
9
|
+
* src/runtime/python/_mcp_mesh/media/resolver.py
|
|
10
|
+
*/
|
|
11
|
+
export interface ResolvedContent {
|
|
12
|
+
type: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
export declare function formatForOpenai(b64: string, mimeType: string): ResolvedContent;
|
|
16
|
+
/**
|
|
17
|
+
* Scan tool result for resource_link items and resolve to provider-native format.
|
|
18
|
+
*
|
|
19
|
+
* Returns a list of content parts for the LLM message.
|
|
20
|
+
* - For image resource_links: fetches bytes, base64 encodes, formats per vendor
|
|
21
|
+
* - For non-image or non-resource_link: wraps in text content
|
|
22
|
+
*
|
|
23
|
+
* @param toolResult - The raw tool result (could be object, string, etc.)
|
|
24
|
+
* @param vendor - One of "anthropic", "openai", "gemini", "google"
|
|
25
|
+
* @returns List of content dicts suitable for provider-specific message content arrays
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveResourceLinks(toolResult: unknown, vendor: string): Promise<ResolvedContent[]>;
|
|
28
|
+
/** Vendors that do NOT support images in tool/function result messages. */
|
|
29
|
+
export declare const TOOL_IMAGE_UNSUPPORTED_VENDORS: Set<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Resolve resource_links for inclusion in a tool result message.
|
|
32
|
+
*
|
|
33
|
+
* For vendors that support images in tool messages (Anthropic/Claude),
|
|
34
|
+
* returns the full multimodal content (text + image parts).
|
|
35
|
+
*
|
|
36
|
+
* For vendors that do NOT support images in tool messages (OpenAI, Gemini),
|
|
37
|
+
* returns text-only content with descriptive placeholders. The actual image
|
|
38
|
+
* should be injected via a separate user message using
|
|
39
|
+
* `resolveMediaAsUserMessage()`.
|
|
40
|
+
*
|
|
41
|
+
* @param toolResult - Raw tool result
|
|
42
|
+
* @param vendor - e.g. "anthropic", "openai", "gemini"
|
|
43
|
+
* @returns Content parts suitable for a tool result message
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveResourceLinksForToolMessage(toolResult: unknown, vendor: string): Promise<ResolvedContent[]>;
|
|
46
|
+
/**
|
|
47
|
+
* Return a user message containing resolved images from a tool result.
|
|
48
|
+
*
|
|
49
|
+
* For vendors that do NOT support images in tool messages (OpenAI, Gemini),
|
|
50
|
+
* resolves resource_link items and packages the image parts into a
|
|
51
|
+
* `role: "user"` message that can be appended after the tool result message.
|
|
52
|
+
*
|
|
53
|
+
* For vendors that support images in tool messages (Anthropic), returns null.
|
|
54
|
+
*
|
|
55
|
+
* @param toolResult - Raw tool result
|
|
56
|
+
* @param vendor - e.g. "anthropic", "openai", "gemini"
|
|
57
|
+
* @returns A user message object with image content, or null
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveMediaAsUserMessage(toolResult: unknown, vendor: string): Promise<Record<string, unknown> | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Quick check whether a tool result contains any resource_link items.
|
|
62
|
+
*
|
|
63
|
+
* This is a lightweight synchronous check used to decide whether the
|
|
64
|
+
* more expensive async resolution is needed.
|
|
65
|
+
*/
|
|
66
|
+
export declare function hasResourceLink(toolResult: unknown): boolean;
|
|
67
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/media/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAaD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAQ9E;AAwID;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,EAAE,CAAC,CA+D5B;AAED,2EAA2E;AAC3E,eAAO,MAAM,8BAA8B,aAA0C,CAAC;AAEtF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kCAAkC,CACtD,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAoBzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAoB5D"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve resource_link URIs to provider-native multimodal content.
|
|
3
|
+
*
|
|
4
|
+
* When an LLM provider calls a tool that returns a resource_link (e.g., an image URI),
|
|
5
|
+
* the LLM currently sees just a JSON string. This module resolves the URI to base64
|
|
6
|
+
* media in provider-native format so the LLM can actually "see" the image.
|
|
7
|
+
*
|
|
8
|
+
* Based on Python's resolver:
|
|
9
|
+
* src/runtime/python/_mcp_mesh/media/resolver.py
|
|
10
|
+
*/
|
|
11
|
+
import { createDebug } from "../debug.js";
|
|
12
|
+
import { getMediaStore } from "./media-store.js";
|
|
13
|
+
const debug = createDebug("media-resolver");
|
|
14
|
+
const IMAGE_MIME_TYPES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
|
|
15
|
+
const PDF_MIME_TYPES = new Set(["application/pdf"]);
|
|
16
|
+
const TEXT_MIME_TYPES = new Set([
|
|
17
|
+
"text/plain",
|
|
18
|
+
"text/csv",
|
|
19
|
+
"text/markdown",
|
|
20
|
+
"text/html",
|
|
21
|
+
"text/xml",
|
|
22
|
+
"application/json",
|
|
23
|
+
"application/xml",
|
|
24
|
+
"application/csv",
|
|
25
|
+
]);
|
|
26
|
+
function formatForClaude(b64, mimeType) {
|
|
27
|
+
return {
|
|
28
|
+
type: "image",
|
|
29
|
+
source: {
|
|
30
|
+
type: "base64",
|
|
31
|
+
media_type: mimeType,
|
|
32
|
+
data: b64,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function formatForOpenai(b64, mimeType) {
|
|
37
|
+
return {
|
|
38
|
+
type: "image_url",
|
|
39
|
+
image_url: {
|
|
40
|
+
url: `data:${mimeType};base64,${b64}`,
|
|
41
|
+
detail: "high",
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function formatForGemini(b64, mimeType) {
|
|
46
|
+
// Vercel AI SDK handles Gemini images via OpenAI-compatible format
|
|
47
|
+
return formatForOpenai(b64, mimeType);
|
|
48
|
+
}
|
|
49
|
+
const VENDOR_FORMATTERS = {
|
|
50
|
+
anthropic: formatForClaude,
|
|
51
|
+
openai: formatForOpenai,
|
|
52
|
+
gemini: formatForGemini,
|
|
53
|
+
google: formatForGemini,
|
|
54
|
+
};
|
|
55
|
+
function formatPdfForClaude(b64) {
|
|
56
|
+
return {
|
|
57
|
+
type: "document",
|
|
58
|
+
source: {
|
|
59
|
+
type: "base64",
|
|
60
|
+
media_type: "application/pdf",
|
|
61
|
+
data: b64,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function formatPdfForOpenai(_b64, filename) {
|
|
66
|
+
return {
|
|
67
|
+
type: "text",
|
|
68
|
+
text: `[Attached PDF document: ${filename}. OpenAI does not support PDF analysis. Please use Claude for PDF processing.]`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function formatPdfForGemini(_b64, filename) {
|
|
72
|
+
return {
|
|
73
|
+
type: "text",
|
|
74
|
+
text: `[Attached PDF document: ${filename}. Gemini PDF support via LiteLLM may vary.]`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function formatTextContent(data, mimeType, filename) {
|
|
78
|
+
let text;
|
|
79
|
+
try {
|
|
80
|
+
text = data.toString("utf-8");
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
text = data.toString("latin1");
|
|
84
|
+
}
|
|
85
|
+
const maxChars = 50_000;
|
|
86
|
+
if (text.length > maxChars) {
|
|
87
|
+
text = text.slice(0, maxChars) + `\n\n[... truncated, ${text.length} total characters]`;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
type: "text",
|
|
91
|
+
text: `--- Content of ${filename} (${mimeType}) ---\n${text}\n--- End of ${filename} ---`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolve a single resource_link dict to a provider-native content part.
|
|
96
|
+
*
|
|
97
|
+
* @param resourceLink - Dict with type "resource_link" and either flat or nested resource fields
|
|
98
|
+
* @param vendor - One of "anthropic", "openai", "gemini", "google"
|
|
99
|
+
* @returns Provider-native content dict (image block or text fallback)
|
|
100
|
+
*/
|
|
101
|
+
async function resolveSingleResourceLink(resourceLink, vendor) {
|
|
102
|
+
// Support both flat format and nested resource sub-object
|
|
103
|
+
const resource = (resourceLink.resource ?? {});
|
|
104
|
+
const uri = (resource.uri ?? resourceLink.uri ?? "");
|
|
105
|
+
const mimeType = (resource.mimeType ?? resourceLink.mimeType ?? "");
|
|
106
|
+
const name = (resource.name ?? resourceLink.name ?? uri);
|
|
107
|
+
// --- Images: existing behaviour ---
|
|
108
|
+
if (IMAGE_MIME_TYPES.has(mimeType)) {
|
|
109
|
+
try {
|
|
110
|
+
const store = getMediaStore();
|
|
111
|
+
const { data, mimeType: fetchedMime } = await store.fetch(uri);
|
|
112
|
+
const b64 = data.toString("base64");
|
|
113
|
+
const formatter = VENDOR_FORMATTERS[vendor] ?? formatForOpenai;
|
|
114
|
+
const result = formatter(b64, mimeType || fetchedMime);
|
|
115
|
+
debug(`Resolved resource_link ${name} to ${vendor} image block (${data.length} bytes)`);
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
120
|
+
debug(`Failed to fetch resource_link ${uri}: ${errMsg}`);
|
|
121
|
+
return {
|
|
122
|
+
type: "text",
|
|
123
|
+
text: `[resource_link: ${name} (${mimeType || "unknown"}) at ${uri} (fetch failed)]`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// --- PDFs: provider-specific ---
|
|
128
|
+
if (PDF_MIME_TYPES.has(mimeType)) {
|
|
129
|
+
try {
|
|
130
|
+
const store = getMediaStore();
|
|
131
|
+
const { data } = await store.fetch(uri);
|
|
132
|
+
const b64 = data.toString("base64");
|
|
133
|
+
if (vendor === "anthropic" || vendor === "claude") {
|
|
134
|
+
return formatPdfForClaude(b64);
|
|
135
|
+
}
|
|
136
|
+
else if (vendor === "gemini" || vendor === "google") {
|
|
137
|
+
return formatPdfForGemini(b64, name);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return formatPdfForOpenai(b64, name);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
145
|
+
debug(`Failed to fetch PDF ${uri}: ${errMsg}`);
|
|
146
|
+
return { type: "text", text: `[PDF document: ${name} at ${uri}]` };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// --- Text files: read content and include as text (all providers) ---
|
|
150
|
+
if (TEXT_MIME_TYPES.has(mimeType) || mimeType.startsWith("text/")) {
|
|
151
|
+
try {
|
|
152
|
+
const store = getMediaStore();
|
|
153
|
+
const { data } = await store.fetch(uri);
|
|
154
|
+
return formatTextContent(data, mimeType, name);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
158
|
+
debug(`Failed to fetch text file ${uri}: ${errMsg}`);
|
|
159
|
+
return { type: "text", text: `[Text document: ${name} at ${uri}]` };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// --- Unknown / unsupported MIME type ---
|
|
163
|
+
return {
|
|
164
|
+
type: "text",
|
|
165
|
+
text: `[resource_link: ${name} (${mimeType || "unknown"}) at ${uri}]`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Scan tool result for resource_link items and resolve to provider-native format.
|
|
170
|
+
*
|
|
171
|
+
* Returns a list of content parts for the LLM message.
|
|
172
|
+
* - For image resource_links: fetches bytes, base64 encodes, formats per vendor
|
|
173
|
+
* - For non-image or non-resource_link: wraps in text content
|
|
174
|
+
*
|
|
175
|
+
* @param toolResult - The raw tool result (could be object, string, etc.)
|
|
176
|
+
* @param vendor - One of "anthropic", "openai", "gemini", "google"
|
|
177
|
+
* @returns List of content dicts suitable for provider-specific message content arrays
|
|
178
|
+
*/
|
|
179
|
+
export async function resolveResourceLinks(toolResult, vendor) {
|
|
180
|
+
// resource_link dict
|
|
181
|
+
if (toolResult &&
|
|
182
|
+
typeof toolResult === "object" &&
|
|
183
|
+
toolResult.type === "resource_link") {
|
|
184
|
+
const part = await resolveSingleResourceLink(toolResult, vendor);
|
|
185
|
+
return [part];
|
|
186
|
+
}
|
|
187
|
+
// multi_content dict (from extractContent in proxy.ts)
|
|
188
|
+
if (toolResult &&
|
|
189
|
+
typeof toolResult === "object" &&
|
|
190
|
+
toolResult.type === "multi_content") {
|
|
191
|
+
const obj = toolResult;
|
|
192
|
+
const items = (obj.items ?? obj.content ?? []);
|
|
193
|
+
const parts = [];
|
|
194
|
+
for (const item of items) {
|
|
195
|
+
if (item &&
|
|
196
|
+
typeof item === "object" &&
|
|
197
|
+
item.type === "resource_link") {
|
|
198
|
+
parts.push(await resolveSingleResourceLink(item, vendor));
|
|
199
|
+
}
|
|
200
|
+
else if (typeof item === "string") {
|
|
201
|
+
parts.push({ type: "text", text: item });
|
|
202
|
+
}
|
|
203
|
+
else if (item && typeof item === "object") {
|
|
204
|
+
// Non-resource_link objects (e.g., text items) — preserve or serialize
|
|
205
|
+
const itemObj = item;
|
|
206
|
+
if (itemObj.type === "text" && typeof itemObj.text === "string") {
|
|
207
|
+
parts.push({ type: "text", text: itemObj.text });
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
parts.push({ type: "text", text: JSON.stringify(item) });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
parts.push({ type: "text", text: String(item) });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return parts;
|
|
218
|
+
}
|
|
219
|
+
// Plain string
|
|
220
|
+
if (typeof toolResult === "string") {
|
|
221
|
+
return [{ type: "text", text: toolResult }];
|
|
222
|
+
}
|
|
223
|
+
// Anything else (dict without resource_link type, number, etc.)
|
|
224
|
+
try {
|
|
225
|
+
const text = JSON.stringify(toolResult);
|
|
226
|
+
return [{ type: "text", text }];
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return [{ type: "text", text: String(toolResult) }];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/** Vendors that do NOT support images in tool/function result messages. */
|
|
233
|
+
export const TOOL_IMAGE_UNSUPPORTED_VENDORS = new Set(["openai", "gemini", "google"]);
|
|
234
|
+
/**
|
|
235
|
+
* Resolve resource_links for inclusion in a tool result message.
|
|
236
|
+
*
|
|
237
|
+
* For vendors that support images in tool messages (Anthropic/Claude),
|
|
238
|
+
* returns the full multimodal content (text + image parts).
|
|
239
|
+
*
|
|
240
|
+
* For vendors that do NOT support images in tool messages (OpenAI, Gemini),
|
|
241
|
+
* returns text-only content with descriptive placeholders. The actual image
|
|
242
|
+
* should be injected via a separate user message using
|
|
243
|
+
* `resolveMediaAsUserMessage()`.
|
|
244
|
+
*
|
|
245
|
+
* @param toolResult - Raw tool result
|
|
246
|
+
* @param vendor - e.g. "anthropic", "openai", "gemini"
|
|
247
|
+
* @returns Content parts suitable for a tool result message
|
|
248
|
+
*/
|
|
249
|
+
export async function resolveResourceLinksForToolMessage(toolResult, vendor) {
|
|
250
|
+
if (!TOOL_IMAGE_UNSUPPORTED_VENDORS.has(vendor)) {
|
|
251
|
+
return resolveResourceLinks(toolResult, vendor);
|
|
252
|
+
}
|
|
253
|
+
const parts = await resolveResourceLinks(toolResult, vendor);
|
|
254
|
+
return parts.map((part) => {
|
|
255
|
+
if (part.type === "image" || part.type === "image_url") {
|
|
256
|
+
return { type: "text", text: "[Image content — see next message]" };
|
|
257
|
+
}
|
|
258
|
+
return part;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Return a user message containing resolved images from a tool result.
|
|
263
|
+
*
|
|
264
|
+
* For vendors that do NOT support images in tool messages (OpenAI, Gemini),
|
|
265
|
+
* resolves resource_link items and packages the image parts into a
|
|
266
|
+
* `role: "user"` message that can be appended after the tool result message.
|
|
267
|
+
*
|
|
268
|
+
* For vendors that support images in tool messages (Anthropic), returns null.
|
|
269
|
+
*
|
|
270
|
+
* @param toolResult - Raw tool result
|
|
271
|
+
* @param vendor - e.g. "anthropic", "openai", "gemini"
|
|
272
|
+
* @returns A user message object with image content, or null
|
|
273
|
+
*/
|
|
274
|
+
export async function resolveMediaAsUserMessage(toolResult, vendor) {
|
|
275
|
+
if (!TOOL_IMAGE_UNSUPPORTED_VENDORS.has(vendor)) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
const parts = await resolveResourceLinks(toolResult, vendor);
|
|
279
|
+
const imageParts = parts.filter((p) => p.type === "image" || p.type === "image_url");
|
|
280
|
+
if (imageParts.length === 0) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
role: "user",
|
|
285
|
+
content: [
|
|
286
|
+
{ type: "text", text: "The tool returned this image:" },
|
|
287
|
+
...imageParts,
|
|
288
|
+
],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Quick check whether a tool result contains any resource_link items.
|
|
293
|
+
*
|
|
294
|
+
* This is a lightweight synchronous check used to decide whether the
|
|
295
|
+
* more expensive async resolution is needed.
|
|
296
|
+
*/
|
|
297
|
+
export function hasResourceLink(toolResult) {
|
|
298
|
+
if (!toolResult || typeof toolResult !== "object") {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
const obj = toolResult;
|
|
302
|
+
if (obj.type === "resource_link") {
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
if (obj.type === "multi_content") {
|
|
306
|
+
const items = (obj.items ?? obj.content ?? []);
|
|
307
|
+
return items.some((i) => i && typeof i === "object" && i.type === "resource_link");
|
|
308
|
+
}
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/media/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema post-processing for media-typed tool parameters.
|
|
3
|
+
*
|
|
4
|
+
* Detects the "[media:TYPE]" convention in property descriptions
|
|
5
|
+
* (set by mediaParam() in types.ts) and enriches the JSON Schema
|
|
6
|
+
* with x-media-type annotations for LLM tool discovery.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Post-process a JSON Schema to enrich properties that use the
|
|
10
|
+
* [media:TYPE] description convention with x-media-type annotations.
|
|
11
|
+
*
|
|
12
|
+
* Modifies the schema in place.
|
|
13
|
+
*
|
|
14
|
+
* @param schema - JSON Schema object (from zodToJsonSchema)
|
|
15
|
+
*/
|
|
16
|
+
export declare function enrichSchemaWithMediaTypes(schema: Record<string, unknown>): void;
|
|
17
|
+
//# sourceMappingURL=media-param.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-param.d.ts","sourceRoot":"","sources":["../src/media-param.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAgBhF"}
|