backdraw 2.1.0 → 2.1.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/README.md +34 -2
- package/README.tr.md +34 -2
- package/bin/backdraw.js +4 -0
- package/extension/manifest.json +1 -1
- package/host.js +4 -2
- package/lib/results.js +6 -1
- package/mcp-server.js +8 -0
- package/package.json +3 -5
- package/setup.js +2 -1
package/README.md
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
<b>Let Claude generate images with your own ChatGPT account, in a background Chrome tab.<br>No API key, no extra cost, nothing to watch.</b>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/backdraw"><img src="https://img.shields.io/npm/v/backdraw" alt="npm version"></a>
|
|
11
|
+
<a href="https://glama.ai/mcp/servers/devtalh/backdraw"><img src="https://glama.ai/mcp/servers/devtalh/backdraw/badges/score.svg" alt="devtalh/backdraw MCP server"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
9
14
|
<p align="center">
|
|
10
15
|
<img src="branding/demo/backdraw-demo.gif" alt="Right-click images on the web to save them as references, then Claude Code asks Backdraw for an image in that style; ChatGPT draws it in a background tab and the file is saved on the PC" width="100%">
|
|
11
16
|
</p>
|
|
@@ -123,6 +128,8 @@ Run this in PowerShell or cmd (no admin rights needed):
|
|
|
123
128
|
npx backdraw@latest setup
|
|
124
129
|
```
|
|
125
130
|
|
|
131
|
+
It runs the [`backdraw` package from npm](https://www.npmjs.com/package/backdraw).
|
|
132
|
+
|
|
126
133
|
`setup` does everything except one click in the browser:
|
|
127
134
|
|
|
128
135
|
1. It copies Backdraw to `%USERPROFILE%\.backdraw` (npx's own copy is temporary) and sets up the
|
|
@@ -145,6 +152,28 @@ npx backdraw@latest setup
|
|
|
145
152
|
The native host is still named `io.github.muhammedtalha04.backdraw`, after the project's old GitHub
|
|
146
153
|
user name: renaming it would break existing installs.
|
|
147
154
|
|
|
155
|
+
### Install from your client
|
|
156
|
+
|
|
157
|
+
Your MCP client can also add Backdraw itself; it then starts the server with
|
|
158
|
+
`npx backdraw@latest mcp`. The browser side still needs a one-time setup on the PC, which leaves the
|
|
159
|
+
clients alone:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
npx backdraw@latest setup --clients=none
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| Client | Add Backdraw |
|
|
166
|
+
|---|---|
|
|
167
|
+
| Claude Code | `/plugin install backdraw --marketplace devtalh/backdraw` (Claude Code 2.1.275 or later; or `/plugin marketplace add devtalh/backdraw`, then `/plugin install backdraw@backdraw`). `/backdraw:setup` explains the browser step. |
|
|
168
|
+
| Cursor | [](https://cursor.com/install-mcp?name=backdraw&config=eyJjb21tYW5kIjoiY21kIiwiYXJncyI6WyIvYyIsIm5weCIsIi15IiwiYmFja2RyYXdAbGF0ZXN0IiwibWNwIl19) |
|
|
169
|
+
| VS Code | [](https://insiders.vscode.dev/redirect/mcp/install?name=backdraw&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22cmd%22%2C%22args%22%3A%5B%22%2Fc%22%2C%22npx%22%2C%22-y%22%2C%22backdraw%40latest%22%2C%22mcp%22%5D%7D) |
|
|
170
|
+
| Codex | `codex mcp add backdraw -- cmd /c npx -y backdraw@latest mcp` |
|
|
171
|
+
| Gemini CLI | `npx backdraw@latest setup --clients=gemini` |
|
|
172
|
+
|
|
173
|
+
On Windows the command goes through `cmd /c`, because clients start `npx` without a shell. Use one
|
|
174
|
+
way per client: if setup already added Backdraw to Claude Code, the plugin would start a second
|
|
175
|
+
server with the same tools.
|
|
176
|
+
|
|
148
177
|
### Manual install
|
|
149
178
|
|
|
150
179
|
1. **Get the code.** Clone the repository with git, or download it as a ZIP (**Code** →
|
|
@@ -388,7 +417,7 @@ themselves stay in your images folder.
|
|
|
388
417
|
|
|
389
418
|
| Tool | Parameters (default) | What it does |
|
|
390
419
|
|---|---|---|
|
|
391
|
-
| `generate_image` | `prompt` (required), `aspect_ratio`, `transparent_background` (false), `reference_images`, `reference_collection`, `reference_files`, `conversation_url`, `auto_reattach` (false), `send_as_is` (false), `output_dir`, `wait_seconds` (45), `include_preview` (true) | Starts a new chat in your Project (or continues `conversation_url`) and generates or edits an image. |
|
|
420
|
+
| `generate_image` | `prompt` (required), `aspect_ratio`, `transparent_background` (false), `reference_images`, `reference_collection`, `reference_files`, `conversation_url`, `auto_reattach` (false), `send_as_is` (false), `output_dir`, `filename_hint`, `wait_seconds` (45), `include_preview` (true) | Starts a new chat in your Project (or continues `conversation_url`) and generates or edits an image. |
|
|
392
421
|
| `job_status` | `job_id`, `wait_seconds` (45), `include_preview` (true) | Waits for a job and reports it. Without `job_id`: the bridge status (Chrome connected, selected Project, images folder, queue, recent jobs). |
|
|
393
422
|
| `cancel_job` | `job_id` (required) | Cancels a queued or running job. If ChatGPT is already generating, it presses Stop in the background tab. |
|
|
394
423
|
| `fetch_images` | `conversation_url` (required), `aspect_ratio`, `output_dir`, `wait_seconds` (45), `include_preview` (true) | Downloads the images of the latest answer in an existing chat, without sending anything. |
|
|
@@ -406,6 +435,8 @@ themselves stay in your images folder.
|
|
|
406
435
|
- `send_as_is`: send the prompt word for word, without the short instruction Backdraw adds (e.g. to
|
|
407
436
|
answer a question ChatGPT asked).
|
|
408
437
|
- `output_dir`: also copy the result into this folder; the images folder always keeps a copy.
|
|
438
|
+
- `filename_hint`: a few words naming the subject, used for the file name instead of the start of
|
|
439
|
+
the prompt (handy when the prompt opens with instructions about the reference images).
|
|
409
440
|
- `wait_seconds`: 0 to 900.
|
|
410
441
|
|
|
411
442
|
What a result can say:
|
|
@@ -435,7 +466,8 @@ waiting; the job keeps running until `cancel_job` stops it.
|
|
|
435
466
|
|
|
436
467
|
For setup and troubleshooting, run these in the Backdraw folder (`%USERPROFILE%\.backdraw`, or the
|
|
437
468
|
folder you installed from). From anywhere, `npx backdraw <command>` runs the same commands, e.g.
|
|
438
|
-
`npx backdraw status`. `npm run status` is the same as `node cli.js status`.
|
|
469
|
+
`npx backdraw status`. `npm run status` is the same as `node cli.js status`. `backdraw mcp` runs
|
|
470
|
+
the MCP server itself on stdio; that is what MCP clients start.
|
|
439
471
|
|
|
440
472
|
```
|
|
441
473
|
node cli.js status Bridge status (Chrome connected, selected project, queue)
|
package/README.tr.md
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
<b>Claude, kendi ChatGPT hesabınla, Chrome'da arka plandaki bir sekmede görsel üretsin.<br>API anahtarı yok, ek ücret yok, başında beklemene gerek yok.</b>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/backdraw"><img src="https://img.shields.io/npm/v/backdraw" alt="npm sürümü"></a>
|
|
11
|
+
<a href="https://glama.ai/mcp/servers/devtalh/backdraw"><img src="https://glama.ai/mcp/servers/devtalh/backdraw/badges/score.svg" alt="devtalh/backdraw MCP sunucusu"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
9
14
|
<p align="center">
|
|
10
15
|
<img src="branding/demo/backdraw-demo.gif" alt="Web'deki görseller sağ tıkla referans olarak kaydediliyor, sonra Claude Code Backdraw'dan o tarzda bir görsel istiyor; ChatGPT görseli arka plan sekmesinde çiziyor ve dosya bilgisayara kaydediliyor" width="100%">
|
|
11
16
|
</p>
|
|
@@ -123,6 +128,8 @@ Bunu PowerShell'de ya da cmd'de çalıştır (yönetici izni gerekmez):
|
|
|
123
128
|
npx backdraw@latest setup
|
|
124
129
|
```
|
|
125
130
|
|
|
131
|
+
Bu komut [npm'deki `backdraw` paketini](https://www.npmjs.com/package/backdraw) çalıştırır.
|
|
132
|
+
|
|
126
133
|
`setup`, tarayıcıdaki tek bir tıklama dışında her şeyi yapar:
|
|
127
134
|
|
|
128
135
|
1. Backdraw'ı `%USERPROFILE%\.backdraw` klasörüne kopyalar (npx'in kendi kopyası geçicidir) ve görsel
|
|
@@ -146,6 +153,28 @@ npx backdraw@latest setup
|
|
|
146
153
|
Native host'un adı, projenin eski GitHub kullanıcı adından gelen
|
|
147
154
|
`io.github.muhammedtalha04.backdraw` olarak kalıyor: adı değiştirmek mevcut kurulumları bozardı.
|
|
148
155
|
|
|
156
|
+
### İstemcinden kur
|
|
157
|
+
|
|
158
|
+
MCP istemcin Backdraw'ı kendisi de ekleyebilir; o zaman sunucuyu `npx backdraw@latest mcp` ile
|
|
159
|
+
başlatır. Tarayıcı tarafı yine de bilgisayarda bir kerelik bir kurulum ister; bu kurulum istemcilere
|
|
160
|
+
dokunmaz:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
npx backdraw@latest setup --clients=none
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| İstemci | Backdraw'ı ekle |
|
|
167
|
+
|---|---|
|
|
168
|
+
| Claude Code | `/plugin install backdraw --marketplace devtalh/backdraw` (Claude Code 2.1.275 ya da daha yeni; ya da önce `/plugin marketplace add devtalh/backdraw`, sonra `/plugin install backdraw@backdraw`). `/backdraw:setup` tarayıcı adımını anlatır. |
|
|
169
|
+
| Cursor | [](https://cursor.com/install-mcp?name=backdraw&config=eyJjb21tYW5kIjoiY21kIiwiYXJncyI6WyIvYyIsIm5weCIsIi15IiwiYmFja2RyYXdAbGF0ZXN0IiwibWNwIl19) |
|
|
170
|
+
| VS Code | [](https://insiders.vscode.dev/redirect/mcp/install?name=backdraw&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22cmd%22%2C%22args%22%3A%5B%22%2Fc%22%2C%22npx%22%2C%22-y%22%2C%22backdraw%40latest%22%2C%22mcp%22%5D%7D) |
|
|
171
|
+
| Codex | `codex mcp add backdraw -- cmd /c npx -y backdraw@latest mcp` |
|
|
172
|
+
| Gemini CLI | `npx backdraw@latest setup --clients=gemini` |
|
|
173
|
+
|
|
174
|
+
Windows'ta komut `cmd /c` üzerinden çalışır, çünkü istemciler `npx`'i kabuk olmadan başlatır. Her
|
|
175
|
+
istemci için tek yol kullan: setup Backdraw'ı Claude Code'a zaten eklediyse, plugin aynı araçlarla
|
|
176
|
+
ikinci bir sunucu başlatır.
|
|
177
|
+
|
|
149
178
|
### Elle kurulum
|
|
150
179
|
|
|
151
180
|
1. **Kodu indir.** Depoyu git ile klonla ya da ZIP olarak indir (**Code** → **Download ZIP**) ve
|
|
@@ -398,7 +427,7 @@ klasöründe kalır.
|
|
|
398
427
|
|
|
399
428
|
| Araç | Parametreler (varsayılan) | Ne yapar |
|
|
400
429
|
|---|---|---|
|
|
401
|
-
| `generate_image` | `prompt` (zorunlu), `aspect_ratio`, `transparent_background` (false), `reference_images`, `reference_collection`, `reference_files`, `conversation_url`, `auto_reattach` (false), `send_as_is` (false), `output_dir`, `wait_seconds` (45), `include_preview` (true) | Projende yeni bir sohbet başlatır (ya da `conversation_url`'deki sohbete devam eder) ve görsel üretir veya düzenler. |
|
|
430
|
+
| `generate_image` | `prompt` (zorunlu), `aspect_ratio`, `transparent_background` (false), `reference_images`, `reference_collection`, `reference_files`, `conversation_url`, `auto_reattach` (false), `send_as_is` (false), `output_dir`, `filename_hint`, `wait_seconds` (45), `include_preview` (true) | Projende yeni bir sohbet başlatır (ya da `conversation_url`'deki sohbete devam eder) ve görsel üretir veya düzenler. |
|
|
402
431
|
| `job_status` | `job_id`, `wait_seconds` (45), `include_preview` (true) | Bir işi bekler ve durumunu bildirir. `job_id` olmadan köprünün durumunu verir (Chrome bağlı mı, seçili Proje, görsel klasörü, kuyruk, son işler). |
|
|
403
432
|
| `cancel_job` | `job_id` (zorunlu) | Kuyruktaki ya da çalışan bir işi iptal eder. ChatGPT üretmeye başladıysa arka plan sekmesinde Durdur'a basar. |
|
|
404
433
|
| `fetch_images` | `conversation_url` (zorunlu), `aspect_ratio`, `output_dir`, `wait_seconds` (45), `include_preview` (true) | Var olan bir sohbetin son cevabındaki görselleri, hiçbir şey göndermeden indirir. |
|
|
@@ -417,6 +446,8 @@ klasöründe kalır.
|
|
|
417
446
|
- `send_as_is`: istemi, Backdraw'ın eklediği kısa talimat olmadan, olduğu gibi gönderir (örneğin
|
|
418
447
|
ChatGPT'nin sorduğu bir soruyu yanıtlamak için).
|
|
419
448
|
- `output_dir`: sonucu bu klasöre de kopyalar; görsel klasöründe her zaman bir kopya kalır.
|
|
449
|
+
- `filename_hint`: konuyu anlatan birkaç kelime; dosya adı istemin başı yerine bundan üretilir
|
|
450
|
+
(istem referans görsellerle ilgili talimatlarla başlıyorsa işe yarar).
|
|
420
451
|
- `wait_seconds`: 0 ile 900 arası.
|
|
421
452
|
|
|
422
453
|
Bir sonuç şunları söyleyebilir:
|
|
@@ -446,7 +477,8 @@ beklemeyi durdurur; iş, `cancel_job` onu durdurana kadar sürer.
|
|
|
446
477
|
|
|
447
478
|
Kurulum ve sorun giderme için bunları Backdraw klasöründe çalıştır (`%USERPROFILE%\.backdraw` ya da
|
|
448
479
|
kurulumu yaptığın klasör). Her yerden `npx backdraw <komut>` aynı komutları çalıştırır, örneğin
|
|
449
|
-
`npx backdraw status`. `npm run status`, `node cli.js status` ile aynıdır.
|
|
480
|
+
`npx backdraw status`. `npm run status`, `node cli.js status` ile aynıdır. `backdraw mcp`, MCP
|
|
481
|
+
sunucusunun kendisini stdio üzerinde çalıştırır; MCP istemcilerinin başlattığı budur.
|
|
450
482
|
|
|
451
483
|
```
|
|
452
484
|
node cli.js status Köprünün durumu (Chrome bağlı mı, seçili proje, kuyruk)
|
package/bin/backdraw.js
CHANGED
|
@@ -16,6 +16,7 @@ Usage: backdraw <command>
|
|
|
16
16
|
clients: claude-code, claude-desktop, codex, cursor, vscode, gemini
|
|
17
17
|
doctor [--fix] Check the install; --fix repairs registrations
|
|
18
18
|
uninstall [--dry-run] Remove the registrations (your images and settings stay)
|
|
19
|
+
mcp Run the MCP server on stdio (what MCP clients start; needs setup once)
|
|
19
20
|
--version Print the version
|
|
20
21
|
${cli.USAGE.split('\n').slice(1).join('\n')}`;
|
|
21
22
|
|
|
@@ -33,6 +34,9 @@ async function main(argv) {
|
|
|
33
34
|
const [cmd, ...rest] = argv;
|
|
34
35
|
const { flags } = parseArgs(rest, { booleans: ['yes', 'fix', 'dry-run', 'no-wait'] });
|
|
35
36
|
switch (cmd) {
|
|
37
|
+
// stdout belongs to the JSON-RPC stream from here on; the server reads stdin until it closes.
|
|
38
|
+
case 'mcp':
|
|
39
|
+
return require('../mcp-server');
|
|
36
40
|
case '-v': case '--version': case 'version':
|
|
37
41
|
return console.log(VERSION);
|
|
38
42
|
case 'setup':
|
package/extension/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Backdraw",
|
|
4
4
|
"short_name": "Backdraw",
|
|
5
|
-
"version": "2.1.
|
|
5
|
+
"version": "2.1.2",
|
|
6
6
|
"description": "__MSG_extDescription__",
|
|
7
7
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtu/jyAJ3e3hnNrNGCxfzvHLOp80L9c3j71jmQV2ymY1DbPfZNJUdrszM3dnk6SFlm/X42F/e1Pf9RoQqMKujWr7KRTtH257vBMmLbk8Eo0LytpGP0F8WOQIcp5TxLZgvqSlGTjdbB2QFJt+uisJFE8Y3nWnZpsmejes0m9NObpqBc7Q1tzZrDAnh6gzddyF8fkYU/gS2Qtu5Vd2YbRiVN18tUUh2Bb+QuXlTlzOE1JQ49A9qRTmXejtcn943ZaQ0aucooNQU4hZAFVUT+25UhzuGMZDFzZALqL19hP0EP4Erm1yitjICvR5yK/7nYObGa3LynEeH7dDJ+qoJaf4TEQIDAQAB",
|
|
8
8
|
"default_locale": "en",
|
package/host.js
CHANGED
|
@@ -199,6 +199,8 @@ function createJob(p) {
|
|
|
199
199
|
// outputDir: legacy clients, the host writes a copy there. copyTo: the MCP server copies itself
|
|
200
200
|
// (it runs in the caller's context, so the copy lands where the caller can see it).
|
|
201
201
|
outputDir: p.outputDir || null, copyTo: p.copyTo || null, copies: [],
|
|
202
|
+
// Names the saved files instead of the prompt (whose opening may be instructions, not the subject).
|
|
203
|
+
filenameHint: String(p.filenameHint || '').trim().slice(0, 200) || null,
|
|
202
204
|
references: refs.map(r => ({ name: r.name, bytes: Math.round(r.data.length * 0.75) })), autoReattach: !!p.autoReattach,
|
|
203
205
|
timeoutSec: clamp(Number(p.timeoutSec) || 600, 60, 1800),
|
|
204
206
|
createdAt: now(), startedAt: null, finishedAt: null,
|
|
@@ -323,9 +325,9 @@ function uniquePath(dir, base, ext) {
|
|
|
323
325
|
function saveImages(job, images, title) {
|
|
324
326
|
fs.mkdirSync(config.outputDir, { recursive: true });
|
|
325
327
|
fs.mkdirSync(shared.PREVIEW_DIR, { recursive: true });
|
|
326
|
-
// Named after the prompt; when only collecting (no prompt) ChatGPT's chat title
|
|
328
|
+
// Named after filename_hint, else the prompt; when only collecting (no prompt) ChatGPT's chat title.
|
|
327
329
|
const usefulTitle = title && !/^(chatgpt\b|generate an image|update the image)/i.test(title.trim()) ? title : '';
|
|
328
|
-
const base = `${stamp()}_${slugify(job.prompt || usefulTitle)}`;
|
|
330
|
+
const base = `${stamp()}_${slugify(job.filenameHint || job.prompt || usefulTitle)}`;
|
|
329
331
|
return images.map((img, i) => {
|
|
330
332
|
const buf = Buffer.from(img.data || '', 'base64');
|
|
331
333
|
if (buf.length < 100) throw new Error('empty image data');
|
package/lib/results.js
CHANGED
|
@@ -15,6 +15,9 @@ const checkAgain = id => `Call job_status with job_id="${id}" and wait_seconds=$
|
|
|
15
15
|
// A prompt that asks to change an existing image rather than draw a new one.
|
|
16
16
|
const EDIT_INTENT = /\b(edit(s|ed|ing)?|modif(y|ies|ied|ying)|retouch(es|ed|ing)?|inpaint(s|ed|ing)?|change only|only change|change [a-z ]{1,30} only|keep (everything|it|the rest)|pixel-identical|same (pose|image|drawing|character))\b|düzenle|değiştir|aynı (kalsın|bırak|tut)|koru(yarak)?\b/i;
|
|
17
17
|
|
|
18
|
+
const SHOW_IMAGE = 'Show the image to the user in the chat: if you can display or share a local file with the user, do that with the Saved path above ' +
|
|
19
|
+
'(any preview attached here is a small copy for you to check); otherwise give that path clearly.';
|
|
20
|
+
|
|
18
21
|
const neutral = (pct, against) => `Similarity to ${against}: ${pct}% (a local edit keeps ~95-100%, a redraw is usually under 60%).`;
|
|
19
22
|
|
|
20
23
|
function editCheckLines(job) {
|
|
@@ -156,6 +159,8 @@ function resultLines(job) {
|
|
|
156
159
|
for (const im of job.images || []) lines.push(...imageLines(job, im));
|
|
157
160
|
for (const c of job.copies || []) lines.push(`Copied to: ${c}`);
|
|
158
161
|
if (job.copyError) lines.push(`Could not copy into output_dir: ${job.copyError}`);
|
|
162
|
+
// Clients differ: some show the attached preview only as a small icon, so ask for the file itself.
|
|
163
|
+
if (job.status === 'succeeded' && (job.images || []).length) lines.push(SHOW_IMAGE);
|
|
159
164
|
lines.push(...editCheckLines(job));
|
|
160
165
|
if (job.assistantText) {
|
|
161
166
|
lines.push(job.status === 'succeeded' ? `ChatGPT's text: ${job.assistantText.slice(0, 1500)}` : `ChatGPT's reply:\n${job.assistantText.slice(0, 3000)}`);
|
|
@@ -167,4 +172,4 @@ function resultLines(job) {
|
|
|
167
172
|
return lines;
|
|
168
173
|
}
|
|
169
174
|
|
|
170
|
-
module.exports = { FINAL, DEFAULT_WAIT, EDIT_INTENT, waitSeconds, editCheckLines, imageLines, referenceLines, resultLines };
|
|
175
|
+
module.exports = { FINAL, DEFAULT_WAIT, EDIT_INTENT, SHOW_IMAGE, waitSeconds, editCheckLines, imageLines, referenceLines, resultLines };
|
package/mcp-server.js
CHANGED
|
@@ -19,12 +19,14 @@ const INSTRUCTIONS = `Generates images with the user's own ChatGPT account (alre
|
|
|
19
19
|
- To EDIT an image or keep a character consistent, pass the image file(s) in reference_images (e.g. a file saved by an earlier call). A fresh chat with reference_images is the most reliable way to edit; long revision chains via conversation_url make ChatGPT lose track of earlier images.
|
|
20
20
|
- For a specific shape (banner, avatar, phone wallpaper) pass aspect_ratio instead of describing the size in the prompt; for stickers/logos/icons that need a see-through background pass transparent_background=true and read the transparency line in the result.
|
|
21
21
|
- When the user mentions one of their Backdraw collections (reference images they saved from the web in Chrome), call list_collections if needed and pass reference_collection to generate_image.
|
|
22
|
+
- The saved file is named after the start of the prompt. When the prompt opens with something other than the subject (e.g. instructions about the reference images), pass filename_hint with a few words naming what the user asked for.
|
|
22
23
|
- Read every result line: NEEDS REFERENCE IMAGE means ChatGPT could not reach the image to edit; CHATGPT REPLIED WITHOUT AN IMAGE shows ChatGPT's own text. Never resend the identical prompt in a loop; follow the next step given in the result.
|
|
23
24
|
- An EDIT CHECK warning means ChatGPT drew a new picture instead of editing; tell the user and retry with reference_images in a fresh chat if an exact edit is needed.
|
|
24
25
|
- The work happens in a background Chrome tab; never tell the user to switch tabs unless a result says NEEDS USER ACTION.
|
|
25
26
|
- NEEDS USER ACTION means ChatGPT shows a login or human-verification (CAPTCHA) page: ask the user to open the ChatGPT tab in Chrome and finish it themselves. Never try to get around it. The job continues automatically afterwards (check with job_status).
|
|
26
27
|
- If no project is selected, call list_projects, then select_project with the user's images project.
|
|
27
28
|
- If a job timed out but has a conversation link, fetch_images can still download the result later; pass the job's aspect_ratio again so it is cropped the same way.
|
|
29
|
+
- After SUCCESS, show the saved image to the user in the chat: if you can display or share a local file with the user, do that with the saved path (the preview in the result is a small copy for you to check); otherwise give the saved path clearly.
|
|
28
30
|
- Report the saved file path(s) and the ChatGPT conversation link to the user.`;
|
|
29
31
|
|
|
30
32
|
// Shared by the tools that wait for a job.
|
|
@@ -78,6 +80,11 @@ const TOOLS = [
|
|
|
78
80
|
type: 'string',
|
|
79
81
|
description: "Optional folder to also copy the image(s) into, e.g. the current project's assets folder (absolute path preferred). The central images folder always keeps a copy.",
|
|
80
82
|
},
|
|
83
|
+
filename_hint: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description: "Optional few words naming the subject (e.g. 'red fox mascot'), used for the saved file name instead of the start of the prompt. " +
|
|
86
|
+
'Pass it when the prompt opens with something else, such as instructions about the reference images.',
|
|
87
|
+
},
|
|
81
88
|
wait_seconds: WAIT_SECONDS,
|
|
82
89
|
include_preview: { type: 'boolean', default: true, description: 'Attach a downscaled preview of the result so you can check it.' },
|
|
83
90
|
send_as_is: { type: 'boolean', default: false, description: 'Send the prompt verbatim, without the short instruction the bridge adds (useful to answer a question ChatGPT asked).' },
|
|
@@ -302,6 +309,7 @@ async function generateImage(args, call) {
|
|
|
302
309
|
prompt, references, autoReattach: !!args.auto_reattach, sendAsIs: !!args.send_as_is,
|
|
303
310
|
aspect: args.aspect_ratio, transparent: !!args.transparent_background,
|
|
304
311
|
copyTo: args.output_dir ? path.resolve(String(args.output_dir)) : undefined,
|
|
312
|
+
filenameHint: args.filename_hint ? String(args.filename_hint) : undefined,
|
|
305
313
|
startUrl: args.conversation_url ? String(args.conversation_url) : undefined,
|
|
306
314
|
referenceCollection: args.reference_collection ? String(args.reference_collection) : undefined,
|
|
307
315
|
// A single file name as a string works too, like reference_images.
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backdraw",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "Local MCP server, native messaging host and Chrome extension that let Claude generate images with your own signed-in ChatGPT account in a background tab.",
|
|
5
|
+
"mcpName": "io.github.devtalh/backdraw",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"author": "devtalh",
|
|
7
8
|
"homepage": "https://github.com/devtalh/backdraw#readme",
|
|
@@ -49,8 +50,5 @@
|
|
|
49
50
|
"status": "node cli.js status",
|
|
50
51
|
"install-bridge": "node install.js",
|
|
51
52
|
"test": "node --test"
|
|
52
|
-
}
|
|
53
|
-
"os": [
|
|
54
|
-
"win32"
|
|
55
|
-
]
|
|
53
|
+
}
|
|
56
54
|
}
|
package/setup.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// own copy is temporary), registers the native host for the installed browsers, adds Backdraw to
|
|
4
4
|
// the MCP clients the user picks, then walks through loading the extension and waits for it.
|
|
5
5
|
// --yes no questions: every client that was found
|
|
6
|
-
// --clients=a,b exactly these (ids: see CLIENT_IDS)
|
|
6
|
+
// --clients=a,b exactly these (ids: see CLIENT_IDS); --clients=none: none, the browser side only
|
|
7
7
|
// --browser=edge the browser to load the extension in (default: the first one found)
|
|
8
8
|
// --no-wait don't wait for the extension to connect
|
|
9
9
|
const fs = require('fs');
|
|
@@ -31,6 +31,7 @@ function detectClients(c) {
|
|
|
31
31
|
function parseClientList(value) {
|
|
32
32
|
if (value === true || value === '') throw new Error(`--clients needs a list, e.g. --clients=claude-code,cursor (one of: ${CLIENT_IDS.join(', ')}).`);
|
|
33
33
|
const ids = String(value).split(',').map(s => s.trim().toLowerCase()).filter(Boolean);
|
|
34
|
+
if (ids.length === 1 && ids[0] === 'none') return []; // the browser side only (e.g. the Claude Code plugin)
|
|
34
35
|
const unknown = ids.filter(id => !CLIENT_IDS.includes(id));
|
|
35
36
|
if (unknown.length) throw new Error(`Unknown client ${unknown.join(', ')}; use: ${CLIENT_IDS.join(', ')}.`);
|
|
36
37
|
return [...new Set(ids)];
|