main
   1// index.ts
   2import { DynamicBorder } from "@earendil-works/pi-coding-agent";
   3import { execSync } from "node:child_process";
   4import { homedir } from "node:os";
   5import { join } from "node:path";
   6
   7// node_modules/chrono-node/dist/esm/types.js
   8var Meridiem;
   9(function(Meridiem2) {
  10  Meridiem2[Meridiem2["AM"] = 0] = "AM";
  11  Meridiem2[Meridiem2["PM"] = 1] = "PM";
  12})(Meridiem || (Meridiem = {}));
  13var Weekday;
  14(function(Weekday2) {
  15  Weekday2[Weekday2["SUNDAY"] = 0] = "SUNDAY";
  16  Weekday2[Weekday2["MONDAY"] = 1] = "MONDAY";
  17  Weekday2[Weekday2["TUESDAY"] = 2] = "TUESDAY";
  18  Weekday2[Weekday2["WEDNESDAY"] = 3] = "WEDNESDAY";
  19  Weekday2[Weekday2["THURSDAY"] = 4] = "THURSDAY";
  20  Weekday2[Weekday2["FRIDAY"] = 5] = "FRIDAY";
  21  Weekday2[Weekday2["SATURDAY"] = 6] = "SATURDAY";
  22})(Weekday || (Weekday = {}));
  23var Month;
  24(function(Month2) {
  25  Month2[Month2["JANUARY"] = 1] = "JANUARY";
  26  Month2[Month2["FEBRUARY"] = 2] = "FEBRUARY";
  27  Month2[Month2["MARCH"] = 3] = "MARCH";
  28  Month2[Month2["APRIL"] = 4] = "APRIL";
  29  Month2[Month2["MAY"] = 5] = "MAY";
  30  Month2[Month2["JUNE"] = 6] = "JUNE";
  31  Month2[Month2["JULY"] = 7] = "JULY";
  32  Month2[Month2["AUGUST"] = 8] = "AUGUST";
  33  Month2[Month2["SEPTEMBER"] = 9] = "SEPTEMBER";
  34  Month2[Month2["OCTOBER"] = 10] = "OCTOBER";
  35  Month2[Month2["NOVEMBER"] = 11] = "NOVEMBER";
  36  Month2[Month2["DECEMBER"] = 12] = "DECEMBER";
  37})(Month || (Month = {}));
  38
  39// node_modules/chrono-node/dist/esm/utils/dates.js
  40function assignSimilarDate(component, target) {
  41  component.assign("day", target.getDate());
  42  component.assign("month", target.getMonth() + 1);
  43  component.assign("year", target.getFullYear());
  44}
  45function assignSimilarTime(component, target) {
  46  component.assign("hour", target.getHours());
  47  component.assign("minute", target.getMinutes());
  48  component.assign("second", target.getSeconds());
  49  component.assign("millisecond", target.getMilliseconds());
  50  component.assign("meridiem", target.getHours() < 12 ? Meridiem.AM : Meridiem.PM);
  51}
  52function implySimilarDate(component, target) {
  53  component.imply("day", target.getDate());
  54  component.imply("month", target.getMonth() + 1);
  55  component.imply("year", target.getFullYear());
  56}
  57function implySimilarTime(component, target) {
  58  component.imply("hour", target.getHours());
  59  component.imply("minute", target.getMinutes());
  60  component.imply("second", target.getSeconds());
  61  component.imply("millisecond", target.getMilliseconds());
  62  component.imply("meridiem", target.getHours() < 12 ? Meridiem.AM : Meridiem.PM);
  63}
  64
  65// node_modules/chrono-node/dist/esm/timezone.js
  66var TIMEZONE_ABBR_MAP = {
  67  ACDT: 630,
  68  ACST: 570,
  69  ADT: -180,
  70  AEDT: 660,
  71  AEST: 600,
  72  AFT: 270,
  73  AKDT: -480,
  74  AKST: -540,
  75  ALMT: 360,
  76  AMST: -180,
  77  AMT: -240,
  78  ANAST: 720,
  79  ANAT: 720,
  80  AQTT: 300,
  81  ART: -180,
  82  AST: -240,
  83  AWDT: 540,
  84  AWST: 480,
  85  AZOST: 0,
  86  AZOT: -60,
  87  AZST: 300,
  88  AZT: 240,
  89  BNT: 480,
  90  BOT: -240,
  91  BRST: -120,
  92  BRT: -180,
  93  BST: 60,
  94  BTT: 360,
  95  CAST: 480,
  96  CAT: 120,
  97  CCT: 390,
  98  CDT: -300,
  99  CEST: 120,
 100  CET: {
 101    timezoneOffsetDuringDst: 2 * 60,
 102    timezoneOffsetNonDst: 60,
 103    dstStart: (year) => getLastWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2),
 104    dstEnd: (year) => getLastWeekdayOfMonth(year, Month.OCTOBER, Weekday.SUNDAY, 3)
 105  },
 106  CHADT: 825,
 107  CHAST: 765,
 108  CKT: -600,
 109  CLST: -180,
 110  CLT: -240,
 111  COT: -300,
 112  CST: -360,
 113  CT: {
 114    timezoneOffsetDuringDst: -5 * 60,
 115    timezoneOffsetNonDst: -6 * 60,
 116    dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
 117    dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
 118  },
 119  CVT: -60,
 120  CXT: 420,
 121  ChST: 600,
 122  DAVT: 420,
 123  EASST: -300,
 124  EAST: -360,
 125  EAT: 180,
 126  ECT: -300,
 127  EDT: -240,
 128  EEST: 180,
 129  EET: 120,
 130  EGST: 0,
 131  EGT: -60,
 132  EST: -300,
 133  ET: {
 134    timezoneOffsetDuringDst: -4 * 60,
 135    timezoneOffsetNonDst: -5 * 60,
 136    dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
 137    dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
 138  },
 139  FJST: 780,
 140  FJT: 720,
 141  FKST: -180,
 142  FKT: -240,
 143  FNT: -120,
 144  GALT: -360,
 145  GAMT: -540,
 146  GET: 240,
 147  GFT: -180,
 148  GILT: 720,
 149  GMT: 0,
 150  GST: 240,
 151  GYT: -240,
 152  HAA: -180,
 153  HAC: -300,
 154  HADT: -540,
 155  HAE: -240,
 156  HAP: -420,
 157  HAR: -360,
 158  HAST: -600,
 159  HAT: -90,
 160  HAY: -480,
 161  HKT: 480,
 162  HLV: -210,
 163  HNA: -240,
 164  HNC: -360,
 165  HNE: -300,
 166  HNP: -480,
 167  HNR: -420,
 168  HNT: -150,
 169  HNY: -540,
 170  HOVT: 420,
 171  ICT: 420,
 172  IDT: 180,
 173  IOT: 360,
 174  IRDT: 270,
 175  IRKST: 540,
 176  IRKT: 540,
 177  IRST: 210,
 178  IST: 330,
 179  JST: 540,
 180  KGT: 360,
 181  KRAST: 480,
 182  KRAT: 480,
 183  KST: 540,
 184  KUYT: 240,
 185  LHDT: 660,
 186  LHST: 630,
 187  LINT: 840,
 188  MAGST: 720,
 189  MAGT: 720,
 190  MART: -510,
 191  MAWT: 300,
 192  MDT: -360,
 193  MESZ: 120,
 194  MEZ: 60,
 195  MHT: 720,
 196  MMT: 390,
 197  MSD: 240,
 198  MSK: 180,
 199  MST: -420,
 200  MT: {
 201    timezoneOffsetDuringDst: -6 * 60,
 202    timezoneOffsetNonDst: -7 * 60,
 203    dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
 204    dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
 205  },
 206  MUT: 240,
 207  MVT: 300,
 208  MYT: 480,
 209  NCT: 660,
 210  NDT: -90,
 211  NFT: 690,
 212  NOVST: 420,
 213  NOVT: 360,
 214  NPT: 345,
 215  NST: -150,
 216  NUT: -660,
 217  NZDT: 780,
 218  NZST: 720,
 219  OMSST: 420,
 220  OMST: 420,
 221  PDT: -420,
 222  PET: -300,
 223  PETST: 720,
 224  PETT: 720,
 225  PGT: 600,
 226  PHOT: 780,
 227  PHT: 480,
 228  PKT: 300,
 229  PMDT: -120,
 230  PMST: -180,
 231  PONT: 660,
 232  PST: -480,
 233  PT: {
 234    timezoneOffsetDuringDst: -7 * 60,
 235    timezoneOffsetNonDst: -8 * 60,
 236    dstStart: (year) => getNthWeekdayOfMonth(year, Month.MARCH, Weekday.SUNDAY, 2, 2),
 237    dstEnd: (year) => getNthWeekdayOfMonth(year, Month.NOVEMBER, Weekday.SUNDAY, 1, 2)
 238  },
 239  PWT: 540,
 240  PYST: -180,
 241  PYT: -240,
 242  RET: 240,
 243  SAMT: 240,
 244  SAST: 120,
 245  SBT: 660,
 246  SCT: 240,
 247  SGT: 480,
 248  SRT: -180,
 249  SST: -660,
 250  TAHT: -600,
 251  TFT: 300,
 252  TJT: 300,
 253  TKT: 780,
 254  TLT: 540,
 255  TMT: 300,
 256  TVT: 720,
 257  ULAT: 480,
 258  UTC: 0,
 259  UYST: -120,
 260  UYT: -180,
 261  UZT: 300,
 262  VET: -210,
 263  VLAST: 660,
 264  VLAT: 660,
 265  VUT: 660,
 266  WAST: 120,
 267  WAT: 60,
 268  WEST: 60,
 269  WESZ: 60,
 270  WET: 0,
 271  WEZ: 0,
 272  WFT: 720,
 273  WGST: -120,
 274  WGT: -180,
 275  WIB: 420,
 276  WIT: 540,
 277  WITA: 480,
 278  WST: 780,
 279  WT: 0,
 280  YAKST: 600,
 281  YAKT: 600,
 282  YAPT: 600,
 283  YEKST: 360,
 284  YEKT: 360
 285};
 286function getNthWeekdayOfMonth(year, month, weekday, n, hour = 0) {
 287  let dayOfMonth = 0;
 288  let i = 0;
 289  while (i < n) {
 290    dayOfMonth++;
 291    const date = new Date(year, month - 1, dayOfMonth);
 292    if (date.getDay() === weekday)
 293      i++;
 294  }
 295  return new Date(year, month - 1, dayOfMonth, hour);
 296}
 297function getLastWeekdayOfMonth(year, month, weekday, hour = 0) {
 298  const oneIndexedWeekday = weekday === 0 ? 7 : weekday;
 299  const date = new Date(year, month - 1 + 1, 1, 12);
 300  const firstWeekdayNextMonth = date.getDay() === 0 ? 7 : date.getDay();
 301  let dayDiff;
 302  if (firstWeekdayNextMonth === oneIndexedWeekday)
 303    dayDiff = 7;
 304  else if (firstWeekdayNextMonth < oneIndexedWeekday)
 305    dayDiff = 7 + firstWeekdayNextMonth - oneIndexedWeekday;
 306  else
 307    dayDiff = firstWeekdayNextMonth - oneIndexedWeekday;
 308  date.setDate(date.getDate() - dayDiff);
 309  return new Date(year, month - 1, date.getDate(), hour);
 310}
 311function toTimezoneOffset(timezoneInput, date, timezoneOverrides = {}) {
 312  if (timezoneInput == null) {
 313    return null;
 314  }
 315  if (typeof timezoneInput === "number") {
 316    return timezoneInput;
 317  }
 318  const matchedTimezone = timezoneOverrides[timezoneInput] ?? TIMEZONE_ABBR_MAP[timezoneInput];
 319  if (matchedTimezone == null) {
 320    return null;
 321  }
 322  if (typeof matchedTimezone == "number") {
 323    return matchedTimezone;
 324  }
 325  if (date == null) {
 326    return null;
 327  }
 328  if (date > matchedTimezone.dstStart(date.getFullYear()) && !(date > matchedTimezone.dstEnd(date.getFullYear()))) {
 329    return matchedTimezone.timezoneOffsetDuringDst;
 330  }
 331  return matchedTimezone.timezoneOffsetNonDst;
 332}
 333
 334// node_modules/chrono-node/dist/esm/calculation/duration.js
 335var EmptyDuration = {
 336  day: 0,
 337  second: 0,
 338  millisecond: 0
 339};
 340function addDuration(ref, duration) {
 341  let date = new Date(ref);
 342  if (duration["y"]) {
 343    duration["year"] = duration["y"];
 344    delete duration["y"];
 345  }
 346  if (duration["mo"]) {
 347    duration["month"] = duration["mo"];
 348    delete duration["mo"];
 349  }
 350  if (duration["M"]) {
 351    duration["month"] = duration["M"];
 352    delete duration["M"];
 353  }
 354  if (duration["w"]) {
 355    duration["week"] = duration["w"];
 356    delete duration["w"];
 357  }
 358  if (duration["d"]) {
 359    duration["day"] = duration["d"];
 360    delete duration["d"];
 361  }
 362  if (duration["h"]) {
 363    duration["hour"] = duration["h"];
 364    delete duration["h"];
 365  }
 366  if (duration["m"]) {
 367    duration["minute"] = duration["m"];
 368    delete duration["m"];
 369  }
 370  if (duration["s"]) {
 371    duration["second"] = duration["s"];
 372    delete duration["s"];
 373  }
 374  if (duration["ms"]) {
 375    duration["millisecond"] = duration["ms"];
 376    delete duration["ms"];
 377  }
 378  if ("year" in duration) {
 379    const floor = Math.floor(duration["year"]);
 380    date.setFullYear(date.getFullYear() + floor);
 381    const remainingFraction = duration["year"] - floor;
 382    if (remainingFraction > 0) {
 383      duration.month = duration?.month ?? 0;
 384      duration.month += remainingFraction * 12;
 385    }
 386  }
 387  if ("quarter" in duration) {
 388    const floor = Math.floor(duration["quarter"]);
 389    date.setMonth(date.getMonth() + floor * 3);
 390  }
 391  if ("month" in duration) {
 392    const floor = Math.floor(duration["month"]);
 393    date.setMonth(date.getMonth() + floor);
 394    const remainingFraction = duration["month"] - floor;
 395    if (remainingFraction > 0) {
 396      duration.week = duration?.week ?? 0;
 397      duration.week += remainingFraction * 4;
 398    }
 399  }
 400  if ("week" in duration) {
 401    const floor = Math.floor(duration["week"]);
 402    date.setDate(date.getDate() + floor * 7);
 403    const remainingFraction = duration["week"] - floor;
 404    if (remainingFraction > 0) {
 405      duration.day = duration?.day ?? 0;
 406      duration.day += Math.round(remainingFraction * 7);
 407    }
 408  }
 409  if ("day" in duration) {
 410    const floor = Math.floor(duration["day"]);
 411    date.setDate(date.getDate() + floor);
 412    const remainingFraction = duration["day"] - floor;
 413    if (remainingFraction > 0) {
 414      duration.hour = duration?.hour ?? 0;
 415      duration.hour += Math.round(remainingFraction * 24);
 416    }
 417  }
 418  if ("hour" in duration) {
 419    const floor = Math.floor(duration["hour"]);
 420    date.setHours(date.getHours() + floor);
 421    const remainingFraction = duration["hour"] - floor;
 422    if (remainingFraction > 0) {
 423      duration.minute = duration?.minute ?? 0;
 424      duration.minute += Math.round(remainingFraction * 60);
 425    }
 426  }
 427  if ("minute" in duration) {
 428    const floor = Math.floor(duration["minute"]);
 429    date.setMinutes(date.getMinutes() + floor);
 430    const remainingFraction = duration["minute"] - floor;
 431    if (remainingFraction > 0) {
 432      duration.second = duration?.second ?? 0;
 433      duration.second += Math.round(remainingFraction * 60);
 434    }
 435  }
 436  if ("second" in duration) {
 437    const floor = Math.floor(duration["second"]);
 438    date.setSeconds(date.getSeconds() + floor);
 439    const remainingFraction = duration["second"] - floor;
 440    if (remainingFraction > 0) {
 441      duration.millisecond = duration?.millisecond ?? 0;
 442      duration.millisecond += Math.round(remainingFraction * 1000);
 443    }
 444  }
 445  if ("millisecond" in duration) {
 446    const floor = Math.floor(duration["millisecond"]);
 447    date.setMilliseconds(date.getMilliseconds() + floor);
 448  }
 449  return date;
 450}
 451function reverseDuration(duration) {
 452  const reversed = {};
 453  for (const key in duration) {
 454    reversed[key] = -duration[key];
 455  }
 456  return reversed;
 457}
 458
 459// node_modules/chrono-node/dist/esm/results.js
 460class ReferenceWithTimezone {
 461  instant;
 462  timezoneOffset;
 463  constructor(instant, timezoneOffset) {
 464    this.instant = instant ?? new Date;
 465    this.timezoneOffset = timezoneOffset ?? null;
 466  }
 467  static fromDate(date) {
 468    return new ReferenceWithTimezone(date);
 469  }
 470  static fromInput(input, timezoneOverrides) {
 471    if (input instanceof Date) {
 472      return ReferenceWithTimezone.fromDate(input);
 473    }
 474    const instant = input?.instant ?? new Date;
 475    const timezoneOffset = toTimezoneOffset(input?.timezone, instant, timezoneOverrides);
 476    return new ReferenceWithTimezone(instant, timezoneOffset);
 477  }
 478  getDateWithAdjustedTimezone() {
 479    const date = new Date(this.instant);
 480    if (this.timezoneOffset !== null) {
 481      date.setMinutes(date.getMinutes() - this.getSystemTimezoneAdjustmentMinute(this.instant));
 482    }
 483    return date;
 484  }
 485  getSystemTimezoneAdjustmentMinute(date, overrideTimezoneOffset) {
 486    if (!date) {
 487      date = new Date;
 488    }
 489    const currentTimezoneOffset = -date.getTimezoneOffset();
 490    const targetTimezoneOffset = overrideTimezoneOffset ?? this.timezoneOffset ?? currentTimezoneOffset;
 491    return currentTimezoneOffset - targetTimezoneOffset;
 492  }
 493  getTimezoneOffset() {
 494    return this.timezoneOffset ?? -this.instant.getTimezoneOffset();
 495  }
 496}
 497
 498class ParsingComponents {
 499  knownValues;
 500  impliedValues;
 501  reference;
 502  _tags = new Set;
 503  constructor(reference, knownComponents) {
 504    this.reference = reference;
 505    this.knownValues = {};
 506    this.impliedValues = {};
 507    if (knownComponents) {
 508      for (const key in knownComponents) {
 509        this.knownValues[key] = knownComponents[key];
 510      }
 511    }
 512    const date = reference.getDateWithAdjustedTimezone();
 513    this.imply("day", date.getDate());
 514    this.imply("month", date.getMonth() + 1);
 515    this.imply("year", date.getFullYear());
 516    this.imply("hour", 12);
 517    this.imply("minute", 0);
 518    this.imply("second", 0);
 519    this.imply("millisecond", 0);
 520  }
 521  static createRelativeFromReference(reference, duration = EmptyDuration) {
 522    let date = addDuration(reference.getDateWithAdjustedTimezone(), duration);
 523    const components = new ParsingComponents(reference);
 524    components.addTag("result/relativeDate");
 525    if ("hour" in duration || "minute" in duration || "second" in duration || "millisecond" in duration) {
 526      components.addTag("result/relativeDateAndTime");
 527      assignSimilarTime(components, date);
 528      assignSimilarDate(components, date);
 529      components.assign("timezoneOffset", reference.getTimezoneOffset());
 530    } else {
 531      implySimilarTime(components, date);
 532      components.imply("timezoneOffset", reference.getTimezoneOffset());
 533      if ("day" in duration) {
 534        components.assign("day", date.getDate());
 535        components.assign("month", date.getMonth() + 1);
 536        components.assign("year", date.getFullYear());
 537        components.assign("weekday", date.getDay());
 538      } else if ("week" in duration) {
 539        components.assign("day", date.getDate());
 540        components.assign("month", date.getMonth() + 1);
 541        components.assign("year", date.getFullYear());
 542        components.imply("weekday", date.getDay());
 543      } else {
 544        components.imply("day", date.getDate());
 545        if ("month" in duration) {
 546          components.assign("month", date.getMonth() + 1);
 547          components.assign("year", date.getFullYear());
 548        } else {
 549          components.imply("month", date.getMonth() + 1);
 550          if ("year" in duration) {
 551            components.assign("year", date.getFullYear());
 552          } else {
 553            components.imply("year", date.getFullYear());
 554          }
 555        }
 556      }
 557    }
 558    return components;
 559  }
 560  get(component) {
 561    if (component in this.knownValues) {
 562      return this.knownValues[component];
 563    }
 564    if (component in this.impliedValues) {
 565      return this.impliedValues[component];
 566    }
 567    return null;
 568  }
 569  isCertain(component) {
 570    return component in this.knownValues;
 571  }
 572  getCertainComponents() {
 573    return Object.keys(this.knownValues);
 574  }
 575  imply(component, value) {
 576    if (component in this.knownValues) {
 577      return this;
 578    }
 579    this.impliedValues[component] = value;
 580    return this;
 581  }
 582  assign(component, value) {
 583    this.knownValues[component] = value;
 584    delete this.impliedValues[component];
 585    return this;
 586  }
 587  addDurationAsImplied(duration) {
 588    const currentDate = this.dateWithoutTimezoneAdjustment();
 589    const date = addDuration(currentDate, duration);
 590    if ("day" in duration || "week" in duration || "month" in duration || "year" in duration) {
 591      this.delete(["day", "weekday", "month", "year"]);
 592      this.imply("day", date.getDate());
 593      this.imply("weekday", date.getDay());
 594      this.imply("month", date.getMonth() + 1);
 595      this.imply("year", date.getFullYear());
 596    }
 597    if ("second" in duration || "minute" in duration || "hour" in duration) {
 598      this.delete(["second", "minute", "hour"]);
 599      this.imply("second", date.getSeconds());
 600      this.imply("minute", date.getMinutes());
 601      this.imply("hour", date.getHours());
 602    }
 603    return this;
 604  }
 605  delete(components) {
 606    if (typeof components === "string") {
 607      components = [components];
 608    }
 609    for (const component of components) {
 610      delete this.knownValues[component];
 611      delete this.impliedValues[component];
 612    }
 613  }
 614  clone() {
 615    const component = new ParsingComponents(this.reference);
 616    component.knownValues = {};
 617    component.impliedValues = {};
 618    for (const key in this.knownValues) {
 619      component.knownValues[key] = this.knownValues[key];
 620    }
 621    for (const key in this.impliedValues) {
 622      component.impliedValues[key] = this.impliedValues[key];
 623    }
 624    return component;
 625  }
 626  isOnlyDate() {
 627    return !this.isCertain("hour") && !this.isCertain("minute") && !this.isCertain("second");
 628  }
 629  isOnlyTime() {
 630    return !this.isCertain("weekday") && !this.isCertain("day") && !this.isCertain("month") && !this.isCertain("year");
 631  }
 632  isOnlyWeekdayComponent() {
 633    return this.isCertain("weekday") && !this.isCertain("day") && !this.isCertain("month");
 634  }
 635  isDateWithUnknownYear() {
 636    return this.isCertain("month") && !this.isCertain("year");
 637  }
 638  isValidDate() {
 639    const date = this.dateWithoutTimezoneAdjustment();
 640    if (date.getFullYear() !== this.get("year"))
 641      return false;
 642    if (date.getMonth() !== this.get("month") - 1)
 643      return false;
 644    if (date.getDate() !== this.get("day"))
 645      return false;
 646    if (this.get("hour") != null && date.getHours() != this.get("hour"))
 647      return false;
 648    if (this.get("minute") != null && date.getMinutes() != this.get("minute"))
 649      return false;
 650    return true;
 651  }
 652  toString() {
 653    return `[ParsingComponents {
 654            tags: ${JSON.stringify(Array.from(this._tags).sort())}, 
 655            knownValues: ${JSON.stringify(this.knownValues)}, 
 656            impliedValues: ${JSON.stringify(this.impliedValues)}}, 
 657            reference: ${JSON.stringify(this.reference)}]`;
 658  }
 659  date() {
 660    const date = this.dateWithoutTimezoneAdjustment();
 661    const timezoneAdjustment = this.reference.getSystemTimezoneAdjustmentMinute(date, this.get("timezoneOffset"));
 662    return new Date(date.getTime() + timezoneAdjustment * 60000);
 663  }
 664  addTag(tag) {
 665    this._tags.add(tag);
 666    return this;
 667  }
 668  addTags(tags) {
 669    for (const tag of tags) {
 670      this._tags.add(tag);
 671    }
 672    return this;
 673  }
 674  tags() {
 675    return new Set(this._tags);
 676  }
 677  dateWithoutTimezoneAdjustment() {
 678    const date = new Date(this.get("year"), this.get("month") - 1, this.get("day"), this.get("hour"), this.get("minute"), this.get("second"), this.get("millisecond"));
 679    date.setFullYear(this.get("year"));
 680    return date;
 681  }
 682}
 683
 684class ParsingResult {
 685  refDate;
 686  index;
 687  text;
 688  reference;
 689  start;
 690  end;
 691  constructor(reference, index, text, start, end) {
 692    this.reference = reference;
 693    this.refDate = reference.instant;
 694    this.index = index;
 695    this.text = text;
 696    this.start = start || new ParsingComponents(reference);
 697    this.end = end;
 698  }
 699  clone() {
 700    const result = new ParsingResult(this.reference, this.index, this.text);
 701    result.start = this.start ? this.start.clone() : null;
 702    result.end = this.end ? this.end.clone() : null;
 703    return result;
 704  }
 705  date() {
 706    return this.start.date();
 707  }
 708  addTag(tag) {
 709    this.start.addTag(tag);
 710    if (this.end) {
 711      this.end.addTag(tag);
 712    }
 713    return this;
 714  }
 715  addTags(tags) {
 716    this.start.addTags(tags);
 717    if (this.end) {
 718      this.end.addTags(tags);
 719    }
 720    return this;
 721  }
 722  tags() {
 723    const combinedTags = new Set(this.start.tags());
 724    if (this.end) {
 725      for (const tag of this.end.tags()) {
 726        combinedTags.add(tag);
 727      }
 728    }
 729    return combinedTags;
 730  }
 731  toString() {
 732    const tags = Array.from(this.tags()).sort();
 733    return `[ParsingResult {index: ${this.index}, text: '${this.text}', tags: ${JSON.stringify(tags)} ...}]`;
 734  }
 735}
 736
 737// node_modules/chrono-node/dist/esm/utils/pattern.js
 738function repeatedTimeunitPattern(prefix, singleTimeunitPattern, connectorPattern = "\\s{0,5},?\\s{0,5}") {
 739  const singleTimeunitPatternNoCapture = singleTimeunitPattern.replace(/\((?!\?)/g, "(?:");
 740  return `${prefix}${singleTimeunitPatternNoCapture}(?:${connectorPattern}${singleTimeunitPatternNoCapture}){0,10}`;
 741}
 742function extractTerms(dictionary) {
 743  let keys;
 744  if (dictionary instanceof Array) {
 745    keys = [...dictionary];
 746  } else if (dictionary instanceof Map) {
 747    keys = Array.from(dictionary.keys());
 748  } else {
 749    keys = Object.keys(dictionary);
 750  }
 751  return keys;
 752}
 753function matchAnyPattern(dictionary) {
 754  const joinedTerms = extractTerms(dictionary).sort((a, b) => b.length - a.length).join("|").replace(/\./g, "\\.");
 755  return `(?:${joinedTerms})`;
 756}
 757
 758// node_modules/chrono-node/dist/esm/calculation/years.js
 759function findMostLikelyADYear(yearNumber) {
 760  if (yearNumber < 100) {
 761    if (yearNumber > 50) {
 762      yearNumber = yearNumber + 1900;
 763    } else {
 764      yearNumber = yearNumber + 2000;
 765    }
 766  }
 767  return yearNumber;
 768}
 769function findYearClosestToRef(refDate, day, month) {
 770  let date = new Date(refDate);
 771  date.setMonth(month - 1);
 772  date.setDate(day);
 773  const nextYear = addDuration(date, { year: 1 });
 774  const lastYear = addDuration(date, { year: -1 });
 775  if (Math.abs(nextYear.getTime() - refDate.getTime()) < Math.abs(date.getTime() - refDate.getTime())) {
 776    date = nextYear;
 777  } else if (Math.abs(lastYear.getTime() - refDate.getTime()) < Math.abs(date.getTime() - refDate.getTime())) {
 778    date = lastYear;
 779  }
 780  return date.getFullYear();
 781}
 782
 783// node_modules/chrono-node/dist/esm/locales/en/constants.js
 784var WEEKDAY_DICTIONARY = {
 785  sunday: 0,
 786  sun: 0,
 787  "sun.": 0,
 788  monday: 1,
 789  mon: 1,
 790  "mon.": 1,
 791  tuesday: 2,
 792  tue: 2,
 793  "tue.": 2,
 794  wednesday: 3,
 795  wed: 3,
 796  "wed.": 3,
 797  thursday: 4,
 798  thurs: 4,
 799  "thurs.": 4,
 800  thur: 4,
 801  "thur.": 4,
 802  thu: 4,
 803  "thu.": 4,
 804  friday: 5,
 805  fri: 5,
 806  "fri.": 5,
 807  saturday: 6,
 808  sat: 6,
 809  "sat.": 6
 810};
 811var FULL_MONTH_NAME_DICTIONARY = {
 812  january: 1,
 813  february: 2,
 814  march: 3,
 815  april: 4,
 816  may: 5,
 817  june: 6,
 818  july: 7,
 819  august: 8,
 820  september: 9,
 821  october: 10,
 822  november: 11,
 823  december: 12
 824};
 825var MONTH_DICTIONARY = {
 826  ...FULL_MONTH_NAME_DICTIONARY,
 827  jan: 1,
 828  "jan.": 1,
 829  feb: 2,
 830  "feb.": 2,
 831  mar: 3,
 832  "mar.": 3,
 833  apr: 4,
 834  "apr.": 4,
 835  jun: 6,
 836  "jun.": 6,
 837  jul: 7,
 838  "jul.": 7,
 839  aug: 8,
 840  "aug.": 8,
 841  sep: 9,
 842  "sep.": 9,
 843  sept: 9,
 844  "sept.": 9,
 845  oct: 10,
 846  "oct.": 10,
 847  nov: 11,
 848  "nov.": 11,
 849  dec: 12,
 850  "dec.": 12
 851};
 852var INTEGER_WORD_DICTIONARY = {
 853  one: 1,
 854  two: 2,
 855  three: 3,
 856  four: 4,
 857  five: 5,
 858  six: 6,
 859  seven: 7,
 860  eight: 8,
 861  nine: 9,
 862  ten: 10,
 863  eleven: 11,
 864  twelve: 12
 865};
 866var ORDINAL_WORD_DICTIONARY = {
 867  first: 1,
 868  second: 2,
 869  third: 3,
 870  fourth: 4,
 871  fifth: 5,
 872  sixth: 6,
 873  seventh: 7,
 874  eighth: 8,
 875  ninth: 9,
 876  tenth: 10,
 877  eleventh: 11,
 878  twelfth: 12,
 879  thirteenth: 13,
 880  fourteenth: 14,
 881  fifteenth: 15,
 882  sixteenth: 16,
 883  seventeenth: 17,
 884  eighteenth: 18,
 885  nineteenth: 19,
 886  twentieth: 20,
 887  "twenty first": 21,
 888  "twenty-first": 21,
 889  "twenty second": 22,
 890  "twenty-second": 22,
 891  "twenty third": 23,
 892  "twenty-third": 23,
 893  "twenty fourth": 24,
 894  "twenty-fourth": 24,
 895  "twenty fifth": 25,
 896  "twenty-fifth": 25,
 897  "twenty sixth": 26,
 898  "twenty-sixth": 26,
 899  "twenty seventh": 27,
 900  "twenty-seventh": 27,
 901  "twenty eighth": 28,
 902  "twenty-eighth": 28,
 903  "twenty ninth": 29,
 904  "twenty-ninth": 29,
 905  thirtieth: 30,
 906  "thirty first": 31,
 907  "thirty-first": 31
 908};
 909var TIME_UNIT_DICTIONARY_NO_ABBR = {
 910  second: "second",
 911  seconds: "second",
 912  minute: "minute",
 913  minutes: "minute",
 914  hour: "hour",
 915  hours: "hour",
 916  day: "day",
 917  days: "day",
 918  week: "week",
 919  weeks: "week",
 920  month: "month",
 921  months: "month",
 922  quarter: "quarter",
 923  quarters: "quarter",
 924  year: "year",
 925  years: "year"
 926};
 927var TIME_UNIT_DICTIONARY = {
 928  s: "second",
 929  sec: "second",
 930  second: "second",
 931  seconds: "second",
 932  m: "minute",
 933  min: "minute",
 934  mins: "minute",
 935  minute: "minute",
 936  minutes: "minute",
 937  h: "hour",
 938  hr: "hour",
 939  hrs: "hour",
 940  hour: "hour",
 941  hours: "hour",
 942  d: "day",
 943  day: "day",
 944  days: "day",
 945  w: "week",
 946  week: "week",
 947  weeks: "week",
 948  mo: "month",
 949  mon: "month",
 950  mos: "month",
 951  month: "month",
 952  months: "month",
 953  qtr: "quarter",
 954  quarter: "quarter",
 955  quarters: "quarter",
 956  y: "year",
 957  yr: "year",
 958  year: "year",
 959  years: "year",
 960  ...TIME_UNIT_DICTIONARY_NO_ABBR
 961};
 962var 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)?)`;
 963function parseNumberPattern(match) {
 964  const num = match.toLowerCase();
 965  if (INTEGER_WORD_DICTIONARY[num] !== undefined) {
 966    return INTEGER_WORD_DICTIONARY[num];
 967  } else if (num === "a" || num === "an" || num == "the") {
 968    return 1;
 969  } else if (num.match(/few/)) {
 970    return 3;
 971  } else if (num.match(/half/)) {
 972    return 0.5;
 973  } else if (num.match(/couple/)) {
 974    return 2;
 975  } else if (num.match(/several/)) {
 976    return 7;
 977  }
 978  return parseFloat(num);
 979}
 980var ORDINAL_NUMBER_PATTERN = `(?:${matchAnyPattern(ORDINAL_WORD_DICTIONARY)}|[0-9]{1,2}(?:st|nd|rd|th)?)`;
 981function parseOrdinalNumberPattern(match) {
 982  let num = match.toLowerCase();
 983  if (ORDINAL_WORD_DICTIONARY[num] !== undefined) {
 984    return ORDINAL_WORD_DICTIONARY[num];
 985  }
 986  num = num.replace(/(?:st|nd|rd|th)$/i, "");
 987  return parseInt(num);
 988}
 989var YEAR_PATTERN = `(?:[1-9][0-9]{0,3}\\s{0,2}(?:BE|AD|BC|BCE|CE)|[1-9][0-9]{3}|[5-9][0-9]|2[0-5])`;
 990function parseYear(match) {
 991  if (/BE/i.test(match)) {
 992    match = match.replace(/BE/i, "");
 993    return parseInt(match) - 543;
 994  }
 995  if (/BCE?/i.test(match)) {
 996    match = match.replace(/BCE?/i, "");
 997    return -parseInt(match);
 998  }
 999  if (/(AD|CE)/i.test(match)) {
1000    match = match.replace(/(AD|CE)/i, "");
1001    return parseInt(match);
1002  }
1003  const rawYearNumber = parseInt(match);
1004  return findMostLikelyADYear(rawYearNumber);
1005}
1006var SINGLE_TIME_UNIT_PATTERN = `(${NUMBER_PATTERN})\\s{0,3}(${matchAnyPattern(TIME_UNIT_DICTIONARY)})`;
1007var SINGLE_TIME_UNIT_REGEX = new RegExp(SINGLE_TIME_UNIT_PATTERN, "i");
1008var SINGLE_TIME_UNIT_NO_ABBR_PATTERN = `(${NUMBER_PATTERN})\\s{0,3}(${matchAnyPattern(TIME_UNIT_DICTIONARY_NO_ABBR)})`;
1009var TIME_UNIT_CONNECTOR_PATTERN = `\\s{0,5},?(?:\\s*and)?\\s{0,5}`;
1010var TIME_UNITS_PATTERN = repeatedTimeunitPattern(`(?:(?:about|around)\\s{0,3})?`, SINGLE_TIME_UNIT_PATTERN, TIME_UNIT_CONNECTOR_PATTERN);
1011var TIME_UNITS_NO_ABBR_PATTERN = repeatedTimeunitPattern(`(?:(?:about|around)\\s{0,3})?`, SINGLE_TIME_UNIT_NO_ABBR_PATTERN, TIME_UNIT_CONNECTOR_PATTERN);
1012function parseDuration(timeunitText) {
1013  const fragments = {};
1014  let remainingText = timeunitText;
1015  let match = SINGLE_TIME_UNIT_REGEX.exec(remainingText);
1016  while (match) {
1017    collectDateTimeFragment(fragments, match);
1018    remainingText = remainingText.substring(match[0].length).trim();
1019    match = SINGLE_TIME_UNIT_REGEX.exec(remainingText);
1020  }
1021  if (Object.keys(fragments).length == 0) {
1022    return null;
1023  }
1024  return fragments;
1025}
1026function collectDateTimeFragment(fragments, match) {
1027  if (match[0].match(/^[a-zA-Z]+$/)) {
1028    return;
1029  }
1030  const num = parseNumberPattern(match[1]);
1031  const unit = TIME_UNIT_DICTIONARY[match[2].toLowerCase()];
1032  fragments[unit] = num;
1033}
1034
1035// node_modules/chrono-node/dist/esm/common/parsers/AbstractParserWithWordBoundary.js
1036class AbstractParserWithWordBoundaryChecking {
1037  innerPatternHasChange(context, currentInnerPattern) {
1038    return this.innerPattern(context) !== currentInnerPattern;
1039  }
1040  patternLeftBoundary() {
1041    return `(\\W|^)`;
1042  }
1043  cachedInnerPattern = null;
1044  cachedPattern = null;
1045  pattern(context) {
1046    if (this.cachedInnerPattern) {
1047      if (!this.innerPatternHasChange(context, this.cachedInnerPattern)) {
1048        return this.cachedPattern;
1049      }
1050    }
1051    this.cachedInnerPattern = this.innerPattern(context);
1052    this.cachedPattern = new RegExp(`${this.patternLeftBoundary()}${this.cachedInnerPattern.source}`, this.cachedInnerPattern.flags);
1053    return this.cachedPattern;
1054  }
1055  extract(context, match) {
1056    const header = match[1] ?? "";
1057    match.index = match.index + header.length;
1058    match[0] = match[0].substring(header.length);
1059    for (let i = 2;i < match.length; i++) {
1060      match[i - 1] = match[i];
1061    }
1062    return this.innerExtract(context, match);
1063  }
1064}
1065
1066// node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js
1067var PATTERN_WITH_OPTIONAL_PREFIX = new RegExp(`(?:(?:within|in|for)\\s*)?` + `(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
1068var PATTERN_WITH_PREFIX = new RegExp(`(?:within|in|for)\\s*` + `(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
1069var PATTERN_WITH_PREFIX_STRICT = new RegExp(`(?:within|in|for)\\s*` + `(?:(?:about|around|roughly|approximately|just)\\s*(?:~\\s*)?)?(${TIME_UNITS_NO_ABBR_PATTERN})(?=\\W|$)`, "i");
1070
1071class ENTimeUnitWithinFormatParser extends AbstractParserWithWordBoundaryChecking {
1072  strictMode;
1073  constructor(strictMode) {
1074    super();
1075    this.strictMode = strictMode;
1076  }
1077  innerPattern(context) {
1078    if (this.strictMode) {
1079      return PATTERN_WITH_PREFIX_STRICT;
1080    }
1081    return context.option.forwardDate ? PATTERN_WITH_OPTIONAL_PREFIX : PATTERN_WITH_PREFIX;
1082  }
1083  innerExtract(context, match) {
1084    if (match[0].match(/^for\s*the\s*\w+/)) {
1085      return null;
1086    }
1087    const timeUnits = parseDuration(match[1]);
1088    if (!timeUnits) {
1089      return null;
1090    }
1091    return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
1092  }
1093}
1094
1095// node_modules/chrono-node/dist/esm/locales/en/parsers/ENMonthNameLittleEndianParser.js
1096var PATTERN = new RegExp(`(?:on\\s{0,3})?` + `(${ORDINAL_NUMBER_PATTERN})` + `(?:` + `\\s{0,3}(?:to|\\-|\\–|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");
1097var DATE_GROUP = 1;
1098var DATE_TO_GROUP = 2;
1099var MONTH_NAME_GROUP = 3;
1100var YEAR_GROUP = 4;
1101
1102class ENMonthNameLittleEndianParser extends AbstractParserWithWordBoundaryChecking {
1103  innerPattern() {
1104    return PATTERN;
1105  }
1106  innerExtract(context, match) {
1107    const result = context.createParsingResult(match.index, match[0]);
1108    const month = MONTH_DICTIONARY[match[MONTH_NAME_GROUP].toLowerCase()];
1109    const day = parseOrdinalNumberPattern(match[DATE_GROUP]);
1110    if (day > 31) {
1111      match.index = match.index + match[DATE_GROUP].length;
1112      return null;
1113    }
1114    result.start.assign("month", month);
1115    result.start.assign("day", day);
1116    if (match[YEAR_GROUP]) {
1117      const yearNumber = parseYear(match[YEAR_GROUP]);
1118      result.start.assign("year", yearNumber);
1119    } else {
1120      const year = findYearClosestToRef(context.refDate, day, month);
1121      result.start.imply("year", year);
1122    }
1123    if (match[DATE_TO_GROUP]) {
1124      const endDate = parseOrdinalNumberPattern(match[DATE_TO_GROUP]);
1125      result.end = result.start.clone();
1126      result.end.assign("day", endDate);
1127    }
1128    return result;
1129  }
1130}
1131
1132// node_modules/chrono-node/dist/esm/locales/en/parsers/ENMonthNameMiddleEndianParser.js
1133var 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");
1134var MONTH_NAME_GROUP2 = 1;
1135var DATE_GROUP2 = 2;
1136var DATE_TO_GROUP2 = 3;
1137var YEAR_GROUP2 = 4;
1138
1139class ENMonthNameMiddleEndianParser extends AbstractParserWithWordBoundaryChecking {
1140  shouldSkipYearLikeDate;
1141  constructor(shouldSkipYearLikeDate) {
1142    super();
1143    this.shouldSkipYearLikeDate = shouldSkipYearLikeDate;
1144  }
1145  innerPattern() {
1146    return PATTERN2;
1147  }
1148  innerExtract(context, match) {
1149    const month = MONTH_DICTIONARY[match[MONTH_NAME_GROUP2].toLowerCase()];
1150    const day = parseOrdinalNumberPattern(match[DATE_GROUP2]);
1151    if (day > 31) {
1152      return null;
1153    }
1154    if (this.shouldSkipYearLikeDate) {
1155      if (!match[DATE_TO_GROUP2] && !match[YEAR_GROUP2] && match[DATE_GROUP2].match(/^2[0-5]$/)) {
1156        return null;
1157      }
1158    }
1159    const components = context.createParsingComponents({
1160      day,
1161      month
1162    }).addTag("parser/ENMonthNameMiddleEndianParser");
1163    if (match[YEAR_GROUP2]) {
1164      const year = parseYear(match[YEAR_GROUP2]);
1165      components.assign("year", year);
1166    } else {
1167      const year = findYearClosestToRef(context.refDate, day, month);
1168      components.imply("year", year);
1169    }
1170    if (!match[DATE_TO_GROUP2]) {
1171      return components;
1172    }
1173    const endDate = parseOrdinalNumberPattern(match[DATE_TO_GROUP2]);
1174    const result = context.createParsingResult(match.index, match[0]);
1175    result.start = components;
1176    result.end = components.clone();
1177    result.end.assign("day", endDate);
1178    return result;
1179  }
1180}
1181
1182// node_modules/chrono-node/dist/esm/locales/en/parsers/ENMonthNameParser.js
1183var PATTERN3 = new RegExp(`((?:in)\\s*)?` + `(${matchAnyPattern(MONTH_DICTIONARY)})` + `\\s*` + `(?:` + `(?:,|-|of)?\\s*(${YEAR_PATTERN})?` + ")?" + "(?=[^\\s\\w]|\\s+[^0-9]|\\s+$|$)", "i");
1184var PREFIX_GROUP = 1;
1185var MONTH_NAME_GROUP3 = 2;
1186var YEAR_GROUP3 = 3;
1187
1188class ENMonthNameParser extends AbstractParserWithWordBoundaryChecking {
1189  innerPattern() {
1190    return PATTERN3;
1191  }
1192  innerExtract(context, match) {
1193    const monthName = match[MONTH_NAME_GROUP3].toLowerCase();
1194    if (match[0].length <= 3 && !FULL_MONTH_NAME_DICTIONARY[monthName]) {
1195      return null;
1196    }
1197    const result = context.createParsingResult(match.index + (match[PREFIX_GROUP] || "").length, match.index + match[0].length);
1198    result.start.imply("day", 1);
1199    result.start.addTag("parser/ENMonthNameParser");
1200    const month = MONTH_DICTIONARY[monthName];
1201    result.start.assign("month", month);
1202    if (match[YEAR_GROUP3]) {
1203      const year = parseYear(match[YEAR_GROUP3]);
1204      result.start.assign("year", year);
1205    } else {
1206      const year = findYearClosestToRef(context.refDate, 1, month);
1207      result.start.imply("year", year);
1208    }
1209    return result;
1210  }
1211}
1212
1213// node_modules/chrono-node/dist/esm/locales/en/parsers/ENYearMonthDayParser.js
1214var PATTERN4 = new RegExp(`([0-9]{4})[-\\.\\/\\s]` + `(?:(${matchAnyPattern(MONTH_DICTIONARY)})|([0-9]{1,2}))[-\\.\\/\\s]` + `([0-9]{1,2})` + "(?=\\W|$)", "i");
1215var YEAR_NUMBER_GROUP = 1;
1216var MONTH_NAME_GROUP4 = 2;
1217var MONTH_NUMBER_GROUP = 3;
1218var DATE_NUMBER_GROUP = 4;
1219
1220class ENYearMonthDayParser extends AbstractParserWithWordBoundaryChecking {
1221  strictMonthDateOrder;
1222  constructor(strictMonthDateOrder) {
1223    super();
1224    this.strictMonthDateOrder = strictMonthDateOrder;
1225  }
1226  innerPattern() {
1227    return PATTERN4;
1228  }
1229  innerExtract(context, match) {
1230    const year = parseInt(match[YEAR_NUMBER_GROUP]);
1231    let day = parseInt(match[DATE_NUMBER_GROUP]);
1232    let month = match[MONTH_NUMBER_GROUP] ? parseInt(match[MONTH_NUMBER_GROUP]) : MONTH_DICTIONARY[match[MONTH_NAME_GROUP4].toLowerCase()];
1233    if (month < 1 || month > 12) {
1234      if (this.strictMonthDateOrder) {
1235        return null;
1236      }
1237      if (day >= 1 && day <= 12) {
1238        [month, day] = [day, month];
1239      }
1240    }
1241    if (day < 1 || day > 31) {
1242      return null;
1243    }
1244    return {
1245      day,
1246      month,
1247      year
1248    };
1249  }
1250}
1251
1252// node_modules/chrono-node/dist/esm/locales/en/parsers/ENSlashMonthFormatParser.js
1253var PATTERN5 = new RegExp("([0-9]|0[1-9]|1[012])/([0-9]{4})" + "", "i");
1254var MONTH_GROUP = 1;
1255var YEAR_GROUP4 = 2;
1256
1257class ENSlashMonthFormatParser extends AbstractParserWithWordBoundaryChecking {
1258  innerPattern() {
1259    return PATTERN5;
1260  }
1261  innerExtract(context, match) {
1262    const year = parseInt(match[YEAR_GROUP4]);
1263    const month = parseInt(match[MONTH_GROUP]);
1264    return context.createParsingComponents().imply("day", 1).assign("month", month).assign("year", year);
1265  }
1266}
1267
1268// node_modules/chrono-node/dist/esm/common/parsers/AbstractTimeExpressionParser.js
1269function primaryTimePattern(leftBoundary, primaryPrefix, primarySuffix, flags) {
1270  return new RegExp(`${leftBoundary}` + `${primaryPrefix}` + `(\\d{1,4})` + `(?:` + `(?:\\.|:|:)` + `(\\d{1,2})` + `(?:` + `(?::|:)` + `(\\d{2})` + `(?:\\.(\\d{1,6}))?` + `)?` + `)?` + `(?:\\s*(a\\.m\\.|p\\.m\\.|am?|pm?))?` + `${primarySuffix}`, flags);
1271}
1272function followingTimePatten(followingPhase, followingSuffix) {
1273  return new RegExp(`^(${followingPhase})` + `(\\d{1,4})` + `(?:` + `(?:\\.|\\:|\\:)` + `(\\d{1,2})` + `(?:` + `(?:\\.|\\:|\\:)` + `(\\d{1,2})(?:\\.(\\d{1,6}))?` + `)?` + `)?` + `(?:\\s*(a\\.m\\.|p\\.m\\.|am?|pm?))?` + `${followingSuffix}`, "i");
1274}
1275var HOUR_GROUP = 2;
1276var MINUTE_GROUP = 3;
1277var SECOND_GROUP = 4;
1278var MILLI_SECOND_GROUP = 5;
1279var AM_PM_HOUR_GROUP = 6;
1280
1281class AbstractTimeExpressionParser {
1282  strictMode;
1283  constructor(strictMode = false) {
1284    this.strictMode = strictMode;
1285  }
1286  patternFlags() {
1287    return "i";
1288  }
1289  primaryPatternLeftBoundary() {
1290    return `(^|\\s|T|\\b)`;
1291  }
1292  primarySuffix() {
1293    return `(?!/)(?=\\W|$)`;
1294  }
1295  followingSuffix() {
1296    return `(?!/)(?=\\W|$)`;
1297  }
1298  pattern(context) {
1299    return this.getPrimaryTimePatternThroughCache();
1300  }
1301  extract(context, match) {
1302    const startComponents = this.extractPrimaryTimeComponents(context, match);
1303    if (!startComponents) {
1304      if (match[0].match(/^\d{4}/)) {
1305        match.index += 4;
1306        return null;
1307      }
1308      match.index += match[0].length;
1309      return null;
1310    }
1311    const index = match.index + match[1].length;
1312    const text = match[0].substring(match[1].length);
1313    const result = context.createParsingResult(index, text, startComponents);
1314    match.index += match[0].length;
1315    const remainingText = context.text.substring(match.index);
1316    const followingPattern = this.getFollowingTimePatternThroughCache();
1317    const followingMatch = followingPattern.exec(remainingText);
1318    if (text.match(/^\d{3,4}/) && followingMatch) {
1319      if (followingMatch[0].match(/^\s*([+-])\s*\d{2,4}$/)) {
1320        return null;
1321      }
1322      if (followingMatch[0].match(/^\s*([+-])\s*\d{2}\W\d{2}/)) {
1323        return null;
1324      }
1325    }
1326    if (!followingMatch || followingMatch[0].match(/^\s*([+-])\s*\d{3,4}$/)) {
1327      return this.checkAndReturnWithoutFollowingPattern(result);
1328    }
1329    result.end = this.extractFollowingTimeComponents(context, followingMatch, result);
1330    if (result.end) {
1331      result.text += followingMatch[0];
1332    }
1333    return this.checkAndReturnWithFollowingPattern(result);
1334  }
1335  extractPrimaryTimeComponents(context, match, strict = false) {
1336    const components = context.createParsingComponents();
1337    let minute = 0;
1338    let meridiem = null;
1339    let hour = parseInt(match[HOUR_GROUP]);
1340    if (hour > 100) {
1341      if (match[HOUR_GROUP].length == 4 && match[MINUTE_GROUP] == null && !match[AM_PM_HOUR_GROUP]) {
1342        return null;
1343      }
1344      if (this.strictMode || match[MINUTE_GROUP] != null) {
1345        return null;
1346      }
1347      minute = hour % 100;
1348      hour = Math.floor(hour / 100);
1349    }
1350    if (hour > 24) {
1351      return null;
1352    }
1353    if (match[MINUTE_GROUP] != null) {
1354      if (match[MINUTE_GROUP].length == 1 && !match[AM_PM_HOUR_GROUP]) {
1355        return null;
1356      }
1357      minute = parseInt(match[MINUTE_GROUP]);
1358    }
1359    if (minute >= 60) {
1360      return null;
1361    }
1362    if (hour > 12) {
1363      meridiem = Meridiem.PM;
1364    }
1365    if (match[AM_PM_HOUR_GROUP] != null) {
1366      if (hour > 12)
1367        return null;
1368      const ampm = match[AM_PM_HOUR_GROUP][0].toLowerCase();
1369      if (ampm == "a") {
1370        meridiem = Meridiem.AM;
1371        if (hour == 12) {
1372          hour = 0;
1373        }
1374      }
1375      if (ampm == "p") {
1376        meridiem = Meridiem.PM;
1377        if (hour != 12) {
1378          hour += 12;
1379        }
1380      }
1381    }
1382    components.assign("hour", hour);
1383    components.assign("minute", minute);
1384    if (meridiem !== null) {
1385      components.assign("meridiem", meridiem);
1386    } else {
1387      if (hour < 12) {
1388        components.imply("meridiem", Meridiem.AM);
1389      } else {
1390        components.imply("meridiem", Meridiem.PM);
1391      }
1392    }
1393    if (match[MILLI_SECOND_GROUP] != null) {
1394      const millisecond = parseInt(match[MILLI_SECOND_GROUP].substring(0, 3));
1395      if (millisecond >= 1000)
1396        return null;
1397      components.assign("millisecond", millisecond);
1398    }
1399    if (match[SECOND_GROUP] != null) {
1400      const second = parseInt(match[SECOND_GROUP]);
1401      if (second >= 60)
1402        return null;
1403      components.assign("second", second);
1404    }
1405    return components;
1406  }
1407  extractFollowingTimeComponents(context, match, result) {
1408    const components = context.createParsingComponents();
1409    if (match[MILLI_SECOND_GROUP] != null) {
1410      const millisecond = parseInt(match[MILLI_SECOND_GROUP].substring(0, 3));
1411      if (millisecond >= 1000)
1412        return null;
1413      components.assign("millisecond", millisecond);
1414    }
1415    if (match[SECOND_GROUP] != null) {
1416      const second = parseInt(match[SECOND_GROUP]);
1417      if (second >= 60)
1418        return null;
1419      components.assign("second", second);
1420    }
1421    let hour = parseInt(match[HOUR_GROUP]);
1422    let minute = 0;
1423    let meridiem = -1;
1424    if (match[MINUTE_GROUP] != null) {
1425      minute = parseInt(match[MINUTE_GROUP]);
1426    } else if (hour > 100) {
1427      minute = hour % 100;
1428      hour = Math.floor(hour / 100);
1429    }
1430    if (minute >= 60 || hour > 24) {
1431      return null;
1432    }
1433    if (hour >= 12) {
1434      meridiem = Meridiem.PM;
1435    }
1436    if (match[AM_PM_HOUR_GROUP] != null) {
1437      if (hour > 12) {
1438        return null;
1439      }
1440      const ampm = match[AM_PM_HOUR_GROUP][0].toLowerCase();
1441      if (ampm == "a") {
1442        meridiem = Meridiem.AM;
1443        if (hour == 12) {
1444          hour = 0;
1445          if (!components.isCertain("day")) {
1446            components.imply("day", components.get("day") + 1);
1447          }
1448        }
1449      }
1450      if (ampm == "p") {
1451        meridiem = Meridiem.PM;
1452        if (hour != 12)
1453          hour += 12;
1454      }
1455      if (!result.start.isCertain("meridiem")) {
1456        if (meridiem == Meridiem.AM) {
1457          result.start.imply("meridiem", Meridiem.AM);
1458          if (result.start.get("hour") == 12) {
1459            result.start.assign("hour", 0);
1460          }
1461        } else {
1462          result.start.imply("meridiem", Meridiem.PM);
1463          if (result.start.get("hour") != 12) {
1464            result.start.assign("hour", result.start.get("hour") + 12);
1465          }
1466        }
1467      }
1468    }
1469    components.assign("hour", hour);
1470    components.assign("minute", minute);
1471    if (meridiem >= 0) {
1472      components.assign("meridiem", meridiem);
1473    } else {
1474      const startAtPM = result.start.isCertain("meridiem") && result.start.get("hour") > 12;
1475      if (startAtPM) {
1476        if (result.start.get("hour") - 12 > hour) {
1477          components.imply("meridiem", Meridiem.AM);
1478        } else if (hour <= 12) {
1479          components.assign("hour", hour + 12);
1480          components.assign("meridiem", Meridiem.PM);
1481        }
1482      } else if (hour > 12) {
1483        components.imply("meridiem", Meridiem.PM);
1484      } else if (hour <= 12) {
1485        components.imply("meridiem", Meridiem.AM);
1486      }
1487    }
1488    if (components.date().getTime() < result.start.date().getTime()) {
1489      components.imply("day", components.get("day") + 1);
1490    }
1491    return components;
1492  }
1493  checkAndReturnWithoutFollowingPattern(result) {
1494    if (result.text.match(/^\d$/)) {
1495      return null;
1496    }
1497    if (result.text.match(/^\d\d\d+$/)) {
1498      return null;
1499    }
1500    if (result.text.match(/\d[apAP]$/)) {
1501      return null;
1502    }
1503    const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)$/);
1504    if (endingWithNumbers) {
1505      const endingNumbers = endingWithNumbers[1];
1506      if (this.strictMode) {
1507        return null;
1508      }
1509      if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) {
1510        return null;
1511      }
1512      const endingNumberVal = parseInt(endingNumbers);
1513      if (endingNumberVal > 24) {
1514        return null;
1515      }
1516    }
1517    return result;
1518  }
1519  checkAndReturnWithFollowingPattern(result) {
1520    if (result.text.match(/^\d+-\d+$/)) {
1521      return null;
1522    }
1523    const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)\s*-\s*(\d[\d.]+)$/);
1524    if (endingWithNumbers) {
1525      if (this.strictMode) {
1526        return null;
1527      }
1528      const startingNumbers = endingWithNumbers[1];
1529      const endingNumbers = endingWithNumbers[2];
1530      if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) {
1531        return null;
1532      }
1533      const endingNumberVal = parseInt(endingNumbers);
1534      const startingNumberVal = parseInt(startingNumbers);
1535      if (endingNumberVal > 24 || startingNumberVal > 24) {
1536        return null;
1537      }
1538    }
1539    return result;
1540  }
1541  cachedPrimaryPrefix = null;
1542  cachedPrimarySuffix = null;
1543  cachedPrimaryTimePattern = null;
1544  getPrimaryTimePatternThroughCache() {
1545    const primaryPrefix = this.primaryPrefix();
1546    const primarySuffix = this.primarySuffix();
1547    if (this.cachedPrimaryPrefix === primaryPrefix && this.cachedPrimarySuffix === primarySuffix) {
1548      return this.cachedPrimaryTimePattern;
1549    }
1550    this.cachedPrimaryTimePattern = primaryTimePattern(this.primaryPatternLeftBoundary(), primaryPrefix, primarySuffix, this.patternFlags());
1551    this.cachedPrimaryPrefix = primaryPrefix;
1552    this.cachedPrimarySuffix = primarySuffix;
1553    return this.cachedPrimaryTimePattern;
1554  }
1555  cachedFollowingPhase = null;
1556  cachedFollowingSuffix = null;
1557  cachedFollowingTimePatten = null;
1558  getFollowingTimePatternThroughCache() {
1559    const followingPhase = this.followingPhase();
1560    const followingSuffix = this.followingSuffix();
1561    if (this.cachedFollowingPhase === followingPhase && this.cachedFollowingSuffix === followingSuffix) {
1562      return this.cachedFollowingTimePatten;
1563    }
1564    this.cachedFollowingTimePatten = followingTimePatten(followingPhase, followingSuffix);
1565    this.cachedFollowingPhase = followingPhase;
1566    this.cachedFollowingSuffix = followingSuffix;
1567    return this.cachedFollowingTimePatten;
1568  }
1569}
1570
1571// node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeExpressionParser.js
1572class ENTimeExpressionParser extends AbstractTimeExpressionParser {
1573  constructor(strictMode) {
1574    super(strictMode);
1575  }
1576  followingPhase() {
1577    return "\\s*(?:\\-|\\–|\\~|\\〜|to|until|through|till|\\?)\\s*";
1578  }
1579  primaryPrefix() {
1580    return "(?:(?:at|from)\\s*)??";
1581  }
1582  primarySuffix() {
1583    return "(?:\\s*(?:o\\W*clock|at\\s*night|in\\s*the\\s*(?:morning|afternoon)))?(?!/)(?=\\W|$)";
1584  }
1585  extractPrimaryTimeComponents(context, match) {
1586    const components = super.extractPrimaryTimeComponents(context, match);
1587    if (!components) {
1588      return components;
1589    }
1590    if (match[0].endsWith("night")) {
1591      const hour = components.get("hour");
1592      if (hour >= 6 && hour < 12) {
1593        components.assign("hour", components.get("hour") + 12);
1594        components.assign("meridiem", Meridiem.PM);
1595      } else if (hour < 6) {
1596        components.assign("meridiem", Meridiem.AM);
1597      }
1598    }
1599    if (match[0].endsWith("afternoon")) {
1600      components.assign("meridiem", Meridiem.PM);
1601      const hour = components.get("hour");
1602      if (hour >= 0 && hour <= 6) {
1603        components.assign("hour", components.get("hour") + 12);
1604      }
1605    }
1606    if (match[0].endsWith("morning")) {
1607      components.assign("meridiem", Meridiem.AM);
1608      const hour = components.get("hour");
1609      if (hour < 12) {
1610        components.assign("hour", components.get("hour"));
1611      }
1612    }
1613    return components.addTag("parser/ENTimeExpressionParser");
1614  }
1615  extractFollowingTimeComponents(context, match, result) {
1616    const followingComponents = super.extractFollowingTimeComponents(context, match, result);
1617    if (followingComponents) {
1618      followingComponents.addTag("parser/ENTimeExpressionParser");
1619    }
1620    return followingComponents;
1621  }
1622}
1623
1624// node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitAgoFormatParser.js
1625var PATTERN6 = new RegExp(`(${TIME_UNITS_PATTERN})\\s{0,5}(?:ago|before|earlier)(?=\\W|$)`, "i");
1626var STRICT_PATTERN = new RegExp(`(${TIME_UNITS_NO_ABBR_PATTERN})\\s{0,5}(?:ago|before|earlier)(?=\\W|$)`, "i");
1627
1628class ENTimeUnitAgoFormatParser extends AbstractParserWithWordBoundaryChecking {
1629  strictMode;
1630  constructor(strictMode) {
1631    super();
1632    this.strictMode = strictMode;
1633  }
1634  innerPattern() {
1635    return this.strictMode ? STRICT_PATTERN : PATTERN6;
1636  }
1637  innerExtract(context, match) {
1638    const duration = parseDuration(match[1]);
1639    if (!duration) {
1640      return null;
1641    }
1642    return ParsingComponents.createRelativeFromReference(context.reference, reverseDuration(duration));
1643  }
1644}
1645
1646// node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitLaterFormatParser.js
1647var PATTERN7 = new RegExp(`(${TIME_UNITS_PATTERN})\\s{0,5}(?:later|after|from now|henceforth|forward|out)` + "(?=(?:\\W|$))", "i");
1648var STRICT_PATTERN2 = new RegExp(`(${TIME_UNITS_NO_ABBR_PATTERN})\\s{0,5}(later|after|from now)(?=\\W|$)`, "i");
1649var GROUP_NUM_TIMEUNITS = 1;
1650
1651class ENTimeUnitLaterFormatParser extends AbstractParserWithWordBoundaryChecking {
1652  strictMode;
1653  constructor(strictMode) {
1654    super();
1655    this.strictMode = strictMode;
1656  }
1657  innerPattern() {
1658    return this.strictMode ? STRICT_PATTERN2 : PATTERN7;
1659  }
1660  innerExtract(context, match) {
1661    const timeUnits = parseDuration(match[GROUP_NUM_TIMEUNITS]);
1662    if (!timeUnits) {
1663      return null;
1664    }
1665    return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
1666  }
1667}
1668
1669// node_modules/chrono-node/dist/esm/common/abstractRefiners.js
1670class Filter {
1671  refine(context, results) {
1672    return results.filter((r) => this.isValid(context, r));
1673  }
1674}
1675
1676class MergingRefiner {
1677  refine(context, results) {
1678    if (results.length < 2) {
1679      return results;
1680    }
1681    const mergedResults = [];
1682    let curResult = results[0];
1683    let nextResult = null;
1684    for (let i = 1;i < results.length; i++) {
1685      nextResult = results[i];
1686      const textBetween = context.text.substring(curResult.index + curResult.text.length, nextResult.index);
1687      if (!this.shouldMergeResults(textBetween, curResult, nextResult, context)) {
1688        mergedResults.push(curResult);
1689        curResult = nextResult;
1690      } else {
1691        const left = curResult;
1692        const right = nextResult;
1693        const mergedResult = this.mergeResults(textBetween, left, right, context);
1694        context.debug(() => {
1695          console.log(`${this.constructor.name} merged ${left} and ${right} into ${mergedResult}`);
1696        });
1697        curResult = mergedResult;
1698      }
1699    }
1700    if (curResult != null) {
1701      mergedResults.push(curResult);
1702    }
1703    return mergedResults;
1704  }
1705}
1706
1707// node_modules/chrono-node/dist/esm/common/refiners/AbstractMergeDateRangeRefiner.js
1708class AbstractMergeDateRangeRefiner extends MergingRefiner {
1709  shouldMergeResults(textBetween, currentResult, nextResult) {
1710    return !currentResult.end && !nextResult.end && textBetween.match(this.patternBetween()) != null;
1711  }
1712  mergeResults(textBetween, fromResult, toResult) {
1713    if (!fromResult.start.isOnlyWeekdayComponent() && !toResult.start.isOnlyWeekdayComponent()) {
1714      toResult.start.getCertainComponents().forEach((key) => {
1715        if (!fromResult.start.isCertain(key)) {
1716          fromResult.start.imply(key, toResult.start.get(key));
1717        }
1718      });
1719      fromResult.start.getCertainComponents().forEach((key) => {
1720        if (!toResult.start.isCertain(key)) {
1721          toResult.start.imply(key, fromResult.start.get(key));
1722        }
1723      });
1724    }
1725    if (fromResult.start.date() > toResult.start.date()) {
1726      let fromDate = fromResult.start.date();
1727      let toDate = toResult.start.date();
1728      if (toResult.start.isOnlyWeekdayComponent() && addDuration(toDate, { day: 7 }) > fromDate) {
1729        toDate = addDuration(toDate, { day: 7 });
1730        toResult.start.imply("day", toDate.getDate());
1731        toResult.start.imply("month", toDate.getMonth() + 1);
1732        toResult.start.imply("year", toDate.getFullYear());
1733      } else if (fromResult.start.isOnlyWeekdayComponent() && addDuration(fromDate, { day: -7 }) < toDate) {
1734        fromDate = addDuration(fromDate, { day: -7 });
1735        fromResult.start.imply("day", fromDate.getDate());
1736        fromResult.start.imply("month", fromDate.getMonth() + 1);
1737        fromResult.start.imply("year", fromDate.getFullYear());
1738      } else if (toResult.start.isDateWithUnknownYear() && addDuration(toDate, { year: 1 }) > fromDate) {
1739        toDate = addDuration(toDate, { year: 1 });
1740        toResult.start.imply("year", toDate.getFullYear());
1741      } else if (fromResult.start.isDateWithUnknownYear() && addDuration(fromDate, { year: -1 }) < toDate) {
1742        fromDate = addDuration(fromDate, { year: -1 });
1743        fromResult.start.imply("year", fromDate.getFullYear());
1744      } else {
1745        [toResult, fromResult] = [fromResult, toResult];
1746      }
1747    }
1748    const result = fromResult.clone();
1749    result.start = fromResult.start;
1750    result.end = toResult.start;
1751    result.index = Math.min(fromResult.index, toResult.index);
1752    if (fromResult.index < toResult.index) {
1753      result.text = fromResult.text + textBetween + toResult.text;
1754    } else {
1755      result.text = toResult.text + textBetween + fromResult.text;
1756    }
1757    return result;
1758  }
1759}
1760
1761// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeDateRangeRefiner.js
1762class ENMergeDateRangeRefiner extends AbstractMergeDateRangeRefiner {
1763  patternBetween() {
1764    return /^\s*(to|-|–|until|through|till)\s*$/i;
1765  }
1766}
1767
1768// node_modules/chrono-node/dist/esm/calculation/mergingCalculation.js
1769function mergeDateTimeResult(dateResult, timeResult) {
1770  const result = dateResult.clone();
1771  const beginDate = dateResult.start;
1772  const beginTime = timeResult.start;
1773  result.start = mergeDateTimeComponent(beginDate, beginTime);
1774  if (dateResult.end != null || timeResult.end != null) {
1775    const endDate = dateResult.end == null ? dateResult.start : dateResult.end;
1776    const endTime = timeResult.end == null ? timeResult.start : timeResult.end;
1777    const endDateTime = mergeDateTimeComponent(endDate, endTime);
1778    if (dateResult.end == null && endDateTime.date().getTime() < result.start.date().getTime()) {
1779      const nextDay = new Date(endDateTime.date().getTime());
1780      nextDay.setDate(nextDay.getDate() + 1);
1781      if (endDateTime.isCertain("day")) {
1782        assignSimilarDate(endDateTime, nextDay);
1783      } else {
1784        implySimilarDate(endDateTime, nextDay);
1785      }
1786    }
1787    result.end = endDateTime;
1788  }
1789  return result;
1790}
1791function mergeDateTimeComponent(dateComponent, timeComponent) {
1792  const dateTimeComponent = dateComponent.clone();
1793  if (timeComponent.isCertain("hour")) {
1794    dateTimeComponent.assign("hour", timeComponent.get("hour"));
1795    dateTimeComponent.assign("minute", timeComponent.get("minute"));
1796    if (timeComponent.isCertain("second")) {
1797      dateTimeComponent.assign("second", timeComponent.get("second"));
1798      if (timeComponent.isCertain("millisecond")) {
1799        dateTimeComponent.assign("millisecond", timeComponent.get("millisecond"));
1800      } else {
1801        dateTimeComponent.imply("millisecond", timeComponent.get("millisecond"));
1802      }
1803    } else {
1804      dateTimeComponent.imply("second", timeComponent.get("second"));
1805      dateTimeComponent.imply("millisecond", timeComponent.get("millisecond"));
1806    }
1807  } else {
1808    dateTimeComponent.imply("hour", timeComponent.get("hour"));
1809    dateTimeComponent.imply("minute", timeComponent.get("minute"));
1810    dateTimeComponent.imply("second", timeComponent.get("second"));
1811    dateTimeComponent.imply("millisecond", timeComponent.get("millisecond"));
1812  }
1813  if (timeComponent.isCertain("timezoneOffset")) {
1814    dateTimeComponent.assign("timezoneOffset", timeComponent.get("timezoneOffset"));
1815  }
1816  const dateHasMeaningfulMeridiem = dateComponent.get("meridiem") != null && (dateComponent.isCertain("meridiem") || Array.from(dateComponent.tags()).some((t) => t.startsWith("casualReference/")));
1817  if (timeComponent.isCertain("meridiem")) {
1818    dateTimeComponent.assign("meridiem", timeComponent.get("meridiem"));
1819  } else if (timeComponent.get("meridiem") != null && !dateHasMeaningfulMeridiem) {
1820    dateTimeComponent.imply("meridiem", timeComponent.get("meridiem"));
1821  }
1822  if (dateTimeComponent.get("meridiem") == Meridiem.PM && dateTimeComponent.get("hour") < 12) {
1823    if (timeComponent.isCertain("hour")) {
1824      dateTimeComponent.assign("hour", dateTimeComponent.get("hour") + 12);
1825    } else {
1826      dateTimeComponent.imply("hour", dateTimeComponent.get("hour") + 12);
1827    }
1828  }
1829  dateTimeComponent.addTags(dateComponent.tags());
1830  dateTimeComponent.addTags(timeComponent.tags());
1831  return dateTimeComponent;
1832}
1833
1834// node_modules/chrono-node/dist/esm/common/refiners/AbstractMergeDateTimeRefiner.js
1835class AbstractMergeDateTimeRefiner extends MergingRefiner {
1836  shouldMergeResults(textBetween, currentResult, nextResult) {
1837    return (currentResult.start.isOnlyDate() && nextResult.start.isOnlyTime() || nextResult.start.isOnlyDate() && currentResult.start.isOnlyTime()) && textBetween.match(this.patternBetween()) != null;
1838  }
1839  mergeResults(textBetween, currentResult, nextResult) {
1840    const result = currentResult.start.isOnlyDate() ? mergeDateTimeResult(currentResult, nextResult) : mergeDateTimeResult(nextResult, currentResult);
1841    result.index = currentResult.index;
1842    result.text = currentResult.text + textBetween + nextResult.text;
1843    return result;
1844  }
1845}
1846
1847// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeDateTimeRefiner.js
1848class ENMergeDateTimeRefiner extends AbstractMergeDateTimeRefiner {
1849  patternBetween() {
1850    return new RegExp("^\\s*(T|at|after|before|on|of|,|-|\\.|∙|:)?\\s*$");
1851  }
1852}
1853
1854// node_modules/chrono-node/dist/esm/common/refiners/ExtractTimezoneAbbrRefiner.js
1855var TIMEZONE_NAME_PATTERN = new RegExp("^\\s*,?\\s*\\(?([A-Z]{2,4})\\)?(?=\\W|$)", "i");
1856
1857class ExtractTimezoneAbbrRefiner {
1858  timezoneOverrides;
1859  constructor(timezoneOverrides) {
1860    this.timezoneOverrides = timezoneOverrides;
1861  }
1862  refine(context, results) {
1863    const timezoneOverrides = context.option.timezones ?? {};
1864    results.forEach((result) => {
1865      const suffix = context.text.substring(result.index + result.text.length);
1866      const match = TIMEZONE_NAME_PATTERN.exec(suffix);
1867      if (!match) {
1868        return;
1869      }
1870      const timezoneAbbr = match[1].toUpperCase();
1871      const refDate = result.start.date() ?? result.refDate ?? new Date;
1872      const tzOverrides = { ...this.timezoneOverrides, ...timezoneOverrides };
1873      const extractedTimezoneOffset = toTimezoneOffset(timezoneAbbr, refDate, tzOverrides);
1874      if (extractedTimezoneOffset == null) {
1875        return;
1876      }
1877      context.debug(() => {
1878        console.log(`Extracting timezone: '${timezoneAbbr}' into: ${extractedTimezoneOffset} for: ${result.start}`);
1879      });
1880      const currentTimezoneOffset = result.start.get("timezoneOffset");
1881      if (currentTimezoneOffset !== null && extractedTimezoneOffset != currentTimezoneOffset) {
1882        if (result.start.isCertain("timezoneOffset")) {
1883          return;
1884        }
1885        if (timezoneAbbr != match[1]) {
1886          return;
1887        }
1888      }
1889      if (result.start.isOnlyDate()) {
1890        if (timezoneAbbr != match[1]) {
1891          return;
1892        }
1893      }
1894      result.text += match[0];
1895      if (!result.start.isCertain("timezoneOffset")) {
1896        result.start.assign("timezoneOffset", extractedTimezoneOffset);
1897      }
1898      if (result.end != null && !result.end.isCertain("timezoneOffset")) {
1899        result.end.assign("timezoneOffset", extractedTimezoneOffset);
1900      }
1901    });
1902    return results;
1903  }
1904}
1905
1906// node_modules/chrono-node/dist/esm/common/refiners/ExtractTimezoneOffsetRefiner.js
1907var TIMEZONE_OFFSET_PATTERN = new RegExp("^\\s*(?:\\(?(?:GMT|UTC)\\s?)?([+-])(\\d{1,2})(?::?(\\d{2}))?\\)?", "i");
1908var TIMEZONE_OFFSET_SIGN_GROUP = 1;
1909var TIMEZONE_OFFSET_HOUR_OFFSET_GROUP = 2;
1910var TIMEZONE_OFFSET_MINUTE_OFFSET_GROUP = 3;
1911
1912class ExtractTimezoneOffsetRefiner {
1913  refine(context, results) {
1914    results.forEach(function(result) {
1915      if (result.start.isCertain("timezoneOffset")) {
1916        return;
1917      }
1918      const suffix = context.text.substring(result.index + result.text.length);
1919      const match = TIMEZONE_OFFSET_PATTERN.exec(suffix);
1920      if (!match) {
1921        return;
1922      }
1923      context.debug(() => {
1924        console.log(`Extracting timezone: '${match[0]}' into : ${result}`);
1925      });
1926      const hourOffset = parseInt(match[TIMEZONE_OFFSET_HOUR_OFFSET_GROUP]);
1927      const minuteOffset = parseInt(match[TIMEZONE_OFFSET_MINUTE_OFFSET_GROUP] || "0");
1928      let timezoneOffset = hourOffset * 60 + minuteOffset;
1929      if (timezoneOffset > 14 * 60) {
1930        return;
1931      }
1932      if (match[TIMEZONE_OFFSET_SIGN_GROUP] === "-") {
1933        timezoneOffset = -timezoneOffset;
1934      }
1935      if (result.end != null) {
1936        result.end.assign("timezoneOffset", timezoneOffset);
1937      }
1938      result.start.assign("timezoneOffset", timezoneOffset);
1939      result.text += match[0];
1940    });
1941    return results;
1942  }
1943}
1944
1945// node_modules/chrono-node/dist/esm/common/refiners/OverlapRemovalRefiner.js
1946class OverlapRemovalRefiner {
1947  refine(context, results) {
1948    if (results.length < 2) {
1949      return results;
1950    }
1951    const filteredResults = [];
1952    let prevResult = results[0];
1953    for (let i = 1;i < results.length; i++) {
1954      const result = results[i];
1955      if (result.index >= prevResult.index + prevResult.text.length) {
1956        filteredResults.push(prevResult);
1957        prevResult = result;
1958        continue;
1959      }
1960      let kept = null;
1961      let removed = null;
1962      if (result.text.length > prevResult.text.length) {
1963        kept = result;
1964        removed = prevResult;
1965      } else {
1966        kept = prevResult;
1967        removed = result;
1968      }
1969      context.debug(() => {
1970        console.log(`${this.constructor.name} remove ${removed} by ${kept}`);
1971      });
1972      prevResult = kept;
1973    }
1974    if (prevResult != null) {
1975      filteredResults.push(prevResult);
1976    }
1977    return filteredResults;
1978  }
1979}
1980
1981// node_modules/chrono-node/dist/esm/calculation/weekdays.js
1982function createParsingComponentsAtWeekday(reference, weekday, modifier) {
1983  const refDate = reference.getDateWithAdjustedTimezone();
1984  const daysToWeekday = getDaysToWeekday(refDate, weekday, modifier);
1985  let components = new ParsingComponents(reference);
1986  components = components.addDurationAsImplied({ day: daysToWeekday });
1987  components.assign("weekday", weekday);
1988  return components;
1989}
1990function getDaysToWeekday(refDate, weekday, modifier) {
1991  const refWeekday = refDate.getDay();
1992  switch (modifier) {
1993    case "this":
1994      return getDaysForwardToWeekday(refDate, weekday);
1995    case "last":
1996      return getBackwardDaysToWeekday(refDate, weekday);
1997    case "next":
1998      if (refWeekday == Weekday.SUNDAY) {
1999        return weekday == Weekday.SUNDAY ? 7 : weekday;
2000      }
2001      if (refWeekday == Weekday.SATURDAY) {
2002        if (weekday == Weekday.SATURDAY)
2003          return 7;
2004        if (weekday == Weekday.SUNDAY)
2005          return 8;
2006        return 1 + weekday;
2007      }
2008      if (weekday < refWeekday && weekday != Weekday.SUNDAY) {
2009        return getDaysForwardToWeekday(refDate, weekday);
2010      } else {
2011        return getDaysForwardToWeekday(refDate, weekday) + 7;
2012      }
2013  }
2014  return getDaysToWeekdayClosest(refDate, weekday);
2015}
2016function getDaysToWeekdayClosest(refDate, weekday) {
2017  const backward = getBackwardDaysToWeekday(refDate, weekday);
2018  const forward = getDaysForwardToWeekday(refDate, weekday);
2019  return forward < -backward ? forward : backward;
2020}
2021function getDaysForwardToWeekday(refDate, weekday) {
2022  const refWeekday = refDate.getDay();
2023  let forwardCount = weekday - refWeekday;
2024  if (forwardCount < 0) {
2025    forwardCount += 7;
2026  }
2027  return forwardCount;
2028}
2029function getBackwardDaysToWeekday(refDate, weekday) {
2030  const refWeekday = refDate.getDay();
2031  let backwardCount = weekday - refWeekday;
2032  if (backwardCount >= 0) {
2033    backwardCount -= 7;
2034  }
2035  return backwardCount;
2036}
2037
2038// node_modules/chrono-node/dist/esm/common/refiners/ForwardDateRefiner.js
2039class ForwardDateRefiner {
2040  refine(context, results) {
2041    if (!context.option.forwardDate) {
2042      return results;
2043    }
2044    results.forEach((result) => {
2045      let refDate = context.reference.getDateWithAdjustedTimezone();
2046      if (result.start.isOnlyTime() && context.reference.instant > result.start.date()) {
2047        const refDate2 = context.reference.getDateWithAdjustedTimezone();
2048        const refFollowingDay = new Date(refDate2);
2049        refFollowingDay.setDate(refFollowingDay.getDate() + 1);
2050        implySimilarDate(result.start, refFollowingDay);
2051        context.debug(() => {
2052          console.log(`${this.constructor.name} adjusted ${result} time from the ref date (${refDate2}) to the following day (${refFollowingDay})`);
2053        });
2054        if (result.end && result.end.isOnlyTime()) {
2055          implySimilarDate(result.end, refFollowingDay);
2056          if (result.start.date() > result.end.date()) {
2057            refFollowingDay.setDate(refFollowingDay.getDate() + 1);
2058            implySimilarDate(result.end, refFollowingDay);
2059          }
2060        }
2061      }
2062      if (result.start.isOnlyWeekdayComponent() && refDate > result.start.date()) {
2063        let daysToAdd = getDaysForwardToWeekday(refDate, result.start.get("weekday")) || 7;
2064        const forwardedWeekday = addDuration(refDate, { day: daysToAdd });
2065        implySimilarDate(result.start, forwardedWeekday);
2066        context.debug(() => {
2067          console.log(`${this.constructor.name} adjusted ${result} weekday (${result.start})`);
2068        });
2069        if (result.end && result.start.date() > result.end.date()) {
2070          let daysToAdd2 = getDaysForwardToWeekday(refDate, result.start.get("weekday")) || 7;
2071          const forwardedWeekday2 = addDuration(refDate, { day: daysToAdd2 });
2072          implySimilarDate(result.end, forwardedWeekday2);
2073          context.debug(() => {
2074            console.log(`${this.constructor.name} adjusted ${result} weekday (${result.end})`);
2075          });
2076        }
2077      }
2078      if (result.start.isDateWithUnknownYear() && refDate > result.start.date()) {
2079        for (let i = 0;i < 3 && refDate > result.start.date(); i++) {
2080          result.start.imply("year", result.start.get("year") + 1);
2081          context.debug(() => {
2082            console.log(`${this.constructor.name} adjusted ${result} year (${result.start})`);
2083          });
2084          if (result.end && !result.end.isCertain("year")) {
2085            result.end.imply("year", result.end.get("year") + 1);
2086            context.debug(() => {
2087              console.log(`${this.constructor.name} adjusted ${result} month (${result.start})`);
2088            });
2089          }
2090        }
2091      }
2092    });
2093    return results;
2094  }
2095}
2096
2097// node_modules/chrono-node/dist/esm/common/refiners/UnlikelyFormatFilter.js
2098class UnlikelyFormatFilter extends Filter {
2099  strictMode;
2100  constructor(strictMode) {
2101    super();
2102    this.strictMode = strictMode;
2103  }
2104  isValid(context, result) {
2105    if (result.text.replace(" ", "").match(/^\d*(\.\d*)?$/)) {
2106      context.debug(() => {
2107        console.log(`Removing unlikely result '${result.text}'`);
2108      });
2109      return false;
2110    }
2111    if (!result.start.isValidDate()) {
2112      context.debug(() => {
2113        console.log(`Removing invalid result: ${result} (${result.start})`);
2114      });
2115      return false;
2116    }
2117    if (result.end && !result.end.isValidDate()) {
2118      context.debug(() => {
2119        console.log(`Removing invalid result: ${result} (${result.end})`);
2120      });
2121      return false;
2122    }
2123    if (this.strictMode) {
2124      return this.isStrictModeValid(context, result);
2125    }
2126    return true;
2127  }
2128  isStrictModeValid(context, result) {
2129    if (result.start.isOnlyWeekdayComponent()) {
2130      context.debug(() => {
2131        console.log(`(Strict) Removing weekday only component: ${result} (${result.end})`);
2132      });
2133      return false;
2134    }
2135    return true;
2136  }
2137}
2138
2139// node_modules/chrono-node/dist/esm/common/parsers/ISOFormatParser.js
2140var PATTERN8 = 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");
2141var YEAR_NUMBER_GROUP2 = 1;
2142var MONTH_NUMBER_GROUP2 = 2;
2143var DATE_NUMBER_GROUP2 = 3;
2144var HOUR_NUMBER_GROUP = 4;
2145var MINUTE_NUMBER_GROUP = 5;
2146var SECOND_NUMBER_GROUP = 6;
2147var MILLISECOND_NUMBER_GROUP = 7;
2148var TZD_GROUP = 8;
2149var TZD_HOUR_OFFSET_GROUP = 9;
2150var TZD_MINUTE_OFFSET_GROUP = 10;
2151
2152class ISOFormatParser extends AbstractParserWithWordBoundaryChecking {
2153  innerPattern() {
2154    return PATTERN8;
2155  }
2156  innerExtract(context, match) {
2157    const components = context.createParsingComponents({
2158      year: parseInt(match[YEAR_NUMBER_GROUP2]),
2159      month: parseInt(match[MONTH_NUMBER_GROUP2]),
2160      day: parseInt(match[DATE_NUMBER_GROUP2])
2161    });
2162    if (match[HOUR_NUMBER_GROUP] != null) {
2163      components.assign("hour", parseInt(match[HOUR_NUMBER_GROUP]));
2164      components.assign("minute", parseInt(match[MINUTE_NUMBER_GROUP]));
2165      if (match[SECOND_NUMBER_GROUP] != null) {
2166        components.assign("second", parseInt(match[SECOND_NUMBER_GROUP]));
2167      }
2168      if (match[MILLISECOND_NUMBER_GROUP] != null) {
2169        components.assign("millisecond", parseInt(match[MILLISECOND_NUMBER_GROUP]));
2170      }
2171      if (match[TZD_GROUP] != null) {
2172        let offset = 0;
2173        if (match[TZD_HOUR_OFFSET_GROUP]) {
2174          const hourOffset = parseInt(match[TZD_HOUR_OFFSET_GROUP]);
2175          let minuteOffset = 0;
2176          if (match[TZD_MINUTE_OFFSET_GROUP] != null) {
2177            minuteOffset = parseInt(match[TZD_MINUTE_OFFSET_GROUP]);
2178          }
2179          offset = hourOffset * 60;
2180          if (offset < 0) {
2181            offset -= minuteOffset;
2182          } else {
2183            offset += minuteOffset;
2184          }
2185        }
2186        components.assign("timezoneOffset", offset);
2187      }
2188    }
2189    return components.addTag("parser/ISOFormatParser");
2190  }
2191}
2192
2193// node_modules/chrono-node/dist/esm/common/refiners/MergeWeekdayComponentRefiner.js
2194class MergeWeekdayComponentRefiner extends MergingRefiner {
2195  mergeResults(textBetween, currentResult, nextResult) {
2196    const newResult = nextResult.clone();
2197    newResult.index = currentResult.index;
2198    newResult.text = currentResult.text + textBetween + newResult.text;
2199    newResult.start.assign("weekday", currentResult.start.get("weekday"));
2200    if (newResult.end) {
2201      newResult.end.assign("weekday", currentResult.start.get("weekday"));
2202    }
2203    return newResult;
2204  }
2205  shouldMergeResults(textBetween, currentResult, nextResult) {
2206    const weekdayThenNormalDate = currentResult.start.isOnlyWeekdayComponent() && !currentResult.start.isCertain("hour") && nextResult.start.isCertain("day");
2207    return weekdayThenNormalDate && textBetween.match(/^,?\s*$/) != null;
2208  }
2209}
2210
2211// node_modules/chrono-node/dist/esm/configurations.js
2212function includeCommonConfiguration(configuration, strictMode = false) {
2213  configuration.parsers.unshift(new ISOFormatParser);
2214  configuration.refiners.unshift(new MergeWeekdayComponentRefiner);
2215  configuration.refiners.unshift(new ExtractTimezoneOffsetRefiner);
2216  configuration.refiners.unshift(new OverlapRemovalRefiner);
2217  configuration.refiners.push(new ExtractTimezoneAbbrRefiner);
2218  configuration.refiners.push(new OverlapRemovalRefiner);
2219  configuration.refiners.push(new ForwardDateRefiner);
2220  configuration.refiners.push(new UnlikelyFormatFilter(strictMode));
2221  return configuration;
2222}
2223
2224// node_modules/chrono-node/dist/esm/common/casualReferences.js
2225function now(reference) {
2226  const targetDate = reference.getDateWithAdjustedTimezone();
2227  const component = new ParsingComponents(reference, {});
2228  assignSimilarDate(component, targetDate);
2229  assignSimilarTime(component, targetDate);
2230  component.assign("timezoneOffset", reference.getTimezoneOffset());
2231  component.addTag("casualReference/now");
2232  return component;
2233}
2234function today(reference) {
2235  const targetDate = reference.getDateWithAdjustedTimezone();
2236  const component = new ParsingComponents(reference, {});
2237  assignSimilarDate(component, targetDate);
2238  implySimilarTime(component, targetDate);
2239  component.delete("meridiem");
2240  component.addTag("casualReference/today");
2241  return component;
2242}
2243function yesterday(reference) {
2244  return theDayBefore(reference, 1).addTag("casualReference/yesterday");
2245}
2246function tomorrow(reference) {
2247  return theDayAfter(reference, 1).addTag("casualReference/tomorrow");
2248}
2249function theDayBefore(reference, numDay) {
2250  return theDayAfter(reference, -numDay);
2251}
2252function theDayAfter(reference, nDays) {
2253  const targetDate = reference.getDateWithAdjustedTimezone();
2254  const component = new ParsingComponents(reference, {});
2255  const newDate = new Date(targetDate.getTime());
2256  newDate.setDate(newDate.getDate() + nDays);
2257  assignSimilarDate(component, newDate);
2258  implySimilarTime(component, newDate);
2259  component.delete("meridiem");
2260  return component;
2261}
2262function tonight(reference, implyHour = 22) {
2263  const targetDate = reference.getDateWithAdjustedTimezone();
2264  const component = new ParsingComponents(reference, {});
2265  assignSimilarDate(component, targetDate);
2266  component.imply("hour", implyHour);
2267  component.imply("meridiem", Meridiem.PM);
2268  component.addTag("casualReference/tonight");
2269  return component;
2270}
2271function evening(reference, implyHour = 20) {
2272  const component = new ParsingComponents(reference, {});
2273  component.imply("meridiem", Meridiem.PM);
2274  component.imply("hour", implyHour);
2275  component.addTag("casualReference/evening");
2276  return component;
2277}
2278function midnight(reference) {
2279  const component = new ParsingComponents(reference, {});
2280  if (reference.getDateWithAdjustedTimezone().getHours() > 2) {
2281    component.addDurationAsImplied({ day: 1 });
2282  }
2283  component.assign("hour", 0);
2284  component.imply("minute", 0);
2285  component.imply("second", 0);
2286  component.imply("millisecond", 0);
2287  component.addTag("casualReference/midnight");
2288  return component;
2289}
2290function morning(reference, implyHour = 6) {
2291  const component = new ParsingComponents(reference, {});
2292  component.imply("meridiem", Meridiem.AM);
2293  component.imply("hour", implyHour);
2294  component.imply("minute", 0);
2295  component.imply("second", 0);
2296  component.imply("millisecond", 0);
2297  component.addTag("casualReference/morning");
2298  return component;
2299}
2300function afternoon(reference, implyHour = 15) {
2301  const component = new ParsingComponents(reference, {});
2302  component.imply("meridiem", Meridiem.PM);
2303  component.imply("hour", implyHour);
2304  component.imply("minute", 0);
2305  component.imply("second", 0);
2306  component.imply("millisecond", 0);
2307  component.addTag("casualReference/afternoon");
2308  return component;
2309}
2310function noon(reference) {
2311  const component = new ParsingComponents(reference, {});
2312  component.imply("meridiem", Meridiem.AM);
2313  component.assign("hour", 12);
2314  component.imply("minute", 0);
2315  component.imply("second", 0);
2316  component.imply("millisecond", 0);
2317  component.addTag("casualReference/noon");
2318  return component;
2319}
2320
2321// node_modules/chrono-node/dist/esm/locales/en/parsers/ENCasualDateParser.js
2322var PATTERN9 = /(now|today|tonight|tomorrow|overmorrow|tmr|tmrw|yesterday|last\s*night)(?=\W|$)/i;
2323
2324class ENCasualDateParser extends AbstractParserWithWordBoundaryChecking {
2325  innerPattern(context) {
2326    return PATTERN9;
2327  }
2328  innerExtract(context, match) {
2329    let targetDate = context.refDate;
2330    const lowerText = match[0].toLowerCase();
2331    let component = context.createParsingComponents();
2332    switch (lowerText) {
2333      case "now":
2334        component = now(context.reference);
2335        break;
2336      case "today":
2337        component = today(context.reference);
2338        break;
2339      case "yesterday":
2340        component = yesterday(context.reference);
2341        break;
2342      case "tomorrow":
2343      case "tmr":
2344      case "tmrw":
2345        component = tomorrow(context.reference);
2346        break;
2347      case "tonight":
2348        component = tonight(context.reference);
2349        break;
2350      case "overmorrow":
2351        component = theDayAfter(context.reference, 2);
2352        break;
2353      default:
2354        if (lowerText.match(/last\s*night/)) {
2355          if (targetDate.getHours() > 6) {
2356            const previousDay = new Date(targetDate.getTime());
2357            previousDay.setDate(previousDay.getDate() - 1);
2358            targetDate = previousDay;
2359          }
2360          assignSimilarDate(component, targetDate);
2361          component.imply("hour", 0);
2362        }
2363        break;
2364    }
2365    component.addTag("parser/ENCasualDateParser");
2366    return component;
2367  }
2368}
2369
2370// node_modules/chrono-node/dist/esm/locales/en/parsers/ENCasualTimeParser.js
2371var PATTERN10 = /(?:this)?\s{0,3}(morning|afternoon|evening|night|midnight|midday|noon)(?=\W|$)/i;
2372
2373class ENCasualTimeParser extends AbstractParserWithWordBoundaryChecking {
2374  innerPattern() {
2375    return PATTERN10;
2376  }
2377  innerExtract(context, match) {
2378    let component = null;
2379    switch (match[1].toLowerCase()) {
2380      case "afternoon":
2381        component = afternoon(context.reference);
2382        break;
2383      case "evening":
2384      case "night":
2385        component = evening(context.reference);
2386        break;
2387      case "midnight":
2388        component = midnight(context.reference);
2389        break;
2390      case "morning":
2391        component = morning(context.reference);
2392        break;
2393      case "noon":
2394      case "midday":
2395        component = noon(context.reference);
2396        break;
2397    }
2398    if (component) {
2399      component.addTag("parser/ENCasualTimeParser");
2400    }
2401    return component;
2402  }
2403}
2404
2405// node_modules/chrono-node/dist/esm/locales/en/parsers/ENWeekdayParser.js
2406var PATTERN11 = new RegExp("(?:(?:\\,|\\(|\\()\\s*)?" + "(?:on\\s*?)?" + "(?:(this|last|past|next)\\s*)?" + `(${matchAnyPattern(WEEKDAY_DICTIONARY)}|weekend|weekday)` + "(?:\\s*(?:\\,|\\)|\\)))?" + "(?:\\s*(?:of\\s*)?(this|last|past|next)\\s*week)?" + "(?=\\W|$)", "i");
2407var PREFIX_GROUP2 = 1;
2408var WEEKDAY_GROUP = 2;
2409var POSTFIX_GROUP = 3;
2410
2411class ENWeekdayParser extends AbstractParserWithWordBoundaryChecking {
2412  innerPattern() {
2413    return PATTERN11;
2414  }
2415  innerExtract(context, match) {
2416    const prefix = match[PREFIX_GROUP2];
2417    const postfix = match[POSTFIX_GROUP];
2418    let modifierWord = prefix || postfix;
2419    modifierWord = modifierWord || "";
2420    modifierWord = modifierWord.toLowerCase();
2421    let modifier = null;
2422    if (modifierWord == "last" || modifierWord == "past") {
2423      modifier = "last";
2424    } else if (modifierWord == "next") {
2425      modifier = "next";
2426    } else if (modifierWord == "this") {
2427      modifier = "this";
2428    }
2429    const weekday_word = match[WEEKDAY_GROUP].toLowerCase();
2430    let weekday;
2431    if (WEEKDAY_DICTIONARY[weekday_word] !== undefined) {
2432      weekday = WEEKDAY_DICTIONARY[weekday_word];
2433    } else if (weekday_word == "weekend") {
2434      weekday = modifier == "last" ? Weekday.SUNDAY : Weekday.SATURDAY;
2435    } else if (weekday_word == "weekday") {
2436      const refWeekday = context.reference.getDateWithAdjustedTimezone().getDay();
2437      if (refWeekday == Weekday.SUNDAY || refWeekday == Weekday.SATURDAY) {
2438        weekday = modifier == "last" ? Weekday.FRIDAY : Weekday.MONDAY;
2439      } else {
2440        weekday = refWeekday - 1;
2441        weekday = modifier == "last" ? weekday - 1 : weekday + 1;
2442        weekday = weekday % 5 + 1;
2443      }
2444    } else {
2445      return null;
2446    }
2447    return createParsingComponentsAtWeekday(context.reference, weekday, modifier);
2448  }
2449}
2450
2451// node_modules/chrono-node/dist/esm/locales/en/parsers/ENRelativeDateFormatParser.js
2452var PATTERN12 = new RegExp(`(this|last|past|next|after\\s*this)\\s*(${matchAnyPattern(TIME_UNIT_DICTIONARY)})(?=\\s*)` + "(?=\\W|$)", "i");
2453var MODIFIER_WORD_GROUP = 1;
2454var RELATIVE_WORD_GROUP = 2;
2455
2456class ENRelativeDateFormatParser extends AbstractParserWithWordBoundaryChecking {
2457  innerPattern() {
2458    return PATTERN12;
2459  }
2460  innerExtract(context, match) {
2461    const modifier = match[MODIFIER_WORD_GROUP].toLowerCase();
2462    const unitWord = match[RELATIVE_WORD_GROUP].toLowerCase();
2463    const timeunit = TIME_UNIT_DICTIONARY[unitWord];
2464    if (modifier == "next" || modifier.startsWith("after")) {
2465      const timeUnits = {};
2466      timeUnits[timeunit] = 1;
2467      return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
2468    }
2469    if (modifier == "last" || modifier == "past") {
2470      const timeUnits = {};
2471      timeUnits[timeunit] = -1;
2472      return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
2473    }
2474    const components = context.createParsingComponents();
2475    let date = new Date(context.reference.instant.getTime());
2476    if (unitWord.match(/week/i)) {
2477      date.setDate(date.getDate() - date.getDay());
2478      components.imply("day", date.getDate());
2479      components.imply("month", date.getMonth() + 1);
2480      components.imply("year", date.getFullYear());
2481    } else if (unitWord.match(/month/i)) {
2482      date.setDate(1);
2483      components.imply("day", date.getDate());
2484      components.assign("year", date.getFullYear());
2485      components.assign("month", date.getMonth() + 1);
2486    } else if (unitWord.match(/year/i)) {
2487      date.setDate(1);
2488      date.setMonth(0);
2489      components.imply("day", date.getDate());
2490      components.imply("month", date.getMonth() + 1);
2491      components.assign("year", date.getFullYear());
2492    }
2493    return components;
2494  }
2495}
2496
2497// node_modules/chrono-node/dist/esm/common/parsers/SlashDateFormatParser.js
2498var PATTERN13 = 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");
2499var OPENING_GROUP = 1;
2500var ENDING_GROUP = 5;
2501var FIRST_NUMBERS_GROUP = 2;
2502var SECOND_NUMBERS_GROUP = 3;
2503var YEAR_GROUP5 = 4;
2504
2505class SlashDateFormatParser {
2506  groupNumberMonth;
2507  groupNumberDay;
2508  constructor(littleEndian) {
2509    this.groupNumberMonth = littleEndian ? SECOND_NUMBERS_GROUP : FIRST_NUMBERS_GROUP;
2510    this.groupNumberDay = littleEndian ? FIRST_NUMBERS_GROUP : SECOND_NUMBERS_GROUP;
2511  }
2512  pattern() {
2513    return PATTERN13;
2514  }
2515  extract(context, match) {
2516    const index = match.index + match[OPENING_GROUP].length;
2517    const indexEnd = match.index + match[0].length - match[ENDING_GROUP].length;
2518    if (index > 0) {
2519      const textBefore = context.text.substring(0, index);
2520      if (textBefore.match("\\d/?$")) {
2521        return;
2522      }
2523    }
2524    if (indexEnd < context.text.length) {
2525      const textAfter = context.text.substring(indexEnd);
2526      if (textAfter.match("^/?\\d")) {
2527        return;
2528      }
2529    }
2530    const text = context.text.substring(index, indexEnd);
2531    if (text.match(/^\d\.\d$/) || text.match(/^\d\.\d{1,2}\.\d{1,2}\s*$/)) {
2532      return;
2533    }
2534    if (!match[YEAR_GROUP5] && text.indexOf("/") < 0) {
2535      return;
2536    }
2537    const result = context.createParsingResult(index, text);
2538    let month = parseInt(match[this.groupNumberMonth]);
2539    let day = parseInt(match[this.groupNumberDay]);
2540    if (month < 1 || month > 12) {
2541      if (month > 12) {
2542        if (day >= 1 && day <= 12 && month <= 31) {
2543          [day, month] = [month, day];
2544        } else {
2545          return null;
2546        }
2547      }
2548    }
2549    if (day < 1 || day > 31) {
2550      return null;
2551    }
2552    result.start.assign("day", day);
2553    result.start.assign("month", month);
2554    if (match[YEAR_GROUP5]) {
2555      const rawYearNumber = parseInt(match[YEAR_GROUP5]);
2556      const year = findMostLikelyADYear(rawYearNumber);
2557      result.start.assign("year", year);
2558    } else {
2559      const year = findYearClosestToRef(context.refDate, day, month);
2560      result.start.imply("year", year);
2561    }
2562    return result.addTag("parser/SlashDateFormatParser");
2563  }
2564}
2565
2566// node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js
2567var PATTERN14 = new RegExp(`(this|last|past|next|after|\\+|-)\\s*(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
2568var PATTERN_NO_ABBR = new RegExp(`(this|last|past|next|after|\\+|-)\\s*(${TIME_UNITS_NO_ABBR_PATTERN})(?=\\W|$)`, "i");
2569
2570class ENTimeUnitCasualRelativeFormatParser extends AbstractParserWithWordBoundaryChecking {
2571  allowAbbreviations;
2572  constructor(allowAbbreviations = true) {
2573    super();
2574    this.allowAbbreviations = allowAbbreviations;
2575  }
2576  innerPattern() {
2577    return this.allowAbbreviations ? PATTERN14 : PATTERN_NO_ABBR;
2578  }
2579  innerExtract(context, match) {
2580    const prefix = match[1].toLowerCase();
2581    let duration = parseDuration(match[2]);
2582    if (!duration) {
2583      return null;
2584    }
2585    switch (prefix) {
2586      case "last":
2587      case "past":
2588      case "-":
2589        duration = reverseDuration(duration);
2590        break;
2591    }
2592    return ParsingComponents.createRelativeFromReference(context.reference, duration);
2593  }
2594}
2595
2596// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js
2597function IsPositiveFollowingReference(result) {
2598  return result.text.match(/^[+-]/i) != null;
2599}
2600function IsNegativeFollowingReference(result) {
2601  return result.text.match(/^-/i) != null;
2602}
2603
2604class ENMergeRelativeAfterDateRefiner extends MergingRefiner {
2605  shouldMergeResults(textBetween, currentResult, nextResult) {
2606    if (!textBetween.match(/^\s*$/i)) {
2607      return false;
2608    }
2609    return IsPositiveFollowingReference(nextResult) || IsNegativeFollowingReference(nextResult);
2610  }
2611  mergeResults(textBetween, currentResult, nextResult, context) {
2612    let timeUnits = parseDuration(nextResult.text);
2613    if (IsNegativeFollowingReference(nextResult)) {
2614      timeUnits = reverseDuration(timeUnits);
2615    }
2616    const components = ParsingComponents.createRelativeFromReference(ReferenceWithTimezone.fromDate(currentResult.start.date()), timeUnits);
2617    return new ParsingResult(currentResult.reference, currentResult.index, `${currentResult.text}${textBetween}${nextResult.text}`, components);
2618  }
2619}
2620
2621// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeRelativeFollowByDateRefiner.js
2622function hasImpliedEarlierReferenceDate(result) {
2623  return result.text.match(/\s+(before|from)$/i) != null;
2624}
2625function hasImpliedLaterReferenceDate(result) {
2626  return result.text.match(/\s+(after|since)$/i) != null;
2627}
2628
2629class ENMergeRelativeFollowByDateRefiner extends MergingRefiner {
2630  patternBetween() {
2631    return /^\s*$/i;
2632  }
2633  shouldMergeResults(textBetween, currentResult, nextResult) {
2634    if (!textBetween.match(this.patternBetween())) {
2635      return false;
2636    }
2637    if (!hasImpliedEarlierReferenceDate(currentResult) && !hasImpliedLaterReferenceDate(currentResult)) {
2638      return false;
2639    }
2640    return !!nextResult.start.get("day") && !!nextResult.start.get("month") && !!nextResult.start.get("year");
2641  }
2642  mergeResults(textBetween, currentResult, nextResult) {
2643    let duration = parseDuration(currentResult.text);
2644    if (hasImpliedEarlierReferenceDate(currentResult)) {
2645      duration = reverseDuration(duration);
2646    }
2647    const components = ParsingComponents.createRelativeFromReference(ReferenceWithTimezone.fromDate(nextResult.start.date()), duration);
2648    return new ParsingResult(nextResult.reference, currentResult.index, `${currentResult.text}${textBetween}${nextResult.text}`, components);
2649  }
2650}
2651
2652// node_modules/chrono-node/dist/esm/locales/en/refiners/ENExtractYearSuffixRefiner.js
2653var YEAR_SUFFIX_PATTERN = new RegExp(`^\\s*(${YEAR_PATTERN})`, "i");
2654var YEAR_GROUP6 = 1;
2655
2656class ENExtractYearSuffixRefiner {
2657  refine(context, results) {
2658    results.forEach(function(result) {
2659      if (!result.start.isDateWithUnknownYear()) {
2660        return;
2661      }
2662      const suffix = context.text.substring(result.index + result.text.length);
2663      const match = YEAR_SUFFIX_PATTERN.exec(suffix);
2664      if (!match) {
2665        return;
2666      }
2667      if (match[0].trim().length <= 3) {
2668        return;
2669      }
2670      context.debug(() => {
2671        console.log(`Extracting year: '${match[0]}' into : ${result}`);
2672      });
2673      const year = parseYear(match[YEAR_GROUP6]);
2674      if (result.end != null) {
2675        result.end.assign("year", year);
2676      }
2677      result.start.assign("year", year);
2678      result.text += match[0];
2679    });
2680    return results;
2681  }
2682}
2683
2684// node_modules/chrono-node/dist/esm/locales/en/refiners/ENUnlikelyFormatFilter.js
2685class ENUnlikelyFormatFilter extends Filter {
2686  constructor() {
2687    super();
2688  }
2689  isValid(context, result) {
2690    const text = result.text.trim();
2691    if (text === context.text.trim()) {
2692      return true;
2693    }
2694    if (text.toLowerCase() === "may") {
2695      const textBefore = context.text.substring(0, result.index).trim();
2696      if (!textBefore.match(/\b(in)$/i)) {
2697        context.debug(() => {
2698          console.log(`Removing unlikely result: ${result}`);
2699        });
2700        return false;
2701      }
2702    }
2703    if (text.toLowerCase().endsWith("the second")) {
2704      const textAfter = context.text.substring(result.index + result.text.length).trim();
2705      if (textAfter.length > 0) {
2706        context.debug(() => {
2707          console.log(`Removing unlikely result: ${result}`);
2708        });
2709      }
2710      return false;
2711    }
2712    return true;
2713  }
2714}
2715
2716// node_modules/chrono-node/dist/esm/locales/en/configuration.js
2717class ENDefaultConfiguration {
2718  createCasualConfiguration(littleEndian = false) {
2719    const option = this.createConfiguration(false, littleEndian);
2720    option.parsers.push(new ENCasualDateParser);
2721    option.parsers.push(new ENCasualTimeParser);
2722    option.parsers.push(new ENMonthNameParser);
2723    option.parsers.push(new ENRelativeDateFormatParser);
2724    option.parsers.push(new ENTimeUnitCasualRelativeFormatParser);
2725    option.refiners.push(new ENUnlikelyFormatFilter);
2726    return option;
2727  }
2728  createConfiguration(strictMode = true, littleEndian = false) {
2729    const options = includeCommonConfiguration({
2730      parsers: [
2731        new SlashDateFormatParser(littleEndian),
2732        new ENTimeUnitWithinFormatParser(strictMode),
2733        new ENMonthNameLittleEndianParser,
2734        new ENMonthNameMiddleEndianParser(littleEndian),
2735        new ENWeekdayParser,
2736        new ENSlashMonthFormatParser,
2737        new ENTimeExpressionParser(strictMode),
2738        new ENTimeUnitAgoFormatParser(strictMode),
2739        new ENTimeUnitLaterFormatParser(strictMode)
2740      ],
2741      refiners: [new ENMergeDateTimeRefiner]
2742    }, strictMode);
2743    options.parsers.unshift(new ENYearMonthDayParser(strictMode));
2744    options.refiners.unshift(new ENMergeRelativeFollowByDateRefiner);
2745    options.refiners.unshift(new ENMergeRelativeAfterDateRefiner);
2746    options.refiners.unshift(new OverlapRemovalRefiner);
2747    options.refiners.push(new ENMergeDateTimeRefiner);
2748    options.refiners.push(new ENExtractYearSuffixRefiner);
2749    options.refiners.push(new ENMergeDateRangeRefiner);
2750    return options;
2751  }
2752}
2753
2754// node_modules/chrono-node/dist/esm/chrono.js
2755class Chrono {
2756  parsers;
2757  refiners;
2758  defaultConfig = new ENDefaultConfiguration;
2759  constructor(configuration) {
2760    configuration = configuration || this.defaultConfig.createCasualConfiguration();
2761    this.parsers = [...configuration.parsers];
2762    this.refiners = [...configuration.refiners];
2763  }
2764  clone() {
2765    return new Chrono({
2766      parsers: [...this.parsers],
2767      refiners: [...this.refiners]
2768    });
2769  }
2770  parseDate(text, referenceDate, option) {
2771    const results = this.parse(text, referenceDate, option);
2772    return results.length > 0 ? results[0].start.date() : null;
2773  }
2774  parse(text, referenceDate, option) {
2775    const context = new ParsingContext(text, referenceDate, option);
2776    let results = [];
2777    this.parsers.forEach((parser) => {
2778      const parsedResults = Chrono.executeParser(context, parser);
2779      results = results.concat(parsedResults);
2780    });
2781    results.sort((a, b) => {
2782      return a.index - b.index;
2783    });
2784    this.refiners.forEach(function(refiner) {
2785      results = refiner.refine(context, results);
2786    });
2787    return results;
2788  }
2789  static executeParser(context, parser) {
2790    const results = [];
2791    const pattern = parser.pattern(context);
2792    const originalText = context.text;
2793    let remainingText = context.text;
2794    let match = pattern.exec(remainingText);
2795    while (match) {
2796      const index = match.index + originalText.length - remainingText.length;
2797      match.index = index;
2798      const result = parser.extract(context, match);
2799      if (!result) {
2800        remainingText = originalText.substring(match.index + 1);
2801        match = pattern.exec(remainingText);
2802        continue;
2803      }
2804      let parsedResult = null;
2805      if (result instanceof ParsingResult) {
2806        parsedResult = result;
2807      } else if (result instanceof ParsingComponents) {
2808        parsedResult = context.createParsingResult(match.index, match[0]);
2809        parsedResult.start = result;
2810      } else {
2811        parsedResult = context.createParsingResult(match.index, match[0], result);
2812      }
2813      const parsedIndex = parsedResult.index;
2814      const parsedText = parsedResult.text;
2815      context.debug(() => console.log(`${parser.constructor.name} extracted (at index=${parsedIndex}) '${parsedText}'`));
2816      results.push(parsedResult);
2817      remainingText = originalText.substring(parsedIndex + parsedText.length);
2818      match = pattern.exec(remainingText);
2819    }
2820    return results;
2821  }
2822}
2823
2824class ParsingContext {
2825  text;
2826  option;
2827  reference;
2828  refDate;
2829  constructor(text, refDate, option) {
2830    this.text = text;
2831    this.option = option ?? {};
2832    this.reference = ReferenceWithTimezone.fromInput(refDate, this.option.timezones);
2833    this.refDate = this.reference.instant;
2834  }
2835  createParsingComponents(components) {
2836    if (components instanceof ParsingComponents) {
2837      return components;
2838    }
2839    return new ParsingComponents(this.reference, components);
2840  }
2841  createParsingResult(index, textOrEndIndex, startComponents, endComponents) {
2842    const text = typeof textOrEndIndex === "string" ? textOrEndIndex : this.text.substring(index, textOrEndIndex);
2843    const start = startComponents ? this.createParsingComponents(startComponents) : null;
2844    const end = endComponents ? this.createParsingComponents(endComponents) : null;
2845    return new ParsingResult(this.reference, index, text, start, end);
2846  }
2847  debug(block) {
2848    if (this.option.debug) {
2849      if (this.option.debug instanceof Function) {
2850        this.option.debug(block);
2851      } else {
2852        const handler = this.option.debug;
2853        handler.debug(block);
2854      }
2855    }
2856  }
2857}
2858
2859// node_modules/chrono-node/dist/esm/locales/en/index.js
2860var configuration = new ENDefaultConfiguration;
2861var casual = new Chrono(configuration.createCasualConfiguration(false));
2862var strict = new Chrono(configuration.createConfiguration(true, false));
2863var GB = new Chrono(configuration.createCasualConfiguration(true));
2864
2865// node_modules/chrono-node/dist/esm/index.js
2866var casual2 = casual;
2867function parseDate(text, ref, option) {
2868  return casual2.parseDate(text, ref, option);
2869}
2870
2871// index.ts
2872import {
2873  Container,
2874  SelectList,
2875  Text,
2876  fuzzyFilter
2877} from "@earendil-works/pi-tui";
2878var DEFAULT_ORG_FILE = join(homedir(), "desktop/org/todos.org");
2879var INBOX_FILE = join(homedir(), "desktop/org/inbox.org");
2880var DEFAULT_SECTION = "Inbox";
2881function execEmacs(elisp) {
2882  try {
2883    const escaped = elisp.replace(/'/g, "'\\''");
2884    const result = execSync(`emacsclient --eval '${escaped}'`, {
2885      encoding: "utf-8",
2886      timeout: 1e4,
2887      stdio: ["pipe", "pipe", "pipe"]
2888    });
2889    let jsonStr = result.trim();
2890    if (jsonStr.startsWith('"') && jsonStr.endsWith('"')) {
2891      jsonStr = jsonStr.slice(1, -1);
2892    }
2893    jsonStr = jsonStr.replace(/\\"/g, '"');
2894    jsonStr = jsonStr.replace(/\\\\/g, "\\");
2895    return JSON.parse(jsonStr);
2896  } catch (error) {
2897    if (error.message?.includes("emacsclient") || error.status === 1) {
2898      return {
2899        success: false,
2900        error: "Emacs daemon not running. Start with: emacs --daemon"
2901      };
2902    }
2903    return {
2904      success: false,
2905      error: error.message || String(error)
2906    };
2907  }
2908}
2909function stripOrgLinks(text) {
2910  text = text.replace(/\[\[([^\]]*)\]\[([^\]]*)\]\]/g, "$2");
2911  text = text.replace(/\[\[([^\]]*)\]\]/g, "$1");
2912  return text;
2913}
2914function formatTodo(todo) {
2915  const parts = [];
2916  const state = todo.todo || "TODO";
2917  parts.push(`[${state}]`);
2918  if (todo.priority) {
2919    parts.push(`[#${todo.priority}]`);
2920  }
2921  parts.push(stripOrgLinks(todo.heading));
2922  if (todo.tags && todo.tags.length > 0) {
2923    parts.push(`:${todo.tags.join(":")}:`);
2924  }
2925  const dates = [];
2926  if (todo.scheduled) {
2927    dates.push(`SCHEDULED: ${todo.scheduled}`);
2928  }
2929  if (todo.deadline) {
2930    dates.push(`DEADLINE: ${todo.deadline}`);
2931  }
2932  if (dates.length > 0) {
2933    parts.push(`(${dates.join(", ")})`);
2934  }
2935  return parts.join(" ");
2936}
2937function formatTodoMarkdown(todo) {
2938  const parts = [];
2939  const state = todo.todo || "TODO";
2940  parts.push(`**[${state}]**`);
2941  if (todo.priority) {
2942    parts.push(`\`#${todo.priority}\``);
2943  }
2944  parts.push(stripOrgLinks(todo.heading));
2945  if (todo.tags && todo.tags.length > 0) {
2946    const tagStr = todo.tags.map((t) => `\`${t}\``).join(" ");
2947    parts.push(tagStr);
2948  }
2949  const dates = [];
2950  if (todo.scheduled) {
2951    dates.push(`\uD83D\uDCC5 ${todo.scheduled}`);
2952  }
2953  if (todo.deadline) {
2954    dates.push(`${todo.deadline}`);
2955  }
2956  let result = parts.join(" ");
2957  if (dates.length > 0) {
2958    result += ` *(${dates.join(", ")})*`;
2959  }
2960  return result;
2961}
2962function parseNaturalDate(text) {
2963  const result = parseDate(text);
2964  if (!result)
2965    return null;
2966  const year = result.getFullYear();
2967  const month = String(result.getMonth() + 1).padStart(2, "0");
2968  const day = String(result.getDate()).padStart(2, "0");
2969  return `${year}-${month}-${day}`;
2970}
2971function parseCommandArgs(args) {
2972  let remaining = args;
2973  let section;
2974  let scheduled;
2975  let deadline;
2976  let priority;
2977  let state;
2978  const sectionMatch = remaining.match(/@(\w+)/);
2979  if (sectionMatch) {
2980    section = sectionMatch[1];
2981    remaining = remaining.replace(/@\w+/, "").trim();
2982  }
2983  const scheduledMatch = remaining.match(/scheduled:([^\s]+(?:\s+[^\s@:]+)*?)(?=\s+(?:deadline:|priority:|state:|@|$)|$)/i);
2984  if (scheduledMatch) {
2985    const dateStr = scheduledMatch[1].trim();
2986    scheduled = parseNaturalDate(dateStr) || dateStr;
2987    remaining = remaining.replace(scheduledMatch[0], "").trim();
2988  }
2989  const deadlineMatch = remaining.match(/deadline:([^\s]+(?:\s+[^\s@:]+)*?)(?=\s+(?:scheduled:|priority:|state:|@|$)|$)/i);
2990  if (deadlineMatch) {
2991    const dateStr = deadlineMatch[1].trim();
2992    deadline = parseNaturalDate(dateStr) || dateStr;
2993    remaining = remaining.replace(deadlineMatch[0], "").trim();
2994  }
2995  const priorityMatch = remaining.match(/priority:(\d)/i);
2996  if (priorityMatch) {
2997    priority = parseInt(priorityMatch[1], 10);
2998    remaining = remaining.replace(priorityMatch[0], "").trim();
2999  }
3000  const stateMatch = remaining.match(/state:(TODO|NEXT|STRT|WAIT|DONE|CANX)/i);
3001  if (stateMatch) {
3002    state = stateMatch[1].toUpperCase();
3003    remaining = remaining.replace(stateMatch[0], "").trim();
3004  }
3005  return {
3006    title: remaining.trim(),
3007    section,
3008    scheduled,
3009    deadline,
3010    priority,
3011    state
3012  };
3013}
3014function org_todos_default(pi) {
3015  const customTypes = [
3016    "org-todos",
3017    "org-todos-search",
3018    "org-todos-add",
3019    "org-todos-done",
3020    "org-todos-next",
3021    "org-todos-upcoming",
3022    "org-todos-update",
3023    "org-todos-note"
3024  ];
3025  for (const customType of customTypes) {
3026    pi.registerMessageRenderer(customType, (message, options, theme) => {
3027      let text = message.content;
3028      text = text.replace(/\[TODO\]/g, theme.bold(theme.fg("mdHeading", "[TODO]")));
3029      text = text.replace(/\[NEXT\]/g, theme.bold(theme.fg("accent", "[NEXT]")));
3030      text = text.replace(/\[STRT\]/g, theme.bold(theme.fg("mdLink", "[STRT]")));
3031      text = text.replace(/\[WAIT\]/g, theme.bold(theme.fg("muted", "[WAIT]")));
3032      text = text.replace(/\[DONE\]/g, theme.bold(theme.fg("success", "[DONE]")));
3033      text = text.replace(/\[CANX\]/g, theme.bold(theme.fg("error", "[CANX]")));
3034      const container = new Container;
3035      container.addChild(new DynamicBorder((s) => theme.fg("borderMuted", s)));
3036      container.addChild(new Text(text, 1, 1));
3037      container.addChild(new DynamicBorder((s) => theme.fg("borderMuted", s)));
3038      return container;
3039    });
3040  }
3041  pi.registerTool({
3042    name: "org_todo",
3043    label: "Org TODO",
3044    promptSnippet: "Manage org-mode TODOs. Actions: list, scheduled, upcoming, overdue, search, get, done, state, schedule, deadline, priority, add, append, inbox-list, inbox-count, inbox-add, refile-targets, refile",
3045    promptGuidelines: [
3046      "NEVER edit .org files directly — always use the org_todo tool for all TODO operations",
3047      "For scheduling, use YYYY-MM-DD date format (natural language dates are NOT supported by this tool)",
3048      "Use inbox-add for quick capture, then refile to the appropriate section later"
3049    ],
3050    description: `Manage org-mode TODOs. Actions:
3051- list: List active TODOs (TODO, NEXT, STRT)
3052- scheduled: Get today's scheduled items
3053- upcoming: Get tasks in next N days (default 7)
3054- overdue: Get overdue tasks
3055- search: Search TODOs by query
3056- get: Get full content of a TODO
3057- done: Mark TODO as DONE
3058- state: Change TODO state (TODO, NEXT, STRT, WAIT, DONE, CANX)
3059- schedule: Set scheduled date
3060- deadline: Set deadline date
3061- priority: Set priority (1-5)
3062- add: Create new TODO
3063- append: Append content to TODO
3064- inbox-list: List all inbox items
3065- inbox-count: Get count of inbox items
3066- inbox-add: Add item to inbox
3067- refile-targets: Get available refile target sections
3068- refile: Refile item from inbox to a section`,
3069    parameters: {
3070      type: "object",
3071      properties: {
3072        action: {
3073          type: "string",
3074          enum: [
3075            "list",
3076            "scheduled",
3077            "upcoming",
3078            "overdue",
3079            "search",
3080            "get",
3081            "done",
3082            "state",
3083            "schedule",
3084            "deadline",
3085            "priority",
3086            "add",
3087            "append",
3088            "sections",
3089            "statistics",
3090            "archive",
3091            "inbox-list",
3092            "inbox-count",
3093            "inbox-add",
3094            "refile-targets",
3095            "refile"
3096          ],
3097          description: "Action to perform"
3098        },
3099        heading: {
3100          type: "string",
3101          description: "TODO heading (for get, done, state, schedule, etc.)"
3102        },
3103        query: {
3104          type: "string",
3105          description: "Search query (for search action)"
3106        },
3107        section: {
3108          type: "string",
3109          description: "Section name (for add action or by-section filter)"
3110        },
3111        state: {
3112          type: "string",
3113          enum: ["TODO", "NEXT", "STRT", "WAIT", "DONE", "CANX"],
3114          description: "TODO state (for state action)"
3115        },
3116        date: {
3117          type: "string",
3118          description: "Date in YYYY-MM-DD format (for schedule/deadline)"
3119        },
3120        days: {
3121          type: "number",
3122          description: "Number of days (for upcoming action, default 7)"
3123        },
3124        priority: {
3125          type: "number",
3126          description: "Priority 1-5 (1=highest)"
3127        },
3128        content: {
3129          type: "string",
3130          description: "Content to append (org-mode format)"
3131        },
3132        tags: {
3133          type: "array",
3134          items: { type: "string" },
3135          description: "Tags for new TODO"
3136        }
3137      },
3138      required: ["action"]
3139    },
3140    execute: async (toolCallId, params, signal, onUpdate, ctx) => {
3141      const { action, heading, query, section, state, date, days, priority, content, tags } = params;
3142      let elisp;
3143      switch (action) {
3144        case "list":
3145          if (section) {
3146            elisp = `(pi/org-todo-by-section "${section}")`;
3147          } else {
3148            elisp = "(pi/org-todo-list)";
3149          }
3150          break;
3151        case "scheduled":
3152          elisp = `(pi/org-todo-scheduled nil "${date || "today"}")`;
3153          break;
3154        case "upcoming":
3155          elisp = `(pi/org-todo-upcoming nil ${days || 7})`;
3156          break;
3157        case "overdue":
3158          elisp = "(pi/org-todo-overdue)";
3159          break;
3160        case "search":
3161          if (!query) {
3162            return {
3163              content: [{ type: "text", text: "Error: query is required for search action" }]
3164            };
3165          }
3166          elisp = `(pi/org-todo-search "${query.replace(/"/g, "\\\"")}")`;
3167          break;
3168        case "get":
3169          if (!heading) {
3170            return {
3171              content: [{ type: "text", text: "Error: heading is required for get action" }]
3172            };
3173          }
3174          elisp = `(pi/org-todo-get "${heading.replace(/"/g, "\\\"")}")`;
3175          break;
3176        case "done":
3177          if (!heading) {
3178            return {
3179              content: [{ type: "text", text: "Error: heading is required for done action" }]
3180            };
3181          }
3182          elisp = `(pi/org-todo-done "${heading.replace(/"/g, "\\\"")}")`;
3183          break;
3184        case "state":
3185          if (!heading || !state) {
3186            return {
3187              content: [{ type: "text", text: "Error: heading and state are required for state action" }]
3188            };
3189          }
3190          elisp = `(pi/org-todo-state "${heading.replace(/"/g, "\\\"")}" "${state}")`;
3191          break;
3192        case "schedule":
3193          if (!heading || !date) {
3194            return {
3195              content: [{ type: "text", text: "Error: heading and date are required for schedule action" }]
3196            };
3197          }
3198          elisp = `(pi/org-todo-schedule "${heading.replace(/"/g, "\\\"")}" "${date}")`;
3199          break;
3200        case "deadline":
3201          if (!heading || !date) {
3202            return {
3203              content: [{ type: "text", text: "Error: heading and date are required for deadline action" }]
3204            };
3205          }
3206          elisp = `(pi/org-todo-deadline "${heading.replace(/"/g, "\\\"")}" "${date}")`;
3207          break;
3208        case "priority":
3209          if (!heading || priority === undefined) {
3210            return {
3211              content: [{ type: "text", text: "Error: heading and priority are required for priority action" }]
3212            };
3213          }
3214          elisp = `(pi/org-todo-priority "${heading.replace(/"/g, "\\\"")}" ${priority})`;
3215          break;
3216        case "add":
3217          if (!heading || !section) {
3218            return {
3219              content: [{ type: "text", text: "Error: heading and section are required for add action" }]
3220            };
3221          }
3222          const schedArg = date ? `"${date}"` : "nil";
3223          const prioArg = priority !== undefined ? priority : "nil";
3224          const tagsArg = tags && tags.length > 0 ? `'(${tags.map((t) => `"${t}"`).join(" ")})` : "nil";
3225          elisp = `(pi/org-todo-add "${heading.replace(/"/g, "\\\"")}" "${section.replace(/"/g, "\\\"")}" nil ${schedArg} ${prioArg} ${tagsArg})`;
3226          if (content) {
3227            const addResult = execEmacs(elisp);
3228            if (!addResult.success) {
3229              return {
3230                content: [{ type: "text", text: `Error: ${addResult.error}` }]
3231              };
3232            }
3233            elisp = `(pi/org-todo-append "${heading.replace(/"/g, "\\\"")}" "${content.replace(/"/g, "\\\"").replace(/\n/g, "\\n")}")`;
3234          }
3235          break;
3236        case "append":
3237          if (!heading || !content) {
3238            return {
3239              content: [{ type: "text", text: "Error: heading and content are required for append action" }]
3240            };
3241          }
3242          elisp = `(pi/org-todo-append "${heading.replace(/"/g, "\\\"")}" "${content.replace(/"/g, "\\\"").replace(/\n/g, "\\n")}")`;
3243          break;
3244        case "sections":
3245          elisp = "(pi/org-todo-sections)";
3246          break;
3247        case "statistics":
3248          elisp = "(pi/org-todo-statistics)";
3249          break;
3250        case "archive":
3251          elisp = "(pi/org-todo-archive-done)";
3252          break;
3253        case "inbox-list":
3254          elisp = `(pi/org-todo-list "${INBOX_FILE}" "TODO,NEXT,STRT,WAIT")`;
3255          break;
3256        case "inbox-count":
3257          elisp = `(pi/org-todo-inbox-all)`;
3258          break;
3259        case "inbox-add":
3260          if (!heading) {
3261            return {
3262              content: [{ type: "text", text: "Error: heading is required for inbox-add action" }]
3263            };
3264          }
3265          const schedInbox = date ? `"${date}"` : "nil";
3266          const prioInbox = priority !== undefined ? priority : "nil";
3267          const tagsInbox = tags && tags.length > 0 ? `'(${tags.map((t) => `"${t}"`).join(" ")})` : "nil";
3268          elisp = `(pi/org-todo-add "${heading.replace(/"/g, "\\\"")}" "Inbox" "${INBOX_FILE}" ${schedInbox} ${prioInbox} ${tagsInbox})`;
3269          break;
3270        case "refile-targets":
3271          elisp = "(pi/org-todo-get-refile-targets)";
3272          break;
3273        case "refile":
3274          if (!heading || !section) {
3275            return {
3276              content: [{ type: "text", text: "Error: heading and section are required for refile action" }]
3277            };
3278          }
3279          elisp = `(pi/org-todo-refile "${heading.replace(/"/g, "\\\"")}" "${section.replace(/"/g, "\\\"")}")`;
3280          break;
3281        default:
3282          return {
3283            content: [{ type: "text", text: `Unknown action: ${action}` }]
3284          };
3285      }
3286      const result = execEmacs(elisp);
3287      if (!result.success) {
3288        return {
3289          content: [{ type: "text", text: `Error: ${result.error}` }]
3290        };
3291      }
3292      let text;
3293      if (action === "refile-targets" && Array.isArray(result.data)) {
3294        if (result.data.length === 0) {
3295          text = "No refile targets found.";
3296        } else {
3297          text = result.data.map((t) => {
3298            const indent = "  ".repeat((t.level || 1) - 1);
3299            return `${indent}- ${t.section} (${t.file?.replace(/.*\//, "")})`;
3300          }).join(`
3301`);
3302        }
3303      } else if (action === "sections" && Array.isArray(result.data)) {
3304        if (result.data.length === 0) {
3305          text = "No sections found.";
3306        } else {
3307          text = result.data.map((s) => `- ${s.section || s}`).join(`
3308`);
3309        }
3310      } else if (Array.isArray(result.data)) {
3311        if (result.data.length === 0) {
3312          text = "No TODOs found.";
3313        } else {
3314          text = result.data.map(formatTodo).join(`
3315`);
3316        }
3317      } else if (typeof result.data === "object") {
3318        text = JSON.stringify(result.data, null, 2);
3319      } else {
3320        text = String(result.data);
3321      }
3322      return {
3323        content: [{ type: "text", text }]
3324      };
3325    }
3326  });
3327  pi.registerCommand("todos", {
3328    description: "Show today's tasks (scheduled + overdue + NEXT). Usage: /todos [section]",
3329    handler: async (args, ctx) => {
3330      const sectionFilter = (args || "").trim() || null;
3331      let sectionHeadings = null;
3332      if (sectionFilter) {
3333        const sectionResult = execEmacs(`(pi/org-todo-by-section "${sectionFilter.replace(/"/g, "\\\"")}")`);
3334        if (!sectionResult.success) {
3335          const sections = execEmacs("(pi/org-todo-sections)");
3336          const sectionList = sections.success && sections.data ? Array.isArray(sections.data) ? sections.data : Object.values(sections.data) : [];
3337          ctx.ui.notify(`Section "${sectionFilter}" not found. Available: ${sectionList.join(", ")}`, "error");
3338          return;
3339        }
3340        sectionHeadings = new Set((sectionResult.data || []).map((t) => t.heading));
3341      }
3342      function filterBySection(todos) {
3343        if (!sectionHeadings)
3344          return todos;
3345        return todos.filter((t) => sectionHeadings.has(t.heading));
3346      }
3347      const scheduled = execEmacs("(pi/org-todo-scheduled)");
3348      const overdue = execEmacs("(pi/org-todo-overdue)");
3349      const next = execEmacs('(pi/org-todo-list nil "NEXT")');
3350      if (!scheduled.success && !overdue.success && !next.success) {
3351        ctx.ui.notify("Failed to fetch TODOs. Is Emacs daemon running?", "error");
3352        return;
3353      }
3354      const filteredOverdue = filterBySection(overdue.success && overdue.data ? overdue.data : []);
3355      const filteredScheduled = filterBySection(scheduled.success && scheduled.data ? scheduled.data : []);
3356      const filteredNext = filterBySection(next.success && next.data ? next.data : []);
3357      const lines = [];
3358      const title = sectionFilter ? `## \uD83D\uDCCB Today's Tasks — ${sectionFilter}` : "## \uD83D\uDCCB Today's Tasks";
3359      lines.push(title);
3360      lines.push("");
3361      if (filteredOverdue.length > 0) {
3362        lines.push(`### ⚠️ Overdue (${filteredOverdue.length})`);
3363        lines.push("");
3364        for (const todo of filteredOverdue) {
3365          lines.push(`- ${formatTodoMarkdown(todo)}`);
3366        }
3367        lines.push("");
3368      }
3369      if (filteredScheduled.length > 0) {
3370        lines.push(`### \uD83D\uDCC5 Scheduled Today (${filteredScheduled.length})`);
3371        lines.push("");
3372        for (const todo of filteredScheduled) {
3373          lines.push(`- ${formatTodoMarkdown(todo)}`);
3374        }
3375        lines.push("");
3376      }
3377      if (filteredNext.length > 0) {
3378        lines.push(`### ➡️ Next Actions (${filteredNext.length})`);
3379        lines.push("");
3380        for (const todo of filteredNext) {
3381          lines.push(`- ${formatTodoMarkdown(todo)}`);
3382        }
3383        lines.push("");
3384      }
3385      const hasContent = filteredOverdue.length > 0 || filteredScheduled.length > 0 || filteredNext.length > 0;
3386      if (!hasContent) {
3387        if (sectionFilter) {
3388          lines.push(`*No tasks for today in "${sectionFilter}".* \uD83C\uDF89`);
3389        } else {
3390          lines.push("*No tasks for today.* \uD83C\uDF89");
3391        }
3392      }
3393      pi.sendMessage({
3394        customType: "org-todos",
3395        content: lines.join(`
3396`),
3397        display: true
3398      });
3399    }
3400  });
3401  pi.registerCommand("todo-search", {
3402    description: "Search TODOs. Usage: /todo-search <query>",
3403    handler: async (args, ctx) => {
3404      const query = (args || "").trim();
3405      if (!query) {
3406        ctx.ui.notify("Usage: /todo-search <query>", "error");
3407        return;
3408      }
3409      const result = execEmacs(`(pi/org-todo-search "${query.replace(/"/g, "\\\"")}" nil t)`);
3410      if (!result.success) {
3411        ctx.ui.notify(`Search failed: ${result.error}`, "error");
3412        return;
3413      }
3414      if (!result.data || result.data.length === 0) {
3415        ctx.ui.notify(`No TODOs found matching "${query}"`, "info");
3416        return;
3417      }
3418      const lines = [];
3419      lines.push(`## \uD83D\uDD0D Search: "${query}"`);
3420      lines.push("");
3421      lines.push(`*${result.data.length} result(s)*`);
3422      lines.push("");
3423      for (const todo of result.data) {
3424        const matchedIn = todo.matched_in === "heading" ? "" : " *(matched in content)*";
3425        lines.push(`- ${formatTodoMarkdown(todo)}${matchedIn}`);
3426      }
3427      pi.sendMessage({
3428        customType: "org-todos-search",
3429        content: lines.join(`
3430`),
3431        display: true
3432      });
3433    }
3434  });
3435  pi.registerCommand("todo-add", {
3436    description: "Add a new TODO. Usage: /todo-add <title> [@Section] [scheduled:date] [deadline:date] [priority:N]",
3437    handler: async (args, ctx) => {
3438      if (!args?.trim()) {
3439        ctx.ui.notify("Usage: /todo-add <title> [@Section] [scheduled:date] [deadline:date]", "error");
3440        return;
3441      }
3442      const parsed = parseCommandArgs(args);
3443      if (!parsed.title) {
3444        ctx.ui.notify("Error: TODO title is required", "error");
3445        return;
3446      }
3447      const section = parsed.section || DEFAULT_SECTION;
3448      const schedArg = parsed.scheduled ? `"${parsed.scheduled}"` : "nil";
3449      const prioArg = parsed.priority !== undefined ? parsed.priority : "nil";
3450      const sectionsResult = execEmacs("(pi/org-todo-sections)");
3451      if (sectionsResult.success) {
3452        const sections = Array.isArray(sectionsResult.data) ? sectionsResult.data : Object.values(sectionsResult.data || {});
3453        if (!sections.includes(section)) {
3454          ctx.ui.notify(`Section "${section}" not found. Available: ${sections.join(", ")}`, "error");
3455          return;
3456        }
3457      }
3458      const elisp = `(pi/org-todo-add "${parsed.title.replace(/"/g, "\\\"")}" "${section}" nil ${schedArg} ${prioArg} nil)`;
3459      const result = execEmacs(elisp);
3460      if (!result.success) {
3461        ctx.ui.notify(`Failed to add TODO: ${result.error}`, "error");
3462        return;
3463      }
3464      if (parsed.deadline) {
3465        execEmacs(`(pi/org-todo-deadline "${parsed.title.replace(/"/g, "\\\"")}" "${parsed.deadline}")`);
3466      }
3467      const lines = [];
3468      lines.push(`## ✅ TODO Added`);
3469      lines.push("");
3470      lines.push(`**${parsed.title}** added to *${section}*`);
3471      if (parsed.scheduled)
3472        lines.push(`- \uD83D\uDCC5 Scheduled: ${parsed.scheduled}`);
3473      if (parsed.deadline)
3474        lines.push(`- ⏰ Deadline: ${parsed.deadline}`);
3475      if (parsed.priority)
3476        lines.push(`- Priority: #${parsed.priority}`);
3477      pi.sendMessage({
3478        customType: "org-todos-add",
3479        content: lines.join(`
3480`),
3481        display: true
3482      });
3483    }
3484  });
3485  async function selectTodo(ctx, title, filterQuery, states) {
3486    const stateFilter = states || "TODO,NEXT,STRT,WAIT";
3487    const listResult = execEmacs(`(pi/org-todo-list nil "${stateFilter}")`);
3488    if (!listResult.success || !listResult.data || listResult.data.length === 0) {
3489      ctx.ui.notify("No active TODOs found.", "info");
3490      return null;
3491    }
3492    const items = listResult.data.map((todo2, i) => ({
3493      value: String(i),
3494      label: stripOrgLinks(formatTodo(todo2)),
3495      description: todo2.scheduled || todo2.deadline || undefined
3496    }));
3497    const filteredItems = filterQuery ? items.filter((item) => {
3498      const searchable = `${item.label} ${item.description || ""}`.toLowerCase();
3499      return filterQuery.toLowerCase().split(/\s+/).every((t) => searchable.includes(t));
3500    }) : items;
3501    if (filteredItems.length === 0) {
3502      ctx.ui.notify(`No TODOs matching "${filterQuery}"`, "info");
3503      return null;
3504    }
3505    const selectedIdx = await showSelectMenu(ctx, title, filteredItems);
3506    if (selectedIdx === null)
3507      return null;
3508    const todo = listResult.data[parseInt(selectedIdx, 10)];
3509    return {
3510      heading: todo.heading,
3511      display: stripOrgLinks(formatTodo(todo))
3512    };
3513  }
3514  pi.registerCommand("todo-done", {
3515    description: "Mark a TODO as done. Usage: /todo-done [filter] (interactive selector)",
3516    handler: async (args, ctx) => {
3517      const filter = (args || "").trim() || undefined;
3518      const selected = await selectTodo(ctx, "Mark as DONE", filter);
3519      if (!selected) {
3520        if (filter)
3521          ctx.ui.notify("Cancelled or no match.", "info");
3522        return;
3523      }
3524      const result = execEmacs(`(pi/org-todo-done "${selected.heading.replace(/"/g, "\\\"")}")`);
3525      if (!result.success) {
3526        ctx.ui.notify(`Failed: ${result.error}`, "error");
3527        return;
3528      }
3529      pi.sendMessage({
3530        customType: "org-todos-done",
3531        content: `## ✅ Done
3532
3533${selected.display}`,
3534        display: true
3535      });
3536      updateTodayStatus(ctx);
3537    }
3538  });
3539  pi.registerCommand("todo-next", {
3540    description: "Mark a TODO as NEXT (prioritized). Usage: /todo-next [filter] (interactive selector)",
3541    handler: async (args, ctx) => {
3542      const filter = (args || "").trim() || undefined;
3543      const selected = await selectTodo(ctx, "Mark as NEXT", filter, "TODO,STRT,WAIT");
3544      if (!selected) {
3545        if (filter)
3546          ctx.ui.notify("Cancelled or no match.", "info");
3547        return;
3548      }
3549      const result = execEmacs(`(pi/org-todo-state "${selected.heading.replace(/"/g, "\\\"")}" "NEXT")`);
3550      if (!result.success) {
3551        ctx.ui.notify(`Failed: ${result.error}`, "error");
3552        return;
3553      }
3554      pi.sendMessage({
3555        customType: "org-todos-next",
3556        content: `## ➡️ Prioritized
3557
3558${selected.display}`,
3559        display: true
3560      });
3561    }
3562  });
3563  pi.registerCommand("todo-upcoming", {
3564    description: "Show upcoming tasks. Usage: /todo-upcoming [days]",
3565    handler: async (args, ctx) => {
3566      const days = parseInt((args || "").trim(), 10) || 7;
3567      const result = execEmacs(`(pi/org-todo-upcoming nil ${days})`);
3568      if (!result.success) {
3569        ctx.ui.notify(`Failed: ${result.error}`, "error");
3570        return;
3571      }
3572      const lines = [];
3573      lines.push(`## \uD83D\uDCC6 Upcoming (next ${days} days)`);
3574      lines.push("");
3575      if (!result.data || result.data.length === 0) {
3576        lines.push("*No upcoming tasks* \uD83C\uDF89");
3577      } else {
3578        for (const todo of result.data) {
3579          lines.push(`- ${formatTodoMarkdown(todo)}`);
3580        }
3581      }
3582      pi.sendMessage({
3583        customType: "org-todos-upcoming",
3584        content: lines.join(`
3585`),
3586        display: true
3587      });
3588    }
3589  });
3590  pi.registerCommand("todo-update", {
3591    description: "Update a TODO. Usage: /todo-update <heading> [scheduled:date] [deadline:date] [priority:N] [state:STATE]",
3592    handler: async (args, ctx) => {
3593      if (!args?.trim()) {
3594        ctx.ui.notify("Usage: /todo-update <heading> [scheduled:date] [deadline:date] [priority:N] [state:STATE]", "error");
3595        return;
3596      }
3597      const parsed = parseCommandArgs(args);
3598      if (!parsed.title) {
3599        ctx.ui.notify("Error: TODO heading is required", "error");
3600        return;
3601      }
3602      const heading = parsed.title;
3603      const updates = [];
3604      if (parsed.scheduled) {
3605        const result = execEmacs(`(pi/org-todo-schedule "${heading.replace(/"/g, "\\\"")}" "${parsed.scheduled}")`);
3606        if (result.success)
3607          updates.push(`\uD83D\uDCC5 Scheduled: ${parsed.scheduled}`);
3608        else
3609          ctx.ui.notify(`Failed to set schedule: ${result.error}`, "warning");
3610      }
3611      if (parsed.deadline) {
3612        const result = execEmacs(`(pi/org-todo-deadline "${heading.replace(/"/g, "\\\"")}" "${parsed.deadline}")`);
3613        if (result.success)
3614          updates.push(`⏰ Deadline: ${parsed.deadline}`);
3615        else
3616          ctx.ui.notify(`Failed to set deadline: ${result.error}`, "warning");
3617      }
3618      if (parsed.priority !== undefined) {
3619        const result = execEmacs(`(pi/org-todo-priority "${heading.replace(/"/g, "\\\"")}" ${parsed.priority})`);
3620        if (result.success)
3621          updates.push(`Priority: #${parsed.priority}`);
3622        else
3623          ctx.ui.notify(`Failed to set priority: ${result.error}`, "warning");
3624      }
3625      if (parsed.state) {
3626        const result = execEmacs(`(pi/org-todo-state "${heading.replace(/"/g, "\\\"")}" "${parsed.state}")`);
3627        if (result.success)
3628          updates.push(`State: ${parsed.state}`);
3629        else
3630          ctx.ui.notify(`Failed to set state: ${result.error}`, "warning");
3631      }
3632      if (updates.length === 0) {
3633        ctx.ui.notify("No updates specified. Use scheduled:, deadline:, priority:, or state:", "warning");
3634        return;
3635      }
3636      const lines = [];
3637      lines.push(`## \uD83D\uDCDD Updated`);
3638      lines.push("");
3639      lines.push(`**${heading}**`);
3640      lines.push("");
3641      for (const update of updates) {
3642        lines.push(`- ${update}`);
3643      }
3644      pi.sendMessage({
3645        customType: "org-todos-update",
3646        content: lines.join(`
3647`),
3648        display: true
3649      });
3650    }
3651  });
3652  pi.registerCommand("todo-note", {
3653    description: "Add a note to a TODO. Usage: /todo-note <heading> <note>",
3654    handler: async (args, ctx) => {
3655      if (!args?.trim()) {
3656        ctx.ui.notify("Usage: /todo-note <heading> <note>", "error");
3657        return;
3658      }
3659      const input = args.trim();
3660      let heading;
3661      let note;
3662      const newlineIdx = input.indexOf(`
3663`);
3664      if (newlineIdx > 0) {
3665        heading = input.slice(0, newlineIdx).trim();
3666        note = input.slice(newlineIdx + 1).trim();
3667      } else {
3668        const colonIdx = input.indexOf(": ");
3669        const dashIdx = input.indexOf(" - ");
3670        if (colonIdx > 0 && colonIdx < 60) {
3671          heading = input.slice(0, colonIdx).trim();
3672          note = input.slice(colonIdx + 2).trim();
3673        } else if (dashIdx > 0 && dashIdx < 60) {
3674          heading = input.slice(0, dashIdx).trim();
3675          note = input.slice(dashIdx + 3).trim();
3676        } else {
3677          ctx.ui.notify("Could not parse heading and note. Use format: /todo-note Heading: your note here", "error");
3678          return;
3679        }
3680      }
3681      if (!heading || !note) {
3682        ctx.ui.notify("Both heading and note are required", "error");
3683        return;
3684      }
3685      const timestamp = new Date().toISOString().slice(0, 16).replace("T", " ");
3686      const orgContent = `
3687[${timestamp}] ${note}`;
3688      const result = execEmacs(`(pi/org-todo-append "${heading.replace(/"/g, "\\\"")}" "${orgContent.replace(/"/g, "\\\"").replace(/\n/g, "\\n")}")`);
3689      if (!result.success) {
3690        ctx.ui.notify(`Failed: ${result.error}`, "error");
3691        return;
3692      }
3693      pi.sendMessage({
3694        customType: "org-todos-note",
3695        content: `## \uD83D\uDCDD Note Added
3696
3697**${heading}**
3698
3699> ${note}`,
3700        display: true
3701      });
3702    }
3703  });
3704  pi.registerCommand("inbox", {
3705    description: "View all inbox items (TODOs and links)",
3706    handler: async (args, ctx) => {
3707      const result = execEmacs(`(pi/org-todo-inbox-all)`);
3708      if (!result.success) {
3709        ctx.ui.notify(`Failed to fetch inbox: ${result.error}`, "error");
3710        return;
3711      }
3712      const todos = result.data?.filter((item) => item.todo) || [];
3713      const links = result.data?.filter((item) => !item.todo) || [];
3714      const lines = [];
3715      lines.push("## \uD83D\uDCE5 Inbox");
3716      lines.push("");
3717      if (!result.data || result.data.length === 0) {
3718        lines.push("*Inbox is empty* ✨");
3719      } else {
3720        lines.push(`*${result.data.length} item(s)* (${todos.length} tasks, ${links.length} links/notes)`);
3721        lines.push("");
3722        if (todos.length > 0) {
3723          lines.push("### ✅ Tasks");
3724          lines.push("");
3725          for (const todo of todos) {
3726            lines.push(`- ${formatTodoMarkdown(todo)}`);
3727          }
3728          lines.push("");
3729        }
3730        if (links.length > 0) {
3731          lines.push("### \uD83D\uDD17 Links & Notes");
3732          lines.push("");
3733          for (const item of links) {
3734            lines.push(`- ${stripOrgLinks(item.heading)}`);
3735          }
3736        }
3737      }
3738      pi.sendMessage({
3739        customType: "org-todos",
3740        content: lines.join(`
3741`),
3742        display: true
3743      });
3744    }
3745  });
3746  pi.registerCommand("inbox-add", {
3747    description: "Quick capture to inbox. Usage: /inbox-add <title> [scheduled:date] [priority:N]",
3748    handler: async (args, ctx) => {
3749      if (!args?.trim()) {
3750        ctx.ui.notify("Usage: /inbox-add <title> [scheduled:date] [priority:N]", "error");
3751        return;
3752      }
3753      const parsed = parseCommandArgs(args);
3754      if (!parsed.title) {
3755        ctx.ui.notify("Error: TODO title is required", "error");
3756        return;
3757      }
3758      const schedArg = parsed.scheduled ? `"${parsed.scheduled}"` : "nil";
3759      const prioArg = parsed.priority !== undefined ? parsed.priority : "nil";
3760      const elisp = `(with-current-buffer (find-file-noselect "${INBOX_FILE}")
3761        (goto-char (point-max))
3762        (insert "\\n* TODO ${parsed.title.replace(/"/g, "\\\"")}")
3763        ${parsed.scheduled ? `(org-schedule nil "${parsed.scheduled}")` : ""}
3764        ${parsed.priority !== undefined ? `(org-priority ${parsed.priority})` : ""}
3765        (save-buffer)
3766        (kill-buffer)
3767        (json-encode (list (cons 'success t))))`;
3768      const result = execEmacs(elisp);
3769      if (!result.success) {
3770        ctx.ui.notify(`Failed to add to inbox: ${result.error}`, "error");
3771        return;
3772      }
3773      const lines = [];
3774      lines.push(`## \uD83D\uDCE5 Added to Inbox`);
3775      lines.push("");
3776      lines.push(`**${parsed.title}**`);
3777      if (parsed.scheduled)
3778        lines.push(`- \uD83D\uDCC5 Scheduled: ${parsed.scheduled}`);
3779      if (parsed.priority)
3780        lines.push(`- Priority: #${parsed.priority}`);
3781      pi.sendMessage({
3782        customType: "org-todos-add",
3783        content: lines.join(`
3784`),
3785        display: true
3786      });
3787      updateInboxStatus(ctx);
3788      if (parsed.scheduled) {
3789        updateTodayStatus(ctx);
3790      }
3791    }
3792  });
3793  function fuzzyMatch(item, query) {
3794    if (!query)
3795      return true;
3796    const searchable = `${item.label} ${item.description || ""}`.toLowerCase();
3797    const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
3798    return terms.every((term) => searchable.includes(term));
3799  }
3800  async function showSelectMenu(ctx, title, allItems) {
3801    return ctx.ui.custom((tui, theme, _kb, done) => {
3802      let searchQuery = "";
3803      function getFilteredItems() {
3804        if (!searchQuery)
3805          return allItems;
3806        return allItems.filter((item) => fuzzyMatch(item, searchQuery));
3807      }
3808      let currentItems = getFilteredItems();
3809      const container = new Container;
3810      container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
3811      const headerText = new Text("", 0, 0);
3812      function updateHeader() {
3813        const titleStr = theme.fg("accent", theme.bold(title));
3814        if (searchQuery) {
3815          headerText.setText(`${titleStr}  ${theme.fg("warning", `filter: ${searchQuery}`)}`);
3816        } else {
3817          headerText.setText(titleStr);
3818        }
3819      }
3820      updateHeader();
3821      container.addChild(headerText);
3822      const listTheme = {
3823        selectedPrefix: (text) => theme.fg("accent", text),
3824        selectedText: (text) => theme.fg("accent", text),
3825        description: (text) => theme.fg("muted", text),
3826        scrollInfo: (text) => theme.fg("dim", text),
3827        noMatch: (text) => theme.fg("warning", text)
3828      };
3829      let selectList = new SelectList(currentItems, Math.min(currentItems.length, 15), listTheme);
3830      selectList.onSelect = (item) => done(item.value);
3831      selectList.onCancel = () => done(null);
3832      container.addChild(selectList);
3833      container.addChild(new Text(theme.fg("dim", "Type to filter · enter to confirm · esc to cancel")));
3834      container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
3835      function rebuildList() {
3836        currentItems = getFilteredItems();
3837        const newList = new SelectList(currentItems, Math.min(currentItems.length, 15), listTheme);
3838        newList.onSelect = (item) => done(item.value);
3839        newList.onCancel = () => done(null);
3840        const idx = container.children.indexOf(selectList);
3841        if (idx !== -1)
3842          container.children[idx] = newList;
3843        selectList = newList;
3844        updateHeader();
3845      }
3846      return {
3847        render(width) {
3848          return container.render(width);
3849        },
3850        invalidate() {
3851          container.invalidate();
3852        },
3853        handleInput(data) {
3854          if (data === "" || data === "\b") {
3855            if (searchQuery.length > 0) {
3856              searchQuery = searchQuery.slice(0, -1);
3857              rebuildList();
3858              tui.requestRender();
3859            }
3860            return;
3861          }
3862          if (data.length === 1 && data >= " " && data <= "~") {
3863            searchQuery += data;
3864            rebuildList();
3865            tui.requestRender();
3866            return;
3867          }
3868          selectList.handleInput(data);
3869          tui.requestRender();
3870        }
3871      };
3872    });
3873  }
3874  pi.registerCommand("inbox-refile", {
3875    description: "Refile inbox item to a section (interactive)",
3876    handler: async (args, ctx) => {
3877      const inboxResult = execEmacs(`(pi/org-todo-inbox-all)`);
3878      if (!inboxResult.success || !inboxResult.data || inboxResult.data.length === 0) {
3879        ctx.ui.notify("Inbox is empty!", "info");
3880        return;
3881      }
3882      let heading = (args || "").trim();
3883      let sourcePosition = null;
3884      if (!heading) {
3885        const inboxItems = inboxResult.data.map((item, i) => {
3886          const prefix = item.todo ? `[${item.todo}] ` : "";
3887          const label = stripOrgLinks(`${prefix}${item.heading}`);
3888          return {
3889            value: String(i),
3890            label,
3891            description: item.todo ? undefined : "link/note"
3892          };
3893        });
3894        const selectedIdx = await showSelectMenu(ctx, "Select inbox item to refile", inboxItems);
3895        if (selectedIdx === null) {
3896          ctx.ui.notify("Refile cancelled", "info");
3897          return;
3898        }
3899        const sourceItem = inboxResult.data[parseInt(selectedIdx, 10)];
3900        heading = sourceItem.heading;
3901        sourcePosition = sourceItem.position;
3902      }
3903      const targetsResult = execEmacs("(pi/org-todo-get-refile-targets)");
3904      if (!targetsResult.success || !targetsResult.data) {
3905        ctx.ui.notify("Failed to get refile targets", "error");
3906        return;
3907      }
3908      const sectionItems = targetsResult.data.map((t, i) => {
3909        const indent = t.level > 1 ? "  ".repeat(t.level - 1) : "";
3910        return {
3911          value: String(i),
3912          label: `${indent}${stripOrgLinks(t.section)}`,
3913          description: t.level > 1 ? stripOrgLinks(t.path) : undefined
3914        };
3915      });
3916      const displayHeading = stripOrgLinks(heading).slice(0, 60);
3917      const targetIdx = await showSelectMenu(ctx, `Refile "${displayHeading}" to:`, sectionItems);
3918      if (targetIdx === null) {
3919        ctx.ui.notify("Refile cancelled", "info");
3920        return;
3921      }
3922      const target = targetsResult.data[parseInt(targetIdx, 10)];
3923      const srcPosArg = sourcePosition ? ` ${sourcePosition}` : "";
3924      const refileResult = execEmacs(`(pi/org-todo-refile "${heading.replace(/"/g, "\\\"")}" "${target.section.replace(/"/g, "\\\"")}" nil nil ${target.position}${srcPosArg})`);
3925      if (!refileResult.success) {
3926        ctx.ui.notify(`Refile failed: ${refileResult.error}`, "error");
3927        return;
3928      }
3929      const displayTarget = stripOrgLinks(target.path || target.section);
3930      pi.sendMessage({
3931        customType: "org-todos",
3932        content: `## ✅ Refiled
3933
3934**${displayHeading}** → *${displayTarget}*`,
3935        display: true
3936      });
3937      updateInboxStatus(ctx);
3938    }
3939  });
3940  function updateInboxStatus(ctx) {
3941    try {
3942      const result = execEmacs(`(pi/org-todo-inbox-all)`);
3943      if (result.success && Array.isArray(result.data)) {
3944        const count = result.data.length;
3945        if (count > 0) {
3946          ctx.ui.setStatus("inbox-count", ctx.ui.theme.fg("warning", `\uD83D\uDCE5 ${count}`));
3947        } else {
3948          ctx.ui.setStatus("inbox-count", undefined);
3949        }
3950      }
3951    } catch (e) {}
3952  }
3953  function updateTodayStatus(ctx) {
3954    try {
3955      const scheduledResult = execEmacs("(pi/org-todo-scheduled)");
3956      const overdueResult = execEmacs("(pi/org-todo-overdue)");
3957      if (scheduledResult.success && overdueResult.success) {
3958        const schedCount = Array.isArray(scheduledResult.data) ? scheduledResult.data.length : 0;
3959        const overdueCount = Array.isArray(overdueResult.data) ? overdueResult.data.length : 0;
3960        if (schedCount === 0 && overdueCount === 0) {
3961          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("success", "✓"));
3962        } else if (overdueCount > 0 && schedCount > 0) {
3963          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("error", `⚠️ ${overdueCount}`) + " " + ctx.ui.theme.fg("accent", `\uD83D\uDCC5 ${schedCount}`));
3964        } else if (overdueCount > 0) {
3965          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("error", `⚠️ ${overdueCount}`));
3966        } else {
3967          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("accent", `\uD83D\uDCC5 ${schedCount}`));
3968        }
3969      }
3970    } catch (e) {}
3971  }
3972  pi.on("session_start", async (_event, ctx) => {
3973    updateInboxStatus(ctx);
3974    updateTodayStatus(ctx);
3975    setupTodoAutocomplete(ctx);
3976    const updateInterval = setInterval(() => {
3977      updateInboxStatus(ctx);
3978      updateTodayStatus(ctx);
3979    }, 5 * 60 * 1000);
3980    updateInterval.unref();
3981    pi.on("session_end", async () => {
3982      clearInterval(updateInterval);
3983    });
3984  });
3985}
3986var TODO_MAX_SUGGESTIONS = 20;
3987function extractTodoToken(textBeforeCursor) {
3988  const match = textBeforeCursor.match(/(?:^|[ \t])t:([^\s]*)$/);
3989  return match?.[1];
3990}
3991function formatTodoItem(item) {
3992  return {
3993    value: item.heading,
3994    label: item.heading,
3995    description: `[${item.todo}]`
3996  };
3997}
3998function filterTodoItems(items, query) {
3999  if (!query.trim()) {
4000    return items.slice(0, TODO_MAX_SUGGESTIONS).map(formatTodoItem);
4001  }
4002  return fuzzyFilter(items, query, (item) => `${item.todo} ${item.heading}`).slice(0, TODO_MAX_SUGGESTIONS).map(formatTodoItem);
4003}
4004function createTodoAutocompleteProvider(current, getItems) {
4005  return {
4006    async getSuggestions(lines, cursorLine, cursorCol, options) {
4007      const currentLine = lines[cursorLine] ?? "";
4008      const textBeforeCursor = currentLine.slice(0, cursorCol);
4009      const query = extractTodoToken(textBeforeCursor);
4010      if (query === undefined) {
4011        return current.getSuggestions(lines, cursorLine, cursorCol, options);
4012      }
4013      const items = await getItems();
4014      if (options.signal.aborted || !items || items.length === 0) {
4015        return current.getSuggestions(lines, cursorLine, cursorCol, options);
4016      }
4017      const suggestions = filterTodoItems(items, query);
4018      if (suggestions.length === 0) {
4019        return current.getSuggestions(lines, cursorLine, cursorCol, options);
4020      }
4021      return { items: suggestions, prefix: `t:${query}` };
4022    },
4023    applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
4024      if (prefix.startsWith("t:")) {
4025        const currentLine = lines[cursorLine] || "";
4026        const beforePrefix = currentLine.slice(0, cursorCol - prefix.length);
4027        const afterCursor = currentLine.slice(cursorCol);
4028        const value = item.value.includes(" ") ? `"${item.value}"` : item.value;
4029        const newLine = beforePrefix + value + " " + afterCursor;
4030        const newLines = [...lines];
4031        newLines[cursorLine] = newLine;
4032        return {
4033          lines: newLines,
4034          cursorLine,
4035          cursorCol: beforePrefix.length + value.length + 1
4036        };
4037      }
4038      return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);
4039    },
4040    shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
4041      return current.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? true;
4042    }
4043  };
4044}
4045function setupTodoAutocomplete(ctx) {
4046  let itemsPromise;
4047  const getItems = async () => {
4048    itemsPromise ||= (async () => {
4049      const result = execEmacs("(pi/org-todo-list)");
4050      if (!result.success || !Array.isArray(result.data))
4051        return;
4052      return result.data.map((item) => ({
4053        heading: item.heading,
4054        todo: item.todo || "TODO"
4055      }));
4056    })();
4057    return itemsPromise;
4058  };
4059  getItems();
4060  ctx.ui.addAutocompleteProvider((current) => createTodoAutocompleteProvider(current, getItems));
4061}
4062export {
4063  org_todos_default as default
4064};