lovelyai 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 +117 -0
- package/dist/bin/lovely-Ck8s6-LU.d.ts +1 -0
- package/dist/bin/lovely.js +4 -0
- package/dist/src/index-DCCSm2Uc.d.ts +1 -0
- package/dist/src/index.js +381 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
LOVELY PROPRIETARY SOFTWARE LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lovely AI. All rights reserved.
|
|
4
|
+
|
|
5
|
+
IMPORTANT — READ CAREFULLY BEFORE USING THIS SOFTWARE.
|
|
6
|
+
|
|
7
|
+
This software and all associated documentation, source code, binaries, and
|
|
8
|
+
materials (collectively, the "Software") are the proprietary and confidential
|
|
9
|
+
property of Lovely AI ("Licensor"). By accessing, downloading, installing, or
|
|
10
|
+
using the Software in any form, you ("Licensee") agree to be bound by the
|
|
11
|
+
terms of this License. If you do not agree, do not access or use the Software.
|
|
12
|
+
|
|
13
|
+
-------------------------------------------------------------------------------
|
|
14
|
+
1. GRANT OF LICENSE
|
|
15
|
+
|
|
16
|
+
Subject to the terms of a separately executed commercial agreement between
|
|
17
|
+
Licensor and Licensee, Licensor grants Licensee a limited, non-exclusive,
|
|
18
|
+
non-transferable, non-sublicensable license to install and use the Software
|
|
19
|
+
solely for Licensee's internal business operations.
|
|
20
|
+
|
|
21
|
+
No license is granted by this file alone. Use of the Software requires a valid
|
|
22
|
+
commercial license obtained directly from Lovely AI.
|
|
23
|
+
|
|
24
|
+
-------------------------------------------------------------------------------
|
|
25
|
+
2. RESTRICTIONS
|
|
26
|
+
|
|
27
|
+
Licensee may NOT, without the prior written consent of Licensor:
|
|
28
|
+
|
|
29
|
+
a. Copy, reproduce, or duplicate the Software or any portion thereof;
|
|
30
|
+
b. Distribute, sell, resell, sublicense, rent, lease, or otherwise transfer
|
|
31
|
+
the Software or any rights therein to any third party;
|
|
32
|
+
c. Modify, adapt, translate, reverse engineer, decompile, disassemble, or
|
|
33
|
+
create derivative works based on the Software;
|
|
34
|
+
d. Use the Software to build a product or service that competes with the
|
|
35
|
+
Software or with any product or service offered by Licensor;
|
|
36
|
+
e. Remove, alter, or obscure any proprietary notices, labels, or marks on
|
|
37
|
+
the Software;
|
|
38
|
+
f. Use the Software for any unlawful purpose or in violation of any
|
|
39
|
+
applicable law or regulation;
|
|
40
|
+
g. Make the Software available to any third party as a hosted or managed
|
|
41
|
+
service (SaaS, PaaS, or otherwise).
|
|
42
|
+
|
|
43
|
+
-------------------------------------------------------------------------------
|
|
44
|
+
3. OWNERSHIP
|
|
45
|
+
|
|
46
|
+
The Software is licensed, not sold. Licensor retains all right, title, and
|
|
47
|
+
interest in and to the Software, including all intellectual property rights
|
|
48
|
+
therein. Licensee acquires no ownership interest in the Software.
|
|
49
|
+
|
|
50
|
+
-------------------------------------------------------------------------------
|
|
51
|
+
4. SOURCE CODE VISIBILITY
|
|
52
|
+
|
|
53
|
+
The source code of the Software is made available for reference, audit, and
|
|
54
|
+
transparency purposes only. Visibility of source code does not constitute a
|
|
55
|
+
grant of any rights beyond those expressly stated in this License.
|
|
56
|
+
|
|
57
|
+
-------------------------------------------------------------------------------
|
|
58
|
+
5. CONFIDENTIALITY
|
|
59
|
+
|
|
60
|
+
Licensee acknowledges that the Software contains trade secrets and proprietary
|
|
61
|
+
information of Licensor. Licensee agrees to maintain the confidentiality of
|
|
62
|
+
the Software using at least the same degree of care it uses for its own
|
|
63
|
+
confidential information, but in no event less than reasonable care.
|
|
64
|
+
|
|
65
|
+
-------------------------------------------------------------------------------
|
|
66
|
+
6. NO WARRANTY
|
|
67
|
+
|
|
68
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
69
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
70
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. LICENSOR DOES
|
|
71
|
+
NOT WARRANT THAT THE SOFTWARE WILL BE ERROR-FREE OR OPERATE WITHOUT
|
|
72
|
+
INTERRUPTION.
|
|
73
|
+
|
|
74
|
+
-------------------------------------------------------------------------------
|
|
75
|
+
7. LIMITATION OF LIABILITY
|
|
76
|
+
|
|
77
|
+
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL LICENSOR
|
|
78
|
+
BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, CONSEQUENTIAL, OR
|
|
79
|
+
PUNITIVE DAMAGES, INCLUDING LOSS OF PROFITS, DATA, BUSINESS, OR GOODWILL,
|
|
80
|
+
ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THIS LICENSE, EVEN IF
|
|
81
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
82
|
+
|
|
83
|
+
LICENSOR'S TOTAL CUMULATIVE LIABILITY TO LICENSEE FOR ANY CLAIMS ARISING OUT
|
|
84
|
+
OF OR RELATED TO THE SOFTWARE SHALL NOT EXCEED THE AMOUNTS PAID BY LICENSEE
|
|
85
|
+
TO LICENSOR FOR THE SOFTWARE IN THE TWELVE (12) MONTHS PRECEDING THE CLAIM.
|
|
86
|
+
|
|
87
|
+
-------------------------------------------------------------------------------
|
|
88
|
+
8. TERMINATION
|
|
89
|
+
|
|
90
|
+
This License is effective until terminated. It will terminate automatically
|
|
91
|
+
if Licensee breaches any term of this License. Upon termination, Licensee
|
|
92
|
+
must immediately cease all use of the Software and destroy all copies in its
|
|
93
|
+
possession or control.
|
|
94
|
+
|
|
95
|
+
-------------------------------------------------------------------------------
|
|
96
|
+
9. GOVERNING LAW
|
|
97
|
+
|
|
98
|
+
This License shall be governed by and construed in accordance with the laws
|
|
99
|
+
of the State of California, United States, without regard to its conflict of
|
|
100
|
+
law provisions. Any dispute arising under this License shall be subject to the
|
|
101
|
+
exclusive jurisdiction of the courts located in San Francisco County, California.
|
|
102
|
+
|
|
103
|
+
-------------------------------------------------------------------------------
|
|
104
|
+
10. CONTACT
|
|
105
|
+
|
|
106
|
+
To obtain a commercial license, report a licensing issue, or request
|
|
107
|
+
permissions beyond the scope of this License, contact:
|
|
108
|
+
|
|
109
|
+
Lovely AI
|
|
110
|
+
licensing@lovely.ai
|
|
111
|
+
https://lovely.ai
|
|
112
|
+
|
|
113
|
+
-------------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
Unauthorized use, reproduction, or distribution of this Software, or any
|
|
116
|
+
portion of it, may result in severe civil and criminal penalties, and will be
|
|
117
|
+
prosecuted to the maximum extent possible under applicable law.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import ora from "ora";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { createServer } from "node:http";
|
|
10
|
+
import { WebSocketServer } from "ws";
|
|
11
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
12
|
+
import { execFileSync } from "node:child_process";
|
|
13
|
+
|
|
14
|
+
//#region ../core/dist/index.js
|
|
15
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
16
|
+
const GatewayConfigSchema = z.object({
|
|
17
|
+
port: z.number().int().min(1024).max(65535).default(18900),
|
|
18
|
+
host: z.string().default("127.0.0.1"),
|
|
19
|
+
auth: z.enum([
|
|
20
|
+
"none",
|
|
21
|
+
"token",
|
|
22
|
+
"password"
|
|
23
|
+
]).default("none"),
|
|
24
|
+
token: z.string().optional()
|
|
25
|
+
});
|
|
26
|
+
const PrivacyConfigSchema = z.object({
|
|
27
|
+
default: z.enum([
|
|
28
|
+
"local-first",
|
|
29
|
+
"cloud-allowed",
|
|
30
|
+
"local-only"
|
|
31
|
+
]).default("local-first"),
|
|
32
|
+
cloudAllowed: z.array(z.string()).default([]),
|
|
33
|
+
auditLog: z.boolean().default(true),
|
|
34
|
+
piiDetection: z.boolean().default(true),
|
|
35
|
+
perConversation: z.record(z.string(), z.enum([
|
|
36
|
+
"local-only",
|
|
37
|
+
"cloud-allowed",
|
|
38
|
+
"local-first"
|
|
39
|
+
])).default({})
|
|
40
|
+
});
|
|
41
|
+
const HitlConfigSchema = z.object({
|
|
42
|
+
enabled: z.boolean().default(true),
|
|
43
|
+
disambiguationThreshold: z.number().min(0).max(1).default(.7),
|
|
44
|
+
approvalMemoryCount: z.number().int().min(1).default(2),
|
|
45
|
+
approvalDecayDays: z.number().int().min(1).default(30),
|
|
46
|
+
riskThresholds: z.record(z.string(), z.enum([
|
|
47
|
+
"none",
|
|
48
|
+
"fyi",
|
|
49
|
+
"approval"
|
|
50
|
+
])).default({
|
|
51
|
+
sendMessage: "fyi",
|
|
52
|
+
sendEmail: "approval",
|
|
53
|
+
deleteFile: "approval",
|
|
54
|
+
executeCode: "approval",
|
|
55
|
+
webSearch: "fyi",
|
|
56
|
+
readFile: "none"
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
const LLMPrimarySchema = z.object({
|
|
60
|
+
provider: z.string().default("anthropic"),
|
|
61
|
+
model: z.string().default("claude-sonnet-4-6")
|
|
62
|
+
}).default({});
|
|
63
|
+
const LLMConfigSchema = z.object({
|
|
64
|
+
primary: LLMPrimarySchema,
|
|
65
|
+
fallbacks: z.array(z.object({
|
|
66
|
+
provider: z.string(),
|
|
67
|
+
model: z.string()
|
|
68
|
+
})).default([]),
|
|
69
|
+
providers: z.record(z.string(), z.object({
|
|
70
|
+
baseUrl: z.string().optional(),
|
|
71
|
+
apiKey: z.string().optional(),
|
|
72
|
+
type: z.enum([
|
|
73
|
+
"anthropic",
|
|
74
|
+
"openai",
|
|
75
|
+
"ollama",
|
|
76
|
+
"custom"
|
|
77
|
+
]).default("custom")
|
|
78
|
+
})).default({})
|
|
79
|
+
});
|
|
80
|
+
const LovelyConfigSchema = z.object({
|
|
81
|
+
gateway: GatewayConfigSchema.default({}),
|
|
82
|
+
privacy: PrivacyConfigSchema.default({}),
|
|
83
|
+
hitl: HitlConfigSchema.default({}),
|
|
84
|
+
llm: LLMConfigSchema.default({})
|
|
85
|
+
});
|
|
86
|
+
function resolveConfigDir(opts = {}) {
|
|
87
|
+
return opts.configDir ?? join(homedir(), ".lovely");
|
|
88
|
+
}
|
|
89
|
+
function loadConfig(opts = {}) {
|
|
90
|
+
const configDir = resolveConfigDir(opts);
|
|
91
|
+
const configFile = opts.configFile ?? join(configDir, "lovely.json");
|
|
92
|
+
let raw = {};
|
|
93
|
+
if (existsSync(configFile)) {
|
|
94
|
+
const content = readFileSync(configFile, "utf8");
|
|
95
|
+
try {
|
|
96
|
+
raw = JSON.parse(content);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
throw new Error(`Failed to parse config file ${configFile}: ${err.message}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return LovelyConfigSchema.parse(raw);
|
|
102
|
+
}
|
|
103
|
+
function createEventBus() {
|
|
104
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
105
|
+
const anyHandlers = /* @__PURE__ */ new Set();
|
|
106
|
+
return {
|
|
107
|
+
on(event, handler) {
|
|
108
|
+
if (!handlers.has(event)) handlers.set(event, /* @__PURE__ */ new Set());
|
|
109
|
+
handlers.get(event).add(handler);
|
|
110
|
+
return () => {
|
|
111
|
+
handlers.get(event)?.delete(handler);
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
onAny(handler) {
|
|
115
|
+
anyHandlers.add(handler);
|
|
116
|
+
return () => {
|
|
117
|
+
anyHandlers.delete(handler);
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
emit(event, payload) {
|
|
121
|
+
handlers.get(event)?.forEach((h) => h(payload));
|
|
122
|
+
anyHandlers.forEach((h) => h({
|
|
123
|
+
event,
|
|
124
|
+
payload
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function serializeFrame(frame) {
|
|
130
|
+
return JSON.stringify(frame);
|
|
131
|
+
}
|
|
132
|
+
function parseFrame(raw) {
|
|
133
|
+
try {
|
|
134
|
+
const parsed = JSON.parse(raw);
|
|
135
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
136
|
+
const obj = parsed;
|
|
137
|
+
if (obj["type"] !== "req" && obj["type"] !== "res" && obj["type"] !== "event") return null;
|
|
138
|
+
return parsed;
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const express = __require("express");
|
|
144
|
+
async function createGatewayServer(opts) {
|
|
145
|
+
const { port, host = "127.0.0.1" } = opts;
|
|
146
|
+
const bus = opts.bus ?? createEventBus();
|
|
147
|
+
const app = express();
|
|
148
|
+
app.use(express.json());
|
|
149
|
+
app.get("/health", (_req, res) => {
|
|
150
|
+
res.json({
|
|
151
|
+
ok: true,
|
|
152
|
+
version: "0.0.1"
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
const httpServer = createServer(app);
|
|
156
|
+
const wss = new WebSocketServer({ server: httpServer });
|
|
157
|
+
let seq = 0;
|
|
158
|
+
wss.on("connection", (ws) => {
|
|
159
|
+
ws.on("message", (data) => {
|
|
160
|
+
const frame = parseFrame(data.toString());
|
|
161
|
+
if (!frame || frame.type !== "req") return;
|
|
162
|
+
ws.send(serializeFrame({
|
|
163
|
+
type: "res",
|
|
164
|
+
id: frame.id,
|
|
165
|
+
ok: true
|
|
166
|
+
}));
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
function broadcast(event, payload) {
|
|
170
|
+
const frame = serializeFrame({
|
|
171
|
+
type: "event",
|
|
172
|
+
event,
|
|
173
|
+
payload,
|
|
174
|
+
seq: seq++
|
|
175
|
+
});
|
|
176
|
+
for (const client of wss.clients) if (client.readyState === client.OPEN) client.send(frame);
|
|
177
|
+
}
|
|
178
|
+
await new Promise((resolve, reject) => {
|
|
179
|
+
httpServer.once("error", reject);
|
|
180
|
+
httpServer.listen(port, host, () => {
|
|
181
|
+
httpServer.off("error", reject);
|
|
182
|
+
resolve();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
return {
|
|
186
|
+
port,
|
|
187
|
+
bus,
|
|
188
|
+
broadcast,
|
|
189
|
+
stop: () => new Promise((resolve, reject) => {
|
|
190
|
+
wss.close((wsErr) => {
|
|
191
|
+
if (wsErr) {
|
|
192
|
+
reject(wsErr);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
httpServer.close((err) => err ? reject(err) : resolve());
|
|
196
|
+
});
|
|
197
|
+
})
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/commands/gateway.ts
|
|
203
|
+
function gatewayCommand() {
|
|
204
|
+
return new Command("gateway").description("Start the Lovely gateway daemon").option("-p, --port <port>", "Port to listen on", "18900").option("--verbose", "Enable verbose logging").action(async (opts) => {
|
|
205
|
+
const config = loadConfig();
|
|
206
|
+
const port = parseInt(opts.port, 10);
|
|
207
|
+
if (Number.isNaN(port) || port < 1 || port > 65535) {
|
|
208
|
+
console.error(chalk.red(`Invalid port: ${String(opts.port)}`));
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
const spinner = ora(`Starting Lovely gateway on port ${port}...`).start();
|
|
212
|
+
try {
|
|
213
|
+
const server = await createGatewayServer({
|
|
214
|
+
port,
|
|
215
|
+
host: config.gateway.host
|
|
216
|
+
});
|
|
217
|
+
spinner.succeed(chalk.green(`Lovely gateway running on ${chalk.bold(`http://127.0.0.1:${port}`)}`));
|
|
218
|
+
console.log(chalk.dim(" Press Ctrl+C to stop"));
|
|
219
|
+
const shutdown = async () => {
|
|
220
|
+
console.log("\n" + chalk.yellow("Shutting down..."));
|
|
221
|
+
await server.stop();
|
|
222
|
+
process.exit(0);
|
|
223
|
+
};
|
|
224
|
+
process.on("SIGINT", () => {
|
|
225
|
+
shutdown();
|
|
226
|
+
});
|
|
227
|
+
process.on("SIGTERM", () => {
|
|
228
|
+
shutdown();
|
|
229
|
+
});
|
|
230
|
+
} catch (err) {
|
|
231
|
+
spinner.fail(chalk.red(`Failed to start gateway: ${err}`));
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region src/commands/onboard.ts
|
|
239
|
+
function escapeXml(str) {
|
|
240
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
241
|
+
}
|
|
242
|
+
function onboardCommand() {
|
|
243
|
+
return new Command("onboard").description("Interactive setup wizard for Lovely").option("--install-daemon", "Install launchd daemon after setup").action(async (opts) => {
|
|
244
|
+
console.log(chalk.bold.magenta("\nWelcome to Lovely setup\n"));
|
|
245
|
+
const configDir = join(homedir(), ".lovely");
|
|
246
|
+
mkdirSync(configDir, { recursive: true });
|
|
247
|
+
const provider = await select({
|
|
248
|
+
message: "Which AI provider do you want to use?",
|
|
249
|
+
choices: [
|
|
250
|
+
{
|
|
251
|
+
name: "Anthropic (Claude) — recommended",
|
|
252
|
+
value: "anthropic"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "Ollama (local, privacy-first)",
|
|
256
|
+
value: "ollama"
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: "OpenAI",
|
|
260
|
+
value: "openai"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: "Skip for now",
|
|
264
|
+
value: "skip"
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
});
|
|
268
|
+
let apiKey = "";
|
|
269
|
+
let model = "";
|
|
270
|
+
if (provider === "anthropic") {
|
|
271
|
+
apiKey = await input({
|
|
272
|
+
message: "Anthropic API key:",
|
|
273
|
+
validate: (v) => v.startsWith("sk-") || "Must start with sk-"
|
|
274
|
+
});
|
|
275
|
+
model = "claude-sonnet-4-6";
|
|
276
|
+
} else if (provider === "openai") {
|
|
277
|
+
apiKey = await input({
|
|
278
|
+
message: "OpenAI API key:",
|
|
279
|
+
validate: (v) => v.startsWith("sk-") || "Must start with sk-"
|
|
280
|
+
});
|
|
281
|
+
model = "gpt-4o";
|
|
282
|
+
} else if (provider === "ollama") model = await input({
|
|
283
|
+
message: "Ollama model name:",
|
|
284
|
+
default: "llama3.2"
|
|
285
|
+
});
|
|
286
|
+
const privacy = await select({
|
|
287
|
+
message: "Default privacy policy:",
|
|
288
|
+
choices: [
|
|
289
|
+
{
|
|
290
|
+
name: "Local-first (cloud only if explicitly allowed)",
|
|
291
|
+
value: "local-first"
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
name: "Local-only (never send to cloud)",
|
|
295
|
+
value: "local-only"
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
name: "Cloud-allowed (use cloud freely)",
|
|
299
|
+
value: "cloud-allowed"
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
});
|
|
303
|
+
const enableIMessage = await confirm({
|
|
304
|
+
message: "Enable iMessage channel?",
|
|
305
|
+
default: true
|
|
306
|
+
});
|
|
307
|
+
const config = {
|
|
308
|
+
gateway: { port: 18900 },
|
|
309
|
+
privacy: {
|
|
310
|
+
default: privacy,
|
|
311
|
+
cloudAllowed: privacy !== "local-only" && provider !== "skip" ? [provider] : []
|
|
312
|
+
},
|
|
313
|
+
hitl: { enabled: true },
|
|
314
|
+
llm: {
|
|
315
|
+
primary: {
|
|
316
|
+
provider,
|
|
317
|
+
model
|
|
318
|
+
},
|
|
319
|
+
providers: provider !== "ollama" && provider !== "skip" ? { [provider]: {
|
|
320
|
+
apiKey,
|
|
321
|
+
type: provider
|
|
322
|
+
} } : {}
|
|
323
|
+
},
|
|
324
|
+
channels: { imessage: { enabled: enableIMessage } }
|
|
325
|
+
};
|
|
326
|
+
const configFilePath = join(configDir, "lovely.json");
|
|
327
|
+
writeFileSync(configFilePath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
328
|
+
chmodSync(configFilePath, 384);
|
|
329
|
+
console.log(chalk.green(`\n✓ Config written to ${configDir}/lovely.json (permissions: 600)`));
|
|
330
|
+
if (opts.installDaemon === true) installLaunchdDaemon();
|
|
331
|
+
console.log(chalk.bold("\nSetup complete! Run: ") + chalk.cyan("lovely gateway") + "\n");
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
function installLaunchdDaemon() {
|
|
335
|
+
if (process.platform !== "darwin") {
|
|
336
|
+
console.error(chalk.red("--install-daemon is only supported on macOS"));
|
|
337
|
+
process.exit(1);
|
|
338
|
+
}
|
|
339
|
+
const binPath = process.argv[1] ?? "lovely";
|
|
340
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
341
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
342
|
+
<plist version="1.0">
|
|
343
|
+
<dict>
|
|
344
|
+
<key>Label</key>
|
|
345
|
+
<string>ai.lovely.gateway</string>
|
|
346
|
+
<key>ProgramArguments</key>
|
|
347
|
+
<array>
|
|
348
|
+
<string>${escapeXml(process.execPath)}</string>
|
|
349
|
+
<string>${escapeXml(binPath)}</string>
|
|
350
|
+
<string>gateway</string>
|
|
351
|
+
</array>
|
|
352
|
+
<key>RunAtLoad</key>
|
|
353
|
+
<true/>
|
|
354
|
+
<key>KeepAlive</key>
|
|
355
|
+
<true/>
|
|
356
|
+
<key>StandardOutPath</key>
|
|
357
|
+
<string>${homedir()}/.lovely/logs/gateway.log</string>
|
|
358
|
+
<key>StandardErrorPath</key>
|
|
359
|
+
<string>${homedir()}/.lovely/logs/gateway.error.log</string>
|
|
360
|
+
</dict>
|
|
361
|
+
</plist>`;
|
|
362
|
+
const launchAgentsDir = join(homedir(), "Library", "LaunchAgents");
|
|
363
|
+
mkdirSync(launchAgentsDir, { recursive: true });
|
|
364
|
+
mkdirSync(join(homedir(), ".lovely", "logs"), { recursive: true });
|
|
365
|
+
const plistPath = join(launchAgentsDir, "ai.lovely.gateway.plist");
|
|
366
|
+
writeFileSync(plistPath, plist);
|
|
367
|
+
execFileSync("launchctl", ["load", plistPath]);
|
|
368
|
+
console.log(chalk.green("Launchd daemon installed — Lovely will start automatically on login"));
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/index.ts
|
|
373
|
+
const program = new Command();
|
|
374
|
+
program.name("lovely").description("Lovely — your personal AGI. Runs on your hardware.").version(process.env["npm_package_version"] ?? "0.0.1");
|
|
375
|
+
program.addCommand(gatewayCommand());
|
|
376
|
+
program.addCommand(onboardCommand());
|
|
377
|
+
program.parse(process.argv);
|
|
378
|
+
|
|
379
|
+
//#endregion
|
|
380
|
+
export { };
|
|
381
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../core/dist/index.js","../../src/commands/gateway.ts","../../src/commands/onboard.ts","../../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { z } from \"zod\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createServer } from \"node:http\";\nimport { WebSocketServer } from \"ws\";\nimport { createPrivacyGate } from \"@lovely/privacy\";\nimport { createHITLEngine } from \"@lovely/hitl\";\nimport { createAgentRunner } from \"@lovely/agent\";\n\n//#region \\0rolldown/runtime.js\nvar __require = /* @__PURE__ */ createRequire(import.meta.url);\n\n//#endregion\n//#region src/types.ts\nconst defaultRuntime = {\n\tlog: (msg) => console.log(`[lovely] ${msg}`),\n\terror: (msg) => console.error(`[lovely:error] ${msg}`),\n\tdebug: (msg) => {\n\t\tif (process.env.LOVELY_DEBUG) console.debug(`[lovely:debug] ${msg}`);\n\t}\n};\n\n//#endregion\n//#region src/config/types.ts\nconst GatewayConfigSchema = z.object({\n\tport: z.number().int().min(1024).max(65535).default(18900),\n\thost: z.string().default(\"127.0.0.1\"),\n\tauth: z.enum([\n\t\t\"none\",\n\t\t\"token\",\n\t\t\"password\"\n\t]).default(\"none\"),\n\ttoken: z.string().optional()\n});\nconst PrivacyConfigSchema = z.object({\n\tdefault: z.enum([\n\t\t\"local-first\",\n\t\t\"cloud-allowed\",\n\t\t\"local-only\"\n\t]).default(\"local-first\"),\n\tcloudAllowed: z.array(z.string()).default([]),\n\tauditLog: z.boolean().default(true),\n\tpiiDetection: z.boolean().default(true),\n\tperConversation: z.record(z.string(), z.enum([\n\t\t\"local-only\",\n\t\t\"cloud-allowed\",\n\t\t\"local-first\"\n\t])).default({})\n});\nconst HitlConfigSchema = z.object({\n\tenabled: z.boolean().default(true),\n\tdisambiguationThreshold: z.number().min(0).max(1).default(.7),\n\tapprovalMemoryCount: z.number().int().min(1).default(2),\n\tapprovalDecayDays: z.number().int().min(1).default(30),\n\triskThresholds: z.record(z.string(), z.enum([\n\t\t\"none\",\n\t\t\"fyi\",\n\t\t\"approval\"\n\t])).default({\n\t\tsendMessage: \"fyi\",\n\t\tsendEmail: \"approval\",\n\t\tdeleteFile: \"approval\",\n\t\texecuteCode: \"approval\",\n\t\twebSearch: \"fyi\",\n\t\treadFile: \"none\"\n\t})\n});\nconst LLMPrimarySchema = z.object({\n\tprovider: z.string().default(\"anthropic\"),\n\tmodel: z.string().default(\"claude-sonnet-4-6\")\n}).default({});\nconst LLMConfigSchema = z.object({\n\tprimary: LLMPrimarySchema,\n\tfallbacks: z.array(z.object({\n\t\tprovider: z.string(),\n\t\tmodel: z.string()\n\t})).default([]),\n\tproviders: z.record(z.string(), z.object({\n\t\tbaseUrl: z.string().optional(),\n\t\tapiKey: z.string().optional(),\n\t\ttype: z.enum([\n\t\t\t\"anthropic\",\n\t\t\t\"openai\",\n\t\t\t\"ollama\",\n\t\t\t\"custom\"\n\t\t]).default(\"custom\")\n\t})).default({})\n});\nconst LovelyConfigSchema = z.object({\n\tgateway: GatewayConfigSchema.default({}),\n\tprivacy: PrivacyConfigSchema.default({}),\n\thitl: HitlConfigSchema.default({}),\n\tllm: LLMConfigSchema.default({})\n});\n\n//#endregion\n//#region src/config/load.ts\nfunction resolveConfigDir(opts = {}) {\n\treturn opts.configDir ?? join(homedir(), \".lovely\");\n}\nfunction loadConfig(opts = {}) {\n\tconst configDir = resolveConfigDir(opts);\n\tconst configFile = opts.configFile ?? join(configDir, \"lovely.json\");\n\tlet raw = {};\n\tif (existsSync(configFile)) {\n\t\tconst content = readFileSync(configFile, \"utf8\");\n\t\ttry {\n\t\t\traw = JSON.parse(content);\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Failed to parse config file ${configFile}: ${err.message}`);\n\t\t}\n\t}\n\treturn LovelyConfigSchema.parse(raw);\n}\n\n//#endregion\n//#region src/events/bus.ts\nfunction createEventBus() {\n\tconst handlers = /* @__PURE__ */ new Map();\n\tconst anyHandlers = /* @__PURE__ */ new Set();\n\treturn {\n\t\ton(event, handler) {\n\t\t\tif (!handlers.has(event)) handlers.set(event, /* @__PURE__ */ new Set());\n\t\t\thandlers.get(event).add(handler);\n\t\t\treturn () => {\n\t\t\t\thandlers.get(event)?.delete(handler);\n\t\t\t};\n\t\t},\n\t\tonAny(handler) {\n\t\t\tanyHandlers.add(handler);\n\t\t\treturn () => {\n\t\t\t\tanyHandlers.delete(handler);\n\t\t\t};\n\t\t},\n\t\temit(event, payload) {\n\t\t\thandlers.get(event)?.forEach((h) => h(payload));\n\t\t\tanyHandlers.forEach((h) => h({\n\t\t\t\tevent,\n\t\t\t\tpayload\n\t\t\t}));\n\t\t}\n\t};\n}\n\n//#endregion\n//#region src/protocol/frames.ts\nfunction serializeFrame(frame) {\n\treturn JSON.stringify(frame);\n}\nfunction parseFrame(raw) {\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\tif (typeof parsed !== \"object\" || parsed === null) return null;\n\t\tconst obj = parsed;\n\t\tif (obj[\"type\"] !== \"req\" && obj[\"type\"] !== \"res\" && obj[\"type\"] !== \"event\") return null;\n\t\treturn parsed;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n//#endregion\n//#region src/gateway/server.ts\nconst express = __require(\"express\");\nasync function createGatewayServer(opts) {\n\tconst { port, host = \"127.0.0.1\" } = opts;\n\tconst bus = opts.bus ?? createEventBus();\n\tconst app = express();\n\tapp.use(express.json());\n\tapp.get(\"/health\", (_req, res) => {\n\t\tres.json({\n\t\t\tok: true,\n\t\t\tversion: \"0.0.1\"\n\t\t});\n\t});\n\tconst httpServer = createServer(app);\n\tconst wss = new WebSocketServer({ server: httpServer });\n\tlet seq = 0;\n\twss.on(\"connection\", (ws) => {\n\t\tws.on(\"message\", (data) => {\n\t\t\tconst frame = parseFrame(data.toString());\n\t\t\tif (!frame || frame.type !== \"req\") return;\n\t\t\tws.send(serializeFrame({\n\t\t\t\ttype: \"res\",\n\t\t\t\tid: frame.id,\n\t\t\t\tok: true\n\t\t\t}));\n\t\t});\n\t});\n\tfunction broadcast(event, payload) {\n\t\tconst frame = serializeFrame({\n\t\t\ttype: \"event\",\n\t\t\tevent,\n\t\t\tpayload,\n\t\t\tseq: seq++\n\t\t});\n\t\tfor (const client of wss.clients) if (client.readyState === client.OPEN) client.send(frame);\n\t}\n\tawait new Promise((resolve, reject) => {\n\t\thttpServer.once(\"error\", reject);\n\t\thttpServer.listen(port, host, () => {\n\t\t\thttpServer.off(\"error\", reject);\n\t\t\tresolve();\n\t\t});\n\t});\n\treturn {\n\t\tport,\n\t\tbus,\n\t\tbroadcast,\n\t\tstop: () => new Promise((resolve, reject) => {\n\t\t\twss.close((wsErr) => {\n\t\t\t\tif (wsErr) {\n\t\t\t\t\treject(wsErr);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\thttpServer.close((err) => err ? reject(err) : resolve());\n\t\t\t});\n\t\t})\n\t};\n}\n\n//#endregion\n//#region src/dispatch.ts\nfunction createDispatcher(opts) {\n\tconst gate = createPrivacyGate(opts.privacy);\n\tcreateHITLEngine(opts.hitl);\n\tconst runner = createAgentRunner({\n\t\tllm: opts.llm,\n\t\tsessionStoreDir: opts.sessionStoreDir,\n\t\tsystemPrompt: opts.systemPrompt ?? \"You are Lovely, a helpful personal AI assistant.\"\n\t});\n\treturn { async dispatch(ctx) {\n\t\tconst providerName = opts.llm.provider ?? opts.llm.id.split(\":\")[0] ?? \"local\";\n\t\tconst decision = gate.enforce(ctx, {\n\t\t\tprovider: providerName,\n\t\t\tmodel: opts.llm.id\n\t\t});\n\t\tif (!decision.allow) {\n\t\t\tawait opts.onReply({\n\t\t\t\tto: ctx.from,\n\t\t\t\tchannel: ctx.channel,\n\t\t\t\ttext: `Message blocked by privacy policy: ${decision.reason ?? \"unknown reason\"}`\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst sessionKey = `${ctx.channel}:${ctx.from}`;\n\t\tlet fullResponse = \"\";\n\t\ttry {\n\t\t\tawait runner.run({\n\t\t\t\tsessionKey,\n\t\t\t\tuserMessage: ctx.text,\n\t\t\t\tonDelta: (delta) => {\n\t\t\t\t\tfullResponse += delta;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tawait opts.onReply({\n\t\t\t\tto: ctx.from,\n\t\t\t\tchannel: ctx.channel,\n\t\t\t\ttext: \"Sorry, something went wrong. Please try again.\"\n\t\t\t});\n\t\t\tthrow err;\n\t\t}\n\t\tawait opts.onReply({\n\t\t\tto: ctx.from,\n\t\t\tchannel: ctx.channel,\n\t\t\ttext: fullResponse\n\t\t});\n\t} };\n}\n\n//#endregion\n//#region src/plugins/loader.ts\nfunction createPluginRegistry() {\n\tconst plugins = [];\n\treturn {\n\t\tregister: (plugin) => plugins.push(plugin),\n\t\tgetAll: () => [...plugins],\n\t\tgetChannels: () => plugins.flatMap((p) => p.channels ?? [])\n\t};\n}\n\n//#endregion\nexport { GatewayConfigSchema, HitlConfigSchema, LLMConfigSchema, LovelyConfigSchema, PrivacyConfigSchema, createDispatcher, createEventBus, createGatewayServer, createPluginRegistry, defaultRuntime, loadConfig, parseFrame, resolveConfigDir, serializeFrame };\n//# sourceMappingURL=index.js.map","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { createGatewayServer, loadConfig } from '@lovely/core';\n\nexport function gatewayCommand(): Command {\n return new Command('gateway')\n .description('Start the Lovely gateway daemon')\n .option('-p, --port <port>', 'Port to listen on', '18900')\n .option('--verbose', 'Enable verbose logging')\n .action(async (opts: { port: string; verbose?: boolean }) => {\n const config = loadConfig();\n const port = parseInt(opts.port, 10);\n\n if (Number.isNaN(port) || port < 1 || port > 65535) {\n console.error(chalk.red(`Invalid port: ${String(opts.port)}`));\n process.exit(1);\n }\n\n const spinner = ora(`Starting Lovely gateway on port ${port}...`).start();\n\n try {\n const server = await createGatewayServer({ port, host: config.gateway.host });\n spinner.succeed(\n chalk.green(`Lovely gateway running on ${chalk.bold(`http://127.0.0.1:${port}`)}`),\n );\n console.log(chalk.dim(' Press Ctrl+C to stop'));\n\n const shutdown = async (): Promise<void> => {\n console.log('\\n' + chalk.yellow('Shutting down...'));\n await server.stop();\n process.exit(0);\n };\n\n process.on('SIGINT', () => { void shutdown(); });\n process.on('SIGTERM', () => { void shutdown(); });\n } catch (err) {\n spinner.fail(chalk.red(`Failed to start gateway: ${err}`));\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { confirm, input, select } from '@inquirer/prompts';\nimport { writeFileSync, mkdirSync, chmodSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execFileSync } from 'node:child_process';\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nexport function onboardCommand(): Command {\n return new Command('onboard')\n .description('Interactive setup wizard for Lovely')\n .option('--install-daemon', 'Install launchd daemon after setup')\n .action(async (opts: { installDaemon?: boolean }) => {\n console.log(chalk.bold.magenta('\\nWelcome to Lovely setup\\n'));\n\n const configDir = join(homedir(), '.lovely');\n mkdirSync(configDir, { recursive: true });\n\n // Step 1: LLM provider\n const provider = await select({\n message: 'Which AI provider do you want to use?',\n choices: [\n { name: 'Anthropic (Claude) — recommended', value: 'anthropic' },\n { name: 'Ollama (local, privacy-first)', value: 'ollama' },\n { name: 'OpenAI', value: 'openai' },\n { name: 'Skip for now', value: 'skip' },\n ],\n });\n\n let apiKey = '';\n let model = '';\n\n if (provider === 'anthropic') {\n apiKey = await input({\n message: 'Anthropic API key:',\n validate: (v) => v.startsWith('sk-') || 'Must start with sk-',\n });\n model = 'claude-sonnet-4-6';\n } else if (provider === 'openai') {\n apiKey = await input({\n message: 'OpenAI API key:',\n validate: (v) => v.startsWith('sk-') || 'Must start with sk-',\n });\n model = 'gpt-4o';\n } else if (provider === 'ollama') {\n model = await input({ message: 'Ollama model name:', default: 'llama3.2' });\n }\n\n // Step 2: Privacy policy\n const privacy = await select({\n message: 'Default privacy policy:',\n choices: [\n { name: 'Local-first (cloud only if explicitly allowed)', value: 'local-first' },\n { name: 'Local-only (never send to cloud)', value: 'local-only' },\n { name: 'Cloud-allowed (use cloud freely)', value: 'cloud-allowed' },\n ],\n });\n\n // Step 3: iMessage\n const enableIMessage = await confirm({ message: 'Enable iMessage channel?', default: true });\n\n // Write config\n const config = {\n gateway: { port: 18900 },\n privacy: {\n default: privacy,\n cloudAllowed: privacy !== 'local-only' && provider !== 'skip' ? [provider] : [],\n },\n hitl: { enabled: true },\n llm: {\n primary: { provider, model },\n providers:\n provider !== 'ollama' && provider !== 'skip'\n ? { [provider]: { apiKey, type: provider } }\n : {},\n },\n channels: {\n imessage: { enabled: enableIMessage },\n },\n };\n\n const configFilePath = join(configDir, 'lovely.json');\n writeFileSync(configFilePath, JSON.stringify(config, null, 2), { mode: 0o600 });\n chmodSync(configFilePath, 0o600);\n console.log(chalk.green(`\\n✓ Config written to ${configDir}/lovely.json (permissions: 600)`));\n\n if (opts.installDaemon === true) {\n installLaunchdDaemon();\n }\n\n console.log(chalk.bold('\\nSetup complete! Run: ') + chalk.cyan('lovely gateway') + '\\n');\n });\n}\n\nfunction installLaunchdDaemon(): void {\n if (process.platform !== 'darwin') {\n console.error(chalk.red('--install-daemon is only supported on macOS'));\n process.exit(1);\n }\n\n const binPath = process.argv[1] ?? 'lovely';\n\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>ai.lovely.gateway</string>\n <key>ProgramArguments</key>\n <array>\n <string>${escapeXml(process.execPath)}</string>\n <string>${escapeXml(binPath)}</string>\n <string>gateway</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>${homedir()}/.lovely/logs/gateway.log</string>\n <key>StandardErrorPath</key>\n <string>${homedir()}/.lovely/logs/gateway.error.log</string>\n</dict>\n</plist>`;\n\n const launchAgentsDir = join(homedir(), 'Library', 'LaunchAgents');\n mkdirSync(launchAgentsDir, { recursive: true });\n mkdirSync(join(homedir(), '.lovely', 'logs'), { recursive: true });\n\n const plistPath = join(launchAgentsDir, 'ai.lovely.gateway.plist');\n writeFileSync(plistPath, plist);\n\n execFileSync('launchctl', ['load', plistPath]);\n console.log(chalk.green('Launchd daemon installed — Lovely will start automatically on login'));\n}\n","import { Command } from 'commander';\nimport { gatewayCommand } from './commands/gateway.js';\nimport { onboardCommand } from './commands/onboard.js';\n\nconst program = new Command();\n\nprogram\n .name('lovely')\n .description('Lovely — your personal AGI. Runs on your hardware.')\n .version(process.env['npm_package_version'] ?? '0.0.1');\n\nprogram.addCommand(gatewayCommand());\nprogram.addCommand(onboardCommand());\n\nprogram.parse(process.argv);\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lovelyai",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"lovely": "./dist/bin/lovely.js",
|
|
7
|
+
"lovelyai": "./dist/bin/lovely.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/src/index.js",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./dist/src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public",
|
|
19
|
+
"registry": "https://registry.npmjs.org"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@anthropic-ai/sdk": "^0.78.0",
|
|
23
|
+
"@grammyjs/runner": "^2.0.3",
|
|
24
|
+
"@inquirer/prompts": "^7.10.1",
|
|
25
|
+
"@sinclair/typebox": "^0.33.0",
|
|
26
|
+
"@whiskeysockets/baileys": "^6.17.16",
|
|
27
|
+
"better-sqlite3": "^12.0.0",
|
|
28
|
+
"chalk": "^5.6.2",
|
|
29
|
+
"commander": "^12.1.0",
|
|
30
|
+
"express": "^5.0.0",
|
|
31
|
+
"grammy": "^1.40.0",
|
|
32
|
+
"openai": "^6.22.0",
|
|
33
|
+
"ora": "^8.2.0",
|
|
34
|
+
"sqlite-vec": "^0.1.6",
|
|
35
|
+
"ws": "^8.18.0",
|
|
36
|
+
"zod": "^3.22.0"
|
|
37
|
+
},
|
|
38
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsdown --config tsdown.config.ts",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"typecheck": "tsc --noEmit"
|
|
43
|
+
}
|
|
44
|
+
}
|