@naparnik/mcp 0.10.47 → 0.10.48

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Изменения @naparnik/mcp
2
2
 
3
+ ## 0.10.48 — 2026-09-24. Расширение снова обновляется само в Claude
4
+
5
+ В Claude новая версия расширения скачивалась, но не вставала. Теперь
6
+ «обнови» ставит её как надо.
7
+
8
+ Если расширение так и не обновилось — один раз возьмите свежий файл у бота
9
+ и поставьте его поверх. Дальше обновления снова приходят сами.
10
+
3
11
  ## 0.10.47 — 2026-09-24. Поломка приходит к нам сама, и вы знаете, куда писать
4
12
 
5
13
  Если у нас что-то сломалось — в том числе при установке или обновлении, —
@@ -7,6 +7,7 @@ import { promisify } from 'util';
7
7
  import { AsyncLocalStorage } from 'async_hooks';
8
8
  import { gunzipSync } from 'zlib';
9
9
  import { pathToFileURL, fileURLToPath } from 'url';
10
+ import { Worker } from 'worker_threads';
10
11
  import { readFile } from 'fs/promises';
11
12
 
12
13
  var __defProp = Object.defineProperty;
@@ -729,7 +730,7 @@ function parsePositiveInt(raw, fallback) {
729
730
  }
730
731
 
731
732
  // src/version.ts
732
- var VERSION = "0.10.47";
733
+ var VERSION = "0.10.48";
733
734
  var USER_AGENT = `naparnik-mcp/${VERSION}`;
734
735
  var MIN_ENGINE = "2026.09.24-466";
735
736
  var LAUNCHER_PROTOCOL = 1;
@@ -14308,13 +14309,13 @@ async function prepareCopiedCandidateVenv(engine, dir, version2, place) {
14308
14309
  }
14309
14310
  var SYMLINKS_ONLY = "cannot create venvs without using symlinks";
