@avclabs.ai/media-mcp 0.2.1 → 0.3.0
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/README.md +245 -31
- package/README_CN.md +246 -32
- package/config.json +1 -0
- package/dist/image-enhancement.d.ts +3 -0
- package/dist/image-enhancement.d.ts.map +1 -0
- package/dist/image-enhancement.js +185 -0
- package/dist/image-enhancement.js.map +1 -0
- package/dist/sam3.d.ts +7 -0
- package/dist/sam3.d.ts.map +1 -1
- package/dist/sam3.js +148 -104
- package/dist/sam3.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +77 -53
- package/dist/server.js.map +1 -1
- package/dist/service-config.d.ts +62 -0
- package/dist/service-config.d.ts.map +1 -0
- package/dist/service-config.js +58 -0
- package/dist/service-config.js.map +1 -0
- package/dist/tooling.d.ts +42 -0
- package/dist/tooling.d.ts.map +1 -0
- package/dist/tooling.js +153 -0
- package/dist/tooling.js.map +1 -0
- package/dist/tos.d.ts +35 -0
- package/dist/tos.d.ts.map +1 -0
- package/dist/tos.js +281 -0
- package/dist/tos.js.map +1 -0
- package/dist/upload.d.ts +79 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +190 -0
- package/dist/upload.js.map +1 -0
- package/dist/video-enhancement.d.ts.map +1 -1
- package/dist/video-enhancement.js +73 -153
- package/dist/video-enhancement.js.map +1 -1
- package/package.json +10 -5
package/dist/sam3.js
CHANGED
|
@@ -2,12 +2,17 @@ import axios from 'axios';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import
|
|
5
|
+
import { checkLocalFile, decodeBase64Image, downloadToBuffer, parseTosSignature, unwrapEnvelope, uploadToTos, } from './tos.js';
|
|
6
|
+
import { classifyStatus, POLL_REQUEST_TIMEOUT_MS, pollUntilTerminal, registerTool } from './tooling.js';
|
|
7
|
+
const SAM3_SUCCESS_CODES = new Set([0]);
|
|
6
8
|
const Sam3PredictSchema = z.object({
|
|
7
9
|
imagePath: z.string().optional().describe('Absolute path of a local image file (e.g. C:\\\\Users\\\\xxx\\\\photo.png)'),
|
|
8
10
|
imageUrl: z.string().url().optional().describe('Publicly accessible URL of the image to process'),
|
|
9
|
-
imageBase64: z.string().optional().describe('Base64-encoded image data. Use this when the image is provided as an attachment without a local path'),
|
|
10
|
-
prompt: z.string().describe('Text prompt for mask generation. Must be in English. If the user provides Chinese or other non-English text, translate it to English before calling this tool'),
|
|
11
|
+
imageBase64: z.string().optional().describe('Base64-encoded image data (a data: URL prefix is also accepted). Use this when the image is provided as an attachment without a local path'),
|
|
12
|
+
prompt: z.string().min(1).max(500).describe('Text prompt for mask generation. Must be in English. If the user provides Chinese or other non-English text, translate it to English before calling this tool'),
|
|
13
|
+
});
|
|
14
|
+
const GetSam3TaskStatusSchema = z.object({
|
|
15
|
+
task_id: z.string().describe('SAM3 task ID returned by sam3_predict'),
|
|
11
16
|
});
|
|
12
17
|
export function setupSam3Tools(server, baseUrl, apiKey, pollInterval, pollMaxAttempts) {
|
|
13
18
|
const client = axios.create({
|
|
@@ -18,150 +23,189 @@ export function setupSam3Tools(server, baseUrl, apiKey, pollInterval, pollMaxAtt
|
|
|
18
23
|
},
|
|
19
24
|
timeout: 60000,
|
|
20
25
|
});
|
|
21
|
-
server
|
|
26
|
+
registerTool(server, 'sam3_predict', `Analyze an image using the SAM3 segmentation API to generate inference results (masks, boxes, scores).
|
|
22
27
|
The image can be provided in one of three ways:
|
|
23
28
|
1. imagePath: Absolute path of a local image file (e.g. C:\\Users\\xxx\\photo.png). Use this when the user provides a local file path.
|
|
24
29
|
2. imageUrl: Publicly accessible URL of the image (e.g. https://example.com/photo.jpg). Use this when the user provides a web link.
|
|
25
30
|
3. imageBase64: Base64-encoded image data. Use this when the user uploads or drags-and-drops an image as an attachment and no local path is available.
|
|
26
31
|
In this case, encode the image content as base64 and pass it via this parameter.
|
|
27
32
|
If the user mentions an uploaded image but does not provide a path, URL, or base64 data, ask the user for the local absolute path.
|
|
28
|
-
Prompt must be in English. If the user provides Chinese or other non-English text, translate it to English before calling this tool.`, Sam3PredictSchema.shape, async (args) =>
|
|
33
|
+
Prompt must be in English. If the user provides Chinese or other non-English text, translate it to English before calling this tool.`, Sam3PredictSchema.shape, async (args) => sam3PredictTool(client, pollInterval, pollMaxAttempts, args));
|
|
34
|
+
registerTool(server, 'get_sam3_task_status', 'Query SAM3 image segmentation task status by task_id. Status can be: processing, completed, or failed. If completed, the result URL is returned.', GetSam3TaskStatusSchema.shape, async (args) => {
|
|
29
35
|
try {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
const result = await sam3PredictTool(client, pollInterval, pollMaxAttempts, args);
|
|
34
|
-
return {
|
|
35
|
-
content: [{ type: 'text', text: result }],
|
|
36
|
-
};
|
|
36
|
+
const data = await getSam3Result(client, args.task_id);
|
|
37
|
+
return normalizeSam3Status(args.task_id, data);
|
|
37
38
|
}
|
|
38
39
|
catch (error) {
|
|
39
|
-
|
|
40
|
+
// Keep task_id in every failure exit of the status tool, consistent
|
|
41
|
+
// with the polling failure shape.
|
|
40
42
|
return {
|
|
41
|
-
|
|
43
|
+
success: false,
|
|
44
|
+
task_id: args.task_id,
|
|
45
|
+
status: 'unknown',
|
|
46
|
+
error: error instanceof Error ? error.message : String(error),
|
|
42
47
|
};
|
|
43
48
|
}
|
|
44
49
|
});
|
|
45
50
|
}
|
|
51
|
+
function normalizeSam3Status(taskId, data) {
|
|
52
|
+
const kind = classifyStatus(data?.status);
|
|
53
|
+
if (kind === 'ok') {
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
task_id: taskId,
|
|
57
|
+
status: data.status,
|
|
58
|
+
result_url: data.result,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (kind === 'failed') {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
task_id: taskId,
|
|
65
|
+
status: data.status,
|
|
66
|
+
error: data.error_message || 'Task failed',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (kind === 'unknown') {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
task_id: taskId,
|
|
73
|
+
status: data?.status ?? 'unknown',
|
|
74
|
+
error: `Unrecognized task status: ${JSON.stringify(data?.status ?? null)}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
task_id: taskId,
|
|
80
|
+
status: data.status,
|
|
81
|
+
message: 'Task is still processing, please check again later.',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
46
84
|
async function getSam3PostSignature(client, fileName) {
|
|
47
85
|
const response = await client.post('/get_postsignature_url', {
|
|
48
86
|
file_type: 'image',
|
|
49
87
|
file_name: fileName,
|
|
50
88
|
});
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
throw new Error(`get_postsignature_url error: ${
|
|
54
|
-
}
|
|
55
|
-
return data.data;
|
|
56
|
-
}
|
|
57
|
-
async function uploadImageToTos(url, sigData, tosKey, buffer, fileName) {
|
|
58
|
-
const formData = new FormData();
|
|
59
|
-
formData.append('key', tosKey);
|
|
60
|
-
formData.append('policy', sigData.policy);
|
|
61
|
-
formData.append('x-tos-algorithm', sigData.algorithm);
|
|
62
|
-
formData.append('x-tos-credential', sigData.credential);
|
|
63
|
-
formData.append('x-tos-date', sigData.date);
|
|
64
|
-
formData.append('x-tos-signature', sigData.signature);
|
|
65
|
-
formData.append('file', buffer, fileName);
|
|
66
|
-
const response = await axios.post(url, formData, {
|
|
67
|
-
headers: formData.getHeaders(),
|
|
68
|
-
maxBodyLength: Infinity,
|
|
69
|
-
maxContentLength: Infinity,
|
|
70
|
-
});
|
|
71
|
-
if (response.status >= 400) {
|
|
72
|
-
throw new Error(`TOS upload failed: ${response.status} ${response.statusText}`);
|
|
89
|
+
const unwrapped = unwrapEnvelope(response, SAM3_SUCCESS_CODES);
|
|
90
|
+
if (!unwrapped.ok) {
|
|
91
|
+
throw new Error(`get_postsignature_url error: ${unwrapped.error}`);
|
|
73
92
|
}
|
|
93
|
+
return unwrapped.data;
|
|
74
94
|
}
|
|
75
95
|
async function sam3Predict(client, fileId, prompt) {
|
|
76
96
|
const response = await client.post('/predict', { file_id: fileId, prompt });
|
|
77
|
-
|
|
97
|
+
const body = response.data;
|
|
98
|
+
if (!body || typeof body !== 'object' || typeof body.task_id !== 'string' || !body.task_id) {
|
|
99
|
+
const preview = typeof body === 'string' ? body.slice(0, 200) : JSON.stringify(body)?.slice(0, 200);
|
|
100
|
+
throw new Error(`Unexpected /predict response: ${preview}`);
|
|
101
|
+
}
|
|
102
|
+
return body.task_id;
|
|
78
103
|
}
|
|
79
104
|
async function downloadSam3Result(url) {
|
|
80
|
-
const response = await axios.get(url);
|
|
105
|
+
const response = await axios.get(url, { timeout: 30000 });
|
|
81
106
|
return response.data;
|
|
82
107
|
}
|
|
108
|
+
const SAM3_RESULT_DOWNLOAD_NOTE = 'The task has completed; only the result download failed. Do not resubmit. Use get_sam3_task_status with this task_id to recover the result.';
|
|
109
|
+
/**
|
|
110
|
+
* Last-hop fetch for a completed SAM3 task. Never throws: a download failure
|
|
111
|
+
* becomes a structured object that keeps task_id and the terminal status, so
|
|
112
|
+
* the caller can resume via get_sam3_task_status. A download failure is not
|
|
113
|
+
* a truncated wait and never rewrites the remote status to failed/processing.
|
|
114
|
+
*/
|
|
115
|
+
export async function fetchSam3ResultPayload(taskId, resultUrl) {
|
|
116
|
+
if (typeof resultUrl !== 'string' || resultUrl.trim() === '') {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
task_id: taskId,
|
|
120
|
+
status: 'completed',
|
|
121
|
+
error: `Task ${taskId} completed but has no usable result_url; use get_sam3_task_status with this task_id to recover.`,
|
|
122
|
+
note: SAM3_RESULT_DOWNLOAD_NOTE,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const data = await downloadSam3Result(resultUrl);
|
|
127
|
+
return { success: true, task_id: taskId, status: 'completed', result_url: resultUrl, result: data };
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
131
|
+
return {
|
|
132
|
+
success: false,
|
|
133
|
+
task_id: taskId,
|
|
134
|
+
status: 'completed',
|
|
135
|
+
result_url: resultUrl,
|
|
136
|
+
error: `Failed to download the completed result for task ${taskId}: ${message}`,
|
|
137
|
+
note: SAM3_RESULT_DOWNLOAD_NOTE,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
83
141
|
async function prepareImageBuffer(args) {
|
|
84
142
|
const { imagePath, imageUrl, imageBase64 } = args;
|
|
85
|
-
if (!imagePath && !imageUrl && !imageBase64) {
|
|
86
|
-
throw new Error('Missing image input: must provide one of imagePath, imageUrl, or imageBase64');
|
|
87
|
-
}
|
|
88
|
-
let buffer;
|
|
89
|
-
let fileName;
|
|
90
143
|
if (imagePath) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
fileName = path.basename(imagePath);
|
|
95
|
-
buffer = fs.readFileSync(imagePath);
|
|
96
|
-
}
|
|
97
|
-
else if (imageUrl) {
|
|
98
|
-
const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });
|
|
99
|
-
buffer = Buffer.from(response.data);
|
|
100
|
-
fileName = path.basename(new URL(imageUrl).pathname) || 'image.png';
|
|
144
|
+
checkLocalFile(imagePath, 'image');
|
|
145
|
+
return { buffer: fs.readFileSync(imagePath), fileName: path.basename(imagePath) };
|
|
101
146
|
}
|
|
102
|
-
|
|
103
|
-
buffer =
|
|
104
|
-
fileName = 'image.png';
|
|
147
|
+
if (imageUrl) {
|
|
148
|
+
const buffer = await downloadToBuffer(imageUrl);
|
|
149
|
+
const fileName = path.basename(new URL(imageUrl).pathname) || 'image.png';
|
|
150
|
+
return { buffer, fileName };
|
|
105
151
|
}
|
|
106
|
-
|
|
107
|
-
|
|
152
|
+
if (imageBase64) {
|
|
153
|
+
return decodeBase64Image(imageBase64);
|
|
108
154
|
}
|
|
109
|
-
|
|
155
|
+
throw new Error('Missing image input: must provide one of imagePath, imageUrl, or imageBase64');
|
|
110
156
|
}
|
|
111
157
|
async function sam3CreateTask(client, buffer, fileName, prompt) {
|
|
112
158
|
const signatureData = await getSam3PostSignature(client, fileName);
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
const keyObj = JSON.parse(origin_policy).conditions.find((c) => 'key' in c);
|
|
118
|
-
const tosKey = keyObj ? keyObj.key : new URL(url).pathname.slice(1);
|
|
119
|
-
const fileId = new URL(url).pathname.split('/').pop();
|
|
120
|
-
if (!fileId) {
|
|
121
|
-
throw new Error('Could not extract file_id from upload URL');
|
|
122
|
-
}
|
|
123
|
-
await uploadImageToTos(url, signatureData, tosKey, buffer, fileName);
|
|
124
|
-
const taskId = await sam3Predict(client, fileId, prompt);
|
|
125
|
-
return taskId;
|
|
126
|
-
}
|
|
127
|
-
async function getSam3Result(client, taskId) {
|
|
128
|
-
const response = await client.get(`/predict/result/${encodeURIComponent(taskId)}`);
|
|
129
|
-
return response.data;
|
|
159
|
+
const target = parseTosSignature(signatureData);
|
|
160
|
+
await uploadToTos(target, buffer, fileName);
|
|
161
|
+
return sam3Predict(client, target.fileId, prompt);
|
|
130
162
|
}
|
|
131
|
-
async function
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
163
|
+
async function getSam3Result(client, taskId, signal) {
|
|
164
|
+
const response = await client.get(`/predict/result/${encodeURIComponent(taskId)}`, {
|
|
165
|
+
timeout: POLL_REQUEST_TIMEOUT_MS,
|
|
166
|
+
signal,
|
|
167
|
+
});
|
|
168
|
+
const data = response.data;
|
|
169
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
170
|
+
throw new Error(`Unexpected task status response (HTTP ${response.status})`);
|
|
171
|
+
}
|
|
172
|
+
// The endpoint's success body shape is not confirmed against a live backend
|
|
173
|
+
// (envelope {code:0,data:{...}} or bare {status,...}); unwrap only when the
|
|
174
|
+
// body is shaped like an envelope, so auth/business errors surface with
|
|
175
|
+
// their real message instead of degrading to "Unrecognized task status".
|
|
176
|
+
if ('code' in data) {
|
|
177
|
+
const unwrapped = unwrapEnvelope(response, SAM3_SUCCESS_CODES);
|
|
178
|
+
if (!unwrapped.ok) {
|
|
179
|
+
throw new Error(`Task status request failed: ${unwrapped.error}`);
|
|
139
180
|
}
|
|
140
|
-
|
|
181
|
+
return unwrapped.data;
|
|
141
182
|
}
|
|
142
|
-
return
|
|
143
|
-
success: true,
|
|
144
|
-
status: 'processing',
|
|
145
|
-
task_id: taskId,
|
|
146
|
-
message: `Task is still processing (waited about ${Math.round(pollMaxAttempts * pollInterval / 1000)} seconds). Please retry later or record this task_id for manual follow-up.`,
|
|
147
|
-
note: 'The synchronous wait for this long-running task has been truncated.',
|
|
148
|
-
};
|
|
183
|
+
return data;
|
|
149
184
|
}
|
|
150
185
|
async function sam3PredictTool(client, pollInterval, pollMaxAttempts, args) {
|
|
151
|
-
if (!args.prompt) {
|
|
152
|
-
throw new Error('Missing argument: prompt');
|
|
153
|
-
}
|
|
154
186
|
const { buffer, fileName } = await prepareImageBuffer(args);
|
|
155
187
|
const taskId = await sam3CreateTask(client, buffer, fileName, args.prompt);
|
|
156
|
-
const taskResult = await
|
|
157
|
-
|
|
158
|
-
|
|
188
|
+
const taskResult = await pollUntilTerminal({
|
|
189
|
+
taskId,
|
|
190
|
+
timeoutSeconds: (pollInterval * pollMaxAttempts) / 1000,
|
|
191
|
+
pollIntervalSeconds: pollInterval / 1000,
|
|
192
|
+
maxAttempts: pollMaxAttempts,
|
|
193
|
+
continueHint: 'get_sam3_task_status',
|
|
194
|
+
fetchStatus: async (signal) => {
|
|
195
|
+
const data = await getSam3Result(client, taskId, signal);
|
|
196
|
+
return {
|
|
197
|
+
status: data.status,
|
|
198
|
+
payload: { result_url: data.result, error_message: data.error_message },
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
if (!taskResult.success || taskResult.status === 'processing') {
|
|
203
|
+
return taskResult;
|
|
159
204
|
}
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
205
|
+
const outcome = await fetchSam3ResultPayload(taskResult.task_id, taskResult.result_url);
|
|
206
|
+
if (!outcome.success) {
|
|
207
|
+
return outcome;
|
|
208
|
+
}
|
|
209
|
+
return JSON.stringify(outcome.result, null, 2);
|
|
166
210
|
}
|
|
167
211
|
//# sourceMappingURL=sam3.js.map
|
package/dist/sam3.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sam3.js","sourceRoot":"","sources":["../src/sam3.ts"],"names":[],"mappings":"AACA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"sam3.js","sourceRoot":"","sources":["../src/sam3.ts"],"names":[],"mappings":"AACA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAExG,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4EAA4E,CAAC;IACvH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IACjG,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4IAA4I,CAAC;IACzL,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,+JAA+J,CAAC;CAC7M,CAAC,CAAC;AAEH,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;CACtE,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc,CAC5B,MAAiB,EACjB,OAAe,EACf,MAAc,EACd,YAAoB,EACpB,eAAuB;IAEvB,MAAM,MAAM,GAAkB,KAAK,CAAC,MAAM,CAAC;QACzC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;QACnC,OAAO,EAAE;YACP,WAAW,EAAE,MAAM;YACnB,cAAc,EAAE,kBAAkB;SACnC;QACD,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IAEH,YAAY,CACV,MAAM,EACN,cAAc,EACd;;;;;;;qIAOiI,EACjI,iBAAiB,CAAC,KAAK,EACvB,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,IAAI,CAAC,CAC7E,CAAC;IAEF,YAAY,CACV,MAAM,EACN,sBAAsB,EACtB,kJAAkJ,EAClJ,uBAAuB,CAAC,KAAK,EAC7B,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACvD,OAAO,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,oEAAoE;YACpE,kCAAkC;YAClC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAc,EAAE,IAAS;IACpD,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,MAAM;SACxB,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,aAAa,IAAI,aAAa;SAC3C,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,SAAS;YACjC,KAAK,EAAE,6BAA6B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,EAAE;SAC3E,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,MAAM;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,qDAAqD;KAC/D,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,MAAqB,EAAE,QAAgB;IACzE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE;QAC3D,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,gCAAgC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAqB,EAAE,MAAc,EAAE,MAAc;IAC9E,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3F,MAAM,OAAO,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACpG,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAC3C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1D,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC;AAED,MAAM,yBAAyB,GAC7B,6IAA6I,CAAC;AAEhJ;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,MAAc,EAAE,SAAkB;IAC7E,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7D,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,QAAQ,MAAM,iGAAiG;YACtH,IAAI,EAAE,yBAAyB;SAChC,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,WAAW;YACnB,UAAU,EAAE,SAAS;YACrB,KAAK,EAAE,oDAAoD,MAAM,KAAK,OAAO,EAAE;YAC/E,IAAI,EAAE,yBAAyB;SAChC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,IAAqE;IACrG,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAElD,IAAI,SAAS,EAAE,CAAC;QACd,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;IACpF,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC;QAC1E,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;AAClG,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAAqB,EAAE,MAAc,EAAE,QAAgB,EAAE,MAAc;IACnG,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAEhD,MAAM,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,MAAqB,EAAE,MAAc,EAAE,MAAoB;IACtF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,mBAAmB,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE;QACjF,OAAO,EAAE,uBAAuB;QAChC,MAAM;KACP,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/E,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,wEAAwE;IACxE,yEAAyE;IACzE,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,SAAS,GAAG,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAC/D,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,SAAS,CAAC,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,MAAqB,EACrB,YAAoB,EACpB,eAAuB,EACvB,IAAuC;IAEvC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAE3E,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC;QACzC,MAAM;QACN,cAAc,EAAE,CAAC,YAAY,GAAG,eAAe,CAAC,GAAG,IAAI;QACvD,mBAAmB,EAAE,YAAY,GAAG,IAAI;QACxC,WAAW,EAAE,eAAe;QAC5B,YAAY,EAAE,sBAAsB;QACpC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC5B,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACzD,OAAO;gBACL,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE;aACxE,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAC9D,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACxF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
package/dist/server.d.ts
CHANGED
package/dist/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* MCP Server - Video enhancement and SAM3 image segmentation
|
|
3
|
+
* MCP Server - Video enhancement, image enhancement/colorization/denoising, and SAM3 image segmentation
|
|
4
4
|
*/
|
|
5
5
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
6
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -8,67 +8,89 @@ import * as fs from 'fs';
|
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import { fileURLToPath } from 'url';
|
|
10
10
|
import { setupVideoEnhancementTools } from './video-enhancement.js';
|
|
11
|
+
import { setupImageEnhancementTools } from './image-enhancement.js';
|
|
11
12
|
import { setupSam3Tools } from './sam3.js';
|
|
13
|
+
import { resolveMediaHostConfig } from './service-config.js';
|
|
12
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
15
|
const __dirname = path.dirname(__filename);
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
function parseConfigFile(configPath) {
|
|
17
|
+
let raw;
|
|
18
|
+
try {
|
|
19
|
+
raw = fs.readFileSync(configPath, 'utf-8');
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error(`Error: cannot read config file ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
let config;
|
|
26
|
+
try {
|
|
27
|
+
config = JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error(`Error: config file ${configPath} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
// Absent keys stay undefined; defaults are applied by resolveMediaHostConfig.
|
|
34
|
+
return {
|
|
35
|
+
baseUrl: typeof config.baseUrl === 'string' ? config.baseUrl : undefined,
|
|
36
|
+
imageBaseUrl: typeof config.imageBaseUrl === 'string' ? config.imageBaseUrl : undefined,
|
|
37
|
+
sam3BaseUrl: typeof config.sam3BaseUrl === 'string' ? config.sam3BaseUrl : undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function loadConfig(explicitConfigPath) {
|
|
41
|
+
if (explicitConfigPath) {
|
|
42
|
+
const resolved = path.resolve(explicitConfigPath);
|
|
43
|
+
console.error(`Using config file: ${resolved}`);
|
|
44
|
+
return parseConfigFile(resolved);
|
|
45
|
+
}
|
|
46
|
+
// Only the config bundled with the package is considered; a config.json in
|
|
47
|
+
// the caller's working directory must never silently redirect API traffic.
|
|
48
|
+
const bundledPath = path.resolve(__dirname, '..', 'config.json');
|
|
49
|
+
if (fs.existsSync(bundledPath)) {
|
|
50
|
+
return parseConfigFile(bundledPath);
|
|
51
|
+
}
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
// Collect CLI values without consulting the environment; precedence between
|
|
55
|
+
// layers is resolved by resolveMediaHostConfig.
|
|
56
|
+
function parseCliOverrides(args) {
|
|
57
|
+
const overrides = {};
|
|
58
|
+
for (let i = 0; i < args.length; i++) {
|
|
59
|
+
const takeValue = (key) => {
|
|
60
|
+
overrides[key] = args[i + 1];
|
|
61
|
+
i++;
|
|
62
|
+
};
|
|
63
|
+
if (args[i] === '--base-url' && i + 1 < args.length)
|
|
64
|
+
takeValue('baseUrl');
|
|
65
|
+
else if (args[i] === '--image-base-url' && i + 1 < args.length)
|
|
66
|
+
takeValue('imageBaseUrl');
|
|
67
|
+
else if (args[i] === '--api-key' && i + 1 < args.length)
|
|
68
|
+
takeValue('apiKey');
|
|
69
|
+
else if (args[i] === '--sam3-base-url' && i + 1 < args.length)
|
|
70
|
+
takeValue('sam3BaseUrl');
|
|
71
|
+
else if (args[i] === '--sam3-poll-interval' && i + 1 < args.length)
|
|
72
|
+
takeValue('sam3PollIntervalMs');
|
|
73
|
+
else if (args[i] === '--sam3-poll-max-attempts' && i + 1 < args.length)
|
|
74
|
+
takeValue('sam3PollMaxAttempts');
|
|
32
75
|
}
|
|
33
|
-
return
|
|
76
|
+
return overrides;
|
|
34
77
|
}
|
|
35
78
|
// Main entry
|
|
36
79
|
async function main() {
|
|
37
80
|
const args = process.argv.slice(2);
|
|
38
|
-
|
|
39
|
-
let baseUrl = process.env.HTTP_API_BASE_URL || config.baseUrl;
|
|
40
|
-
let apiKey = process.env.API_KEY || '';
|
|
41
|
-
let sam3BaseUrl = process.env.SAM3_API_BASE_URL || config.sam3BaseUrl;
|
|
42
|
-
let sam3ApiKey = apiKey;
|
|
43
|
-
let sam3PollInterval = parseInt(process.env.SAM3_POLL_INTERVAL || '2000', 10);
|
|
44
|
-
let sam3PollMaxAttempts = parseInt(process.env.SAM3_POLL_MAX_ATTEMPTS || '25', 10);
|
|
45
|
-
// Parse command line arguments
|
|
81
|
+
let explicitConfigPath;
|
|
46
82
|
for (let i = 0; i < args.length; i++) {
|
|
47
|
-
if (args[i] === '--
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
else if (args[i] === '--api-key' && i + 1 < args.length) {
|
|
52
|
-
apiKey = args[i + 1];
|
|
53
|
-
i++;
|
|
54
|
-
}
|
|
55
|
-
else if (args[i] === '--sam3-base-url' && i + 1 < args.length) {
|
|
56
|
-
sam3BaseUrl = args[i + 1];
|
|
57
|
-
i++;
|
|
83
|
+
if (args[i] === '--config' && i + 1 < args.length) {
|
|
84
|
+
explicitConfigPath = args[i + 1];
|
|
85
|
+
break;
|
|
58
86
|
}
|
|
59
|
-
else if (args[i] === '--sam3-poll-interval' && i + 1 < args.length) {
|
|
60
|
-
sam3PollInterval = parseInt(args[i + 1], 10);
|
|
61
|
-
i++;
|
|
62
|
-
}
|
|
63
|
-
else if (args[i] === '--sam3-poll-max-attempts' && i + 1 < args.length) {
|
|
64
|
-
sam3PollMaxAttempts = parseInt(args[i + 1], 10);
|
|
65
|
-
i++;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (!apiKey) {
|
|
69
|
-
console.error('Error: --api-key argument or API_KEY environment variable is required');
|
|
70
|
-
process.exit(1);
|
|
71
87
|
}
|
|
88
|
+
const fileConfig = loadConfig(explicitConfigPath);
|
|
89
|
+
// SAM3's sync wait is bounded by two independent limits derived from its
|
|
90
|
+
// config: at most SAM3_POLL_MAX_ATTEMPTS status queries and a time budget of
|
|
91
|
+
// interval x attempts (default 25 x 2000 ms = 50 s). Whichever runs out
|
|
92
|
+
// first truncates the wait; the task keeps running remotely either way.
|
|
93
|
+
const hostConfig = resolveMediaHostConfig({ cli: parseCliOverrides(args), env: process.env, file: fileConfig });
|
|
72
94
|
const server = new McpServer({
|
|
73
95
|
name: 'media-mcp',
|
|
74
96
|
version: '0.3.0',
|
|
@@ -78,9 +100,11 @@ async function main() {
|
|
|
78
100
|
},
|
|
79
101
|
});
|
|
80
102
|
// Register video enhancement tools
|
|
81
|
-
setupVideoEnhancementTools(server,
|
|
103
|
+
setupVideoEnhancementTools(server, hostConfig.enhancementApiBaseUrl, hostConfig.apiKey);
|
|
104
|
+
// Register image enhancement tools
|
|
105
|
+
setupImageEnhancementTools(server, hostConfig.imageApiBaseUrl, hostConfig.apiKey);
|
|
82
106
|
// Register SAM3 tools
|
|
83
|
-
setupSam3Tools(server,
|
|
107
|
+
setupSam3Tools(server, hostConfig.sam3ApiBaseUrl, hostConfig.apiKey, hostConfig.sam3PollIntervalMs, hostConfig.sam3PollMaxAttempts);
|
|
84
108
|
const transport = new StdioServerTransport();
|
|
85
109
|
await server.connect(transport);
|
|
86
110
|
console.error('MCP Server running on stdio');
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export declare const SAM3_POLL_INTERVAL_MS_BOUNDS: {
|
|
2
|
+
readonly min: 500;
|
|
3
|
+
readonly max: 60000;
|
|
4
|
+
};
|
|
5
|
+
export declare const SAM3_POLL_MAX_ATTEMPTS_BOUNDS: {
|
|
6
|
+
readonly min: 1;
|
|
7
|
+
readonly max: 1000;
|
|
8
|
+
};
|
|
9
|
+
export declare class ConfigError extends Error {
|
|
10
|
+
}
|
|
11
|
+
export interface MediaHostFileConfig {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
imageBaseUrl?: string;
|
|
14
|
+
sam3BaseUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface MediaHostCliOverrides {
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
imageBaseUrl?: string;
|
|
19
|
+
sam3BaseUrl?: string;
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
/** Raw argument text; parsed and bounds-checked here. */
|
|
22
|
+
sam3PollIntervalMs?: string;
|
|
23
|
+
sam3PollMaxAttempts?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface MediaHostEnv {
|
|
26
|
+
API_KEY?: string;
|
|
27
|
+
HTTP_API_BASE_URL?: string;
|
|
28
|
+
IMAGE_API_BASE_URL?: string;
|
|
29
|
+
SAM3_API_BASE_URL?: string;
|
|
30
|
+
/** Canonical name. */
|
|
31
|
+
SAM3_POLL_INTERVAL_MS?: string;
|
|
32
|
+
/** Deprecated alias of SAM3_POLL_INTERVAL_MS. */
|
|
33
|
+
SAM3_POLL_INTERVAL?: string;
|
|
34
|
+
SAM3_POLL_MAX_ATTEMPTS?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface MediaHostConfig {
|
|
37
|
+
enhancementApiBaseUrl: string;
|
|
38
|
+
imageApiBaseUrl: string;
|
|
39
|
+
sam3ApiBaseUrl: string;
|
|
40
|
+
apiKey: string;
|
|
41
|
+
sam3PollIntervalMs: number;
|
|
42
|
+
sam3PollMaxAttempts: number;
|
|
43
|
+
}
|
|
44
|
+
export declare function parseSam3WaitInt(raw: string | undefined, name: string, bounds: {
|
|
45
|
+
min: number;
|
|
46
|
+
max: number;
|
|
47
|
+
}, fallback: number): number;
|
|
48
|
+
/**
|
|
49
|
+
* Resolves the final Media host configuration.
|
|
50
|
+
*
|
|
51
|
+
* Precedence per key: CLI override > environment > file config > built-in
|
|
52
|
+
* default. The image API base URL is derived only after the merge: an unset
|
|
53
|
+
* image base falls back to the resolved enhancement base, no matter which
|
|
54
|
+
* layer provided it. All validation happens here, before any tool is created
|
|
55
|
+
* or request is made; error messages never echo secret values.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveMediaHostConfig(options: {
|
|
58
|
+
cli?: MediaHostCliOverrides;
|
|
59
|
+
env?: MediaHostEnv;
|
|
60
|
+
file?: MediaHostFileConfig;
|
|
61
|
+
}): MediaHostConfig;
|
|
62
|
+
//# sourceMappingURL=service-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-config.d.ts","sourceRoot":"","sources":["../src/service-config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,4BAA4B;;;CAAoC,CAAC;AAC9E,eAAO,MAAM,6BAA6B;;;CAAiC,CAAC;AAO5E,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAEzC,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAWD,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ,EAAE,MAAM,GACf,MAAM,CAOR;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,GAAG,CAAC,EAAE,qBAAqB,CAAC;IAC5B,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B,GAAG,eAAe,CAkClB"}
|