flake-update-20260505
   1// index.ts
   2import { DynamicBorder } from "@mariozechner/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 || date.getTime() < 0) {
 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-2][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  if (timeComponent.isCertain("meridiem")) {
1817    dateTimeComponent.assign("meridiem", timeComponent.get("meridiem"));
1818  } else if (timeComponent.get("meridiem") != null && dateTimeComponent.get("meridiem") == null) {
1819    dateTimeComponent.imply("meridiem", timeComponent.get("meridiem"));
1820  }
1821  if (dateTimeComponent.get("meridiem") == Meridiem.PM && dateTimeComponent.get("hour") < 12) {
1822    if (timeComponent.isCertain("hour")) {
1823      dateTimeComponent.assign("hour", dateTimeComponent.get("hour") + 12);
1824    } else {
1825      dateTimeComponent.imply("hour", dateTimeComponent.get("hour") + 12);
1826    }
1827  }
1828  dateTimeComponent.addTags(dateComponent.tags());
1829  dateTimeComponent.addTags(timeComponent.tags());
1830  return dateTimeComponent;
1831}
1832
1833// node_modules/chrono-node/dist/esm/common/refiners/AbstractMergeDateTimeRefiner.js
1834class AbstractMergeDateTimeRefiner extends MergingRefiner {
1835  shouldMergeResults(textBetween, currentResult, nextResult) {
1836    return (currentResult.start.isOnlyDate() && nextResult.start.isOnlyTime() || nextResult.start.isOnlyDate() && currentResult.start.isOnlyTime()) && textBetween.match(this.patternBetween()) != null;
1837  }
1838  mergeResults(textBetween, currentResult, nextResult) {
1839    const result = currentResult.start.isOnlyDate() ? mergeDateTimeResult(currentResult, nextResult) : mergeDateTimeResult(nextResult, currentResult);
1840    result.index = currentResult.index;
1841    result.text = currentResult.text + textBetween + nextResult.text;
1842    return result;
1843  }
1844}
1845
1846// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeDateTimeRefiner.js
1847class ENMergeDateTimeRefiner extends AbstractMergeDateTimeRefiner {
1848  patternBetween() {
1849    return new RegExp("^\\s*(T|at|after|before|on|of|,|-|\\.|∙|:)?\\s*$");
1850  }
1851}
1852
1853// node_modules/chrono-node/dist/esm/common/refiners/ExtractTimezoneAbbrRefiner.js
1854var TIMEZONE_NAME_PATTERN = new RegExp("^\\s*,?\\s*\\(?([A-Z]{2,4})\\)?(?=\\W|$)", "i");
1855
1856class ExtractTimezoneAbbrRefiner {
1857  timezoneOverrides;
1858  constructor(timezoneOverrides) {
1859    this.timezoneOverrides = timezoneOverrides;
1860  }
1861  refine(context, results) {
1862    const timezoneOverrides = context.option.timezones ?? {};
1863    results.forEach((result) => {
1864      const suffix = context.text.substring(result.index + result.text.length);
1865      const match = TIMEZONE_NAME_PATTERN.exec(suffix);
1866      if (!match) {
1867        return;
1868      }
1869      const timezoneAbbr = match[1].toUpperCase();
1870      const refDate = result.start.date() ?? result.refDate ?? new Date;
1871      const tzOverrides = { ...this.timezoneOverrides, ...timezoneOverrides };
1872      const extractedTimezoneOffset = toTimezoneOffset(timezoneAbbr, refDate, tzOverrides);
1873      if (extractedTimezoneOffset == null) {
1874        return;
1875      }
1876      context.debug(() => {
1877        console.log(`Extracting timezone: '${timezoneAbbr}' into: ${extractedTimezoneOffset} for: ${result.start}`);
1878      });
1879      const currentTimezoneOffset = result.start.get("timezoneOffset");
1880      if (currentTimezoneOffset !== null && extractedTimezoneOffset != currentTimezoneOffset) {
1881        if (result.start.isCertain("timezoneOffset")) {
1882          return;
1883        }
1884        if (timezoneAbbr != match[1]) {
1885          return;
1886        }
1887      }
1888      if (result.start.isOnlyDate()) {
1889        if (timezoneAbbr != match[1]) {
1890          return;
1891        }
1892      }
1893      result.text += match[0];
1894      if (!result.start.isCertain("timezoneOffset")) {
1895        result.start.assign("timezoneOffset", extractedTimezoneOffset);
1896      }
1897      if (result.end != null && !result.end.isCertain("timezoneOffset")) {
1898        result.end.assign("timezoneOffset", extractedTimezoneOffset);
1899      }
1900    });
1901    return results;
1902  }
1903}
1904
1905// node_modules/chrono-node/dist/esm/common/refiners/ExtractTimezoneOffsetRefiner.js
1906var TIMEZONE_OFFSET_PATTERN = new RegExp("^\\s*(?:\\(?(?:GMT|UTC)\\s?)?([+-])(\\d{1,2})(?::?(\\d{2}))?\\)?", "i");
1907var TIMEZONE_OFFSET_SIGN_GROUP = 1;
1908var TIMEZONE_OFFSET_HOUR_OFFSET_GROUP = 2;
1909var TIMEZONE_OFFSET_MINUTE_OFFSET_GROUP = 3;
1910
1911class ExtractTimezoneOffsetRefiner {
1912  refine(context, results) {
1913    results.forEach(function(result) {
1914      if (result.start.isCertain("timezoneOffset")) {
1915        return;
1916      }
1917      const suffix = context.text.substring(result.index + result.text.length);
1918      const match = TIMEZONE_OFFSET_PATTERN.exec(suffix);
1919      if (!match) {
1920        return;
1921      }
1922      context.debug(() => {
1923        console.log(`Extracting timezone: '${match[0]}' into : ${result}`);
1924      });
1925      const hourOffset = parseInt(match[TIMEZONE_OFFSET_HOUR_OFFSET_GROUP]);
1926      const minuteOffset = parseInt(match[TIMEZONE_OFFSET_MINUTE_OFFSET_GROUP] || "0");
1927      let timezoneOffset = hourOffset * 60 + minuteOffset;
1928      if (timezoneOffset > 14 * 60) {
1929        return;
1930      }
1931      if (match[TIMEZONE_OFFSET_SIGN_GROUP] === "-") {
1932        timezoneOffset = -timezoneOffset;
1933      }
1934      if (result.end != null) {
1935        result.end.assign("timezoneOffset", timezoneOffset);
1936      }
1937      result.start.assign("timezoneOffset", timezoneOffset);
1938      result.text += match[0];
1939    });
1940    return results;
1941  }
1942}
1943
1944// node_modules/chrono-node/dist/esm/common/refiners/OverlapRemovalRefiner.js
1945class OverlapRemovalRefiner {
1946  refine(context, results) {
1947    if (results.length < 2) {
1948      return results;
1949    }
1950    const filteredResults = [];
1951    let prevResult = results[0];
1952    for (let i = 1;i < results.length; i++) {
1953      const result = results[i];
1954      if (result.index >= prevResult.index + prevResult.text.length) {
1955        filteredResults.push(prevResult);
1956        prevResult = result;
1957        continue;
1958      }
1959      let kept = null;
1960      let removed = null;
1961      if (result.text.length > prevResult.text.length) {
1962        kept = result;
1963        removed = prevResult;
1964      } else {
1965        kept = prevResult;
1966        removed = result;
1967      }
1968      context.debug(() => {
1969        console.log(`${this.constructor.name} remove ${removed} by ${kept}`);
1970      });
1971      prevResult = kept;
1972    }
1973    if (prevResult != null) {
1974      filteredResults.push(prevResult);
1975    }
1976    return filteredResults;
1977  }
1978}
1979
1980// node_modules/chrono-node/dist/esm/common/refiners/ForwardDateRefiner.js
1981class ForwardDateRefiner {
1982  refine(context, results) {
1983    if (!context.option.forwardDate) {
1984      return results;
1985    }
1986    results.forEach((result) => {
1987      let refDate = context.reference.getDateWithAdjustedTimezone();
1988      if (result.start.isOnlyTime() && context.reference.instant > result.start.date()) {
1989        const refDate2 = context.reference.getDateWithAdjustedTimezone();
1990        const refFollowingDay = new Date(refDate2);
1991        refFollowingDay.setDate(refFollowingDay.getDate() + 1);
1992        implySimilarDate(result.start, refFollowingDay);
1993        context.debug(() => {
1994          console.log(`${this.constructor.name} adjusted ${result} time from the ref date (${refDate2}) to the following day (${refFollowingDay})`);
1995        });
1996        if (result.end && result.end.isOnlyTime()) {
1997          implySimilarDate(result.end, refFollowingDay);
1998          if (result.start.date() > result.end.date()) {
1999            refFollowingDay.setDate(refFollowingDay.getDate() + 1);
2000            implySimilarDate(result.end, refFollowingDay);
2001          }
2002        }
2003      }
2004      if (result.start.isOnlyWeekdayComponent() && refDate > result.start.date()) {
2005        let daysToAdd = result.start.get("weekday") - refDate.getDay();
2006        if (daysToAdd <= 0) {
2007          daysToAdd += 7;
2008        }
2009        refDate = addDuration(refDate, { day: daysToAdd });
2010        implySimilarDate(result.start, refDate);
2011        context.debug(() => {
2012          console.log(`${this.constructor.name} adjusted ${result} weekday (${result.start})`);
2013        });
2014        if (result.end && result.end.isOnlyWeekdayComponent()) {
2015          let daysToAdd2 = result.end.get("weekday") - refDate.getDay();
2016          if (daysToAdd2 <= 0) {
2017            daysToAdd2 += 7;
2018          }
2019          refDate = addDuration(refDate, { day: daysToAdd2 });
2020          implySimilarDate(result.end, refDate);
2021          context.debug(() => {
2022            console.log(`${this.constructor.name} adjusted ${result} weekday (${result.end})`);
2023          });
2024        }
2025      }
2026      if (result.start.isDateWithUnknownYear() && refDate > result.start.date()) {
2027        for (let i = 0;i < 3 && refDate > result.start.date(); i++) {
2028          result.start.imply("year", result.start.get("year") + 1);
2029          context.debug(() => {
2030            console.log(`${this.constructor.name} adjusted ${result} year (${result.start})`);
2031          });
2032          if (result.end && !result.end.isCertain("year")) {
2033            result.end.imply("year", result.end.get("year") + 1);
2034            context.debug(() => {
2035              console.log(`${this.constructor.name} adjusted ${result} month (${result.start})`);
2036            });
2037          }
2038        }
2039      }
2040    });
2041    return results;
2042  }
2043}
2044
2045// node_modules/chrono-node/dist/esm/common/refiners/UnlikelyFormatFilter.js
2046class UnlikelyFormatFilter extends Filter {
2047  strictMode;
2048  constructor(strictMode) {
2049    super();
2050    this.strictMode = strictMode;
2051  }
2052  isValid(context, result) {
2053    if (result.text.replace(" ", "").match(/^\d*(\.\d*)?$/)) {
2054      context.debug(() => {
2055        console.log(`Removing unlikely result '${result.text}'`);
2056      });
2057      return false;
2058    }
2059    if (!result.start.isValidDate()) {
2060      context.debug(() => {
2061        console.log(`Removing invalid result: ${result} (${result.start})`);
2062      });
2063      return false;
2064    }
2065    if (result.end && !result.end.isValidDate()) {
2066      context.debug(() => {
2067        console.log(`Removing invalid result: ${result} (${result.end})`);
2068      });
2069      return false;
2070    }
2071    if (this.strictMode) {
2072      return this.isStrictModeValid(context, result);
2073    }
2074    return true;
2075  }
2076  isStrictModeValid(context, result) {
2077    if (result.start.isOnlyWeekdayComponent()) {
2078      context.debug(() => {
2079        console.log(`(Strict) Removing weekday only component: ${result} (${result.end})`);
2080      });
2081      return false;
2082    }
2083    return true;
2084  }
2085}
2086
2087// node_modules/chrono-node/dist/esm/common/parsers/ISOFormatParser.js
2088var 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");
2089var YEAR_NUMBER_GROUP2 = 1;
2090var MONTH_NUMBER_GROUP2 = 2;
2091var DATE_NUMBER_GROUP2 = 3;
2092var HOUR_NUMBER_GROUP = 4;
2093var MINUTE_NUMBER_GROUP = 5;
2094var SECOND_NUMBER_GROUP = 6;
2095var MILLISECOND_NUMBER_GROUP = 7;
2096var TZD_GROUP = 8;
2097var TZD_HOUR_OFFSET_GROUP = 9;
2098var TZD_MINUTE_OFFSET_GROUP = 10;
2099
2100class ISOFormatParser extends AbstractParserWithWordBoundaryChecking {
2101  innerPattern() {
2102    return PATTERN8;
2103  }
2104  innerExtract(context, match) {
2105    const components = context.createParsingComponents({
2106      year: parseInt(match[YEAR_NUMBER_GROUP2]),
2107      month: parseInt(match[MONTH_NUMBER_GROUP2]),
2108      day: parseInt(match[DATE_NUMBER_GROUP2])
2109    });
2110    if (match[HOUR_NUMBER_GROUP] != null) {
2111      components.assign("hour", parseInt(match[HOUR_NUMBER_GROUP]));
2112      components.assign("minute", parseInt(match[MINUTE_NUMBER_GROUP]));
2113      if (match[SECOND_NUMBER_GROUP] != null) {
2114        components.assign("second", parseInt(match[SECOND_NUMBER_GROUP]));
2115      }
2116      if (match[MILLISECOND_NUMBER_GROUP] != null) {
2117        components.assign("millisecond", parseInt(match[MILLISECOND_NUMBER_GROUP]));
2118      }
2119      if (match[TZD_GROUP] != null) {
2120        let offset = 0;
2121        if (match[TZD_HOUR_OFFSET_GROUP]) {
2122          const hourOffset = parseInt(match[TZD_HOUR_OFFSET_GROUP]);
2123          let minuteOffset = 0;
2124          if (match[TZD_MINUTE_OFFSET_GROUP] != null) {
2125            minuteOffset = parseInt(match[TZD_MINUTE_OFFSET_GROUP]);
2126          }
2127          offset = hourOffset * 60;
2128          if (offset < 0) {
2129            offset -= minuteOffset;
2130          } else {
2131            offset += minuteOffset;
2132          }
2133        }
2134        components.assign("timezoneOffset", offset);
2135      }
2136    }
2137    return components.addTag("parser/ISOFormatParser");
2138  }
2139}
2140
2141// node_modules/chrono-node/dist/esm/common/refiners/MergeWeekdayComponentRefiner.js
2142class MergeWeekdayComponentRefiner extends MergingRefiner {
2143  mergeResults(textBetween, currentResult, nextResult) {
2144    const newResult = nextResult.clone();
2145    newResult.index = currentResult.index;
2146    newResult.text = currentResult.text + textBetween + newResult.text;
2147    newResult.start.assign("weekday", currentResult.start.get("weekday"));
2148    if (newResult.end) {
2149      newResult.end.assign("weekday", currentResult.start.get("weekday"));
2150    }
2151    return newResult;
2152  }
2153  shouldMergeResults(textBetween, currentResult, nextResult) {
2154    const weekdayThenNormalDate = currentResult.start.isOnlyWeekdayComponent() && !currentResult.start.isCertain("hour") && nextResult.start.isCertain("day");
2155    return weekdayThenNormalDate && textBetween.match(/^,?\s*$/) != null;
2156  }
2157}
2158
2159// node_modules/chrono-node/dist/esm/configurations.js
2160function includeCommonConfiguration(configuration, strictMode = false) {
2161  configuration.parsers.unshift(new ISOFormatParser);
2162  configuration.refiners.unshift(new MergeWeekdayComponentRefiner);
2163  configuration.refiners.unshift(new ExtractTimezoneOffsetRefiner);
2164  configuration.refiners.unshift(new OverlapRemovalRefiner);
2165  configuration.refiners.push(new ExtractTimezoneAbbrRefiner);
2166  configuration.refiners.push(new OverlapRemovalRefiner);
2167  configuration.refiners.push(new ForwardDateRefiner);
2168  configuration.refiners.push(new UnlikelyFormatFilter(strictMode));
2169  return configuration;
2170}
2171
2172// node_modules/chrono-node/dist/esm/common/casualReferences.js
2173function now(reference) {
2174  const targetDate = reference.getDateWithAdjustedTimezone();
2175  const component = new ParsingComponents(reference, {});
2176  assignSimilarDate(component, targetDate);
2177  assignSimilarTime(component, targetDate);
2178  component.assign("timezoneOffset", reference.getTimezoneOffset());
2179  component.addTag("casualReference/now");
2180  return component;
2181}
2182function today(reference) {
2183  const targetDate = reference.getDateWithAdjustedTimezone();
2184  const component = new ParsingComponents(reference, {});
2185  assignSimilarDate(component, targetDate);
2186  implySimilarTime(component, targetDate);
2187  component.delete("meridiem");
2188  component.addTag("casualReference/today");
2189  return component;
2190}
2191function yesterday(reference) {
2192  return theDayBefore(reference, 1).addTag("casualReference/yesterday");
2193}
2194function tomorrow(reference) {
2195  return theDayAfter(reference, 1).addTag("casualReference/tomorrow");
2196}
2197function theDayBefore(reference, numDay) {
2198  return theDayAfter(reference, -numDay);
2199}
2200function theDayAfter(reference, nDays) {
2201  const targetDate = reference.getDateWithAdjustedTimezone();
2202  const component = new ParsingComponents(reference, {});
2203  const newDate = new Date(targetDate.getTime());
2204  newDate.setDate(newDate.getDate() + nDays);
2205  assignSimilarDate(component, newDate);
2206  implySimilarTime(component, newDate);
2207  component.delete("meridiem");
2208  return component;
2209}
2210function tonight(reference, implyHour = 22) {
2211  const targetDate = reference.getDateWithAdjustedTimezone();
2212  const component = new ParsingComponents(reference, {});
2213  assignSimilarDate(component, targetDate);
2214  component.imply("hour", implyHour);
2215  component.imply("meridiem", Meridiem.PM);
2216  component.addTag("casualReference/tonight");
2217  return component;
2218}
2219function evening(reference, implyHour = 20) {
2220  const component = new ParsingComponents(reference, {});
2221  component.imply("meridiem", Meridiem.PM);
2222  component.imply("hour", implyHour);
2223  component.addTag("casualReference/evening");
2224  return component;
2225}
2226function midnight(reference) {
2227  const component = new ParsingComponents(reference, {});
2228  if (reference.getDateWithAdjustedTimezone().getHours() > 2) {
2229    component.addDurationAsImplied({ day: 1 });
2230  }
2231  component.assign("hour", 0);
2232  component.imply("minute", 0);
2233  component.imply("second", 0);
2234  component.imply("millisecond", 0);
2235  component.addTag("casualReference/midnight");
2236  return component;
2237}
2238function morning(reference, implyHour = 6) {
2239  const component = new ParsingComponents(reference, {});
2240  component.imply("meridiem", Meridiem.AM);
2241  component.imply("hour", implyHour);
2242  component.imply("minute", 0);
2243  component.imply("second", 0);
2244  component.imply("millisecond", 0);
2245  component.addTag("casualReference/morning");
2246  return component;
2247}
2248function afternoon(reference, implyHour = 15) {
2249  const component = new ParsingComponents(reference, {});
2250  component.imply("meridiem", Meridiem.PM);
2251  component.imply("hour", implyHour);
2252  component.imply("minute", 0);
2253  component.imply("second", 0);
2254  component.imply("millisecond", 0);
2255  component.addTag("casualReference/afternoon");
2256  return component;
2257}
2258function noon(reference) {
2259  const component = new ParsingComponents(reference, {});
2260  component.imply("meridiem", Meridiem.AM);
2261  component.assign("hour", 12);
2262  component.imply("minute", 0);
2263  component.imply("second", 0);
2264  component.imply("millisecond", 0);
2265  component.addTag("casualReference/noon");
2266  return component;
2267}
2268
2269// node_modules/chrono-node/dist/esm/locales/en/parsers/ENCasualDateParser.js
2270var PATTERN9 = /(now|today|tonight|tomorrow|overmorrow|tmr|tmrw|yesterday|last\s*night)(?=\W|$)/i;
2271
2272class ENCasualDateParser extends AbstractParserWithWordBoundaryChecking {
2273  innerPattern(context) {
2274    return PATTERN9;
2275  }
2276  innerExtract(context, match) {
2277    let targetDate = context.refDate;
2278    const lowerText = match[0].toLowerCase();
2279    let component = context.createParsingComponents();
2280    switch (lowerText) {
2281      case "now":
2282        component = now(context.reference);
2283        break;
2284      case "today":
2285        component = today(context.reference);
2286        break;
2287      case "yesterday":
2288        component = yesterday(context.reference);
2289        break;
2290      case "tomorrow":
2291      case "tmr":
2292      case "tmrw":
2293        component = tomorrow(context.reference);
2294        break;
2295      case "tonight":
2296        component = tonight(context.reference);
2297        break;
2298      case "overmorrow":
2299        component = theDayAfter(context.reference, 2);
2300        break;
2301      default:
2302        if (lowerText.match(/last\s*night/)) {
2303          if (targetDate.getHours() > 6) {
2304            const previousDay = new Date(targetDate.getTime());
2305            previousDay.setDate(previousDay.getDate() - 1);
2306            targetDate = previousDay;
2307          }
2308          assignSimilarDate(component, targetDate);
2309          component.imply("hour", 0);
2310        }
2311        break;
2312    }
2313    component.addTag("parser/ENCasualDateParser");
2314    return component;
2315  }
2316}
2317
2318// node_modules/chrono-node/dist/esm/locales/en/parsers/ENCasualTimeParser.js
2319var PATTERN10 = /(?:this)?\s{0,3}(morning|afternoon|evening|night|midnight|midday|noon)(?=\W|$)/i;
2320
2321class ENCasualTimeParser extends AbstractParserWithWordBoundaryChecking {
2322  innerPattern() {
2323    return PATTERN10;
2324  }
2325  innerExtract(context, match) {
2326    let component = null;
2327    switch (match[1].toLowerCase()) {
2328      case "afternoon":
2329        component = afternoon(context.reference);
2330        break;
2331      case "evening":
2332      case "night":
2333        component = evening(context.reference);
2334        break;
2335      case "midnight":
2336        component = midnight(context.reference);
2337        break;
2338      case "morning":
2339        component = morning(context.reference);
2340        break;
2341      case "noon":
2342      case "midday":
2343        component = noon(context.reference);
2344        break;
2345    }
2346    if (component) {
2347      component.addTag("parser/ENCasualTimeParser");
2348    }
2349    return component;
2350  }
2351}
2352
2353// node_modules/chrono-node/dist/esm/calculation/weekdays.js
2354function createParsingComponentsAtWeekday(reference, weekday, modifier) {
2355  const refDate = reference.getDateWithAdjustedTimezone();
2356  const daysToWeekday = getDaysToWeekday(refDate, weekday, modifier);
2357  let components = new ParsingComponents(reference);
2358  components = components.addDurationAsImplied({ day: daysToWeekday });
2359  components.assign("weekday", weekday);
2360  return components;
2361}
2362function getDaysToWeekday(refDate, weekday, modifier) {
2363  const refWeekday = refDate.getDay();
2364  switch (modifier) {
2365    case "this":
2366      return getDaysForwardToWeekday(refDate, weekday);
2367    case "last":
2368      return getBackwardDaysToWeekday(refDate, weekday);
2369    case "next":
2370      if (refWeekday == Weekday.SUNDAY) {
2371        return weekday == Weekday.SUNDAY ? 7 : weekday;
2372      }
2373      if (refWeekday == Weekday.SATURDAY) {
2374        if (weekday == Weekday.SATURDAY)
2375          return 7;
2376        if (weekday == Weekday.SUNDAY)
2377          return 8;
2378        return 1 + weekday;
2379      }
2380      if (weekday < refWeekday && weekday != Weekday.SUNDAY) {
2381        return getDaysForwardToWeekday(refDate, weekday);
2382      } else {
2383        return getDaysForwardToWeekday(refDate, weekday) + 7;
2384      }
2385  }
2386  return getDaysToWeekdayClosest(refDate, weekday);
2387}
2388function getDaysToWeekdayClosest(refDate, weekday) {
2389  const backward = getBackwardDaysToWeekday(refDate, weekday);
2390  const forward = getDaysForwardToWeekday(refDate, weekday);
2391  return forward < -backward ? forward : backward;
2392}
2393function getDaysForwardToWeekday(refDate, weekday) {
2394  const refWeekday = refDate.getDay();
2395  let forwardCount = weekday - refWeekday;
2396  if (forwardCount < 0) {
2397    forwardCount += 7;
2398  }
2399  return forwardCount;
2400}
2401function getBackwardDaysToWeekday(refDate, weekday) {
2402  const refWeekday = refDate.getDay();
2403  let backwardCount = weekday - refWeekday;
2404  if (backwardCount >= 0) {
2405    backwardCount -= 7;
2406  }
2407  return backwardCount;
2408}
2409
2410// node_modules/chrono-node/dist/esm/locales/en/parsers/ENWeekdayParser.js
2411var PATTERN11 = new RegExp("(?:(?:\\,|\\(|\\()\\s*)?" + "(?:on\\s*?)?" + "(?:(this|last|past|next)\\s*)?" + `(${matchAnyPattern(WEEKDAY_DICTIONARY)}|weekend|weekday)` + "(?:\\s*(?:\\,|\\)|\\)))?" + "(?:\\s*(this|last|past|next)\\s*week)?" + "(?=\\W|$)", "i");
2412var PREFIX_GROUP2 = 1;
2413var WEEKDAY_GROUP = 2;
2414var POSTFIX_GROUP = 3;
2415
2416class ENWeekdayParser extends AbstractParserWithWordBoundaryChecking {
2417  innerPattern() {
2418    return PATTERN11;
2419  }
2420  innerExtract(context, match) {
2421    const prefix = match[PREFIX_GROUP2];
2422    const postfix = match[POSTFIX_GROUP];
2423    let modifierWord = prefix || postfix;
2424    modifierWord = modifierWord || "";
2425    modifierWord = modifierWord.toLowerCase();
2426    let modifier = null;
2427    if (modifierWord == "last" || modifierWord == "past") {
2428      modifier = "last";
2429    } else if (modifierWord == "next") {
2430      modifier = "next";
2431    } else if (modifierWord == "this") {
2432      modifier = "this";
2433    }
2434    const weekday_word = match[WEEKDAY_GROUP].toLowerCase();
2435    let weekday;
2436    if (WEEKDAY_DICTIONARY[weekday_word] !== undefined) {
2437      weekday = WEEKDAY_DICTIONARY[weekday_word];
2438    } else if (weekday_word == "weekend") {
2439      weekday = modifier == "last" ? Weekday.SUNDAY : Weekday.SATURDAY;
2440    } else if (weekday_word == "weekday") {
2441      const refWeekday = context.reference.getDateWithAdjustedTimezone().getDay();
2442      if (refWeekday == Weekday.SUNDAY || refWeekday == Weekday.SATURDAY) {
2443        weekday = modifier == "last" ? Weekday.FRIDAY : Weekday.MONDAY;
2444      } else {
2445        weekday = refWeekday - 1;
2446        weekday = modifier == "last" ? weekday - 1 : weekday + 1;
2447        weekday = weekday % 5 + 1;
2448      }
2449    } else {
2450      return null;
2451    }
2452    return createParsingComponentsAtWeekday(context.reference, weekday, modifier);
2453  }
2454}
2455
2456// node_modules/chrono-node/dist/esm/locales/en/parsers/ENRelativeDateFormatParser.js
2457var PATTERN12 = new RegExp(`(this|last|past|next|after\\s*this)\\s*(${matchAnyPattern(TIME_UNIT_DICTIONARY)})(?=\\s*)` + "(?=\\W|$)", "i");
2458var MODIFIER_WORD_GROUP = 1;
2459var RELATIVE_WORD_GROUP = 2;
2460
2461class ENRelativeDateFormatParser extends AbstractParserWithWordBoundaryChecking {
2462  innerPattern() {
2463    return PATTERN12;
2464  }
2465  innerExtract(context, match) {
2466    const modifier = match[MODIFIER_WORD_GROUP].toLowerCase();
2467    const unitWord = match[RELATIVE_WORD_GROUP].toLowerCase();
2468    const timeunit = TIME_UNIT_DICTIONARY[unitWord];
2469    if (modifier == "next" || modifier.startsWith("after")) {
2470      const timeUnits = {};
2471      timeUnits[timeunit] = 1;
2472      return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
2473    }
2474    if (modifier == "last" || modifier == "past") {
2475      const timeUnits = {};
2476      timeUnits[timeunit] = -1;
2477      return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
2478    }
2479    const components = context.createParsingComponents();
2480    let date = new Date(context.reference.instant.getTime());
2481    if (unitWord.match(/week/i)) {
2482      date.setDate(date.getDate() - date.getDay());
2483      components.imply("day", date.getDate());
2484      components.imply("month", date.getMonth() + 1);
2485      components.imply("year", date.getFullYear());
2486    } else if (unitWord.match(/month/i)) {
2487      date.setDate(1);
2488      components.imply("day", date.getDate());
2489      components.assign("year", date.getFullYear());
2490      components.assign("month", date.getMonth() + 1);
2491    } else if (unitWord.match(/year/i)) {
2492      date.setDate(1);
2493      date.setMonth(0);
2494      components.imply("day", date.getDate());
2495      components.imply("month", date.getMonth() + 1);
2496      components.assign("year", date.getFullYear());
2497    }
2498    return components;
2499  }
2500}
2501
2502// node_modules/chrono-node/dist/esm/common/parsers/SlashDateFormatParser.js
2503var 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");
2504var OPENING_GROUP = 1;
2505var ENDING_GROUP = 5;
2506var FIRST_NUMBERS_GROUP = 2;
2507var SECOND_NUMBERS_GROUP = 3;
2508var YEAR_GROUP5 = 4;
2509
2510class SlashDateFormatParser {
2511  groupNumberMonth;
2512  groupNumberDay;
2513  constructor(littleEndian) {
2514    this.groupNumberMonth = littleEndian ? SECOND_NUMBERS_GROUP : FIRST_NUMBERS_GROUP;
2515    this.groupNumberDay = littleEndian ? FIRST_NUMBERS_GROUP : SECOND_NUMBERS_GROUP;
2516  }
2517  pattern() {
2518    return PATTERN13;
2519  }
2520  extract(context, match) {
2521    const index = match.index + match[OPENING_GROUP].length;
2522    const indexEnd = match.index + match[0].length - match[ENDING_GROUP].length;
2523    if (index > 0) {
2524      const textBefore = context.text.substring(0, index);
2525      if (textBefore.match("\\d/?$")) {
2526        return;
2527      }
2528    }
2529    if (indexEnd < context.text.length) {
2530      const textAfter = context.text.substring(indexEnd);
2531      if (textAfter.match("^/?\\d")) {
2532        return;
2533      }
2534    }
2535    const text = context.text.substring(index, indexEnd);
2536    if (text.match(/^\d\.\d$/) || text.match(/^\d\.\d{1,2}\.\d{1,2}\s*$/)) {
2537      return;
2538    }
2539    if (!match[YEAR_GROUP5] && text.indexOf("/") < 0) {
2540      return;
2541    }
2542    const result = context.createParsingResult(index, text);
2543    let month = parseInt(match[this.groupNumberMonth]);
2544    let day = parseInt(match[this.groupNumberDay]);
2545    if (month < 1 || month > 12) {
2546      if (month > 12) {
2547        if (day >= 1 && day <= 12 && month <= 31) {
2548          [day, month] = [month, day];
2549        } else {
2550          return null;
2551        }
2552      }
2553    }
2554    if (day < 1 || day > 31) {
2555      return null;
2556    }
2557    result.start.assign("day", day);
2558    result.start.assign("month", month);
2559    if (match[YEAR_GROUP5]) {
2560      const rawYearNumber = parseInt(match[YEAR_GROUP5]);
2561      const year = findMostLikelyADYear(rawYearNumber);
2562      result.start.assign("year", year);
2563    } else {
2564      const year = findYearClosestToRef(context.refDate, day, month);
2565      result.start.imply("year", year);
2566    }
2567    return result.addTag("parser/SlashDateFormatParser");
2568  }
2569}
2570
2571// node_modules/chrono-node/dist/esm/locales/en/parsers/ENTimeUnitCasualRelativeFormatParser.js
2572var PATTERN14 = new RegExp(`(this|last|past|next|after|\\+|-)\\s*(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
2573var PATTERN_NO_ABBR = new RegExp(`(this|last|past|next|after|\\+|-)\\s*(${TIME_UNITS_NO_ABBR_PATTERN})(?=\\W|$)`, "i");
2574
2575class ENTimeUnitCasualRelativeFormatParser extends AbstractParserWithWordBoundaryChecking {
2576  allowAbbreviations;
2577  constructor(allowAbbreviations = true) {
2578    super();
2579    this.allowAbbreviations = allowAbbreviations;
2580  }
2581  innerPattern() {
2582    return this.allowAbbreviations ? PATTERN14 : PATTERN_NO_ABBR;
2583  }
2584  innerExtract(context, match) {
2585    const prefix = match[1].toLowerCase();
2586    let duration = parseDuration(match[2]);
2587    if (!duration) {
2588      return null;
2589    }
2590    switch (prefix) {
2591      case "last":
2592      case "past":
2593      case "-":
2594        duration = reverseDuration(duration);
2595        break;
2596    }
2597    return ParsingComponents.createRelativeFromReference(context.reference, duration);
2598  }
2599}
2600
2601// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js
2602function IsPositiveFollowingReference(result) {
2603  return result.text.match(/^[+-]/i) != null;
2604}
2605function IsNegativeFollowingReference(result) {
2606  return result.text.match(/^-/i) != null;
2607}
2608
2609class ENMergeRelativeAfterDateRefiner extends MergingRefiner {
2610  shouldMergeResults(textBetween, currentResult, nextResult) {
2611    if (!textBetween.match(/^\s*$/i)) {
2612      return false;
2613    }
2614    return IsPositiveFollowingReference(nextResult) || IsNegativeFollowingReference(nextResult);
2615  }
2616  mergeResults(textBetween, currentResult, nextResult, context) {
2617    let timeUnits = parseDuration(nextResult.text);
2618    if (IsNegativeFollowingReference(nextResult)) {
2619      timeUnits = reverseDuration(timeUnits);
2620    }
2621    const components = ParsingComponents.createRelativeFromReference(ReferenceWithTimezone.fromDate(currentResult.start.date()), timeUnits);
2622    return new ParsingResult(currentResult.reference, currentResult.index, `${currentResult.text}${textBetween}${nextResult.text}`, components);
2623  }
2624}
2625
2626// node_modules/chrono-node/dist/esm/locales/en/refiners/ENMergeRelativeFollowByDateRefiner.js
2627function hasImpliedEarlierReferenceDate(result) {
2628  return result.text.match(/\s+(before|from)$/i) != null;
2629}
2630function hasImpliedLaterReferenceDate(result) {
2631  return result.text.match(/\s+(after|since)$/i) != null;
2632}
2633
2634class ENMergeRelativeFollowByDateRefiner extends MergingRefiner {
2635  patternBetween() {
2636    return /^\s*$/i;
2637  }
2638  shouldMergeResults(textBetween, currentResult, nextResult) {
2639    if (!textBetween.match(this.patternBetween())) {
2640      return false;
2641    }
2642    if (!hasImpliedEarlierReferenceDate(currentResult) && !hasImpliedLaterReferenceDate(currentResult)) {
2643      return false;
2644    }
2645    return !!nextResult.start.get("day") && !!nextResult.start.get("month") && !!nextResult.start.get("year");
2646  }
2647  mergeResults(textBetween, currentResult, nextResult) {
2648    let duration = parseDuration(currentResult.text);
2649    if (hasImpliedEarlierReferenceDate(currentResult)) {
2650      duration = reverseDuration(duration);
2651    }
2652    const components = ParsingComponents.createRelativeFromReference(ReferenceWithTimezone.fromDate(nextResult.start.date()), duration);
2653    return new ParsingResult(nextResult.reference, currentResult.index, `${currentResult.text}${textBetween}${nextResult.text}`, components);
2654  }
2655}
2656
2657// node_modules/chrono-node/dist/esm/locales/en/refiners/ENExtractYearSuffixRefiner.js
2658var YEAR_SUFFIX_PATTERN = new RegExp(`^\\s*(${YEAR_PATTERN})`, "i");
2659var YEAR_GROUP6 = 1;
2660
2661class ENExtractYearSuffixRefiner {
2662  refine(context, results) {
2663    results.forEach(function(result) {
2664      if (!result.start.isDateWithUnknownYear()) {
2665        return;
2666      }
2667      const suffix = context.text.substring(result.index + result.text.length);
2668      const match = YEAR_SUFFIX_PATTERN.exec(suffix);
2669      if (!match) {
2670        return;
2671      }
2672      if (match[0].trim().length <= 3) {
2673        return;
2674      }
2675      context.debug(() => {
2676        console.log(`Extracting year: '${match[0]}' into : ${result}`);
2677      });
2678      const year = parseYear(match[YEAR_GROUP6]);
2679      if (result.end != null) {
2680        result.end.assign("year", year);
2681      }
2682      result.start.assign("year", year);
2683      result.text += match[0];
2684    });
2685    return results;
2686  }
2687}
2688
2689// node_modules/chrono-node/dist/esm/locales/en/refiners/ENUnlikelyFormatFilter.js
2690class ENUnlikelyFormatFilter extends Filter {
2691  constructor() {
2692    super();
2693  }
2694  isValid(context, result) {
2695    const text = result.text.trim();
2696    if (text === context.text.trim()) {
2697      return true;
2698    }
2699    if (text.toLowerCase() === "may") {
2700      const textBefore = context.text.substring(0, result.index).trim();
2701      if (!textBefore.match(/\b(in)$/i)) {
2702        context.debug(() => {
2703          console.log(`Removing unlikely result: ${result}`);
2704        });
2705        return false;
2706      }
2707    }
2708    if (text.toLowerCase().endsWith("the second")) {
2709      const textAfter = context.text.substring(result.index + result.text.length).trim();
2710      if (textAfter.length > 0) {
2711        context.debug(() => {
2712          console.log(`Removing unlikely result: ${result}`);
2713        });
2714      }
2715      return false;
2716    }
2717    return true;
2718  }
2719}
2720
2721// node_modules/chrono-node/dist/esm/locales/en/configuration.js
2722class ENDefaultConfiguration {
2723  createCasualConfiguration(littleEndian = false) {
2724    const option = this.createConfiguration(false, littleEndian);
2725    option.parsers.push(new ENCasualDateParser);
2726    option.parsers.push(new ENCasualTimeParser);
2727    option.parsers.push(new ENMonthNameParser);
2728    option.parsers.push(new ENRelativeDateFormatParser);
2729    option.parsers.push(new ENTimeUnitCasualRelativeFormatParser);
2730    option.refiners.push(new ENUnlikelyFormatFilter);
2731    return option;
2732  }
2733  createConfiguration(strictMode = true, littleEndian = false) {
2734    const options = includeCommonConfiguration({
2735      parsers: [
2736        new SlashDateFormatParser(littleEndian),
2737        new ENTimeUnitWithinFormatParser(strictMode),
2738        new ENMonthNameLittleEndianParser,
2739        new ENMonthNameMiddleEndianParser(littleEndian),
2740        new ENWeekdayParser,
2741        new ENSlashMonthFormatParser,
2742        new ENTimeExpressionParser(strictMode),
2743        new ENTimeUnitAgoFormatParser(strictMode),
2744        new ENTimeUnitLaterFormatParser(strictMode)
2745      ],
2746      refiners: [new ENMergeDateTimeRefiner]
2747    }, strictMode);
2748    options.parsers.unshift(new ENYearMonthDayParser(strictMode));
2749    options.refiners.unshift(new ENMergeRelativeFollowByDateRefiner);
2750    options.refiners.unshift(new ENMergeRelativeAfterDateRefiner);
2751    options.refiners.unshift(new OverlapRemovalRefiner);
2752    options.refiners.push(new ENMergeDateTimeRefiner);
2753    options.refiners.push(new ENExtractYearSuffixRefiner);
2754    options.refiners.push(new ENMergeDateRangeRefiner);
2755    return options;
2756  }
2757}
2758
2759// node_modules/chrono-node/dist/esm/chrono.js
2760class Chrono {
2761  parsers;
2762  refiners;
2763  defaultConfig = new ENDefaultConfiguration;
2764  constructor(configuration) {
2765    configuration = configuration || this.defaultConfig.createCasualConfiguration();
2766    this.parsers = [...configuration.parsers];
2767    this.refiners = [...configuration.refiners];
2768  }
2769  clone() {
2770    return new Chrono({
2771      parsers: [...this.parsers],
2772      refiners: [...this.refiners]
2773    });
2774  }
2775  parseDate(text, referenceDate, option) {
2776    const results = this.parse(text, referenceDate, option);
2777    return results.length > 0 ? results[0].start.date() : null;
2778  }
2779  parse(text, referenceDate, option) {
2780    const context = new ParsingContext(text, referenceDate, option);
2781    let results = [];
2782    this.parsers.forEach((parser) => {
2783      const parsedResults = Chrono.executeParser(context, parser);
2784      results = results.concat(parsedResults);
2785    });
2786    results.sort((a, b) => {
2787      return a.index - b.index;
2788    });
2789    this.refiners.forEach(function(refiner) {
2790      results = refiner.refine(context, results);
2791    });
2792    return results;
2793  }
2794  static executeParser(context, parser) {
2795    const results = [];
2796    const pattern = parser.pattern(context);
2797    const originalText = context.text;
2798    let remainingText = context.text;
2799    let match = pattern.exec(remainingText);
2800    while (match) {
2801      const index = match.index + originalText.length - remainingText.length;
2802      match.index = index;
2803      const result = parser.extract(context, match);
2804      if (!result) {
2805        remainingText = originalText.substring(match.index + 1);
2806        match = pattern.exec(remainingText);
2807        continue;
2808      }
2809      let parsedResult = null;
2810      if (result instanceof ParsingResult) {
2811        parsedResult = result;
2812      } else if (result instanceof ParsingComponents) {
2813        parsedResult = context.createParsingResult(match.index, match[0]);
2814        parsedResult.start = result;
2815      } else {
2816        parsedResult = context.createParsingResult(match.index, match[0], result);
2817      }
2818      const parsedIndex = parsedResult.index;
2819      const parsedText = parsedResult.text;
2820      context.debug(() => console.log(`${parser.constructor.name} extracted (at index=${parsedIndex}) '${parsedText}'`));
2821      results.push(parsedResult);
2822      remainingText = originalText.substring(parsedIndex + parsedText.length);
2823      match = pattern.exec(remainingText);
2824    }
2825    return results;
2826  }
2827}
2828
2829class ParsingContext {
2830  text;
2831  option;
2832  reference;
2833  refDate;
2834  constructor(text, refDate, option) {
2835    this.text = text;
2836    this.option = option ?? {};
2837    this.reference = ReferenceWithTimezone.fromInput(refDate, this.option.timezones);
2838    this.refDate = this.reference.instant;
2839  }
2840  createParsingComponents(components) {
2841    if (components instanceof ParsingComponents) {
2842      return components;
2843    }
2844    return new ParsingComponents(this.reference, components);
2845  }
2846  createParsingResult(index, textOrEndIndex, startComponents, endComponents) {
2847    const text = typeof textOrEndIndex === "string" ? textOrEndIndex : this.text.substring(index, textOrEndIndex);
2848    const start = startComponents ? this.createParsingComponents(startComponents) : null;
2849    const end = endComponents ? this.createParsingComponents(endComponents) : null;
2850    return new ParsingResult(this.reference, index, text, start, end);
2851  }
2852  debug(block) {
2853    if (this.option.debug) {
2854      if (this.option.debug instanceof Function) {
2855        this.option.debug(block);
2856      } else {
2857        const handler = this.option.debug;
2858        handler.debug(block);
2859      }
2860    }
2861  }
2862}
2863
2864// node_modules/chrono-node/dist/esm/locales/en/index.js
2865var configuration = new ENDefaultConfiguration;
2866var casual = new Chrono(configuration.createCasualConfiguration(false));
2867var strict = new Chrono(configuration.createConfiguration(true, false));
2868var GB = new Chrono(configuration.createCasualConfiguration(true));
2869
2870// node_modules/chrono-node/dist/esm/index.js
2871var casual2 = casual;
2872function parseDate(text, ref, option) {
2873  return casual2.parseDate(text, ref, option);
2874}
2875
2876// index.ts
2877import { Container, SelectList, Text } from "@mariozechner/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    description: `Manage org-mode TODOs. Actions:
3045- list: List active TODOs (TODO, NEXT, STRT)
3046- scheduled: Get today's scheduled items
3047- upcoming: Get tasks in next N days (default 7)
3048- overdue: Get overdue tasks
3049- search: Search TODOs by query
3050- get: Get full content of a TODO
3051- done: Mark TODO as DONE
3052- state: Change TODO state (TODO, NEXT, STRT, WAIT, DONE, CANX)
3053- schedule: Set scheduled date
3054- deadline: Set deadline date
3055- priority: Set priority (1-5)
3056- add: Create new TODO
3057- append: Append content to TODO
3058- inbox-list: List all inbox items
3059- inbox-count: Get count of inbox items
3060- inbox-add: Add item to inbox
3061- refile-targets: Get available refile target sections
3062- refile: Refile item from inbox to a section`,
3063    parameters: {
3064      type: "object",
3065      properties: {
3066        action: {
3067          type: "string",
3068          enum: [
3069            "list",
3070            "scheduled",
3071            "upcoming",
3072            "overdue",
3073            "search",
3074            "get",
3075            "done",
3076            "state",
3077            "schedule",
3078            "deadline",
3079            "priority",
3080            "add",
3081            "append",
3082            "sections",
3083            "statistics",
3084            "archive",
3085            "inbox-list",
3086            "inbox-count",
3087            "inbox-add",
3088            "refile-targets",
3089            "refile"
3090          ],
3091          description: "Action to perform"
3092        },
3093        heading: {
3094          type: "string",
3095          description: "TODO heading (for get, done, state, schedule, etc.)"
3096        },
3097        query: {
3098          type: "string",
3099          description: "Search query (for search action)"
3100        },
3101        section: {
3102          type: "string",
3103          description: "Section name (for add action or by-section filter)"
3104        },
3105        state: {
3106          type: "string",
3107          enum: ["TODO", "NEXT", "STRT", "WAIT", "DONE", "CANX"],
3108          description: "TODO state (for state action)"
3109        },
3110        date: {
3111          type: "string",
3112          description: "Date in YYYY-MM-DD format (for schedule/deadline)"
3113        },
3114        days: {
3115          type: "number",
3116          description: "Number of days (for upcoming action, default 7)"
3117        },
3118        priority: {
3119          type: "number",
3120          description: "Priority 1-5 (1=highest)"
3121        },
3122        content: {
3123          type: "string",
3124          description: "Content to append (org-mode format)"
3125        },
3126        tags: {
3127          type: "array",
3128          items: { type: "string" },
3129          description: "Tags for new TODO"
3130        }
3131      },
3132      required: ["action"]
3133    },
3134    execute: async (toolCallId, params, signal, onUpdate, ctx) => {
3135      const { action, heading, query, section, state, date, days, priority, content, tags } = params;
3136      let elisp;
3137      switch (action) {
3138        case "list":
3139          if (section) {
3140            elisp = `(pi/org-todo-by-section "${section}")`;
3141          } else {
3142            elisp = "(pi/org-todo-list)";
3143          }
3144          break;
3145        case "scheduled":
3146          elisp = `(pi/org-todo-scheduled nil "${date || "today"}")`;
3147          break;
3148        case "upcoming":
3149          elisp = `(pi/org-todo-upcoming nil ${days || 7})`;
3150          break;
3151        case "overdue":
3152          elisp = "(pi/org-todo-overdue)";
3153          break;
3154        case "search":
3155          if (!query) {
3156            return {
3157              content: [{ type: "text", text: "Error: query is required for search action" }]
3158            };
3159          }
3160          elisp = `(pi/org-todo-search "${query.replace(/"/g, "\\\"")}")`;
3161          break;
3162        case "get":
3163          if (!heading) {
3164            return {
3165              content: [{ type: "text", text: "Error: heading is required for get action" }]
3166            };
3167          }
3168          elisp = `(pi/org-todo-get "${heading.replace(/"/g, "\\\"")}")`;
3169          break;
3170        case "done":
3171          if (!heading) {
3172            return {
3173              content: [{ type: "text", text: "Error: heading is required for done action" }]
3174            };
3175          }
3176          elisp = `(pi/org-todo-done "${heading.replace(/"/g, "\\\"")}")`;
3177          break;
3178        case "state":
3179          if (!heading || !state) {
3180            return {
3181              content: [{ type: "text", text: "Error: heading and state are required for state action" }]
3182            };
3183          }
3184          elisp = `(pi/org-todo-state "${heading.replace(/"/g, "\\\"")}" "${state}")`;
3185          break;
3186        case "schedule":
3187          if (!heading || !date) {
3188            return {
3189              content: [{ type: "text", text: "Error: heading and date are required for schedule action" }]
3190            };
3191          }
3192          elisp = `(pi/org-todo-schedule "${heading.replace(/"/g, "\\\"")}" "${date}")`;
3193          break;
3194        case "deadline":
3195          if (!heading || !date) {
3196            return {
3197              content: [{ type: "text", text: "Error: heading and date are required for deadline action" }]
3198            };
3199          }
3200          elisp = `(pi/org-todo-deadline "${heading.replace(/"/g, "\\\"")}" "${date}")`;
3201          break;
3202        case "priority":
3203          if (!heading || priority === undefined) {
3204            return {
3205              content: [{ type: "text", text: "Error: heading and priority are required for priority action" }]
3206            };
3207          }
3208          elisp = `(pi/org-todo-priority "${heading.replace(/"/g, "\\\"")}" ${priority})`;
3209          break;
3210        case "add":
3211          if (!heading || !section) {
3212            return {
3213              content: [{ type: "text", text: "Error: heading and section are required for add action" }]
3214            };
3215          }
3216          const schedArg = date ? `"${date}"` : "nil";
3217          const prioArg = priority !== undefined ? priority : "nil";
3218          const tagsArg = tags && tags.length > 0 ? `'(${tags.map((t) => `"${t}"`).join(" ")})` : "nil";
3219          elisp = `(pi/org-todo-add "${heading.replace(/"/g, "\\\"")}" "${section.replace(/"/g, "\\\"")}" nil ${schedArg} ${prioArg} ${tagsArg})`;
3220          if (content) {
3221            const addResult = execEmacs(elisp);
3222            if (!addResult.success) {
3223              return {
3224                content: [{ type: "text", text: `Error: ${addResult.error}` }]
3225              };
3226            }
3227            elisp = `(pi/org-todo-append "${heading.replace(/"/g, "\\\"")}" "${content.replace(/"/g, "\\\"").replace(/\n/g, "\\n")}")`;
3228          }
3229          break;
3230        case "append":
3231          if (!heading || !content) {
3232            return {
3233              content: [{ type: "text", text: "Error: heading and content are required for append action" }]
3234            };
3235          }
3236          elisp = `(pi/org-todo-append "${heading.replace(/"/g, "\\\"")}" "${content.replace(/"/g, "\\\"").replace(/\n/g, "\\n")}")`;
3237          break;
3238        case "sections":
3239          elisp = "(pi/org-todo-sections)";
3240          break;
3241        case "statistics":
3242          elisp = "(pi/org-todo-statistics)";
3243          break;
3244        case "archive":
3245          elisp = "(pi/org-todo-archive-done)";
3246          break;
3247        case "inbox-list":
3248          elisp = `(pi/org-todo-list "${INBOX_FILE}" "TODO,NEXT,STRT,WAIT")`;
3249          break;
3250        case "inbox-count":
3251          elisp = `(pi/org-todo-inbox-all)`;
3252          break;
3253        case "inbox-add":
3254          if (!heading) {
3255            return {
3256              content: [{ type: "text", text: "Error: heading is required for inbox-add action" }]
3257            };
3258          }
3259          const schedInbox = date ? `"${date}"` : "nil";
3260          const prioInbox = priority !== undefined ? priority : "nil";
3261          const tagsInbox = tags && tags.length > 0 ? `'(${tags.map((t) => `"${t}"`).join(" ")})` : "nil";
3262          elisp = `(pi/org-todo-add "${heading.replace(/"/g, "\\\"")}" "Inbox" "${INBOX_FILE}" ${schedInbox} ${prioInbox} ${tagsInbox})`;
3263          break;
3264        case "refile-targets":
3265          elisp = "(pi/org-todo-get-refile-targets)";
3266          break;
3267        case "refile":
3268          if (!heading || !section) {
3269            return {
3270              content: [{ type: "text", text: "Error: heading and section are required for refile action" }]
3271            };
3272          }
3273          elisp = `(pi/org-todo-refile "${heading.replace(/"/g, "\\\"")}" "${section.replace(/"/g, "\\\"")}")`;
3274          break;
3275        default:
3276          return {
3277            content: [{ type: "text", text: `Unknown action: ${action}` }]
3278          };
3279      }
3280      const result = execEmacs(elisp);
3281      if (!result.success) {
3282        return {
3283          content: [{ type: "text", text: `Error: ${result.error}` }]
3284        };
3285      }
3286      let text;
3287      if (action === "refile-targets" && Array.isArray(result.data)) {
3288        if (result.data.length === 0) {
3289          text = "No refile targets found.";
3290        } else {
3291          text = result.data.map((t) => {
3292            const indent = "  ".repeat((t.level || 1) - 1);
3293            return `${indent}- ${t.section} (${t.file?.replace(/.*\//, "")})`;
3294          }).join(`
3295`);
3296        }
3297      } else if (action === "sections" && Array.isArray(result.data)) {
3298        if (result.data.length === 0) {
3299          text = "No sections found.";
3300        } else {
3301          text = result.data.map((s) => `- ${s.section || s}`).join(`
3302`);
3303        }
3304      } else if (Array.isArray(result.data)) {
3305        if (result.data.length === 0) {
3306          text = "No TODOs found.";
3307        } else {
3308          text = result.data.map(formatTodo).join(`
3309`);
3310        }
3311      } else if (typeof result.data === "object") {
3312        text = JSON.stringify(result.data, null, 2);
3313      } else {
3314        text = String(result.data);
3315      }
3316      return {
3317        content: [{ type: "text", text }]
3318      };
3319    }
3320  });
3321  pi.registerCommand("todos", {
3322    description: "Show today's tasks (scheduled + overdue + NEXT). Usage: /todos [section]",
3323    handler: async (args, ctx) => {
3324      const sectionFilter = (args || "").trim() || null;
3325      let sectionHeadings = null;
3326      if (sectionFilter) {
3327        const sectionResult = execEmacs(`(pi/org-todo-by-section "${sectionFilter.replace(/"/g, "\\\"")}")`);
3328        if (!sectionResult.success) {
3329          const sections = execEmacs("(pi/org-todo-sections)");
3330          const sectionList = sections.success && sections.data ? Array.isArray(sections.data) ? sections.data : Object.values(sections.data) : [];
3331          ctx.ui.notify(`Section "${sectionFilter}" not found. Available: ${sectionList.join(", ")}`, "error");
3332          return;
3333        }
3334        sectionHeadings = new Set((sectionResult.data || []).map((t) => t.heading));
3335      }
3336      function filterBySection(todos) {
3337        if (!sectionHeadings)
3338          return todos;
3339        return todos.filter((t) => sectionHeadings.has(t.heading));
3340      }
3341      const scheduled = execEmacs("(pi/org-todo-scheduled)");
3342      const overdue = execEmacs("(pi/org-todo-overdue)");
3343      const next = execEmacs('(pi/org-todo-list nil "NEXT")');
3344      if (!scheduled.success && !overdue.success && !next.success) {
3345        ctx.ui.notify("Failed to fetch TODOs. Is Emacs daemon running?", "error");
3346        return;
3347      }
3348      const filteredOverdue = filterBySection(overdue.success && overdue.data ? overdue.data : []);
3349      const filteredScheduled = filterBySection(scheduled.success && scheduled.data ? scheduled.data : []);
3350      const filteredNext = filterBySection(next.success && next.data ? next.data : []);
3351      const lines = [];
3352      const title = sectionFilter ? `## \uD83D\uDCCB Today's Tasks — ${sectionFilter}` : "## \uD83D\uDCCB Today's Tasks";
3353      lines.push(title);
3354      lines.push("");
3355      if (filteredOverdue.length > 0) {
3356        lines.push(`### ⚠️ Overdue (${filteredOverdue.length})`);
3357        lines.push("");
3358        for (const todo of filteredOverdue) {
3359          lines.push(`- ${formatTodoMarkdown(todo)}`);
3360        }
3361        lines.push("");
3362      }
3363      if (filteredScheduled.length > 0) {
3364        lines.push(`### \uD83D\uDCC5 Scheduled Today (${filteredScheduled.length})`);
3365        lines.push("");
3366        for (const todo of filteredScheduled) {
3367          lines.push(`- ${formatTodoMarkdown(todo)}`);
3368        }
3369        lines.push("");
3370      }
3371      if (filteredNext.length > 0) {
3372        lines.push(`### ➡️ Next Actions (${filteredNext.length})`);
3373        lines.push("");
3374        for (const todo of filteredNext) {
3375          lines.push(`- ${formatTodoMarkdown(todo)}`);
3376        }
3377        lines.push("");
3378      }
3379      const hasContent = filteredOverdue.length > 0 || filteredScheduled.length > 0 || filteredNext.length > 0;
3380      if (!hasContent) {
3381        if (sectionFilter) {
3382          lines.push(`*No tasks for today in "${sectionFilter}".* \uD83C\uDF89`);
3383        } else {
3384          lines.push("*No tasks for today.* \uD83C\uDF89");
3385        }
3386      }
3387      pi.sendMessage({
3388        customType: "org-todos",
3389        content: lines.join(`
3390`),
3391        display: true
3392      });
3393    }
3394  });
3395  pi.registerCommand("todo-search", {
3396    description: "Search TODOs. Usage: /todo-search <query>",
3397    handler: async (args, ctx) => {
3398      const query = (args || "").trim();
3399      if (!query) {
3400        ctx.ui.notify("Usage: /todo-search <query>", "error");
3401        return;
3402      }
3403      const result = execEmacs(`(pi/org-todo-search "${query.replace(/"/g, "\\\"")}" nil t)`);
3404      if (!result.success) {
3405        ctx.ui.notify(`Search failed: ${result.error}`, "error");
3406        return;
3407      }
3408      if (!result.data || result.data.length === 0) {
3409        ctx.ui.notify(`No TODOs found matching "${query}"`, "info");
3410        return;
3411      }
3412      const lines = [];
3413      lines.push(`## \uD83D\uDD0D Search: "${query}"`);
3414      lines.push("");
3415      lines.push(`*${result.data.length} result(s)*`);
3416      lines.push("");
3417      for (const todo of result.data) {
3418        const matchedIn = todo.matched_in === "heading" ? "" : " *(matched in content)*";
3419        lines.push(`- ${formatTodoMarkdown(todo)}${matchedIn}`);
3420      }
3421      pi.sendMessage({
3422        customType: "org-todos-search",
3423        content: lines.join(`
3424`),
3425        display: true
3426      });
3427    }
3428  });
3429  pi.registerCommand("todo-add", {
3430    description: "Add a new TODO. Usage: /todo-add <title> [@Section] [scheduled:date] [deadline:date] [priority:N]",
3431    handler: async (args, ctx) => {
3432      if (!args?.trim()) {
3433        ctx.ui.notify("Usage: /todo-add <title> [@Section] [scheduled:date] [deadline:date]", "error");
3434        return;
3435      }
3436      const parsed = parseCommandArgs(args);
3437      if (!parsed.title) {
3438        ctx.ui.notify("Error: TODO title is required", "error");
3439        return;
3440      }
3441      const section = parsed.section || DEFAULT_SECTION;
3442      const schedArg = parsed.scheduled ? `"${parsed.scheduled}"` : "nil";
3443      const prioArg = parsed.priority !== undefined ? parsed.priority : "nil";
3444      const sectionsResult = execEmacs("(pi/org-todo-sections)");
3445      if (sectionsResult.success) {
3446        const sections = Array.isArray(sectionsResult.data) ? sectionsResult.data : Object.values(sectionsResult.data || {});
3447        if (!sections.includes(section)) {
3448          ctx.ui.notify(`Section "${section}" not found. Available: ${sections.join(", ")}`, "error");
3449          return;
3450        }
3451      }
3452      const elisp = `(pi/org-todo-add "${parsed.title.replace(/"/g, "\\\"")}" "${section}" nil ${schedArg} ${prioArg} nil)`;
3453      const result = execEmacs(elisp);
3454      if (!result.success) {
3455        ctx.ui.notify(`Failed to add TODO: ${result.error}`, "error");
3456        return;
3457      }
3458      if (parsed.deadline) {
3459        execEmacs(`(pi/org-todo-deadline "${parsed.title.replace(/"/g, "\\\"")}" "${parsed.deadline}")`);
3460      }
3461      const lines = [];
3462      lines.push(`## ✅ TODO Added`);
3463      lines.push("");
3464      lines.push(`**${parsed.title}** added to *${section}*`);
3465      if (parsed.scheduled)
3466        lines.push(`- \uD83D\uDCC5 Scheduled: ${parsed.scheduled}`);
3467      if (parsed.deadline)
3468        lines.push(`- ⏰ Deadline: ${parsed.deadline}`);
3469      if (parsed.priority)
3470        lines.push(`- Priority: #${parsed.priority}`);
3471      pi.sendMessage({
3472        customType: "org-todos-add",
3473        content: lines.join(`
3474`),
3475        display: true
3476      });
3477    }
3478  });
3479  async function selectTodo(ctx, title, filterQuery, states) {
3480    const stateFilter = states || "TODO,NEXT,STRT,WAIT";
3481    const listResult = execEmacs(`(pi/org-todo-list nil "${stateFilter}")`);
3482    if (!listResult.success || !listResult.data || listResult.data.length === 0) {
3483      ctx.ui.notify("No active TODOs found.", "info");
3484      return null;
3485    }
3486    const items = listResult.data.map((todo2, i) => ({
3487      value: String(i),
3488      label: stripOrgLinks(formatTodo(todo2)),
3489      description: todo2.scheduled || todo2.deadline || undefined
3490    }));
3491    const filteredItems = filterQuery ? items.filter((item) => {
3492      const searchable = `${item.label} ${item.description || ""}`.toLowerCase();
3493      return filterQuery.toLowerCase().split(/\s+/).every((t) => searchable.includes(t));
3494    }) : items;
3495    if (filteredItems.length === 0) {
3496      ctx.ui.notify(`No TODOs matching "${filterQuery}"`, "info");
3497      return null;
3498    }
3499    const selectedIdx = await showSelectMenu(ctx, title, filteredItems);
3500    if (selectedIdx === null)
3501      return null;
3502    const todo = listResult.data[parseInt(selectedIdx, 10)];
3503    return {
3504      heading: todo.heading,
3505      display: stripOrgLinks(formatTodo(todo))
3506    };
3507  }
3508  pi.registerCommand("todo-done", {
3509    description: "Mark a TODO as done. Usage: /todo-done [filter] (interactive selector)",
3510    handler: async (args, ctx) => {
3511      const filter = (args || "").trim() || undefined;
3512      const selected = await selectTodo(ctx, "Mark as DONE", filter);
3513      if (!selected) {
3514        if (filter)
3515          ctx.ui.notify("Cancelled or no match.", "info");
3516        return;
3517      }
3518      const result = execEmacs(`(pi/org-todo-done "${selected.heading.replace(/"/g, "\\\"")}")`);
3519      if (!result.success) {
3520        ctx.ui.notify(`Failed: ${result.error}`, "error");
3521        return;
3522      }
3523      pi.sendMessage({
3524        customType: "org-todos-done",
3525        content: `## ✅ Done
3526
3527${selected.display}`,
3528        display: true
3529      });
3530      updateTodayStatus(ctx);
3531    }
3532  });
3533  pi.registerCommand("todo-next", {
3534    description: "Mark a TODO as NEXT (prioritized). Usage: /todo-next [filter] (interactive selector)",
3535    handler: async (args, ctx) => {
3536      const filter = (args || "").trim() || undefined;
3537      const selected = await selectTodo(ctx, "Mark as NEXT", filter, "TODO,STRT,WAIT");
3538      if (!selected) {
3539        if (filter)
3540          ctx.ui.notify("Cancelled or no match.", "info");
3541        return;
3542      }
3543      const result = execEmacs(`(pi/org-todo-state "${selected.heading.replace(/"/g, "\\\"")}" "NEXT")`);
3544      if (!result.success) {
3545        ctx.ui.notify(`Failed: ${result.error}`, "error");
3546        return;
3547      }
3548      pi.sendMessage({
3549        customType: "org-todos-next",
3550        content: `## ➡️ Prioritized
3551
3552${selected.display}`,
3553        display: true
3554      });
3555    }
3556  });
3557  pi.registerCommand("todo-upcoming", {
3558    description: "Show upcoming tasks. Usage: /todo-upcoming [days]",
3559    handler: async (args, ctx) => {
3560      const days = parseInt((args || "").trim(), 10) || 7;
3561      const result = execEmacs(`(pi/org-todo-upcoming nil ${days})`);
3562      if (!result.success) {
3563        ctx.ui.notify(`Failed: ${result.error}`, "error");
3564        return;
3565      }
3566      const lines = [];
3567      lines.push(`## \uD83D\uDCC6 Upcoming (next ${days} days)`);
3568      lines.push("");
3569      if (!result.data || result.data.length === 0) {
3570        lines.push("*No upcoming tasks* \uD83C\uDF89");
3571      } else {
3572        for (const todo of result.data) {
3573          lines.push(`- ${formatTodoMarkdown(todo)}`);
3574        }
3575      }
3576      pi.sendMessage({
3577        customType: "org-todos-upcoming",
3578        content: lines.join(`
3579`),
3580        display: true
3581      });
3582    }
3583  });
3584  pi.registerCommand("todo-update", {
3585    description: "Update a TODO. Usage: /todo-update <heading> [scheduled:date] [deadline:date] [priority:N] [state:STATE]",
3586    handler: async (args, ctx) => {
3587      if (!args?.trim()) {
3588        ctx.ui.notify("Usage: /todo-update <heading> [scheduled:date] [deadline:date] [priority:N] [state:STATE]", "error");
3589        return;
3590      }
3591      const parsed = parseCommandArgs(args);
3592      if (!parsed.title) {
3593        ctx.ui.notify("Error: TODO heading is required", "error");
3594        return;
3595      }
3596      const heading = parsed.title;
3597      const updates = [];
3598      if (parsed.scheduled) {
3599        const result = execEmacs(`(pi/org-todo-schedule "${heading.replace(/"/g, "\\\"")}" "${parsed.scheduled}")`);
3600        if (result.success)
3601          updates.push(`\uD83D\uDCC5 Scheduled: ${parsed.scheduled}`);
3602        else
3603          ctx.ui.notify(`Failed to set schedule: ${result.error}`, "warning");
3604      }
3605      if (parsed.deadline) {
3606        const result = execEmacs(`(pi/org-todo-deadline "${heading.replace(/"/g, "\\\"")}" "${parsed.deadline}")`);
3607        if (result.success)
3608          updates.push(`⏰ Deadline: ${parsed.deadline}`);
3609        else
3610          ctx.ui.notify(`Failed to set deadline: ${result.error}`, "warning");
3611      }
3612      if (parsed.priority !== undefined) {
3613        const result = execEmacs(`(pi/org-todo-priority "${heading.replace(/"/g, "\\\"")}" ${parsed.priority})`);
3614        if (result.success)
3615          updates.push(`Priority: #${parsed.priority}`);
3616        else
3617          ctx.ui.notify(`Failed to set priority: ${result.error}`, "warning");
3618      }
3619      if (parsed.state) {
3620        const result = execEmacs(`(pi/org-todo-state "${heading.replace(/"/g, "\\\"")}" "${parsed.state}")`);
3621        if (result.success)
3622          updates.push(`State: ${parsed.state}`);
3623        else
3624          ctx.ui.notify(`Failed to set state: ${result.error}`, "warning");
3625      }
3626      if (updates.length === 0) {
3627        ctx.ui.notify("No updates specified. Use scheduled:, deadline:, priority:, or state:", "warning");
3628        return;
3629      }
3630      const lines = [];
3631      lines.push(`## \uD83D\uDCDD Updated`);
3632      lines.push("");
3633      lines.push(`**${heading}**`);
3634      lines.push("");
3635      for (const update of updates) {
3636        lines.push(`- ${update}`);
3637      }
3638      pi.sendMessage({
3639        customType: "org-todos-update",
3640        content: lines.join(`
3641`),
3642        display: true
3643      });
3644    }
3645  });
3646  pi.registerCommand("todo-note", {
3647    description: "Add a note to a TODO. Usage: /todo-note <heading> <note>",
3648    handler: async (args, ctx) => {
3649      if (!args?.trim()) {
3650        ctx.ui.notify("Usage: /todo-note <heading> <note>", "error");
3651        return;
3652      }
3653      const input = args.trim();
3654      let heading;
3655      let note;
3656      const newlineIdx = input.indexOf(`
3657`);
3658      if (newlineIdx > 0) {
3659        heading = input.slice(0, newlineIdx).trim();
3660        note = input.slice(newlineIdx + 1).trim();
3661      } else {
3662        const colonIdx = input.indexOf(": ");
3663        const dashIdx = input.indexOf(" - ");
3664        if (colonIdx > 0 && colonIdx < 60) {
3665          heading = input.slice(0, colonIdx).trim();
3666          note = input.slice(colonIdx + 2).trim();
3667        } else if (dashIdx > 0 && dashIdx < 60) {
3668          heading = input.slice(0, dashIdx).trim();
3669          note = input.slice(dashIdx + 3).trim();
3670        } else {
3671          ctx.ui.notify("Could not parse heading and note. Use format: /todo-note Heading: your note here", "error");
3672          return;
3673        }
3674      }
3675      if (!heading || !note) {
3676        ctx.ui.notify("Both heading and note are required", "error");
3677        return;
3678      }
3679      const timestamp = new Date().toISOString().slice(0, 16).replace("T", " ");
3680      const orgContent = `
3681[${timestamp}] ${note}`;
3682      const result = execEmacs(`(pi/org-todo-append "${heading.replace(/"/g, "\\\"")}" "${orgContent.replace(/"/g, "\\\"").replace(/\n/g, "\\n")}")`);
3683      if (!result.success) {
3684        ctx.ui.notify(`Failed: ${result.error}`, "error");
3685        return;
3686      }
3687      pi.sendMessage({
3688        customType: "org-todos-note",
3689        content: `## \uD83D\uDCDD Note Added
3690
3691**${heading}**
3692
3693> ${note}`,
3694        display: true
3695      });
3696    }
3697  });
3698  pi.registerCommand("inbox", {
3699    description: "View all inbox items (TODOs and links)",
3700    handler: async (args, ctx) => {
3701      const result = execEmacs(`(pi/org-todo-inbox-all)`);
3702      if (!result.success) {
3703        ctx.ui.notify(`Failed to fetch inbox: ${result.error}`, "error");
3704        return;
3705      }
3706      const todos = result.data?.filter((item) => item.todo) || [];
3707      const links = result.data?.filter((item) => !item.todo) || [];
3708      const lines = [];
3709      lines.push("## \uD83D\uDCE5 Inbox");
3710      lines.push("");
3711      if (!result.data || result.data.length === 0) {
3712        lines.push("*Inbox is empty* ✨");
3713      } else {
3714        lines.push(`*${result.data.length} item(s)* (${todos.length} tasks, ${links.length} links/notes)`);
3715        lines.push("");
3716        if (todos.length > 0) {
3717          lines.push("### ✅ Tasks");
3718          lines.push("");
3719          for (const todo of todos) {
3720            lines.push(`- ${formatTodoMarkdown(todo)}`);
3721          }
3722          lines.push("");
3723        }
3724        if (links.length > 0) {
3725          lines.push("### \uD83D\uDD17 Links & Notes");
3726          lines.push("");
3727          for (const item of links) {
3728            lines.push(`- ${stripOrgLinks(item.heading)}`);
3729          }
3730        }
3731      }
3732      pi.sendMessage({
3733        customType: "org-todos",
3734        content: lines.join(`
3735`),
3736        display: true
3737      });
3738    }
3739  });
3740  pi.registerCommand("inbox-add", {
3741    description: "Quick capture to inbox. Usage: /inbox-add <title> [scheduled:date] [priority:N]",
3742    handler: async (args, ctx) => {
3743      if (!args?.trim()) {
3744        ctx.ui.notify("Usage: /inbox-add <title> [scheduled:date] [priority:N]", "error");
3745        return;
3746      }
3747      const parsed = parseCommandArgs(args);
3748      if (!parsed.title) {
3749        ctx.ui.notify("Error: TODO title is required", "error");
3750        return;
3751      }
3752      const schedArg = parsed.scheduled ? `"${parsed.scheduled}"` : "nil";
3753      const prioArg = parsed.priority !== undefined ? parsed.priority : "nil";
3754      const elisp = `(with-current-buffer (find-file-noselect "${INBOX_FILE}")
3755        (goto-char (point-max))
3756        (insert "\\n* TODO ${parsed.title.replace(/"/g, "\\\"")}")
3757        ${parsed.scheduled ? `(org-schedule nil "${parsed.scheduled}")` : ""}
3758        ${parsed.priority !== undefined ? `(org-priority ${parsed.priority})` : ""}
3759        (save-buffer)
3760        (kill-buffer)
3761        (json-encode (list (cons 'success t))))`;
3762      const result = execEmacs(elisp);
3763      if (!result.success) {
3764        ctx.ui.notify(`Failed to add to inbox: ${result.error}`, "error");
3765        return;
3766      }
3767      const lines = [];
3768      lines.push(`## \uD83D\uDCE5 Added to Inbox`);
3769      lines.push("");
3770      lines.push(`**${parsed.title}**`);
3771      if (parsed.scheduled)
3772        lines.push(`- \uD83D\uDCC5 Scheduled: ${parsed.scheduled}`);
3773      if (parsed.priority)
3774        lines.push(`- Priority: #${parsed.priority}`);
3775      pi.sendMessage({
3776        customType: "org-todos-add",
3777        content: lines.join(`
3778`),
3779        display: true
3780      });
3781      updateInboxStatus(ctx);
3782      if (parsed.scheduled) {
3783        updateTodayStatus(ctx);
3784      }
3785    }
3786  });
3787  function fuzzyMatch(item, query) {
3788    if (!query)
3789      return true;
3790    const searchable = `${item.label} ${item.description || ""}`.toLowerCase();
3791    const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
3792    return terms.every((term) => searchable.includes(term));
3793  }
3794  async function showSelectMenu(ctx, title, allItems) {
3795    return ctx.ui.custom((tui, theme, _kb, done) => {
3796      let searchQuery = "";
3797      function getFilteredItems() {
3798        if (!searchQuery)
3799          return allItems;
3800        return allItems.filter((item) => fuzzyMatch(item, searchQuery));
3801      }
3802      let currentItems = getFilteredItems();
3803      const container = new Container;
3804      container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
3805      const headerText = new Text("", 0, 0);
3806      function updateHeader() {
3807        const titleStr = theme.fg("accent", theme.bold(title));
3808        if (searchQuery) {
3809          headerText.setText(`${titleStr}  ${theme.fg("warning", `filter: ${searchQuery}`)}`);
3810        } else {
3811          headerText.setText(titleStr);
3812        }
3813      }
3814      updateHeader();
3815      container.addChild(headerText);
3816      const listTheme = {
3817        selectedPrefix: (text) => theme.fg("accent", text),
3818        selectedText: (text) => theme.fg("accent", text),
3819        description: (text) => theme.fg("muted", text),
3820        scrollInfo: (text) => theme.fg("dim", text),
3821        noMatch: (text) => theme.fg("warning", text)
3822      };
3823      let selectList = new SelectList(currentItems, Math.min(currentItems.length, 15), listTheme);
3824      selectList.onSelect = (item) => done(item.value);
3825      selectList.onCancel = () => done(null);
3826      container.addChild(selectList);
3827      container.addChild(new Text(theme.fg("dim", "Type to filter · enter to confirm · esc to cancel")));
3828      container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
3829      function rebuildList() {
3830        currentItems = getFilteredItems();
3831        const newList = new SelectList(currentItems, Math.min(currentItems.length, 15), listTheme);
3832        newList.onSelect = (item) => done(item.value);
3833        newList.onCancel = () => done(null);
3834        const idx = container.children.indexOf(selectList);
3835        if (idx !== -1)
3836          container.children[idx] = newList;
3837        selectList = newList;
3838        updateHeader();
3839      }
3840      return {
3841        render(width) {
3842          return container.render(width);
3843        },
3844        invalidate() {
3845          container.invalidate();
3846        },
3847        handleInput(data) {
3848          if (data === "" || data === "\b") {
3849            if (searchQuery.length > 0) {
3850              searchQuery = searchQuery.slice(0, -1);
3851              rebuildList();
3852              tui.requestRender();
3853            }
3854            return;
3855          }
3856          if (data.length === 1 && data >= " " && data <= "~") {
3857            searchQuery += data;
3858            rebuildList();
3859            tui.requestRender();
3860            return;
3861          }
3862          selectList.handleInput(data);
3863          tui.requestRender();
3864        }
3865      };
3866    });
3867  }
3868  pi.registerCommand("inbox-refile", {
3869    description: "Refile inbox item to a section (interactive)",
3870    handler: async (args, ctx) => {
3871      const inboxResult = execEmacs(`(pi/org-todo-inbox-all)`);
3872      if (!inboxResult.success || !inboxResult.data || inboxResult.data.length === 0) {
3873        ctx.ui.notify("Inbox is empty!", "info");
3874        return;
3875      }
3876      let heading = (args || "").trim();
3877      let sourcePosition = null;
3878      if (!heading) {
3879        const inboxItems = inboxResult.data.map((item, i) => {
3880          const prefix = item.todo ? `[${item.todo}] ` : "";
3881          const label = stripOrgLinks(`${prefix}${item.heading}`);
3882          return {
3883            value: String(i),
3884            label,
3885            description: item.todo ? undefined : "link/note"
3886          };
3887        });
3888        const selectedIdx = await showSelectMenu(ctx, "Select inbox item to refile", inboxItems);
3889        if (selectedIdx === null) {
3890          ctx.ui.notify("Refile cancelled", "info");
3891          return;
3892        }
3893        const sourceItem = inboxResult.data[parseInt(selectedIdx, 10)];
3894        heading = sourceItem.heading;
3895        sourcePosition = sourceItem.position;
3896      }
3897      const targetsResult = execEmacs("(pi/org-todo-get-refile-targets)");
3898      if (!targetsResult.success || !targetsResult.data) {
3899        ctx.ui.notify("Failed to get refile targets", "error");
3900        return;
3901      }
3902      const sectionItems = targetsResult.data.map((t, i) => {
3903        const indent = t.level > 1 ? "  ".repeat(t.level - 1) : "";
3904        return {
3905          value: String(i),
3906          label: `${indent}${stripOrgLinks(t.section)}`,
3907          description: t.level > 1 ? stripOrgLinks(t.path) : undefined
3908        };
3909      });
3910      const displayHeading = stripOrgLinks(heading).slice(0, 60);
3911      const targetIdx = await showSelectMenu(ctx, `Refile "${displayHeading}" to:`, sectionItems);
3912      if (targetIdx === null) {
3913        ctx.ui.notify("Refile cancelled", "info");
3914        return;
3915      }
3916      const target = targetsResult.data[parseInt(targetIdx, 10)];
3917      const srcPosArg = sourcePosition ? ` ${sourcePosition}` : "";
3918      const refileResult = execEmacs(`(pi/org-todo-refile "${heading.replace(/"/g, "\\\"")}" "${target.section.replace(/"/g, "\\\"")}" nil nil ${target.position}${srcPosArg})`);
3919      if (!refileResult.success) {
3920        ctx.ui.notify(`Refile failed: ${refileResult.error}`, "error");
3921        return;
3922      }
3923      const displayTarget = stripOrgLinks(target.path || target.section);
3924      pi.sendMessage({
3925        customType: "org-todos",
3926        content: `## ✅ Refiled
3927
3928**${displayHeading}** → *${displayTarget}*`,
3929        display: true
3930      });
3931      updateInboxStatus(ctx);
3932    }
3933  });
3934  function updateInboxStatus(ctx) {
3935    try {
3936      const result = execEmacs(`(pi/org-todo-inbox-all)`);
3937      if (result.success && Array.isArray(result.data)) {
3938        const count = result.data.length;
3939        if (count > 0) {
3940          ctx.ui.setStatus("inbox-count", ctx.ui.theme.fg("warning", `\uD83D\uDCE5 ${count}`));
3941        } else {
3942          ctx.ui.setStatus("inbox-count", undefined);
3943        }
3944      }
3945    } catch (e) {}
3946  }
3947  function updateTodayStatus(ctx) {
3948    try {
3949      const scheduledResult = execEmacs("(pi/org-todo-scheduled)");
3950      const overdueResult = execEmacs("(pi/org-todo-overdue)");
3951      if (scheduledResult.success && overdueResult.success) {
3952        const schedCount = Array.isArray(scheduledResult.data) ? scheduledResult.data.length : 0;
3953        const overdueCount = Array.isArray(overdueResult.data) ? overdueResult.data.length : 0;
3954        if (schedCount === 0 && overdueCount === 0) {
3955          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("success", "✓"));
3956        } else if (overdueCount > 0 && schedCount > 0) {
3957          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("error", `⚠️ ${overdueCount}`) + " " + ctx.ui.theme.fg("accent", `\uD83D\uDCC5 ${schedCount}`));
3958        } else if (overdueCount > 0) {
3959          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("error", `⚠️ ${overdueCount}`));
3960        } else {
3961          ctx.ui.setStatus("today-todos", ctx.ui.theme.fg("accent", `\uD83D\uDCC5 ${schedCount}`));
3962        }
3963      }
3964    } catch (e) {}
3965  }
3966  pi.on("session_start", async (_event, ctx) => {
3967    updateInboxStatus(ctx);
3968    updateTodayStatus(ctx);
3969    const updateInterval = setInterval(() => {
3970      updateInboxStatus(ctx);
3971      updateTodayStatus(ctx);
3972    }, 5 * 60 * 1000);
3973    pi.on("session_end", async () => {
3974      clearInterval(updateInterval);
3975    });
3976  });
3977}
3978export {
3979  org_todos_default as default
3980};