@garuda-agent/garuda 0.0.1 → 0.15.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +4 -0
  4. package/README.md +1097 -0
  5. package/SECURITY.md +32 -0
  6. package/dist/acpCommand-FZ2P5JFO.js +153 -0
  7. package/dist/anthropic-NQDBCHJU.js +327 -0
  8. package/dist/chunk-23FXBNBB.js +46 -0
  9. package/dist/chunk-2S62ZNTC.js +320 -0
  10. package/dist/chunk-2TAXSFWN.js +49 -0
  11. package/dist/chunk-36GQIVGT.js +526 -0
  12. package/dist/chunk-3CEPHS4C.js +231 -0
  13. package/dist/chunk-3NJNVZTK.js +123 -0
  14. package/dist/chunk-42DSA4EA.js +116 -0
  15. package/dist/chunk-4JSUUDFQ.js +118 -0
  16. package/dist/chunk-4P26OKTP.js +100 -0
  17. package/dist/chunk-5DEWP3YX.js +139 -0
  18. package/dist/chunk-A2QAIRQL.js +45 -0
  19. package/dist/chunk-ATW7BNIG.js +31 -0
  20. package/dist/chunk-B25VL4RU.js +242 -0
  21. package/dist/chunk-EPKWDCV4.js +9 -0
  22. package/dist/chunk-EU7PA45O.js +324 -0
  23. package/dist/chunk-FARS4R67.js +206 -0
  24. package/dist/chunk-G2AX7MGS.js +36 -0
  25. package/dist/chunk-HRGX53VC.js +173 -0
  26. package/dist/chunk-HUIK3WXO.js +234 -0
  27. package/dist/chunk-INRZR772.js +73 -0
  28. package/dist/chunk-K3SIUOAG.js +138 -0
  29. package/dist/chunk-K7KK7U44.js +9358 -0
  30. package/dist/chunk-KKB5W47S.js +231 -0
  31. package/dist/chunk-N4I6YS3E.js +73 -0
  32. package/dist/chunk-NXJ4XLB5.js +19 -0
  33. package/dist/chunk-OUCV3FCT.js +205 -0
  34. package/dist/chunk-PQNT34LY.js +1247 -0
  35. package/dist/chunk-PZS3V6P3.js +46 -0
  36. package/dist/chunk-S77XDSD4.js +157 -0
  37. package/dist/chunk-SI2QJYCR.js +1341 -0
  38. package/dist/chunk-WMOLXTBU.js +61 -0
  39. package/dist/chunk-YFQJXRIJ.js +193 -0
  40. package/dist/chunk-YQTGMCU6.js +111 -0
  41. package/dist/chunk-ZAE25JM2.js +158 -0
  42. package/dist/cli/index.js +1203 -0
  43. package/dist/create-N4I7TIZE.js +223 -0
  44. package/dist/deadline-F5RJJ2QW.js +86 -0
  45. package/dist/detect-LARDSLLZ.js +10 -0
  46. package/dist/evalCommand-3SSFMZQD.js +2798 -0
  47. package/dist/export-HN3CT7AV.js +158 -0
  48. package/dist/inkChat-34BTFG2K.js +1193 -0
  49. package/dist/install-VRPBZY5H.js +17 -0
  50. package/dist/job-3NYDMP2M.js +31 -0
  51. package/dist/jobCommand-XJ5GULS5.js +30 -0
  52. package/dist/launchd-QVHQ3VNN.js +40 -0
  53. package/dist/lspCommand-XNTBHXLA.js +99 -0
  54. package/dist/manager-4PMSXT47.js +14 -0
  55. package/dist/manager-CSI76AWF.js +847 -0
  56. package/dist/nightCommand-CR6ZHYGP.js +247 -0
  57. package/dist/oauth-W6OK6XXO.js +23 -0
  58. package/dist/openaiCompatible-CJWVJP5M.js +501 -0
  59. package/dist/policy-EJPLEEXP.js +31 -0
  60. package/dist/proxy-XJAHCZB2.js +192 -0
  61. package/dist/remove-LE7Q7K46.js +59 -0
  62. package/dist/run-ML6GSPN4.js +888 -0
  63. package/dist/server-R3GNIC33.js +676 -0
  64. package/dist/servers-6YDGWOZ6.js +24 -0
  65. package/dist/text-J2GD647J.js +11 -0
  66. package/package.json +84 -3
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/mcp/trust.ts
4
+ import { randomBytes } from "crypto";
5
+ import { mkdir, readFile, rename, writeFile } from "fs/promises";
6
+ import { homedir } from "os";
7
+ import { dirname, join } from "path";
8
+ import { z } from "zod";
9
+ var TRUST_FILE = join(".garuda", "trust.json");
10
+ var entry = z.object({
11
+ def: z.string().optional(),
12
+ tools: z.string().optional(),
13
+ /** A hash per tool name, to say which tools changed. */
14
+ toolHashes: z.record(z.string(), z.string()).optional()
15
+ });
16
+ var schema = z.object({
17
+ version: z.literal(1),
18
+ mcp: z.record(z.string(), z.record(z.string(), entry)).default({}),
19
+ /** Project root → hash of the approved project hooks. */
20
+ hooks: z.record(z.string(), z.string()).default({}),
21
+ /** Project root → command name → hash of the approved command file (0.4). */
22
+ commands: z.record(z.string(), z.record(z.string(), z.string())).default({}),
23
+ /** Project root → skill name → hash of the approved SKILL.md (0.5). */
24
+ skills: z.record(z.string(), z.record(z.string(), z.string())).default({}),
25
+ /** Project root → agent name → hash of the approved agent file (0.5). */
26
+ agents: z.record(z.string(), z.record(z.string(), z.string())).default({}),
27
+ /** Project root → hash of the approved network allowlist (0.13). */
28
+ network: z.record(z.string(), z.string()).default({}),
29
+ /** Project root → language plugin name → hash of the approved plugin file (0.16). */
30
+ languages: z.record(z.string(), z.record(z.string(), z.string())).default({}),
31
+ /** Project root → hash of the approved settings parts that loosen safety (review, 2026-10). */
32
+ settings: z.record(z.string(), z.string()).default({})
33
+ });
34
+ var USER_SCOPE = "~";
35
+ var TrustStore = class _TrustStore {
36
+ constructor(file) {
37
+ this.file = file;
38
+ }
39
+ file;
40
+ data = {
41
+ version: 1,
42
+ mcp: {},
43
+ hooks: {},
44
+ commands: {},
45
+ skills: {},
46
+ agents: {},
47
+ network: {},
48
+ languages: {},
49
+ settings: {}
50
+ };
51
+ static async open(home = homedir()) {
52
+ const store = new _TrustStore(join(home, TRUST_FILE));
53
+ try {
54
+ const parsed = schema.safeParse(JSON.parse(await readFile(store.file, "utf8")));
55
+ if (parsed.success) store.data = parsed.data;
56
+ } catch {
57
+ }
58
+ return store;
59
+ }
60
+ get(scope, server) {
61
+ return this.data.mcp[scope]?.[server] ?? {};
62
+ }
63
+ hooksHash(root) {
64
+ return this.data.hooks[root];
65
+ }
66
+ async setHooksHash(root, hash) {
67
+ this.data.hooks[root] = hash;
68
+ await this.save();
69
+ }
70
+ commandHash(root, name) {
71
+ return this.data.commands[root]?.[name];
72
+ }
73
+ async setCommandHash(root, name, hash) {
74
+ const commands = this.data.commands[root] ?? {};
75
+ this.data.commands[root] = commands;
76
+ commands[name] = hash;
77
+ await this.save();
78
+ }
79
+ skillHash(root, name) {
80
+ return this.data.skills[root]?.[name];
81
+ }
82
+ async setSkillHash(root, name, hash) {
83
+ const skills = this.data.skills[root] ?? {};
84
+ this.data.skills[root] = skills;
85
+ skills[name] = hash;
86
+ await this.save();
87
+ }
88
+ agentHash(root, name) {
89
+ return this.data.agents[root]?.[name];
90
+ }
91
+ async setAgentHash(root, name, hash) {
92
+ const agents = this.data.agents[root] ?? {};
93
+ this.data.agents[root] = agents;
94
+ agents[name] = hash;
95
+ await this.save();
96
+ }
97
+ networkHash(root) {
98
+ return this.data.network[root];
99
+ }
100
+ async setNetworkHash(root, hash) {
101
+ this.data.network[root] = hash;
102
+ await this.save();
103
+ }
104
+ settingsHash(root) {
105
+ return this.data.settings[root];
106
+ }
107
+ async setSettingsHash(root, hash) {
108
+ this.data.settings[root] = hash;
109
+ await this.save();
110
+ }
111
+ languageHash(root, name) {
112
+ return this.data.languages[root]?.[name];
113
+ }
114
+ async setLanguageHash(root, name, hash) {
115
+ const languages = this.data.languages[root] ?? {};
116
+ this.data.languages[root] = languages;
117
+ languages[name] = hash;
118
+ await this.save();
119
+ }
120
+ async set(scope, server, value) {
121
+ const servers = this.data.mcp[scope] ?? {};
122
+ this.data.mcp[scope] = servers;
123
+ servers[server] = { ...servers[server], ...value };
124
+ await this.save();
125
+ }
126
+ async save() {
127
+ await mkdir(dirname(this.file), { recursive: true, mode: 448 });
128
+ const temp = `${this.file}.${randomBytes(4).toString("hex")}.tmp`;
129
+ await writeFile(temp, `${JSON.stringify(this.data, null, 2)}
130
+ `, { mode: 384, flag: "wx" });
131
+ await rename(temp, this.file);
132
+ }
133
+ };
134
+
135
+ export {
136
+ USER_SCOPE,
137
+ TrustStore
138
+ };
139
+ //# sourceMappingURL=chunk-5DEWP3YX.js.map
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/model/serverTools.ts
4
+ function serverCallText(call) {
5
+ const input = call.input ?? {};
6
+ return typeof input.query === "string" ? input.query : JSON.stringify(call.input);
7
+ }
8
+ function serverResultSummary(result) {
9
+ if (result === void 0) return "runs with the next request";
10
+ if (result.error !== void 0) return `error ${result.error}`;
11
+ const n = result.results.length;
12
+ return n === 0 ? "no results" : `${n} result${n === 1 ? "" : "s"}`;
13
+ }
14
+ function serverPairText(call, result) {
15
+ const head = `[Earlier ${result.name}${call === void 0 ? "" : ` "${serverCallText(call)}"`}: ${serverResultSummary(result)}]`;
16
+ return [head, ...result.results.map((r, i) => `${i + 1}. ${r.title} \u2014 ${r.url}`)].join("\n");
17
+ }
18
+ function withoutServerBlocks(content) {
19
+ const calls = /* @__PURE__ */ new Map();
20
+ for (const block of content) if (block.type === "server_tool_use") calls.set(block.id, block);
21
+ const out = [];
22
+ for (const block of content) {
23
+ if (block.type === "server_tool_use") continue;
24
+ if (block.type === "server_tool_result") {
25
+ out.push({ type: "text", text: serverPairText(calls.get(block.toolUseId), block) });
26
+ } else if (block.type === "text" && block.citations !== void 0) {
27
+ out.push({ type: "text", text: block.text });
28
+ } else out.push(block);
29
+ }
30
+ return out;
31
+ }
32
+ function hasServerBlocks(content) {
33
+ return content.some(
34
+ (b) => b.type === "server_tool_use" || b.type === "server_tool_result" || b.type === "text" && b.citations !== void 0
35
+ );
36
+ }
37
+
38
+ export {
39
+ serverCallText,
40
+ serverResultSummary,
41
+ serverPairText,
42
+ withoutServerBlocks,
43
+ hasServerBlocks
44
+ };
45
+ //# sourceMappingURL=chunk-A2QAIRQL.js.map
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/net/address.ts
4
+ import ipaddr from "ipaddr.js";
5
+ function checkAddress(address, allowLocalhost) {
6
+ let parsed;
7
+ try {
8
+ parsed = ipaddr.process(address);
9
+ } catch {
10
+ return { ok: false, range: "invalid" };
11
+ }
12
+ const range = parsed.range();
13
+ if (range === "unicast") return { ok: true };
14
+ if (range === "loopback" && allowLocalhost) return { ok: true };
15
+ return { ok: false, range };
16
+ }
17
+ function isIpLiteral(host) {
18
+ return ipaddr.isValid(host.replace(/^\[|\]$/g, ""));
19
+ }
20
+ function isLoopbackHost(host) {
21
+ const bare = host.replace(/^\[|\]$/g, "");
22
+ if (bare === "localhost") return true;
23
+ return ipaddr.isValid(bare) && ipaddr.process(bare).range() === "loopback";
24
+ }
25
+
26
+ export {
27
+ checkAddress,
28
+ isIpLiteral,
29
+ isLoopbackHost
30
+ };
31
+ //# sourceMappingURL=chunk-ATW7BNIG.js.map
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ isLoopbackHost
4
+ } from "./chunk-ATW7BNIG.js";
5
+
6
+ // src/web/search.ts
7
+ import { mkdir, readFile, writeFile } from "fs/promises";
8
+ import { homedir } from "os";
9
+ import { dirname, join } from "path";
10
+ import { z } from "zod";
11
+ var SEARCH_FILE = join(".garuda", "search.json");
12
+ var SEARCH_TIMEOUT_MS = 2e4;
13
+ var SEARCH_MAX_BYTES = 2 * 1024 * 1024;
14
+ var DEFAULT_RESULTS = 5;
15
+ var MAX_RESULTS = 10;
16
+ var SEARCH_USES = ["claude", "provider", "off"];
17
+ var DEFAULT_CLAUDE_MAX_USES = 5;
18
+ var domains = z.array(
19
+ z.string().min(1).regex(/^[^\s:/][^\s:]*$/, "a bare domain, with an optional path (no scheme)")
20
+ );
21
+ var claudeSchema = z.strictObject({
22
+ /** Searches per model request, 1–20. Default 5. */
23
+ maxUses: z.number().int().min(1).max(20).optional(),
24
+ allowedDomains: domains.optional(),
25
+ blockedDomains: domains.optional()
26
+ }).refine((c) => c.allowedDomains === void 0 || c.blockedDomains === void 0, {
27
+ message: "use allowedDomains or blockedDomains, not both"
28
+ });
29
+ var fileSchema = z.strictObject({
30
+ /** The user's choice (0.14); absent: the chat asks once and saves the answer. */
31
+ use: z.enum(SEARCH_USES).optional(),
32
+ provider: z.enum(["brave", "tavily", "searxng"]).optional(),
33
+ /** Claude's own web search (0.6). */
34
+ claude: claudeSchema.optional(),
35
+ /** SearXNG only: the server's base URL. */
36
+ url: z.string().optional(),
37
+ /** The environment variable with the key. Default: BRAVE_API_KEY or TAVILY_API_KEY. */
38
+ apiKeyEnv: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).optional(),
39
+ /** Results per search, 1–10. Default 5. */
40
+ maxResults: z.number().int().min(1).max(MAX_RESULTS).optional()
41
+ });
42
+ var LABELS = {
43
+ brave: "Brave Search",
44
+ tavily: "Tavily",
45
+ searxng: "SearXNG"
46
+ };
47
+ function providerLabel(config) {
48
+ return `${LABELS[config.provider]} (${config.endpoint.host})`;
49
+ }
50
+ async function loadSearchConfig(home = homedir(), env = process.env) {
51
+ const file = join(home, SEARCH_FILE);
52
+ let text;
53
+ try {
54
+ text = await readFile(file, "utf8");
55
+ } catch (error) {
56
+ if (error.code !== "ENOENT") {
57
+ return { problem: `${file}: ${error.message}` };
58
+ }
59
+ }
60
+ if (text === void 0) return fromEnv(env, DEFAULT_RESULTS);
61
+ let parsed;
62
+ try {
63
+ const result = fileSchema.safeParse(JSON.parse(text));
64
+ if (!result.success) return { problem: `${file}: ${z.prettifyError(result.error)}` };
65
+ parsed = result.data;
66
+ } catch (error) {
67
+ return { problem: `${file}: invalid JSON: ${error.message}` };
68
+ }
69
+ const max = parsed.maxResults ?? DEFAULT_RESULTS;
70
+ const use = parsed.use === void 0 ? {} : { use: parsed.use };
71
+ const claude = parsed.claude === void 0 ? {} : {
72
+ claude: {
73
+ maxUses: parsed.claude.maxUses ?? DEFAULT_CLAUDE_MAX_USES,
74
+ ...parsed.claude.allowedDomains === void 0 ? {} : { allowedDomains: parsed.claude.allowedDomains },
75
+ ...parsed.claude.blockedDomains === void 0 ? {} : { blockedDomains: parsed.claude.blockedDomains }
76
+ }
77
+ };
78
+ if (parsed.provider === void 0) {
79
+ if (parsed.claude === void 0 && parsed.use === void 0) {
80
+ return { problem: `${file}: name a "provider", or add a "claude" section.` };
81
+ }
82
+ return { ...fromEnv(env, max), ...claude, ...use };
83
+ }
84
+ const client = clientConfig(file, { ...parsed, provider: parsed.provider }, env, max);
85
+ return "problem" in client ? { ...client, ...claude, ...use } : { config: client.config, ...claude, ...use };
86
+ }
87
+ async function saveSearchUse(home, use) {
88
+ const file = join(home, SEARCH_FILE);
89
+ let data = {};
90
+ try {
91
+ data = JSON.parse(await readFile(file, "utf8"));
92
+ } catch (error) {
93
+ if (error.code !== "ENOENT") throw error;
94
+ }
95
+ await mkdir(dirname(file), { recursive: true });
96
+ await writeFile(file, `${JSON.stringify({ ...data, use }, null, 2)}
97
+ `, { mode: 384 });
98
+ return file;
99
+ }
100
+ function fromEnv(env, max) {
101
+ if (env.BRAVE_API_KEY) return { config: brave(env.BRAVE_API_KEY, max) };
102
+ if (env.TAVILY_API_KEY) return { config: tavily(env.TAVILY_API_KEY, max) };
103
+ return {};
104
+ }
105
+ function clientConfig(file, parsed, env, max) {
106
+ if (parsed.provider === "searxng") {
107
+ if (parsed.url === void 0) return { problem: `${file}: "searxng" needs a "url".` };
108
+ const endpoint = searxngEndpoint(parsed.url);
109
+ if (typeof endpoint === "string") return { problem: `${file}: ${endpoint}` };
110
+ return { config: { provider: "searxng", endpoint, maxResults: max } };
111
+ }
112
+ const variable = parsed.apiKeyEnv ?? (parsed.provider === "brave" ? "BRAVE_API_KEY" : "TAVILY_API_KEY");
113
+ const key = env[variable];
114
+ if (!key) return { problem: `${file}: web search needs the key in ${variable}; it is not set.` };
115
+ return { config: parsed.provider === "brave" ? brave(key, max) : tavily(key, max) };
116
+ }
117
+ function brave(apiKey, maxResults) {
118
+ return {
119
+ provider: "brave",
120
+ endpoint: new URL("https://api.search.brave.com/res/v1/web/search"),
121
+ apiKey,
122
+ maxResults
123
+ };
124
+ }
125
+ function tavily(apiKey, maxResults) {
126
+ return {
127
+ provider: "tavily",
128
+ endpoint: new URL("https://api.tavily.com/search"),
129
+ apiKey,
130
+ maxResults
131
+ };
132
+ }
133
+ function searxngEndpoint(raw) {
134
+ let url;
135
+ try {
136
+ url = new URL(raw);
137
+ } catch {
138
+ return `"${raw}" is not a valid URL.`;
139
+ }
140
+ if (url.username !== "" || url.password !== "")
141
+ return "a URL with a user name or password is not allowed.";
142
+ const local = isLoopbackHost(url.hostname.replace(/^\[|\]$/g, ""));
143
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && local)) {
144
+ return "use https (http only for localhost).";
145
+ }
146
+ return new URL(`${url.pathname.replace(/\/+$/, "")}/search`, url);
147
+ }
148
+ async function search(config, query, maxResults, signal, fetchFn = fetch) {
149
+ const count = Math.min(Math.max(1, maxResults), MAX_RESULTS);
150
+ const timeout = AbortSignal.any([signal, AbortSignal.timeout(SEARCH_TIMEOUT_MS)]);
151
+ let request;
152
+ if (config.provider === "brave") {
153
+ const url = new URL(config.endpoint);
154
+ url.searchParams.set("q", query);
155
+ url.searchParams.set("count", String(count));
156
+ request = new Request(url, {
157
+ headers: { accept: "application/json", "x-subscription-token": config.apiKey ?? "" }
158
+ });
159
+ } else if (config.provider === "tavily") {
160
+ request = new Request(config.endpoint, {
161
+ method: "POST",
162
+ headers: {
163
+ "content-type": "application/json",
164
+ authorization: `Bearer ${config.apiKey ?? ""}`
165
+ },
166
+ body: JSON.stringify({ query, max_results: count, search_depth: "basic" })
167
+ });
168
+ } else {
169
+ const url = new URL(config.endpoint);
170
+ url.searchParams.set("q", query);
171
+ url.searchParams.set("format", "json");
172
+ request = new Request(url, { headers: { accept: "application/json" } });
173
+ }
174
+ let response;
175
+ try {
176
+ response = await fetchFn(request, { signal: timeout, redirect: "error" });
177
+ } catch (error) {
178
+ if (signal.aborted) throw error;
179
+ throw new Error(`${LABELS[config.provider]} did not answer: ${error.message}`);
180
+ }
181
+ if (!response.ok) {
182
+ const hint = response.status === 401 || response.status === 403 ? " Check the API key." : response.status === 429 ? " Too many searches; wait, or check your plan." : "";
183
+ throw new Error(`${LABELS[config.provider]} answered ${response.status}.${hint}`);
184
+ }
185
+ const text = await readCapped(response, SEARCH_MAX_BYTES);
186
+ let json;
187
+ try {
188
+ json = JSON.parse(text);
189
+ } catch {
190
+ throw new Error(
191
+ `${LABELS[config.provider]} did not answer with JSON.${config.provider === "searxng" ? ' Turn on the "json" format in its settings.yml (search.formats).' : ""}`
192
+ );
193
+ }
194
+ return parseResults(config.provider, json).slice(0, count);
195
+ }
196
+ function parseResults(provider, json) {
197
+ const obj = (v) => v !== null && typeof v === "object" ? v : {};
198
+ const str = (v) => typeof v === "string" ? v : "";
199
+ const list = provider === "brave" ? obj(obj(json).web).results : obj(json).results;
200
+ if (!Array.isArray(list)) return [];
201
+ const out = [];
202
+ for (const item of list) {
203
+ const r = obj(item);
204
+ const url = str(r.url);
205
+ if (!/^https?:\/\//.test(url)) continue;
206
+ const snippet = provider === "brave" ? str(r.description) : str(r.content);
207
+ const age = provider === "brave" ? str(r.age) : str(r.publishedDate);
208
+ out.push({
209
+ title: str(r.title),
210
+ url,
211
+ snippet,
212
+ ...age === "" ? {} : { age }
213
+ });
214
+ }
215
+ return out;
216
+ }
217
+ async function readCapped(response, max) {
218
+ const reader = response.body?.getReader();
219
+ if (reader === void 0) return "";
220
+ const chunks = [];
221
+ let size = 0;
222
+ for (; ; ) {
223
+ const { done, value } = await reader.read();
224
+ if (done) break;
225
+ size += value.byteLength;
226
+ if (size > max) {
227
+ await reader.cancel();
228
+ throw new Error(`The search answer is larger than ${max} bytes.`);
229
+ }
230
+ chunks.push(value);
231
+ }
232
+ return Buffer.concat(chunks).toString("utf8");
233
+ }
234
+
235
+ export {
236
+ MAX_RESULTS,
237
+ providerLabel,
238
+ loadSearchConfig,
239
+ saveSearchUse,
240
+ search
241
+ };
242
+ //# sourceMappingURL=chunk-B25VL4RU.js.map
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/version.ts
4
+ var VERSION = "0.15.0";
5
+
6
+ export {
7
+ VERSION
8
+ };
9
+ //# sourceMappingURL=chunk-EPKWDCV4.js.map