@sberpay-cli/cli-diagnostic 0.4.0-dev.8 → 0.4.0-dev.9
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/build-info.json +4 -4
- package/dist/npm-entry.mjs +187 -98
- package/manifest.json +8 -7
- package/package/SHA256SUMS +5 -4
- package/package/dist/binding-worker.mjs +29 -8
- package/package/dist/cli.mjs +599 -96
- package/package/package.json +1 -1
- package/package/skill/sberpay/SKILL.md +27 -2
- package/package/skill/sberpay/scripts/approved-message.mjs +79 -0
- package/package.json +1 -1
package/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"profile": "diagnostic",
|
|
3
|
-
"version": "0.4.0-dev.
|
|
4
|
-
"sourceCommit": "
|
|
5
|
-
"sourceTreeDigest": "
|
|
3
|
+
"version": "0.4.0-dev.9",
|
|
4
|
+
"sourceCommit": "db0ec0c6594c1d28d55158cde8f6e5d564251e46",
|
|
5
|
+
"sourceTreeDigest": "5f12d63abb08dee373fbdd3ffd173836b8efbaa8d84886af05d5e85c3401db46",
|
|
6
6
|
"snapshot": false,
|
|
7
|
-
"buildId": "
|
|
7
|
+
"buildId": "81921baa6ca1b7998a4feb445c67515af5251419e7bd514bc95dd70384c32abd",
|
|
8
8
|
"stateFormat": 2
|
|
9
9
|
}
|
package/dist/npm-entry.mjs
CHANGED
|
@@ -106,7 +106,7 @@ var require_polyfills = __commonJS({
|
|
|
106
106
|
}
|
|
107
107
|
if (platform === "win32") {
|
|
108
108
|
fs.rename = typeof fs.rename !== "function" ? fs.rename : (function(fs$rename) {
|
|
109
|
-
function
|
|
109
|
+
function rename8(from, to, cb) {
|
|
110
110
|
var start = Date.now();
|
|
111
111
|
var backoff = 0;
|
|
112
112
|
fs$rename(from, to, function CB(er) {
|
|
@@ -126,8 +126,8 @@ var require_polyfills = __commonJS({
|
|
|
126
126
|
if (cb) cb(er);
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
|
-
if (Object.setPrototypeOf) Object.setPrototypeOf(
|
|
130
|
-
return
|
|
129
|
+
if (Object.setPrototypeOf) Object.setPrototypeOf(rename8, fs$rename);
|
|
130
|
+
return rename8;
|
|
131
131
|
})(fs.rename);
|
|
132
132
|
}
|
|
133
133
|
fs.read = typeof fs.read !== "function" ? fs.read : (function(fs$read) {
|
|
@@ -531,8 +531,8 @@ var require_graceful_fs = __commonJS({
|
|
|
531
531
|
fs2.createReadStream = createReadStream;
|
|
532
532
|
fs2.createWriteStream = createWriteStream;
|
|
533
533
|
var fs$readFile = fs2.readFile;
|
|
534
|
-
fs2.readFile =
|
|
535
|
-
function
|
|
534
|
+
fs2.readFile = readFile5;
|
|
535
|
+
function readFile5(path, options, cb) {
|
|
536
536
|
if (typeof options === "function")
|
|
537
537
|
cb = options, options = null;
|
|
538
538
|
return go$readFile(path, options, cb);
|
|
@@ -548,8 +548,8 @@ var require_graceful_fs = __commonJS({
|
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
550
|
var fs$writeFile = fs2.writeFile;
|
|
551
|
-
fs2.writeFile =
|
|
552
|
-
function
|
|
551
|
+
fs2.writeFile = writeFile5;
|
|
552
|
+
function writeFile5(path, data, options, cb) {
|
|
553
553
|
if (typeof options === "function")
|
|
554
554
|
cb = options, options = null;
|
|
555
555
|
return go$writeFile(path, data, options, cb);
|
|
@@ -708,7 +708,7 @@ var require_graceful_fs = __commonJS({
|
|
|
708
708
|
}
|
|
709
709
|
function ReadStream$open() {
|
|
710
710
|
var that = this;
|
|
711
|
-
|
|
711
|
+
open9(that.path, that.flags, that.mode, function(err, fd) {
|
|
712
712
|
if (err) {
|
|
713
713
|
if (that.autoClose)
|
|
714
714
|
that.destroy();
|
|
@@ -728,7 +728,7 @@ var require_graceful_fs = __commonJS({
|
|
|
728
728
|
}
|
|
729
729
|
function WriteStream$open() {
|
|
730
730
|
var that = this;
|
|
731
|
-
|
|
731
|
+
open9(that.path, that.flags, that.mode, function(err, fd) {
|
|
732
732
|
if (err) {
|
|
733
733
|
that.destroy();
|
|
734
734
|
that.emit("error", err);
|
|
@@ -745,8 +745,8 @@ var require_graceful_fs = __commonJS({
|
|
|
745
745
|
return new fs2.WriteStream(path, options);
|
|
746
746
|
}
|
|
747
747
|
var fs$open = fs2.open;
|
|
748
|
-
fs2.open =
|
|
749
|
-
function
|
|
748
|
+
fs2.open = open9;
|
|
749
|
+
function open9(path, flags, mode, cb) {
|
|
750
750
|
if (typeof mode === "function")
|
|
751
751
|
cb = mode, mode = null;
|
|
752
752
|
return go$open(path, flags, mode, cb);
|
|
@@ -1617,8 +1617,8 @@ var require_proper_lockfile = __commonJS({
|
|
|
1617
1617
|
});
|
|
1618
1618
|
|
|
1619
1619
|
// scripts/diagnostics/npm-entry.mts
|
|
1620
|
-
import { readFile as
|
|
1621
|
-
import { dirname as dirname7, join as
|
|
1620
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
1621
|
+
import { dirname as dirname7, join as join12 } from "node:path";
|
|
1622
1622
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
1623
1623
|
import { homedir as homedir4 } from "node:os";
|
|
1624
1624
|
|
|
@@ -2348,9 +2348,9 @@ function floatSafeRemainder(val, step) {
|
|
|
2348
2348
|
return ratio - roundedRatio;
|
|
2349
2349
|
}
|
|
2350
2350
|
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
2351
|
-
function defineLazy(
|
|
2351
|
+
function defineLazy(object3, key, getter) {
|
|
2352
2352
|
let value = void 0;
|
|
2353
|
-
Object.defineProperty(
|
|
2353
|
+
Object.defineProperty(object3, key, {
|
|
2354
2354
|
get() {
|
|
2355
2355
|
if (value === EVALUATING) {
|
|
2356
2356
|
return void 0;
|
|
@@ -2362,7 +2362,7 @@ function defineLazy(object2, key, getter) {
|
|
|
2362
2362
|
return value;
|
|
2363
2363
|
},
|
|
2364
2364
|
set(v) {
|
|
2365
|
-
Object.defineProperty(
|
|
2365
|
+
Object.defineProperty(object3, key, {
|
|
2366
2366
|
value: v
|
|
2367
2367
|
// configurable: true,
|
|
2368
2368
|
});
|
|
@@ -17429,8 +17429,8 @@ function foldObjects(members2) {
|
|
|
17429
17429
|
}
|
|
17430
17430
|
const properties = {};
|
|
17431
17431
|
const required2 = /* @__PURE__ */ new Set();
|
|
17432
|
-
for (const
|
|
17433
|
-
for (const key in
|
|
17432
|
+
for (const object3 of objects) {
|
|
17433
|
+
for (const key in object3.properties) {
|
|
17434
17434
|
if (Object.prototype.hasOwnProperty.call(properties, key))
|
|
17435
17435
|
continue;
|
|
17436
17436
|
const parts = [];
|
|
@@ -17444,18 +17444,18 @@ function foldObjects(members2) {
|
|
|
17444
17444
|
const merged = parts.length === 1 ? parts[0] : foldObjects(parts) ?? { allOf: parts };
|
|
17445
17445
|
assignProp(properties, key, merged);
|
|
17446
17446
|
}
|
|
17447
|
-
for (const key of
|
|
17447
|
+
for (const key of object3.required ?? [])
|
|
17448
17448
|
required2.add(key);
|
|
17449
17449
|
}
|
|
17450
17450
|
const folded = { type: "object", properties };
|
|
17451
17451
|
if (required2.size)
|
|
17452
17452
|
folded.required = [...required2];
|
|
17453
|
-
if (objects.every((
|
|
17453
|
+
if (objects.every((object3) => object3.additionalProperties === false)) {
|
|
17454
17454
|
folded.additionalProperties = false;
|
|
17455
17455
|
} else {
|
|
17456
17456
|
const constraints = [];
|
|
17457
|
-
for (const
|
|
17458
|
-
const constraint = undeclaredConstraint(
|
|
17457
|
+
for (const object3 of objects) {
|
|
17458
|
+
const constraint = undeclaredConstraint(object3);
|
|
17459
17459
|
if (constraint && !constraints.some((seen) => JSON.stringify(seen) === JSON.stringify(constraint)))
|
|
17460
17460
|
constraints.push(constraint);
|
|
17461
17461
|
}
|
|
@@ -21374,7 +21374,7 @@ function skillFileHashes(skill, files, platform = process.platform) {
|
|
|
21374
21374
|
}
|
|
21375
21375
|
function renderDiagnosticSkill(source2, platform, launcher, node2) {
|
|
21376
21376
|
if (platform === "win32") source2 = source2.replace(/(\{\{diagnosticLauncher\}\} auth complete --json) <<'TOKEN'\n([\s\S]*?)\nTOKEN/g, "@'\n$2\n'@ | $1").replace(/\\\r?\n\s*/g, " ");
|
|
21377
|
-
return source2.replaceAll("{{diagnosticLauncher}}", diagnosticLauncherCommand(platform, launcher, node2)) + (platform === "win32" ? "\n\u041D\u0430 Windows \u043A\u043E\u043C\u0430\u043D\u0434\u044B \u0432\u044B\u0448\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u044E\u0442\u0441\u044F \u0432 PowerShell. \
|
|
21377
|
+
return source2.replaceAll("{{diagnosticLauncher}}", diagnosticLauncherCommand(platform, launcher, node2)) + (platform === "win32" ? "\n\u041D\u0430 Windows \u043A\u043E\u043C\u0430\u043D\u0434\u044B \u0432\u044B\u0448\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u044E\u0442\u0441\u044F \u0432 PowerShell. \u041F\u0440\u0438\u0432\u044F\u0437\u043A\u0435 \u043A \u0447\u0430\u0442\u0443 Claude Code \u0445\u0443\u043A SessionStart \u0438 Git Bash \u043D\u0435 \u043D\u0443\u0436\u043D\u044B.\n" : "");
|
|
21378
21378
|
}
|
|
21379
21379
|
|
|
21380
21380
|
// packages/cli/src/core/paths.ts
|
|
@@ -21418,7 +21418,7 @@ import { join as join2 } from "node:path";
|
|
|
21418
21418
|
import { mkdirSync, existsSync, openSync, writeFileSync, fsyncSync, closeSync, renameSync, rmSync } from "node:fs";
|
|
21419
21419
|
import { dirname as dirname2 } from "node:path";
|
|
21420
21420
|
import { randomUUID } from "node:crypto";
|
|
21421
|
-
function atomicJson(path, value) {
|
|
21421
|
+
function atomicJson(path, value, options = {}) {
|
|
21422
21422
|
if (process.platform === "win32") {
|
|
21423
21423
|
ensureWindowsPrivateDirectory(dirname2(path));
|
|
21424
21424
|
if (existsSync(path)) assertWindowsPrivatePath(path);
|
|
@@ -21427,7 +21427,7 @@ function atomicJson(path, value) {
|
|
|
21427
21427
|
try {
|
|
21428
21428
|
const fd = openSync(temp, "wx", 384);
|
|
21429
21429
|
try {
|
|
21430
|
-
writeFileSync(fd, JSON.stringify(value, null, 2) + "\n");
|
|
21430
|
+
writeFileSync(fd, (options.compact ? JSON.stringify(value) : JSON.stringify(value, null, 2)) + "\n");
|
|
21431
21431
|
fsyncSync(fd);
|
|
21432
21432
|
} finally {
|
|
21433
21433
|
closeSync(fd);
|
|
@@ -22220,7 +22220,15 @@ import { createHash as createHash4 } from "node:crypto";
|
|
|
22220
22220
|
var windowsArgument = (s) => '"' + s.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/, "$1$1") + '"';
|
|
22221
22221
|
function windowsSenderConfig(home, launcher, node2) {
|
|
22222
22222
|
if (!win323.isAbsolute(launcher) || !win323.isAbsolute(node2) || /[\0\r\n]/.test(launcher + node2)) throw Error("INVALID_SENDER_PATH");
|
|
22223
|
-
return { path: win323.join(home, ".local", "share", "sberpay-diagnostic", "sender-task.json"), text: JSON.stringify({
|
|
22223
|
+
return { path: win323.join(home, ".local", "share", "sberpay-diagnostic", "sender-task.json"), text: JSON.stringify({
|
|
22224
|
+
name: "SberPay.Diagnostic." + createHash4("sha256").update(launcher.toLowerCase()).digest("hex").slice(0, 24),
|
|
22225
|
+
node: node2,
|
|
22226
|
+
launcher,
|
|
22227
|
+
arguments: windowsArgument(launcher) + " report flush --json",
|
|
22228
|
+
// node.exe is a console program: started by Task Scheduler in the user's session it opens a console window every
|
|
22229
|
+
// 5 minutes. conhost.exe --headless hosts the same process without a window; same user, token and arguments.
|
|
22230
|
+
headlessArguments: "--headless " + windowsArgument(node2) + " " + windowsArgument(launcher) + " report flush --json"
|
|
22231
|
+
}) };
|
|
22224
22232
|
}
|
|
22225
22233
|
var SCRIPT2 = String.raw`
|
|
22226
22234
|
$ErrorActionPreference='Stop'
|
|
@@ -22258,15 +22266,18 @@ $timer.Enabled=$true
|
|
|
22258
22266
|
$logon=$task.Triggers.Create(9)
|
|
22259
22267
|
$logon.UserId=$sid
|
|
22260
22268
|
$logon.Enabled=$true
|
|
22269
|
+
# Hidden console: the system conhost.exe hosts node without a window. Without it, fall back to node itself.
|
|
22270
|
+
$conhost=[IO.Path]::Combine($env:SystemRoot,'System32','conhost.exe')
|
|
22271
|
+
if($c.headlessArguments -and (Test-Path -LiteralPath $conhost -PathType Leaf)){$program=$conhost;$programArguments=$c.headlessArguments}else{$program=$c.node;$programArguments=$c.arguments}
|
|
22261
22272
|
$action=$task.Actions.Create(0)
|
|
22262
|
-
$action.Path=$
|
|
22263
|
-
$action.Arguments=$
|
|
22273
|
+
$action.Path=$program
|
|
22274
|
+
$action.Arguments=$programArguments
|
|
22264
22275
|
$action.WorkingDirectory=[IO.Path]::GetDirectoryName($c.launcher)
|
|
22265
22276
|
$registered=$folder.RegisterTaskDefinition($c.name,$task,6,$sid,$null,3,$null)
|
|
22266
22277
|
$read=$folder.GetTask($c.name)
|
|
22267
22278
|
$d=$read.Definition
|
|
22268
|
-
if($d.Settings.ExecutionTimeLimit -ne 'PT0S' -or $d.Settings.MultipleInstances -ne 2 -or !$read.Enabled -or (SidOf $d.Principal.UserId) -ne $sid -or $d.Principal.LogonType -ne 3 -or $d.Principal.RunLevel -ne 0 -or $d.Actions.Count -ne 1 -or $d.Actions.Item(1).Path -cne $
|
|
22269
|
-
@{status='active';taskName=$c.name}|ConvertTo-Json -Compress
|
|
22279
|
+
if($d.Settings.ExecutionTimeLimit -ne 'PT0S' -or $d.Settings.MultipleInstances -ne 2 -or !$read.Enabled -or (SidOf $d.Principal.UserId) -ne $sid -or $d.Principal.LogonType -ne 3 -or $d.Principal.RunLevel -ne 0 -or $d.Actions.Count -ne 1 -or $d.Actions.Item(1).Path -cne $program -or $d.Actions.Item(1).Arguments -cne $programArguments -or $d.Triggers.Count -ne 2 -or $d.Triggers.Item(1).Repetition.Interval -ne 'PT5M'){throw 'SENDER_TASK_NOT_ACTIVE'}
|
|
22280
|
+
@{status='active';taskName=$c.name;hidden=($program -ceq $conhost)}|ConvertTo-Json -Compress
|
|
22270
22281
|
`;
|
|
22271
22282
|
function windowsSenderCommand(path, env = process.env) {
|
|
22272
22283
|
if (!env.SystemRoot || !win323.isAbsolute(env.SystemRoot)) throw Error("WINDOWS_SYSTEM_ROOT_MISSING");
|
|
@@ -22347,6 +22358,81 @@ async function installSender(home, launcher) {
|
|
|
22347
22358
|
}
|
|
22348
22359
|
}
|
|
22349
22360
|
|
|
22361
|
+
// packages/cli/src/report/claudeHook.ts
|
|
22362
|
+
import { open as open7, chmod, lstat as lstat5, mkdir as mkdir4, readFile as readFile2, realpath, rename as rename6, writeFile as writeFile3 } from "node:fs/promises";
|
|
22363
|
+
import { join as join10 } from "node:path";
|
|
22364
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
22365
|
+
|
|
22366
|
+
// packages/cli/src/report/adapters/types.ts
|
|
22367
|
+
function object2(value) {
|
|
22368
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
22369
|
+
}
|
|
22370
|
+
|
|
22371
|
+
// packages/cli/src/report/claudeHook.ts
|
|
22372
|
+
var shellQuote = (text) => `'${text.replace(/'/g, "'\\''")}'`;
|
|
22373
|
+
var claudeHookCommandFor = (args) => [...args, "report", "claude-hook"].map((s) => shellQuote(process.platform === "win32" ? s.replaceAll("\\", "/") : s)).join(" ");
|
|
22374
|
+
var HOOK_SUFFIX = " 'report' 'claude-hook'";
|
|
22375
|
+
async function readSettings(configDir, create) {
|
|
22376
|
+
if (create) {
|
|
22377
|
+
if (process.platform === "win32") ensureWindowsPrivateDirectory(configDir);
|
|
22378
|
+
else await mkdir4(configDir, { recursive: true, mode: 448 });
|
|
22379
|
+
}
|
|
22380
|
+
const path = join10(configDir, "settings.json");
|
|
22381
|
+
let original;
|
|
22382
|
+
try {
|
|
22383
|
+
const info = await lstat5(path);
|
|
22384
|
+
if (!info.isFile() || info.isSymbolicLink()) throw new BindingError("UNSAFE_SETTINGS");
|
|
22385
|
+
if (process.platform === "win32") assertWindowsPrivatePath(path);
|
|
22386
|
+
original = await readFile2(path, "utf8");
|
|
22387
|
+
} catch (error62) {
|
|
22388
|
+
if (error62.code !== "ENOENT") throw error62;
|
|
22389
|
+
}
|
|
22390
|
+
const settings = original === void 0 ? {} : object2(JSON.parse(original));
|
|
22391
|
+
if (!settings) throw new BindingError("INVALID_SETTINGS");
|
|
22392
|
+
const hooks = settings.hooks === void 0 ? {} : object2(settings.hooks);
|
|
22393
|
+
if (!hooks) throw new BindingError("INVALID_HOOK_SETTINGS");
|
|
22394
|
+
const start = hooks.SessionStart === void 0 ? [] : hooks.SessionStart;
|
|
22395
|
+
if (!Array.isArray(start)) throw new BindingError("INVALID_HOOK_SETTINGS");
|
|
22396
|
+
return { path, original, settings, hooks, start };
|
|
22397
|
+
}
|
|
22398
|
+
async function writeSettings(path, original, settings) {
|
|
22399
|
+
const suffix = randomUUID7();
|
|
22400
|
+
if (original !== void 0) await writeFile3(`${path}.sberpay-${suffix}.bak`, original, { flag: "wx", mode: 384 });
|
|
22401
|
+
const temp = `${path}.sberpay-${suffix}.tmp`;
|
|
22402
|
+
await writeFile3(temp, JSON.stringify(settings, null, 2) + "\n", { flag: "wx", mode: 384 });
|
|
22403
|
+
await rename6(temp, path);
|
|
22404
|
+
await chmod(path, 384);
|
|
22405
|
+
}
|
|
22406
|
+
async function updateClaudeHook(configDir, command) {
|
|
22407
|
+
let read;
|
|
22408
|
+
try {
|
|
22409
|
+
read = await readSettings(configDir, false);
|
|
22410
|
+
} catch (error62) {
|
|
22411
|
+
if (error62.code === "ENOENT") return "absent";
|
|
22412
|
+
throw error62;
|
|
22413
|
+
}
|
|
22414
|
+
const { path, original, settings, start } = read;
|
|
22415
|
+
if (original === void 0) return "absent";
|
|
22416
|
+
let found = false, changed = false;
|
|
22417
|
+
for (const entry of start) {
|
|
22418
|
+
const group = object2(entry);
|
|
22419
|
+
if (!group || !Array.isArray(group.hooks)) continue;
|
|
22420
|
+
for (const value of group.hooks) {
|
|
22421
|
+
const hook = object2(value);
|
|
22422
|
+
if (hook?.type !== "command" || typeof hook.command !== "string" || !hook.command.endsWith(HOOK_SUFFIX) || !hook.command.includes("sberpay-diagnostic")) continue;
|
|
22423
|
+
found = true;
|
|
22424
|
+
if (hook.command !== command) {
|
|
22425
|
+
hook.command = command;
|
|
22426
|
+
changed = true;
|
|
22427
|
+
}
|
|
22428
|
+
}
|
|
22429
|
+
}
|
|
22430
|
+
if (!found) return "absent";
|
|
22431
|
+
if (!changed) return "current";
|
|
22432
|
+
await writeSettings(path, original, settings);
|
|
22433
|
+
return "updated";
|
|
22434
|
+
}
|
|
22435
|
+
|
|
22350
22436
|
// packages/cli/src/setup/steps.ts
|
|
22351
22437
|
var MIN_NODE_MINOR = { 22: 19, 24: 5 };
|
|
22352
22438
|
var LAST_LISTED_MAJOR = 24;
|
|
@@ -22355,27 +22441,27 @@ var LAST_LISTED_MAJOR = 24;
|
|
|
22355
22441
|
import { constants as constants4 } from "node:fs";
|
|
22356
22442
|
import { pathToFileURL } from "node:url";
|
|
22357
22443
|
import { homedir as homedir3 } from "node:os";
|
|
22358
|
-
import { join as
|
|
22359
|
-
import { mkdir as
|
|
22360
|
-
import { createHash as createHash5, randomUUID as
|
|
22444
|
+
import { join as join11, resolve, dirname as dirname6 } from "node:path";
|
|
22445
|
+
import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile4, lstat as lstat6, rename as rename7, rm as rm6, cp, open as open8, chmod as chmod2 } from "node:fs/promises";
|
|
22446
|
+
import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
|
|
22361
22447
|
var hash3 = (text) => createHash5("sha256").update(text).digest("hex");
|
|
22362
22448
|
var Manifest2 = external_exports.object({ schemaVersion: external_exports.literal(1), buildId: external_exports.string().regex(/^[a-f0-9]{64}$/), setupHash: external_exports.string().regex(/^[a-f0-9]{64}$/).optional(), files: external_exports.record(external_exports.string(), external_exports.string().regex(/^[a-f0-9]{64}$/)) }).strict();
|
|
22363
22449
|
async function regular(path) {
|
|
22364
|
-
const s = await
|
|
22450
|
+
const s = await lstat6(path);
|
|
22365
22451
|
if (!s.isFile() || s.isSymbolicLink()) throw Error("UNSAFE_PACKAGE");
|
|
22366
22452
|
}
|
|
22367
22453
|
async function atomic(path, text, mode = 384) {
|
|
22368
|
-
const temp = path + "." +
|
|
22454
|
+
const temp = path + "." + randomUUID8() + ".tmp";
|
|
22369
22455
|
try {
|
|
22370
|
-
await
|
|
22371
|
-
await
|
|
22456
|
+
await writeFile4(temp, text, { flag: "wx", mode });
|
|
22457
|
+
await rename7(temp, path);
|
|
22372
22458
|
} finally {
|
|
22373
22459
|
await rm6(temp, { force: true });
|
|
22374
22460
|
}
|
|
22375
22461
|
}
|
|
22376
22462
|
async function installDiagnostic(source2, home = homedir3(), options = {}) {
|
|
22377
|
-
const root2 = privateDir2(
|
|
22378
|
-
return withInstallLock(root2, () => withPaymentLock(cliPaths({ SBERPAY_CLI_HOME:
|
|
22463
|
+
const root2 = privateDir2(join11(home, ".local", "share", "sberpay-diagnostic"));
|
|
22464
|
+
return withInstallLock(root2, () => withPaymentLock(cliPaths({ SBERPAY_CLI_HOME: join11(root2, "profile") }), () => installLocked(source2, home, options), true));
|
|
22379
22465
|
}
|
|
22380
22466
|
async function installLocked(source2, home, options) {
|
|
22381
22467
|
const enroll = typeof options === "function" ? options : options.enrollInvitation ?? enrollInvitation;
|
|
@@ -22383,15 +22469,15 @@ async function installLocked(source2, home, options) {
|
|
|
22383
22469
|
if (!(major > LAST_LISTED_MAJOR || MIN_NODE_MINOR[major] !== void 0 && minor >= MIN_NODE_MINOR[major])) throw Error("UNSUPPORTED_RUNTIME");
|
|
22384
22470
|
source2 = resolve(source2);
|
|
22385
22471
|
try {
|
|
22386
|
-
const info = JSON.parse(await
|
|
22472
|
+
const info = JSON.parse(await readFile3(join11(source2, "build-info.json"), "utf8"));
|
|
22387
22473
|
if (info.profile !== "diagnostic" || info.stateFormat !== 2) throw Error();
|
|
22388
22474
|
} catch {
|
|
22389
22475
|
throw Error("INCOMPATIBLE_STATE_FORMAT");
|
|
22390
22476
|
}
|
|
22391
|
-
const packageRoot =
|
|
22392
|
-
await regular(
|
|
22393
|
-
const manifest = Manifest2.parse(JSON.parse(await
|
|
22394
|
-
if (manifest.setupHash && hash3(await
|
|
22477
|
+
const packageRoot = join11(source2, "package");
|
|
22478
|
+
await regular(join11(source2, "manifest.json"));
|
|
22479
|
+
const manifest = Manifest2.parse(JSON.parse(await readFile3(join11(source2, "manifest.json"), "utf8")));
|
|
22480
|
+
if (manifest.setupHash && hash3(await readFile3(join11(source2, "dist/npm-entry.mjs"))) !== manifest.setupHash) throw Error("PACKAGE_HASH_MISMATCH");
|
|
22395
22481
|
const entries = Object.entries(manifest.files);
|
|
22396
22482
|
if (entries.length < 2 || entries.length > 1e3 || !manifest.files["dist/cli.mjs"] || !manifest.files["bin/sberpay-cli.mjs"] || !manifest.files["skill/sberpay/SKILL.md"]) throw Error("INVALID_MANIFEST");
|
|
22397
22483
|
for (const [path, digest] of entries) {
|
|
@@ -22399,17 +22485,17 @@ async function installLocked(source2, home, options) {
|
|
|
22399
22485
|
let cursor = packageRoot;
|
|
22400
22486
|
const parts = path.split("/");
|
|
22401
22487
|
for (const part of parts.slice(0, -1)) {
|
|
22402
|
-
cursor =
|
|
22403
|
-
const s = await
|
|
22488
|
+
cursor = join11(cursor, part);
|
|
22489
|
+
const s = await lstat6(cursor);
|
|
22404
22490
|
if (!s.isDirectory() || s.isSymbolicLink()) throw Error("UNSAFE_PACKAGE");
|
|
22405
22491
|
}
|
|
22406
|
-
await regular(
|
|
22407
|
-
if (hash3(await
|
|
22492
|
+
await regular(join11(packageRoot, path));
|
|
22493
|
+
if (hash3(await readFile3(join11(packageRoot, path))) !== digest) throw Error("PACKAGE_HASH_MISMATCH");
|
|
22408
22494
|
}
|
|
22409
22495
|
if (process.platform === "win32" && !manifest.files[`helpers/win32-${process.arch}/sberpay-tpm.exe`]) throw Error("WINDOWS_HELPER_NOT_PACKAGED");
|
|
22410
|
-
const root2 = privateDir2(
|
|
22411
|
-
const skill =
|
|
22412
|
-
const markerPath =
|
|
22496
|
+
const root2 = privateDir2(join11(home, ".local", "share", "sberpay-diagnostic"));
|
|
22497
|
+
const skill = join11(home, ".agents", "skills", "sberpay-diagnostic");
|
|
22498
|
+
const markerPath = join11(root2, "installed.json");
|
|
22413
22499
|
let prior;
|
|
22414
22500
|
try {
|
|
22415
22501
|
prior = JSON.parse((await privateRead(markerPath, 8192)).toString());
|
|
@@ -22418,20 +22504,20 @@ async function installLocked(source2, home, options) {
|
|
|
22418
22504
|
}
|
|
22419
22505
|
let pending;
|
|
22420
22506
|
try {
|
|
22421
|
-
pending = JSON.parse((await privateRead(
|
|
22507
|
+
pending = JSON.parse((await privateRead(join11(root2, "install-pending.json"), 1024 * 1024)).toString());
|
|
22422
22508
|
} catch (e) {
|
|
22423
22509
|
if (e.code !== "ENOENT") throw Error("INSTALLATION_STATE_INVALID");
|
|
22424
22510
|
}
|
|
22425
22511
|
if (pending && pending.buildId !== manifest.buildId) throw Error("INSTALLATION_CONFLICT");
|
|
22426
22512
|
if (prior?.stateFormat !== void 0 && ![1, 2].includes(prior.stateFormat)) throw Error("INCOMPATIBLE_STATE_FORMAT");
|
|
22427
|
-
const paymentPaths = cliPaths({ SBERPAY_CLI_HOME:
|
|
22513
|
+
const paymentPaths = cliPaths({ SBERPAY_CLI_HOME: join11(root2, "profile") });
|
|
22428
22514
|
const paymentModeFile = modeFile(paymentPaths);
|
|
22429
22515
|
let modeState;
|
|
22430
22516
|
if (prior?.stateFormat === 2) modeState = readPaymentMode(paymentPaths);
|
|
22431
22517
|
else {
|
|
22432
22518
|
let modeExists = false;
|
|
22433
22519
|
try {
|
|
22434
|
-
await
|
|
22520
|
+
await lstat6(paymentModeFile);
|
|
22435
22521
|
modeExists = true;
|
|
22436
22522
|
} catch (e) {
|
|
22437
22523
|
if (e.code !== "ENOENT") throw e;
|
|
@@ -22443,18 +22529,18 @@ async function installLocked(source2, home, options) {
|
|
|
22443
22529
|
}
|
|
22444
22530
|
const acceptedPending = (path, digest) => pending?.files.some((f) => f.path === path && (f.before === digest || f.after === digest));
|
|
22445
22531
|
try {
|
|
22446
|
-
const info = await
|
|
22532
|
+
const info = await lstat6(skill);
|
|
22447
22533
|
if (!info.isDirectory() || info.isSymbolicLink()) throw Error("SKILL_MODIFIED");
|
|
22448
|
-
const text2 = await
|
|
22449
|
-
if (!acceptedPending(
|
|
22534
|
+
const text2 = await readFile3(join11(skill, "SKILL.md"), "utf8");
|
|
22535
|
+
if (!acceptedPending(join11(skill, "SKILL.md"), hash3(text2)) && (!prior || hash3(text2) !== prior.skillHash && hash3(text2) !== prior.previousSkillHash)) throw Error("SKILL_MODIFIED");
|
|
22450
22536
|
} catch (error62) {
|
|
22451
22537
|
if (error62.code !== "ENOENT") throw error62;
|
|
22452
22538
|
}
|
|
22453
|
-
const releases = privateDir2(
|
|
22454
|
-
const release =
|
|
22539
|
+
const releases = privateDir2(join11(root2, "releases"));
|
|
22540
|
+
const release = join11(releases, manifest.buildId);
|
|
22455
22541
|
let exists = false;
|
|
22456
22542
|
try {
|
|
22457
|
-
const info = await
|
|
22543
|
+
const info = await lstat6(release);
|
|
22458
22544
|
if (!info.isDirectory() || info.isSymbolicLink()) throw Error("UNSAFE_RELEASE");
|
|
22459
22545
|
exists = true;
|
|
22460
22546
|
} catch (error62) {
|
|
@@ -22464,64 +22550,64 @@ async function installLocked(source2, home, options) {
|
|
|
22464
22550
|
for (const [path, digest] of entries) {
|
|
22465
22551
|
let cursor = release;
|
|
22466
22552
|
for (const part of path.split("/").slice(0, -1)) {
|
|
22467
|
-
cursor =
|
|
22468
|
-
const info = await
|
|
22553
|
+
cursor = join11(cursor, part);
|
|
22554
|
+
const info = await lstat6(cursor);
|
|
22469
22555
|
if (!info.isDirectory() || info.isSymbolicLink()) throw Error("UNSAFE_RELEASE");
|
|
22470
22556
|
}
|
|
22471
|
-
await regular(
|
|
22472
|
-
if (hash3(await
|
|
22557
|
+
await regular(join11(release, path));
|
|
22558
|
+
if (hash3(await readFile3(join11(release, path))) !== digest) throw Error("RELEASE_MODIFIED");
|
|
22473
22559
|
}
|
|
22474
22560
|
} else {
|
|
22475
|
-
const staged =
|
|
22476
|
-
await
|
|
22561
|
+
const staged = join11(releases, ".staging-" + randomUUID8());
|
|
22562
|
+
await mkdir5(staged, { mode: 448 });
|
|
22477
22563
|
try {
|
|
22478
22564
|
for (const [path] of entries) {
|
|
22479
|
-
const target =
|
|
22480
|
-
await
|
|
22481
|
-
await cp(
|
|
22482
|
-
await
|
|
22565
|
+
const target = join11(staged, path);
|
|
22566
|
+
await mkdir5(dirname6(target), { recursive: true, mode: 448 });
|
|
22567
|
+
await cp(join11(packageRoot, path), target, { force: false, errorOnExist: true });
|
|
22568
|
+
await chmod2(target, /^helpers\/[^/]+\/sberpay-(se|tpm)(\.exe)?$/.test(path) ? 448 : 384);
|
|
22483
22569
|
}
|
|
22484
|
-
await
|
|
22570
|
+
await rename7(staged, release);
|
|
22485
22571
|
} finally {
|
|
22486
22572
|
await rm6(staged, { recursive: true, force: true });
|
|
22487
22573
|
}
|
|
22488
22574
|
}
|
|
22489
|
-
const profile = privateDir2(
|
|
22575
|
+
const profile = privateDir2(join11(root2, "profile"));
|
|
22490
22576
|
let hasInvitation = false;
|
|
22491
22577
|
try {
|
|
22492
|
-
await regular(
|
|
22578
|
+
await regular(join11(source2, "invitation.json"));
|
|
22493
22579
|
hasInvitation = true;
|
|
22494
22580
|
} catch (error62) {
|
|
22495
22581
|
if (error62.code !== "ENOENT") throw error62;
|
|
22496
22582
|
}
|
|
22497
22583
|
if (hasInvitation) {
|
|
22498
|
-
const invitationFile = await
|
|
22584
|
+
const invitationFile = await open8(join11(source2, "invitation.json"), constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
22499
22585
|
try {
|
|
22500
22586
|
const info = await invitationFile.stat();
|
|
22501
22587
|
if (!info.isFile() || process.getuid && info.uid !== process.getuid()) throw Error("UNSAFE_INVITATION");
|
|
22502
|
-
if (process.platform === "win32") assertWindowsPrivatePath(
|
|
22588
|
+
if (process.platform === "win32") assertWindowsPrivatePath(join11(source2, "invitation.json"));
|
|
22503
22589
|
else await invitationFile.chmod(384);
|
|
22504
22590
|
} finally {
|
|
22505
22591
|
await invitationFile.close();
|
|
22506
22592
|
}
|
|
22507
|
-
await enroll(
|
|
22593
|
+
await enroll(join11(source2, "invitation.json"), { ...process.env, SBERPAY_CLI_HOME: profile });
|
|
22508
22594
|
} else {
|
|
22509
22595
|
let hasCredential = false;
|
|
22510
22596
|
try {
|
|
22511
|
-
await regular(
|
|
22597
|
+
await regular(join11(profile, "config", "report-upload.json"));
|
|
22512
22598
|
hasCredential = true;
|
|
22513
22599
|
} catch (e) {
|
|
22514
22600
|
if (e.code !== "ENOENT") throw e;
|
|
22515
22601
|
}
|
|
22516
22602
|
if (hasCredential) {
|
|
22517
22603
|
try {
|
|
22518
|
-
external_exports.object({ endpoint: external_exports.literal(DIAGNOSTIC_ENDPOINT), token: external_exports.string().min(32).max(512).regex(/^[A-Za-z0-9_-]+$/) }).strict().parse(JSON.parse((await privateRead(
|
|
22604
|
+
external_exports.object({ endpoint: external_exports.literal(DIAGNOSTIC_ENDPOINT), token: external_exports.string().min(32).max(512).regex(/^[A-Za-z0-9_-]+$/) }).strict().parse(JSON.parse((await privateRead(join11(profile, "config", "report-upload.json"), 16384)).toString()));
|
|
22519
22605
|
} catch {
|
|
22520
22606
|
throw Error("ENROLLMENT_REQUIRED");
|
|
22521
22607
|
}
|
|
22522
22608
|
} else await (typeof options === "function" ? enrollOpen : options.enrollOpen ?? enrollOpen)({ ...process.env, SBERPAY_CLI_HOME: profile });
|
|
22523
22609
|
}
|
|
22524
|
-
const configFile =
|
|
22610
|
+
const configFile = join11(privateDir2(join11(profile, "config")), "config.json");
|
|
22525
22611
|
let config2 = { stand: "prod", stands: {} };
|
|
22526
22612
|
try {
|
|
22527
22613
|
config2 = JSON.parse((await privateRead(configFile, 65536)).toString());
|
|
@@ -22534,45 +22620,46 @@ async function installLocked(source2, home, options) {
|
|
|
22534
22620
|
config2.stands[stand].merchantsUrl ??= "https://aiplatilka.ru/aim/aipay/gw/agent/api/v1";
|
|
22535
22621
|
}
|
|
22536
22622
|
await atomic(configFile, JSON.stringify(config2));
|
|
22537
|
-
const launcher =
|
|
22623
|
+
const launcher = join11(privateDir2(join11(root2, "bin")), "sberpay-cli-diagnostic.mjs");
|
|
22538
22624
|
const launcherText = `#!/usr/bin/env node
|
|
22539
22625
|
import {existsSync,readFileSync} from "node:fs";
|
|
22540
|
-
if(existsSync(${JSON.stringify(
|
|
22626
|
+
if(existsSync(${JSON.stringify(join11(root2, "install-pending.json"))})){console.log(JSON.stringify({status:"not_ready",code:"INSTALL_IN_PROGRESS"}));process.exit(4);}
|
|
22541
22627
|
try{const marker=JSON.parse(readFileSync(${JSON.stringify(markerPath)},"utf8"));if(marker.stateFormat!==2||marker.buildId!==${JSON.stringify(manifest.buildId)})throw Error();}catch{console.log(JSON.stringify({status:"not_ready",code:"SETUP_REQUIRED"}));process.exit(4);}
|
|
22542
22628
|
process.env.SBERPAY_CLI_HOME=${JSON.stringify(profile)};
|
|
22543
22629
|
process.env.SBERPAY_DIAGNOSTIC_CAPTURE="1";
|
|
22544
|
-
|
|
22630
|
+
process.env.SBERPAY_DIAGNOSTIC_LAUNCHER=${JSON.stringify(launcher)};
|
|
22631
|
+
await import(${JSON.stringify(pathToFileURL(join11(release, "bin", "sberpay-cli.mjs")).href)});
|
|
22545
22632
|
`;
|
|
22546
|
-
const original = await
|
|
22633
|
+
const original = await readFile3(join11(release, "skill", "sberpay", "SKILL.md"), "utf8");
|
|
22547
22634
|
const text = renderDiagnosticSkill(original, process.platform, launcher, process.execPath);
|
|
22548
22635
|
if (process.platform === "win32") privateDir2(skill);
|
|
22549
22636
|
else {
|
|
22550
|
-
await
|
|
22551
|
-
await
|
|
22637
|
+
await mkdir5(dirname6(skill), { recursive: true, mode: 448 });
|
|
22638
|
+
await mkdir5(skill, { mode: 448 }).catch((e) => {
|
|
22552
22639
|
if (e.code !== "EEXIST") throw e;
|
|
22553
22640
|
});
|
|
22554
22641
|
}
|
|
22555
|
-
const managed = [{ path: paymentModeFile, text: JSON.stringify(modeState), mode: 384 }, { path: launcher, text: launcherText, mode: 448 }, { path:
|
|
22642
|
+
const managed = [{ path: paymentModeFile, text: JSON.stringify(modeState), mode: 384 }, { path: launcher, text: launcherText, mode: 448 }, { path: join11(skill, "SKILL.md"), text, mode: 384 }];
|
|
22556
22643
|
for (const [path] of entries) {
|
|
22557
22644
|
if (!path.startsWith("skill/sberpay/") || path === "skill/sberpay/SKILL.md") continue;
|
|
22558
22645
|
const rel = path.slice("skill/sberpay/".length);
|
|
22559
22646
|
let cursor = skill;
|
|
22560
22647
|
for (const part of rel.split("/").slice(0, -1)) {
|
|
22561
|
-
cursor =
|
|
22562
|
-
await
|
|
22648
|
+
cursor = join11(cursor, part);
|
|
22649
|
+
await mkdir5(cursor, { mode: 448 }).catch((e) => {
|
|
22563
22650
|
if (e.code !== "EEXIST") throw e;
|
|
22564
22651
|
});
|
|
22565
|
-
const info = await
|
|
22652
|
+
const info = await lstat6(cursor);
|
|
22566
22653
|
if (!info.isDirectory() || info.isSymbolicLink()) throw Error("UNSAFE_SKILL_PATH");
|
|
22567
22654
|
}
|
|
22568
|
-
const target =
|
|
22655
|
+
const target = join11(skill, rel);
|
|
22569
22656
|
try {
|
|
22570
22657
|
await regular(target);
|
|
22571
|
-
const current = hash3(await
|
|
22658
|
+
const current = hash3(await readFile3(target, "utf8"));
|
|
22572
22659
|
let expected = prior?.skillFiles?.[rel];
|
|
22573
22660
|
if (!expected && prior?.buildId) {
|
|
22574
22661
|
try {
|
|
22575
|
-
expected = hash3(await
|
|
22662
|
+
expected = hash3(await readFile3(join11(releases, prior.buildId, "skill/sberpay", rel), "utf8"));
|
|
22576
22663
|
} catch {
|
|
22577
22664
|
}
|
|
22578
22665
|
}
|
|
@@ -22580,7 +22667,7 @@ await import(${JSON.stringify(pathToFileURL(join10(release, "bin", "sberpay-cli.
|
|
|
22580
22667
|
} catch (e) {
|
|
22581
22668
|
if (e.code !== "ENOENT") throw e;
|
|
22582
22669
|
}
|
|
22583
|
-
managed.push({ path: target, text: await
|
|
22670
|
+
managed.push({ path: target, text: await readFile3(join11(release, path), "utf8"), mode: 384 });
|
|
22584
22671
|
}
|
|
22585
22672
|
const skillFiles = skillFileHashes(skill, managed);
|
|
22586
22673
|
const marker = { buildId: manifest.buildId, stateFormat: 2, skillHash: hash3(text), skillFiles, launcher, profile };
|
|
@@ -22590,27 +22677,29 @@ await import(${JSON.stringify(pathToFileURL(join10(release, "bin", "sberpay-cli.
|
|
|
22590
22677
|
if (sender.status === "needs_activation") throw Error("SENDER_ACTIVATION_REQUIRED");
|
|
22591
22678
|
await durableWrite(markerPath, JSON.stringify(marker));
|
|
22592
22679
|
});
|
|
22593
|
-
|
|
22680
|
+
const claudeConfig = home === homedir3() && process.env.CLAUDE_CONFIG_DIR ? process.env.CLAUDE_CONFIG_DIR : join11(home, ".claude");
|
|
22681
|
+
const claudeHook = await updateClaudeHook(claudeConfig, claudeHookCommandFor([process.execPath, launcher])).catch(() => "skipped");
|
|
22682
|
+
return { status: "ready", profile: "diagnostic", buildId: manifest.buildId, launcher, skill, sender, claudeHook };
|
|
22594
22683
|
}
|
|
22595
22684
|
|
|
22596
22685
|
// scripts/diagnostics/npm-entry.mts
|
|
22597
22686
|
var source = dirname7(dirname7(fileURLToPath2(import.meta.url)));
|
|
22598
|
-
var root =
|
|
22687
|
+
var root = join12(homedir4(), ".local/share/sberpay-diagnostic");
|
|
22599
22688
|
try {
|
|
22600
22689
|
if (process.argv[2] === "setup") {
|
|
22601
22690
|
if (process.argv.slice(3).some((x) => x !== "--json")) throw Error("INVALID_SETUP_ARGUMENT");
|
|
22602
22691
|
const result = await installDiagnostic(source);
|
|
22603
22692
|
console.log(JSON.stringify(result));
|
|
22604
22693
|
} else {
|
|
22605
|
-
const manifest = JSON.parse(await
|
|
22694
|
+
const manifest = JSON.parse(await readFile4(join12(source, "manifest.json"), "utf8"));
|
|
22606
22695
|
let marker;
|
|
22607
22696
|
try {
|
|
22608
|
-
marker = JSON.parse(await
|
|
22697
|
+
marker = JSON.parse(await readFile4(join12(root, "installed.json"), "utf8"));
|
|
22609
22698
|
} catch {
|
|
22610
22699
|
throw Error("SETUP_REQUIRED");
|
|
22611
22700
|
}
|
|
22612
22701
|
if (marker.stateFormat !== 2 || marker.buildId !== manifest.buildId) throw Error("SETUP_REQUIRED");
|
|
22613
|
-
await import(pathToFileURL2(
|
|
22702
|
+
await import(pathToFileURL2(join12(root, "bin/sberpay-cli-diagnostic.mjs")).href);
|
|
22614
22703
|
}
|
|
22615
22704
|
} catch (e) {
|
|
22616
22705
|
console.log(JSON.stringify({ status: "not_ready", code: e.message, hint: "\u0412\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u0435 sberpay-cli-diagnostic setup --json; \u043F\u0440\u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u043C \u043E\u0442\u043A\u0430\u0437\u0435 \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u0435 \u043A\u043E\u0434 \u043E\u0448\u0438\u0431\u043A\u0438." }));
|