va-claw 0.1.0 → 0.1.2

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.
@@ -0,0 +1,2816 @@
1
+ #!/usr/bin/env node
2
+
3
+ // packages/cli/dist/deps.js
4
+ import { spawnSync as spawnSync4 } from "node:child_process";
5
+ import { readFile as readFile4 } from "node:fs/promises";
6
+ import { createInterface as createInterface2 } from "node:readline/promises";
7
+
8
+ // packages/identity/dist/path.js
9
+ import { homedir } from "node:os";
10
+ import { resolve } from "node:path";
11
+ var DEFAULT_CONFIG_PATH = resolve(homedir(), ".va-claw", "config.json");
12
+ function resolveConfigPath(configPath) {
13
+ if (!configPath || configPath.trim() === "") {
14
+ return DEFAULT_CONFIG_PATH;
15
+ }
16
+ if (configPath === "~") {
17
+ return homedir();
18
+ }
19
+ if (configPath.startsWith("~/")) {
20
+ return resolve(homedir(), configPath.slice(2));
21
+ }
22
+ return resolve(configPath);
23
+ }
24
+
25
+ // packages/identity/dist/storage.js
26
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
27
+ import { dirname } from "node:path";
28
+
29
+ // packages/identity/dist/defaults.js
30
+ var DEFAULT_LOOP_INTERVAL = "0 * * * *";
31
+ var DEFAULT_CONFIG = {
32
+ name: "va-claw",
33
+ persona: "A pragmatic CLI identity that values clarity, rigor, and continuity.",
34
+ systemPrompt: "You are va-claw. Be direct, honest about uncertainty, and keep actions aligned with the saved identity.",
35
+ wakePrompt: "Wake up, load the saved identity, and continue from the most recent remembered state.",
36
+ loopInterval: DEFAULT_LOOP_INTERVAL,
37
+ channels: {
38
+ discord: {
39
+ token: "",
40
+ clientId: "",
41
+ cliCommand: "",
42
+ autoStart: false
43
+ },
44
+ telegram: {
45
+ token: "",
46
+ cliCommand: ""
47
+ },
48
+ slack: {
49
+ botToken: "",
50
+ appToken: "",
51
+ cliCommand: ""
52
+ }
53
+ }
54
+ };
55
+ function pickString(value, fallback) {
56
+ return typeof value === "string" ? value : fallback;
57
+ }
58
+ function pickBoolean(value, fallback) {
59
+ return typeof value === "boolean" ? value : fallback;
60
+ }
61
+ function getDefaultIdentity() {
62
+ return { ...DEFAULT_CONFIG };
63
+ }
64
+ function normalizeConfig(input) {
65
+ const base = getDefaultIdentity();
66
+ const data = input && typeof input === "object" ? input : {};
67
+ const channels = readObject(Reflect.get(data, "channels"));
68
+ const discord = readObject(Reflect.get(channels, "discord"));
69
+ const telegram = readObject(Reflect.get(channels, "telegram"));
70
+ const slack = readObject(Reflect.get(channels, "slack"));
71
+ return {
72
+ name: pickString(Reflect.get(data, "name"), base.name),
73
+ persona: pickString(Reflect.get(data, "persona"), base.persona),
74
+ systemPrompt: pickString(Reflect.get(data, "systemPrompt"), base.systemPrompt),
75
+ wakePrompt: pickString(Reflect.get(data, "wakePrompt"), base.wakePrompt),
76
+ loopInterval: pickString(Reflect.get(data, "loopInterval"), base.loopInterval),
77
+ channels: {
78
+ discord: {
79
+ token: pickString(Reflect.get(discord, "token"), base.channels.discord.token),
80
+ clientId: pickString(Reflect.get(discord, "clientId"), base.channels.discord.clientId),
81
+ cliCommand: pickString(Reflect.get(discord, "cliCommand"), base.channels.discord.cliCommand),
82
+ autoStart: pickBoolean(Reflect.get(discord, "autoStart"), base.channels.discord.autoStart)
83
+ },
84
+ telegram: {
85
+ token: pickString(Reflect.get(telegram, "token"), base.channels.telegram.token),
86
+ cliCommand: pickString(Reflect.get(telegram, "cliCommand"), base.channels.telegram.cliCommand)
87
+ },
88
+ slack: {
89
+ botToken: pickString(Reflect.get(slack, "botToken"), base.channels.slack.botToken),
90
+ appToken: pickString(Reflect.get(slack, "appToken"), base.channels.slack.appToken),
91
+ cliCommand: pickString(Reflect.get(slack, "cliCommand"), base.channels.slack.cliCommand)
92
+ }
93
+ }
94
+ };
95
+ }
96
+ function readObject(value) {
97
+ return value && typeof value === "object" ? value : {};
98
+ }
99
+
100
+ // packages/identity/dist/storage.js
101
+ async function loadIdentity(configPath) {
102
+ const resolvedPath = resolveConfigPath(configPath);
103
+ try {
104
+ const raw = await readFile(resolvedPath, "utf8");
105
+ return normalizeConfig(JSON.parse(raw));
106
+ } catch (error) {
107
+ if (isMissingFileError(error)) {
108
+ return getDefaultIdentity();
109
+ }
110
+ throw error;
111
+ }
112
+ }
113
+ async function saveIdentity(config, configPath) {
114
+ const resolvedPath = resolveConfigPath(configPath);
115
+ const normalized = normalizeConfig(config);
116
+ await mkdir(dirname(resolvedPath), { recursive: true });
117
+ await writeFile(resolvedPath, `${JSON.stringify(normalized, null, 2)}
118
+ `, "utf8");
119
+ }
120
+ function isMissingFileError(error) {
121
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
122
+ }
123
+
124
+ // packages/identity/dist/render.js
125
+ function textBlock(label, value) {
126
+ return [label, "~~~text", value || "(empty)", "~~~"].join("\n");
127
+ }
128
+ function toClaudeMdSnippet(config) {
129
+ const normalized = normalizeConfig(config);
130
+ return [
131
+ "<!-- va-claw:identity:start -->",
132
+ "## VaClaw Identity",
133
+ `- Name: ${normalized.name}`,
134
+ "",
135
+ "Persona:",
136
+ normalized.persona,
137
+ "",
138
+ textBlock("System Prompt:", normalized.systemPrompt),
139
+ "<!-- va-claw:identity:end -->"
140
+ ].join("\n");
141
+ }
142
+ function toCodexSystemPrompt(config) {
143
+ const normalized = normalizeConfig(config);
144
+ return [
145
+ `Identity name: ${normalized.name}`,
146
+ `Persona: ${normalized.persona}`,
147
+ "",
148
+ "System prompt:",
149
+ normalized.systemPrompt,
150
+ "",
151
+ "Wake prompt:",
152
+ normalized.wakePrompt,
153
+ "",
154
+ `Loop interval: ${normalized.loopInterval}`
155
+ ].join("\n");
156
+ }
157
+
158
+ // node_modules/.pnpm/@clack+prompts@file+packages+identity+vendor+clack-prompts/node_modules/@clack/prompts/index.js
159
+ import { createInterface } from "node:readline/promises";
160
+ import { stdin, stdout } from "node:process";
161
+ var CANCEL = /* @__PURE__ */ Symbol("clack-cancel");
162
+ function intro(title = "") {
163
+ if (title) {
164
+ stdout.write(`
165
+ ${title}
166
+ `);
167
+ }
168
+ }
169
+ function note(message = "", title = "") {
170
+ const prefix = title ? `${title}: ` : "";
171
+ stdout.write(`${prefix}${message}
172
+ `);
173
+ }
174
+ function outro(message = "") {
175
+ if (message) {
176
+ stdout.write(`${message}
177
+ `);
178
+ }
179
+ }
180
+ function cancel(message = "") {
181
+ if (message) {
182
+ stdout.write(`${message}
183
+ `);
184
+ }
185
+ }
186
+ function isCancel(value) {
187
+ return value === CANCEL;
188
+ }
189
+ async function text({ message, initialValue = "", validate }) {
190
+ const rl = createInterface({ input: stdin, output: stdout });
191
+ while (true) {
192
+ const suffix = initialValue ? ` [${initialValue}]` : "";
193
+ const answer = await rl.question(`${message}${suffix}: `);
194
+ const value = answer === "" ? initialValue : answer;
195
+ if (value.toLowerCase() === ":cancel") {
196
+ rl.close();
197
+ return CANCEL;
198
+ }
199
+ const error = validate?.(value);
200
+ if (!error) {
201
+ rl.close();
202
+ return value;
203
+ }
204
+ const detail = error instanceof Error ? error.message : String(error);
205
+ stdout.write(`${detail}
206
+ `);
207
+ }
208
+ }
209
+
210
+ // packages/identity/dist/wizard.js
211
+ async function runInstallWizard() {
212
+ const current = normalizeConfig(await loadIdentity());
213
+ intro("va-claw identity setup");
214
+ note(DEFAULT_CONFIG_PATH, "Config path");
215
+ const config = normalizeConfig({
216
+ name: await ask("Name", current.name, true),
217
+ persona: await ask("Persona", current.persona, true),
218
+ systemPrompt: await ask("System prompt", current.systemPrompt, false),
219
+ wakePrompt: await ask("Wake prompt", current.wakePrompt, false),
220
+ loopInterval: await ask("Loop interval (cron)", current.loopInterval, true)
221
+ });
222
+ await saveIdentity(config);
223
+ outro(`Saved identity to ${DEFAULT_CONFIG_PATH}`);
224
+ return config;
225
+ }
226
+ async function ask(message, initialValue, required) {
227
+ const value = await text({
228
+ message,
229
+ initialValue,
230
+ validate(input) {
231
+ if (!required || input.trim() !== "") {
232
+ return void 0;
233
+ }
234
+ return `${message} is required.`;
235
+ }
236
+ });
237
+ if (isCancel(value)) {
238
+ cancel("Identity setup cancelled.");
239
+ throw new Error("Identity setup cancelled.");
240
+ }
241
+ return value;
242
+ }
243
+
244
+ // packages/daemon/dist/cli-adapter.js
245
+ import { spawnSync } from "node:child_process";
246
+ var DEFAULT_WARN = (message) => console.warn(message);
247
+ var CLI_CANDIDATES = ["claude-copilot", "claude", "codex"];
248
+ async function detectCliAdapter(deps = {}) {
249
+ const runWhich = deps.runWhich ?? whichCommandExists;
250
+ const configuredCommand = readEnv(deps.env).VA_CLAW_CLI?.trim();
251
+ if (configuredCommand) {
252
+ return toCliAdapter(configuredCommand, configuredCommand);
253
+ }
254
+ for (const name of CLI_CANDIDATES) {
255
+ const command = runWhich(name);
256
+ if (command) {
257
+ return toCliAdapter(name, command);
258
+ }
259
+ }
260
+ (deps.warn ?? DEFAULT_WARN)("[va-claw/daemon] no supported CLI is available in PATH; skipping wake.");
261
+ return null;
262
+ }
263
+ function whichCommandExists(command) {
264
+ const result = spawnSync("which", [command], { encoding: "utf8" });
265
+ const resolved = typeof result.stdout === "string" ? result.stdout.trim() : "";
266
+ return result.status === 0 && resolved !== "" ? resolved : null;
267
+ }
268
+ function toCliAdapter(name, command) {
269
+ return { name, command, args: name === "codex" ? ["exec", "--full-auto"] : ["-p"] };
270
+ }
271
+ function readEnv(env) {
272
+ return env ?? (process.env ?? {});
273
+ }
274
+
275
+ // node_modules/.pnpm/croner@file+vendor+croner/node_modules/croner/dist/croner.js
276
+ function T(s2) {
277
+ return Date.UTC(s2.y, s2.m - 1, s2.d, s2.h, s2.i, s2.s);
278
+ }
279
+ function D(s2, e) {
280
+ return s2.y === e.y && s2.m === e.m && s2.d === e.d && s2.h === e.h && s2.i === e.i && s2.s === e.s;
281
+ }
282
+ function A(s2, e) {
283
+ let t = new Date(Date.parse(s2));
284
+ if (isNaN(t)) throw new Error("Invalid ISO8601 passed to timezone parser.");
285
+ let r = s2.substring(9);
286
+ return r.includes("Z") || r.includes("+") || r.includes("-") ? b(t.getUTCFullYear(), t.getUTCMonth() + 1, t.getUTCDate(), t.getUTCHours(), t.getUTCMinutes(), t.getUTCSeconds(), "Etc/UTC") : b(t.getFullYear(), t.getMonth() + 1, t.getDate(), t.getHours(), t.getMinutes(), t.getSeconds(), e);
287
+ }
288
+ function v(s2, e, t) {
289
+ return k(A(s2, e), t);
290
+ }
291
+ function k(s2, e) {
292
+ let t = new Date(T(s2)), r = g(t, s2.tz), n = T(s2), i = T(r), a = n - i, o = new Date(t.getTime() + a), h = g(o, s2.tz);
293
+ if (D(h, s2)) {
294
+ let u = new Date(o.getTime() - 36e5), d = g(u, s2.tz);
295
+ return D(d, s2) ? u : o;
296
+ }
297
+ let l = new Date(o.getTime() + T(s2) - T(h)), y = g(l, s2.tz);
298
+ if (D(y, s2)) return l;
299
+ if (e) throw new Error("Invalid date passed to fromTZ()");
300
+ return o.getTime() > l.getTime() ? o : l;
301
+ }
302
+ function g(s2, e) {
303
+ let t, r;
304
+ try {
305
+ t = new Intl.DateTimeFormat("en-US", { timeZone: e, year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: false }), r = t.formatToParts(s2);
306
+ } catch (i) {
307
+ let a = i instanceof Error ? i.message : String(i);
308
+ throw new RangeError(`toTZ: Invalid timezone '${e}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${a}`);
309
+ }
310
+ let n = { year: 0, month: 0, day: 0, hour: 0, minute: 0, second: 0 };
311
+ for (let i of r) (i.type === "year" || i.type === "month" || i.type === "day" || i.type === "hour" || i.type === "minute" || i.type === "second") && (n[i.type] = parseInt(i.value, 10));
312
+ if (isNaN(n.year) || isNaN(n.month) || isNaN(n.day) || isNaN(n.hour) || isNaN(n.minute) || isNaN(n.second)) throw new Error(`toTZ: Failed to parse all date components from timezone '${e}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify(n)}`);
313
+ return n.hour === 24 && (n.hour = 0), { y: n.year, m: n.month, d: n.day, h: n.hour, i: n.minute, s: n.second, tz: e };
314
+ }
315
+ function b(s2, e, t, r, n, i, a) {
316
+ return { y: s2, m: e, d: t, h: r, i: n, s: i, tz: a };
317
+ }
318
+ var O = [1, 2, 4, 8, 16];
319
+ var C = class {
320
+ pattern;
321
+ timezone;
322
+ mode;
323
+ alternativeWeekdays;
324
+ sloppyRanges;
325
+ second;
326
+ minute;
327
+ hour;
328
+ day;
329
+ month;
330
+ dayOfWeek;
331
+ year;
332
+ lastDayOfMonth;
333
+ lastWeekday;
334
+ nearestWeekdays;
335
+ starDOM;
336
+ starDOW;
337
+ starYear;
338
+ useAndLogic;
339
+ constructor(e, t, r) {
340
+ this.pattern = e, this.timezone = t, this.mode = r?.mode ?? "auto", this.alternativeWeekdays = r?.alternativeWeekdays ?? false, this.sloppyRanges = r?.sloppyRanges ?? false, this.second = Array(60).fill(0), this.minute = Array(60).fill(0), this.hour = Array(24).fill(0), this.day = Array(31).fill(0), this.month = Array(12).fill(0), this.dayOfWeek = Array(7).fill(0), this.year = Array(1e4).fill(0), this.lastDayOfMonth = false, this.lastWeekday = false, this.nearestWeekdays = Array(31).fill(0), this.starDOM = false, this.starDOW = false, this.starYear = false, this.useAndLogic = false, this.parse();
341
+ }
342
+ parse() {
343
+ if (!(typeof this.pattern == "string" || this.pattern instanceof String)) throw new TypeError("CronPattern: Pattern has to be of type string.");
344
+ this.pattern.indexOf("@") >= 0 && (this.pattern = this.handleNicknames(this.pattern).trim());
345
+ let e = this.pattern.match(/\S+/g) || [""], t = e.length;
346
+ if (e.length < 5 || e.length > 7) throw new TypeError("CronPattern: invalid configuration format ('" + this.pattern + "'), exactly five, six, or seven space separated parts are required.");
347
+ if (this.mode !== "auto") {
348
+ let n;
349
+ switch (this.mode) {
350
+ case "5-part":
351
+ n = 5;
352
+ break;
353
+ case "6-part":
354
+ n = 6;
355
+ break;
356
+ case "7-part":
357
+ n = 7;
358
+ break;
359
+ case "5-or-6-parts":
360
+ n = [5, 6];
361
+ break;
362
+ case "6-or-7-parts":
363
+ n = [6, 7];
364
+ break;
365
+ default:
366
+ n = 0;
367
+ }
368
+ if (!(Array.isArray(n) ? n.includes(t) : t === n)) {
369
+ let a = Array.isArray(n) ? n.join(" or ") : n.toString();
370
+ throw new TypeError(`CronPattern: mode '${this.mode}' requires exactly ${a} parts, but pattern '${this.pattern}' has ${t} parts.`);
371
+ }
372
+ }
373
+ if (e.length === 5 && e.unshift("0"), e.length === 6 && e.push("*"), e[3].toUpperCase() === "LW" ? (this.lastWeekday = true, e[3] = "") : e[3].toUpperCase().indexOf("L") >= 0 && (e[3] = e[3].replace(/L/gi, ""), this.lastDayOfMonth = true), e[3] == "*" && (this.starDOM = true), e[6] == "*" && (this.starYear = true), e[4].length >= 3 && (e[4] = this.replaceAlphaMonths(e[4])), e[5].length >= 3 && (e[5] = this.alternativeWeekdays ? this.replaceAlphaDaysQuartz(e[5]) : this.replaceAlphaDays(e[5])), e[5].startsWith("+") && (this.useAndLogic = true, e[5] = e[5].substring(1), e[5] === "")) throw new TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");
374
+ switch (e[5] == "*" && (this.starDOW = true), this.pattern.indexOf("?") >= 0 && (e[0] = e[0].replace(/\?/g, "*"), e[1] = e[1].replace(/\?/g, "*"), e[2] = e[2].replace(/\?/g, "*"), e[3] = e[3].replace(/\?/g, "*"), e[4] = e[4].replace(/\?/g, "*"), e[5] = e[5].replace(/\?/g, "*"), e[6] && (e[6] = e[6].replace(/\?/g, "*"))), this.mode) {
375
+ case "5-part":
376
+ e[0] = "0", e[6] = "*";
377
+ break;
378
+ case "6-part":
379
+ e[6] = "*";
380
+ break;
381
+ case "5-or-6-parts":
382
+ e[6] = "*";
383
+ break;
384
+ case "6-or-7-parts":
385
+ break;
386
+ case "7-part":
387
+ case "auto":
388
+ break;
389
+ }
390
+ this.throwAtIllegalCharacters(e), this.partToArray("second", e[0], 0, 1), this.partToArray("minute", e[1], 0, 1), this.partToArray("hour", e[2], 0, 1), this.partToArray("day", e[3], -1, 1), this.partToArray("month", e[4], -1, 1);
391
+ let r = this.alternativeWeekdays ? -1 : 0;
392
+ this.partToArray("dayOfWeek", e[5], r, 63), this.partToArray("year", e[6], 0, 1), !this.alternativeWeekdays && this.dayOfWeek[7] && (this.dayOfWeek[0] = this.dayOfWeek[7]);
393
+ }
394
+ partToArray(e, t, r, n) {
395
+ let i = this[e], a = e === "day" && this.lastDayOfMonth, o = e === "day" && this.lastWeekday;
396
+ if (t === "" && !a && !o) throw new TypeError("CronPattern: configuration entry " + e + " (" + t + ") is empty, check for trailing spaces.");
397
+ if (t === "*") return i.fill(n);
398
+ let h = t.split(",");
399
+ if (h.length > 1) for (let l = 0; l < h.length; l++) this.partToArray(e, h[l], r, n);
400
+ else t.indexOf("-") !== -1 && t.indexOf("/") !== -1 ? this.handleRangeWithStepping(t, e, r, n) : t.indexOf("-") !== -1 ? this.handleRange(t, e, r, n) : t.indexOf("/") !== -1 ? this.handleStepping(t, e, r, n) : t !== "" && this.handleNumber(t, e, r, n);
401
+ }
402
+ throwAtIllegalCharacters(e) {
403
+ for (let t = 0; t < e.length; t++) if ((t === 3 ? /[^/*0-9,\-WwLl]+/ : t === 5 ? /[^/*0-9,\-#Ll]+/ : /[^/*0-9,\-]+/).test(e[t])) throw new TypeError("CronPattern: configuration entry " + t + " (" + e[t] + ") contains illegal characters.");
404
+ }
405
+ handleNumber(e, t, r, n) {
406
+ let i = this.extractNth(e, t), a = e.toUpperCase().includes("W");
407
+ if (t !== "day" && a) throw new TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");
408
+ a && (t = "nearestWeekdays");
409
+ let o = parseInt(i[0], 10) + r;
410
+ if (isNaN(o)) throw new TypeError("CronPattern: " + t + " is not a number: '" + e + "'");
411
+ this.setPart(t, o, i[1] || n);
412
+ }
413
+ setPart(e, t, r) {
414
+ if (!Object.prototype.hasOwnProperty.call(this, e)) throw new TypeError("CronPattern: Invalid part specified: " + e);
415
+ if (e === "dayOfWeek") {
416
+ if (t === 7 && (t = 0), t < 0 || t > 6) throw new RangeError("CronPattern: Invalid value for dayOfWeek: " + t);
417
+ this.setNthWeekdayOfMonth(t, r);
418
+ return;
419
+ }
420
+ if (e === "second" || e === "minute") {
421
+ if (t < 0 || t >= 60) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
422
+ } else if (e === "hour") {
423
+ if (t < 0 || t >= 24) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
424
+ } else if (e === "day" || e === "nearestWeekdays") {
425
+ if (t < 0 || t >= 31) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
426
+ } else if (e === "month") {
427
+ if (t < 0 || t >= 12) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
428
+ } else if (e === "year" && (t < 1 || t >= 1e4)) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t + " (supported range: 1-9999)");
429
+ this[e][t] = r;
430
+ }
431
+ validateNotNaN(e, t) {
432
+ if (isNaN(e)) throw new TypeError(t);
433
+ }
434
+ validateRange(e, t, r, n, i) {
435
+ if (e > t) throw new TypeError("CronPattern: From value is larger than to value: '" + i + "'");
436
+ if (r !== void 0) {
437
+ if (r === 0) throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");
438
+ if (r > this[n].length) throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part (" + this[n].length + ")");
439
+ }
440
+ }
441
+ handleRangeWithStepping(e, t, r, n) {
442
+ if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");
443
+ let i = this.extractNth(e, t), a = i[0].match(/^(\d+)-(\d+)\/(\d+)$/);
444
+ if (a === null) throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '" + e + "'");
445
+ let [, o, h, l] = a, y = parseInt(o, 10) + r, u = parseInt(h, 10) + r, d = parseInt(l, 10);
446
+ this.validateNotNaN(y, "CronPattern: Syntax error, illegal lower range (NaN)"), this.validateNotNaN(u, "CronPattern: Syntax error, illegal upper range (NaN)"), this.validateNotNaN(d, "CronPattern: Syntax error, illegal stepping: (NaN)"), this.validateRange(y, u, d, t, e);
447
+ for (let c = y; c <= u; c += d) this.setPart(t, c, i[1] || n);
448
+ }
449
+ extractNth(e, t) {
450
+ let r = e, n;
451
+ if (r.includes("#")) {
452
+ if (t !== "dayOfWeek") throw new Error("CronPattern: nth (#) only allowed in day-of-week field");
453
+ n = r.split("#")[1], r = r.split("#")[0];
454
+ } else if (r.toUpperCase().endsWith("L")) {
455
+ if (t !== "dayOfWeek") throw new Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");
456
+ n = "L", r = r.slice(0, -1);
457
+ }
458
+ return [r, n];
459
+ }
460
+ handleRange(e, t, r, n) {
461
+ if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in a range.");
462
+ let i = this.extractNth(e, t), a = i[0].split("-");
463
+ if (a.length !== 2) throw new TypeError("CronPattern: Syntax error, illegal range: '" + e + "'");
464
+ let o = parseInt(a[0], 10) + r, h = parseInt(a[1], 10) + r;
465
+ this.validateNotNaN(o, "CronPattern: Syntax error, illegal lower range (NaN)"), this.validateNotNaN(h, "CronPattern: Syntax error, illegal upper range (NaN)"), this.validateRange(o, h, void 0, t, e);
466
+ for (let l = o; l <= h; l++) this.setPart(t, l, i[1] || n);
467
+ }
468
+ handleStepping(e, t, r, n) {
469
+ if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");
470
+ let i = this.extractNth(e, t), a = i[0].split("/");
471
+ if (a.length !== 2) throw new TypeError("CronPattern: Syntax error, illegal stepping: '" + e + "'");
472
+ if (this.sloppyRanges) a[0] === "" && (a[0] = "*");
473
+ else {
474
+ if (a[0] === "") throw new TypeError("CronPattern: Syntax error, stepping with missing prefix ('" + e + "') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");
475
+ if (a[0] !== "*") throw new TypeError("CronPattern: Syntax error, stepping with numeric prefix ('" + e + "') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");
476
+ }
477
+ let o = 0;
478
+ a[0] !== "*" && (o = parseInt(a[0], 10) + r);
479
+ let h = parseInt(a[1], 10);
480
+ this.validateNotNaN(h, "CronPattern: Syntax error, illegal stepping: (NaN)"), this.validateRange(0, this[t].length - 1, h, t, e);
481
+ for (let l = o; l < this[t].length; l += h) this.setPart(t, l, i[1] || n);
482
+ }
483
+ replaceAlphaDays(e) {
484
+ return e.replace(/-sun/gi, "-7").replace(/sun/gi, "0").replace(/mon/gi, "1").replace(/tue/gi, "2").replace(/wed/gi, "3").replace(/thu/gi, "4").replace(/fri/gi, "5").replace(/sat/gi, "6");
485
+ }
486
+ replaceAlphaDaysQuartz(e) {
487
+ return e.replace(/sun/gi, "1").replace(/mon/gi, "2").replace(/tue/gi, "3").replace(/wed/gi, "4").replace(/thu/gi, "5").replace(/fri/gi, "6").replace(/sat/gi, "7");
488
+ }
489
+ replaceAlphaMonths(e) {
490
+ return e.replace(/jan/gi, "1").replace(/feb/gi, "2").replace(/mar/gi, "3").replace(/apr/gi, "4").replace(/may/gi, "5").replace(/jun/gi, "6").replace(/jul/gi, "7").replace(/aug/gi, "8").replace(/sep/gi, "9").replace(/oct/gi, "10").replace(/nov/gi, "11").replace(/dec/gi, "12");
491
+ }
492
+ handleNicknames(e) {
493
+ let t = e.trim().toLowerCase();
494
+ if (t === "@yearly" || t === "@annually") return "0 0 1 1 *";
495
+ if (t === "@monthly") return "0 0 1 * *";
496
+ if (t === "@weekly") return "0 0 * * 0";
497
+ if (t === "@daily" || t === "@midnight") return "0 0 * * *";
498
+ if (t === "@hourly") return "0 * * * *";
499
+ if (t === "@reboot") throw new TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");
500
+ return e;
501
+ }
502
+ setNthWeekdayOfMonth(e, t) {
503
+ if (typeof t != "number" && t.toUpperCase() === "L") this.dayOfWeek[e] = this.dayOfWeek[e] | 32;
504
+ else if (t === 63) this.dayOfWeek[e] = 63;
505
+ else if (t < 6 && t > 0) this.dayOfWeek[e] = this.dayOfWeek[e] | O[t - 1];
506
+ else throw new TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${t}, Type: ${typeof t}`);
507
+ }
508
+ };
509
+ var P = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
510
+ var f = [["month", "year", 0], ["day", "month", -1], ["hour", "day", 0], ["minute", "hour", 0], ["second", "minute", 0]];
511
+ var m = class s {
512
+ tz;
513
+ ms;
514
+ second;
515
+ minute;
516
+ hour;
517
+ day;
518
+ month;
519
+ year;
520
+ constructor(e, t) {
521
+ if (this.tz = t, e && e instanceof Date) if (!isNaN(e)) this.fromDate(e);
522
+ else throw new TypeError("CronDate: Invalid date passed to CronDate constructor");
523
+ else if (e == null) this.fromDate(/* @__PURE__ */ new Date());
524
+ else if (e && typeof e == "string") this.fromString(e);
525
+ else if (e instanceof s) this.fromCronDate(e);
526
+ else throw new TypeError("CronDate: Invalid type (" + typeof e + ") passed to CronDate constructor");
527
+ }
528
+ getLastDayOfMonth(e, t) {
529
+ return t !== 1 ? P[t] : new Date(Date.UTC(e, t + 1, 0)).getUTCDate();
530
+ }
531
+ getLastWeekday(e, t) {
532
+ let r = this.getLastDayOfMonth(e, t), i = new Date(Date.UTC(e, t, r)).getUTCDay();
533
+ return i === 0 ? r - 2 : i === 6 ? r - 1 : r;
534
+ }
535
+ getNearestWeekday(e, t, r) {
536
+ let n = this.getLastDayOfMonth(e, t);
537
+ if (r > n) return -1;
538
+ let a = new Date(Date.UTC(e, t, r)).getUTCDay();
539
+ return a === 0 ? r === n ? r - 2 : r + 1 : a === 6 ? r === 1 ? r + 2 : r - 1 : r;
540
+ }
541
+ isNthWeekdayOfMonth(e, t, r, n) {
542
+ let a = new Date(Date.UTC(e, t, r)).getUTCDay(), o = 0;
543
+ for (let h = 1; h <= r; h++) new Date(Date.UTC(e, t, h)).getUTCDay() === a && o++;
544
+ if (n & 63 && O[o - 1] & n) return true;
545
+ if (n & 32) {
546
+ let h = this.getLastDayOfMonth(e, t);
547
+ for (let l = r + 1; l <= h; l++) if (new Date(Date.UTC(e, t, l)).getUTCDay() === a) return false;
548
+ return true;
549
+ }
550
+ return false;
551
+ }
552
+ fromDate(e) {
553
+ if (this.tz !== void 0) if (typeof this.tz == "number") this.ms = e.getUTCMilliseconds(), this.second = e.getUTCSeconds(), this.minute = e.getUTCMinutes() + this.tz, this.hour = e.getUTCHours(), this.day = e.getUTCDate(), this.month = e.getUTCMonth(), this.year = e.getUTCFullYear(), this.apply();
554
+ else try {
555
+ let t = g(e, this.tz);
556
+ this.ms = e.getMilliseconds(), this.second = t.s, this.minute = t.i, this.hour = t.h, this.day = t.d, this.month = t.m - 1, this.year = t.y;
557
+ } catch (t) {
558
+ let r = t instanceof Error ? t.message : String(t);
559
+ throw new TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${r}`);
560
+ }
561
+ else this.ms = e.getMilliseconds(), this.second = e.getSeconds(), this.minute = e.getMinutes(), this.hour = e.getHours(), this.day = e.getDate(), this.month = e.getMonth(), this.year = e.getFullYear();
562
+ }
563
+ fromCronDate(e) {
564
+ this.tz = e.tz, this.year = e.year, this.month = e.month, this.day = e.day, this.hour = e.hour, this.minute = e.minute, this.second = e.second, this.ms = e.ms;
565
+ }
566
+ apply() {
567
+ if (this.month > 11 || this.month < 0 || this.day > P[this.month] || this.day < 1 || this.hour > 59 || this.minute > 59 || this.second > 59 || this.hour < 0 || this.minute < 0 || this.second < 0) {
568
+ let e = new Date(Date.UTC(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms));
569
+ return this.ms = e.getUTCMilliseconds(), this.second = e.getUTCSeconds(), this.minute = e.getUTCMinutes(), this.hour = e.getUTCHours(), this.day = e.getUTCDate(), this.month = e.getUTCMonth(), this.year = e.getUTCFullYear(), true;
570
+ } else return false;
571
+ }
572
+ fromString(e) {
573
+ if (typeof this.tz == "number") {
574
+ let t = v(e);
575
+ this.ms = t.getUTCMilliseconds(), this.second = t.getUTCSeconds(), this.minute = t.getUTCMinutes(), this.hour = t.getUTCHours(), this.day = t.getUTCDate(), this.month = t.getUTCMonth(), this.year = t.getUTCFullYear(), this.apply();
576
+ } else return this.fromDate(v(e, this.tz));
577
+ }
578
+ findNext(e, t, r, n) {
579
+ return this._findMatch(e, t, r, n, 1);
580
+ }
581
+ _findMatch(e, t, r, n, i) {
582
+ let a = this[t], o;
583
+ r.lastDayOfMonth && (o = this.getLastDayOfMonth(this.year, this.month));
584
+ let h = !r.starDOW && t == "day" ? new Date(Date.UTC(this.year, this.month, 1, 0, 0, 0, 0)).getUTCDay() : void 0, l = this[t] + n, y = i === 1 ? (u) => u < r[t].length : (u) => u >= 0;
585
+ for (let u = l; y(u); u += i) {
586
+ let d = r[t][u];
587
+ if (t === "day" && !d) {
588
+ for (let c = 0; c < r.nearestWeekdays.length; c++) if (r.nearestWeekdays[c]) {
589
+ let M = this.getNearestWeekday(this.year, this.month, c - n);
590
+ if (M === -1) continue;
591
+ if (M === u - n) {
592
+ d = 1;
593
+ break;
594
+ }
595
+ }
596
+ }
597
+ if (t === "day" && r.lastWeekday) {
598
+ let c = this.getLastWeekday(this.year, this.month);
599
+ u - n === c && (d = 1);
600
+ }
601
+ if (t === "day" && r.lastDayOfMonth && u - n == o && (d = 1), t === "day" && !r.starDOW) {
602
+ let c = r.dayOfWeek[(h + (u - n - 1)) % 7];
603
+ if (c && c & 63) c = this.isNthWeekdayOfMonth(this.year, this.month, u - n, c) ? 1 : 0;
604
+ else if (c) throw new Error(`CronDate: Invalid value for dayOfWeek encountered. ${c}`);
605
+ r.useAndLogic ? d = d && c : !e.domAndDow && !r.starDOM ? d = d || c : d = d && c;
606
+ }
607
+ if (d) return this[t] = u - n, a !== this[t] ? 2 : 1;
608
+ }
609
+ return 3;
610
+ }
611
+ recurse(e, t, r) {
612
+ if (r === 0 && !e.starYear) {
613
+ if (this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0) {
614
+ let i = -1;
615
+ for (let a = this.year + 1; a < e.year.length && a < 1e4; a++) if (e.year[a] === 1) {
616
+ i = a;
617
+ break;
618
+ }
619
+ if (i === -1) return null;
620
+ this.year = i, this.month = 0, this.day = 1, this.hour = 0, this.minute = 0, this.second = 0, this.ms = 0;
621
+ }
622
+ if (this.year >= 1e4) return null;
623
+ }
624
+ let n = this.findNext(t, f[r][0], e, f[r][2]);
625
+ if (n > 1) {
626
+ let i = r + 1;
627
+ for (; i < f.length; ) this[f[i][0]] = -f[i][2], i++;
628
+ if (n === 3) {
629
+ if (this[f[r][1]]++, this[f[r][0]] = -f[r][2], this.apply(), r === 0 && !e.starYear) {
630
+ for (; this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0 && this.year < 1e4; ) this.year++;
631
+ if (this.year >= 1e4 || this.year >= e.year.length) return null;
632
+ }
633
+ return this.recurse(e, t, 0);
634
+ } else if (this.apply()) return this.recurse(e, t, r - 1);
635
+ }
636
+ return r += 1, r >= f.length ? this : (e.starYear ? this.year >= 3e3 : this.year >= 1e4) ? null : this.recurse(e, t, r);
637
+ }
638
+ increment(e, t, r) {
639
+ return this.second += t.interval !== void 0 && t.interval > 1 && r ? t.interval : 1, this.ms = 0, this.apply(), this.recurse(e, t, 0);
640
+ }
641
+ decrement(e, t) {
642
+ return this.second -= t.interval !== void 0 && t.interval > 1 ? t.interval : 1, this.ms = 0, this.apply(), this.recurseBackward(e, t, 0, 0);
643
+ }
644
+ recurseBackward(e, t, r, n = 0) {
645
+ if (n > 1e4) return null;
646
+ if (r === 0 && !e.starYear) {
647
+ if (this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0) {
648
+ let a = -1;
649
+ for (let o = this.year - 1; o >= 0; o--) if (e.year[o] === 1) {
650
+ a = o;
651
+ break;
652
+ }
653
+ if (a === -1) return null;
654
+ this.year = a, this.month = 11, this.day = 31, this.hour = 23, this.minute = 59, this.second = 59, this.ms = 0;
655
+ }
656
+ if (this.year < 0) return null;
657
+ }
658
+ let i = this.findPrevious(t, f[r][0], e, f[r][2]);
659
+ if (i > 1) {
660
+ let a = r + 1;
661
+ for (; a < f.length; ) {
662
+ let o = f[a][0], h = f[a][2], l = this.getMaxPatternValue(o, e, h);
663
+ this[o] = l, a++;
664
+ }
665
+ if (i === 3) {
666
+ if (this[f[r][1]]--, r === 0) {
667
+ let y = this.getLastDayOfMonth(this.year, this.month);
668
+ this.day > y && (this.day = y);
669
+ }
670
+ if (r === 1) if (this.day <= 0) this.day = 1;
671
+ else {
672
+ let y = this.year, u = this.month;
673
+ for (; u < 0; ) u += 12, y--;
674
+ for (; u > 11; ) u -= 12, y++;
675
+ let d = u !== 1 ? P[u] : new Date(Date.UTC(y, u + 1, 0)).getUTCDate();
676
+ this.day > d && (this.day = d);
677
+ }
678
+ this.apply();
679
+ let o = f[r][0], h = f[r][2], l = this.getMaxPatternValue(o, e, h);
680
+ if (o === "day") {
681
+ let y = this.getLastDayOfMonth(this.year, this.month);
682
+ this[o] = Math.min(l, y);
683
+ } else this[o] = l;
684
+ if (this.apply(), r === 0) {
685
+ let y = f[1][2], u = this.getMaxPatternValue("day", e, y), d = this.getLastDayOfMonth(this.year, this.month), c = Math.min(u, d);
686
+ c !== this.day && (this.day = c, this.hour = this.getMaxPatternValue("hour", e, f[2][2]), this.minute = this.getMaxPatternValue("minute", e, f[3][2]), this.second = this.getMaxPatternValue("second", e, f[4][2]));
687
+ }
688
+ if (r === 0 && !e.starYear) {
689
+ for (; this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0; ) this.year--;
690
+ if (this.year < 0) return null;
691
+ }
692
+ return this.recurseBackward(e, t, 0, n + 1);
693
+ } else if (this.apply()) return this.recurseBackward(e, t, r - 1, n + 1);
694
+ }
695
+ return r += 1, r >= f.length ? this : this.year < 0 ? null : this.recurseBackward(e, t, r, n + 1);
696
+ }
697
+ getMaxPatternValue(e, t, r) {
698
+ if (e === "day" && t.lastDayOfMonth) return this.getLastDayOfMonth(this.year, this.month);
699
+ if (e === "day" && !t.starDOW) return this.getLastDayOfMonth(this.year, this.month);
700
+ for (let n = t[e].length - 1; n >= 0; n--) if (t[e][n]) return n - r;
701
+ return t[e].length - 1 - r;
702
+ }
703
+ findPrevious(e, t, r, n) {
704
+ return this._findMatch(e, t, r, n, -1);
705
+ }
706
+ getDate(e) {
707
+ return e || this.tz === void 0 ? new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms) : typeof this.tz == "number" ? new Date(Date.UTC(this.year, this.month, this.day, this.hour, this.minute - this.tz, this.second, this.ms)) : k(b(this.year, this.month + 1, this.day, this.hour, this.minute, this.second, this.tz), false);
708
+ }
709
+ getTime() {
710
+ return this.getDate(false).getTime();
711
+ }
712
+ match(e, t) {
713
+ if (!e.starYear && (this.year < 0 || this.year >= e.year.length || e.year[this.year] === 0)) return false;
714
+ for (let r = 0; r < f.length; r++) {
715
+ let n = f[r][0], i = f[r][2], a = this[n];
716
+ if (a + i < 0 || a + i >= e[n].length) return false;
717
+ let o = e[n][a + i];
718
+ if (n === "day") {
719
+ if (!o) {
720
+ for (let h = 0; h < e.nearestWeekdays.length; h++) if (e.nearestWeekdays[h]) {
721
+ let l = this.getNearestWeekday(this.year, this.month, h - i);
722
+ if (l !== -1 && l === a) {
723
+ o = 1;
724
+ break;
725
+ }
726
+ }
727
+ }
728
+ if (e.lastWeekday) {
729
+ let h = this.getLastWeekday(this.year, this.month);
730
+ a === h && (o = 1);
731
+ }
732
+ if (e.lastDayOfMonth) {
733
+ let h = this.getLastDayOfMonth(this.year, this.month);
734
+ a === h && (o = 1);
735
+ }
736
+ if (!e.starDOW) {
737
+ let h = new Date(Date.UTC(this.year, this.month, 1, 0, 0, 0, 0)).getUTCDay(), l = e.dayOfWeek[(h + (a - 1)) % 7];
738
+ l && l & 63 && (l = this.isNthWeekdayOfMonth(this.year, this.month, a, l) ? 1 : 0), e.useAndLogic ? o = o && l : !t.domAndDow && !e.starDOM ? o = o || l : o = o && l;
739
+ }
740
+ }
741
+ if (!o) return false;
742
+ }
743
+ return true;
744
+ }
745
+ };
746
+ function R(s2) {
747
+ if (s2 === void 0 && (s2 = {}), delete s2.name, s2.legacyMode !== void 0 && s2.domAndDow === void 0 ? s2.domAndDow = !s2.legacyMode : s2.domAndDow === void 0 && (s2.domAndDow = false), s2.legacyMode = !s2.domAndDow, s2.paused = s2.paused === void 0 ? false : s2.paused, s2.maxRuns = s2.maxRuns === void 0 ? 1 / 0 : s2.maxRuns, s2.catch = s2.catch === void 0 ? false : s2.catch, s2.interval = s2.interval === void 0 ? 0 : parseInt(s2.interval.toString(), 10), s2.utcOffset = s2.utcOffset === void 0 ? void 0 : parseInt(s2.utcOffset.toString(), 10), s2.dayOffset = s2.dayOffset === void 0 ? 0 : parseInt(s2.dayOffset.toString(), 10), s2.unref = s2.unref === void 0 ? false : s2.unref, s2.mode = s2.mode === void 0 ? "auto" : s2.mode, s2.alternativeWeekdays = s2.alternativeWeekdays === void 0 ? false : s2.alternativeWeekdays, s2.sloppyRanges = s2.sloppyRanges === void 0 ? false : s2.sloppyRanges, !["auto", "5-part", "6-part", "7-part", "5-or-6-parts", "6-or-7-parts"].includes(s2.mode)) throw new Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");
748
+ if (s2.startAt && (s2.startAt = new m(s2.startAt, s2.timezone)), s2.stopAt && (s2.stopAt = new m(s2.stopAt, s2.timezone)), s2.interval !== null) {
749
+ if (isNaN(s2.interval)) throw new Error("CronOptions: Supplied value for interval is not a number");
750
+ if (s2.interval < 0) throw new Error("CronOptions: Supplied value for interval can not be negative");
751
+ }
752
+ if (s2.utcOffset !== void 0) {
753
+ if (isNaN(s2.utcOffset)) throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");
754
+ if (s2.utcOffset < -870 || s2.utcOffset > 870) throw new Error("CronOptions: utcOffset out of bounds.");
755
+ if (s2.utcOffset !== void 0 && s2.timezone) throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.");
756
+ }
757
+ if (s2.unref !== true && s2.unref !== false) throw new Error("CronOptions: Unref should be either true, false or undefined(false).");
758
+ if (s2.dayOffset !== void 0 && s2.dayOffset !== 0 && isNaN(s2.dayOffset)) throw new Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");
759
+ return s2;
760
+ }
761
+ function p(s2) {
762
+ return Object.prototype.toString.call(s2) === "[object Function]" || typeof s2 == "function" || s2 instanceof Function;
763
+ }
764
+ function _(s2) {
765
+ return p(s2);
766
+ }
767
+ function x(s2) {
768
+ typeof Deno < "u" && typeof Deno.unrefTimer < "u" ? Deno.unrefTimer(s2) : s2 && typeof s2.unref < "u" && s2.unref();
769
+ }
770
+ var W = 30 * 1e3;
771
+ var w = [];
772
+ var E = class {
773
+ name;
774
+ options;
775
+ _states;
776
+ fn;
777
+ getTz() {
778
+ return this.options.timezone || this.options.utcOffset;
779
+ }
780
+ applyDayOffset(e) {
781
+ if (this.options.dayOffset !== void 0 && this.options.dayOffset !== 0) {
782
+ let t = this.options.dayOffset * 24 * 60 * 60 * 1e3;
783
+ return new Date(e.getTime() + t);
784
+ }
785
+ return e;
786
+ }
787
+ constructor(e, t, r) {
788
+ let n, i;
789
+ if (p(t)) i = t;
790
+ else if (typeof t == "object") n = t;
791
+ else if (t !== void 0) throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");
792
+ if (p(r)) i = r;
793
+ else if (typeof r == "object") n = r;
794
+ else if (r !== void 0) throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");
795
+ if (this.name = n?.name, this.options = R(n), this._states = { kill: false, blocking: false, previousRun: void 0, currentRun: void 0, once: void 0, currentTimeout: void 0, maxRuns: n ? n.maxRuns : void 0, paused: n ? n.paused : false, pattern: new C("* * * * *", void 0, { mode: "auto" }) }, e && (e instanceof Date || typeof e == "string" && e.indexOf(":") > 0) ? this._states.once = new m(e, this.getTz()) : this._states.pattern = new C(e, this.options.timezone, { mode: this.options.mode, alternativeWeekdays: this.options.alternativeWeekdays, sloppyRanges: this.options.sloppyRanges }), this.name) {
796
+ if (w.find((o) => o.name === this.name)) throw new Error("Cron: Tried to initialize new named job '" + this.name + "', but name already taken.");
797
+ w.push(this);
798
+ }
799
+ return i !== void 0 && _(i) && (this.fn = i, this.schedule()), this;
800
+ }
801
+ nextRun(e) {
802
+ let t = this._next(e);
803
+ return t ? this.applyDayOffset(t.getDate(false)) : null;
804
+ }
805
+ nextRuns(e, t) {
806
+ this._states.maxRuns !== void 0 && e > this._states.maxRuns && (e = this._states.maxRuns);
807
+ let r = t || this._states.currentRun || void 0;
808
+ return this._enumerateRuns(e, r, "next");
809
+ }
810
+ previousRuns(e, t) {
811
+ return this._enumerateRuns(e, t || void 0, "previous");
812
+ }
813
+ _enumerateRuns(e, t, r) {
814
+ let n = [], i = t ? new m(t, this.getTz()) : null, a = r === "next" ? this._next : this._previous;
815
+ for (; e--; ) {
816
+ let o = a.call(this, i);
817
+ if (!o) break;
818
+ let h = o.getDate(false);
819
+ n.push(this.applyDayOffset(h)), i = o;
820
+ }
821
+ return n;
822
+ }
823
+ match(e) {
824
+ if (this._states.once) {
825
+ let r = new m(e, this.getTz());
826
+ r.ms = 0;
827
+ let n = new m(this._states.once, this.getTz());
828
+ return n.ms = 0, r.getTime() === n.getTime();
829
+ }
830
+ let t = new m(e, this.getTz());
831
+ return t.ms = 0, t.match(this._states.pattern, this.options);
832
+ }
833
+ getPattern() {
834
+ if (!this._states.once) return this._states.pattern ? this._states.pattern.pattern : void 0;
835
+ }
836
+ getOnce() {
837
+ return this._states.once ? this._states.once.getDate() : null;
838
+ }
839
+ isRunning() {
840
+ let e = this.nextRun(this._states.currentRun), t = !this._states.paused, r = this.fn !== void 0, n = !this._states.kill;
841
+ return t && r && n && e !== null;
842
+ }
843
+ isStopped() {
844
+ return this._states.kill;
845
+ }
846
+ isBusy() {
847
+ return this._states.blocking;
848
+ }
849
+ currentRun() {
850
+ return this._states.currentRun ? this._states.currentRun.getDate() : null;
851
+ }
852
+ previousRun() {
853
+ return this._states.previousRun ? this._states.previousRun.getDate() : null;
854
+ }
855
+ msToNext(e) {
856
+ let t = this._next(e);
857
+ return t ? e instanceof m || e instanceof Date ? t.getTime() - e.getTime() : t.getTime() - new m(e).getTime() : null;
858
+ }
859
+ stop() {
860
+ this._states.kill = true, this._states.currentTimeout && clearTimeout(this._states.currentTimeout);
861
+ let e = w.indexOf(this);
862
+ e >= 0 && w.splice(e, 1);
863
+ }
864
+ pause() {
865
+ return this._states.paused = true, !this._states.kill;
866
+ }
867
+ resume() {
868
+ return this._states.paused = false, !this._states.kill;
869
+ }
870
+ schedule(e) {
871
+ if (e && this.fn) throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");
872
+ e && (this.fn = e);
873
+ let t = this.msToNext(), r = this.nextRun(this._states.currentRun);
874
+ return t == null || isNaN(t) || r === null ? this : (t > W && (t = W), this._states.currentTimeout = setTimeout(() => this._checkTrigger(r), t), this._states.currentTimeout && this.options.unref && x(this._states.currentTimeout), this);
875
+ }
876
+ async _trigger(e) {
877
+ this._states.blocking = true, this._states.currentRun = new m(void 0, this.getTz());
878
+ try {
879
+ if (this.options.catch) try {
880
+ this.fn !== void 0 && await this.fn(this, this.options.context);
881
+ } catch (t) {
882
+ if (p(this.options.catch)) try {
883
+ this.options.catch(t, this);
884
+ } catch {
885
+ }
886
+ }
887
+ else this.fn !== void 0 && await this.fn(this, this.options.context);
888
+ } finally {
889
+ this._states.previousRun = new m(e, this.getTz()), this._states.blocking = false;
890
+ }
891
+ }
892
+ async trigger() {
893
+ await this._trigger();
894
+ }
895
+ runsLeft() {
896
+ return this._states.maxRuns;
897
+ }
898
+ _checkTrigger(e) {
899
+ let t = /* @__PURE__ */ new Date(), r = !this._states.paused && t.getTime() >= e.getTime(), n = this._states.blocking && this.options.protect;
900
+ r && !n ? (this._states.maxRuns !== void 0 && this._states.maxRuns--, this._trigger()) : r && n && p(this.options.protect) && setTimeout(() => this.options.protect(this), 0), this.schedule();
901
+ }
902
+ _next(e) {
903
+ let t = !!(e || this._states.currentRun), r = false;
904
+ !e && this.options.startAt && this.options.interval && ([e, t] = this._calculatePreviousRun(e, t), r = !e), e = new m(e, this.getTz()), this.options.startAt && e && e.getTime() < this.options.startAt.getTime() && (e = this.options.startAt);
905
+ let n = this._states.once || new m(e, this.getTz());
906
+ return !r && n !== this._states.once && (n = n.increment(this._states.pattern, this.options, t)), this._states.once && this._states.once.getTime() <= e.getTime() || n === null || this._states.maxRuns !== void 0 && this._states.maxRuns <= 0 || this._states.kill || this.options.stopAt && n.getTime() >= this.options.stopAt.getTime() ? null : n;
907
+ }
908
+ _previous(e) {
909
+ let t = new m(e, this.getTz());
910
+ this.options.stopAt && t.getTime() > this.options.stopAt.getTime() && (t = this.options.stopAt);
911
+ let r = new m(t, this.getTz());
912
+ return this._states.once ? this._states.once.getTime() < t.getTime() ? this._states.once : null : (r = r.decrement(this._states.pattern, this.options), r === null || this.options.startAt && r.getTime() < this.options.startAt.getTime() ? null : r);
913
+ }
914
+ _calculatePreviousRun(e, t) {
915
+ let r = new m(void 0, this.getTz()), n = e;
916
+ if (this.options.startAt.getTime() <= r.getTime()) {
917
+ n = this.options.startAt;
918
+ let i = n.getTime() + this.options.interval * 1e3;
919
+ for (; i <= r.getTime(); ) n = new m(n, this.getTz()).increment(this._states.pattern, this.options, true), i = n.getTime() + this.options.interval * 1e3;
920
+ t = true;
921
+ }
922
+ return n === null && (n = void 0), [n, t];
923
+ }
924
+ };
925
+
926
+ // packages/daemon/dist/wake-cycle.js
927
+ import { spawnSync as spawnSync2 } from "node:child_process";
928
+
929
+ // packages/memory/dist/default-store.js
930
+ import { homedir as homedir2 } from "node:os";
931
+ import { join } from "node:path";
932
+
933
+ // packages/memory/dist/memory-store.js
934
+ import { randomUUID } from "node:crypto";
935
+
936
+ // packages/memory/dist/embedding.js
937
+ var EMBEDDING_DIMENSIONS = 32;
938
+ function buildSearchText(text2, metadata) {
939
+ const metadataText = metadata ? flattenMetadata(metadata).join(" ") : "";
940
+ return `${text2} ${metadataText}`.trim().toLowerCase();
941
+ }
942
+ function createEmbedding(input) {
943
+ const vector = Array.from({ length: EMBEDDING_DIMENSIONS }, () => 0);
944
+ for (const token of tokenize(input)) {
945
+ const hash = hashToken(token);
946
+ const index = Math.abs(hash) % EMBEDDING_DIMENSIONS;
947
+ vector[index] += hash < 0 ? -1 : 1;
948
+ }
949
+ const magnitude = Math.hypot(...vector) || 1;
950
+ return vector.map((value) => value / magnitude);
951
+ }
952
+ function cosineSimilarity(left, right) {
953
+ const size = Math.min(left.length, right.length);
954
+ let score = 0;
955
+ for (let index = 0; index < size; index += 1) {
956
+ score += left[index] * right[index];
957
+ }
958
+ return score;
959
+ }
960
+ function keywordTokens(query) {
961
+ return Array.from(new Set(tokenize(query)));
962
+ }
963
+ function tokenize(input) {
964
+ return input.toLowerCase().split(/[^a-z0-9\u4e00-\u9fff]+/).filter(Boolean);
965
+ }
966
+ function flattenMetadata(value) {
967
+ if (value == null) {
968
+ return [];
969
+ }
970
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
971
+ return [String(value)];
972
+ }
973
+ if (Array.isArray(value)) {
974
+ return value.flatMap((item) => flattenMetadata(item));
975
+ }
976
+ if (typeof value === "object") {
977
+ return Object.entries(value).flatMap(([key, item]) => [
978
+ key,
979
+ ...flattenMetadata(item)
980
+ ]);
981
+ }
982
+ return [];
983
+ }
984
+ function hashToken(token) {
985
+ let hash = 2166136261;
986
+ for (let index = 0; index < token.length; index += 1) {
987
+ hash ^= token.charCodeAt(index);
988
+ hash = Math.imul(hash, 16777619);
989
+ }
990
+ return hash | 0;
991
+ }
992
+
993
+ // packages/memory/dist/forgetting-curve.js
994
+ var DAY_IN_MS = 864e5;
995
+ function computeRetention(strength, lastAccessedAt, decayTau, importance, accessCount) {
996
+ const normalizedStrength = clamp(Number(strength), 0, 1);
997
+ const normalizedImportance = clamp(Number(importance), 0, 1);
998
+ const normalizedDecayTau = Number.isFinite(decayTau) && decayTau > 0 ? decayTau : DAY_IN_MS;
999
+ const now = Date.now();
1000
+ const lastAccess = Date.parse(lastAccessedAt ?? "");
1001
+ const elapsed = Number.isFinite(lastAccess) ? Math.max(0, now - lastAccess) : 0;
1002
+ const dynamicTau = normalizedDecayTau * (1 + normalizedImportance * 2) * 1.2 ** Math.min(Math.max(0, Math.round(accessCount)), 10);
1003
+ return clamp(normalizedStrength * Math.exp(-elapsed / dynamicTau), 0, 1);
1004
+ }
1005
+ function reinforceOnAccess(current, importance) {
1006
+ return clamp(Number(current) + 0.1 * (1 + clamp(Number(importance), 0, 1)), 0, 1);
1007
+ }
1008
+ function clamp(value, min, max) {
1009
+ if (!Number.isFinite(value)) {
1010
+ return min;
1011
+ }
1012
+ return Math.max(min, Math.min(max, value));
1013
+ }
1014
+
1015
+ // packages/memory/dist/sqlite.js
1016
+ import { mkdirSync } from "node:fs";
1017
+ import { dirname as dirname2 } from "node:path";
1018
+ import { DatabaseSync } from "node:sqlite";
1019
+ var SqliteMemoryDb = class {
1020
+ vectorAvailable;
1021
+ db;
1022
+ constructor(options = {}) {
1023
+ const dbPath = options.dbPath ?? ":memory:";
1024
+ if (dbPath !== ":memory:") {
1025
+ mkdirSync(dirname2(dbPath), { recursive: true });
1026
+ }
1027
+ this.db = new DatabaseSync(dbPath);
1028
+ this.db.exec(`
1029
+ CREATE TABLE IF NOT EXISTS memories (
1030
+ id TEXT PRIMARY KEY,
1031
+ text TEXT NOT NULL,
1032
+ essence TEXT,
1033
+ details TEXT,
1034
+ tags TEXT,
1035
+ trigger_conditions TEXT,
1036
+ importance REAL DEFAULT 0.5,
1037
+ strength REAL DEFAULT 1.0,
1038
+ decay_tau INTEGER DEFAULT 86400000,
1039
+ last_accessed_at TEXT,
1040
+ access_count INTEGER DEFAULT 0,
1041
+ metadata TEXT,
1042
+ created_at TEXT NOT NULL,
1043
+ updated_at TEXT NOT NULL,
1044
+ search_text TEXT NOT NULL,
1045
+ embedding TEXT
1046
+ );
1047
+ CREATE INDEX IF NOT EXISTS idx_memories_created_at ON memories(created_at DESC);
1048
+ `);
1049
+ this.ensureColumn('"key" TEXT');
1050
+ try {
1051
+ this.db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_memories_key_unique ON memories("key")');
1052
+ } catch {
1053
+ }
1054
+ this.ensureColumn("essence TEXT");
1055
+ this.ensureColumn("details TEXT");
1056
+ this.ensureColumn("tags TEXT");
1057
+ this.ensureColumn("trigger_conditions TEXT");
1058
+ this.ensureColumn("importance REAL DEFAULT 0.5");
1059
+ this.ensureColumn("strength REAL DEFAULT 1.0");
1060
+ this.ensureColumn("decay_tau INTEGER DEFAULT 86400000");
1061
+ this.ensureColumn("last_accessed_at TEXT");
1062
+ this.ensureColumn("access_count INTEGER DEFAULT 0");
1063
+ this.ensureColumn("updated_at TEXT");
1064
+ this.vectorAvailable = options.enableVectorSearch === false ? false : tryLoadVectorExtension(this.db, options.vectorExtensionPath);
1065
+ try {
1066
+ try {
1067
+ this.db.exec('CREATE INDEX IF NOT EXISTS idx_memories_key ON memories("key")');
1068
+ } catch {
1069
+ }
1070
+ } catch {
1071
+ }
1072
+ this.backfillMissingKeys();
1073
+ }
1074
+ insert(row) {
1075
+ this.db.prepare(`INSERT INTO memories
1076
+ (id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, "key", search_text, embedding)
1077
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.id, row.text, row.essence, row.details, row.tags, row.trigger_conditions, row.importance, row.strength, row.decay_tau, row.last_accessed_at, row.access_count, row.metadata, row.created_at, row.updated_at, row.key, row.search_text, row.embedding);
1078
+ }
1079
+ upsertByKey(row) {
1080
+ this.db.prepare(`INSERT INTO memories
1081
+ (id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, "key", search_text, embedding)
1082
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1083
+ ON CONFLICT("key") DO UPDATE SET
1084
+ text = excluded.text,
1085
+ essence = excluded.essence,
1086
+ details = excluded.details,
1087
+ tags = excluded.tags,
1088
+ trigger_conditions = excluded.trigger_conditions,
1089
+ importance = excluded.importance,
1090
+ strength = excluded.strength,
1091
+ decay_tau = excluded.decay_tau,
1092
+ last_accessed_at = excluded.last_accessed_at,
1093
+ access_count = excluded.access_count,
1094
+ metadata = excluded.metadata,
1095
+ updated_at = excluded.updated_at,
1096
+ search_text = excluded.search_text,
1097
+ embedding = excluded.embedding`).run(row.id, row.text, row.essence, row.details, row.tags, row.trigger_conditions, row.importance, row.strength, row.decay_tau, row.last_accessed_at, row.access_count, row.metadata, row.created_at, row.updated_at, row.key, row.search_text, row.embedding);
1098
+ }
1099
+ getByKey(key) {
1100
+ return this.db.prepare(`SELECT
1101
+ id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, search_text, embedding, "key"
1102
+ FROM memories
1103
+ WHERE "key" = ?`).get(key);
1104
+ }
1105
+ deleteByKey(key) {
1106
+ const result = this.db.prepare('DELETE FROM memories WHERE "key" = ?').run(key);
1107
+ return Number(result.changes) > 0;
1108
+ }
1109
+ listAll() {
1110
+ return this.db.prepare(`SELECT id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, search_text, embedding, "key"
1111
+ FROM memories
1112
+ ORDER BY created_at DESC, id DESC`).all();
1113
+ }
1114
+ list(limit) {
1115
+ return this.db.prepare(`SELECT id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, search_text, embedding, "key"
1116
+ FROM memories
1117
+ ORDER BY created_at DESC, id DESC
1118
+ LIMIT ?`).all(limit);
1119
+ }
1120
+ listWithEmbeddings() {
1121
+ return this.db.prepare(`SELECT id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, search_text, embedding, "key"
1122
+ FROM memories
1123
+ WHERE embedding IS NOT NULL`).all();
1124
+ }
1125
+ searchByKeywords(query, topK) {
1126
+ const tokens = keywordTokens(query);
1127
+ if (tokens.length === 0) {
1128
+ return this.list(topK);
1129
+ }
1130
+ const predicates = tokens.map(() => "search_text LIKE ?").join(" OR ");
1131
+ const params = tokens.map((token) => `%${token}%`);
1132
+ const rows = this.db.prepare(`SELECT id, text, essence, details, tags, trigger_conditions, importance, strength, decay_tau, last_accessed_at, access_count, metadata, created_at, updated_at, search_text, embedding, "key"
1133
+ FROM memories
1134
+ WHERE ${predicates}
1135
+ ORDER BY created_at DESC`).all(...params);
1136
+ return rows.map((row) => ({ ...row, score: scoreKeywordMatch(row.search_text, tokens) })).sort(compareRankedRows).slice(0, topK);
1137
+ }
1138
+ clear() {
1139
+ this.db.prepare("DELETE FROM memories").run();
1140
+ }
1141
+ close() {
1142
+ this.db.close();
1143
+ }
1144
+ ensureColumn(definition) {
1145
+ try {
1146
+ this.db.exec(`ALTER TABLE memories ADD COLUMN ${definition}`);
1147
+ } catch {
1148
+ }
1149
+ }
1150
+ backfillMissingKeys() {
1151
+ try {
1152
+ this.db.exec('UPDATE memories SET "key" = id WHERE "key" IS NULL');
1153
+ } catch {
1154
+ }
1155
+ }
1156
+ };
1157
+ function tryLoadVectorExtension(db, extensionPath) {
1158
+ if (!extensionPath) {
1159
+ return false;
1160
+ }
1161
+ try {
1162
+ db.enableLoadExtension(true);
1163
+ db.loadExtension(extensionPath);
1164
+ return true;
1165
+ } catch {
1166
+ return false;
1167
+ } finally {
1168
+ db.enableLoadExtension(false);
1169
+ }
1170
+ }
1171
+ function scoreKeywordMatch(searchText, tokens) {
1172
+ return tokens.reduce((score, token) => score + Number(searchText.includes(token)), 0);
1173
+ }
1174
+ function compareRankedRows(left, right) {
1175
+ return right.score - left.score || right.created_at.localeCompare(left.created_at);
1176
+ }
1177
+
1178
+ // packages/memory/dist/memory-store.js
1179
+ var DAY_IN_MS2 = 864e5;
1180
+ var ONE_WEEK_IN_MS = 7 * DAY_IN_MS2;
1181
+ var DEFAULT_IMPORTANCE = 0.5;
1182
+ var DEFAULT_STRENGTH = 1;
1183
+ var DEFAULT_DECAY_TAU = DAY_IN_MS2;
1184
+ var KEYWORD_WEIGHTS = {
1185
+ tag: 1,
1186
+ trigger: 0.9,
1187
+ essence: 0.8,
1188
+ details: 0.4
1189
+ };
1190
+ var MemoryStore = class {
1191
+ db;
1192
+ constructor(options = {}) {
1193
+ this.db = new SqliteMemoryDb(options);
1194
+ }
1195
+ async memorize(key, essence, options = {}) {
1196
+ const existing = this.db.getByKey(key);
1197
+ const now = nowString();
1198
+ const existingEntry = existing ? toMemoryEntry(existing) : void 0;
1199
+ const normalizedImportance = clamp01(options.importance ?? existingEntry?.importance ?? DEFAULT_IMPORTANCE);
1200
+ const tags = normalizeStringArray(options.tags ?? existingEntry?.tags ?? []);
1201
+ const triggerConditions = normalizeStringArray(options.triggerConditions ?? existingEntry?.triggerConditions ?? []);
1202
+ const details = options.details === void 0 ? existingEntry?.details : options.details;
1203
+ const searchText = buildSearchTextFromParts(essence, {
1204
+ details,
1205
+ tags,
1206
+ triggerConditions,
1207
+ metadata: existingEntry?.metadata
1208
+ });
1209
+ const row = {
1210
+ id: existingEntry?.id ?? randomUUID(),
1211
+ text: essence,
1212
+ essence,
1213
+ details: details ?? null,
1214
+ metadata: existingEntry?.metadata ? JSON.stringify(existingEntry.metadata) : null,
1215
+ created_at: existingEntry?.createdAt ?? now,
1216
+ search_text: searchText,
1217
+ embedding: this.db.vectorAvailable ? JSON.stringify(createEmbedding(searchText)) : null,
1218
+ key,
1219
+ tags: JSON.stringify(tags),
1220
+ trigger_conditions: JSON.stringify(triggerConditions),
1221
+ importance: normalizedImportance,
1222
+ strength: existingEntry?.strength ?? DEFAULT_STRENGTH,
1223
+ decay_tau: existingEntry?.decayTau ?? DEFAULT_DECAY_TAU,
1224
+ last_accessed_at: existingEntry?.lastAccessedAt ?? now,
1225
+ access_count: existingEntry?.accessCount ?? 0,
1226
+ updated_at: now
1227
+ };
1228
+ this.db.upsertByKey(row);
1229
+ return toMemoryEntry(this.db.getByKey(key) ?? row);
1230
+ }
1231
+ async get(key) {
1232
+ const row = this.db.getByKey(key);
1233
+ return row ? toMemoryEntry(row) : void 0;
1234
+ }
1235
+ async update(key, changes) {
1236
+ const row = this.db.getByKey(key);
1237
+ if (!row) {
1238
+ return void 0;
1239
+ }
1240
+ const entry = toMemoryEntry(row);
1241
+ const nextEssence = changes.essence ?? entry.essence;
1242
+ const nextDetails = changes.details === void 0 ? entry.details : changes.details;
1243
+ const nextTags = changes.tags ?? entry.tags;
1244
+ const nextTriggerConditions = changes.triggerConditions ?? entry.triggerConditions;
1245
+ const nextImportance = clamp01(changes.importance ?? entry.importance);
1246
+ const searchText = buildSearchTextFromParts(nextEssence, {
1247
+ details: nextDetails,
1248
+ tags: nextTags,
1249
+ triggerConditions: nextTriggerConditions,
1250
+ metadata: entry.metadata
1251
+ });
1252
+ const updated = {
1253
+ ...row,
1254
+ text: nextEssence,
1255
+ essence: nextEssence,
1256
+ details: nextDetails ?? null,
1257
+ tags: JSON.stringify(normalizeStringArray(nextTags)),
1258
+ trigger_conditions: JSON.stringify(normalizeStringArray(nextTriggerConditions)),
1259
+ importance: nextImportance,
1260
+ search_text: searchText,
1261
+ embedding: this.db.vectorAvailable ? JSON.stringify(createEmbedding(searchText)) : row.embedding,
1262
+ updated_at: nowString()
1263
+ };
1264
+ this.db.upsertByKey(updated);
1265
+ return toMemoryEntry(updated);
1266
+ }
1267
+ async forget(key) {
1268
+ return this.db.deleteByKey(key);
1269
+ }
1270
+ async recall(query, limit = 5) {
1271
+ const safeLimit = Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 5;
1272
+ const tokens = keywordTokens(query);
1273
+ if (tokens.length === 0) {
1274
+ return [];
1275
+ }
1276
+ const now = nowString();
1277
+ const candidates = this.db.listAll().map((row) => toMemoryEntry(row));
1278
+ const scored = candidates.map((entry) => {
1279
+ const keywordScore = computeKeywordScore(entry, tokens);
1280
+ if (keywordScore <= 0) {
1281
+ return void 0;
1282
+ }
1283
+ const retention = computeRetention(entry.strength, entry.lastAccessedAt ?? entry.updatedAt, entry.decayTau, entry.importance, entry.accessCount);
1284
+ return {
1285
+ entry,
1286
+ keywordScore,
1287
+ retention
1288
+ };
1289
+ }).filter((candidate) => candidate !== void 0).map((candidate) => {
1290
+ const finalScore = candidate.keywordScore * 0.7 + candidate.retention * 0.3;
1291
+ return { ...candidate, finalScore };
1292
+ }).sort((left, right) => right.finalScore - left.finalScore || right.retention - left.retention);
1293
+ const results = [];
1294
+ for (const selected of scored.slice(0, safeLimit)) {
1295
+ const strengthenedStrength = reinforceOnAccess(selected.entry.strength, selected.entry.importance);
1296
+ const strengthenedCount = selected.entry.accessCount + 1;
1297
+ const row = this.db.getByKey(selected.entry.key);
1298
+ if (row) {
1299
+ this.db.upsertByKey({
1300
+ ...row,
1301
+ strength: strengthenedStrength,
1302
+ access_count: strengthenedCount,
1303
+ last_accessed_at: now,
1304
+ updated_at: now
1305
+ });
1306
+ results.push({
1307
+ ...selected.entry,
1308
+ strength: strengthenedStrength,
1309
+ accessCount: strengthenedCount,
1310
+ lastAccessedAt: now,
1311
+ updatedAt: now
1312
+ });
1313
+ } else {
1314
+ results.push({
1315
+ ...selected.entry,
1316
+ strength: strengthenedStrength,
1317
+ accessCount: strengthenedCount,
1318
+ lastAccessedAt: now,
1319
+ updatedAt: now
1320
+ });
1321
+ }
1322
+ }
1323
+ return results;
1324
+ }
1325
+ async consolidate() {
1326
+ const now = Date.now();
1327
+ const nowIso = toISOString(now);
1328
+ const weekAgo = now - ONE_WEEK_IN_MS;
1329
+ const rows = this.db.listAll();
1330
+ const entries = rows.map((row) => toMemoryEntry(row));
1331
+ const potentialDuplicates = [];
1332
+ for (let index = 0; index < entries.length; index += 1) {
1333
+ for (let inner = index + 1; inner < entries.length; inner += 1) {
1334
+ const left = entries[index];
1335
+ const right = entries[inner];
1336
+ if (computeEssenceSimilarity(left.essence, right.essence) > 0.8) {
1337
+ potentialDuplicates.push([left.key, right.key]);
1338
+ }
1339
+ }
1340
+ }
1341
+ let forgotten = 0;
1342
+ let strengthened = 0;
1343
+ const survivors = [];
1344
+ for (const row of rows) {
1345
+ const entry = toMemoryEntry(row);
1346
+ const retention = computeRetention(entry.strength, entry.lastAccessedAt ?? entry.updatedAt, entry.decayTau, entry.importance, entry.accessCount);
1347
+ if (retention < 0.1) {
1348
+ if (this.db.deleteByKey(entry.key)) {
1349
+ forgotten += 1;
1350
+ }
1351
+ continue;
1352
+ }
1353
+ const accessedRecently = entry.lastAccessedAt ? Date.parse(entry.lastAccessedAt) >= weekAgo : false;
1354
+ if (accessedRecently) {
1355
+ const nextStrength = reinforceOnAccess(entry.strength, entry.importance);
1356
+ const nextCount = entry.accessCount + 1;
1357
+ const searchText = buildSearchTextFromParts(entry.essence, {
1358
+ details: entry.details,
1359
+ tags: entry.tags,
1360
+ triggerConditions: entry.triggerConditions,
1361
+ metadata: entry.metadata
1362
+ });
1363
+ const updated = {
1364
+ ...row,
1365
+ strength: nextStrength,
1366
+ access_count: nextCount,
1367
+ last_accessed_at: nowIso,
1368
+ updated_at: nowIso,
1369
+ search_text: searchText,
1370
+ embedding: this.db.vectorAvailable ? JSON.stringify(createEmbedding(searchText)) : row.embedding
1371
+ };
1372
+ this.db.upsertByKey(updated);
1373
+ survivors.push(toMemoryEntry(updated));
1374
+ strengthened += 1;
1375
+ } else {
1376
+ survivors.push(entry);
1377
+ }
1378
+ }
1379
+ return {
1380
+ forgotten,
1381
+ strengthened,
1382
+ total: this.db.listAll().length,
1383
+ potentialDuplicates
1384
+ };
1385
+ }
1386
+ async reflect() {
1387
+ const rows = this.db.listAll();
1388
+ if (rows.length === 0) {
1389
+ return "## No memories yet.";
1390
+ }
1391
+ const groups = /* @__PURE__ */ new Map();
1392
+ for (const entry of rows.map(toMemoryEntry)) {
1393
+ const tag = entry.tags[0] ?? "untagged";
1394
+ const bucket = groups.get(tag) ?? [];
1395
+ bucket.push(entry);
1396
+ groups.set(tag, bucket);
1397
+ }
1398
+ const lines = [];
1399
+ for (const [tag, memories] of [...groups.entries()].sort(([left], [right]) => left.localeCompare(right))) {
1400
+ lines.push(`## ${tag}`);
1401
+ for (const memory of memories) {
1402
+ lines.push(`- **${memory.key}**: ${memory.essence}`);
1403
+ }
1404
+ lines.push("");
1405
+ }
1406
+ return lines.join("\n").trim();
1407
+ }
1408
+ async count() {
1409
+ return this.db.listAll().length;
1410
+ }
1411
+ async search(query, topK = 5) {
1412
+ const safeTopK = Number.isFinite(topK) ? Math.max(0, Math.floor(topK)) : 5;
1413
+ if (safeTopK <= 0) {
1414
+ return [];
1415
+ }
1416
+ if (this.db.vectorAvailable) {
1417
+ const queryEmbedding = createEmbedding(query);
1418
+ return this.db.listWithEmbeddings().map((row) => ({ row, score: cosineSimilarity(queryEmbedding, parseEmbedding(row.embedding)) })).sort((left, right) => right.score - left.score || compareRows(left.row, right.row)).slice(0, safeTopK).map(({ row }) => toMemoryEntry(row));
1419
+ }
1420
+ return this.db.searchByKeywords(query, safeTopK).map((row) => toMemoryEntry(row));
1421
+ }
1422
+ async list(limit = 50) {
1423
+ const safeLimit = Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 50;
1424
+ if (safeLimit === 0) {
1425
+ return [];
1426
+ }
1427
+ return this.db.list(safeLimit).map((row) => toMemoryEntry(row));
1428
+ }
1429
+ async store(text2, metadata = null) {
1430
+ const key = randomUUID();
1431
+ const entry = await this.memorize(key, text2, { tags: ["auto"] });
1432
+ const row = this.db.getByKey(key);
1433
+ if (row) {
1434
+ const serializedMetadata = metadata ? JSON.stringify(metadata) : null;
1435
+ if (row.metadata !== serializedMetadata) {
1436
+ const searchText = buildSearchTextFromParts(entry.essence, {
1437
+ details: entry.details,
1438
+ tags: entry.tags,
1439
+ triggerConditions: entry.triggerConditions,
1440
+ metadata
1441
+ });
1442
+ this.db.upsertByKey({
1443
+ ...row,
1444
+ metadata: serializedMetadata,
1445
+ search_text: searchText,
1446
+ embedding: this.db.vectorAvailable ? JSON.stringify(createEmbedding(searchText)) : row.embedding
1447
+ });
1448
+ }
1449
+ }
1450
+ return entry.id;
1451
+ }
1452
+ async clear() {
1453
+ this.db.clear();
1454
+ }
1455
+ close() {
1456
+ this.db.close();
1457
+ }
1458
+ };
1459
+ function buildSearchTextFromParts(essence, context) {
1460
+ const searchMetadata = {
1461
+ tags: context.tags,
1462
+ triggerConditions: context.triggerConditions,
1463
+ details: context.details,
1464
+ ...context.metadata ?? {}
1465
+ };
1466
+ return buildSearchText(essence, searchMetadata);
1467
+ }
1468
+ function computeEssenceSimilarity(left, right) {
1469
+ const leftTokens = new Set(keywordTokens(left));
1470
+ const rightTokens = new Set(keywordTokens(right));
1471
+ const union = /* @__PURE__ */ new Set([...leftTokens, ...rightTokens]);
1472
+ if (union.size === 0) {
1473
+ return 0;
1474
+ }
1475
+ let overlap = 0;
1476
+ for (const token of leftTokens) {
1477
+ if (rightTokens.has(token)) {
1478
+ overlap += 1;
1479
+ }
1480
+ }
1481
+ return overlap / union.size;
1482
+ }
1483
+ function computeKeywordScore(entry, tokens) {
1484
+ const normalizedTokens = new Set(tokens);
1485
+ return Number(matchTokens(entry.tags, normalizedTokens)) * KEYWORD_WEIGHTS.tag + Number(matchText(entry.triggerConditions, normalizedTokens)) * KEYWORD_WEIGHTS.trigger + Number(matchText([entry.essence], normalizedTokens)) * KEYWORD_WEIGHTS.essence + Number(matchText(entry.details ? [entry.details] : [], normalizedTokens)) * KEYWORD_WEIGHTS.details;
1486
+ }
1487
+ function compareRows(left, right) {
1488
+ return right.updated_at.localeCompare(left.updated_at) || right.created_at.localeCompare(left.created_at) || right.id.localeCompare(left.id);
1489
+ }
1490
+ function parseEmbedding(embedding) {
1491
+ if (!embedding) {
1492
+ return [];
1493
+ }
1494
+ const value = JSON.parse(embedding);
1495
+ return Array.isArray(value) ? value.filter((item) => typeof item === "number") : [];
1496
+ }
1497
+ function parseMetadata(metadata) {
1498
+ if (!metadata) {
1499
+ return null;
1500
+ }
1501
+ const value = JSON.parse(metadata);
1502
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1503
+ }
1504
+ function parseStringArray(raw) {
1505
+ if (!raw) {
1506
+ return [];
1507
+ }
1508
+ const value = JSON.parse(raw);
1509
+ if (!Array.isArray(value)) {
1510
+ return [];
1511
+ }
1512
+ return value.flatMap((item) => typeof item === "string" ? [item.trim()] : []).filter(Boolean);
1513
+ }
1514
+ function matchText(values, tokens) {
1515
+ return values.flatMap((value) => keywordTokens(value)).some((token) => tokens.has(token));
1516
+ }
1517
+ function matchTokens(values, tokens) {
1518
+ const normalizedValues = values.map((value) => value.toLowerCase());
1519
+ return normalizedValues.some((value) => {
1520
+ if (tokens.has(value)) {
1521
+ return true;
1522
+ }
1523
+ return [...tokens].some((token) => value.includes(token));
1524
+ });
1525
+ }
1526
+ function normalizeStringArray(values) {
1527
+ return values.map((value) => value.toLowerCase().trim()).filter((value, index, array) => value.length > 0 && !array.slice(0, index).includes(value));
1528
+ }
1529
+ function toMemoryEntry(row) {
1530
+ const tags = normalizeStringArray(parseStringArray(row.tags));
1531
+ const triggerConditions = normalizeStringArray(parseStringArray(row.trigger_conditions));
1532
+ const essence = row.essence || row.text;
1533
+ return {
1534
+ id: row.id,
1535
+ key: row.key ?? row.id,
1536
+ essence,
1537
+ text: essence,
1538
+ details: row.details ?? void 0,
1539
+ tags,
1540
+ triggerConditions,
1541
+ importance: clamp01(row.importance),
1542
+ strength: clamp01(row.strength),
1543
+ decayTau: clampPositiveNumber(row.decay_tau, DEFAULT_DECAY_TAU),
1544
+ lastAccessedAt: row.last_accessed_at ?? void 0,
1545
+ accessCount: Math.max(0, Number.isFinite(row.access_count) ? row.access_count : 0),
1546
+ metadata: parseMetadata(row.metadata),
1547
+ createdAt: row.created_at,
1548
+ updatedAt: row.updated_at || row.created_at
1549
+ };
1550
+ }
1551
+ function clamp01(value) {
1552
+ return clamp2(value, 0, 1);
1553
+ }
1554
+ function clamp2(value, min, max) {
1555
+ if (!Number.isFinite(value)) {
1556
+ return min;
1557
+ }
1558
+ return Math.max(min, Math.min(max, value));
1559
+ }
1560
+ function clampPositiveNumber(value, fallback) {
1561
+ return Number.isFinite(value) && value > 0 ? value : fallback;
1562
+ }
1563
+ function nowString() {
1564
+ return (/* @__PURE__ */ new Date()).toISOString();
1565
+ }
1566
+ function toISOString(time) {
1567
+ return new Date(time).toISOString();
1568
+ }
1569
+
1570
+ // packages/memory/dist/default-store.js
1571
+ var defaultStore = null;
1572
+ function createMemoryStore(options = {}) {
1573
+ return new MemoryStore({
1574
+ dbPath: options.dbPath ?? join(homedir2(), ".va-claw", "memory.db"),
1575
+ enableVectorSearch: options.enableVectorSearch,
1576
+ vectorExtensionPath: options.vectorExtensionPath
1577
+ });
1578
+ }
1579
+ async function store(text2, metadata) {
1580
+ return getDefaultStore().store(text2, metadata ?? null);
1581
+ }
1582
+ async function memorize(key, essence, options) {
1583
+ return getDefaultStore().memorize(key, essence, options);
1584
+ }
1585
+ async function get(key) {
1586
+ return getDefaultStore().get(key);
1587
+ }
1588
+ async function update(key, changes) {
1589
+ return getDefaultStore().update(key, changes);
1590
+ }
1591
+ async function forget(key) {
1592
+ return getDefaultStore().forget(key);
1593
+ }
1594
+ async function recall(query, limit = 5) {
1595
+ return getDefaultStore().recall(query, limit);
1596
+ }
1597
+ async function consolidate() {
1598
+ return getDefaultStore().consolidate();
1599
+ }
1600
+ async function reflect() {
1601
+ return getDefaultStore().reflect();
1602
+ }
1603
+ async function count() {
1604
+ return getDefaultStore().count();
1605
+ }
1606
+ async function search(query, topK) {
1607
+ return getDefaultStore().search(query, topK);
1608
+ }
1609
+ async function list(limit) {
1610
+ return getDefaultStore().list(limit);
1611
+ }
1612
+ async function clear() {
1613
+ return getDefaultStore().clear();
1614
+ }
1615
+ function getDefaultStore() {
1616
+ defaultStore ??= createMemoryStore();
1617
+ return defaultStore;
1618
+ }
1619
+
1620
+ // packages/skills/dist/frontmatter.js
1621
+ var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
1622
+ function parseSkillMarkdown(source, path) {
1623
+ const match = FRONTMATTER_RE.exec(source);
1624
+ if (!match) {
1625
+ throw new Error(`Skill "${path}" is missing YAML frontmatter.`);
1626
+ }
1627
+ const frontmatter = parseFrontmatterBlock(match[1]);
1628
+ return {
1629
+ ...frontmatter,
1630
+ content: match[2].trim(),
1631
+ path
1632
+ };
1633
+ }
1634
+ function parseFrontmatterBlock(block) {
1635
+ const values = /* @__PURE__ */ new Map();
1636
+ const lines = block.split(/\r?\n/);
1637
+ for (let index = 0; index < lines.length; index += 1) {
1638
+ const rawLine = lines[index];
1639
+ const line = rawLine.trim();
1640
+ if (line === "") {
1641
+ continue;
1642
+ }
1643
+ const separator = line.indexOf(":");
1644
+ if (separator === -1) {
1645
+ throw new Error(`Invalid frontmatter line: ${rawLine}`);
1646
+ }
1647
+ const key = line.slice(0, separator).trim();
1648
+ const value = line.slice(separator + 1).trim();
1649
+ if (value !== "") {
1650
+ values.set(key, value);
1651
+ continue;
1652
+ }
1653
+ const baseIndent = rawLine.length - rawLine.trimStart().length;
1654
+ const items = [];
1655
+ while (index + 1 < lines.length) {
1656
+ const nextRawLine = lines[index + 1];
1657
+ const nextLine = nextRawLine.trim();
1658
+ if (nextLine === "") {
1659
+ index += 1;
1660
+ continue;
1661
+ }
1662
+ const nextIndent = nextRawLine.length - nextRawLine.trimStart().length;
1663
+ if (nextIndent <= baseIndent) {
1664
+ break;
1665
+ }
1666
+ if (!nextLine.startsWith("-")) {
1667
+ throw new Error(`Invalid frontmatter line: ${nextRawLine}`);
1668
+ }
1669
+ items.push(nextLine.slice(1).trim());
1670
+ index += 1;
1671
+ }
1672
+ values.set(key, items);
1673
+ }
1674
+ const name = parseScalar(values.get("name"), "name");
1675
+ const description = parseScalar(values.get("description"), "description");
1676
+ const version = parseScalar(values.get("version"), "version");
1677
+ const triggers = parseArray(values.get("triggers"), "triggers");
1678
+ return { name, description, version, triggers };
1679
+ }
1680
+ function parseScalar(rawValue, field) {
1681
+ if (!rawValue) {
1682
+ throw new Error(`Skill frontmatter is missing "${field}".`);
1683
+ }
1684
+ if (Array.isArray(rawValue)) {
1685
+ throw new Error(`Skill frontmatter field "${field}" must be a scalar.`);
1686
+ }
1687
+ if (rawValue.startsWith("'") && rawValue.endsWith("'") || rawValue.startsWith('"') && rawValue.endsWith('"')) {
1688
+ return rawValue.slice(1, -1);
1689
+ }
1690
+ return rawValue;
1691
+ }
1692
+ function parseArray(rawValue, field) {
1693
+ if (!rawValue) {
1694
+ throw new Error(`Skill frontmatter is missing "${field}".`);
1695
+ }
1696
+ if (Array.isArray(rawValue)) {
1697
+ return rawValue.map((item) => parseScalar(item.trim(), field));
1698
+ }
1699
+ if (!rawValue.startsWith("[") || !rawValue.endsWith("]")) {
1700
+ throw new Error(`Skill frontmatter field "${field}" must be an array.`);
1701
+ }
1702
+ const body = rawValue.slice(1, -1).trim();
1703
+ if (body === "") {
1704
+ return [];
1705
+ }
1706
+ return splitInlineArray(body).map((item) => parseScalar(item.trim(), field));
1707
+ }
1708
+ function splitInlineArray(value) {
1709
+ const items = [];
1710
+ let current = "";
1711
+ let quote = null;
1712
+ for (const character of value) {
1713
+ if ((character === "'" || character === '"') && quote === null) {
1714
+ quote = character;
1715
+ current += character;
1716
+ continue;
1717
+ }
1718
+ if (quote !== null && character === quote) {
1719
+ quote = null;
1720
+ current += character;
1721
+ continue;
1722
+ }
1723
+ if (character === "," && quote === null) {
1724
+ items.push(current);
1725
+ current = "";
1726
+ continue;
1727
+ }
1728
+ current += character;
1729
+ }
1730
+ if (current !== "") {
1731
+ items.push(current);
1732
+ }
1733
+ return items;
1734
+ }
1735
+
1736
+ // packages/skills/dist/paths.js
1737
+ import { homedir as homedir3 } from "node:os";
1738
+ import { isAbsolute, join as join2, resolve as resolve2 } from "node:path";
1739
+ var overrides = {};
1740
+ function resolveInstalledSkillsDir() {
1741
+ const baseDir = overrides.homeDir ? resolve2(overrides.homeDir) : resolve2(homedir3(), ".va-claw");
1742
+ return join2(baseDir, "skills");
1743
+ }
1744
+ function resolveProjectSkillsDir() {
1745
+ const baseDir = overrides.projectDir ? resolve2(overrides.projectDir) : process.cwd();
1746
+ return join2(baseDir, "skills");
1747
+ }
1748
+ function resolveSkillLookupDirs(dir) {
1749
+ if (dir) {
1750
+ return [resolvePathInput(dir)];
1751
+ }
1752
+ return [resolveProjectSkillsDir(), resolveInstalledSkillsDir()];
1753
+ }
1754
+ function resolvePathInput(value) {
1755
+ if (value === "~") {
1756
+ return homedir3();
1757
+ }
1758
+ if (value.startsWith("~/")) {
1759
+ return resolve2(homedir3(), value.slice(2));
1760
+ }
1761
+ return isAbsolute(value) ? value : resolve2(value);
1762
+ }
1763
+ function toSkillFileName(name) {
1764
+ const normalized = name.trim().replace(/\.md$/i, "");
1765
+ if (normalized === "") {
1766
+ throw new Error("Skill name cannot be empty.");
1767
+ }
1768
+ if (!/^[a-z0-9][a-z0-9-_]*$/i.test(normalized)) {
1769
+ throw new Error(`Invalid skill name: ${name}`);
1770
+ }
1771
+ return `${normalized}.md`;
1772
+ }
1773
+
1774
+ // packages/skills/dist/search.js
1775
+ function matchesSkillQuery(skill, query) {
1776
+ const normalizedQuery = normalize(query);
1777
+ if (normalizedQuery === "") {
1778
+ return true;
1779
+ }
1780
+ const haystack = normalize([skill.name, skill.description, ...skill.triggers].join(" "));
1781
+ if (haystack.includes(normalizedQuery)) {
1782
+ return true;
1783
+ }
1784
+ return tokenize2(query).some((token) => token.length > 1 && haystack.includes(token));
1785
+ }
1786
+ function tokenize2(value) {
1787
+ return normalize(value).split(/[^a-z0-9]+/).filter(Boolean);
1788
+ }
1789
+ function normalize(value) {
1790
+ return value.trim().toLowerCase();
1791
+ }
1792
+
1793
+ // packages/skills/dist/store.js
1794
+ import { access, mkdir as mkdir2, readFile as readFile2, readdir, rm, writeFile as writeFile2 } from "node:fs/promises";
1795
+ import { join as join3 } from "node:path";
1796
+ async function loadSkill(nameOrPath) {
1797
+ const path = await resolveSkillPath(nameOrPath);
1798
+ return readSkillFile(path);
1799
+ }
1800
+ async function listSkills(dir) {
1801
+ const skills = [];
1802
+ const seen = /* @__PURE__ */ new Set();
1803
+ for (const lookupDir of resolveSkillLookupDirs(dir)) {
1804
+ for (const skill of await readSkillsFromDir(lookupDir)) {
1805
+ if (seen.has(skill.name)) {
1806
+ continue;
1807
+ }
1808
+ seen.add(skill.name);
1809
+ skills.push(skill);
1810
+ }
1811
+ }
1812
+ return skills;
1813
+ }
1814
+ async function installSkill(content, name) {
1815
+ const skillPath = join3(resolveInstalledSkillsDir(), toSkillFileName(name));
1816
+ parseSkillMarkdown(content, skillPath);
1817
+ await mkdir2(resolveInstalledSkillsDir(), { recursive: true });
1818
+ await writeFile2(skillPath, content, "utf8");
1819
+ return skillPath;
1820
+ }
1821
+ async function removeSkill(name) {
1822
+ await rm(join3(resolveInstalledSkillsDir(), toSkillFileName(name)), { force: true });
1823
+ }
1824
+ function injectSkillIntoPrompt(skill, basePrompt) {
1825
+ const prompt = basePrompt.trimEnd();
1826
+ const skillBlock = [`[Skill: ${skill.name}@${skill.version}]`, skill.content.trim()].join("\n");
1827
+ return prompt === "" ? skillBlock : `${prompt}
1828
+
1829
+ ${skillBlock}`;
1830
+ }
1831
+ async function resolveSkillPath(nameOrPath) {
1832
+ const candidates = looksLikePath(nameOrPath) ? [resolvePathInput(nameOrPath)] : resolveSkillLookupDirs().map((dir) => join3(dir, toSkillFileName(nameOrPath)));
1833
+ for (const candidate of candidates) {
1834
+ if (await exists(candidate)) {
1835
+ return candidate;
1836
+ }
1837
+ }
1838
+ throw new Error(`Skill not found: ${nameOrPath}`);
1839
+ }
1840
+ async function readSkillsFromDir(dir) {
1841
+ if (!await exists(dir)) {
1842
+ return [];
1843
+ }
1844
+ const names = (await readdir(dir)).filter((entry) => entry.toLowerCase().endsWith(".md")).sort();
1845
+ return Promise.all(names.map((name) => readSkillFile(join3(dir, name))));
1846
+ }
1847
+ async function readSkillFile(path) {
1848
+ return parseSkillMarkdown(await readFile2(path, "utf8"), path);
1849
+ }
1850
+ async function exists(path) {
1851
+ try {
1852
+ await access(path);
1853
+ return true;
1854
+ } catch {
1855
+ return false;
1856
+ }
1857
+ }
1858
+ function looksLikePath(value) {
1859
+ return /[\\/]/.test(value) || value.startsWith(".") || value.startsWith("~") || value.endsWith(".md");
1860
+ }
1861
+
1862
+ // packages/daemon/dist/wake-cycle.js
1863
+ var DEFAULT_WARN2 = (message) => console.warn(message);
1864
+ async function runWakeCycle(config, deps = {}) {
1865
+ const adapter = await (deps.detect ?? detectCliAdapter)({ warn: deps.warn });
1866
+ if (!adapter) {
1867
+ return null;
1868
+ }
1869
+ const prompt = await resolveWakePrompt(config, deps);
1870
+ const spawnOptions = {
1871
+ cwd: process.cwd(),
1872
+ encoding: "utf8",
1873
+ env: {
1874
+ ...readProcessEnv(),
1875
+ CLAUDECODE: void 0,
1876
+ CLAUDE_CODE_SESSION: void 0
1877
+ },
1878
+ maxBuffer: 10 * 1024 * 1024
1879
+ };
1880
+ const result = (deps.spawn ?? spawnSync2)(adapter.command, [...adapter.args, prompt], spawnOptions);
1881
+ if (result.status !== 0) {
1882
+ (deps.warn ?? DEFAULT_WARN2)(`[va-claw/daemon] ${adapter.name} wake failed: ${readStderr(result.stderr)}`);
1883
+ return null;
1884
+ }
1885
+ const wokeAt = (deps.now ?? (() => /* @__PURE__ */ new Date()))();
1886
+ await (deps.storeMemory ?? store)(result.stdout ?? "", {
1887
+ source: "va-claw-daemon",
1888
+ kind: "wake",
1889
+ cli: adapter.name,
1890
+ identity: config.name,
1891
+ wokeAt: wokeAt.toISOString()
1892
+ });
1893
+ return wokeAt;
1894
+ }
1895
+ function readStderr(stderr) {
1896
+ if (typeof stderr === "string" && stderr.trim() !== "") {
1897
+ return stderr.trim();
1898
+ }
1899
+ return "unknown error";
1900
+ }
1901
+ function readProcessEnv() {
1902
+ return process.env ?? {};
1903
+ }
1904
+ async function resolveWakePrompt(config, deps) {
1905
+ try {
1906
+ const skills = await (deps.listSkills ?? listSkills)();
1907
+ return skills.filter((skill) => matchesSkillQuery(skill, config.wakePrompt)).reduce((prompt, skill) => (deps.injectSkill ?? injectSkillIntoPrompt)(skill, prompt), config.wakePrompt);
1908
+ } catch (error) {
1909
+ (deps.warn ?? DEFAULT_WARN2)(`[va-claw/daemon] skill injection skipped: ${String(error)}`);
1910
+ return config.wakePrompt;
1911
+ }
1912
+ }
1913
+
1914
+ // packages/daemon/dist/runtime.js
1915
+ var runtimeState = {
1916
+ discord: null,
1917
+ job: null,
1918
+ wakeCount: 0
1919
+ };
1920
+ var runtimeDeps = {
1921
+ createScheduler(pattern, onTick) {
1922
+ const job = new E(pattern, { catch: false }, () => {
1923
+ void onTick().catch((error) => {
1924
+ console.warn(`[va-claw/daemon] wake tick failed: ${String(error)}`);
1925
+ });
1926
+ });
1927
+ return { stop: () => job.stop() };
1928
+ },
1929
+ async startDiscord(config) {
1930
+ const moduleUrl = new URL("../../channels/discord/dist/index.js", import.meta.url);
1931
+ const channelModule = await import(moduleUrl.href);
1932
+ return channelModule.startDiscordChannel(config);
1933
+ },
1934
+ wake: runWakeCycle
1935
+ };
1936
+ async function startDaemon(config) {
1937
+ await stopDaemon();
1938
+ runtimeState.wakeCount = 0;
1939
+ runtimeState.lastWakeAt = void 0;
1940
+ runtimeState.discord = null;
1941
+ if (config.channels.discord.autoStart) {
1942
+ runtimeState.discord = await runtimeDeps.startDiscord({
1943
+ token: config.channels.discord.token,
1944
+ clientId: config.channels.discord.clientId,
1945
+ cliCommand: config.channels.discord.cliCommand
1946
+ });
1947
+ }
1948
+ runtimeState.job = runtimeDeps.createScheduler(config.loopInterval, async () => {
1949
+ const wokeAt = await runtimeDeps.wake(config);
1950
+ if (!wokeAt) {
1951
+ return;
1952
+ }
1953
+ runtimeState.lastWakeAt = wokeAt;
1954
+ runtimeState.wakeCount += 1;
1955
+ });
1956
+ }
1957
+ async function stopDaemon() {
1958
+ await runtimeState.discord?.stop();
1959
+ runtimeState.discord = null;
1960
+ runtimeState.job?.stop();
1961
+ runtimeState.job = null;
1962
+ }
1963
+ async function getDaemonStatus() {
1964
+ return {
1965
+ discord: runtimeState.discord?.status() ?? "disconnected",
1966
+ running: runtimeState.job !== null,
1967
+ lastWakeAt: runtimeState.lastWakeAt ? new Date(runtimeState.lastWakeAt) : void 0,
1968
+ wakeCount: runtimeState.wakeCount
1969
+ };
1970
+ }
1971
+
1972
+ // packages/daemon/dist/service.js
1973
+ import { mkdir as mkdir3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
1974
+ import { dirname as dirname4 } from "node:path";
1975
+ import { spawnSync as spawnSync3 } from "node:child_process";
1976
+
1977
+ // packages/daemon/dist/service-files.js
1978
+ import { homedir as homedir4 } from "node:os";
1979
+ import { dirname as dirname3, join as join4, resolve as resolve3 } from "node:path";
1980
+ import { fileURLToPath } from "node:url";
1981
+ function createServiceDefinition(type) {
1982
+ const packageRoot = resolve3(dirname3(fileURLToPath(import.meta.url)), "..");
1983
+ const repoRoot = resolve3(packageRoot, "../..");
1984
+ const runnerPath = join4(packageRoot, "dist", "runner.js");
1985
+ const nodePath = process.execPath;
1986
+ if (type === "launchd") {
1987
+ return {
1988
+ path: join4(homedir4(), "Library", "LaunchAgents", "com.va-claw.daemon.plist"),
1989
+ content: renderLaunchdPlist(repoRoot, [nodePath, runnerPath]),
1990
+ command: "launchctl",
1991
+ args: ["load", join4(homedir4(), "Library", "LaunchAgents", "com.va-claw.daemon.plist")]
1992
+ };
1993
+ }
1994
+ return {
1995
+ path: join4(homedir4(), ".config", "systemd", "user", "va-claw.service"),
1996
+ content: renderSystemdUnit(repoRoot, [nodePath, runnerPath]),
1997
+ command: "systemctl",
1998
+ args: ["--user", "enable", "--now", "va-claw.service"]
1999
+ };
2000
+ }
2001
+ function createUninstallCommand(type) {
2002
+ if (type === "launchd") {
2003
+ return {
2004
+ command: "launchctl",
2005
+ args: ["unload", join4(homedir4(), "Library", "LaunchAgents", "com.va-claw.daemon.plist")]
2006
+ };
2007
+ }
2008
+ return {
2009
+ command: "systemctl",
2010
+ args: ["--user", "disable", "--now", "va-claw.service"]
2011
+ };
2012
+ }
2013
+ function renderLaunchdPlist(workingDirectory, programArguments) {
2014
+ const argsXml = programArguments.map((arg) => ` <string>${escapeXml(arg)}</string>`).join("\n");
2015
+ return `<?xml version="1.0" encoding="UTF-8"?>
2016
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
2017
+ <plist version="1.0">
2018
+ <dict>
2019
+ <key>Label</key>
2020
+ <string>com.va-claw.daemon</string>
2021
+ <key>ProgramArguments</key>
2022
+ <array>
2023
+ ${argsXml}
2024
+ </array>
2025
+ <key>WorkingDirectory</key>
2026
+ <string>${escapeXml(workingDirectory)}</string>
2027
+ <key>RunAtLoad</key>
2028
+ <true/>
2029
+ <key>KeepAlive</key>
2030
+ <true/>
2031
+ </dict>
2032
+ </plist>
2033
+ `;
2034
+ }
2035
+ function renderSystemdUnit(workingDirectory, programArguments) {
2036
+ return `[Unit]
2037
+ Description=va-claw daemon
2038
+
2039
+ [Service]
2040
+ Type=simple
2041
+ WorkingDirectory=${workingDirectory}
2042
+ ExecStart=${programArguments.map(quoteSystemdArg).join(" ")}
2043
+ Restart=always
2044
+ RestartSec=5
2045
+
2046
+ [Install]
2047
+ WantedBy=default.target
2048
+ `;
2049
+ }
2050
+ function escapeXml(value) {
2051
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
2052
+ }
2053
+ function quoteSystemdArg(value) {
2054
+ return `'${value.replaceAll("'", `'\\''`)}'`;
2055
+ }
2056
+
2057
+ // packages/daemon/dist/service.js
2058
+ async function installDaemonService(type) {
2059
+ const definition = createServiceDefinition(type);
2060
+ await mkdir3(dirname4(definition.path), { recursive: true });
2061
+ await writeFile3(definition.path, definition.content, "utf8");
2062
+ if (type === "systemd") {
2063
+ runCommand("systemctl", ["--user", "daemon-reload"]);
2064
+ }
2065
+ runCommand(definition.command, definition.args);
2066
+ }
2067
+ async function uninstallDaemonService(type) {
2068
+ const definition = createServiceDefinition(type);
2069
+ const uninstall = createUninstallCommand(type);
2070
+ runCommand(uninstall.command, uninstall.args, true);
2071
+ await rm2(definition.path, { force: true });
2072
+ if (type === "systemd") {
2073
+ runCommand("systemctl", ["--user", "daemon-reload"], true);
2074
+ }
2075
+ }
2076
+ function runCommand(command, args, allowFailure = false) {
2077
+ const result = spawnSync3(command, args, { encoding: "utf8" });
2078
+ if (allowFailure || result.status === 0) {
2079
+ return;
2080
+ }
2081
+ const stderr = result.stderr?.trim() || result.stdout?.trim() || "unknown error";
2082
+ throw new Error(`[va-claw/daemon] command failed: ${command} ${args.join(" ")}: ${stderr}`);
2083
+ }
2084
+
2085
+ // packages/cli/dist/install-files.js
2086
+ import { access as access2, mkdir as mkdir4, readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
2087
+ import { homedir as homedir5 } from "node:os";
2088
+ import { dirname as dirname5, join as join5 } from "node:path";
2089
+ var CLAUDE_MARKERS = {
2090
+ start: "<!-- va-claw:identity:start -->",
2091
+ end: "<!-- va-claw:identity:end -->"
2092
+ };
2093
+ var CODEX_MARKERS = {
2094
+ start: "<!-- va-claw:codex:start -->",
2095
+ end: "<!-- va-claw:codex:end -->"
2096
+ };
2097
+ function resolveClaudeMdPath(home = homedir5()) {
2098
+ return join5(home, ".claude", "CLAUDE.md");
2099
+ }
2100
+ function resolveCodexInstructionsPath(home = homedir5()) {
2101
+ return join5(home, ".codex", "instructions.md");
2102
+ }
2103
+ function resolveMemoryDbPath(home = homedir5()) {
2104
+ return join5(home, ".va-claw", "memory.db");
2105
+ }
2106
+ async function fileExists(path) {
2107
+ try {
2108
+ await access2(path);
2109
+ return true;
2110
+ } catch {
2111
+ return false;
2112
+ }
2113
+ }
2114
+ async function upsertManagedBlock(path, block, markers) {
2115
+ const current = (await readOptionalFile(path)).trim();
2116
+ const next = appendManagedBlock(current, block, markers);
2117
+ await mkdir4(dirname5(path), { recursive: true });
2118
+ await writeFile4(path, next, "utf8");
2119
+ }
2120
+ async function removeManagedBlock(path, markers) {
2121
+ const current = await readOptionalFile(path);
2122
+ if (current === "") {
2123
+ return;
2124
+ }
2125
+ const next = stripManagedBlock(current, markers).trim();
2126
+ await mkdir4(dirname5(path), { recursive: true });
2127
+ await writeFile4(path, next === "" ? "" : `${next}
2128
+ `, "utf8");
2129
+ }
2130
+ function wrapCodexPrompt(prompt) {
2131
+ return [CODEX_MARKERS.start, prompt.trim(), CODEX_MARKERS.end].join("\n");
2132
+ }
2133
+ function appendManagedBlock(source, block, markers) {
2134
+ const stripped = stripManagedBlock(source, markers).trim();
2135
+ const suffix = block.trim();
2136
+ return stripped === "" ? `${suffix}
2137
+ ` : `${stripped}
2138
+
2139
+ ${suffix}
2140
+ `;
2141
+ }
2142
+ function stripManagedBlock(source, markers) {
2143
+ const escaped = [markers.start, markers.end].map(escapeRegExp);
2144
+ const pattern = new RegExp(`\\s*${escaped[0]}[\\s\\S]*?${escaped[1]}\\s*`, "g");
2145
+ return source.replace(pattern, "\n");
2146
+ }
2147
+ async function readOptionalFile(path) {
2148
+ try {
2149
+ return await readFile3(path, "utf8");
2150
+ } catch (error) {
2151
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
2152
+ return "";
2153
+ }
2154
+ throw error;
2155
+ }
2156
+ }
2157
+ function escapeRegExp(value) {
2158
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2159
+ }
2160
+
2161
+ // packages/cli/dist/deps.js
2162
+ function createDefaultCliDeps() {
2163
+ return {
2164
+ claudePath: resolveClaudeMdPath(),
2165
+ codexPath: resolveCodexInstructionsPath(),
2166
+ configPath: DEFAULT_CONFIG_PATH,
2167
+ memoryDbPath: resolveMemoryDbPath(),
2168
+ platform: process.platform,
2169
+ spawnSync: spawnSync4,
2170
+ stdout: process.stdout,
2171
+ stderr: process.stderr,
2172
+ fileExists,
2173
+ readTextFile: (path) => readFile4(path, "utf8"),
2174
+ upsertManagedBlock,
2175
+ removeManagedBlock,
2176
+ wrapCodexPrompt,
2177
+ loadIdentity: () => loadIdentity(),
2178
+ saveIdentity: (config) => saveIdentity(config),
2179
+ runInstallWizard,
2180
+ toClaudeMdSnippet,
2181
+ toCodexSystemPrompt,
2182
+ installDaemonService,
2183
+ uninstallDaemonService,
2184
+ startDaemon,
2185
+ stopDaemon,
2186
+ getDaemonStatus,
2187
+ memoryMemorize: (key, essence, options) => memorize(key, essence, options),
2188
+ memoryGet: (key) => get(key),
2189
+ memoryUpdate: (key, changes) => update(key, changes),
2190
+ memoryForget: (key) => forget(key),
2191
+ memoryRecall: (query, limit) => recall(query, limit),
2192
+ memoryConsolidate: () => consolidate(),
2193
+ memoryReflect: () => reflect(),
2194
+ memoryCount: () => count(),
2195
+ memorySearch: (query, limit) => search(query, limit),
2196
+ memoryList: (limit) => list(limit),
2197
+ memoryClear: () => clear(),
2198
+ startTelegramChannel: (config) => loadChannelsModule().then((module) => module.startTelegramChannel(config)),
2199
+ stopTelegramChannel: (channel) => loadChannelsModule().then((module) => module.stopTelegramChannel(channel)),
2200
+ startSlackChannel: (config) => loadChannelsModule().then((module) => module.startSlackChannel(config)),
2201
+ stopSlackChannel: (channel) => loadChannelsModule().then((module) => module.stopSlackChannel(channel)),
2202
+ skillInstall: (content, name) => installSkill(content, name),
2203
+ skillList: (dir) => listSkills(dir),
2204
+ skillLoad: (nameOrPath) => loadSkill(nameOrPath),
2205
+ skillRemove: (name) => removeSkill(name),
2206
+ confirm: (message) => askForConfirmation(message),
2207
+ prompt: (message, initialValue) => askForValue(message, initialValue)
2208
+ };
2209
+ }
2210
+ async function askForConfirmation(message) {
2211
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
2212
+ try {
2213
+ const value = await rl.question(`${message} [y/N] `);
2214
+ return ["y", "yes"].includes(value.trim().toLowerCase());
2215
+ } finally {
2216
+ rl.close();
2217
+ }
2218
+ }
2219
+ async function askForValue(message, initialValue = "") {
2220
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
2221
+ const suffix = initialValue.trim() === "" ? "" : ` [${initialValue}]`;
2222
+ try {
2223
+ const value = await rl.question(`${message}${suffix} `);
2224
+ return value.trim() === "" ? initialValue : value.trim();
2225
+ } finally {
2226
+ rl.close();
2227
+ }
2228
+ }
2229
+ async function loadChannelsModule() {
2230
+ const moduleUrl = new URL("../../channels/dist/index.js", import.meta.url);
2231
+ return import(moduleUrl.href);
2232
+ }
2233
+
2234
+ // packages/cli/dist/output.js
2235
+ function formatMemoryEntries(entries) {
2236
+ if (entries.length === 0) {
2237
+ return "No memory entries found.";
2238
+ }
2239
+ return entries.map((entry, index) => {
2240
+ const lines = [
2241
+ `${index + 1}. ${entry.text}`,
2242
+ ` id: ${entry.id}`,
2243
+ ` key: ${entry.key}`,
2244
+ ` created: ${entry.createdAt}`,
2245
+ ` updated: ${entry.updatedAt}`,
2246
+ ` tags: ${entry.tags.join(", ") || "(none)"}`
2247
+ ];
2248
+ if (entry.metadata) {
2249
+ lines.push(` metadata: ${JSON.stringify(entry.metadata)}`);
2250
+ }
2251
+ if (entry.details) {
2252
+ lines.push(` details: ${entry.details}`);
2253
+ }
2254
+ if (entry.triggerConditions.length > 0) {
2255
+ lines.push(` trigger_conditions: ${entry.triggerConditions.join(", ")}`);
2256
+ }
2257
+ lines.push(` importance: ${entry.importance}`, ` strength: ${entry.strength}`, ` access_count: ${entry.accessCount}`);
2258
+ return lines.join("\n");
2259
+ }).join("\n\n");
2260
+ }
2261
+ function formatSkills(skills) {
2262
+ if (skills.length === 0) {
2263
+ return "No skills found.";
2264
+ }
2265
+ return skills.map((skill) => [
2266
+ `${skill.name} (${skill.version})`,
2267
+ ` description: ${skill.description}`,
2268
+ ` triggers: ${skill.triggers.join(", ") || "(none)"}`,
2269
+ ` path: ${skill.path}`
2270
+ ].join("\n")).join("\n\n");
2271
+ }
2272
+ function writeLine(stream, message) {
2273
+ stream.write(`${message}
2274
+ `);
2275
+ }
2276
+
2277
+ // packages/cli/dist/wait.js
2278
+ async function waitForStopSignal(stop) {
2279
+ await new Promise((resolve4, reject) => {
2280
+ let stopping = false;
2281
+ const cleanup = () => {
2282
+ process.off("SIGINT", onSignal);
2283
+ process.off("SIGTERM", onSignal);
2284
+ };
2285
+ const onSignal = () => {
2286
+ if (stopping) {
2287
+ return;
2288
+ }
2289
+ stopping = true;
2290
+ void stop().then(() => {
2291
+ cleanup();
2292
+ resolve4();
2293
+ }, (error) => {
2294
+ cleanup();
2295
+ reject(error);
2296
+ });
2297
+ };
2298
+ process.on("SIGINT", onSignal);
2299
+ process.on("SIGTERM", onSignal);
2300
+ });
2301
+ }
2302
+
2303
+ // packages/cli/dist/channel-handlers.js
2304
+ async function runTelegramChannelSetup(token, cliCommand, deps) {
2305
+ const config = await deps.loadIdentity();
2306
+ const next = withChannels(config, {
2307
+ telegram: {
2308
+ ...config.channels.telegram,
2309
+ token: token ?? config.channels.telegram.token,
2310
+ cliCommand: cliCommand ?? config.channels.telegram.cliCommand
2311
+ }
2312
+ });
2313
+ ensureTelegramConfigured(next);
2314
+ await deps.saveIdentity(next);
2315
+ writeLine(deps.stdout, `Saved Telegram config to ${deps.configPath}`);
2316
+ }
2317
+ async function runTelegramChannelStart(deps) {
2318
+ const config = await deps.loadIdentity();
2319
+ ensureTelegramConfigured(config);
2320
+ const channel = await deps.startTelegramChannel(config.channels.telegram);
2321
+ writeLine(deps.stdout, "Telegram channel started in foreground. Press Ctrl+C to stop.");
2322
+ await waitForStopSignal(async () => {
2323
+ await deps.stopTelegramChannel(channel);
2324
+ writeLine(deps.stdout, "Telegram channel stopped.");
2325
+ });
2326
+ }
2327
+ async function runTelegramChannelStatus(deps) {
2328
+ const config = await deps.loadIdentity();
2329
+ writeLine(deps.stdout, `Telegram configured: ${config.channels.telegram.token ? "yes" : "no"}`);
2330
+ writeLine(deps.stdout, `Telegram CLI command: ${config.channels.telegram.cliCommand || "va-claw"}`);
2331
+ }
2332
+ async function runSlackChannelSetup(botToken, appToken, cliCommand, deps) {
2333
+ const config = await deps.loadIdentity();
2334
+ const next = withChannels(config, {
2335
+ slack: {
2336
+ ...config.channels.slack,
2337
+ botToken: botToken ?? config.channels.slack.botToken,
2338
+ appToken: appToken ?? config.channels.slack.appToken,
2339
+ cliCommand: cliCommand ?? config.channels.slack.cliCommand
2340
+ }
2341
+ });
2342
+ ensureSlackConfigured(next);
2343
+ await deps.saveIdentity(next);
2344
+ writeLine(deps.stdout, `Saved Slack config to ${deps.configPath}`);
2345
+ }
2346
+ async function runSlackChannelStart(deps) {
2347
+ const config = await deps.loadIdentity();
2348
+ ensureSlackConfigured(config);
2349
+ const channel = await deps.startSlackChannel(config.channels.slack);
2350
+ writeLine(deps.stdout, "Slack channel started in foreground. Press Ctrl+C to stop.");
2351
+ await waitForStopSignal(async () => {
2352
+ await deps.stopSlackChannel(channel);
2353
+ writeLine(deps.stdout, "Slack channel stopped.");
2354
+ });
2355
+ }
2356
+ async function runSlackChannelStatus(deps) {
2357
+ const config = await deps.loadIdentity();
2358
+ const configured = config.channels.slack.botToken !== "" && config.channels.slack.appToken !== "";
2359
+ writeLine(deps.stdout, `Slack configured: ${configured ? "yes" : "no"}`);
2360
+ writeLine(deps.stdout, `Slack CLI command: ${config.channels.slack.cliCommand || "va-claw"}`);
2361
+ }
2362
+ function ensureTelegramConfigured(config) {
2363
+ if (!config.channels.telegram.token) {
2364
+ throw new Error("Telegram token is required. Use `va-claw channel telegram setup --token <token>`.");
2365
+ }
2366
+ }
2367
+ function ensureSlackConfigured(config) {
2368
+ if (!config.channels.slack.botToken || !config.channels.slack.appToken) {
2369
+ throw new Error("Slack bot/app tokens are required. Use `va-claw channel slack setup --bot-token <token> --app-token <token>`.");
2370
+ }
2371
+ }
2372
+ function withChannels(config, patch) {
2373
+ return {
2374
+ ...config,
2375
+ channels: {
2376
+ ...config.channels,
2377
+ ...patch
2378
+ }
2379
+ };
2380
+ }
2381
+
2382
+ // packages/cli/dist/memory-status.js
2383
+ import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
2384
+ async function countMemoryEntries(memoryDbPath, fileExists2) {
2385
+ if (!await fileExists2(memoryDbPath)) {
2386
+ return 0;
2387
+ }
2388
+ const db = new DatabaseSync2(memoryDbPath);
2389
+ try {
2390
+ const row = db.prepare("SELECT COUNT(*) AS count FROM memories").get();
2391
+ return Number(row?.count ?? 0);
2392
+ } finally {
2393
+ db.close();
2394
+ }
2395
+ }
2396
+ async function findLastWakeAt(memoryDbPath, fileExists2) {
2397
+ if (!await fileExists2(memoryDbPath)) {
2398
+ return null;
2399
+ }
2400
+ const db = new DatabaseSync2(memoryDbPath);
2401
+ try {
2402
+ const rows = db.prepare("SELECT metadata, created_at FROM memories ORDER BY created_at DESC LIMIT 100").all();
2403
+ for (const row of rows) {
2404
+ const metadata = parseMetadata2(row.metadata);
2405
+ if (metadata?.source === "va-claw-daemon" || metadata?.kind === "wake") {
2406
+ return typeof metadata.wokeAt === "string" ? metadata.wokeAt : row.created_at;
2407
+ }
2408
+ }
2409
+ return null;
2410
+ } finally {
2411
+ db.close();
2412
+ }
2413
+ }
2414
+ function parseMetadata2(raw) {
2415
+ if (!raw) {
2416
+ return null;
2417
+ }
2418
+ const value = JSON.parse(raw);
2419
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2420
+ }
2421
+
2422
+ // packages/cli/dist/platform.js
2423
+ import { homedir as homedir6 } from "node:os";
2424
+ import { join as join6 } from "node:path";
2425
+ function detectServiceType(platform) {
2426
+ if (platform === "darwin") {
2427
+ return "launchd";
2428
+ }
2429
+ if (platform === "linux") {
2430
+ return "systemd";
2431
+ }
2432
+ throw new Error(`Unsupported platform for va-claw daemon service: ${platform}`);
2433
+ }
2434
+ function probeServiceRunning(type, spawnSync5) {
2435
+ if (type === "launchd") {
2436
+ return spawnSync5("launchctl", ["list", "com.va-claw.daemon"], { encoding: "utf8" }).status === 0;
2437
+ }
2438
+ const result = spawnSync5("systemctl", ["--user", "is-active", "va-claw.service"], {
2439
+ encoding: "utf8"
2440
+ });
2441
+ return result.status === 0 && result.stdout.trim() === "active";
2442
+ }
2443
+ function stopInstalledService(type, spawnSync5) {
2444
+ if (type === "launchd") {
2445
+ spawnSync5("launchctl", ["unload", resolveLaunchdPath()], { encoding: "utf8" });
2446
+ return;
2447
+ }
2448
+ spawnSync5("systemctl", ["--user", "stop", "va-claw.service"], { encoding: "utf8" });
2449
+ }
2450
+ function resolveLaunchdPath() {
2451
+ return join6(homedir6(), "Library", "LaunchAgents", "com.va-claw.daemon.plist");
2452
+ }
2453
+
2454
+ // packages/cli/dist/handlers.js
2455
+ async function runInstall(target, deps) {
2456
+ const installTarget = normalizeInstallTarget(target);
2457
+ const config = await deps.fileExists(deps.configPath) ? await deps.loadIdentity() : await deps.runInstallWizard();
2458
+ const summary = [`Installed va-claw for ${installTarget}.`, `Config: ${deps.configPath}`];
2459
+ if (installTarget === "claude-code" || installTarget === "all") {
2460
+ await deps.upsertManagedBlock(deps.claudePath, deps.toClaudeMdSnippet(config), CLAUDE_MARKERS);
2461
+ summary.push(`CLAUDE.md: ${deps.claudePath}`);
2462
+ }
2463
+ if (installTarget === "codex" || installTarget === "all") {
2464
+ const prompt = deps.wrapCodexPrompt(deps.toCodexSystemPrompt(config));
2465
+ await deps.upsertManagedBlock(deps.codexPath, prompt, CODEX_MARKERS);
2466
+ summary.push(`Codex instructions: ${deps.codexPath}`);
2467
+ }
2468
+ const serviceType = detectServiceType(deps.platform);
2469
+ await deps.installDaemonService(serviceType);
2470
+ summary.push(`Daemon service: ${serviceType}`);
2471
+ for (const line of summary) {
2472
+ writeLine(deps.stdout, line);
2473
+ }
2474
+ }
2475
+ async function runStart(deps) {
2476
+ const config = await deps.loadIdentity();
2477
+ await deps.startDaemon(config);
2478
+ writeLine(deps.stdout, "va-claw daemon started in foreground. Press Ctrl+C to stop.");
2479
+ await waitForStopSignal(async () => {
2480
+ await deps.stopDaemon();
2481
+ writeLine(deps.stdout, "va-claw daemon stopped.");
2482
+ });
2483
+ }
2484
+ async function runStop(deps) {
2485
+ await deps.stopDaemon();
2486
+ const serviceType = safeDetectServiceType(deps.platform);
2487
+ if (serviceType) {
2488
+ stopInstalledService(serviceType, deps.spawnSync);
2489
+ }
2490
+ writeLine(deps.stdout, "va-claw stop requested.");
2491
+ }
2492
+ async function runStatus(deps) {
2493
+ const runtime = await deps.getDaemonStatus();
2494
+ const serviceType = safeDetectServiceType(deps.platform);
2495
+ const serviceRunning = serviceType ? probeServiceRunning(serviceType, deps.spawnSync) : false;
2496
+ const lastWakeAt = runtime.lastWakeAt?.toISOString() ?? await findLastWakeAt(deps.memoryDbPath, deps.fileExists);
2497
+ const memoryCount = await countMemoryEntries(deps.memoryDbPath, deps.fileExists);
2498
+ writeLine(deps.stdout, `Daemon: ${runtime.running || serviceRunning ? "running" : "stopped"}`);
2499
+ writeLine(deps.stdout, `Discord: ${runtime.discord}`);
2500
+ writeLine(deps.stdout, `Last wake: ${lastWakeAt ?? "never"}`);
2501
+ writeLine(deps.stdout, `Memory entries: ${memoryCount}`);
2502
+ }
2503
+ async function runMemorySearch(query, deps) {
2504
+ writeLine(deps.stdout, formatMemoryEntries(await deps.memorySearch(query, 10)));
2505
+ }
2506
+ async function runMemoryList(deps) {
2507
+ writeLine(deps.stdout, formatMemoryEntries(await deps.memoryList(20)));
2508
+ }
2509
+ async function runMemoryMemorize(key, essence, options, deps) {
2510
+ const importance = options.importance === void 0 ? void 0 : Number(options.importance);
2511
+ const entry = await deps.memoryMemorize(key, essence, {
2512
+ tags: options.tags ? splitCommaList(options.tags) : [],
2513
+ details: options.details,
2514
+ importance: Number.isFinite(importance) ? importance : void 0
2515
+ });
2516
+ writeLine(deps.stdout, formatMemoryEntries([entry]));
2517
+ }
2518
+ async function runMemoryGet(key, deps) {
2519
+ const entry = await deps.memoryGet(key);
2520
+ if (!entry) {
2521
+ writeLine(deps.stdout, `Memory not found: ${key}`);
2522
+ return;
2523
+ }
2524
+ writeLine(deps.stdout, formatMemoryEntries([entry]));
2525
+ }
2526
+ async function runMemoryUpdate(key, options, deps) {
2527
+ const importance = options.importance === void 0 ? void 0 : Number(options.importance);
2528
+ const entry = await deps.memoryUpdate(key, {
2529
+ essence: options.essence,
2530
+ tags: options.tags ? splitCommaList(options.tags) : void 0,
2531
+ details: options.details,
2532
+ importance: Number.isFinite(importance) ? importance : void 0
2533
+ });
2534
+ if (!entry) {
2535
+ writeLine(deps.stdout, `Memory not found: ${key}`);
2536
+ return;
2537
+ }
2538
+ writeLine(deps.stdout, formatMemoryEntries([entry]));
2539
+ }
2540
+ async function runMemoryForget(key, deps) {
2541
+ const removed = await deps.memoryForget(key);
2542
+ writeLine(deps.stdout, removed ? `Forgot memory: ${key}` : `Memory not found: ${key}`);
2543
+ }
2544
+ async function runMemoryRecall(query, limit, deps) {
2545
+ writeLine(deps.stdout, formatMemoryEntries(await deps.memoryRecall(query, limit)));
2546
+ }
2547
+ async function runMemoryConsolidate(deps) {
2548
+ writeLine(deps.stdout, JSON.stringify(await deps.memoryConsolidate(), null, 2));
2549
+ }
2550
+ async function runMemoryReflect(deps) {
2551
+ writeLine(deps.stdout, await deps.memoryReflect());
2552
+ }
2553
+ async function runMemoryClear(deps) {
2554
+ if (!await deps.confirm("Clear all va-claw memory entries?")) {
2555
+ writeLine(deps.stdout, "Memory clear aborted.");
2556
+ return;
2557
+ }
2558
+ await deps.memoryClear();
2559
+ writeLine(deps.stdout, "Memory cleared.");
2560
+ }
2561
+ async function runDiscordSetup(deps) {
2562
+ const config = await deps.loadIdentity();
2563
+ const token = await deps.prompt("Discord Bot Token", config.channels.discord.token);
2564
+ const clientId = await deps.prompt("Discord Client ID", config.channels.discord.clientId);
2565
+ await deps.saveIdentity({
2566
+ ...config,
2567
+ channels: {
2568
+ ...config.channels,
2569
+ discord: {
2570
+ ...config.channels.discord,
2571
+ token,
2572
+ clientId
2573
+ }
2574
+ }
2575
+ });
2576
+ writeLine(deps.stdout, `Saved Discord config to ${deps.configPath}`);
2577
+ }
2578
+ async function runDiscordStart(deps) {
2579
+ const config = await deps.loadIdentity();
2580
+ const discord = await loadDiscordChannelModule();
2581
+ const channel = await discord.startDiscordChannel({
2582
+ token: config.channels.discord.token,
2583
+ clientId: config.channels.discord.clientId,
2584
+ cliCommand: config.channels.discord.cliCommand
2585
+ });
2586
+ writeLine(deps.stdout, "Discord channel started in foreground. Press Ctrl+C to stop.");
2587
+ await waitForStopSignal(async () => {
2588
+ await discord.stopDiscordChannel(channel);
2589
+ writeLine(deps.stdout, "Discord channel stopped.");
2590
+ });
2591
+ }
2592
+ async function runDiscordStatus(deps) {
2593
+ const config = await deps.loadIdentity();
2594
+ const configured = config.channels.discord.token.trim() !== "" && config.channels.discord.clientId.trim() !== "";
2595
+ const runtime = await deps.getDaemonStatus();
2596
+ writeLine(deps.stdout, `Discord: ${configured ? runtime.discord : "disconnected"}`);
2597
+ writeLine(deps.stdout, `Configured: ${configured ? "yes" : "no"}`);
2598
+ writeLine(deps.stdout, `Auto-start: ${config.channels.discord.autoStart ? "enabled" : "disabled"}`);
2599
+ }
2600
+ async function runSkillList(deps) {
2601
+ writeLine(deps.stdout, formatSkills(await deps.skillList()));
2602
+ }
2603
+ async function runSkillAdd(pathOrUrl, deps) {
2604
+ if (/^https?:\/\//i.test(pathOrUrl)) {
2605
+ throw new Error("Network installs are not supported. Use a local skill file path.");
2606
+ }
2607
+ const source = await deps.skillLoad(pathOrUrl);
2608
+ const content = await deps.readTextFile(source.path);
2609
+ const installedPath = await deps.skillInstall(content, source.name);
2610
+ writeLine(deps.stdout, `Installed skill ${source.name} -> ${installedPath}`);
2611
+ }
2612
+ async function runSkillRemove(name, deps) {
2613
+ await deps.skillRemove(name);
2614
+ writeLine(deps.stdout, `Removed skill ${name}.`);
2615
+ }
2616
+ async function runSkillShow(name, deps) {
2617
+ const skill = await deps.skillLoad(name);
2618
+ writeLine(deps.stdout, await deps.readTextFile(skill.path));
2619
+ }
2620
+ async function runUninstall(deps) {
2621
+ const serviceType = detectServiceType(deps.platform);
2622
+ await deps.uninstallDaemonService(serviceType);
2623
+ await deps.removeManagedBlock(deps.claudePath, CLAUDE_MARKERS);
2624
+ await deps.removeManagedBlock(deps.codexPath, CODEX_MARKERS);
2625
+ writeLine(deps.stdout, "va-claw uninstalled.");
2626
+ }
2627
+ function normalizeInstallTarget(target) {
2628
+ if (target === "claude-code" || target === "codex" || target === "all") {
2629
+ return target;
2630
+ }
2631
+ throw new Error(`Invalid --for target: ${target}`);
2632
+ }
2633
+ function safeDetectServiceType(platform) {
2634
+ try {
2635
+ return detectServiceType(platform);
2636
+ } catch {
2637
+ return null;
2638
+ }
2639
+ }
2640
+ async function loadDiscordChannelModule() {
2641
+ const moduleUrl = new URL("../../channels/discord/dist/index.js", import.meta.url);
2642
+ return import(moduleUrl.href);
2643
+ }
2644
+ function splitCommaList(value) {
2645
+ return value.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
2646
+ }
2647
+
2648
+ // node_modules/.pnpm/commander@file+vendor+commander/node_modules/commander/index.js
2649
+ var Command = class _Command {
2650
+ constructor(name = "") {
2651
+ this._name = name;
2652
+ this._description = "";
2653
+ this._action = null;
2654
+ this._arguments = [];
2655
+ this._options = [];
2656
+ this._parsedOptions = {};
2657
+ this.commands = [];
2658
+ this.parent = null;
2659
+ }
2660
+ name(value) {
2661
+ this._name = value;
2662
+ return this;
2663
+ }
2664
+ description(value) {
2665
+ this._description = value;
2666
+ return this;
2667
+ }
2668
+ showHelpAfterError() {
2669
+ return this;
2670
+ }
2671
+ command(spec) {
2672
+ const child = new _Command(spec.trim().split(/\s+/)[0]);
2673
+ child.parent = this;
2674
+ this.commands.push(child);
2675
+ return child;
2676
+ }
2677
+ argument(spec) {
2678
+ this._arguments.push({ required: spec.startsWith("<"), name: spec.slice(1, -1) });
2679
+ return this;
2680
+ }
2681
+ option(flags, _description, defaultValue) {
2682
+ const long = flags.match(/--([a-z0-9-]+)/i)?.[1];
2683
+ if (!long) throw new Error(`Unsupported option flags: ${flags}`);
2684
+ const key = long.replace(/-([a-z])/g, (_2, letter) => letter.toUpperCase());
2685
+ this._options.push({ key, flag: `--${long}`, requiresValue: /<.+>/.test(flags), defaultValue });
2686
+ return this;
2687
+ }
2688
+ action(handler) {
2689
+ this._action = handler;
2690
+ return this;
2691
+ }
2692
+ opts() {
2693
+ return { ...this._parsedOptions };
2694
+ }
2695
+ async parseAsync(argv) {
2696
+ await this._dispatch(argv.slice(2));
2697
+ }
2698
+ async _dispatch(tokens) {
2699
+ if (tokens.includes("--help") || tokens.includes("-h")) {
2700
+ process.stdout.write(`${this.helpInformation()}
2701
+ `);
2702
+ return;
2703
+ }
2704
+ const child = tokens[0] ? this.commands.find((command) => command._name === tokens[0]) : null;
2705
+ if (child) {
2706
+ await child._dispatch(tokens.slice(1));
2707
+ return;
2708
+ }
2709
+ const { options, positionals } = this._parseTokens(tokens);
2710
+ this._parsedOptions = options;
2711
+ const required = this._arguments.filter((argument) => argument.required).length;
2712
+ if (positionals.length < required) {
2713
+ throw new Error(`Missing required argument for ${this._commandPath()}.`);
2714
+ }
2715
+ if (!this._action) {
2716
+ process.stdout.write(`${this.helpInformation()}
2717
+ `);
2718
+ return;
2719
+ }
2720
+ await this._action(...positionals, options, this);
2721
+ }
2722
+ _parseTokens(tokens) {
2723
+ const options = Object.fromEntries(this._options.map((option) => [option.key, option.defaultValue]));
2724
+ const positionals = [];
2725
+ for (let index = 0; index < tokens.length; index += 1) {
2726
+ const token = tokens[index];
2727
+ const option = this._options.find((entry) => entry.flag === token);
2728
+ if (!option) {
2729
+ positionals.push(token);
2730
+ continue;
2731
+ }
2732
+ options[option.key] = option.requiresValue ? tokens[++index] : true;
2733
+ }
2734
+ return { options, positionals };
2735
+ }
2736
+ helpInformation() {
2737
+ const lines = [`Usage: ${this._commandPath()}${this.commands.length ? " [command]" : ""}`];
2738
+ if (this._description) lines.push("", this._description);
2739
+ const commands = this._flattenCommands();
2740
+ if (commands.length) {
2741
+ lines.push("", "Commands:");
2742
+ for (const entry of commands) lines.push(` ${entry}`);
2743
+ }
2744
+ return lines.join("\n");
2745
+ }
2746
+ _flattenCommands(prefix = "") {
2747
+ const nextPrefix = prefix ? `${prefix} ${this._name}`.trim() : this._name;
2748
+ return this.commands.flatMap((command) => {
2749
+ const label = `${nextPrefix} ${command._name}`.trim();
2750
+ return [label, ...command._flattenCommands(nextPrefix)];
2751
+ });
2752
+ }
2753
+ _commandPath() {
2754
+ const names = [];
2755
+ for (let current = this; current; current = current.parent) {
2756
+ if (current._name) names.push(current._name);
2757
+ }
2758
+ return names.reverse().join(" ");
2759
+ }
2760
+ };
2761
+
2762
+ // packages/cli/dist/program.js
2763
+ function createCliProgram(deps = createDefaultCliDeps()) {
2764
+ const program = new Command("va-claw");
2765
+ program.description("va-claw CLI");
2766
+ program.showHelpAfterError();
2767
+ program.command("install").description("Install va-claw config, prompt injections, and daemon service.").option("--for <target>", "claude-code | codex | all", "all").action(async (options) => runInstall(options.for ?? "all", deps));
2768
+ program.command("start").description("Start the daemon in the foreground.").action(async () => runStart(deps));
2769
+ program.command("stop").description("Stop the daemon.").action(async () => runStop(deps));
2770
+ program.command("status").description("Show daemon and memory status.").action(async () => runStatus(deps));
2771
+ program.command("uninstall").description("Remove daemon service and injected prompts.").action(async () => runUninstall(deps));
2772
+ const memory = program.command("memory").description("Memory operations.");
2773
+ memory.command("search").description("Search memory.").argument("<query>").action(async (query) => runMemorySearch(query, deps));
2774
+ memory.command("memorize").description("Store or update a memory entry by key.").argument("<key>").argument("<essence>").option("--tags <tags>", "Comma-separated tags.").option("--details <details>", "Details text.").option("--importance <importance>", "Importance from 0 to 1.").action((key, essence, options) => runMemoryMemorize(key, essence, options, deps));
2775
+ memory.command("get").description("Get a memory entry by key.").argument("<key>").action(async (key) => runMemoryGet(key, deps));
2776
+ memory.command("update").description("Update a memory entry by key.").argument("<key>").option("--essence <essence>", "Replace essence text.").option("--tags <tags>", "Comma-separated tags.").option("--importance <importance>", "Importance from 0 to 1.").option("--details <details>", "Replace details text.").action((key, options) => runMemoryUpdate(key, options, deps));
2777
+ memory.command("list").description("List recent memory entries.").action(async () => runMemoryList(deps));
2778
+ memory.command("forget").description("Forget a memory by key.").argument("<key>").action(async (key) => runMemoryForget(key, deps));
2779
+ memory.command("recall").description("Recall memories by query.").argument("<query>").option("--limit <limit>", "Max results.").action((query, options) => runMemoryRecall(query, options.limit ? Number(options.limit) : 5, deps));
2780
+ memory.command("consolidate").description("Consolidate memory store.").action(async () => runMemoryConsolidate(deps));
2781
+ memory.command("reflect").description("Reflect memory map grouped by tags.").action(async () => runMemoryReflect(deps));
2782
+ memory.command("clear").description("Clear all memory entries.").action(async () => runMemoryClear(deps));
2783
+ const skill = program.command("skill").description("Skill operations.");
2784
+ skill.command("list").description("List installed and project skills.").action(async () => runSkillList(deps));
2785
+ skill.command("add").description("Install a skill from a local Markdown file or URL.\n\nTip: vet unknown skills first \u2014 va-claw skill add https://clawhub.ai/spclaudehome/Skill-vetter").argument("<path-or-url>").action(async (pathOrUrl) => runSkillAdd(pathOrUrl, deps));
2786
+ skill.command("remove").description("Remove an installed skill by name.").argument("<name>").action(async (name) => runSkillRemove(name, deps));
2787
+ skill.command("show").description("Show the raw Markdown content for a skill.").argument("<name>").action(async (name) => runSkillShow(name, deps));
2788
+ const channel = program.command("channel").description("Channel operations.");
2789
+ const discord = channel.command("discord").description("Discord channel operations.");
2790
+ discord.command("setup").description("Configure Discord bot credentials.").action(async () => runDiscordSetup(deps));
2791
+ discord.command("start").description("Start the Discord channel in the foreground.").action(async () => runDiscordStart(deps));
2792
+ discord.command("status").description("Show Discord channel status.").action(async () => runDiscordStatus(deps));
2793
+ const telegram = channel.command("telegram").description("Telegram channel operations.");
2794
+ telegram.command("setup").description("Configure Telegram bot credentials.").option("--token <token>", "Telegram bot token").option("--cli-command <command>", "CLI command to invoke for each message").action(async (options) => runTelegramChannelSetup(options.token, options.cliCommand, deps));
2795
+ telegram.command("start").description("Start the Telegram channel in the foreground.").action(async () => runTelegramChannelStart(deps));
2796
+ telegram.command("status").description("Show Telegram channel status.").action(async () => runTelegramChannelStatus(deps));
2797
+ const slack = channel.command("slack").description("Slack channel operations.");
2798
+ slack.command("setup").description("Configure Slack bot credentials.").option("--bot-token <token>", "Slack bot token").option("--app-token <token>", "Slack app token").option("--cli-command <command>", "CLI command to invoke for each message").action(async (options) => runSlackChannelSetup(options.botToken, options.appToken, options.cliCommand, deps));
2799
+ slack.command("start").description("Start the Slack channel in the foreground.").action(async () => runSlackChannelStart(deps));
2800
+ slack.command("status").description("Show Slack channel status.").action(async () => runSlackChannelStatus(deps));
2801
+ return program;
2802
+ }
2803
+ async function runCli(argv = process.argv, deps) {
2804
+ const program = createCliProgram(deps ?? createDefaultCliDeps());
2805
+ try {
2806
+ await program.parseAsync(argv);
2807
+ } catch (error) {
2808
+ const message = error instanceof Error ? error.message : String(error);
2809
+ (deps ?? createDefaultCliDeps()).stderr.write(`${message}
2810
+ `);
2811
+ process.exitCode = 1;
2812
+ }
2813
+ }
2814
+
2815
+ // packages/cli/dist/bin/va-claw.mjs
2816
+ await runCli();