editmamei 0.18.0 → 0.19.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/dist/bin/editmamei-core-darwin-arm64 +0 -0
- package/dist/bin/editmamei-core-darwin-x64 +0 -0
- package/dist/bin/editmamei-core-win-x64.exe +0 -0
- package/dist/cli/config.js +7 -0
- package/dist/core/server.js +32 -5
- package/dist/core/settings.js +8 -0
- package/dist/install-channel.js +8 -0
- package/dist/skills/editmamei-skill.zip +0 -0
- package/dist/update/check.js +77 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/cli/config.js
CHANGED
|
@@ -43,6 +43,13 @@ const KEYS = {
|
|
|
43
43
|
},
|
|
44
44
|
coerce: coercePath,
|
|
45
45
|
},
|
|
46
|
+
update_check: {
|
|
47
|
+
get: (s) => s.update_check,
|
|
48
|
+
set: (s, v) => {
|
|
49
|
+
s.update_check = v;
|
|
50
|
+
},
|
|
51
|
+
coerce: coerceBool,
|
|
52
|
+
},
|
|
46
53
|
};
|
|
47
54
|
function knownKeysHint() {
|
|
48
55
|
return `Known keys:\n${Object.keys(KEYS)
|
package/dist/core/server.js
CHANGED
|
@@ -9,8 +9,9 @@ import { EDITION } from '../edition.js';
|
|
|
9
9
|
import { VERSION } from '../version.js';
|
|
10
10
|
import { Session } from './session.js';
|
|
11
11
|
import { SessionLog, classifyError } from '../utils/session-log.js';
|
|
12
|
-
import { loadSettings, applyTelemetryEnvOverrides } from './settings.js';
|
|
12
|
+
import { loadSettings, applyTelemetryEnvOverrides, applyUpdateCheckEnvOverride, } from './settings.js';
|
|
13
13
|
import { TelemetryClient } from '../telemetry/client.js';
|
|
14
|
+
import { checkForUpdate, shouldCheckForUpdate } from '../update/check.js';
|
|
14
15
|
import { join, dirname } from 'node:path';
|
|
15
16
|
import { pathToFileURL } from 'node:url';
|
|
16
17
|
import { GoSnippetClient, resolveProBinaryPath, coreBinaryName } from '../api/snippet-client.js';
|
|
@@ -49,6 +50,7 @@ export class EditmameiServer {
|
|
|
49
50
|
kernel;
|
|
50
51
|
proModule = null;
|
|
51
52
|
psVersion = null;
|
|
53
|
+
updateInfo = null;
|
|
52
54
|
snippetClient = new GoSnippetClient();
|
|
53
55
|
constructor() {
|
|
54
56
|
this.logger = new Logger('EditmameiServer');
|
|
@@ -56,13 +58,18 @@ export class EditmameiServer {
|
|
|
56
58
|
this.sessionLog = new SessionLog(this.session.getSessionId());
|
|
57
59
|
this.logger.info(`Session ${this.session.getSessionId()} → ${this.sessionLog.path}`);
|
|
58
60
|
const { settings, created } = loadSettings();
|
|
59
|
-
const effectiveSettings = applyTelemetryEnvOverrides(settings);
|
|
61
|
+
const effectiveSettings = applyUpdateCheckEnvOverride(applyTelemetryEnvOverrides(settings));
|
|
60
62
|
this.telemetry = new TelemetryClient({
|
|
61
63
|
settings: effectiveSettings,
|
|
62
64
|
getPsVersion: () => this.psVersion,
|
|
63
65
|
});
|
|
64
66
|
if (created)
|
|
65
67
|
this.logger.info(FIRST_RUN_DISCLOSURE);
|
|
68
|
+
if (shouldCheckForUpdate(effectiveSettings.update_check)) {
|
|
69
|
+
void checkForUpdate().then((info) => {
|
|
70
|
+
this.updateInfo = info;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
66
73
|
warnLogScriptOnErrorOnce(this.logger);
|
|
67
74
|
this.toolRegistry = new ToolRegistry({
|
|
68
75
|
onCall: (entry) => {
|
|
@@ -124,6 +131,16 @@ export class EditmameiServer {
|
|
|
124
131
|
items: { type: 'string' },
|
|
125
132
|
description: 'List of optional discovery signals that could not be gathered (e.g. "pingState" if the in-PS state snippet failed, "templates" if ~/.editmamei/templates was unreadable). Empty when all signals were collected cleanly. Returned defaults for any degraded field cannot be trusted as ground truth.',
|
|
126
133
|
},
|
|
134
|
+
update_available: {
|
|
135
|
+
type: ['object', 'null'],
|
|
136
|
+
description: 'Set when a newer Editmamei version is published, else null. When present, TELL THE USER: relay current → latest and how_to_update verbatim. { current, latest, channel (npm/mcpb/dev), how_to_update }. Anonymous npm-registry check at boot; opt out with `editmamei config set update_check false`.',
|
|
137
|
+
properties: {
|
|
138
|
+
current: { type: 'string' },
|
|
139
|
+
latest: { type: 'string' },
|
|
140
|
+
channel: { type: 'string' },
|
|
141
|
+
how_to_update: { type: 'string' },
|
|
142
|
+
},
|
|
143
|
+
},
|
|
127
144
|
},
|
|
128
145
|
},
|
|
129
146
|
annotations: {
|
|
@@ -286,8 +303,10 @@ export class EditmameiServer {
|
|
|
286
303
|
const isConnected = await connection.ping();
|
|
287
304
|
if (!isConnected) {
|
|
288
305
|
return {
|
|
289
|
-
content: [
|
|
290
|
-
|
|
306
|
+
content: [
|
|
307
|
+
{ type: 'text', text: 'Failed to connect to Photoshop' + this.updateNote() },
|
|
308
|
+
],
|
|
309
|
+
structuredContent: { connected: false, update_available: this.updateInfo },
|
|
291
310
|
};
|
|
292
311
|
}
|
|
293
312
|
let version = 'Unknown';
|
|
@@ -336,7 +355,8 @@ export class EditmameiServer {
|
|
|
336
355
|
text: `Connected to Photoshop (v${version}). ` +
|
|
337
356
|
`${actionSetsCount} custom action set(s), ${userTemplates} saved template(s), ` +
|
|
338
357
|
`${openDocuments.length} open document(s)${openDocuments.length ? ': ' + openDocuments.join(', ') : ''}` +
|
|
339
|
-
`${degradedNote}
|
|
358
|
+
`${degradedNote}.` +
|
|
359
|
+
this.updateNote(),
|
|
340
360
|
},
|
|
341
361
|
],
|
|
342
362
|
structuredContent: {
|
|
@@ -346,9 +366,16 @@ export class EditmameiServer {
|
|
|
346
366
|
user_templates: userTemplates,
|
|
347
367
|
open_documents: openDocuments,
|
|
348
368
|
degraded,
|
|
369
|
+
update_available: this.updateInfo,
|
|
349
370
|
},
|
|
350
371
|
};
|
|
351
372
|
}
|
|
373
|
+
updateNote() {
|
|
374
|
+
const u = this.updateInfo;
|
|
375
|
+
if (!u)
|
|
376
|
+
return '';
|
|
377
|
+
return ` Update available: v${u.current} → v${u.latest}. ${u.how_to_update}`;
|
|
378
|
+
}
|
|
352
379
|
async start() {
|
|
353
380
|
await this.session.initialize();
|
|
354
381
|
await this.loadModules();
|
package/dist/core/settings.js
CHANGED
|
@@ -20,6 +20,7 @@ function defaults(installId) {
|
|
|
20
20
|
telemetry: { usage: true, diagnostics: false, install_id: installId },
|
|
21
21
|
privacy: { send_previews_to_llm: true },
|
|
22
22
|
photoshop_path: null,
|
|
23
|
+
update_check: true,
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
function coerce(raw, installId) {
|
|
@@ -43,6 +44,7 @@ function coerce(raw, installId) {
|
|
|
43
44
|
: base.privacy.send_previews_to_llm,
|
|
44
45
|
},
|
|
45
46
|
photoshop_path: typeof r.photoshop_path === 'string' ? r.photoshop_path : null,
|
|
47
|
+
update_check: typeof r.update_check === 'boolean' ? r.update_check : base.update_check,
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
50
|
export function loadSettings(opts = {}) {
|
|
@@ -102,6 +104,12 @@ export function applyTelemetryEnvOverrides(settings, env = process.env) {
|
|
|
102
104
|
},
|
|
103
105
|
};
|
|
104
106
|
}
|
|
107
|
+
export function applyUpdateCheckEnvOverride(settings, env = process.env) {
|
|
108
|
+
const v = parseBoolEnv(env.EDITMAMEI_UPDATE_CHECK);
|
|
109
|
+
if (v === undefined)
|
|
110
|
+
return settings;
|
|
111
|
+
return { ...settings, update_check: v };
|
|
112
|
+
}
|
|
105
113
|
export function saveSettings(settings, opts = {}) {
|
|
106
114
|
const path = settingsPath(opts);
|
|
107
115
|
const dir = dirname(path);
|
|
Binary file
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { VERSION } from '../version.js';
|
|
2
|
+
import { resolveInstallChannel } from '../install-channel.js';
|
|
3
|
+
const DEFAULT_DIST_TAGS_URL = 'https://registry.npmjs.org/-/package/editmamei/dist-tags';
|
|
4
|
+
const RELEASES_URL = 'https://github.com/editmamei/editmamei-wiki/releases/latest';
|
|
5
|
+
export function resolveUpdateCheckUrl(env = process.env) {
|
|
6
|
+
const override = env.EDITMAMEI_UPDATE_CHECK_URL;
|
|
7
|
+
return override && override.length > 0 ? override : DEFAULT_DIST_TAGS_URL;
|
|
8
|
+
}
|
|
9
|
+
export function httpFetchLatest() {
|
|
10
|
+
return async (url, timeoutMs) => {
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetch(url, {
|
|
15
|
+
headers: { accept: 'application/json' },
|
|
16
|
+
signal: controller.signal,
|
|
17
|
+
});
|
|
18
|
+
if (!res.ok)
|
|
19
|
+
return null;
|
|
20
|
+
const data = (await res.json());
|
|
21
|
+
return typeof data.latest === 'string' ? data.latest : null;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function parseSemver(v) {
|
|
32
|
+
const m = /^(\d+)\.(\d+)\.(\d+)$/.exec(v.trim());
|
|
33
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
34
|
+
}
|
|
35
|
+
export function isNewer(latest, current) {
|
|
36
|
+
const a = parseSemver(latest);
|
|
37
|
+
const b = parseSemver(current);
|
|
38
|
+
if (!a || !b)
|
|
39
|
+
return false;
|
|
40
|
+
for (let i = 0; i < 3; i++) {
|
|
41
|
+
if (a[i] !== b[i])
|
|
42
|
+
return a[i] > b[i];
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
export function updateMessage(channel, latest) {
|
|
47
|
+
switch (channel) {
|
|
48
|
+
case 'mcpb':
|
|
49
|
+
return `Download editmamei.mcpb (v${latest}) from ${RELEASES_URL} and reinstall the Claude Desktop extension.`;
|
|
50
|
+
case 'dev':
|
|
51
|
+
return `You're on a local dev build — pull the latest source and rebuild.`;
|
|
52
|
+
case 'npm':
|
|
53
|
+
default:
|
|
54
|
+
return `Run: npm install -g editmamei@latest (then restart your MCP client).`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function shouldCheckForUpdate(updateCheckEnabled, env = process.env) {
|
|
58
|
+
const inTest = env.VITEST !== undefined || env.NODE_ENV === 'test';
|
|
59
|
+
return updateCheckEnabled === true && !inTest;
|
|
60
|
+
}
|
|
61
|
+
export async function checkForUpdate(opts = {}) {
|
|
62
|
+
try {
|
|
63
|
+
const env = opts.env ?? process.env;
|
|
64
|
+
const current = opts.current ?? VERSION;
|
|
65
|
+
const channel = resolveInstallChannel(env);
|
|
66
|
+
const fetchLatest = opts.fetchLatest ?? httpFetchLatest();
|
|
67
|
+
const latest = await fetchLatest(resolveUpdateCheckUrl(env), opts.timeoutMs ?? 4000);
|
|
68
|
+
if (!latest || !parseSemver(latest))
|
|
69
|
+
return null;
|
|
70
|
+
if (!isNewer(latest, current))
|
|
71
|
+
return null;
|
|
72
|
+
return { current, latest, channel, how_to_update: updateMessage(channel, latest) };
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.19.0';
|