14310
14311
  async function copiedVenv(engine, venv) {
14311
- const { execFile: execFile4 } = await import('child_process');
14312
- const { promisify: promisify3 } = await import('util');
14312
+ const { execFile: execFile3 } = await import('child_process');
14313
+ const { promisify: promisify2 } = await import('util');
14313
14314
  const pythons = engine.bootstrapPythons?.() ?? [engine.bootstrapPython()];
14314
14315
  const refusals = [];
14315
14316
  for (const python of pythons) {
14316
14317
  try {
14317
- await promisify3(execFile4)(python, ["-m", "venv", "--copies", venv], {
14318
+ await promisify2(execFile3)(python, ["-m", "venv", "--copies", venv], {
14318
14319
  timeout: 10 * 6e4,
14319
14320
  encoding: "utf8",
14320
14321
  env: { ...engine.pythonEnv(), PYTHONDONTWRITEBYTECODE: "1" }
@@ -14332,15 +14333,15 @@ async function copiedVenv(engine, venv) {
14332
14333
  }
14333
14334
  async function candidatePipReady(engine, python) {
14334
14335
  if (engine.candidatePipReady !== void 0) return engine.candidatePipReady(python);
14335
- const { execFile: execFile4 } = await import('child_process');
14336
- const { promisify: promisify3 } = await import('util');
14336
+ const { execFile: execFile3 } = await import('child_process');
14337
+ const { promisify: promisify2 } = await import('util');
14337
14338
  const env = { ...engine.pythonEnv(), PYTHONDONTWRITEBYTECODE: "1" };
14338
14339
  delete env["PYTHONHOME"];
14339
14340
  delete env["PYTHONPATH"];
14340
14341
  delete env["VIRTUAL_ENV"];
14341
14342
  delete env["__PYVENV_LAUNCHER__"];
14342
14343
  try {
14343
- await promisify3(execFile4)(python, ["-B", "-m", "pip", "--version"], {
14344
+ await promisify2(execFile3)(python, ["-B", "-m", "pip", "--version"], {
14344
14345
  timeout: 6e4,
14345
14346
  encoding: "utf8",
14346
14347
  env
@@ -14654,9 +14655,9 @@ async function dryRun(engine, build, expected, trial) {
14654
14655
  }
14655
14656
  }
14656
14657
  async function probe(engine, consolePy) {
14657
- const { execFile: execFile4 } = await import('child_process');
14658
- const { promisify: promisify3 } = await import('util');
14659
- return promisify3(execFile4)(engine.enginePython(), [consolePy, "version"], {
14658
+ const { execFile: execFile3 } = await import('child_process');
14659
+ const { promisify: promisify2 } = await import('util');
14660
+ return promisify2(execFile3)(engine.enginePython(), [consolePy, "version"], {
14660
14661
  timeout: 6e4,
14661
14662
  encoding: "utf8",
14662
14663
  env: engine.pythonEnv()
@@ -15085,50 +15086,100 @@ function removePublication(dir, version2) {
15085
15086
  function publicationMatchesManifest(publication, manifest) {
15086
15087
  return publication.version === manifest.version && publication.artifactSha256 === manifest.body?.sha256 && publication.artifactBytes === manifest.body.bytes;
15087
15088
  }
15089
+ var PROBE_TIMEOUT_MS = 6e4;
15090
+ var REQUIRED_TOOLS = ["setup", "render", "wait"];
15091
+ var PROBE_THREAD = `
15092
+ const { parentPort, workerData } = require('node:worker_threads')
15093
+ import(workerData.entry).then((body) => {
15094
+ if (typeof body.start !== 'function') throw new Error('\u0432\u0445\u043E\u0434 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435 \u043E\u0442\u0434\u0430\u0451\u0442 start()')
15095
+ return body.start()
15096
+ }).catch((trouble) => {
15097
+ parentPort.postMessage(trouble instanceof Error
15098
+ ? { message: trouble.name + ': ' + String(trouble.message).split('\\n')[0], stack: String(trouble.stack || '') }
15099
+ : { message: String(trouble), stack: '' })
15100
+ })
15101
+ `;
15088
15102
  var probeShell = async (entry) => {
15089
15103
  const probeHome = mkdtempSync(join(tmpdir(), "naparnik-shell-probe-"));
15090
- const env = {
15091
- ...process.env,
15092
- NAPARNIK_HOME: probeHome,
15093
- NAPARNIK_NO_BODY: "1",
15094
- NAPARNIK_NO_UPDATE: "1"
15095
- };
15104
+ const env = {};
15105
+ for (const [name, value] of Object.entries(process.env)) {
15106
+ if (value !== void 0 && name !== "NAPARNIK_API_KEY") env[name] = value;
15107
+ }
15108
+ Object.assign(env, { NAPARNIK_HOME: probeHome, NAPARNIK_NO_BODY: "1", NAPARNIK_NO_UPDATE: "1" });
15109
+ const thread = new Worker(PROBE_THREAD, {
15110
+ eval: true,
15111
+ argv: [],
15112
+ env,
15113
+ stdin: true,
15114
+ stdout: true,
15115
+ stderr: true,
15116
+ workerData: { entry: pathToFileURL(entry).href }
15117
+ });
15096
15118
  try {
15097
- const version2 = await promisify(execFile)(process.execPath, [entry, "--version"], {
15098
- timeout: 6e4,
15099
- encoding: "utf8",
15100
- env
15101
- });
15102
- await new Promise((resolve5, reject) => {
15103
- const child = spawn(process.execPath, [entry], { stdio: ["pipe", "pipe", "pipe"], env });
15119
+ const named = await new Promise((resolve5, reject) => {
15104
15120
  let output = "";
15105
15121
  let errors = "";
15106
15122
  let finished = false;
15107
- const timer = setTimeout(() => finish(new Error("\u0442\u0435\u043B\u043E \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B\u043E \u043D\u0430 initialize/tools-list")), 15e3);
15108
- const finish = (trouble) => {
15123
+ const timer = setTimeout(
15124
+ () => finish(failure(`\u0442\u0435\u043B\u043E \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B\u043E \u043D\u0430 initialize/tools-list \u0437\u0430 ${PROBE_TIMEOUT_MS / 1e3} \u0441`)),
15125
+ PROBE_TIMEOUT_MS
15126
+ );
15127
+ const finish = (trouble, said) => {
15109
15128
  if (finished) return;
15110
15129
  finished = true;
15111
15130
  clearTimeout(timer);
15112
- child.kill();
15113
- if (trouble === void 0) resolve5();
15131
+ if (trouble === null) resolve5(said ?? "");
15114
15132
  else reject(trouble);
15115
15133
  };
15116
15134
  const send = (message) => {
15117
- child.stdin.write(`${JSON.stringify(message)}
15135
+ thread.stdin?.write(`${JSON.stringify(message)}
15118
15136
  `);
15119
15137
  };
15120
- child.stderr.setEncoding("utf8");
15121
- child.stderr.on("data", (chunk) => {
15122
- errors += chunk;
15138
+ const failure = (text2, stack = "") => {
15139
+ const trouble = new Error(text2);
15140
+ const said = errors.trim();
15141
+ trouble.stack = [text2, stack, said === "" ? "" : `stderr \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430:
15142
+ ${said.slice(-4e3)}`].filter((part) => part !== "").join("\n");
15143
+ return trouble;
15144
+ };
15145
+ thread.on("message", (message) => {
15146
+ finish(failure(`\u0442\u0435\u043B\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u043B\u043E\u0441\u044C: ${String(message.message)}`, String(message.stack ?? "")));
15123
15147
  });
15124
- child.on("error", (trouble) => {
15125
- finish(trouble);
15148
+ thread.on("error", (trouble) => {
15149
+ finish(failure(`\u0442\u0435\u043B\u043E \u0443\u043F\u0430\u043B\u043E: ${describeFailure(trouble)}`, trouble.stack ?? ""));
15126
15150
  });
15127
- child.on("exit", (code) => {
15128
- if (!finished) finish(new Error(`\u0442\u0435\u043B\u043E \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u043E\u0441\u044C \u0441 \u043A\u043E\u0434\u043E\u043C ${String(code)}: ${errors.trim()}`));
15151
+ thread.on("exit", (code) => {
15152
+ finish(failure(`\u0442\u0435\u043B\u043E \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u043E\u0441\u044C \u0441 \u043A\u043E\u0434\u043E\u043C ${String(code)}`));
15129
15153
  });
15130
- child.stdout.setEncoding("utf8");
15131
- child.stdout.on("data", (chunk) => {
15154
+ thread.stderr.setEncoding("utf8");
15155
+ thread.stderr.on("data", (chunk) => {
15156
+ errors += chunk;
15157
+ });
15158
+ let version2 = null;
15159
+ const answer = (reply) => {
15160
+ if (reply.error !== void 0) {
15161
+ finish(failure(`MCP-\u043F\u0440\u043E\u0431\u0430 \u043F\u043E\u043B\u0443\u0447\u0438\u043B\u0430 \u043E\u0442\u043A\u0430\u0437: ${JSON.stringify(reply.error)}`));
15162
+ } else if (reply.id === 1) {
15163
+ const named2 = reply.result?.serverInfo?.version;
15164
+ if (typeof named2 !== "string" || named2 === "") {
15165
+ finish(failure("initialize \u043D\u0435 \u043D\u0430\u0437\u0432\u0430\u043B \u0432\u0435\u0440\u0441\u0438\u044E \u0442\u0435\u043B\u0430"));
15166
+ return;
15167
+ }
15168
+ version2 = named2;
15169
+ send({ jsonrpc: "2.0", method: "notifications/initialized" });
15170
+ send({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
15171
+ } else if (reply.id === 2 && version2 !== null) {
15172
+ const names = new Set((reply.result?.tools ?? []).map((tool) => tool.name));
15173
+ const missing = REQUIRED_TOOLS.filter((name) => !names.has(name));
15174
+ if (missing.length > 0) {
15175
+ finish(failure(`tools/list \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B: ${missing.join(", ")}`));
15176
+ return;
15177
+ }
15178
+ finish(null, version2);
15179
+ }
15180
+ };
15181
+ thread.stdout.setEncoding("utf8");
15182
+ thread.stdout.on("data", (chunk) => {
15132
15183
  output += chunk;
15133
15184
  for (; ; ) {
15134
15185
  const end = output.indexOf("\n");
@@ -15136,36 +15187,14 @@ var probeShell = async (entry) => {
15136
15187
  const line = output.slice(0, end).trim();
15137
15188
  output = output.slice(end + 1);
15138
15189
  if (line === "") continue;
15139
- let response;
15190
+ let reply;
15140
15191
  try {
15141
- response = JSON.parse(line);
15192
+ reply = JSON.parse(line);
15142
15193
  } catch {
15143
- finish(new Error(`\u0442\u0435\u043B\u043E \u043D\u0430\u043F\u0435\u0447\u0430\u0442\u0430\u043B\u043E \u043D\u0435 JSON: ${line.slice(0, 200)}`));
15144
- return;
15145
- }
15146
- if (response.error !== void 0) {
15147
- finish(new Error(`MCP-\u043F\u0440\u043E\u0431\u0430 \u043F\u043E\u043B\u0443\u0447\u0438\u043B\u0430 \u043E\u0442\u043A\u0430\u0437: ${JSON.stringify(response.error)}`));
15194
+ finish(failure(`\u0442\u0435\u043B\u043E \u043D\u0430\u043F\u0435\u0447\u0430\u0442\u0430\u043B\u043E \u043D\u0435 JSON: ${line.slice(0, 200)}`));
15148
15195
  return;
15149
15196
  }
15150
- if (response.id === 1) {
15151
- const expected = version2.stdout.trim();
15152
- if (response.result?.serverInfo?.version !== expected) {
15153
- finish(new Error(
15154
- `initialize \u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043B \u0442\u0435\u043B\u043E \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \xAB${String(response.result?.serverInfo?.version)}\xBB, \u0430 --version \u043E\u0442\u0432\u0435\u0442\u0438\u043B \xAB${expected}\xBB`
15155
- ));
15156
- return;
15157
- }
15158
- send({ jsonrpc: "2.0", method: "notifications/initialized" });
15159
- send({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
15160
- } else if (response.id === 2) {
15161
- const names = new Set((response.result?.tools ?? []).map((tool) => tool.name));
15162
- const missing = ["setup", "render", "wait"].filter((name) => !names.has(name));
15163
- if (missing.length > 0) {
15164
- finish(new Error(`tools/list \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B: ${missing.join(", ")}`));
15165
- return;
15166
- }
15167
- finish();
15168
- }
15197
+ answer(reply);
15169
15198
  }
15170
15199
  });
15171
15200
  send({
@@ -15175,8 +15204,10 @@ var probeShell = async (entry) => {
15175
15204
  params: { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "update-probe", version: "1" } }
15176
15205
  });
15177
15206
  });
15178
- return version2;
15207
+ return { stdout: `${named}
15208
+ ` };
15179
15209
  } finally {
15210
+ await thread.terminate();
15180
15211
  rmSync(probeHome, { recursive: true, force: true, maxRetries: 3 });
15181
15212
  }
15182
15213
  };
@@ -15327,9 +15358,14 @@ async function dryRun2(build, expected, trial) {
15327
15358
  const { stdout } = await trial(entry);
15328
15359
  const line = stdout.trim().split("\n").pop() ?? "";
15329
15360
  const said = versionFrom(line);
15330
- if (said !== expected) return `\u0441\u0431\u043E\u0440\u043A\u0430 \u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043B\u0430\u0441\u044C \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \xAB${said}\xBB, \u0430 \u0436\u0434\u0430\u043B\u0438 \xAB${expected}\xBB`;
15361
+ if (said !== expected) {
15362
+ const trouble = `\u0441\u0431\u043E\u0440\u043A\u0430 \u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043B\u0430\u0441\u044C \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \xAB${said}\xBB, \u0430 \u0436\u0434\u0430\u043B\u0438 \xAB${expected}\xBB`;
15363
+ noteInstallFault("shell-probe", new Error(trouble));
15364
+ return trouble;
15365
+ }
15331
15366
  return null;
15332
15367
  } catch (trouble) {
15368
+ noteInstallFault("shell-probe", trouble);
15333
15369
  return describeFailure(trouble);
15334
15370
  }
15335
15371
  }
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Engine, chooseBody, handOverToBody, VERSION, rollback, rollbackShell, remove, fromNpxCache, install, keyFromBlock, readConfig, ForeignBlockError, currentMachineFingerprint, CrashReporter, watchProcessCrashes, McpServer, buildAll, realPace, buildResources, StdioServerTransport, reportInstallFaults, fromHost, WHERE_TO_GET_KEY, Wakefulness, systemBlocker, updateEngine, installStep, NaparnikApiClient, timeToCheck2, manifestUrlFor, fetchManifest, markChecked2, decide, shellDir, timeToCheck, bundleUrlFor, fetchShellManifest, markChecked, decideShell, installedShell, NaparnikConfigError } from './chunk-PT34EZZ7.js';
2
+ import { Engine, chooseBody, handOverToBody, VERSION, rollback, rollbackShell, remove, fromNpxCache, install, keyFromBlock, readConfig, ForeignBlockError, currentMachineFingerprint, CrashReporter, watchProcessCrashes, McpServer, buildAll, realPace, buildResources, StdioServerTransport, reportInstallFaults, fromHost, WHERE_TO_GET_KEY, Wakefulness, systemBlocker, updateEngine, installStep, NaparnikApiClient, timeToCheck2, manifestUrlFor, fetchManifest, markChecked2, decide, shellDir, timeToCheck, bundleUrlFor, fetchShellManifest, markChecked, decideShell, installedShell, NaparnikConfigError } from './chunk-Q7HJ7ROV.js';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { realpathSync, readFileSync } from 'fs';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1590,9 +1590,9 @@ declare class NaparnikConfigError extends NaparnikError {
1590
1590
  * годится ли она для новой начинки: разойдись она с пакетом, и в логах будет
1591
1591
  * стоять чужое число, а обновление начнёт считать оболочку не той.
1592
1592
  */
1593
- declare const VERSION = "0.10.47";
1593
+ declare const VERSION = "0.10.48";
1594
1594
  /** Как мы представляемся серверу Напарника. По нему в логах видно оболочку. */
1595
- declare const USER_AGENT = "naparnik-mcp/0.10.47";
1595
+ declare const USER_AGENT = "naparnik-mcp/0.10.48";
1596
1596
  /**
1597
1597
  * Самая старая начинка (движок монтажа), с которой эта оболочка работает.
1598
1598
  * Обновление начинки ниже этой версии не ставится, а выше — требует оболочки
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { DEFAULT_HOME, DeliveryError, Engine, ForeignBlockError, INSIDE_PYTHON, INSTALL_STEPS, KEEP_COPIES, KEEP_VERSIONS, LONG_STEPS, MANIFEST_TIMEOUT_MS, MANIFEST_URL, MARKER, MIN_ENGINE, NaparnikApiClient, NaparnikAuthError, NaparnikClientError, NaparnikConfigError, NaparnikError, NaparnikInsufficientBalanceError, NaparnikScopeError, NaparnikServerError, NaparnikTimeoutError, PAUSE_HOURS, SERVER_NAME, SOURCES_FILE, START_SEC, TOOL_SEC, USER_AGENT, VERSION, buildAll, buildBlock, buildResources, compare, configPath, decide, defineTool, deploy, downloadFile, fetchManifest, fileOrRefusal, findBlock, fromNpxCache, inside, install, installPayload, installPython, jsonSchemaOf, keyInTable, lastLine, loadConfig, markChecked2 as markChecked, markCurrent, parseEngineManifest, parseFailure, path, platformKey, previousVersion, probe, pythonSource, refusalFor, remove, rollback, tarEntries, tidyOld, timeToCheck2 as timeToCheck, unpackArchive, withArgs } from './chunk-PT34EZZ7.js';
1
+ export { DEFAULT_HOME, DeliveryError, Engine, ForeignBlockError, INSIDE_PYTHON, INSTALL_STEPS, KEEP_COPIES, KEEP_VERSIONS, LONG_STEPS, MANIFEST_TIMEOUT_MS, MANIFEST_URL, MARKER, MIN_ENGINE, NaparnikApiClient, NaparnikAuthError, NaparnikClientError, NaparnikConfigError, NaparnikError, NaparnikInsufficientBalanceError, NaparnikScopeError, NaparnikServerError, NaparnikTimeoutError, PAUSE_HOURS, SERVER_NAME, SOURCES_FILE, START_SEC, TOOL_SEC, USER_AGENT, VERSION, buildAll, buildBlock, buildResources, compare, configPath, decide, defineTool, deploy, downloadFile, fetchManifest, fileOrRefusal, findBlock, fromNpxCache, inside, install, installPayload, installPython, jsonSchemaOf, keyInTable, lastLine, loadConfig, markChecked2 as markChecked, markCurrent, parseEngineManifest, parseFailure, path, platformKey, previousVersion, probe, pythonSource, refusalFor, remove, rollback, tarEntries, tidyOld, timeToCheck2 as timeToCheck, unpackArchive, withArgs } from './chunk-Q7HJ7ROV.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naparnik/mcp",
3
- "version": "0.10.47",
3
+ "version": "0.10.48",
4
4
  "description": "MCP-сервер Напарника: монтаж вертикального видео на машине пользователя — паузы, субтитры, герой на новом фоне, звук. Видео никуда не уезжает.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "private": false,