@wirecat/cli-memo 0.131.45 → 0.131.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/bin/memo.js +2 -2
  2. package/dist/bundle/{all-profiles-ZBASDAVU.js → all-profiles-75EGCXK3.js} +5 -5
  3. package/dist/bundle/{anthropic-3ZS3RCUH.js → anthropic-PTAYBCPR.js} +3 -3
  4. package/dist/bundle/{app-server-PQF22PMD.js → app-server-YSUBXGGB.js} +41 -38
  5. package/dist/bundle/auto-GB35FRTV.js +86 -0
  6. package/dist/bundle/{bun-3CGVV3V2.js → bun-3AIG5ML4.js} +2 -2
  7. package/dist/bundle/{bun-sqlite-D6T3ESTG.js → bun-sqlite-5FCGI6EO.js} +2 -2
  8. package/dist/bundle/{chunk-CAPDRDQU.js → chunk-25RDNYKZ.js} +5 -5
  9. package/dist/bundle/{chunk-L45FSDH3.js → chunk-32QM6X5H.js} +1 -1
  10. package/dist/bundle/{chunk-NB267XRJ.js → chunk-3HPFTKDH.js} +4 -4
  11. package/dist/bundle/{chunk-UP2K5XUA.js → chunk-4LWX2WOB.js} +3 -3
  12. package/dist/bundle/{chunk-TVZEELSS.js → chunk-5N6HWFXN.js} +508 -338
  13. package/dist/bundle/{chunk-SK3TPK5Y.js → chunk-6IVHND3S.js} +4 -4
  14. package/dist/bundle/{chunk-75EEQB2R.js → chunk-6QNPOBR5.js} +11 -11
  15. package/dist/bundle/{chunk-75RJJQ2Q.js → chunk-6TKWJKPS.js} +10 -10
  16. package/dist/bundle/{chunk-CH37NCAP.js → chunk-BNIWLVWG.js} +3 -3
  17. package/dist/bundle/{chunk-IQ2MW47B.js → chunk-CODD5SXC.js} +27 -27
  18. package/dist/bundle/{chunk-HAPE26JK.js → chunk-DDADFHR7.js} +12 -12
  19. package/dist/bundle/{chunk-CGJFYMVZ.js → chunk-DMTLG2GD.js} +7 -7
  20. package/dist/bundle/{chunk-GOJZ3FQY.js → chunk-DS4DOK75.js} +22 -21
  21. package/dist/bundle/{chunk-PMUAUR5S.js → chunk-DWBTCOF2.js} +4 -4
  22. package/dist/bundle/{chunk-5IYS3BWO.js → chunk-EFQCDCLY.js} +56 -56
  23. package/dist/bundle/{chunk-IYJGFBNN.js → chunk-ELKK5M66.js} +5 -5
  24. package/dist/bundle/{chunk-YDNM5KYV.js → chunk-EVZI54B5.js} +4 -4
  25. package/dist/bundle/{chunk-GTPWWGQI.js → chunk-F4HMPMET.js} +7 -7
  26. package/dist/bundle/{chunk-2OYB4PWV.js → chunk-FSAMZHIM.js} +5 -5
  27. package/dist/bundle/{chunk-G3FRUKAD.js → chunk-G3YSCD77.js} +182 -158
  28. package/dist/bundle/{chunk-NTFEJ52I.js → chunk-G4W42RGE.js} +1 -1
  29. package/dist/bundle/{chunk-7EA6M6RA.js → chunk-GA3KFYEZ.js} +4 -4
  30. package/dist/bundle/{chunk-CXRCADXS.js → chunk-GOFPCOEI.js} +9 -9
  31. package/dist/bundle/{chunk-65MK55RS.js → chunk-GQLSVXS2.js} +20 -20
  32. package/dist/bundle/{chunk-YWTWDX4F.js → chunk-HCZV537M.js} +1 -1
  33. package/dist/bundle/{chunk-OMBFF6Z6.js → chunk-HVTW2M6T.js} +1 -1
  34. package/dist/bundle/{chunk-EJ2PEYQU.js → chunk-HYEYRFWX.js} +1 -1
  35. package/dist/bundle/{chunk-AOSSO4YI.js → chunk-I2RDACUF.js} +6 -6
  36. package/dist/bundle/{chunk-KE3CYUON.js → chunk-ILK5BCBB.js} +1 -1
  37. package/dist/bundle/{chunk-U4J7TAOW.js → chunk-IPLPMD6H.js} +1 -1
  38. package/dist/bundle/{chunk-7WJEQ36E.js → chunk-IPMBB6W5.js} +2 -2
  39. package/dist/bundle/{chunk-ZJXAYYLF.js → chunk-J324GKJM.js} +1 -1
  40. package/dist/bundle/{chunk-PXSGUVZP.js → chunk-KLBZJZD2.js} +637 -119
  41. package/dist/bundle/{chunk-FMMIPFTU.js → chunk-KWM7HLAI.js} +4 -4
  42. package/dist/bundle/{chunk-CRLYBXV5.js → chunk-LE7NROV6.js} +43 -36
  43. package/dist/bundle/{chunk-25MS26SH.js → chunk-MCMEBL3C.js} +23 -10
  44. package/dist/bundle/{chunk-FRT7URL7.js → chunk-MMJDQQFX.js} +483 -282
  45. package/dist/bundle/{chunk-TKFG75MJ.js → chunk-MSBRZ5QD.js} +2 -2
  46. package/dist/bundle/{chunk-IJBJ47GI.js → chunk-N5QQFDNV.js} +2 -2
  47. package/dist/bundle/{chunk-B4PZQYGP.js → chunk-N63KZFH4.js} +8 -8
  48. package/dist/bundle/{chunk-NBA3GJBR.js → chunk-OSCRP52P.js} +805 -347
  49. package/dist/bundle/{chunk-GBRK3WXY.js → chunk-PGVADNDD.js} +2 -2
  50. package/dist/bundle/{chunk-HXCSD2XV.js → chunk-R44PUK7G.js} +1 -1
  51. package/dist/bundle/{chunk-F2VTAFIT.js → chunk-SYTYLLYO.js} +1 -1
  52. package/dist/bundle/{chunk-MKVUBQEG.js → chunk-U35N3EC7.js} +1 -1
  53. package/dist/bundle/{chunk-5ZHM6SZW.js → chunk-U75ANK5K.js} +1 -1
  54. package/dist/bundle/{chunk-7G7N3IUO.js → chunk-UE4GMPBY.js} +4 -2
  55. package/dist/bundle/{chunk-OTOKJAYR.js → chunk-UFVGAFID.js} +3 -3
  56. package/dist/bundle/{chunk-OT4CLMVF.js → chunk-V3B5COFP.js} +3 -3
  57. package/dist/bundle/{chunk-6NQTGFAL.js → chunk-V6OYLCCM.js} +2 -2
  58. package/dist/bundle/{chunk-IAPKZSC5.js → chunk-W2JVP7GK.js} +1 -1
  59. package/dist/bundle/{chunk-LL3Z6KA3.js → chunk-W3T45MMN.js} +5 -5
  60. package/dist/bundle/{chunk-EJ4X6XH2.js → chunk-XRRPQCTS.js} +1 -1
  61. package/dist/bundle/{chunk-G6TRTDHB.js → chunk-Y4ZXDJQF.js} +2 -2
  62. package/dist/bundle/{chunk-WGX73SAA.js → chunk-YMK35KVV.js} +2 -2
  63. package/dist/bundle/{chunk-7G63XPDR.js → chunk-ZKH6LC5P.js} +7 -7
  64. package/dist/bundle/{chunk-C6GSSMDG.js → chunk-ZLIARJU4.js} +1 -1
  65. package/dist/bundle/{command-contract-K3GJRRXT.js → command-contract-YYILWWYQ.js} +11 -11
  66. package/dist/bundle/{decode-TTMBMSGQ.js → decode-F2A2BLIA.js} +2 -2
  67. package/dist/bundle/{echarts-7XN2RLJT.js → echarts-JL55HJCM.js} +2 -2
  68. package/dist/bundle/{embed-UKTHDQH5.js → embed-74KVORNN.js} +3 -3
  69. package/dist/bundle/{embedder-SCKLAVKW.js → embedder-GACNPCZN.js} +6 -6
  70. package/dist/bundle/{entry-VQRYB2HE.js → entry-7FI2H4RQ.js} +4 -4
  71. package/dist/bundle/failure-AHPPXHAW.js +66 -0
  72. package/dist/bundle/{first-run-RL6ZRY3Y.js → first-run-D4VBIJ7H.js} +5 -5
  73. package/dist/bundle/{first-screen-CRURWNKP.js → first-screen-D7Q2U7VP.js} +12 -12
  74. package/dist/bundle/{instructions-KGU67SPR.js → instructions-QNPIVGKX.js} +1 -1
  75. package/dist/bundle/{mcp-CSN7BDNG.js → mcp-AFXHH33V.js} +35 -35
  76. package/dist/bundle/memo.js +6 -6
  77. package/dist/bundle/{node-S5LQLVMO.js → node-SPFML2D5.js} +2 -2
  78. package/dist/bundle/{node-sqlite-PFCIEDPX.js → node-sqlite-T3KILRCP.js} +3 -3
  79. package/dist/bundle/{oauth-KJOGYDPV.js → oauth-ZOGSHZF3.js} +4 -4
  80. package/dist/bundle/{open-TPBENKAD.js → open-XXFVCGCA.js} +2 -2
  81. package/dist/bundle/{openai-UOYTHO32.js → openai-JRHZLFKD.js} +7 -7
  82. package/dist/bundle/{process-JWKE7GPV.js → process-OGYYVVLG.js} +1 -1
  83. package/dist/bundle/{program-RJ6X4DXE.js → program-EFCQACPD.js} +138 -61
  84. package/dist/bundle/{prompt-5HQ3Z7ZS.js → prompt-53D5WVD3.js} +2 -2
  85. package/dist/bundle/{recognize-5ILXEPII.js → recognize-7GYZKJCD.js} +1 -1
  86. package/dist/bundle/{remote-WIN3HJII.js → remote-V5GUFZCG.js} +4 -4
  87. package/dist/bundle/{rerank-JKHDSEBI.js → rerank-FUNVBYFI.js} +4 -4
  88. package/dist/bundle/{serve-VMHFRDYH.js → serve-ZLUYFAXC.js} +6 -6
  89. package/dist/bundle/server-4OJC7ZWM.js +61 -0
  90. package/dist/bundle/server-CGUUZBLB.js +48 -0
  91. package/dist/bundle/{server-TKWVP4OJ.js → server-HJRMD3XD.js} +50 -50
  92. package/dist/bundle/{state-OWOLD7JI.js → state-4P7H6KBM.js} +3 -3
  93. package/dist/bundle/{store-6GFFSNRY.js → store-NILJK24C.js} +11 -9
  94. package/dist/bundle/store-maintenance-command-VP7CIBSS.js +48 -0
  95. package/dist/bundle/update-NPK4DT2E.js +69 -0
  96. package/dist/contract-overrides/doctor.d.ts.map +1 -1
  97. package/dist/contract-overrides/doctor.js +6 -0
  98. package/dist/contract-overrides/doctor.js.map +1 -1
  99. package/dist/doctor/command.d.ts +23 -2
  100. package/dist/doctor/command.d.ts.map +1 -1
  101. package/dist/doctor/command.js +13 -5
  102. package/dist/doctor/command.js.map +1 -1
  103. package/dist/examples.d.ts.map +1 -1
  104. package/dist/examples.js +2 -0
  105. package/dist/examples.js.map +1 -1
  106. package/dist/schedule/command.d.ts.map +1 -1
  107. package/dist/schedule/command.js +2 -0
  108. package/dist/schedule/command.js.map +1 -1
  109. package/dist/schedule/mail-triage-input.d.ts +24 -0
  110. package/dist/schedule/mail-triage-input.d.ts.map +1 -0
  111. package/dist/schedule/mail-triage-input.js +53 -0
  112. package/dist/schedule/mail-triage-input.js.map +1 -0
  113. package/dist/store/info-command.d.ts.map +1 -1
  114. package/dist/store/info-command.js +23 -1
  115. package/dist/store/info-command.js.map +1 -1
  116. package/dist/version.d.ts +1 -1
  117. package/dist/version.js +1 -1
  118. package/package.json +3 -3
  119. package/skills/mail-triage/SKILL.md +25 -27
  120. package/dist/bundle/auto-NW7IP4ST.js +0 -86
  121. package/dist/bundle/failure-JHW2U2OF.js +0 -66
  122. package/dist/bundle/server-IBJ23GCB.js +0 -48
  123. package/dist/bundle/server-SNWCFMJN.js +0 -61
  124. package/dist/bundle/store-maintenance-command-7DMPWFT4.js +0 -48
  125. package/dist/bundle/update-KSB7VYAW.js +0 -69
  126. /package/dist/bundle/{chunk-DL5LDAOS.js → chunk-JPGEFBRW.js} +0 -0
