autodev-cli 1.4.151 → 1.4.153

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.
@@ -12,18 +12,29 @@ export interface GimpInstallDeps {
12
12
  /** Read an existing file (for idempotent-skip content comparison). '' if unreadable. */
13
13
  readFile: (p: string) => string;
14
14
  /**
15
- * The auto-start plugin source. Defaults to the EMBEDDED string
15
+ * The GIMP-side plug-in (server) source. Defaults to the EMBEDDED string
16
16
  * (GIMP_PLUGIN_SOURCE) so it works when esbuild-bundled into the VS Code
17
17
  * extension where media/gimp/gimp_mcp_server.py is NOT on disk at runtime.
18
18
  */
19
19
  readPluginSource: () => string;
20
+ /**
21
+ * The MCP client source. Defaults to the EMBEDDED string (GIMP_CLIENT_SOURCE),
22
+ * same bundle-safety rationale as readPluginSource.
23
+ */
24
+ readClientSource: () => string;
20
25
  /** GIMP detection (to gate on major < 3). Defaults to detectApp('gimp'). */
21
26
  detectGimp: () => DetectAppResult;
22
27
  }
23
28
  export interface GimpInstallResult {
24
29
  installed: boolean;
25
- /** Absolute path(s) of the written gimp_mcp_server.py file(s). */
30
+ /** Primary GIMP-side plug-in .py path written (the real %APPDATA%/config one). */
31
+ serverPath: string | null;
32
+ /** Primary MCP client .py path written (<ver>/mcp/gimp_mcp_client.py). */
33
+ clientPath: string | null;
34
+ /** All plug-in (server) .py paths written (incl. the win32 Store fallback). */
26
35
  paths: string[];
36
+ /** All MCP client .py paths written. */
37
+ clientPaths: string[];
27
38
  /** The GIMP minor-version dir chosen (e.g. "3.2"), or null when not installed. */
28
39
  version: string | null;
29
40
  warnings: string[];
@@ -35,23 +46,35 @@ export interface GimpInstallOpts {
35
46
  */
36
47
  targetDir?: string;
37
48
  }
38
- /** Absolute path to the vendored auto-start plugin shipped in the tarball. */
49
+ /** Absolute path to the vendored plug-in (server) shipped in the tarball. */
39
50
  export declare function vendoredPluginSourcePath(): string;
51
+ /** Absolute path to the vendored MCP client shipped in the tarball. */
52
+ export declare function vendoredClientSourcePath(): string;
53
+ /** The MCP client .py path for a versioned config dir (sibling `mcp/` folder). */
54
+ export declare function clientPathFor(configDir: string): string;
40
55
  /** Extract the GIMP MAJOR version from a launcher path (e.g. gimp-2.10 → 2). */
41
56
  export declare function gimpMajorFromPath(p: string | null): number | null;
42
57
  /**
43
- * Install the auto-start GIMP MCP plugin. Resolves the target plug-ins dir(s)
44
- * per-OS and writes the vendored plugin so GIMP opens the localhost:9876 socket
45
- * on launch. Does NOT install when a clearly < 3 GIMP is the only one detected.
58
+ * Install BOTH the GIMP-side plug-in (server) and the MCP client. Resolves the
59
+ * target config dir(s) per-OS and writes the vendored files. Does NOT install
60
+ * when a clearly < 3 GIMP is the only one detected.
46
61
  */
47
62
  export declare function installGimpPlugin(opts?: GimpInstallOpts, deps?: Partial<GimpInstallDeps>): GimpInstallResult;
48
63
  /**
49
- * Sync-path variant: install the auto-start plugin ONLY when GIMP 3.x is actually
50
- * DETECTED. Unlike installGimpPlugin (which will create a 3.0 config dir even with
51
- * no GIMP present — appropriate for the explicit `mcp detect --enable gimp` /
52
- * `gimp-install-plugin` flows), this refuses to touch the filesystem when GIMP is
53
- * absent or is clearly < 3, so a routine ConfigManager.syncProjectMcpServers on a
54
- * box without GIMP never spuriously creates a config dir. Returns a skip result
55
- * (installed:false + warning) instead of throwing so callers can swallow it.
64
+ * Sync-path variant: install ONLY when GIMP 3.x is actually DETECTED. Unlike
65
+ * installGimpPlugin (which will create a 3.0 config dir even with no GIMP present
66
+ * — appropriate for the explicit `mcp detect --enable gimp` / `gimp-install-plugin`
67
+ * flows), this refuses to touch the filesystem when GIMP is absent or is clearly
68
+ * < 3, so a routine ConfigManager.syncProjectMcpServers on a box without GIMP
69
+ * never spuriously creates a config dir. Returns a skip result (installed:false +
70
+ * warning) instead of throwing so callers can swallow it.
56
71
  */
57
72
  export declare function installGimpPluginIfDetected(opts?: GimpInstallOpts, deps?: Partial<GimpInstallDeps>): GimpInstallResult;
73
+ /**
74
+ * Resolve the PRIMARY MCP client path for the current machine WITHOUT writing
75
+ * anything — gated on GIMP 3.x being detected (same gate as
76
+ * installGimpPluginIfDetected). Returns null when GIMP is absent / clearly < 3,
77
+ * so callers (the migration, catalog display) can decide not to bake a path in.
78
+ * This is the exact path installGimpPlugin() would write the client to.
79
+ */
80
+ export declare function resolveGimpClientPath(opts?: GimpInstallOpts, deps?: Partial<GimpInstallDeps>): string | null;
@@ -1,8 +1,15 @@
1
1
  "use strict";
2
2
  // ---------------------------------------------------------------------------
3
- // gimpPluginInstall — drop the vendored AUTO-START GIMP MCP plugin into the
4
- // correct GIMP 3.x user plug-ins folder so the socket bridge opens on GIMP
5
- // launch (no manual copy, no menu click).
3
+ // gimpPluginInstall — drop the vendored, USER-VERIFIED GIMP MCP files into the
4
+ // correct GIMP 3.x user config so the socket bridge works end-to-end:
5
+ // - the GIMP-side PLUG-IN (server) → plug-ins/gimp_mcp_server/gimp_mcp_server.py
6
+ // - the MCP CLIENT → mcp/gimp_mcp_client.py (a sibling dir)
7
+ //
8
+ // The plug-in is MENU-TRIGGERED (the user's verified flow): in GIMP the user runs
9
+ // Tools → MCP → Start MCP Server (or Filters → Development → Start MCP Server) and
10
+ // keeps the "GIMP MCP Server" window open — that holds the out-of-process plug-in
11
+ // alive and the :9876 socket. We do NOT auto-start it (the PERSISTENT approach we
12
+ // tried did not work on GIMP 3.2); we only install the files.
6
13
  //
7
14
  // GROUNDED RULES (see AutoDev research):
8
15
  // - GIMP 3.x user config is MINOR-versioned: GIMP 3.2 → .../GIMP/3.2/ (NOT 3.0).
@@ -12,14 +19,15 @@
12
19
  // exists, create 3.0 and warn (user should launch GIMP once).
13
20
  // - GIMP 3.x layout: plug-ins/gimp_mcp_server/gimp_mcp_server.py — the .py MUST
14
21
  // sit in a sub-folder whose name == the .py basename (a loose .py is ignored).
15
- // On non-Windows the .py must be executable (0o755).
22
+ // On non-Windows the .py must be executable (0o755). The client sits at
23
+ // <ver>/mcp/gimp_mcp_client.py (also 0o755 on non-Windows).
16
24
  // - Windows Store (MSIX) GIMP reads the REAL %APPDATA%\GIMP\<ver>. As a safety
17
25
  // net we ALSO write the virtualized path when a package dir exists:
18
- // %LOCALAPPDATA%\Packages\GIMP.<...>_*\LocalCache\Roaming\GIMP\<ver>\plug-ins.
26
+ // %LOCALAPPDATA%\Packages\GIMP.<...>_*\LocalCache\Roaming\GIMP\<ver>\… .
19
27
  //
20
28
  // Everything is dependency-injected (platform/env/homedir/fileExists/listDir/
21
- // mkdirp/writeFile/chmod/copyFile/readPluginSource/detectGimp) so the resolver is
22
- // unit-testable without a real GIMP or filesystem.
29
+ // mkdirp/writeFile/chmod/copyFile/readPluginSource/readClientSource/detectGimp) so
30
+ // the resolver is unit-testable without a real GIMP or filesystem.
23
31
  // ---------------------------------------------------------------------------
24
32
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
33
  if (k2 === undefined) k2 = k;
@@ -56,19 +64,27 @@ var __importStar = (this && this.__importStar) || (function () {
56
64
  })();
57
65
  Object.defineProperty(exports, "__esModule", { value: true });
58
66
  exports.vendoredPluginSourcePath = vendoredPluginSourcePath;
67
+ exports.vendoredClientSourcePath = vendoredClientSourcePath;
68
+ exports.clientPathFor = clientPathFor;
59
69
  exports.gimpMajorFromPath = gimpMajorFromPath;
60
70
  exports.installGimpPlugin = installGimpPlugin;
61
71
  exports.installGimpPluginIfDetected = installGimpPluginIfDetected;
72
+ exports.resolveGimpClientPath = resolveGimpClientPath;
62
73
  const fs = __importStar(require("fs"));
63
74
  const path = __importStar(require("path"));
64
75
  const os = __importStar(require("os"));
65
76
  const binDetect_1 = require("./binDetect");
66
77
  const gimpPluginSource_1 = require("./gimpPluginSource");
67
- /** Absolute path to the vendored auto-start plugin shipped in the tarball. */
78
+ const gimpClientSource_1 = require("./gimpClientSource");
79
+ /** Absolute path to the vendored plug-in (server) shipped in the tarball. */
68
80
  function vendoredPluginSourcePath() {
69
81
  // Compiled to out/core/gimpPluginInstall.js → package root is ../../ .
70
82
  return path.join(__dirname, '..', '..', 'media', 'gimp', 'gimp_mcp_server.py');
71
83
  }
84
+ /** Absolute path to the vendored MCP client shipped in the tarball. */
85
+ function vendoredClientSourcePath() {
86
+ return path.join(__dirname, '..', '..', 'media', 'gimp', 'gimp_mcp_client.py');
87
+ }
72
88
  function realDeps() {
73
89
  return {
74
90
  platform: process.platform,
@@ -99,9 +115,10 @@ function realDeps() {
99
115
  catch {
100
116
  return '';
101
117
  } },
102
- // Runtime uses the EMBEDDED source (bundle-safe). media/gimp/gimp_mcp_server.py
103
- // stays the canonical source + GPL attribution, but is no longer read at runtime.
118
+ // Runtime uses the EMBEDDED sources (bundle-safe). media/gimp/*.py stay the
119
+ // canonical source + GPL attribution, but are no longer read at runtime.
104
120
  readPluginSource: () => gimpPluginSource_1.GIMP_PLUGIN_SOURCE,
121
+ readClientSource: () => gimpClientSource_1.GIMP_CLIENT_SOURCE,
105
122
  detectGimp: () => (0, binDetect_1.detectApp)('gimp'),
106
123
  };
107
124
  }
@@ -140,10 +157,38 @@ function chooseVersion(base, d) {
140
157
  return { version: kids[0].name, existed: true };
141
158
  }
142
159
  /**
143
- * Windows Store virtualized fallback plug-ins dir(s) for a given version. Only
144
- * returned when a `GIMP.*` package dir actually exists under %LOCALAPPDATA%\Packages.
160
+ * The versioned GIMP config dir(s) to install into — the parent of both
161
+ * `plug-ins/` (server) and `mcp/` (client). The first entry is the PRIMARY
162
+ * (the real %APPDATA%/config dir); the rest are the win32 Store safety net.
145
163
  */
146
- function storeVirtualizedPluginDirs(version, d) {
164
+ function resolveConfigDirs(opts, d) {
165
+ const warnings = [];
166
+ const override = (opts?.targetDir && opts.targetDir.trim()) || (d.env.GIMP3_DIRECTORY && d.env.GIMP3_DIRECTORY.trim());
167
+ if (override) {
168
+ const version = path.basename(override) || 'custom';
169
+ if (!d.fileExists(override)) {
170
+ warnings.push(`GIMP dir ${override} does not exist yet — creating it. Launch GIMP once so it initialises its config.`);
171
+ }
172
+ return { dirs: [override], version, warnings };
173
+ }
174
+ const base = gimpConfigBase(d);
175
+ const chosen = chooseVersion(base, d);
176
+ if (!chosen.existed) {
177
+ warnings.push(`No GIMP 3.x config dir found under ${base} — creating ${chosen.version}. ` +
178
+ 'Launch GIMP 3 at least once (so it creates its real config dir), then re-run to be sure it lands in the right place.');
179
+ }
180
+ const dirs = [path.join(base, chosen.version)];
181
+ // Windows Store virtualized safety net (only when a package dir exists).
182
+ for (const vdir of storeVirtualizedConfigDirs(chosen.version, d)) {
183
+ dirs.push(vdir);
184
+ }
185
+ return { dirs, version: chosen.version, warnings };
186
+ }
187
+ /**
188
+ * Windows Store virtualized config dir(s) for a version. Only returned when a
189
+ * `GIMP.*` package dir actually exists under %LOCALAPPDATA%\Packages.
190
+ */
191
+ function storeVirtualizedConfigDirs(version, d) {
147
192
  if (d.platform !== 'win32') {
148
193
  return [];
149
194
  }
@@ -151,7 +196,15 @@ function storeVirtualizedPluginDirs(version, d) {
151
196
  const localAppData = d.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
152
197
  const packagesDir = path.join(localAppData, 'Packages');
153
198
  const pkgs = d.listDir(packagesDir).filter((n) => /^GIMP\./i.test(n));
154
- return pkgs.map((pkg) => path.join(packagesDir, pkg, 'LocalCache', 'Roaming', 'GIMP', version, 'plug-ins'));
199
+ return pkgs.map((pkg) => path.join(packagesDir, pkg, 'LocalCache', 'Roaming', 'GIMP', version));
200
+ }
201
+ /** The server plug-in .py path for a versioned config dir. */
202
+ function serverPathFor(configDir) {
203
+ return path.join(configDir, 'plug-ins', 'gimp_mcp_server', 'gimp_mcp_server.py');
204
+ }
205
+ /** The MCP client .py path for a versioned config dir (sibling `mcp/` folder). */
206
+ function clientPathFor(configDir) {
207
+ return path.join(configDir, 'mcp', 'gimp_mcp_client.py');
155
208
  }
156
209
  /** Extract the GIMP MAJOR version from a launcher path (e.g. gimp-2.10 → 2). */
157
210
  function gimpMajorFromPath(p) {
@@ -163,96 +216,94 @@ function gimpMajorFromPath(p) {
163
216
  return m ? parseInt(m[1], 10) : null;
164
217
  }
165
218
  /**
166
- * Write the plugin into one plug-ins dir. IDEMPOTENT: if the target already
167
- * holds byte-identical content, skip the write (and the .bak) — but still ensure
168
- * the executable bit on non-Windows. A .bak backup is made ONLY when overwriting
219
+ * Write `source` to `target`. IDEMPOTENT: if the target already holds
220
+ * byte-identical content, skip the write (and the .bak) — but still ensure the
221
+ * executable bit on non-Windows. A .bak backup is made ONLY when overwriting
169
222
  * content that DIFFERS from the source.
170
223
  */
171
- function installInto(pluginsDir, source, d) {
172
- const sub = path.join(pluginsDir, 'gimp_mcp_server');
173
- const py = path.join(sub, 'gimp_mcp_server.py');
174
- d.mkdirp(sub);
175
- if (d.fileExists(py)) {
176
- const existing = d.readFile(py);
224
+ function writeIdempotent(target, source, d) {
225
+ d.mkdirp(path.dirname(target));
226
+ if (d.fileExists(target)) {
227
+ const existing = d.readFile(target);
177
228
  if (existing === source) {
178
- // Already up to date — no write, no backup. Still ensure it's executable.
179
229
  if (d.platform !== 'win32') {
180
- d.chmod(py, 0o755);
230
+ d.chmod(target, 0o755);
181
231
  }
182
- return py;
232
+ return target;
183
233
  }
184
- // Different content → back it up before overwriting.
185
- d.copyFile(py, py + '.bak');
234
+ d.copyFile(target, target + '.bak');
186
235
  }
187
- d.writeFile(py, source);
236
+ d.writeFile(target, source);
188
237
  if (d.platform !== 'win32') {
189
- d.chmod(py, 0o755);
238
+ d.chmod(target, 0o755);
190
239
  }
191
- return py;
240
+ return target;
192
241
  }
193
242
  /**
194
- * Install the auto-start GIMP MCP plugin. Resolves the target plug-ins dir(s)
195
- * per-OS and writes the vendored plugin so GIMP opens the localhost:9876 socket
196
- * on launch. Does NOT install when a clearly < 3 GIMP is the only one detected.
243
+ * Gate helper: is this a GIMP we must NOT install for? (detected AND clearly < 3).
244
+ * Returns a warning string to surface, or null when install may proceed.
197
245
  */
198
- function installGimpPlugin(opts, deps) {
199
- const d = { ...realDeps(), ...deps };
200
- const warnings = [];
201
- // Gate: if a GIMP is detected and is clearly < 3, do not install.
246
+ function refuseIfOldGimp(d) {
202
247
  const det = d.detectGimp();
203
248
  const major = gimpMajorFromPath(det.path);
204
249
  if (det.installed && major !== null && major < 3) {
205
- warnings.push(`Detected GIMP ${major}.x at ${det.path}. GIMP MCP needs GIMP 3.x — ` +
206
- 'the auto-start plugin uses the GIMP 3.0 Python API and was NOT installed. ' +
250
+ return (`Detected GIMP ${major}.x at ${det.path}. GIMP MCP needs GIMP 3.x — ` +
251
+ 'the plugin uses the GIMP 3.0 Python API and was NOT installed. ' +
207
252
  'Install GIMP 3 and re-run.');
208
- return { installed: false, paths: [], version: null, warnings };
209
253
  }
210
- const source = d.readPluginSource();
211
- // Resolve the versioned config dir(s). GIMP3_DIRECTORY / opts.targetDir
212
- // override the WHOLE versioned dir.
213
- const override = (opts?.targetDir && opts.targetDir.trim()) || (d.env.GIMP3_DIRECTORY && d.env.GIMP3_DIRECTORY.trim());
214
- const targets = [];
215
- let version;
216
- if (override) {
217
- version = path.basename(override) || 'custom';
218
- if (!d.fileExists(override)) {
219
- warnings.push(`GIMP dir ${override} does not exist yet — creating it. Launch GIMP once so it initialises its config.`);
220
- }
221
- targets.push(path.join(override, 'plug-ins'));
254
+ return null;
255
+ }
256
+ /**
257
+ * Install BOTH the GIMP-side plug-in (server) and the MCP client. Resolves the
258
+ * target config dir(s) per-OS and writes the vendored files. Does NOT install
259
+ * when a clearly < 3 GIMP is the only one detected.
260
+ */
261
+ function installGimpPlugin(opts, deps) {
262
+ const d = { ...realDeps(), ...deps };
263
+ const warnings = [];
264
+ const refusal = refuseIfOldGimp(d);
265
+ if (refusal) {
266
+ warnings.push(refusal);
267
+ return { installed: false, serverPath: null, clientPath: null, paths: [], clientPaths: [], version: null, warnings };
222
268
  }
223
- else {
224
- const base = gimpConfigBase(d);
225
- const chosen = chooseVersion(base, d);
226
- version = chosen.version;
227
- if (!chosen.existed) {
228
- warnings.push(`No GIMP 3.x config dir found under ${base} — creating ${version}. ` +
229
- 'Launch GIMP 3 at least once (so it creates its real config dir), then re-run to be sure it lands in the right place.');
269
+ const serverSource = d.readPluginSource();
270
+ const clientSource = d.readClientSource();
271
+ const { dirs, version, warnings: resolveWarnings } = resolveConfigDirs(opts, d);
272
+ warnings.push(...resolveWarnings);
273
+ const paths = [];
274
+ const clientPaths = [];
275
+ for (const configDir of dirs) {
276
+ try {
277
+ paths.push(writeIdempotent(serverPathFor(configDir), serverSource, d));
230
278
  }
231
- targets.push(path.join(base, version, 'plug-ins'));
232
- // Windows Store virtualized safety net (only when a package dir exists).
233
- for (const vdir of storeVirtualizedPluginDirs(version, d)) {
234
- targets.push(vdir);
279
+ catch (e) {
280
+ warnings.push(`Failed to write plugin into ${configDir}: ${e.message}`);
235
281
  }
236
- }
237
- const paths = [];
238
- for (const pluginsDir of targets) {
239
282
  try {
240
- paths.push(installInto(pluginsDir, source, d));
283
+ clientPaths.push(writeIdempotent(clientPathFor(configDir), clientSource, d));
241
284
  }
242
285
  catch (e) {
243
- warnings.push(`Failed to write plugin into ${pluginsDir}: ${e.message}`);
286
+ warnings.push(`Failed to write client into ${configDir}: ${e.message}`);
244
287
  }
245
288
  }
246
- return { installed: paths.length > 0, paths, version, warnings };
289
+ return {
290
+ installed: paths.length > 0,
291
+ serverPath: paths[0] ?? null,
292
+ clientPath: clientPaths[0] ?? null,
293
+ paths,
294
+ clientPaths,
295
+ version,
296
+ warnings,
297
+ };
247
298
  }
248
299
  /**
249
- * Sync-path variant: install the auto-start plugin ONLY when GIMP 3.x is actually
250
- * DETECTED. Unlike installGimpPlugin (which will create a 3.0 config dir even with
251
- * no GIMP present — appropriate for the explicit `mcp detect --enable gimp` /
252
- * `gimp-install-plugin` flows), this refuses to touch the filesystem when GIMP is
253
- * absent or is clearly < 3, so a routine ConfigManager.syncProjectMcpServers on a
254
- * box without GIMP never spuriously creates a config dir. Returns a skip result
255
- * (installed:false + warning) instead of throwing so callers can swallow it.
300
+ * Sync-path variant: install ONLY when GIMP 3.x is actually DETECTED. Unlike
301
+ * installGimpPlugin (which will create a 3.0 config dir even with no GIMP present
302
+ * — appropriate for the explicit `mcp detect --enable gimp` / `gimp-install-plugin`
303
+ * flows), this refuses to touch the filesystem when GIMP is absent or is clearly
304
+ * < 3, so a routine ConfigManager.syncProjectMcpServers on a box without GIMP
305
+ * never spuriously creates a config dir. Returns a skip result (installed:false +
306
+ * warning) instead of throwing so callers can swallow it.
256
307
  */
257
308
  function installGimpPluginIfDetected(opts, deps) {
258
309
  const d = { ...realDeps(), ...deps };
@@ -263,11 +314,32 @@ function installGimpPluginIfDetected(opts, deps) {
263
314
  if (!det.installed || (major !== null && major < 3)) {
264
315
  return {
265
316
  installed: false,
317
+ serverPath: null,
318
+ clientPath: null,
266
319
  paths: [],
320
+ clientPaths: [],
267
321
  version: null,
268
- warnings: ['GIMP 3.x not detected — auto-start plugin install skipped (sync path).'],
322
+ warnings: ['GIMP 3.x not detected — plugin install skipped (sync path).'],
269
323
  };
270
324
  }
271
325
  return installGimpPlugin(opts, deps);
272
326
  }
327
+ /**
328
+ * Resolve the PRIMARY MCP client path for the current machine WITHOUT writing
329
+ * anything — gated on GIMP 3.x being detected (same gate as
330
+ * installGimpPluginIfDetected). Returns null when GIMP is absent / clearly < 3,
331
+ * so callers (the migration, catalog display) can decide not to bake a path in.
332
+ * This is the exact path installGimpPlugin() would write the client to.
333
+ */
334
+ function resolveGimpClientPath(opts, deps) {
335
+ const d = { ...realDeps(), ...deps };
336
+ const det = d.detectGimp();
337
+ const major = gimpMajorFromPath(det.path);
338
+ if (!det.installed || (major !== null && major < 3)) {
339
+ return null;
340
+ }
341
+ const { dirs } = resolveConfigDirs(opts, d);
342
+ const primary = dirs[0];
343
+ return primary ? clientPathFor(primary) : null;
344
+ }
273
345
  //# sourceMappingURL=gimpPluginInstall.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gimpPluginInstall.js","sourceRoot":"","sources":["../../src/core/gimpPluginInstall.ts"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,0CAA0C;AAC1C,EAAE;AACF,yCAAyC;AACzC,kFAAkF;AAClF,iFAAiF;AACjF,iFAAiF;AACjF,iFAAiF;AACjF,iEAAiE;AACjE,iFAAiF;AACjF,kFAAkF;AAClF,wDAAwD;AACxD,gFAAgF;AAChF,uEAAuE;AACvE,kFAAkF;AAClF,EAAE;AACF,8EAA8E;AAC9E,kFAAkF;AAClF,mDAAmD;AACnD,8EAA8E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgD9E,4DAGC;AAuED,8CAKC;AAgCD,8CAwDC;AAWD,kEAkBC;AAlPD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,2CAA8D;AAC9D,yDAAwD;AAyCxD,8EAA8E;AAC9E,SAAgB,wBAAwB;IACtC,uEAAuE;IACvE,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,QAAQ;IACf,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,EAAE,CAAC,OAAO;QACnB,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;YAAC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC,CAAC,CAAC;QAC/E,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;YAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,CAAC;QAC1E,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,SAAS,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACtD,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC;YAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;QACnF,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QACtD,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;YAAC,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,CAAC;QACpF,gFAAgF;QAChF,kFAAkF;QAClF,gBAAgB,EAAE,GAAG,EAAE,CAAC,qCAAkB;QAC1C,UAAU,EAAE,GAAG,EAAE,CAAC,IAAA,qBAAS,EAAC,MAAM,CAAC;KACpC,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,SAAS,cAAc,CAAC,CAAkB;IACxC,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACzB,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IAClE,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,8EAA8E;AAC9E,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,CAAkB;IACrD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC5C,MAAM,CAAC,CAAC,CAAC,EAAwC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACzE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAAC,CAAC;IACrE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,SAAS,0BAA0B,CAAC,OAAe,EAAE,CAAkB;IACrE,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACzB,MAAM,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACtB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,gFAAgF;AAChF,SAAgB,iBAAiB,CAAC,CAAgB;IAChD,IAAI,CAAC,CAAC,EAAE,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACxB,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,UAAkB,EAAE,MAAc,EAAE,CAAkB;IACzE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;IAChD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACxB,0EAA0E;YAC1E,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAAC,CAAC;YACnD,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,qDAAqD;QACrD,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC;IAC9B,CAAC;IACD,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACxB,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAAC,CAAC;IACnD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,SAAgB,iBAAiB,CAC/B,IAAsB,EACtB,IAA+B;IAE/B,MAAM,CAAC,GAAoB,EAAE,GAAG,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;IACtD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,kEAAkE;IAClE,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,GAAG,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CACX,iBAAiB,KAAK,SAAS,GAAG,CAAC,IAAI,8BAA8B;YACrE,4EAA4E;YAC5E,4BAA4B,CAAC,CAAC;QAChC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAClE,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAEpC,wEAAwE;IACxE,oCAAoC;IACpC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC;IACvH,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAe,CAAC;IAEpB,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;QAC9C,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,QAAQ,CAAC,IAAI,CAAC,YAAY,QAAQ,mFAAmF,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACtC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CACX,sCAAsC,IAAI,eAAe,OAAO,IAAI;gBACpE,sHAAsH,CAAC,CAAC;QAC5H,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QACnD,yEAAyE;QACzE,KAAK,MAAM,IAAI,IAAI,0BAA0B,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;IACpF,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,+BAA+B,UAAU,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,2BAA2B,CACzC,IAAsB,EACtB,IAA+B;IAE/B,MAAM,CAAC,GAAoB,EAAE,GAAG,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;IACtD,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1C,+EAA+E;IAC/E,yDAAyD;IACzD,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;QACpD,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,CAAC,wEAAwE,CAAC;SACrF,CAAC;IACJ,CAAC;IACD,OAAO,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"gimpPluginInstall.js","sourceRoot":"","sources":["../../src/core/gimpPluginInstall.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  /** sha256 (first 12 hex) of the canonical media/gimp/gimp_mcp_server.py. */
2
- export declare const GIMP_PLUGIN_SOURCE_HASH = "93b608412db2";
3
- /** Full body of the auto-start GIMP 3.x MCP plugin (media/gimp/gimp_mcp_server.py). */
4
- export declare const GIMP_PLUGIN_SOURCE = "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n#\n# gimp_mcp_server.py \u2014 AutoDev auto-start GIMP 3.x MCP bridge\n#\n# Derived from libreearth/gimp-mcp @49c46dd (GPL-3.0); modified by AutoDev to\n# auto-start as a GIMP 3.x PERSISTENT extension. The upstream plugin registered a\n# manual \"<Image>/Filters/Development/ \u2192 Start MCP Server\" ImageProcedure that the\n# user had to click; this variant registers a PERSISTENT extension so GIMP starts\n# the socket server automatically on launch \u2014 no menu click, no open image needed.\n#\n# The socket / command-marshalling logic (start_server, handle_client,\n# execute_command, GLib.idle_add onto GIMP's main thread) is kept from upstream.\n# ONLY the registration + run() model changed to PERSISTENT + defensive ordering.\n#\n# ---------------------------------------------------------------------------\n# GIMP 3.x plugin layout (REQUIRED): this file must live at\n# <gimp-config>/<ver>/plug-ins/gimp_mcp_server/gimp_mcp_server.py\n# i.e. inside a sub-folder whose name == this file's basename. A loose .py is\n# IGNORED by GIMP 3.x. On Linux/macOS it must ALSO be executable (chmod 0o755).\n# ---------------------------------------------------------------------------\n#\n# Copyright (C) 2023 libreearth (upstream, GPL-3.0)\n# Modifications Copyright (C) 2025 AutoDev\n#\n# This program is free software: you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation, either version 3 of the License, or (at your option) any later\n# version.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n# PARTICULAR PURPOSE. See the GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program. If not, see <https://www.gnu.org/licenses/>. A copy is vendored\n# next to this file as LICENSE.\n\nimport os\nimport sys\nimport json\nimport socket\nimport threading\nimport traceback\nimport datetime\n\nimport gi\ngi.require_version('Gimp', '3.0')\nfrom gi.repository import Gimp\nfrom gi.repository import GLib\n\n\n# ---------------------------------------------------------------------------\n# Logging \u2014 an auto-start extension has NO console, so every diagnostic goes to\n# a log file the user can read. We resolve it next to this plug-in first (always\n# writable if the plug-in loaded at all), falling back to the GIMP config dir.\n# Nothing here may raise: a logging failure must never stop GIMP from launching.\n# ---------------------------------------------------------------------------\ndef _log_path():\n try:\n here = os.path.dirname(os.path.abspath(__file__))\n return os.path.join(here, 'gimp-mcp-server.log')\n except Exception:\n try:\n return os.path.join(GLib.get_user_config_dir(), 'gimp-mcp-server.log')\n except Exception:\n return os.path.join(os.path.expanduser('~'), 'gimp-mcp-server.log')\n\n\n_LOG_FILE = _log_path()\n\n\ndef log(msg):\n \"\"\"Best-effort append to the log file AND stderr. Never raises.\"\"\"\n line = '[%s] %s' % (datetime.datetime.now().isoformat(timespec='seconds'), msg)\n try:\n with open(_LOG_FILE, 'a', encoding='utf-8') as fh:\n fh.write(line + '\\n')\n except Exception:\n pass\n try:\n sys.stderr.write(line + '\\n')\n except Exception:\n pass\n\n\nclass MCPPlugin(Gimp.PlugIn):\n # \u2500\u2500 Registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n def do_query_procedures(self):\n return [\"plug-in-mcp-server-autostart\"]\n\n def do_create_procedure(self, name):\n # PERSISTENT + no args + no menu = GIMP auto-starts this extension at\n # launch. Adding ANY argument, a menu label, or a menu path would turn\n # it back into a user-invoked plug-in and disable auto-start.\n procedure = Gimp.Procedure.new(\n self, name, Gimp.PDBProcType.PERSISTENT, self.run, None,\n )\n try:\n procedure.set_documentation(\n \"AutoDev MCP server (auto-start)\",\n \"Auto-starts a localhost:9876 socket bridge so external MCP \"\n \"clients can drive GIMP. Derived from libreearth/gimp-mcp \"\n \"(GPL-3.0), modified by AutoDev to run as a PERSISTENT extension.\",\n name,\n )\n procedure.set_attribution(\"AutoDev\", \"AutoDev (GPL-3.0)\", \"2025\")\n except Exception as e:\n # Attribution/doc setters are cosmetic \u2014 never let a binding\n # mismatch here prevent the procedure from registering.\n log(\"do_create_procedure: non-fatal setter error: %s\" % e)\n return procedure\n\n # \u2500\u2500 Extension entry point \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n def run(self, procedure, config, run_data):\n \"\"\"PERSISTENT extension entry point.\n\n DEFENSIVE ORDER (the brick-risk part): call persistent_ready() FIRST.\n Its ABSENCE is what hangs GIMP at startup, so it must run before\n anything that could throw. Everything after it is wrapped so a bind\n failure logs + degrades instead of taking GIMP core down with it.\n \"\"\"\n # 1) Hand control back to GIMP core IMMEDIATELY so the UI keeps loading.\n try:\n procedure.persistent_ready()\n log(\"persistent_ready() OK \u2014 extension is live\")\n except Exception as e:\n # A binding mismatch on this exact call is the known lock-up cause;\n # log it (do NOT re-raise) so GIMP still finishes launching.\n log(\"persistent_ready() FAILED (non-fatal): %s\\n%s\"\n % (e, traceback.format_exc()))\n\n # 2) Start the socket server on a daemon thread. A bind failure (port in\n # use, sandbox denial) MUST NOT crash the process or block launch.\n try:\n t = threading.Thread(target=self.start_server, daemon=True)\n t.start()\n log(\"MCP server thread started (listening on localhost:9876)\")\n except Exception as e:\n log(\"failed to start MCP server thread (non-fatal): %s\\n%s\"\n % (e, traceback.format_exc()))\n\n # 3) Keep this extension process alive for the whole GIMP session so the\n # socket stays open and idle_add callbacks can marshal onto core.\n try:\n GLib.MainLoop().run()\n except Exception as e:\n log(\"main loop exited (non-fatal): %s\" % e)\n\n # 4) Standard PERSISTENT success return.\n return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())\n\n # \u2500\u2500 Socket server (kept from upstream) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n def start_server(self):\n host = 'localhost'\n port = 9876\n sock = None\n try:\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n sock.bind((host, port))\n sock.listen(1)\n log(\"server listening on %s:%d\" % (host, port))\n except Exception as e:\n # Bind/listen failed (e.g. port already taken by Blender's MCP or a\n # second GIMP). Log + bail out of the thread; GIMP keeps running.\n log(\"bind/listen failed (non-fatal): %s\\n%s\" % (e, traceback.format_exc()))\n try:\n if sock is not None:\n sock.close()\n except Exception:\n pass\n return\n\n while True:\n try:\n client, addr = sock.accept()\n log(\"client connected: %s\" % (addr,))\n threading.Thread(\n target=self.handle_client, args=(client,), daemon=True,\n ).start()\n except Exception as e:\n log(\"accept error: %s\" % e)\n break\n try:\n sock.close()\n except Exception:\n pass\n\n def handle_client(self, client):\n buffer = b''\n while True:\n try:\n data = client.recv(1024)\n if not data:\n break\n buffer += data\n try:\n command = json.loads(buffer.decode('utf-8'))\n buffer = b''\n # Marshal onto GIMP's main thread \u2014 the PDB is not thread-safe.\n GLib.idle_add(self.execute_command, command, client)\n except json.JSONDecodeError:\n # Partial frame \u2014 keep buffering until it parses.\n continue\n except Exception as e:\n log(\"client error: %s\" % e)\n break\n try:\n client.close()\n except Exception:\n pass\n\n def execute_command(self, command, client):\n \"\"\"Runs on GIMP's main thread via idle_add. Guarded so a bad command or\n a wrong binding logs + returns an error frame rather than hanging.\"\"\"\n response = {}\n try:\n cmd_type = command.get(\"type\")\n params = command.get(\"params\", {})\n\n if cmd_type == \"call_api\":\n api_path = params[\"api_path\"]\n args = params.get(\"args\", [])\n kwargs = params.get(\"kwargs\", {})\n\n module = Gimp\n for part in api_path.split(\".\"):\n module = getattr(module, part)\n\n result = module(*args, **kwargs)\n\n if hasattr(result, \"ID\"):\n result = {\"id\": result.ID}\n elif isinstance(result, list):\n result = [self.serialize_gimp_object(item) for item in result]\n else:\n result = str(result)\n\n response = {\"status\": \"success\", \"result\": result}\n else:\n response = {\"status\": \"error\", \"message\": \"Unknown command: %s\" % cmd_type}\n except Exception as e:\n response = {\"status\": \"error\", \"message\": str(e),\n \"traceback\": traceback.format_exc()}\n\n try:\n client.sendall(json.dumps(response).encode('utf-8'))\n except Exception as e:\n log(\"failed to send response: %s\" % e)\n return False # one-shot idle callback\n\n def serialize_gimp_object(self, obj):\n try:\n if hasattr(obj, \"ID\"):\n return {\"id\": obj.ID, \"type\": obj.__class__.__name__}\n except Exception:\n pass\n return str(obj)\n\n\ntry:\n Gimp.main(MCPPlugin.__gtype__, sys.argv)\nexcept Exception as _e:\n # If GIMP's main dispatch itself fails, log it \u2014 never let the plug-in\n # process take the launch down with an unhandled traceback.\n log(\"Gimp.main failed: %s\\n%s\" % (_e, traceback.format_exc()))\n";
2
+ export declare const GIMP_PLUGIN_SOURCE_HASH = "e9f5d21b82f7";
3
+ /** Full body of the user-verified GIMP 3.x MCP server plug-in (media/gimp/gimp_mcp_server.py). */
4
+ export declare const GIMP_PLUGIN_SOURCE = "#!/usr/bin/env python3\n# ---------------------------------------------------------------------------\n# gimp_mcp_server.py \u2014 vendored, USER-VERIFIED GIMP 3.2 MCP bridge (plug-in).\n#\n# Derived from libreearth/gimp-mcp (GPL-3.0; see media/gimp/LICENSE) and fixed by\n# the user / AutoDev for GIMP 3.2 (Store / MSIX). Verified working on real GIMP\n# 3.2.44: a menu-triggered PLUGIN (Tools -> MCP / Filters -> Development -> Start\n# MCP Server) that listens on 127.0.0.1:9876 and drives GIMP. Keep the \"GIMP MCP\n# Server\" window open \u2014 GLib.MainLoop() holds the out-of-process plug-in alive.\n#\n# This is the user's verified file; the body below is kept byte-for-byte. The\n# lines in THIS block are a provenance comment only \u2014 do not edit the code below.\n# ---------------------------------------------------------------------------\n\n# GIMP MCP Server Plugin (GIMP 3.2)\n# Listens on localhost:9876 so the libreearth gimp-mcp client can drive GIMP.\n\nimport gi\ngi.require_version('Gimp', '3.0')\nfrom gi.repository import Gimp\nfrom gi.repository import GLib\nfrom gi.repository import Gio\nfrom gi.repository import GObject\n\nimport io\nimport json\nimport os\nimport socket\nimport sys\nimport threading\nimport traceback\n\nHOST = '127.0.0.1'\nPORT = 9876\n# Store GIMP redirects GLib config dir into the MSIX LocalCache. Also write\n# to the real roaming profile so the log is findable.\n_LOG_PATHS = [\n os.path.join(GLib.get_user_config_dir(), 'GIMP', '3.2', 'gimp_mcp_server.log'),\n os.path.join(os.environ.get('APPDATA', ''), 'GIMP', '3.2', 'gimp_mcp_server.log'),\n]\n\n_server_lock = threading.Lock()\n_server_started = False\n_exec_globals = None\n_main_loop = None\n\n\ndef _log(msg):\n line = msg.rstrip() + '\\n'\n for path in _LOG_PATHS:\n if not path:\n continue\n try:\n os.makedirs(os.path.dirname(path), exist_ok=True)\n with open(path, 'a', encoding='utf-8') as fh:\n fh.write(line)\n except Exception:\n pass\n print(msg, flush=True)\n\n\ndef N_(message):\n return message\n\n\ndef _(message):\n return GLib.dgettext(None, message)\n\n\ndef _serialize(obj):\n if obj is None or isinstance(obj, (str, int, float, bool)):\n return obj\n if isinstance(obj, (list, tuple)):\n return [_serialize(item) for item in obj]\n if isinstance(obj, dict):\n return {str(k): _serialize(v) for k, v in obj.items()}\n data = {'type': obj.__class__.__name__}\n if hasattr(obj, 'get_id'):\n try:\n data['id'] = int(obj.get_id())\n except Exception:\n pass\n elif hasattr(obj, 'ID'):\n data['id'] = obj.ID\n if hasattr(obj, 'get_name'):\n try:\n data['name'] = obj.get_name()\n except Exception:\n pass\n if 'id' not in data and len(data) == 1:\n return str(obj)\n return data\n\n\ndef _resolve_api(api_path):\n parts = [p for p in str(api_path).split('.') if p]\n if parts and parts[0] == 'Gimp':\n parts = parts[1:]\n elif len(parts) >= 3 and parts[0] == 'gi' and parts[1] == 'repository' and parts[2] == 'Gimp':\n parts = parts[3:]\n\n aliases = {\n 'list_images': 'get_images',\n 'list_fonts': 'get_fonts',\n 'fonts_get_list': 'get_fonts',\n }\n\n if not parts:\n return Gimp\n\n obj = Gimp\n for part in parts:\n part = aliases.get(part, part)\n obj = getattr(obj, part)\n return obj\n\n\ndef _exec_namespace():\n global _exec_globals\n if _exec_globals is None:\n ns = {\n '__builtins__': __builtins__,\n '__name__': '__main__',\n 'Gimp': Gimp,\n 'GLib': GLib,\n 'Gio': Gio,\n 'GObject': GObject,\n 'sys': sys,\n 'os': os,\n 'json': json,\n }\n try:\n gi.require_version('Gegl', '0.4')\n from gi.repository import Gegl\n ns['Gegl'] = Gegl\n except Exception as exc:\n _log(f'Gegl import failed: {exc}')\n try:\n gi.require_version('Babl', '0.1')\n from gi.repository import Babl\n ns['Babl'] = Babl\n except Exception:\n pass\n _exec_globals = ns\n return _exec_globals\n\n\ndef _extract_code(args, kwargs):\n if kwargs.get('code'):\n return str(kwargs['code'])\n if not args:\n return ''\n if len(args) >= 2 and args[0] in ('exec', 'eval', 'pyGObject-console'):\n payload = args[1]\n if isinstance(payload, (list, tuple)):\n return '\\n'.join(str(item) for item in payload)\n return str(payload)\n if isinstance(args[0], (list, tuple)):\n return '\\n'.join(str(item) for item in args[0])\n return str(args[0])\n\n\ndef _run_python(code):\n ns = _exec_namespace()\n stdout = io.StringIO()\n old_stdout = sys.stdout\n sys.stdout = stdout\n try:\n exec(code, ns)\n finally:\n sys.stdout = old_stdout\n printed = stdout.getvalue()\n result = ns.get('_result')\n if result is not None:\n return {'printed': printed, 'result': _serialize(result)}\n return {'printed': printed, 'result': None}\n\n\nclass MCPPlugin(Gimp.PlugIn):\n def do_set_i18n(self, name):\n return False\n\n def do_query_procedures(self):\n return ['plug-in-mcp-server']\n\n def do_create_procedure(self, name):\n procedure = Gimp.Procedure.new(\n self, name, Gimp.PDBProcType.PLUGIN, self.run, None\n )\n procedure.set_menu_label(_('Start MCP Server'))\n procedure.set_documentation(\n _('Starts an MCP server to control GIMP externally'),\n _('Listens on 127.0.0.1:9876 for the GIMP MCP client'),\n name,\n )\n procedure.set_attribution('GIMP MCP', 'GIMP MCP', '2026')\n procedure.set_sensitivity_mask(Gimp.ProcedureSensitivityMask.ALWAYS)\n procedure.add_enum_argument(\n 'run-mode',\n _('Run mode'),\n _('The run mode'),\n Gimp.RunMode,\n Gimp.RunMode.INTERACTIVE,\n GObject.ParamFlags.READWRITE,\n )\n procedure.add_menu_path('<Image>/Tools/MCP')\n procedure.add_menu_path('<Image>/Filters/Development/')\n return procedure\n\n def run(self, procedure, config, data):\n global _main_loop\n started, message = self.ensure_server()\n _log(message)\n if not started:\n return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, GLib.Error(message))\n\n # GIMP 3 launches Python plug-ins out of process. Returning from run()\n # would exit that process and kill the socket thread. Stay alive and\n # dispatch GLib.idle_add work (API calls) on this main loop.\n # A visible window is required: otherwise \"Start MCP Server\" looks like\n # it did not open anything.\n try:\n self._show_status_window(message)\n except Exception as exc:\n _log(f'Status window failed: {exc}\\n{traceback.format_exc()}')\n\n _main_loop = GLib.MainLoop()\n _log('Entering GLib.MainLoop to keep MCP server process alive')\n try:\n _main_loop.run()\n except Exception as exc:\n _log(f'MainLoop exited: {exc}')\n return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())\n\n def _show_status_window(self, message):\n gi.require_version('Gtk', '3.0')\n gi.require_version('GimpUi', '3.0')\n from gi.repository import Gtk\n from gi.repository import GimpUi\n\n GimpUi.init('gimp_mcp_server.py')\n window = Gtk.Window(title='GIMP MCP Server')\n window.set_default_size(360, 120)\n window.set_keep_above(False)\n window.set_skip_taskbar_hint(False)\n box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)\n box.set_border_width(16)\n label = Gtk.Label(label=message + '\\nLeave this window open.')\n label.set_line_wrap(True)\n box.pack_start(label, True, True, 0)\n button = Gtk.Button(label='Stop server')\n button.connect('clicked', lambda *_: window.destroy())\n box.pack_start(button, False, False, 0)\n window.add(box)\n window.connect('destroy', self._on_status_closed)\n window.show_all()\n _log('Status window opened')\n\n def _on_status_closed(self, *_args):\n global _main_loop\n _log('Status window closed; stopping MCP server')\n if _main_loop is not None:\n _main_loop.quit()\n\n def ensure_server(self):\n global _server_started\n with _server_lock:\n if _server_started:\n return True, f'MCP Server already listening on {HOST}:{PORT}'\n try:\n thread = threading.Thread(target=self.start_server, daemon=True)\n thread.start()\n _server_started = True\n return True, f'MCP Server started on {HOST}:{PORT}'\n except Exception as exc:\n return False, f'Failed to start MCP Server: {exc}'\n\n def start_server(self):\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n try:\n sock.bind((HOST, PORT))\n sock.listen(8)\n _log(f'Server listening on {HOST}:{PORT}')\n except Exception as exc:\n _log(f'Bind/listen failed: {exc}')\n return\n\n while True:\n try:\n client, addr = sock.accept()\n _log(f'Connected to {addr}')\n threading.Thread(target=self.handle_client, args=(client,), daemon=True).start()\n except Exception as exc:\n _log(f'Server accept error: {exc}')\n break\n sock.close()\n\n def handle_client(self, client):\n buffer = b''\n try:\n client.settimeout(120)\n while True:\n chunk = client.recv(65536)\n if not chunk:\n break\n buffer += chunk\n while buffer:\n try:\n command = json.loads(buffer.decode('utf-8'))\n buffer = b''\n except json.JSONDecodeError:\n break\n GLib.idle_add(self.execute_command, command, client)\n except Exception as exc:\n _log(f'Client error: {exc}')\n finally:\n try:\n client.close()\n except Exception:\n pass\n\n def execute_command(self, command, client):\n cmd_type = command.get('type')\n params = command.get('params', {}) or {}\n try:\n if cmd_type == 'ping':\n response = {'status': 'success', 'result': 'pong'}\n elif cmd_type == 'exec':\n code = _extract_code(params.get('args', []), params.get('kwargs', {}))\n if not code:\n code = str(params.get('code', ''))\n response = {'status': 'success', 'result': _run_python(code)}\n elif cmd_type == 'call_api':\n api_path = params.get('api_path', '')\n args = params.get('args', []) or []\n kwargs = params.get('kwargs', {}) or {}\n if api_path in ('exec', 'eval', '__exec__'):\n response = {'status': 'success', 'result': _run_python(_extract_code(args, kwargs))}\n else:\n method = _resolve_api(api_path)\n result = method(*args, **kwargs)\n response = {'status': 'success', 'result': _serialize(result)}\n else:\n response = {'status': 'error', 'message': f'Unknown command: {cmd_type}'}\n except Exception as exc:\n response = {\n 'status': 'error',\n 'message': str(exc),\n 'traceback': traceback.format_exc(),\n }\n _log(f'Command error: {response[\"message\"]}\\n{response[\"traceback\"]}')\n\n try:\n payload = json.dumps(response).encode('utf-8')\n client.sendall(payload)\n except Exception as exc:\n _log(f'Response send failed: {exc}')\n return False\n\n\nGimp.main(MCPPlugin.__gtype__, sys.argv)\n";