moonlait 0.1.0 → 0.2.0
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 +24 -3
- package/dist/cli.js +278 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,11 +26,30 @@ one-time code and the command to run with it:
|
|
|
26
26
|
npx moonlait@latest pair <CODE> --server <your Moonlait address>
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Then allow a folder
|
|
30
|
-
long as it runs:
|
|
29
|
+
Then allow a folder your agents may work in:
|
|
31
30
|
|
|
32
31
|
```sh
|
|
33
|
-
npx moonlait@latest
|
|
32
|
+
npx moonlait@latest folders add ~/Desktop
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Keep it running
|
|
36
|
+
|
|
37
|
+
Installed as a service, the bridge starts when you log in, restarts after
|
|
38
|
+
a crash, and needs no window open — launchd on macOS, systemd on Linux, a
|
|
39
|
+
logon task on Windows:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
npm install -g moonlait
|
|
43
|
+
moonlait service install
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`moonlait service status` says whether it is running, `moonlait service
|
|
47
|
+
uninstall` removes it, and its log is `~/.moonlait/bridge.log`.
|
|
48
|
+
|
|
49
|
+
To run it just for now instead, in a window you keep open:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
npx moonlait@latest start
|
|
34
53
|
```
|
|
35
54
|
|
|
36
55
|
## Commands
|
|
@@ -42,6 +61,8 @@ npx moonlait@latest start --workspace ~/code/my-project
|
|
|
42
61
|
| `folders remove <folder>…` | Takes folders off the list |
|
|
43
62
|
| `folders` | Lists the allowed folders |
|
|
44
63
|
| `start [--workspace <folder>]` | Runs the bridge; `--workspace` allows a folder for this run only |
|
|
64
|
+
| `service install` | Runs the bridge in the background, from every login |
|
|
65
|
+
| `service status` / `service uninstall` | How it is doing; remove it again |
|
|
45
66
|
| `agents` | Lists the agents found on this computer |
|
|
46
67
|
|
|
47
68
|
The pairing is kept in `~/.moonlait/bridge.json`, readable by you only.
|
package/dist/cli.js
CHANGED
|
@@ -8,9 +8,9 @@ var __export = (target, all) => {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
// bridge/cli.ts
|
|
11
|
-
import { existsSync as
|
|
12
|
-
import { homedir as
|
|
13
|
-
import
|
|
11
|
+
import { existsSync as existsSync5, realpathSync as realpathSync2, statSync as statSync2, unwatchFile, watchFile } from "node:fs";
|
|
12
|
+
import { homedir as homedir3, hostname as hostname3 } from "node:os";
|
|
13
|
+
import path6 from "node:path";
|
|
14
14
|
|
|
15
15
|
// bridge/agents.ts
|
|
16
16
|
import { execFileSync } from "node:child_process";
|
|
@@ -1108,10 +1108,10 @@ function mergeDefs(...defs) {
|
|
|
1108
1108
|
function cloneDef(schema) {
|
|
1109
1109
|
return mergeDefs(schema._zod.def);
|
|
1110
1110
|
}
|
|
1111
|
-
function getElementAtPath(obj,
|
|
1112
|
-
if (!
|
|
1111
|
+
function getElementAtPath(obj, path7) {
|
|
1112
|
+
if (!path7)
|
|
1113
1113
|
return obj;
|
|
1114
|
-
return
|
|
1114
|
+
return path7.reduce((acc, key) => acc?.[key], obj);
|
|
1115
1115
|
}
|
|
1116
1116
|
function promiseAllObject(promisesObj) {
|
|
1117
1117
|
const keys = Object.keys(promisesObj);
|
|
@@ -1451,11 +1451,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1451
1451
|
}
|
|
1452
1452
|
return false;
|
|
1453
1453
|
}
|
|
1454
|
-
function prefixIssues(
|
|
1454
|
+
function prefixIssues(path7, issues) {
|
|
1455
1455
|
return issues.map((iss) => {
|
|
1456
1456
|
var _a3;
|
|
1457
1457
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1458
|
-
iss.path.unshift(
|
|
1458
|
+
iss.path.unshift(path7);
|
|
1459
1459
|
return iss;
|
|
1460
1460
|
});
|
|
1461
1461
|
}
|
|
@@ -1905,16 +1905,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
1905
1905
|
}
|
|
1906
1906
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
1907
1907
|
const fieldErrors = { _errors: [] };
|
|
1908
|
-
const processError = (error63,
|
|
1908
|
+
const processError = (error63, path7 = []) => {
|
|
1909
1909
|
for (const issue2 of error63.issues) {
|
|
1910
1910
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1911
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1911
|
+
issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
|
|
1912
1912
|
} else if (issue2.code === "invalid_key") {
|
|
1913
|
-
processError({ issues: issue2.issues }, [...
|
|
1913
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
1914
1914
|
} else if (issue2.code === "invalid_element") {
|
|
1915
|
-
processError({ issues: issue2.issues }, [...
|
|
1915
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
1916
1916
|
} else {
|
|
1917
|
-
const fullpath = [...
|
|
1917
|
+
const fullpath = [...path7, ...issue2.path];
|
|
1918
1918
|
if (fullpath.length === 0) {
|
|
1919
1919
|
fieldErrors._errors.push(mapper(issue2));
|
|
1920
1920
|
} else {
|
|
@@ -1953,17 +1953,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
1953
1953
|
}
|
|
1954
1954
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
1955
1955
|
const result = { errors: [] };
|
|
1956
|
-
const processError = (error63,
|
|
1956
|
+
const processError = (error63, path7 = []) => {
|
|
1957
1957
|
var _a3;
|
|
1958
1958
|
for (const issue2 of error63.issues) {
|
|
1959
1959
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1960
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1960
|
+
issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
|
|
1961
1961
|
} else if (issue2.code === "invalid_key") {
|
|
1962
|
-
processError({ issues: issue2.issues }, [...
|
|
1962
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
1963
1963
|
} else if (issue2.code === "invalid_element") {
|
|
1964
|
-
processError({ issues: issue2.issues }, [...
|
|
1964
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
1965
1965
|
} else {
|
|
1966
|
-
const fullpath = [...
|
|
1966
|
+
const fullpath = [...path7, ...issue2.path];
|
|
1967
1967
|
if (fullpath.length === 0) {
|
|
1968
1968
|
result.errors.push(mapper(issue2));
|
|
1969
1969
|
continue;
|
|
@@ -2002,8 +2002,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
2002
2002
|
}
|
|
2003
2003
|
function toDotPath(_path) {
|
|
2004
2004
|
const segs = [];
|
|
2005
|
-
const
|
|
2006
|
-
for (const seg of
|
|
2005
|
+
const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2006
|
+
for (const seg of path7) {
|
|
2007
2007
|
if (typeof seg === "number")
|
|
2008
2008
|
segs.push(`[${seg}]`);
|
|
2009
2009
|
else if (typeof seg === "symbol")
|
|
@@ -5988,8 +5988,8 @@ var error3 = () => {
|
|
|
5988
5988
|
const sizing = getSizing(issue2.origin);
|
|
5989
5989
|
if (sizing) {
|
|
5990
5990
|
const maxValue = Number(issue2.maximum);
|
|
5991
|
-
const
|
|
5992
|
-
return `\u0417\u0430\u043D\u0430\u0434\u0442\u0430 \u0432\u044F\u043B\u0456\u043A\u0456: \u0447\u0430\u043A\u0430\u043B\u0430\u0441\u044F, \u0448\u0442\u043E ${issue2.origin ?? "\u0437\u043D\u0430\u0447\u044D\u043D\u043D\u0435"} \u043F\u0430\u0432\u0456\u043D\u043D\u0430 ${sizing.verb} ${adj}${issue2.maximum.toString()} ${
|
|
5991
|
+
const unit2 = getBelarusianPlural(maxValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
|
5992
|
+
return `\u0417\u0430\u043D\u0430\u0434\u0442\u0430 \u0432\u044F\u043B\u0456\u043A\u0456: \u0447\u0430\u043A\u0430\u043B\u0430\u0441\u044F, \u0448\u0442\u043E ${issue2.origin ?? "\u0437\u043D\u0430\u0447\u044D\u043D\u043D\u0435"} \u043F\u0430\u0432\u0456\u043D\u043D\u0430 ${sizing.verb} ${adj}${issue2.maximum.toString()} ${unit2}`;
|
|
5993
5993
|
}
|
|
5994
5994
|
return `\u0417\u0430\u043D\u0430\u0434\u0442\u0430 \u0432\u044F\u043B\u0456\u043A\u0456: \u0447\u0430\u043A\u0430\u043B\u0430\u0441\u044F, \u0448\u0442\u043E ${issue2.origin ?? "\u0437\u043D\u0430\u0447\u044D\u043D\u043D\u0435"} \u043F\u0430\u0432\u0456\u043D\u043D\u0430 \u0431\u044B\u0446\u044C ${adj}${issue2.maximum.toString()}`;
|
|
5995
5995
|
}
|
|
@@ -5998,8 +5998,8 @@ var error3 = () => {
|
|
|
5998
5998
|
const sizing = getSizing(issue2.origin);
|
|
5999
5999
|
if (sizing) {
|
|
6000
6000
|
const minValue = Number(issue2.minimum);
|
|
6001
|
-
const
|
|
6002
|
-
return `\u0417\u0430\u043D\u0430\u0434\u0442\u0430 \u043C\u0430\u043B\u044B: \u0447\u0430\u043A\u0430\u043B\u0430\u0441\u044F, \u0448\u0442\u043E ${issue2.origin} \u043F\u0430\u0432\u0456\u043D\u043D\u0430 ${sizing.verb} ${adj}${issue2.minimum.toString()} ${
|
|
6001
|
+
const unit2 = getBelarusianPlural(minValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
|
6002
|
+
return `\u0417\u0430\u043D\u0430\u0434\u0442\u0430 \u043C\u0430\u043B\u044B: \u0447\u0430\u043A\u0430\u043B\u0430\u0441\u044F, \u0448\u0442\u043E ${issue2.origin} \u043F\u0430\u0432\u0456\u043D\u043D\u0430 ${sizing.verb} ${adj}${issue2.minimum.toString()} ${unit2}`;
|
|
6003
6003
|
}
|
|
6004
6004
|
return `\u0417\u0430\u043D\u0430\u0434\u0442\u0430 \u043C\u0430\u043B\u044B: \u0447\u0430\u043A\u0430\u043B\u0430\u0441\u044F, \u0448\u0442\u043E ${issue2.origin} \u043F\u0430\u0432\u0456\u043D\u043D\u0430 \u0431\u044B\u0446\u044C ${adj}${issue2.minimum.toString()}`;
|
|
6005
6005
|
}
|
|
@@ -8626,8 +8626,8 @@ var error24 = () => {
|
|
|
8626
8626
|
const sizing = getSizing(issue2.origin);
|
|
8627
8627
|
if (sizing) {
|
|
8628
8628
|
const maxValue = Number(issue2.maximum);
|
|
8629
|
-
const
|
|
8630
|
-
return `\u0549\u0561\u0583\u0561\u0566\u0561\u0576\u0581 \u0574\u0565\u056E \u0561\u0580\u056A\u0565\u0584\u2024 \u057D\u057A\u0561\u057D\u057E\u0578\u0582\u0574 \u0567, \u0578\u0580 ${withDefiniteArticle(issue2.origin ?? "\u0561\u0580\u056A\u0565\u0584")} \u056F\u0578\u0582\u0576\u0565\u0576\u0561 ${adj}${issue2.maximum.toString()} ${
|
|
8629
|
+
const unit2 = getArmenianPlural(maxValue, sizing.unit.one, sizing.unit.many);
|
|
8630
|
+
return `\u0549\u0561\u0583\u0561\u0566\u0561\u0576\u0581 \u0574\u0565\u056E \u0561\u0580\u056A\u0565\u0584\u2024 \u057D\u057A\u0561\u057D\u057E\u0578\u0582\u0574 \u0567, \u0578\u0580 ${withDefiniteArticle(issue2.origin ?? "\u0561\u0580\u056A\u0565\u0584")} \u056F\u0578\u0582\u0576\u0565\u0576\u0561 ${adj}${issue2.maximum.toString()} ${unit2}`;
|
|
8631
8631
|
}
|
|
8632
8632
|
return `\u0549\u0561\u0583\u0561\u0566\u0561\u0576\u0581 \u0574\u0565\u056E \u0561\u0580\u056A\u0565\u0584\u2024 \u057D\u057A\u0561\u057D\u057E\u0578\u0582\u0574 \u0567, \u0578\u0580 ${withDefiniteArticle(issue2.origin ?? "\u0561\u0580\u056A\u0565\u0584")} \u056C\u056B\u0576\u056B ${adj}${issue2.maximum.toString()}`;
|
|
8633
8633
|
}
|
|
@@ -8636,8 +8636,8 @@ var error24 = () => {
|
|
|
8636
8636
|
const sizing = getSizing(issue2.origin);
|
|
8637
8637
|
if (sizing) {
|
|
8638
8638
|
const minValue = Number(issue2.minimum);
|
|
8639
|
-
const
|
|
8640
|
-
return `\u0549\u0561\u0583\u0561\u0566\u0561\u0576\u0581 \u0583\u0578\u0584\u0580 \u0561\u0580\u056A\u0565\u0584\u2024 \u057D\u057A\u0561\u057D\u057E\u0578\u0582\u0574 \u0567, \u0578\u0580 ${withDefiniteArticle(issue2.origin)} \u056F\u0578\u0582\u0576\u0565\u0576\u0561 ${adj}${issue2.minimum.toString()} ${
|
|
8639
|
+
const unit2 = getArmenianPlural(minValue, sizing.unit.one, sizing.unit.many);
|
|
8640
|
+
return `\u0549\u0561\u0583\u0561\u0566\u0561\u0576\u0581 \u0583\u0578\u0584\u0580 \u0561\u0580\u056A\u0565\u0584\u2024 \u057D\u057A\u0561\u057D\u057E\u0578\u0582\u0574 \u0567, \u0578\u0580 ${withDefiniteArticle(issue2.origin)} \u056F\u0578\u0582\u0576\u0565\u0576\u0561 ${adj}${issue2.minimum.toString()} ${unit2}`;
|
|
8641
8641
|
}
|
|
8642
8642
|
return `\u0549\u0561\u0583\u0561\u0566\u0561\u0576\u0581 \u0583\u0578\u0584\u0580 \u0561\u0580\u056A\u0565\u0584\u2024 \u057D\u057A\u0561\u057D\u057E\u0578\u0582\u0574 \u0567, \u0578\u0580 ${withDefiniteArticle(issue2.origin)} \u056C\u056B\u0576\u056B ${adj}${issue2.minimum.toString()}`;
|
|
8643
8643
|
}
|
|
@@ -9551,18 +9551,18 @@ var error32 = () => {
|
|
|
9551
9551
|
const adj = issue2.inclusive ? "\uC774\uD558" : "\uBBF8\uB9CC";
|
|
9552
9552
|
const suffix = adj === "\uBBF8\uB9CC" ? "\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" : "\uC5EC\uC57C \uD569\uB2C8\uB2E4";
|
|
9553
9553
|
const sizing = getSizing(issue2.origin);
|
|
9554
|
-
const
|
|
9554
|
+
const unit2 = sizing?.unit ?? "\uC694\uC18C";
|
|
9555
9555
|
if (sizing)
|
|
9556
|
-
return `${issue2.origin ?? "\uAC12"}\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4: ${issue2.maximum.toString()}${
|
|
9556
|
+
return `${issue2.origin ?? "\uAC12"}\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4: ${issue2.maximum.toString()}${unit2} ${adj}${suffix}`;
|
|
9557
9557
|
return `${issue2.origin ?? "\uAC12"}\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4: ${issue2.maximum.toString()} ${adj}${suffix}`;
|
|
9558
9558
|
}
|
|
9559
9559
|
case "too_small": {
|
|
9560
9560
|
const adj = issue2.inclusive ? "\uC774\uC0C1" : "\uCD08\uACFC";
|
|
9561
9561
|
const suffix = adj === "\uC774\uC0C1" ? "\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" : "\uC5EC\uC57C \uD569\uB2C8\uB2E4";
|
|
9562
9562
|
const sizing = getSizing(issue2.origin);
|
|
9563
|
-
const
|
|
9563
|
+
const unit2 = sizing?.unit ?? "\uC694\uC18C";
|
|
9564
9564
|
if (sizing) {
|
|
9565
|
-
return `${issue2.origin ?? "\uAC12"}\uC774 \uB108\uBB34 \uC791\uC2B5\uB2C8\uB2E4: ${issue2.minimum.toString()}${
|
|
9565
|
+
return `${issue2.origin ?? "\uAC12"}\uC774 \uB108\uBB34 \uC791\uC2B5\uB2C8\uB2E4: ${issue2.minimum.toString()}${unit2} ${adj}${suffix}`;
|
|
9566
9566
|
}
|
|
9567
9567
|
return `${issue2.origin ?? "\uAC12"}\uC774 \uB108\uBB34 \uC791\uC2B5\uB2C8\uB2E4: ${issue2.minimum.toString()} ${adj}${suffix}`;
|
|
9568
9568
|
}
|
|
@@ -11375,8 +11375,8 @@ var error46 = () => {
|
|
|
11375
11375
|
const sizing = getSizing(issue2.origin);
|
|
11376
11376
|
if (sizing) {
|
|
11377
11377
|
const maxValue = Number(issue2.maximum);
|
|
11378
|
-
const
|
|
11379
|
-
return `\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435: \u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C, \u0447\u0442\u043E ${issue2.origin ?? "\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"} \u0431\u0443\u0434\u0435\u0442 \u0438\u043C\u0435\u0442\u044C ${adj}${issue2.maximum.toString()} ${
|
|
11378
|
+
const unit2 = getRussianPlural(maxValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
|
11379
|
+
return `\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435: \u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C, \u0447\u0442\u043E ${issue2.origin ?? "\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"} \u0431\u0443\u0434\u0435\u0442 \u0438\u043C\u0435\u0442\u044C ${adj}${issue2.maximum.toString()} ${unit2}`;
|
|
11380
11380
|
}
|
|
11381
11381
|
return `\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435: \u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C, \u0447\u0442\u043E ${issue2.origin ?? "\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"} \u0431\u0443\u0434\u0435\u0442 ${adj}${issue2.maximum.toString()}`;
|
|
11382
11382
|
}
|
|
@@ -11385,8 +11385,8 @@ var error46 = () => {
|
|
|
11385
11385
|
const sizing = getSizing(issue2.origin);
|
|
11386
11386
|
if (sizing) {
|
|
11387
11387
|
const minValue = Number(issue2.minimum);
|
|
11388
|
-
const
|
|
11389
|
-
return `\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u0430\u043B\u0435\u043D\u044C\u043A\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435: \u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C, \u0447\u0442\u043E ${issue2.origin} \u0431\u0443\u0434\u0435\u0442 \u0438\u043C\u0435\u0442\u044C ${adj}${issue2.minimum.toString()} ${
|
|
11388
|
+
const unit2 = getRussianPlural(minValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
|
11389
|
+
return `\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u0430\u043B\u0435\u043D\u044C\u043A\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435: \u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C, \u0447\u0442\u043E ${issue2.origin} \u0431\u0443\u0434\u0435\u0442 \u0438\u043C\u0435\u0442\u044C ${adj}${issue2.minimum.toString()} ${unit2}`;
|
|
11390
11390
|
}
|
|
11391
11391
|
return `\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u0430\u043B\u0435\u043D\u044C\u043A\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435: \u043E\u0436\u0438\u0434\u0430\u043B\u043E\u0441\u044C, \u0447\u0442\u043E ${issue2.origin} \u0431\u0443\u0434\u0435\u0442 ${adj}${issue2.minimum.toString()}`;
|
|
11392
11392
|
}
|
|
@@ -19105,13 +19105,13 @@ function resolveRef(ref, ctx) {
|
|
|
19105
19105
|
if (!ref.startsWith("#")) {
|
|
19106
19106
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
19107
19107
|
}
|
|
19108
|
-
const
|
|
19109
|
-
if (
|
|
19108
|
+
const path7 = ref.slice(1).split("/").filter(Boolean);
|
|
19109
|
+
if (path7.length === 0) {
|
|
19110
19110
|
return ctx.rootSchema;
|
|
19111
19111
|
}
|
|
19112
19112
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
19113
|
-
if (
|
|
19114
|
-
const key =
|
|
19113
|
+
if (path7[0] === defsKey) {
|
|
19114
|
+
const key = path7[1] === void 0 ? void 0 : decodeJSONPointerSegment(path7[1]);
|
|
19115
19115
|
if (!key || !ctx.defs[key]) {
|
|
19116
19116
|
throw new Error(`Reference not found: ${ref}`);
|
|
19117
19117
|
}
|
|
@@ -19746,7 +19746,7 @@ function visit(schema, fnOrHandlers) {
|
|
|
19746
19746
|
return h ? h(node2, rewritten) : node2;
|
|
19747
19747
|
};
|
|
19748
19748
|
const cache = /* @__PURE__ */ new Map();
|
|
19749
|
-
function
|
|
19749
|
+
function run2(s) {
|
|
19750
19750
|
const cached2 = cache.get(s);
|
|
19751
19751
|
if (cached2 === RESOLVING) {
|
|
19752
19752
|
return new $ZodLazy({
|
|
@@ -19772,21 +19772,21 @@ function visit(schema, fnOrHandlers) {
|
|
|
19772
19772
|
let changed = false;
|
|
19773
19773
|
const newShape = {};
|
|
19774
19774
|
for (const k of keys) {
|
|
19775
|
-
const mapped =
|
|
19775
|
+
const mapped = run2(oldShape[k]);
|
|
19776
19776
|
if (mapped !== oldShape[k])
|
|
19777
19777
|
changed = true;
|
|
19778
19778
|
newShape[k] = mapped;
|
|
19779
19779
|
}
|
|
19780
19780
|
let newCatchall = def.catchall;
|
|
19781
19781
|
if (def.catchall) {
|
|
19782
|
-
newCatchall =
|
|
19782
|
+
newCatchall = run2(def.catchall);
|
|
19783
19783
|
if (newCatchall !== def.catchall)
|
|
19784
19784
|
changed = true;
|
|
19785
19785
|
}
|
|
19786
19786
|
return changed ? clone(s, { ...def, shape: newShape, catchall: newCatchall }) : s;
|
|
19787
19787
|
}
|
|
19788
19788
|
case "array": {
|
|
19789
|
-
const mapped =
|
|
19789
|
+
const mapped = run2(def.element);
|
|
19790
19790
|
return mapped === def.element ? s : clone(s, { ...def, element: mapped });
|
|
19791
19791
|
}
|
|
19792
19792
|
case "tuple": {
|
|
@@ -19794,14 +19794,14 @@ function visit(schema, fnOrHandlers) {
|
|
|
19794
19794
|
let changed = false;
|
|
19795
19795
|
const newItems = [];
|
|
19796
19796
|
for (const item of oldItems) {
|
|
19797
|
-
const mapped =
|
|
19797
|
+
const mapped = run2(item);
|
|
19798
19798
|
if (mapped !== item)
|
|
19799
19799
|
changed = true;
|
|
19800
19800
|
newItems.push(mapped);
|
|
19801
19801
|
}
|
|
19802
19802
|
let newRest = def.rest;
|
|
19803
19803
|
if (def.rest) {
|
|
19804
|
-
newRest =
|
|
19804
|
+
newRest = run2(def.rest);
|
|
19805
19805
|
if (newRest !== def.rest)
|
|
19806
19806
|
changed = true;
|
|
19807
19807
|
}
|
|
@@ -19809,12 +19809,12 @@ function visit(schema, fnOrHandlers) {
|
|
|
19809
19809
|
}
|
|
19810
19810
|
case "record":
|
|
19811
19811
|
case "map": {
|
|
19812
|
-
const newKey =
|
|
19813
|
-
const newVal =
|
|
19812
|
+
const newKey = run2(def.keyType);
|
|
19813
|
+
const newVal = run2(def.valueType);
|
|
19814
19814
|
return newKey === def.keyType && newVal === def.valueType ? s : clone(s, { ...def, keyType: newKey, valueType: newVal });
|
|
19815
19815
|
}
|
|
19816
19816
|
case "set": {
|
|
19817
|
-
const newVal =
|
|
19817
|
+
const newVal = run2(def.valueType);
|
|
19818
19818
|
return newVal === def.valueType ? s : clone(s, { ...def, valueType: newVal });
|
|
19819
19819
|
}
|
|
19820
19820
|
case "union": {
|
|
@@ -19822,7 +19822,7 @@ function visit(schema, fnOrHandlers) {
|
|
|
19822
19822
|
let changed = false;
|
|
19823
19823
|
const newOptions = [];
|
|
19824
19824
|
for (const opt of oldOptions) {
|
|
19825
|
-
const mapped =
|
|
19825
|
+
const mapped = run2(opt);
|
|
19826
19826
|
if (mapped !== opt)
|
|
19827
19827
|
changed = true;
|
|
19828
19828
|
newOptions.push(mapped);
|
|
@@ -19830,8 +19830,8 @@ function visit(schema, fnOrHandlers) {
|
|
|
19830
19830
|
return changed ? clone(s, { ...def, options: newOptions }) : s;
|
|
19831
19831
|
}
|
|
19832
19832
|
case "intersection": {
|
|
19833
|
-
const newLeft =
|
|
19834
|
-
const newRight =
|
|
19833
|
+
const newLeft = run2(def.left);
|
|
19834
|
+
const newRight = run2(def.right);
|
|
19835
19835
|
return newLeft === def.left && newRight === def.right ? s : clone(s, { ...def, left: newLeft, right: newRight });
|
|
19836
19836
|
}
|
|
19837
19837
|
case "optional":
|
|
@@ -19843,23 +19843,23 @@ function visit(schema, fnOrHandlers) {
|
|
|
19843
19843
|
case "nonoptional":
|
|
19844
19844
|
case "promise":
|
|
19845
19845
|
case "success": {
|
|
19846
|
-
const newInner =
|
|
19846
|
+
const newInner = run2(def.innerType);
|
|
19847
19847
|
return newInner === def.innerType ? s : clone(s, { ...def, innerType: newInner });
|
|
19848
19848
|
}
|
|
19849
19849
|
case "pipe": {
|
|
19850
|
-
const newIn =
|
|
19851
|
-
const newOut =
|
|
19850
|
+
const newIn = run2(def.in);
|
|
19851
|
+
const newOut = run2(def.out);
|
|
19852
19852
|
return newIn === def.in && newOut === def.out ? s : clone(s, { ...def, in: newIn, out: newOut });
|
|
19853
19853
|
}
|
|
19854
19854
|
case "function": {
|
|
19855
|
-
const newInput =
|
|
19856
|
-
const newOutput =
|
|
19855
|
+
const newInput = run2(def.input);
|
|
19856
|
+
const newOutput = run2(def.output);
|
|
19857
19857
|
return newInput === def.input && newOutput === def.output ? s : clone(s, { ...def, input: newInput, output: newOutput });
|
|
19858
19858
|
}
|
|
19859
19859
|
case "lazy": {
|
|
19860
19860
|
const original = def.getter;
|
|
19861
19861
|
const { _cachedInner, ...rest } = def;
|
|
19862
|
-
return clone(s, { ...rest, getter: () =>
|
|
19862
|
+
return clone(s, { ...rest, getter: () => run2(original()) });
|
|
19863
19863
|
}
|
|
19864
19864
|
// A leaf by choice: `parts` are regex fragments, not data positions.
|
|
19865
19865
|
case "template_literal":
|
|
@@ -19890,7 +19890,7 @@ function visit(schema, fnOrHandlers) {
|
|
|
19890
19890
|
}
|
|
19891
19891
|
}
|
|
19892
19892
|
}
|
|
19893
|
-
return
|
|
19893
|
+
return run2(schema);
|
|
19894
19894
|
}
|
|
19895
19895
|
|
|
19896
19896
|
// node_modules/zod/v4/classic/deep-partial.js
|
|
@@ -24235,6 +24235,184 @@ ${name} said: ${reason}`), false);
|
|
|
24235
24235
|
}
|
|
24236
24236
|
};
|
|
24237
24237
|
|
|
24238
|
+
// bridge/service.ts
|
|
24239
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
24240
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
24241
|
+
import { homedir as homedir2 } from "node:os";
|
|
24242
|
+
import path5 from "node:path";
|
|
24243
|
+
var LABEL = "com.moonlait.bridge";
|
|
24244
|
+
var TASK = "Moonlait bridge";
|
|
24245
|
+
var logPath = () => path5.join(bridgeHome(), "bridge.log");
|
|
24246
|
+
function plistPath() {
|
|
24247
|
+
return path5.join(homedir2(), "Library", "LaunchAgents", `${LABEL}.plist`);
|
|
24248
|
+
}
|
|
24249
|
+
function unitPath() {
|
|
24250
|
+
return path5.join(homedir2(), ".config", "systemd", "user", "moonlait.service");
|
|
24251
|
+
}
|
|
24252
|
+
var runnerPath = () => path5.join(bridgeHome(), "bridge-service.cmd");
|
|
24253
|
+
var launcherPath = () => path5.join(bridgeHome(), "bridge-service.vbs");
|
|
24254
|
+
function runnerScript(paths) {
|
|
24255
|
+
const config2 = paths.config === void 0 ? "" : ` --config "${paths.config}"`;
|
|
24256
|
+
return [
|
|
24257
|
+
"@echo off",
|
|
24258
|
+
":loop",
|
|
24259
|
+
`"${paths.node}" "${paths.script}" start${config2} >> "${logPath()}" 2>&1`,
|
|
24260
|
+
"timeout /t 5 /nobreak > nul",
|
|
24261
|
+
"goto loop",
|
|
24262
|
+
""
|
|
24263
|
+
].join("\r\n");
|
|
24264
|
+
}
|
|
24265
|
+
function launcherScript() {
|
|
24266
|
+
return ['Set shell = CreateObject("WScript.Shell")', `shell.Run """${runnerPath()}""", 0, False`, ""].join("\r\n");
|
|
24267
|
+
}
|
|
24268
|
+
var escape = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
24269
|
+
function plist(paths) {
|
|
24270
|
+
const args = [paths.node, paths.script, "start", ...paths.config === void 0 ? [] : ["--config", paths.config]];
|
|
24271
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
24272
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
24273
|
+
<plist version="1.0">
|
|
24274
|
+
<dict>
|
|
24275
|
+
<key>Label</key><string>${LABEL}</string>
|
|
24276
|
+
<key>ProgramArguments</key>
|
|
24277
|
+
<array>${args.map((arg) => `
|
|
24278
|
+
<string>${escape(arg)}</string>`).join("")}
|
|
24279
|
+
</array>
|
|
24280
|
+
<key>RunAtLoad</key><true/>
|
|
24281
|
+
<key>KeepAlive</key><true/>
|
|
24282
|
+
<key>WorkingDirectory</key><string>${escape(homedir2())}</string>
|
|
24283
|
+
<key>EnvironmentVariables</key>
|
|
24284
|
+
<dict>
|
|
24285
|
+
<key>PATH</key><string>${escape(process.env.PATH ?? "/usr/bin:/bin")}</string>
|
|
24286
|
+
<key>HOME</key><string>${escape(homedir2())}</string>
|
|
24287
|
+
</dict>
|
|
24288
|
+
<key>StandardOutPath</key><string>${escape(logPath())}</string>
|
|
24289
|
+
<key>StandardErrorPath</key><string>${escape(logPath())}</string>
|
|
24290
|
+
</dict>
|
|
24291
|
+
</plist>
|
|
24292
|
+
`;
|
|
24293
|
+
}
|
|
24294
|
+
function unit(paths) {
|
|
24295
|
+
const args = [paths.node, paths.script, "start", ...paths.config === void 0 ? [] : ["--config", paths.config]];
|
|
24296
|
+
return `[Unit]
|
|
24297
|
+
Description=Moonlait bridge
|
|
24298
|
+
After=network-online.target
|
|
24299
|
+
|
|
24300
|
+
[Service]
|
|
24301
|
+
ExecStart=${args.map((arg) => JSON.stringify(arg)).join(" ")}
|
|
24302
|
+
Environment=PATH=${process.env.PATH ?? "/usr/bin:/bin"}
|
|
24303
|
+
Restart=always
|
|
24304
|
+
RestartSec=5
|
|
24305
|
+
|
|
24306
|
+
[Install]
|
|
24307
|
+
WantedBy=default.target
|
|
24308
|
+
`;
|
|
24309
|
+
}
|
|
24310
|
+
function run(command, args) {
|
|
24311
|
+
execFileSync2(command, [...args], { stdio: "ignore" });
|
|
24312
|
+
}
|
|
24313
|
+
function install(paths) {
|
|
24314
|
+
if (process.platform === "darwin") {
|
|
24315
|
+
const file2 = plistPath();
|
|
24316
|
+
mkdirSync2(path5.dirname(file2), { recursive: true });
|
|
24317
|
+
mkdirSync2(bridgeHome(), { recursive: true });
|
|
24318
|
+
writeFileSync2(file2, plist(paths));
|
|
24319
|
+
try {
|
|
24320
|
+
run("launchctl", ["bootout", `gui/${process.getuid?.() ?? 501}/${LABEL}`]);
|
|
24321
|
+
} catch {
|
|
24322
|
+
}
|
|
24323
|
+
run("launchctl", ["bootstrap", `gui/${process.getuid?.() ?? 501}`, file2]);
|
|
24324
|
+
return file2;
|
|
24325
|
+
}
|
|
24326
|
+
if (process.platform === "linux") {
|
|
24327
|
+
const file2 = unitPath();
|
|
24328
|
+
mkdirSync2(path5.dirname(file2), { recursive: true });
|
|
24329
|
+
writeFileSync2(file2, unit(paths));
|
|
24330
|
+
run("systemctl", ["--user", "daemon-reload"]);
|
|
24331
|
+
run("systemctl", ["--user", "enable", "--now", "moonlait.service"]);
|
|
24332
|
+
return file2;
|
|
24333
|
+
}
|
|
24334
|
+
if (process.platform === "win32") {
|
|
24335
|
+
mkdirSync2(bridgeHome(), { recursive: true });
|
|
24336
|
+
writeFileSync2(runnerPath(), runnerScript(paths));
|
|
24337
|
+
writeFileSync2(launcherPath(), launcherScript());
|
|
24338
|
+
run("schtasks", ["/Create", "/TN", TASK, "/TR", `wscript.exe "${launcherPath()}"`, "/SC", "ONLOGON", "/F"]);
|
|
24339
|
+
run("schtasks", ["/Run", "/TN", TASK]);
|
|
24340
|
+
return launcherPath();
|
|
24341
|
+
}
|
|
24342
|
+
throw new Error(`Installing as a service is not supported on ${process.platform}. Run \`moonlait start\` in a terminal instead.`);
|
|
24343
|
+
}
|
|
24344
|
+
function uninstall() {
|
|
24345
|
+
if (process.platform === "darwin") {
|
|
24346
|
+
const file2 = plistPath();
|
|
24347
|
+
if (!existsSync4(file2)) return null;
|
|
24348
|
+
try {
|
|
24349
|
+
run("launchctl", ["bootout", `gui/${process.getuid?.() ?? 501}/${LABEL}`]);
|
|
24350
|
+
} catch {
|
|
24351
|
+
}
|
|
24352
|
+
rmSync(file2);
|
|
24353
|
+
return file2;
|
|
24354
|
+
}
|
|
24355
|
+
if (process.platform === "linux") {
|
|
24356
|
+
const file2 = unitPath();
|
|
24357
|
+
if (!existsSync4(file2)) return null;
|
|
24358
|
+
try {
|
|
24359
|
+
run("systemctl", ["--user", "disable", "--now", "moonlait.service"]);
|
|
24360
|
+
} catch {
|
|
24361
|
+
}
|
|
24362
|
+
rmSync(file2);
|
|
24363
|
+
run("systemctl", ["--user", "daemon-reload"]);
|
|
24364
|
+
return file2;
|
|
24365
|
+
}
|
|
24366
|
+
if (process.platform === "win32") {
|
|
24367
|
+
if (!existsSync4(launcherPath())) return null;
|
|
24368
|
+
try {
|
|
24369
|
+
run("schtasks", ["/End", "/TN", TASK]);
|
|
24370
|
+
run("schtasks", ["/Delete", "/TN", TASK, "/F"]);
|
|
24371
|
+
} catch {
|
|
24372
|
+
}
|
|
24373
|
+
rmSync(launcherPath());
|
|
24374
|
+
rmSync(runnerPath(), { force: true });
|
|
24375
|
+
return launcherPath();
|
|
24376
|
+
}
|
|
24377
|
+
throw new Error(`Nothing to remove: the service is not installed on ${process.platform}.`);
|
|
24378
|
+
}
|
|
24379
|
+
function status() {
|
|
24380
|
+
if (process.platform === "darwin") {
|
|
24381
|
+
const file2 = plistPath();
|
|
24382
|
+
let running = false;
|
|
24383
|
+
try {
|
|
24384
|
+
execFileSync2("launchctl", ["print", `gui/${process.getuid?.() ?? 501}/${LABEL}`], { stdio: "ignore" });
|
|
24385
|
+
running = true;
|
|
24386
|
+
} catch {
|
|
24387
|
+
running = false;
|
|
24388
|
+
}
|
|
24389
|
+
return { installed: existsSync4(file2), running, file: file2 };
|
|
24390
|
+
}
|
|
24391
|
+
if (process.platform === "linux") {
|
|
24392
|
+
const file2 = unitPath();
|
|
24393
|
+
let running = false;
|
|
24394
|
+
try {
|
|
24395
|
+
execFileSync2("systemctl", ["--user", "is-active", "--quiet", "moonlait.service"], { stdio: "ignore" });
|
|
24396
|
+
running = true;
|
|
24397
|
+
} catch {
|
|
24398
|
+
running = false;
|
|
24399
|
+
}
|
|
24400
|
+
return { installed: existsSync4(file2), running, file: file2 };
|
|
24401
|
+
}
|
|
24402
|
+
if (process.platform === "win32") {
|
|
24403
|
+
const file2 = launcherPath();
|
|
24404
|
+
let running = false;
|
|
24405
|
+
try {
|
|
24406
|
+
const output2 = execFileSync2("schtasks", ["/Query", "/TN", TASK, "/FO", "LIST"], { encoding: "utf8" });
|
|
24407
|
+
running = /\bRunning\b/i.test(output2);
|
|
24408
|
+
} catch {
|
|
24409
|
+
return { installed: false, running: false, file: file2 };
|
|
24410
|
+
}
|
|
24411
|
+
return { installed: true, running, file: file2 };
|
|
24412
|
+
}
|
|
24413
|
+
return { installed: false, running: false, file: "" };
|
|
24414
|
+
}
|
|
24415
|
+
|
|
24238
24416
|
// bridge/cli.ts
|
|
24239
24417
|
function option(name) {
|
|
24240
24418
|
const index = process.argv.indexOf(`--${name}`);
|
|
@@ -24286,7 +24464,7 @@ async function main() {
|
|
|
24286
24464
|
const config2 = loadConfig(file2);
|
|
24287
24465
|
if (config2 === null) throw new Error(`Not paired yet. Run: ${RUN} pair <CODE> --server <url>`);
|
|
24288
24466
|
const given = options("workspace");
|
|
24289
|
-
const allowed = () => discoverWorkspaces((given.length > 0 ? given : loadConfig(file2)?.folders ?? []).filter((folder) =>
|
|
24467
|
+
const allowed = () => discoverWorkspaces((given.length > 0 ? given : loadConfig(file2)?.folders ?? []).filter((folder) => existsSync5(folder)));
|
|
24290
24468
|
let workspaces = allowed();
|
|
24291
24469
|
if (workspaces.length === 0) {
|
|
24292
24470
|
throw new Error(`No folders allowed yet. Choose where agents may work, e.g.:
|
|
@@ -24335,7 +24513,41 @@ async function main() {
|
|
|
24335
24513
|
);
|
|
24336
24514
|
return;
|
|
24337
24515
|
}
|
|
24338
|
-
|
|
24516
|
+
if (command === "service") {
|
|
24517
|
+
const action = argument ?? "status";
|
|
24518
|
+
if (action === "status") {
|
|
24519
|
+
const state = status();
|
|
24520
|
+
console.log(
|
|
24521
|
+
!state.installed ? `Not installed. Keep the bridge running with: ${RUN} service install` : state.running ? `Installed and running (${state.file}).
|
|
24522
|
+
Log: ${logPath()}` : `Installed but not running (${state.file}).
|
|
24523
|
+
Log: ${logPath()}`
|
|
24524
|
+
);
|
|
24525
|
+
return;
|
|
24526
|
+
}
|
|
24527
|
+
if (action === "uninstall") {
|
|
24528
|
+
const file3 = uninstall();
|
|
24529
|
+
console.log(file3 === null ? "The service was not installed." : `Removed ${file3}. The bridge stops at the next login, or now.`);
|
|
24530
|
+
return;
|
|
24531
|
+
}
|
|
24532
|
+
if (action !== "install") throw new Error(`Usage: ${RUN} service [install|uninstall|status]`);
|
|
24533
|
+
if (import.meta.filename.endsWith(".ts")) {
|
|
24534
|
+
throw new Error("Install the published package first: npm install -g moonlait, then `moonlait service install`.");
|
|
24535
|
+
}
|
|
24536
|
+
if (/[\\/]_npx[\\/]/.test(import.meta.filename)) {
|
|
24537
|
+
throw new Error("This copy lives in npx's cache, which npm can clear.\nInstall it for good first: npm install -g moonlait, then `moonlait service install`.");
|
|
24538
|
+
}
|
|
24539
|
+
if (loadConfig(file2) === null) throw new Error(`Not paired yet. Run: ${RUN} pair <CODE> --server <url>`);
|
|
24540
|
+
const installed2 = install({
|
|
24541
|
+
node: process.execPath,
|
|
24542
|
+
script: import.meta.filename,
|
|
24543
|
+
...option("config") !== void 0 ? { config: path6.resolve(option("config")) } : {}
|
|
24544
|
+
});
|
|
24545
|
+
console.log(`The bridge now runs in the background and starts at login (${installed2}).`);
|
|
24546
|
+
console.log(`Log: ${logPath()}`);
|
|
24547
|
+
console.log(`Stop it with: ${RUN} service uninstall`);
|
|
24548
|
+
return;
|
|
24549
|
+
}
|
|
24550
|
+
console.log(`Usage: ${RUN} pair <CODE> --server <url> | folders [add|remove <folder>\u2026] | start | service [install|uninstall|status] | agents`);
|
|
24339
24551
|
}
|
|
24340
24552
|
function sameFolders(a, b) {
|
|
24341
24553
|
return a.map((folder) => folder.path).join("\n") === b.map((folder) => folder.path).join("\n");
|
|
@@ -24347,16 +24559,16 @@ function changeFolders(current, action, given) {
|
|
|
24347
24559
|
}
|
|
24348
24560
|
let next = [...current];
|
|
24349
24561
|
for (const folder of given) {
|
|
24350
|
-
const absolute =
|
|
24562
|
+
const absolute = path6.resolve(folder);
|
|
24351
24563
|
if (action === "remove") {
|
|
24352
|
-
const real2 =
|
|
24564
|
+
const real2 = existsSync5(absolute) ? realpathSync2(absolute) : absolute;
|
|
24353
24565
|
next = next.filter((candidate) => candidate !== real2 && candidate !== absolute);
|
|
24354
24566
|
continue;
|
|
24355
24567
|
}
|
|
24356
|
-
if (!
|
|
24568
|
+
if (!existsSync5(absolute) || !statSync2(absolute).isDirectory()) throw new Error(`Not a folder: ${folder}`);
|
|
24357
24569
|
const real = realpathSync2(absolute);
|
|
24358
|
-
if (real ===
|
|
24359
|
-
if (real ===
|
|
24570
|
+
if (real === path6.parse(real).root) throw new Error("Pick a folder, not the whole disk.");
|
|
24571
|
+
if (real === homedir3()) console.log("Note: agents can now work anywhere in your home folder (they still ask before risky steps).");
|
|
24360
24572
|
if (!next.includes(real)) next.push(real);
|
|
24361
24573
|
}
|
|
24362
24574
|
return next.join("\n") === current.join("\n") ? current : next;
|
package/package.json
CHANGED