-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimplementation.js
139 lines (117 loc) · 3.73 KB
/
implementation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
async function gpt_image_editor(params, userSettings, authorizedResources) {
const prompt = params.prompt;
const openaikey = userSettings.openaikey;
const quality = userSettings.quality || 'auto';
const resolution = userSettings.resolution || 'auto';
const background = userSettings.background || 'auto';
if (!openaikey) {
throw new Error(
'No OpenAI key provided to the DALL-3 plugin. Please enter your OpenAI key in the plugin settings seperately and try again.',
);
}
let resultBase64;
const content = authorizedResources?.lastUserMessage?.content || [];
let attachedImages = content
.filter((item) => item.type === 'tm_image_file')
.map((c) => ({
url: c.sync?.url || c.metadata?.base64,
name: c.metadata?.name,
}));
const lastToolCallCards =
authorizedResources?.lastSameToolCallResponse?.cards;
if (!attachedImages.length && Array.isArray(lastToolCallCards)) {
attachedImages = lastToolCallCards
.filter((c) => c.type === 'image')
.map((c) => ({
url: c.image.url,
name: 'output.png', // no name provided for tool output
}));
}
const mode = attachedImages.length ? 'edit' : 'create';
if (mode === 'create') {
const body = {
model: 'gpt-image-1',
prompt: prompt,
n: 1,
size: resolution,
quality: quality,
output_format: 'png',
background: background,
};
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + openaikey,
},
body: JSON.stringify(body),
};
let response = await fetch(
'https://api.openai.com/v1/images/generations',
requestOptions,
);
if (response.status === 401) {
throw new Error('Invalid OpenAI API Key. Please check your settings.');
}
if (!response.ok) {
const errorText = await response.text();
throw new Error(errorText);
}
let data = await response.json();
resultBase64 = data.data[0].b64_json;
} else if (mode === 'edit') {
const imagesAsBlobs = await Promise.all(
attachedImages.map(async ({ url, name }) => {
if (url.startsWith('data:image/')) {
const blob = await fetch(url).then((res) => res.blob());
return { blob, name };
}
const response = await fetch(url);
const blob = await response.blob();
return { blob, name };
}),
);
const formData = new FormData();
// Model and prompt are simple
formData.append('model', 'gpt-image-1');
formData.append('prompt', prompt);
formData.append('n', 1);
formData.append('size', resolution);
formData.append('quality', quality);
formData.append('output_format', 'png');
formData.append('background', background);
// Load images (from URLs) and append as Blobs
for (const { blob, name } of imagesAsBlobs) {
formData.append('image[]', blob, name);
}
// Call the API
const response = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
Authorization: `Bearer ${openaikey}`,
},
body: formData,
});
if (!response.ok) {
const err = await response.text();
throw new Error(`OpenAI API error: ${err}`);
}
const result = await response.json();
// Decode base64 and save as image (browser code varies; see below)
resultBase64 = result.data[0].b64_json;
} else {
throw new Error('Invalid mode. Please use "create" or "edit".');
}
return {
cards: [
{
type: 'image',
image: {
url: 'data:image/png;base64,' + resultBase64,
alt: prompt.replace(/[[]]/, ''),
sync: true,
},
},
],
};
}