@@ -3,13 +3,16 @@ const require = __bundleRequire(import.meta.url);
3
3
  import {
4
4
  answerOf,
5
5
  messengerContext
6
- } from "./chunk-65MK55RS.js";
6
+ } from "./chunk-GQLSVXS2.js";
7
7
  import {
8
8
  FETCHING,
9
+ QUICK_HEALTH_CHECKS,
9
10
  RULES_VERSION,
10
11
  applyTaskRulesOnArrival,
11
12
  capability,
12
13
  chatEventAnswer,
14
+ explainDamage,
15
+ fts5Tables,
13
16
  memberAnswer,
14
17
  newSendId,
15
18
  onlineDeps,
@@ -20,11 +23,12 @@ import {
20
23
  senderIsMe,
21
24
  serveRelay,
22
25
  servicesFor,
26
+ storeHealth,
23
27
  syncsOneChat,
24
28
  typedQuery,
25
29
  withQuery,
26
30
  withTimeLimit
27
- } from "./chunk-TVZEELSS.js";
31
+ } from "./chunk-5N6HWFXN.js";
28
32
  import {
29
33
  stringWidth,
30
34
  wrapAnsi
@@ -56,30 +60,35 @@ import {
56
60
  snakeKeys,
57
61
  storeTable,
58
62
  withoutProviderRefs
59
- } from "./chunk-G3FRUKAD.js";
63
+ } from "./chunk-G3YSCD77.js";
60
64
  import {
61
65
  failureKey
62
- } from "./chunk-7G63XPDR.js";
66
+ } from "./chunk-ZKH6LC5P.js";
63
67
  import {
64
68
  envName
65
- } from "./chunk-F2VTAFIT.js";
69
+ } from "./chunk-SYTYLLYO.js";
66
70
  import {
67
71
  holdLock,
68
72
  lockPath,
69
73
  releaseLock,
70
74
  servingProfiles,
71
75
  takeLock
72
- } from "./chunk-TKFG75MJ.js";
76
+ } from "./chunk-MSBRZ5QD.js";
73
77
  import {
74
78
  holdersOf
75
- } from "./chunk-IAPKZSC5.js";
79
+ } from "./chunk-W2JVP7GK.js";
76
80
  import {
81
+ CORPORA,
77
82
  MIGRATIONS,
83
+ drainCorpus,
84
+ drainMeetingIndex,
78
85
  drainNoteIndex,
79
86
  dropAllUnusedVectors,
80
87
  fileFacts,
81
88
  fillSearchIndex,
82
89
  fillStems,
90
+ fillTrigrams,
91
+ fillVectorIndexes,
83
92
  formatLocator,
84
93
  involvementStoreOver,
85
94
  migrate,
@@ -90,10 +99,12 @@ import {
90
99
  parseLocator,
91
100
  pendingNormalization,
92
101
  readStoreTables,
102
+ rebuildMentions,
93
103
  resetAttachmentWords,
94
104
  resetNoteIndex,
95
105
  resetSearchIndex,
96
106
  resetStems,
107
+ rollBack,
97
108
  rowCounts,
98
109
  searchIndexState,
99
110
  stemmerCache,
@@ -101,28 +112,28 @@ import {
101
112
  storeClients,
102
113
  storeContents,
103
114
  vectorIndexCounts
104
- } from "./chunk-NBA3GJBR.js";
115
+ } from "./chunk-OSCRP52P.js";
105
116
  import {
106
117
  queryFieldsOf
107
- } from "./chunk-5IYS3BWO.js";
118
+ } from "./chunk-EFQCDCLY.js";
108
119
  import {
109
120
  readSecret
110
- } from "./chunk-6NQTGFAL.js";
121
+ } from "./chunk-V6OYLCCM.js";
111
122
  import {
112
123
  checkedOptions,
113
124
  range
114
- } from "./chunk-L45FSDH3.js";
125
+ } from "./chunk-32QM6X5H.js";
115
126
  import {
116
127
  messagesFor,
117
128
  systemFor,
118
129
  validateImages
119
- } from "./chunk-MKVUBQEG.js";
130
+ } from "./chunk-U35N3EC7.js";
120
131
  import {
121
132
  storePath
122
- } from "./chunk-U4J7TAOW.js";
133
+ } from "./chunk-IPLPMD6H.js";
123
134
  import {
124
135
  openCache
125
- } from "./chunk-CAPDRDQU.js";
136
+ } from "./chunk-25RDNYKZ.js";
126
137
  import {
127
138
  Credentials,
128
139
  pathsAreOverridden,
@@ -1811,7 +1822,7 @@ var require_liquid_node = __commonJS({
1811
1822
  return readFileAsync(filepath, "utf8");
1812
1823
  }
1813
1824
  __name(readFile, "readFile");
1814
- function existsSync8(filepath) {
1825
+ function existsSync10(filepath) {
1815
1826
  try {
1816
1827
  fs$1.statSync(filepath);
1817
1828
  return true;
@@ -1819,11 +1830,11 @@ var require_liquid_node = __commonJS({
1819
1830
  return false;
1820
1831
  }
1821
1832
  }
1822
- __name(existsSync8, "existsSync");
1823
- function readFileSync4(filepath) {
1833
+ __name(existsSync10, "existsSync");
1834
+ function readFileSync5(filepath) {
1824
1835
  return fs$1.readFileSync(filepath, "utf8");
1825
1836
  }
1826
- __name(readFileSync4, "readFileSync");
1837
+ __name(readFileSync5, "readFileSync");
1827
1838
  function resolve2(root, file2, ext) {
1828
1839
  if (!path.extname(file2))
1829
1840
  file2 += ext;
@@ -1837,10 +1848,10 @@ var require_liquid_node = __commonJS({
1837
1848
  }
1838
1849
  }
1839
1850
  __name(fallback, "fallback");
1840
- function dirname2(filepath) {
1851
+ function dirname3(filepath) {
1841
1852
  return path.dirname(filepath);
1842
1853
  }
1843
- __name(dirname2, "dirname");
1854
+ __name(dirname3, "dirname");
1844
1855
  var realpathAsync = promisify(fs$1.realpath);
1845
1856
  async function contains(root, file2) {
1846
1857
  try {
@@ -1868,11 +1879,11 @@ var require_liquid_node = __commonJS({
1868
1879
  __proto__: null,
1869
1880
  exists,
1870
1881
  readFile,
1871
- existsSync: existsSync8,
1872
- readFileSync: readFileSync4,
1882
+ existsSync: existsSync10,
1883
+ readFileSync: readFileSync5,
1873
1884
  resolve: resolve2,
1874
1885
  fallback,
1875
- dirname: dirname2,
1886
+ dirname: dirname3,
1876
1887
  contains,
1877
1888
  containsSync,
1878
1889
  sep: path.sep
@@ -3597,7 +3608,7 @@ var require_liquid_node = __commonJS({
3597
3608
  uri_escape,
3598
3609
  slugify
3599
3610
  });
3600
- var join4 = argumentsToValue(function(v, arg) {
3611
+ var join5 = argumentsToValue(function(v, arg) {
3601
3612
  const array2 = toArray(v);
3602
3613
  const sep = isNil(arg) ? " " : stringify(arg);
3603
3614
  let outputSize = sep.length * Math.max(array2.length - 1, 0);
@@ -3873,7 +3884,7 @@ var require_liquid_node = __commonJS({
3873
3884
  __name(sample, "sample");
3874
3885
  var arrayFilters = /* @__PURE__ */ Object.freeze({
3875
3886
  __proto__: null,
3876
- join: join4,
3887
+ join: join5,
3877
3888
  last,
3878
3889
  first,
3879
3890
  reverse,
@@ -4801,15 +4812,15 @@ var require_liquid_node = __commonJS({
4801
4812
  }
4802
4813
  *render(ctx, emitter) {
4803
4814
  const group = yield evalToken(this.group, ctx);
4804
- const fingerprint = `cycle:${group}:` + this.candidates.join(",");
4815
+ const fingerprint2 = `cycle:${group}:` + this.candidates.join(",");
4805
4816
  const groups = ctx.getRegister("cycle", {});
4806
- let idx = groups[fingerprint];
4817
+ let idx = groups[fingerprint2];
4807
4818
  if (idx === void 0) {
4808
- idx = groups[fingerprint] = 0;
4819
+ idx = groups[fingerprint2] = 0;
4809
4820
  }
4810
4821
  const candidate = this.candidates[idx];
4811
4822
  idx = (idx + 1) % this.candidates.length;
4812
- groups[fingerprint] = idx;
4823
+ groups[fingerprint2] = idx;
4813
4824
  return yield evalToken(candidate, ctx);
4814
4825
  }
4815
4826
  *arguments() {
@@ -5497,11 +5508,11 @@ var require_liquid_node = __commonJS({
5497
5508
  }
5498
5509
  });
5499
5510
 
5500
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/store-maintenance-command.js
5501
- import { chmodSync, constants, copyFileSync, existsSync as existsSync7, mkdirSync, realpathSync, renameSync as renameSync2, rmSync as rmSync2, statfsSync, statSync as statSync3, writeFileSync } from "node:fs";
5502
- import { dirname, resolve } from "node:path";
5511
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/store-maintenance-command.js
5512
+ import { chmodSync, constants, copyFileSync, existsSync as existsSync9, mkdirSync, realpathSync as realpathSync2, renameSync as renameSync3, rmSync as rmSync3, statfsSync as statfsSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "node:fs";
5513
+ import { dirname as dirname2, resolve } from "node:path";
5503
5514
 
5504
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/sealed.js
5515
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/sealed.js
5505
5516
  import { createCipheriv, createDecipheriv, createHash, randomBytes, scrypt, timingSafeEqual } from "node:crypto";
5506
5517
  import { closeSync, createReadStream, createWriteStream, existsSync, openSync, readSync, renameSync, rmSync, statSync } from "node:fs";
5507
5518
  import { Transform } from "node:stream";
@@ -5608,7 +5619,7 @@ var unsealFile = /* @__PURE__ */ __name(async (from, to, password) => {
5608
5619
  renameSync(pending, to);
5609
5620
  }, "unsealFile");
5610
5621
 
5611
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/store/compatibility.js
5622
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/store/compatibility.js
5612
5623
  var SPEAKS = MIGRATIONS.at(-1)?.version ?? 0;
5613
5624
  var fileSchemaOf = /* @__PURE__ */ __name((database) => {
5614
5625
  const tracked = database.prepare("SELECT 1 FROM sqlite_master WHERE name = 'schema_migrations'").get();
@@ -5632,7 +5643,7 @@ var compatibilityOf = /* @__PURE__ */ __name((file2, migrations = MIGRATIONS) =>
5632
5643
  };
5633
5644
  }, "compatibilityOf");
5634
5645
 
5635
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/store/repair.js
5646
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/store/repair.js
5636
5647
  import { createHash as createHash2 } from "node:crypto";
5637
5648
  var COPY_MARK = "__repair_";
5638
5649
  var COPY_NAME = /__repair_[0-9a-f]{8}(_\d+)?$/;
@@ -5886,10 +5897,457 @@ var deleteCopy = /* @__PURE__ */ __name((database, name) => {
5886
5897
  return found;
5887
5898
  }, "deleteCopy");
5888
5899
 
5889
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/store-info.js
5890
- import { existsSync as existsSync2, statSync as statSync2 } from "node:fs";
5900
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/store-info.js
5901
+ import { existsSync as existsSync4, statSync as statSync3 } from "node:fs";
5902
+
5903
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/store-recover.js
5904
+ import { existsSync as existsSync3 } from "node:fs";
5905
+
5906
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/store/recover.js
5907
+ import { execFileSync, spawn } from "node:child_process";
5908
+ import { existsSync as existsSync2, readFileSync, realpathSync, renameSync as renameSync2, rmSync as rmSync2, statfsSync, statSync as statSync2, writeFileSync } from "node:fs";
5909
+ import { basename, dirname, join } from "node:path";
5910
+ import { Transform as Transform2 } from "node:stream";
5911
+ var SQLITE3_MINIMUM = [3, 43, 0];
5912
+ var STORE_PARTS = ["", "-wal", "-shm"];
5913
+ var INSERTED = /^INSERT OR IGNORE INTO '([^']+)'/;
5914
+ var LOST_AND_FOUND = "recover_lost_and_found";
5915
+ var recovers = /* @__PURE__ */ __name((program) => {
5916
+ try {
5917
+ execFileSync(program, [":memory:", ".recover"], { stdio: ["ignore", "ignore", "pipe"] });
5918
+ return true;
5919
+ } catch {
5920
+ return false;
5921
+ }
5922
+ }, "recovers");
5923
+ var sqlite3Program = /* @__PURE__ */ __name((program = "sqlite3") => {
5924
+ let version = null;
5925
+ try {
5926
+ version = execFileSync(program, ["--version"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).split(" ")[0] ?? null;
5927
+ } catch {
5928
+ return { program, version: null, usable: false };
5929
+ }
5930
+ const parts2 = (version ?? "").split(".").map(Number);
5931
+ const at = SQLITE3_MINIMUM.findIndex((wanted, i) => (parts2[i] ?? 0) !== wanted);
5932
+ const recent = at === -1 || (parts2[at] ?? 0) > (SQLITE3_MINIMUM[at] ?? 0);
5933
+ return { program, version, usable: recent && recovers(program) };
5934
+ }, "sqlite3Program");
5935
+ var activeTimers = /* @__PURE__ */ __name(() => {
5936
+ if (process.platform !== "linux")
5937
+ return void 0;
5938
+ try {
5939
+ return execFileSync("systemctl", ["--user", "list-timers", "--plain", "--no-legend"], {
5940
+ encoding: "utf8",
5941
+ stdio: ["ignore", "pipe", "ignore"]
5942
+ }).split("\n").map((line) => line.trim().split(/\s+/).at(-2) ?? "").filter((unit) => /^(memo|mail|tg|max|whatsapp|zoom|drive|gcal|wirecat)-.*\.timer$/.test(unit));
5943
+ } catch {
5944
+ return void 0;
5945
+ }
5946
+ }, "activeTimers");
5947
+ var storeHolders = /* @__PURE__ */ __name((path) => {
5948
+ const folder = realpathSync(dirname(path));
5949
+ const files = STORE_PARTS.map((suffix) => join(folder, `${basename(path)}${suffix}`));
5950
+ const wanted = process.platform === "linux" ? files.flatMap((file2) => [file2, `${file2} (deleted)`]) : files.filter(existsSync2);
5951
+ return holdersOf(wanted)?.map((pid) => {
5952
+ let name = "?";
5953
+ try {
5954
+ name = readFileSync(`/proc/${pid}/comm`, "utf8").trim();
5955
+ } catch {
5956
+ }
5957
+ return { pid, name };
5958
+ });
5959
+ }, "storeHolders");
5960
+ var tableRows = /* @__PURE__ */ __name((database) => {
5961
+ const indexes = fts5Tables(database).map((index) => index.name);
5962
+ const tables = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND rootpage > 0 AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'vector_index_%' ORDER BY name").all().map((row) => String(row.name)).filter((name) => !indexes.some((index) => name.startsWith(`${index}_`)));
5963
+ return Object.fromEntries(tables.map((table) => {
5964
+ try {
5965
+ return [table, Number(database.prepare(`SELECT count(*) AS n FROM "${table}"`).get()?.n)];
5966
+ } catch {
5967
+ return [table, null];
5968
+ }
5969
+ }));
5970
+ }, "tableRows");
5971
+ var copyReadableRows = /* @__PURE__ */ __name((path, target, program = "sqlite3") => new Promise((resolve2, reject) => {
5972
+ const reader = spawn(program, ["-readonly", path, `.recover --ignore-freelist --lost-and-found ${LOST_AND_FOUND}`], {
5973
+ stdio: ["ignore", "pipe", "pipe"]
5974
+ });
5975
+ const writer = spawn(program, ["-cmd", ".dbconfig defensive off", target], { stdio: ["pipe", "ignore", "pipe"] });
5976
+ const errors = [];
5977
+ const collect = /* @__PURE__ */ __name((chunk) => {
5978
+ for (const line of chunk.toString("utf8").split("\n"))
5979
+ if (line && errors.length < 50)
5980
+ errors.push(line.slice(0, 300));
5981
+ }, "collect");
5982
+ reader.stderr.on("data", collect);
5983
+ writer.stderr.on("data", collect);
5984
+ const read = {};
5985
+ let rest = "";
5986
+ const counter = new Transform2({
5987
+ transform(chunk, _encoding, done) {
5988
+ const lines = (rest + chunk.toString("latin1")).split("\n");
5989
+ rest = lines.pop() ?? "";
5990
+ for (const line of lines) {
5991
+ const table = INSERTED.exec(line)?.[1];
5992
+ if (table)
5993
+ read[table] = (read[table] ?? 0) + 1;
5994
+ }
5995
+ done(null, chunk);
5996
+ }
5997
+ });
5998
+ reader.stdout.pipe(counter).pipe(writer.stdin);
5999
+ let exits = 0;
6000
+ let readerCode = null;
6001
+ const exited = /* @__PURE__ */ __name(() => {
6002
+ exits += 1;
6003
+ if (exits < 2)
6004
+ return;
6005
+ if (readerCode !== 0)
6006
+ reject(new CliError("validation_error", `sqlite3 could not read the store: ${errors.join("; ")}`));
6007
+ else
6008
+ resolve2({ errors, read });
6009
+ }, "exited");
6010
+ reader.on("error", reject);
6011
+ writer.on("error", reject);
6012
+ reader.on("close", (code) => {
6013
+ readerCode = code;
6014
+ exited();
6015
+ });
6016
+ writer.on("close", exited);
6017
+ }), "copyReadableRows");
6018
+ var FILLERS = {
6019
+ message_words: /* @__PURE__ */ __name((database, now) => {
6020
+ resetSearchIndex(database);
6021
+ fillSearchIndex(database, { now });
6022
+ }, "message_words"),
6023
+ message_stems: /* @__PURE__ */ __name((database, now) => {
6024
+ resetStems(database, { force: true, now });
6025
+ fillStems(database, { now });
6026
+ }, "message_stems"),
6027
+ attachment_words: /* @__PURE__ */ __name((database) => void resetAttachmentWords(database), "attachment_words"),
6028
+ attachment_name_words: /* @__PURE__ */ __name((database) => (
6029
+ // As migration 20 filled it: й and ё fold as the triggers fold them.
6030
+ database.exec("INSERT INTO attachment_name_words (rowid, name) SELECT id, replace(replace(replace(replace(name, '\u0439', '\u0438'), '\u0419', '\u0418'), '\u0451', '\u0435'), '\u0401', '\u0415') FROM attachments WHERE name IS NOT NULL")
6031
+ ), "attachment_name_words"),
6032
+ meeting_words: /* @__PURE__ */ __name((database) => {
6033
+ database.exec("INSERT OR IGNORE INTO meeting_index_pending (indexable_type, id) SELECT 'meeting_transcript_row', id FROM meeting_transcript_rows UNION ALL SELECT 'meeting_chat_message', id FROM meeting_chat_messages UNION ALL SELECT 'meeting_summary', id FROM meeting_summaries");
6034
+ drainMeetingIndex(database);
6035
+ }, "meeting_words"),
6036
+ // Built per account by the first search that needs them.
6037
+ meeting_stems: /* @__PURE__ */ __name((database) => database.exec("UPDATE search_index_state SET filled_through = 0, built_at = NULL WHERE name LIKE 'meeting_stems:%'"), "meeting_stems")
6038
+ };
6039
+ var CORPUS_TABLES = new Set(Object.values(CORPORA).flatMap((corpus) => [`${corpus.type}_words`, `${corpus.type}_stems`]));
6040
+ var TRIGRAMS = ["note_trigrams", "document_trigrams"];
6041
+ var rebuildDerived = /* @__PURE__ */ __name((database, { now = Date.now, note = /* @__PURE__ */ __name(() => {
6042
+ }, "note") } = {}) => {
6043
+ const lost = database.prepare("SELECT 1 FROM sqlite_master WHERE name = ?").get(LOST_AND_FOUND);
6044
+ const lostAndFound = lost ? Number(database.prepare(`SELECT count(*) AS n FROM ${LOST_AND_FOUND}`).get()?.n) : 0;
6045
+ if (lost)
6046
+ database.exec(`DROP TABLE ${LOST_AND_FOUND}`);
6047
+ const indexes = fts5Tables(database);
6048
+ for (const { name, sql } of indexes) {
6049
+ database.exec(`DROP TABLE "${name}"`);
6050
+ database.exec(sql);
6051
+ }
6052
+ const vectors = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name GLOB 'vector_index_[0-9]*' AND sql LIKE 'CREATE VIRTUAL%'").all().map((row) => String(row.name));
6053
+ for (const table of vectors) {
6054
+ database.exec(`DROP TRIGGER IF EXISTS "${table}_redo"`);
6055
+ database.exec(`DROP TABLE "${table}"`);
6056
+ database.prepare("DELETE FROM vector_indexes WHERE id = ?").run(Number(table.replace("vector_index_", "")));
6057
+ }
6058
+ const unfilled = [];
6059
+ const stemmerFor = stemmerCache();
6060
+ for (const { name, external } of indexes) {
6061
+ note(`rebuilding ${name}`);
6062
+ if (external)
6063
+ database.exec(`INSERT INTO "${name}" ("${name}") VALUES ('rebuild')`);
6064
+ else if (FILLERS[name])
6065
+ FILLERS[name](database, now);
6066
+ else if (!CORPUS_TABLES.has(name) && !TRIGRAMS.includes(name))
6067
+ unfilled.push(name);
6068
+ }
6069
+ note("rebuilding the words of notes, documents, memories, mail, tasks, transcripts and events");
6070
+ resetNoteIndex(database);
6071
+ for (const corpus of Object.values(CORPORA))
6072
+ drainCorpus(database, corpus, stemmerFor);
6073
+ for (const name of TRIGRAMS) {
6074
+ const type = name.replace("_trigrams", "");
6075
+ database.prepare(`UPDATE search_index_state SET filled_through = 0, watermark = (SELECT coalesce(max(id), 0) FROM ${type}s) WHERE name = ?`).run(name);
6076
+ }
6077
+ fillTrigrams(database);
6078
+ note("finding mentions again");
6079
+ const mentions = rebuildMentions(database, { now: now() }).mentions;
6080
+ involvementStoreOver({ database, now }).rebuild();
6081
+ note("indexing the stored vectors");
6082
+ const vectorModels = fillVectorIndexes(database);
6083
+ const without = database.prepare("SELECT count(*) AS n FROM chunks k WHERE NOT EXISTS (SELECT 1 FROM embeddings v WHERE v.model = ? AND v.content_hash = k.content_hash)");
6084
+ const chunksWithoutVector = Object.fromEntries(database.prepare("SELECT model FROM vector_indexes ORDER BY model").all().map((row) => [String(row.model), Number(without.get(String(row.model))?.n)]));
6085
+ return {
6086
+ lostAndFound,
6087
+ searchIndexes: indexes.map((index) => index.name),
6088
+ unfilled,
6089
+ mentions,
6090
+ vectorModels,
6091
+ chunksWithoutVector
6092
+ };
6093
+ }, "rebuildDerived");
6094
+ var danglingRows = /* @__PURE__ */ __name((database) => database.prepare(`SELECT "table" AS child, parent, fkid, count(*) AS n FROM pragma_foreign_key_check GROUP BY 1, 2, 3 ORDER BY 4 DESC`).all().map((group) => {
6095
+ const child = String(group.child);
6096
+ const column = database.prepare(`SELECT "from" AS name FROM pragma_foreign_key_list(?) WHERE id = ? ORDER BY seq LIMIT 1`).get(child, Number(group.fkid))?.name;
6097
+ let missing = [];
6098
+ try {
6099
+ missing = database.prepare(`SELECT DISTINCT "${String(column)}" AS id FROM "${child}" WHERE rowid IN (SELECT rowid FROM pragma_foreign_key_check(?) WHERE fkid = ?) ORDER BY 1 LIMIT 20`).all(child, Number(group.fkid)).map((row) => typeof row.id === "number" ? row.id : String(row.id));
6100
+ } catch {
6101
+ }
6102
+ return { table: child, parent: String(group.parent), rows: Number(group.n), missing };
6103
+ }), "danglingRows");
6104
+ var mailToFetch = /* @__PURE__ */ __name((database) => {
6105
+ try {
6106
+ return database.prepare(`SELECT a.external_id AS account, count(DISTINCT l.email_id) AS n FROM email_locations l
6107
+ JOIN mailboxes b ON b.id = l.mailbox_id JOIN accounts a ON a.id = b.account_id
6108
+ WHERE NOT EXISTS (SELECT 1 FROM emails e WHERE e.id = l.email_id) GROUP BY a.id ORDER BY a.external_id`).all().map((row) => ({ account: String(row.account), emails: Number(row.n) }));
6109
+ } catch {
6110
+ return [];
6111
+ }
6112
+ }, "mailToFetch");
6113
+ var fingerprint = /* @__PURE__ */ __name((path) => ["", "-wal"].map((suffix) => {
6114
+ const stat = statSync2(`${path}${suffix}`, { throwIfNoEntry: false });
6115
+ return stat ? `${stat.size}:${stat.mtimeMs}` : "-";
6116
+ }).join("|"), "fingerprint");
6117
+ var refuseInUse = /* @__PURE__ */ __name((path) => {
6118
+ const holders = storeHolders(path);
6119
+ if (holders && holders.length > 0) {
6120
+ const timers = activeTimers() ?? [];
6121
+ throw new CliError("validation_error", `the store is open in ${holders.map(({ pid, name }) => `${name} (process ${pid})`).join(", ")} \u2014 stop it first` + (timers.length ? `, and the timers: systemctl --user stop ${timers.join(" ")}` : ""), { reason: "store.in-use" });
6122
+ }
6123
+ }, "refuseInUse");
6124
+ var recoverStore = /* @__PURE__ */ __name(async ({ path, command, version, sqlite3 = "sqlite3", now = Date.now, note = /* @__PURE__ */ __name(() => {
6125
+ }, "note"), copy }) => {
6126
+ const started = Date.now();
6127
+ if (!existsSync2(path))
6128
+ throw new CliError("not_found", `no store at ${path}`);
6129
+ const program = copy ? { program: sqlite3, version: "given", usable: true } : sqlite3Program(sqlite3);
6130
+ if (!program.usable) {
6131
+ throw new CliError("configuration_error", program.version ? `sqlite3 ${program.version} cannot recover: the recovery needs ${SQLITE3_MINIMUM.join(".")} or newer, built with .recover` : "the recovery needs the sqlite3 program with its .recover command: install it (apt install sqlite3, brew install sqlite)", { reason: "store.sqlite3-missing" });
6132
+ }
6133
+ refuseInUse(path);
6134
+ const bytes = STORE_PARTS.reduce((sum, suffix) => sum + (statSync2(`${path}${suffix}`, { throwIfNoEntry: false })?.size ?? 0), 0);
6135
+ const { bavail, bsize } = statfsSync(dirname(path));
6136
+ if (Number(bavail) * Number(bsize) < bytes * 1.2)
6137
+ throw new CliError("validation_error", `the recovery needs about ${Math.ceil(bytes * 1.2 / 1e9)} GB free beside the store`);
6138
+ const old = await openSqlite(path, { readOnly: true });
6139
+ let rowsBefore;
6140
+ try {
6141
+ rowsBefore = tableRows(old.database);
6142
+ } finally {
6143
+ old.database.close();
6144
+ }
6145
+ const before = fingerprint(path);
6146
+ const stamp = new Date(now()).toISOString().replace(/[:.]/g, "-");
6147
+ const target = `${path}.recovering-${stamp}`;
6148
+ writeFileSync(target, "", { flag: "wx", mode: 384 });
6149
+ const dropTarget = /* @__PURE__ */ __name(() => {
6150
+ for (const suffix of [...STORE_PARTS, "-journal"])
6151
+ rmSync2(`${target}${suffix}`, { force: true });
6152
+ }, "dropTarget");
6153
+ note(`copying the readable rows into ${target}`);
6154
+ let copied;
6155
+ let copyErrors;
6156
+ let read;
6157
+ let opened;
6158
+ try {
6159
+ ;
6160
+ ({ errors: copyErrors, read } = await (copy ?? ((from, to) => copyReadableRows(from, to, sqlite3)))(path, target));
6161
+ copied = Date.now();
6162
+ opened = await openSqlite(target);
6163
+ } catch (error) {
6164
+ dropTarget();
6165
+ throw error;
6166
+ }
6167
+ let rebuilt;
6168
+ let kept;
6169
+ let dangling;
6170
+ let fetch2;
6171
+ try {
6172
+ kept = tableRows(opened.database);
6173
+ migrate(opened.database, { command, ...version ? { version } : {} });
6174
+ rebuilt = rebuildDerived(opened.database, { now, note });
6175
+ note("looking for rows that point at rows that were lost");
6176
+ dangling = danglingRows(opened.database);
6177
+ fetch2 = mailToFetch(opened.database);
6178
+ opened.database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
6179
+ } catch (error) {
6180
+ opened.database.close();
6181
+ dropTarget();
6182
+ throw error;
6183
+ }
6184
+ opened.database.close();
6185
+ const rebuiltAt = Date.now();
6186
+ note("checking the recovered file");
6187
+ const health = await storeHealth(target, { deep: true });
6188
+ const checkedAt = Date.now();
6189
+ if (!health.ok) {
6190
+ throw new CliError("validation_error", `the recovered file did not pass its check, so the store was left as it was; the file is kept at ${target}`, { reason: "store.recovery-failed" });
6191
+ }
6192
+ refuseInUse(path);
6193
+ if (fingerprint(path) !== before) {
6194
+ throw new CliError("validation_error", `the store was written to during the recovery, so it was left as it was \u2014 stop every timer and run it again; ${target} can be deleted`, { reason: "store.changed-during-recovery" });
6195
+ }
6196
+ const keptAt = `${path}.before-recover-${stamp}`;
6197
+ for (const suffix of STORE_PARTS)
6198
+ if (existsSync2(`${path}${suffix}`))
6199
+ renameSync2(`${path}${suffix}`, `${keptAt}${suffix}`);
6200
+ for (const suffix of STORE_PARTS)
6201
+ if (existsSync2(`${target}${suffix}`))
6202
+ renameSync2(`${target}${suffix}`, `${path}${suffix}`);
6203
+ const lost = Object.entries(rowsBefore).map(([table, before2]) => ({ table, before: before2, read: read[table] ?? 0, kept: kept[table] ?? 0 })).filter(({ before: before2, read: read2, kept: kept2 }) => before2 === null || before2 > kept2 || read2 > kept2);
6204
+ const seconds = /* @__PURE__ */ __name((from, to) => Math.round((to - from) / 100) / 10, "seconds");
6205
+ return {
6206
+ path,
6207
+ keptAt,
6208
+ sqlite3: program.version,
6209
+ lost,
6210
+ dangling,
6211
+ mailToFetch: fetch2,
6212
+ rebuilt,
6213
+ copyErrors,
6214
+ health,
6215
+ seconds: {
6216
+ copy: seconds(started, copied),
6217
+ rebuild: seconds(copied, rebuiltAt),
6218
+ check: seconds(rebuiltAt, checkedAt),
6219
+ total: seconds(started, Date.now())
6220
+ }
6221
+ };
6222
+ }, "recoverStore");
6223
+
6224
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/store-recover.js
6225
+ var COUNTED = [
6226
+ "accounts",
6227
+ "chats",
6228
+ "messages",
6229
+ "attachments",
6230
+ "emails",
6231
+ "documents",
6232
+ "notes",
6233
+ "meetings",
6234
+ "chunks",
6235
+ "embeddings",
6236
+ "mentions"
6237
+ ];
6238
+ var stopTimers = /* @__PURE__ */ __name((timers) => `systemctl --user stop ${timers.join(" ")}`, "stopTimers");
6239
+ var storeRecoveryCheck = /* @__PURE__ */ __name(async (env, command) => {
6240
+ const path = storePath(env);
6241
+ if (!existsSync3(path))
6242
+ return { path, exists: false, ok: true, next: [] };
6243
+ const health = await storeHealth(path, { deep: true });
6244
+ let rows = {};
6245
+ try {
6246
+ const { database } = await openSqlite(path, { readOnly: true });
6247
+ try {
6248
+ const all = tableRows(database);
6249
+ rows = Object.fromEntries(COUNTED.filter((table) => table in all).map((table) => [table, all[table] ?? null]));
6250
+ } finally {
6251
+ database.close();
6252
+ }
6253
+ } catch {
6254
+ }
6255
+ const explanation = explainDamage(health, command);
6256
+ const inUse = storeHolders(path) ?? null;
6257
+ const timers = activeTimers() ?? null;
6258
+ const sqlite3 = sqlite3Program();
6259
+ const next = health.ok ? [] : [
6260
+ ...timers?.length ? [stopTimers(timers)] : [],
6261
+ ...(inUse ?? []).map(({ pid, name }) => `stop ${name} (process ${pid}): it has the store open`),
6262
+ ...sqlite3.usable ? [] : ["install sqlite3 3.43 or newer (apt install sqlite3, brew install sqlite)"],
6263
+ `${command} store recover run`
6264
+ ];
6265
+ return {
6266
+ path,
6267
+ exists: true,
6268
+ ok: health.ok,
6269
+ seconds: Math.round(health.ms / 100) / 10,
6270
+ problems: health.problems ?? 0,
6271
+ damagedTables: health.damagedTables ?? [],
6272
+ damagedSearchIndexes: (health.searchIndexes ?? []).filter((index) => !index.ok).map(({ name, error }) => ({ name, ...error ? { error } : {} })),
6273
+ rows,
6274
+ explanation,
6275
+ inUse,
6276
+ timers,
6277
+ sqlite3: { version: sqlite3.version, usable: sqlite3.usable },
6278
+ next
6279
+ };
6280
+ }, "storeRecoveryCheck");
6281
+ var storeRecoveryRun = /* @__PURE__ */ __name(async (env, { command, version, note, timers: scheduled = activeTimers, copy }) => {
6282
+ const timers = scheduled() ?? [];
6283
+ if (timers.length > 0)
6284
+ throw new CliError("validation_error", `stop the timers first, they open the store: ${stopTimers(timers)}`, {
6285
+ reason: "store.in-use"
6286
+ });
6287
+ const recovery = await recoverStore({
6288
+ path: storePath(env),
6289
+ command,
6290
+ ...version ? { version } : {},
6291
+ ...note ? { note } : {},
6292
+ ...copy ? { copy } : {}
6293
+ });
6294
+ const mail = recovery.mailToFetch.map(({ account, emails }) => `mail <profile of ${account}> sync --rescan # ${emails} emails`);
6295
+ const lostMail = recovery.lost.some(({ table }) => table === "emails") && mail.length === 0 ? ["mail <profile> sync --rescan # each mail profile"] : [];
6296
+ const { health, copyErrors, ...kept } = recovery;
6297
+ return {
6298
+ ...kept,
6299
+ copyErrors: copyErrors.length,
6300
+ checkedOk: health.ok,
6301
+ next: [...mail, ...lostMail, "systemctl --user start <the timers stopped before>"]
6302
+ };
6303
+ }, "storeRecoveryRun");
6304
+ var recoveryNotes = /* @__PURE__ */ __name((answer) => {
6305
+ if ("keptAt" in answer) {
6306
+ const lost = answer.lost.map(({ table, before, read, kept }) => `${table}: ${kept} kept of ${before ?? "an uncountable number"}${read > kept ? `, ${read - kept} read but unusable` : ""}`);
6307
+ return [
6308
+ `recovered in ${answer.seconds.total} s; the damaged file is kept at ${answer.keptAt}`,
6309
+ ...lost.length ? lost : ["no table lost a row"],
6310
+ ...answer.dangling.map(({ table, parent, rows }) => `${rows} rows of ${table} point at ${parent} rows the store does not hold`),
6311
+ ...answer.next.map((line) => `next: ${line}`)
6312
+ ];
6313
+ }
6314
+ if (!answer.exists)
6315
+ return ["no store yet"];
6316
+ if (answer.ok)
6317
+ return [`the store is healthy (checked every page and search index in ${answer.seconds} s)`];
6318
+ const why = answer.explanation;
6319
+ return [
6320
+ ...why ? [why.what, ...why.impact, why.externalUnaffected] : [],
6321
+ ...answer.next.map((line) => `next: ${line}`)
6322
+ ];
6323
+ }, "recoveryNotes");
6324
+ var storeRecoverCommand = /* @__PURE__ */ __name(({ command, version }) => {
6325
+ const recover = annotate(new Command("recover"), { effects: LOCAL_READ, examples: [`${command} store recover`] }).summary("what is damaged in the store and how to recover it").description("check every page and search index of the store, say what is damaged, what it means and the commands that recover it; changes nothing").action(async function() {
6326
+ const output = outputFor(this);
6327
+ const answer = await storeRecoveryCheck(environmentOf(this).env ?? process.env, command);
6328
+ renderAnswer(this, output, itemOf(snakeKeys(answer)));
6329
+ if (output.format === "pretty")
6330
+ for (const line of recoveryNotes(answer))
6331
+ output.renderer.note(line);
6332
+ });
6333
+ recover.addCommand(annotate(new Command("run"), { effects: LOCAL_WRITE, examples: [`${command} store recover run`] }).summary("rebuild a damaged store from every row it can read").description("copy every readable row into a new file with the sqlite3 program, rebuild the search indexes, mentions and vector index, check it, and put it in place of the store; the damaged file is kept beside it. Refuses while a WireCat timer or process has the store").action(async function() {
6334
+ const output = outputFor(this);
6335
+ const answer = await storeRecoveryRun(environmentOf(this).env ?? process.env, {
6336
+ command,
6337
+ ...version ? { version } : {},
6338
+ note: /* @__PURE__ */ __name((text) => output.renderer.note(text), "note")
6339
+ });
6340
+ renderAnswer(this, output, itemOf(snakeKeys(answer)));
6341
+ if (output.format === "pretty")
6342
+ for (const line of recoveryNotes(answer))
6343
+ output.renderer.note(line);
6344
+ }));
6345
+ return recover;
6346
+ }, "storeRecoverCommand");
6347
+
6348
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/store-info.js
5891
6349
  var pendingIfKnown = /* @__PURE__ */ __name((database) => database.prepare("SELECT 1 FROM pragma_table_info('messages') WHERE name = 'normalized_text'").get() ? pendingNormalization(database) : null, "pendingIfKnown");
5892
- var bytesOf = /* @__PURE__ */ __name((path) => existsSync2(path) ? statSync2(path).size : 0, "bytesOf");
6350
+ var bytesOf = /* @__PURE__ */ __name((path) => existsSync4(path) ? statSync3(path).size : 0, "bytesOf");
5893
6351
  var messageOf = /* @__PURE__ */ __name((error) => error instanceof Error ? error.message : String(error), "messageOf");
5894
6352
  var contentsOf = /* @__PURE__ */ __name((database, version, writable) => version > 0 && writable ? {
5895
6353
  rows: rowCounts(database),
@@ -5900,7 +6358,7 @@ var contentsOf = /* @__PURE__ */ __name((database, version, writable) => version
5900
6358
  } : { rows: {}, pendingNormalization: null, wordIndex: null, stemIndex: null }, "contentsOf");
5901
6359
  var storeInfo = /* @__PURE__ */ __name(async (env) => {
5902
6360
  const path = storePath(env);
5903
- if (!existsSync2(path))
6361
+ if (!existsSync4(path))
5904
6362
  return snakeKeys({ path, exists: false, schema: compatibilityOf(void 0) });
5905
6363
  let schema = compatibilityOf(void 0);
5906
6364
  try {
@@ -5933,7 +6391,7 @@ var storeInfoCommand = /* @__PURE__ */ __name(() => annotate(new Command("info")
5933
6391
  renderAnswer(this, outputFor(this), itemOf(answer));
5934
6392
  }), "storeInfoCommand");
5935
6393
 
5936
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/password.js
6394
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/password.js
5937
6395
  var ENCRYPT_OPTION = [
5938
6396
  "--encrypt",
5939
6397
  "compress and encrypt with a password, typed at a hidden prompt or piped on stdin; it is never kept \u2014 lose it and the file cannot be opened"
@@ -5952,9 +6410,9 @@ var passwordOf = /* @__PURE__ */ __name(async (command, { twice }) => {
5952
6410
  return password;
5953
6411
  }, "passwordOf");
5954
6412
 
5955
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/rules.js
5956
- import { existsSync as existsSync3, readFileSync } from "node:fs";
5957
- import { join } from "node:path";
6413
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/rules.js
6414
+ import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
6415
+ import { join as join2 } from "node:path";
5958
6416
  var REPLY_ACTIONS = ["reply", "task"];
5959
6417
  var REPLY_MODELS = ["fill-only", "may-reword"];
5960
6418
  var REPLY_KINDS = ["dialog", "group"];
@@ -6040,7 +6498,7 @@ var defaultRule = /* @__PURE__ */ __name((id) => ({
6040
6498
  reply: { template: "", asReply: true },
6041
6499
  limits: { perChat: "1/1d", perPerson: "1/1d" }
6042
6500
  }), "defaultRule");
6043
- var repliesPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).config, `${profile}.replies.json`), "repliesPathFor");
6501
+ var repliesPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join2(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).config, `${profile}.replies.json`), "repliesPathFor");
6044
6502
  var EVERYONE = { reply: "all", allow: { people: [], chats: [] }, deny: { people: [], chats: [] } };
6045
6503
  var outsideAudience = /* @__PURE__ */ __name((audience, person, chat) => {
6046
6504
  if (person !== null && audience.deny.people.includes(person))
@@ -6070,11 +6528,11 @@ var readReplies = /* @__PURE__ */ __name((path, provider) => {
6070
6528
  return parseReplies(readRepliesFile(path, provider), path, provider);
6071
6529
  }, "readReplies");
6072
6530
  var readRepliesFile = /* @__PURE__ */ __name((path, provider) => {
6073
- if (!existsSync3(path))
6531
+ if (!existsSync5(path))
6074
6532
  return { audience: structuredClone(EVERYONE), rules: [] };
6075
6533
  let parsed;
6076
6534
  try {
6077
- parsed = JSON.parse(readFileSync(path, "utf8"));
6535
+ parsed = JSON.parse(readFileSync2(path, "utf8"));
6078
6536
  } catch (error) {
6079
6537
  throw broken(path, error instanceof Error ? error.message : String(error));
6080
6538
  }
@@ -6123,9 +6581,9 @@ var problem = /* @__PURE__ */ __name((issue) => {
6123
6581
  }, "problem");
6124
6582
  var broken = /* @__PURE__ */ __name((path, why) => new CliError("configuration_error", `the reply rules ${path} cannot be read (${why}) \u2014 fix the file`), "broken");
6125
6583
 
6126
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/state.js
6127
- import { existsSync as existsSync4, readFileSync as readFileSync2 } from "node:fs";
6128
- import { join as join2 } from "node:path";
6584
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/state.js
6585
+ import { existsSync as existsSync6, readFileSync as readFileSync3 } from "node:fs";
6586
+ import { join as join3 } from "node:path";
6129
6587
  var ANSWERED_KEPT = 1e3;
6130
6588
  var times = record(string(), array(string()));
6131
6589
  var stateFile = object({
@@ -6137,13 +6595,13 @@ var stateFile = object({
6137
6595
  });
6138
6596
  var emptyState = /* @__PURE__ */ __name(() => ({ paused: false, answered: [], sent: {} }), "emptyState");
6139
6597
  var answeredKey = /* @__PURE__ */ __name((message) => `${message.chatId}:${message.id}`, "answeredKey");
6140
- var repliesStatePathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join2(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).state, `${profile}.replies-state.json`), "repliesStatePathFor");
6598
+ var repliesStatePathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join3(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).state, `${profile}.replies-state.json`), "repliesStatePathFor");
6141
6599
  var readRepliesState = /* @__PURE__ */ __name((path) => {
6142
- if (!existsSync4(path))
6600
+ if (!existsSync6(path))
6143
6601
  return emptyState();
6144
6602
  let parsed;
6145
6603
  try {
6146
- parsed = JSON.parse(readFileSync2(path, "utf8"));
6604
+ parsed = JSON.parse(readFileSync3(path, "utf8"));
6147
6605
  } catch (error) {
6148
6606
  throw broken2(path, error instanceof Error ? error.message : String(error));
6149
6607
  }
@@ -6176,7 +6634,7 @@ var recordReply = /* @__PURE__ */ __name((state, rule2, message, now) => {
6176
6634
  }, "recordReply");
6177
6635
  var broken2 = /* @__PURE__ */ __name((path, why) => new CliError("configuration_error", `the reply state ${path} cannot be read (${why}) \u2014 fix or move the file`), "broken");
6178
6636
 
6179
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/decide.js
6637
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/decide.js
6180
6638
  var skip = /* @__PURE__ */ __name((why) => ({ skip: why }), "skip");
6181
6639
  var decide = /* @__PURE__ */ __name((rule2, incoming, state, now) => {
6182
6640
  const { message, chat, owner, sender } = incoming;
@@ -6282,7 +6740,7 @@ var filled = /* @__PURE__ */ __name((template2, senderName) => {
6282
6740
  return template2.replaceAll("{firstName}", name.split(/\s+/)[0] ?? name).replaceAll("{name}", name);
6283
6741
  }, "filled");
6284
6742
 
6285
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/template.js
6743
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/template.js
6286
6744
  var import_liquidjs = __toESM(require_liquid_node(), 1);
6287
6745
  var TEMPLATE_LIMITS = {
6288
6746
  parse: 32768,
@@ -6442,7 +6900,7 @@ var renderReplyTemplate = /* @__PURE__ */ __name(async (reply, input) => {
6442
6900
  }
6443
6901
  }, "renderReplyTemplate");
6444
6902
 
6445
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/dry-run.js
6903
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/dry-run.js
6446
6904
  var DRY_RUN_DAYS = 7;
6447
6905
  var PAGE = 500;
6448
6906
  var dryRun = /* @__PURE__ */ __name(async (store, account, rules, { since, until = Date.now(), only, audience, render }) => {
@@ -6556,7 +7014,7 @@ var storedSince = /* @__PURE__ */ __name(async (store, account, chat, since) =>
6556
7014
  }
6557
7015
  }, "storedSince");
6558
7016
 
6559
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/embeddings/keys.js
7017
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/embeddings/keys.js
6560
7018
  var endpointKeyName = /* @__PURE__ */ __name((baseUrl) => {
6561
7019
  const host = new URL(baseUrl).host;
6562
7020
  return ["openai", "anthropic"].includes(host) ? `endpoint:${host}` : host;
@@ -6587,7 +7045,7 @@ var embeddingKeys = /* @__PURE__ */ __name((app, env = process.env, keyring) =>
6587
7045
  };
6588
7046
  }, "embeddingKeys");
6589
7047
 
6590
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/models/openai.js
7048
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/models/openai.js
6591
7049
  var options = strictObject({
6592
7050
  temperature: range(0, 2),
6593
7051
  top_p: range(0, 1),
@@ -6636,7 +7094,7 @@ var openai = {
6636
7094
  }), "complete")
6637
7095
  };
6638
7096
 
6639
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/models/index.js
7097
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/models/index.js
6640
7098
  var modelGateway = /* @__PURE__ */ __name((deps) => ({
6641
7099
  complete: /* @__PURE__ */ __name(async (request) => {
6642
7100
  if (deps.signal?.aborted)
@@ -6651,7 +7109,7 @@ var modelGateway = /* @__PURE__ */ __name((deps) => ({
6651
7109
  if (!adapter && target.provider === "openai")
6652
7110
  adapter = openai;
6653
7111
  if (!adapter && target.provider === "anthropic")
6654
- adapter = (await import("./anthropic-3ZS3RCUH.js")).anthropic;
7112
+ adapter = (await import("./anthropic-PTAYBCPR.js")).anthropic;
6655
7113
  if (!adapter)
6656
7114
  throw new CliError("validation_error", `no model adapter for ${target.provider}`);
6657
7115
  if (request.images !== void 0 && adapter.images !== true)
@@ -6692,19 +7150,19 @@ var modelGateway = /* @__PURE__ */ __name((deps) => ({
6692
7150
  }, "complete")
6693
7151
  }), "modelGateway");
6694
7152
 
6695
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/consents.js
6696
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
6697
- import { join as join3 } from "node:path";
7153
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/consents.js
7154
+ import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
7155
+ import { join as join4 } from "node:path";
6698
7156
  var shape = strictObject({
6699
7157
  provider: nullable(pipe(string(), minLength(1))),
6700
7158
  deniedChats: array(pipe(string(), minLength(1)))
6701
7159
  });
6702
- var replyConsentPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join3(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).config, `${profile}.replies-consents.json`), "replyConsentPathFor");
7160
+ var replyConsentPathFor = /* @__PURE__ */ __name((app, profile, env = process.env) => join4(resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).config, `${profile}.replies-consents.json`), "replyConsentPathFor");
6703
7161
  var readReplyConsent = /* @__PURE__ */ __name((path) => {
6704
- if (!existsSync5(path))
7162
+ if (!existsSync7(path))
6705
7163
  return { provider: null, deniedChats: [] };
6706
7164
  try {
6707
- return parse(shape, JSON.parse(readFileSync3(path, "utf8")));
7165
+ return parse(shape, JSON.parse(readFileSync4(path, "utf8")));
6708
7166
  } catch {
6709
7167
  throw new CliError("configuration_error", "reply model consent is invalid; fix its file before granting consent");
6710
7168
  }
@@ -6717,7 +7175,7 @@ var mayModelReply = /* @__PURE__ */ __name((path, provider, chat) => {
6717
7175
  return consent.provider === provider && !consent.deniedChats.includes(chat);
6718
7176
  }, "mayModelReply");
6719
7177
 
6720
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/rendering.js
7178
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/rendering.js
6721
7179
  var replyRenderer = /* @__PURE__ */ __name((app, profile, settings, env, warn, options2 = {
6722
7180
  ai: true
6723
7181
  }) => async (rule2, message, chat, now) => {
@@ -6764,7 +7222,7 @@ var replyRenderer = /* @__PURE__ */ __name((app, profile, settings, env, warn, o
6764
7222
  return result2;
6765
7223
  }, "replyRenderer");
6766
7224
 
6767
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/replies/serve.js
7225
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/replies/serve.js
6768
7226
  var NOT_ALLOWED = "replies.send is not allow";
6769
7227
  var NO_RULES = "no rules";
6770
7228
  var ONLY_TASK = "opened a task, sent nothing";
@@ -6857,7 +7315,7 @@ var replyTo = /* @__PURE__ */ __name(async (deps, message) => {
6857
7315
  return { skip: why };
6858
7316
  }, "replyTo");
6859
7317
 
6860
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-catch-up.js
7318
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-catch-up.js
6861
7319
  var START_SYNC_DELAY_MS = 3e4;
6862
7320
  var START_SYNC_BUDGET_MS = 5 * 6e4;
6863
7321
  var START_SYNC_WINDOW_MS = 7 * 864e5;
@@ -6934,7 +7392,7 @@ var startSync = /* @__PURE__ */ __name(({ chats, newestHeld, fetch: fetch2, note
6934
7392
  };
6935
7393
  }, "startSync");
6936
7394
 
6937
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-members.js
7395
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-members.js
6938
7396
  var FIRST_FETCH_MS = 6e4;
6939
7397
  var DAY_MS = 864e5;
6940
7398
  var memberFetches = /* @__PURE__ */ __name(({ withStore, fetch: fetch2, warn, firstMs = FIRST_FETCH_MS, everyMs = DAY_MS }) => {
@@ -6988,7 +7446,7 @@ var memberFetches = /* @__PURE__ */ __name(({ withStore, fetch: fetch2, warn, fi
6988
7446
  };
6989
7447
  }, "memberFetches");
6990
7448
 
6991
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-notice.js
7449
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-notice.js
6992
7450
  var record2 = /* @__PURE__ */ __name((context, app, severity, attributes) => recordLogFor(context.streams.diagnostic, app, { command: currentRun().command || "serve" })[severity](attributes), "record");
6993
7451
  var noticeFor = /* @__PURE__ */ __name((context, app, severity = "warn") => ({ text, ...attributes }) => {
6994
7452
  if (context.format === "pretty") {
@@ -7021,7 +7479,7 @@ var recordDiagnostics = /* @__PURE__ */ __name((context, app) => {
7021
7479
  return context;
7022
7480
  }, "recordDiagnostics");
7023
7481
 
7024
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-stems.js
7482
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-stems.js
7025
7483
  var STEMS_EVERY_MS = 3e4;
7026
7484
  var STEMS_SLICE_MS = 2e3;
7027
7485
  var stemFills = /* @__PURE__ */ __name(({ withStore, warn, everyMs = STEMS_EVERY_MS, sliceMs = STEMS_SLICE_MS }) => {
@@ -7061,7 +7519,7 @@ var stemFills = /* @__PURE__ */ __name(({ withStore, warn, everyMs = STEMS_EVERY
7061
7519
  };
7062
7520
  }, "stemFills");
7063
7521
 
7064
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/render/messages.js
7522
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/render/messages.js
7065
7523
  import { styleText } from "node:util";
7066
7524
  var TIME_WIDTH = 8;
7067
7525
  var INDENT = " ".repeat(TIME_WIDTH + 2);
@@ -7237,7 +7695,7 @@ var editedAt = /* @__PURE__ */ __name((message, options2) => {
7237
7695
  return day(edited) === day(message.timestamp) ? time : `${day(edited)} ${time}`;
7238
7696
  }, "editedAt");
7239
7697
 
7240
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/message-items.js
7698
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/message-items.js
7241
7699
  var defined = /* @__PURE__ */ __name((value) => Object.fromEntries(Object.entries(value).filter(([, one]) => one !== void 0)), "defined");
7242
7700
  var attachmentItem = /* @__PURE__ */ __name((attachment) => defined({
7243
7701
  kind: attachment.kind,
@@ -7332,7 +7790,7 @@ var viewOf = /* @__PURE__ */ __name((context, messenger) => ({
7332
7790
  locale: messenger.app.locale
7333
7791
  }), "viewOf");
7334
7792
 
7335
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/watch-answers.js
7793
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/watch-answers.js
7336
7794
  var observed = /* @__PURE__ */ __name((value) => ({
7337
7795
  value: value.value,
7338
7796
  observed_at: value.observedAt,
@@ -7399,7 +7857,7 @@ var watchEventItem = /* @__PURE__ */ __name((value, account) => {
7399
7857
  }
7400
7858
  }, "watchEventItem");
7401
7859
 
7402
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/watch-command.js
7860
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/watch-command.js
7403
7861
  var watchCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("watch"), {
7404
7862
  output: { entity: "watch_item" },
7405
7863
  effects: REMOTE_READ,
@@ -7554,7 +8012,7 @@ var describe = /* @__PURE__ */ __name((event, render) => {
7554
8012
  }
7555
8013
  }, "describe");
7556
8014
 
7557
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-command.js
8015
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/serve-command.js
7558
8016
  var serveCommand = /* @__PURE__ */ __name((messenger) => {
7559
8017
  const command = annotate(new Command("serve"), {
7560
8018
  output: { entity: "serve_summary" },
@@ -7818,8 +8276,8 @@ var tasking = /* @__PURE__ */ __name((context, warn) => {
7818
8276
  };
7819
8277
  }, "tasking");
7820
8278
 
7821
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/store-tables-command.js
7822
- import { existsSync as existsSync6 } from "node:fs";
8279
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/store-tables-command.js
8280
+ import { existsSync as existsSync8 } from "node:fs";
7823
8281
  var PATH = "store tables list";
7824
8282
  var STORE_TABLES_QUERY = {
7825
8283
  entity: "store_table",
@@ -7848,7 +8306,7 @@ var storeTablesCommand = /* @__PURE__ */ __name((messenger) => {
7848
8306
  const filter = filterOf(words);
7849
8307
  const { full } = this.optsWithGlobals();
7850
8308
  const path = storePath(environmentOf(this).env ?? process.env);
7851
- if (!existsSync6(path))
8309
+ if (!existsSync8(path))
7852
8310
  throw new CliError("not_found", `no store at ${path}`);
7853
8311
  const items = await readStoreTables(path, { filter, sizes: full === true });
7854
8312
  renderAnswer(this, outputFor(this), listOf(PATH, {
@@ -7861,7 +8319,7 @@ var storeTablesCommand = /* @__PURE__ */ __name((messenger) => {
7861
8319
  return tables;
7862
8320
  }, "storeTablesCommand");
7863
8321
 
7864
- // node_modules/.pnpm/@wirecat+cli-core@0.593.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_a38dc1e51ab7f561f21ddbf6a1611494/node_modules/@wirecat/cli-core/dist/cli/messenger/store-maintenance-command.js
8322
+ // node_modules/.pnpm/@wirecat+cli-core@0.599.0_@wirecat+cli-base@0.78.0_commander@15.0.0_esbuild@0.28.2_type_9abdd607bcc42461f37eac6c77838a67/node_modules/@wirecat/cli-core/dist/cli/messenger/store-maintenance-command.js
7865
8323
  var SEARCH_INDEXES = ["messages_fts", "chats_fts", "identities_fts"];
7866
8324
  var WORD_INDEX = "message_words";
7867
8325
  var schemaOf = /* @__PURE__ */ __name((database) => {
@@ -7870,7 +8328,7 @@ var schemaOf = /* @__PURE__ */ __name((database) => {
7870
8328
  }, "schemaOf");
7871
8329
  var count2 = /* @__PURE__ */ __name((database, table) => Number(database.prepare(`SELECT count(*) AS n FROM ${table}`).get()?.n ?? 0), "count");
7872
8330
  var pendingIfKnown2 = /* @__PURE__ */ __name((database) => database.prepare("SELECT 1 FROM pragma_table_info('messages') WHERE name = 'normalized_text'").get() ? pendingNormalization(database) : null, "pendingIfKnown");
7873
- var bytesOf2 = /* @__PURE__ */ __name((path) => existsSync7(path) ? statSync3(path).size : 0, "bytesOf");
8331
+ var bytesOf2 = /* @__PURE__ */ __name((path) => existsSync9(path) ? statSync4(path).size : 0, "bytesOf");
7874
8332
  var reading = /* @__PURE__ */ __name(async (path, read) => {
7875
8333
  const database = await openCache(path);
7876
8334
  try {
@@ -7887,10 +8345,22 @@ var readingOnly = /* @__PURE__ */ __name(async (path, read) => {
7887
8345
  database.close();
7888
8346
  }
7889
8347
  }, "readingOnly");
7890
- var storeSummary = /* @__PURE__ */ __name(async (env) => {
8348
+ var storeSummary = /* @__PURE__ */ __name(async (env, { deep = false, command } = {}) => {
7891
8349
  const path = storePath(env);
7892
- if (!existsSync7(path))
8350
+ if (!existsSync9(path))
7893
8351
  return { path, exists: false };
8352
+ const checked = await storeHealth(path, { deep });
8353
+ const health = {
8354
+ checked: checked.checked,
8355
+ covers: deep ? "every page and every search index" : QUICK_HEALTH_CHECKS,
8356
+ ok: checked.ok,
8357
+ ms: checked.ms,
8358
+ ...checked.problems ? { problems: checked.problems } : {},
8359
+ ...checked.damagedTables?.length ? { damagedTables: checked.damagedTables } : {},
8360
+ ...checked.searchIndexes?.some((index) => !index.ok) ? { damagedSearchIndexes: checked.searchIndexes.filter((index) => !index.ok).map((index) => index.name) } : {}
8361
+ };
8362
+ const damage = command ? explainDamage(checked, command) : null;
8363
+ const healthOf = { health, ...damage ? { damage } : {} };
7894
8364
  try {
7895
8365
  return await reading(path, (database) => {
7896
8366
  const { version, writable } = schemaOf(database);
@@ -7900,11 +8370,12 @@ var storeSummary = /* @__PURE__ */ __name(async (env) => {
7900
8370
  schema: version,
7901
8371
  speaks: SPEAKS,
7902
8372
  writable,
7903
- ...version > 0 ? { chats: count2(database, "chats"), messages: count2(database, "messages") } : {}
8373
+ ...version > 0 ? { chats: count2(database, "chats"), messages: count2(database, "messages") } : {},
8374
+ ...healthOf
7904
8375
  };
7905
8376
  });
7906
8377
  } catch (error) {
7907
- return { path, exists: true, error: messageOf2(error) };
8378
+ return { path, exists: true, error: messageOf2(error), ...healthOf };
7908
8379
  }
7909
8380
  }, "storeSummary");
7910
8381
  var result = /* @__PURE__ */ __name((command, value, next = []) => renderAnswer(command, outputFor(command), itemOf(snakeKeys(value), { next })), "result");
@@ -7919,7 +8390,8 @@ var storeMaintenanceCommands = /* @__PURE__ */ __name((messenger) => [
7919
8390
  repairCommand(messenger),
7920
8391
  resetCommand(messenger),
7921
8392
  copiesCommand(),
7922
- storeTablesCommand(messenger)
8393
+ storeTablesCommand(messenger),
8394
+ storeRecoverCommand({ command: messenger.app.command, version: messenger.app.version })
7923
8395
  ], "storeMaintenanceCommands");
7924
8396
  var refuseWhileServing = /* @__PURE__ */ __name((command, messenger) => {
7925
8397
  const serving = servingProfiles(messenger.app, environmentOf(command).env ?? process.env);
@@ -7931,7 +8403,7 @@ var repairCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("
7931
8403
  const { renderer, format } = outputFor(this);
7932
8404
  const { dryRun: dryRun2 } = this.opts();
7933
8405
  const path = storePath(environmentOf(this).env ?? process.env);
7934
- if (!existsSync7(path)) {
8406
+ if (!existsSync9(path)) {
7935
8407
  result(this, { path, exists: false });
7936
8408
  return;
7937
8409
  }
@@ -7971,7 +8443,7 @@ var notesOf = /* @__PURE__ */ __name((report, command) => {
7971
8443
  }, "notesOf");
7972
8444
  var copiesCommand = /* @__PURE__ */ __name(() => new Command("copies").description("the tables `store repair` kept as copies").addCommand(annotate(new Command("delete"), { output: { entity: "store_copy_removal" }, effects: LOCAL_WRITE }).description("delete one copy `store repair` kept, named exactly; refuses any other table").argument("<name>", "the copy's name, as `store repair` printed it").action(async function(name) {
7973
8445
  const path = storePath(environmentOf(this).env ?? process.env);
7974
- if (!existsSync7(path))
8446
+ if (!existsSync9(path))
7975
8447
  throw new CliError("not_found", `no store at ${path}`);
7976
8448
  const deleted = await reading(path, (database) => deleteCopy(database, name));
7977
8449
  result(this, { path, deleted });
@@ -7979,7 +8451,7 @@ var copiesCommand = /* @__PURE__ */ __name(() => new Command("copies").descripti
7979
8451
  var checkCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("check"), { output: { entity: "store_check" }, effects: LOCAL_READ }).summary("check the local archive for problems").description("whether the store is healthy \u2014 integrity, search indexes, disk, and which chats are behind").action(async function() {
7980
8452
  const { renderer } = outputFor(this);
7981
8453
  const path = storePath(environmentOf(this).env ?? process.env);
7982
- if (!existsSync7(path)) {
8454
+ if (!existsSync9(path)) {
7983
8455
  result(this, { path, exists: false, ok: true });
7984
8456
  return;
7985
8457
  }
@@ -8042,7 +8514,7 @@ var inspect = /* @__PURE__ */ __name((path) => reading(path, (database) => {
8042
8514
  ...schema.version > 0 ? [["attachment_words", indexIntegrity(database, "attachment_words", 0)]] : []
8043
8515
  ]);
8044
8516
  const size = bytesOf2(path) + bytesOf2(`${path}-wal`);
8045
- const { bavail, bsize } = statfsSync(dirname(path));
8517
+ const { bavail, bsize } = statfsSync2(dirname2(path));
8046
8518
  const free = Number(bavail) * Number(bsize);
8047
8519
  const behind = schema.version > 0 ? chatsBehind(database) : [];
8048
8520
  const vectorIndexes = schema.version >= 34 ? vectorIndexCounts(database) : [];
@@ -8130,14 +8602,18 @@ var chatsBehind = /* @__PURE__ */ __name((database) => database.prepare(`SELECT
8130
8602
  var migrateCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("migrate"), { output: { entity: "store_migration" }, effects: LOCAL_WRITE }).summary("migrate an older local archive").description("bring the store up to this build's schema, then normalize, index and stem the messages and notes stored before it").action(async function() {
8131
8603
  const { renderer } = outputFor(this);
8132
8604
  const path = storePath(environmentOf(this).env ?? process.env);
8133
- if (!existsSync7(path)) {
8605
+ if (!existsSync9(path)) {
8134
8606
  result(this, { path, exists: false });
8135
8607
  renderer.note(`no store yet \u2014 the first \`${messenger.app.command}\` command that reads a chat creates it`);
8136
8608
  return;
8137
8609
  }
8138
8610
  const answer = await reading(path, (database) => {
8139
8611
  const from = schemaOf(database).version;
8140
- migrate(database, { command: messenger.app.command, version: messenger.app.version });
8612
+ migrate(database, {
8613
+ command: messenger.app.command,
8614
+ version: messenger.app.version,
8615
+ rollback: { store: path, warn: /* @__PURE__ */ __name((line) => renderer.warn(line), "warn") }
8616
+ });
8141
8617
  const { normalized, indexed, terms } = buildWordIndex(database, (note) => renderer.note(note));
8142
8618
  const stemmed = buildStems(database, (note) => renderer.note(note));
8143
8619
  const notes = buildNoteIndex(database, (note) => renderer.note(note));
@@ -8190,7 +8666,7 @@ var buildNoteIndex = /* @__PURE__ */ __name((database, note, { reset = false } =
8190
8666
  var reindexCommand = /* @__PURE__ */ __name((messenger) => destroysNothing(annotate(new Command("rebuild"), { output: { entity: "store_reindex" }, effects: LOCAL_WRITE })).summary("rebuild the local archive's search indexes").description("rebuild the word index, its typo vocabulary, the stems, the files' word index, the notes' indexes and who took part in what, from what is stored, and drop the vectors no stored text uses; loses nothing").action(async function() {
8191
8667
  const { renderer } = outputFor(this);
8192
8668
  const path = storePath(environmentOf(this).env ?? process.env);
8193
- if (!existsSync7(path)) {
8669
+ if (!existsSync9(path)) {
8194
8670
  result(this, { path, exists: false });
8195
8671
  return;
8196
8672
  }
@@ -8219,11 +8695,11 @@ var reindexCommand = /* @__PURE__ */ __name((messenger) => destroysNothing(annot
8219
8695
  result(this, answer);
8220
8696
  }), "reindexCommand");
8221
8697
  var vacuumInto = /* @__PURE__ */ __name(async (path, target) => {
8222
- writeFileSync(target, "", { flag: "wx", mode: 384 });
8698
+ writeFileSync2(target, "", { flag: "wx", mode: 384 });
8223
8699
  try {
8224
8700
  await reading(path, (database) => database.prepare("VACUUM INTO ?").run(target));
8225
8701
  } catch (error) {
8226
- rmSync2(target, { force: true });
8702
+ rmSync3(target, { force: true });
8227
8703
  throw error;
8228
8704
  }
8229
8705
  }, "vacuumInto");
@@ -8232,9 +8708,9 @@ var backupCommand = /* @__PURE__ */ __name(() => destroysNothing(annotate(new Co
8232
8708
  const { encrypt } = this.opts();
8233
8709
  const path = storePath(environmentOf(this).env ?? process.env);
8234
8710
  const target = resolve(file2);
8235
- if (!existsSync7(path))
8711
+ if (!existsSync9(path))
8236
8712
  throw new CliError("not_found", `no store at ${path} to back up`);
8237
- if (existsSync7(target))
8713
+ if (existsSync9(target))
8238
8714
  throw new CliError("validation_error", `${target} exists \u2014 a backup never overwrites a file`);
8239
8715
  const password = encrypt ? await passwordOf(this, { twice: true }) : void 0;
8240
8716
  const copyAt = password === void 0 ? target : `${path}.backup-${process.pid}`;
@@ -8256,67 +8732,69 @@ var backupCommand = /* @__PURE__ */ __name(() => destroysNothing(annotate(new Co
8256
8732
  });
8257
8733
  } catch (error) {
8258
8734
  if (password === void 0)
8259
- rmSync2(target, { force: true });
8735
+ rmSync3(target, { force: true });
8260
8736
  throw error;
8261
8737
  } finally {
8262
8738
  if (password !== void 0)
8263
- rmSync2(copyAt, { force: true });
8739
+ rmSync3(copyAt, { force: true });
8264
8740
  }
8265
8741
  }), "backupCommand");
8266
8742
  var decryptCommand = /* @__PURE__ */ __name(() => annotate(new Command("decrypt"), { output: { entity: "store_decrypt" }, effects: LOCAL_WRITE }).description("open a file written with --encrypt into a new file; asks for its password").argument("<file>", "a file `store backup --encrypt` or `store export --encrypt` wrote").requiredOption("--output <file>", "the new file, readable only by you").action(async function(file2) {
8267
8743
  const { output } = this.opts();
8268
8744
  const from = resolve(file2);
8269
8745
  const to = resolve(output);
8270
- if (!existsSync7(from))
8746
+ if (!existsSync9(from))
8271
8747
  throw new CliError("not_found", `no file at ${from}`);
8272
8748
  if (!isSealed(from))
8273
8749
  throw new CliError("validation_error", `${from} was not written with --encrypt`);
8274
- if (existsSync7(to))
8750
+ if (existsSync9(to))
8275
8751
  throw new CliError("validation_error", `${to} exists \u2014 never overwritten`);
8276
8752
  await unsealFile(from, to, await passwordOf(this, { twice: false }));
8277
8753
  result(this, { path: to, from, bytes: bytesOf2(to) });
8278
8754
  }), "decryptCommand");
8279
- var restoreCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("restore"), { output: { entity: "store_restore" }, effects: LOCAL_WRITE }).summary("restore a backup while keeping the current store").description("put a backup in place of the store; the store it replaces is kept beside it, never deleted").argument("<file>", "a file `store backup` wrote; one written with --encrypt asks for its password").action(async function(file2) {
8755
+ var restoreCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("restore"), { output: { entity: "store_restore" }, effects: LOCAL_WRITE }).summary("restore a backup and keep the current store, or roll back a breaking upgrade").description("put a backup in place of the store; the store it replaces is kept beside it, never deleted. Given a rollback copy (backups/<store>-rollback-schema-<version>-<time>.db, kept for a day before an upgrade older tools cannot open), put its tables back in the store and return it to that version instead").argument("<file>", "a file `store backup` wrote, or a rollback copy; one written with --encrypt asks for its password").action(async function(file2) {
8280
8756
  const path = storePath(environmentOf(this).env ?? process.env);
8281
8757
  const given = resolve(file2);
8282
- if (!existsSync7(given))
8758
+ if (!existsSync9(given))
8283
8759
  throw new CliError("not_found", `no file at ${given}`);
8284
8760
  refuseWhileServing(this, messenger);
8285
8761
  if (!isSealed(given))
8286
8762
  return restoreFrom(this, messenger, given, given);
8287
8763
  const opened = `${path}.unsealing-${process.pid}`;
8288
- mkdirSync(dirname(path), { recursive: true, mode: 448 });
8764
+ mkdirSync(dirname2(path), { recursive: true, mode: 448 });
8289
8765
  try {
8290
8766
  await unsealFile(given, opened, await passwordOf(this, { twice: false }));
8291
8767
  await restoreFrom(this, messenger, opened, given);
8292
8768
  } finally {
8293
- rmSync2(opened, { force: true });
8769
+ rmSync3(opened, { force: true });
8294
8770
  }
8295
8771
  }), "restoreCommand");
8296
8772
  var restoreFrom = /* @__PURE__ */ __name(async (command, messenger, backup, given) => {
8297
8773
  const { renderer } = outputFor(command);
8298
8774
  const path = storePath(environmentOf(command).env ?? process.env);
8299
- if (existsSync7(path) && realpathSync(backup) === realpathSync(path)) {
8775
+ if (existsSync9(path) && realpathSync2(backup) === realpathSync2(path)) {
8300
8776
  throw new CliError("validation_error", `${backup} is the store itself`);
8301
8777
  }
8778
+ if (await isRollbackCopy(backup))
8779
+ return rollBackFrom(command, messenger, backup);
8302
8780
  const schema = await backupSchema(backup);
8303
8781
  const stamp = stampNow();
8304
- const kept = existsSync7(path) ? `${path}.before-restore-${stamp}` : null;
8782
+ const kept = existsSync9(path) ? `${path}.before-restore-${stamp}` : null;
8305
8783
  if (kept) {
8306
8784
  const waitMs = environmentOf(command).storeLockWaitMs;
8307
8785
  await quiesce(path, messenger, "restore", (message) => renderer.warn(message), waitMs);
8308
8786
  } else
8309
- mkdirSync(dirname(path), { recursive: true, mode: 448 });
8787
+ mkdirSync(dirname2(path), { recursive: true, mode: 448 });
8310
8788
  const incoming = `${path}.restoring-${stamp}`;
8311
8789
  copyFileSync(backup, incoming, constants.COPYFILE_EXCL);
8312
8790
  chmodSync(incoming, 384);
8313
8791
  if (kept) {
8314
- renameSync2(path, kept);
8792
+ renameSync3(path, kept);
8315
8793
  for (const suffix of ["-wal", "-shm"])
8316
- if (existsSync7(`${path}${suffix}`))
8317
- renameSync2(`${path}${suffix}`, `${kept}${suffix}`);
8794
+ if (existsSync9(`${path}${suffix}`))
8795
+ renameSync3(`${path}${suffix}`, `${kept}${suffix}`);
8318
8796
  }
8319
- renameSync2(incoming, path);
8797
+ renameSync3(incoming, path);
8320
8798
  result(command, { path, restoredFrom: given, keptAt: kept, schema: schema.version });
8321
8799
  if (kept)
8322
8800
  renderer.note(`the store it replaced is kept at ${kept}`);
@@ -8325,6 +8803,43 @@ var restoreFrom = /* @__PURE__ */ __name(async (command, messenger, backup, give
8325
8803
  renderer.note(`the backup is behind this build; the next command migrates it \u2014 \`${lineOf(command, "store migrate")}\` now`);
8326
8804
  }
8327
8805
  }, "restoreFrom");
8806
+ var isRollbackCopy = /* @__PURE__ */ __name(async (file2) => {
8807
+ try {
8808
+ return await readingOnly(file2, (database) => database.prepare("SELECT 1 FROM sqlite_master WHERE name = 'rollback_meta'").get() !== void 0);
8809
+ } catch {
8810
+ return false;
8811
+ }
8812
+ }, "isRollbackCopy");
8813
+ var rollBackFrom = /* @__PURE__ */ __name(async (command, messenger, copy) => {
8814
+ const { renderer } = outputFor(command);
8815
+ const path = storePath(environmentOf(command).env ?? process.env);
8816
+ if (!existsSync9(path))
8817
+ throw new CliError("not_found", `no store at ${path} to roll back`);
8818
+ const waitMs = environmentOf(command).storeLockWaitMs;
8819
+ await quiesce(path, messenger, "restore", (message) => renderer.warn(message), waitMs);
8820
+ const { database } = await openSqlite(path);
8821
+ let rolled;
8822
+ try {
8823
+ rolled = rollBack(database, copy);
8824
+ } finally {
8825
+ database.close();
8826
+ }
8827
+ result(command, {
8828
+ path,
8829
+ restoredFrom: copy,
8830
+ rolledBack: true,
8831
+ schema: rolled.from,
8832
+ was: rolled.was,
8833
+ tables: rolled.restored,
8834
+ rebuilt: rolled.rebuilt,
8835
+ foreignKeyViolations: rolled.foreignKeyViolations
8836
+ });
8837
+ const taken = new Date(rolled.createdAt).toISOString();
8838
+ renderer.note(`the store is back at schema ${rolled.from}; ${rolled.tables.length > 0 ? rolled.tables.join(", ") : "no table"} hold what they held at ${taken}, and what was written to them since is not kept`);
8839
+ renderer.note("open it with the older tool and run its `store rebuild`: the search indexes are behind the tables");
8840
+ renderer.note(`a tool that speaks schema ${rolled.to} or later migrates it again on its next run`);
8841
+ renderer.note("restart every serve and mcp of either CLI that was running, so they read the restored store");
8842
+ }, "rollBackFrom");
8328
8843
  var backupSchema = /* @__PURE__ */ __name(async (backup) => {
8329
8844
  let read;
8330
8845
  try {
@@ -8348,7 +8863,7 @@ var backupSchema = /* @__PURE__ */ __name(async (backup) => {
8348
8863
  var STORE_LOCK_WAIT_MS = 1e3;
8349
8864
  var quiesce = /* @__PURE__ */ __name(async (path, messenger, then, warn, waitMs = STORE_LOCK_WAIT_MS) => {
8350
8865
  const { command } = messenger.app;
8351
- const files = [path, `${path}-wal`, `${path}-shm`].filter((file2) => existsSync7(file2)).map((file2) => realpathSync(file2));
8866
+ const files = [path, `${path}-wal`, `${path}-shm`].filter((file2) => existsSync9(file2)).map((file2) => realpathSync2(file2));
8352
8867
  const holders = holdersOf(files);
8353
8868
  if (holders === void 0) {
8354
8869
  warn(`this system cannot say which processes have the store open \u2014 restart every running serve and mcp after this`);
@@ -8374,7 +8889,7 @@ var resetCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("r
8374
8889
  const { command } = messenger.app;
8375
8890
  const env = environmentOf(this).env ?? process.env;
8376
8891
  const path = storePath(env);
8377
- if (!existsSync7(path)) {
8892
+ if (!existsSync9(path)) {
8378
8893
  result(this, { path, exists: false, reset: false });
8379
8894
  renderer.note(`no store at ${path} \u2014 nothing to reset; the first \`${command}\` command that reads a chat creates it`);
8380
8895
  return;
@@ -8410,17 +8925,17 @@ var resetCommand = /* @__PURE__ */ __name((messenger) => annotate(new Command("r
8410
8925
  });
8411
8926
  renderer.note(`backed the store up to ${backup}`);
8412
8927
  }
8413
- for (const suffix of STORE_PARTS)
8414
- rmSync2(`${path}${suffix}`, { force: true });
8928
+ for (const suffix of STORE_PARTS2)
8929
+ rmSync3(`${path}${suffix}`, { force: true });
8415
8930
  await (await openStore({ path, command })).close();
8416
8931
  const schema = await reading(path, (database) => schemaOf(database).version);
8417
8932
  result(this, { path, exists: true, reset: true, backup, backedUp, schema });
8418
8933
  renderer.note(backup ? `the store is empty at schema ${schema}; \`${command} store restore ${backup}\` puts the old one back once a build can read it` : `the store is empty at schema ${schema}; there is no backup`);
8419
8934
  }), "resetCommand");
8420
- var STORE_PARTS = ["", "-wal", "-shm"];
8935
+ var STORE_PARTS2 = ["", "-wal", "-shm"];
8421
8936
  var resetPreview = /* @__PURE__ */ __name(async (path, messenger, env, keep) => {
8422
- const files = STORE_PARTS.map((suffix) => `${path}${suffix}`).filter((file2) => existsSync7(file2));
8423
- const holders = holdersOf(files.map((file2) => realpathSync(file2)));
8937
+ const files = STORE_PARTS2.map((suffix) => `${path}${suffix}`).filter((file2) => existsSync9(file2));
8938
+ const holders = holdersOf(files.map((file2) => realpathSync2(file2)));
8424
8939
  const serving = servingProfiles(messenger.app, env).length > 0;
8425
8940
  const read = await readingOnly(path, (database) => ({
8426
8941
  schema: schemaOf(database).version,
@@ -8451,6 +8966,9 @@ export {
8451
8966
  checkFor,
8452
8967
  passes,
8453
8968
  seal,
8969
+ storeRecoveryCheck,
8970
+ storeRecoveryRun,
8971
+ recoveryNotes,
8454
8972
  storeInfo,
8455
8973
  ENCRYPT_OPTION,
8456
8974
  passwordOf,