agentplugged 0.0.0-stage → 0.0.1
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/LICENSE +110 -0
- package/README.md +26 -2
- package/bin.mjs +228 -0
- package/package.json +27 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, MIT Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-MIT
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Innovel Studio SASU
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or
|
|
34
|
+
service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software
|
|
39
|
+
that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee
|
|
52
|
+
using the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to
|
|
59
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
+
remove any copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
+
|
|
77
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
+
|
|
81
|
+
### Trademarks
|
|
82
|
+
|
|
83
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
+
trademarks, trade names, service marks or product names.
|
|
86
|
+
|
|
87
|
+
## Grant of Future License
|
|
88
|
+
|
|
89
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
+
the MIT license that is effective on the second anniversary of the date we make
|
|
91
|
+
the Software available. On or after that date, you may use the Software under
|
|
92
|
+
the MIT license, in which case the following will apply:
|
|
93
|
+
|
|
94
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
95
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
96
|
+
the Software without restriction, including without limitation the rights to
|
|
97
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
98
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
99
|
+
so, subject to the following conditions:
|
|
100
|
+
|
|
101
|
+
The above copyright notice and this permission notice shall be included in all
|
|
102
|
+
copies or substantial portions of the Software.
|
|
103
|
+
|
|
104
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
105
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
106
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
107
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
108
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
109
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
110
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AgentPlugged
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Coming soon: the cockpit for your team of AI coding agents.**
|
|
4
|
+
|
|
5
|
+
Your agents code in Claude Code, Codex or Cursor. You follow, approve and decide from the web, your phone or your voice, with a signed journal of everything your product went through.
|
|
6
|
+
|
|
7
|
+
The method is not published yet. To be notified on launch day:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npx agentplugged
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
It asks for your email (optional) and adds you to the waitlist: one email, on launch day, no spam, unsubscribe in one click. Nothing is installed or written to your project.
|
|
14
|
+
|
|
15
|
+
On launch day, the same command installs the method:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npx agentplugged init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
You can also join at [agentplugged.ai](https://agentplugged.ai).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
**Français.** AgentPlugged arrive bientôt. `npx agentplugged` vous inscrit à la liste d'attente (un seul e-mail, le jour du lancement) ; le jour venu, `npx agentplugged init` installera la méthode.
|
|
26
|
+
|
|
27
|
+
© Innovel Studio SASU
|
package/bin.mjs
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// AgentPlugged waitlist package: explains the project, offers to join the launch waitlist,
|
|
3
|
+
// and points to the real release as soon as it is published. Installs nothing, writes nothing.
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import readline from "node:readline";
|
|
6
|
+
|
|
7
|
+
const VERSION = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8")).version;
|
|
8
|
+
const WAITLIST_URL = process.env.AGENTPLUGGED_WAITLIST_URL || "https://agentplugged.ai/api/waitlist";
|
|
9
|
+
const REGISTRY_URL = "https://registry.npmjs.org/agentplugged/latest";
|
|
10
|
+
const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
|
|
11
|
+
|
|
12
|
+
const MESSAGES = {
|
|
13
|
+
en: {
|
|
14
|
+
intro: "AgentPlugged is coming soon: the cockpit for your team of AI coding agents.",
|
|
15
|
+
detail:
|
|
16
|
+
"Your agents code in Claude Code, Codex or Cursor; you follow, approve and decide from the web, your phone or your voice.",
|
|
17
|
+
notYet: "The method is not published yet.",
|
|
18
|
+
released: (v) => `AgentPlugged ${v} is out. Run: npx agentplugged@latest init`,
|
|
19
|
+
ask: "Your email to be notified on launch day (leave empty to skip): ",
|
|
20
|
+
consent: "One email, on launch day. No spam, unsubscribe in one click.",
|
|
21
|
+
invalid: "This address doesn't look valid. Check it and try again.",
|
|
22
|
+
skipped: "No problem. You can also join at https://agentplugged.ai",
|
|
23
|
+
sending: "Sending…",
|
|
24
|
+
ok: "You're on the list. You'll be among the first to know.",
|
|
25
|
+
then: "On launch day, this same command will install the method: npx agentplugged init",
|
|
26
|
+
failed: "Sign-up didn't go through. Try again later or join at https://agentplugged.ai",
|
|
27
|
+
noTty: "Join the waitlist at https://agentplugged.ai",
|
|
28
|
+
help: "Usage: npx agentplugged [init]\n\nJoins the AgentPlugged launch waitlist. Nothing is installed or written to your project.",
|
|
29
|
+
},
|
|
30
|
+
fr: {
|
|
31
|
+
intro: "AgentPlugged arrive bientôt : le poste de pilotage de votre équipe d'agents IA de développement.",
|
|
32
|
+
detail:
|
|
33
|
+
"Vos agents codent dans Claude Code, Codex ou Cursor ; vous suivez, validez et décidez depuis le web, le téléphone ou la voix.",
|
|
34
|
+
notYet: "La méthode n'est pas encore publiée.",
|
|
35
|
+
released: (v) => `AgentPlugged ${v} est en ligne. Lancez : npx agentplugged@latest init`,
|
|
36
|
+
ask: "Votre e-mail pour être prévenu le jour du lancement (vide pour passer) : ",
|
|
37
|
+
consent: "Un seul e-mail, le jour du lancement. Pas de spam, désinscription en un clic.",
|
|
38
|
+
invalid: "Cette adresse ne semble pas valide. Vérifiez-la et réessayez.",
|
|
39
|
+
skipped: "Pas de souci. Vous pouvez aussi vous inscrire sur https://agentplugged.ai",
|
|
40
|
+
sending: "Envoi…",
|
|
41
|
+
ok: "C'est noté. Vous serez parmi les premiers prévenus.",
|
|
42
|
+
then: "Le jour du lancement, cette même commande installera la méthode : npx agentplugged init",
|
|
43
|
+
failed: "L'inscription n'a pas abouti. Réessayez plus tard ou inscrivez-vous sur https://agentplugged.ai",
|
|
44
|
+
noTty: "Inscrivez-vous à la liste d'attente sur https://agentplugged.ai",
|
|
45
|
+
help: "Usage : npx agentplugged [init]\n\nInscrit à la liste d'attente du lancement d'AgentPlugged. Rien n'est installé ni écrit dans votre projet.",
|
|
46
|
+
},
|
|
47
|
+
es: {
|
|
48
|
+
intro: "AgentPlugged llega pronto: el puesto de mando de tu equipo de agentes de IA de desarrollo.",
|
|
49
|
+
detail:
|
|
50
|
+
"Tus agentes programan en Claude Code, Codex o Cursor; tú sigues, validas y decides desde la web, el teléfono o la voz.",
|
|
51
|
+
notYet: "El método aún no está publicado.",
|
|
52
|
+
released: (v) => `AgentPlugged ${v} ya está disponible. Ejecuta: npx agentplugged@latest init`,
|
|
53
|
+
ask: "Tu correo para avisarte el día del lanzamiento (vacío para saltar): ",
|
|
54
|
+
consent: "Un solo correo, el día del lanzamiento. Sin spam, baja en un clic.",
|
|
55
|
+
invalid: "Esta dirección no parece válida. Revísala e inténtalo de nuevo.",
|
|
56
|
+
skipped: "Sin problema. También puedes apuntarte en https://agentplugged.ai",
|
|
57
|
+
sending: "Enviando…",
|
|
58
|
+
ok: "Apuntado. Serás de los primeros en saberlo.",
|
|
59
|
+
then: "El día del lanzamiento, este mismo comando instalará el método: npx agentplugged init",
|
|
60
|
+
failed: "La inscripción no se completó. Inténtalo más tarde o apúntate en https://agentplugged.ai",
|
|
61
|
+
noTty: "Apúntate a la lista de espera en https://agentplugged.ai",
|
|
62
|
+
help: "Uso: npx agentplugged [init]\n\nTe apunta a la lista de espera del lanzamiento de AgentPlugged. No se instala ni se escribe nada en tu proyecto.",
|
|
63
|
+
},
|
|
64
|
+
pt: {
|
|
65
|
+
intro: "AgentPlugged chega em breve: o cockpit da sua equipe de agentes de IA de desenvolvimento.",
|
|
66
|
+
detail:
|
|
67
|
+
"Seus agentes programam no Claude Code, Codex ou Cursor; você acompanha, valida e decide pela web, pelo celular ou pela voz.",
|
|
68
|
+
notYet: "O método ainda não foi publicado.",
|
|
69
|
+
released: (v) => `AgentPlugged ${v} já está disponível. Execute: npx agentplugged@latest init`,
|
|
70
|
+
ask: "Seu e-mail para ser avisado no dia do lançamento (vazio para pular): ",
|
|
71
|
+
consent: "Um único e-mail, no dia do lançamento. Sem spam, descadastro em um clique.",
|
|
72
|
+
invalid: "Este endereço não parece válido. Confira e tente de novo.",
|
|
73
|
+
skipped: "Sem problema. Você também pode se inscrever em https://agentplugged.ai",
|
|
74
|
+
sending: "Enviando…",
|
|
75
|
+
ok: "Anotado. Você estará entre os primeiros a saber.",
|
|
76
|
+
then: "No dia do lançamento, este mesmo comando instalará o método: npx agentplugged init",
|
|
77
|
+
failed: "A inscrição não foi concluída. Tente mais tarde ou inscreva-se em https://agentplugged.ai",
|
|
78
|
+
noTty: "Inscreva-se na lista de espera em https://agentplugged.ai",
|
|
79
|
+
help: "Uso: npx agentplugged [init]\n\nInscreve você na lista de espera do lançamento do AgentPlugged. Nada é instalado nem escrito no seu projeto.",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
function detectLanguage() {
|
|
84
|
+
const candidates = [process.env.LC_ALL, process.env.LC_MESSAGES, process.env.LANG];
|
|
85
|
+
try {
|
|
86
|
+
candidates.push(Intl.DateTimeFormat().resolvedOptions().locale);
|
|
87
|
+
} catch {}
|
|
88
|
+
for (const value of candidates) {
|
|
89
|
+
const code = String(value || "").slice(0, 2).toLowerCase();
|
|
90
|
+
if (code in MESSAGES) return code;
|
|
91
|
+
}
|
|
92
|
+
return "en";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const color = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
96
|
+
const bold = (text) => (color ? `\x1b[1m${text}\x1b[22m` : text);
|
|
97
|
+
const dim = (text) => (color ? `\x1b[2m${text}\x1b[22m` : text);
|
|
98
|
+
const green = (text) => (color ? `\x1b[32m${text}\x1b[39m` : text);
|
|
99
|
+
|
|
100
|
+
async function fetchWithTimeout(url, options, ms) {
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
const timer = setTimeout(() => controller.abort(), ms);
|
|
103
|
+
try {
|
|
104
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
105
|
+
} finally {
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// npx can reuse a cached copy of this package after the real release: ask the registry.
|
|
111
|
+
async function releasedVersion() {
|
|
112
|
+
try {
|
|
113
|
+
const response = await fetchWithTimeout(REGISTRY_URL, {}, 3000);
|
|
114
|
+
if (!response.ok) return null;
|
|
115
|
+
const { version } = await response.json();
|
|
116
|
+
return typeof version === "string" && !version.startsWith("0.0.") ? version : null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// One interface for the whole session, so piped answers are not lost between questions.
|
|
123
|
+
function createAsker() {
|
|
124
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
125
|
+
const lines = [];
|
|
126
|
+
let waiting = null;
|
|
127
|
+
let closed = false;
|
|
128
|
+
rl.on("line", (line) => {
|
|
129
|
+
if (waiting) {
|
|
130
|
+
const resolve = waiting;
|
|
131
|
+
waiting = null;
|
|
132
|
+
resolve(line.trim());
|
|
133
|
+
} else lines.push(line.trim());
|
|
134
|
+
});
|
|
135
|
+
const finish = () => {
|
|
136
|
+
closed = true;
|
|
137
|
+
if (waiting) {
|
|
138
|
+
process.stdout.write("\n");
|
|
139
|
+
waiting("");
|
|
140
|
+
waiting = null;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
rl.on("close", finish);
|
|
144
|
+
rl.on("SIGINT", () => rl.close());
|
|
145
|
+
return {
|
|
146
|
+
ask(question) {
|
|
147
|
+
process.stdout.write(question);
|
|
148
|
+
if (lines.length) {
|
|
149
|
+
const line = lines.shift();
|
|
150
|
+
process.stdout.write(`${line}\n`);
|
|
151
|
+
return Promise.resolve(line);
|
|
152
|
+
}
|
|
153
|
+
if (closed) return Promise.resolve("");
|
|
154
|
+
return new Promise((resolve) => {
|
|
155
|
+
waiting = resolve;
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
close: () => rl.close(),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function main() {
|
|
163
|
+
const args = process.argv.slice(2);
|
|
164
|
+
const t = MESSAGES[detectLanguage()];
|
|
165
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
166
|
+
console.log(VERSION);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
170
|
+
console.log(t.help);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
console.log(`\n${bold("AgentPlugged")}\n${t.intro}`);
|
|
175
|
+
console.log(dim(t.detail));
|
|
176
|
+
|
|
177
|
+
const released = await releasedVersion();
|
|
178
|
+
if (released) {
|
|
179
|
+
console.log(`\n${green(t.released(released))}\n`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
console.log(`\n${t.notYet}`);
|
|
183
|
+
|
|
184
|
+
if (!process.stdin.isTTY || process.env.CI) {
|
|
185
|
+
console.log(`${t.noTty}\n`);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log(dim(t.consent));
|
|
190
|
+
const asker = createAsker();
|
|
191
|
+
let email = "";
|
|
192
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
193
|
+
email = (await asker.ask(t.ask)).toLowerCase();
|
|
194
|
+
if (!email || (email.length <= 254 && EMAIL.test(email))) break;
|
|
195
|
+
console.log(t.invalid);
|
|
196
|
+
email = "";
|
|
197
|
+
}
|
|
198
|
+
asker.close();
|
|
199
|
+
if (!email) {
|
|
200
|
+
console.log(`${t.skipped}\n`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
console.log(dim(t.sending));
|
|
205
|
+
try {
|
|
206
|
+
const response = await fetchWithTimeout(
|
|
207
|
+
WAITLIST_URL,
|
|
208
|
+
{
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers: { "content-type": "application/json" },
|
|
211
|
+
body: JSON.stringify({ email, lang: detectLanguage(), source: "npm" }),
|
|
212
|
+
},
|
|
213
|
+
10000,
|
|
214
|
+
);
|
|
215
|
+
const body = await response.json().catch(() => ({}));
|
|
216
|
+
if (response.ok && body.ok) {
|
|
217
|
+
console.log(`${green(t.ok)}\n${t.then}\n`);
|
|
218
|
+
} else if (body.error === "invalid_email") {
|
|
219
|
+
console.log(`${t.invalid}\n`);
|
|
220
|
+
} else {
|
|
221
|
+
console.log(`${t.failed}\n`);
|
|
222
|
+
}
|
|
223
|
+
} catch {
|
|
224
|
+
console.log(`${t.failed}\n`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
await main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentplugged",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "AgentPlugged is coming soon: the cockpit for your team of AI coding agents. Run npx agentplugged to join the waitlist.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"agents",
|
|
8
|
+
"claude-code",
|
|
9
|
+
"codex",
|
|
10
|
+
"cursor",
|
|
11
|
+
"workflow",
|
|
12
|
+
"cli"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://agentplugged.ai",
|
|
15
|
+
"license": "FSL-1.1-MIT",
|
|
16
|
+
"author": "Innovel Studio SASU",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"bin": {
|
|
19
|
+
"agentplugged": "bin.mjs"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"bin.mjs",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
}
|
|
29
|
+
}
|