@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 CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "profile": "diagnostic",
3
- "version": "0.4.0-dev.8",
4
- "sourceCommit": "7f4bbd2ecf2ceb9eec2d043b2487863d9a74e578",
5
- "sourceTreeDigest": "2e19606a8b85f5779342801793be1b04f45b0f2724fdbee7afc5b7560d25dcb1",
3
+ "version": "0.4.0-dev.9",
4
+ "sourceCommit": "db0ec0c6594c1d28d55158cde8f6e5d564251e46",
5
+ "sourceTreeDigest": "5f12d63abb08dee373fbdd3ffd173836b8efbaa8d84886af05d5e85c3401db46",
6
6
  "snapshot": false,
7
- "buildId": "ca3e76623fce6cdcefb29c8b9ca5e70ceba2d0b755fe54d14205484c89ffac7e",
7
+ "buildId": "81921baa6ca1b7998a4feb445c67515af5251419e7bd514bc95dd70384c32abd",
8
8
  "stateFormat": 2
9
9
  }
@@ -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 rename7(from, to, cb) {
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(rename7, fs$rename);
130
- return rename7;
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 = readFile4;
535
- function readFile4(path, options, cb) {
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 = writeFile4;
552
- function writeFile4(path, data, options, cb) {
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
- open8(that.path, that.flags, that.mode, function(err, fd) {
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
- open8(that.path, that.flags, that.mode, function(err, fd) {
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 = open8;
749
- function open8(path, flags, mode, cb) {
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 readFile3 } from "node:fs/promises";
1621
- import { dirname as dirname7, join as join11 } from "node:path";
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(object2, key, getter) {
2351
+ function defineLazy(object3, key, getter) {
2352
2352
  let value = void 0;
2353
- Object.defineProperty(object2, key, {
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(object2, key, {
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 object2 of objects) {
17433
- for (const key in object2.properties) {
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 object2.required ?? [])
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((object2) => object2.additionalProperties === false)) {
17453
+ if (objects.every((object3) => object3.additionalProperties === false)) {
17454
17454
  folded.additionalProperties = false;
17455
17455
  } else {
17456
17456
  const constraints = [];
17457
- for (const object2 of objects) {
17458
- const constraint = undeclaredConstraint(object2);
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. \u0414\u043B\u044F Claude Code SessionStart hook \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F Git Bash; CLAUDE_ENV_FILE \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 Bash export, \u0430 \u043D\u0435 PowerShell.\n" : "");
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({ name: "SberPay.Diagnostic." + createHash4("sha256").update(launcher.toLowerCase()).digest("hex").slice(0, 24), node: node2, launcher, arguments: windowsArgument(launcher) + " report flush --json" }) };
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=$c.node
22263
- $action.Arguments=$c.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 $c.node -or $d.Actions.Item(1).Arguments -cne $c.arguments -or $d.Triggers.Count -ne 2 -or $d.Triggers.Item(1).Repetition.Interval -ne 'PT5M'){throw 'SENDER_TASK_NOT_ACTIVE'}
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 join10, resolve, dirname as dirname6 } from "node:path";
22359
- import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile3, lstat as lstat5, rename as rename6, rm as rm6, cp, open as open7, chmod } from "node:fs/promises";
22360
- import { createHash as createHash5, randomUUID as randomUUID7 } from "node:crypto";
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 lstat5(path);
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 + "." + randomUUID7() + ".tmp";
22454
+ const temp = path + "." + randomUUID8() + ".tmp";
22369
22455
  try {
22370
- await writeFile3(temp, text, { flag: "wx", mode });
22371
- await rename6(temp, path);
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(join10(home, ".local", "share", "sberpay-diagnostic"));
22378
- return withInstallLock(root2, () => withPaymentLock(cliPaths({ SBERPAY_CLI_HOME: join10(root2, "profile") }), () => installLocked(source2, home, options), true));
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 readFile2(join10(source2, "build-info.json"), "utf8"));
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 = join10(source2, "package");
22392
- await regular(join10(source2, "manifest.json"));
22393
- const manifest = Manifest2.parse(JSON.parse(await readFile2(join10(source2, "manifest.json"), "utf8")));
22394
- if (manifest.setupHash && hash3(await readFile2(join10(source2, "dist/npm-entry.mjs"))) !== manifest.setupHash) throw Error("PACKAGE_HASH_MISMATCH");
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 = join10(cursor, part);
22403
- const s = await lstat5(cursor);
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(join10(packageRoot, path));
22407
- if (hash3(await readFile2(join10(packageRoot, path))) !== digest) throw Error("PACKAGE_HASH_MISMATCH");
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(join10(home, ".local", "share", "sberpay-diagnostic"));
22411
- const skill = join10(home, ".agents", "skills", "sberpay-diagnostic");
22412
- const markerPath = join10(root2, "installed.json");
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(join10(root2, "install-pending.json"), 1024 * 1024)).toString());
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: join10(root2, "profile") });
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 lstat5(paymentModeFile);
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 lstat5(skill);
22532
+ const info = await lstat6(skill);
22447
22533
  if (!info.isDirectory() || info.isSymbolicLink()) throw Error("SKILL_MODIFIED");
22448
- const text2 = await readFile2(join10(skill, "SKILL.md"), "utf8");
22449
- if (!acceptedPending(join10(skill, "SKILL.md"), hash3(text2)) && (!prior || hash3(text2) !== prior.skillHash && hash3(text2) !== prior.previousSkillHash)) throw Error("SKILL_MODIFIED");
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(join10(root2, "releases"));
22454
- const release = join10(releases, manifest.buildId);
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 lstat5(release);
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 = join10(cursor, part);
22468
- const info = await lstat5(cursor);
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(join10(release, path));
22472
- if (hash3(await readFile2(join10(release, path))) !== digest) throw Error("RELEASE_MODIFIED");
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 = join10(releases, ".staging-" + randomUUID7());
22476
- await mkdir4(staged, { mode: 448 });
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 = join10(staged, path);
22480
- await mkdir4(dirname6(target), { recursive: true, mode: 448 });
22481
- await cp(join10(packageRoot, path), target, { force: false, errorOnExist: true });
22482
- await chmod(target, /^helpers\/[^/]+\/sberpay-(se|tpm)(\.exe)?$/.test(path) ? 448 : 384);
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 rename6(staged, release);
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(join10(root2, "profile"));
22575
+ const profile = privateDir2(join11(root2, "profile"));
22490
22576
  let hasInvitation = false;
22491
22577
  try {
22492
- await regular(join10(source2, "invitation.json"));
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 open7(join10(source2, "invitation.json"), constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
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(join10(source2, "invitation.json"));
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(join10(source2, "invitation.json"), { ...process.env, SBERPAY_CLI_HOME: profile });
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(join10(profile, "config", "report-upload.json"));
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(join10(profile, "config", "report-upload.json"), 16384)).toString()));
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 = join10(privateDir2(join10(profile, "config")), "config.json");
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 = join10(privateDir2(join10(root2, "bin")), "sberpay-cli-diagnostic.mjs");
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(join10(root2, "install-pending.json"))})){console.log(JSON.stringify({status:"not_ready",code:"INSTALL_IN_PROGRESS"}));process.exit(4);}
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
- await import(${JSON.stringify(pathToFileURL(join10(release, "bin", "sberpay-cli.mjs")).href)});
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 readFile2(join10(release, "skill", "sberpay", "SKILL.md"), "utf8");
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 mkdir4(dirname6(skill), { recursive: true, mode: 448 });
22551
- await mkdir4(skill, { mode: 448 }).catch((e) => {
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: join10(skill, "SKILL.md"), text, mode: 384 }];
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 = join10(cursor, part);
22562
- await mkdir4(cursor, { mode: 448 }).catch((e) => {
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 lstat5(cursor);
22652
+ const info = await lstat6(cursor);
22566
22653
  if (!info.isDirectory() || info.isSymbolicLink()) throw Error("UNSAFE_SKILL_PATH");
22567
22654
  }
22568
- const target = join10(skill, rel);
22655
+ const target = join11(skill, rel);
22569
22656
  try {
22570
22657
  await regular(target);
22571
- const current = hash3(await readFile2(target, "utf8"));
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 readFile2(join10(releases, prior.buildId, "skill/sberpay", rel), "utf8"));
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 readFile2(join10(release, path), "utf8"), mode: 384 });
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
- return { status: "ready", profile: "diagnostic", buildId: manifest.buildId, launcher, skill, sender };
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 = join11(homedir4(), ".local/share/sberpay-diagnostic");
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 readFile3(join11(source, "manifest.json"), "utf8"));
22694
+ const manifest = JSON.parse(await readFile4(join12(source, "manifest.json"), "utf8"));
22606
22695
  let marker;
22607
22696
  try {
22608
- marker = JSON.parse(await readFile3(join11(root, "installed.json"), "utf8"));
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(join11(root, "bin/sberpay-cli-diagnostic.mjs")).href);
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." }));