grok-imagine-image-mcp-server 1.0.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/.env.example +15 -0
- package/LICENSE +21 -0
- package/README.ja.md +225 -0
- package/README.md +225 -0
- package/dist/cli/batch.d.ts +19 -0
- package/dist/cli/batch.d.ts.map +1 -0
- package/dist/cli/batch.js +288 -0
- package/dist/cli/batch.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +203 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/edit.d.ts +14 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +236 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/generate.d.ts +13 -0
- package/dist/tools/generate.d.ts.map +1 -0
- package/dist/tools/generate.js +183 -0
- package/dist/tools/generate.js.map +1 -0
- package/dist/types/batch.d.ts +137 -0
- package/dist/types/batch.d.ts.map +1 -0
- package/dist/types/batch.js +5 -0
- package/dist/types/batch.js.map +1 -0
- package/dist/types/tools.d.ts +52 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +20 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/utils/batch-config.d.ts +31 -0
- package/dist/utils/batch-config.d.ts.map +1 -0
- package/dist/utils/batch-config.js +236 -0
- package/dist/utils/batch-config.js.map +1 -0
- package/dist/utils/batch-manager.d.ts +24 -0
- package/dist/utils/batch-manager.d.ts.map +1 -0
- package/dist/utils/batch-manager.js +301 -0
- package/dist/utils/batch-manager.js.map +1 -0
- package/dist/utils/debug.d.ts +5 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +16 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/image.d.ts +36 -0
- package/dist/utils/image.d.ts.map +1 -0
- package/dist/utils/image.js +85 -0
- package/dist/utils/image.js.map +1 -0
- package/dist/utils/path.d.ts +16 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +70 -0
- package/dist/utils/path.js.map +1 -0
- package/examples/batch-detailed.json +41 -0
- package/examples/batch-simple.json +14 -0
- package/examples/batch-variants.json +23 -0
- package/examples/batch-with-edits.json +26 -0
- package/package.json +66 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Grok Imagine Image MCP Server
|
|
3
|
+
*/
|
|
4
|
+
export declare const MODELS: readonly ["grok-imagine-image"];
|
|
5
|
+
export type Model = (typeof MODELS)[number];
|
|
6
|
+
export declare const GROK_IMAGINE_ASPECT_RATIOS: readonly ["1:1", "3:4", "4:3", "9:16", "16:9"];
|
|
7
|
+
export declare const ASPECT_RATIOS: readonly ["1:1", "3:4", "4:3", "9:16", "16:9"];
|
|
8
|
+
export type AspectRatio = (typeof ASPECT_RATIOS)[number];
|
|
9
|
+
export declare const RESOLUTIONS: readonly ["1k"];
|
|
10
|
+
export type Resolution = (typeof RESOLUTIONS)[number];
|
|
11
|
+
export declare const QUALITIES: readonly ["low", "medium", "high"];
|
|
12
|
+
export type Quality = (typeof QUALITIES)[number];
|
|
13
|
+
export interface GenerateImageParams {
|
|
14
|
+
prompt: string;
|
|
15
|
+
output_path?: string;
|
|
16
|
+
model?: Model;
|
|
17
|
+
n?: number;
|
|
18
|
+
aspect_ratio?: AspectRatio;
|
|
19
|
+
resolution?: Resolution;
|
|
20
|
+
quality?: Quality;
|
|
21
|
+
response_format?: 'url' | 'b64_json';
|
|
22
|
+
return_base64?: boolean;
|
|
23
|
+
include_thumbnail?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface EditImageParams {
|
|
26
|
+
prompt: string;
|
|
27
|
+
image_path?: string;
|
|
28
|
+
image_base64?: string;
|
|
29
|
+
image_url?: string;
|
|
30
|
+
output_path?: string;
|
|
31
|
+
model?: Model;
|
|
32
|
+
n?: number;
|
|
33
|
+
resolution?: Resolution;
|
|
34
|
+
response_format?: 'url' | 'b64_json';
|
|
35
|
+
return_base64?: boolean;
|
|
36
|
+
include_thumbnail?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface XAIImageResponse {
|
|
39
|
+
data: Array<{
|
|
40
|
+
url?: string;
|
|
41
|
+
b64_json?: string;
|
|
42
|
+
revised_prompt?: string;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export interface XAIErrorResponse {
|
|
46
|
+
error?: {
|
|
47
|
+
message: string;
|
|
48
|
+
type?: string;
|
|
49
|
+
code?: string;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,MAAM,iCAAkC,CAAC;AAEtD,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAG5C,eAAO,MAAM,0BAA0B,gDAM7B,CAAC;AAGX,eAAO,MAAM,aAAa,gDAA6B,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAGzD,eAAO,MAAM,WAAW,iBAAkB,CAAC;AAC3C,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAGtD,eAAO,MAAM,SAAS,oCAAqC,CAAC;AAC5D,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,eAAe,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,KAAK,CAAC;QACV,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Grok Imagine Image MCP Server
|
|
3
|
+
*/
|
|
4
|
+
// Supported models (grok-2-image removed due to aspect ratio issues)
|
|
5
|
+
export const MODELS = ['grok-imagine-image'];
|
|
6
|
+
// Supported aspect ratios for grok-imagine-image (5 options)
|
|
7
|
+
export const GROK_IMAGINE_ASPECT_RATIOS = [
|
|
8
|
+
'1:1',
|
|
9
|
+
'3:4',
|
|
10
|
+
'4:3',
|
|
11
|
+
'9:16',
|
|
12
|
+
'16:9',
|
|
13
|
+
];
|
|
14
|
+
// All supported aspect ratios (grok-imagine-image only)
|
|
15
|
+
export const ASPECT_RATIOS = GROK_IMAGINE_ASPECT_RATIOS;
|
|
16
|
+
// Supported resolutions (2k is not currently available)
|
|
17
|
+
export const RESOLUTIONS = ['1k'];
|
|
18
|
+
// Quality options (currently no-op, reserved for future use)
|
|
19
|
+
export const QUALITIES = ['low', 'medium', 'high'];
|
|
20
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qEAAqE;AACrE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,oBAAoB,CAAU,CAAC;AAItD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;CACE,CAAC;AAEX,wDAAwD;AACxD,MAAM,CAAC,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAIxD,wDAAwD;AACxD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAI,CAAU,CAAC;AAG3C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch configuration loading and validation
|
|
3
|
+
*/
|
|
4
|
+
import type { BatchConfig, BatchJobConfig, BatchExecutionOptions } from '../types/batch.js';
|
|
5
|
+
/**
|
|
6
|
+
* Custom error for batch configuration issues
|
|
7
|
+
*/
|
|
8
|
+
export declare class BatchConfigError extends Error {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Load and parse batch configuration from JSON file
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadBatchConfig(configPath: string): Promise<BatchConfig>;
|
|
15
|
+
/**
|
|
16
|
+
* Validate batch configuration
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateBatchConfig(config: BatchConfig): void;
|
|
19
|
+
/**
|
|
20
|
+
* Merge batch configuration with CLI options and environment defaults
|
|
21
|
+
*/
|
|
22
|
+
export declare function mergeBatchConfig(config: BatchConfig, options: BatchExecutionOptions): BatchConfig;
|
|
23
|
+
/**
|
|
24
|
+
* Get default output directory
|
|
25
|
+
*/
|
|
26
|
+
export declare function getDefaultOutputDirectory(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve output path for a job
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveOutputPath(job: BatchJobConfig, index: number, outputDir: string, allowAnyPath?: boolean): string;
|
|
31
|
+
//# sourceMappingURL=batch-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-config.d.ts","sourceRoot":"","sources":["../../src/utils/batch-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAO3B;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAwE7D;AAsGD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,qBAAqB,GAC7B,WAAW,CAoCb;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,OAAe,GAC5B,MAAM,CA2BR"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch configuration loading and validation
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { MODELS, ASPECT_RATIOS, RESOLUTIONS, } from '../types/tools.js';
|
|
7
|
+
/**
|
|
8
|
+
* Custom error for batch configuration issues
|
|
9
|
+
*/
|
|
10
|
+
export class BatchConfigError extends Error {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'BatchConfigError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load and parse batch configuration from JSON file
|
|
18
|
+
*/
|
|
19
|
+
export async function loadBatchConfig(configPath) {
|
|
20
|
+
const absolutePath = path.isAbsolute(configPath)
|
|
21
|
+
? configPath
|
|
22
|
+
: path.join(process.cwd(), configPath);
|
|
23
|
+
try {
|
|
24
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
25
|
+
const config = JSON.parse(content);
|
|
26
|
+
return config;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error.code === 'ENOENT') {
|
|
30
|
+
throw new BatchConfigError(`Configuration file not found: ${configPath}`);
|
|
31
|
+
}
|
|
32
|
+
if (error instanceof SyntaxError) {
|
|
33
|
+
throw new BatchConfigError(`Invalid JSON in configuration file: ${error.message}`);
|
|
34
|
+
}
|
|
35
|
+
throw new BatchConfigError(`Failed to load configuration: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Validate batch configuration
|
|
40
|
+
*/
|
|
41
|
+
export function validateBatchConfig(config) {
|
|
42
|
+
// Validate jobs array
|
|
43
|
+
if (!config.jobs || !Array.isArray(config.jobs)) {
|
|
44
|
+
throw new BatchConfigError('Configuration must have a "jobs" array');
|
|
45
|
+
}
|
|
46
|
+
if (config.jobs.length === 0) {
|
|
47
|
+
throw new BatchConfigError('Jobs array cannot be empty');
|
|
48
|
+
}
|
|
49
|
+
if (config.jobs.length > 100) {
|
|
50
|
+
throw new BatchConfigError('Maximum 100 jobs allowed per batch');
|
|
51
|
+
}
|
|
52
|
+
// Validate each job
|
|
53
|
+
config.jobs.forEach((job, index) => {
|
|
54
|
+
validateJobConfig(job, index);
|
|
55
|
+
});
|
|
56
|
+
// Validate max_concurrent
|
|
57
|
+
if (config.max_concurrent !== undefined) {
|
|
58
|
+
if (typeof config.max_concurrent !== 'number' ||
|
|
59
|
+
config.max_concurrent < 1 ||
|
|
60
|
+
config.max_concurrent > 10) {
|
|
61
|
+
throw new BatchConfigError('max_concurrent must be a number between 1 and 10');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Validate timeout
|
|
65
|
+
if (config.timeout !== undefined) {
|
|
66
|
+
if (typeof config.timeout !== 'number' ||
|
|
67
|
+
config.timeout < 1000 ||
|
|
68
|
+
config.timeout > 3600000) {
|
|
69
|
+
throw new BatchConfigError('timeout must be between 1000 and 3600000 milliseconds');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Validate retry_policy
|
|
73
|
+
if (config.retry_policy) {
|
|
74
|
+
validateRetryPolicy(config.retry_policy);
|
|
75
|
+
}
|
|
76
|
+
// Validate default_model
|
|
77
|
+
if (config.default_model !== undefined) {
|
|
78
|
+
if (!MODELS.includes(config.default_model)) {
|
|
79
|
+
throw new BatchConfigError(`Invalid default_model: ${config.default_model}. Must be one of: ${MODELS.join(', ')}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Validate default_resolution
|
|
83
|
+
if (config.default_resolution !== undefined) {
|
|
84
|
+
if (!RESOLUTIONS.includes(config.default_resolution)) {
|
|
85
|
+
throw new BatchConfigError(`Invalid default_resolution: ${config.default_resolution}. Must be one of: ${RESOLUTIONS.join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Validate default_aspect_ratio
|
|
89
|
+
if (config.default_aspect_ratio !== undefined) {
|
|
90
|
+
if (!ASPECT_RATIOS.includes(config.default_aspect_ratio)) {
|
|
91
|
+
throw new BatchConfigError(`Invalid default_aspect_ratio: ${config.default_aspect_ratio}. Must be one of: ${ASPECT_RATIOS.join(', ')}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validate individual job configuration
|
|
97
|
+
*/
|
|
98
|
+
function validateJobConfig(job, index) {
|
|
99
|
+
const prefix = `Job ${index + 1}`;
|
|
100
|
+
// Validate prompt
|
|
101
|
+
if (!job.prompt || typeof job.prompt !== 'string' || job.prompt.trim().length === 0) {
|
|
102
|
+
throw new BatchConfigError(`${prefix}: prompt is required and must be a non-empty string`);
|
|
103
|
+
}
|
|
104
|
+
// Validate model
|
|
105
|
+
if (job.model !== undefined) {
|
|
106
|
+
if (!MODELS.includes(job.model)) {
|
|
107
|
+
throw new BatchConfigError(`${prefix}: Invalid model "${job.model}". Must be one of: ${MODELS.join(', ')}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Validate aspect_ratio
|
|
111
|
+
if (job.aspect_ratio !== undefined) {
|
|
112
|
+
if (!ASPECT_RATIOS.includes(job.aspect_ratio)) {
|
|
113
|
+
throw new BatchConfigError(`${prefix}: Invalid aspect_ratio "${job.aspect_ratio}". Must be one of: ${ASPECT_RATIOS.join(', ')}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Validate resolution
|
|
117
|
+
if (job.resolution !== undefined) {
|
|
118
|
+
if (!RESOLUTIONS.includes(job.resolution)) {
|
|
119
|
+
throw new BatchConfigError(`${prefix}: Invalid resolution "${job.resolution}". Must be one of: ${RESOLUTIONS.join(', ')}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Validate n
|
|
123
|
+
if (job.n !== undefined) {
|
|
124
|
+
if (typeof job.n !== 'number' || job.n < 1 || job.n > 10) {
|
|
125
|
+
throw new BatchConfigError(`${prefix}: n must be a number between 1 and 10`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Check for edit job requirements
|
|
129
|
+
const isEditJob = job.image_path || job.image_base64 || job.image_url;
|
|
130
|
+
if (isEditJob) {
|
|
131
|
+
const model = job.model || 'grok-imagine-image';
|
|
132
|
+
if (model !== 'grok-imagine-image') {
|
|
133
|
+
throw new BatchConfigError(`${prefix}: Image editing is only supported by grok-imagine-image model`);
|
|
134
|
+
}
|
|
135
|
+
// Edit jobs cannot specify aspect_ratio
|
|
136
|
+
if (job.aspect_ratio !== undefined) {
|
|
137
|
+
throw new BatchConfigError(`${prefix}: aspect_ratio cannot be specified for edit jobs (auto-detected from input image)`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Validate retry policy
|
|
143
|
+
*/
|
|
144
|
+
function validateRetryPolicy(policy) {
|
|
145
|
+
if (policy.max_retries !== undefined) {
|
|
146
|
+
if (typeof policy.max_retries !== 'number' ||
|
|
147
|
+
policy.max_retries < 0 ||
|
|
148
|
+
policy.max_retries > 5) {
|
|
149
|
+
throw new BatchConfigError('retry_policy.max_retries must be between 0 and 5');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (policy.retry_delay_ms !== undefined) {
|
|
153
|
+
if (typeof policy.retry_delay_ms !== 'number' ||
|
|
154
|
+
policy.retry_delay_ms < 100 ||
|
|
155
|
+
policy.retry_delay_ms > 60000) {
|
|
156
|
+
throw new BatchConfigError('retry_policy.retry_delay_ms must be between 100 and 60000');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (policy.retry_on_errors !== undefined) {
|
|
160
|
+
if (!Array.isArray(policy.retry_on_errors)) {
|
|
161
|
+
throw new BatchConfigError('retry_policy.retry_on_errors must be an array');
|
|
162
|
+
}
|
|
163
|
+
if (!policy.retry_on_errors.every((e) => typeof e === 'string')) {
|
|
164
|
+
throw new BatchConfigError('retry_policy.retry_on_errors must contain only strings');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Merge batch configuration with CLI options and environment defaults
|
|
170
|
+
*/
|
|
171
|
+
export function mergeBatchConfig(config, options) {
|
|
172
|
+
const merged = { ...config };
|
|
173
|
+
// Apply environment defaults
|
|
174
|
+
if (!merged.output_dir && process.env.OUTPUT_DIR) {
|
|
175
|
+
merged.output_dir = process.env.OUTPUT_DIR;
|
|
176
|
+
}
|
|
177
|
+
// Apply CLI overrides
|
|
178
|
+
if (options.outputDir) {
|
|
179
|
+
merged.output_dir = options.outputDir;
|
|
180
|
+
}
|
|
181
|
+
if (options.maxConcurrent !== undefined) {
|
|
182
|
+
merged.max_concurrent = options.maxConcurrent;
|
|
183
|
+
}
|
|
184
|
+
if (options.timeout !== undefined) {
|
|
185
|
+
merged.timeout = options.timeout;
|
|
186
|
+
}
|
|
187
|
+
// Set defaults
|
|
188
|
+
merged.max_concurrent = merged.max_concurrent ?? 2;
|
|
189
|
+
merged.timeout = merged.timeout ?? 600000; // 10 minutes
|
|
190
|
+
merged.default_model = merged.default_model ?? 'grok-imagine-image';
|
|
191
|
+
merged.default_resolution = merged.default_resolution ?? '1k';
|
|
192
|
+
merged.default_aspect_ratio = merged.default_aspect_ratio ?? '1:1';
|
|
193
|
+
// Default retry policy
|
|
194
|
+
merged.retry_policy = merged.retry_policy ?? {
|
|
195
|
+
max_retries: 2,
|
|
196
|
+
retry_delay_ms: 1000,
|
|
197
|
+
retry_on_errors: ['rate_limit', 'timeout', '429', '503'],
|
|
198
|
+
};
|
|
199
|
+
return merged;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get default output directory
|
|
203
|
+
*/
|
|
204
|
+
export function getDefaultOutputDirectory() {
|
|
205
|
+
return process.env.OUTPUT_DIR || process.cwd();
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Resolve output path for a job
|
|
209
|
+
*/
|
|
210
|
+
export function resolveOutputPath(job, index, outputDir, allowAnyPath = false) {
|
|
211
|
+
let outputPath;
|
|
212
|
+
if (job.output_path) {
|
|
213
|
+
if (path.isAbsolute(job.output_path)) {
|
|
214
|
+
if (!allowAnyPath) {
|
|
215
|
+
// Security check: ensure path is within allowed directory
|
|
216
|
+
const resolved = path.resolve(job.output_path);
|
|
217
|
+
const allowedDir = path.resolve(outputDir);
|
|
218
|
+
if (!resolved.startsWith(allowedDir)) {
|
|
219
|
+
throw new BatchConfigError(`Job ${index + 1}: Output path must be within output directory. Use --allow-any-path to override.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
outputPath = job.output_path;
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
outputPath = path.join(outputDir, job.output_path);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// Generate default filename
|
|
230
|
+
const isEditJob = job.image_path || job.image_base64 || job.image_url;
|
|
231
|
+
const prefix = isEditJob ? 'edited' : 'generated';
|
|
232
|
+
outputPath = path.join(outputDir, `${prefix}_${index + 1}.jpg`);
|
|
233
|
+
}
|
|
234
|
+
return outputPath;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=batch-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-config.js","sourceRoot":"","sources":["../../src/utils/batch-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch execution manager with concurrency control
|
|
3
|
+
*/
|
|
4
|
+
import type { BatchConfig, BatchResult, BatchExecutionOptions, CostEstimate } from '../types/batch.js';
|
|
5
|
+
/**
|
|
6
|
+
* BatchManager handles batch execution with concurrency control
|
|
7
|
+
*/
|
|
8
|
+
export declare class BatchManager {
|
|
9
|
+
private apiKey;
|
|
10
|
+
constructor(apiKey: string);
|
|
11
|
+
/**
|
|
12
|
+
* Estimate cost for batch execution
|
|
13
|
+
*/
|
|
14
|
+
estimateBatchCost(config: BatchConfig): CostEstimate;
|
|
15
|
+
/**
|
|
16
|
+
* Execute batch jobs with concurrency control
|
|
17
|
+
*/
|
|
18
|
+
executeBatch(config: BatchConfig, options?: BatchExecutionOptions): Promise<BatchResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Execute a single job with retry logic
|
|
21
|
+
*/
|
|
22
|
+
private executeJob;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=batch-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-manager.d.ts","sourceRoot":"","sources":["../../src/utils/batch-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,WAAW,EAEX,WAAW,EAEX,qBAAqB,EACrB,YAAY,EACb,MAAM,mBAAmB,CAAC;AAgD3B;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY;IAkDpD;;OAEG;IACG,YAAY,CAChB,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,WAAW,CAAC;IA8FvB;;OAEG;YACW,UAAU;CAqIzB"}
|