stickyinc 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3575,24 +3575,24 @@ var require_fast_uri = __commonJS({
3575
3575
  function normalize(uri, options) {
3576
3576
  if (typeof uri === "string") {
3577
3577
  uri = /** @type {T} */
3578
- serialize(parse3(uri, options), options);
3578
+ serialize(parse4(uri, options), options);
3579
3579
  } else if (typeof uri === "object") {
3580
3580
  uri = /** @type {T} */
3581
- parse3(serialize(uri, options), options);
3581
+ parse4(serialize(uri, options), options);
3582
3582
  }
3583
3583
  return uri;
3584
3584
  }
3585
3585
  function resolve2(baseURI, relativeURI, options) {
3586
3586
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3587
- const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
3587
+ const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
3588
3588
  schemelessOptions.skipEscape = true;
3589
3589
  return serialize(resolved, schemelessOptions);
3590
3590
  }
3591
3591
  function resolveComponent(base, relative, options, skipNormalization) {
3592
3592
  const target = {};
3593
3593
  if (!skipNormalization) {
3594
- base = parse3(serialize(base, options), options);
3595
- relative = parse3(serialize(relative, options), options);
3594
+ base = parse4(serialize(base, options), options);
3595
+ relative = parse4(serialize(relative, options), options);
3596
3596
  }
3597
3597
  options = options || {};
3598
3598
  if (!options.tolerant && relative.scheme) {
@@ -3644,13 +3644,13 @@ var require_fast_uri = __commonJS({
3644
3644
  function equal(uriA, uriB, options) {
3645
3645
  if (typeof uriA === "string") {
3646
3646
  uriA = unescape(uriA);
3647
- uriA = serialize(normalizeComponentEncoding(parse3(uriA, options), true), { ...options, skipEscape: true });
3647
+ uriA = serialize(normalizeComponentEncoding(parse4(uriA, options), true), { ...options, skipEscape: true });
3648
3648
  } else if (typeof uriA === "object") {
3649
3649
  uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
3650
3650
  }
3651
3651
  if (typeof uriB === "string") {
3652
3652
  uriB = unescape(uriB);
3653
- uriB = serialize(normalizeComponentEncoding(parse3(uriB, options), true), { ...options, skipEscape: true });
3653
+ uriB = serialize(normalizeComponentEncoding(parse4(uriB, options), true), { ...options, skipEscape: true });
3654
3654
  } else if (typeof uriB === "object") {
3655
3655
  uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
3656
3656
  }
@@ -3719,7 +3719,7 @@ var require_fast_uri = __commonJS({
3719
3719
  return uriTokens.join("");
3720
3720
  }
3721
3721
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
3722
- function parse3(uri, opts) {
3722
+ function parse4(uri, opts) {
3723
3723
  const options = Object.assign({}, opts);
3724
3724
  const parsed = {
3725
3725
  scheme: void 0,
@@ -3813,7 +3813,7 @@ var require_fast_uri = __commonJS({
3813
3813
  resolveComponent,
3814
3814
  equal,
3815
3815
  serialize,
3816
- parse: parse3
3816
+ parse: parse4
3817
3817
  };
3818
3818
  module.exports = fastUri;
3819
3819
  module.exports.default = fastUri;
@@ -4224,7 +4224,7 @@ var require_core = __commonJS({
4224
4224
  errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
4225
4225
  if (!errors || errors.length === 0)
4226
4226
  return "No errors";
4227
- return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text, msg) => text + separator + msg);
4227
+ return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
4228
4228
  }
4229
4229
  $dataMetaSchema(metaSchema, keywordsJsonPointers) {
4230
4230
  const rules = this.RULES.all;
@@ -21013,14 +21013,41 @@ var StdioServerTransport = class {
21013
21013
  // src/db.ts
21014
21014
  import { createHash, randomUUID } from "node:crypto";
21015
21015
  import { mkdirSync } from "node:fs";
21016
+ import { createRequire } from "node:module";
21016
21017
  import { homedir } from "node:os";
21017
21018
  import { dirname, join, resolve } from "node:path";
21018
- import { DatabaseSync } from "node:sqlite";
21019
+
21020
+ // src/search.ts
21021
+ function searchWords(query) {
21022
+ return query.match(/[\p{L}\p{N}]+/gu) ?? [];
21023
+ }
21024
+ function ftsQuery(words) {
21025
+ return words.map((w) => `"${w}"*`).join(" ");
21026
+ }
21027
+ function toSqliteUtc(iso) {
21028
+ return iso.replace("T", " ").replace(/(\.\d+)?Z$/, "");
21029
+ }
21030
+ function likeAnywhere(word) {
21031
+ return `%${word.replace(/[\\%_]/g, "\\$&")}%`;
21032
+ }
21033
+
21034
+ // src/db.ts
21019
21035
  function dbPath() {
21020
21036
  const override = process.env.STICKYINC_DB;
21021
21037
  if (!override) return join(homedir(), ".stickyinc", "tasks.db");
21022
21038
  return resolve(override.replace(/^~(?=$|[\\/])/, homedir()));
21023
21039
  }
21040
+ function loadSqlite() {
21041
+ try {
21042
+ return createRequire(import.meta.url)("node:sqlite");
21043
+ } catch {
21044
+ console.error(
21045
+ `StickyInc needs Node.js 22.13+ (or 23.4+) for its built-in SQLite, but this is Node ${process.version}. Install a current Node from https://nodejs.org and restart your MCP client.`
21046
+ );
21047
+ process.exit(1);
21048
+ }
21049
+ }
21050
+ var { DatabaseSync } = loadSqlite();
21024
21051
  var DB_PATH = dbPath();
21025
21052
  mkdirSync(dirname(DB_PATH), { recursive: true });
21026
21053
  var db = new DatabaseSync(DB_PATH);
@@ -21044,8 +21071,12 @@ db.exec(`
21044
21071
  created_at TEXT NOT NULL DEFAULT (datetime('now')),
21045
21072
  completed_at TEXT,
21046
21073
  due_at TEXT,
21074
+ due_phrase TEXT,
21047
21075
  source TEXT NOT NULL DEFAULT 'claude',
21048
- fingerprint TEXT
21076
+ fingerprint TEXT,
21077
+ source_client TEXT,
21078
+ source_ref TEXT,
21079
+ source_excerpt TEXT
21049
21080
  );
21050
21081
  CREATE INDEX IF NOT EXISTS idx_tasks_completed ON tasks(completed_at);
21051
21082
  CREATE INDEX IF NOT EXISTS idx_tasks_due ON tasks(due_at);
@@ -21067,6 +21098,15 @@ db.exec(`
21067
21098
  );
21068
21099
  CREATE INDEX IF NOT EXISTS idx_task_events_task ON task_events(task_uuid);
21069
21100
  CREATE INDEX IF NOT EXISTS idx_task_events_lamport ON task_events(device_id, lamport);
21101
+
21102
+ -- User-defined routines: a named prompt, and a hint of when to run it
21103
+ -- (StickyInc doesn't run them itself; see docs/routines.md).
21104
+ CREATE TABLE IF NOT EXISTS routines (
21105
+ name TEXT PRIMARY KEY,
21106
+ prompt TEXT NOT NULL,
21107
+ schedule TEXT,
21108
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
21109
+ );
21070
21110
  `);
21071
21111
  {
21072
21112
  const cols = db.prepare(`PRAGMA table_info(tasks)`).all();
@@ -21076,6 +21116,14 @@ db.exec(`
21076
21116
  if (!cols.some((c) => c.name === "uuid")) {
21077
21117
  db.exec(`ALTER TABLE tasks ADD COLUMN uuid TEXT`);
21078
21118
  }
21119
+ if (!cols.some((c) => c.name === "due_phrase")) {
21120
+ db.exec(`ALTER TABLE tasks ADD COLUMN due_phrase TEXT`);
21121
+ }
21122
+ for (const col of ["source_client", "source_ref", "source_excerpt"]) {
21123
+ if (!cols.some((c) => c.name === col)) {
21124
+ db.exec(`ALTER TABLE tasks ADD COLUMN ${col} TEXT`);
21125
+ }
21126
+ }
21079
21127
  const pending = db.prepare(`SELECT id FROM tasks WHERE uuid IS NULL`).all();
21080
21128
  if (pending.length > 0) {
21081
21129
  const setUuid = db.prepare(`UPDATE tasks SET uuid = ? WHERE id = ?`);
@@ -21118,7 +21166,9 @@ function recordEvent(op, taskUuid, payload) {
21118
21166
  );
21119
21167
  }
21120
21168
  var insertTaskStmt = db.prepare(
21121
- `INSERT INTO tasks (uuid, text, due_at, source, fingerprint) VALUES (?, ?, ?, ?, ?) RETURNING *`
21169
+ `INSERT INTO tasks (uuid, text, due_at, due_phrase, source, fingerprint,
21170
+ source_client, source_ref, source_excerpt)
21171
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`
21122
21172
  );
21123
21173
  var findOpenByFingerprintStmt = db.prepare(
21124
21174
  `SELECT * FROM tasks WHERE fingerprint = ? AND completed_at IS NULL LIMIT 1`
@@ -21154,16 +21204,37 @@ var completeTaskUpdateStmt = db.prepare(
21154
21204
  `UPDATE tasks SET completed_at = datetime('now') WHERE id = ? AND completed_at IS NULL`
21155
21205
  );
21156
21206
  var getTaskStmt = db.prepare(`SELECT * FROM tasks WHERE id = ?`);
21157
- function fingerprint(text) {
21158
- return createHash("sha256").update(text.toLowerCase().replace(/\s+/g, " ").trim()).digest("hex").slice(0, 16);
21207
+ function fingerprint(text2) {
21208
+ return createHash("sha256").update(text2.toLowerCase().replace(/\s+/g, " ").trim()).digest("hex").slice(0, 16);
21159
21209
  }
21160
- function addTask(text, dueAt = null, source = "claude") {
21210
+ function insertTask({ text: text2, due: due2 = null, source = "claude", from }) {
21161
21211
  const taskUuid = randomUUID();
21162
- const fp = fingerprint(text);
21212
+ const row = {
21213
+ due_at: due2?.at ?? null,
21214
+ due_phrase: due2?.phrase ?? null,
21215
+ source_client: from?.client ?? null,
21216
+ source_ref: from?.ref ?? null,
21217
+ source_excerpt: from?.excerpt ?? null
21218
+ };
21219
+ const task = insertTaskStmt.get(
21220
+ taskUuid,
21221
+ text2,
21222
+ row.due_at,
21223
+ row.due_phrase,
21224
+ source,
21225
+ fingerprint(text2),
21226
+ row.source_client,
21227
+ row.source_ref,
21228
+ row.source_excerpt
21229
+ );
21230
+ recordEvent("create", taskUuid, { text: text2, ...row, due_ref: due2?.ref ?? null, source });
21231
+ return task;
21232
+ }
21233
+ function addTaskUnique(t) {
21163
21234
  return inTransaction(() => {
21164
- const task = insertTaskStmt.get(taskUuid, text, dueAt, source, fp);
21165
- recordEvent("create", taskUuid, { text, due_at: dueAt, source });
21166
- return task;
21235
+ const existing = findOpenByFingerprintStmt.get(fingerprint(t.text));
21236
+ if (existing) return { task: existing, inserted: false };
21237
+ return { task: insertTask(t), inserted: true };
21167
21238
  });
21168
21239
  }
21169
21240
  function countDoneToday() {
@@ -21172,75 +21243,3118 @@ function countDoneToday() {
21172
21243
  function listOpenTasks() {
21173
21244
  return selectOpenStmt.all();
21174
21245
  }
21175
- function listAllTasks(limit = 50) {
21176
- return selectAllStmt.all(limit);
21246
+ function listAllTasks(limit = 50) {
21247
+ return selectAllStmt.all(limit);
21248
+ }
21249
+ function listRecentlyCompleted(hoursAgo = 24) {
21250
+ return selectRecentDoneStmt.all(`-${hoursAgo} hours`);
21251
+ }
21252
+ function listArchived(hoursAgo = 24, limit = 100) {
21253
+ return selectArchivedStmt.all(`-${hoursAgo} hours`, limit);
21254
+ }
21255
+ function completeTask(id) {
21256
+ return inTransaction(() => {
21257
+ const prior = completeTaskFindStmt.get(id);
21258
+ if (!prior) return null;
21259
+ const completed = prior.completed_at === null;
21260
+ if (completed) {
21261
+ completeTaskUpdateStmt.run(id);
21262
+ recordEvent("complete", prior.uuid, null);
21263
+ }
21264
+ return { task: getTaskStmt.get(id), completed };
21265
+ });
21266
+ }
21267
+ var HAS_FTS5 = (() => {
21268
+ try {
21269
+ db.exec(
21270
+ `CREATE VIRTUAL TABLE IF NOT EXISTS temp.task_search
21271
+ USING fts5(text, excerpt, tokenize = 'unicode61 remove_diacritics 2')`
21272
+ );
21273
+ return true;
21274
+ } catch {
21275
+ return false;
21276
+ }
21277
+ })();
21278
+ function searchTasks({
21279
+ query = "",
21280
+ status = "all",
21281
+ since,
21282
+ completedSince,
21283
+ limit = 20
21284
+ }) {
21285
+ const words = searchWords(query);
21286
+ const where = [];
21287
+ const params = [];
21288
+ if (status === "open") where.push("t.completed_at IS NULL");
21289
+ if (status === "done") where.push("t.completed_at IS NOT NULL");
21290
+ if (since) {
21291
+ where.push("t.created_at >= ?");
21292
+ params.push(toSqliteUtc(since));
21293
+ }
21294
+ if (completedSince) {
21295
+ where.push("t.completed_at >= ?");
21296
+ params.push(toSqliteUtc(completedSince));
21297
+ }
21298
+ if (words.length > 0 && HAS_FTS5) {
21299
+ db.exec(
21300
+ `DELETE FROM temp.task_search;
21301
+ INSERT INTO temp.task_search (rowid, text, excerpt)
21302
+ SELECT id, text, source_excerpt FROM main.tasks;`
21303
+ );
21304
+ const filters2 = where.map((w) => ` AND ${w}`).join("");
21305
+ return db.prepare(
21306
+ `SELECT t.* FROM temp.task_search JOIN main.tasks t ON t.id = task_search.rowid
21307
+ WHERE task_search MATCH ?${filters2}
21308
+ ORDER BY task_search.rank LIMIT ?`
21309
+ ).all(ftsQuery(words), ...params, limit);
21310
+ }
21311
+ for (const word of words) {
21312
+ where.push(`(t.text LIKE ? ESCAPE '\\' OR t.source_excerpt LIKE ? ESCAPE '\\')`);
21313
+ params.push(likeAnywhere(word), likeAnywhere(word));
21314
+ }
21315
+ const filters = where.length > 0 ? `WHERE ${where.join(" AND ")}` : "";
21316
+ return db.prepare(`SELECT t.* FROM main.tasks t ${filters} ORDER BY t.created_at DESC, t.id DESC LIMIT ?`).all(...params, limit);
21317
+ }
21318
+ function listRoutines() {
21319
+ return db.prepare(`SELECT * FROM routines ORDER BY name`).all();
21320
+ }
21321
+ function saveRoutine(r) {
21322
+ return inTransaction(() => {
21323
+ const existed = db.prepare(`SELECT 1 FROM routines WHERE name = ?`).get(r.name) !== void 0;
21324
+ db.prepare(
21325
+ `INSERT INTO routines (name, prompt, schedule, updated_at) VALUES (?, ?, ?, datetime('now'))
21326
+ ON CONFLICT (name) DO UPDATE SET prompt = excluded.prompt, schedule = excluded.schedule,
21327
+ updated_at = excluded.updated_at`
21328
+ ).run(r.name, r.prompt, r.schedule ?? null);
21329
+ return !existed;
21330
+ });
21331
+ }
21332
+ function deleteRoutine(name) {
21333
+ return Number(db.prepare(`DELETE FROM routines WHERE name = ?`).run(name).changes) > 0;
21334
+ }
21335
+
21336
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/types.js
21337
+ var Meridiem;
21338
+ (function(Meridiem2) {
21339
+ Meridiem2[Meridiem2["AM"] = 0] = "AM";
21340
+ Meridiem2[Meridiem2["PM"] = 1] = "PM";
21341
+ })(Meridiem || (Meridiem = {}));
21342
+ var Weekday;
21343
+ (function(Weekday2) {
21344
+ Weekday2[Weekday2["SUNDAY"] = 0] = "SUNDAY";
21345
+ Weekday2[Weekday2["MONDAY"] = 1] = "MONDAY";
21346
+ Weekday2[Weekday2["TUESDAY"] = 2] = "TUESDAY";
21347
+ Weekday2[Weekday2["WEDNESDAY"] = 3] = "WEDNESDAY";
21348
+ Weekday2[Weekday2["THURSDAY"] = 4] = "THURSDAY";
21349
+ Weekday2[Weekday2["FRIDAY"] = 5] = "FRIDAY";
21350
+ Weekday2[Weekday2["SATURDAY"] = 6] = "SATURDAY";
21351
+ })(Weekday || (Weekday = {}));
21352
+ var Month;
21353
+ (function(Month2) {
21354
+ Month2[Month2["JANUARY"] = 1] = "JANUARY";
21355
+ Month2[Month2["FEBRUARY"] = 2] = "FEBRUARY";
21356
+ Month2[Month2["MARCH"] = 3] = "MARCH";
21357
+ Month2[Month2["APRIL"] = 4] = "APRIL";
21358
+ Month2[Month2["MAY"] = 5] = "MAY";
21359
+ Month2[Month2["JUNE"] = 6] = "JUNE";
21360
+ Month2[Month2["JULY"] = 7] = "JULY";
21361
+ Month2[Month2["AUGUST"] = 8] = "AUGUST";
21362
+ Month2[Month2["SEPTEMBER"] = 9] = "SEPTEMBER";
21363
+ Month2[Month2["OCTOBER"] = 10] = "OCTOBER";
21364
+ Month2[Month2["NOVEMBER"] = 11] = "NOVEMBER";
21365
+ Month2[Month2["DECEMBER"] = 12] = "DECEMBER";
21366
+ })(Month || (Month = {}));
21367
+
21368
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/utils/dates.js
21369
+ function assignSimilarDate(component, target) {
21370
+ component.assign("day", target.getDate());
21371
+ component.assign("month", target.getMonth() + 1);
21372
+ component.assign("year", target.getFullYear());
21373
+ }
21374
+ function assignSimilarTime(component, target) {
21375
+ component.assign("hour", target.getHours());
21376
+ component.assign("minute", target.getMinutes());
21377
+ component.assign("second", target.getSeconds());
21378
+ component.assign("millisecond", target.getMilliseconds());
21379
+ component.assign("meridiem", target.getHours() < 12 ? Meridiem.AM : Meridiem.PM);
21380
+ }
21381
+ function implySimilarDate(component, target) {
21382
+ component.imply("day", target.getDate());
21383
+ component.imply("month", target.getMonth() + 1);
21384
+ component.imply("year", target.getFullYear());
21385
+ }
21386
+ function implySimilarTime(component, target) {
21387
+ component.imply("hour", target.getHours());
21388
+ component.imply("minute", target.getMinutes());
21389
+ component.imply("second", target.getSeconds());
21390
+ component.imply("millisecond", target.getMilliseconds());
21391
+ component.imply("meridiem", target.getHours() < 12 ? Meridiem.AM : Meridiem.PM);
21392
+ }
21393
+
21394
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/timezone.js
21395
+ var TIMEZONE_ABBR_MAP = {
21396
+ ACDT: 630,
21397
+ ACST: 570,
21398
+ ADT: -180,
21399
+ AEDT: 660,
21400
+ AEST: 600,
21401
+ AFT: 270,
21402
+ AKDT: -480,
21403
+ AKST: -540,
21404
+ ALMT: 360,
21405
+ AMST: -180,
21406
+ AMT: -240,
21407
+ ANAST: 720,
21408
+ ANAT: 720,
21409
+ AQTT: 300,
21410
+ ART: -180,
21411
+ AST: -240,
21412
+ AWDT: 540,
21413
+ AWST: 480,
21414
+ AZOST: 0,
21415
+ AZOT: -60,
21416
+ AZST: 300,
21417
+ AZT: 240,
21418
+ BNT: 480,
21419
+ BOT: -240,
21420
+ BRST: -120,
21421
+ BRT: -180,
21422
+ BST: 60,
21423
+ BTT: 360,
21424
+ CAST: 480,
21425
+ CAT: 120,
21426
+ CCT: 390,
21427
+ CDT: -300,
21428
+ CEST: 120,
21429
+ CET: {
21430
+ timezoneOffsetDuringDst: 2 * 60,
21431
+ timezoneOffsetNonDst: 60,
21432
+ dstStart: (year) => getLastWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2),
21433
+ dstEnd: (year) => getLastWeekdayOfMonth(year, Month.OCTOBER, Weekday.SUNDAY, 3)
21434
+ },
21435
+ CHADT: 825,
21436
+ CHAST: 765,
21437
+ CKT: -600,
21438
+ CLST: -180,
21439
+ CLT: -240,
21440
+ COT: -300,
21441
+ CST: -360,
21442
+ CT: {
21443
+ timezoneOffsetDuringDst: -5 * 60,
21444
+ timezoneOffsetNonDst: -6 * 60,
21445
+ dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
21446
+ dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
21447
+ },
21448
+ CVT: -60,
21449
+ CXT: 420,
21450
+ ChST: 600,
21451
+ DAVT: 420,
21452
+ EASST: -300,
21453
+ EAST: -360,
21454
+ EAT: 180,
21455
+ ECT: -300,
21456
+ EDT: -240,
21457
+ EEST: 180,
21458
+ EET: 120,
21459
+ EGST: 0,
21460
+ EGT: -60,
21461
+ EST: -300,
21462
+ ET: {
21463
+ timezoneOffsetDuringDst: -4 * 60,
21464
+ timezoneOffsetNonDst: -5 * 60,
21465
+ dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
21466
+ dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
21467
+ },
21468
+ FJST: 780,
21469
+ FJT: 720,
21470
+ FKST: -180,
21471
+ FKT: -240,
21472
+ FNT: -120,
21473
+ GALT: -360,
21474
+ GAMT: -540,
21475
+ GET: 240,
21476
+ GFT: -180,
21477
+ GILT: 720,
21478
+ GMT: 0,
21479
+ GST: 240,
21480
+ GYT: -240,
21481
+ HAA: -180,
21482
+ HAC: -300,
21483
+ HADT: -540,
21484
+ HAE: -240,
21485
+ HAP: -420,
21486
+ HAR: -360,
21487
+ HAST: -600,
21488
+ HAT: -90,
21489
+ HAY: -480,
21490
+ HKT: 480,
21491
+ HLV: -210,
21492
+ HNA: -240,
21493
+ HNC: -360,
21494
+ HNE: -300,
21495
+ HNP: -480,
21496
+ HNR: -420,
21497
+ HNT: -150,
21498
+ HNY: -540,
21499
+ HOVT: 420,
21500
+ ICT: 420,
21501
+ IDT: 180,
21502
+ IOT: 360,
21503
+ IRDT: 270,
21504
+ IRKST: 540,
21505
+ IRKT: 540,
21506
+ IRST: 210,
21507
+ IST: 330,
21508
+ JST: 540,
21509
+ KGT: 360,
21510
+ KRAST: 480,
21511
+ KRAT: 480,
21512
+ KST: 540,
21513
+ KUYT: 240,
21514
+ LHDT: 660,
21515
+ LHST: 630,
21516
+ LINT: 840,
21517
+ MAGST: 720,
21518
+ MAGT: 720,
21519
+ MART: -510,
21520
+ MAWT: 300,
21521
+ MDT: -360,
21522
+ MESZ: 120,
21523
+ MEZ: 60,
21524
+ MHT: 720,
21525
+ MMT: 390,
21526
+ MSD: 240,
21527
+ MSK: 180,
21528
+ MST: -420,
21529
+ MT: {
21530
+ timezoneOffsetDuringDst: -6 * 60,
21531
+ timezoneOffsetNonDst: -7 * 60,
21532
+ dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
21533
+ dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
21534
+ },
21535
+ MUT: 240,
21536
+ MVT: 300,
21537
+ MYT: 480,
21538
+ NCT: 660,
21539
+ NDT: -90,
21540
+ NFT: 690,
21541
+ NOVST: 420,
21542
+ NOVT: 360,
21543
+ NPT: 345,
21544
+ NST: -150,
21545
+ NUT: -660,
21546
+ NZDT: 780,
21547
+ NZST: 720,
21548
+ OMSST: 420,
21549
+ OMST: 420,
21550
+ PDT: -420,
21551
+ PET: -300,
21552
+ PETST: 720,
21553
+ PETT: 720,
21554
+ PGT: 600,
21555
+ PHOT: 780,
21556
+ PHT: 480,
21557
+ PKT: 300,
21558
+ PMDT: -120,
21559
+ PMST: -180,
21560
+ PONT: 660,
21561
+ PST: -480,
21562
+ PT: {
21563
+ timezoneOffsetDuringDst: -7 * 60,
21564
+ timezoneOffsetNonDst: -8 * 60,
21565
+ dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
21566
+ dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
21567
+ },
21568
+ PWT: 540,
21569
+ PYST: -180,
21570
+ PYT: -240,
21571
+ RET: 240,
21572
+ SAMT: 240,
21573
+ SAST: 120,
21574
+ SBT: 660,
21575
+ SCT: 240,
21576
+ SGT: 480,
21577
+ SRT: -180,
21578
+ SST: -660,
21579
+ TAHT: -600,
21580
+ TFT: 300,
21581
+ TJT: 300,
21582
+ TKT: 780,
21583
+ TLT: 540,
21584
+ TMT: 300,
21585
+ TVT: 720,
21586
+ ULAT: 480,
21587
+ UTC: 0,
21588
+ UYST: -120,
21589
+ UYT: -180,
21590
+ UZT: 300,
21591
+ VET: -210,
21592
+ VLAST: 660,
21593
+ VLAT: 660,
21594
+ VUT: 660,
21595
+ WAST: 120,
21596
+ WAT: 60,
21597
+ WEST: 60,
21598
+ WESZ: 60,
21599
+ WET: 0,
21600
+ WEZ: 0,
21601
+ WFT: 720,
21602
+ WGST: -120,
21603
+ WGT: -180,
21604
+ WIB: 420,
21605
+ WIT: 540,
21606
+ WITA: 480,
21607
+ WST: 780,
21608
+ WT: 0,
21609
+ YAKST: 600,
21610
+ YAKT: 600,
21611
+ YAPT: 600,
21612
+ YEKST: 360,
21613
+ YEKT: 360
21614
+ };
21615
+ function getNthWeekdayOfMonth(year, month, weekday, n, hour = 0) {
21616
+ let dayOfMonth2 = 0;
21617
+ let i = 0;
21618
+ while (i < n) {
21619
+ dayOfMonth2++;
21620
+ const date3 = new Date(year, month - 1, dayOfMonth2);
21621
+ if (date3.getDay() === weekday)
21622
+ i++;
21623
+ }
21624
+ return new Date(year, month - 1, dayOfMonth2, hour);
21625
+ }
21626
+ function getLastWeekdayOfMonth(year, month, weekday, hour = 0) {
21627
+ const oneIndexedWeekday = weekday === 0 ? 7 : weekday;
21628
+ const date3 = new Date(year, month - 1 + 1, 1, 12);
21629
+ const firstWeekdayNextMonth = date3.getDay() === 0 ? 7 : date3.getDay();
21630
+ let dayDiff;
21631
+ if (firstWeekdayNextMonth === oneIndexedWeekday)
21632
+ dayDiff = 7;
21633
+ else if (firstWeekdayNextMonth < oneIndexedWeekday)
21634
+ dayDiff = 7 + firstWeekdayNextMonth - oneIndexedWeekday;
21635
+ else
21636
+ dayDiff = firstWeekdayNextMonth - oneIndexedWeekday;
21637
+ date3.setDate(date3.getDate() - dayDiff);
21638
+ return new Date(year, month - 1, date3.getDate(), hour);
21639
+ }
21640
+ function toTimezoneOffset(timezoneInput, date3, timezoneOverrides = {}) {
21641
+ if (timezoneInput == null) {
21642
+ return null;
21643
+ }
21644
+ if (typeof timezoneInput === "number") {
21645
+ return timezoneInput;
21646
+ }
21647
+ const matchedTimezone = timezoneOverrides[timezoneInput] ?? TIMEZONE_ABBR_MAP[timezoneInput];
21648
+ if (matchedTimezone == null) {
21649
+ return null;
21650
+ }
21651
+ if (typeof matchedTimezone == "number") {
21652
+ return matchedTimezone;
21653
+ }
21654
+ if (date3 == null) {
21655
+ return null;
21656
+ }
21657
+ if (date3 > matchedTimezone.dstStart(date3.getFullYear()) && !(date3 > matchedTimezone.dstEnd(date3.getFullYear()))) {
21658
+ return matchedTimezone.timezoneOffsetDuringDst;
21659
+ }
21660
+ return matchedTimezone.timezoneOffsetNonDst;
21661
+ }
21662
+
21663
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/calculation/duration.js
21664
+ var EmptyDuration = {
21665
+ day: 0,
21666
+ second: 0,
21667
+ millisecond: 0
21668
+ };
21669
+ function addDuration(ref, duration3) {
21670
+ let date3 = new Date(ref);
21671
+ if (duration3["y"]) {
21672
+ duration3["year"] = duration3["y"];
21673
+ delete duration3["y"];
21674
+ }
21675
+ if (duration3["mo"]) {
21676
+ duration3["month"] = duration3["mo"];
21677
+ delete duration3["mo"];
21678
+ }
21679
+ if (duration3["M"]) {
21680
+ duration3["month"] = duration3["M"];
21681
+ delete duration3["M"];
21682
+ }
21683
+ if (duration3["w"]) {
21684
+ duration3["week"] = duration3["w"];
21685
+ delete duration3["w"];
21686
+ }
21687
+ if (duration3["d"]) {
21688
+ duration3["day"] = duration3["d"];
21689
+ delete duration3["d"];
21690
+ }
21691
+ if (duration3["h"]) {
21692
+ duration3["hour"] = duration3["h"];
21693
+ delete duration3["h"];
21694
+ }
21695
+ if (duration3["m"]) {
21696
+ duration3["minute"] = duration3["m"];
21697
+ delete duration3["m"];
21698
+ }
21699
+ if (duration3["s"]) {
21700
+ duration3["second"] = duration3["s"];
21701
+ delete duration3["s"];
21702
+ }
21703
+ if (duration3["ms"]) {
21704
+ duration3["millisecond"] = duration3["ms"];
21705
+ delete duration3["ms"];
21706
+ }
21707
+ if ("year" in duration3) {
21708
+ const floor = Math.floor(duration3["year"]);
21709
+ date3.setFullYear(date3.getFullYear() + floor);
21710
+ const remainingFraction = duration3["year"] - floor;
21711
+ if (remainingFraction > 0) {
21712
+ duration3.month = duration3?.month ?? 0;
21713
+ duration3.month += remainingFraction * 12;
21714
+ }
21715
+ }
21716
+ if ("quarter" in duration3) {
21717
+ const floor = Math.floor(duration3["quarter"]);
21718
+ date3.setMonth(date3.getMonth() + floor * 3);
21719
+ }
21720
+ if ("month" in duration3) {
21721
+ const floor = Math.floor(duration3["month"]);
21722
+ date3.setMonth(date3.getMonth() + floor);
21723
+ const remainingFraction = duration3["month"] - floor;
21724
+ if (remainingFraction > 0) {
21725
+ duration3.week = duration3?.week ?? 0;
21726
+ duration3.week += remainingFraction * 4;
21727
+ }
21728
+ }
21729
+ if ("week" in duration3) {
21730
+ const floor = Math.floor(duration3["week"]);
21731
+ date3.setDate(date3.getDate() + floor * 7);
21732
+ const remainingFraction = duration3["week"] - floor;
21733
+ if (remainingFraction > 0) {
21734
+ duration3.day = duration3?.day ?? 0;
21735
+ duration3.day += Math.round(remainingFraction * 7);
21736
+ }
21737
+ }
21738
+ if ("day" in duration3) {
21739
+ const floor = Math.floor(duration3["day"]);
21740
+ date3.setDate(date3.getDate() + floor);
21741
+ const remainingFraction = duration3["day"] - floor;
21742
+ if (remainingFraction > 0) {
21743
+ duration3.hour = duration3?.hour ?? 0;
21744
+ duration3.hour += Math.round(remainingFraction * 24);
21745
+ }
21746
+ }
21747
+ if ("hour" in duration3) {
21748
+ const floor = Math.floor(duration3["hour"]);
21749
+ date3.setHours(date3.getHours() + floor);
21750
+ const remainingFraction = duration3["hour"] - floor;
21751
+ if (remainingFraction > 0) {
21752
+ duration3.minute = duration3?.minute ?? 0;
21753
+ duration3.minute += Math.round(remainingFraction * 60);
21754
+ }
21755
+ }
21756
+ if ("minute" in duration3) {
21757
+ const floor = Math.floor(duration3["minute"]);
21758
+ date3.setMinutes(date3.getMinutes() + floor);
21759
+ const remainingFraction = duration3["minute"] - floor;
21760
+ if (remainingFraction > 0) {
21761
+ duration3.second = duration3?.second ?? 0;
21762
+ duration3.second += Math.round(remainingFraction * 60);
21763
+ }
21764
+ }
21765
+ if ("second" in duration3) {
21766
+ const floor = Math.floor(duration3["second"]);
21767
+ date3.setSeconds(date3.getSeconds() + floor);
21768
+ const remainingFraction = duration3["second"] - floor;
21769
+ if (remainingFraction > 0) {
21770
+ duration3.millisecond = duration3?.millisecond ?? 0;
21771
+ duration3.millisecond += Math.round(remainingFraction * 1e3);
21772
+ }
21773
+ }
21774
+ if ("millisecond" in duration3) {
21775
+ const floor = Math.floor(duration3["millisecond"]);
21776
+ date3.setMilliseconds(date3.getMilliseconds() + floor);
21777
+ }
21778
+ return date3;
21779
+ }
21780
+ function reverseDuration(duration3) {
21781
+ const reversed = {};
21782
+ for (const key in duration3) {
21783
+ reversed[key] = -duration3[key];
21784
+ }
21785
+ return reversed;
21786
+ }
21787
+
21788
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/results.js
21789
+ var ReferenceWithTimezone = class _ReferenceWithTimezone {
21790
+ instant;
21791
+ timezoneOffset;
21792
+ constructor(instant, timezoneOffset) {
21793
+ this.instant = instant ?? /* @__PURE__ */ new Date();
21794
+ this.timezoneOffset = timezoneOffset ?? null;
21795
+ }
21796
+ static fromDate(date3) {
21797
+ return new _ReferenceWithTimezone(date3);
21798
+ }
21799
+ static fromInput(input, timezoneOverrides) {
21800
+ if (input instanceof Date) {
21801
+ return _ReferenceWithTimezone.fromDate(input);
21802
+ }
21803
+ const instant = input?.instant ?? /* @__PURE__ */ new Date();
21804
+ const timezoneOffset = toTimezoneOffset(input?.timezone, instant, timezoneOverrides);
21805
+ return new _ReferenceWithTimezone(instant, timezoneOffset);
21806
+ }
21807
+ getDateWithAdjustedTimezone() {
21808
+ const date3 = new Date(this.instant);
21809
+ if (this.timezoneOffset !== null) {
21810
+ date3.setMinutes(date3.getMinutes() - this.getSystemTimezoneAdjustmentMinute(this.instant));
21811
+ }
21812
+ return date3;
21813
+ }
21814
+ getSystemTimezoneAdjustmentMinute(date3, overrideTimezoneOffset) {
21815
+ if (!date3) {
21816
+ date3 = /* @__PURE__ */ new Date();
21817
+ }
21818
+ const currentTimezoneOffset = -date3.getTimezoneOffset();
21819
+ const targetTimezoneOffset = overrideTimezoneOffset ?? this.timezoneOffset ?? currentTimezoneOffset;
21820
+ return currentTimezoneOffset - targetTimezoneOffset;
21821
+ }
21822
+ getTimezoneOffset() {
21823
+ return this.timezoneOffset ?? -this.instant.getTimezoneOffset();
21824
+ }
21825
+ };
21826
+ var ParsingComponents = class _ParsingComponents {
21827
+ knownValues;
21828
+ impliedValues;
21829
+ reference;
21830
+ _tags = /* @__PURE__ */ new Set();
21831
+ constructor(reference, knownComponents) {
21832
+ this.reference = reference;
21833
+ this.knownValues = {};
21834
+ this.impliedValues = {};
21835
+ if (knownComponents) {
21836
+ for (const key in knownComponents) {
21837
+ this.knownValues[key] = knownComponents[key];
21838
+ }
21839
+ }
21840
+ const date3 = reference.getDateWithAdjustedTimezone();
21841
+ this.imply("day", date3.getDate());
21842
+ this.imply("month", date3.getMonth() + 1);
21843
+ this.imply("year", date3.getFullYear());
21844
+ this.imply("hour", 12);
21845
+ this.imply("minute", 0);
21846
+ this.imply("second", 0);
21847
+ this.imply("millisecond", 0);
21848
+ }
21849
+ static createRelativeFromReference(reference, duration3 = EmptyDuration) {
21850
+ let date3 = addDuration(reference.getDateWithAdjustedTimezone(), duration3);
21851
+ const components = new _ParsingComponents(reference);
21852
+ components.addTag("result/relativeDate");
21853
+ if ("hour" in duration3 || "minute" in duration3 || "second" in duration3 || "millisecond" in duration3) {
21854
+ components.addTag("result/relativeDateAndTime");
21855
+ assignSimilarTime(components, date3);
21856
+ assignSimilarDate(components, date3);
21857
+ components.assign("timezoneOffset", reference.getTimezoneOffset());
21858
+ } else {
21859
+ implySimilarTime(components, date3);
21860
+ components.imply("timezoneOffset", reference.getTimezoneOffset());
21861
+ if ("day" in duration3) {
21862
+ components.assign("day", date3.getDate());
21863
+ components.assign("month", date3.getMonth() + 1);
21864
+ components.assign("year", date3.getFullYear());
21865
+ components.assign("weekday", date3.getDay());
21866
+ } else if ("week" in duration3) {
21867
+ components.assign("day", date3.getDate());
21868
+ components.assign("month", date3.getMonth() + 1);
21869
+ components.assign("year", date3.getFullYear());
21870
+ components.imply("weekday", date3.getDay());
21871
+ } else {
21872
+ components.imply("day", date3.getDate());
21873
+ if ("month" in duration3) {
21874
+ components.assign("month", date3.getMonth() + 1);
21875
+ components.assign("year", date3.getFullYear());
21876
+ } else {
21877
+ components.imply("month", date3.getMonth() + 1);
21878
+ if ("year" in duration3) {
21879
+ components.assign("year", date3.getFullYear());
21880
+ } else {
21881
+ components.imply("year", date3.getFullYear());
21882
+ }
21883
+ }
21884
+ }
21885
+ }
21886
+ return components;
21887
+ }
21888
+ get(component) {
21889
+ if (component in this.knownValues) {
21890
+ return this.knownValues[component];
21891
+ }
21892
+ if (component in this.impliedValues) {
21893
+ return this.impliedValues[component];
21894
+ }
21895
+ return null;
21896
+ }
21897
+ isCertain(component) {
21898
+ return component in this.knownValues;
21899
+ }
21900
+ getCertainComponents() {
21901
+ return Object.keys(this.knownValues);
21902
+ }
21903
+ imply(component, value) {
21904
+ if (component in this.knownValues) {
21905
+ return this;
21906
+ }
21907
+ this.impliedValues[component] = value;
21908
+ return this;
21909
+ }
21910
+ assign(component, value) {
21911
+ this.knownValues[component] = value;
21912
+ delete this.impliedValues[component];
21913
+ return this;
21914
+ }
21915
+ addDurationAsImplied(duration3) {
21916
+ const currentDate = this.dateWithoutTimezoneAdjustment();
21917
+ const date3 = addDuration(currentDate, duration3);
21918
+ if ("day" in duration3 || "week" in duration3 || "month" in duration3 || "year" in duration3) {
21919
+ this.delete(["day", "weekday", "month", "year"]);
21920
+ this.imply("day", date3.getDate());
21921
+ this.imply("weekday", date3.getDay());
21922
+ this.imply("month", date3.getMonth() + 1);
21923
+ this.imply("year", date3.getFullYear());
21924
+ }
21925
+ if ("second" in duration3 || "minute" in duration3 || "hour" in duration3) {
21926
+ this.delete(["second", "minute", "hour"]);
21927
+ this.imply("second", date3.getSeconds());
21928
+ this.imply("minute", date3.getMinutes());
21929
+ this.imply("hour", date3.getHours());
21930
+ }
21931
+ return this;
21932
+ }
21933
+ delete(components) {
21934
+ if (typeof components === "string") {
21935
+ components = [components];
21936
+ }
21937
+ for (const component of components) {
21938
+ delete this.knownValues[component];
21939
+ delete this.impliedValues[component];
21940
+ }
21941
+ }
21942
+ clone() {
21943
+ const component = new _ParsingComponents(this.reference);
21944
+ component.knownValues = {};
21945
+ component.impliedValues = {};
21946
+ for (const key in this.knownValues) {
21947
+ component.knownValues[key] = this.knownValues[key];
21948
+ }
21949
+ for (const key in this.impliedValues) {
21950
+ component.impliedValues[key] = this.impliedValues[key];
21951
+ }
21952
+ return component;
21953
+ }
21954
+ isOnlyDate() {
21955
+ return !this.isCertain("hour") && !this.isCertain("minute") && !this.isCertain("second");
21956
+ }
21957
+ isOnlyTime() {
21958
+ return !this.isCertain("weekday") && !this.isCertain("day") && !this.isCertain("month") && !this.isCertain("year");
21959
+ }
21960
+ isOnlyWeekdayComponent() {
21961
+ return this.isCertain("weekday") && !this.isCertain("day") && !this.isCertain("month");
21962
+ }
21963
+ isDateWithUnknownYear() {
21964
+ return this.isCertain("month") && !this.isCertain("year");
21965
+ }
21966
+ isValidDate() {
21967
+ const date3 = new Date(Date.UTC(this.get("year"), this.get("month") - 1, this.get("day"), this.get("hour"), this.get("minute"), this.get("second"), this.get("millisecond")));
21968
+ date3.setUTCFullYear(this.get("year"));
21969
+ if (date3.getUTCFullYear() !== this.get("year"))
21970
+ return false;
21971
+ if (date3.getUTCMonth() !== this.get("month") - 1)
21972
+ return false;
21973
+ if (date3.getUTCDate() !== this.get("day"))
21974
+ return false;
21975
+ if (this.get("hour") != null && date3.getUTCHours() != this.get("hour"))
21976
+ return false;
21977
+ if (this.get("minute") != null && date3.getUTCMinutes() != this.get("minute"))
21978
+ return false;
21979
+ return true;
21980
+ }
21981
+ toString() {
21982
+ return `[ParsingComponents {
21983
+ tags: ${JSON.stringify(Array.from(this._tags).sort())},
21984
+ knownValues: ${JSON.stringify(this.knownValues)},
21985
+ impliedValues: ${JSON.stringify(this.impliedValues)}},
21986
+ reference: ${JSON.stringify(this.reference)}]`;
21987
+ }
21988
+ date() {
21989
+ const timezoneOffset = this.get("timezoneOffset") ?? this.reference.timezoneOffset;
21990
+ if (timezoneOffset === null || timezoneOffset === void 0) {
21991
+ return this.dateWithoutTimezoneAdjustment();
21992
+ }
21993
+ const date3 = new Date(Date.UTC(this.get("year"), this.get("month") - 1, this.get("day"), this.get("hour"), this.get("minute"), this.get("second"), this.get("millisecond")));
21994
+ date3.setUTCFullYear(this.get("year"));
21995
+ return new Date(date3.getTime() - timezoneOffset * 6e4);
21996
+ }
21997
+ addTag(tag) {
21998
+ this._tags.add(tag);
21999
+ return this;
22000
+ }
22001
+ addTags(tags) {
22002
+ for (const tag of tags) {
22003
+ this._tags.add(tag);
22004
+ }
22005
+ return this;
22006
+ }
22007
+ tags() {
22008
+ return new Set(this._tags);
22009
+ }
22010
+ dateWithoutTimezoneAdjustment() {
22011
+ const date3 = new Date(this.get("year"), this.get("month") - 1, this.get("day"), this.get("hour"), this.get("minute"), this.get("second"), this.get("millisecond"));
22012
+ date3.setFullYear(this.get("year"));
22013
+ return date3;
22014
+ }
22015
+ };
22016
+ var ParsingResult = class _ParsingResult {
22017
+ refDate;
22018
+ index;
22019
+ text;
22020
+ reference;
22021
+ start;
22022
+ end;
22023
+ constructor(reference, index, text2, start, end) {
22024
+ this.reference = reference;
22025
+ this.refDate = reference.instant;
22026
+ this.index = index;
22027
+ this.text = text2;
22028
+ this.start = start || new ParsingComponents(reference);
22029
+ this.end = end;
22030
+ }
22031
+ clone() {
22032
+ const result = new _ParsingResult(this.reference, this.index, this.text);
22033
+ result.start = this.start ? this.start.clone() : null;
22034
+ result.end = this.end ? this.end.clone() : null;
22035
+ return result;
22036
+ }
22037
+ date() {
22038
+ return this.start.date();
22039
+ }
22040
+ addTag(tag) {
22041
+ this.start.addTag(tag);
22042
+ if (this.end) {
22043
+ this.end.addTag(tag);
22044
+ }
22045
+ return this;
22046
+ }
22047
+ addTags(tags) {
22048
+ this.start.addTags(tags);
22049
+ if (this.end) {
22050
+ this.end.addTags(tags);
22051
+ }
22052
+ return this;
22053
+ }
22054
+ tags() {
22055
+ const combinedTags = new Set(this.start.tags());
22056
+ if (this.end) {
22057
+ for (const tag of this.end.tags()) {
22058
+ combinedTags.add(tag);
22059
+ }
22060
+ }
22061
+ return combinedTags;
22062
+ }
22063
+ toString() {
22064
+ const tags = Array.from(this.tags()).sort();
22065
+ return `[ParsingResult {index: ${this.index}, text: '${this.text}', tags: ${JSON.stringify(tags)} ...}]`;
22066
+ }
22067
+ };
22068
+
22069
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/utils/pattern.js
22070
+ function repeatedTimeunitPattern(prefix, singleTimeunitPattern, connectorPattern = "\\s{0,5},?\\s{0,5}") {
22071
+ const singleTimeunitPatternNoCapture = singleTimeunitPattern.replace(/\((?!\?)/g, "(?:");
22072
+ return `${prefix}${singleTimeunitPatternNoCapture}(?:${connectorPattern}${singleTimeunitPatternNoCapture}){0,10}`;
22073
+ }
22074
+ function extractTerms(dictionary) {
22075
+ let keys;
22076
+ if (dictionary instanceof Array) {
22077
+ keys = [...dictionary];
22078
+ } else if (dictionary instanceof Map) {
22079
+ keys = Array.from(dictionary.keys());
22080
+ } else {
22081
+ keys = Object.keys(dictionary);
22082
+ }
22083
+ return keys;
22084
+ }
22085
+ function matchAnyPattern(dictionary) {
22086
+ const joinedTerms = extractTerms(dictionary).sort((a, b) => b.length - a.length).join("|").replace(/\./g, "\\.");
22087
+ return `(?:${joinedTerms})`;
22088
+ }
22089
+
22090
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/calculation/years.js
22091
+ function findMostLikelyADYear(yearNumber) {
22092
+ if (yearNumber < 100) {
22093
+ if (yearNumber > 50) {
22094
+ yearNumber = yearNumber + 1900;
22095
+ } else {
22096
+ yearNumber = yearNumber + 2e3;
22097
+ }
22098
+ }
22099
+ return yearNumber;
22100
+ }
22101
+ function findYearClosestToRef(refDate, day, month) {
22102
+ let date3 = new Date(refDate);
22103
+ date3.setMonth(month - 1);
22104
+ date3.setDate(day);
22105
+ const nextYear = addDuration(date3, { "year": 1 });
22106
+ const lastYear = addDuration(date3, { "year": -1 });
22107
+ if (Math.abs(nextYear.getTime() - refDate.getTime()) < Math.abs(date3.getTime() - refDate.getTime())) {
22108
+ date3 = nextYear;
22109
+ } else if (Math.abs(lastYear.getTime() - refDate.getTime()) < Math.abs(date3.getTime() - refDate.getTime())) {
22110
+ date3 = lastYear;
22111
+ }
22112
+ return date3.getFullYear();
22113
+ }
22114
+
22115
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/constants.js
22116
+ var WEEKDAY_DICTIONARY = {
22117
+ sunday: 0,
22118
+ sun: 0,
22119
+ "sun.": 0,
22120
+ monday: 1,
22121
+ mon: 1,
22122
+ "mon.": 1,
22123
+ tuesday: 2,
22124
+ tue: 2,
22125
+ "tue.": 2,
22126
+ wednesday: 3,
22127
+ wed: 3,
22128
+ "wed.": 3,
22129
+ thursday: 4,
22130
+ thurs: 4,
22131
+ "thurs.": 4,
22132
+ thur: 4,
22133
+ "thur.": 4,
22134
+ thu: 4,
22135
+ "thu.": 4,
22136
+ friday: 5,
22137
+ fri: 5,
22138
+ "fri.": 5,
22139
+ saturday: 6,
22140
+ sat: 6,
22141
+ "sat.": 6
22142
+ };
22143
+ var FULL_MONTH_NAME_DICTIONARY = {
22144
+ january: 1,
22145
+ february: 2,
22146
+ march: 3,
22147
+ april: 4,
22148
+ may: 5,
22149
+ june: 6,
22150
+ july: 7,
22151
+ august: 8,
22152
+ september: 9,
22153
+ october: 10,
22154
+ november: 11,
22155
+ december: 12
22156
+ };
22157
+ var MONTH_DICTIONARY = {
22158
+ ...FULL_MONTH_NAME_DICTIONARY,
22159
+ jan: 1,
22160
+ "jan.": 1,
22161
+ feb: 2,
22162
+ "feb.": 2,
22163
+ mar: 3,
22164
+ "mar.": 3,
22165
+ apr: 4,
22166
+ "apr.": 4,
22167
+ jun: 6,
22168
+ "jun.": 6,
22169
+ jul: 7,
22170
+ "jul.": 7,
22171
+ aug: 8,
22172
+ "aug.": 8,
22173
+ sep: 9,
22174
+ "sep.": 9,
22175
+ sept: 9,
22176
+ "sept.": 9,
22177
+ oct: 10,
22178
+ "oct.": 10,
22179
+ nov: 11,
22180
+ "nov.": 11,
22181
+ dec: 12,
22182
+ "dec.": 12
22183
+ };
22184
+ var INTEGER_WORD_DICTIONARY = {
22185
+ one: 1,
22186
+ two: 2,
22187
+ three: 3,
22188
+ four: 4,
22189
+ five: 5,
22190
+ six: 6,
22191
+ seven: 7,
22192
+ eight: 8,
22193
+ nine: 9,
22194
+ ten: 10,
22195
+ eleven: 11,
22196
+ twelve: 12
22197
+ };
22198
+ var ORDINAL_WORD_DICTIONARY = {
22199
+ first: 1,
22200
+ second: 2,
22201
+ third: 3,
22202
+ fourth: 4,
22203
+ fifth: 5,
22204
+ sixth: 6,
22205
+ seventh: 7,
22206
+ eighth: 8,
22207
+ ninth: 9,
22208
+ tenth: 10,
22209
+ eleventh: 11,
22210
+ twelfth: 12,
22211
+ thirteenth: 13,
22212
+ fourteenth: 14,
22213
+ fifteenth: 15,
22214
+ sixteenth: 16,
22215
+ seventeenth: 17,
22216
+ eighteenth: 18,
22217
+ nineteenth: 19,
22218
+ twentieth: 20,
22219
+ "twenty first": 21,
22220
+ "twenty-first": 21,
22221
+ "twenty second": 22,
22222
+ "twenty-second": 22,
22223
+ "twenty third": 23,
22224
+ "twenty-third": 23,
22225
+ "twenty fourth": 24,
22226
+ "twenty-fourth": 24,
22227
+ "twenty fifth": 25,
22228
+ "twenty-fifth": 25,
22229
+ "twenty sixth": 26,
22230
+ "twenty-sixth": 26,
22231
+ "twenty seventh": 27,
22232
+ "twenty-seventh": 27,
22233
+ "twenty eighth": 28,
22234
+ "twenty-eighth": 28,
22235
+ "twenty ninth": 29,
22236
+ "twenty-ninth": 29,
22237
+ "thirtieth": 30,
22238
+ "thirty first": 31,
22239
+ "thirty-first": 31
22240
+ };
22241
+ var TIME_UNIT_DICTIONARY_NO_ABBR = {
22242
+ second: "second",
22243
+ seconds: "second",
22244
+ minute: "minute",
22245
+ minutes: "minute",
22246
+ hour: "hour",
22247
+ hours: "hour",
22248
+ day: "day",
22249
+ days: "day",
22250
+ week: "week",
22251
+ weeks: "week",
22252
+ month: "month",
22253
+ months: "month",
22254
+ quarter: "quarter",
22255
+ quarters: "quarter",
22256
+ year: "year",
22257
+ years: "year"
22258
+ };
22259
+ var TIME_UNIT_DICTIONARY = {
22260
+ s: "second",
22261
+ sec: "second",
22262
+ second: "second",
22263
+ seconds: "second",
22264
+ m: "minute",
22265
+ min: "minute",
22266
+ mins: "minute",
22267
+ minute: "minute",
22268
+ minutes: "minute",
22269
+ h: "hour",
22270
+ hr: "hour",
22271
+ hrs: "hour",
22272
+ hour: "hour",
22273
+ hours: "hour",
22274
+ d: "day",
22275
+ day: "day",
22276
+ days: "day",
22277
+ w: "week",
22278
+ week: "week",
22279
+ weeks: "week",
22280
+ mo: "month",
22281
+ mon: "month",
22282
+ mos: "month",
22283
+ month: "month",
22284
+ months: "month",
22285
+ qtr: "quarter",
22286
+ quarter: "quarter",
22287
+ quarters: "quarter",
22288
+ y: "year",
22289
+ yr: "year",
22290
+ year: "year",
22291
+ years: "year",
22292
+ ...TIME_UNIT_DICTIONARY_NO_ABBR
22293
+ };
22294
+ var NUMBER_PATTERN = `(?:${matchAnyPattern(INTEGER_WORD_DICTIONARY)}|[0-9]+|[0-9]+\\.[0-9]+|half(?:\\s{0,2}an?)?|an?\\b(?:\\s{0,2}few)?|few|several|the|a?\\s{0,2}couple\\s{0,2}(?:of)?)`;
22295
+ function parseNumberPattern(match) {
22296
+ const num = match.toLowerCase();
22297
+ if (INTEGER_WORD_DICTIONARY[num] !== void 0) {
22298
+ return INTEGER_WORD_DICTIONARY[num];
22299
+ } else if (num === "a" || num === "an" || num == "the") {
22300
+ return 1;
22301
+ } else if (num.match(/few/)) {
22302
+ return 3;
22303
+ } else if (num.match(/half/)) {
22304
+ return 0.5;
22305
+ } else if (num.match(/couple/)) {
22306
+ return 2;
22307
+ } else if (num.match(/several/)) {
22308
+ return 7;
22309
+ }
22310
+ return parseFloat(num);
22311
+ }
22312
+ var ORDINAL_NUMBER_PATTERN = `(?:${matchAnyPattern(ORDINAL_WORD_DICTIONARY)}|[0-9]{1,2}(?:st|nd|rd|th)?)`;
22313
+ function parseOrdinalNumberPattern(match) {
22314
+ let num = match.toLowerCase();
22315
+ if (ORDINAL_WORD_DICTIONARY[num] !== void 0) {
22316
+ return ORDINAL_WORD_DICTIONARY[num];
22317
+ }
22318
+ num = num.replace(/(?:st|nd|rd|th)$/i, "");
22319
+ return parseInt(num);
22320
+ }
22321
+ var YEAR_PATTERN = `(?:[1-9][0-9]{0,3}\\s{0,2}(?:BE|AD|BC|BCE|CE)|[1-9][0-9]{3}|[0-9]{2}(?!\\w|:\\d|\\s+(?:am|pm|o\\s*clock|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)))`;
22322
+ function parseYear(match) {
22323
+ if (/BE/i.test(match)) {
22324
+ match = match.replace(/BE/i, "");
22325
+ return parseInt(match) - 543;
22326
+ }
22327
+ if (/BCE?/i.test(match)) {
22328
+ match = match.replace(/BCE?/i, "");
22329
+ return -parseInt(match);
22330
+ }
22331
+ if (/(AD|CE)/i.test(match)) {
22332
+ match = match.replace(/(AD|CE)/i, "");
22333
+ return parseInt(match);
22334
+ }
22335
+ const rawYearNumber = parseInt(match);
22336
+ return findMostLikelyADYear(rawYearNumber);
22337
+ }
22338
+ var SINGLE_TIME_UNIT_PATTERN = `(${NUMBER_PATTERN})\\s{0,3}(${matchAnyPattern(TIME_UNIT_DICTIONARY)})`;
22339
+ var SINGLE_TIME_UNIT_REGEX = new RegExp(SINGLE_TIME_UNIT_PATTERN, "i");
22340
+ var SINGLE_TIME_UNIT_NO_ABBR_PATTERN = `(${NUMBER_PATTERN})\\s{0,3}(${matchAnyPattern(TIME_UNIT_DICTIONARY_NO_ABBR)})`;
22341
+ var TIME_UNIT_CONNECTOR_PATTERN = `\\s{0,5},?(?:\\s*and)?\\s{0,5}`;
22342
+ var TIME_UNITS_PATTERN = repeatedTimeunitPattern(`(?:(?:about|around)\\s{0,3})?`, SINGLE_TIME_UNIT_PATTERN, TIME_UNIT_CONNECTOR_PATTERN);
22343
+ var TIME_UNITS_NO_ABBR_PATTERN = repeatedTimeunitPattern(`(?:(?:about|around)\\s{0,3})?`, SINGLE_TIME_UNIT_NO_ABBR_PATTERN, TIME_UNIT_CONNECTOR_PATTERN);
22344
+ function parseDuration(timeunitText) {
22345
+ const fragments = {};
22346
+ let remainingText = timeunitText;
22347
+ let match = SINGLE_TIME_UNIT_REGEX.exec(remainingText);
22348
+ while (match) {
22349
+ collectDateTimeFragment(fragments, match);
22350
+ remainingText = remainingText.substring(match[0].length).trim();
22351
+ match = SINGLE_TIME_UNIT_REGEX.exec(remainingText);
22352
+ }
22353
+ if (Object.keys(fragments).length == 0) {
22354
+ return null;
22355
+ }
22356
+ return fragments;
22357
+ }
22358
+ function collectDateTimeFragment(fragments, match) {
22359
+ if (match[0].match(/^[a-zA-Z]+$/)) {
22360
+ return;
22361
+ }
22362
+ const num = parseNumberPattern(match[1]);
22363
+ const unit = TIME_UNIT_DICTIONARY[match[2].toLowerCase()];
22364
+ fragments[unit] = num;
22365
+ }
22366
+
22367
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/parsers/AbstractParserWithWordBoundary.js
22368
+ var AbstractParserWithWordBoundaryChecking = class {
22369
+ innerPatternHasChange(context, currentInnerPattern) {
22370
+ return this.innerPattern(context) !== currentInnerPattern;
22371
+ }
22372
+ patternLeftBoundary() {
22373
+ return `(\\W|^)`;
22374
+ }
22375
+ cachedInnerPattern = null;
22376
+ cachedPattern = null;
22377
+ pattern(context) {
22378
+ if (this.cachedInnerPattern) {
22379
+ if (!this.innerPatternHasChange(context, this.cachedInnerPattern)) {
22380
+ return this.cachedPattern;
22381
+ }
22382
+ }
22383
+ this.cachedInnerPattern = this.innerPattern(context);
22384
+ this.cachedPattern = new RegExp(`${this.patternLeftBoundary()}${this.cachedInnerPattern.source}`, this.cachedInnerPattern.flags);
22385
+ return this.cachedPattern;
22386
+ }
22387
+ extract(context, match) {
22388
+ const header = match[1] ?? "";
22389
+ match.index = match.index + header.length;
22390
+ match[0] = match[0].substring(header.length);
22391
+ for (let i = 2; i < match.length; i++) {
22392
+ match[i - 1] = match[i];
22393
+ }
22394
+ return this.innerExtract(context, match);
22395
+ }
22396
+ };
22397
+
22398
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js
22399
+ var PATTERN_WITH_OPTIONAL_PREFIX = new RegExp(`(?:(?:within|in|for)\\s*)?(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
22400
+ var PATTERN_WITH_PREFIX = new RegExp(`(?:within|in|for)\\s*(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
22401
+ var PATTERN_WITH_PREFIX_STRICT = new RegExp(`(?:within|in|for)\\s*(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_NO_ABBR_PATTERN})(?=\\W|$)`, "i");
22402
+ var ENTimeUnitWithinFormatParser = class extends AbstractParserWithWordBoundaryChecking {
22403
+ strictMode;
22404
+ constructor(strictMode) {
22405
+ super();
22406
+ this.strictMode = strictMode;
22407
+ }
22408
+ innerPattern(context) {
22409
+ if (this.strictMode) {
22410
+ return PATTERN_WITH_PREFIX_STRICT;
22411
+ }
22412
+ return context.option.forwardDate ? PATTERN_WITH_OPTIONAL_PREFIX : PATTERN_WITH_PREFIX;
22413
+ }
22414
+ innerExtract(context, match) {
22415
+ if (match[0].match(/^for\s*the\s*\w+/)) {
22416
+ return null;
22417
+ }
22418
+ const timeUnits = parseDuration(match[1]);
22419
+ if (!timeUnits) {
22420
+ return null;
22421
+ }
22422
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
22423
+ }
22424
+ };
22425
+
22426
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENMonthNameLittleEndianParser.js
22427
+ var PATTERN = new RegExp(`(?:on\\s{0,3})?(${ORDINAL_NUMBER_PATTERN})(?:\\s{0,3}(?:to|\\-|\\\u2013|until|through|till)\\s{0,3}(${ORDINAL_NUMBER_PATTERN}))?(?:-|/|\\s{0,3}(?:of)?\\s{0,3})(${matchAnyPattern(MONTH_DICTIONARY)})(?:(?:-|/|,?\\s{0,3})(${YEAR_PATTERN}(?!\\w)))?(?=\\W|$)`, "i");
22428
+ var DATE_GROUP = 1;
22429
+ var DATE_TO_GROUP = 2;
22430
+ var MONTH_NAME_GROUP = 3;
22431
+ var YEAR_GROUP = 4;
22432
+ var ENMonthNameLittleEndianParser = class extends AbstractParserWithWordBoundaryChecking {
22433
+ innerPattern() {
22434
+ return PATTERN;
22435
+ }
22436
+ innerExtract(context, match) {
22437
+ const result = context.createParsingResult(match.index, match[0]);
22438
+ const month = MONTH_DICTIONARY[match[MONTH_NAME_GROUP].toLowerCase()];
22439
+ const day = parseOrdinalNumberPattern(match[DATE_GROUP]);
22440
+ if (day > 31) {
22441
+ match.index = match.index + match[DATE_GROUP].length;
22442
+ return null;
22443
+ }
22444
+ result.start.assign("month", month);
22445
+ result.start.assign("day", day);
22446
+ if (match[YEAR_GROUP]) {
22447
+ const yearNumber = parseYear(match[YEAR_GROUP]);
22448
+ result.start.assign("year", yearNumber);
22449
+ } else {
22450
+ const year = findYearClosestToRef(context.refDate, day, month);
22451
+ result.start.imply("year", year);
22452
+ }
22453
+ if (match[DATE_TO_GROUP]) {
22454
+ const endDate = parseOrdinalNumberPattern(match[DATE_TO_GROUP]);
22455
+ result.end = result.start.clone();
22456
+ result.end.assign("day", endDate);
22457
+ }
22458
+ return result;
22459
+ }
22460
+ };
22461
+
22462
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENMonthNameMiddleEndianParser.js
22463
+ var PATTERN2 = new RegExp(`(${matchAnyPattern(MONTH_DICTIONARY)})(?:-|/|\\s*,?\\s*)(${ORDINAL_NUMBER_PATTERN})(?!\\s*(?:am|pm))\\s*(?:(?:to|\\-)\\s*(${ORDINAL_NUMBER_PATTERN})\\s*)?(?:(?:-|/|\\s*,\\s*|\\s+)(${YEAR_PATTERN}))?(?=\\W|$)(?!\\:\\d)`, "i");
22464
+ var MONTH_NAME_GROUP2 = 1;
22465
+ var DATE_GROUP2 = 2;
22466
+ var DATE_TO_GROUP2 = 3;
22467
+ var YEAR_GROUP2 = 4;
22468
+ var ENMonthNameMiddleEndianParser = class extends AbstractParserWithWordBoundaryChecking {
22469
+ shouldSkipYearLikeDate;
22470
+ constructor(shouldSkipYearLikeDate) {
22471
+ super();
22472
+ this.shouldSkipYearLikeDate = shouldSkipYearLikeDate;
22473
+ }
22474
+ innerPattern() {
22475
+ return PATTERN2;
22476
+ }
22477
+ innerExtract(context, match) {
22478
+ const month = MONTH_DICTIONARY[match[MONTH_NAME_GROUP2].toLowerCase()];
22479
+ const day = parseOrdinalNumberPattern(match[DATE_GROUP2]);
22480
+ if (day > 31) {
22481
+ return null;
22482
+ }
22483
+ if (this.shouldSkipYearLikeDate) {
22484
+ if (!match[DATE_TO_GROUP2] && !match[YEAR_GROUP2] && match[DATE_GROUP2].match(/^\d{2}$/)) {
22485
+ return null;
22486
+ }
22487
+ }
22488
+ const components = context.createParsingComponents({
22489
+ day,
22490
+ month
22491
+ }).addTag("parser/ENMonthNameMiddleEndianParser");
22492
+ if (match[YEAR_GROUP2]) {
22493
+ const year = parseYear(match[YEAR_GROUP2]);
22494
+ components.assign("year", year);
22495
+ } else {
22496
+ const year = findYearClosestToRef(context.refDate, day, month);
22497
+ components.imply("year", year);
22498
+ }
22499
+ if (!match[DATE_TO_GROUP2]) {
22500
+ return components;
22501
+ }
22502
+ const endDate = parseOrdinalNumberPattern(match[DATE_TO_GROUP2]);
22503
+ const result = context.createParsingResult(match.index, match[0]);
22504
+ result.start = components;
22505
+ result.end = components.clone();
22506
+ result.end.assign("day", endDate);
22507
+ return result;
22508
+ }
22509
+ };
22510
+
22511
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENMonthNameParser.js
22512
+ var PATTERN3 = new RegExp(`((?:in)\\s*)?(${matchAnyPattern(MONTH_DICTIONARY)})\\s*(?:(?:,|-|of)?\\s*(${YEAR_PATTERN})?)?(?=[^\\s\\w]|\\s+[^0-9]|\\s+$|$)`, "i");
22513
+ var PREFIX_GROUP = 1;
22514
+ var MONTH_NAME_GROUP3 = 2;
22515
+ var YEAR_GROUP3 = 3;
22516
+ var ENMonthNameParser = class extends AbstractParserWithWordBoundaryChecking {
22517
+ innerPattern() {
22518
+ return PATTERN3;
22519
+ }
22520
+ innerExtract(context, match) {
22521
+ const monthName = match[MONTH_NAME_GROUP3].toLowerCase();
22522
+ if (match[0].length <= 3 && !FULL_MONTH_NAME_DICTIONARY[monthName]) {
22523
+ return null;
22524
+ }
22525
+ const result = context.createParsingResult(match.index + (match[PREFIX_GROUP] || "").length, match.index + match[0].length);
22526
+ result.start.imply("day", 1);
22527
+ result.start.addTag("parser/ENMonthNameParser");
22528
+ const month = MONTH_DICTIONARY[monthName];
22529
+ result.start.assign("month", month);
22530
+ if (match[YEAR_GROUP3]) {
22531
+ const year = parseYear(match[YEAR_GROUP3]);
22532
+ result.start.assign("year", year);
22533
+ } else {
22534
+ const year = findYearClosestToRef(context.refDate, 1, month);
22535
+ result.start.imply("year", year);
22536
+ }
22537
+ return result;
22538
+ }
22539
+ };
22540
+
22541
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENYearMonthDayParser.js
22542
+ var PATTERN4 = new RegExp(`([0-9]{4})[-\\.\\/\\s](?:(${matchAnyPattern(MONTH_DICTIONARY)})|([0-9]{1,2}))[-\\.\\/\\s]([0-9]{1,2})(?=\\W|$)`, "i");
22543
+ var YEAR_NUMBER_GROUP = 1;
22544
+ var MONTH_NAME_GROUP4 = 2;
22545
+ var MONTH_NUMBER_GROUP = 3;
22546
+ var DATE_NUMBER_GROUP = 4;
22547
+ var ENYearMonthDayParser = class extends AbstractParserWithWordBoundaryChecking {
22548
+ strictMonthDateOrder;
22549
+ constructor(strictMonthDateOrder) {
22550
+ super();
22551
+ this.strictMonthDateOrder = strictMonthDateOrder;
22552
+ }
22553
+ innerPattern() {
22554
+ return PATTERN4;
22555
+ }
22556
+ innerExtract(context, match) {
22557
+ const year = parseInt(match[YEAR_NUMBER_GROUP]);
22558
+ let day = parseInt(match[DATE_NUMBER_GROUP]);
22559
+ let month = match[MONTH_NUMBER_GROUP] ? parseInt(match[MONTH_NUMBER_GROUP]) : MONTH_DICTIONARY[match[MONTH_NAME_GROUP4].toLowerCase()];
22560
+ if (month < 1 || month > 12) {
22561
+ if (this.strictMonthDateOrder) {
22562
+ return null;
22563
+ }
22564
+ if (day >= 1 && day <= 12) {
22565
+ [month, day] = [day, month];
22566
+ }
22567
+ }
22568
+ if (day < 1 || day > 31) {
22569
+ return null;
22570
+ }
22571
+ return {
22572
+ day,
22573
+ month,
22574
+ year
22575
+ };
22576
+ }
22577
+ };
22578
+
22579
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENYearMonthNameParser.js
22580
+ var YEAR_PATTERN2 = `(?:[1-9][0-9]{0,3}\\s{0,2}(?:BE|AD|BC|BCE|CE)|[1-9][0-9]{3})`;
22581
+ var PATTERN5 = new RegExp(`(${YEAR_PATTERN2})(?:\\s*[-.\\/,]?\\s*|\\s+of\\s+)(${matchAnyPattern(MONTH_DICTIONARY)})(?=[^\\s\\w]|\\s+[^0-9]|\\s+$|$)`, "i");
22582
+ var YEAR_GROUP4 = 1;
22583
+ var MONTH_NAME_GROUP5 = 2;
22584
+ var ENYearMonthNameParser = class extends AbstractParserWithWordBoundaryChecking {
22585
+ innerPattern() {
22586
+ return PATTERN5;
22587
+ }
22588
+ innerExtract(context, match) {
22589
+ const year = parseYear(match[YEAR_GROUP4]);
22590
+ const monthName = match[MONTH_NAME_GROUP5].toLowerCase();
22591
+ const month = MONTH_DICTIONARY[monthName];
22592
+ const result = context.createParsingResult(match.index, match[0]);
22593
+ result.start.imply("day", 1);
22594
+ result.start.assign("month", month);
22595
+ result.start.assign("year", year);
22596
+ result.start.addTag("parser/ENYearMonthNameParser");
22597
+ return result;
22598
+ }
22599
+ };
22600
+
22601
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENSlashMonthFormatParser.js
22602
+ var PATTERN6 = new RegExp("([0-9]|0[1-9]|1[012])/([0-9]{4})", "i");
22603
+ var MONTH_GROUP = 1;
22604
+ var YEAR_GROUP5 = 2;
22605
+ var ENSlashMonthFormatParser = class extends AbstractParserWithWordBoundaryChecking {
22606
+ innerPattern() {
22607
+ return PATTERN6;
22608
+ }
22609
+ innerExtract(context, match) {
22610
+ const year = parseInt(match[YEAR_GROUP5]);
22611
+ const month = parseInt(match[MONTH_GROUP]);
22612
+ return context.createParsingComponents().imply("day", 1).assign("month", month).assign("year", year);
22613
+ }
22614
+ };
22615
+
22616
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/parsers/AbstractTimeExpressionParser.js
22617
+ function primaryTimePattern(leftBoundary, primaryPrefix, primarySuffix, flags) {
22618
+ return new RegExp(`${leftBoundary}${primaryPrefix}(\\d{1,4})(?:(?:\\.|:|\uFF1A)(\\d{1,2})(?:(?::|\uFF1A)(\\d{2})(?:\\.(\\d{1,6}))?)?)?(?:\\s*(a\\.m\\.|p\\.m\\.|am?|pm?))?${primarySuffix}`, flags);
22619
+ }
22620
+ function followingTimePatten(followingPhase, followingSuffix) {
22621
+ return new RegExp(`^(${followingPhase})(\\d{1,4})(?:(?:\\.|\\:|\\\uFF1A)(\\d{1,2})(?:(?:\\.|\\:|\\\uFF1A)(\\d{1,2})(?:\\.(\\d{1,6}))?)?)?(?:\\s*(a\\.m\\.|p\\.m\\.|am?|pm?))?${followingSuffix}`, "i");
22622
+ }
22623
+ var HOUR_GROUP = 2;
22624
+ var MINUTE_GROUP = 3;
22625
+ var SECOND_GROUP = 4;
22626
+ var MILLI_SECOND_GROUP = 5;
22627
+ var AM_PM_HOUR_GROUP = 6;
22628
+ var AbstractTimeExpressionParser = class {
22629
+ strictMode;
22630
+ constructor(strictMode = false) {
22631
+ this.strictMode = strictMode;
22632
+ }
22633
+ patternFlags() {
22634
+ return "i";
22635
+ }
22636
+ primaryPatternLeftBoundary() {
22637
+ return `(^|\\s|T|\\b)`;
22638
+ }
22639
+ primarySuffix() {
22640
+ return `(?!/)(?=\\W|$)`;
22641
+ }
22642
+ followingSuffix() {
22643
+ return `(?!/)(?=\\W|$)`;
22644
+ }
22645
+ pattern(context) {
22646
+ return this.getPrimaryTimePatternThroughCache();
22647
+ }
22648
+ extract(context, match) {
22649
+ const startComponents = this.extractPrimaryTimeComponents(context, match);
22650
+ if (!startComponents) {
22651
+ if (match[0].match(/^\d{4}/)) {
22652
+ match.index += 4;
22653
+ return null;
22654
+ }
22655
+ match.index += match[0].length;
22656
+ return null;
22657
+ }
22658
+ const index = match.index + match[1].length;
22659
+ const text2 = match[0].substring(match[1].length);
22660
+ const result = context.createParsingResult(index, text2, startComponents);
22661
+ match.index += match[0].length;
22662
+ const remainingText = context.text.substring(match.index);
22663
+ const followingPattern = this.getFollowingTimePatternThroughCache();
22664
+ const followingMatch = followingPattern.exec(remainingText);
22665
+ if (text2.match(/^\d{3,4}/) && followingMatch) {
22666
+ if (followingMatch[0].match(/^\s*([+-])\s*\d{2,4}$/)) {
22667
+ return null;
22668
+ }
22669
+ if (followingMatch[0].match(/^\s*([+-])\s*\d{2}\W\d{2}/)) {
22670
+ return null;
22671
+ }
22672
+ }
22673
+ if (!followingMatch || followingMatch[0].match(/^\s*([+-])\s*\d{3,4}$/)) {
22674
+ return this.checkAndReturnWithoutFollowingPattern(result);
22675
+ }
22676
+ result.end = this.extractFollowingTimeComponents(context, followingMatch, result);
22677
+ if (result.end) {
22678
+ result.text += followingMatch[0];
22679
+ }
22680
+ return this.checkAndReturnWithFollowingPattern(result);
22681
+ }
22682
+ extractPrimaryTimeComponents(context, match, strict2 = false) {
22683
+ const components = context.createParsingComponents();
22684
+ let minute = 0;
22685
+ let meridiem = null;
22686
+ let hour = parseInt(match[HOUR_GROUP]);
22687
+ if (hour > 100) {
22688
+ if (match[HOUR_GROUP].length == 4 && match[MINUTE_GROUP] == null && !match[AM_PM_HOUR_GROUP]) {
22689
+ return null;
22690
+ }
22691
+ if (this.strictMode || match[MINUTE_GROUP] != null) {
22692
+ return null;
22693
+ }
22694
+ minute = hour % 100;
22695
+ hour = Math.floor(hour / 100);
22696
+ }
22697
+ if (hour > 24) {
22698
+ return null;
22699
+ }
22700
+ if (match[MINUTE_GROUP] != null) {
22701
+ if (match[MINUTE_GROUP].length == 1 && !match[AM_PM_HOUR_GROUP]) {
22702
+ return null;
22703
+ }
22704
+ minute = parseInt(match[MINUTE_GROUP]);
22705
+ }
22706
+ if (minute >= 60) {
22707
+ return null;
22708
+ }
22709
+ if (hour > 12) {
22710
+ meridiem = Meridiem.PM;
22711
+ }
22712
+ if (match[AM_PM_HOUR_GROUP] != null) {
22713
+ if (hour > 12)
22714
+ return null;
22715
+ const ampm = match[AM_PM_HOUR_GROUP][0].toLowerCase();
22716
+ if (ampm == "a") {
22717
+ meridiem = Meridiem.AM;
22718
+ if (hour == 12) {
22719
+ hour = 0;
22720
+ }
22721
+ }
22722
+ if (ampm == "p") {
22723
+ meridiem = Meridiem.PM;
22724
+ if (hour != 12) {
22725
+ hour += 12;
22726
+ }
22727
+ }
22728
+ }
22729
+ components.assign("hour", hour);
22730
+ components.assign("minute", minute);
22731
+ if (meridiem !== null) {
22732
+ components.assign("meridiem", meridiem);
22733
+ } else {
22734
+ if (hour < 12) {
22735
+ components.imply("meridiem", Meridiem.AM);
22736
+ } else {
22737
+ components.imply("meridiem", Meridiem.PM);
22738
+ }
22739
+ }
22740
+ if (match[MILLI_SECOND_GROUP] != null) {
22741
+ const millisecond = parseInt(match[MILLI_SECOND_GROUP].substring(0, 3));
22742
+ if (millisecond >= 1e3)
22743
+ return null;
22744
+ components.assign("millisecond", millisecond);
22745
+ }
22746
+ if (match[SECOND_GROUP] != null) {
22747
+ const second = parseInt(match[SECOND_GROUP]);
22748
+ if (second >= 60)
22749
+ return null;
22750
+ components.assign("second", second);
22751
+ }
22752
+ return components;
22753
+ }
22754
+ extractFollowingTimeComponents(context, match, result) {
22755
+ const components = context.createParsingComponents();
22756
+ if (match[MILLI_SECOND_GROUP] != null) {
22757
+ const millisecond = parseInt(match[MILLI_SECOND_GROUP].substring(0, 3));
22758
+ if (millisecond >= 1e3)
22759
+ return null;
22760
+ components.assign("millisecond", millisecond);
22761
+ }
22762
+ if (match[SECOND_GROUP] != null) {
22763
+ const second = parseInt(match[SECOND_GROUP]);
22764
+ if (second >= 60)
22765
+ return null;
22766
+ components.assign("second", second);
22767
+ }
22768
+ let hour = parseInt(match[HOUR_GROUP]);
22769
+ let minute = 0;
22770
+ let meridiem = -1;
22771
+ if (match[MINUTE_GROUP] != null) {
22772
+ minute = parseInt(match[MINUTE_GROUP]);
22773
+ } else if (hour > 100) {
22774
+ minute = hour % 100;
22775
+ hour = Math.floor(hour / 100);
22776
+ }
22777
+ if (minute >= 60 || hour > 24) {
22778
+ return null;
22779
+ }
22780
+ if (hour >= 12) {
22781
+ meridiem = Meridiem.PM;
22782
+ }
22783
+ if (match[AM_PM_HOUR_GROUP] != null) {
22784
+ if (hour > 12) {
22785
+ return null;
22786
+ }
22787
+ const ampm = match[AM_PM_HOUR_GROUP][0].toLowerCase();
22788
+ if (ampm == "a") {
22789
+ meridiem = Meridiem.AM;
22790
+ if (hour == 12) {
22791
+ hour = 0;
22792
+ if (!components.isCertain("day")) {
22793
+ components.imply("day", components.get("day") + 1);
22794
+ }
22795
+ }
22796
+ }
22797
+ if (ampm == "p") {
22798
+ meridiem = Meridiem.PM;
22799
+ if (hour != 12)
22800
+ hour += 12;
22801
+ }
22802
+ if (!result.start.isCertain("meridiem")) {
22803
+ if (meridiem == Meridiem.AM) {
22804
+ result.start.imply("meridiem", Meridiem.AM);
22805
+ if (result.start.get("hour") == 12) {
22806
+ result.start.assign("hour", 0);
22807
+ }
22808
+ } else {
22809
+ result.start.imply("meridiem", Meridiem.PM);
22810
+ if (result.start.get("hour") != 12) {
22811
+ result.start.assign("hour", result.start.get("hour") + 12);
22812
+ }
22813
+ }
22814
+ }
22815
+ }
22816
+ components.assign("hour", hour);
22817
+ components.assign("minute", minute);
22818
+ if (meridiem >= 0) {
22819
+ components.assign("meridiem", meridiem);
22820
+ } else {
22821
+ const startAtPM = result.start.isCertain("meridiem") && result.start.get("hour") > 12;
22822
+ if (startAtPM) {
22823
+ if (result.start.get("hour") - 12 > hour) {
22824
+ components.imply("meridiem", Meridiem.AM);
22825
+ } else if (hour <= 12) {
22826
+ components.assign("hour", hour + 12);
22827
+ components.assign("meridiem", Meridiem.PM);
22828
+ }
22829
+ } else if (hour > 12) {
22830
+ components.imply("meridiem", Meridiem.PM);
22831
+ } else if (hour <= 12) {
22832
+ components.imply("meridiem", Meridiem.AM);
22833
+ }
22834
+ }
22835
+ if (components.date().getTime() < result.start.date().getTime()) {
22836
+ components.imply("day", components.get("day") + 1);
22837
+ }
22838
+ return components;
22839
+ }
22840
+ checkAndReturnWithoutFollowingPattern(result) {
22841
+ if (result.text.match(/^\d$/)) {
22842
+ return null;
22843
+ }
22844
+ if (result.text.match(/^\d\d\d+$/)) {
22845
+ return null;
22846
+ }
22847
+ if (result.text.match(/\d[apAP]$/)) {
22848
+ return null;
22849
+ }
22850
+ const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)$/);
22851
+ if (endingWithNumbers) {
22852
+ const endingNumbers = endingWithNumbers[1];
22853
+ if (this.strictMode) {
22854
+ return null;
22855
+ }
22856
+ if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) {
22857
+ return null;
22858
+ }
22859
+ const endingNumberVal = parseInt(endingNumbers);
22860
+ if (endingNumberVal > 24) {
22861
+ return null;
22862
+ }
22863
+ }
22864
+ return result;
22865
+ }
22866
+ checkAndReturnWithFollowingPattern(result) {
22867
+ if (result.text.match(/^\d+-\d+$/)) {
22868
+ return null;
22869
+ }
22870
+ const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)\s*-\s*(\d[\d.]+)$/);
22871
+ if (endingWithNumbers) {
22872
+ if (this.strictMode) {
22873
+ return null;
22874
+ }
22875
+ const startingNumbers = endingWithNumbers[1];
22876
+ const endingNumbers = endingWithNumbers[2];
22877
+ if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) {
22878
+ return null;
22879
+ }
22880
+ const endingNumberVal = parseInt(endingNumbers);
22881
+ const startingNumberVal = parseInt(startingNumbers);
22882
+ if (endingNumberVal > 24 || startingNumberVal > 24) {
22883
+ return null;
22884
+ }
22885
+ }
22886
+ return result;
22887
+ }
22888
+ cachedPrimaryPrefix = null;
22889
+ cachedPrimarySuffix = null;
22890
+ cachedPrimaryTimePattern = null;
22891
+ getPrimaryTimePatternThroughCache() {
22892
+ const primaryPrefix = this.primaryPrefix();
22893
+ const primarySuffix = this.primarySuffix();
22894
+ if (this.cachedPrimaryPrefix === primaryPrefix && this.cachedPrimarySuffix === primarySuffix) {
22895
+ return this.cachedPrimaryTimePattern;
22896
+ }
22897
+ this.cachedPrimaryTimePattern = primaryTimePattern(this.primaryPatternLeftBoundary(), primaryPrefix, primarySuffix, this.patternFlags());
22898
+ this.cachedPrimaryPrefix = primaryPrefix;
22899
+ this.cachedPrimarySuffix = primarySuffix;
22900
+ return this.cachedPrimaryTimePattern;
22901
+ }
22902
+ cachedFollowingPhase = null;
22903
+ cachedFollowingSuffix = null;
22904
+ cachedFollowingTimePatten = null;
22905
+ getFollowingTimePatternThroughCache() {
22906
+ const followingPhase = this.followingPhase();
22907
+ const followingSuffix = this.followingSuffix();
22908
+ if (this.cachedFollowingPhase === followingPhase && this.cachedFollowingSuffix === followingSuffix) {
22909
+ return this.cachedFollowingTimePatten;
22910
+ }
22911
+ this.cachedFollowingTimePatten = followingTimePatten(followingPhase, followingSuffix);
22912
+ this.cachedFollowingPhase = followingPhase;
22913
+ this.cachedFollowingSuffix = followingSuffix;
22914
+ return this.cachedFollowingTimePatten;
22915
+ }
22916
+ };
22917
+
22918
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeExpressionParser.js
22919
+ var ENTimeExpressionParser = class extends AbstractTimeExpressionParser {
22920
+ constructor(strictMode) {
22921
+ super(strictMode);
22922
+ }
22923
+ followingPhase() {
22924
+ return "\\s*(?:\\-|\\\u2013|\\~|\\\u301C|to|until|through|till|\\?)\\s*";
22925
+ }
22926
+ primaryPrefix() {
22927
+ return "(?:(?:at|from)\\s*)??";
22928
+ }
22929
+ primarySuffix() {
22930
+ return "(?:\\s*(?:o\\W*clock|at\\s*night|in\\s*the\\s*(?:morning|afternoon)))?(?!/)(?=\\W|$)";
22931
+ }
22932
+ extractPrimaryTimeComponents(context, match) {
22933
+ const components = super.extractPrimaryTimeComponents(context, match);
22934
+ if (!components) {
22935
+ return components;
22936
+ }
22937
+ if (match[0].endsWith("night")) {
22938
+ const hour = components.get("hour");
22939
+ if (hour >= 6 && hour < 12) {
22940
+ components.assign("hour", components.get("hour") + 12);
22941
+ components.assign("meridiem", Meridiem.PM);
22942
+ } else if (hour < 6) {
22943
+ components.assign("meridiem", Meridiem.AM);
22944
+ }
22945
+ }
22946
+ if (match[0].endsWith("afternoon")) {
22947
+ components.assign("meridiem", Meridiem.PM);
22948
+ const hour = components.get("hour");
22949
+ if (hour >= 0 && hour <= 6) {
22950
+ components.assign("hour", components.get("hour") + 12);
22951
+ }
22952
+ }
22953
+ if (match[0].endsWith("morning")) {
22954
+ components.assign("meridiem", Meridiem.AM);
22955
+ const hour = components.get("hour");
22956
+ if (hour < 12) {
22957
+ components.assign("hour", components.get("hour"));
22958
+ }
22959
+ }
22960
+ return components.addTag("parser/ENTimeExpressionParser");
22961
+ }
22962
+ extractFollowingTimeComponents(context, match, result) {
22963
+ const followingComponents = super.extractFollowingTimeComponents(context, match, result);
22964
+ if (followingComponents) {
22965
+ followingComponents.addTag("parser/ENTimeExpressionParser");
22966
+ }
22967
+ return followingComponents;
22968
+ }
22969
+ };
22970
+
22971
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitAgoFormatParser.js
22972
+ var PATTERN7 = new RegExp(`(${TIME_UNITS_PATTERN})\\s{0,5}(?:ago|before|earlier)(?=\\W|$)`, "i");
22973
+ var STRICT_PATTERN = new RegExp(`(${TIME_UNITS_NO_ABBR_PATTERN})\\s{0,5}(?:ago|before|earlier)(?=\\W|$)`, "i");
22974
+ var ENTimeUnitAgoFormatParser = class extends AbstractParserWithWordBoundaryChecking {
22975
+ strictMode;
22976
+ constructor(strictMode) {
22977
+ super();
22978
+ this.strictMode = strictMode;
22979
+ }
22980
+ innerPattern() {
22981
+ return this.strictMode ? STRICT_PATTERN : PATTERN7;
22982
+ }
22983
+ innerExtract(context, match) {
22984
+ const duration3 = parseDuration(match[1]);
22985
+ if (!duration3) {
22986
+ return null;
22987
+ }
22988
+ return ParsingComponents.createRelativeFromReference(context.reference, reverseDuration(duration3));
22989
+ }
22990
+ };
22991
+
22992
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitLaterFormatParser.js
22993
+ var PATTERN8 = new RegExp(`(${TIME_UNITS_PATTERN})\\s{0,5}(?:later|after|from now|henceforth|forward|out)(?=(?:\\W|$))`, "i");
22994
+ var STRICT_PATTERN2 = new RegExp(`(${TIME_UNITS_NO_ABBR_PATTERN})\\s{0,5}(later|after|from now)(?=\\W|$)`, "i");
22995
+ var GROUP_NUM_TIMEUNITS = 1;
22996
+ var ENTimeUnitLaterFormatParser = class extends AbstractParserWithWordBoundaryChecking {
22997
+ strictMode;
22998
+ constructor(strictMode) {
22999
+ super();
23000
+ this.strictMode = strictMode;
23001
+ }
23002
+ innerPattern() {
23003
+ return this.strictMode ? STRICT_PATTERN2 : PATTERN8;
23004
+ }
23005
+ innerExtract(context, match) {
23006
+ const timeUnits = parseDuration(match[GROUP_NUM_TIMEUNITS]);
23007
+ if (!timeUnits) {
23008
+ return null;
23009
+ }
23010
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
23011
+ }
23012
+ };
23013
+
23014
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/abstractRefiners.js
23015
+ var Filter = class {
23016
+ refine(context, results) {
23017
+ return results.filter((r) => this.isValid(context, r));
23018
+ }
23019
+ };
23020
+ var MergingRefiner = class {
23021
+ refine(context, results) {
23022
+ if (results.length < 2) {
23023
+ return results;
23024
+ }
23025
+ const mergedResults = [];
23026
+ let curResult = results[0];
23027
+ let nextResult = null;
23028
+ for (let i = 1; i < results.length; i++) {
23029
+ nextResult = results[i];
23030
+ const textBetween = context.text.substring(curResult.index + curResult.text.length, nextResult.index);
23031
+ if (!this.shouldMergeResults(textBetween, curResult, nextResult, context)) {
23032
+ mergedResults.push(curResult);
23033
+ curResult = nextResult;
23034
+ } else {
23035
+ const left = curResult;
23036
+ const right = nextResult;
23037
+ const mergedResult = this.mergeResults(textBetween, left, right, context);
23038
+ context.debug(() => {
23039
+ console.log(`${this.constructor.name} merged ${left} and ${right} into ${mergedResult}`);
23040
+ });
23041
+ curResult = mergedResult;
23042
+ }
23043
+ }
23044
+ if (curResult != null) {
23045
+ mergedResults.push(curResult);
23046
+ }
23047
+ return mergedResults;
23048
+ }
23049
+ };
23050
+
23051
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/AbstractMergeDateRangeRefiner.js
23052
+ var AbstractMergeDateRangeRefiner = class extends MergingRefiner {
23053
+ shouldMergeResults(textBetween, currentResult, nextResult) {
23054
+ return !currentResult.end && !nextResult.end && textBetween.match(this.patternBetween()) != null;
23055
+ }
23056
+ mergeResults(textBetween, fromResult, toResult) {
23057
+ if (!fromResult.start.isOnlyWeekdayComponent() && !toResult.start.isOnlyWeekdayComponent()) {
23058
+ toResult.start.getCertainComponents().forEach((key) => {
23059
+ if (!fromResult.start.isCertain(key)) {
23060
+ fromResult.start.imply(key, toResult.start.get(key));
23061
+ }
23062
+ });
23063
+ fromResult.start.getCertainComponents().forEach((key) => {
23064
+ if (!toResult.start.isCertain(key)) {
23065
+ toResult.start.imply(key, fromResult.start.get(key));
23066
+ }
23067
+ });
23068
+ }
23069
+ if (fromResult.start.date() > toResult.start.date()) {
23070
+ let fromDate = fromResult.start.date();
23071
+ let toDate = toResult.start.date();
23072
+ if (toResult.start.isOnlyWeekdayComponent() && addDuration(toDate, { day: 7 }) > fromDate) {
23073
+ toDate = addDuration(toDate, { day: 7 });
23074
+ toResult.start.imply("day", toDate.getDate());
23075
+ toResult.start.imply("month", toDate.getMonth() + 1);
23076
+ toResult.start.imply("year", toDate.getFullYear());
23077
+ } else if (fromResult.start.isOnlyWeekdayComponent() && addDuration(fromDate, { day: -7 }) < toDate) {
23078
+ fromDate = addDuration(fromDate, { day: -7 });
23079
+ fromResult.start.imply("day", fromDate.getDate());
23080
+ fromResult.start.imply("month", fromDate.getMonth() + 1);
23081
+ fromResult.start.imply("year", fromDate.getFullYear());
23082
+ } else if (toResult.start.isDateWithUnknownYear() && addDuration(toDate, { year: 1 }) > fromDate) {
23083
+ toDate = addDuration(toDate, { year: 1 });
23084
+ toResult.start.imply("year", toDate.getFullYear());
23085
+ } else if (fromResult.start.isDateWithUnknownYear() && addDuration(fromDate, { year: -1 }) < toDate) {
23086
+ fromDate = addDuration(fromDate, { year: -1 });
23087
+ fromResult.start.imply("year", fromDate.getFullYear());
23088
+ } else {
23089
+ [toResult, fromResult] = [fromResult, toResult];
23090
+ }
23091
+ }
23092
+ const result = fromResult.clone();
23093
+ result.start = fromResult.start;
23094
+ result.end = toResult.start;
23095
+ result.index = Math.min(fromResult.index, toResult.index);
23096
+ if (fromResult.index < toResult.index) {
23097
+ result.text = fromResult.text + textBetween + toResult.text;
23098
+ } else {
23099
+ result.text = toResult.text + textBetween + fromResult.text;
23100
+ }
23101
+ return result;
23102
+ }
23103
+ };
23104
+
23105
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeDateRangeRefiner.js
23106
+ var ENMergeDateRangeRefiner = class extends AbstractMergeDateRangeRefiner {
23107
+ patternBetween() {
23108
+ return /^\s*(to|-|–|until|through|till)\s*$/i;
23109
+ }
23110
+ };
23111
+
23112
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/calculation/mergingCalculation.js
23113
+ function mergeDateTimeResult(dateResult, timeResult) {
23114
+ const result = dateResult.clone();
23115
+ const beginDate = dateResult.start;
23116
+ const beginTime = timeResult.start;
23117
+ result.start = mergeDateTimeComponent(beginDate, beginTime);
23118
+ if (dateResult.end != null || timeResult.end != null) {
23119
+ const endDate = dateResult.end == null ? dateResult.start : dateResult.end;
23120
+ const endTime = timeResult.end == null ? timeResult.start : timeResult.end;
23121
+ const endDateTime = mergeDateTimeComponent(endDate, endTime);
23122
+ if (dateResult.end == null && endDateTime.date().getTime() < result.start.date().getTime()) {
23123
+ const nextDay = new Date(endDateTime.date().getTime());
23124
+ nextDay.setDate(nextDay.getDate() + 1);
23125
+ if (endDateTime.isCertain("day")) {
23126
+ assignSimilarDate(endDateTime, nextDay);
23127
+ } else {
23128
+ implySimilarDate(endDateTime, nextDay);
23129
+ }
23130
+ }
23131
+ result.end = endDateTime;
23132
+ }
23133
+ return result;
23134
+ }
23135
+ function mergeDateTimeComponent(dateComponent, timeComponent) {
23136
+ const dateTimeComponent = dateComponent.clone();
23137
+ if (timeComponent.isCertain("hour")) {
23138
+ dateTimeComponent.assign("hour", timeComponent.get("hour"));
23139
+ dateTimeComponent.assign("minute", timeComponent.get("minute"));
23140
+ if (timeComponent.isCertain("second")) {
23141
+ dateTimeComponent.assign("second", timeComponent.get("second"));
23142
+ if (timeComponent.isCertain("millisecond")) {
23143
+ dateTimeComponent.assign("millisecond", timeComponent.get("millisecond"));
23144
+ } else {
23145
+ dateTimeComponent.imply("millisecond", timeComponent.get("millisecond"));
23146
+ }
23147
+ } else {
23148
+ dateTimeComponent.imply("second", timeComponent.get("second"));
23149
+ dateTimeComponent.imply("millisecond", timeComponent.get("millisecond"));
23150
+ }
23151
+ } else {
23152
+ dateTimeComponent.imply("hour", timeComponent.get("hour"));
23153
+ dateTimeComponent.imply("minute", timeComponent.get("minute"));
23154
+ dateTimeComponent.imply("second", timeComponent.get("second"));
23155
+ dateTimeComponent.imply("millisecond", timeComponent.get("millisecond"));
23156
+ }
23157
+ if (timeComponent.isCertain("timezoneOffset")) {
23158
+ dateTimeComponent.assign("timezoneOffset", timeComponent.get("timezoneOffset"));
23159
+ }
23160
+ const dateHasMeaningfulMeridiem = dateComponent.get("meridiem") != null && (dateComponent.isCertain("meridiem") || Array.from(dateComponent.tags()).some((t) => t.startsWith("casualReference/")));
23161
+ if (timeComponent.isCertain("meridiem")) {
23162
+ dateTimeComponent.assign("meridiem", timeComponent.get("meridiem"));
23163
+ } else if (timeComponent.get("meridiem") != null && !dateHasMeaningfulMeridiem) {
23164
+ dateTimeComponent.imply("meridiem", timeComponent.get("meridiem"));
23165
+ }
23166
+ if (dateTimeComponent.get("meridiem") == Meridiem.PM && dateTimeComponent.get("hour") < 12) {
23167
+ if (timeComponent.isCertain("hour")) {
23168
+ dateTimeComponent.assign("hour", dateTimeComponent.get("hour") + 12);
23169
+ } else {
23170
+ dateTimeComponent.imply("hour", dateTimeComponent.get("hour") + 12);
23171
+ }
23172
+ }
23173
+ dateTimeComponent.addTags(dateComponent.tags());
23174
+ dateTimeComponent.addTags(timeComponent.tags());
23175
+ return dateTimeComponent;
23176
+ }
23177
+
23178
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/AbstractMergeDateTimeRefiner.js
23179
+ var AbstractMergeDateTimeRefiner = class extends MergingRefiner {
23180
+ shouldMergeResults(textBetween, currentResult, nextResult) {
23181
+ return (currentResult.start.isOnlyDate() && nextResult.start.isOnlyTime() || nextResult.start.isOnlyDate() && currentResult.start.isOnlyTime()) && textBetween.match(this.patternBetween()) != null;
23182
+ }
23183
+ mergeResults(textBetween, currentResult, nextResult) {
23184
+ const result = currentResult.start.isOnlyDate() ? mergeDateTimeResult(currentResult, nextResult) : mergeDateTimeResult(nextResult, currentResult);
23185
+ result.index = currentResult.index;
23186
+ result.text = currentResult.text + textBetween + nextResult.text;
23187
+ return result;
23188
+ }
23189
+ };
23190
+
23191
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeDateTimeRefiner.js
23192
+ var ENMergeDateTimeRefiner = class extends AbstractMergeDateTimeRefiner {
23193
+ patternBetween() {
23194
+ return new RegExp("^\\s*(T|at|after|before|on|of|,|-|\\.|\u2219|:)?\\s*$");
23195
+ }
23196
+ };
23197
+
23198
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/ExtractTimezoneAbbrRefiner.js
23199
+ var TIMEZONE_NAME_PATTERN = new RegExp("^\\s*,?\\s*\\(?([A-Z]{2,4})\\)?(?=\\W|$)", "i");
23200
+ var ExtractTimezoneAbbrRefiner = class {
23201
+ timezoneOverrides;
23202
+ constructor(timezoneOverrides) {
23203
+ this.timezoneOverrides = timezoneOverrides;
23204
+ }
23205
+ refine(context, results) {
23206
+ const timezoneOverrides = context.option.timezones ?? {};
23207
+ results.forEach((result) => {
23208
+ const suffix = context.text.substring(result.index + result.text.length);
23209
+ const match = TIMEZONE_NAME_PATTERN.exec(suffix);
23210
+ if (!match) {
23211
+ return;
23212
+ }
23213
+ const timezoneAbbr = match[1].toUpperCase();
23214
+ const refDate = result.start.date() ?? result.refDate ?? /* @__PURE__ */ new Date();
23215
+ const tzOverrides = { ...this.timezoneOverrides, ...timezoneOverrides };
23216
+ const extractedTimezoneOffset = toTimezoneOffset(timezoneAbbr, refDate, tzOverrides);
23217
+ if (extractedTimezoneOffset == null) {
23218
+ return;
23219
+ }
23220
+ context.debug(() => {
23221
+ console.log(`Extracting timezone: '${timezoneAbbr}' into: ${extractedTimezoneOffset} for: ${result.start}`);
23222
+ });
23223
+ const currentTimezoneOffset = result.start.get("timezoneOffset");
23224
+ if (currentTimezoneOffset !== null && extractedTimezoneOffset != currentTimezoneOffset) {
23225
+ if (result.start.isCertain("timezoneOffset")) {
23226
+ return;
23227
+ }
23228
+ if (timezoneAbbr != match[1]) {
23229
+ return;
23230
+ }
23231
+ }
23232
+ if (result.start.isOnlyDate()) {
23233
+ if (timezoneAbbr != match[1]) {
23234
+ return;
23235
+ }
23236
+ }
23237
+ result.text += match[0];
23238
+ if (!result.start.isCertain("timezoneOffset")) {
23239
+ result.start.assign("timezoneOffset", extractedTimezoneOffset);
23240
+ }
23241
+ if (result.end != null && !result.end.isCertain("timezoneOffset")) {
23242
+ result.end.assign("timezoneOffset", extractedTimezoneOffset);
23243
+ }
23244
+ });
23245
+ return results;
23246
+ }
23247
+ };
23248
+
23249
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/ExtractTimezoneOffsetRefiner.js
23250
+ var TIMEZONE_OFFSET_PATTERN = new RegExp("^\\s*(?:\\(?(?:GMT|UTC)\\s?)?([+-])(\\d{1,2})(?::?(\\d{2}))?\\)?", "i");
23251
+ var TIMEZONE_OFFSET_SIGN_GROUP = 1;
23252
+ var TIMEZONE_OFFSET_HOUR_OFFSET_GROUP = 2;
23253
+ var TIMEZONE_OFFSET_MINUTE_OFFSET_GROUP = 3;
23254
+ var ExtractTimezoneOffsetRefiner = class {
23255
+ refine(context, results) {
23256
+ results.forEach(function(result) {
23257
+ if (result.start.isCertain("timezoneOffset")) {
23258
+ return;
23259
+ }
23260
+ const suffix = context.text.substring(result.index + result.text.length);
23261
+ const match = TIMEZONE_OFFSET_PATTERN.exec(suffix);
23262
+ if (!match) {
23263
+ return;
23264
+ }
23265
+ context.debug(() => {
23266
+ console.log(`Extracting timezone: '${match[0]}' into : ${result}`);
23267
+ });
23268
+ const hourOffset = parseInt(match[TIMEZONE_OFFSET_HOUR_OFFSET_GROUP]);
23269
+ const minuteOffset = parseInt(match[TIMEZONE_OFFSET_MINUTE_OFFSET_GROUP] || "0");
23270
+ let timezoneOffset = hourOffset * 60 + minuteOffset;
23271
+ if (timezoneOffset > 14 * 60) {
23272
+ return;
23273
+ }
23274
+ if (match[TIMEZONE_OFFSET_SIGN_GROUP] === "-") {
23275
+ timezoneOffset = -timezoneOffset;
23276
+ }
23277
+ if (result.end != null) {
23278
+ result.end.assign("timezoneOffset", timezoneOffset);
23279
+ }
23280
+ result.start.assign("timezoneOffset", timezoneOffset);
23281
+ result.text += match[0];
23282
+ });
23283
+ return results;
23284
+ }
23285
+ };
23286
+
23287
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/OverlapRemovalRefiner.js
23288
+ var OverlapRemovalRefiner = class {
23289
+ refine(context, results) {
23290
+ if (results.length < 2) {
23291
+ return results;
23292
+ }
23293
+ const filteredResults = [];
23294
+ let prevResult = results[0];
23295
+ for (let i = 1; i < results.length; i++) {
23296
+ const result = results[i];
23297
+ if (result.index >= prevResult.index + prevResult.text.length) {
23298
+ filteredResults.push(prevResult);
23299
+ prevResult = result;
23300
+ continue;
23301
+ }
23302
+ let kept = null;
23303
+ let removed = null;
23304
+ if (result.text.length > prevResult.text.length) {
23305
+ kept = result;
23306
+ removed = prevResult;
23307
+ } else {
23308
+ kept = prevResult;
23309
+ removed = result;
23310
+ }
23311
+ context.debug(() => {
23312
+ console.log(`${this.constructor.name} remove ${removed} by ${kept}`);
23313
+ });
23314
+ prevResult = kept;
23315
+ }
23316
+ if (prevResult != null) {
23317
+ filteredResults.push(prevResult);
23318
+ }
23319
+ return filteredResults;
23320
+ }
23321
+ };
23322
+
23323
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/calculation/weekdays.js
23324
+ function createParsingComponentsAtWeekday(reference, weekday, modifier) {
23325
+ const refDate = reference.getDateWithAdjustedTimezone();
23326
+ const daysToWeekday = getDaysToWeekday(refDate, weekday, modifier);
23327
+ let components = new ParsingComponents(reference);
23328
+ components = components.addDurationAsImplied({ day: daysToWeekday });
23329
+ components.assign("weekday", weekday);
23330
+ return components;
23331
+ }
23332
+ function getDaysToWeekday(refDate, weekday, modifier) {
23333
+ const refWeekday = refDate.getDay();
23334
+ switch (modifier) {
23335
+ case "this":
23336
+ return getDaysForwardToWeekday(refDate, weekday);
23337
+ case "last":
23338
+ return getBackwardDaysToWeekday(refDate, weekday);
23339
+ case "next":
23340
+ if (refWeekday == Weekday.SUNDAY) {
23341
+ return weekday == Weekday.SUNDAY ? 7 : weekday;
23342
+ }
23343
+ if (refWeekday == Weekday.SATURDAY) {
23344
+ if (weekday == Weekday.SATURDAY)
23345
+ return 7;
23346
+ if (weekday == Weekday.SUNDAY)
23347
+ return 8;
23348
+ return 1 + weekday;
23349
+ }
23350
+ if (weekday < refWeekday && weekday != Weekday.SUNDAY) {
23351
+ return getDaysForwardToWeekday(refDate, weekday);
23352
+ } else {
23353
+ return getDaysForwardToWeekday(refDate, weekday) + 7;
23354
+ }
23355
+ }
23356
+ return getDaysToWeekdayClosest(refDate, weekday);
23357
+ }
23358
+ function getDaysToWeekdayClosest(refDate, weekday) {
23359
+ const backward = getBackwardDaysToWeekday(refDate, weekday);
23360
+ const forward = getDaysForwardToWeekday(refDate, weekday);
23361
+ return forward < -backward ? forward : backward;
23362
+ }
23363
+ function getDaysForwardToWeekday(refDate, weekday) {
23364
+ const refWeekday = refDate.getDay();
23365
+ let forwardCount = weekday - refWeekday;
23366
+ if (forwardCount < 0) {
23367
+ forwardCount += 7;
23368
+ }
23369
+ return forwardCount;
23370
+ }
23371
+ function getBackwardDaysToWeekday(refDate, weekday) {
23372
+ const refWeekday = refDate.getDay();
23373
+ let backwardCount = weekday - refWeekday;
23374
+ if (backwardCount >= 0) {
23375
+ backwardCount -= 7;
23376
+ }
23377
+ return backwardCount;
23378
+ }
23379
+
23380
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/ForwardDateRefiner.js
23381
+ var ForwardDateRefiner = class {
23382
+ refine(context, results) {
23383
+ if (!context.option.forwardDate) {
23384
+ return results;
23385
+ }
23386
+ results.forEach((result) => {
23387
+ let refDate = context.reference.getDateWithAdjustedTimezone();
23388
+ if (result.start.isOnlyTime() && context.reference.instant > result.start.date()) {
23389
+ const refDate2 = context.reference.getDateWithAdjustedTimezone();
23390
+ const refFollowingDay = new Date(refDate2);
23391
+ refFollowingDay.setDate(refFollowingDay.getDate() + 1);
23392
+ implySimilarDate(result.start, refFollowingDay);
23393
+ context.debug(() => {
23394
+ console.log(`${this.constructor.name} adjusted ${result} time from the ref date (${refDate2}) to the following day (${refFollowingDay})`);
23395
+ });
23396
+ if (result.end && result.end.isOnlyTime()) {
23397
+ implySimilarDate(result.end, refFollowingDay);
23398
+ if (result.start.date() > result.end.date()) {
23399
+ refFollowingDay.setDate(refFollowingDay.getDate() + 1);
23400
+ implySimilarDate(result.end, refFollowingDay);
23401
+ }
23402
+ }
23403
+ }
23404
+ if (result.start.isOnlyWeekdayComponent() && refDate > result.start.date()) {
23405
+ let daysToAdd = getDaysForwardToWeekday(refDate, result.start.get("weekday")) || 7;
23406
+ const forwardedWeekday = addDuration(refDate, { day: daysToAdd });
23407
+ implySimilarDate(result.start, forwardedWeekday);
23408
+ context.debug(() => {
23409
+ console.log(`${this.constructor.name} adjusted ${result} weekday (${result.start})`);
23410
+ });
23411
+ if (result.end && result.start.date() > result.end.date()) {
23412
+ let daysToAdd2 = getDaysForwardToWeekday(refDate, result.start.get("weekday")) || 7;
23413
+ const forwardedWeekday2 = addDuration(refDate, { day: daysToAdd2 });
23414
+ implySimilarDate(result.end, forwardedWeekday2);
23415
+ context.debug(() => {
23416
+ console.log(`${this.constructor.name} adjusted ${result} weekday (${result.end})`);
23417
+ });
23418
+ }
23419
+ }
23420
+ if (result.start.isDateWithUnknownYear() && refDate > result.start.date()) {
23421
+ for (let i = 0; i < 3 && refDate > result.start.date(); i++) {
23422
+ result.start.imply("year", result.start.get("year") + 1);
23423
+ context.debug(() => {
23424
+ console.log(`${this.constructor.name} adjusted ${result} year (${result.start})`);
23425
+ });
23426
+ if (result.end && !result.end.isCertain("year")) {
23427
+ result.end.imply("year", result.end.get("year") + 1);
23428
+ context.debug(() => {
23429
+ console.log(`${this.constructor.name} adjusted ${result} month (${result.start})`);
23430
+ });
23431
+ }
23432
+ }
23433
+ }
23434
+ });
23435
+ return results;
23436
+ }
23437
+ };
23438
+
23439
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/UnlikelyFormatFilter.js
23440
+ var UnlikelyFormatFilter = class extends Filter {
23441
+ strictMode;
23442
+ constructor(strictMode) {
23443
+ super();
23444
+ this.strictMode = strictMode;
23445
+ }
23446
+ isValid(context, result) {
23447
+ if (result.text.replace(" ", "").match(/^\d*(\.\d*)?$/)) {
23448
+ context.debug(() => {
23449
+ console.log(`Removing unlikely result '${result.text}'`);
23450
+ });
23451
+ return false;
23452
+ }
23453
+ if (!result.start.isValidDate()) {
23454
+ context.debug(() => {
23455
+ console.log(`Removing invalid result: ${result} (${result.start})`);
23456
+ });
23457
+ return false;
23458
+ }
23459
+ if (result.end && !result.end.isValidDate()) {
23460
+ context.debug(() => {
23461
+ console.log(`Removing invalid result: ${result} (${result.end})`);
23462
+ });
23463
+ return false;
23464
+ }
23465
+ if (this.strictMode) {
23466
+ return this.isStrictModeValid(context, result);
23467
+ }
23468
+ return true;
23469
+ }
23470
+ isStrictModeValid(context, result) {
23471
+ if (result.start.isOnlyWeekdayComponent()) {
23472
+ context.debug(() => {
23473
+ console.log(`(Strict) Removing weekday only component: ${result} (${result.end})`);
23474
+ });
23475
+ return false;
23476
+ }
23477
+ return true;
23478
+ }
23479
+ };
23480
+
23481
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/parsers/ISOFormatParser.js
23482
+ var PATTERN9 = new RegExp("([0-9]{4})\\-([0-9]{1,2})\\-([0-9]{1,2})(?:T([0-9]{1,2}):([0-9]{1,2})(?::([0-9]{1,2})(?:\\.(\\d{1,4}))?)?(Z|([+-]\\d{2}):?(\\d{2})?)?)?(?=\\W|$)", "i");
23483
+ var YEAR_NUMBER_GROUP2 = 1;
23484
+ var MONTH_NUMBER_GROUP2 = 2;
23485
+ var DATE_NUMBER_GROUP2 = 3;
23486
+ var HOUR_NUMBER_GROUP = 4;
23487
+ var MINUTE_NUMBER_GROUP = 5;
23488
+ var SECOND_NUMBER_GROUP = 6;
23489
+ var MILLISECOND_NUMBER_GROUP = 7;
23490
+ var TZD_GROUP = 8;
23491
+ var TZD_HOUR_OFFSET_GROUP = 9;
23492
+ var TZD_MINUTE_OFFSET_GROUP = 10;
23493
+ var ISOFormatParser = class extends AbstractParserWithWordBoundaryChecking {
23494
+ innerPattern() {
23495
+ return PATTERN9;
23496
+ }
23497
+ innerExtract(context, match) {
23498
+ const components = context.createParsingComponents({
23499
+ "year": parseInt(match[YEAR_NUMBER_GROUP2]),
23500
+ "month": parseInt(match[MONTH_NUMBER_GROUP2]),
23501
+ "day": parseInt(match[DATE_NUMBER_GROUP2])
23502
+ });
23503
+ if (match[HOUR_NUMBER_GROUP] != null) {
23504
+ components.assign("hour", parseInt(match[HOUR_NUMBER_GROUP]));
23505
+ components.assign("minute", parseInt(match[MINUTE_NUMBER_GROUP]));
23506
+ if (match[SECOND_NUMBER_GROUP] != null) {
23507
+ components.assign("second", parseInt(match[SECOND_NUMBER_GROUP]));
23508
+ }
23509
+ if (match[MILLISECOND_NUMBER_GROUP] != null) {
23510
+ components.assign("millisecond", parseInt(match[MILLISECOND_NUMBER_GROUP]));
23511
+ }
23512
+ if (match[TZD_GROUP] != null) {
23513
+ let offset = 0;
23514
+ if (match[TZD_HOUR_OFFSET_GROUP]) {
23515
+ const hourOffset = parseInt(match[TZD_HOUR_OFFSET_GROUP]);
23516
+ let minuteOffset = 0;
23517
+ if (match[TZD_MINUTE_OFFSET_GROUP] != null) {
23518
+ minuteOffset = parseInt(match[TZD_MINUTE_OFFSET_GROUP]);
23519
+ }
23520
+ offset = hourOffset * 60;
23521
+ if (offset < 0) {
23522
+ offset -= minuteOffset;
23523
+ } else {
23524
+ offset += minuteOffset;
23525
+ }
23526
+ }
23527
+ components.assign("timezoneOffset", offset);
23528
+ }
23529
+ }
23530
+ return components.addTag("parser/ISOFormatParser");
23531
+ }
23532
+ };
23533
+
23534
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/refiners/MergeWeekdayComponentRefiner.js
23535
+ var MergeWeekdayComponentRefiner = class extends MergingRefiner {
23536
+ mergeResults(textBetween, currentResult, nextResult) {
23537
+ const newResult = nextResult.clone();
23538
+ newResult.index = currentResult.index;
23539
+ newResult.text = currentResult.text + textBetween + newResult.text;
23540
+ newResult.start.assign("weekday", currentResult.start.get("weekday"));
23541
+ if (newResult.end) {
23542
+ newResult.end.assign("weekday", currentResult.start.get("weekday"));
23543
+ }
23544
+ return newResult;
23545
+ }
23546
+ shouldMergeResults(textBetween, currentResult, nextResult) {
23547
+ const weekdayThenNormalDate = currentResult.start.isOnlyWeekdayComponent() && !currentResult.start.isCertain("hour") && nextResult.start.isCertain("day");
23548
+ return weekdayThenNormalDate && textBetween.match(/^,?\s*$/) != null;
23549
+ }
23550
+ };
23551
+
23552
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/configurations.js
23553
+ function includeCommonConfiguration(configuration2, strictMode = false) {
23554
+ configuration2.parsers.unshift(new ISOFormatParser());
23555
+ configuration2.refiners.unshift(new MergeWeekdayComponentRefiner());
23556
+ configuration2.refiners.unshift(new ExtractTimezoneOffsetRefiner());
23557
+ configuration2.refiners.unshift(new OverlapRemovalRefiner());
23558
+ configuration2.refiners.push(new ExtractTimezoneAbbrRefiner());
23559
+ configuration2.refiners.push(new OverlapRemovalRefiner());
23560
+ configuration2.refiners.push(new ForwardDateRefiner());
23561
+ configuration2.refiners.push(new UnlikelyFormatFilter(strictMode));
23562
+ return configuration2;
23563
+ }
23564
+
23565
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/casualReferences.js
23566
+ function now(reference) {
23567
+ const targetDate = reference.getDateWithAdjustedTimezone();
23568
+ const component = new ParsingComponents(reference, {});
23569
+ assignSimilarDate(component, targetDate);
23570
+ assignSimilarTime(component, targetDate);
23571
+ component.assign("timezoneOffset", reference.getTimezoneOffset());
23572
+ component.addTag("casualReference/now");
23573
+ return component;
23574
+ }
23575
+ function today(reference) {
23576
+ const targetDate = reference.getDateWithAdjustedTimezone();
23577
+ const component = new ParsingComponents(reference, {});
23578
+ assignSimilarDate(component, targetDate);
23579
+ implySimilarTime(component, targetDate);
23580
+ component.delete("meridiem");
23581
+ component.addTag("casualReference/today");
23582
+ return component;
23583
+ }
23584
+ function yesterday(reference) {
23585
+ return theDayBefore(reference, 1).addTag("casualReference/yesterday");
23586
+ }
23587
+ function tomorrow(reference) {
23588
+ return theDayAfter(reference, 1).addTag("casualReference/tomorrow");
23589
+ }
23590
+ function theDayBefore(reference, numDay) {
23591
+ return theDayAfter(reference, -numDay);
23592
+ }
23593
+ function theDayAfter(reference, nDays) {
23594
+ const targetDate = reference.getDateWithAdjustedTimezone();
23595
+ const component = new ParsingComponents(reference, {});
23596
+ const newDate = new Date(targetDate.getTime());
23597
+ newDate.setDate(newDate.getDate() + nDays);
23598
+ assignSimilarDate(component, newDate);
23599
+ implySimilarTime(component, newDate);
23600
+ component.delete("meridiem");
23601
+ return component;
23602
+ }
23603
+ function tonight(reference, implyHour = 22) {
23604
+ const targetDate = reference.getDateWithAdjustedTimezone();
23605
+ const component = new ParsingComponents(reference, {});
23606
+ assignSimilarDate(component, targetDate);
23607
+ component.imply("hour", implyHour);
23608
+ component.imply("meridiem", Meridiem.PM);
23609
+ component.addTag("casualReference/tonight");
23610
+ return component;
23611
+ }
23612
+ function evening(reference, implyHour = 20) {
23613
+ const component = new ParsingComponents(reference, {});
23614
+ component.imply("meridiem", Meridiem.PM);
23615
+ component.imply("hour", implyHour);
23616
+ component.addTag("casualReference/evening");
23617
+ return component;
23618
+ }
23619
+ function midnight(reference) {
23620
+ const component = new ParsingComponents(reference, {});
23621
+ if (reference.getDateWithAdjustedTimezone().getHours() > 2) {
23622
+ component.addDurationAsImplied({ day: 1 });
23623
+ }
23624
+ component.assign("hour", 0);
23625
+ component.imply("minute", 0);
23626
+ component.imply("second", 0);
23627
+ component.imply("millisecond", 0);
23628
+ component.addTag("casualReference/midnight");
23629
+ return component;
23630
+ }
23631
+ function morning(reference, implyHour = 6) {
23632
+ const component = new ParsingComponents(reference, {});
23633
+ component.imply("meridiem", Meridiem.AM);
23634
+ component.imply("hour", implyHour);
23635
+ component.imply("minute", 0);
23636
+ component.imply("second", 0);
23637
+ component.imply("millisecond", 0);
23638
+ component.addTag("casualReference/morning");
23639
+ return component;
23640
+ }
23641
+ function afternoon(reference, implyHour = 15) {
23642
+ const component = new ParsingComponents(reference, {});
23643
+ component.imply("meridiem", Meridiem.PM);
23644
+ component.imply("hour", implyHour);
23645
+ component.imply("minute", 0);
23646
+ component.imply("second", 0);
23647
+ component.imply("millisecond", 0);
23648
+ component.addTag("casualReference/afternoon");
23649
+ return component;
23650
+ }
23651
+ function noon(reference) {
23652
+ const component = new ParsingComponents(reference, {});
23653
+ component.imply("meridiem", Meridiem.AM);
23654
+ component.assign("hour", 12);
23655
+ component.imply("minute", 0);
23656
+ component.imply("second", 0);
23657
+ component.imply("millisecond", 0);
23658
+ component.addTag("casualReference/noon");
23659
+ return component;
23660
+ }
23661
+
23662
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENCasualDateParser.js
23663
+ var PATTERN10 = /(now|today|tonight|tomorrow|overmorrow|tmr|tmrw|yesterday|last\s*night)(?=\W|$)/i;
23664
+ var ENCasualDateParser = class extends AbstractParserWithWordBoundaryChecking {
23665
+ innerPattern(context) {
23666
+ return PATTERN10;
23667
+ }
23668
+ innerExtract(context, match) {
23669
+ let targetDate = context.refDate;
23670
+ const lowerText = match[0].toLowerCase();
23671
+ let component = context.createParsingComponents();
23672
+ switch (lowerText) {
23673
+ case "now":
23674
+ component = now(context.reference);
23675
+ break;
23676
+ case "today":
23677
+ component = today(context.reference);
23678
+ break;
23679
+ case "yesterday":
23680
+ component = yesterday(context.reference);
23681
+ break;
23682
+ case "tomorrow":
23683
+ case "tmr":
23684
+ case "tmrw":
23685
+ component = tomorrow(context.reference);
23686
+ break;
23687
+ case "tonight":
23688
+ component = tonight(context.reference);
23689
+ break;
23690
+ case "overmorrow":
23691
+ component = theDayAfter(context.reference, 2);
23692
+ break;
23693
+ default:
23694
+ if (lowerText.match(/last\s*night/)) {
23695
+ if (targetDate.getHours() > 6) {
23696
+ const previousDay = new Date(targetDate.getTime());
23697
+ previousDay.setDate(previousDay.getDate() - 1);
23698
+ targetDate = previousDay;
23699
+ }
23700
+ assignSimilarDate(component, targetDate);
23701
+ component.imply("hour", 0);
23702
+ }
23703
+ break;
23704
+ }
23705
+ component.addTag("parser/ENCasualDateParser");
23706
+ return component;
23707
+ }
23708
+ };
23709
+
23710
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENCasualTimeParser.js
23711
+ var PATTERN11 = /(?:this)?\s{0,3}(morning|afternoon|evening|night|midnight|midday|noon)(?=\W|$)/i;
23712
+ var ENCasualTimeParser = class extends AbstractParserWithWordBoundaryChecking {
23713
+ innerPattern() {
23714
+ return PATTERN11;
23715
+ }
23716
+ innerExtract(context, match) {
23717
+ let component = null;
23718
+ switch (match[1].toLowerCase()) {
23719
+ case "afternoon":
23720
+ component = afternoon(context.reference);
23721
+ break;
23722
+ case "evening":
23723
+ case "night":
23724
+ component = evening(context.reference);
23725
+ break;
23726
+ case "midnight":
23727
+ component = midnight(context.reference);
23728
+ break;
23729
+ case "morning":
23730
+ component = morning(context.reference);
23731
+ break;
23732
+ case "noon":
23733
+ case "midday":
23734
+ component = noon(context.reference);
23735
+ break;
23736
+ }
23737
+ if (component) {
23738
+ component.addTag("parser/ENCasualTimeParser");
23739
+ }
23740
+ return component;
23741
+ }
23742
+ };
23743
+
23744
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENWeekdayParser.js
23745
+ var PATTERN12 = new RegExp(`(?:(?:\\,|\\(|\\\uFF08)\\s*)?(?:on\\s*?)?(?:(this|last|past|next)\\s*)?(${matchAnyPattern(WEEKDAY_DICTIONARY)}|weekend|weekday)(?:\\s*(?:\\,|\\)|\\\uFF09))?(?:\\s*(?:of\\s*)?(this|last|past|next)\\s*week)?(?=\\W|$)`, "i");
23746
+ var PREFIX_GROUP2 = 1;
23747
+ var WEEKDAY_GROUP = 2;
23748
+ var POSTFIX_GROUP = 3;
23749
+ var ENWeekdayParser = class extends AbstractParserWithWordBoundaryChecking {
23750
+ innerPattern() {
23751
+ return PATTERN12;
23752
+ }
23753
+ innerExtract(context, match) {
23754
+ const prefix = match[PREFIX_GROUP2];
23755
+ const postfix = match[POSTFIX_GROUP];
23756
+ let modifierWord = prefix || postfix;
23757
+ modifierWord = modifierWord || "";
23758
+ modifierWord = modifierWord.toLowerCase();
23759
+ let modifier = null;
23760
+ if (modifierWord == "last" || modifierWord == "past") {
23761
+ modifier = "last";
23762
+ } else if (modifierWord == "next") {
23763
+ modifier = "next";
23764
+ } else if (modifierWord == "this") {
23765
+ modifier = "this";
23766
+ }
23767
+ const weekday_word = match[WEEKDAY_GROUP].toLowerCase();
23768
+ let weekday;
23769
+ if (WEEKDAY_DICTIONARY[weekday_word] !== void 0) {
23770
+ weekday = WEEKDAY_DICTIONARY[weekday_word];
23771
+ } else if (weekday_word == "weekend") {
23772
+ weekday = modifier == "last" ? Weekday.SUNDAY : Weekday.SATURDAY;
23773
+ } else if (weekday_word == "weekday") {
23774
+ const refWeekday = context.reference.getDateWithAdjustedTimezone().getDay();
23775
+ if (refWeekday == Weekday.SUNDAY || refWeekday == Weekday.SATURDAY) {
23776
+ weekday = modifier == "last" ? Weekday.FRIDAY : Weekday.MONDAY;
23777
+ } else {
23778
+ weekday = refWeekday - 1;
23779
+ weekday = modifier == "last" ? weekday - 1 : weekday + 1;
23780
+ weekday = weekday % 5 + 1;
23781
+ }
23782
+ } else {
23783
+ return null;
23784
+ }
23785
+ return createParsingComponentsAtWeekday(context.reference, weekday, modifier);
23786
+ }
23787
+ };
23788
+
23789
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENRelativeDateFormatParser.js
23790
+ var PATTERN13 = new RegExp(`(this|last|past|next|after\\s*this)\\s*(${matchAnyPattern(TIME_UNIT_DICTIONARY)})(?=\\s*)(?=\\W|$)`, "i");
23791
+ var MODIFIER_WORD_GROUP = 1;
23792
+ var RELATIVE_WORD_GROUP = 2;
23793
+ var ENRelativeDateFormatParser = class extends AbstractParserWithWordBoundaryChecking {
23794
+ innerPattern() {
23795
+ return PATTERN13;
23796
+ }
23797
+ innerExtract(context, match) {
23798
+ const modifier = match[MODIFIER_WORD_GROUP].toLowerCase();
23799
+ const unitWord = match[RELATIVE_WORD_GROUP].toLowerCase();
23800
+ const timeunit = TIME_UNIT_DICTIONARY[unitWord];
23801
+ if (modifier == "next" || modifier.startsWith("after")) {
23802
+ const timeUnits = {};
23803
+ timeUnits[timeunit] = 1;
23804
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
23805
+ }
23806
+ if (modifier == "last" || modifier == "past") {
23807
+ const timeUnits = {};
23808
+ timeUnits[timeunit] = -1;
23809
+ return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
23810
+ }
23811
+ const components = context.createParsingComponents();
23812
+ let date3 = new Date(context.reference.instant.getTime());
23813
+ if (unitWord.match(/week/i)) {
23814
+ date3.setDate(date3.getDate() - date3.getDay());
23815
+ components.imply("day", date3.getDate());
23816
+ components.imply("month", date3.getMonth() + 1);
23817
+ components.imply("year", date3.getFullYear());
23818
+ } else if (unitWord.match(/month/i)) {
23819
+ date3.setDate(1);
23820
+ components.imply("day", date3.getDate());
23821
+ components.assign("year", date3.getFullYear());
23822
+ components.assign("month", date3.getMonth() + 1);
23823
+ } else if (unitWord.match(/year/i)) {
23824
+ date3.setDate(1);
23825
+ date3.setMonth(0);
23826
+ components.imply("day", date3.getDate());
23827
+ components.imply("month", date3.getMonth() + 1);
23828
+ components.assign("year", date3.getFullYear());
23829
+ }
23830
+ return components;
23831
+ }
23832
+ };
23833
+
23834
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/common/parsers/SlashDateFormatParser.js
23835
+ var PATTERN14 = new RegExp("([^\\d]|^)([0-3]{0,1}[0-9]{1})[\\/\\.\\-]([0-3]{0,1}[0-9]{1})(?:[\\/\\.\\-]([0-9]{4}|[0-9]{2}))?(\\W|$)", "i");
23836
+ var OPENING_GROUP = 1;
23837
+ var ENDING_GROUP = 5;
23838
+ var FIRST_NUMBERS_GROUP = 2;
23839
+ var SECOND_NUMBERS_GROUP = 3;
23840
+ var YEAR_GROUP6 = 4;
23841
+ var SlashDateFormatParser = class {
23842
+ groupNumberMonth;
23843
+ groupNumberDay;
23844
+ constructor(littleEndian) {
23845
+ this.groupNumberMonth = littleEndian ? SECOND_NUMBERS_GROUP : FIRST_NUMBERS_GROUP;
23846
+ this.groupNumberDay = littleEndian ? FIRST_NUMBERS_GROUP : SECOND_NUMBERS_GROUP;
23847
+ }
23848
+ pattern() {
23849
+ return PATTERN14;
23850
+ }
23851
+ extract(context, match) {
23852
+ const index = match.index + match[OPENING_GROUP].length;
23853
+ const indexEnd = match.index + match[0].length - match[ENDING_GROUP].length;
23854
+ if (index > 0) {
23855
+ const textBefore = context.text.substring(0, index);
23856
+ if (textBefore.match("\\d/?$")) {
23857
+ return;
23858
+ }
23859
+ }
23860
+ if (indexEnd < context.text.length) {
23861
+ const textAfter = context.text.substring(indexEnd);
23862
+ if (textAfter.match("^/?\\d")) {
23863
+ return;
23864
+ }
23865
+ }
23866
+ const text2 = context.text.substring(index, indexEnd);
23867
+ if (text2.match(/^\d\.\d$/) || text2.match(/^\d\.\d{1,2}\.\d{1,2}\s*$/)) {
23868
+ return;
23869
+ }
23870
+ if (!match[YEAR_GROUP6] && text2.indexOf("/") < 0) {
23871
+ return;
23872
+ }
23873
+ const result = context.createParsingResult(index, text2);
23874
+ let month = parseInt(match[this.groupNumberMonth]);
23875
+ let day = parseInt(match[this.groupNumberDay]);
23876
+ if (month < 1 || month > 12) {
23877
+ if (month > 12) {
23878
+ if (day >= 1 && day <= 12 && month <= 31) {
23879
+ [day, month] = [month, day];
23880
+ } else {
23881
+ return null;
23882
+ }
23883
+ }
23884
+ }
23885
+ if (day < 1 || day > 31) {
23886
+ return null;
23887
+ }
23888
+ result.start.assign("day", day);
23889
+ result.start.assign("month", month);
23890
+ if (match[YEAR_GROUP6]) {
23891
+ const rawYearNumber = parseInt(match[YEAR_GROUP6]);
23892
+ const year = findMostLikelyADYear(rawYearNumber);
23893
+ result.start.assign("year", year);
23894
+ } else {
23895
+ const year = findYearClosestToRef(context.refDate, day, month);
23896
+ result.start.imply("year", year);
23897
+ }
23898
+ return result.addTag("parser/SlashDateFormatParser");
23899
+ }
23900
+ };
23901
+
23902
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js
23903
+ var PATTERN15 = new RegExp(`(this|last|past|next|after|\\+|-)\\s*(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
23904
+ var PATTERN_NO_ABBR = new RegExp(`(this|last|past|next|after|\\+|-)\\s*(${TIME_UNITS_NO_ABBR_PATTERN})(?=\\W|$)`, "i");
23905
+ var ENTimeUnitCasualRelativeFormatParser = class extends AbstractParserWithWordBoundaryChecking {
23906
+ allowAbbreviations;
23907
+ constructor(allowAbbreviations = true) {
23908
+ super();
23909
+ this.allowAbbreviations = allowAbbreviations;
23910
+ }
23911
+ innerPattern() {
23912
+ return this.allowAbbreviations ? PATTERN15 : PATTERN_NO_ABBR;
23913
+ }
23914
+ innerExtract(context, match) {
23915
+ const prefix = match[1].toLowerCase();
23916
+ let duration3 = parseDuration(match[2]);
23917
+ if (!duration3) {
23918
+ return null;
23919
+ }
23920
+ switch (prefix) {
23921
+ case "last":
23922
+ case "past":
23923
+ case "-":
23924
+ duration3 = reverseDuration(duration3);
23925
+ break;
23926
+ }
23927
+ return ParsingComponents.createRelativeFromReference(context.reference, duration3);
23928
+ }
23929
+ };
23930
+
23931
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js
23932
+ function IsPositiveFollowingReference(result) {
23933
+ return result.text.match(/^[+-]/i) != null;
23934
+ }
23935
+ function IsNegativeFollowingReference(result) {
23936
+ return result.text.match(/^-/i) != null;
21177
23937
  }
21178
- function listRecentlyCompleted(hoursAgo = 24) {
21179
- return selectRecentDoneStmt.all(`-${hoursAgo} hours`);
23938
+ var ENMergeRelativeAfterDateRefiner = class extends MergingRefiner {
23939
+ shouldMergeResults(textBetween, currentResult, nextResult) {
23940
+ if (!textBetween.match(/^\s*$/i)) {
23941
+ return false;
23942
+ }
23943
+ return IsPositiveFollowingReference(nextResult) || IsNegativeFollowingReference(nextResult);
23944
+ }
23945
+ mergeResults(textBetween, currentResult, nextResult, context) {
23946
+ let timeUnits = parseDuration(nextResult.text);
23947
+ if (IsNegativeFollowingReference(nextResult)) {
23948
+ timeUnits = reverseDuration(timeUnits);
23949
+ }
23950
+ const components = ParsingComponents.createRelativeFromReference(ReferenceWithTimezone.fromDate(currentResult.start.date()), timeUnits);
23951
+ return new ParsingResult(currentResult.reference, currentResult.index, `${currentResult.text}${textBetween}${nextResult.text}`, components);
23952
+ }
23953
+ };
23954
+
23955
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeRelativeFollowByDateRefiner.js
23956
+ function hasImpliedEarlierReferenceDate(result) {
23957
+ return result.text.match(/\s+(before|from)$/i) != null;
21180
23958
  }
21181
- function listArchived(hoursAgo = 24, limit = 100) {
21182
- return selectArchivedStmt.all(`-${hoursAgo} hours`, limit);
23959
+ function hasImpliedLaterReferenceDate(result) {
23960
+ return result.text.match(/\s+(after|since)$/i) != null;
21183
23961
  }
21184
- function completeTask(id) {
21185
- return inTransaction(() => {
21186
- const prior = completeTaskFindStmt.get(id);
21187
- if (!prior) return null;
21188
- const completed = prior.completed_at === null;
21189
- if (completed) {
21190
- completeTaskUpdateStmt.run(id);
21191
- recordEvent("complete", prior.uuid, null);
23962
+ var ENMergeRelativeFollowByDateRefiner = class extends MergingRefiner {
23963
+ patternBetween() {
23964
+ return /^\s*$/i;
23965
+ }
23966
+ shouldMergeResults(textBetween, currentResult, nextResult) {
23967
+ if (!textBetween.match(this.patternBetween())) {
23968
+ return false;
21192
23969
  }
21193
- return { task: getTaskStmt.get(id), completed };
21194
- });
23970
+ if (!hasImpliedEarlierReferenceDate(currentResult) && !hasImpliedLaterReferenceDate(currentResult)) {
23971
+ return false;
23972
+ }
23973
+ return !!nextResult.start.get("day") && !!nextResult.start.get("month") && !!nextResult.start.get("year");
23974
+ }
23975
+ mergeResults(textBetween, currentResult, nextResult) {
23976
+ let duration3 = parseDuration(currentResult.text);
23977
+ if (hasImpliedEarlierReferenceDate(currentResult)) {
23978
+ duration3 = reverseDuration(duration3);
23979
+ }
23980
+ const components = ParsingComponents.createRelativeFromReference(ReferenceWithTimezone.fromDate(nextResult.start.date()), duration3);
23981
+ return new ParsingResult(nextResult.reference, currentResult.index, `${currentResult.text}${textBetween}${nextResult.text}`, components);
23982
+ }
23983
+ };
23984
+
23985
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/refiners/ENExtractYearSuffixRefiner.js
23986
+ var YEAR_SUFFIX_PATTERN = new RegExp(`^\\s*(${YEAR_PATTERN})`, "i");
23987
+ var YEAR_GROUP7 = 1;
23988
+ var ENExtractYearSuffixRefiner = class {
23989
+ refine(context, results) {
23990
+ results.forEach(function(result) {
23991
+ if (!result.start.isDateWithUnknownYear()) {
23992
+ return;
23993
+ }
23994
+ const suffix = context.text.substring(result.index + result.text.length);
23995
+ const match = YEAR_SUFFIX_PATTERN.exec(suffix);
23996
+ if (!match) {
23997
+ return;
23998
+ }
23999
+ if (match[0].trim().length <= 3) {
24000
+ return;
24001
+ }
24002
+ context.debug(() => {
24003
+ console.log(`Extracting year: '${match[0]}' into : ${result}`);
24004
+ });
24005
+ const year = parseYear(match[YEAR_GROUP7]);
24006
+ if (result.end != null) {
24007
+ result.end.assign("year", year);
24008
+ }
24009
+ result.start.assign("year", year);
24010
+ result.text += match[0];
24011
+ });
24012
+ return results;
24013
+ }
24014
+ };
24015
+
24016
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/refiners/ENUnlikelyFormatFilter.js
24017
+ var ENUnlikelyFormatFilter = class extends Filter {
24018
+ constructor() {
24019
+ super();
24020
+ }
24021
+ isValid(context, result) {
24022
+ const text2 = result.text.trim();
24023
+ if (text2 === context.text.trim()) {
24024
+ return true;
24025
+ }
24026
+ if (text2.toLowerCase() === "may") {
24027
+ const textBefore = context.text.substring(0, result.index).trim();
24028
+ if (!textBefore.match(/\b(in)$/i)) {
24029
+ context.debug(() => {
24030
+ console.log(`Removing unlikely result: ${result}`);
24031
+ });
24032
+ return false;
24033
+ }
24034
+ }
24035
+ if (text2.toLowerCase().endsWith("the second")) {
24036
+ const textAfter = context.text.substring(result.index + result.text.length).trim();
24037
+ if (textAfter.length > 0) {
24038
+ context.debug(() => {
24039
+ console.log(`Removing unlikely result: ${result}`);
24040
+ });
24041
+ }
24042
+ return false;
24043
+ }
24044
+ return true;
24045
+ }
24046
+ };
24047
+
24048
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/configuration.js
24049
+ var ENDefaultConfiguration = class {
24050
+ createCasualConfiguration(littleEndian = false) {
24051
+ const option = this.createConfiguration(false, littleEndian);
24052
+ option.parsers.push(new ENCasualDateParser());
24053
+ option.parsers.push(new ENCasualTimeParser());
24054
+ option.parsers.push(new ENMonthNameParser());
24055
+ option.parsers.push(new ENRelativeDateFormatParser());
24056
+ option.parsers.push(new ENTimeUnitCasualRelativeFormatParser());
24057
+ option.refiners.push(new ENUnlikelyFormatFilter());
24058
+ return option;
24059
+ }
24060
+ createConfiguration(strictMode = true, littleEndian = false) {
24061
+ const options = includeCommonConfiguration({
24062
+ parsers: [
24063
+ new SlashDateFormatParser(littleEndian),
24064
+ new ENTimeUnitWithinFormatParser(strictMode),
24065
+ new ENMonthNameLittleEndianParser(),
24066
+ new ENMonthNameMiddleEndianParser(littleEndian),
24067
+ new ENWeekdayParser(),
24068
+ new ENSlashMonthFormatParser(),
24069
+ new ENTimeExpressionParser(strictMode),
24070
+ new ENTimeUnitAgoFormatParser(strictMode),
24071
+ new ENTimeUnitLaterFormatParser(strictMode),
24072
+ new ENYearMonthNameParser()
24073
+ ],
24074
+ refiners: [new ENMergeDateTimeRefiner()]
24075
+ }, strictMode);
24076
+ options.parsers.unshift(new ENYearMonthDayParser(strictMode));
24077
+ options.refiners.unshift(new ENMergeRelativeFollowByDateRefiner());
24078
+ options.refiners.unshift(new ENMergeRelativeAfterDateRefiner());
24079
+ options.refiners.unshift(new OverlapRemovalRefiner());
24080
+ options.refiners.push(new ENMergeDateTimeRefiner());
24081
+ options.refiners.push(new ENExtractYearSuffixRefiner());
24082
+ options.refiners.push(new ENMergeDateRangeRefiner());
24083
+ return options;
24084
+ }
24085
+ };
24086
+
24087
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/chrono.js
24088
+ var Chrono = class _Chrono {
24089
+ parsers;
24090
+ refiners;
24091
+ defaultConfig = new ENDefaultConfiguration();
24092
+ constructor(configuration2) {
24093
+ configuration2 = configuration2 || this.defaultConfig.createCasualConfiguration();
24094
+ this.parsers = [...configuration2.parsers];
24095
+ this.refiners = [...configuration2.refiners];
24096
+ }
24097
+ clone() {
24098
+ return new _Chrono({
24099
+ parsers: [...this.parsers],
24100
+ refiners: [...this.refiners]
24101
+ });
24102
+ }
24103
+ parseDate(text2, referenceDate, option) {
24104
+ const results = this.parse(text2, referenceDate, option);
24105
+ return results.length > 0 ? results[0].start.date() : null;
24106
+ }
24107
+ parse(text2, referenceDate, option) {
24108
+ const context = new ParsingContext(text2, referenceDate, option);
24109
+ let results = [];
24110
+ this.parsers.forEach((parser) => {
24111
+ const parsedResults = _Chrono.executeParser(context, parser);
24112
+ results = results.concat(parsedResults);
24113
+ });
24114
+ results.sort((a, b) => {
24115
+ return a.index - b.index;
24116
+ });
24117
+ this.refiners.forEach(function(refiner) {
24118
+ results = refiner.refine(context, results);
24119
+ });
24120
+ return results;
24121
+ }
24122
+ static executeParser(context, parser) {
24123
+ const results = [];
24124
+ const pattern = parser.pattern(context);
24125
+ const originalText = context.text;
24126
+ let remainingText = context.text;
24127
+ let match = pattern.exec(remainingText);
24128
+ while (match) {
24129
+ const index = match.index + originalText.length - remainingText.length;
24130
+ match.index = index;
24131
+ const result = parser.extract(context, match);
24132
+ if (!result) {
24133
+ remainingText = originalText.substring(match.index + 1);
24134
+ match = pattern.exec(remainingText);
24135
+ continue;
24136
+ }
24137
+ let parsedResult = null;
24138
+ if (result instanceof ParsingResult) {
24139
+ parsedResult = result;
24140
+ } else if (result instanceof ParsingComponents) {
24141
+ parsedResult = context.createParsingResult(match.index, match[0]);
24142
+ parsedResult.start = result;
24143
+ } else {
24144
+ parsedResult = context.createParsingResult(match.index, match[0], result);
24145
+ }
24146
+ const parsedIndex = parsedResult.index;
24147
+ const parsedText = parsedResult.text;
24148
+ context.debug(() => console.log(`${parser.constructor.name} extracted (at index=${parsedIndex}) '${parsedText}'`));
24149
+ results.push(parsedResult);
24150
+ remainingText = originalText.substring(parsedIndex + parsedText.length);
24151
+ match = pattern.exec(remainingText);
24152
+ }
24153
+ return results;
24154
+ }
24155
+ };
24156
+ var ParsingContext = class {
24157
+ text;
24158
+ option;
24159
+ reference;
24160
+ refDate;
24161
+ constructor(text2, refDate, option) {
24162
+ this.text = text2;
24163
+ this.option = option ?? {};
24164
+ this.reference = ReferenceWithTimezone.fromInput(refDate, this.option.timezones);
24165
+ this.refDate = this.reference.instant;
24166
+ }
24167
+ createParsingComponents(components) {
24168
+ if (components instanceof ParsingComponents) {
24169
+ return components;
24170
+ }
24171
+ return new ParsingComponents(this.reference, components);
24172
+ }
24173
+ createParsingResult(index, textOrEndIndex, startComponents, endComponents) {
24174
+ const text2 = typeof textOrEndIndex === "string" ? textOrEndIndex : this.text.substring(index, textOrEndIndex);
24175
+ const start = startComponents ? this.createParsingComponents(startComponents) : null;
24176
+ const end = endComponents ? this.createParsingComponents(endComponents) : null;
24177
+ return new ParsingResult(this.reference, index, text2, start, end);
24178
+ }
24179
+ debug(block) {
24180
+ if (this.option.debug) {
24181
+ if (this.option.debug instanceof Function) {
24182
+ this.option.debug(block);
24183
+ } else {
24184
+ const handler = this.option.debug;
24185
+ handler.debug(block);
24186
+ }
24187
+ }
24188
+ }
24189
+ };
24190
+
24191
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/locales/en/index.js
24192
+ var configuration = new ENDefaultConfiguration();
24193
+ var casual = new Chrono(configuration.createCasualConfiguration(false));
24194
+ var strict = new Chrono(configuration.createConfiguration(true, false));
24195
+ var GB = new Chrono(configuration.createCasualConfiguration(true));
24196
+
24197
+ // node_modules/.pnpm/chrono-node@2.10.1/node_modules/chrono-node/dist/esm/index.js
24198
+ var casual2 = casual;
24199
+ function parse3(text2, ref, option) {
24200
+ return casual2.parse(text2, ref, option);
21195
24201
  }
21196
24202
 
21197
24203
  // src/dates.ts
24204
+ var ISO_DATE = /^\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/i;
24205
+ var PART_OF_DAY = /\b(?:morning|afternoon|evening|night|tonight|noon|midday|midnight)\b/i;
24206
+ function stamp(d) {
24207
+ return d.toISOString().replace(/\.\d{3}Z$/, "Z");
24208
+ }
21198
24209
  function toStoredDue(input) {
21199
24210
  const s = input.trim();
21200
24211
  const d = /^\d{4}-\d{2}-\d{2}$/.test(s) ? /* @__PURE__ */ new Date(`${s}T09:00:00`) : new Date(s);
21201
24212
  if (Number.isNaN(d.getTime())) return null;
21202
- return d.toISOString().replace(/\.\d{3}Z$/, "Z");
24213
+ return stamp(d);
24214
+ }
24215
+ function resolveDue(phrase, ref = /* @__PURE__ */ new Date()) {
24216
+ const s = phrase.trim();
24217
+ const base = { phrase: s, ref: stamp(ref) };
24218
+ if (ISO_DATE.test(s)) return { ...base, at: toStoredDue(s) };
24219
+ const d = endOf(s, ref) ?? fromChrono(s.replace(HOUR_TONIGHT, "at $1 tonight"), ref) ?? dayOfMonth(s, ref);
24220
+ return { ...base, at: d && stamp(d) };
24221
+ }
24222
+ function onDay(day, hour, ref) {
24223
+ const d = new Date(day.getFullYear(), day.getMonth(), day.getDate(), hour);
24224
+ if (d < ref && d.toDateString() === ref.toDateString()) d.setHours(23, 59);
24225
+ return d;
24226
+ }
24227
+ function fromChrono(s, ref) {
24228
+ const [result] = parse3(s, ref, { forwardDate: true });
24229
+ if (!result) return null;
24230
+ if (result.start.isCertain("hour") || PART_OF_DAY.test(result.text)) return result.start.date();
24231
+ return onDay(result.start.date(), 9, ref);
24232
+ }
24233
+ var HOUR_TONIGHT = /(?<!\bat\s)\b(\d{1,2}(?::\d{2})?)\s+tonight\b/i;
24234
+ var END_OF = /\b(?:end\s+of\s+(?:the\s+)?(day|week|month)|eod|cob|close\s+of\s+business)\b/i;
24235
+ function endOf(s, ref) {
24236
+ const m = END_OF.exec(s);
24237
+ if (!m) return null;
24238
+ const unit = (m[1] ?? "day").toLowerCase();
24239
+ let day = ref;
24240
+ if (unit === "day") {
24241
+ const [other] = parse3(s.replace(m[0], " "), ref, { forwardDate: true });
24242
+ if (other) day = other.start.date();
24243
+ } else if (unit === "week") {
24244
+ day = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate() + (5 - ref.getDay() + 7) % 7);
24245
+ } else {
24246
+ day = new Date(ref.getFullYear(), ref.getMonth() + 1, 0);
24247
+ }
24248
+ return onDay(day, 17, ref);
24249
+ }
24250
+ var ORDINAL_DAY = /\b(\d{1,2})(?:st|nd|rd|th)\b/i;
24251
+ function dayOfMonth(s, ref) {
24252
+ const m = ORDINAL_DAY.exec(s);
24253
+ const n = m ? Number(m[1]) : 0;
24254
+ if (n < 1 || n > 31) return null;
24255
+ for (let ahead = 0; ahead < 12; ahead++) {
24256
+ const d = new Date(ref.getFullYear(), ref.getMonth() + ahead, n);
24257
+ if (d.getDate() !== n) continue;
24258
+ if (d < ref && d.toDateString() !== ref.toDateString()) continue;
24259
+ return onDay(d, 9, ref);
24260
+ }
24261
+ return null;
21203
24262
  }
21204
- function timeContext(now = /* @__PURE__ */ new Date()) {
21205
- const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
21206
- const weekday = (d) => d.toLocaleDateString("en-US", { weekday: "long" });
21207
- const ymd = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
21208
- const hm = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
21209
- const week = Array.from({ length: 7 }, (_, i) => {
21210
- const d = new Date(now.getFullYear(), now.getMonth(), now.getDate() + i + 1, 12);
21211
- return `${weekday(d)} ${ymd(d)}`;
24263
+ function resolveSince(phrase, ref = /* @__PURE__ */ new Date()) {
24264
+ const s = phrase.trim();
24265
+ if (ISO_DATE.test(s)) {
24266
+ const d2 = /^\d{4}-\d{2}-\d{2}$/.test(s) ? /* @__PURE__ */ new Date(`${s}T00:00:00`) : new Date(s);
24267
+ return Number.isNaN(d2.getTime()) ? null : stamp(d2);
24268
+ }
24269
+ const [result] = parse3(s, ref);
24270
+ if (!result) return null;
24271
+ const start = result.start;
24272
+ const d = start.date();
24273
+ if (!start.isCertain("hour")) d.setHours(0, 0, 0, 0);
24274
+ if (d > ref && start.isCertain("weekday") && !start.isCertain("day")) d.setDate(d.getDate() - 7);
24275
+ else if (d > ref && !start.isCertain("year")) d.setFullYear(d.getFullYear() - 1);
24276
+ return stamp(d);
24277
+ }
24278
+ function describeDue(due2) {
24279
+ if (!due2.at) return `couldn't read "${due2.phrase}" as a date, so no due date`;
24280
+ const local = new Date(due2.at).toLocaleString("en-US", {
24281
+ weekday: "short",
24282
+ month: "short",
24283
+ day: "numeric",
24284
+ hour: "2-digit",
24285
+ minute: "2-digit",
24286
+ hourCycle: "h23",
24287
+ timeZoneName: "short"
21212
24288
  });
21213
- return `Now (user's local time, ${tz}): ${weekday(now)} ${ymd(now)} ${hm}.
21214
- The next 7 days: ${week.join(", ")}.`;
24289
+ return `due ${local} (${due2.at})` + (due2.phrase === due2.at ? "" : ` from "${due2.phrase}"`);
24290
+ }
24291
+
24292
+ // src/provenance.ts
24293
+ var EXCERPT_MAX = 200;
24294
+ var REF_MAX = 500;
24295
+ var contextSchema = external_exports.object({
24296
+ excerpt: external_exports.string().optional().describe(
24297
+ `The user's words this task came from, quoted exactly as they said them, e.g. 'I really need to call the dentist before Friday'. The pane shows it when they hover over the task, so they can see why it's there. Kept to ${EXCERPT_MAX} characters.`
24298
+ ),
24299
+ ref: external_exports.string().optional().describe("Where it came from, if there's a pointer to it: a file path, URL, ticket, or email subject.")
24300
+ }).optional().describe("Where this task came from. Include it whenever you can: tasks nobody recognizes get deleted.");
24301
+ function cap(s, max) {
24302
+ const flat = (s ?? "").replace(/\s+/g, " ").trim();
24303
+ if (!flat) return null;
24304
+ const chars = Array.from(flat);
24305
+ return chars.length <= max ? flat : chars.slice(0, max - 1).join("").trimEnd() + "\u2026";
24306
+ }
24307
+ var CLIENT_NAMES = {
24308
+ "claude-ai": "Claude Desktop",
24309
+ "cursor-vscode": "Cursor"
24310
+ };
24311
+ function clientLabel(info) {
24312
+ if (!info) return null;
24313
+ return info.title || CLIENT_NAMES[info.name] || info.name;
24314
+ }
24315
+ function fromTool(client2, context) {
24316
+ return {
24317
+ client: client2,
24318
+ ref: cap(context?.ref, REF_MAX),
24319
+ excerpt: cap(context?.excerpt, EXCERPT_MAX)
24320
+ };
24321
+ }
24322
+
24323
+ // src/tools/duplicate.ts
24324
+ function alreadyListed(task) {
24325
+ const due2 = task.due_at ? `, ${describeDue({ at: task.due_at, phrase: task.due_phrase ?? task.due_at, ref: "" })}` : "";
24326
+ return `Already on the list as #${task.id}: ${task.text}${due2}. Not added again.`;
21215
24327
  }
21216
24328
 
21217
24329
  // src/tools/add_task.ts
21218
24330
  var addTaskSchema = {
21219
24331
  text: external_exports.string().min(1).describe("The task text, e.g. 'Call the dentist'"),
21220
24332
  due_at: external_exports.string().optional().describe(
21221
- "Optional due date/time, ISO 8601. With Z or an offset it's exact ('2026-04-24T15:00:00Z'); without one it's the user's local time ('2026-04-24T15:00'); a date alone means 09:00 local."
21222
- )
24333
+ "Optional: when it's due, in the user's own words ('tomorrow', 'Friday 3pm', 'in 2 hours', 'next week'). Don't work out the date yourself; StickyInc does, in the user's time zone. Add am/pm to a bare hour. ISO 8601 works too: with Z or an offset it's exact, without one it's local time. No time of day means 09:00 local."
24334
+ ),
24335
+ context: contextSchema
21223
24336
  };
21224
- async function handleAddTask(args) {
21225
- const dueAt = args.due_at ? toStoredDue(args.due_at) : null;
21226
- if (args.due_at && !dueAt) {
24337
+ async function handleAddTask(args, client2) {
24338
+ const due2 = args.due_at ? resolveDue(args.due_at) : null;
24339
+ if (due2 && !due2.at) {
21227
24340
  return {
21228
24341
  content: [
21229
24342
  {
21230
24343
  type: "text",
21231
- text: `due_at "${args.due_at}" isn't a date/time. Use ISO 8601, e.g. 2026-04-24T15:00:00Z.`
24344
+ text: `due_at "${args.due_at}" isn't a date StickyInc can read. Try words like "Friday 5pm" or "in 3 days", or ISO 8601 (2026-04-24T17:00).`
21232
24345
  }
21233
24346
  ],
21234
24347
  isError: true
21235
24348
  };
21236
24349
  }
21237
- const task = addTask(args.text, dueAt);
21238
- const due = task.due_at ? ` (due ${task.due_at})` : "";
24350
+ const { task, inserted } = addTaskUnique({ text: args.text, due: due2, from: fromTool(client2, args.context) });
24351
+ if (!inserted) return { content: [{ type: "text", text: alreadyListed(task) }] };
24352
+ const dueText = due2 ? `, ${describeDue(due2)}` : "";
21239
24353
  return {
21240
24354
  content: [
21241
24355
  {
21242
24356
  type: "text",
21243
- text: `Added task #${task.id}: ${task.text}${due}`
24357
+ text: `Added task #${task.id}: ${task.text}${dueText}`
21244
24358
  }
21245
24359
  ]
21246
24360
  };
@@ -21287,9 +24401,9 @@ var AnthropicProvider = class {
21287
24401
  throw new Error(`Anthropic API error: ${res.status} ${await res.text()}`);
21288
24402
  }
21289
24403
  const data = await res.json();
21290
- const text = data.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("");
24404
+ const text2 = data.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("");
21291
24405
  return {
21292
- content: text,
24406
+ content: text2,
21293
24407
  model: data.model,
21294
24408
  provider: this.name,
21295
24409
  usage: { input: data.usage.input_tokens, output: data.usage.output_tokens }
@@ -21708,69 +24822,74 @@ async function resolveLLMProvider() {
21708
24822
  cached2 = provider ? { provider, configMtime: mtime } : void 0;
21709
24823
  return provider;
21710
24824
  }
24825
+ async function providerFromConfig(cfg) {
24826
+ switch (cfg.provider) {
24827
+ case "anthropic": {
24828
+ const key = cfg.api_key ?? process.env.ANTHROPIC_API_KEY;
24829
+ if (!key) return null;
24830
+ return new AnthropicProvider({ api_key: key, model: cfg.model, base_url: cfg.base_url });
24831
+ }
24832
+ case "openrouter": {
24833
+ const key = cfg.api_key ?? process.env.OPENROUTER_API_KEY;
24834
+ if (!key) return null;
24835
+ return new OpenAICompatProvider({
24836
+ api_key: key,
24837
+ model: cfg.model ?? "anthropic/claude-haiku-4.5",
24838
+ base_url: cfg.base_url ?? "https://openrouter.ai/api/v1",
24839
+ provider_label: "openrouter",
24840
+ extra_headers: {
24841
+ "HTTP-Referer": "https://github.com/Astralchemist/stickyinc",
24842
+ "X-Title": "StickyInc",
24843
+ ...cfg.extra_headers ?? {}
24844
+ }
24845
+ });
24846
+ }
24847
+ case "openai": {
24848
+ const key = cfg.api_key ?? process.env.OPENAI_API_KEY;
24849
+ if (!key) return null;
24850
+ return new OpenAICompatProvider({
24851
+ api_key: key,
24852
+ model: cfg.model ?? "gpt-4o-mini",
24853
+ base_url: cfg.base_url ?? "https://api.openai.com/v1",
24854
+ provider_label: "openai"
24855
+ });
24856
+ }
24857
+ case "compat": {
24858
+ if (!cfg.api_key || !cfg.model || !cfg.base_url) return null;
24859
+ return new OpenAICompatProvider({
24860
+ api_key: cfg.api_key,
24861
+ model: cfg.model,
24862
+ base_url: cfg.base_url,
24863
+ provider_label: "compat",
24864
+ extra_headers: cfg.extra_headers
24865
+ });
24866
+ }
24867
+ case "claude-code": {
24868
+ const binary = findClaudeBinary();
24869
+ if (!binary) return null;
24870
+ return new ClaudeCodeProvider({ binary, model: cfg.model });
24871
+ }
24872
+ case "codex": {
24873
+ const binary = findCodexBinary();
24874
+ if (!binary) return null;
24875
+ return new CodexProvider({ binary, model: cfg.model });
24876
+ }
24877
+ case "gemini": {
24878
+ const binary = findGeminiBinary();
24879
+ if (!binary) return null;
24880
+ return new GeminiProvider({ binary, model: cfg.model });
24881
+ }
24882
+ case "local": {
24883
+ return probeLocalProvider(cfg.model);
24884
+ }
24885
+ }
24886
+ return void 0;
24887
+ }
21711
24888
  async function resolveInternal() {
21712
24889
  const cfg = readConfigFile();
21713
24890
  if (cfg) {
21714
- switch (cfg.provider) {
21715
- case "anthropic": {
21716
- const key = cfg.api_key ?? process.env.ANTHROPIC_API_KEY;
21717
- if (!key) return null;
21718
- return new AnthropicProvider({ api_key: key, model: cfg.model, base_url: cfg.base_url });
21719
- }
21720
- case "openrouter": {
21721
- const key = cfg.api_key ?? process.env.OPENROUTER_API_KEY;
21722
- if (!key) return null;
21723
- return new OpenAICompatProvider({
21724
- api_key: key,
21725
- model: cfg.model ?? "anthropic/claude-haiku-4.5",
21726
- base_url: cfg.base_url ?? "https://openrouter.ai/api/v1",
21727
- provider_label: "openrouter",
21728
- extra_headers: {
21729
- "HTTP-Referer": "https://github.com/Astralchemist/stickyinc",
21730
- "X-Title": "StickyInc",
21731
- ...cfg.extra_headers ?? {}
21732
- }
21733
- });
21734
- }
21735
- case "openai": {
21736
- const key = cfg.api_key ?? process.env.OPENAI_API_KEY;
21737
- if (!key) return null;
21738
- return new OpenAICompatProvider({
21739
- api_key: key,
21740
- model: cfg.model ?? "gpt-4o-mini",
21741
- base_url: cfg.base_url ?? "https://api.openai.com/v1",
21742
- provider_label: "openai"
21743
- });
21744
- }
21745
- case "compat": {
21746
- if (!cfg.api_key || !cfg.model || !cfg.base_url) return null;
21747
- return new OpenAICompatProvider({
21748
- api_key: cfg.api_key,
21749
- model: cfg.model,
21750
- base_url: cfg.base_url,
21751
- provider_label: "compat",
21752
- extra_headers: cfg.extra_headers
21753
- });
21754
- }
21755
- case "claude-code": {
21756
- const binary = findClaudeBinary();
21757
- if (!binary) return null;
21758
- return new ClaudeCodeProvider({ binary, model: cfg.model });
21759
- }
21760
- case "codex": {
21761
- const binary = findCodexBinary();
21762
- if (!binary) return null;
21763
- return new CodexProvider({ binary, model: cfg.model });
21764
- }
21765
- case "gemini": {
21766
- const binary = findGeminiBinary();
21767
- if (!binary) return null;
21768
- return new GeminiProvider({ binary, model: cfg.model });
21769
- }
21770
- case "local": {
21771
- return probeLocalProvider(cfg.model);
21772
- }
21773
- }
24891
+ const provider = await providerFromConfig(cfg);
24892
+ if (provider !== void 0) return provider;
21774
24893
  }
21775
24894
  if (process.env.OPENROUTER_API_KEY) {
21776
24895
  return new OpenAICompatProvider({
@@ -21819,22 +24938,21 @@ async function resolveInternal() {
21819
24938
  var addTaskNaturalSchema = {
21820
24939
  input: external_exports.string().min(1).describe(
21821
24940
  "Free-text phrase like 'call dentist Friday 3pm' or 'buy bread'. Will be parsed by the configured LLM."
21822
- )
24941
+ ),
24942
+ context: contextSchema
21823
24943
  };
21824
24944
  var SYSTEM_PROMPT = `You convert a user phrase into a JSON task description.
21825
24945
 
21826
24946
  Output ONLY a single JSON object, no prose, no code fences. Schema:
21827
24947
  {
21828
24948
  "text": "<the thing to do, concise, no date>",
21829
- "due_at": "<local date-time YYYY-MM-DDTHH:MM, or null>"
24949
+ "due": "<the words that say when, copied from the phrase, or null>"
21830
24950
  }
21831
24951
 
21832
24952
  Rules:
21833
24953
  - "text" is the action, cleaned of date/time phrasing.
21834
- - "due_at" is the user's local time, with no offset or Z, or null if no time is implied. Take weekdays and "tomorrow" from the dates listed below.
21835
- - A weekday means its next occurrence; if that is today and the time has already passed, the one a week later.
21836
- - If a date is given without a time, use 09:00.
21837
- - If only a time is given, use today (or tomorrow if that time has passed).`;
24954
+ - "due" copies the date/time words as written ("Friday 3pm", "tomorrow", "in 2 hours", "next week"), or null if the phrase doesn't say when.
24955
+ - Don't work out a date; copy the words. If an hour has no am/pm, add the one the user means.`;
21838
24956
  function stripFences(s) {
21839
24957
  return s.replace(/^\s*```(?:json)?\s*/i, "").replace(/\s*```\s*$/, "").trim();
21840
24958
  }
@@ -21858,9 +24976,7 @@ async function parseTask(input) {
21858
24976
  const res = await provider.chat({
21859
24977
  system: SYSTEM_PROMPT,
21860
24978
  messages: [
21861
- { role: "user", content: `${timeContext()}
21862
-
21863
- Phrase: ${input}` }
24979
+ { role: "user", content: `Phrase: ${input}` }
21864
24980
  ],
21865
24981
  response_format: "json",
21866
24982
  max_tokens: 200,
@@ -21872,19 +24988,24 @@ Phrase: ${input}` }
21872
24988
  }
21873
24989
  return {
21874
24990
  text: parsed.text,
21875
- due_at: typeof parsed.due_at === "string" ? toStoredDue(parsed.due_at) : null
24991
+ due: typeof parsed.due === "string" && parsed.due.trim() ? resolveDue(parsed.due) : null
21876
24992
  };
21877
24993
  }
21878
- async function handleAddTaskNatural(args) {
24994
+ async function handleAddTaskNatural(args, client2) {
21879
24995
  try {
21880
24996
  const parsed = await parseTask(args.input);
21881
- const task = addTask(parsed.text, parsed.due_at);
21882
- const due = task.due_at ? ` (due ${task.due_at})` : "";
24997
+ const { task, inserted } = addTaskUnique({
24998
+ text: parsed.text,
24999
+ due: parsed.due,
25000
+ from: fromTool(client2, args.context)
25001
+ });
25002
+ if (!inserted) return { content: [{ type: "text", text: alreadyListed(task) }] };
25003
+ const due2 = parsed.due ? `, ${describeDue(parsed.due)}` : "";
21883
25004
  return {
21884
25005
  content: [
21885
25006
  {
21886
25007
  type: "text",
21887
- text: `Parsed & added task #${task.id}: ${task.text}${due}`
25008
+ text: `Parsed & added task #${task.id}: ${task.text}${due2}`
21888
25009
  }
21889
25010
  ]
21890
25011
  };
@@ -21911,8 +25032,8 @@ async function handleListTasks(args) {
21911
25032
  }
21912
25033
  const lines = tasks.map((t) => {
21913
25034
  const mark = t.completed_at ? "[x]" : "[ ]";
21914
- const due = t.due_at ? ` \u2014 due ${t.due_at}` : "";
21915
- return `${mark} #${t.id} ${t.text}${due}`;
25035
+ const due2 = t.due_at ? ` \u2014 due ${t.due_at}` : "";
25036
+ return `${mark} #${t.id} ${t.text}${due2}`;
21916
25037
  });
21917
25038
  const doneToday = countDoneToday();
21918
25039
  if (doneToday > 0) {
@@ -21949,31 +25070,38 @@ async function handleCompleteTask(args) {
21949
25070
  var scheduleEventSchema = {
21950
25071
  title: external_exports.string().min(1).describe("Event title"),
21951
25072
  start: external_exports.string().describe(
21952
- "Start, ISO 8601. With Z or an offset it's exact ('2026-04-24T15:00:00Z'); without one it's the user's local time."
25073
+ "When it starts, in the user's own words ('Friday 3pm', 'tomorrow at 10am'); StickyInc works out the date in their time zone. Or ISO 8601: with Z or an offset it's exact, without one local."
21953
25074
  ),
21954
25075
  end: external_exports.string().optional().describe("Optional end, ISO 8601. Echoed back, not stored."),
21955
- notes: external_exports.string().optional().describe("Optional notes/description")
25076
+ notes: external_exports.string().optional().describe("Optional notes/description"),
25077
+ context: contextSchema
21956
25078
  };
21957
- async function handleScheduleEvent(args) {
21958
- const start = toStoredDue(args.start);
21959
- if (!start) {
25079
+ async function handleScheduleEvent(args, client2) {
25080
+ const start = resolveDue(args.start);
25081
+ if (!start.at) {
21960
25082
  return {
21961
25083
  content: [
21962
25084
  {
21963
25085
  type: "text",
21964
- text: `start "${args.start}" isn't a date/time. Use ISO 8601, e.g. 2026-04-24T15:00:00Z.`
25086
+ text: `start "${args.start}" isn't a date StickyInc can read. Try words like "Friday 3pm", or ISO 8601 (2026-04-24T15:00).`
21965
25087
  }
21966
25088
  ],
21967
25089
  isError: true
21968
25090
  };
21969
25091
  }
21970
- const text = args.notes ? `${args.title} \u2014 ${args.notes}` : args.title;
21971
- const task = addTask(text, start, "calendar");
25092
+ const text2 = args.notes ? `${args.title} \u2014 ${args.notes}` : args.title;
25093
+ const { task, inserted } = addTaskUnique({
25094
+ text: text2,
25095
+ due: start,
25096
+ source: "calendar",
25097
+ from: fromTool(client2, args.context)
25098
+ });
25099
+ if (!inserted) return { content: [{ type: "text", text: alreadyListed(task) }] };
21972
25100
  return {
21973
25101
  content: [
21974
25102
  {
21975
25103
  type: "text",
21976
- text: `Scheduled task #${task.id}: ${args.title} @ ${start}` + (args.end ? ` \u2192 ${args.end}` : "") + `
25104
+ text: `Scheduled task #${task.id}: ${args.title}, ${describeDue(start)}` + (args.end ? ` \u2192 ${args.end}` : "") + `
21977
25105
  (If you want this on your Google Calendar too, ask me in the same turn \u2014 I'll use my Google Calendar connector. StickyInc only stores it locally.)`
21978
25106
  }
21979
25107
  ]
@@ -22009,19 +25137,285 @@ async function handleListDone(args) {
22009
25137
  return { content: [{ type: "text", text: lines.join("\n") }] };
22010
25138
  }
22011
25139
 
25140
+ // src/format.ts
25141
+ function sqliteUtcMs(s) {
25142
+ return Date.parse(s.replace(" ", "T") + "Z");
25143
+ }
25144
+ function addedOn(sqliteUtc) {
25145
+ return new Date(sqliteUtcMs(sqliteUtc)).toLocaleDateString("en-US", {
25146
+ weekday: "short",
25147
+ month: "short",
25148
+ day: "numeric"
25149
+ });
25150
+ }
25151
+ function ago(sqliteUtc, now2 = Date.now()) {
25152
+ const days = Math.floor((now2 - sqliteUtcMs(sqliteUtc)) / 864e5);
25153
+ if (days < 1) return "today";
25154
+ if (days === 1) return "yesterday";
25155
+ if (days < 14) return `${days} days ago`;
25156
+ if (days < 60) return `${Math.round(days / 7)} weeks ago`;
25157
+ return `${Math.round(days / 30)} months ago`;
25158
+ }
25159
+ function describeTask(t, now2 = Date.now()) {
25160
+ const mark = t.completed_at ? "[x]" : "[ ]";
25161
+ const from = t.source_client ? ` from ${t.source_client}` : "";
25162
+ const due2 = t.due_at ? ` \u2014 ${describeDue({ at: t.due_at, phrase: t.due_phrase ?? t.due_at, ref: "" })}` : "";
25163
+ const page = t.source_ref?.startsWith("http") ? ` \u2014 ${t.source_ref}` : "";
25164
+ const line = `${mark} #${t.id} ${t.text} \u2014 added ${addedOn(t.created_at)} (${ago(t.created_at, now2)})${from}${due2}${page}`;
25165
+ return t.source_excerpt ? `${line}
25166
+ \u201C${t.source_excerpt}\u201D` : line;
25167
+ }
25168
+
25169
+ // src/tools/sticky_search.ts
25170
+ var MAX_RESULTS = 20;
25171
+ var stickySearchSchema = {
25172
+ query: external_exports.string().optional().describe(
25173
+ "Words to look for in the task or in what the user said when it was added, e.g. 'dentist'. Leave out to list by status and date alone."
25174
+ ),
25175
+ status: external_exports.enum(["open", "done", "all"]).optional().describe("open (not done yet), done, or all. Default: all."),
25176
+ since: external_exports.string().optional().describe(
25177
+ "Only tasks added since then: the user's words ('3 weeks ago', 'last month', 'September 1') or ISO 8601."
25178
+ )
25179
+ };
25180
+ async function handleStickySearch(args) {
25181
+ const since = args.since ? resolveSince(args.since) : void 0;
25182
+ if (args.since && !since) {
25183
+ return {
25184
+ content: [
25185
+ {
25186
+ type: "text",
25187
+ text: `since "${args.since}" isn't a date StickyInc can read. Try "3 weeks ago", "last month", or 2026-09-01.`
25188
+ }
25189
+ ],
25190
+ isError: true
25191
+ };
25192
+ }
25193
+ const rows = searchTasks({ query: args.query, status: args.status, since: since ?? void 0, limit: MAX_RESULTS + 1 });
25194
+ const what = [
25195
+ args.query ? `matching "${args.query}"` : null,
25196
+ args.status && args.status !== "all" ? `${args.status}` : null,
25197
+ args.since ? `added since ${args.since}` : null
25198
+ ].filter(Boolean).join(", ");
25199
+ if (rows.length === 0) {
25200
+ return { content: [{ type: "text", text: `No tasks${what ? ` ${what}` : ""}.` }] };
25201
+ }
25202
+ const shown = rows.slice(0, MAX_RESULTS);
25203
+ const more = rows.length > MAX_RESULTS ? `
25204
+
25205
+ (More than ${MAX_RESULTS} match; narrow the search to see the rest.)` : "";
25206
+ return {
25207
+ content: [
25208
+ {
25209
+ type: "text",
25210
+ text: `${shown.length} task${shown.length === 1 ? "" : "s"}${what ? ` ${what}` : ""}:
25211
+
25212
+ ${shown.map((t) => describeTask(t)).join("\n")}${more}`
25213
+ }
25214
+ ]
25215
+ };
25216
+ }
25217
+
25218
+ // src/prompts.ts
25219
+ var DAY = 864e5;
25220
+ function actionList(scope, max) {
25221
+ return `End with an **Action list**: at most ${max} concrete next steps ${scope}, most important first, numbered, each naming its task number, e.g. "1. Call the dentist (#12) before 10am". If I agree something is done or should be dropped, mark it with complete_task.`;
25222
+ }
25223
+ function section(title, tasks, now2) {
25224
+ if (tasks.length === 0) return "";
25225
+ return `## ${title} (${tasks.length})
25226
+ ${tasks.map((t) => describeTask(t, now2)).join("\n")}
25227
+ `;
25228
+ }
25229
+ var due = (t) => t.due_at ? Date.parse(t.due_at) : Infinity;
25230
+ var byDue = (a, b) => due(a) - due(b);
25231
+ var byAdded = (a, b) => sqliteUtcMs(a.created_at) - sqliteUtcMs(b.created_at);
25232
+ function endOfDay(now2) {
25233
+ return new Date(now2.getFullYear(), now2.getMonth(), now2.getDate() + 1).getTime();
25234
+ }
25235
+ function today2(now2) {
25236
+ return now2.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" });
25237
+ }
25238
+ function morningReview(open, now2 = /* @__PURE__ */ new Date()) {
25239
+ const t = now2.getTime();
25240
+ const eod = endOfDay(now2);
25241
+ const dated = open.filter((x) => x.due_at).sort(byDue);
25242
+ const overdue = dated.filter((x) => due(x) < t);
25243
+ const dueToday = dated.filter((x) => due(x) >= t && due(x) < eod);
25244
+ const thisWeek = dated.filter((x) => due(x) >= eod && due(x) < t + 7 * DAY);
25245
+ const undated = open.filter((x) => !x.due_at).sort(byAdded).slice(0, 10);
25246
+ const body = section("Overdue", overdue, t) + section("Due today", dueToday, t) + section("Due in the next 7 days", thisWeek, t) + section("No due date (oldest first)", undated, t);
25247
+ return [
25248
+ `Morning review for ${today2(now2)}. Here's what's on my StickyInc list:`,
25249
+ body || "Nothing is open.",
25250
+ "Go through it with me: what matters most today, what's slipping, and what I should reschedule or drop. Point out anything I've been carrying for a long time.",
25251
+ actionList("for today", 5)
25252
+ ].join("\n\n");
25253
+ }
25254
+ function overdueReview(open, now2 = /* @__PURE__ */ new Date()) {
25255
+ const t = now2.getTime();
25256
+ const overdue = open.filter((x) => x.due_at && due(x) < t).sort(byDue);
25257
+ if (overdue.length === 0) {
25258
+ const upcoming = open.filter((x) => x.due_at && due(x) < t + 7 * DAY).sort(byDue);
25259
+ return [
25260
+ `Nothing on my StickyInc list is overdue as of ${today2(now2)}.`,
25261
+ section("Due in the next 7 days", upcoming, t) || "Nothing is due in the next 7 days either.",
25262
+ "Tell me I'm clear, then suggest what to get ahead on.",
25263
+ actionList("to get ahead", 3)
25264
+ ].join("\n\n");
25265
+ }
25266
+ return [
25267
+ `These StickyInc tasks are overdue as of ${today2(now2)}, with when I added them and the words they came from:`,
25268
+ section("Overdue", overdue, t),
25269
+ "For each one, say whether I should do it now, reschedule it (to when), or drop it, and why, going by what I said when I added it.",
25270
+ actionList("to clear the backlog", 7)
25271
+ ].join("\n\n");
25272
+ }
25273
+ function weeklyCloseout(open, doneThisWeek, now2 = /* @__PURE__ */ new Date()) {
25274
+ const t = now2.getTime();
25275
+ const weekAgo = t - 7 * DAY;
25276
+ const addedThisWeek = open.filter((x) => sqliteUtcMs(x.created_at) >= weekAgo).sort(byAdded);
25277
+ const dated = open.filter((x) => x.due_at).sort(byDue);
25278
+ const overdue = dated.filter((x) => due(x) < t);
25279
+ const nextWeek = dated.filter((x) => due(x) >= t && due(x) < t + 7 * DAY);
25280
+ const body = section("Done in the last 7 days", doneThisWeek, t) + section("Added this week and still open", addedThisWeek, t) + section("Overdue", overdue, t) + section("Due in the next 7 days", nextWeek, t);
25281
+ return [
25282
+ `Weekly close-out, ${today2(now2)}. Here's my week in StickyInc:`,
25283
+ body || "Nothing was done or added this week, and nothing is due.",
25284
+ "Close out the week with me: what got done, what slipped and why it might have, and what to carry into next week versus drop.",
25285
+ actionList("for next week", 7)
25286
+ ].join("\n\n");
25287
+ }
25288
+
25289
+ // src/routines.ts
25290
+ var BUILT_IN_PROMPTS = ["morning_review", "overdue", "weekly_closeout"];
25291
+ var PROMPT_MAX = 4e3;
25292
+ var SCHEDULE_MAX = 100;
25293
+ function routineName(name) {
25294
+ const slug = name.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 40).replace(/_+$/, "");
25295
+ return /^[a-z0-9]/.test(slug) ? slug : null;
25296
+ }
25297
+ function checkRoutine(input) {
25298
+ if (!input || typeof input !== "object") return { error: "a routine is an object with a name and a prompt" };
25299
+ const { name, prompt, schedule } = input;
25300
+ if (typeof name !== "string" || !routineName(name)) return { error: "it needs a name with letters or digits in it" };
25301
+ const slug = routineName(name);
25302
+ if (BUILT_IN_PROMPTS.includes(slug)) return { error: `"${slug}" is a built-in prompt; pick another name` };
25303
+ if (typeof prompt !== "string" || !prompt.trim()) return { error: `"${slug}" needs a prompt` };
25304
+ if (prompt.length > PROMPT_MAX) return { error: `"${slug}": the prompt is over ${PROMPT_MAX} characters` };
25305
+ if (schedule != null && (typeof schedule !== "string" || schedule.length > SCHEDULE_MAX)) {
25306
+ return { error: `"${slug}": the schedule should be a short phrase like "weekdays at 8:30"` };
25307
+ }
25308
+ return { routine: { name: slug, prompt: prompt.trim(), schedule: schedule ? String(schedule).trim() : null } };
25309
+ }
25310
+ function parseRoutines(json) {
25311
+ let data;
25312
+ try {
25313
+ data = JSON.parse(json);
25314
+ } catch (e) {
25315
+ return { error: `that isn't JSON (${e instanceof Error ? e.message : e})` };
25316
+ }
25317
+ const items = Array.isArray(data) ? data : [data];
25318
+ if (items.length === 0) return { error: "there are no routines in it" };
25319
+ const routines = [];
25320
+ for (const [i, item] of items.entries()) {
25321
+ const checked = checkRoutine(item);
25322
+ if ("error" in checked) return { error: items.length > 1 ? `routine ${i + 1}: ${checked.error}` : checked.error };
25323
+ routines.push(checked.routine);
25324
+ }
25325
+ const names = routines.map((r) => r.name);
25326
+ const dup = names.find((n, i) => names.indexOf(n) !== i);
25327
+ if (dup) return { error: `"${dup}" appears twice` };
25328
+ return { routines };
25329
+ }
25330
+ function exportRoutines(routines) {
25331
+ return JSON.stringify(
25332
+ routines.map(({ name, prompt, schedule }) => ({ name, prompt, schedule: schedule ?? null })),
25333
+ null,
25334
+ 2
25335
+ );
25336
+ }
25337
+ function routinePromptText(r) {
25338
+ return `${r.prompt}
25339
+
25340
+ (This is my StickyInc routine "${r.name}". Look up what it needs with sticky_search.)`;
25341
+ }
25342
+
25343
+ // src/tools/routines.ts
25344
+ var text = (t, isError = false) => ({
25345
+ content: [{ type: "text", text: t }],
25346
+ ...isError && { isError: true }
25347
+ });
25348
+ var howToRun = (name) => `Run it from the prompt menu, or in Claude Code as /mcp__stickyinc__${name}.`;
25349
+ var routineListSchema = {
25350
+ format: external_exports.enum(["text", "json"]).optional().describe("text (default) to read them, or json to export them for sharing or backup.")
25351
+ };
25352
+ async function handleRoutineList(args) {
25353
+ const routines = listRoutines();
25354
+ if (args.format === "json") return text(exportRoutines(routines));
25355
+ if (routines.length === 0) {
25356
+ return text("No routines yet. Save one with sticky_routine_save, or import some with sticky_routine_import.");
25357
+ }
25358
+ const lines = routines.map(
25359
+ (r) => `\u2022 ${r.name}${r.schedule ? ` (${r.schedule})` : ""}
25360
+ ${r.prompt.replace(/\s+/g, " ").slice(0, 160)}`
25361
+ );
25362
+ return text(`${routines.length} routine${routines.length === 1 ? "" : "s"}:
25363
+
25364
+ ${lines.join("\n")}
25365
+
25366
+ ${howToRun("<name>")}`);
25367
+ }
25368
+ var routineSaveSchema = {
25369
+ name: external_exports.string().min(1).describe("Short name, e.g. 'waiting on others'; stored as waiting_on_others."),
25370
+ prompt: external_exports.string().min(1).max(PROMPT_MAX).describe("What to ask when it runs, e.g. 'What am I waiting on from other people? Who should I chase?'"),
25371
+ schedule: external_exports.string().optional().describe("When it's meant to run, in words ('weekdays at 8:30', 'Fridays at 4pm'). A hint for whatever runs it.")
25372
+ };
25373
+ async function handleRoutineSave(args, onChange) {
25374
+ const checked = checkRoutine(args);
25375
+ if ("error" in checked) return text(`Can't save that routine: ${checked.error}.`, true);
25376
+ const isNew = saveRoutine(checked.routine);
25377
+ onChange();
25378
+ return text(`${isNew ? "Saved" : "Updated"} routine "${checked.routine.name}". ${howToRun(checked.routine.name)}`);
25379
+ }
25380
+ var routineDeleteSchema = {
25381
+ name: external_exports.string().min(1).describe("The routine's name.")
25382
+ };
25383
+ async function handleRoutineDelete(args, onChange) {
25384
+ const name = routineName(args.name) ?? args.name;
25385
+ if (!deleteRoutine(name)) return text(`There's no routine called "${name}".`, true);
25386
+ onChange();
25387
+ return text(`Deleted routine "${name}".`);
25388
+ }
25389
+ var routineImportSchema = {
25390
+ json: external_exports.string().min(1).describe(
25391
+ 'Routines as JSON: one {"name", "prompt", "schedule"} object or an array of them, as sticky_routine_list exports. Routines with the same name are replaced.'
25392
+ )
25393
+ };
25394
+ async function handleRoutineImport(args, onChange) {
25395
+ const parsed = parseRoutines(args.json);
25396
+ if ("error" in parsed) return text(`Nothing imported: ${parsed.error}.`, true);
25397
+ const added = parsed.routines.filter((r) => saveRoutine(r)).length;
25398
+ onChange();
25399
+ const replaced = parsed.routines.length - added;
25400
+ return text(
25401
+ `Imported ${parsed.routines.map((r) => r.name).join(", ")} (${added} new${replaced ? `, ${replaced} replaced` : ""}). ${howToRun("<name>")}`
25402
+ );
25403
+ }
25404
+
22012
25405
  // src/index.ts
22013
25406
  var server = new McpServer({
22014
25407
  name: "stickyinc",
22015
- version: "0.5.2"
25408
+ version: "0.6.1"
22016
25409
  });
25410
+ var client = () => clientLabel(server.server.getClientVersion());
22017
25411
  server.registerTool(
22018
25412
  "add_task",
22019
25413
  {
22020
25414
  title: "Add Task",
22021
- description: "Add a todo to StickyInc. The user sees it appear in their floating pane.",
25415
+ description: "Add a todo to StickyInc. The user sees it appear in their floating pane, and hovering over it shows context.excerpt: quote their words so they can tell where it came from.",
22022
25416
  inputSchema: addTaskSchema
22023
25417
  },
22024
- handleAddTask
25418
+ (args) => handleAddTask(args, client())
22025
25419
  );
22026
25420
  server.registerTool(
22027
25421
  "add_task_natural",
@@ -22030,7 +25424,7 @@ server.registerTool(
22030
25424
  description: "Parse a free-text phrase like 'call dentist Friday 3pm' into a task with optional due date, using the configured LLM (Anthropic/OpenRouter/OpenAI).",
22031
25425
  inputSchema: addTaskNaturalSchema
22032
25426
  },
22033
- handleAddTaskNatural
25427
+ (args) => handleAddTaskNatural(args, client())
22034
25428
  );
22035
25429
  server.registerTool(
22036
25430
  "list_tasks",
@@ -22066,7 +25460,116 @@ server.registerTool(
22066
25460
  description: "Save an event as a StickyInc task due at its start time. StickyInc doesn't sync calendars; use a calendar connector for that.",
22067
25461
  inputSchema: scheduleEventSchema
22068
25462
  },
22069
- handleScheduleEvent
25463
+ (args) => handleScheduleEvent(args, client())
25464
+ );
25465
+ server.registerTool(
25466
+ "sticky_search",
25467
+ {
25468
+ title: "Search Tasks",
25469
+ description: `Search everything the user has put in StickyInc, open and done, by words in the task or in what they said when it was added, optionally only since a date. Use it to remind them what they committed to and when, e.g. "you said you'd call the dentist three weeks ago". Returns up to 20 tasks, best match first.`,
25470
+ inputSchema: stickySearchSchema
25471
+ },
25472
+ handleStickySearch
25473
+ );
25474
+ var openTasks = () => searchTasks({ status: "open", limit: 500 });
25475
+ var asPrompt = (text2) => ({
25476
+ messages: [{ role: "user", content: { type: "text", text: text2 } }]
25477
+ });
25478
+ server.registerPrompt(
25479
+ "morning_review",
25480
+ {
25481
+ title: "Morning review",
25482
+ description: "Go through today's StickyInc list (overdue, due today, this week) and end with an action list for today."
25483
+ },
25484
+ () => asPrompt(morningReview(openTasks()))
25485
+ );
25486
+ server.registerPrompt(
25487
+ "overdue",
25488
+ {
25489
+ title: "Overdue",
25490
+ description: "Decide what to do about each overdue StickyInc task (do now, reschedule, or drop), ending with an action list."
25491
+ },
25492
+ () => asPrompt(overdueReview(openTasks()))
25493
+ );
25494
+ server.registerPrompt(
25495
+ "weekly_closeout",
25496
+ {
25497
+ title: "Weekly close-out",
25498
+ description: "Review the week in StickyInc (done, slipped, due next) and end with an action list for next week."
25499
+ },
25500
+ () => {
25501
+ const weekAgo = new Date(Date.now() - 7 * 864e5).toISOString();
25502
+ const done = searchTasks({ status: "done", completedSince: weekAgo, limit: 200 });
25503
+ return asPrompt(weeklyCloseout(openTasks(), done));
25504
+ }
25505
+ );
25506
+ var routinePrompts = /* @__PURE__ */ new Map();
25507
+ var describeRoutine = (prompt, schedule) => `Your routine${schedule ? ` (${schedule})` : ""}: ${prompt.replace(/\s+/g, " ").slice(0, 120)}`;
25508
+ function syncRoutinePrompts() {
25509
+ const routines = listRoutines();
25510
+ const names = new Set(routines.map((r) => r.name));
25511
+ for (const [name, registered] of routinePrompts) {
25512
+ if (!names.has(name)) {
25513
+ registered.remove();
25514
+ routinePrompts.delete(name);
25515
+ }
25516
+ }
25517
+ for (const r of routines) {
25518
+ const description = describeRoutine(r.prompt, r.schedule);
25519
+ const registered = routinePrompts.get(r.name);
25520
+ if (!registered) {
25521
+ routinePrompts.set(
25522
+ r.name,
25523
+ server.registerPrompt(r.name, { title: r.name.replace(/_/g, " "), description }, () => {
25524
+ const current = listRoutines().find((x) => x.name === r.name) ?? r;
25525
+ return asPrompt(routinePromptText(current));
25526
+ })
25527
+ );
25528
+ } else if (registered.description !== description) {
25529
+ registered.update({ description });
25530
+ }
25531
+ }
25532
+ }
25533
+ server.registerTool(
25534
+ "sticky_routine_list",
25535
+ {
25536
+ title: "List Routines",
25537
+ description: "List the user's StickyInc routines (saved prompts they run on a schedule or by hand), or export them as JSON.",
25538
+ inputSchema: routineListSchema
25539
+ },
25540
+ handleRoutineList
25541
+ );
25542
+ server.registerTool(
25543
+ "sticky_routine_save",
25544
+ {
25545
+ title: "Save Routine",
25546
+ description: "Save a routine: a named prompt the user wants to run regularly, like a Friday check on what they're waiting on from others. Replaces one with the same name. It shows up as a prompt they can run.",
25547
+ inputSchema: routineSaveSchema
25548
+ },
25549
+ (args) => handleRoutineSave(args, syncRoutinePrompts)
25550
+ );
25551
+ server.registerTool(
25552
+ "sticky_routine_delete",
25553
+ {
25554
+ title: "Delete Routine",
25555
+ description: "Delete one of the user's StickyInc routines by name.",
25556
+ inputSchema: routineDeleteSchema
25557
+ },
25558
+ (args) => handleRoutineDelete(args, syncRoutinePrompts)
25559
+ );
25560
+ server.registerTool(
25561
+ "sticky_routine_import",
25562
+ {
25563
+ title: "Import Routines",
25564
+ description: "Import routines from JSON (one routine or an array, as sticky_routine_list exports), e.g. ones someone shared.",
25565
+ inputSchema: routineImportSchema
25566
+ },
25567
+ (args) => handleRoutineImport(args, syncRoutinePrompts)
22070
25568
  );
25569
+ syncRoutinePrompts();
25570
+ setInterval(syncRoutinePrompts, 3e4).unref();
22071
25571
  var transport = new StdioServerTransport();
22072
25572
  await server.connect(transport);
25573
+ setTimeout(() => {
25574
+ for (const phrase of ["tomorrow at 3pm", "Friday", "in 2 hours", "the 30th"]) describeDue(resolveDue(phrase));
25575
+ }, 200).unref();