shortcutxl 0.3.57 → 0.3.59
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/BINARY-INVENTORY.json +9 -9
- package/CHANGELOG.md +4 -0
- package/dist/cli.js +209 -147
- package/dist/main.js +9 -1
- package/dist/startup/python-abi.d.ts +3 -0
- package/dist/startup/python-abi.js +32 -0
- package/dist/startup/sync-xll.js +3 -28
- package/dist/startup/update-action.d.ts +7 -3
- package/dist/startup/update-action.js +78 -6
- package/package.json +1 -1
- package/user-docs/dist/shortcutxl-docs.pdf +0 -0
- package/xll/ShortcutXL.xll +0 -0
- package/xll/python/Lib/site-packages/httpx-0.28.1.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/idna-3.18.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/pip-26.1.2.dist-info/RECORD +3 -3
- package/xll/python/Lib/site-packages/pywin32-311.dist-info/RECORD +2 -2
- package/xll/python/Scripts/httpx.exe +0 -0
- package/xll/python/Scripts/idna.exe +0 -0
- package/xll/python/Scripts/pip.exe +0 -0
- package/xll/python/Scripts/pip3.13.exe +0 -0
- package/xll/python/Scripts/pip3.exe +0 -0
- package/xll/python/Scripts/pywin32_postinstall.exe +0 -0
- package/xll/python/Scripts/pywin32_testall.exe +0 -0
package/BINARY-INVENTORY.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-03T05:23:21.387Z",
|
|
4
4
|
"package": "shortcutxl",
|
|
5
5
|
"binaryExtensions": [
|
|
6
6
|
".dll",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
{
|
|
13
13
|
"path": "xll/ShortcutXL.xll",
|
|
14
|
-
"sha256": "
|
|
14
|
+
"sha256": "3852e0b282c00d510c51da0501cac4971f335d4c99dba6272f15b335ad5068fd",
|
|
15
15
|
"source": "ShortcutXL native XLL build",
|
|
16
16
|
"version": "package",
|
|
17
17
|
"builtBy": "shortcut",
|
|
@@ -523,7 +523,7 @@
|
|
|
523
523
|
},
|
|
524
524
|
{
|
|
525
525
|
"path": "xll/python/Scripts/httpx.exe",
|
|
526
|
-
"sha256": "
|
|
526
|
+
"sha256": "84a59a562fcdd84adaa995aba93673f883ad1b3dc06708fcb268ea3275f839cd",
|
|
527
527
|
"source": "httpx console launcher installed into embedded Python",
|
|
528
528
|
"version": "see packaged httpx distribution",
|
|
529
529
|
"builtBy": "third-party",
|
|
@@ -531,7 +531,7 @@
|
|
|
531
531
|
},
|
|
532
532
|
{
|
|
533
533
|
"path": "xll/python/Scripts/idna.exe",
|
|
534
|
-
"sha256": "
|
|
534
|
+
"sha256": "a5bd06e740a8c4af1bd8d7883efc7ad16b0b2151b2a9e59ef6d64282c164a56b",
|
|
535
535
|
"source": "Python package console launcher installed into embedded Python",
|
|
536
536
|
"version": "see owning Python package metadata in site-packages",
|
|
537
537
|
"builtBy": "third-party",
|
|
@@ -539,7 +539,7 @@
|
|
|
539
539
|
},
|
|
540
540
|
{
|
|
541
541
|
"path": "xll/python/Scripts/pip.exe",
|
|
542
|
-
"sha256": "
|
|
542
|
+
"sha256": "2e4bed34ea1c99aee03259cf79f1fd9a56a9900cafd7ecb60c818c45e1125533",
|
|
543
543
|
"source": "pip console launcher installed into embedded Python",
|
|
544
544
|
"version": "see packaged pip distribution",
|
|
545
545
|
"builtBy": "third-party",
|
|
@@ -547,7 +547,7 @@
|
|
|
547
547
|
},
|
|
548
548
|
{
|
|
549
549
|
"path": "xll/python/Scripts/pip3.13.exe",
|
|
550
|
-
"sha256": "
|
|
550
|
+
"sha256": "2e4bed34ea1c99aee03259cf79f1fd9a56a9900cafd7ecb60c818c45e1125533",
|
|
551
551
|
"source": "pip console launcher installed into embedded Python",
|
|
552
552
|
"version": "see packaged pip distribution",
|
|
553
553
|
"builtBy": "third-party",
|
|
@@ -555,7 +555,7 @@
|
|
|
555
555
|
},
|
|
556
556
|
{
|
|
557
557
|
"path": "xll/python/Scripts/pip3.exe",
|
|
558
|
-
"sha256": "
|
|
558
|
+
"sha256": "2e4bed34ea1c99aee03259cf79f1fd9a56a9900cafd7ecb60c818c45e1125533",
|
|
559
559
|
"source": "pip console launcher installed into embedded Python",
|
|
560
560
|
"version": "see packaged pip distribution",
|
|
561
561
|
"builtBy": "third-party",
|
|
@@ -563,7 +563,7 @@
|
|
|
563
563
|
},
|
|
564
564
|
{
|
|
565
565
|
"path": "xll/python/Scripts/pywin32_postinstall.exe",
|
|
566
|
-
"sha256": "
|
|
566
|
+
"sha256": "7c02775810d083f1e70a026c2ea80ea086373bdaac811a9a4f1c19dad9e54e6f",
|
|
567
567
|
"source": "Python package console launcher installed into embedded Python",
|
|
568
568
|
"version": "see owning Python package metadata in site-packages",
|
|
569
569
|
"builtBy": "third-party",
|
|
@@ -571,7 +571,7 @@
|
|
|
571
571
|
},
|
|
572
572
|
{
|
|
573
573
|
"path": "xll/python/Scripts/pywin32_testall.exe",
|
|
574
|
-
"sha256": "
|
|
574
|
+
"sha256": "ba14591c7c28b8e58a291040d70b0acff797598645abfc4f9eb4e2f3b6e0b9c7",
|
|
575
575
|
"source": "Python package console launcher installed into embedded Python",
|
|
576
576
|
"version": "see owning Python package metadata in site-packages",
|
|
577
577
|
"builtBy": "third-party",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.59]
|
|
4
|
+
|
|
5
|
+
- **Security and model updates** - Strengthened account policy checks and updated model routing/defaults.
|
|
6
|
+
|
|
3
7
|
## [0.3.57]
|
|
4
8
|
|
|
5
9
|
- **Improved Windows reliability** - Improved ShortcutXL install, upgrade, and uninstall behavior on Windows.
|
package/dist/cli.js
CHANGED
|
@@ -26528,7 +26528,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
26528
26528
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
|
|
26529
26529
|
"use strict";
|
|
26530
26530
|
var { writeFile: writeFile10, readFile: readFile11, mkdir: mkdir11 } = __require("node:fs/promises");
|
|
26531
|
-
var { dirname:
|
|
26531
|
+
var { dirname: dirname38, resolve: resolve22 } = __require("node:path");
|
|
26532
26532
|
var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
|
|
26533
26533
|
var { InvalidArgumentError, UndiciError } = require_errors();
|
|
26534
26534
|
var { hashId, isUrlExcludedFactory, normalizeHeaders: normalizeHeaders2, createHeaderFilters } = require_snapshot_utils();
|
|
@@ -26759,7 +26759,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
26759
26759
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
26760
26760
|
}
|
|
26761
26761
|
const resolvedPath = resolve22(path21);
|
|
26762
|
-
await mkdir11(
|
|
26762
|
+
await mkdir11(dirname38(resolvedPath), { recursive: true });
|
|
26763
26763
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
26764
26764
|
hash: hash2,
|
|
26765
26765
|
snapshot
|
|
@@ -167005,9 +167005,9 @@ var require_buffer_from = __commonJS({
|
|
|
167005
167005
|
}
|
|
167006
167006
|
});
|
|
167007
167007
|
|
|
167008
|
-
// ../../node_modules/.pnpm/source-map-support@0.5.
|
|
167008
|
+
// ../../node_modules/.pnpm/source-map-support@0.5.13/node_modules/source-map-support/source-map-support.js
|
|
167009
167009
|
var require_source_map_support = __commonJS({
|
|
167010
|
-
"../../node_modules/.pnpm/source-map-support@0.5.
|
|
167010
|
+
"../../node_modules/.pnpm/source-map-support@0.5.13/node_modules/source-map-support/source-map-support.js"(exports) {
|
|
167011
167011
|
var SourceMapConsumer = require_source_map().SourceMapConsumer;
|
|
167012
167012
|
var path21 = __require("path");
|
|
167013
167013
|
var fs16;
|
|
@@ -167019,9 +167019,6 @@ var require_source_map_support = __commonJS({
|
|
|
167019
167019
|
} catch (err) {
|
|
167020
167020
|
}
|
|
167021
167021
|
var bufferFrom = require_buffer_from();
|
|
167022
|
-
function dynamicRequire(mod, request) {
|
|
167023
|
-
return mod.require(request);
|
|
167024
|
-
}
|
|
167025
167022
|
var errorFormatterInstalled = false;
|
|
167026
167023
|
var uncaughtShimInstalled = false;
|
|
167027
167024
|
var emptyCacheBetweenOperations = false;
|
|
@@ -167041,23 +167038,6 @@ var require_source_map_support = __commonJS({
|
|
|
167041
167038
|
function hasGlobalProcessEventEmitter() {
|
|
167042
167039
|
return typeof process === "object" && process !== null && typeof process.on === "function";
|
|
167043
167040
|
}
|
|
167044
|
-
function globalProcessVersion() {
|
|
167045
|
-
if (typeof process === "object" && process !== null) {
|
|
167046
|
-
return process.version;
|
|
167047
|
-
} else {
|
|
167048
|
-
return "";
|
|
167049
|
-
}
|
|
167050
|
-
}
|
|
167051
|
-
function globalProcessStderr() {
|
|
167052
|
-
if (typeof process === "object" && process !== null) {
|
|
167053
|
-
return process.stderr;
|
|
167054
|
-
}
|
|
167055
|
-
}
|
|
167056
|
-
function globalProcessExit(code) {
|
|
167057
|
-
if (typeof process === "object" && process !== null && typeof process.exit === "function") {
|
|
167058
|
-
return process.exit(code);
|
|
167059
|
-
}
|
|
167060
|
-
}
|
|
167061
167041
|
function handlerExec(list2) {
|
|
167062
167042
|
return function(arg) {
|
|
167063
167043
|
for (var i2 = 0; i2 < list2.length; i2++) {
|
|
@@ -167282,20 +167262,15 @@ var require_source_map_support = __commonJS({
|
|
|
167282
167262
|
object3.toString = CallSiteToString;
|
|
167283
167263
|
return object3;
|
|
167284
167264
|
}
|
|
167285
|
-
function wrapCallSite(frame
|
|
167286
|
-
if (state === void 0) {
|
|
167287
|
-
state = { nextPosition: null, curPosition: null };
|
|
167288
|
-
}
|
|
167265
|
+
function wrapCallSite(frame) {
|
|
167289
167266
|
if (frame.isNative()) {
|
|
167290
|
-
state.curPosition = null;
|
|
167291
167267
|
return frame;
|
|
167292
167268
|
}
|
|
167293
167269
|
var source = frame.getFileName() || frame.getScriptNameOrSourceURL();
|
|
167294
167270
|
if (source) {
|
|
167295
167271
|
var line = frame.getLineNumber();
|
|
167296
167272
|
var column = frame.getColumnNumber() - 1;
|
|
167297
|
-
var
|
|
167298
|
-
var headerLength = noHeader.test(globalProcessVersion()) ? 0 : 62;
|
|
167273
|
+
var headerLength = 62;
|
|
167299
167274
|
if (line === 1 && column > headerLength && !isInBrowser() && !frame.isEval()) {
|
|
167300
167275
|
column -= headerLength;
|
|
167301
167276
|
}
|
|
@@ -167304,14 +167279,10 @@ var require_source_map_support = __commonJS({
|
|
|
167304
167279
|
line,
|
|
167305
167280
|
column
|
|
167306
167281
|
});
|
|
167307
|
-
state.curPosition = position;
|
|
167308
167282
|
frame = cloneCallSite(frame);
|
|
167309
167283
|
var originalFunctionName = frame.getFunctionName;
|
|
167310
167284
|
frame.getFunctionName = function() {
|
|
167311
|
-
|
|
167312
|
-
return originalFunctionName();
|
|
167313
|
-
}
|
|
167314
|
-
return state.nextPosition.name || originalFunctionName();
|
|
167285
|
+
return position.name || originalFunctionName();
|
|
167315
167286
|
};
|
|
167316
167287
|
frame.getFileName = function() {
|
|
167317
167288
|
return position.source;
|
|
@@ -167346,14 +167317,9 @@ var require_source_map_support = __commonJS({
|
|
|
167346
167317
|
var name = error2.name || "Error";
|
|
167347
167318
|
var message = error2.message || "";
|
|
167348
167319
|
var errorString = name + ": " + message;
|
|
167349
|
-
|
|
167350
|
-
|
|
167351
|
-
|
|
167352
|
-
processedStack.push("\n at " + wrapCallSite(stack[i2], state));
|
|
167353
|
-
state.nextPosition = state.curPosition;
|
|
167354
|
-
}
|
|
167355
|
-
state.curPosition = state.nextPosition = null;
|
|
167356
|
-
return errorString + processedStack.reverse().join("");
|
|
167320
|
+
return errorString + stack.map(function(frame) {
|
|
167321
|
+
return "\n at " + wrapCallSite(frame);
|
|
167322
|
+
}).join("");
|
|
167357
167323
|
}
|
|
167358
167324
|
function getErrorSource(error2) {
|
|
167359
167325
|
var match2 = /\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(error2.stack);
|
|
@@ -167380,16 +167346,15 @@ var require_source_map_support = __commonJS({
|
|
|
167380
167346
|
}
|
|
167381
167347
|
function printErrorAndExit(error2) {
|
|
167382
167348
|
var source = getErrorSource(error2);
|
|
167383
|
-
|
|
167384
|
-
|
|
167385
|
-
stderr._handle.setBlocking(true);
|
|
167349
|
+
if (process.stderr._handle && process.stderr._handle.setBlocking) {
|
|
167350
|
+
process.stderr._handle.setBlocking(true);
|
|
167386
167351
|
}
|
|
167387
167352
|
if (source) {
|
|
167388
167353
|
console.error();
|
|
167389
167354
|
console.error(source);
|
|
167390
167355
|
}
|
|
167391
167356
|
console.error(error2.stack);
|
|
167392
|
-
|
|
167357
|
+
process.exit(1);
|
|
167393
167358
|
}
|
|
167394
167359
|
function shimEmitUncaughtException() {
|
|
167395
167360
|
var origEmit = process.emit;
|
|
@@ -167431,7 +167396,11 @@ var require_source_map_support = __commonJS({
|
|
|
167431
167396
|
retrieveMapHandlers.unshift(options2.retrieveSourceMap);
|
|
167432
167397
|
}
|
|
167433
167398
|
if (options2.hookRequire && !isInBrowser()) {
|
|
167434
|
-
var Module2
|
|
167399
|
+
var Module2;
|
|
167400
|
+
try {
|
|
167401
|
+
Module2 = __require("module");
|
|
167402
|
+
} catch (err) {
|
|
167403
|
+
}
|
|
167435
167404
|
var $compile = Module2.prototype._compile;
|
|
167436
167405
|
if (!$compile.__sourceMapSupport) {
|
|
167437
167406
|
Module2.prototype._compile = function(content, filename) {
|
|
@@ -167451,13 +167420,6 @@ var require_source_map_support = __commonJS({
|
|
|
167451
167420
|
}
|
|
167452
167421
|
if (!uncaughtShimInstalled) {
|
|
167453
167422
|
var installHandler = "handleUncaughtExceptions" in options2 ? options2.handleUncaughtExceptions : true;
|
|
167454
|
-
try {
|
|
167455
|
-
var worker_threads = dynamicRequire(module, "worker_threads");
|
|
167456
|
-
if (worker_threads.isMainThread === false) {
|
|
167457
|
-
installHandler = false;
|
|
167458
|
-
}
|
|
167459
|
-
} catch (e2) {
|
|
167460
|
-
}
|
|
167461
167423
|
if (installHandler && hasGlobalProcessEventEmitter()) {
|
|
167462
167424
|
uncaughtShimInstalled = true;
|
|
167463
167425
|
shimEmitUncaughtException();
|
|
@@ -474819,13 +474781,46 @@ var init_shell = __esm({
|
|
|
474819
474781
|
}
|
|
474820
474782
|
});
|
|
474821
474783
|
|
|
474784
|
+
// src/startup/python-abi.ts
|
|
474785
|
+
import { existsSync as existsSync42, readdirSync as readdirSync12 } from "fs";
|
|
474786
|
+
function listVersionedPythonRuntimeFiles(pythonDir) {
|
|
474787
|
+
if (!existsSync42(pythonDir)) return /* @__PURE__ */ new Set();
|
|
474788
|
+
try {
|
|
474789
|
+
return new Set(
|
|
474790
|
+
readdirSync12(pythonDir).filter((entry) => VERSIONED_PYTHON_RUNTIME_FILE.test(entry)).map((entry) => entry.toLowerCase())
|
|
474791
|
+
);
|
|
474792
|
+
} catch {
|
|
474793
|
+
return /* @__PURE__ */ new Set();
|
|
474794
|
+
}
|
|
474795
|
+
}
|
|
474796
|
+
function hasVersionedPythonRuntimeFileDrift(sourcePythonDir, destPythonDir) {
|
|
474797
|
+
const sourceFiles = listVersionedPythonRuntimeFiles(sourcePythonDir);
|
|
474798
|
+
if (sourceFiles.size === 0) return false;
|
|
474799
|
+
const destFiles = listVersionedPythonRuntimeFiles(destPythonDir);
|
|
474800
|
+
if (destFiles.size === 0) return false;
|
|
474801
|
+
for (const file2 of destFiles) {
|
|
474802
|
+
if (!sourceFiles.has(file2)) return true;
|
|
474803
|
+
}
|
|
474804
|
+
for (const file2 of sourceFiles) {
|
|
474805
|
+
if (!destFiles.has(file2)) return true;
|
|
474806
|
+
}
|
|
474807
|
+
return false;
|
|
474808
|
+
}
|
|
474809
|
+
var VERSIONED_PYTHON_RUNTIME_FILE;
|
|
474810
|
+
var init_python_abi = __esm({
|
|
474811
|
+
"src/startup/python-abi.ts"() {
|
|
474812
|
+
"use strict";
|
|
474813
|
+
VERSIONED_PYTHON_RUNTIME_FILE = /^python\d{2,}(?:\.dll|\.zip|\._pth)$/i;
|
|
474814
|
+
}
|
|
474815
|
+
});
|
|
474816
|
+
|
|
474822
474817
|
// src/startup/sync-xll.ts
|
|
474823
474818
|
import { createHash as createHash3 } from "crypto";
|
|
474824
474819
|
import {
|
|
474825
474820
|
copyFileSync,
|
|
474826
|
-
existsSync as
|
|
474821
|
+
existsSync as existsSync43,
|
|
474827
474822
|
mkdirSync as mkdirSync20,
|
|
474828
|
-
readdirSync as
|
|
474823
|
+
readdirSync as readdirSync13,
|
|
474829
474824
|
readFileSync as readFileSync33,
|
|
474830
474825
|
rmSync as rmSync4,
|
|
474831
474826
|
statSync as statSync11,
|
|
@@ -474841,7 +474836,7 @@ function stripMotw(filePath) {
|
|
|
474841
474836
|
}
|
|
474842
474837
|
}
|
|
474843
474838
|
function filesMatch(src, dest) {
|
|
474844
|
-
if (!
|
|
474839
|
+
if (!existsSync43(dest)) return false;
|
|
474845
474840
|
const srcStat = statSync11(src);
|
|
474846
474841
|
const destStat = statSync11(dest);
|
|
474847
474842
|
return srcStat.size === destStat.size && srcStat.mtimeMs === destStat.mtimeMs;
|
|
@@ -474851,11 +474846,11 @@ function filesContentMatch(src, dest) {
|
|
|
474851
474846
|
return hash2(src) === hash2(dest);
|
|
474852
474847
|
}
|
|
474853
474848
|
function syncDir(src, dest) {
|
|
474854
|
-
if (!
|
|
474849
|
+
if (!existsSync43(src)) return { updated: 0, staleLocked: false };
|
|
474855
474850
|
mkdirSync20(dest, { recursive: true });
|
|
474856
474851
|
let updated = 0;
|
|
474857
474852
|
let staleLocked = false;
|
|
474858
|
-
for (const entry of
|
|
474853
|
+
for (const entry of readdirSync13(src)) {
|
|
474859
474854
|
const srcPath = join58(src, entry);
|
|
474860
474855
|
const destPath = join58(dest, entry);
|
|
474861
474856
|
const stat8 = statSync11(srcPath);
|
|
@@ -474886,28 +474881,8 @@ function syncDir(src, dest) {
|
|
|
474886
474881
|
}
|
|
474887
474882
|
return { updated, staleLocked };
|
|
474888
474883
|
}
|
|
474889
|
-
function listVersionedPythonRuntimeFiles(pythonDir) {
|
|
474890
|
-
if (!existsSync42(pythonDir)) return /* @__PURE__ */ new Set();
|
|
474891
|
-
try {
|
|
474892
|
-
return new Set(
|
|
474893
|
-
readdirSync12(pythonDir).filter((entry) => /^python\d{2,}(?:\.dll|\.zip|\._pth)$/i.test(entry)).map((entry) => entry.toLowerCase())
|
|
474894
|
-
);
|
|
474895
|
-
} catch {
|
|
474896
|
-
return /* @__PURE__ */ new Set();
|
|
474897
|
-
}
|
|
474898
|
-
}
|
|
474899
474884
|
function hasPythonAbiDrift(shippedDir, stableDir) {
|
|
474900
|
-
|
|
474901
|
-
if (shippedRuntimeFiles.size === 0) return false;
|
|
474902
|
-
const stableRuntimeFiles = listVersionedPythonRuntimeFiles(join58(stableDir, "python"));
|
|
474903
|
-
if (stableRuntimeFiles.size === 0) return false;
|
|
474904
|
-
for (const file2 of stableRuntimeFiles) {
|
|
474905
|
-
if (!shippedRuntimeFiles.has(file2)) return true;
|
|
474906
|
-
}
|
|
474907
|
-
for (const file2 of shippedRuntimeFiles) {
|
|
474908
|
-
if (!stableRuntimeFiles.has(file2)) return true;
|
|
474909
|
-
}
|
|
474910
|
-
return false;
|
|
474885
|
+
return hasVersionedPythonRuntimeFileDrift(join58(shippedDir, "python"), join58(stableDir, "python"));
|
|
474911
474886
|
}
|
|
474912
474887
|
function resetStablePythonRuntime(stableDir) {
|
|
474913
474888
|
try {
|
|
@@ -474937,11 +474912,11 @@ function syncXll() {
|
|
|
474937
474912
|
mkdirSync20(stableDir, { recursive: true });
|
|
474938
474913
|
const pythonRuntimeNeedsReset = hasPythonAbiDrift(shippedDir, stableDir);
|
|
474939
474914
|
try {
|
|
474940
|
-
if (
|
|
474915
|
+
if (existsSync43(versionFile)) {
|
|
474941
474916
|
const stamped = readFileSync33(versionFile, "utf-8").trim();
|
|
474942
474917
|
if (stamped === VERSION) {
|
|
474943
|
-
const xllReady2 =
|
|
474944
|
-
const shippedXllReady =
|
|
474918
|
+
const xllReady2 = existsSync43(stableXll);
|
|
474919
|
+
const shippedXllReady = existsSync43(shippedXll);
|
|
474945
474920
|
if (!pythonRuntimeNeedsReset && (!shippedXllReady || xllReady2 && filesContentMatch(shippedXll, stableXll))) {
|
|
474946
474921
|
return { updated: 0, stableDir, xllReady: xllReady2, skipped: true, staleLocked: false };
|
|
474947
474922
|
}
|
|
@@ -474956,11 +474931,11 @@ function syncXll() {
|
|
|
474956
474931
|
hasStaleLockedFiles = true;
|
|
474957
474932
|
syncFailed = true;
|
|
474958
474933
|
}
|
|
474959
|
-
if (
|
|
474934
|
+
if (existsSync43(shippedDir)) {
|
|
474960
474935
|
try {
|
|
474961
474936
|
const { updated, staleLocked } = syncDir(shippedDir, stableDir);
|
|
474962
474937
|
totalUpdated += updated;
|
|
474963
|
-
hasStaleLockedFiles = staleLocked;
|
|
474938
|
+
hasStaleLockedFiles = hasStaleLockedFiles || staleLocked;
|
|
474964
474939
|
if (staleLocked) {
|
|
474965
474940
|
console.warn(
|
|
474966
474941
|
"Warning: A ShortcutXL update is available but Excel has files locked. Please close Excel and restart the Shortcut agent to apply it."
|
|
@@ -474977,7 +474952,7 @@ function syncXll() {
|
|
|
474977
474952
|
} catch {
|
|
474978
474953
|
}
|
|
474979
474954
|
}
|
|
474980
|
-
const xllReady =
|
|
474955
|
+
const xllReady = existsSync43(stableXll);
|
|
474981
474956
|
return {
|
|
474982
474957
|
updated: totalUpdated,
|
|
474983
474958
|
stableDir,
|
|
@@ -474991,13 +474966,14 @@ var init_sync_xll = __esm({
|
|
|
474991
474966
|
"src/startup/sync-xll.ts"() {
|
|
474992
474967
|
"use strict";
|
|
474993
474968
|
init_config();
|
|
474969
|
+
init_python_abi();
|
|
474994
474970
|
SYNC_VERSION_FILE = ".sync-version";
|
|
474995
474971
|
PIP_VERSION_FILE = ".pip-version";
|
|
474996
474972
|
}
|
|
474997
474973
|
});
|
|
474998
474974
|
|
|
474999
474975
|
// src/startup/startup-xll.ts
|
|
475000
|
-
import { existsSync as
|
|
474976
|
+
import { existsSync as existsSync44 } from "fs";
|
|
475001
474977
|
import { join as join59 } from "path";
|
|
475002
474978
|
function getSourceCheckoutRequiredPaths() {
|
|
475003
474979
|
return [
|
|
@@ -475011,7 +474987,7 @@ function resolveStartupXll({
|
|
|
475011
474987
|
needsSetup
|
|
475012
474988
|
}) {
|
|
475013
474989
|
if (sourceCheckout) {
|
|
475014
|
-
const missingPaths = getSourceCheckoutRequiredPaths().filter((p2) => !
|
|
474990
|
+
const missingPaths = getSourceCheckoutRequiredPaths().filter((p2) => !existsSync44(p2));
|
|
475015
474991
|
return missingPaths.length === 0 ? { kind: "ok", updated: 0 } : { kind: "source-missing", missingPaths };
|
|
475016
474992
|
}
|
|
475017
474993
|
const result = syncXll();
|
|
@@ -475713,7 +475689,7 @@ var init_mog_command = __esm({
|
|
|
475713
475689
|
});
|
|
475714
475690
|
|
|
475715
475691
|
// src/app/permissions/permissions-command.ts
|
|
475716
|
-
import { existsSync as
|
|
475692
|
+
import { existsSync as existsSync45, statSync as statSync12 } from "fs";
|
|
475717
475693
|
import { join as join60 } from "path";
|
|
475718
475694
|
function getGlobalSettingsPath() {
|
|
475719
475695
|
return join60(getAgentDir(), "settings.json");
|
|
@@ -475724,7 +475700,7 @@ function normalizeWorkspaceRoot(input, cwd) {
|
|
|
475724
475700
|
return "Workspace path is required";
|
|
475725
475701
|
}
|
|
475726
475702
|
const resolved = resolveToCwd(trimmed, cwd);
|
|
475727
|
-
if (!
|
|
475703
|
+
if (!existsSync45(resolved)) {
|
|
475728
475704
|
return `Path does not exist: ${resolved}`;
|
|
475729
475705
|
}
|
|
475730
475706
|
try {
|
|
@@ -475746,7 +475722,7 @@ function normalizeFilesystemGrantPath(input, cwd, scope) {
|
|
|
475746
475722
|
return "Grant path is required";
|
|
475747
475723
|
}
|
|
475748
475724
|
const resolved = resolveToCwd(trimmed, cwd);
|
|
475749
|
-
if (!
|
|
475725
|
+
if (!existsSync45(resolved)) {
|
|
475750
475726
|
return `Path does not exist: ${resolved}`;
|
|
475751
475727
|
}
|
|
475752
475728
|
try {
|
|
@@ -476527,9 +476503,9 @@ var init_remote_skill_files = __esm({
|
|
|
476527
476503
|
// src/app/sync/skills-download.ts
|
|
476528
476504
|
import { createHash as createHash4 } from "crypto";
|
|
476529
476505
|
import {
|
|
476530
|
-
existsSync as
|
|
476506
|
+
existsSync as existsSync46,
|
|
476531
476507
|
mkdirSync as mkdirSync21,
|
|
476532
|
-
readdirSync as
|
|
476508
|
+
readdirSync as readdirSync14,
|
|
476533
476509
|
readFileSync as readFileSync34,
|
|
476534
476510
|
rmSync as rmSync5,
|
|
476535
476511
|
statSync as statSync13,
|
|
@@ -476543,9 +476519,9 @@ function getSkillsDir() {
|
|
|
476543
476519
|
return join61(getAgentDir(), "skills");
|
|
476544
476520
|
}
|
|
476545
476521
|
function collectLocalFiles(dir, rootDir = dir) {
|
|
476546
|
-
if (!
|
|
476522
|
+
if (!existsSync46(dir)) return [];
|
|
476547
476523
|
const files = [];
|
|
476548
|
-
for (const entry of
|
|
476524
|
+
for (const entry of readdirSync14(dir, { withFileTypes: true })) {
|
|
476549
476525
|
const fullPath = join61(dir, entry.name);
|
|
476550
476526
|
if (entry.isDirectory()) {
|
|
476551
476527
|
files.push(...collectLocalFiles(fullPath, rootDir));
|
|
@@ -476847,7 +476823,7 @@ var init_skills_download = __esm({
|
|
|
476847
476823
|
|
|
476848
476824
|
// src/app/sync/skills-status.ts
|
|
476849
476825
|
import { createHash as createHash5 } from "crypto";
|
|
476850
|
-
import { existsSync as
|
|
476826
|
+
import { existsSync as existsSync47, readdirSync as readdirSync15, readFileSync as readFileSync35 } from "fs";
|
|
476851
476827
|
import { join as join62, relative as relative10 } from "path";
|
|
476852
476828
|
function sha2562(data) {
|
|
476853
476829
|
return createHash5("sha256").update(data).digest("hex");
|
|
@@ -476856,13 +476832,13 @@ function getSkillsDir2() {
|
|
|
476856
476832
|
return join62(getAgentDir(), "skills");
|
|
476857
476833
|
}
|
|
476858
476834
|
function listLocalSkillNames(skillsDir) {
|
|
476859
|
-
if (!
|
|
476860
|
-
return
|
|
476835
|
+
if (!existsSync47(skillsDir)) return [];
|
|
476836
|
+
return readdirSync15(skillsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
|
|
476861
476837
|
}
|
|
476862
476838
|
function collectLocalFiles2(dir, rootDir = dir) {
|
|
476863
|
-
if (!
|
|
476839
|
+
if (!existsSync47(dir)) return [];
|
|
476864
476840
|
const files = [];
|
|
476865
|
-
for (const entry of
|
|
476841
|
+
for (const entry of readdirSync15(dir, { withFileTypes: true })) {
|
|
476866
476842
|
const fullPath = join62(dir, entry.name);
|
|
476867
476843
|
if (entry.isDirectory()) {
|
|
476868
476844
|
files.push(...collectLocalFiles2(fullPath, rootDir));
|
|
@@ -477104,7 +477080,7 @@ var init_skills_status = __esm({
|
|
|
477104
477080
|
|
|
477105
477081
|
// src/app/sync/skills-upload.ts
|
|
477106
477082
|
import { createHash as createHash6 } from "crypto";
|
|
477107
|
-
import { existsSync as
|
|
477083
|
+
import { existsSync as existsSync48, readdirSync as readdirSync16, readFileSync as readFileSync36, statSync as statSync14 } from "fs";
|
|
477108
477084
|
import { join as join63, relative as relative11 } from "path";
|
|
477109
477085
|
function sha2563(data) {
|
|
477110
477086
|
return createHash6("sha256").update(data).digest("hex");
|
|
@@ -477113,8 +477089,8 @@ function getSkillsDir3() {
|
|
|
477113
477089
|
return join63(getAgentDir(), "skills");
|
|
477114
477090
|
}
|
|
477115
477091
|
function listLocalSkillNames2(skillsDir) {
|
|
477116
|
-
if (!
|
|
477117
|
-
return
|
|
477092
|
+
if (!existsSync48(skillsDir)) return [];
|
|
477093
|
+
return readdirSync16(skillsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
|
|
477118
477094
|
}
|
|
477119
477095
|
function validateSkillName2(name, parentDirName) {
|
|
477120
477096
|
const errors = [];
|
|
@@ -477137,7 +477113,7 @@ function validateSkillName2(name, parentDirName) {
|
|
|
477137
477113
|
}
|
|
477138
477114
|
function validateLocalSkill(skillName, skillDir) {
|
|
477139
477115
|
const skillPath = join63(skillDir, "SKILL.md");
|
|
477140
|
-
if (!
|
|
477116
|
+
if (!existsSync48(skillPath)) {
|
|
477141
477117
|
return "missing SKILL.md";
|
|
477142
477118
|
}
|
|
477143
477119
|
try {
|
|
@@ -477158,7 +477134,7 @@ function validateLocalSkill(skillName, skillDir) {
|
|
|
477158
477134
|
}
|
|
477159
477135
|
function collectLocalFiles3(dir, rootDir = dir) {
|
|
477160
477136
|
const files = [];
|
|
477161
|
-
for (const entry of
|
|
477137
|
+
for (const entry of readdirSync16(dir, { withFileTypes: true })) {
|
|
477162
477138
|
const fullPath = join63(dir, entry.name);
|
|
477163
477139
|
if (entry.isDirectory()) {
|
|
477164
477140
|
files.push(...collectLocalFiles3(fullPath, rootDir));
|
|
@@ -477409,7 +477385,7 @@ var init_skills_upload = __esm({
|
|
|
477409
477385
|
});
|
|
477410
477386
|
|
|
477411
477387
|
// src/startup/interactive-commands.ts
|
|
477412
|
-
import { existsSync as
|
|
477388
|
+
import { existsSync as existsSync49 } from "fs";
|
|
477413
477389
|
async function fetchAuthorizedSkillTeamIds(accessToken) {
|
|
477414
477390
|
const userInfo = await fetchUserInfo(accessToken);
|
|
477415
477391
|
if (!userInfo) return null;
|
|
@@ -477443,7 +477419,7 @@ function createInteractiveCommandHandler(context) {
|
|
|
477443
477419
|
}
|
|
477444
477420
|
if (command === "/docs") {
|
|
477445
477421
|
const docsFile = getUserDocsPath();
|
|
477446
|
-
if (
|
|
477422
|
+
if (existsSync49(docsFile)) {
|
|
477447
477423
|
void openInEditor(docsFile).catch(
|
|
477448
477424
|
(error2) => showStatus(`Could not open documentation: ${formatOpenError(error2)}`)
|
|
477449
477425
|
);
|
|
@@ -477781,12 +477757,12 @@ var init_install_utils = __esm({
|
|
|
477781
477757
|
});
|
|
477782
477758
|
|
|
477783
477759
|
// src/startup/preflight/shared.ts
|
|
477784
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
477760
|
+
import { chmodSync as chmodSync3, existsSync as existsSync50, mkdirSync as mkdirSync22, readFileSync as readFileSync37, unlinkSync as unlinkSync8, writeFileSync as writeFileSync20 } from "fs";
|
|
477785
477761
|
import { dirname as dirname34, join as join64 } from "path";
|
|
477786
477762
|
async function ensureUv(platformTarget) {
|
|
477787
477763
|
header("Python Toolchain");
|
|
477788
477764
|
const uvPath = getUvBinPath();
|
|
477789
|
-
if (
|
|
477765
|
+
if (existsSync50(uvPath)) {
|
|
477790
477766
|
const check2 = run(`"${uvPath}" --version`, { timeout: 5e3 });
|
|
477791
477767
|
if (check2.ok) {
|
|
477792
477768
|
ok(`uv ${check2.stdout.replace("uv ", "").trim()} installed.`);
|
|
@@ -477842,7 +477818,7 @@ async function ensureUvPython() {
|
|
|
477842
477818
|
const uvPath = getUvBinPath();
|
|
477843
477819
|
const venvDir = getUvVenvDir();
|
|
477844
477820
|
const venvPython = join64(venvDir, "bin", "python3");
|
|
477845
|
-
if (
|
|
477821
|
+
if (existsSync50(venvPython)) {
|
|
477846
477822
|
const check2 = run(`"${venvPython}" --version`, { timeout: 5e3 });
|
|
477847
477823
|
if (check2.ok) {
|
|
477848
477824
|
ok(`${check2.stdout.trim()} ready.`);
|
|
@@ -477877,7 +477853,7 @@ async function ensureUvPackages() {
|
|
|
477877
477853
|
const uvPath = getUvBinPath();
|
|
477878
477854
|
const venvDir = getUvVenvDir();
|
|
477879
477855
|
const venvPython = join64(venvDir, "bin", "python3");
|
|
477880
|
-
if (!
|
|
477856
|
+
if (!existsSync50(venvPython)) {
|
|
477881
477857
|
log2(
|
|
477882
477858
|
"Shortcut agent will install packages after Python is ready.",
|
|
477883
477859
|
"Will finish setup automatically."
|
|
@@ -477887,7 +477863,7 @@ async function ensureUvPackages() {
|
|
|
477887
477863
|
const stampFile = join64(venvDir, ".packages-stamp");
|
|
477888
477864
|
const stampValue = `${VERSION}:${UV_PIP_PACKAGES.join(",")}`;
|
|
477889
477865
|
try {
|
|
477890
|
-
if (
|
|
477866
|
+
if (existsSync50(stampFile) && readFileSync37(stampFile, "utf-8").trim() === stampValue) {
|
|
477891
477867
|
ok("Packages already installed.", "Ready.");
|
|
477892
477868
|
return;
|
|
477893
477869
|
}
|
|
@@ -477971,13 +477947,13 @@ __export(mac_exports, {
|
|
|
477971
477947
|
ensureUvPython: () => ensureUvPython,
|
|
477972
477948
|
smokeTestSheetEngine: () => smokeTestSheetEngine
|
|
477973
477949
|
});
|
|
477974
|
-
import { existsSync as
|
|
477950
|
+
import { existsSync as existsSync51 } from "fs";
|
|
477975
477951
|
async function ensureUv2() {
|
|
477976
477952
|
return ensureUv("apple-darwin");
|
|
477977
477953
|
}
|
|
477978
477954
|
function ensureChromeMac() {
|
|
477979
477955
|
header("Chrome");
|
|
477980
|
-
if (
|
|
477956
|
+
if (existsSync51("/Applications/Google Chrome.app")) {
|
|
477981
477957
|
ok("Chrome found \u2014 SEC filing support ready.");
|
|
477982
477958
|
} else {
|
|
477983
477959
|
log2("Chrome not installed \u2014 Shortcut agent can set this up for SEC filing support.");
|
|
@@ -478001,13 +477977,13 @@ __export(linux_exports, {
|
|
|
478001
477977
|
ensureUvPython: () => ensureUvPython,
|
|
478002
477978
|
smokeTestSheetEngine: () => smokeTestSheetEngine
|
|
478003
477979
|
});
|
|
478004
|
-
import { existsSync as
|
|
477980
|
+
import { existsSync as existsSync52 } from "fs";
|
|
478005
477981
|
async function ensureUv3() {
|
|
478006
477982
|
return ensureUv("unknown-linux-gnu");
|
|
478007
477983
|
}
|
|
478008
477984
|
function ensureChromeLinux() {
|
|
478009
477985
|
header("Chrome");
|
|
478010
|
-
const found = LINUX_CHROME_PATHS.find((p2) =>
|
|
477986
|
+
const found = LINUX_CHROME_PATHS.find((p2) => existsSync52(p2));
|
|
478011
477987
|
if (found) {
|
|
478012
477988
|
ok("Chrome found \u2014 SEC filing support ready.");
|
|
478013
477989
|
} else {
|
|
@@ -478039,12 +478015,12 @@ __export(windows_exports, {
|
|
|
478039
478015
|
ensureXllRegistry: () => ensureXllRegistry,
|
|
478040
478016
|
smokeTestExcel: () => smokeTestExcel
|
|
478041
478017
|
});
|
|
478042
|
-
import { existsSync as
|
|
478018
|
+
import { existsSync as existsSync53, readFileSync as readFileSync38, writeFileSync as writeFileSync21 } from "fs";
|
|
478043
478019
|
import { join as join65, resolve as resolve18 } from "path";
|
|
478044
478020
|
async function ensurePipPackages() {
|
|
478045
478021
|
header("Python Packages", "Calculation Engine");
|
|
478046
478022
|
const pythonExe = getEmbeddedPythonExe();
|
|
478047
|
-
if (!
|
|
478023
|
+
if (!existsSync53(pythonExe)) {
|
|
478048
478024
|
log2("Shortcut agent will set up Python.", "Will finish setup automatically.");
|
|
478049
478025
|
return;
|
|
478050
478026
|
}
|
|
@@ -478063,7 +478039,7 @@ async function ensurePipPackages() {
|
|
|
478063
478039
|
const pipStampFile = join65(getStableXllDir(), ".pip-version");
|
|
478064
478040
|
let pipUpToDate = false;
|
|
478065
478041
|
try {
|
|
478066
|
-
pipUpToDate =
|
|
478042
|
+
pipUpToDate = existsSync53(pipStampFile) && readFileSync38(pipStampFile, "utf-8").trim() === VERSION;
|
|
478067
478043
|
} catch {
|
|
478068
478044
|
}
|
|
478069
478045
|
if (pipUpToDate) {
|
|
@@ -478093,7 +478069,7 @@ async function ensureChromeWindows() {
|
|
|
478093
478069
|
return;
|
|
478094
478070
|
}
|
|
478095
478071
|
const pythonExe = getEmbeddedPythonExe();
|
|
478096
|
-
if (!
|
|
478072
|
+
if (!existsSync53(pythonExe)) {
|
|
478097
478073
|
log2("Shortcut agent will set up Chrome.", "Will finish setup automatically.");
|
|
478098
478074
|
return;
|
|
478099
478075
|
}
|
|
@@ -478177,7 +478153,7 @@ async function ensureGitBash() {
|
|
|
478177
478153
|
function ensureXllRegistry() {
|
|
478178
478154
|
header("Excel Add-in", "Excel Integration");
|
|
478179
478155
|
const xllPath = resolve18(getXllPath()).replace(/\//g, "\\");
|
|
478180
|
-
if (!
|
|
478156
|
+
if (!existsSync53(xllPath)) {
|
|
478181
478157
|
log2("Shortcut agent will set up the Excel add-in.", "Will finish setup automatically.");
|
|
478182
478158
|
return;
|
|
478183
478159
|
}
|
|
@@ -478373,7 +478349,7 @@ var diagnostics_exports = {};
|
|
|
478373
478349
|
__export(diagnostics_exports, {
|
|
478374
478350
|
collectPreflightDiagnostics: () => collectPreflightDiagnostics
|
|
478375
478351
|
});
|
|
478376
|
-
import { closeSync as closeSync2, existsSync as
|
|
478352
|
+
import { closeSync as closeSync2, existsSync as existsSync54, openSync as openSync2, readSync as readSync2, statSync as statSync15 } from "fs";
|
|
478377
478353
|
import { resolve as resolve19 } from "path";
|
|
478378
478354
|
function safeRun(command, timeout = DIAGNOSTIC_TIMEOUT_MS) {
|
|
478379
478355
|
try {
|
|
@@ -478498,7 +478474,7 @@ function collectXllLog() {
|
|
|
478498
478474
|
`${process.env.TEMP ?? ""}\\shortcutxl.log`
|
|
478499
478475
|
];
|
|
478500
478476
|
for (const path21 of logPaths) {
|
|
478501
|
-
if (path21 &&
|
|
478477
|
+
if (path21 && existsSync54(path21)) {
|
|
478502
478478
|
return readLogTail(path21);
|
|
478503
478479
|
}
|
|
478504
478480
|
}
|
|
@@ -478550,7 +478526,7 @@ function collectPreflightDiagnostics() {
|
|
|
478550
478526
|
setCurrentStep("diagnostics");
|
|
478551
478527
|
const xllPath = resolve19(getXllPath()).replace(/\//g, "\\");
|
|
478552
478528
|
const diagnostics = {
|
|
478553
|
-
xllExists:
|
|
478529
|
+
xllExists: existsSync54(xllPath),
|
|
478554
478530
|
xllPath,
|
|
478555
478531
|
motw: collectMotw(xllPath),
|
|
478556
478532
|
xllArch: collectXllArch(xllPath),
|
|
@@ -478634,7 +478610,7 @@ var init_preflight = __esm({
|
|
|
478634
478610
|
});
|
|
478635
478611
|
|
|
478636
478612
|
// src/startup/prune-sessions.ts
|
|
478637
|
-
import { readdirSync as
|
|
478613
|
+
import { readdirSync as readdirSync17, rmSync as rmSync6, statSync as statSync16 } from "node:fs";
|
|
478638
478614
|
import { join as join66 } from "node:path";
|
|
478639
478615
|
function pruneStaleFiles() {
|
|
478640
478616
|
const cutoff = Date.now() - FOURTEEN_DAYS_MS;
|
|
@@ -478643,7 +478619,7 @@ function pruneStaleFiles() {
|
|
|
478643
478619
|
function pruneSessionFiles(cutoff) {
|
|
478644
478620
|
try {
|
|
478645
478621
|
const sessionsRoot = getSessionsDir();
|
|
478646
|
-
for (const projectDir of
|
|
478622
|
+
for (const projectDir of readdirSync17(sessionsRoot)) {
|
|
478647
478623
|
pruneJsonlFilesRecursively(join66(sessionsRoot, projectDir), cutoff);
|
|
478648
478624
|
}
|
|
478649
478625
|
} catch {
|
|
@@ -478651,7 +478627,7 @@ function pruneSessionFiles(cutoff) {
|
|
|
478651
478627
|
}
|
|
478652
478628
|
function pruneJsonlFilesRecursively(dir, cutoff) {
|
|
478653
478629
|
try {
|
|
478654
|
-
for (const entry of
|
|
478630
|
+
for (const entry of readdirSync17(dir, { withFileTypes: true })) {
|
|
478655
478631
|
const entryPath = join66(dir, entry.name);
|
|
478656
478632
|
if (entry.isDirectory()) {
|
|
478657
478633
|
pruneJsonlFilesRecursively(entryPath, cutoff);
|
|
@@ -478751,19 +478727,38 @@ var init_session_selection = __esm({
|
|
|
478751
478727
|
|
|
478752
478728
|
// src/startup/update-action.ts
|
|
478753
478729
|
import { spawn as spawn12 } from "child_process";
|
|
478730
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync23 } from "fs";
|
|
478731
|
+
import { dirname as dirname35 } from "path";
|
|
478754
478732
|
async function runForegroundUpdate(request, deps = {}) {
|
|
478755
478733
|
const resolveShell = deps.resolveShell ?? getShellConfig;
|
|
478756
478734
|
const resolveEnv = deps.resolveEnv ?? getShellEnv;
|
|
478757
478735
|
const spawnProcess = deps.spawnProcess ?? spawn12;
|
|
478736
|
+
const resolveLogPath = deps.resolveLogPath ?? getDebugLogPath;
|
|
478758
478737
|
const shellConfig = resolveShell();
|
|
478759
478738
|
return await new Promise((resolve22, reject) => {
|
|
478739
|
+
const output = [];
|
|
478740
|
+
let outputBytes = 0;
|
|
478741
|
+
let outputTruncated = false;
|
|
478760
478742
|
const child = spawnProcess(shellConfig.shell, [...shellConfig.args, request.command], {
|
|
478761
478743
|
cwd: request.cwd ?? process.cwd(),
|
|
478762
478744
|
env: resolveEnv(),
|
|
478763
|
-
stdio: "
|
|
478745
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
478764
478746
|
});
|
|
478747
|
+
const capture = (chunk) => {
|
|
478748
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
478749
|
+
const remaining = MAX_CAPTURED_OUTPUT_BYTES - outputBytes;
|
|
478750
|
+
if (remaining > 0) {
|
|
478751
|
+
output.push(buffer.subarray(0, remaining));
|
|
478752
|
+
outputBytes += Math.min(buffer.length, remaining);
|
|
478753
|
+
}
|
|
478754
|
+
if (buffer.length > remaining) {
|
|
478755
|
+
outputTruncated = true;
|
|
478756
|
+
}
|
|
478757
|
+
};
|
|
478758
|
+
child.stdout?.on("data", capture);
|
|
478759
|
+
child.stderr?.on("data", capture);
|
|
478765
478760
|
child.once("error", reject);
|
|
478766
|
-
child.once("
|
|
478761
|
+
child.once("close", (exitCode, signal) => {
|
|
478767
478762
|
if (exitCode === 0) {
|
|
478768
478763
|
resolve22({
|
|
478769
478764
|
kind: "success",
|
|
@@ -478772,24 +478767,83 @@ async function runForegroundUpdate(request, deps = {}) {
|
|
|
478772
478767
|
});
|
|
478773
478768
|
return;
|
|
478774
478769
|
}
|
|
478770
|
+
const capturedOutput = Buffer.concat(output).toString("utf-8");
|
|
478771
|
+
const logPath = writeUpdateFailureLog({
|
|
478772
|
+
command: request.command,
|
|
478773
|
+
exitCode,
|
|
478774
|
+
signal,
|
|
478775
|
+
output: capturedOutput,
|
|
478776
|
+
truncated: outputTruncated,
|
|
478777
|
+
resolveLogPath
|
|
478778
|
+
});
|
|
478775
478779
|
resolve22({
|
|
478776
478780
|
kind: "failed",
|
|
478777
478781
|
exitCode,
|
|
478778
|
-
signal
|
|
478782
|
+
signal,
|
|
478783
|
+
message: summarizeUpdateFailure(capturedOutput, request.command),
|
|
478784
|
+
logPath
|
|
478779
478785
|
});
|
|
478780
478786
|
});
|
|
478781
478787
|
});
|
|
478782
478788
|
}
|
|
478789
|
+
function summarizeUpdateFailure(output, updateCommand) {
|
|
478790
|
+
if (/EEXIST[\s\S]*shortcut\.cmd/i.test(output) || /File exists:[\s\S]*shortcut\.cmd/i.test(output)) {
|
|
478791
|
+
return [
|
|
478792
|
+
"ShortcutXL could not update because an existing global `shortcut` command blocked npm from replacing it.",
|
|
478793
|
+
`Close any running ShortcutXL terminals, remove the existing global ShortcutXL package, then retry \`${updateCommand}\`.`
|
|
478794
|
+
].join(" ");
|
|
478795
|
+
}
|
|
478796
|
+
if (/EPERM|ENOTEMPTY|ENOENT/i.test(output) && /AppData[\\/]+Roaming[\\/]+npm[\\/]+node_modules[\\/]+shortcutxl/i.test(output)) {
|
|
478797
|
+
return [
|
|
478798
|
+
"ShortcutXL could not update because npm could not clean up the previous global install.",
|
|
478799
|
+
`Close ShortcutXL terminals and retry \`${updateCommand}\`.`
|
|
478800
|
+
].join(" ");
|
|
478801
|
+
}
|
|
478802
|
+
return `ShortcutXL could not update automatically. Retry with \`${updateCommand}\`.`;
|
|
478803
|
+
}
|
|
478804
|
+
function writeUpdateFailureLog({
|
|
478805
|
+
command,
|
|
478806
|
+
exitCode,
|
|
478807
|
+
signal,
|
|
478808
|
+
output,
|
|
478809
|
+
truncated,
|
|
478810
|
+
resolveLogPath
|
|
478811
|
+
}) {
|
|
478812
|
+
try {
|
|
478813
|
+
const logPath = resolveLogPath();
|
|
478814
|
+
mkdirSync23(dirname35(logPath), { recursive: true });
|
|
478815
|
+
appendFileSync6(
|
|
478816
|
+
logPath,
|
|
478817
|
+
[
|
|
478818
|
+
"",
|
|
478819
|
+
"--- ShortcutXL update failure ---",
|
|
478820
|
+
`time=${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
478821
|
+
`command=${command}`,
|
|
478822
|
+
`exitCode=${String(exitCode)}`,
|
|
478823
|
+
`signal=${String(signal)}`,
|
|
478824
|
+
truncated ? `outputTruncatedAfterBytes=${MAX_CAPTURED_OUTPUT_BYTES}` : void 0,
|
|
478825
|
+
output
|
|
478826
|
+
].filter((line) => line !== void 0).join("\n"),
|
|
478827
|
+
"utf-8"
|
|
478828
|
+
);
|
|
478829
|
+
return logPath;
|
|
478830
|
+
} catch {
|
|
478831
|
+
return void 0;
|
|
478832
|
+
}
|
|
478833
|
+
}
|
|
478834
|
+
var MAX_CAPTURED_OUTPUT_BYTES;
|
|
478783
478835
|
var init_update_action = __esm({
|
|
478784
478836
|
"src/startup/update-action.ts"() {
|
|
478785
478837
|
"use strict";
|
|
478786
478838
|
init_bash_runtime();
|
|
478839
|
+
init_config();
|
|
478840
|
+
MAX_CAPTURED_OUTPUT_BYTES = 1024 * 1024;
|
|
478787
478841
|
}
|
|
478788
478842
|
});
|
|
478789
478843
|
|
|
478790
478844
|
// src/startup/update-manager.ts
|
|
478791
|
-
import { mkdirSync as
|
|
478792
|
-
import { dirname as
|
|
478845
|
+
import { mkdirSync as mkdirSync24, readFileSync as readFileSync39, writeFileSync as writeFileSync22 } from "fs";
|
|
478846
|
+
import { dirname as dirname36 } from "path";
|
|
478793
478847
|
async function resolveStartupUpdateStatus(options2 = {}, deps = {}) {
|
|
478794
478848
|
const cachePath = options2.cachePath ?? getUpdateCachePath();
|
|
478795
478849
|
const currentVersion = options2.currentVersion ?? VERSION;
|
|
@@ -478902,7 +478956,7 @@ function readUpdateCache(cachePath) {
|
|
|
478902
478956
|
}
|
|
478903
478957
|
}
|
|
478904
478958
|
function writeUpdateCache(cachePath, cache) {
|
|
478905
|
-
|
|
478959
|
+
mkdirSync24(dirname36(cachePath), { recursive: true });
|
|
478906
478960
|
writeFileSync22(cachePath, `${JSON.stringify(cache, null, 2)}
|
|
478907
478961
|
`, "utf-8");
|
|
478908
478962
|
}
|
|
@@ -480350,7 +480404,7 @@ __export(uninstall_exports, {
|
|
|
480350
480404
|
removeOwnedInstallArtifacts: () => removeOwnedInstallArtifacts,
|
|
480351
480405
|
runUninstall: () => runUninstall
|
|
480352
480406
|
});
|
|
480353
|
-
import { existsSync as
|
|
480407
|
+
import { existsSync as existsSync55, readdirSync as readdirSync18, rmSync as rmSync7, rmdirSync } from "fs";
|
|
480354
480408
|
import { isAbsolute as isAbsolute10, join as join67, relative as relative12, resolve as resolve20 } from "path";
|
|
480355
480409
|
function isWithinDir(parentDir, targetPath) {
|
|
480356
480410
|
const parent = resolve20(parentDir);
|
|
@@ -480360,7 +480414,7 @@ function isWithinDir(parentDir, targetPath) {
|
|
|
480360
480414
|
}
|
|
480361
480415
|
function removeIfInsideAgentDir(agentDir, relativePath) {
|
|
480362
480416
|
const target = join67(agentDir, relativePath);
|
|
480363
|
-
if (!isWithinDir(agentDir, target) || !
|
|
480417
|
+
if (!isWithinDir(agentDir, target) || !existsSync55(target)) {
|
|
480364
480418
|
return false;
|
|
480365
480419
|
}
|
|
480366
480420
|
rmSync7(target, { recursive: true, force: true });
|
|
@@ -480368,10 +480422,10 @@ function removeIfInsideAgentDir(agentDir, relativePath) {
|
|
|
480368
480422
|
}
|
|
480369
480423
|
function removeEmptyDirIfInsideAgentDir(agentDir, relativePath) {
|
|
480370
480424
|
const target = join67(agentDir, relativePath);
|
|
480371
|
-
if (!isWithinDir(agentDir, target) || !
|
|
480425
|
+
if (!isWithinDir(agentDir, target) || !existsSync55(target)) {
|
|
480372
480426
|
return false;
|
|
480373
480427
|
}
|
|
480374
|
-
if (
|
|
480428
|
+
if (readdirSync18(target).length > 0) {
|
|
480375
480429
|
return false;
|
|
480376
480430
|
}
|
|
480377
480431
|
rmdirSync(target);
|
|
@@ -480398,7 +480452,7 @@ function removeOwnedInstallArtifacts(agentDir) {
|
|
|
480398
480452
|
}
|
|
480399
480453
|
}
|
|
480400
480454
|
try {
|
|
480401
|
-
if (
|
|
480455
|
+
if (existsSync55(agentDir) && readdirSync18(agentDir).length === 0) {
|
|
480402
480456
|
rmdirSync(agentDir);
|
|
480403
480457
|
result.removed.push(".");
|
|
480404
480458
|
}
|
|
@@ -480474,7 +480528,7 @@ function runUninstall() {
|
|
|
480474
480528
|
}
|
|
480475
480529
|
header2("Playwright Browsers");
|
|
480476
480530
|
const pythonExe = getEmbeddedPythonExe();
|
|
480477
|
-
if (
|
|
480531
|
+
if (existsSync55(pythonExe)) {
|
|
480478
480532
|
const pwResult = run(`"${pythonExe}" -m playwright uninstall --all`, { timeout: 3e4 });
|
|
480479
480533
|
if (pwResult.ok) {
|
|
480480
480534
|
ok2("Removed Playwright browsers.");
|
|
@@ -480490,7 +480544,7 @@ function runUninstall() {
|
|
|
480490
480544
|
}
|
|
480491
480545
|
header2("Files");
|
|
480492
480546
|
const agentDir = getAgentDir();
|
|
480493
|
-
if (
|
|
480547
|
+
if (existsSync55(agentDir)) {
|
|
480494
480548
|
const cleanup = removeOwnedInstallArtifacts(agentDir);
|
|
480495
480549
|
if (cleanup.removed.length > 0) {
|
|
480496
480550
|
ok2(`Removed generated install files from ${agentDir}`);
|
|
@@ -480543,7 +480597,7 @@ __export(main_exports, {
|
|
|
480543
480597
|
isMogRuntimeEnabledForUser: () => isMogRuntimeEnabledForUser,
|
|
480544
480598
|
main: () => main
|
|
480545
480599
|
});
|
|
480546
|
-
import { existsSync as
|
|
480600
|
+
import { existsSync as existsSync56 } from "fs";
|
|
480547
480601
|
async function resolveShortcutUserInfo(authStorage) {
|
|
480548
480602
|
const accessToken = await authStorage.getApiKey(SHORTCUT_PROVIDER_ID);
|
|
480549
480603
|
return accessToken ? fetchUserInfo(accessToken) : null;
|
|
@@ -480968,7 +481022,7 @@ async function main(args) {
|
|
|
480968
481022
|
if (sandboxMode === "enabled" && sandboxAvailable) {
|
|
480969
481023
|
const sandboxFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
480970
481024
|
let sandboxFrame = 0;
|
|
480971
|
-
const needsDownload = !
|
|
481025
|
+
const needsDownload = !existsSync56(getAlpineRootfsPath());
|
|
480972
481026
|
const spinnerMsg = needsDownload ? "Downloading sandbox (~80 MB)..." : "Checking sandbox...";
|
|
480973
481027
|
const sandboxSpinner = setInterval(() => {
|
|
480974
481028
|
process.stderr.write(
|
|
@@ -481109,10 +481163,18 @@ async function main(args) {
|
|
|
481109
481163
|
if (updateResult.kind === "failed") {
|
|
481110
481164
|
const exitDetail = updateResult.exitCode !== null ? `exit code ${updateResult.exitCode}` : updateResult.signal ? `signal ${updateResult.signal}` : "unknown error";
|
|
481111
481165
|
console.error(source_default.red(`Update failed (${exitDetail}). ShortcutXL will not launch.`));
|
|
481166
|
+
if (updateResult.message) {
|
|
481167
|
+
console.error(source_default.yellow(updateResult.message));
|
|
481168
|
+
}
|
|
481169
|
+
if (updateResult.logPath) {
|
|
481170
|
+
console.error(source_default.dim(`Details were written to ${updateResult.logPath}`));
|
|
481171
|
+
}
|
|
481112
481172
|
process.exit(updateResult.exitCode ?? 1);
|
|
481113
481173
|
}
|
|
481114
481174
|
console.log(source_default.green(`Update to v${updatePromptOutcome.update.latestVersion} succeeded.`));
|
|
481115
|
-
console.log(source_default.green("
|
|
481175
|
+
console.log(source_default.green("Restart ShortcutXL to finish applying the update:"));
|
|
481176
|
+
console.log(source_default.bold(" shortcut"));
|
|
481177
|
+
process.exit(0);
|
|
481116
481178
|
}
|
|
481117
481179
|
initTheme(settingsManager.getTheme(), isInteractive);
|
|
481118
481180
|
sessionManager = await createSessionManager2(parsed, cwd);
|
|
@@ -481571,9 +481633,9 @@ ${loop.prompt}`;
|
|
|
481571
481633
|
|
|
481572
481634
|
// src/cli.ts
|
|
481573
481635
|
var import_dotenv = __toESM(require_main(), 1);
|
|
481574
|
-
import { dirname as
|
|
481636
|
+
import { dirname as dirname37, resolve as resolve21 } from "path";
|
|
481575
481637
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
481576
|
-
var __dirname3 =
|
|
481638
|
+
var __dirname3 = dirname37(fileURLToPath4(import.meta.url));
|
|
481577
481639
|
var agentRoot = resolve21(__dirname3, "..");
|
|
481578
481640
|
import_dotenv.default.config({ path: resolve21(agentRoot, ".env.development") });
|
|
481579
481641
|
process.title = "shortcut";
|
package/dist/main.js
CHANGED
|
@@ -669,10 +669,18 @@ export async function main(args) {
|
|
|
669
669
|
? `signal ${updateResult.signal}`
|
|
670
670
|
: 'unknown error';
|
|
671
671
|
console.error(chalk.red(`Update failed (${exitDetail}). ShortcutXL will not launch.`));
|
|
672
|
+
if (updateResult.message) {
|
|
673
|
+
console.error(chalk.yellow(updateResult.message));
|
|
674
|
+
}
|
|
675
|
+
if (updateResult.logPath) {
|
|
676
|
+
console.error(chalk.dim(`Details were written to ${updateResult.logPath}`));
|
|
677
|
+
}
|
|
672
678
|
process.exit(updateResult.exitCode ?? 1);
|
|
673
679
|
}
|
|
674
680
|
console.log(chalk.green(`Update to v${updatePromptOutcome.update.latestVersion} succeeded.`));
|
|
675
|
-
console.log(chalk.green('
|
|
681
|
+
console.log(chalk.green('Restart ShortcutXL to finish applying the update:'));
|
|
682
|
+
console.log(chalk.bold(' shortcut'));
|
|
683
|
+
process.exit(0);
|
|
676
684
|
}
|
|
677
685
|
initTheme(settingsManager.getTheme(), isInteractive);
|
|
678
686
|
// Create session manager based on CLI flags
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from 'fs';
|
|
2
|
+
const VERSIONED_PYTHON_RUNTIME_FILE = /^python\d{2,}(?:\.dll|\.zip|\._pth)$/i;
|
|
3
|
+
export function listVersionedPythonRuntimeFiles(pythonDir) {
|
|
4
|
+
if (!existsSync(pythonDir))
|
|
5
|
+
return new Set();
|
|
6
|
+
try {
|
|
7
|
+
return new Set(readdirSync(pythonDir)
|
|
8
|
+
.filter((entry) => VERSIONED_PYTHON_RUNTIME_FILE.test(entry))
|
|
9
|
+
.map((entry) => entry.toLowerCase()));
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return new Set();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function hasVersionedPythonRuntimeFileDrift(sourcePythonDir, destPythonDir) {
|
|
16
|
+
const sourceFiles = listVersionedPythonRuntimeFiles(sourcePythonDir);
|
|
17
|
+
if (sourceFiles.size === 0)
|
|
18
|
+
return false;
|
|
19
|
+
const destFiles = listVersionedPythonRuntimeFiles(destPythonDir);
|
|
20
|
+
if (destFiles.size === 0)
|
|
21
|
+
return false;
|
|
22
|
+
for (const file of destFiles) {
|
|
23
|
+
if (!sourceFiles.has(file))
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
for (const file of sourceFiles) {
|
|
27
|
+
if (!destFiles.has(file))
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=python-abi.js.map
|
package/dist/startup/sync-xll.js
CHANGED
|
@@ -22,6 +22,7 @@ import { createHash } from 'crypto';
|
|
|
22
22
|
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, unlinkSync, utimesSync, writeFileSync } from 'fs';
|
|
23
23
|
import { join } from 'path';
|
|
24
24
|
import { getPackageDir, getStableXllDir, VERSION } from '../config.js';
|
|
25
|
+
import { hasVersionedPythonRuntimeFileDrift } from './python-abi.js';
|
|
25
26
|
/** Strip the NTFS Zone.Identifier alternate data stream (Mark of the Web). */
|
|
26
27
|
function stripMotw(filePath) {
|
|
27
28
|
try {
|
|
@@ -101,34 +102,8 @@ function syncDir(src, dest) {
|
|
|
101
102
|
}
|
|
102
103
|
const SYNC_VERSION_FILE = '.sync-version';
|
|
103
104
|
const PIP_VERSION_FILE = '.pip-version';
|
|
104
|
-
function listVersionedPythonRuntimeFiles(pythonDir) {
|
|
105
|
-
if (!existsSync(pythonDir))
|
|
106
|
-
return new Set();
|
|
107
|
-
try {
|
|
108
|
-
return new Set(readdirSync(pythonDir)
|
|
109
|
-
.filter((entry) => /^python\d{2,}(?:\.dll|\.zip|\._pth)$/i.test(entry))
|
|
110
|
-
.map((entry) => entry.toLowerCase()));
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
return new Set();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
105
|
export function hasPythonAbiDrift(shippedDir, stableDir) {
|
|
117
|
-
|
|
118
|
-
if (shippedRuntimeFiles.size === 0)
|
|
119
|
-
return false;
|
|
120
|
-
const stableRuntimeFiles = listVersionedPythonRuntimeFiles(join(stableDir, 'python'));
|
|
121
|
-
if (stableRuntimeFiles.size === 0)
|
|
122
|
-
return false;
|
|
123
|
-
for (const file of stableRuntimeFiles) {
|
|
124
|
-
if (!shippedRuntimeFiles.has(file))
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
127
|
-
for (const file of shippedRuntimeFiles) {
|
|
128
|
-
if (!stableRuntimeFiles.has(file))
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
return false;
|
|
106
|
+
return hasVersionedPythonRuntimeFileDrift(join(shippedDir, 'python'), join(stableDir, 'python'));
|
|
132
107
|
}
|
|
133
108
|
function resetStablePythonRuntime(stableDir) {
|
|
134
109
|
try {
|
|
@@ -203,7 +178,7 @@ export function syncXll() {
|
|
|
203
178
|
try {
|
|
204
179
|
const { updated, staleLocked } = syncDir(shippedDir, stableDir);
|
|
205
180
|
totalUpdated += updated;
|
|
206
|
-
hasStaleLockedFiles = staleLocked;
|
|
181
|
+
hasStaleLockedFiles = hasStaleLockedFiles || staleLocked;
|
|
207
182
|
if (staleLocked) {
|
|
208
183
|
console.warn('Warning: A ShortcutXL update is available but Excel has files locked. ' +
|
|
209
184
|
'Please close Excel and restart the Shortcut agent to apply it.');
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Foreground update execution path.
|
|
3
3
|
*
|
|
4
|
-
* Runs the updater command in the startup flow
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Runs the updater command in the startup flow. Updaters such as npm can emit
|
|
5
|
+
* huge cleanup dumps on Windows when a global install tree is locked or
|
|
6
|
+
* half-deleted, so stdout/stderr are captured and summarized instead of being
|
|
7
|
+
* streamed directly into the user's terminal.
|
|
7
8
|
*/
|
|
8
9
|
import { spawn } from 'child_process';
|
|
9
10
|
export interface UpdateLaunchRequest {
|
|
@@ -14,6 +15,8 @@ export interface ForegroundUpdateResult {
|
|
|
14
15
|
kind: 'success' | 'failed';
|
|
15
16
|
exitCode: number | null;
|
|
16
17
|
signal: NodeJS.Signals | null;
|
|
18
|
+
message?: string;
|
|
19
|
+
logPath?: string;
|
|
17
20
|
}
|
|
18
21
|
interface UpdateActionDeps {
|
|
19
22
|
spawnProcess?: typeof spawn;
|
|
@@ -22,6 +25,7 @@ interface UpdateActionDeps {
|
|
|
22
25
|
args: string[];
|
|
23
26
|
};
|
|
24
27
|
resolveEnv?: () => NodeJS.ProcessEnv;
|
|
28
|
+
resolveLogPath?: () => string;
|
|
25
29
|
}
|
|
26
30
|
export declare function runForegroundUpdate(request: UpdateLaunchRequest, deps?: UpdateActionDeps): Promise<ForegroundUpdateResult>;
|
|
27
31
|
export {};
|
|
@@ -1,25 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Foreground update execution path.
|
|
3
3
|
*
|
|
4
|
-
* Runs the updater command in the startup flow
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Runs the updater command in the startup flow. Updaters such as npm can emit
|
|
5
|
+
* huge cleanup dumps on Windows when a global install tree is locked or
|
|
6
|
+
* half-deleted, so stdout/stderr are captured and summarized instead of being
|
|
7
|
+
* streamed directly into the user's terminal.
|
|
7
8
|
*/
|
|
8
9
|
import { spawn } from 'child_process';
|
|
10
|
+
import { appendFileSync, mkdirSync } from 'fs';
|
|
11
|
+
import { dirname } from 'path';
|
|
9
12
|
import { getShellConfig, getShellEnv } from '../app/tools/bash-runtime.js';
|
|
13
|
+
import { getDebugLogPath } from '../config.js';
|
|
14
|
+
const MAX_CAPTURED_OUTPUT_BYTES = 1024 * 1024;
|
|
10
15
|
export async function runForegroundUpdate(request, deps = {}) {
|
|
11
16
|
const resolveShell = deps.resolveShell ?? getShellConfig;
|
|
12
17
|
const resolveEnv = deps.resolveEnv ?? getShellEnv;
|
|
13
18
|
const spawnProcess = deps.spawnProcess ?? spawn;
|
|
19
|
+
const resolveLogPath = deps.resolveLogPath ?? getDebugLogPath;
|
|
14
20
|
const shellConfig = resolveShell();
|
|
15
21
|
return await new Promise((resolve, reject) => {
|
|
22
|
+
const output = [];
|
|
23
|
+
let outputBytes = 0;
|
|
24
|
+
let outputTruncated = false;
|
|
16
25
|
const child = spawnProcess(shellConfig.shell, [...shellConfig.args, request.command], {
|
|
17
26
|
cwd: request.cwd ?? process.cwd(),
|
|
18
27
|
env: resolveEnv(),
|
|
19
|
-
stdio: '
|
|
28
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
20
29
|
});
|
|
30
|
+
const capture = (chunk) => {
|
|
31
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
32
|
+
const remaining = MAX_CAPTURED_OUTPUT_BYTES - outputBytes;
|
|
33
|
+
if (remaining > 0) {
|
|
34
|
+
output.push(buffer.subarray(0, remaining));
|
|
35
|
+
outputBytes += Math.min(buffer.length, remaining);
|
|
36
|
+
}
|
|
37
|
+
if (buffer.length > remaining) {
|
|
38
|
+
outputTruncated = true;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
child.stdout?.on('data', capture);
|
|
42
|
+
child.stderr?.on('data', capture);
|
|
21
43
|
child.once('error', reject);
|
|
22
|
-
child.once('
|
|
44
|
+
child.once('close', (exitCode, signal) => {
|
|
23
45
|
if (exitCode === 0) {
|
|
24
46
|
resolve({
|
|
25
47
|
kind: 'success',
|
|
@@ -28,12 +50,62 @@ export async function runForegroundUpdate(request, deps = {}) {
|
|
|
28
50
|
});
|
|
29
51
|
return;
|
|
30
52
|
}
|
|
53
|
+
const capturedOutput = Buffer.concat(output).toString('utf-8');
|
|
54
|
+
const logPath = writeUpdateFailureLog({
|
|
55
|
+
command: request.command,
|
|
56
|
+
exitCode,
|
|
57
|
+
signal,
|
|
58
|
+
output: capturedOutput,
|
|
59
|
+
truncated: outputTruncated,
|
|
60
|
+
resolveLogPath
|
|
61
|
+
});
|
|
31
62
|
resolve({
|
|
32
63
|
kind: 'failed',
|
|
33
64
|
exitCode,
|
|
34
|
-
signal
|
|
65
|
+
signal,
|
|
66
|
+
message: summarizeUpdateFailure(capturedOutput, request.command),
|
|
67
|
+
logPath
|
|
35
68
|
});
|
|
36
69
|
});
|
|
37
70
|
});
|
|
38
71
|
}
|
|
72
|
+
function summarizeUpdateFailure(output, updateCommand) {
|
|
73
|
+
if (/EEXIST[\s\S]*shortcut\.cmd/i.test(output) ||
|
|
74
|
+
/File exists:[\s\S]*shortcut\.cmd/i.test(output)) {
|
|
75
|
+
return [
|
|
76
|
+
'ShortcutXL could not update because an existing global `shortcut` command blocked npm from replacing it.',
|
|
77
|
+
`Close any running ShortcutXL terminals, remove the existing global ShortcutXL package, then retry \`${updateCommand}\`.`
|
|
78
|
+
].join(' ');
|
|
79
|
+
}
|
|
80
|
+
if (/EPERM|ENOTEMPTY|ENOENT/i.test(output) &&
|
|
81
|
+
/AppData[\\/]+Roaming[\\/]+npm[\\/]+node_modules[\\/]+shortcutxl/i.test(output)) {
|
|
82
|
+
return [
|
|
83
|
+
'ShortcutXL could not update because npm could not clean up the previous global install.',
|
|
84
|
+
`Close ShortcutXL terminals and retry \`${updateCommand}\`.`
|
|
85
|
+
].join(' ');
|
|
86
|
+
}
|
|
87
|
+
return `ShortcutXL could not update automatically. Retry with \`${updateCommand}\`.`;
|
|
88
|
+
}
|
|
89
|
+
function writeUpdateFailureLog({ command, exitCode, signal, output, truncated, resolveLogPath }) {
|
|
90
|
+
try {
|
|
91
|
+
const logPath = resolveLogPath();
|
|
92
|
+
mkdirSync(dirname(logPath), { recursive: true });
|
|
93
|
+
appendFileSync(logPath, [
|
|
94
|
+
'',
|
|
95
|
+
'--- ShortcutXL update failure ---',
|
|
96
|
+
`time=${new Date().toISOString()}`,
|
|
97
|
+
`command=${command}`,
|
|
98
|
+
`exitCode=${String(exitCode)}`,
|
|
99
|
+
`signal=${String(signal)}`,
|
|
100
|
+
truncated ? `outputTruncatedAfterBytes=${MAX_CAPTURED_OUTPUT_BYTES}` : undefined,
|
|
101
|
+
output
|
|
102
|
+
]
|
|
103
|
+
.filter((line) => line !== undefined)
|
|
104
|
+
.join('\n'), 'utf-8');
|
|
105
|
+
return logPath;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
39
111
|
//# sourceMappingURL=update-action.js.map
|
package/package.json
CHANGED
|
Binary file
|
package/xll/ShortcutXL.xll
CHANGED
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
../../Scripts/httpx.exe,sha256=
|
|
1
|
+
../../Scripts/httpx.exe,sha256=hKWaVi_N2EraqZWrqTZz-IOtGz3AZwj8smjqMnX4Oc0,108375
|
|
2
2
|
httpx-0.28.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
3
3
|
httpx-0.28.1.dist-info/METADATA,sha256=_rubD48-gNV8gZnDBPNcQzboWB0dGNeYPJJ2a4J5OyU,7052
|
|
4
4
|
httpx-0.28.1.dist-info/RECORD,,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
../../Scripts/idna.exe,sha256=
|
|
1
|
+
../../Scripts/idna.exe,sha256=pb0G50CoxK8b2NeIPvx60WsLIVGyqeWe9tZCgsFkpWs,108378
|
|
2
2
|
idna-3.18.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
3
3
|
idna-3.18.dist-info/METADATA,sha256=Rt_m5axGLQ9oDs2avPZugptqIzSCS02eOXmzETXK8oE,6119
|
|
4
4
|
idna-3.18.dist-info/RECORD,,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
../../Scripts/pip.exe,sha256=
|
|
2
|
-
../../Scripts/pip3.13.exe,sha256=
|
|
3
|
-
../../Scripts/pip3.exe,sha256=
|
|
1
|
+
../../Scripts/pip.exe,sha256=LkvtNOocma7gMlnPefH9mlapkAyv1-y2DIGMReESVTM,108392
|
|
2
|
+
../../Scripts/pip3.13.exe,sha256=LkvtNOocma7gMlnPefH9mlapkAyv1-y2DIGMReESVTM,108392
|
|
3
|
+
../../Scripts/pip3.exe,sha256=LkvtNOocma7gMlnPefH9mlapkAyv1-y2DIGMReESVTM,108392
|
|
4
4
|
pip-26.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
5
5
|
pip-26.1.2.dist-info/METADATA,sha256=F4Mt5Htdwj5GJTuhZGJSADbyjZon1cMBV3hJUspOabI,4566
|
|
6
6
|
pip-26.1.2.dist-info/RECORD,,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
../../Scripts/__pycache__/pywin32_postinstall.cpython-313.pyc,,
|
|
2
2
|
../../Scripts/__pycache__/pywin32_testall.cpython-313.pyc,,
|
|
3
|
-
../../Scripts/pywin32_postinstall.exe,sha256=
|
|
3
|
+
../../Scripts/pywin32_postinstall.exe,sha256=fAJ3WBDQg_HnCgJsLqgOoIY3O9qsgRqaTxwZ2tnlTm8,108403
|
|
4
4
|
../../Scripts/pywin32_postinstall.py,sha256=mx4WVp1hD_8xgkSXttNtto1BVDECZOc3FCClrR1SjFM,25736
|
|
5
|
-
../../Scripts/pywin32_testall.exe,sha256=
|
|
5
|
+
../../Scripts/pywin32_testall.exe,sha256=uhRZHHwouOWKKRBA1wsKz_eXWYZFq_xPnrTi87bgucc,108399
|
|
6
6
|
../../Scripts/pywin32_testall.py,sha256=hyGLMKILn3_W0q-McP1VJnNFW_z5yk_gesTMQDlUocM,3847
|
|
7
7
|
PyWin32.chm,sha256=S3fN4iKEUFyW4IIm3Zf5jtdrlTJLh93MzIrT9wX3z9o,2646518
|
|
8
8
|
__pycache__/pythoncom.cpython-313.pyc,,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|