@quanta-intellect/vessel-browser 0.1.30 → 0.1.32
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/README.md +14 -1
- package/out/main/index.js +332 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
Open source chromium-based browser for persistent web agents
|
|
14
|
+
Open source chromium-based browser for persistent web agents. Linux is the most mature install target today, and macOS release packaging is available from source.
|
|
15
15
|
|
|
16
16
|
Vessel gives external agent harnesses a real browser with durable state, MCP control, and a human-visible supervisory UI. It is built for long-running workflows where the agent drives and the human audits, intervenes, and redirects when needed.
|
|
17
17
|
|
|
@@ -200,12 +200,25 @@ npm run dist:dir
|
|
|
200
200
|
|
|
201
201
|
# Package a Linux AppImage
|
|
202
202
|
npm run dist
|
|
203
|
+
|
|
204
|
+
# Package an unpacked macOS app bundle (run on macOS)
|
|
205
|
+
npm run dist:mac:dir
|
|
206
|
+
|
|
207
|
+
# Package macOS DMG + ZIP artifacts (run on macOS)
|
|
208
|
+
npm run dist:mac
|
|
209
|
+
|
|
210
|
+
# Package signed macOS DMG + ZIP artifacts (run on macOS with signing set up)
|
|
211
|
+
npm run dist:mac:signed
|
|
203
212
|
```
|
|
204
213
|
|
|
205
214
|
Notes:
|
|
206
215
|
|
|
207
216
|
- `npm run dev` still launches the stock Electron binary, so Linux may continue showing the default Electron gear icon in development
|
|
208
217
|
- packaged builds created with `npm run dist` / `npm run dist:dir` use the Vessel app icon
|
|
218
|
+
- `npm run build:icon:mac` regenerates `resources/vessel-icon.icns` from `resources/vessel-icon.png` for macOS packaging
|
|
219
|
+
- `npm run dist:mac` and `npm run dist:mac:dir` intentionally disable auto-signing so local packaging works on any Mac without keychain setup
|
|
220
|
+
- `npm run dist:mac:signed` and `npm run dist:mac:dir:signed` use normal `electron-builder` signing discovery; if your login keychain has duplicate Apple certs, clean those up or use a dedicated keychain before running the signed path
|
|
221
|
+
- signed builds are still not notarized by this repo out of the box, so Gatekeeper warnings remain until notarization is added for release publishing
|
|
209
222
|
- the tracked smoke test runs typecheck, build, the MCP stdio proxy regression check, and the Electron navigation regression harness
|
|
210
223
|
- for headless CI, run the smoke test under `xvfb-run -a npm run smoke:test`
|
|
211
224
|
|
package/out/main/index.js
CHANGED
|
@@ -11509,6 +11509,325 @@ async function submitForm$1(wc, args) {
|
|
|
11509
11509
|
async function clickElementBySelector(wc, selector) {
|
|
11510
11510
|
return clickResolvedSelector$1(wc, selector);
|
|
11511
11511
|
}
|
|
11512
|
+
const HUGGING_FACE_HUB_HOSTS = /* @__PURE__ */ new Set(["huggingface.co", "www.huggingface.co"]);
|
|
11513
|
+
const HUGGING_FACE_MODEL_TASKS = [
|
|
11514
|
+
{
|
|
11515
|
+
value: "automatic-speech-recognition",
|
|
11516
|
+
label: "automatic speech recognition",
|
|
11517
|
+
phrases: ["automatic speech recognition", "speech recognition", "asr"]
|
|
11518
|
+
},
|
|
11519
|
+
{
|
|
11520
|
+
value: "text-classification",
|
|
11521
|
+
label: "text classification",
|
|
11522
|
+
phrases: ["text classification", "classification"]
|
|
11523
|
+
},
|
|
11524
|
+
{
|
|
11525
|
+
value: "token-classification",
|
|
11526
|
+
label: "token classification",
|
|
11527
|
+
phrases: ["token classification", "named entity recognition", "ner"]
|
|
11528
|
+
},
|
|
11529
|
+
{
|
|
11530
|
+
value: "question-answering",
|
|
11531
|
+
label: "question answering",
|
|
11532
|
+
phrases: ["question answering", "qa"]
|
|
11533
|
+
},
|
|
11534
|
+
{
|
|
11535
|
+
value: "sentence-similarity",
|
|
11536
|
+
label: "sentence similarity",
|
|
11537
|
+
phrases: ["sentence similarity", "semantic similarity"]
|
|
11538
|
+
},
|
|
11539
|
+
{
|
|
11540
|
+
value: "feature-extraction",
|
|
11541
|
+
label: "feature extraction",
|
|
11542
|
+
phrases: ["feature extraction", "embeddings", "embedding"]
|
|
11543
|
+
},
|
|
11544
|
+
{
|
|
11545
|
+
value: "image-classification",
|
|
11546
|
+
label: "image classification",
|
|
11547
|
+
phrases: ["image classification"]
|
|
11548
|
+
},
|
|
11549
|
+
{
|
|
11550
|
+
value: "object-detection",
|
|
11551
|
+
label: "object detection",
|
|
11552
|
+
phrases: ["object detection"]
|
|
11553
|
+
},
|
|
11554
|
+
{
|
|
11555
|
+
value: "image-to-text",
|
|
11556
|
+
label: "image to text",
|
|
11557
|
+
phrases: ["image to text", "image-to-text", "ocr"]
|
|
11558
|
+
},
|
|
11559
|
+
{
|
|
11560
|
+
value: "text-to-image",
|
|
11561
|
+
label: "text to image",
|
|
11562
|
+
phrases: ["text to image", "text-to-image"]
|
|
11563
|
+
},
|
|
11564
|
+
{
|
|
11565
|
+
value: "text-to-speech",
|
|
11566
|
+
label: "text to speech",
|
|
11567
|
+
phrases: ["text to speech", "text-to-speech", "tts"]
|
|
11568
|
+
},
|
|
11569
|
+
{
|
|
11570
|
+
value: "text-generation",
|
|
11571
|
+
label: "text generation",
|
|
11572
|
+
phrases: [
|
|
11573
|
+
"text generation",
|
|
11574
|
+
"text-generation",
|
|
11575
|
+
"llm",
|
|
11576
|
+
"chat model",
|
|
11577
|
+
"chat models",
|
|
11578
|
+
"instruct model",
|
|
11579
|
+
"instruct models"
|
|
11580
|
+
]
|
|
11581
|
+
},
|
|
11582
|
+
{
|
|
11583
|
+
value: "text2text-generation",
|
|
11584
|
+
label: "text2text generation",
|
|
11585
|
+
phrases: [
|
|
11586
|
+
"text2text generation",
|
|
11587
|
+
"text-to-text generation",
|
|
11588
|
+
"text to text generation"
|
|
11589
|
+
]
|
|
11590
|
+
},
|
|
11591
|
+
{
|
|
11592
|
+
value: "summarization",
|
|
11593
|
+
label: "summarization",
|
|
11594
|
+
phrases: ["summarization", "summarize", "summarizer"]
|
|
11595
|
+
},
|
|
11596
|
+
{
|
|
11597
|
+
value: "translation",
|
|
11598
|
+
label: "translation",
|
|
11599
|
+
phrases: ["translation", "translate", "translator"]
|
|
11600
|
+
}
|
|
11601
|
+
];
|
|
11602
|
+
const HUGGING_FACE_MODEL_LIBRARIES = [
|
|
11603
|
+
{ value: "sentence-transformers", label: "sentence-transformers", phrases: ["sentence-transformers"] },
|
|
11604
|
+
{ value: "transformers.js", label: "transformers.js", phrases: ["transformers.js"] },
|
|
11605
|
+
{ value: "transformers", label: "transformers", phrases: ["transformers"] },
|
|
11606
|
+
{ value: "diffusers", label: "diffusers", phrases: ["diffusers"] },
|
|
11607
|
+
{ value: "safetensors", label: "safetensors", phrases: ["safetensors"] },
|
|
11608
|
+
{ value: "pytorch", label: "pytorch", phrases: ["pytorch"] },
|
|
11609
|
+
{ value: "tf", label: "tensorflow", phrases: ["tensorflow", "tf"] },
|
|
11610
|
+
{ value: "jax", label: "jax", phrases: ["jax"] },
|
|
11611
|
+
{ value: "onnx", label: "onnx", phrases: ["onnx"] },
|
|
11612
|
+
{ value: "gguf", label: "gguf", phrases: ["gguf"] },
|
|
11613
|
+
{ value: "mlx", label: "mlx", phrases: ["mlx"] }
|
|
11614
|
+
];
|
|
11615
|
+
function escapeRegex(value) {
|
|
11616
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11617
|
+
}
|
|
11618
|
+
function stripSearchPhrase(query, phrase) {
|
|
11619
|
+
return query.replace(
|
|
11620
|
+
new RegExp(`(^|[^\\w])${escapeRegex(phrase)}(?=[^\\w]|$)`, "gi"),
|
|
11621
|
+
" "
|
|
11622
|
+
);
|
|
11623
|
+
}
|
|
11624
|
+
function collapseSearchTerms(query) {
|
|
11625
|
+
return query.replace(/\b(on|in|for|with|without|from|by|to|of|the|a|an|and|or)\b/gi, " ").replace(/\b(find|show|search|browse|look(?:ing)?(?:\s+for)?|need|want)\b/gi, " ").replace(/\bhugging\s*face\b/gi, " ").replace(/\s+/g, " ").trim();
|
|
11626
|
+
}
|
|
11627
|
+
function normalizeSearchQuery(query) {
|
|
11628
|
+
return query.replace(/\s+/g, " ").trim();
|
|
11629
|
+
}
|
|
11630
|
+
function extractFirstMatchingFilter(query, filters) {
|
|
11631
|
+
for (const filter of filters) {
|
|
11632
|
+
for (const phrase of filter.phrases) {
|
|
11633
|
+
const pattern = new RegExp(
|
|
11634
|
+
`(^|[^\\w])${escapeRegex(phrase)}(?=[^\\w]|$)`,
|
|
11635
|
+
"i"
|
|
11636
|
+
);
|
|
11637
|
+
if (!pattern.test(query)) continue;
|
|
11638
|
+
return {
|
|
11639
|
+
match: { value: filter.value, label: filter.label },
|
|
11640
|
+
remainingQuery: stripSearchPhrase(query, phrase)
|
|
11641
|
+
};
|
|
11642
|
+
}
|
|
11643
|
+
}
|
|
11644
|
+
return { match: null, remainingQuery: query };
|
|
11645
|
+
}
|
|
11646
|
+
function mapHuggingFaceParameterBucket(query) {
|
|
11647
|
+
const match = query.match(/\b(\d+(?:\.\d+)?)\s*(b|bn|billion|t|tn|trillion)\b/i);
|
|
11648
|
+
if (!match) {
|
|
11649
|
+
return { value: null, label: null, remainingQuery: query };
|
|
11650
|
+
}
|
|
11651
|
+
const amount = Number(match[1]);
|
|
11652
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
11653
|
+
return { value: null, label: null, remainingQuery: query };
|
|
11654
|
+
}
|
|
11655
|
+
const unit = match[2].toLowerCase();
|
|
11656
|
+
const billions = unit === "t" || unit === "tn" || unit === "trillion" ? amount * 1e3 : amount;
|
|
11657
|
+
let value;
|
|
11658
|
+
if (billions < 1) value = "n<1B";
|
|
11659
|
+
else if (billions < 3) value = "1B<n<3B";
|
|
11660
|
+
else if (billions < 6) value = "3B<n<6B";
|
|
11661
|
+
else if (billions < 9) value = "6B<n<9B";
|
|
11662
|
+
else if (billions < 12) value = "9B<n<12B";
|
|
11663
|
+
else if (billions < 24) value = "12B<n<24B";
|
|
11664
|
+
else if (billions < 32) value = "24B<n<32B";
|
|
11665
|
+
else if (billions < 64) value = "32B<n<64B";
|
|
11666
|
+
else if (billions < 128) value = "64B<n<128B";
|
|
11667
|
+
else if (billions < 256) value = "128B<n<256B";
|
|
11668
|
+
else if (billions < 500) value = "256B<n<500B";
|
|
11669
|
+
else if (billions < 1e3) value = "500B<n<1T";
|
|
11670
|
+
else value = "n>1T";
|
|
11671
|
+
return {
|
|
11672
|
+
value,
|
|
11673
|
+
label: `${amount}${unit.startsWith("t") ? "T" : "B"} size bucket`,
|
|
11674
|
+
remainingQuery: query.replace(match[0], " ")
|
|
11675
|
+
};
|
|
11676
|
+
}
|
|
11677
|
+
function chooseHuggingFaceSection(url, query) {
|
|
11678
|
+
const pathname = url.pathname.toLowerCase();
|
|
11679
|
+
const normalized = query.toLowerCase();
|
|
11680
|
+
const mentionsDatasets = /\b(dataset|datasets|corpus|benchmark|benchmarks)\b/.test(
|
|
11681
|
+
normalized
|
|
11682
|
+
);
|
|
11683
|
+
const mentionsSpaces = /\b(space|spaces|app|apps|demo|demos|gradio|streamlit)\b/.test(
|
|
11684
|
+
normalized
|
|
11685
|
+
);
|
|
11686
|
+
const mentionsModels = /\b(model|models|checkpoint|checkpoints|lora|loras|weights)\b/.test(
|
|
11687
|
+
normalized
|
|
11688
|
+
);
|
|
11689
|
+
if (mentionsDatasets && !mentionsModels && !mentionsSpaces) return "datasets";
|
|
11690
|
+
if (mentionsSpaces && !mentionsModels && !mentionsDatasets) return "spaces";
|
|
11691
|
+
if (mentionsModels && !mentionsDatasets && !mentionsSpaces) return "models";
|
|
11692
|
+
if (pathname.startsWith("/models")) return "models";
|
|
11693
|
+
if (pathname.startsWith("/datasets")) return "datasets";
|
|
11694
|
+
if (pathname.startsWith("/spaces")) return "spaces";
|
|
11695
|
+
if (HUGGING_FACE_MODEL_TASKS.some(
|
|
11696
|
+
(entry) => entry.phrases.some(
|
|
11697
|
+
(phrase) => new RegExp(`(^|[^\\w])${escapeRegex(phrase)}(?=[^\\w]|$)`, "i").test(
|
|
11698
|
+
normalized
|
|
11699
|
+
)
|
|
11700
|
+
)
|
|
11701
|
+
) || HUGGING_FACE_MODEL_LIBRARIES.some(
|
|
11702
|
+
(entry) => entry.phrases.some(
|
|
11703
|
+
(phrase) => new RegExp(`(^|[^\\w])${escapeRegex(phrase)}(?=[^\\w]|$)`, "i").test(
|
|
11704
|
+
normalized
|
|
11705
|
+
)
|
|
11706
|
+
)
|
|
11707
|
+
) || /\b\d+(?:\.\d+)?\s*(b|bn|billion|t|tn|trillion)\b/i.test(normalized)) {
|
|
11708
|
+
return "models";
|
|
11709
|
+
}
|
|
11710
|
+
return null;
|
|
11711
|
+
}
|
|
11712
|
+
function buildHuggingFaceSearchShortcut(currentUrl, rawQuery) {
|
|
11713
|
+
let url;
|
|
11714
|
+
try {
|
|
11715
|
+
url = new URL(currentUrl);
|
|
11716
|
+
} catch {
|
|
11717
|
+
return null;
|
|
11718
|
+
}
|
|
11719
|
+
const hostname = url.hostname.toLowerCase();
|
|
11720
|
+
if (!HUGGING_FACE_HUB_HOSTS.has(hostname)) {
|
|
11721
|
+
return null;
|
|
11722
|
+
}
|
|
11723
|
+
const query = rawQuery.trim();
|
|
11724
|
+
if (!query) return null;
|
|
11725
|
+
const section = chooseHuggingFaceSection(url, query);
|
|
11726
|
+
if (!section) return null;
|
|
11727
|
+
let remainingQuery = query;
|
|
11728
|
+
const target = new URL(`https://huggingface.co/${section}`);
|
|
11729
|
+
const appliedFilters = [];
|
|
11730
|
+
if (section === "models") {
|
|
11731
|
+
const taskResult = extractFirstMatchingFilter(
|
|
11732
|
+
remainingQuery,
|
|
11733
|
+
HUGGING_FACE_MODEL_TASKS
|
|
11734
|
+
);
|
|
11735
|
+
remainingQuery = taskResult.remainingQuery;
|
|
11736
|
+
if (taskResult.match) {
|
|
11737
|
+
target.searchParams.append("pipeline_tag", taskResult.match.value);
|
|
11738
|
+
appliedFilters.push(`task: ${taskResult.match.label}`);
|
|
11739
|
+
}
|
|
11740
|
+
const libraryResult = extractFirstMatchingFilter(
|
|
11741
|
+
remainingQuery,
|
|
11742
|
+
HUGGING_FACE_MODEL_LIBRARIES
|
|
11743
|
+
);
|
|
11744
|
+
remainingQuery = libraryResult.remainingQuery;
|
|
11745
|
+
if (libraryResult.match) {
|
|
11746
|
+
target.searchParams.append("library", libraryResult.match.value);
|
|
11747
|
+
appliedFilters.push(`library: ${libraryResult.match.label}`);
|
|
11748
|
+
}
|
|
11749
|
+
const parameterResult = mapHuggingFaceParameterBucket(remainingQuery);
|
|
11750
|
+
remainingQuery = parameterResult.remainingQuery;
|
|
11751
|
+
if (parameterResult.value && parameterResult.label) {
|
|
11752
|
+
target.searchParams.append("num_parameters", parameterResult.value);
|
|
11753
|
+
appliedFilters.push(parameterResult.label);
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11756
|
+
remainingQuery = collapseSearchTerms(
|
|
11757
|
+
remainingQuery.replace(/\bmodels?\b/gi, " ").replace(/\bdatasets?\b/gi, " ").replace(/\bspaces?\b/gi, " ").replace(/\bapps?\b/gi, " ")
|
|
11758
|
+
);
|
|
11759
|
+
if (remainingQuery) {
|
|
11760
|
+
target.searchParams.set("search", remainingQuery);
|
|
11761
|
+
}
|
|
11762
|
+
if (!remainingQuery && appliedFilters.length === 0) {
|
|
11763
|
+
return null;
|
|
11764
|
+
}
|
|
11765
|
+
if (section === "spaces" && remainingQuery) {
|
|
11766
|
+
target.searchParams.set("includeNonRunning", "true");
|
|
11767
|
+
}
|
|
11768
|
+
return {
|
|
11769
|
+
url: target.toString(),
|
|
11770
|
+
source: "Hugging Face",
|
|
11771
|
+
section,
|
|
11772
|
+
appliedFilters
|
|
11773
|
+
};
|
|
11774
|
+
}
|
|
11775
|
+
const COMMON_SEARCH_QUERY_PARAMS = [
|
|
11776
|
+
"search",
|
|
11777
|
+
"q",
|
|
11778
|
+
"query",
|
|
11779
|
+
"keyword",
|
|
11780
|
+
"keywords",
|
|
11781
|
+
"term",
|
|
11782
|
+
"text"
|
|
11783
|
+
];
|
|
11784
|
+
const COMMON_PAGINATION_PARAMS = [
|
|
11785
|
+
"p",
|
|
11786
|
+
"page",
|
|
11787
|
+
"offset",
|
|
11788
|
+
"start",
|
|
11789
|
+
"cursor",
|
|
11790
|
+
"skip"
|
|
11791
|
+
];
|
|
11792
|
+
function looksLikeSearchResultsPath(pathname) {
|
|
11793
|
+
return /\/(search|results|browse|discover|find)(\/|$)/i.test(pathname);
|
|
11794
|
+
}
|
|
11795
|
+
function buildCommonSearchUrlShortcut(currentUrl, rawQuery) {
|
|
11796
|
+
let url;
|
|
11797
|
+
try {
|
|
11798
|
+
url = new URL(currentUrl);
|
|
11799
|
+
} catch {
|
|
11800
|
+
return null;
|
|
11801
|
+
}
|
|
11802
|
+
if (!/^https?:$/i.test(url.protocol)) {
|
|
11803
|
+
return null;
|
|
11804
|
+
}
|
|
11805
|
+
const query = normalizeSearchQuery(rawQuery);
|
|
11806
|
+
if (!query) return null;
|
|
11807
|
+
const existingParam = COMMON_SEARCH_QUERY_PARAMS.find(
|
|
11808
|
+
(param) => url.searchParams.has(param)
|
|
11809
|
+
);
|
|
11810
|
+
if (!existingParam && !looksLikeSearchResultsPath(url.pathname)) {
|
|
11811
|
+
return null;
|
|
11812
|
+
}
|
|
11813
|
+
const target = new URL(url.toString());
|
|
11814
|
+
const searchParam = existingParam ?? "q";
|
|
11815
|
+
target.searchParams.set(searchParam, query);
|
|
11816
|
+
for (const param of COMMON_PAGINATION_PARAMS) {
|
|
11817
|
+
target.searchParams.delete(param);
|
|
11818
|
+
}
|
|
11819
|
+
if (target.toString() === url.toString()) {
|
|
11820
|
+
return null;
|
|
11821
|
+
}
|
|
11822
|
+
return {
|
|
11823
|
+
url: target.toString(),
|
|
11824
|
+
source: "page URL",
|
|
11825
|
+
appliedFilters: existingParam ? [`updated ${existingParam} query`] : []
|
|
11826
|
+
};
|
|
11827
|
+
}
|
|
11828
|
+
function buildSearchShortcut(currentUrl, rawQuery) {
|
|
11829
|
+
return buildHuggingFaceSearchShortcut(currentUrl, rawQuery) ?? buildCommonSearchUrlShortcut(currentUrl, rawQuery);
|
|
11830
|
+
}
|
|
11512
11831
|
async function locateSearchTarget(wc, explicitSelector) {
|
|
11513
11832
|
if (explicitSelector) {
|
|
11514
11833
|
return { selector: explicitSelector, submitSelector: null };
|
|
@@ -11775,6 +12094,19 @@ async function searchPage(wc, args) {
|
|
|
11775
12094
|
if (buttonLikePatterns.some((p) => queryLower.includes(p))) {
|
|
11776
12095
|
return `Error: "${query}" looks like a button label, not a search query. Use the click tool to interact with this element instead.`;
|
|
11777
12096
|
}
|
|
12097
|
+
if (typeof args.selector !== "string") {
|
|
12098
|
+
const shortcut = buildSearchShortcut(wc.getURL(), query);
|
|
12099
|
+
if (shortcut) {
|
|
12100
|
+
const beforeUrl2 = wc.getURL();
|
|
12101
|
+
assertSafeURL(shortcut.url);
|
|
12102
|
+
wc.loadURL(shortcut.url);
|
|
12103
|
+
await waitForPotentialNavigation$1(wc, beforeUrl2, 4e3);
|
|
12104
|
+
const afterUrl2 = wc.getURL();
|
|
12105
|
+
const applied = shortcut.appliedFilters.length > 0 ? ` (${shortcut.appliedFilters.join(", ")})` : "";
|
|
12106
|
+
const destination = shortcut.section ? ` ${shortcut.section}` : "";
|
|
12107
|
+
return `Searched "${query}" via ${shortcut.source}${destination} shortcut${applied} → ${afterUrl2}`;
|
|
12108
|
+
}
|
|
12109
|
+
}
|
|
11778
12110
|
const searchInfo = await locateSearchTarget(
|
|
11779
12111
|
wc,
|
|
11780
12112
|
typeof args.selector === "string" ? args.selector : void 0
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quanta-intellect/vessel-browser",
|
|
3
3
|
"mcpName": "io.github.unmodeled-tyler/vessel-browser",
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"description": "AI-native web browser
|
|
4
|
+
"version": "0.1.32",
|
|
5
|
+
"description": "AI-native web browser runtime for autonomous agents with human supervision",
|
|
6
6
|
"main": "./out/main/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"vessel-browser": "./bin/vessel-browser.js"
|
|
@@ -16,10 +16,15 @@
|
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"dev": "electron-vite dev",
|
|
19
|
+
"dev": "ELECTRON_DISABLE_SANDBOX=1 electron-vite dev",
|
|
20
20
|
"build": "electron-vite build",
|
|
21
|
+
"build:icon:mac": "scripts/build-macos-icon.sh",
|
|
21
22
|
"dist": "npm run build && electron-builder --linux --publish never",
|
|
22
23
|
"dist:dir": "npm run build && electron-builder --linux dir --publish never",
|
|
24
|
+
"dist:mac": "npm run build:icon:mac && npm run build && CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac dmg zip --publish never",
|
|
25
|
+
"dist:mac:dir": "npm run build:icon:mac && npm run build && CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac dir --publish never",
|
|
26
|
+
"dist:mac:signed": "npm run build:icon:mac && npm run build && electron-builder --mac dmg zip --publish never",
|
|
27
|
+
"dist:mac:dir:signed": "npm run build:icon:mac && npm run build && electron-builder --mac dir --publish never",
|
|
23
28
|
"preview": "electron-vite preview",
|
|
24
29
|
"typecheck": "tsc --noEmit",
|
|
25
30
|
"prepublishOnly": "npm run build",
|