@naparnik/mcp 0.10.47 → 0.10.50
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 +20 -0
- package/dist/{chunk-PT34EZZ7.js → chunk-DH5ID6CT.js} +575 -678
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +56 -85
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { createHash, randomUUID, randomBytes } from 'crypto';
|
|
2
|
+
import { existsSync, readFileSync, closeSync, mkdirSync, openSync, rmSync, renameSync, readdirSync, statSync, writeFileSync, symlinkSync, chmodSync, lstatSync, realpathSync, mkdtempSync, linkSync, readlinkSync, appendFileSync, fstatSync, readSync, fsyncSync } from 'fs';
|
|
3
|
+
import { win32, join, dirname, sep, resolve, basename, relative, isAbsolute, extname } from 'path';
|
|
4
|
+
import { gunzipSync } from 'zlib';
|
|
1
5
|
import { execFile, spawn, execFileSync } from 'child_process';
|
|
2
|
-
import { createHash, randomBytes, randomUUID } from 'crypto';
|
|
3
|
-
import { existsSync, readFileSync, closeSync, mkdirSync, openSync, readdirSync, statSync, rmSync, writeFileSync, renameSync, symlinkSync, chmodSync, lstatSync, realpathSync, mkdtempSync, linkSync, readlinkSync, appendFileSync, fstatSync, readSync, fsyncSync } from 'fs';
|
|
4
6
|
import { platform, homedir, arch, release, userInfo, tmpdir } from 'os';
|
|
5
|
-
import { win32, join, dirname, sep, resolve, basename, relative, isAbsolute, extname } from 'path';
|
|
6
7
|
import { promisify } from 'util';
|
|
7
8
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
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,9 +730,9 @@ function parsePositiveInt(raw, fallback) {
|
|
|
729
730
|
}
|
|
730
731
|
|
|
731
732
|
// src/version.ts
|
|
732
|
-
var VERSION = "0.10.
|
|
733
|
+
var VERSION = "0.10.50";
|
|
733
734
|
var USER_AGENT = `naparnik-mcp/${VERSION}`;
|
|
734
|
-
var MIN_ENGINE = "2026.09.24-
|
|
735
|
+
var MIN_ENGINE = "2026.09.24-478";
|
|
735
736
|
var LAUNCHER_PROTOCOL = 1;
|
|
736
737
|
|
|
737
738
|
// src/contracts/sdk-headers.ts
|
|
@@ -1000,6 +1001,258 @@ function describe(err) {
|
|
|
1000
1001
|
function sleep(ms) {
|
|
1001
1002
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1002
1003
|
}
|
|
1004
|
+
var DeliveryError = class extends Error {
|
|
1005
|
+
constructor(message) {
|
|
1006
|
+
super(message);
|
|
1007
|
+
this.name = "DeliveryTrouble";
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
async function downloadFile(opts) {
|
|
1011
|
+
const { url: url2, dest, sha256, bytes, timeoutMs = 30 * 6e4, report, key } = opts;
|
|
1012
|
+
if (!/^[a-f0-9]{64}$/.test(sha256)) {
|
|
1013
|
+
throw new DeliveryError(`\u043D\u0435\u0447\u0435\u043C \u0441\u0432\u0435\u0440\u0438\u0442\u044C \u0441\u043A\u0430\u0447\u0430\u043D\u043D\u043E\u0435: \u0441\u0443\u043C\u043C\u0430 \xAB${sha256}\xBB \u043D\u0435 \u043F\u043E\u0445\u043E\u0436\u0430 \u043D\u0430 sha256`);
|
|
1014
|
+
}
|
|
1015
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
1016
|
+
const temp = `${dest}.downloading-${process.pid}-${randomUUID()}`;
|
|
1017
|
+
const guard = new AbortController();
|
|
1018
|
+
const timer = setTimeout(() => {
|
|
1019
|
+
guard.abort();
|
|
1020
|
+
}, timeoutMs);
|
|
1021
|
+
try {
|
|
1022
|
+
const response = await fetch(url2, {
|
|
1023
|
+
signal: guard.signal,
|
|
1024
|
+
redirect: "follow",
|
|
1025
|
+
...key !== null && key !== void 0 ? { headers: { authorization: `Bearer ${key}` } } : {}
|
|
1026
|
+
});
|
|
1027
|
+
const hasKey = key !== null && key !== void 0;
|
|
1028
|
+
if (!response.ok) {
|
|
1029
|
+
if (response.status === 401 || response.status === 403) {
|
|
1030
|
+
if (response.status === 403 && hasKey) {
|
|
1031
|
+
throw new DeliveryError(
|
|
1032
|
+
`${url2} \u043D\u0435 \u043E\u0442\u0434\u0430\u0451\u0442 \u0444\u0430\u0439\u043B: \u043A\u043B\u044E\u0447 \u043F\u0440\u0438\u0437\u043D\u0430\u043D, \u043D\u043E \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438 \u043D\u0430 \u043C\u043E\u043D\u0442\u0430\u0436 \u043D\u0435\u0442. \u0421\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435 \u043D\u043E\u0432\u043E\u0433\u043E \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E, \u043F\u043E\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u0430\u043A\u0442\u0438\u0432\u043D\u0430; \u0432\u0441\u0451, \u0447\u0442\u043E \u0443\u0436\u0435 \u0441\u0442\u043E\u0438\u0442 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435, \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C. \u041F\u0440\u043E\u0434\u043B\u0438\u0442\u0435 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0443 \u0432 \u0431\u043E\u0442\u0435 \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
throw new DeliveryError(
|
|
1036
|
+
!hasKey ? `${url2} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043A\u043B\u044E\u0447 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430, \u0430 \u043E\u043D \u043D\u0435 \u0437\u0430\u0434\u0430\u043D. \u0412\u043F\u0438\u0448\u0438\u0442\u0435 \u043A\u043B\u044E\u0447 \u0432 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044E MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u0441\u0435\u043A\u0446\u0438\u044F env) \u0438 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0443 \u2014 \u041A\u043B\u043E\u0434\u0430 \u0438\u043B\u0438 Codex.` : `${url2} \u043D\u0435 \u043F\u0440\u0438\u043D\u044F\u043B \u043A\u043B\u044E\u0447 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430 (${response.status}). \u0421\u043A\u043E\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u043A\u043B\u044E\u0447 \u0437\u0430\u043C\u0435\u043D\u0451\u043D \u0431\u043E\u043B\u0435\u0435 \u043D\u043E\u0432\u044B\u043C: \u043D\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B \u0438\u0437 \u0431\u043E\u0442\u0430 \u0443\u0436\u0435 \u043F\u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D \u0437\u0434\u0435\u0441\u044C \u0438\u043B\u0438 \u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u043C \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435. \u0412\u043E\u0437\u044C\u043C\u0438\u0442\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0444\u0430\u0439\u043B \u0443 \u0431\u043E\u0442\u0430 ${KEY_SOURCE_BOT} \u0438 \u043F\u043E\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u0435\u0433\u043E.`
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
throw new DeliveryError(`${url2} \u043E\u0442\u0432\u0435\u0442\u0438\u043B ${response.status} ${response.statusText}`);
|
|
1040
|
+
}
|
|
1041
|
+
const body = await response.arrayBuffer();
|
|
1042
|
+
const buffer = Buffer.from(body);
|
|
1043
|
+
const sum = createHash("sha256").update(buffer).digest("hex");
|
|
1044
|
+
if (bytes !== void 0 && buffer.length !== bytes) {
|
|
1045
|
+
throw new DeliveryError(
|
|
1046
|
+
looksLikeHtml(buffer) ? `\u043F\u043E \u0430\u0434\u0440\u0435\u0441\u0443 ${url2} \u043B\u0435\u0436\u0438\u0442 \u043D\u0435 \u0430\u0440\u0445\u0438\u0432, \u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u2014 \u0444\u0430\u0439\u043B \u0435\u0449\u0451 \u043D\u0435 \u0432\u044B\u043B\u043E\u0436\u0435\u043D.` : `\u0441\u043A\u0430\u0447\u0430\u043B\u043E\u0441\u044C ${buffer.length} \u0431\u0430\u0439\u0442 \u0432\u043C\u0435\u0441\u0442\u043E ${bytes} \u2014 \u0441\u0432\u044F\u0437\u044C \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u0430\u0441\u044C, \u043F\u043E\u0432\u0442\u043E\u0440\u0438.`
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
if (sum !== sha256) {
|
|
1050
|
+
throw new DeliveryError(
|
|
1051
|
+
looksLikeHtml(buffer) ? `\u043F\u043E \u0430\u0434\u0440\u0435\u0441\u0443 ${url2} \u043B\u0435\u0436\u0438\u0442 \u043D\u0435 \u0430\u0440\u0445\u0438\u0432, \u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u2014 \u0444\u0430\u0439\u043B \u0435\u0449\u0451 \u043D\u0435 \u0432\u044B\u043B\u043E\u0436\u0435\u043D.` : `\u0441\u043A\u0430\u0447\u0430\u043D\u043D\u043E\u0435 \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u043B\u043E \u0441 \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u043E\u0439 \u0441\u0443\u043C\u043C\u043E\u0439.
|
|
1052
|
+
\u0436\u0434\u0430\u043B\u0438 ${sha256}
|
|
1053
|
+
\u0432\u044B\u0448\u043B\u043E ${sum}
|
|
1054
|
+
\u041F\u043E\u0432\u0442\u043E\u0440\u0438; \u0435\u0441\u043B\u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u0442\u0441\u044F \u2014 \u0444\u0430\u0439\u043B \u043F\u043E\u0434\u043C\u0435\u043D\u0451\u043D \u0438\u043B\u0438 \u0431\u0438\u0442\u044B\u0439, \u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0435\u0433\u043E \u043D\u0435\u043B\u044C\u0437\u044F.`
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
writeFileSync(temp, buffer);
|
|
1058
|
+
if (existsSync(dest)) {
|
|
1059
|
+
throw new DeliveryError(
|
|
1060
|
+
`\u0444\u0430\u0439\u043B ${dest} \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u043B \u0434\u0440\u0443\u0433\u043E\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u044F\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0441 \u043D\u043E\u0432\u044B\u043C staging.`
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
renameSync(temp, dest);
|
|
1064
|
+
report?.(`\u0441\u043A\u0430\u0447\u0430\u043D\u043E ${Math.round(buffer.length / 1024 / 1024)} \u041C\u0411`);
|
|
1065
|
+
return { file: dest, bytes: buffer.length, sha256: sum };
|
|
1066
|
+
} catch (trouble) {
|
|
1067
|
+
rmSync(temp, { force: true });
|
|
1068
|
+
if (trouble instanceof DeliveryError) throw trouble;
|
|
1069
|
+
if (guard.signal.aborted) {
|
|
1070
|
+
throw new DeliveryError(`${url2} \u043D\u0435 \u043E\u0442\u0434\u0430\u043B \u0444\u0430\u0439\u043B \u0437\u0430 ${Math.round(timeoutMs / 6e4)} \u043C\u0438\u043D.`);
|
|
1071
|
+
}
|
|
1072
|
+
throw new DeliveryError(`\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u043A\u0430\u0447\u0430\u0442\u044C ${url2}: ${describeFailure(trouble)}`);
|
|
1073
|
+
} finally {
|
|
1074
|
+
clearTimeout(timer);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
function looksLikeHtml(buffer) {
|
|
1078
|
+
const start = buffer.subarray(0, 200).toString("latin1").trimStart().toLowerCase();
|
|
1079
|
+
return start.startsWith("<!doctype html") || start.startsWith("<html");
|
|
1080
|
+
}
|
|
1081
|
+
var BLOCK = 512;
|
|
1082
|
+
function tarEntries(data) {
|
|
1083
|
+
const entries = [];
|
|
1084
|
+
let offset = 0;
|
|
1085
|
+
let longName = null;
|
|
1086
|
+
let longTarget = null;
|
|
1087
|
+
while (offset + BLOCK <= data.length) {
|
|
1088
|
+
const header = data.subarray(offset, offset + BLOCK);
|
|
1089
|
+
if (header.every((b) => b === 0)) break;
|
|
1090
|
+
const name = fieldLine(header, 0, 100);
|
|
1091
|
+
const mode = octal(header, 100, 8);
|
|
1092
|
+
const size = fieldSize(header, 124, 12);
|
|
1093
|
+
const type = String.fromCharCode(header[156]);
|
|
1094
|
+
const target = fieldLine(header, 157, 100);
|
|
1095
|
+
const prefix = fieldLine(header, 345, 155);
|
|
1096
|
+
offset += BLOCK;
|
|
1097
|
+
const body = data.subarray(offset, offset + size);
|
|
1098
|
+
offset += Math.ceil(size / BLOCK) * BLOCK;
|
|
1099
|
+
if (type === "L") {
|
|
1100
|
+
longName = body.toString("utf8").replace(/\0+$/, "");
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
if (type === "K") {
|
|
1104
|
+
longTarget = body.toString("utf8").replace(/\0+$/, "");
|
|
1105
|
+
continue;
|
|
1106
|
+
}
|
|
1107
|
+
if (type === "x") {
|
|
1108
|
+
const fields = parsePax(body);
|
|
1109
|
+
if (fields["path"] !== void 0) longName = fields["path"];
|
|
1110
|
+
if (fields["linkpath"] !== void 0) longTarget = fields["linkpath"];
|
|
1111
|
+
continue;
|
|
1112
|
+
}
|
|
1113
|
+
if (type === "g") continue;
|
|
1114
|
+
const full = longName ?? (prefix !== "" ? `${prefix}/${name}` : name);
|
|
1115
|
+
const linkTarget = longTarget ?? target;
|
|
1116
|
+
longName = null;
|
|
1117
|
+
longTarget = null;
|
|
1118
|
+
const kind = type === "5" ? "dir" : type === "2" ? "symlink" : type === "1" ? "hardlink" : "file";
|
|
1119
|
+
if (type !== "" && type !== "0" && type !== "\0" && kind === "file" && type !== "7") continue;
|
|
1120
|
+
entries.push({ name: full, kind, mode, body, target: linkTarget });
|
|
1121
|
+
}
|
|
1122
|
+
return entries;
|
|
1123
|
+
}
|
|
1124
|
+
function parsePax(body) {
|
|
1125
|
+
const fields = {};
|
|
1126
|
+
let offset = 0;
|
|
1127
|
+
while (offset < body.length) {
|
|
1128
|
+
const space = body.indexOf(32, offset);
|
|
1129
|
+
if (space === -1) break;
|
|
1130
|
+
const length = Number.parseInt(body.subarray(offset, space).toString("ascii"), 10);
|
|
1131
|
+
if (!Number.isFinite(length) || length <= 0 || offset + length > body.length) break;
|
|
1132
|
+
const entry = body.subarray(space + 1, offset + length).toString("utf8").replace(/\n$/, "");
|
|
1133
|
+
const equal = entry.indexOf("=");
|
|
1134
|
+
if (equal > 0) fields[entry.slice(0, equal)] = entry.slice(equal + 1);
|
|
1135
|
+
offset += length;
|
|
1136
|
+
}
|
|
1137
|
+
return fields;
|
|
1138
|
+
}
|
|
1139
|
+
function fieldLine(header, start, length) {
|
|
1140
|
+
const chunk = header.subarray(start, start + length);
|
|
1141
|
+
const end = chunk.indexOf(0);
|
|
1142
|
+
return chunk.subarray(0, end === -1 ? chunk.length : end).toString("utf8");
|
|
1143
|
+
}
|
|
1144
|
+
function octal(header, start, length) {
|
|
1145
|
+
const text2 = fieldLine(header, start, length).trim();
|
|
1146
|
+
const ch = Number.parseInt(text2, 8);
|
|
1147
|
+
return Number.isFinite(ch) ? ch : 0;
|
|
1148
|
+
}
|
|
1149
|
+
function fieldSize(header, start, length) {
|
|
1150
|
+
if ((header[start] & 128) !== 0) {
|
|
1151
|
+
let ch = 0;
|
|
1152
|
+
for (let i = start + 1; i < start + length; i += 1) ch = ch * 256 + header[i];
|
|
1153
|
+
return ch;
|
|
1154
|
+
}
|
|
1155
|
+
return octal(header, start, length);
|
|
1156
|
+
}
|
|
1157
|
+
function inside(root, path2) {
|
|
1158
|
+
if (path2 === "" || path2.startsWith("/") || path2.startsWith("\\")) return false;
|
|
1159
|
+
if (/^[A-Za-z]:/.test(path2)) return false;
|
|
1160
|
+
const target = resolve(root, path2);
|
|
1161
|
+
const bottom = resolve(root);
|
|
1162
|
+
return target === bottom || target.startsWith(bottom + sep);
|
|
1163
|
+
}
|
|
1164
|
+
function unpackArchive(archive, dest) {
|
|
1165
|
+
const entries = tarEntries(gunzipSync(readFileSync(archive)));
|
|
1166
|
+
if (entries.length === 0) throw new DeliveryError(`\u0430\u0440\u0445\u0438\u0432 ${archive} \u043F\u0443\u0441\u0442 \u2014 \u0440\u0430\u0441\u043F\u0430\u043A\u043E\u0432\u044B\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E`);
|
|
1167
|
+
for (const entry of entries) {
|
|
1168
|
+
if (!inside(dest, entry.name)) throw escapesRoot(archive, entry.name);
|
|
1169
|
+
if (entry.kind === "symlink" || entry.kind === "hardlink") {
|
|
1170
|
+
if (entry.target.startsWith("/") || entry.target.startsWith("\\") || /^[A-Za-z]:/.test(entry.target)) {
|
|
1171
|
+
throw escapesRoot(archive, `${entry.name} \u2192 ${entry.target}`);
|
|
1172
|
+
}
|
|
1173
|
+
const from = entry.kind === "hardlink" ? entry.target : join(dirname(entry.name), entry.target);
|
|
1174
|
+
if (!inside(dest, from)) throw escapesRoot(archive, `${entry.name} \u2192 ${entry.target}`);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
for (const entry of entries) {
|
|
1178
|
+
const path2 = join(dest, entry.name);
|
|
1179
|
+
if (entry.kind === "dir") {
|
|
1180
|
+
mkdirSync(path2, { recursive: true });
|
|
1181
|
+
continue;
|
|
1182
|
+
}
|
|
1183
|
+
mkdirSync(dirname(path2), { recursive: true });
|
|
1184
|
+
if (entry.kind === "symlink") {
|
|
1185
|
+
rmSync(path2, { force: true });
|
|
1186
|
+
symlinkSync(entry.target, path2);
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
if (entry.kind === "hardlink") {
|
|
1190
|
+
writeFileSync(path2, readFileSync(join(dest, entry.target)));
|
|
1191
|
+
continue;
|
|
1192
|
+
}
|
|
1193
|
+
writeFileSync(path2, entry.body);
|
|
1194
|
+
if ((entry.mode & 73) !== 0) chmodSync(path2, entry.mode & 511);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
function escapesRoot(archive, name) {
|
|
1198
|
+
return new DeliveryError(
|
|
1199
|
+
`\u0430\u0440\u0445\u0438\u0432 ${archive} \u043F\u044B\u0442\u0430\u0435\u0442\u0441\u044F \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0444\u0430\u0439\u043B \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u043F\u0430\u043F\u043A\u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438: \xAB${name}\xBB.
|
|
1200
|
+
\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0440\u0430\u0441\u043F\u0430\u043A\u043E\u0432\u0430\u043D\u043E. \u0421\u043A\u0430\u0447\u0430\u0439 \u0437\u0430\u043D\u043E\u0432\u043E \u2014 \u0432\u0435\u0440\u043E\u044F\u0442\u043D\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u0444\u0430\u0439\u043B \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0451\u043D \u0438\u043B\u0438 \u043F\u043E\u0434\u043C\u0435\u043D\u0451\u043D.`
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
function dirExists(path2) {
|
|
1204
|
+
try {
|
|
1205
|
+
return statSync(path2).isDirectory();
|
|
1206
|
+
} catch {
|
|
1207
|
+
return false;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
var LOCK_FILE = "deps.lock.json";
|
|
1211
|
+
function platformKey(os = process.platform, arch2 = process.arch) {
|
|
1212
|
+
if (os === "darwin") return arch2 === "arm64" ? "Darwin-arm64" : arch2 === "x64" ? "Darwin-x86_64" : null;
|
|
1213
|
+
if (os === "win32") return arch2 === "x64" ? "Windows-AMD64" : null;
|
|
1214
|
+
if (os === "linux") return arch2 === "x64" ? "Linux-x86_64" : arch2 === "arm64" ? "Linux-aarch64" : null;
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
function depFolderName(entry) {
|
|
1218
|
+
return `${entry.version}-${entry.archives.map((one) => one.sha256.slice(0, 8)).join("")}`;
|
|
1219
|
+
}
|
|
1220
|
+
function lockedPython(engineDir, home, key = platformKey()) {
|
|
1221
|
+
if (key === null) return null;
|
|
1222
|
+
const file2 = join(engineDir, LOCK_FILE);
|
|
1223
|
+
if (!existsSync(file2)) return null;
|
|
1224
|
+
const lock = JSON.parse(readFileSync(file2, "utf8"));
|
|
1225
|
+
const entry = lock.python?.platforms?.[key];
|
|
1226
|
+
const archive = entry?.archives[0];
|
|
1227
|
+
if (entry === void 0 || archive === void 0) return null;
|
|
1228
|
+
const folder = join(home, "deps", "python", depFolderName(entry));
|
|
1229
|
+
return { version: entry.version, archive, folder, executable: join(folder, entry.run) };
|
|
1230
|
+
}
|
|
1231
|
+
async function bringPython(python, report) {
|
|
1232
|
+
if (existsSync(python.executable)) return python.executable;
|
|
1233
|
+
const stage = `${python.folder}.partial-${process.pid}`;
|
|
1234
|
+
rmSync(stage, { recursive: true, force: true });
|
|
1235
|
+
try {
|
|
1236
|
+
const archive = join(stage, "python.tar.gz");
|
|
1237
|
+
await downloadFile({
|
|
1238
|
+
url: python.archive.url,
|
|
1239
|
+
dest: archive,
|
|
1240
|
+
sha256: python.archive.sha256,
|
|
1241
|
+
bytes: python.archive.bytes,
|
|
1242
|
+
key: null,
|
|
1243
|
+
...report !== void 0 ? { report } : {}
|
|
1244
|
+
});
|
|
1245
|
+
unpackArchive(archive, join(stage, "tree"));
|
|
1246
|
+
if (!existsSync(join(stage, "tree", python.executable.slice(python.folder.length + 1)))) {
|
|
1247
|
+
throw new DeliveryError("\u0432 \u0430\u0440\u0445\u0438\u0432\u0435 \u043F\u0438\u0442\u043E\u043D\u0430 \u043D\u0435\u0442 \u0438\u043D\u0442\u0435\u0440\u043F\u0440\u0435\u0442\u0430\u0442\u043E\u0440\u0430, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u043D\u0430\u0437\u0432\u0430\u043B \u0437\u0430\u043C\u043E\u043A");
|
|
1248
|
+
}
|
|
1249
|
+
mkdirSync(dirname(python.folder), { recursive: true });
|
|
1250
|
+
if (!dirExists(python.folder)) renameSync(join(stage, "tree"), python.folder);
|
|
1251
|
+
} finally {
|
|
1252
|
+
rmSync(stage, { recursive: true, force: true });
|
|
1253
|
+
}
|
|
1254
|
+
return python.executable;
|
|
1255
|
+
}
|
|
1003
1256
|
var TAIL_MS = 10 * 6e4;
|
|
1004
1257
|
var AWAY_NOTE = "\u0421\u043A\u0430\u0436\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443: \u043C\u043E\u0436\u043D\u043E \u043E\u0442\u043E\u0439\u0442\u0438, \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440 \u043D\u0435 \u0443\u0441\u043D\u0451\u0442, \u043F\u043E\u043A\u0430 \u0438\u0434\u0451\u0442 \u0440\u0430\u0431\u043E\u0442\u0430. \u0422\u043E\u043B\u044C\u043A\u043E \u043A\u0440\u044B\u0448\u043A\u0443 \u043D\u043E\u0443\u0442\u0431\u0443\u043A\u0430 \u043D\u0435 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u0442\u044C.";
|
|
1005
1258
|
var realClock = {
|
|
@@ -1314,7 +1567,6 @@ function currentMachineFingerprint() {
|
|
|
1314
1567
|
return cached;
|
|
1315
1568
|
}
|
|
1316
1569
|
var execFileP = promisify(execFile);
|
|
1317
|
-
var INSIDE_PYTHON = ["python.exe", join("bin", "python3"), join("bin", "python")];
|
|
1318
1570
|
var FOREIGN_PYTHON_VARS = [
|
|
1319
1571
|
"PYTHONHOME",
|
|
1320
1572
|
"PYTHONPATH",
|
|
@@ -1520,94 +1772,44 @@ var Engine = class {
|
|
|
1520
1772
|
return null;
|
|
1521
1773
|
}
|
|
1522
1774
|
/**
|
|
1523
|
-
*
|
|
1775
|
+
* Питон по замку начинки (`engine/deps.lock.json`), если он уже в хранилище.
|
|
1524
1776
|
*
|
|
1525
|
-
* ⚠
|
|
1526
|
-
*
|
|
1527
|
-
*
|
|
1528
|
-
*
|
|
1529
|
-
*
|
|
1777
|
+
* ⚠ ТОЛЬКО СВОЙ. До 2026-09-24 здесь был «python3» из PATH на случай, когда
|
|
1778
|
+
* своего нет, а окружение новой версии собиралось перебором «свой → базовый
|
|
1779
|
+
* питон рабочей версии → системный». Claude Desktop подсунул питон Xcode 3.9,
|
|
1780
|
+
* тот не собрал окружение, и обновление у владельца не вставало целый день.
|
|
1781
|
+
* Решение владельца — «как node_modules»: свой питон по замку, чужого нет.
|
|
1530
1782
|
*/
|
|
1531
|
-
ourPython() {
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
if (existsSync(candidate)) return candidate;
|
|
1536
|
-
}
|
|
1537
|
-
return null;
|
|
1783
|
+
ourPython(place = this.place()) {
|
|
1784
|
+
if (place === null) return null;
|
|
1785
|
+
const python = lockedPython(place.engine, this.home());
|
|
1786
|
+
return python !== null && existsSync(python.executable) ? python.executable : null;
|
|
1538
1787
|
}
|
|
1539
1788
|
/**
|
|
1540
|
-
* Python для команд
|
|
1789
|
+
* Python для команд движка: окружение пака, а пока его нет — свой питон по
|
|
1790
|
+
* замку. Нет ни того, ни другого — путь, которого нет: `pythonTrouble`
|
|
1791
|
+
* ответит словами «позови setup», а не «spawn python3 ENOENT».
|
|
1541
1792
|
*
|
|
1542
|
-
*
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
1545
|
-
* системным python'ом, когда своего ещё нет.
|
|
1793
|
+
* ⚠ «python3» ИЗ PATH — ТОЛЬКО ПРИ `NAPARNIK_SYSTEM_TOOLS=1`: так тесты и
|
|
1794
|
+
* разработка гоняют движок из исходников без хранилища (та же переменная у
|
|
1795
|
+
* движка, `engine/media/ffmpeg.py`). У покупателя её нет.
|
|
1546
1796
|
*/
|
|
1547
1797
|
enginePython() {
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
/** Python подготовки кандидата — намеренно без fallback на venv старого пака. */
|
|
1551
|
-
bootstrapPython() {
|
|
1552
|
-
return this.bootstrapPythons()[0] ?? (platform() === "win32" ? "python" : "python3");
|
|
1798
|
+
const fallback = this.env["NAPARNIK_SYSTEM_TOOLS"] === "1" ? platform() === "win32" ? "python" : "python3" : join(this.home(), "deps", "python", "not-installed");
|
|
1799
|
+
return this.packPython() ?? this.ourPython() ?? fallback;
|
|
1553
1800
|
}
|
|
1554
1801
|
/**
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1557
|
-
* ⚠ БАЗОВЫЙ ПИТОН РАБОЧЕЙ ВЕРСИИ СТОИТ ВПЕРЕДИ «python3» ИЗ PATH, И ЭТО
|
|
1558
|
-
* ПОЧИНКА, А НЕ ВКУС. Claude Desktop на маке запускает нас без
|
|
1559
|
-
* `/opt/homebrew/bin` в PATH, и «python3» там — `/usr/bin/python3`, питон
|
|
1560
|
-
* Xcode 3.9. Он собирает venv только ссылками («This build of python cannot
|
|
1561
|
-
* create venvs without using symlinks»), а ссылка на интерпретатор вне версии
|
|
1562
|
-
* не проходит сверку `candidateVenvTrouble`. Обновление 2026.09.24-467 у
|
|
1563
|
-
* владельца встало ровно на этом, хотя рабочая версия собрана Homebrew 3.14
|
|
1564
|
-
* копиями и работает. Движок при первой установке ищет питон сам
|
|
1565
|
-
* (`setup/python_finder.py`) и пишет, какой взял, в `pyvenv.cfg` окружения —
|
|
1566
|
-
* этот и берём: он уже однажды собрал здесь рабочее окружение копиями.
|
|
1567
|
-
*
|
|
1568
|
-
* ⚠ НЕ ПИТОН САМОГО VENV. Окружение старой версии удаляется уборкой после
|
|
1569
|
-
* обновления, и кандидат, собранный его питоном, остался бы без интерпретатора
|
|
1570
|
-
* (`engine-candidate.test.ts`). База из `pyvenv.cfg` лежит вне версий.
|
|
1571
|
-
*/
|
|
1572
|
-
bootstrapPythons() {
|
|
1573
|
-
const found = [
|
|
1574
|
-
this.ourPython(),
|
|
1575
|
-
this.workingBasePython(),
|
|
1576
|
-
platform() === "win32" ? "python" : "python3"
|
|
1577
|
-
].filter((one) => one !== null);
|
|
1578
|
-
return [...new Set(found)];
|
|
1579
|
-
}
|
|
1580
|
-
/**
|
|
1581
|
-
* Базовый интерпретатор окружения рабочей версии — из её `pyvenv.cfg`.
|
|
1582
|
-
*
|
|
1583
|
-
* `home` раньше `executable`: у Homebrew `executable` указывает в папку
|
|
1584
|
-
* конкретного выпуска (`Cellar/python@3.14/3.14.7/…`), и после `brew upgrade`
|
|
1585
|
-
* её уже нет, а `home` (`/opt/homebrew/opt/python@3.14/bin`) переживает
|
|
1586
|
-
* обновление. Нет файла или записанного питона на диске — `null`.
|
|
1802
|
+
* Принести питон замка ЭТОГО кандидата (или взять уже лежащий) — им движок
|
|
1803
|
+
* кандидата доводит до замка всё остальное (`env-install --step env`).
|
|
1587
1804
|
*/
|
|
1588
|
-
|
|
1589
|
-
const
|
|
1590
|
-
if (
|
|
1591
|
-
|
|
1592
|
-
try {
|
|
1593
|
-
text2 = readFileSync(join(place.pack, ".venv", "pyvenv.cfg"), "utf8");
|
|
1594
|
-
} catch {
|
|
1595
|
-
return null;
|
|
1805
|
+
async bringPython(place, report) {
|
|
1806
|
+
const python = lockedPython(place.engine, this.home());
|
|
1807
|
+
if (python === null) {
|
|
1808
|
+
throw new Error(`\u043F\u043E\u0434 \u044D\u0442\u0443 \u0441\u0438\u0441\u0442\u0435\u043C\u0443 \u0432 \u0437\u0430\u043C\u043A\u0435 \u043D\u0435\u0442 \u0441\u0431\u043E\u0440\u043A\u0438 \u043F\u0438\u0442\u043E\u043D\u0430. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043D\u0430\u043F\u0438\u0448\u0438 \u0431\u043E\u0442\u0443 ${KEY_SOURCE_BOT} \u2014 \u043F\u043E\u0434\u0431\u0435\u0440\u0451\u043C \u0441\u0431\u043E\u0440\u043A\u0443`);
|
|
1596
1809
|
}
|
|
1597
|
-
const
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
};
|
|
1601
|
-
const home = value("home");
|
|
1602
|
-
if (home !== null) {
|
|
1603
|
-
const names = platform() === "win32" ? ["python.exe"] : ["python3", "python"];
|
|
1604
|
-
for (const name of names) {
|
|
1605
|
-
const candidate = join(home, name);
|
|
1606
|
-
if (existsSync(candidate)) return candidate;
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
const executable = value("executable");
|
|
1610
|
-
return executable !== null && existsSync(executable) ? executable : null;
|
|
1810
|
+
const executable = await bringPython(python, report);
|
|
1811
|
+
this.forgetPython();
|
|
1812
|
+
return executable;
|
|
1611
1813
|
}
|
|
1612
1814
|
/** Python ровно названного кандидата, а не текущей версии. */
|
|
1613
1815
|
candidatePython(place) {
|
|
@@ -1631,6 +1833,9 @@ var Engine = class {
|
|
|
1631
1833
|
pythonEnv() {
|
|
1632
1834
|
const env = { ...this.env, PYTHONUTF8: "1", PYTHONIOENCODING: "utf-8" };
|
|
1633
1835
|
for (const name of FOREIGN_PYTHON_VARS) delete env[name];
|
|
1836
|
+
for (const [name, value] of Object.entries(env)) {
|
|
1837
|
+
if (value !== void 0 && value.trim() !== "" && fromHost(value) === "") delete env[name];
|
|
1838
|
+
}
|
|
1634
1839
|
delete env["NAPARNIK_API_KEY"];
|
|
1635
1840
|
return env;
|
|
1636
1841
|
}
|
|
@@ -1640,12 +1845,7 @@ var Engine = class {
|
|
|
1640
1845
|
* Весь движок (включая проверку и установку) идёт через запуск python'а.
|
|
1641
1846
|
* Когда его нет, `execFile` бросает ENOENT, и клиентской нейросети
|
|
1642
1847
|
* доставалось «spawn python3 ENOENT» — текст, из которого человеку не понять
|
|
1643
|
-
* ничего.
|
|
1644
|
-
* недостижим по устройству: он сам запускается python'ом.
|
|
1645
|
-
*
|
|
1646
|
-
* На Windows есть отдельная беда: в PATH лежит заглушка Microsoft Store —
|
|
1647
|
-
* `python` там есть, он печатает рекламу магазина и выходит с кодом 9009.
|
|
1648
|
-
* Поэтому проверяем не наличие файла, а ответ на вопрос о версии.
|
|
1848
|
+
* ничего. Проверяем не наличие файла, а ответ на вопрос о версии.
|
|
1649
1849
|
*/
|
|
1650
1850
|
async pythonTrouble() {
|
|
1651
1851
|
if (this.pythonChecked !== void 0) return this.pythonChecked;
|
|
@@ -1661,7 +1861,7 @@ var Engine = class {
|
|
|
1661
1861
|
}
|
|
1662
1862
|
} catch {
|
|
1663
1863
|
}
|
|
1664
|
-
this.pythonChecked = "\
|
|
1864
|
+
this.pythonChecked = "\u0421\u0432\u043E\u0435\u0433\u043E \u043F\u0438\u0442\u043E\u043D\u0430 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u043D\u0430 \u044D\u0442\u043E\u043C \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u0435\u0449\u0451 \u043D\u0435\u0442 \u2014 \u043E\u043D \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044F \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 \u0434\u0432\u0438\u0436\u043A\u043E\u043C, \u043E\u0434\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u043E\u0439, \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u0443 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044F.\n\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 setup \u0441 what=all \u2014 \u043F\u043E\u0441\u0442\u0430\u0432\u043B\u044E \u0434\u0432\u0438\u0436\u043E\u043A \u0438 \u0432\u0441\u0451, \u0447\u0442\u043E \u0435\u043C\u0443 \u043D\u0443\u0436\u043D\u043E.";
|
|
1665
1865
|
return this.pythonChecked;
|
|
1666
1866
|
}
|
|
1667
1867
|
// ─── запуск ─────────────────────────────────────────────────────────────
|
|
@@ -13356,6 +13556,9 @@ function candidateVenvTrouble(dir, version2, place, requirePresent = false) {
|
|
|
13356
13556
|
if (venvStat.isSymbolicLink() || !venvStat.isDirectory()) return ".venv \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043E\u0431\u044B\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u043E\u0439";
|
|
13357
13557
|
if (!realpathSync(venv).startsWith(buildReal + sep)) return ".venv \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u0432\u044B\u0448\u0435\u043B \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u0432\u0435\u0440\u0441\u0438\u0438";
|
|
13358
13558
|
const insideBuild = (path2) => path2 === buildReal || path2.startsWith(buildReal + sep);
|
|
13559
|
+
const store = join(dirname(dir), "deps", "python");
|
|
13560
|
+
const storeReal = existsSync(store) ? realpathSync(store) : null;
|
|
13561
|
+
const insideStore = (path2) => storeReal !== null && path2.startsWith(storeReal + sep);
|
|
13359
13562
|
const inspectedDirectories = /* @__PURE__ */ new Set();
|
|
13360
13563
|
const inspectTree = (folder, insideCriticalParent, insideSitePackages) => {
|
|
13361
13564
|
const folderReal = realpathSync(folder);
|
|
@@ -13369,8 +13572,10 @@ function candidateVenvTrouble(dir, version2, place, requirePresent = false) {
|
|
|
13369
13572
|
const inSitePackages = insideSitePackages || entry.name.toLowerCase() === "site-packages";
|
|
13370
13573
|
const stat = lstatSync(path2);
|
|
13371
13574
|
if (stat.isSymbolicLink()) {
|
|
13372
|
-
|
|
13575
|
+
const interpreter = /^(python(?:3(?:\.\d+)?)?|python\.exe)$/i.test(entry.name);
|
|
13576
|
+
if (inCriticalParent || inSitePackages || interpreter) {
|
|
13373
13577
|
const actual = realpathSync(path2);
|
|
13578
|
+
if (!insideBuild(actual) && interpreter && insideStore(actual)) continue;
|
|
13374
13579
|
if (!insideBuild(actual)) return `${path2} \u0432\u0435\u0434\u0451\u0442 \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 ${actual}`;
|
|
13375
13580
|
if (statSync(path2).isDirectory()) {
|
|
13376
13581
|
const trouble = inspectTree(path2, inCriticalParent, inSitePackages);
|
|
@@ -13955,7 +14160,7 @@ function tidyOld2(engine) {
|
|
|
13955
14160
|
}
|
|
13956
14161
|
function candidateDeps(engine) {
|
|
13957
14162
|
const value = engine;
|
|
13958
|
-
return typeof value.home === "function" && typeof value.placeForVersion === "function" && typeof value.
|
|
14163
|
+
return typeof value.home === "function" && typeof value.placeForVersion === "function" && typeof value.bringPython === "function" && typeof value.candidatePython === "function" && typeof value.runWith === "function";
|
|
13959
14164
|
}
|
|
13960
14165
|
async function deploy(engine, manifest, trial = probe, key, hooks = {}) {
|
|
13961
14166
|
const place = engine.place();
|
|
@@ -13998,6 +14203,9 @@ async function deployLocked(engine, manifest, trial, key, hooks) {
|
|
|
13998
14203
|
text: `\u041F\u0430\u043F\u043A\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 ${manifest.version} \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043D\u043E digest \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0438\u043B\u0438 \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043D: \u0447\u0443\u0436\u043E\u0439 final \u043D\u0435 \u043F\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043B \u0438 \u043D\u0435 \u0443\u0434\u0430\u043B\u044F\u043B. \u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0438\u0441\u044B\u0432\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u0432\u044B\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0434\u0440\u0443\u0433\u043E\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0435 \u043F\u043E\u0434 \u043D\u043E\u0432\u044B\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0432\u0435\u0440\u0441\u0438\u0438.`
|
|
13999
14204
|
};
|
|
14000
14205
|
}
|
|
14206
|
+
if (candidate.state === "blocked" && currentVersion(dir) !== manifest.version && pollutedPayload(dest, candidate)) {
|
|
14207
|
+
keepBroken(dir, manifest.version, "\u0424\u0430\u0439\u043B\u044B \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0438\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F \u2014 \u043E\u043F\u0438\u0441\u044C \u0431\u0430\u0439\u0442\u043E\u0432 \u043D\u0435 \u0441\u043E\u0448\u043B\u0430\u0441\u044C; \u0441\u043A\u0430\u0447\u0430\u043D \u0437\u0430\u043D\u043E\u0432\u043E.");
|
|
14208
|
+
}
|
|
14001
14209
|
}
|
|
14002
14210
|
if (!existsSync(dest)) {
|
|
14003
14211
|
const stage = createVersionStage(dir, manifest.version);
|
|
@@ -14124,16 +14332,12 @@ function recoverPublicationLocked(dir) {
|
|
|
14124
14332
|
}
|
|
14125
14333
|
clearPublication(dir, publication.operationId);
|
|
14126
14334
|
}
|
|
14127
|
-
async function continuePreparedCandidate(engine, expected,
|
|
14335
|
+
async function continuePreparedCandidate(engine, expected, trial = probe, extras = "now") {
|
|
14128
14336
|
try {
|
|
14129
14337
|
return await withVersionLock(engine.versionsDir(), async () => {
|
|
14130
|
-
const checked =
|
|
14338
|
+
const checked = preparedCandidateBeforeActivation(engine, expected);
|
|
14131
14339
|
if (!checked.ok) return checked.outcome;
|
|
14132
|
-
|
|
14133
|
-
const after = preparedCandidateAfterBootstrap(engine, checked.candidate);
|
|
14134
|
-
if (!after.ok) return after.outcome;
|
|
14135
|
-
if (!bootstrapped.ok) return bootstrapped;
|
|
14136
|
-
return activatePreparedCandidateLocked(engine, after.candidate, trial, extras);
|
|
14340
|
+
return activatePreparedCandidateLocked(engine, checked.candidate, trial, extras);
|
|
14137
14341
|
});
|
|
14138
14342
|
} catch (trouble) {
|
|
14139
14343
|
if (trouble instanceof VersionLockError) return { ok: false, text: trouble.message };
|
|
@@ -14144,7 +14348,7 @@ async function continuePreparedCandidate(engine, expected, bootstrap, trial = pr
|
|
|
14144
14348
|
};
|
|
14145
14349
|
}
|
|
14146
14350
|
}
|
|
14147
|
-
function
|
|
14351
|
+
function preparedCandidateBeforeActivation(engine, expected) {
|
|
14148
14352
|
const dir = engine.versionsDir();
|
|
14149
14353
|
const candidate = readCandidate(dir);
|
|
14150
14354
|
if (candidate === null || !sameCandidateState(candidate, expected)) {
|
|
@@ -14152,21 +14356,21 @@ function preparedCandidateBeforeBootstrap(engine, expected) {
|
|
|
14152
14356
|
ok: false,
|
|
14153
14357
|
outcome: {
|
|
14154
14358
|
ok: false,
|
|
14155
|
-
text: "\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0439 candidate \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0434\u043E
|
|
14359
|
+
text: "\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0439 candidate \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0434\u043E \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u043B \u0438 \u043D\u0435 \u0437\u0430\u0442\u0438\u0440\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup."
|
|
14156
14360
|
}
|
|
14157
14361
|
};
|
|
14158
14362
|
}
|
|
14159
14363
|
const place = engine.placeForVersion(candidate.version);
|
|
14160
14364
|
if (place === null) {
|
|
14161
|
-
return { ok: false, outcome: blockCandidate(dir, candidate, "\u0423 prepared-\u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435\u0442 engine/console.py \u2014
|
|
14365
|
+
return { ok: false, outcome: blockCandidate(dir, candidate, "\u0423 prepared-\u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435\u0442 engine/console.py \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u043B.") };
|
|
14162
14366
|
}
|
|
14163
14367
|
const proofTrouble = candidateProofTrouble(dir, candidate, place);
|
|
14164
14368
|
if (proofTrouble !== null) {
|
|
14165
|
-
return { ok: false, outcome: blockCandidate(dir, candidate, `${proofTrouble}
|
|
14369
|
+
return { ok: false, outcome: blockCandidate(dir, candidate, `${proofTrouble} \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u043B; current \u043D\u0435 \u043C\u0435\u043D\u044F\u043B.`) };
|
|
14166
14370
|
}
|
|
14167
14371
|
const venvTrouble = candidateVenvTrouble(dir, candidate.version, place, false);
|
|
14168
14372
|
if (venvTrouble !== null) {
|
|
14169
|
-
return { ok: false, outcome: blockCandidate(dir, candidate, `${venvTrouble}
|
|
14373
|
+
return { ok: false, outcome: blockCandidate(dir, candidate, `${venvTrouble} \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u043B; current \u043D\u0435 \u043C\u0435\u043D\u044F\u043B.`) };
|
|
14170
14374
|
}
|
|
14171
14375
|
const current = currentVersion(dir);
|
|
14172
14376
|
if (current !== candidate.baseCurrent) {
|
|
@@ -14174,58 +14378,14 @@ function preparedCandidateBeforeBootstrap(engine, expected) {
|
|
|
14174
14378
|
ok: false,
|
|
14175
14379
|
outcome: {
|
|
14176
14380
|
ok: false,
|
|
14177
|
-
text: `current \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0434\u043E
|
|
14381
|
+
text: `current \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0434\u043E \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F (${candidate.baseCurrent ?? "\u043D\u0435\u0442"} \u2192 ${current ?? "\u043D\u0435\u0442"}) \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u043B \u0438 \u043D\u0435 \u0437\u0430\u0442\u0438\u0440\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u0437\u0430\u043D\u043E\u0432\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0438\u0442\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 setup.`
|
|
14178
14382
|
}
|
|
14179
14383
|
};
|
|
14180
14384
|
}
|
|
14181
14385
|
return { ok: true, candidate, place };
|
|
14182
14386
|
}
|
|
14183
|
-
function
|
|
14184
|
-
|
|
14185
|
-
const candidate = readCandidate(dir);
|
|
14186
|
-
if (candidate === null || !sameCandidateState(candidate, before)) {
|
|
14187
|
-
return {
|
|
14188
|
-
ok: false,
|
|
14189
|
-
outcome: {
|
|
14190
|
-
ok: false,
|
|
14191
|
-
text: "candidate \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0432\u043E \u0432\u0440\u0435\u043C\u044F bootstrap \u2014 \u0447\u0443\u0436\u043E\u0439 \u0443\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C \u043D\u0435 \u0437\u0430\u0442\u0438\u0440\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup."
|
|
14192
|
-
}
|
|
14193
|
-
};
|
|
14194
|
-
}
|
|
14195
|
-
if (currentVersion(dir) !== before.baseCurrent) {
|
|
14196
|
-
return {
|
|
14197
|
-
ok: false,
|
|
14198
|
-
outcome: {
|
|
14199
|
-
ok: false,
|
|
14200
|
-
text: "current \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0432\u043E \u0432\u0440\u0435\u043C\u044F bootstrap \u2014 \u0447\u0443\u0436\u043E\u0439 current \u043D\u0435 \u0437\u0430\u0442\u0438\u0440\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup."
|
|
14201
|
-
}
|
|
14202
|
-
};
|
|
14203
|
-
}
|
|
14204
|
-
const place = engine.placeForVersion(candidate.version);
|
|
14205
|
-
if (place === null) {
|
|
14206
|
-
return {
|
|
14207
|
-
ok: false,
|
|
14208
|
-
outcome: {
|
|
14209
|
-
ok: false,
|
|
14210
|
-
text: "\u041F\u0443\u0442\u044C prepared-\u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0432\u043E \u0432\u0440\u0435\u043C\u044F bootstrap \u2014 current \u043D\u0435 \u043C\u0435\u043D\u044F\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup."
|
|
14211
|
-
}
|
|
14212
|
-
};
|
|
14213
|
-
}
|
|
14214
|
-
const proofTrouble = candidateProofTrouble(dir, candidate, place);
|
|
14215
|
-
const venvTrouble = candidateVenvTrouble(dir, candidate.version, place, false);
|
|
14216
|
-
if (proofTrouble !== null || venvTrouble !== null) {
|
|
14217
|
-
return {
|
|
14218
|
-
ok: false,
|
|
14219
|
-
outcome: {
|
|
14220
|
-
ok: false,
|
|
14221
|
-
text: `${proofTrouble ?? venvTrouble} \u043F\u043E\u0441\u043B\u0435 bootstrap \u2014 candidate \u0438 current \u043D\u0435 \u0437\u0430\u0442\u0438\u0440\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup \u043F\u043E\u0441\u043B\u0435 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u0444\u0430\u0439\u043B\u043E\u0432 \u043D\u0430 \u0434\u0438\u0441\u043A\u0435.`
|
|
14222
|
-
}
|
|
14223
|
-
};
|
|
14224
|
-
}
|
|
14225
|
-
return { ok: true, candidate, place };
|
|
14226
|
-
}
|
|
14227
|
-
function blockCandidate(dir, candidate, text2) {
|
|
14228
|
-
if (!sameCandidateState(readCandidate(dir), candidate)) {
|
|
14387
|
+
function blockCandidate(dir, candidate, text2) {
|
|
14388
|
+
if (!sameCandidateState(readCandidate(dir), candidate)) {
|
|
14229
14389
|
return {
|
|
14230
14390
|
ok: false,
|
|
14231
14391
|
text: "\u0423\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C candidate \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0441\u044F \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u2014 \u0447\u0443\u0436\u043E\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u044B\u0432\u0430\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup."
|
|
@@ -14238,7 +14398,7 @@ function blockCandidate(dir, candidate, text2) {
|
|
|
14238
14398
|
text: text2.includes("\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C:") ? `${lead}
|
|
14239
14399
|
${text2}` : `${lead}
|
|
14240
14400
|
${text2}
|
|
14241
|
-
\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \
|
|
14401
|
+
\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043C\u043E\u043D\u0442\u0438\u0440\u0443\u0439 \u043D\u0430 \u043F\u0440\u0435\u0436\u043D\u0435\u0439. \u0421\u0440\u0430\u0437\u0443 setup \u043D\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0439 \u2014 \u043E\u0442\u043A\u0430\u0436\u0435\u0442 \u0442\u0435\u043C \u0436\u0435; \xAB\u043E\u0431\u043D\u043E\u0432\u0438\xBB \u0435\u0449\u0451 \u0440\u0430\u0437 \u2014 \u043F\u043E\u0437\u0436\u0435 \u0438\u043B\u0438 \u043A\u043E\u0433\u0434\u0430 \u0432\u044B\u0439\u0434\u0435\u0442 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0430\u044F \u0432\u0435\u0440\u0441\u0438\u044F.`
|
|
14242
14402
|
};
|
|
14243
14403
|
}
|
|
14244
14404
|
function commandWords(trouble) {
|
|
@@ -14259,12 +14419,25 @@ function candidateProofTrouble(dir, candidate, place) {
|
|
|
14259
14419
|
if (pathTrouble !== null) return pathTrouble;
|
|
14260
14420
|
try {
|
|
14261
14421
|
const actual = payloadProof(join(dir, candidate.version));
|
|
14262
|
-
if (!samePayloadProof(candidate.payload, actual))
|
|
14422
|
+
if (!samePayloadProof(candidate.payload, actual)) {
|
|
14423
|
+
const said = "\u0424\u0430\u0439\u043B\u044B \u043D\u043E\u0432\u043E\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u0438\u0441\u044C \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F (\u043E\u043F\u0438\u0441\u044C \u0431\u0430\u0439\u0442\u043E\u0432 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435 \u0441\u043E\u0448\u043B\u0430\u0441\u044C).";
|
|
14424
|
+
noteInstallFault("candidate-payload", new Error(said));
|
|
14425
|
+
return said;
|
|
14426
|
+
}
|
|
14263
14427
|
} catch (trouble) {
|
|
14264
|
-
return `\u0424\u0430\
|
|
14428
|
+
return `\u0424\u0430\u0439\u043B\u044B \u043D\u043E\u0432\u043E\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C (\u043E\u043F\u0438\u0441\u044C \u0431\u0430\u0439\u0442\u043E\u0432 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430): ${describeFailure(trouble)}`;
|
|
14265
14429
|
}
|
|
14266
14430
|
return null;
|
|
14267
14431
|
}
|
|
14432
|
+
function pollutedPayload(dest, candidate) {
|
|
14433
|
+
if (candidate.payload === void 0) return false;
|
|
14434
|
+
try {
|
|
14435
|
+
removePythonBytecode(dest);
|
|
14436
|
+
return !samePayloadProof(candidate.payload, payloadProof(dest));
|
|
14437
|
+
} catch {
|
|
14438
|
+
return false;
|
|
14439
|
+
}
|
|
14440
|
+
}
|
|
14268
14441
|
function samePreparedCandidate(actual, expected) {
|
|
14269
14442
|
return actual !== null && actual.version === expected.version && actual.sha256 === expected.sha256 && actual.state === "prepared" && actual.baseCurrent === expected.baseCurrent && actual.environment === expected.environment && actual.mineDigest === expected.mineDigest && actual.payload !== void 0 && expected.payload !== void 0 && samePayloadProof(actual.payload, expected.payload);
|
|
14270
14443
|
}
|
|
@@ -14285,71 +14458,6 @@ async function runCandidateWith(engine, dir, version2, executable, place, args,
|
|
|
14285
14458
|
removePythonBytecode(join(dir, version2));
|
|
14286
14459
|
return result;
|
|
14287
14460
|
}
|
|
14288
|
-
async function prepareCopiedCandidateVenv(engine, dir, version2, place) {
|
|
14289
|
-
const trouble = candidateVenvTrouble(dir, version2, place, false);
|
|
14290
|
-
if (trouble !== null) throw new Error(trouble);
|
|
14291
|
-
const venv = join(place.pack, ".venv");
|
|
14292
|
-
const existingPython = engine.candidatePython(place);
|
|
14293
|
-
const ready = existingPython !== null && await candidatePipReady(engine, existingPython);
|
|
14294
|
-
if (!ready) {
|
|
14295
|
-
rmSync(venv, { recursive: true, force: true });
|
|
14296
|
-
if (engine.prepareCandidateVenv !== void 0) {
|
|
14297
|
-
await engine.prepareCandidateVenv(place);
|
|
14298
|
-
} else {
|
|
14299
|
-
await copiedVenv(engine, venv);
|
|
14300
|
-
}
|
|
14301
|
-
}
|
|
14302
|
-
const createdTrouble = candidateVenvTrouble(dir, version2, place, true);
|
|
14303
|
-
if (createdTrouble !== null) throw new Error(createdTrouble);
|
|
14304
|
-
const python = engine.candidatePython(place);
|
|
14305
|
-
if (python === null || !await candidatePipReady(engine, python)) {
|
|
14306
|
-
throw new Error("\u0448\u0442\u0430\u0442\u043D\u044B\u0439 .venv \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D \u0431\u0435\u0437 \u0440\u0430\u0431\u043E\u0447\u0435\u0433\u043E pip");
|
|
14307
|
-
}
|
|
14308
|
-
}
|
|
14309
|
-
var SYMLINKS_ONLY = "cannot create venvs without using symlinks";
|
|
14310
|
-
async function copiedVenv(engine, venv) {
|
|
14311
|
-
const { execFile: execFile4 } = await import('child_process');
|
|
14312
|
-
const { promisify: promisify3 } = await import('util');
|
|
14313
|
-
const pythons = engine.bootstrapPythons?.() ?? [engine.bootstrapPython()];
|
|
14314
|
-
const refusals = [];
|
|
14315
|
-
for (const python of pythons) {
|
|
14316
|
-
try {
|
|
14317
|
-
await promisify3(execFile4)(python, ["-m", "venv", "--copies", venv], {
|
|
14318
|
-
timeout: 10 * 6e4,
|
|
14319
|
-
encoding: "utf8",
|
|
14320
|
-
env: { ...engine.pythonEnv(), PYTHONDONTWRITEBYTECODE: "1" }
|
|
14321
|
-
});
|
|
14322
|
-
return;
|
|
14323
|
-
} catch (trouble) {
|
|
14324
|
-
rmSync(venv, { recursive: true, force: true });
|
|
14325
|
-
const said = `${String(trouble.stderr ?? "")} ${describeFailure(trouble)}`;
|
|
14326
|
-
refusals.push(said.includes(SYMLINKS_ONLY) ? `${python}: \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u0442\u043E\u043B\u044C\u043A\u043E \u0441\u0441\u044B\u043B\u043A\u0430\u043C\u0438` : `${python}: ${lastLine(said.trim())}`);
|
|
14327
|
-
}
|
|
14328
|
-
}
|
|
14329
|
-
throw new Error(
|
|
14330
|
-
`\u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043D\u043E\u0432\u043E\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u043C \u2014 ${refusals.join("; ")}. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0441\u0442\u0430\u0432\u044C Python \u0441 python.org/downloads \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438 \xAB\u043E\u0431\u043D\u043E\u0432\u0438\xBB.`
|
|
14331
|
-
);
|
|
14332
|
-
}
|
|
14333
|
-
async function candidatePipReady(engine, python) {
|
|
14334
|
-
if (engine.candidatePipReady !== void 0) return engine.candidatePipReady(python);
|
|
14335
|
-
const { execFile: execFile4 } = await import('child_process');
|
|
14336
|
-
const { promisify: promisify3 } = await import('util');
|
|
14337
|
-
const env = { ...engine.pythonEnv(), PYTHONDONTWRITEBYTECODE: "1" };
|
|
14338
|
-
delete env["PYTHONHOME"];
|
|
14339
|
-
delete env["PYTHONPATH"];
|
|
14340
|
-
delete env["VIRTUAL_ENV"];
|
|
14341
|
-
delete env["__PYVENV_LAUNCHER__"];
|
|
14342
|
-
try {
|
|
14343
|
-
await promisify3(execFile4)(python, ["-B", "-m", "pip", "--version"], {
|
|
14344
|
-
timeout: 6e4,
|
|
14345
|
-
encoding: "utf8",
|
|
14346
|
-
env
|
|
14347
|
-
});
|
|
14348
|
-
return true;
|
|
14349
|
-
} catch {
|
|
14350
|
-
return false;
|
|
14351
|
-
}
|
|
14352
|
-
}
|
|
14353
14461
|
async function compatibilityProof(engine, dir, version2, python, place) {
|
|
14354
14462
|
let output = "";
|
|
14355
14463
|
try {
|
|
@@ -14412,24 +14520,12 @@ async function activatePreparedCandidateLocked(engine, manifest, trial, extras =
|
|
|
14412
14520
|
const resumesReadyBeforeCurrent = candidate.state === "ready" && current !== candidate.version;
|
|
14413
14521
|
if (candidate.environment !== "ready" || resumesReadyBeforeCurrent) {
|
|
14414
14522
|
try {
|
|
14415
|
-
|
|
14416
|
-
await runCandidateWith(
|
|
14417
|
-
engine,
|
|
14418
|
-
dir,
|
|
14419
|
-
candidate.version,
|
|
14420
|
-
engine.bootstrapPython(),
|
|
14421
|
-
place,
|
|
14422
|
-
["env-install", "--pack", place.pack, "--step", "ffmpeg", "--consent"],
|
|
14423
|
-
{ timeout: 60 * 6e4 },
|
|
14424
|
-
false
|
|
14425
|
-
);
|
|
14426
|
-
}
|
|
14427
|
-
await prepareCopiedCandidateVenv(engine, dir, candidate.version, place);
|
|
14523
|
+
const base = await engine.bringPython(place);
|
|
14428
14524
|
await runCandidateWith(
|
|
14429
14525
|
engine,
|
|
14430
14526
|
dir,
|
|
14431
14527
|
candidate.version,
|
|
14432
|
-
|
|
14528
|
+
base,
|
|
14433
14529
|
place,
|
|
14434
14530
|
[
|
|
14435
14531
|
"env-install",
|
|
@@ -14441,7 +14537,7 @@ async function activatePreparedCandidateLocked(engine, manifest, trial, extras =
|
|
|
14441
14537
|
...extras === "later" ? requiredOnly(dir, candidate.version) : []
|
|
14442
14538
|
],
|
|
14443
14539
|
{ timeout: 60 * 6e4 },
|
|
14444
|
-
|
|
14540
|
+
false
|
|
14445
14541
|
);
|
|
14446
14542
|
const installedVenvTrouble = candidateVenvTrouble(dir, candidate.version, place, true);
|
|
14447
14543
|
if (installedVenvTrouble !== null) throw new Error(installedVenvTrouble);
|
|
@@ -14654,9 +14750,9 @@ async function dryRun(engine, build, expected, trial) {
|
|
|
14654
14750
|
}
|
|
14655
14751
|
}
|
|
14656
14752
|
async function probe(engine, consolePy) {
|
|
14657
|
-
const { execFile:
|
|
14658
|
-
const { promisify:
|
|
14659
|
-
return
|
|
14753
|
+
const { execFile: execFile3 } = await import('child_process');
|
|
14754
|
+
const { promisify: promisify2 } = await import('util');
|
|
14755
|
+
return promisify2(execFile3)(engine.enginePython(), [consolePy, "version"], {
|
|
14660
14756
|
timeout: 6e4,
|
|
14661
14757
|
encoding: "utf8",
|
|
14662
14758
|
env: engine.pythonEnv()
|
|
@@ -14697,212 +14793,6 @@ function rollback(engine) {
|
|
|
14697
14793
|
};
|
|
14698
14794
|
}
|
|
14699
14795
|
}
|
|
14700
|
-
var DeliveryError = class extends Error {
|
|
14701
|
-
constructor(message) {
|
|
14702
|
-
super(message);
|
|
14703
|
-
this.name = "DeliveryTrouble";
|
|
14704
|
-
}
|
|
14705
|
-
};
|
|
14706
|
-
async function downloadFile(opts) {
|
|
14707
|
-
const { url: url2, dest, sha256, bytes, timeoutMs = 30 * 6e4, report, key } = opts;
|
|
14708
|
-
if (!/^[a-f0-9]{64}$/.test(sha256)) {
|
|
14709
|
-
throw new DeliveryError(`\u043D\u0435\u0447\u0435\u043C \u0441\u0432\u0435\u0440\u0438\u0442\u044C \u0441\u043A\u0430\u0447\u0430\u043D\u043D\u043E\u0435: \u0441\u0443\u043C\u043C\u0430 \xAB${sha256}\xBB \u043D\u0435 \u043F\u043E\u0445\u043E\u0436\u0430 \u043D\u0430 sha256`);
|
|
14710
|
-
}
|
|
14711
|
-
mkdirSync(dirname(dest), { recursive: true });
|
|
14712
|
-
const temp = `${dest}.downloading-${process.pid}-${randomUUID()}`;
|
|
14713
|
-
const guard = new AbortController();
|
|
14714
|
-
const timer = setTimeout(() => {
|
|
14715
|
-
guard.abort();
|
|
14716
|
-
}, timeoutMs);
|
|
14717
|
-
try {
|
|
14718
|
-
const response = await fetch(url2, {
|
|
14719
|
-
signal: guard.signal,
|
|
14720
|
-
redirect: "follow",
|
|
14721
|
-
...key !== null && key !== void 0 ? { headers: { authorization: `Bearer ${key}` } } : {}
|
|
14722
|
-
});
|
|
14723
|
-
const hasKey = key !== null && key !== void 0;
|
|
14724
|
-
if (!response.ok) {
|
|
14725
|
-
if (response.status === 401 || response.status === 403) {
|
|
14726
|
-
if (response.status === 403 && hasKey) {
|
|
14727
|
-
throw new DeliveryError(
|
|
14728
|
-
`${url2} \u043D\u0435 \u043E\u0442\u0434\u0430\u0451\u0442 \u0444\u0430\u0439\u043B: \u043A\u043B\u044E\u0447 \u043F\u0440\u0438\u0437\u043D\u0430\u043D, \u043D\u043E \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438 \u043D\u0430 \u043C\u043E\u043D\u0442\u0430\u0436 \u043D\u0435\u0442. \u0421\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435 \u043D\u043E\u0432\u043E\u0433\u043E \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E, \u043F\u043E\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u0430\u043A\u0442\u0438\u0432\u043D\u0430; \u0432\u0441\u0451, \u0447\u0442\u043E \u0443\u0436\u0435 \u0441\u0442\u043E\u0438\u0442 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435, \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C. \u041F\u0440\u043E\u0434\u043B\u0438\u0442\u0435 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0443 \u0432 \u0431\u043E\u0442\u0435 \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`
|
|
14729
|
-
);
|
|
14730
|
-
}
|
|
14731
|
-
throw new DeliveryError(
|
|
14732
|
-
!hasKey ? `${url2} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043A\u043B\u044E\u0447 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430, \u0430 \u043E\u043D \u043D\u0435 \u0437\u0430\u0434\u0430\u043D. \u0412\u043F\u0438\u0448\u0438\u0442\u0435 \u043A\u043B\u044E\u0447 \u0432 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044E MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u0441\u0435\u043A\u0446\u0438\u044F env) \u0438 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0443 \u2014 \u041A\u043B\u043E\u0434\u0430 \u0438\u043B\u0438 Codex.` : `${url2} \u043D\u0435 \u043F\u0440\u0438\u043D\u044F\u043B \u043A\u043B\u044E\u0447 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430 (${response.status}). \u0421\u043A\u043E\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u043A\u043B\u044E\u0447 \u0437\u0430\u043C\u0435\u043D\u0451\u043D \u0431\u043E\u043B\u0435\u0435 \u043D\u043E\u0432\u044B\u043C: \u043D\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B \u0438\u0437 \u0431\u043E\u0442\u0430 \u0443\u0436\u0435 \u043F\u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D \u0437\u0434\u0435\u0441\u044C \u0438\u043B\u0438 \u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u043C \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435. \u0412\u043E\u0437\u044C\u043C\u0438\u0442\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0444\u0430\u0439\u043B \u0443 \u0431\u043E\u0442\u0430 ${KEY_SOURCE_BOT} \u0438 \u043F\u043E\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u0435\u0433\u043E.`
|
|
14733
|
-
);
|
|
14734
|
-
}
|
|
14735
|
-
throw new DeliveryError(`${url2} \u043E\u0442\u0432\u0435\u0442\u0438\u043B ${response.status} ${response.statusText}`);
|
|
14736
|
-
}
|
|
14737
|
-
const body = await response.arrayBuffer();
|
|
14738
|
-
const buffer = Buffer.from(body);
|
|
14739
|
-
const sum = createHash("sha256").update(buffer).digest("hex");
|
|
14740
|
-
if (bytes !== void 0 && buffer.length !== bytes) {
|
|
14741
|
-
throw new DeliveryError(
|
|
14742
|
-
looksLikeHtml(buffer) ? `\u043F\u043E \u0430\u0434\u0440\u0435\u0441\u0443 ${url2} \u043B\u0435\u0436\u0438\u0442 \u043D\u0435 \u0430\u0440\u0445\u0438\u0432, \u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u2014 \u0444\u0430\u0439\u043B \u0435\u0449\u0451 \u043D\u0435 \u0432\u044B\u043B\u043E\u0436\u0435\u043D.` : `\u0441\u043A\u0430\u0447\u0430\u043B\u043E\u0441\u044C ${buffer.length} \u0431\u0430\u0439\u0442 \u0432\u043C\u0435\u0441\u0442\u043E ${bytes} \u2014 \u0441\u0432\u044F\u0437\u044C \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u0430\u0441\u044C, \u043F\u043E\u0432\u0442\u043E\u0440\u0438.`
|
|
14743
|
-
);
|
|
14744
|
-
}
|
|
14745
|
-
if (sum !== sha256) {
|
|
14746
|
-
throw new DeliveryError(
|
|
14747
|
-
looksLikeHtml(buffer) ? `\u043F\u043E \u0430\u0434\u0440\u0435\u0441\u0443 ${url2} \u043B\u0435\u0436\u0438\u0442 \u043D\u0435 \u0430\u0440\u0445\u0438\u0432, \u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u2014 \u0444\u0430\u0439\u043B \u0435\u0449\u0451 \u043D\u0435 \u0432\u044B\u043B\u043E\u0436\u0435\u043D.` : `\u0441\u043A\u0430\u0447\u0430\u043D\u043D\u043E\u0435 \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u043B\u043E \u0441 \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u043E\u0439 \u0441\u0443\u043C\u043C\u043E\u0439.
|
|
14748
|
-
\u0436\u0434\u0430\u043B\u0438 ${sha256}
|
|
14749
|
-
\u0432\u044B\u0448\u043B\u043E ${sum}
|
|
14750
|
-
\u041F\u043E\u0432\u0442\u043E\u0440\u0438; \u0435\u0441\u043B\u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0435\u0442\u0441\u044F \u2014 \u0444\u0430\u0439\u043B \u043F\u043E\u0434\u043C\u0435\u043D\u0451\u043D \u0438\u043B\u0438 \u0431\u0438\u0442\u044B\u0439, \u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0435\u0433\u043E \u043D\u0435\u043B\u044C\u0437\u044F.`
|
|
14751
|
-
);
|
|
14752
|
-
}
|
|
14753
|
-
writeFileSync(temp, buffer);
|
|
14754
|
-
if (existsSync(dest)) {
|
|
14755
|
-
throw new DeliveryError(
|
|
14756
|
-
`\u0444\u0430\u0439\u043B ${dest} \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u043B \u0434\u0440\u0443\u0433\u043E\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u2014 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0443\u0434\u0430\u043B\u044F\u043B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0441 \u043D\u043E\u0432\u044B\u043C staging.`
|
|
14757
|
-
);
|
|
14758
|
-
}
|
|
14759
|
-
renameSync(temp, dest);
|
|
14760
|
-
report?.(`\u0441\u043A\u0430\u0447\u0430\u043D\u043E ${Math.round(buffer.length / 1024 / 1024)} \u041C\u0411`);
|
|
14761
|
-
return { file: dest, bytes: buffer.length, sha256: sum };
|
|
14762
|
-
} catch (trouble) {
|
|
14763
|
-
rmSync(temp, { force: true });
|
|
14764
|
-
if (trouble instanceof DeliveryError) throw trouble;
|
|
14765
|
-
if (guard.signal.aborted) {
|
|
14766
|
-
throw new DeliveryError(`${url2} \u043D\u0435 \u043E\u0442\u0434\u0430\u043B \u0444\u0430\u0439\u043B \u0437\u0430 ${Math.round(timeoutMs / 6e4)} \u043C\u0438\u043D.`);
|
|
14767
|
-
}
|
|
14768
|
-
throw new DeliveryError(`\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u043A\u0430\u0447\u0430\u0442\u044C ${url2}: ${describeFailure(trouble)}`);
|
|
14769
|
-
} finally {
|
|
14770
|
-
clearTimeout(timer);
|
|
14771
|
-
}
|
|
14772
|
-
}
|
|
14773
|
-
function looksLikeHtml(buffer) {
|
|
14774
|
-
const start = buffer.subarray(0, 200).toString("latin1").trimStart().toLowerCase();
|
|
14775
|
-
return start.startsWith("<!doctype html") || start.startsWith("<html");
|
|
14776
|
-
}
|
|
14777
|
-
var BLOCK = 512;
|
|
14778
|
-
function tarEntries(data) {
|
|
14779
|
-
const entries = [];
|
|
14780
|
-
let offset = 0;
|
|
14781
|
-
let longName = null;
|
|
14782
|
-
let longTarget = null;
|
|
14783
|
-
while (offset + BLOCK <= data.length) {
|
|
14784
|
-
const header = data.subarray(offset, offset + BLOCK);
|
|
14785
|
-
if (header.every((b) => b === 0)) break;
|
|
14786
|
-
const name = fieldLine(header, 0, 100);
|
|
14787
|
-
const mode = octal(header, 100, 8);
|
|
14788
|
-
const size = fieldSize(header, 124, 12);
|
|
14789
|
-
const type = String.fromCharCode(header[156]);
|
|
14790
|
-
const target = fieldLine(header, 157, 100);
|
|
14791
|
-
const prefix = fieldLine(header, 345, 155);
|
|
14792
|
-
offset += BLOCK;
|
|
14793
|
-
const body = data.subarray(offset, offset + size);
|
|
14794
|
-
offset += Math.ceil(size / BLOCK) * BLOCK;
|
|
14795
|
-
if (type === "L") {
|
|
14796
|
-
longName = body.toString("utf8").replace(/\0+$/, "");
|
|
14797
|
-
continue;
|
|
14798
|
-
}
|
|
14799
|
-
if (type === "K") {
|
|
14800
|
-
longTarget = body.toString("utf8").replace(/\0+$/, "");
|
|
14801
|
-
continue;
|
|
14802
|
-
}
|
|
14803
|
-
if (type === "x") {
|
|
14804
|
-
const fields = parsePax(body);
|
|
14805
|
-
if (fields["path"] !== void 0) longName = fields["path"];
|
|
14806
|
-
if (fields["linkpath"] !== void 0) longTarget = fields["linkpath"];
|
|
14807
|
-
continue;
|
|
14808
|
-
}
|
|
14809
|
-
if (type === "g") continue;
|
|
14810
|
-
const full = longName ?? (prefix !== "" ? `${prefix}/${name}` : name);
|
|
14811
|
-
const linkTarget = longTarget ?? target;
|
|
14812
|
-
longName = null;
|
|
14813
|
-
longTarget = null;
|
|
14814
|
-
const kind = type === "5" ? "dir" : type === "2" ? "symlink" : type === "1" ? "hardlink" : "file";
|
|
14815
|
-
if (type !== "" && type !== "0" && type !== "\0" && kind === "file" && type !== "7") continue;
|
|
14816
|
-
entries.push({ name: full, kind, mode, body, target: linkTarget });
|
|
14817
|
-
}
|
|
14818
|
-
return entries;
|
|
14819
|
-
}
|
|
14820
|
-
function parsePax(body) {
|
|
14821
|
-
const fields = {};
|
|
14822
|
-
let offset = 0;
|
|
14823
|
-
while (offset < body.length) {
|
|
14824
|
-
const space = body.indexOf(32, offset);
|
|
14825
|
-
if (space === -1) break;
|
|
14826
|
-
const length = Number.parseInt(body.subarray(offset, space).toString("ascii"), 10);
|
|
14827
|
-
if (!Number.isFinite(length) || length <= 0 || offset + length > body.length) break;
|
|
14828
|
-
const entry = body.subarray(space + 1, offset + length).toString("utf8").replace(/\n$/, "");
|
|
14829
|
-
const equal = entry.indexOf("=");
|
|
14830
|
-
if (equal > 0) fields[entry.slice(0, equal)] = entry.slice(equal + 1);
|
|
14831
|
-
offset += length;
|
|
14832
|
-
}
|
|
14833
|
-
return fields;
|
|
14834
|
-
}
|
|
14835
|
-
function fieldLine(header, start, length) {
|
|
14836
|
-
const chunk = header.subarray(start, start + length);
|
|
14837
|
-
const end = chunk.indexOf(0);
|
|
14838
|
-
return chunk.subarray(0, end === -1 ? chunk.length : end).toString("utf8");
|
|
14839
|
-
}
|
|
14840
|
-
function octal(header, start, length) {
|
|
14841
|
-
const text2 = fieldLine(header, start, length).trim();
|
|
14842
|
-
const ch = Number.parseInt(text2, 8);
|
|
14843
|
-
return Number.isFinite(ch) ? ch : 0;
|
|
14844
|
-
}
|
|
14845
|
-
function fieldSize(header, start, length) {
|
|
14846
|
-
if ((header[start] & 128) !== 0) {
|
|
14847
|
-
let ch = 0;
|
|
14848
|
-
for (let i = start + 1; i < start + length; i += 1) ch = ch * 256 + header[i];
|
|
14849
|
-
return ch;
|
|
14850
|
-
}
|
|
14851
|
-
return octal(header, start, length);
|
|
14852
|
-
}
|
|
14853
|
-
function inside(root, path2) {
|
|
14854
|
-
if (path2 === "" || path2.startsWith("/") || path2.startsWith("\\")) return false;
|
|
14855
|
-
if (/^[A-Za-z]:/.test(path2)) return false;
|
|
14856
|
-
const target = resolve(root, path2);
|
|
14857
|
-
const bottom = resolve(root);
|
|
14858
|
-
return target === bottom || target.startsWith(bottom + sep);
|
|
14859
|
-
}
|
|
14860
|
-
function unpackArchive(archive, dest) {
|
|
14861
|
-
const entries = tarEntries(gunzipSync(readFileSync(archive)));
|
|
14862
|
-
if (entries.length === 0) throw new DeliveryError(`\u0430\u0440\u0445\u0438\u0432 ${archive} \u043F\u0443\u0441\u0442 \u2014 \u0440\u0430\u0441\u043F\u0430\u043A\u043E\u0432\u044B\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E`);
|
|
14863
|
-
for (const entry of entries) {
|
|
14864
|
-
if (!inside(dest, entry.name)) throw escapesRoot(archive, entry.name);
|
|
14865
|
-
if (entry.kind === "symlink" || entry.kind === "hardlink") {
|
|
14866
|
-
if (entry.target.startsWith("/") || entry.target.startsWith("\\") || /^[A-Za-z]:/.test(entry.target)) {
|
|
14867
|
-
throw escapesRoot(archive, `${entry.name} \u2192 ${entry.target}`);
|
|
14868
|
-
}
|
|
14869
|
-
const from = entry.kind === "hardlink" ? entry.target : join(dirname(entry.name), entry.target);
|
|
14870
|
-
if (!inside(dest, from)) throw escapesRoot(archive, `${entry.name} \u2192 ${entry.target}`);
|
|
14871
|
-
}
|
|
14872
|
-
}
|
|
14873
|
-
for (const entry of entries) {
|
|
14874
|
-
const path2 = join(dest, entry.name);
|
|
14875
|
-
if (entry.kind === "dir") {
|
|
14876
|
-
mkdirSync(path2, { recursive: true });
|
|
14877
|
-
continue;
|
|
14878
|
-
}
|
|
14879
|
-
mkdirSync(dirname(path2), { recursive: true });
|
|
14880
|
-
if (entry.kind === "symlink") {
|
|
14881
|
-
rmSync(path2, { force: true });
|
|
14882
|
-
symlinkSync(entry.target, path2);
|
|
14883
|
-
continue;
|
|
14884
|
-
}
|
|
14885
|
-
if (entry.kind === "hardlink") {
|
|
14886
|
-
writeFileSync(path2, readFileSync(join(dest, entry.target)));
|
|
14887
|
-
continue;
|
|
14888
|
-
}
|
|
14889
|
-
writeFileSync(path2, entry.body);
|
|
14890
|
-
if ((entry.mode & 73) !== 0) chmodSync(path2, entry.mode & 511);
|
|
14891
|
-
}
|
|
14892
|
-
}
|
|
14893
|
-
function escapesRoot(archive, name) {
|
|
14894
|
-
return new DeliveryError(
|
|
14895
|
-
`\u0430\u0440\u0445\u0438\u0432 ${archive} \u043F\u044B\u0442\u0430\u0435\u0442\u0441\u044F \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0444\u0430\u0439\u043B \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u043F\u0430\u043F\u043A\u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438: \xAB${name}\xBB.
|
|
14896
|
-
\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0440\u0430\u0441\u043F\u0430\u043A\u043E\u0432\u0430\u043D\u043E. \u0421\u043A\u0430\u0447\u0430\u0439 \u0437\u0430\u043D\u043E\u0432\u043E \u2014 \u0432\u0435\u0440\u043E\u044F\u0442\u043D\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u0444\u0430\u0439\u043B \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0451\u043D \u0438\u043B\u0438 \u043F\u043E\u0434\u043C\u0435\u043D\u0451\u043D.`
|
|
14897
|
-
);
|
|
14898
|
-
}
|
|
14899
|
-
function dirExists(path2) {
|
|
14900
|
-
try {
|
|
14901
|
-
return statSync(path2).isDirectory();
|
|
14902
|
-
} catch {
|
|
14903
|
-
return false;
|
|
14904
|
-
}
|
|
14905
|
-
}
|
|
14906
14796
|
var BODY_ENTRY = "cli.js";
|
|
14907
14797
|
var BODY_MANIFEST = "shell.json";
|
|
14908
14798
|
function shellDir(home) {
|
|
@@ -15085,50 +14975,100 @@ function removePublication(dir, version2) {
|
|
|
15085
14975
|
function publicationMatchesManifest(publication, manifest) {
|
|
15086
14976
|
return publication.version === manifest.version && publication.artifactSha256 === manifest.body?.sha256 && publication.artifactBytes === manifest.body.bytes;
|
|
15087
14977
|
}
|
|
14978
|
+
var PROBE_TIMEOUT_MS = 6e4;
|
|
14979
|
+
var REQUIRED_TOOLS = ["setup", "render", "wait"];
|
|
14980
|
+
var PROBE_THREAD = `
|
|
14981
|
+
const { parentPort, workerData } = require('node:worker_threads')
|
|
14982
|
+
import(workerData.entry).then((body) => {
|
|
14983
|
+
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()')
|
|
14984
|
+
return body.start()
|
|
14985
|
+
}).catch((trouble) => {
|
|
14986
|
+
parentPort.postMessage(trouble instanceof Error
|
|
14987
|
+
? { message: trouble.name + ': ' + String(trouble.message).split('\\n')[0], stack: String(trouble.stack || '') }
|
|
14988
|
+
: { message: String(trouble), stack: '' })
|
|
14989
|
+
})
|
|
14990
|
+
`;
|
|
15088
14991
|
var probeShell = async (entry) => {
|
|
15089
14992
|
const probeHome = mkdtempSync(join(tmpdir(), "naparnik-shell-probe-"));
|
|
15090
|
-
const env = {
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
14993
|
+
const env = {};
|
|
14994
|
+
for (const [name, value] of Object.entries(process.env)) {
|
|
14995
|
+
if (value !== void 0 && name !== "NAPARNIK_API_KEY") env[name] = value;
|
|
14996
|
+
}
|
|
14997
|
+
Object.assign(env, { NAPARNIK_HOME: probeHome, NAPARNIK_NO_BODY: "1", NAPARNIK_NO_UPDATE: "1" });
|
|
14998
|
+
const thread = new Worker(PROBE_THREAD, {
|
|
14999
|
+
eval: true,
|
|
15000
|
+
argv: [],
|
|
15001
|
+
env,
|
|
15002
|
+
stdin: true,
|
|
15003
|
+
stdout: true,
|
|
15004
|
+
stderr: true,
|
|
15005
|
+
workerData: { entry: pathToFileURL(entry).href }
|
|
15006
|
+
});
|
|
15096
15007
|
try {
|
|
15097
|
-
const
|
|
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 });
|
|
15008
|
+
const named = await new Promise((resolve5, reject) => {
|
|
15104
15009
|
let output = "";
|
|
15105
15010
|
let errors = "";
|
|
15106
15011
|
let finished = false;
|
|
15107
|
-
const timer = setTimeout(
|
|
15108
|
-
|
|
15012
|
+
const timer = setTimeout(
|
|
15013
|
+
() => 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`)),
|
|
15014
|
+
PROBE_TIMEOUT_MS
|
|
15015
|
+
);
|
|
15016
|
+
const finish = (trouble, said) => {
|
|
15109
15017
|
if (finished) return;
|
|
15110
15018
|
finished = true;
|
|
15111
15019
|
clearTimeout(timer);
|
|
15112
|
-
|
|
15113
|
-
if (trouble === void 0) resolve5();
|
|
15020
|
+
if (trouble === null) resolve5(said ?? "");
|
|
15114
15021
|
else reject(trouble);
|
|
15115
15022
|
};
|
|
15116
15023
|
const send = (message) => {
|
|
15117
|
-
|
|
15024
|
+
thread.stdin?.write(`${JSON.stringify(message)}
|
|
15118
15025
|
`);
|
|
15119
15026
|
};
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15027
|
+
const failure = (text2, stack = "") => {
|
|
15028
|
+
const trouble = new Error(text2);
|
|
15029
|
+
const said = errors.trim();
|
|
15030
|
+
trouble.stack = [text2, stack, said === "" ? "" : `stderr \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430:
|
|
15031
|
+
${said.slice(-4e3)}`].filter((part) => part !== "").join("\n");
|
|
15032
|
+
return trouble;
|
|
15033
|
+
};
|
|
15034
|
+
thread.on("message", (message) => {
|
|
15035
|
+
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
15036
|
});
|
|
15124
|
-
|
|
15125
|
-
finish(trouble);
|
|
15037
|
+
thread.on("error", (trouble) => {
|
|
15038
|
+
finish(failure(`\u0442\u0435\u043B\u043E \u0443\u043F\u0430\u043B\u043E: ${describeFailure(trouble)}`, trouble.stack ?? ""));
|
|
15126
15039
|
});
|
|
15127
|
-
|
|
15128
|
-
|
|
15040
|
+
thread.on("exit", (code) => {
|
|
15041
|
+
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
15042
|
});
|
|
15130
|
-
|
|
15131
|
-
|
|
15043
|
+
thread.stderr.setEncoding("utf8");
|
|
15044
|
+
thread.stderr.on("data", (chunk) => {
|
|
15045
|
+
errors += chunk;
|
|
15046
|
+
});
|
|
15047
|
+
let version2 = null;
|
|
15048
|
+
const answer = (reply) => {
|
|
15049
|
+
if (reply.error !== void 0) {
|
|
15050
|
+
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)}`));
|
|
15051
|
+
} else if (reply.id === 1) {
|
|
15052
|
+
const named2 = reply.result?.serverInfo?.version;
|
|
15053
|
+
if (typeof named2 !== "string" || named2 === "") {
|
|
15054
|
+
finish(failure("initialize \u043D\u0435 \u043D\u0430\u0437\u0432\u0430\u043B \u0432\u0435\u0440\u0441\u0438\u044E \u0442\u0435\u043B\u0430"));
|
|
15055
|
+
return;
|
|
15056
|
+
}
|
|
15057
|
+
version2 = named2;
|
|
15058
|
+
send({ jsonrpc: "2.0", method: "notifications/initialized" });
|
|
15059
|
+
send({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
|
|
15060
|
+
} else if (reply.id === 2 && version2 !== null) {
|
|
15061
|
+
const names = new Set((reply.result?.tools ?? []).map((tool) => tool.name));
|
|
15062
|
+
const missing = REQUIRED_TOOLS.filter((name) => !names.has(name));
|
|
15063
|
+
if (missing.length > 0) {
|
|
15064
|
+
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(", ")}`));
|
|
15065
|
+
return;
|
|
15066
|
+
}
|
|
15067
|
+
finish(null, version2);
|
|
15068
|
+
}
|
|
15069
|
+
};
|
|
15070
|
+
thread.stdout.setEncoding("utf8");
|
|
15071
|
+
thread.stdout.on("data", (chunk) => {
|
|
15132
15072
|
output += chunk;
|
|
15133
15073
|
for (; ; ) {
|
|
15134
15074
|
const end = output.indexOf("\n");
|
|
@@ -15136,36 +15076,14 @@ var probeShell = async (entry) => {
|
|
|
15136
15076
|
const line = output.slice(0, end).trim();
|
|
15137
15077
|
output = output.slice(end + 1);
|
|
15138
15078
|
if (line === "") continue;
|
|
15139
|
-
let
|
|
15079
|
+
let reply;
|
|
15140
15080
|
try {
|
|
15141
|
-
|
|
15081
|
+
reply = JSON.parse(line);
|
|
15142
15082
|
} catch {
|
|
15143
|
-
finish(
|
|
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)}`));
|
|
15083
|
+
finish(failure(`\u0442\u0435\u043B\u043E \u043D\u0430\u043F\u0435\u0447\u0430\u0442\u0430\u043B\u043E \u043D\u0435 JSON: ${line.slice(0, 200)}`));
|
|
15148
15084
|
return;
|
|
15149
15085
|
}
|
|
15150
|
-
|
|
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
|
-
}
|
|
15086
|
+
answer(reply);
|
|
15169
15087
|
}
|
|
15170
15088
|
});
|
|
15171
15089
|
send({
|
|
@@ -15175,8 +15093,10 @@ var probeShell = async (entry) => {
|
|
|
15175
15093
|
params: { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "update-probe", version: "1" } }
|
|
15176
15094
|
});
|
|
15177
15095
|
});
|
|
15178
|
-
return
|
|
15096
|
+
return { stdout: `${named}
|
|
15097
|
+
` };
|
|
15179
15098
|
} finally {
|
|
15099
|
+
await thread.terminate();
|
|
15180
15100
|
rmSync(probeHome, { recursive: true, force: true, maxRetries: 3 });
|
|
15181
15101
|
}
|
|
15182
15102
|
};
|
|
@@ -15327,9 +15247,14 @@ async function dryRun2(build, expected, trial) {
|
|
|
15327
15247
|
const { stdout } = await trial(entry);
|
|
15328
15248
|
const line = stdout.trim().split("\n").pop() ?? "";
|
|
15329
15249
|
const said = versionFrom(line);
|
|
15330
|
-
if (said !== expected)
|
|
15250
|
+
if (said !== expected) {
|
|
15251
|
+
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`;
|
|
15252
|
+
noteInstallFault("shell-probe", new Error(trouble));
|
|
15253
|
+
return trouble;
|
|
15254
|
+
}
|
|
15331
15255
|
return null;
|
|
15332
15256
|
} catch (trouble) {
|
|
15257
|
+
noteInstallFault("shell-probe", trouble);
|
|
15333
15258
|
return describeFailure(trouble);
|
|
15334
15259
|
}
|
|
15335
15260
|
}
|
|
@@ -15382,7 +15307,6 @@ function rollbackShell(home) {
|
|
|
15382
15307
|
};
|
|
15383
15308
|
}
|
|
15384
15309
|
}
|
|
15385
|
-
var SOURCES_FILE = "python-sources.json";
|
|
15386
15310
|
var PUBLICATION_FILE2 = ".publication.json";
|
|
15387
15311
|
var CANDIDATE_FILE = ".candidate.json";
|
|
15388
15312
|
function recoverInterruptedPublication(dir) {
|
|
@@ -15446,26 +15370,6 @@ function recoverInterruptedPublication(dir) {
|
|
|
15446
15370
|
\u041E\u043D\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0440\u0430\u0431\u043E\u0447\u0430\u044F: setup \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442 \u044D\u0442\u043E\u0442 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442 \u0438 \u0441\u043D\u0430\u0447\u0430\u043B\u0430 \u0441\u043E\u0431\u0435\u0440\u0451\u0442 \u0435\u0433\u043E \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435.`
|
|
15447
15371
|
};
|
|
15448
15372
|
}
|
|
15449
|
-
function platformKey(os = process.platform, arch2 = process.arch) {
|
|
15450
|
-
if (os === "darwin") return arch2 === "arm64" ? "Darwin-arm64" : arch2 === "x64" ? "Darwin-x86_64" : null;
|
|
15451
|
-
if (os === "win32") return arch2 === "x64" ? "Windows-AMD64" : null;
|
|
15452
|
-
if (os === "linux") return arch2 === "x64" ? "Linux-x86_64" : arch2 === "arm64" ? "Linux-aarch64" : null;
|
|
15453
|
-
return null;
|
|
15454
|
-
}
|
|
15455
|
-
function pythonSource(engineDir, key = platformKey()) {
|
|
15456
|
-
if (key === null) return null;
|
|
15457
|
-
const file2 = join(engineDir, SOURCES_FILE);
|
|
15458
|
-
if (!existsSync(file2)) return null;
|
|
15459
|
-
const table = JSON.parse(readFileSync(file2, "utf8"));
|
|
15460
|
-
const row = table["platforms"][key];
|
|
15461
|
-
if (row === void 0) return null;
|
|
15462
|
-
return { url: table["base"] + row["tail"], sha256: row.sha256, mb: row["mb"] };
|
|
15463
|
-
}
|
|
15464
|
-
function pythonVersion(engineDir) {
|
|
15465
|
-
const file2 = join(engineDir, SOURCES_FILE);
|
|
15466
|
-
if (!existsSync(file2)) return "";
|
|
15467
|
-
return JSON.parse(readFileSync(file2, "utf8"))["version"];
|
|
15468
|
-
}
|
|
15469
15373
|
async function installPayload(engine, opts, hooks = {}) {
|
|
15470
15374
|
if (engine.pathSetByHand()) {
|
|
15471
15375
|
return {
|
|
@@ -15564,7 +15468,7 @@ ${VOICE_CLEANER_NOTE}
|
|
|
15564
15468
|
return {
|
|
15565
15469
|
ok: true,
|
|
15566
15470
|
text: `\u041D\u0430\u0447\u0438\u043D\u043A\u0430 ${manifest.version} \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043B\u0435\u043D\u0430: ${dest}
|
|
15567
|
-
\u041E\u043D\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0441\u0442\u0430\u043B\u0430 \u0440\u0430\u0431\u043E\u0447\u0435\u0439. \u0414\u0430\u043B\u044C\u0448\u0435 setup \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442 \u044D\u0442\u043E\u0442 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442: \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442
|
|
15471
|
+
\u041E\u043D\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0441\u0442\u0430\u043B\u0430 \u0440\u0430\u0431\u043E\u0447\u0435\u0439. \u0414\u0430\u043B\u044C\u0448\u0435 setup \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442 \u044D\u0442\u043E\u0442 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442: \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442 \u0431\u0438\u0431\u043B\u0438\u043E\u0442\u0435\u043A\u0438 \u043F\u043E \u0435\u0433\u043E \u0437\u0430\u043C\u043A\u0443 \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E\u0441\u043B\u0435 \u043F\u0440\u043E\u0432\u0435\u0440\u043E\u043A \u043F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442 current.
|
|
15568
15472
|
\u0420\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0447\u0438, \u0432\u044B\u0440\u0435\u0437 \u0433\u0435\u0440\u043E\u044F \u0438 \u0447\u0438\u0441\u0442\u043A\u0430 \u0433\u043E\u043B\u043E\u0441\u0430 \u0432 \u043D\u0435\u0433\u043E \u043D\u0435 \u0432\u0445\u043E\u0434\u044F\u0442: \u043E\u043D\u0438 \u0441\u0442\u0430\u0432\u044F\u0442\u0441\u044F \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u044B\u043C\u0438 \u0448\u0430\u0433\u0430\u043C\u0438 \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E \u043F\u0440\u043E\u0441\u044C\u0431\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430.`
|
|
15569
15473
|
};
|
|
15570
15474
|
});
|
|
@@ -15604,113 +15508,6 @@ async function deliver(manifest, dest, intakeNear, key, baseCurrent, hooks) {
|
|
|
15604
15508
|
discardVersionStage(stage);
|
|
15605
15509
|
}
|
|
15606
15510
|
}
|
|
15607
|
-
async function installPython(engine, opts) {
|
|
15608
|
-
try {
|
|
15609
|
-
return await withVersionLock(
|
|
15610
|
-
engine.versionsDir(),
|
|
15611
|
-
async () => installPythonUnderLock(engine, opts)
|
|
15612
|
-
);
|
|
15613
|
-
} catch (trouble) {
|
|
15614
|
-
if (trouble instanceof VersionLockError) return { ok: false, text: trouble.message };
|
|
15615
|
-
return { ok: false, text: troubleText("Python \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C", trouble) };
|
|
15616
|
-
}
|
|
15617
|
-
}
|
|
15618
|
-
async function installPythonUnderLock(engine, opts) {
|
|
15619
|
-
const place = opts.version === void 0 ? engine.place() : engine.placeForVersion(opts.version);
|
|
15620
|
-
if (place === null) {
|
|
15621
|
-
return { ok: false, text: engine.whyNoEngine() };
|
|
15622
|
-
}
|
|
15623
|
-
const key = platformKey();
|
|
15624
|
-
const source = pythonSource(place.engine, key);
|
|
15625
|
-
if (source === null || source.sha256 === "") {
|
|
15626
|
-
return {
|
|
15627
|
-
ok: false,
|
|
15628
|
-
text: `\u0413\u043E\u0442\u043E\u0432\u043E\u0439 \u043F\u043E\u0440\u0442\u0430\u0442\u0438\u0432\u043D\u043E\u0439 \u0441\u0431\u043E\u0440\u043A\u0438 Python \u043F\u043E\u0434 \u044D\u0442\u0443 \u0441\u0438\u0441\u0442\u0435\u043C\u0443 (${key ?? `${process.platform}-${process.arch}`}) \u0443 \u043C\u0435\u043D\u044F \u043D\u0435\u0442.
|
|
15629
|
-
\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u0441\u043A\u0430\u0436\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C Python 3.10 \u0438\u043B\u0438 \u043D\u043E\u0432\u0435\u0435 \u0441 python.org/downloads \u0438 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0443.`
|
|
15630
|
-
};
|
|
15631
|
-
}
|
|
15632
|
-
const dest = join(engine.home(), "bin");
|
|
15633
|
-
const version2 = pythonVersion(place.engine);
|
|
15634
|
-
if (!opts.consent) {
|
|
15635
|
-
return {
|
|
15636
|
-
ok: false,
|
|
15637
|
-
text: `\u041D\u0430 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435 \u043D\u0435\u0442 Python, \u0430 \u0431\u0435\u0437 \u043D\u0435\u0433\u043E \u043C\u043E\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u043C.
|
|
15638
|
-
\u041C\u043E\u0433\u0443 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u043F\u043E\u0440\u0442\u0430\u0442\u0438\u0432\u043D\u044B\u0439 Python ${version2} (${source.mb} \u041C\u0411) \u0432 ${dest}: \u043E\u043D \u043B\u0435\u0436\u0438\u0442 \u043E\u0434\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u043E\u0439 \u0438 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043E\u0442\u0442\u0443\u0434\u0430 \u2014 \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u0443 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044F, PATH \u043D\u0435 \u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F, \u043F\u0440\u0430\u0432\u0430 \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u043D\u0435 \u043D\u0443\u0436\u043D\u044B, \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0437\u043D\u0430\u0447\u0438\u0442 \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u043F\u0430\u043F\u043A\u0443. \u041F\u043E\u0434\u043F\u0438\u0441\u044C \u0444\u0430\u0439\u043B\u0430 \u0443 \u043C\u0435\u043D\u044F \u0435\u0441\u0442\u044C, \u0441\u0432\u0435\u0440\u044E.
|
|
15639
|
-
\u0421\u043F\u0440\u043E\u0441\u0438 \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0435 \u0438 \u043F\u043E\u0437\u043E\u0432\u0438 setup \u0441 what=all \u0438 consent=true.`
|
|
15640
|
-
};
|
|
15641
|
-
}
|
|
15642
|
-
const pythonDir = join(dest, "python");
|
|
15643
|
-
try {
|
|
15644
|
-
safePythonParent(engine.home(), dest);
|
|
15645
|
-
if (existsSync(pythonDir)) {
|
|
15646
|
-
safePythonDirectory(engine.home(), pythonDir);
|
|
15647
|
-
engine.forgetPython();
|
|
15648
|
-
if (await engine.pythonTrouble() === null) {
|
|
15649
|
-
return {
|
|
15650
|
-
ok: true,
|
|
15651
|
-
text: `Python ${version2} \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D: ${pythonDir}
|
|
15652
|
-
\u041F\u043E\u0432\u0442\u043E\u0440\u043D\u043E \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043B.`
|
|
15653
|
-
};
|
|
15654
|
-
}
|
|
15655
|
-
throw new DeliveryError(
|
|
15656
|
-
`\u0412 ${pythonDir} \u0443\u0436\u0435 \u0447\u0442\u043E-\u0442\u043E \u043B\u0435\u0436\u0438\u0442, \u043D\u043E \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u044D\u0442\u043E \u043D\u0435 \u0432\u044B\u0448\u043B\u043E. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435, \u043D\u0435 \u0438\u0434\u0451\u0442 \u043B\u0438 \u0434\u0440\u0443\u0433\u0430\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430, \u0437\u0430\u0442\u0435\u043C \u0443\u0434\u0430\u043B\u0438\u0442\u0435 \u043E\u0441\u0442\u0430\u0442\u043E\u043A \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`
|
|
15657
|
-
);
|
|
15658
|
-
}
|
|
15659
|
-
const stage = createVersionStage(engine.versionsDir(), opts.version ?? "0-python-bootstrap");
|
|
15660
|
-
try {
|
|
15661
|
-
const archive = join(stage.root, "python.tar.gz");
|
|
15662
|
-
await downloadFile({ url: source.url, dest: archive, sha256: source.sha256, key: null });
|
|
15663
|
-
unpackArchive(archive, stage.payload);
|
|
15664
|
-
const stagedPython = join(stage.payload, "python");
|
|
15665
|
-
if (!dirExists(stagedPython)) throw new DeliveryError("\u0432 \u0430\u0440\u0445\u0438\u0432\u0435 Python \u043D\u0435\u0442 \u043F\u0430\u043F\u043A\u0438 python");
|
|
15666
|
-
if (dirExists(pythonDir)) {
|
|
15667
|
-
throw new DeliveryError(`\u043F\u0430\u043F\u043A\u0430 ${pythonDir} \u0437\u0430\u043D\u044F\u0442\u0430 \u0434\u0440\u0443\u0433\u0438\u043C \u043F\u0440\u043E\u0446\u0435\u0441\u0441\u043E\u043C. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup \u043F\u043E\u0437\u0436\u0435`);
|
|
15668
|
-
}
|
|
15669
|
-
renameSync(stagedPython, pythonDir);
|
|
15670
|
-
} finally {
|
|
15671
|
-
discardVersionStage(stage);
|
|
15672
|
-
}
|
|
15673
|
-
} catch (trouble2) {
|
|
15674
|
-
return { ok: false, text: troubleText("Python \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C", trouble2) };
|
|
15675
|
-
}
|
|
15676
|
-
engine.forgetPython();
|
|
15677
|
-
const trouble = await engine.pythonTrouble();
|
|
15678
|
-
if (trouble !== null) {
|
|
15679
|
-
return {
|
|
15680
|
-
ok: false,
|
|
15681
|
-
text: `Python \u0441\u043A\u0430\u0447\u0430\u043B\u0441\u044F \u0438 \u0440\u0430\u0441\u043F\u0430\u043A\u043E\u0432\u0430\u043B\u0441\u044F \u0432 ${pythonDir}, \u043D\u043E \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u043B\u0441\u044F.
|
|
15682
|
-
${trouble}`
|
|
15683
|
-
};
|
|
15684
|
-
}
|
|
15685
|
-
return {
|
|
15686
|
-
ok: true,
|
|
15687
|
-
text: `Python ${version2} \u043F\u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D: ${pythonDir}
|
|
15688
|
-
\u0412 \u0441\u0438\u0441\u0442\u0435\u043C\u0443 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0441\u0442\u0430\u0432\u0438\u043B\u043E\u0441\u044C. \u0414\u0430\u043B\u044C\u0448\u0435 \u2014 setup \u0441 what=all.`
|
|
15689
|
-
};
|
|
15690
|
-
}
|
|
15691
|
-
function safePythonParent(home, parent) {
|
|
15692
|
-
mkdirSync(parent, { recursive: true });
|
|
15693
|
-
const stat = lstatSync(parent);
|
|
15694
|
-
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
15695
|
-
throw new DeliveryError(`${parent} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043E\u0431\u044B\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u043E\u0439 \u0432\u043D\u0443\u0442\u0440\u0438 \u0434\u043E\u043C\u0430 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430`);
|
|
15696
|
-
}
|
|
15697
|
-
const homeReal = realpathSync(home);
|
|
15698
|
-
const parentReal = realpathSync(parent);
|
|
15699
|
-
if (!parentReal.startsWith(homeReal + sep)) {
|
|
15700
|
-
throw new DeliveryError(`${parent} \u0432\u044B\u0448\u0435\u043B \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u0434\u043E\u043C\u0430 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430`);
|
|
15701
|
-
}
|
|
15702
|
-
}
|
|
15703
|
-
function safePythonDirectory(home, pythonDir) {
|
|
15704
|
-
const stat = lstatSync(pythonDir);
|
|
15705
|
-
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
15706
|
-
throw new DeliveryError(`${pythonDir} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043E\u0431\u044B\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u043E\u0439`);
|
|
15707
|
-
}
|
|
15708
|
-
const homeReal = realpathSync(home);
|
|
15709
|
-
const pythonReal = realpathSync(pythonDir);
|
|
15710
|
-
if (!pythonReal.startsWith(homeReal + sep)) {
|
|
15711
|
-
throw new DeliveryError(`${pythonDir} \u0432\u044B\u0448\u0435\u043B \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u0434\u043E\u043C\u0430 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430`);
|
|
15712
|
-
}
|
|
15713
|
-
}
|
|
15714
15511
|
function troubleText(what, trouble) {
|
|
15715
15512
|
const tail2 = trouble instanceof DeliveryError ? trouble.message : trouble instanceof Error ? trouble.message : String(trouble);
|
|
15716
15513
|
return `${what}, \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043C\u0435\u043D\u044F\u043B.
|
|
@@ -16888,6 +16685,10 @@ function cardRows(readiness) {
|
|
|
16888
16685
|
}));
|
|
16889
16686
|
return rows.map((row) => ({ ...row, mb: row.state === "ok" ? 0 : row.mb, say: rowWords(row.state, row.mb) }));
|
|
16890
16687
|
}
|
|
16688
|
+
var FOR_MODEL = /\bsetup\b|\bwait\b|what=|consent|\bjob\b|Скажи человеку|Спроси человека|скажи ему|перескажи/i;
|
|
16689
|
+
function forHuman(line) {
|
|
16690
|
+
return FOR_MODEL.test(line) ? "" : line;
|
|
16691
|
+
}
|
|
16891
16692
|
function setupCard(o) {
|
|
16892
16693
|
const rows = cardRows(o.readiness);
|
|
16893
16694
|
const missingMb = rows.filter((row) => row.state === "missing").reduce((all, row) => all + row.mb, 0);
|
|
@@ -16899,7 +16700,7 @@ function setupCard(o) {
|
|
|
16899
16700
|
next = `\u041D\u0430\u043F\u0438\u0448\u0438 \xAB\u0441\u043A\u0430\u0447\u0430\u0439\xBB \u2014 \u0441\u043A\u0430\u0447\u0430\u044E ${o.noEngine ? "\u043C\u043E\u043D\u0442\u0430\u0436" : "Python"}.`;
|
|
16900
16701
|
} else if (o.readiness === null) {
|
|
16901
16702
|
title = o.title ?? TITLE_UNKNOWN;
|
|
16902
|
-
next = o.note ?? "";
|
|
16703
|
+
next = forHuman(o.note ?? "");
|
|
16903
16704
|
} else if (!ready) {
|
|
16904
16705
|
title = missingMb ? `\u041D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u0441\u043A\u0430\u0447\u0430\u0442\u044C ${weight(missingMb)} \u0434\u043B\u044F \u043F\u043E\u043B\u043D\u043E\u0446\u0435\u043D\u043D\u043E\u0439 \u0440\u0430\u0431\u043E\u0442\u044B` : "\u041D\u0435 \u0432\u0441\u0451 \u0433\u043E\u0442\u043E\u0432\u043E \u0434\u043B\u044F \u043F\u043E\u043B\u043D\u043E\u0446\u0435\u043D\u043D\u043E\u0439 \u0440\u0430\u0431\u043E\u0442\u044B";
|
|
16905
16706
|
next = missingMb ? `\u041D\u0430\u043F\u0438\u0448\u0438 \xAB\u0441\u043A\u0430\u0447\u0430\u0439\xBB \u2014 \u0441\u043A\u0430\u0447\u0430\u044E ${weight(missingMb)}.` : "\u041D\u0430\u043F\u0438\u0448\u0438 \xAB\u0441\u043A\u0430\u0447\u0430\u0439\xBB \u2014 \u043F\u043E\u0441\u0442\u0430\u0432\u043B\u044E, \u0447\u0435\u0433\u043E \u043D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442.";
|
|
@@ -18055,8 +17856,6 @@ function nameOrRefusal(candidate) {
|
|
|
18055
17856
|
\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043D\u0430\u0437\u043E\u0432\u0438 \u0448\u0430\u0433 \u043E\u0434\u043D\u0438\u043C \u0441\u043B\u043E\u0432\u043E\u043C \u2014 \u0442\u0430\u043A, \u043A\u0430\u043A \u043D\u0430\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u0435\u0433\u043E \u043F\u0430\u043F\u043A\u0430. \u0421\u0432\u043E\u0439 \u0448\u0430\u0433 \u043B\u0435\u0436\u0438\u0442 \u0432 \`mine/steps/<\u0438\u043C\u044F>\` \u0432 \u0434\u043E\u043C\u0435 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430, \u043D\u0430\u0448\u0438 \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u044F\u0435\u0442 setup, \u0438\u043C\u044F \u0443 \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u0441\u0442\u043E\u0438\u0442 \u0432 \u0441\u043A\u043E\u0431\u043A\u0430\u0445.`
|
|
18056
17857
|
};
|
|
18057
17858
|
}
|
|
18058
|
-
|
|
18059
|
-
// src/setup-job.ts
|
|
18060
17859
|
var SETUP_JOB_MARK = "setup-";
|
|
18061
17860
|
function isSetupJob(id) {
|
|
18062
17861
|
return id.startsWith(SETUP_JOB_MARK);
|
|
@@ -18071,13 +17870,108 @@ var CHECK = "\u041F\u0440\u043E\u0432\u0435\u0440\u044F\u044E, \u0447\u0442\u043
|
|
|
18071
17870
|
var INSTALL_NEW = "\u0421\u0442\u0430\u0432\u043B\u044E \u043D\u043E\u0432\u0443\u044E \u0432\u0435\u0440\u0441\u0438\u044E";
|
|
18072
17871
|
var MISSING = "\u0421\u0442\u0430\u0432\u043B\u044E \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u044E\u0449\u0435\u0435";
|
|
18073
17872
|
var works = /* @__PURE__ */ new Map();
|
|
18074
|
-
|
|
18075
|
-
|
|
17873
|
+
var JOBS_DIR = "jobs";
|
|
17874
|
+
var JOBS_KEPT2 = 10;
|
|
17875
|
+
var BEAT_MS = 1e4;
|
|
17876
|
+
var STALE_MS = 6e4;
|
|
17877
|
+
var JOB_ID = /^setup-[\w-]{1,80}$/;
|
|
17878
|
+
function running(home, clock) {
|
|
17879
|
+
for (const work of works.values()) if (work.ended === null) return work.id;
|
|
17880
|
+
if (home === null) return null;
|
|
17881
|
+
for (const record2 of records(home)) {
|
|
17882
|
+
if (record2.ended === null && alive(record2, clock)) return record2.id;
|
|
17883
|
+
}
|
|
18076
17884
|
return null;
|
|
18077
17885
|
}
|
|
18078
|
-
function
|
|
18079
|
-
|
|
18080
|
-
|
|
17886
|
+
function records(home) {
|
|
17887
|
+
let names;
|
|
17888
|
+
try {
|
|
17889
|
+
names = readdirSync(join(home, JOBS_DIR)).filter((name) => name.endsWith(".json"));
|
|
17890
|
+
} catch {
|
|
17891
|
+
return [];
|
|
17892
|
+
}
|
|
17893
|
+
return names.sort().reverse().map((name) => load(home, name.slice(0, -".json".length))).filter((record2) => record2 !== null);
|
|
17894
|
+
}
|
|
17895
|
+
function load(home, id) {
|
|
17896
|
+
if (!JOB_ID.test(id)) return null;
|
|
17897
|
+
try {
|
|
17898
|
+
const value = JSON.parse(readFileSync(join(home, JOBS_DIR, `${id}.json`), "utf8"));
|
|
17899
|
+
if (value.id !== id || typeof value.what !== "string" || typeof value.started !== "number" || !Array.isArray(value.stages) || typeof value.at !== "number" || typeof value.pid !== "number" || typeof value.beat !== "number") return null;
|
|
17900
|
+
return {
|
|
17901
|
+
id,
|
|
17902
|
+
what: value.what,
|
|
17903
|
+
started: value.started,
|
|
17904
|
+
stages: value.stages.map(String),
|
|
17905
|
+
at: value.at,
|
|
17906
|
+
message: typeof value.message === "string" ? value.message : "",
|
|
17907
|
+
ended: value.ended ?? null,
|
|
17908
|
+
pid: value.pid,
|
|
17909
|
+
beat: value.beat
|
|
17910
|
+
};
|
|
17911
|
+
} catch {
|
|
17912
|
+
return null;
|
|
17913
|
+
}
|
|
17914
|
+
}
|
|
17915
|
+
function alive(record2, clock) {
|
|
17916
|
+
if (clock() - record2.beat > STALE_MS) return false;
|
|
17917
|
+
try {
|
|
17918
|
+
process.kill(record2.pid, 0);
|
|
17919
|
+
return true;
|
|
17920
|
+
} catch (trouble) {
|
|
17921
|
+
return trouble.code === "EPERM";
|
|
17922
|
+
}
|
|
17923
|
+
}
|
|
17924
|
+
function save(work, clock) {
|
|
17925
|
+
if (work.home === null) return;
|
|
17926
|
+
try {
|
|
17927
|
+
const dir = join(work.home, JOBS_DIR);
|
|
17928
|
+
mkdirSync(dir, { recursive: true });
|
|
17929
|
+
const file2 = join(dir, `${work.id}.json`);
|
|
17930
|
+
const temp = `${file2}.${process.pid}.tmp`;
|
|
17931
|
+
const record2 = {
|
|
17932
|
+
id: work.id,
|
|
17933
|
+
what: work.what,
|
|
17934
|
+
started: work.started,
|
|
17935
|
+
stages: work.stages,
|
|
17936
|
+
at: work.at,
|
|
17937
|
+
message: work.message,
|
|
17938
|
+
ended: work.ended,
|
|
17939
|
+
pid: process.pid,
|
|
17940
|
+
beat: clock()
|
|
17941
|
+
};
|
|
17942
|
+
writeFileSync(temp, JSON.stringify(record2), "utf8");
|
|
17943
|
+
renameSync(temp, file2);
|
|
17944
|
+
} catch {
|
|
17945
|
+
}
|
|
17946
|
+
}
|
|
17947
|
+
function prune2(home) {
|
|
17948
|
+
try {
|
|
17949
|
+
const dir = join(home, JOBS_DIR);
|
|
17950
|
+
const names = readdirSync(dir).filter((name) => JOB_ID.test(name.replace(/\.json$/, ""))).sort();
|
|
17951
|
+
for (const name of names.slice(0, Math.max(0, names.length - JOBS_KEPT2))) rmSync(join(dir, name), { force: true });
|
|
17952
|
+
} catch {
|
|
17953
|
+
}
|
|
17954
|
+
}
|
|
17955
|
+
function fromDisk(home, id, clock) {
|
|
17956
|
+
const record2 = load(home, id);
|
|
17957
|
+
if (record2 === null) return null;
|
|
17958
|
+
if (record2.ended !== null || alive(record2, clock)) return record2;
|
|
17959
|
+
return {
|
|
17960
|
+
...record2,
|
|
17961
|
+
ended: {
|
|
17962
|
+
at: record2.beat,
|
|
17963
|
+
ending: {
|
|
17964
|
+
ok: false,
|
|
17965
|
+
trouble: "\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u043E\u0441\u044C: \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0430, \u043A\u043E\u0442\u043E\u0440\u0430\u044F \u0435\u0433\u043E \u0432\u0435\u043B\u0430, \u0437\u0430\u043A\u0440\u044B\u043B\u0430\u0441\u044C \u043F\u043E\u0441\u0440\u0435\u0434\u0438 \u0440\u0430\u0431\u043E\u0442\u044B. \u041F\u0440\u0435\u0436\u043D\u044F\u044F \u0432\u0435\u0440\u0441\u0438\u044F \u043D\u0430 \u043C\u0435\u0441\u0442\u0435, \u043C\u043E\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043C\u043E\u0436\u043D\u043E.",
|
|
17966
|
+
advice: "\u041D\u0430\u043F\u0438\u0448\u0438 \xAB\u043E\u0431\u043D\u043E\u0432\u0438\xBB \u0435\u0449\u0451 \u0440\u0430\u0437 \u2014 \u043D\u0430\u0447\u043D\u0443 \u0437\u0430\u043D\u043E\u0432\u043E.",
|
|
17967
|
+
report: `\u041F\u0440\u043E\u0446\u0435\u0441\u0441 \u043E\u0431\u043E\u043B\u043E\u0447\u043A\u0438 ${record2.pid}, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0432\u0451\u043B \u0437\u0430\u0434\u0430\u0447\u0443, \u043F\u0440\u043E\u043F\u0430\u043B \u043D\u0430 \u044D\u0442\u0430\u043F\u0435 \xAB${record2.stages[record2.at - 1] ?? CHECK}\xBB.`
|
|
17968
|
+
}
|
|
17969
|
+
}
|
|
17970
|
+
};
|
|
17971
|
+
}
|
|
17972
|
+
function startSetupJob(what, run, clock = Date.now, home = null) {
|
|
17973
|
+
const already = running(home, clock);
|
|
17974
|
+
if (already !== null) return already;
|
|
18081
17975
|
const started = clock();
|
|
18082
17976
|
const id = `${SETUP_JOB_MARK}${new Date(started).toISOString().replace(/[:.]/g, "-")}`;
|
|
18083
17977
|
const work = {
|
|
@@ -18088,23 +17982,31 @@ function startSetupJob(what, run, clock = Date.now) {
|
|
|
18088
17982
|
at: 1,
|
|
18089
17983
|
message: "",
|
|
18090
17984
|
ended: null,
|
|
18091
|
-
done: Promise.resolve()
|
|
17985
|
+
done: Promise.resolve(),
|
|
17986
|
+
home
|
|
18092
17987
|
};
|
|
18093
17988
|
const control = {
|
|
18094
17989
|
plan(stages) {
|
|
18095
17990
|
work.stages = stages;
|
|
18096
17991
|
work.at = Math.min(work.at, stages.length);
|
|
17992
|
+
save(work, clock);
|
|
18097
17993
|
},
|
|
18098
17994
|
go(stage) {
|
|
18099
17995
|
const index = work.stages.indexOf(stage);
|
|
18100
17996
|
if (index >= 0) work.at = index + 1;
|
|
18101
17997
|
work.message = "";
|
|
17998
|
+
save(work, clock);
|
|
18102
17999
|
},
|
|
18103
18000
|
line(text2) {
|
|
18104
18001
|
work.message = text2;
|
|
18002
|
+
save(work, clock);
|
|
18105
18003
|
}
|
|
18106
18004
|
};
|
|
18107
18005
|
works.set(id, work);
|
|
18006
|
+
if (home !== null) prune2(home);
|
|
18007
|
+
save(work, clock);
|
|
18008
|
+
const beat = home === null ? null : setInterval(() => save(work, clock), BEAT_MS);
|
|
18009
|
+
beat?.unref();
|
|
18108
18010
|
work.done = collectJobInstallFaults(id, () => run(control).catch((trouble) => {
|
|
18109
18011
|
noteInstallFault("update-job", trouble);
|
|
18110
18012
|
return {
|
|
@@ -18115,15 +18017,17 @@ function startSetupJob(what, run, clock = Date.now) {
|
|
|
18115
18017
|
};
|
|
18116
18018
|
})).then((ending) => {
|
|
18117
18019
|
work.ended = { at: clock(), ending };
|
|
18020
|
+
if (beat !== null) clearInterval(beat);
|
|
18021
|
+
save(work, clock);
|
|
18118
18022
|
});
|
|
18119
18023
|
return id;
|
|
18120
18024
|
}
|
|
18121
18025
|
function quiet(line) {
|
|
18122
18026
|
return line.replace(/^⚠\s*/, "").replace(/^Что делать:/, "\u0421\u043E\u0432\u0435\u0442:");
|
|
18123
18027
|
}
|
|
18124
|
-
function setupJobText(id, clock = Date.now) {
|
|
18125
|
-
const work = works.get(id);
|
|
18126
|
-
if (work ===
|
|
18028
|
+
function setupJobText(id, clock = Date.now, home = null) {
|
|
18029
|
+
const work = works.get(id) ?? (home === null ? null : fromDisk(home, id, clock));
|
|
18030
|
+
if (work === null) return null;
|
|
18127
18031
|
const head2 = `\u0417\u0430\u0434\u0430\u043D\u0438\u0435 ${work.id}: ${work.what}`;
|
|
18128
18032
|
if (work.ended === null) {
|
|
18129
18033
|
const sec2 = Math.max(0, Math.round((clock() - work.started) / 1e3));
|
|
@@ -18147,8 +18051,8 @@ function setupJobText(id, clock = Date.now) {
|
|
|
18147
18051
|
`\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: ${ending.advice}`
|
|
18148
18052
|
].join("\n");
|
|
18149
18053
|
}
|
|
18150
|
-
function setupJobReport(id) {
|
|
18151
|
-
const text2 = setupJobText(id);
|
|
18054
|
+
function setupJobReport(id, home = null) {
|
|
18055
|
+
const text2 = setupJobText(id, Date.now, home);
|
|
18152
18056
|
return text2 === null ? null : readJob(text2);
|
|
18153
18057
|
}
|
|
18154
18058
|
function weightExact(bytes) {
|
|
@@ -18229,9 +18133,10 @@ async function runUpdate(job, deps) {
|
|
|
18229
18133
|
updated = true;
|
|
18230
18134
|
steps.push({ report: outcome.text });
|
|
18231
18135
|
} else {
|
|
18136
|
+
const cause = causeOf(outcome.text);
|
|
18232
18137
|
steps.push({
|
|
18233
18138
|
report: outcome.text,
|
|
18234
|
-
trouble: `\u041D\u043E\u0432\u0430\u044F \u0432\u0435\u0440\u0441\u0438\u044F \u0434\u0432\u0438\u0436\u043A\u0430 \u043D\u0435 \u0432\u0441\u0442\u0430\u043B\u0430
|
|
18139
|
+
trouble: `\u041D\u043E\u0432\u0430\u044F \u0432\u0435\u0440\u0441\u0438\u044F \u0434\u0432\u0438\u0436\u043A\u0430 \u043D\u0435 \u0432\u0441\u0442\u0430\u043B\u0430${cause === "" ? "" : `: ${cause}`}. \u0420\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043F\u0440\u0435\u0436\u043D\u044F\u044F${engineWas === null ? "" : ` ${engineWas}`}, \u043C\u043E\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043C\u043E\u0436\u043D\u043E.`
|
|
18235
18140
|
});
|
|
18236
18141
|
}
|
|
18237
18142
|
}
|
|
@@ -18247,6 +18152,11 @@ async function runUpdate(job, deps) {
|
|
|
18247
18152
|
if (updated) return { ok: true, say: SAY_RESTART, report };
|
|
18248
18153
|
return { ok: true, say: installed ? SAY_INSTALLED : SAY_NOTHING, report };
|
|
18249
18154
|
}
|
|
18155
|
+
function causeOf(text2) {
|
|
18156
|
+
const line = text2.split("\n").map((one) => one.trim()).find((one) => one !== "" && !/^(Новая версия|Версия) \S+ не встала/.test(one) && !/^Что делать:/.test(one)) ?? "";
|
|
18157
|
+
const phrase = (line.split(/\.\s|\s—\s|;\s/)[0] ?? "").replace(/\s*\([^)]*\)/g, "").replace(/\.$/, "").trim();
|
|
18158
|
+
return phrase === "" ? "" : phrase[0].toLowerCase() + phrase.slice(1);
|
|
18159
|
+
}
|
|
18250
18160
|
async function deliverMissing(job, deps) {
|
|
18251
18161
|
const answer = await deps.installMissing();
|
|
18252
18162
|
if (answer.type === "error") {
|
|
@@ -18346,25 +18256,15 @@ async function installStep(engine, asked, key, baseUrl, tell) {
|
|
|
18346
18256
|
`\u041A\u0430\u043D\u0434\u0438\u0434\u0430\u0442 ${candidate.version} \u0443\u0436\u0435 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043B\u0435\u043D, \u043D\u043E \u0435\u0449\u0451 \u043D\u0435 \u0440\u0430\u0431\u043E\u0447\u0438\u0439. \u0421\u043F\u0440\u043E\u0441\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0435 \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u0435\u0433\u043E \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u0438 \u043F\u043E\u0437\u043E\u0432\u0438 setup \u0441 consent=true.`
|
|
18347
18257
|
);
|
|
18348
18258
|
}
|
|
18349
|
-
let bootstrapText = "";
|
|
18350
18259
|
const extras = step === "all" ? "later" : "now";
|
|
18351
|
-
const activated = await continuePreparedCandidate(engine, candidate,
|
|
18352
|
-
if (await engine.pythonTrouble() === null) {
|
|
18353
|
-
return { ok: true, text: "Python \u0443\u0436\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D; \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043B." };
|
|
18354
|
-
}
|
|
18355
|
-
const python2 = await installPythonUnderLock(engine, { consent, version: locked.version });
|
|
18356
|
-
bootstrapText = python2.text;
|
|
18357
|
-
return python2;
|
|
18358
|
-
}, void 0, extras);
|
|
18260
|
+
const activated = await continuePreparedCandidate(engine, candidate, void 0, extras);
|
|
18359
18261
|
if (!activated.ok) return toolError(activated.text);
|
|
18360
18262
|
engine.forgetPlace();
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
${activated.text}`.trim());
|
|
18364
|
-
}
|
|
18263
|
+
engine.forgetPython();
|
|
18264
|
+
if (step === "python") return toolSuccess(activated.text);
|
|
18365
18265
|
if (step === "all") {
|
|
18366
18266
|
const ready = `${activated.text}
|
|
18367
|
-
\u041A\u0430\u043D\u0434\u0438\u0434\u0430\u0442 \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u043B
|
|
18267
|
+
\u041A\u0430\u043D\u0434\u0438\u0434\u0430\u0442 \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u043B \u0431\u0438\u0431\u043B\u0438\u043E\u0442\u0435\u043A\u0438 \u043F\u043E \u0441\u0432\u043E\u0435\u043C\u0443 \u0437\u0430\u043C\u043A\u0443 \u0438 \u043F\u0440\u043E\u0448\u0451\u043B env-check. \u0412\u0441\u0451 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0433\u043E\u0442\u043E\u0432\u043E.`;
|
|
18368
18268
|
const later = await installStep(engine, asked, key, baseUrl, tell);
|
|
18369
18269
|
if (later.type === "error") {
|
|
18370
18270
|
return toolSuccess(
|
|
@@ -18378,16 +18278,15 @@ ${activated.text}`.trim());
|
|
|
18378
18278
|
${EXTRAS_LATER}`), later]);
|
|
18379
18279
|
}
|
|
18380
18280
|
}
|
|
18381
|
-
if (step === "python" || step === "all") {
|
|
18382
|
-
if (await engine.pythonTrouble() !== null) {
|
|
18383
|
-
const result = await installPython(engine, { consent });
|
|
18384
|
-
if (!result.ok) return toolError(result.text);
|
|
18385
|
-
if (step === "python") return toolSuccess(result.text);
|
|
18386
|
-
return toolSuccess(result.text + "\n\u041F\u043E\u0437\u043E\u0432\u0438 setup \u0441 what=all \u0435\u0449\u0451 \u0440\u0430\u0437.");
|
|
18387
|
-
}
|
|
18388
|
-
}
|
|
18389
18281
|
const place = engine.place();
|
|
18390
18282
|
if (place === null) return toolError(engine.whyNoEngine());
|
|
18283
|
+
if (consent && await engine.pythonTrouble() !== null) {
|
|
18284
|
+
try {
|
|
18285
|
+
await engine.bringPython(place);
|
|
18286
|
+
} catch (trouble) {
|
|
18287
|
+
return toolError(`\u041F\u0438\u0442\u043E\u043D \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C: ${describeFailure(trouble)}. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438 setup.`);
|
|
18288
|
+
}
|
|
18289
|
+
}
|
|
18391
18290
|
const common = [
|
|
18392
18291
|
"--pack",
|
|
18393
18292
|
place.pack,
|
|
@@ -18623,7 +18522,7 @@ async function lookAround(engine, model, key, baseUrl) {
|
|
|
18623
18522
|
shell: shellNews,
|
|
18624
18523
|
...o.noEngine === true ? { noEngine: true } : {},
|
|
18625
18524
|
...o.noPython === true ? { noPython: true } : {},
|
|
18626
|
-
note: firstLine(said),
|
|
18525
|
+
note: o.note ?? firstLine(said),
|
|
18627
18526
|
shellVersion: VERSION
|
|
18628
18527
|
}));
|
|
18629
18528
|
const shell = updateShell(engine, false, key, baseUrl, NEWS_POINTER_MS, toShell);
|
|
@@ -18635,10 +18534,10 @@ async function lookAround(engine, model, key, baseUrl) {
|
|
|
18635
18534
|
});
|
|
18636
18535
|
return card(together([toolSuccess(payload.text), await shell]), { noEngine: true });
|
|
18637
18536
|
}
|
|
18638
|
-
|
|
18639
|
-
|
|
18537
|
+
const noPython = await engine.pythonTrouble();
|
|
18538
|
+
if (noPython !== null) {
|
|
18640
18539
|
return card(together([
|
|
18641
|
-
toolSuccess(
|
|
18540
|
+
toolSuccess(noPython),
|
|
18642
18541
|
await updateEngine(engine, false, key, baseUrl, NEWS_POINTER_MS, toEngine),
|
|
18643
18542
|
await shell
|
|
18644
18543
|
]), { noPython: true });
|
|
@@ -18650,7 +18549,7 @@ async function lookAround(engine, model, key, baseUrl) {
|
|
|
18650
18549
|
]);
|
|
18651
18550
|
return card(
|
|
18652
18551
|
together([newsForModel(shellNews, engineNews), machine.result, news, own]),
|
|
18653
|
-
{ readiness: machine.readiness }
|
|
18552
|
+
{ readiness: machine.readiness, note: firstLine(together([machine.result, news, own])) }
|
|
18654
18553
|
);
|
|
18655
18554
|
}
|
|
18656
18555
|
function newsForModel(shell, engine) {
|
|
@@ -18680,8 +18579,8 @@ function startUpdate(engine, what, key, baseUrl) {
|
|
|
18680
18579
|
what,
|
|
18681
18580
|
pointerMs: ASKED_POINTER_MS,
|
|
18682
18581
|
installMissing: () => installMissing(engine, key, baseUrl, void 0)
|
|
18683
|
-
}));
|
|
18684
|
-
const report = setupJobReport(id);
|
|
18582
|
+
}), Date.now, engine.home());
|
|
18583
|
+
const report = setupJobReport(id, engine.home());
|
|
18685
18584
|
return toolSuccess(
|
|
18686
18585
|
`\u0417\u0430\u0434\u0430\u0447\u0430 ${id}: ${report?.what ?? title}.
|
|
18687
18586
|
\u0418\u0434\u0451\u0442 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F: \u043F\u0440\u043E\u0432\u0435\u0440\u044E, \u0447\u0442\u043E \u0432\u044B\u0448\u043B\u043E, \u0441\u043A\u0430\u0447\u0430\u044E \u0438 \u043F\u043E\u0441\u0442\u0430\u0432\u043B\u044E. \u041F\u043E\u043B\u043E\u0441\u0430 \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0441\u0430\u043C\u0430. \u041F\u043E\u0437\u043E\u0432\u0438 wait \u0441 job "` + id + '" \u2014 \u0434\u043E\u0436\u0434\u0451\u0442\u0441\u044F \u0438 \u0441\u043A\u0430\u0436\u0435\u0442, \u0447\u0435\u043C \u043A\u043E\u043D\u0447\u0438\u043B\u043E\u0441\u044C; setup \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E \u043D\u0435 \u0437\u043E\u0432\u0438. \u0413\u043E\u0442\u043E\u0432\u043E \u2014 \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0436\u0438 \u0441\u0442\u0440\u043E\u043A\u0443 \xAB\u0427\u0435\u043B\u043E\u0432\u0435\u043A\u0443\xBB.',
|
|
@@ -18713,10 +18612,8 @@ async function askBeforeHeavy(engine, step, model, key, baseUrl) {
|
|
|
18713
18612
|
});
|
|
18714
18613
|
return toolSuccess(payload.text);
|
|
18715
18614
|
}
|
|
18716
|
-
|
|
18717
|
-
|
|
18718
|
-
return toolSuccess(python.text);
|
|
18719
|
-
}
|
|
18615
|
+
const noPython = await engine.pythonTrouble();
|
|
18616
|
+
if (noPython !== null) return toolSuccess(noPython);
|
|
18720
18617
|
return asToolResult(await engine.command([
|
|
18721
18618
|
"env-install",
|
|
18722
18619
|
"--pack",
|
|
@@ -18821,7 +18718,7 @@ var TRIALS_STEP = "\u041F\u043E\u0442\u043E\u043C \u0441\u043E\u0431\u0435\u0440
|
|
|
18821
18718
|
async function followWork(engine, asked, pace = realPace, tell) {
|
|
18822
18719
|
const ask2 = async () => {
|
|
18823
18720
|
if (!isSetupJob(asked.job)) return engine.command(["job", asked.job]);
|
|
18824
|
-
const text2 = setupJobText(asked.job);
|
|
18721
|
+
const text2 = setupJobText(asked.job, Date.now, engine.home());
|
|
18825
18722
|
return text2 !== null ? { ok: true, text: text2 } : {
|
|
18826
18723
|
ok: false,
|
|
18827
18724
|
text: `\u0417\u0430\u0434\u0430\u0447\u0438 ${asked.job} \u043D\u0435\u0442: \u0435\u0451 \u0432\u0451\u043B \u043F\u0440\u0435\u0436\u043D\u0438\u0439 \u0437\u0430\u043F\u0443\u0441\u043A \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 setup \u2014 \u043E\u043D \u0441\u043A\u0430\u0436\u0435\u0442, \u0447\u0442\u043E \u0441\u0442\u043E\u0438\u0442 \u0441\u0435\u0439\u0447\u0430\u0441.`
|
|
@@ -23129,4 +23026,4 @@ ${inTable}`, file2);
|
|
|
23129
23026
|
};
|
|
23130
23027
|
}
|
|
23131
23028
|
|
|
23132
|
-
export { CrashReporter, DEFAULT_HOME, DeliveryError, Engine, ForeignBlockError,
|
|
23029
|
+
export { CrashReporter, DEFAULT_HOME, DeliveryError, Engine, ForeignBlockError, INSTALL_STEPS, KEEP_COPIES, KEEP_VERSIONS, LOCK_FILE, LONG_STEPS, MANIFEST_TIMEOUT_MS, MANIFEST_URL, MARKER, MIN_ENGINE, McpServer, NaparnikApiClient, NaparnikAuthError, NaparnikClientError, NaparnikConfigError, NaparnikError, NaparnikInsufficientBalanceError, NaparnikScopeError, NaparnikServerError, NaparnikTimeoutError, PAUSE_HOURS, SERVER_NAME, START_SEC, StdioServerTransport, TOOL_SEC, USER_AGENT, VERSION, WHERE_TO_GET_KEY, Wakefulness, bringPython, buildAll, buildBlock, buildResources, bundleUrlFor, chooseBody, compare, configPath, currentMachineFingerprint, decide, decideShell, defineTool, depFolderName, deploy, downloadFile, fetchManifest, fetchShellManifest, fileOrRefusal, findBlock, fromHost, fromNpxCache, handOverToBody, inside, install, installPayload, installStep, installedShell, jsonSchemaOf, keyFromBlock, keyInTable, lastLine, loadConfig, lockedPython, manifestUrlFor, markChecked, markChecked2, markCurrent2 as markCurrent, parseEngineManifest, parseFailure, path, platformKey, previousVersion2 as previousVersion, probe, readConfig, realPace, refusalFor, remove, reportInstallFaults, rollback, rollbackShell, shellDir, systemBlocker, tarEntries, tidyOld2 as tidyOld, timeToCheck, timeToCheck2, unpackArchive, updateEngine, watchProcessCrashes, withArgs };
|