@mutmutco/cli 2.41.0 → 2.43.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/dist/main.cjs +5565 -6125
- package/dist/saga.cjs +178 -190
- package/package.json +1 -1
package/dist/saga.cjs
CHANGED
|
@@ -3631,7 +3631,6 @@ function buildHealth(i) {
|
|
|
3631
3631
|
authorized: i.authorized,
|
|
3632
3632
|
sagaApiUrl: i.sagaApiUrl,
|
|
3633
3633
|
pendingNotes: i.pendingNotes ?? 0,
|
|
3634
|
-
honchoPending: i.honchoPending ?? 0,
|
|
3635
3634
|
key: i.key,
|
|
3636
3635
|
source: i.source,
|
|
3637
3636
|
problems,
|
|
@@ -3650,194 +3649,8 @@ function healthBanner(report) {
|
|
|
3650
3649
|
}
|
|
3651
3650
|
function memorySyncBanner(report) {
|
|
3652
3651
|
const saga = report.pendingNotes;
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
const parts = [];
|
|
3656
|
-
if (saga > 0) parts.push(`${saga} saga`);
|
|
3657
|
-
if (honcho > 0) parts.push(`${honcho} honcho`);
|
|
3658
|
-
return `MEMORY SYNC \u2014 ${parts.join(" + ")} write(s) queued locally \u2014 run \`mmi-cli saga flush\` / \`honcho flush\` (this device only).`;
|
|
3659
|
-
}
|
|
3660
|
-
|
|
3661
|
-
// src/saga-pending.ts
|
|
3662
|
-
var import_node_fs4 = require("node:fs");
|
|
3663
|
-
var import_node_path4 = require("node:path");
|
|
3664
|
-
function classifyCaptureOutcome(r) {
|
|
3665
|
-
if (r.threw) return "queued";
|
|
3666
|
-
return r.ok ? "confirmed" : "failed";
|
|
3667
|
-
}
|
|
3668
|
-
var PENDING_MAX = 50;
|
|
3669
|
-
var PENDING_MAX_ATTEMPTS = 10;
|
|
3670
|
-
var PENDING_FILE = "saga-pending.jsonl";
|
|
3671
|
-
var FLUSH_LOCK_FILE = "saga-flush.lock";
|
|
3672
|
-
var FLUSH_LOCK_STALE_MS = 5 * 6e4;
|
|
3673
|
-
function pendingPath(dir = ".mmi") {
|
|
3674
|
-
return (0, import_node_path4.join)(dir, PENDING_FILE);
|
|
3675
|
-
}
|
|
3676
|
-
var PENDING_TMP_STALE_MS = 6e4;
|
|
3677
|
-
function sweepStaleTmp(dir = ".mmi", now = Date.now()) {
|
|
3678
|
-
try {
|
|
3679
|
-
for (const name of (0, import_node_fs4.readdirSync)(dir)) {
|
|
3680
|
-
if (!name.startsWith(`${PENDING_FILE}.`) || !name.endsWith(".tmp")) continue;
|
|
3681
|
-
const path2 = (0, import_node_path4.join)(dir, name);
|
|
3682
|
-
try {
|
|
3683
|
-
if (now - (0, import_node_fs4.statSync)(path2).mtimeMs > PENDING_TMP_STALE_MS) (0, import_node_fs4.unlinkSync)(path2);
|
|
3684
|
-
} catch {
|
|
3685
|
-
}
|
|
3686
|
-
}
|
|
3687
|
-
} catch {
|
|
3688
|
-
}
|
|
3689
|
-
}
|
|
3690
|
-
function flushLockPath(dir = ".mmi") {
|
|
3691
|
-
return (0, import_node_path4.join)(dir, FLUSH_LOCK_FILE);
|
|
3692
|
-
}
|
|
3693
|
-
function acquireFlushLock(dir = ".mmi", now = Date.now()) {
|
|
3694
|
-
const path2 = flushLockPath(dir);
|
|
3695
|
-
try {
|
|
3696
|
-
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
3697
|
-
(0, import_node_fs4.writeFileSync)(path2, String(process.pid), { encoding: "utf8", flag: "wx" });
|
|
3698
|
-
return true;
|
|
3699
|
-
} catch {
|
|
3700
|
-
try {
|
|
3701
|
-
if (now - (0, import_node_fs4.statSync)(path2).mtimeMs > FLUSH_LOCK_STALE_MS) {
|
|
3702
|
-
(0, import_node_fs4.unlinkSync)(path2);
|
|
3703
|
-
(0, import_node_fs4.writeFileSync)(path2, String(process.pid), { encoding: "utf8", flag: "wx" });
|
|
3704
|
-
return true;
|
|
3705
|
-
}
|
|
3706
|
-
} catch {
|
|
3707
|
-
}
|
|
3708
|
-
return false;
|
|
3709
|
-
}
|
|
3710
|
-
}
|
|
3711
|
-
function releaseFlushLock(dir = ".mmi") {
|
|
3712
|
-
try {
|
|
3713
|
-
(0, import_node_fs4.unlinkSync)(flushLockPath(dir));
|
|
3714
|
-
} catch {
|
|
3715
|
-
}
|
|
3716
|
-
}
|
|
3717
|
-
function readPending(dir = ".mmi") {
|
|
3718
|
-
const path2 = pendingPath(dir);
|
|
3719
|
-
if (!(0, import_node_fs4.existsSync)(path2)) return [];
|
|
3720
|
-
const out = [];
|
|
3721
|
-
for (const line of (0, import_node_fs4.readFileSync)(path2, "utf8").split(/\r?\n/)) {
|
|
3722
|
-
const t = line.trim();
|
|
3723
|
-
if (!t) continue;
|
|
3724
|
-
try {
|
|
3725
|
-
const e = JSON.parse(t);
|
|
3726
|
-
if (e && typeof e.id === "string" && e.body && typeof e.body === "object") out.push(e);
|
|
3727
|
-
} catch {
|
|
3728
|
-
}
|
|
3729
|
-
}
|
|
3730
|
-
return out;
|
|
3731
|
-
}
|
|
3732
|
-
function writePending(entries, dir = ".mmi") {
|
|
3733
|
-
const tmp = `${pendingPath(dir)}.${process.pid}.tmp`;
|
|
3734
|
-
try {
|
|
3735
|
-
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
3736
|
-
sweepStaleTmp(dir);
|
|
3737
|
-
const trimmed = entries.slice(-PENDING_MAX);
|
|
3738
|
-
const body = trimmed.map((e) => JSON.stringify(e)).join("\n");
|
|
3739
|
-
(0, import_node_fs4.writeFileSync)(tmp, trimmed.length ? `${body}
|
|
3740
|
-
` : "", "utf8");
|
|
3741
|
-
(0, import_node_fs4.renameSync)(tmp, pendingPath(dir));
|
|
3742
|
-
} catch {
|
|
3743
|
-
try {
|
|
3744
|
-
(0, import_node_fs4.unlinkSync)(tmp);
|
|
3745
|
-
} catch {
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
}
|
|
3749
|
-
function enqueuePending(body, dir = ".mmi") {
|
|
3750
|
-
try {
|
|
3751
|
-
const id = typeof body.id === "string" ? body.id : "";
|
|
3752
|
-
const existing = readPending(dir);
|
|
3753
|
-
if (id && existing.some((e) => e.id === id)) return;
|
|
3754
|
-
if (existing.length >= PENDING_MAX) {
|
|
3755
|
-
writePending([...existing, { id, body }], dir);
|
|
3756
|
-
return;
|
|
3757
|
-
}
|
|
3758
|
-
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
3759
|
-
sweepStaleTmp(dir);
|
|
3760
|
-
(0, import_node_fs4.appendFileSync)(pendingPath(dir), `${JSON.stringify({ id, body })}
|
|
3761
|
-
`, "utf8");
|
|
3762
|
-
} catch {
|
|
3763
|
-
}
|
|
3764
|
-
}
|
|
3765
|
-
function entryKey(e) {
|
|
3766
|
-
return e.id || JSON.stringify(e.body);
|
|
3767
|
-
}
|
|
3768
|
-
async function drainOnce(post, dir, seen) {
|
|
3769
|
-
const entries = readPending(dir);
|
|
3770
|
-
if (!entries.length) return { flushed: 0, dropped: [], remaining: 0, halted: false };
|
|
3771
|
-
let flushed = 0;
|
|
3772
|
-
const dropped = [];
|
|
3773
|
-
const processed = /* @__PURE__ */ new Set();
|
|
3774
|
-
const kept = /* @__PURE__ */ new Map();
|
|
3775
|
-
let halted = false;
|
|
3776
|
-
for (const e of entries) {
|
|
3777
|
-
const key = entryKey(e);
|
|
3778
|
-
if (halted) continue;
|
|
3779
|
-
if (seen.has(key)) {
|
|
3780
|
-
processed.add(key);
|
|
3781
|
-
continue;
|
|
3782
|
-
}
|
|
3783
|
-
const r = await post(e.body);
|
|
3784
|
-
const outcome = classifyCaptureOutcome(r);
|
|
3785
|
-
if (outcome === "confirmed") {
|
|
3786
|
-
seen.add(key);
|
|
3787
|
-
flushed++;
|
|
3788
|
-
processed.add(key);
|
|
3789
|
-
continue;
|
|
3790
|
-
}
|
|
3791
|
-
if (outcome === "failed") {
|
|
3792
|
-
seen.add(key);
|
|
3793
|
-
dropped.push(r);
|
|
3794
|
-
processed.add(key);
|
|
3795
|
-
continue;
|
|
3796
|
-
}
|
|
3797
|
-
const attempts = (e.attempts ?? 0) + 1;
|
|
3798
|
-
if (attempts >= PENDING_MAX_ATTEMPTS) {
|
|
3799
|
-
seen.add(key);
|
|
3800
|
-
dropped.push(r);
|
|
3801
|
-
processed.add(key);
|
|
3802
|
-
continue;
|
|
3803
|
-
}
|
|
3804
|
-
kept.set(key, { ...e, attempts });
|
|
3805
|
-
halted = true;
|
|
3806
|
-
}
|
|
3807
|
-
const out = [];
|
|
3808
|
-
const written = /* @__PURE__ */ new Set();
|
|
3809
|
-
for (const c of readPending(dir)) {
|
|
3810
|
-
const key = entryKey(c);
|
|
3811
|
-
if (processed.has(key) || written.has(key)) continue;
|
|
3812
|
-
written.add(key);
|
|
3813
|
-
out.push(kept.get(key) ?? c);
|
|
3814
|
-
}
|
|
3815
|
-
writePending(out, dir);
|
|
3816
|
-
return { flushed, dropped, remaining: out.length, halted };
|
|
3817
|
-
}
|
|
3818
|
-
async function flushPending(post, dir = ".mmi") {
|
|
3819
|
-
if (!acquireFlushLock(dir)) return { flushed: 0, dropped: [], remaining: readPending(dir).length, skipped: true };
|
|
3820
|
-
let flushed = 0;
|
|
3821
|
-
const dropped = [];
|
|
3822
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3823
|
-
try {
|
|
3824
|
-
for (; ; ) {
|
|
3825
|
-
const r = await drainOnce(post, dir, seen);
|
|
3826
|
-
flushed += r.flushed;
|
|
3827
|
-
dropped.push(...r.dropped);
|
|
3828
|
-
if (r.halted || r.remaining === 0) break;
|
|
3829
|
-
if (!r.flushed && !r.dropped.length) break;
|
|
3830
|
-
}
|
|
3831
|
-
} finally {
|
|
3832
|
-
releaseFlushLock(dir);
|
|
3833
|
-
}
|
|
3834
|
-
return { flushed, dropped, remaining: readPending(dir).length };
|
|
3835
|
-
}
|
|
3836
|
-
|
|
3837
|
-
// src/honcho-pending.ts
|
|
3838
|
-
var HONCHO_QUEUE_DIR = ".mmi/honcho";
|
|
3839
|
-
function readHonchoPending(dir = HONCHO_QUEUE_DIR) {
|
|
3840
|
-
return readPending(dir);
|
|
3652
|
+
if (saga <= 0) return null;
|
|
3653
|
+
return `MEMORY SYNC \u2014 ${saga} saga write(s) queued locally \u2014 run \`mmi-cli saga flush\` (this device only).`;
|
|
3841
3654
|
}
|
|
3842
3655
|
|
|
3843
3656
|
// src/fetch-retry.ts
|
|
@@ -4213,6 +4026,182 @@ function formatSnapshotHuman(snapshot) {
|
|
|
4213
4026
|
return lines.join("\n");
|
|
4214
4027
|
}
|
|
4215
4028
|
|
|
4029
|
+
// src/saga-pending.ts
|
|
4030
|
+
var import_node_fs4 = require("node:fs");
|
|
4031
|
+
var import_node_path4 = require("node:path");
|
|
4032
|
+
function classifyCaptureOutcome(r) {
|
|
4033
|
+
if (r.threw) return "queued";
|
|
4034
|
+
return r.ok ? "confirmed" : "failed";
|
|
4035
|
+
}
|
|
4036
|
+
var PENDING_MAX = 50;
|
|
4037
|
+
var PENDING_MAX_ATTEMPTS = 10;
|
|
4038
|
+
var PENDING_FILE = "saga-pending.jsonl";
|
|
4039
|
+
var FLUSH_LOCK_FILE = "saga-flush.lock";
|
|
4040
|
+
var FLUSH_LOCK_STALE_MS = 5 * 6e4;
|
|
4041
|
+
function pendingPath(dir = ".mmi") {
|
|
4042
|
+
return (0, import_node_path4.join)(dir, PENDING_FILE);
|
|
4043
|
+
}
|
|
4044
|
+
var PENDING_TMP_STALE_MS = 6e4;
|
|
4045
|
+
function sweepStaleTmp(dir = ".mmi", now = Date.now()) {
|
|
4046
|
+
try {
|
|
4047
|
+
for (const name of (0, import_node_fs4.readdirSync)(dir)) {
|
|
4048
|
+
if (!name.startsWith(`${PENDING_FILE}.`) || !name.endsWith(".tmp")) continue;
|
|
4049
|
+
const path2 = (0, import_node_path4.join)(dir, name);
|
|
4050
|
+
try {
|
|
4051
|
+
if (now - (0, import_node_fs4.statSync)(path2).mtimeMs > PENDING_TMP_STALE_MS) (0, import_node_fs4.unlinkSync)(path2);
|
|
4052
|
+
} catch {
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
} catch {
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
function flushLockPath(dir = ".mmi") {
|
|
4059
|
+
return (0, import_node_path4.join)(dir, FLUSH_LOCK_FILE);
|
|
4060
|
+
}
|
|
4061
|
+
function acquireFlushLock(dir = ".mmi", now = Date.now()) {
|
|
4062
|
+
const path2 = flushLockPath(dir);
|
|
4063
|
+
try {
|
|
4064
|
+
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
4065
|
+
(0, import_node_fs4.writeFileSync)(path2, String(process.pid), { encoding: "utf8", flag: "wx" });
|
|
4066
|
+
return true;
|
|
4067
|
+
} catch {
|
|
4068
|
+
try {
|
|
4069
|
+
if (now - (0, import_node_fs4.statSync)(path2).mtimeMs > FLUSH_LOCK_STALE_MS) {
|
|
4070
|
+
(0, import_node_fs4.unlinkSync)(path2);
|
|
4071
|
+
(0, import_node_fs4.writeFileSync)(path2, String(process.pid), { encoding: "utf8", flag: "wx" });
|
|
4072
|
+
return true;
|
|
4073
|
+
}
|
|
4074
|
+
} catch {
|
|
4075
|
+
}
|
|
4076
|
+
return false;
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
function releaseFlushLock(dir = ".mmi") {
|
|
4080
|
+
try {
|
|
4081
|
+
(0, import_node_fs4.unlinkSync)(flushLockPath(dir));
|
|
4082
|
+
} catch {
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
function readPending(dir = ".mmi") {
|
|
4086
|
+
const path2 = pendingPath(dir);
|
|
4087
|
+
if (!(0, import_node_fs4.existsSync)(path2)) return [];
|
|
4088
|
+
const out = [];
|
|
4089
|
+
for (const line of (0, import_node_fs4.readFileSync)(path2, "utf8").split(/\r?\n/)) {
|
|
4090
|
+
const t = line.trim();
|
|
4091
|
+
if (!t) continue;
|
|
4092
|
+
try {
|
|
4093
|
+
const e = JSON.parse(t);
|
|
4094
|
+
if (e && typeof e.id === "string" && e.body && typeof e.body === "object") out.push(e);
|
|
4095
|
+
} catch {
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
return out;
|
|
4099
|
+
}
|
|
4100
|
+
function writePending(entries, dir = ".mmi") {
|
|
4101
|
+
const tmp = `${pendingPath(dir)}.${process.pid}.tmp`;
|
|
4102
|
+
try {
|
|
4103
|
+
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
4104
|
+
sweepStaleTmp(dir);
|
|
4105
|
+
const trimmed = entries.slice(-PENDING_MAX);
|
|
4106
|
+
const body = trimmed.map((e) => JSON.stringify(e)).join("\n");
|
|
4107
|
+
(0, import_node_fs4.writeFileSync)(tmp, trimmed.length ? `${body}
|
|
4108
|
+
` : "", "utf8");
|
|
4109
|
+
(0, import_node_fs4.renameSync)(tmp, pendingPath(dir));
|
|
4110
|
+
} catch {
|
|
4111
|
+
try {
|
|
4112
|
+
(0, import_node_fs4.unlinkSync)(tmp);
|
|
4113
|
+
} catch {
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
function enqueuePending(body, dir = ".mmi") {
|
|
4118
|
+
try {
|
|
4119
|
+
const id = typeof body.id === "string" ? body.id : "";
|
|
4120
|
+
const existing = readPending(dir);
|
|
4121
|
+
if (id && existing.some((e) => e.id === id)) return;
|
|
4122
|
+
if (existing.length >= PENDING_MAX) {
|
|
4123
|
+
writePending([...existing, { id, body }], dir);
|
|
4124
|
+
return;
|
|
4125
|
+
}
|
|
4126
|
+
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
4127
|
+
sweepStaleTmp(dir);
|
|
4128
|
+
(0, import_node_fs4.appendFileSync)(pendingPath(dir), `${JSON.stringify({ id, body })}
|
|
4129
|
+
`, "utf8");
|
|
4130
|
+
} catch {
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
function entryKey(e) {
|
|
4134
|
+
return e.id || JSON.stringify(e.body);
|
|
4135
|
+
}
|
|
4136
|
+
async function drainOnce(post, dir, seen) {
|
|
4137
|
+
const entries = readPending(dir);
|
|
4138
|
+
if (!entries.length) return { flushed: 0, dropped: [], remaining: 0, halted: false };
|
|
4139
|
+
let flushed = 0;
|
|
4140
|
+
const dropped = [];
|
|
4141
|
+
const processed = /* @__PURE__ */ new Set();
|
|
4142
|
+
const kept = /* @__PURE__ */ new Map();
|
|
4143
|
+
let halted = false;
|
|
4144
|
+
for (const e of entries) {
|
|
4145
|
+
const key = entryKey(e);
|
|
4146
|
+
if (halted) continue;
|
|
4147
|
+
if (seen.has(key)) {
|
|
4148
|
+
processed.add(key);
|
|
4149
|
+
continue;
|
|
4150
|
+
}
|
|
4151
|
+
const r = await post(e.body);
|
|
4152
|
+
const outcome = classifyCaptureOutcome(r);
|
|
4153
|
+
if (outcome === "confirmed") {
|
|
4154
|
+
seen.add(key);
|
|
4155
|
+
flushed++;
|
|
4156
|
+
processed.add(key);
|
|
4157
|
+
continue;
|
|
4158
|
+
}
|
|
4159
|
+
if (outcome === "failed") {
|
|
4160
|
+
seen.add(key);
|
|
4161
|
+
dropped.push(r);
|
|
4162
|
+
processed.add(key);
|
|
4163
|
+
continue;
|
|
4164
|
+
}
|
|
4165
|
+
const attempts = (e.attempts ?? 0) + 1;
|
|
4166
|
+
if (attempts >= PENDING_MAX_ATTEMPTS) {
|
|
4167
|
+
seen.add(key);
|
|
4168
|
+
dropped.push(r);
|
|
4169
|
+
processed.add(key);
|
|
4170
|
+
continue;
|
|
4171
|
+
}
|
|
4172
|
+
kept.set(key, { ...e, attempts });
|
|
4173
|
+
halted = true;
|
|
4174
|
+
}
|
|
4175
|
+
const out = [];
|
|
4176
|
+
const written = /* @__PURE__ */ new Set();
|
|
4177
|
+
for (const c of readPending(dir)) {
|
|
4178
|
+
const key = entryKey(c);
|
|
4179
|
+
if (processed.has(key) || written.has(key)) continue;
|
|
4180
|
+
written.add(key);
|
|
4181
|
+
out.push(kept.get(key) ?? c);
|
|
4182
|
+
}
|
|
4183
|
+
writePending(out, dir);
|
|
4184
|
+
return { flushed, dropped, remaining: out.length, halted };
|
|
4185
|
+
}
|
|
4186
|
+
async function flushPending(post, dir = ".mmi") {
|
|
4187
|
+
if (!acquireFlushLock(dir)) return { flushed: 0, dropped: [], remaining: readPending(dir).length, skipped: true };
|
|
4188
|
+
let flushed = 0;
|
|
4189
|
+
const dropped = [];
|
|
4190
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4191
|
+
try {
|
|
4192
|
+
for (; ; ) {
|
|
4193
|
+
const r = await drainOnce(post, dir, seen);
|
|
4194
|
+
flushed += r.flushed;
|
|
4195
|
+
dropped.push(...r.dropped);
|
|
4196
|
+
if (r.halted || r.remaining === 0) break;
|
|
4197
|
+
if (!r.flushed && !r.dropped.length) break;
|
|
4198
|
+
}
|
|
4199
|
+
} finally {
|
|
4200
|
+
releaseFlushLock(dir);
|
|
4201
|
+
}
|
|
4202
|
+
return { flushed, dropped, remaining: readPending(dir).length };
|
|
4203
|
+
}
|
|
4204
|
+
|
|
4216
4205
|
// src/hub-auth.ts
|
|
4217
4206
|
var import_node_crypto = require("node:crypto");
|
|
4218
4207
|
var import_node_fs5 = require("node:fs");
|
|
@@ -4660,7 +4649,6 @@ async function runSagaHealth(o, io = consoleIo) {
|
|
|
4660
4649
|
authorized,
|
|
4661
4650
|
sagaApiUrl: cfg.sagaApiUrl,
|
|
4662
4651
|
pendingNotes: readPending().length,
|
|
4663
|
-
honchoPending: readHonchoPending().length,
|
|
4664
4652
|
memoryAgeDays
|
|
4665
4653
|
});
|
|
4666
4654
|
if (o.json) return io.log(JSON.stringify(report));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutmutco/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.43.0",
|
|
4
4
|
"description": "MMI Future CLI — delivers the org rules (whole-file), plus saga and KB access. The cross-IDE engine the plugin's SessionStart hook drives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|