@wirecat/cli-memo 0.131.67 → 0.131.69
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.
- package/dist/bin/memo.js +2 -2
- package/dist/bundle/{all-profiles-W3GRNNLJ.js → all-profiles-6JKSPBBO.js} +5 -5
- package/dist/bundle/{anthropic-GWMYHBO4.js → anthropic-YA2N6EJ4.js} +2 -2
- package/dist/bundle/{app-server-RQ26EXNI.js → app-server-UP3AL2XQ.js} +35 -35
- package/dist/bundle/auto-IKZIROGF.js +85 -0
- package/dist/bundle/{bun-KKLPQTG5.js → bun-OUFOAYV4.js} +2 -2
- package/dist/bundle/{bun-sqlite-WKIZJNTG.js → bun-sqlite-5RZTFU2Q.js} +2 -2
- package/dist/bundle/{chunk-R4H5HSQZ.js → chunk-22CDLXSR.js} +4 -4
- package/dist/bundle/{chunk-XI5UABKO.js → chunk-267N22E4.js} +1 -1
- package/dist/bundle/{chunk-7IKET6ES.js → chunk-276KPJI5.js} +2 -2
- package/dist/bundle/{chunk-32ROGX5N.js → chunk-2C7Z7CKD.js} +1 -1
- package/dist/bundle/{chunk-NNUJWCEJ.js → chunk-2DQYP2K3.js} +1 -1
- package/dist/bundle/{chunk-TQXXOUOX.js → chunk-2F35N6BI.js} +1 -1
- package/dist/bundle/{chunk-BOOEDDVY.js → chunk-2NFI7SDW.js} +83 -63
- package/dist/bundle/{chunk-ECMYCWG2.js → chunk-3LGLKLBA.js} +2 -2
- package/dist/bundle/{chunk-Q4JYHQ47.js → chunk-3TFK7RBA.js} +342 -323
- package/dist/bundle/{chunk-VVTC2YAX.js → chunk-3YVLNOPE.js} +4 -4
- package/dist/bundle/{chunk-MLF5FLAP.js → chunk-4HSWIXYE.js} +4 -4
- package/dist/bundle/{chunk-GU3MRYK2.js → chunk-53EAI4VZ.js} +1 -1
- package/dist/bundle/{chunk-ZU6HZLZP.js → chunk-5EHUHZU5.js} +429 -90
- package/dist/bundle/{chunk-MCA265JM.js → chunk-5MUR6D2G.js} +19 -1
- package/dist/bundle/{chunk-ZVXXJYNW.js → chunk-5OMM4CDT.js} +2 -2
- package/dist/bundle/{chunk-AGNWFOAJ.js → chunk-67VEVKMJ.js} +1 -1
- package/dist/bundle/{chunk-JG7EDH7K.js → chunk-7JFLHRQL.js} +1 -1
- package/dist/bundle/{chunk-CQNYBTWP.js → chunk-7L4PBN5S.js} +2 -2
- package/dist/bundle/{chunk-WJ2OYD2D.js → chunk-BGWPKEKK.js} +4 -4
- package/dist/bundle/{chunk-TPYXULNG.js → chunk-BJJULUUC.js} +5 -5
- package/dist/bundle/{chunk-VUCD4DAQ.js → chunk-ECHN36DC.js} +4 -4
- package/dist/bundle/{chunk-TXWVZVDK.js → chunk-EDPA54WQ.js} +3 -3
- package/dist/bundle/{chunk-JEKIBI7P.js → chunk-EKSOPEFQ.js} +4 -4
- package/dist/bundle/{chunk-ZOIW2YEU.js → chunk-EO4JMJFZ.js} +7 -7
- package/dist/bundle/{chunk-7DANHJF6.js → chunk-FQ54GW57.js} +31 -31
- package/dist/bundle/{chunk-DNDELSVT.js → chunk-FZHYGJQ2.js} +5 -5
- package/dist/bundle/{chunk-IKZBO7NV.js → chunk-GGFL64HF.js} +623 -509
- package/dist/bundle/{chunk-FBSHWCIZ.js → chunk-GVEY6743.js} +9 -9
- package/dist/bundle/{chunk-TNHFKR6P.js → chunk-GVP6CAPH.js} +21 -21
- package/dist/bundle/{chunk-4JTCNMW6.js → chunk-IHHXGTMX.js} +1 -1
- package/dist/bundle/{chunk-TWTAWPC7.js → chunk-IJAILIZR.js} +12 -12
- package/dist/bundle/{chunk-XK4VVGMH.js → chunk-JMGQATR6.js} +2 -2
- package/dist/bundle/{chunk-GHN2KYMO.js → chunk-LYAJUZM4.js} +21 -21
- package/dist/bundle/{chunk-YAFSD345.js → chunk-MK6SQ32Q.js} +12 -12
- package/dist/bundle/{chunk-XVPMSMSP.js → chunk-MWQI6FSU.js} +3 -3
- package/dist/bundle/{chunk-7OMKWYFN.js → chunk-MYLNRBDF.js} +16 -9
- package/dist/bundle/{chunk-W7FYMZOW.js → chunk-N73YBQ42.js} +6 -6
- package/dist/bundle/{chunk-ZNBLWLCD.js → chunk-OAO5UCPJ.js} +151 -151
- package/dist/bundle/{chunk-OUSLPKWY.js → chunk-OBQ7TSUB.js} +1 -1
- package/dist/bundle/{chunk-TFAUB6JO.js → chunk-OHA7HDPX.js} +374 -306
- package/dist/bundle/{chunk-QCWA3JUT.js → chunk-PHSYMVYX.js} +2 -2
- package/dist/bundle/{chunk-HUPZ6XYH.js → chunk-PSYQPO6D.js} +2 -2
- package/dist/bundle/{chunk-SKBDI7LU.js → chunk-QAXIZHK7.js} +28 -28
- package/dist/bundle/{chunk-GUWRR7F2.js → chunk-QZU5IM5E.js} +2 -2
- package/dist/bundle/{chunk-SUCG5HBF.js → chunk-RHW3DDWI.js} +1 -1
- package/dist/bundle/{chunk-OU4PN7PF.js → chunk-TV75OHKJ.js} +7 -7
- package/dist/bundle/{chunk-4C6RU7DG.js → chunk-TVZXLAID.js} +4 -4
- package/dist/bundle/{chunk-7KYVUVDS.js → chunk-TXOXPQN2.js} +2 -2
- package/dist/bundle/{chunk-QMTCYKAA.js → chunk-UEMI6FXR.js} +6 -6
- package/dist/bundle/{chunk-QFSMJTEA.js → chunk-V2YS63Z5.js} +1 -1
- package/dist/bundle/{chunk-6SFTVGNL.js → chunk-VPKJZKXV.js} +1 -1
- package/dist/bundle/{chunk-XYL7GDCX.js → chunk-W2FFA7T5.js} +5 -5
- package/dist/bundle/{chunk-DNS2QWK3.js → chunk-WNA2WNDK.js} +3 -3
- package/dist/bundle/{chunk-ORKWFXWV.js → chunk-XTEJXJJ3.js} +10 -10
- package/dist/bundle/{chunk-GJ3P7RJF.js → chunk-YTJWIJIG.js} +5 -5
- package/dist/bundle/{chunk-PBOVHHYG.js → chunk-YXXAPVAZ.js} +8 -8
- package/dist/bundle/{command-contract-46BU5YKL.js → command-contract-OGW2DX4C.js} +11 -11
- package/dist/bundle/{decode-KRVQZPSB.js → decode-IJMDTGTW.js} +2 -2
- package/dist/bundle/{echarts-O6QQRVZE.js → echarts-EHYUXOKP.js} +2 -2
- package/dist/bundle/{embed-DA4H2F4F.js → embed-RUY3UIVC.js} +3 -3
- package/dist/bundle/{embedder-HWAFLIYM.js → embedder-P6WBMEGP.js} +6 -6
- package/dist/bundle/{entry-DE7GJOIZ.js → entry-7S2ONYSF.js} +4 -4
- package/dist/bundle/failure-NRZUB77S.js +65 -0
- package/dist/bundle/{first-run-GOBPIKQF.js → first-run-MLIFZSVH.js} +5 -5
- package/dist/bundle/{first-screen-3V3HWSQM.js → first-screen-DGTTK6VK.js} +12 -12
- package/dist/bundle/{instructions-GYYMBSZW.js → instructions-ZMG4FLGO.js} +1 -1
- package/dist/bundle/{mcp-6RDHWRXG.js → mcp-CFIL7WZU.js} +35 -35
- package/dist/bundle/memo.js +6 -6
- package/dist/bundle/{node-R3OFASC5.js → node-QYL4B7JS.js} +2 -2
- package/dist/bundle/{node-sqlite-DYHDZJ5A.js → node-sqlite-ESTT2OCF.js} +3 -3
- package/dist/bundle/{oauth-SMCDSCXQ.js → oauth-CFQFSIRQ.js} +4 -4
- package/dist/bundle/{open-GX7RPGQW.js → open-3XO2HMIT.js} +2 -2
- package/dist/bundle/{openai-WM4TRXCC.js → openai-STUNDBD6.js} +7 -7
- package/dist/bundle/{process-NT5OZH2V.js → process-P4UAJCZX.js} +1 -1
- package/dist/bundle/{program-YQ3UT2LI.js → program-BXL5ZOVQ.js} +2052 -1870
- package/dist/bundle/{prompt-5XJNSXCW.js → prompt-ZCYMFMIG.js} +2 -2
- package/dist/bundle/{recognize-DQNGZLRX.js → recognize-V3BY33FK.js} +1 -1
- package/dist/bundle/{remote-RMRYJZSZ.js → remote-IP4QR7SP.js} +4 -4
- package/dist/bundle/{rerank-5J6JM43S.js → rerank-VKUSF3DM.js} +4 -4
- package/dist/bundle/{serve-4RVWOQVC.js → serve-VBIUARHJ.js} +6 -6
- package/dist/bundle/server-AASCSGCI.js +61 -0
- package/dist/bundle/{server-NKCRFK26.js → server-JLPZUC42.js} +49 -49
- package/dist/bundle/server-YQLPZK4Z.js +48 -0
- package/dist/bundle/{state-MGVPOLPZ.js → state-UBAIZ2WP.js} +3 -3
- package/dist/bundle/{store-IEK4PPOE.js → store-VQQVUA4W.js} +9 -9
- package/dist/bundle/store-maintenance-command-GCBABKEZ.js +47 -0
- package/dist/bundle/update-M54Z3SEU.js +68 -0
- package/dist/digest/backfill.d.ts +9 -0
- package/dist/digest/backfill.d.ts.map +1 -0
- package/dist/digest/backfill.js +142 -0
- package/dist/digest/backfill.js.map +1 -0
- package/dist/digest/command.d.ts +2 -0
- package/dist/digest/command.d.ts.map +1 -1
- package/dist/digest/command.js +18 -1
- package/dist/digest/command.js.map +1 -1
- package/dist/digest/digest.d.ts +6 -1
- package/dist/digest/digest.d.ts.map +1 -1
- package/dist/digest/digest.js +26 -15
- package/dist/digest/digest.js.map +1 -1
- package/dist/digest/sync-health.d.ts +1 -2
- package/dist/digest/sync-health.d.ts.map +1 -1
- package/dist/digest/tasks.d.ts +14 -1
- package/dist/digest/tasks.d.ts.map +1 -1
- package/dist/digest/tasks.js +31 -4
- package/dist/digest/tasks.js.map +1 -1
- package/dist/discovery/command.d.ts.map +1 -1
- package/dist/discovery/command.js +1 -0
- package/dist/discovery/command.js.map +1 -1
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +7 -1
- package/dist/examples.js.map +1 -1
- package/dist/knowledge/command.d.ts.map +1 -1
- package/dist/knowledge/command.js +17 -6
- package/dist/knowledge/command.js.map +1 -1
- package/dist/knowledge/project-context.d.ts.map +1 -1
- package/dist/knowledge/project-context.js +3 -2
- package/dist/knowledge/project-context.js.map +1 -1
- package/dist/knowledge/relationships.d.ts +2 -0
- package/dist/knowledge/relationships.d.ts.map +1 -1
- package/dist/knowledge/relationships.js +11 -2
- package/dist/knowledge/relationships.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +2 -0
- package/dist/program.js.map +1 -1
- package/dist/read-only.d.ts +1 -1
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +18 -0
- package/dist/reasons.js.map +1 -1
- package/dist/schedule/command.d.ts +2 -1
- package/dist/schedule/command.d.ts.map +1 -1
- package/dist/schedule/command.js +6 -2
- package/dist/schedule/command.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/skills/cli-memo/topics/projects.md +7 -0
- package/skills/mail-triage/SKILL.md +25 -19
- package/skills/morning-digest/SKILL.md +15 -1
- package/dist/bundle/auto-FR6LX5KO.js +0 -85
- package/dist/bundle/failure-U3VNIQNX.js +0 -65
- package/dist/bundle/server-HH2X6G7V.js +0 -61
- package/dist/bundle/server-MS3JKMGF.js +0 -48
- package/dist/bundle/store-maintenance-command-GSS2AY4J.js +0 -47
- package/dist/bundle/update-S5XRRWTH.js +0 -68
- /package/dist/bundle/{chunk-DS7NXKAN.js → chunk-AWVQHWIS.js} +0 -0
|
@@ -6,17 +6,17 @@ import {
|
|
|
6
6
|
autoState,
|
|
7
7
|
lastAutoRun,
|
|
8
8
|
recordAutoRun
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-EKSOPEFQ.js";
|
|
10
10
|
import {
|
|
11
11
|
installer,
|
|
12
12
|
latest,
|
|
13
13
|
upgradeCommand
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BJJULUUC.js";
|
|
15
15
|
import {
|
|
16
16
|
mcpOwnerAllowed,
|
|
17
17
|
readOnlyAvailability,
|
|
18
18
|
refuseWritesUnderLock
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-W2FFA7T5.js";
|
|
20
20
|
import {
|
|
21
21
|
answers,
|
|
22
22
|
atDetail,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
trackAnswers,
|
|
28
28
|
wholeList,
|
|
29
29
|
withStore
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-TVZXLAID.js";
|
|
31
31
|
import {
|
|
32
32
|
ATTACHMENT_CHARS,
|
|
33
33
|
DIALECTS,
|
|
@@ -59,22 +59,24 @@ import {
|
|
|
59
59
|
showMail,
|
|
60
60
|
unsetConfigKey,
|
|
61
61
|
updateConfig
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-FQ54GW57.js";
|
|
63
63
|
import "./chunk-QP3KNC5D.js";
|
|
64
|
-
import "./chunk-
|
|
65
|
-
import "./chunk-
|
|
66
|
-
import "./chunk-
|
|
64
|
+
import "./chunk-TXOXPQN2.js";
|
|
65
|
+
import "./chunk-EO4JMJFZ.js";
|
|
66
|
+
import "./chunk-MWQI6FSU.js";
|
|
67
67
|
import {
|
|
68
68
|
errorObject,
|
|
69
69
|
recognisable
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-3YVLNOPE.js";
|
|
71
71
|
import {
|
|
72
72
|
AGENT_INPUT_MAX_CHARS,
|
|
73
73
|
DISCOVERY_DESCRIPTIONS,
|
|
74
74
|
DOCTOR_DEEP_OPTION,
|
|
75
|
+
SCHEDULE_DEFAULTS,
|
|
75
76
|
addContractInfo,
|
|
76
77
|
addMeetingPreparationCommand,
|
|
77
78
|
advancePastSkipped,
|
|
79
|
+
backfillScheduleRun,
|
|
78
80
|
checkJson,
|
|
79
81
|
dateOrNone,
|
|
80
82
|
entityFields,
|
|
@@ -97,42 +99,45 @@ import {
|
|
|
97
99
|
projectStatusText,
|
|
98
100
|
projectWindowOf,
|
|
99
101
|
readMailFindingsJson,
|
|
102
|
+
readSchedule,
|
|
100
103
|
recordRuns,
|
|
101
104
|
runsCommand,
|
|
102
105
|
scheduleCommandFor,
|
|
106
|
+
scheduleFile,
|
|
103
107
|
scheduledRuns,
|
|
104
108
|
sharedCommandTemplate,
|
|
105
109
|
skillCommand as skillCommand2,
|
|
110
|
+
spentToday,
|
|
106
111
|
tasksCommand,
|
|
107
112
|
tasksStatsCommand,
|
|
108
113
|
templatesCommand,
|
|
109
114
|
withSqliteSidecars
|
|
110
|
-
} from "./chunk-
|
|
111
|
-
import "./chunk-
|
|
112
|
-
import "./chunk-
|
|
115
|
+
} from "./chunk-OHA7HDPX.js";
|
|
116
|
+
import "./chunk-7JFLHRQL.js";
|
|
117
|
+
import "./chunk-RHW3DDWI.js";
|
|
113
118
|
import {
|
|
114
119
|
allHitItem,
|
|
115
120
|
coverageGaps,
|
|
116
121
|
messageHitItem,
|
|
117
122
|
noteHitItem,
|
|
118
123
|
shownOf
|
|
119
|
-
} from "./chunk-
|
|
120
|
-
import "./chunk-
|
|
124
|
+
} from "./chunk-LYAJUZM4.js";
|
|
125
|
+
import "./chunk-OBQ7TSUB.js";
|
|
121
126
|
import {
|
|
122
127
|
REASONS as REASONS2,
|
|
123
128
|
SKILL_TARGETS,
|
|
124
129
|
skillCommand,
|
|
125
130
|
skillPath,
|
|
126
131
|
skillVersion
|
|
127
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-MYLNRBDF.js";
|
|
128
133
|
import {
|
|
129
134
|
recoveryNotes,
|
|
130
135
|
storeInfo,
|
|
131
136
|
storeRecoveryCheck,
|
|
132
137
|
storeRecoveryRun,
|
|
133
138
|
storeSummary
|
|
134
|
-
} from "./chunk-
|
|
135
|
-
import "./chunk-
|
|
139
|
+
} from "./chunk-5EHUHZU5.js";
|
|
140
|
+
import "./chunk-GVP6CAPH.js";
|
|
136
141
|
import {
|
|
137
142
|
LIST_QUERY_GUIDE,
|
|
138
143
|
STATUS_SIGNALS,
|
|
@@ -192,18 +197,18 @@ import {
|
|
|
192
197
|
timeLimit,
|
|
193
198
|
typedQuery,
|
|
194
199
|
withQuery
|
|
195
|
-
} from "./chunk-
|
|
200
|
+
} from "./chunk-3TFK7RBA.js";
|
|
196
201
|
import {
|
|
197
202
|
readBoundedUtf8File,
|
|
198
203
|
writeFileAtomic
|
|
199
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-MK6SQ32Q.js";
|
|
200
205
|
import {
|
|
201
206
|
commandsText,
|
|
202
207
|
inSection,
|
|
203
208
|
installHelp
|
|
204
|
-
} from "./chunk-
|
|
209
|
+
} from "./chunk-UEMI6FXR.js";
|
|
205
210
|
import "./chunk-HTQTIKWP.js";
|
|
206
|
-
import "./chunk-
|
|
211
|
+
import "./chunk-JMGQATR6.js";
|
|
207
212
|
import {
|
|
208
213
|
Command,
|
|
209
214
|
DEFAULT_TEXT_MODEL,
|
|
@@ -240,23 +245,23 @@ import {
|
|
|
240
245
|
snakeKeys,
|
|
241
246
|
textModels,
|
|
242
247
|
textModelsFile
|
|
243
|
-
} from "./chunk-
|
|
244
|
-
import "./chunk-
|
|
245
|
-
import "./chunk-
|
|
248
|
+
} from "./chunk-OAO5UCPJ.js";
|
|
249
|
+
import "./chunk-N73YBQ42.js";
|
|
250
|
+
import "./chunk-XTEJXJJ3.js";
|
|
246
251
|
import {
|
|
247
252
|
isNewer
|
|
248
253
|
} from "./chunk-LJCT7YG6.js";
|
|
249
254
|
import "./chunk-L62FWN3Y.js";
|
|
250
|
-
import "./chunk-
|
|
251
|
-
import "./chunk-
|
|
252
|
-
import "./chunk-
|
|
253
|
-
import "./chunk-
|
|
255
|
+
import "./chunk-EDPA54WQ.js";
|
|
256
|
+
import "./chunk-GVEY6743.js";
|
|
257
|
+
import "./chunk-2DQYP2K3.js";
|
|
258
|
+
import "./chunk-22CDLXSR.js";
|
|
254
259
|
import {
|
|
255
260
|
releaseLock,
|
|
256
261
|
servingProfiles,
|
|
257
262
|
takeLock
|
|
258
|
-
} from "./chunk-
|
|
259
|
-
import "./chunk-
|
|
263
|
+
} from "./chunk-7L4PBN5S.js";
|
|
264
|
+
import "./chunk-IHHXGTMX.js";
|
|
260
265
|
import {
|
|
261
266
|
EVIDENCE_FINDINGS_KIND,
|
|
262
267
|
MAIL_FINDINGS_KIND,
|
|
@@ -298,7 +303,7 @@ import {
|
|
|
298
303
|
plainQuery,
|
|
299
304
|
providerNamed,
|
|
300
305
|
refLabel
|
|
301
|
-
} from "./chunk-
|
|
306
|
+
} from "./chunk-GGFL64HF.js";
|
|
302
307
|
import {
|
|
303
308
|
CATALOG_KINDS,
|
|
304
309
|
CONTRACT_KINDS,
|
|
@@ -306,6 +311,7 @@ import {
|
|
|
306
311
|
DEAL_KINDS,
|
|
307
312
|
DEAL_ROLES,
|
|
308
313
|
DEAL_STATUSES,
|
|
314
|
+
ENGAGEMENT_LEVELS,
|
|
309
315
|
FACT_STATUSES,
|
|
310
316
|
FACT_TYPES,
|
|
311
317
|
FINANCE_REVIEWS,
|
|
@@ -326,6 +332,7 @@ import {
|
|
|
326
332
|
TRANSACTION_STATUSES,
|
|
327
333
|
WALLET_KINDS,
|
|
328
334
|
WORK_TASK_TYPES,
|
|
335
|
+
byEngagement,
|
|
329
336
|
createUpcomingMeetingReader,
|
|
330
337
|
dateRange,
|
|
331
338
|
dayBoundary,
|
|
@@ -347,21 +354,21 @@ import {
|
|
|
347
354
|
timezoneOf,
|
|
348
355
|
validateQuery,
|
|
349
356
|
walkQuery
|
|
350
|
-
} from "./chunk-
|
|
351
|
-
import "./chunk-
|
|
352
|
-
import "./chunk-
|
|
353
|
-
import "./chunk-
|
|
354
|
-
import "./chunk-
|
|
355
|
-
import "./chunk-
|
|
356
|
-
import "./chunk-
|
|
357
|
-
import "./chunk-
|
|
358
|
-
import "./chunk-
|
|
357
|
+
} from "./chunk-2NFI7SDW.js";
|
|
358
|
+
import "./chunk-3LGLKLBA.js";
|
|
359
|
+
import "./chunk-TV75OHKJ.js";
|
|
360
|
+
import "./chunk-BGWPKEKK.js";
|
|
361
|
+
import "./chunk-PHSYMVYX.js";
|
|
362
|
+
import "./chunk-2C7Z7CKD.js";
|
|
363
|
+
import "./chunk-5OMM4CDT.js";
|
|
364
|
+
import "./chunk-QZU5IM5E.js";
|
|
365
|
+
import "./chunk-FZHYGJQ2.js";
|
|
359
366
|
import {
|
|
360
367
|
sharedModelsDirectory
|
|
361
|
-
} from "./chunk-
|
|
368
|
+
} from "./chunk-WNA2WNDK.js";
|
|
362
369
|
import {
|
|
363
370
|
storePath
|
|
364
|
-
} from "./chunk-
|
|
371
|
+
} from "./chunk-V2YS63Z5.js";
|
|
365
372
|
import {
|
|
366
373
|
provideTerminal,
|
|
367
374
|
terminalOf
|
|
@@ -371,12 +378,12 @@ import {
|
|
|
371
378
|
REASONS,
|
|
372
379
|
STORE_CLIENT,
|
|
373
380
|
VERSION
|
|
374
|
-
} from "./chunk-
|
|
381
|
+
} from "./chunk-5MUR6D2G.js";
|
|
375
382
|
import "./chunk-DSU6UR2X.js";
|
|
376
383
|
import "./chunk-SYWHHQMC.js";
|
|
377
384
|
import "./chunk-D72URWJE.js";
|
|
378
|
-
import "./chunk-
|
|
379
|
-
import "./chunk-
|
|
385
|
+
import "./chunk-YTJWIJIG.js";
|
|
386
|
+
import "./chunk-67VEVKMJ.js";
|
|
380
387
|
import {
|
|
381
388
|
configFilePath,
|
|
382
389
|
createDeadline,
|
|
@@ -416,7 +423,7 @@ import {
|
|
|
416
423
|
errorCodes,
|
|
417
424
|
isCliError
|
|
418
425
|
} from "./chunk-ZTONSM5X.js";
|
|
419
|
-
import "./chunk-
|
|
426
|
+
import "./chunk-VPKJZKXV.js";
|
|
420
427
|
import {
|
|
421
428
|
__name
|
|
422
429
|
} from "./chunk-ZVVMGPBJ.js";
|
|
@@ -703,7 +710,7 @@ var readScope = /* @__PURE__ */ __name((command, help = ONE_ACCOUNT_HELP) => sou
|
|
|
703
710
|
var writeScope = /* @__PURE__ */ __name((command, help) => writeOptions(command, help).option("--json", "print JSON; --json=id,title keeps only those fields"), "writeScope");
|
|
704
711
|
var jsonOption = /* @__PURE__ */ __name((command, fields = "ref,title") => command.option("--json", `print JSON; --json=${fields} keeps only those fields`), "jsonOption");
|
|
705
712
|
|
|
706
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
713
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/mail/sender-scores.js
|
|
707
714
|
var SCORED = "mail_sender_scores";
|
|
708
715
|
var DAY = 864e5;
|
|
709
716
|
var RECENT = 2 * 365 * DAY;
|
|
@@ -719,7 +726,7 @@ var demotedSenders = /* @__PURE__ */ __name(async (store) => {
|
|
|
719
726
|
return senders;
|
|
720
727
|
}, "demotedSenders");
|
|
721
728
|
|
|
722
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
729
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/mail/sync.js
|
|
723
730
|
var DAY2 = 864e5;
|
|
724
731
|
var EDGE = 2 * DAY2;
|
|
725
732
|
|
|
@@ -2028,7 +2035,7 @@ import { createHash } from "node:crypto";
|
|
|
2028
2035
|
import { existsSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
2029
2036
|
import { basename, extname, relative, sep } from "node:path";
|
|
2030
2037
|
|
|
2031
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
2038
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/services/documents/extraction.js
|
|
2032
2039
|
var Proposal = object({
|
|
2033
2040
|
kind: picklist(["summary", "digest", "fact", "preference"]),
|
|
2034
2041
|
body: pipe(string(), trim(), minLength(1), maxLength(15e3)),
|
|
@@ -2036,13 +2043,13 @@ var Proposal = object({
|
|
|
2036
2043
|
});
|
|
2037
2044
|
var Proposals = object({ items: pipe(array(Proposal), maxLength(20)) });
|
|
2038
2045
|
|
|
2039
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
2046
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/services/documents/mirrors.js
|
|
2040
2047
|
var ID = pipe(string(), regex(/^[A-Za-z0-9_-]{1,200}$/));
|
|
2041
2048
|
|
|
2042
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
2049
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/services/documents/sync.js
|
|
2043
2050
|
var MAX_PICTURE_BYTES = 25 * 1024 * 1024;
|
|
2044
2051
|
|
|
2045
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
2052
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/fetch/addresses.js
|
|
2046
2053
|
import { isIP } from "node:net";
|
|
2047
2054
|
var within3 = /* @__PURE__ */ __name((address, [prefix, bits]) => {
|
|
2048
2055
|
for (let bit = 0; bit < bits; bit++) {
|
|
@@ -2113,7 +2120,7 @@ var isPublicAddress = /* @__PURE__ */ __name((address) => {
|
|
|
2113
2120
|
return within3(bytes, [[32], 3]) && !V6_PRIVATE.some((prefix) => within3(bytes, prefix));
|
|
2114
2121
|
}, "isPublicAddress");
|
|
2115
2122
|
|
|
2116
|
-
// node_modules/.pnpm/@wirecat+cli-core@0.
|
|
2123
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/fetch/page.js
|
|
2117
2124
|
import { lookup as dnsLookup } from "node:dns/promises";
|
|
2118
2125
|
import { request as httpRequest } from "node:http";
|
|
2119
2126
|
import { request as httpsRequest } from "node:https";
|
|
@@ -4426,1822 +4433,1957 @@ var skill = [
|
|
|
4426
4433
|
// dist/contract-overrides.js
|
|
4427
4434
|
var SHELL_OVERRIDES = { search, doctor, skill, mcp, commands, notes, meetings };
|
|
4428
4435
|
|
|
4429
|
-
// dist/
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4436
|
+
// dist/digest/backfill.js
|
|
4437
|
+
import { existsSync as existsSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
4438
|
+
import { join as join6 } from "node:path";
|
|
4439
|
+
|
|
4440
|
+
// dist/digest/tasks.js
|
|
4441
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
4442
|
+
import { join as join5 } from "node:path";
|
|
4443
|
+
|
|
4444
|
+
// dist/tasks/list.js
|
|
4445
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
4446
|
+
var OPEN_WORK = "state:(open OR todo OR in_progress)";
|
|
4447
|
+
var TASKS_LIST_QUERY = {
|
|
4448
|
+
entity: "task",
|
|
4449
|
+
backend: "sql",
|
|
4450
|
+
fields: [
|
|
4451
|
+
...PROJECT_TASK_FIELDS,
|
|
4452
|
+
{
|
|
4453
|
+
name: "source",
|
|
4454
|
+
type: "ref",
|
|
4455
|
+
operators: ["term", "phrase"],
|
|
4456
|
+
example: 'source:"msg:telegram/1/7/1"',
|
|
4457
|
+
relation: "tasks from this message, note or document; an account's tasks only"
|
|
4446
4458
|
}
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
[
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
var placeInSections = /* @__PURE__ */ __name((program) => {
|
|
4502
|
-
for (const [path, section2] of SECTIONS) {
|
|
4503
|
-
let command = program;
|
|
4504
|
-
for (const name2 of path.split(" "))
|
|
4505
|
-
command = command?.commands.find((child) => child.name() === name2);
|
|
4506
|
-
if (!command)
|
|
4507
|
-
throw new Error(`no command to place in a section: ${path}`);
|
|
4508
|
-
inSection(command, section2);
|
|
4459
|
+
],
|
|
4460
|
+
defaults: [OPEN_WORK]
|
|
4461
|
+
};
|
|
4462
|
+
var ACCOUNT_FIELDS = /* @__PURE__ */ new Set(["state", "source"]);
|
|
4463
|
+
var taskItem = /* @__PURE__ */ __name((task, extra = {}) => {
|
|
4464
|
+
const { held, readiness } = extra;
|
|
4465
|
+
return {
|
|
4466
|
+
ref: task.ref,
|
|
4467
|
+
id: task.id,
|
|
4468
|
+
key: task.key,
|
|
4469
|
+
title: task.title,
|
|
4470
|
+
description: task.description,
|
|
4471
|
+
kind: task.type,
|
|
4472
|
+
state: task.status,
|
|
4473
|
+
project: task.project,
|
|
4474
|
+
project_key: task.projectKey,
|
|
4475
|
+
project_name: task.projectName,
|
|
4476
|
+
...held ? {
|
|
4477
|
+
origin: held.origin,
|
|
4478
|
+
account: held.account,
|
|
4479
|
+
chat: held.sourceKind === "note" ? null : formatReference({
|
|
4480
|
+
type: "chat",
|
|
4481
|
+
provider: held.account.split(":")[0] ?? "",
|
|
4482
|
+
account: held.account.split(":").slice(1).join(":"),
|
|
4483
|
+
chat: held.group
|
|
4484
|
+
})
|
|
4485
|
+
} : {},
|
|
4486
|
+
source_message: task.source,
|
|
4487
|
+
external_id: task.externalId,
|
|
4488
|
+
source_url: task.sourceUrl,
|
|
4489
|
+
priority: task.priority,
|
|
4490
|
+
priority_label: task.priorityLabel,
|
|
4491
|
+
agent: task.agent,
|
|
4492
|
+
revision: task.revision,
|
|
4493
|
+
parent: task.parent,
|
|
4494
|
+
due_at: task.dueAt,
|
|
4495
|
+
closed_at: task.closedAt,
|
|
4496
|
+
reason: task.reason,
|
|
4497
|
+
category: task.category,
|
|
4498
|
+
claimed_by: task.claimedBy,
|
|
4499
|
+
claimed_until: task.claimedUntil,
|
|
4500
|
+
...readiness ? { assignments: task.assignments, ready: readiness.ready, blocked_by: readiness.blockers } : {},
|
|
4501
|
+
created_by: task.createdBy,
|
|
4502
|
+
created_at: task.createdAt,
|
|
4503
|
+
updated_at: task.updatedAt
|
|
4504
|
+
};
|
|
4505
|
+
}, "taskItem");
|
|
4506
|
+
var accountTasks = /* @__PURE__ */ __name(async (store, keys, options) => {
|
|
4507
|
+
const pages = await Promise.all(keys.map((key) => store.knowledge.taskIds(key, options)));
|
|
4508
|
+
const items = [];
|
|
4509
|
+
for (const id of pages.flatMap((page) => page.items)) {
|
|
4510
|
+
const held = await store.tasks.get(id);
|
|
4511
|
+
if (held)
|
|
4512
|
+
items.push(taskItem(await store.tasks.details(id), { held }));
|
|
4509
4513
|
}
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
if (!command)
|
|
4517
|
-
throw new Error("discovery builder did not install its command");
|
|
4518
|
-
return command;
|
|
4519
|
-
}, SHELL_OVERRIDES.commands);
|
|
4520
|
-
}, "commandsCommand");
|
|
4521
|
-
|
|
4522
|
-
// dist/doctor/command.js
|
|
4523
|
-
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync4 } from "node:fs";
|
|
4524
|
-
import { homedir } from "node:os";
|
|
4525
|
-
import { dirname, join as join3 } from "node:path";
|
|
4526
|
-
var retiredMailAddresses = /* @__PURE__ */ __name((mail) => {
|
|
4527
|
-
const accounts = mail?.accounts;
|
|
4528
|
-
if (!Array.isArray(accounts))
|
|
4529
|
-
return [];
|
|
4530
|
-
return accounts.map((account2) => account2?.address).filter((address) => typeof address === "string");
|
|
4531
|
-
}, "retiredMailAddresses");
|
|
4532
|
-
var unitPaths = /* @__PURE__ */ __name((unit) => [...(/^ExecStart=(.*)$/m.exec(unit)?.[1] ?? "").matchAll(/"((?:[^"\\]|\\.)*)"/g)].map(([, path]) => path?.replace(/\\(["\\])/g, "$1") ?? "").filter((path) => path.startsWith("/")), "unitPaths");
|
|
4533
|
-
var diagnose = /* @__PURE__ */ __name(async (env, program, { deep = false } = {}) => {
|
|
4534
|
-
const problems = [];
|
|
4535
|
-
const paths = resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env });
|
|
4536
|
-
const { config, ...configReport } = inspectConfig(env, program);
|
|
4537
|
-
const files = privateFiles({
|
|
4538
|
-
files: [configReport.path, ...withSqliteSidecars(storePath(env))],
|
|
4539
|
-
// A folder the owner chose with MESSAGING_STORE may rightly be shared, like the home folder itself.
|
|
4540
|
-
dirs: [dirname(configReport.path), ...env.MESSAGING_STORE ? [] : [dirname(storePath(env))], runsDirFor(APP, env)]
|
|
4514
|
+
items.sort((a, b) => a.created_at.localeCompare(b.created_at));
|
|
4515
|
+
return listAnswer("tasks list", {
|
|
4516
|
+
items: items.slice(0, options.limit),
|
|
4517
|
+
limit: options.limit,
|
|
4518
|
+
has_more: items.length > options.limit || pages.some((page) => page.hasMore),
|
|
4519
|
+
meta: { accounts: keys.map(accountName) }
|
|
4541
4520
|
});
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
if (
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
what: `memo no longer imports mail, so the config's mail settings do nothing; the mail CLI syncs ${addresses.length ? addresses.join(", ") : "each mailbox"} into the same store (mail <profile> session start --address <address>, then mail <profile> sync), and the mail already stored stays`,
|
|
4570
|
-
fix: "memo config unset mail"
|
|
4571
|
-
});
|
|
4572
|
-
}
|
|
4573
|
-
let textModel = DEFAULT_TEXT_MODEL;
|
|
4521
|
+
}, "accountTasks");
|
|
4522
|
+
var accountTerms = /* @__PURE__ */ __name((query) => {
|
|
4523
|
+
const leaves2 = query ? walkQuery(query.root) : [];
|
|
4524
|
+
const other = leaves2.find(({ field: field2 }) => !ACCOUNT_FIELDS.has(field2));
|
|
4525
|
+
if (other)
|
|
4526
|
+
throw new CliError("validation_error", `${other.field}: narrows project tasks: add project:<key>, or project:* for every project`);
|
|
4527
|
+
const states = new Set(leaves2.filter(({ field: field2 }) => field2 === "state").map(({ value }) => value.toLowerCase()));
|
|
4528
|
+
if ((states.has("todo") || states.has("in_progress")) && !states.has("open"))
|
|
4529
|
+
throw new CliError("validation_error", "todo and in_progress are steps of a project task: add project:");
|
|
4530
|
+
const closed = [...states].filter(isClosedState);
|
|
4531
|
+
if (closed.length > 1 || closed.length === 1 && states.size > 1)
|
|
4532
|
+
throw new CliError("validation_error", "an account's tasks are listed in one state: state:open, done or dismissed");
|
|
4533
|
+
const sources = leaves2.filter(({ field: field2 }) => field2 === "source").map(({ value }) => value);
|
|
4534
|
+
if (sources.length > 1)
|
|
4535
|
+
throw new CliError("validation_error", "source: only once here");
|
|
4536
|
+
return { state: closed[0] ?? "open", source: sources[0] };
|
|
4537
|
+
}, "accountTerms");
|
|
4538
|
+
var resolveProjects = /* @__PURE__ */ __name(async (store, query) => {
|
|
4539
|
+
for (const node of query ? walkQuery(query.root) : [])
|
|
4540
|
+
if (node.field === "project" && node.operator !== "wildcard" && node.operator !== "range")
|
|
4541
|
+
node.value = await canonicalProject(store, node.value);
|
|
4542
|
+
return query;
|
|
4543
|
+
}, "resolveProjects");
|
|
4544
|
+
var offsetOf = /* @__PURE__ */ __name((cursor, key) => {
|
|
4545
|
+
if (cursor === void 0)
|
|
4546
|
+
return 0;
|
|
4547
|
+
let read;
|
|
4574
4548
|
try {
|
|
4575
|
-
|
|
4576
|
-
} catch
|
|
4577
|
-
|
|
4578
|
-
what: `the embedding model choice cannot be read: ${error instanceof Error ? error.message : String(error)}`,
|
|
4579
|
-
fix: `fix text_models in ${textModelsFile(env)}, or remove it to go back to ${DEFAULT_TEXT_MODEL}`
|
|
4580
|
-
});
|
|
4549
|
+
read = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
4550
|
+
} catch {
|
|
4551
|
+
read = void 0;
|
|
4581
4552
|
}
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
const
|
|
4588
|
-
const
|
|
4589
|
-
const
|
|
4590
|
-
const
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4553
|
+
if (read?.version !== 1 || read.key !== key || !Number.isSafeInteger(read.offset) || read.offset < 0)
|
|
4554
|
+
throw new CliError("validation_error", "the cursor belongs to another query or order; list again without it");
|
|
4555
|
+
return read.offset;
|
|
4556
|
+
}, "offsetOf");
|
|
4557
|
+
var projectTasks = /* @__PURE__ */ __name(async (store, typed, query, options) => {
|
|
4558
|
+
const { limit, sort = "priority", desc = false } = options;
|
|
4559
|
+
const key = createHash2("sha256").update(JSON.stringify([typed, sort, desc])).digest("base64url");
|
|
4560
|
+
const offset = offsetOf(options.cursor, key);
|
|
4561
|
+
const page = await store.tasks.board(query, { limit, offset, sort, descending: desc, zone: timezoneOf() });
|
|
4562
|
+
const items = [];
|
|
4563
|
+
for (const task of page.items)
|
|
4564
|
+
items.push(taskItem(task, { readiness: await store.tasks.taskReadiness(task.id) }));
|
|
4565
|
+
const next = offset + items.length;
|
|
4566
|
+
const more = next < page.total;
|
|
4567
|
+
return listAnswer("tasks list", {
|
|
4568
|
+
items,
|
|
4569
|
+
limit,
|
|
4570
|
+
has_more: more,
|
|
4571
|
+
paging: "cursor",
|
|
4572
|
+
...more ? {
|
|
4573
|
+
cursor: Buffer.from(JSON.stringify({ version: 1, key, offset: next })).toString("base64url")
|
|
4574
|
+
} : {},
|
|
4575
|
+
total: { value: page.total, relation: "eq" },
|
|
4576
|
+
args: { query: typed, ...options.sort ? { sort } : {}, ...desc ? { desc: true } : {} }
|
|
4601
4577
|
});
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
}
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
`cache ${d.cache}`,
|
|
4627
|
-
`store ${d.store.path}${!d.store.exists ? " (none yet; the first memo sync makes it)" : "schema" in d.store ? ` (schema ${d.store.schema}, memo speaks ${d.store.speaks})` : ""}`,
|
|
4628
|
-
..."health" in d.store && d.store.health ? [
|
|
4629
|
-
`health ${d.store.health.ok ? "ok" : "DAMAGED"}, checked ${d.store.health.covers}${d.store.health.checked === "quick" ? " (memo doctor --deep reads every page)" : ""}`
|
|
4630
|
-
] : [],
|
|
4631
|
-
...d.notes.map((f) => `notes ${f.path} \u2014 exists ${yes(f.exists)}, folder id ${yes(f.bound)}`),
|
|
4632
|
-
`search ${d.search_model.name} ${d.search_model.present ? "present" : "not downloaded \u2014 search is by words"}`,
|
|
4633
|
-
`timer ${d.timer.enabled ? `on, every ${d.timer.every}` : "off"}`,
|
|
4634
|
-
...d.skills.map((s) => `skill ${s.path} ${s.version === null ? "(not installed)" : `(${s.version})`}`),
|
|
4635
|
-
...online ? [onlineLine(online)] : [],
|
|
4636
|
-
"",
|
|
4637
|
-
...d.problems.length + d.config.issues.length + fileLines(d, fixes).length === 0 ? ["nothing needs attention"] : [
|
|
4638
|
-
...d.config.issues.map(({ what, fix }) => `! ${what}${fix ? ` \u2014 ${fix}` : ""}`),
|
|
4639
|
-
...fileLines(d, fixes),
|
|
4640
|
-
...d.problems.map(({ what, fix }) => `! ${what}${fix ? ` \u2014 ${fix}` : ""}`)
|
|
4641
|
-
]
|
|
4642
|
-
].join("\n"), "doctorText");
|
|
4643
|
-
var sharedDoctor = sharedCommandTemplate(APP, "doctor");
|
|
4644
|
-
var ONLINE_FLAGS = "--online";
|
|
4645
|
-
var onlineText = sharedDoctor.options.find((option) => option.long === ONLINE_FLAGS)?.description ?? "";
|
|
4646
|
-
var onlineCheck = /* @__PURE__ */ __name(async () => {
|
|
4647
|
-
const started = Date.now();
|
|
4648
|
-
const newest = await latest();
|
|
4649
|
-
return {
|
|
4650
|
-
ok: true,
|
|
4651
|
-
duration_ms: Date.now() - started,
|
|
4652
|
-
version: { current: VERSION, latest: newest ?? null, newer: newest !== void 0 && isNewer(newest, VERSION) }
|
|
4653
|
-
};
|
|
4654
|
-
}, "onlineCheck");
|
|
4655
|
-
var doctorCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
|
|
4656
|
-
const { print } = answers(program, streams, env);
|
|
4657
|
-
annotate(program.command("doctor"), { effects: REMOTE_READ }).description(sharedDoctor.description()).option(ONLINE_FLAGS, onlineText).option("--deep", DOCTOR_DEEP_OPTION).option("--json", "print JSON; --json=id,title keeps only those fields").addHelpText("after", "\nReads this computer only, unless --online: the config, the store, the notes folders, the search model, the timer and the agent skill, each problem with the command that fixes it. --online also asks npm whether a newer memo is published, and nothing else leaves this computer. Exits 1 when something other than the config file or a file mode needs attention; problems in the config file are listed in config.issues, and files or folders other users can read in files.problems, and neither changes the exit code.").action(async (options) => {
|
|
4658
|
-
const { fixes, ...diagnosis } = await diagnose(env, program, { deep: options.deep === true });
|
|
4659
|
-
const online = options.online ? await onlineCheck() : void 0;
|
|
4660
|
-
print(options.json, itemAnswer(online ? { ...diagnosis, online } : diagnosis), doctorText(diagnosis, fixes, online));
|
|
4661
|
-
if (options.json)
|
|
4662
|
-
for (const fix of fixes)
|
|
4663
|
-
streams.diagnostic(`to make it private: ${fix}`);
|
|
4664
|
-
if (diagnosis.problems.length > 0)
|
|
4665
|
-
process.exitCode = 1;
|
|
4578
|
+
}, "projectTasks");
|
|
4579
|
+
var listTasks = /* @__PURE__ */ __name(async (store, words, options, accounts) => {
|
|
4580
|
+
const flag = Array.isArray(words) ? words.findIndex((word) => /^--[a-z]+$/.test(word)) : -1;
|
|
4581
|
+
if (flag >= 0) {
|
|
4582
|
+
const field2 = words[flag]?.slice(2) ?? "";
|
|
4583
|
+
const value = words[flag + 1] ?? "<value>";
|
|
4584
|
+
const fields = TASKS_LIST_QUERY.fields.map(({ name: name2 }) => name2);
|
|
4585
|
+
throw new CliError("validation_error", fields.includes(field2) ? `tasks list takes ${field2} as a query word: memo tasks list ${field2}:${value}` : `tasks list has no --${field2}; its query words are ${fields.map((name2) => `${name2}:`).join(", ")}`);
|
|
4586
|
+
}
|
|
4587
|
+
const typed = typedQuery(words);
|
|
4588
|
+
const query = listQuery(typed, TASKS_LIST_QUERY, "tasks list", { defaultField: "text" });
|
|
4589
|
+
const leaves2 = query ? walkQuery(query.root) : [];
|
|
4590
|
+
if (leaves2.some(({ field: field2 }) => field2 === "project")) {
|
|
4591
|
+
if (leaves2.some(({ field: field2 }) => field2 === "source"))
|
|
4592
|
+
throw new CliError("validation_error", "source: narrows an account's tasks, not a project's");
|
|
4593
|
+
return projectTasks(store, typed, await resolveProjects(store, query), options);
|
|
4594
|
+
}
|
|
4595
|
+
if (options.cursor !== void 0 || options.sort !== void 0 || options.desc)
|
|
4596
|
+
throw new CliError("validation_error", "--cursor, --sort and --desc page and order project tasks: add project:");
|
|
4597
|
+
const { state, source } = accountTerms(query);
|
|
4598
|
+
return accountTasks(store, await accounts(), {
|
|
4599
|
+
state,
|
|
4600
|
+
limit: options.limit,
|
|
4601
|
+
...source === void 0 ? {} : { sources: [source] }
|
|
4666
4602
|
});
|
|
4667
|
-
}, "
|
|
4668
|
-
var
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
return command;
|
|
4675
|
-
}, SHELL_OVERRIDES.doctor);
|
|
4676
|
-
}, "doctorCommand");
|
|
4603
|
+
}, "listTasks");
|
|
4604
|
+
var countTasks = /* @__PURE__ */ __name(async (store, words) => {
|
|
4605
|
+
const query = listQuery(typedQuery(words), TASKS_LIST_QUERY, "tasks counts", { defaultField: "text" });
|
|
4606
|
+
if (query && walkQuery(query.root).some(({ field: field2 }) => field2 === "source"))
|
|
4607
|
+
throw new CliError("validation_error", "source: narrows an account's tasks; tasks counts counts project tasks");
|
|
4608
|
+
return store.tasks.boardCounts(await resolveProjects(store, query), { zone: timezoneOf() });
|
|
4609
|
+
}, "countTasks");
|
|
4677
4610
|
|
|
4678
|
-
//
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4611
|
+
// dist/digest/sync-health.js
|
|
4612
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
4613
|
+
import { join as join4 } from "node:path";
|
|
4614
|
+
|
|
4615
|
+
// dist/knowledge/messenger-sync.js
|
|
4616
|
+
import { spawn } from "node:child_process";
|
|
4617
|
+
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync4, realpathSync, statSync as statSync2 } from "node:fs";
|
|
4618
|
+
import { delimiter, join as join3 } from "node:path";
|
|
4619
|
+
var STATE = {
|
|
4620
|
+
tg: { appName: "tg-cli", envPrefix: "TG" },
|
|
4621
|
+
max: { appName: "max-cli", envPrefix: "MAX" },
|
|
4622
|
+
wa: { appName: "whatsapp-cli", envPrefix: "WA" }
|
|
4623
|
+
};
|
|
4624
|
+
var messengerToolOf = /* @__PURE__ */ __name((provider) => {
|
|
4625
|
+
const tool = providerNamed(provider)?.command;
|
|
4626
|
+
const state = tool === void 0 ? void 0 : STATE[tool];
|
|
4627
|
+
return tool === void 0 || state === void 0 ? void 0 : { tool, ...state };
|
|
4628
|
+
}, "messengerToolOf");
|
|
4629
|
+
var syncProfileOf = /* @__PURE__ */ __name((value, previous = {}) => {
|
|
4630
|
+
const [tool, profile] = value.split("=", 2);
|
|
4631
|
+
const tools = Object.keys(STATE);
|
|
4632
|
+
if (!tool || !profile || !tools.includes(tool))
|
|
4633
|
+
throw new InvalidArgumentError(`<tool>=<profile>, where the tool is ${tools.join(", ")}: max=default`);
|
|
4634
|
+
if (previous[tool] !== void 0 && previous[tool] !== profile)
|
|
4635
|
+
throw new InvalidArgumentError(`one profile per tool; ${tool} is already ${previous[tool]}`);
|
|
4636
|
+
return { ...previous, [tool]: profile };
|
|
4637
|
+
}, "syncProfileOf");
|
|
4638
|
+
var accountsDir = /* @__PURE__ */ __name((tool, env) => join3(resolvePaths({ appName: tool.appName, prefix: tool.envPrefix, env }).state, "accounts"), "accountsDir");
|
|
4639
|
+
var signedInAccount = /* @__PURE__ */ __name((tool, profile, env) => {
|
|
4707
4640
|
try {
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4641
|
+
return JSON.parse(readFileSync4(join3(accountsDir(tool, env), `${profile}.json`), "utf8"))?.account;
|
|
4642
|
+
} catch {
|
|
4643
|
+
return void 0;
|
|
4644
|
+
}
|
|
4645
|
+
}, "signedInAccount");
|
|
4646
|
+
var profileFor = /* @__PURE__ */ __name((provider, account2, env, chosen = {}) => {
|
|
4647
|
+
const tool = messengerToolOf(provider);
|
|
4648
|
+
if (!tool)
|
|
4649
|
+
return void 0;
|
|
4650
|
+
const dir = accountsDir(tool, env);
|
|
4651
|
+
const profiles = existsSync3(dir) ? readdirSync(dir).filter((name2) => name2.endsWith(".json")).map((name2) => name2.slice(0, -".json".length)).sort() : [];
|
|
4652
|
+
const accountOf = /* @__PURE__ */ __name((profile) => signedInAccount(tool, profile, env), "accountOf");
|
|
4653
|
+
const all = profiles.join(", ") || "none";
|
|
4654
|
+
const pick = chosen[tool.tool];
|
|
4655
|
+
if (pick !== void 0) {
|
|
4656
|
+
if (!profiles.includes(pick))
|
|
4657
|
+
return { why: `${tool.tool} profile ${pick} is not signed in here; profiles: ${all}`, profiles };
|
|
4658
|
+
const held = accountOf(pick);
|
|
4659
|
+
return held === account2 ? { profile: pick } : { why: `${tool.tool} profile ${pick} is signed in to account ${String(held)}, not ${account2}`, profiles: [] };
|
|
4660
|
+
}
|
|
4661
|
+
const matching = profiles.filter((profile) => accountOf(profile) === account2);
|
|
4662
|
+
if (matching.length === 1 && matching[0])
|
|
4663
|
+
return { profile: matching[0] };
|
|
4664
|
+
if (matching.length > 1)
|
|
4717
4665
|
return {
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
window,
|
|
4721
|
-
fullAt,
|
|
4722
|
-
updatedAt: cursor.updatedAt ?? null,
|
|
4723
|
-
done: cursor.done,
|
|
4724
|
-
round,
|
|
4725
|
-
...cursor.restored === true ? { restored: true } : {},
|
|
4726
|
-
...typeof cursor.slotsTo === "number" ? { slotsTo: cursor.slotsTo } : {}
|
|
4666
|
+
why: `${matching.length} ${tool.tool} profiles are signed in to account ${account2}: ${matching.join(", ")} \u2014 choose one with --sync-profile ${tool.tool}=<profile>`,
|
|
4667
|
+
profiles: matching
|
|
4727
4668
|
};
|
|
4669
|
+
return { why: `no ${tool.tool} profile here is signed in to account ${account2}; profiles: ${all}`, profiles: [] };
|
|
4670
|
+
}, "profileFor");
|
|
4671
|
+
var onPath = /* @__PURE__ */ __name((name2, env) => (env.PATH ?? "").split(delimiter).filter(Boolean).map((dir) => join3(dir, name2)).find((path) => {
|
|
4672
|
+
try {
|
|
4673
|
+
return statSync2(path).isFile();
|
|
4728
4674
|
} catch {
|
|
4729
|
-
return
|
|
4675
|
+
return false;
|
|
4730
4676
|
}
|
|
4731
|
-
}, "
|
|
4732
|
-
var
|
|
4733
|
-
const
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
var oneSided = /* @__PURE__ */ __name((field2, example) => (node) => {
|
|
4773
|
-
if (node.operator !== "range" || node.upper !== "*")
|
|
4774
|
-
queryError("query.unsupported-operator", node.span, `${field2} takes only an earliest moment, such as ${example}`, {
|
|
4775
|
-
command: LIST,
|
|
4776
|
-
guide: LIST_QUERY_GUIDE
|
|
4777
|
-
});
|
|
4778
|
-
}, "oneSided");
|
|
4779
|
-
var EVENTS_QUERY = {
|
|
4780
|
-
entity: "event",
|
|
4781
|
-
backend: "native",
|
|
4782
|
-
fields: queryFieldsOf(event, {
|
|
4783
|
-
native: ["id", "starts_at", "ends_at", "changed_at", "overlapping", "calendar", "person", "event_type"],
|
|
4784
|
-
negatable: ["event_type"],
|
|
4785
|
-
relations: {
|
|
4786
|
-
event_type: {
|
|
4787
|
-
type: "enum",
|
|
4788
|
-
values: EVENT_TYPES,
|
|
4789
|
-
example: "event_type:default",
|
|
4790
|
-
relation: "events with a copy of this kind; -event_type:<kind> leaves out events with one"
|
|
4791
|
-
},
|
|
4792
|
-
calendar: {
|
|
4793
|
-
type: "kw",
|
|
4794
|
-
example: "calendar:3",
|
|
4795
|
-
relation: "one calendar, by its id, the provider's id or its title"
|
|
4796
|
-
},
|
|
4797
|
-
person: {
|
|
4798
|
-
type: "kw",
|
|
4799
|
-
example: "person:ana@example.com",
|
|
4800
|
-
relation: "events one person attends: an address, or a person id from search"
|
|
4801
|
-
}
|
|
4802
|
-
},
|
|
4803
|
-
examples: {
|
|
4804
|
-
id: "id:42",
|
|
4805
|
-
starts_at: "starts_at:[2026-11-02 TO 2026-11-07}",
|
|
4806
|
-
ends_at: "ends_at>=2026-11-02",
|
|
4807
|
-
changed_at: "changed_at>=2026-10-01",
|
|
4808
|
-
overlapping: "overlapping:true"
|
|
4809
|
-
},
|
|
4810
|
-
validate: {
|
|
4811
|
-
ends_at: oneSided("ends_at", "ends_at>=2026-11-02; for the latest, write starts_at<2026-11-07"),
|
|
4812
|
-
changed_at: oneSided("changed_at", "changed_at>=2026-10-01")
|
|
4677
|
+
}), "onPath");
|
|
4678
|
+
var runChild = /* @__PURE__ */ __name((command, args, { env, signal, onStderr }) => new Promise((resolve6, reject) => {
|
|
4679
|
+
const child = spawn(command, args, { env, stdio: ["ignore", "pipe", "pipe"] });
|
|
4680
|
+
let stdout = "";
|
|
4681
|
+
let pending2 = "";
|
|
4682
|
+
child.stdout.setEncoding("utf8").on("data", (chunk) => {
|
|
4683
|
+
stdout += chunk;
|
|
4684
|
+
});
|
|
4685
|
+
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
|
4686
|
+
const lines2 = (pending2 + chunk).split("\n");
|
|
4687
|
+
pending2 = lines2.pop() ?? "";
|
|
4688
|
+
for (const line3 of lines2)
|
|
4689
|
+
if (line3)
|
|
4690
|
+
onStderr?.(line3);
|
|
4691
|
+
});
|
|
4692
|
+
let hard;
|
|
4693
|
+
const stop = /* @__PURE__ */ __name(() => {
|
|
4694
|
+
child.kill("SIGINT");
|
|
4695
|
+
hard = setTimeout(() => child.kill("SIGTERM"), 1e4);
|
|
4696
|
+
}, "stop");
|
|
4697
|
+
signal?.addEventListener("abort", stop, { once: true });
|
|
4698
|
+
child.on("error", reject);
|
|
4699
|
+
child.on("close", (code) => {
|
|
4700
|
+
clearTimeout(hard);
|
|
4701
|
+
signal?.removeEventListener("abort", stop);
|
|
4702
|
+
if (pending2)
|
|
4703
|
+
onStderr?.(pending2);
|
|
4704
|
+
resolve6({ code, stdout });
|
|
4705
|
+
});
|
|
4706
|
+
}), "runChild");
|
|
4707
|
+
var binaryOf = /* @__PURE__ */ __name(async (provider, env, run) => {
|
|
4708
|
+
const tool = messengerToolOf(provider);
|
|
4709
|
+
if (!tool)
|
|
4710
|
+
return void 0;
|
|
4711
|
+
const umbrella = onPath(`wcat-${tool.tool}`, env);
|
|
4712
|
+
if (umbrella) {
|
|
4713
|
+
const described = await run(umbrella, ["--wcat-describe"], { env }).catch(() => void 0);
|
|
4714
|
+
try {
|
|
4715
|
+
if (described?.code === 0 && JSON.parse(described.stdout)?.name === tool.tool)
|
|
4716
|
+
return umbrella;
|
|
4717
|
+
} catch {
|
|
4813
4718
|
}
|
|
4814
|
-
}).map((field2) => field2.native ? {
|
|
4815
|
-
...field2,
|
|
4816
|
-
operators: field2.type === "time" ? ["term", "range"] : field2.type === "bool" ? ["term"] : ["term", "phrase"]
|
|
4817
|
-
} : field2)
|
|
4818
|
-
};
|
|
4819
|
-
var nameOf2 = /* @__PURE__ */ __name(({ provider, account: account2 }) => `${provider}:${account2}`, "nameOf");
|
|
4820
|
-
var accountsMeta = /* @__PURE__ */ __name(async (store, accounts, skipped, now) => {
|
|
4821
|
-
const issues = [...skipped];
|
|
4822
|
-
for (const { id, key } of accounts) {
|
|
4823
|
-
if (isImportedProvider(key.provider))
|
|
4824
|
-
continue;
|
|
4825
|
-
const { items } = await calendarStatus(store, id, { profile: nameOf2(key), now });
|
|
4826
|
-
if (items.length === 0)
|
|
4827
|
-
issues.push({ code: "not_found", reason: "calendar.unsynced", source: nameOf2(key) });
|
|
4828
|
-
else if (items.some(({ state }) => state !== "complete"))
|
|
4829
|
-
issues.push({ code: "not_found", reason: "calendar.sync-incomplete", source: nameOf2(key) });
|
|
4830
4719
|
}
|
|
4720
|
+
const short = onPath(tool.tool, env);
|
|
4721
|
+
if (!short)
|
|
4722
|
+
return void 0;
|
|
4723
|
+
const mark = `@wirecat/${tool.appName}`;
|
|
4724
|
+
const real = realpathSync(short);
|
|
4725
|
+
if (real.includes(`/${mark}/`))
|
|
4726
|
+
return short;
|
|
4727
|
+
return statSync2(real).size < 65536 && readFileSync4(real, "utf8").includes(mark) ? short : void 0;
|
|
4728
|
+
}, "binaryOf");
|
|
4729
|
+
var answerOf = /* @__PURE__ */ __name((stdout) => {
|
|
4730
|
+
try {
|
|
4731
|
+
return JSON.parse(stdout.trim().split("\n").at(-1) ?? "");
|
|
4732
|
+
} catch {
|
|
4733
|
+
return {};
|
|
4734
|
+
}
|
|
4735
|
+
}, "answerOf");
|
|
4736
|
+
var MARGIN_MS = 5e3;
|
|
4737
|
+
var messengerFetcher = /* @__PURE__ */ __name(({ env, note, chosen = {}, run = runChild, now = Date.now }) => {
|
|
4738
|
+
const binaries = /* @__PURE__ */ new Map();
|
|
4831
4739
|
return {
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4740
|
+
fetch: /* @__PURE__ */ __name(async ({ account: account2, chatId, after, until, signal }) => {
|
|
4741
|
+
const tool = messengerToolOf(account2.provider);
|
|
4742
|
+
if (!tool)
|
|
4743
|
+
return { state: "failed", reason: `no WireCat messenger CLI syncs ${account2.provider}` };
|
|
4744
|
+
const found = profileFor(account2.provider, account2.account, env, chosen);
|
|
4745
|
+
if (!found || !("profile" in found))
|
|
4746
|
+
return { state: "failed", reason: found?.why ?? "no profile" };
|
|
4747
|
+
if (!binaries.has(tool.tool))
|
|
4748
|
+
binaries.set(tool.tool, binaryOf(account2.provider, env, run));
|
|
4749
|
+
const bin = await binaries.get(tool.tool);
|
|
4750
|
+
if (!bin)
|
|
4751
|
+
return { state: "failed", reason: `${tool.tool} is not installed, or the one on PATH is not WireCat's` };
|
|
4752
|
+
const seconds = Math.max(1, Math.floor((until - now() - MARGIN_MS) / 1e3));
|
|
4753
|
+
const args = [
|
|
4754
|
+
found.profile,
|
|
4755
|
+
"messages",
|
|
4756
|
+
"sync",
|
|
4757
|
+
"--since-time",
|
|
4758
|
+
new Date(after).toISOString(),
|
|
4759
|
+
"--limit",
|
|
4760
|
+
"1000000",
|
|
4761
|
+
"--timeout",
|
|
4762
|
+
`${seconds}s`,
|
|
4763
|
+
"--json",
|
|
4764
|
+
chatId
|
|
4765
|
+
];
|
|
4766
|
+
const done = await run(bin, args, {
|
|
4767
|
+
env,
|
|
4768
|
+
signal,
|
|
4769
|
+
onStderr: /* @__PURE__ */ __name((line3) => {
|
|
4770
|
+
if (!isEvent(line3))
|
|
4771
|
+
note(`${tool.tool}: ${line3}`);
|
|
4772
|
+
}, "onStderr")
|
|
4773
|
+
});
|
|
4774
|
+
const answer = answerOf(done.stdout);
|
|
4775
|
+
if (done.code !== 0) {
|
|
4776
|
+
const why = answer.error?.message?.split("\n")[0];
|
|
4777
|
+
const code = answer.error?.code ?? `exit ${done.code ?? "signal"}`;
|
|
4778
|
+
return {
|
|
4779
|
+
state: "partial",
|
|
4780
|
+
reason: `${tool.tool} ${found.profile} messages sync: ${code}${why ? ` \u2014 ${why}` : ""}`
|
|
4781
|
+
};
|
|
4782
|
+
}
|
|
4783
|
+
const item = answer.item ?? {};
|
|
4784
|
+
if (item.issue?.code)
|
|
4785
|
+
return { state: "partial", reason: item.issue.code };
|
|
4786
|
+
if (item.stopped || signal.aborted)
|
|
4787
|
+
return { state: "partial", reason: "fetch-budget" };
|
|
4788
|
+
return item.complete || item.reached_since ? { state: "complete" } : { state: "partial", reason: "limit" };
|
|
4789
|
+
}, "fetch")
|
|
4835
4790
|
};
|
|
4836
|
-
}, "
|
|
4791
|
+
}, "messengerFetcher");
|
|
4792
|
+
var isEvent = /* @__PURE__ */ __name((line3) => {
|
|
4793
|
+
if (!line3.startsWith("{"))
|
|
4794
|
+
return false;
|
|
4795
|
+
try {
|
|
4796
|
+
return typeof JSON.parse(line3)?.event === "string";
|
|
4797
|
+
} catch {
|
|
4798
|
+
return false;
|
|
4799
|
+
}
|
|
4800
|
+
}, "isEvent");
|
|
4801
|
+
var chatCommand = /* @__PURE__ */ __name((chat, words, env, chosen) => {
|
|
4802
|
+
const tool = messengerToolOf(chat.provider);
|
|
4803
|
+
if (!tool)
|
|
4804
|
+
return null;
|
|
4805
|
+
const found = profileFor(chat.provider, chat.account, env, chosen);
|
|
4806
|
+
const line3 = /* @__PURE__ */ __name((profile) => `${tool.tool} ${profile} ${words}`, "line");
|
|
4807
|
+
if (found && "profile" in found)
|
|
4808
|
+
return { command: line3(found.profile) };
|
|
4809
|
+
return { command: null, line: line3("<profile>"), why: found?.why ?? "no profile" };
|
|
4810
|
+
}, "chatCommand");
|
|
4811
|
+
var chatSync = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => (
|
|
4812
|
+
// A negative group id needs no `--`: no WireCat CLI has a digit short option.
|
|
4813
|
+
chatCommand(chat, `messages sync ${chat.chat} --since-time ${since}`, env, chosen)
|
|
4814
|
+
), "chatSync");
|
|
4815
|
+
var chatRead = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => chatCommand(chat, `messages list --compact ${chat.chat} "date>=${since}"`, env, chosen), "chatRead");
|
|
4816
|
+
var syncHint = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => {
|
|
4817
|
+
const sync = chatSync(chat, since, env, chosen);
|
|
4818
|
+
if (!sync)
|
|
4819
|
+
return null;
|
|
4820
|
+
return sync.command ?? `${sync.line} (${sync.why})`;
|
|
4821
|
+
}, "syncHint");
|
|
4837
4822
|
|
|
4838
|
-
//
|
|
4839
|
-
var
|
|
4840
|
-
var
|
|
4841
|
-
var
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
"events.update": "allow",
|
|
4847
|
-
"events.respond": "allow",
|
|
4848
|
-
"events.move": "allow",
|
|
4849
|
-
"events.delete": "ask",
|
|
4850
|
-
[EVENTS_DELETE_SERIES_KEY]: "deny",
|
|
4851
|
-
[EVENTS_NOTIFY_KEY]: "deny",
|
|
4852
|
-
// Not ask: `--yes` answers ask, and anything that can type a gcal command can add it.
|
|
4853
|
-
[EVENTS_REMIND_HOOK_KEY]: "deny"
|
|
4823
|
+
// dist/digest/sync-health.js
|
|
4824
|
+
var HEALTH_REASONS = ["sync-failed", "no-schedule", "quiet"];
|
|
4825
|
+
var MAIL2 = { appName: "mail-cli", envPrefix: "MAIL" };
|
|
4826
|
+
var SOURCE_WORDS = {
|
|
4827
|
+
telegram: "Telegram",
|
|
4828
|
+
max: "MAX",
|
|
4829
|
+
whatsapp: "WhatsApp",
|
|
4830
|
+
email: "mail"
|
|
4854
4831
|
};
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
var
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
}
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
const stored = await store.accounts.storedAccounts();
|
|
4895
|
-
const read = [];
|
|
4896
|
-
for (const key of held) {
|
|
4897
|
-
const one2 = stored.find(({ provider, account: account2 }) => provider === key.provider && account2 === key.account);
|
|
4898
|
-
if (one2)
|
|
4899
|
-
read.push({ id: one2.id, key, calendars: await store.calendar.calendars(one2.id) });
|
|
4832
|
+
var toolOf = /* @__PURE__ */ __name((provider) => provider === "email" ? MAIL2 : messengerToolOf(provider), "toolOf");
|
|
4833
|
+
var stateDirs = /* @__PURE__ */ __name((tool, env) => resolvePaths({ appName: tool.appName, prefix: tool.envPrefix, env }), "stateDirs");
|
|
4834
|
+
var schedulesOf = /* @__PURE__ */ __name((state) => {
|
|
4835
|
+
const dir = join4(state, "schedules");
|
|
4836
|
+
if (!existsSync4(dir))
|
|
4837
|
+
return [];
|
|
4838
|
+
const last = new Map(scheduledRuns(state).map((one2) => [one2.job, one2.last]));
|
|
4839
|
+
return readdirSync2(dir).flatMap((name2) => {
|
|
4840
|
+
try {
|
|
4841
|
+
const schedule = JSON.parse(readFileSync5(join4(dir, name2, "schedule.json"), "utf8"));
|
|
4842
|
+
return [
|
|
4843
|
+
{
|
|
4844
|
+
name: String(schedule.name),
|
|
4845
|
+
kind: String(schedule.kind),
|
|
4846
|
+
argv: Array.isArray(schedule.argv) ? schedule.argv.map(String) : [],
|
|
4847
|
+
environment: schedule.environment ?? {},
|
|
4848
|
+
last: last.get(String(schedule.name))
|
|
4849
|
+
}
|
|
4850
|
+
];
|
|
4851
|
+
} catch {
|
|
4852
|
+
return [];
|
|
4853
|
+
}
|
|
4854
|
+
});
|
|
4855
|
+
}, "schedulesOf");
|
|
4856
|
+
var signedIn = /* @__PURE__ */ __name((dir) => existsSync4(dir) ? readdirSync2(dir).filter((name2) => name2.endsWith(".json")).map((name2) => name2.slice(0, -".json".length)) : [], "signedIn");
|
|
4857
|
+
var profilesOf = /* @__PURE__ */ __name((provider, tool, env) => {
|
|
4858
|
+
if (provider !== "email")
|
|
4859
|
+
return new Map(signedIn(join4(stateDirs(tool, env).state, "accounts")).map((profile) => [
|
|
4860
|
+
profile,
|
|
4861
|
+
signedInAccount(tool, profile, env)
|
|
4862
|
+
]));
|
|
4863
|
+
try {
|
|
4864
|
+
const config = JSON.parse(readFileSync5(configFilePath(stateDirs(MAIL2, env).config), "utf8"));
|
|
4865
|
+
return new Map(Object.entries(config?.profiles ?? {}).map(([profile, one2]) => [
|
|
4866
|
+
profile,
|
|
4867
|
+
one2?.address
|
|
4868
|
+
]));
|
|
4869
|
+
} catch {
|
|
4870
|
+
return /* @__PURE__ */ new Map();
|
|
4900
4871
|
}
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4872
|
+
}, "profilesOf");
|
|
4873
|
+
var profileRun = /* @__PURE__ */ __name((schedule, tool, profiles) => {
|
|
4874
|
+
const first = schedule.argv[0];
|
|
4875
|
+
return first !== void 0 && profiles.has(first) ? first : schedule.environment[`${tool.envPrefix}_PROFILE`] ?? "default";
|
|
4876
|
+
}, "profileRun");
|
|
4877
|
+
var syncRunsOf = /* @__PURE__ */ __name((env) => {
|
|
4878
|
+
const cache = /* @__PURE__ */ new Map();
|
|
4879
|
+
const read = /* @__PURE__ */ __name((provider, tool) => {
|
|
4880
|
+
const known2 = cache.get(tool.appName);
|
|
4881
|
+
if (known2)
|
|
4882
|
+
return known2;
|
|
4883
|
+
const app = { ...APP, appName: tool.appName, envPrefix: tool.envPrefix };
|
|
4884
|
+
const fresh = {
|
|
4885
|
+
schedules: schedulesOf(stateDirs(tool, env).state).filter((one2) => one2.kind === "command" && one2.argv.includes("sync")),
|
|
4886
|
+
serving: servingProfiles(app, env),
|
|
4887
|
+
profiles: profilesOf(provider, tool, env)
|
|
4888
|
+
};
|
|
4889
|
+
cache.set(tool.appName, fresh);
|
|
4890
|
+
return fresh;
|
|
4891
|
+
}, "read");
|
|
4892
|
+
return (key) => {
|
|
4893
|
+
const tool = toolOf(key.provider);
|
|
4894
|
+
if (!tool)
|
|
4895
|
+
return { runs: [], scheduled: false, serving: false, known: false };
|
|
4896
|
+
const { schedules, serving, profiles } = read(key.provider, tool);
|
|
4897
|
+
const mine = new Set([...profiles].filter(([, account2]) => account2 === key.account).map(([profile]) => profile));
|
|
4898
|
+
const runs = schedules.filter((one2) => mine.has(profileRun(one2, tool, profiles)));
|
|
4899
|
+
return {
|
|
4900
|
+
runs: runs.flatMap((one2) => one2.last ? [one2.last] : []),
|
|
4901
|
+
scheduled: runs.length > 0,
|
|
4902
|
+
serving: serving.some((profile) => mine.has(profile)),
|
|
4903
|
+
known: mine.size > 0
|
|
4904
|
+
};
|
|
4930
4905
|
};
|
|
4931
|
-
}, "
|
|
4932
|
-
var
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4906
|
+
}, "syncRunsOf");
|
|
4907
|
+
var HOUR = 36e5;
|
|
4908
|
+
var DAY3 = 24 * HOUR;
|
|
4909
|
+
var QUIET_AFTER = 3 * DAY3;
|
|
4910
|
+
var QUIET_GAPS = 3;
|
|
4911
|
+
var hours = /* @__PURE__ */ __name((from, now) => Math.max(0, Math.floor((now - from) / HOUR)), "hours");
|
|
4912
|
+
var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
|
|
4913
|
+
const recent = /* @__PURE__ */ __name((at) => at !== null && at >= now - DAY3, "recent");
|
|
4914
|
+
if (recent(activity.storedAt) || sync.runs.some((run) => run.exitCode === 0 && recent(Date.parse(run.at))))
|
|
4915
|
+
return void 0;
|
|
4916
|
+
if (!sync.serving && sync.runs.length > 0 && sync.runs.every((run) => run.exitCode !== 0)) {
|
|
4917
|
+
const first = [...sync.runs].sort((a, b) => (a.failingSince ?? a.at).localeCompare(b.failingSince ?? b.at))[0];
|
|
4918
|
+
const since = first?.failingSince ?? first?.at ?? new Date(now).toISOString();
|
|
4919
|
+
return {
|
|
4920
|
+
reason: "sync-failed",
|
|
4921
|
+
since,
|
|
4922
|
+
staleHours: hours(Date.parse(since), now),
|
|
4923
|
+
...first?.reason ? { failure: first.reason } : {}
|
|
4924
|
+
};
|
|
4940
4925
|
}
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
timezone: zone,
|
|
4947
|
-
window: {
|
|
4948
|
-
...since === void 0 ? {} : { since: new Date(since).toISOString() },
|
|
4949
|
-
...filter.to === void 0 ? {} : { until: new Date(filter.to - 1).toISOString() }
|
|
4950
|
-
}
|
|
4951
|
-
};
|
|
4952
|
-
}, "windowMeta");
|
|
4953
|
-
var rowOf = /* @__PURE__ */ __name((details, accounts) => {
|
|
4954
|
-
const live = details.entries.filter(({ deletedAt }) => deletedAt === null);
|
|
4955
|
-
const copies = live.length ? live : details.entries;
|
|
4956
|
-
const held = accounts.flatMap((account2) => account2.calendars.filter(({ id }) => copies.some(({ calendarId }) => calendarId === id)).map((calendar) => ({ account: accountName(account2.key), calendar: calendar.title ?? String(calendar.id) })));
|
|
4957
|
-
return {
|
|
4958
|
-
...eventItem(details.event),
|
|
4959
|
-
ref: `event:${details.event.id}`,
|
|
4960
|
-
event_type: copies.find(({ eventType }) => eventType !== null)?.eventType ?? "default",
|
|
4961
|
-
accounts: [...new Set(held.map(({ account: account2 }) => account2))],
|
|
4962
|
-
in: held.map(({ account: account2, calendar }) => `${account2}/${calendar}`).join(", "),
|
|
4963
|
-
untrusted: UNTRUSTED
|
|
4964
|
-
};
|
|
4965
|
-
}, "rowOf");
|
|
4966
|
-
var listEvents = /* @__PURE__ */ __name(async (store, words, limit, { now = Date.now(), zone = timezoneOf() } = {}) => {
|
|
4967
|
-
const terms2 = nativeTerms(listQuery(typedQuery(words), EVENTS_QUERY2, LIST2), LIST2);
|
|
4968
|
-
const every = await readAccounts(store);
|
|
4969
|
-
const account2 = terms2.get("account");
|
|
4970
|
-
let accounts = account2 ? narrowed(every, account2.value) : every;
|
|
4971
|
-
const filter = { newest: true };
|
|
4972
|
-
const calendar = terms2.get("calendar");
|
|
4973
|
-
if (calendar) {
|
|
4974
|
-
const found = calendarOf(accounts, calendar.value);
|
|
4975
|
-
accounts = [found.account];
|
|
4976
|
-
filter.calendarId = found.calendar.id;
|
|
4926
|
+
if (!sync.scheduled && !sync.serving) {
|
|
4927
|
+
if (!sync.known)
|
|
4928
|
+
return void 0;
|
|
4929
|
+
const last = activity.newest ?? activity.storedAt;
|
|
4930
|
+
return { reason: "no-schedule", since: null, staleHours: last === null ? 0 : hours(last, now) };
|
|
4977
4931
|
}
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4932
|
+
if (activity.newest === null || activity.moved30d === 0)
|
|
4933
|
+
return void 0;
|
|
4934
|
+
const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 * DAY3 / activity.moved30d);
|
|
4935
|
+
if (activity.newest < now - usual)
|
|
4936
|
+
return { reason: "quiet", since: new Date(activity.newest).toISOString(), staleHours: hours(activity.newest, now) };
|
|
4937
|
+
return void 0;
|
|
4938
|
+
}, "healthOf");
|
|
4939
|
+
|
|
4940
|
+
// dist/digest/tasks.js
|
|
4941
|
+
var DIGEST_SCHEDULE = "morning-digest";
|
|
4942
|
+
var DAY4 = 864e5;
|
|
4943
|
+
var digestSchedule = /* @__PURE__ */ __name((env) => {
|
|
4944
|
+
const state = resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env }).state;
|
|
4945
|
+
const schedule = schedulesOf(state).find((one2) => one2.name === DIGEST_SCHEDULE || one2.kind === "agent" && one2.argv.join(" ").includes(DIGEST_SCHEDULE));
|
|
4946
|
+
return { state, schedule };
|
|
4947
|
+
}, "digestSchedule");
|
|
4948
|
+
var runTime = /* @__PURE__ */ __name((file) => {
|
|
4949
|
+
const [, day2, hour, minute3, second] = /^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})Z\./.exec(file) ?? [];
|
|
4950
|
+
return day2 ? Date.parse(`${day2}T${hour}:${minute3}:${second}Z`) : Number.NaN;
|
|
4951
|
+
}, "runTime");
|
|
4952
|
+
var digestReportTimes = /* @__PURE__ */ __name((env) => {
|
|
4953
|
+
const { state, schedule } = digestSchedule(env);
|
|
4954
|
+
const runs = schedule ? join5(state, "schedules", schedule.name, "runs") : void 0;
|
|
4955
|
+
if (!runs || !existsSync5(runs))
|
|
4956
|
+
return [];
|
|
4957
|
+
return readdirSync3(runs).filter((file) => file.endsWith(".report.json")).map(runTime).filter((at) => !Number.isNaN(at)).sort((a, b) => a - b);
|
|
4958
|
+
}, "digestReportTimes");
|
|
4959
|
+
var digestRunBefore = /* @__PURE__ */ __name((env, until) => new Date(digestReportTimes(env).findLast((at) => at < until) ?? until - DAY4).toISOString(), "digestRunBefore");
|
|
4960
|
+
var previousDigestAt = /* @__PURE__ */ __name((env, now) => {
|
|
4961
|
+
const last = digestSchedule(env).schedule?.last;
|
|
4962
|
+
if (!last)
|
|
4963
|
+
return new Date(now - DAY4).toISOString();
|
|
4964
|
+
return last.exitCode === 0 ? last.at : last.failingSince ?? last.at;
|
|
4965
|
+
}, "previousDigestAt");
|
|
4966
|
+
var dayOf = /* @__PURE__ */ __name((zone) => {
|
|
4967
|
+
const format = new Intl.DateTimeFormat("en-CA", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" });
|
|
4968
|
+
return (ms) => format.format(ms);
|
|
4969
|
+
}, "dayOf");
|
|
4970
|
+
var PAGE3 = 500;
|
|
4971
|
+
var openAccountTasks = /* @__PURE__ */ __name(async (store, key) => {
|
|
4972
|
+
const ids = [];
|
|
4973
|
+
for (let offset = 0; ; offset += PAGE3) {
|
|
4974
|
+
const page = await store.knowledge.taskIds(key, { state: "open", limit: PAGE3, offset });
|
|
4975
|
+
for (const id of page.items)
|
|
4976
|
+
ids.push(id);
|
|
4977
|
+
if (!page.hasMore)
|
|
4978
|
+
break;
|
|
4992
4979
|
}
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
const
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
4980
|
+
return Promise.all(ids.map((id) => store.tasks.details(id)));
|
|
4981
|
+
}, "openAccountTasks");
|
|
4982
|
+
var openProjectTasks = /* @__PURE__ */ __name(async (store, zone) => {
|
|
4983
|
+
const query = listQuery(typedQuery("project:* state:(open OR todo OR in_progress)"), TASKS_LIST_QUERY, "review agenda", {
|
|
4984
|
+
defaultField: "text"
|
|
4985
|
+
});
|
|
4986
|
+
const items = [];
|
|
4987
|
+
for (let offset = 0; ; offset += PAGE3) {
|
|
4988
|
+
const page = await store.tasks.board(query, { limit: PAGE3, offset, sort: "priority", descending: false, zone });
|
|
4989
|
+
for (const task of page.items)
|
|
4990
|
+
items.push(task);
|
|
4991
|
+
if (page.items.length < PAGE3 || items.length >= page.total)
|
|
4992
|
+
break;
|
|
5001
4993
|
}
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
const
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
const
|
|
5015
|
-
const
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
4994
|
+
return items;
|
|
4995
|
+
}, "openProjectTasks");
|
|
4996
|
+
var personName = /* @__PURE__ */ __name(async (store, ref) => {
|
|
4997
|
+
if (!ref?.startsWith("person:"))
|
|
4998
|
+
return null;
|
|
4999
|
+
return (await store.people.personByUid(ref.slice("person:".length)))?.name ?? null;
|
|
5000
|
+
}, "personName");
|
|
5001
|
+
var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince, until }) => {
|
|
5002
|
+
const zone = timezoneOf();
|
|
5003
|
+
const day2 = dayOf(zone);
|
|
5004
|
+
const today2 = day2(now);
|
|
5005
|
+
const tomorrow = day2(now + DAY4);
|
|
5006
|
+
const since = Date.parse(newSince);
|
|
5007
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5008
|
+
let accounts = 0;
|
|
5009
|
+
for (const key of keys) {
|
|
5010
|
+
const held = await openAccountTasks(store, key);
|
|
5011
|
+
if (held.length)
|
|
5012
|
+
accounts++;
|
|
5013
|
+
for (const task of held)
|
|
5014
|
+
seen.set(task.id, task);
|
|
5015
|
+
}
|
|
5016
|
+
const projects = await openProjectTasks(store, zone);
|
|
5017
|
+
if (projects.length)
|
|
5018
|
+
accounts++;
|
|
5019
|
+
for (const task of projects)
|
|
5020
|
+
seen.set(task.id, task);
|
|
5021
|
+
const counts = { overdue: 0, today: 0, tomorrow: 0, new: 0, newSince, undated: 0 };
|
|
5022
|
+
const tasks = [];
|
|
5023
|
+
for (const task of seen.values()) {
|
|
5024
|
+
if (until !== void 0 && Date.parse(task.createdAt) > until)
|
|
5025
|
+
continue;
|
|
5026
|
+
const groups = [];
|
|
5027
|
+
const due = task.dueAt === null ? null : day2(Date.parse(task.dueAt));
|
|
5028
|
+
if (due === null)
|
|
5029
|
+
counts.undated++;
|
|
5030
|
+
if (due !== null && due < today2)
|
|
5031
|
+
groups.push("overdue");
|
|
5032
|
+
if (due === today2)
|
|
5033
|
+
groups.push("today");
|
|
5034
|
+
if (due === tomorrow)
|
|
5035
|
+
groups.push("tomorrow");
|
|
5036
|
+
if (Date.parse(task.createdAt) >= since)
|
|
5037
|
+
groups.push("new");
|
|
5038
|
+
if (groups.length === 0)
|
|
5039
|
+
continue;
|
|
5040
|
+
for (const group of groups)
|
|
5041
|
+
counts[group]++;
|
|
5042
|
+
const assignees = await Promise.all(task.assignments.filter((one2) => one2.role === "assignee").map((one2) => personName(store, one2.to)));
|
|
5043
|
+
tasks.push({
|
|
5044
|
+
task,
|
|
5045
|
+
groups,
|
|
5046
|
+
askedBy: await personName(store, await store.tasks.sourceSender(task.id)),
|
|
5047
|
+
for: assignees.filter(Boolean).join(", ") || null
|
|
5048
|
+
});
|
|
5049
|
+
}
|
|
5050
|
+
return { tasks, counts, accounts };
|
|
5051
|
+
}, "gatherTasks");
|
|
5031
5052
|
|
|
5032
|
-
// dist/
|
|
5033
|
-
var
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
return
|
|
5038
|
-
}, "
|
|
5039
|
-
var
|
|
5053
|
+
// dist/digest/backfill.js
|
|
5054
|
+
var DAY5 = 864e5;
|
|
5055
|
+
var DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
5056
|
+
var localDate = /* @__PURE__ */ __name((at) => {
|
|
5057
|
+
const day2 = new Date(at);
|
|
5058
|
+
return `${day2.getFullYear()}-${String(day2.getMonth() + 1).padStart(2, "0")}-${String(day2.getDate()).padStart(2, "0")}`;
|
|
5059
|
+
}, "localDate");
|
|
5060
|
+
var dateOf = /* @__PURE__ */ __name((value, flag) => {
|
|
5061
|
+
const [, year, month, day2] = DATE.exec(value) ?? [];
|
|
5062
|
+
const date = new Date(Number(year), Number(month) - 1, Number(day2));
|
|
5063
|
+
if (!year || localDate(date.getTime()) !== value)
|
|
5064
|
+
throw new CliError("validation_error", `${flag} takes a date, YYYY-MM-DD, not "${value}"`, { param: flag });
|
|
5065
|
+
return date;
|
|
5066
|
+
}, "dateOf");
|
|
5067
|
+
var daysOf = /* @__PURE__ */ __name((from, to, time) => {
|
|
5068
|
+
const [hour, minute3] = time.split(":").map(Number);
|
|
5069
|
+
const days2 = [];
|
|
5070
|
+
for (const day2 = new Date(from); day2 <= to; day2.setDate(day2.getDate() + 1))
|
|
5071
|
+
days2.push({
|
|
5072
|
+
date: localDate(day2.getTime()),
|
|
5073
|
+
at: new Date(day2.getFullYear(), day2.getMonth(), day2.getDate(), hour, minute3).getTime()
|
|
5074
|
+
});
|
|
5075
|
+
return days2;
|
|
5076
|
+
}, "daysOf");
|
|
5077
|
+
var inputOf = /* @__PURE__ */ __name((date, at) => `backfill: ${date}
|
|
5078
|
+
window: --since-time ${new Date(at - DAY5).toISOString()} --before-time ${new Date(at).toISOString()}
|
|
5079
|
+
`, "inputOf");
|
|
5080
|
+
var usd = /* @__PURE__ */ __name((value) => `$${value.toFixed(2)}`, "usd");
|
|
5081
|
+
var cents = /* @__PURE__ */ __name((value) => Math.round(value * 100) / 100, "cents");
|
|
5082
|
+
var digestCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5040
5083
|
const { print } = answers(program, streams, env);
|
|
5041
|
-
const
|
|
5042
|
-
|
|
5043
|
-
const
|
|
5044
|
-
const
|
|
5045
|
-
|
|
5046
|
-
|
|
5084
|
+
const digest = program.command("digest").description("the morning digest's history: build the digests of past days").summary("the morning digest's history");
|
|
5085
|
+
fromAppOption(annotate(digest.command("backfill"), { effects: LOCAL_WRITE })).summary("build the morning digests of past days, without sending them").description("build the morning digest each past day would have had: the morning-digest schedule's agent runs as its timer does (the same skill, flags and cost caps), reading the agenda as of that day's run time, and the result is kept as that day's run, marked backfill, for WireCat Desktop's digests screen. It is never sent to Telegram or mail. A day that already has a digest is skipped. Without --yes it only prints what it would build and the estimate: the days times the last digest run's cost. Each day is a paid model call: it stops once today's runs cost the schedule's daily cap or a day fails, and only you run it, never an agent. The store keeps what holds now, so a chat answered since reads as answered").requiredOption("--from <date>", "the first day, YYYY-MM-DD").requiredOption("--to <date>", "the last day, YYYY-MM-DD; not a day whose run time is still ahead").option("--yes", "build them; without it, only the estimate is printed").option("--json", "print JSON").action(async (given2, command) => {
|
|
5086
|
+
const from = dateOf(given2.from, "--from");
|
|
5087
|
+
const to = dateOf(given2.to, "--to");
|
|
5088
|
+
if (from > to)
|
|
5089
|
+
throw new CliError("validation_error", "--from is after --to", { param: "--from" });
|
|
5090
|
+
const { state, schedule } = digestSchedule(env);
|
|
5091
|
+
if (!schedule)
|
|
5092
|
+
throw new CliError("not_found", `no ${DIGEST_SCHEDULE} schedule to build from \u2014 memo skill show morning-digest says how to make one`, { reason: "backfill.no-schedule" });
|
|
5093
|
+
const file = scheduleFile(state, schedule.name);
|
|
5094
|
+
const when = readSchedule(file).when;
|
|
5095
|
+
if (!("daily" in when))
|
|
5096
|
+
throw new CliError("validation_error", `${schedule.name} does not run at a daily time, so it has no past days`, {
|
|
5097
|
+
reason: "backfill.not-daily",
|
|
5098
|
+
schedule: schedule.name
|
|
5099
|
+
});
|
|
5100
|
+
const all = daysOf(from, to, when.daily);
|
|
5101
|
+
if ((all.at(-1)?.at ?? 0) > Date.now())
|
|
5102
|
+
throw new CliError("validation_error", `the ${given2.to} digest's time has not come yet; --to an earlier day`, {
|
|
5103
|
+
param: "--to"
|
|
5104
|
+
});
|
|
5105
|
+
const runs = join6(file, "..", "runs");
|
|
5106
|
+
const done = new Set((existsSync6(runs) ? readdirSync4(runs) : []).filter((name2) => name2.endsWith(".report.json")).map((name2) => localDate(runTime(name2))));
|
|
5107
|
+
const days2 = all.filter((day2) => !done.has(day2.date));
|
|
5108
|
+
const skipped = all.filter((day2) => done.has(day2.date)).map((day2) => day2.date);
|
|
5109
|
+
const lastCost = schedule.last?.costUsd;
|
|
5110
|
+
const estimate = {
|
|
5111
|
+
days: days2.map((day2) => day2.date),
|
|
5112
|
+
skipped,
|
|
5113
|
+
estimateUsd: typeof lastCost === "number" ? cents(days2.length * lastCost) : null
|
|
5114
|
+
};
|
|
5115
|
+
const cap = readSchedule(file).maxCostPerDay ?? scheduleLimits(env).maxCostPerDay ?? SCHEDULE_DEFAULTS.maxCostPerDay;
|
|
5116
|
+
if (!given2.yes) {
|
|
5117
|
+
const room = cap > 0 ? cap - spentToday(file) : Number.POSITIVE_INFINITY;
|
|
5118
|
+
print(given2.json, itemAnswer(estimate), [
|
|
5119
|
+
`Would build ${days2.length} day(s)${days2.length ? `: ${estimate.days.join(", ")}` : ""}.`,
|
|
5120
|
+
...skipped.length ? [`Skipped, a digest exists: ${skipped.join(", ")}.`] : [],
|
|
5121
|
+
estimate.estimateUsd === null ? "No digest run has a cost yet, so there is no estimate." : `Estimate: ${usd(estimate.estimateUsd)} (${days2.length} \xD7 the last run's ${usd(lastCost)}).`,
|
|
5122
|
+
...estimate.estimateUsd !== null && estimate.estimateUsd > room ? [`Today's cap leaves ${usd(Math.max(0, room))}: it stops there, and the rest waits for another day.`] : [],
|
|
5123
|
+
...days2.length ? ["Build them, sending nothing: add --yes."] : []
|
|
5124
|
+
].join("\n"));
|
|
5125
|
+
return;
|
|
5126
|
+
}
|
|
5127
|
+
const who = await whoRuns(command, env, { question: `spend about ${usd(estimate.estimateUsd ?? 0)}?` });
|
|
5128
|
+
if (who !== "owner")
|
|
5129
|
+
throw new CliError("permission_error", "a backfill spends the owner's money on model calls; the owner runs it at a terminal or in WireCat Desktop", { reason: "backfill.owner-only" });
|
|
5130
|
+
const built = [];
|
|
5131
|
+
const left = [];
|
|
5132
|
+
for (const day2 of days2) {
|
|
5133
|
+
const failed = built.some((one2) => one2.exitCode !== 0);
|
|
5134
|
+
if (left.length || failed || cap > 0 && spentToday(file) >= cap) {
|
|
5135
|
+
left.push(day2.date);
|
|
5136
|
+
continue;
|
|
5137
|
+
}
|
|
5138
|
+
const run = await backfillScheduleRun(command, APP, env, file, {
|
|
5139
|
+
at: new Date(day2.at),
|
|
5140
|
+
input: inputOf(day2.date, day2.at)
|
|
5141
|
+
});
|
|
5142
|
+
built.push({ date: day2.date, at: run.at, exitCode: run.exitCode, costUsd: run.costUsd ?? null });
|
|
5143
|
+
}
|
|
5144
|
+
const costUsd = cents(built.reduce((sum, one2) => sum + (one2.costUsd ?? 0), 0));
|
|
5145
|
+
if (built.some((one2) => one2.exitCode !== 0))
|
|
5146
|
+
process.exitCode = 1;
|
|
5147
|
+
print(given2.json, itemAnswer({ ...estimate, built, left, costUsd }), [
|
|
5148
|
+
...built.map((one2) => `${one2.date}: ${one2.exitCode === 0 ? "built" : `failed (exit ${one2.exitCode})`}${one2.costUsd === null ? "" : `, ${usd(one2.costUsd)}`}`),
|
|
5149
|
+
...skipped.length ? [`Skipped, a digest exists: ${skipped.join(", ")}.`] : [],
|
|
5150
|
+
...left.length ? [`Not built, after a failed day or once today's cap of ${usd(cap)} was spent: ${left.join(", ")}.`] : [],
|
|
5151
|
+
`Cost: ${usd(costUsd)}. Nothing was sent.`
|
|
5152
|
+
].join("\n"));
|
|
5047
5153
|
});
|
|
5048
|
-
|
|
5049
|
-
}, "eventsCommand");
|
|
5154
|
+
}, "digestCommand");
|
|
5050
5155
|
|
|
5051
|
-
// dist/
|
|
5052
|
-
var
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
],
|
|
5069
|
-
"notes edit": ["memo notes edit note:12 --revision 2 --text 'Prefers calls after ten'"],
|
|
5070
|
-
"notes remove": ["memo notes remove note:12"],
|
|
5071
|
-
"notes export": ["memo notes export --output-dir ~/notes/memo --format obsidian"],
|
|
5072
|
-
"sources add": [
|
|
5073
|
-
"memo sources add ~/Downloads/runner-notes.pdf --subject project:3 --keep-copy",
|
|
5074
|
-
"memo sources add https://example.org/release-notes --title 'Release notes' --json",
|
|
5075
|
-
"memo sources add - --title 'Call with Kai' --subject person:12"
|
|
5076
|
-
],
|
|
5077
|
-
"sources show": ["memo sources show document:42", "memo sources show document:42 --bytes 65536 --json"],
|
|
5078
|
-
"sources mentions": ["memo sources mentions document:42 --json"],
|
|
5079
|
-
"sources remove": ["memo sources remove document:42"],
|
|
5080
|
-
"folders add": ["memo folders add ~/notes"],
|
|
5081
|
-
"folders update": ["memo folders update 1 ~/notes"],
|
|
5082
|
-
"folders remove": ["memo folders remove 1", "memo folders remove 1 --allow-delete --yes"],
|
|
5083
|
-
"folders list": ["memo folders list --json"],
|
|
5084
|
-
"config show": ["memo config show", "memo config show --json"],
|
|
5085
|
-
"config migrate": ["memo config migrate"],
|
|
5086
|
-
"config unset": ["memo config unset permissions.notes.edit"],
|
|
5087
|
-
"mentions list": [
|
|
5088
|
-
"memo mentions list kind:phone --source notes",
|
|
5089
|
-
"memo mentions list domain:example.com --source email:personal,email:work --json",
|
|
5090
|
-
"memo mentions list kind:place --source mail"
|
|
5091
|
-
],
|
|
5092
|
-
"mentions show": ["memo mentions show 12", "memo mentions show 40 --source email:personal --json"],
|
|
5093
|
-
"mentions confirm": ["memo mentions confirm 12 person:7", "memo mentions confirm 40 --source email:personal"],
|
|
5094
|
-
"mentions reject": ["memo mentions reject 12", "memo mentions reject 40 --source email:personal"],
|
|
5095
|
-
"mail review": [
|
|
5096
|
-
"memo mail review --holder mail-triage --source email:work --json",
|
|
5097
|
-
"memo mail review --unanswered 1d --source email:personal",
|
|
5098
|
-
"memo mail review 'date>2h' --source email:me@example.com"
|
|
5099
|
-
],
|
|
5100
|
-
"messages acknowledge": [
|
|
5101
|
-
"memo messages acknowledge --holder mail-triage --cursor 9123.1762090000000 --source email:work",
|
|
5102
|
-
"memo messages acknowledge --holder mail-triage --cursor 9123.1762090000000 --source email:me@example.com --json",
|
|
5103
|
-
"memo messages acknowledge --holder backfill --cursor 870.1762090000000 --source email:personal"
|
|
5104
|
-
],
|
|
5105
|
-
"messages reset": [
|
|
5106
|
-
"memo messages reset --holder mail-triage --last 8 --dry-run --source email:me@example.com",
|
|
5107
|
-
"memo messages reset --holder mail-triage --since-time 2026-11-04T00:00:00Z --source email:work --json"
|
|
5108
|
-
],
|
|
5109
|
-
"mail findings add": [
|
|
5110
|
-
"memo mail findings add findings.json --source email:work",
|
|
5111
|
-
"memo mail findings add findings.json --source email:work --key mail-triage:9123 --dry-run --json",
|
|
5112
|
-
`memo mail findings add '{"schema_version":1,"key":"mail-triage:9123","extractor":"mail-triage/1","findings":[\u2026]}' --source email:me@example.com --json`
|
|
5113
|
-
],
|
|
5114
|
-
"mail findings show": [
|
|
5115
|
-
"memo mail findings show 41",
|
|
5116
|
-
"memo mail findings show 41 --json",
|
|
5117
|
-
"memo mail findings show 41 --json=id,input.findings"
|
|
5118
|
-
],
|
|
5119
|
-
"mail findings list": [
|
|
5120
|
-
"memo mail findings list status:proposed",
|
|
5121
|
-
"memo mail findings list --source email:work --json",
|
|
5122
|
-
"memo mail findings list status:reviewed --limit 50 --page 2"
|
|
5123
|
-
],
|
|
5124
|
-
"messages show": ["memo messages show 'msg:email/me%40example.com/thread/42' --before-n 2 --after-n 2"],
|
|
5125
|
-
"projects actions add": ["memo projects actions add findings.json"],
|
|
5126
|
-
"projects actions list": [
|
|
5127
|
-
"memo projects actions list SYH",
|
|
5128
|
-
"memo projects actions list SYH status:reviewed --brief --json"
|
|
5129
|
-
],
|
|
5130
|
-
"projects actions confirm": [
|
|
5131
|
-
"memo projects actions confirm SYH 12 budget accountant --fingerprint 3f9a0c --reason 'both are stated plainly'",
|
|
5132
|
-
"memo projects actions confirm SYH key:4"
|
|
5133
|
-
],
|
|
5134
|
-
"projects actions reject": [
|
|
5135
|
-
"memo projects actions reject SYH 12 --fingerprint 3f9a0c --reason 'not about this project'"
|
|
5136
|
-
],
|
|
5137
|
-
"projects evidence": [
|
|
5138
|
-
"memo projects evidence SYH --source telegram:1,email:personal --contact 'Alice Example'",
|
|
5139
|
-
"memo projects evidence SYH --source all --context-query 'crane tender' --since-time 180d --json"
|
|
5140
|
-
],
|
|
5141
|
-
"models list": ["memo models list kind:text --json"],
|
|
5142
|
-
"commands info": ["memo commands info --json"],
|
|
5143
|
-
"models download": ["memo models download e5-small", "memo models download e5-large"],
|
|
5144
|
-
"models set": ["memo models set e5-large"],
|
|
5145
|
-
"models consents show": ["memo models consents show --json"],
|
|
5146
|
-
"models consents set": [
|
|
5147
|
-
"memo models consents set openai --model gpt-4o-mini",
|
|
5148
|
-
"memo models consents set openai --model gpt-4o-mini --yes"
|
|
5149
|
-
],
|
|
5150
|
-
"models consents revoke": ["memo models consents revoke"],
|
|
5151
|
-
"models add": [
|
|
5152
|
-
`memo models add e5-base --payload '{"repository":"Xenova/multilingual-e5-base","onnx":"onnx/model_quantized.onnx","dims":768,"pooling":"mean","prefix":{"query":"query: ","passage":"passage: "}}'`
|
|
5153
|
-
],
|
|
5154
|
-
"notes links show": ["memo notes links show telegram:101 --json"],
|
|
5155
|
-
"notes links add": ["memo notes links add telegram:101 ~/notes/People/Kai.md"],
|
|
5156
|
-
"notes links clear": ["memo notes links clear telegram:101"],
|
|
5157
|
-
"tags add": ["memo tags add follow-up --note note:12", "memo tags add harbour --project HRB"],
|
|
5158
|
-
"tags remove": ["memo tags remove follow-up --note note:12"],
|
|
5159
|
-
"tags list": ["memo tags list tag:follow-up", "memo tags list --source email:me@example.com --json"],
|
|
5160
|
-
"tasks link": ["memo tasks link HRB-2 HRB-1 --kind blocked-by"],
|
|
5161
|
-
"tasks unlink": ["memo tasks unlink HRB-2 HRB-1 --kind blocked-by"],
|
|
5162
|
-
"tasks links": ["memo tasks links HRB-2 --json"],
|
|
5163
|
-
"tasks status": ["memo tasks status HRB-2"],
|
|
5164
|
-
"tasks add": [
|
|
5165
|
-
"memo tasks add 'msg:telegram/1/77/42' --account telegram:1 --type request",
|
|
5166
|
-
"memo tasks add --project HRB --title 'Draft the budget' --type feature",
|
|
5167
|
-
"memo tasks add --project INBOX --title 'Reply on Avito to Ivan' --external-id avito:4512345678 --source-url https://www.avito.ru/4512345678"
|
|
5168
|
-
],
|
|
5169
|
-
"tasks list": [
|
|
5170
|
-
"memo tasks list state:done --source telegram:1",
|
|
5171
|
-
"memo tasks list project:HRB ready:true --json",
|
|
5172
|
-
'memo tasks list project:* priority:[high TO critical] "invoice" --sort due --json'
|
|
5173
|
-
],
|
|
5174
|
-
"tasks counts": ["memo tasks counts project:* --json"],
|
|
5175
|
-
"tasks history": ["memo tasks history HRB-1 --json"],
|
|
5176
|
-
"tasks comments add": ["memo tasks comments add HRB-1 Booked the hall for Friday"],
|
|
5177
|
-
"tasks comments list": ["memo tasks comments list HRB-1 --json"],
|
|
5178
|
-
"tasks move": ["memo tasks move HRB-3 --status in_progress --before HRB-1 --revision 4"],
|
|
5179
|
-
"people list": ["memo people list --json"],
|
|
5180
|
-
"people add": ["memo people add Lena Example"],
|
|
5181
|
-
"tasks agenda": [
|
|
5182
|
-
"memo tasks agenda --source telegram:1",
|
|
5183
|
-
"memo tasks agenda --source max:1 --waiting 3d --within 90d --json"
|
|
5184
|
-
],
|
|
5185
|
-
"tasks claim": ["memo tasks claim HRB-1 --lease 2h --account telegram:1"],
|
|
5186
|
-
"tasks release": ["memo tasks release HRB-1 --account telegram:1"],
|
|
5187
|
-
"tasks show": ["memo tasks show 1a2b3c4d --source telegram:1 --json"],
|
|
5188
|
-
"stats tasks show": [
|
|
5189
|
-
"memo stats tasks show --source telegram:1",
|
|
5190
|
-
"memo stats tasks show --type question --source telegram:1 --json"
|
|
5191
|
-
],
|
|
5192
|
-
"tasks close": ["memo tasks close 7 --account telegram:1 --as dismissed --reason 'answered by phone'"],
|
|
5193
|
-
"tasks update": [
|
|
5194
|
-
"memo tasks update HRB-1 --title 'Send the budget' --priority high --account telegram:1",
|
|
5195
|
-
"memo tasks update 1a2b3c4d --due 2d --title 'Send the revised budget' --account telegram:1"
|
|
5196
|
-
],
|
|
5197
|
-
"tasks assign": ["memo tasks assign 7 person:3", "memo tasks assign HRB-1 person:3 --clear --revision 4"],
|
|
5198
|
-
"organizations add": [
|
|
5199
|
-
"memo organizations add 'Harbour Studio' --kind company --scope work",
|
|
5200
|
-
"memo organizations add 'Harbour Family' --kind family"
|
|
5201
|
-
],
|
|
5202
|
-
"organizations rename": [
|
|
5203
|
-
"memo organizations rename organization:1 'Harbour Studio Ltd'",
|
|
5204
|
-
"memo organizations rename 1 'Harbour Studio Ltd' --json"
|
|
5205
|
-
],
|
|
5206
|
-
"organizations show": ["memo organizations show organization:1"],
|
|
5207
|
-
"organizations list": ["memo organizations list name:*harbour*", "memo organizations list --json"],
|
|
5208
|
-
"organizations context": ["memo organizations context organization:1"],
|
|
5209
|
-
"projects meetings list": ["memo projects meetings list HRB --source zoom:me@example.com"],
|
|
5210
|
-
"projects meetings link": ["memo projects meetings link HRB 31 --account zoom:me@example.com"],
|
|
5211
|
-
"projects add": ["memo projects add 'Harbour' --key HRB --type client --organization 1"],
|
|
5212
|
-
"projects list": ["memo projects list"],
|
|
5213
|
-
"projects context": ["memo projects context HRB", "memo projects context project:2 --json"],
|
|
5214
|
-
"projects status": ["memo projects status HRB --context-query 1C", "memo projects status HRB --compact"],
|
|
5215
|
-
"projects annotations show": ["memo projects annotations show HRB --max-read-bytes 1048576 --json"],
|
|
5216
|
-
"projects annotations export": ["memo projects annotations export HRB --output harbour-annotations.json --json"],
|
|
5217
|
-
"projects annotations check": [
|
|
5218
|
-
"memo projects annotations check harbour-annotations.json --target-store ./trial/wirecat.db --project project:2 --bindings bindings.json --json"
|
|
5219
|
-
],
|
|
5220
|
-
"projects annotations restore": [
|
|
5221
|
-
"memo projects annotations restore harbour-annotations.json --target-store ./trial/wirecat.db --project project:2 --bindings bindings.json --fingerprint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --json"
|
|
5222
|
-
],
|
|
5223
|
-
"projects key-documents add": ["memo projects key-documents add HRB note:12 --reason 'the brief'"],
|
|
5224
|
-
"projects key-documents remove": ["memo projects key-documents remove HRB note:12"],
|
|
5225
|
-
"projects key-documents list": ["memo projects key-documents list HRB"],
|
|
5226
|
-
"relationships update": [
|
|
5227
|
-
"memo relationships update 12 --purpose sales",
|
|
5228
|
-
"memo relationships update 12 --role contractor --reason 'builds the site'"
|
|
5229
|
-
],
|
|
5230
|
-
"relationships add": [
|
|
5231
|
-
"memo relationships add person:3 organization:1 --role employee",
|
|
5232
|
-
"memo relationships add project:2 organization:1 --kind related-to --reason 'same client'"
|
|
5233
|
-
],
|
|
5234
|
-
"relationships list": ['memo relationships list about:"person:3"', "memo relationships list confirmed:false"],
|
|
5235
|
-
"relationships remove": ["memo relationships remove 4"],
|
|
5236
|
-
"relationships confirm": ["memo relationships confirm 4"],
|
|
5237
|
-
"relationships scan": [
|
|
5238
|
-
"memo relationships scan HRB --source all",
|
|
5239
|
-
"memo relationships scan HRB --source telegram:1,email:personal --yes",
|
|
5240
|
-
"memo relationships scan --source email:me@example.com"
|
|
5241
|
-
],
|
|
5242
|
-
"reminders add": [
|
|
5243
|
-
"memo reminders add 7 --at-time 2026-10-20T09:00:00+02:00 --timezone Europe/Madrid --account telegram:1"
|
|
5244
|
-
],
|
|
5245
|
-
"reminders list": ["memo reminders list --source telegram:1"],
|
|
5246
|
-
"reminders claim": ["memo reminders claim --account telegram:1 --json"],
|
|
5247
|
-
"reminders acknowledge": ["memo reminders acknowledge 3 3:1 --account telegram:1"],
|
|
5248
|
-
"reminders cancel": ["memo reminders cancel 3 --account telegram:1"],
|
|
5249
|
-
"reminders update": ["memo reminders update 3 --revision 1 --at-time 2026-10-21T09:00:00+02:00 --account telegram:1"],
|
|
5250
|
-
"vocabulary list": ["memo vocabulary list kind:tag"],
|
|
5251
|
-
"vocabulary show": ["memo vocabulary show Harbour --kind project"],
|
|
5252
|
-
"vocabulary check": ["memo vocabulary check on-boarding --kind tag", "memo vocabulary check --limit 20 --json"],
|
|
5253
|
-
"vocabulary inspect": [
|
|
5254
|
-
"memo vocabulary inspect tag:1 tag:2 --fingerprint v1:all:all:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --limit 5 --json"
|
|
5255
|
-
],
|
|
5256
|
-
"vocabulary create": ["memo vocabulary create onboarding --kind tag --fingerprint 3f9a"],
|
|
5257
|
-
"vocabulary aliases add": ["memo vocabulary aliases add project:2 Harbor --fingerprint 3f9a"],
|
|
5258
|
-
"vocabulary aliases remove": ["memo vocabulary aliases remove project:2 5 --fingerprint 3f9a"],
|
|
5259
|
-
"memories add": ["memo memories add 'Kai prefers Friday meetings' --kind preference --scope work --evidence note:12"],
|
|
5260
|
-
"memories list": ["memo memories list status:proposed kind:preference"],
|
|
5261
|
-
"memories show": ["memo memories show memory:4 --sources"],
|
|
5262
|
-
"memories update": ["memo memories update memory:4 --project SYH", "memo memories update memory:4 --project none"],
|
|
5263
|
-
"memories confirm": ["memo memories confirm memory:4"],
|
|
5264
|
-
"memories invalidate": ["memo memories invalidate memory:4"],
|
|
5265
|
-
"memories remove": ["memo memories remove memory:4"],
|
|
5266
|
-
"memories check": ["memo memories check", "memo memories check --limit 2000 --json"],
|
|
5267
|
-
"memories challenge": [
|
|
5268
|
-
"memo memories challenge memory:4 --evidence note:15 --reason 'the later note moves delivery to the 30th'",
|
|
5269
|
-
"memo memories challenge memory:4 --evidence note:15 --reason 'moved' --suggest 'Delivery is on the 30th' --json"
|
|
5270
|
-
],
|
|
5271
|
-
"facts add": [
|
|
5272
|
-
"memo facts add 'We moved the launch to spring' --kind decision --evidence 'msg:telegram/1/77/42' --project HRB"
|
|
5273
|
-
],
|
|
5274
|
-
"facts list": ["memo facts list kind:decision project:HRB"],
|
|
5275
|
-
"orders list": ["memo orders list status:shipped", `memo orders list number:A-1042 'supplier:"Shop One"' --json`],
|
|
5276
|
-
"orders show": ["memo orders show order:3"],
|
|
5277
|
-
"pipelines list": ["memo pipelines list", "memo pipelines list kind:lead --json"],
|
|
5278
|
-
"pipelines show": ["memo pipelines show pipeline:2", "memo pipelines show Sales --since-time 2026-09-01"],
|
|
5279
|
-
"pipelines add": [
|
|
5280
|
-
"memo pipelines add Sales Call Quote Contract won lost",
|
|
5281
|
-
"memo pipelines add Inbound new called --kind lead"
|
|
5282
|
-
],
|
|
5283
|
-
"deals list": ["memo deals list status:open project:HRB", "memo deals list stage:Quote --json"],
|
|
5284
|
-
"deals show": ["memo deals show deal:5"],
|
|
5285
|
-
"deals add": [
|
|
5286
|
-
"memo deals add 'Site for the clinic' Call 500000.00 RUB --organization organization:3 --project HRB",
|
|
5287
|
-
"memo deals add 'Support contract' Sales/Quote --person person:7 --role decision-maker --due 2026-12-01"
|
|
5288
|
-
],
|
|
5289
|
-
"deals move": ["memo deals move deal:5 Quote"],
|
|
5290
|
-
"deals close": ["memo deals close deal:5 won", "memo deals close deal:6 lost --reason 'chose a cheaper studio'"],
|
|
5291
|
-
"leads list": ["memo leads list status:open"],
|
|
5292
|
-
"leads show": ["memo leads show lead:3"],
|
|
5293
|
-
"leads add": ["memo leads add 'Call from the site'", "memo leads add 'Clinic in Kazan' contacted --person person:9"],
|
|
5294
|
-
"leads move": ["memo leads move lead:3 qualified"],
|
|
5295
|
-
"leads close": ["memo leads close lead:3 lost --reason 'no budget'"],
|
|
5296
|
-
"orders add": [
|
|
5297
|
-
"memo orders add 'Shop One' 2499.00 RUB --kind personal --title A-1042",
|
|
5298
|
-
"memo orders add 'Office Supply' --kind client --organization organization:3"
|
|
5299
|
-
],
|
|
5300
|
-
"events list": [
|
|
5301
|
-
"memo events list event_type:call",
|
|
5302
|
-
"memo events list account:phone:pixel 'starts_at:[2026-11-02 TO 2026-11-07}' --json"
|
|
5303
|
-
],
|
|
5304
|
-
"events show": ["memo events show event:42"],
|
|
5305
|
-
"invoices list": ["memo invoices list project:HRB open:true", "memo invoices list review:proposed --json"],
|
|
5306
|
-
"invoices show": ["memo invoices show invoice:4"],
|
|
5307
|
-
"invoices add": [
|
|
5308
|
-
"memo invoices add 50000.00 RUB Bed rental, November --kind receivable --organization organization:3 --project HRB",
|
|
5309
|
-
"memo invoices add 1200.50 EUR Hosting --kind payable --person person:7 --title 2026-118 --due 2026-11-15"
|
|
5310
|
-
],
|
|
5311
|
-
"payments list": ["memo payments list project:HRB direction:in", "memo payments list review:proposed --json"],
|
|
5312
|
-
"payments show": ["memo payments show payment:9"],
|
|
5313
|
-
"payments add": [
|
|
5314
|
-
"memo payments add 25000.00 RUB --kind in --organization organization:3 --occurred-time 2026-11-01 --project HRB",
|
|
5315
|
-
"memo payments add 5000.00 RUB --kind out --organization organization:3 --refund-of payment:9"
|
|
5316
|
-
],
|
|
5317
|
-
"records import": [
|
|
5318
|
-
"memo records import payments.jsonl --account rentals --dry-run",
|
|
5319
|
-
"memo records import envelope.json --account rentals --json",
|
|
5320
|
-
"memo records import contacts.vcf --account phone:pixel --region gb"
|
|
5321
|
-
],
|
|
5322
|
-
"records check": ["memo records check - --account rentals"],
|
|
5323
|
-
"records list": [
|
|
5324
|
-
"memo records list waiting:true --account sheet:rentals",
|
|
5325
|
-
"memo records list type:organization --account sheet:rentals --json",
|
|
5326
|
-
`memo records list 'entity:"organization:3"' deleted:false --account sheet:rentals`
|
|
5327
|
-
],
|
|
5328
|
-
"records link": ["memo records link organization:client organization:3 --account sheet:rentals"],
|
|
5329
|
-
"payments allocate": ["memo payments allocate payment:9 invoice:4 25000.00"],
|
|
5330
|
-
"products list": ["memo products list kind:service", "memo products list archived:true --json"],
|
|
5331
|
-
"products show": ["memo products show product:4"],
|
|
5332
|
-
"products add": [
|
|
5333
|
-
"memo products add 'Bike rental, month' 10000.00 RUB --kind service --unit month",
|
|
5334
|
-
"memo products add 'Helmet' 2500.00 RUB --sku H-12 --supplier organization:3"
|
|
5335
|
-
],
|
|
5336
|
-
"products update": [
|
|
5337
|
-
"memo products update product:4 --amount 12000.00 --currency RUB",
|
|
5338
|
-
"memo products update product:4 --archived on"
|
|
5339
|
-
],
|
|
5340
|
-
"orders lines add": [
|
|
5341
|
-
"memo orders lines add order:3 12 --product product:4",
|
|
5342
|
-
"memo orders lines add order:3 1 Rental, first week --product product:4 --amount 2000.00",
|
|
5343
|
-
"memo orders lines add order:3 2 Helmet --amount 2500.00"
|
|
5344
|
-
],
|
|
5345
|
-
"orders lines remove": ["memo orders lines remove order:3 2"],
|
|
5346
|
-
"invoices lines add": [
|
|
5347
|
-
"memo invoices lines add invoice:4 1 --product product:4",
|
|
5348
|
-
"memo invoices lines add invoice:4 2 Delivery --amount 1500.00"
|
|
5349
|
-
],
|
|
5350
|
-
"invoices lines remove": ["memo invoices lines remove invoice:4 2"],
|
|
5351
|
-
"contracts list": ["memo contracts list status:active", "memo contracts list expires:2026-12-31 --json"],
|
|
5352
|
-
"contracts show": ["memo contracts show contract:2"],
|
|
5353
|
-
"contracts add": [
|
|
5354
|
-
"memo contracts add 'Rental agreement' --kind service --start-date 2026-11-01 --end-date 2027-10-31 --auto-renew on --notice-days 30 --amount 120000.00 --currency RUB",
|
|
5355
|
-
"memo contracts add 'NDA with the studio' --kind nda --project HRB"
|
|
5356
|
-
],
|
|
5357
|
-
"contracts update": [
|
|
5358
|
-
"memo contracts update contract:2 --status terminated",
|
|
5359
|
-
"memo contracts update contract:2 --end-date 2027-12-31"
|
|
5360
|
-
],
|
|
5361
|
-
"subscriptions list": [
|
|
5362
|
-
"memo subscriptions list status:active direction:payable",
|
|
5363
|
-
"memo subscriptions list renews:2026-12-01 --json"
|
|
5364
|
-
],
|
|
5365
|
-
"subscriptions show": ["memo subscriptions show subscription:5"],
|
|
5366
|
-
"subscriptions add": [
|
|
5367
|
-
"memo subscriptions add Hosting 990.00 RUB --kind payable --supplier organization:3 --period 1-month --start-date 2026-11-01",
|
|
5368
|
-
"memo subscriptions add 'Bike rental' 10000.00 RUB --kind receivable --customer organization:3 --period 1-month --trial-end-date 2026-11-14 --status trial"
|
|
5369
|
-
],
|
|
5370
|
-
"subscriptions update": [
|
|
5371
|
-
"memo subscriptions update subscription:5 --status paused",
|
|
5372
|
-
"memo subscriptions update subscription:5 --period 1-year"
|
|
5373
|
-
],
|
|
5374
|
-
"subscriptions cancel": ["memo subscriptions cancel subscription:5 --occurred-time 2026-11-30"],
|
|
5375
|
-
"subscriptions prices add": ["memo subscriptions prices add subscription:5 1190.00 RUB --start-date 2027-01-01"],
|
|
5376
|
-
"wallets list": ["memo wallets list", "memo wallets list kind:card --json"],
|
|
5377
|
-
"wallets show": ["memo wallets show wallet:2", "memo wallets show wallet:2 --until-time 2026-10-31"],
|
|
5378
|
-
"wallets add": ["memo wallets add 'Main card' RUB --kind card --institution 'Bank One'"],
|
|
5379
|
-
"wallets update": ["memo wallets update wallet:2 --opening-balance 15000.00 --opening-date 2026-01-01"],
|
|
5380
|
-
"transactions list": [
|
|
5381
|
-
`memo transactions list 'wallet:"wallet:2"' status:pending`,
|
|
5382
|
-
"memo transactions list uncategorized:true --json"
|
|
5383
|
-
],
|
|
5384
|
-
"transactions show": ["memo transactions show transaction:12"],
|
|
5385
|
-
"transactions add": [
|
|
5386
|
-
"memo transactions add wallet:2 500.00 --kind out --occurred-time 2026-11-14 --description 'Coffee shop'",
|
|
5387
|
-
"memo transactions add wallet:2 10000.00 --kind in --payment payment:9"
|
|
5388
|
-
],
|
|
5389
|
-
"transactions update": [
|
|
5390
|
-
"memo transactions update transaction:12 --status booked",
|
|
5391
|
-
"memo transactions update transaction:12 --payment payment:9"
|
|
5392
|
-
],
|
|
5393
|
-
"transactions splits add": ["memo transactions splits add transaction:12 300.00 Rent --project HRB"],
|
|
5394
|
-
"transactions splits remove": ["memo transactions splits remove transaction:12 1"],
|
|
5395
|
-
"records show": [
|
|
5396
|
-
"memo records show custom:quote:Q-7 --account example-erp:demo",
|
|
5397
|
-
"memo records show organization:client --account sheet:rentals --json"
|
|
5398
|
-
],
|
|
5399
|
-
"records delete": ["memo records delete payment:sheet-12 --account sheet:rentals"],
|
|
5400
|
-
"records match": ["memo records match --account sheet:rentals"],
|
|
5401
|
-
"payments unlink": ["memo payments unlink payment:9 invoice:4"],
|
|
5402
|
-
"facts show": ["memo facts show fact:4 --sources"],
|
|
5403
|
-
"facts confirm": ["memo facts confirm fact:4"],
|
|
5404
|
-
"facts revoke": ["memo facts revoke fact:4"],
|
|
5405
|
-
"facts reverse": ["memo facts reverse fact:4"],
|
|
5406
|
-
"facts reject": ["memo facts reject fact:4"],
|
|
5407
|
-
"facts remove": ["memo facts remove fact:4"],
|
|
5408
|
-
"facts challenge": ["memo facts challenge fact:4 --evidence 'msg:telegram/1/77/50' --reason 'reversed in chat'"],
|
|
5409
|
-
"actions add": [
|
|
5410
|
-
`memo actions add reply --reason 'Kai asked twice' --account telegram:1 --target 'msg:telegram/1/77/42' --payload '{"text":"Friday works"}'`
|
|
5411
|
-
],
|
|
5412
|
-
"meetings actions add": ["memo meetings actions add findings.json --account zoom:me@example.com"],
|
|
5413
|
-
"meetings passage": [
|
|
5414
|
-
"memo meetings passage meeting:1/1/1/0 --source zoom:me@example.com --before-n 1 --after-n 1 --json"
|
|
5415
|
-
],
|
|
5416
|
-
"meetings prepare": [
|
|
5417
|
-
"memo meetings prepare example-series --source zoom:me@example.com --json",
|
|
5418
|
-
"memo meetings prepare example-series --source zoom:me@example.com --context-source tg.personal --context-query Harbour --json"
|
|
5419
|
-
],
|
|
5420
|
-
"search meetings": [
|
|
5421
|
-
"memo search meetings budget --source zoom:me@example.com --project Harbour --since-time 2026-10-01 --limit 10 --json"
|
|
5422
|
-
],
|
|
5423
|
-
"meetings actions list": ["memo meetings actions list status:proposed --source zoom:me@example.com"],
|
|
5424
|
-
"meetings actions show": ["memo meetings actions show 5 --source zoom:me@example.com"],
|
|
5425
|
-
"meetings actions confirm": [
|
|
5426
|
-
"memo meetings actions confirm 5 decision --fingerprint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --account zoom:me@example.com"
|
|
5427
|
-
],
|
|
5428
|
-
"meetings actions reject": [
|
|
5429
|
-
"memo meetings actions reject 5 --fingerprint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --account zoom:me@example.com"
|
|
5430
|
-
],
|
|
5431
|
-
"actions list": ["memo actions list status:proposed"],
|
|
5432
|
-
"actions show": ["memo actions show 5"],
|
|
5433
|
-
"actions confirm": ["memo actions confirm 5"],
|
|
5434
|
-
"actions reject": ["memo actions reject 5"],
|
|
5435
|
-
"review list": [
|
|
5436
|
-
"memo review list project:HRB",
|
|
5437
|
-
"memo review list kind:relationship,fact by:agent",
|
|
5438
|
-
"memo review list via:chat:max/1/-100"
|
|
5439
|
-
],
|
|
5440
|
-
"review show": ["memo review show 17079", "memo review show 17080 --brief --json"],
|
|
5441
|
-
"review confirm": [
|
|
5442
|
-
"memo review confirm 17078-17081",
|
|
5443
|
-
"memo review confirm 17080/f1,17080/f3",
|
|
5444
|
-
"memo review confirm close:Q-15"
|
|
5445
|
-
],
|
|
5446
|
-
"review reject": [
|
|
5447
|
-
'memo review reject 17081 --reason "not this project"',
|
|
5448
|
-
"memo review reject close:Q-15 --reason 'still open'"
|
|
5449
|
-
],
|
|
5450
|
-
"review agenda": ["memo review agenda --compact", "memo review agenda --since-time 3d --json"],
|
|
5451
|
-
"review status": ["memo review status", "memo review status --since-time 7d --json"],
|
|
5452
|
-
"schedule command": [
|
|
5453
|
-
"memo schedule command digest --at 08:30 -- review status",
|
|
5454
|
-
"memo schedule command mail-sync --every 1h -- sync --only mail"
|
|
5455
|
-
],
|
|
5456
|
-
"schedule agent": [
|
|
5457
|
-
"memo schedule agent triage claude 'read memo review status and list what needs me today' --at 08:45 --max-cost 1",
|
|
5458
|
-
"memo schedule agent mail-triage claude 'Run memo skill show mail-triage and follow it.' --every 5m --on-new-mail mail-triage --mail-wait 1h --mail-batch 20 --max-cost 1 --max-cost-per-day 5",
|
|
5459
|
-
"memo schedule agent weekly claude 'read memo review status and sum up the week' --at 09:00 --model opus"
|
|
5460
|
-
],
|
|
5461
|
-
"schedule list": ["memo schedule list", "memo schedule list kind:agent --json"],
|
|
5462
|
-
"schedule run": ["memo schedule run digest"],
|
|
5463
|
-
"schedule remove": ["memo schedule remove digest"],
|
|
5464
|
-
"schedule exec": ["memo schedule exec ~/.local/state/cli-memo/schedules/digest/schedule.json"],
|
|
5465
|
-
"templates list": ["memo templates list", "memo templates list channel:telegram source:stored --json"],
|
|
5466
|
-
"templates show": [
|
|
5467
|
-
"memo templates show report/morning-digest --channel telegram",
|
|
5468
|
-
"memo templates show report/weekly-gaps --channel email --locale en --json"
|
|
5469
|
-
],
|
|
5470
|
-
"templates edit": [
|
|
5471
|
-
"memo templates edit report/morning-digest --channel telegram",
|
|
5472
|
-
"memo templates edit report/morning-digest --channel text --file digest.text.liquid",
|
|
5473
|
-
"memo templates edit report/morning-digest --channel telegram --undo"
|
|
5474
|
-
],
|
|
5475
|
-
"templates preview": [
|
|
5476
|
-
"memo templates preview report/morning-digest --channel telegram",
|
|
5477
|
-
"memo templates preview report/morning-digest --channel email --locale en --file draft.liquid"
|
|
5478
|
-
],
|
|
5479
|
-
"templates reset": ["memo templates reset report/morning-digest --channel telegram"],
|
|
5480
|
-
"agents list": ["memo agents list agent:claude-code --limit 20"],
|
|
5481
|
-
"mcp serve": ["memo mcp serve", "memo mcp serve --http --public-url https://laptop.example.ts.net"],
|
|
5482
|
-
"mcp revoke": ["memo mcp revoke --json"],
|
|
5483
|
-
"mcp server start": ["memo mcp server start --public-url https://laptop.example.ts.net"],
|
|
5484
|
-
"mcp server status": ["memo mcp server status --json"],
|
|
5485
|
-
"mcp server stop": ["memo mcp server stop"],
|
|
5486
|
-
"search all": [
|
|
5487
|
-
"memo search all 'budget harbour'",
|
|
5488
|
-
"memo search all 'content:invoice' --only mail,notes --json",
|
|
5489
|
-
"memo search all 'Rental agreement' --only business"
|
|
5490
|
-
],
|
|
5491
|
-
"search messages": ["memo search messages 'friday meeting has:voice'"],
|
|
5492
|
-
"search mail": ["memo search mail 'mailbox:important budget' --source email:me@example.com"],
|
|
5493
|
-
"search notes": ["memo search notes budget notes:2", "memo search notes kickoff --project HRB --json"],
|
|
5494
|
-
"search memories": ["memo search memories friday meetings scope:work"],
|
|
5495
|
-
"search people": ["memo search people ana", "memo search people Ana Example --source telegram --json"],
|
|
5496
|
-
"answers create": [
|
|
5497
|
-
"memo answers create 'what did Kai say about the budget?' --all",
|
|
5498
|
-
"memo answers create 'when is the launch?' --source telegram:1"
|
|
5499
|
-
],
|
|
5500
|
-
sync: ["memo sync", "memo sync --only mail", "memo sync --only notes --folder ~/notes --no-embed"],
|
|
5501
|
-
"jobs start": ["memo jobs start --every 10m"],
|
|
5502
|
-
"jobs stop": ["memo jobs stop"],
|
|
5503
|
-
"jobs status": ["memo jobs status --json"],
|
|
5504
|
-
doctor: ["memo doctor", "memo doctor --json"],
|
|
5505
|
-
"runs list": ["memo runs list status:failed --limit 10", "memo runs list --page 2 --json"],
|
|
5506
|
-
"runs show": ["memo runs show 20261025T090000Z-mail-sync-a81f2c --json"],
|
|
5507
|
-
"runs path": ["memo runs path 20261025T090000Z-mail-sync-a81f2c"],
|
|
5508
|
-
"store info": ["memo store info", "memo store info --json"],
|
|
5509
|
-
"store recover": ["memo store recover", "memo store recover --json"],
|
|
5510
|
-
"store recover run": ["memo store recover run"],
|
|
5511
|
-
upgrade: ["memo upgrade --check"],
|
|
5512
|
-
commands: ["memo commands --json", "memo commands tags add --json"],
|
|
5513
|
-
"skill show": ["memo skill show"],
|
|
5514
|
-
"skill install": ["memo skill install --for all"],
|
|
5515
|
-
"skill status": ["memo skill status", "memo skill status --json"],
|
|
5516
|
-
guide: ["memo guide", "memo guide person-brief --json"],
|
|
5517
|
-
help: ["memo help options", "memo help tasks agenda"]
|
|
5518
|
-
};
|
|
5519
|
-
var leaves = /* @__PURE__ */ __name((command, path = []) => command.commands.flatMap((child) => {
|
|
5520
|
-
const at = [...path, child.name()];
|
|
5521
|
-
return child.commands.length ? leaves(child, at) : [[at.join(" "), child]];
|
|
5522
|
-
}), "leaves");
|
|
5523
|
-
var addExamples = /* @__PURE__ */ __name((program) => {
|
|
5524
|
-
for (const [path, command] of leaves(program)) {
|
|
5525
|
-
const examples = EXAMPLES[path];
|
|
5526
|
-
if (!examples || JSON.stringify(metaOf(command).examples) === JSON.stringify(examples))
|
|
5527
|
-
continue;
|
|
5528
|
-
if (hasSharedContract(command))
|
|
5529
|
-
overrideSharedContract(command, "Memo examples use explicit stored-account scope rather than messenger profile words.", (one2) => {
|
|
5530
|
-
annotate(one2, { examples });
|
|
5531
|
-
});
|
|
5532
|
-
else
|
|
5533
|
-
annotate(command, { examples });
|
|
5534
|
-
}
|
|
5535
|
-
}, "addExamples");
|
|
5536
|
-
|
|
5537
|
-
// dist/memories/memories.js
|
|
5538
|
-
var addMemory = /* @__PURE__ */ __name(async (store, memory, by) => store.memories.add({
|
|
5539
|
-
kind: memory.kind,
|
|
5540
|
-
body: memory.text,
|
|
5541
|
-
scope: memory.scope,
|
|
5542
|
-
evidence: memory.evidence,
|
|
5543
|
-
author: by,
|
|
5544
|
-
status: by === "owner" ? "confirmed" : "proposed",
|
|
5545
|
-
...memory.subject === void 0 ? {} : { subject: memory.subject },
|
|
5546
|
-
...memory.project === void 0 ? {} : { project: await canonicalProject(store, memory.project) },
|
|
5547
|
-
...memory.supersedes === void 0 ? {} : { supersedes: memory.supersedes }
|
|
5548
|
-
}), "addMemory");
|
|
5549
|
-
|
|
5550
|
-
// dist/memories/memory.js
|
|
5551
|
-
var MEMORY_QUERY = {
|
|
5552
|
-
entity: "memory",
|
|
5553
|
-
backend: "native",
|
|
5554
|
-
fields: [
|
|
5555
|
-
termField("kind", "enum", "kind:preference", { values: MEMORY_KINDS }),
|
|
5556
|
-
termField("status", "enum", "status:proposed", { values: MEMORY_STATUSES }),
|
|
5557
|
-
termField("scope", "enum", "scope:work", { values: MEMORY_SCOPES }),
|
|
5558
|
-
termField("subject", "ref", 'subject:"person:42"'),
|
|
5559
|
-
termField("project", "kw", "project:SYH")
|
|
5560
|
-
]
|
|
5561
|
-
};
|
|
5562
|
-
var memoryItem = /* @__PURE__ */ __name(({ body, ...memory }) => ({
|
|
5563
|
-
ref: memory.ref,
|
|
5564
|
-
id: memory.id,
|
|
5565
|
-
kind: memory.kind,
|
|
5566
|
-
text: body,
|
|
5567
|
-
subject: memory.subject,
|
|
5568
|
-
subjectName: memory.subjectName,
|
|
5569
|
-
subjectIsOwner: memory.subjectIsOwner,
|
|
5570
|
-
project: memory.project,
|
|
5571
|
-
projectName: memory.projectName,
|
|
5572
|
-
author: memory.author,
|
|
5573
|
-
model: memory.model,
|
|
5574
|
-
confidence: memory.confidence,
|
|
5575
|
-
status: memory.status,
|
|
5576
|
-
scope: memory.scope,
|
|
5577
|
-
supersedes: memory.supersedes,
|
|
5578
|
-
evidence: memory.evidence,
|
|
5579
|
-
lastVerifiedAt: memory.lastVerifiedAt,
|
|
5580
|
-
sourceReview: memory.sourceReview,
|
|
5581
|
-
createdAt: memory.createdAt,
|
|
5582
|
-
updatedAt: memory.updatedAt
|
|
5583
|
-
}), "memoryItem");
|
|
5584
|
-
var listMemories = /* @__PURE__ */ __name(async (store, query, limit) => {
|
|
5585
|
-
const terms2 = queryTerms(query, MEMORY_QUERY, "memories list");
|
|
5586
|
-
const project = terms2.get("project");
|
|
5587
|
-
const filters = {
|
|
5588
|
-
...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
|
|
5589
|
-
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
5590
|
-
...terms2.has("scope") ? { scope: terms2.get("scope") } : {},
|
|
5591
|
-
...terms2.has("subject") ? { subject: terms2.get("subject") } : {},
|
|
5592
|
-
...project === void 0 ? {} : { project: await canonicalProject(store, project) }
|
|
5593
|
-
};
|
|
5594
|
-
return pageOf("memories list", limit, async (most) => (await store.memories.list({ ...filters, limit: most })).map(memoryItem));
|
|
5595
|
-
}, "listMemories");
|
|
5596
|
-
var SEARCH = { command: "search memories", guide: LIST_QUERY_GUIDE };
|
|
5597
|
-
var MEMORY_FIELDS = /* @__PURE__ */ new Set(["text", ...MEMORY_QUERY.fields.map(({ name: name2 }) => name2)]);
|
|
5598
|
-
var searchMemories = /* @__PURE__ */ __name((store, query, limit) => {
|
|
5599
|
-
const { root } = parseLucene(plainQuery(typedQuery(query), MEMORY_FIELDS), { ...SEARCH, defaultField: "text" });
|
|
5600
|
-
const clauses = [];
|
|
5601
|
-
if (root.kind === "predicate")
|
|
5602
|
-
clauses.push(root);
|
|
5603
|
-
else
|
|
5604
|
-
for (const { occur, node } of root.clauses) {
|
|
5605
|
-
if (occur !== "must" || node.kind !== "predicate")
|
|
5606
|
-
queryError("query.unsupported-operator", node.span, "join words and scope: with AND only", SEARCH);
|
|
5607
|
-
clauses.push(node);
|
|
5156
|
+
// dist/discovery/command.js
|
|
5157
|
+
var CONTRACT = 4;
|
|
5158
|
+
var commandsCommandDefinition = /* @__PURE__ */ __name((program, streams) => {
|
|
5159
|
+
annotate(program.command("commands"), { effects: NO_EFFECTS }).argument("[path...]", "one command, such as tags add").description(DISCOVERY_DESCRIPTIONS.commands).option("--json", "print JSON; --json=id,title keeps only those fields").action((path, options) => {
|
|
5160
|
+
const annotateAvailability = /* @__PURE__ */ __name((commands2) => commands2.map((info) => ({
|
|
5161
|
+
...info,
|
|
5162
|
+
availability: environmentOf(program).discoveryAvailability?.(info),
|
|
5163
|
+
commands: annotateAvailability(info.commands)
|
|
5164
|
+
})), "annotateAvailability");
|
|
5165
|
+
const plain = commandsDocument(program, { cli: "memo", version: VERSION, contract: CONTRACT });
|
|
5166
|
+
const document = { ...plain, commands: annotateAvailability(plain.commands) };
|
|
5167
|
+
const answer = path.length ? scoped(document, path) : document;
|
|
5168
|
+
if (options.json)
|
|
5169
|
+
createRenderer({ format: "json", color: false, streams }).result(answer);
|
|
5170
|
+
else {
|
|
5171
|
+
const found = path.length ? flatten(document.commands).find((item) => same(item.path, answer.scope)) : void 0;
|
|
5172
|
+
streams.data(commandsText(program, found ? [found] : document.commands, found?.path));
|
|
5608
5173
|
}
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5174
|
+
});
|
|
5175
|
+
}, "commandsCommandDefinition");
|
|
5176
|
+
var scoped = /* @__PURE__ */ __name((document, path) => {
|
|
5177
|
+
const all = flatten(document.commands);
|
|
5178
|
+
const found = all.find((item) => item.path.join(" ") === path.join(" "));
|
|
5179
|
+
if (!found)
|
|
5180
|
+
throw new CliError("not_found", "command path was not found");
|
|
5181
|
+
const inheritedOptions = all.filter((item) => item.path.length < path.length && item.path.every((word, index) => word === path[index])).filter((item) => item.options.length > 0).map((item) => ({ path: item.path, options: item.options }));
|
|
5182
|
+
return { ...document, scope: found.path, inherited_options: inheritedOptions, commands: [found] };
|
|
5183
|
+
}, "scoped");
|
|
5184
|
+
var same = /* @__PURE__ */ __name((a, b) => a.join(" ") === b?.join(" "), "same");
|
|
5185
|
+
var SECTIONS = [
|
|
5186
|
+
["context", "read"],
|
|
5187
|
+
["show", "read"],
|
|
5188
|
+
["notes", "read"],
|
|
5189
|
+
["notes add", "write"],
|
|
5190
|
+
["notes edit", "write"],
|
|
5191
|
+
["notes remove", "write"],
|
|
5192
|
+
["notes export", "write"],
|
|
5193
|
+
["sources", "read"],
|
|
5194
|
+
["sources add", "write"],
|
|
5195
|
+
["sources remove", "write"],
|
|
5196
|
+
["mail", "read"],
|
|
5197
|
+
["events", "read"],
|
|
5198
|
+
["agents", "read"],
|
|
5199
|
+
["answers", "read"],
|
|
5200
|
+
["memories", "write"],
|
|
5201
|
+
["facts", "write"],
|
|
5202
|
+
["actions", "write"],
|
|
5203
|
+
["review", "write"],
|
|
5204
|
+
["notes links", "organise"],
|
|
5205
|
+
["organizations", "organise"],
|
|
5206
|
+
["invoices", "organise"],
|
|
5207
|
+
["orders", "organise"],
|
|
5208
|
+
["deals", "organise"],
|
|
5209
|
+
["leads", "organise"],
|
|
5210
|
+
["pipelines", "organise"],
|
|
5211
|
+
["payments", "organise"],
|
|
5212
|
+
["products", "organise"],
|
|
5213
|
+
["contracts", "organise"],
|
|
5214
|
+
["subscriptions", "organise"],
|
|
5215
|
+
["wallets", "organise"],
|
|
5216
|
+
["transactions", "organise"],
|
|
5217
|
+
["records", "organise"],
|
|
5218
|
+
["projects", "organise"],
|
|
5219
|
+
["people", "organise"],
|
|
5220
|
+
["relationships", "organise"],
|
|
5221
|
+
["reminders", "organise"],
|
|
5222
|
+
["vocabulary", "organise"],
|
|
5223
|
+
["sync", "automate"],
|
|
5224
|
+
["jobs", "automate"],
|
|
5225
|
+
["digest", "automate"],
|
|
5226
|
+
["folders", "setup"],
|
|
5227
|
+
["config", "setup"]
|
|
5228
|
+
];
|
|
5229
|
+
var placeInSections = /* @__PURE__ */ __name((program) => {
|
|
5230
|
+
for (const [path, section2] of SECTIONS) {
|
|
5231
|
+
let command = program;
|
|
5232
|
+
for (const name2 of path.split(" "))
|
|
5233
|
+
command = command?.commands.find((child) => child.name() === name2);
|
|
5234
|
+
if (!command)
|
|
5235
|
+
throw new Error(`no command to place in a section: ${path}`);
|
|
5236
|
+
inSection(command, section2);
|
|
5621
5237
|
}
|
|
5622
|
-
|
|
5623
|
-
|
|
5238
|
+
}, "placeInSections");
|
|
5239
|
+
var commandsCommand = /* @__PURE__ */ __name((program, streams) => {
|
|
5240
|
+
customizeSharedCommand(sharedCommandTemplate(APP, "commands"), "Memo binds discovery to its command-local JSON renderer and scoped stored-data document format.", () => {
|
|
5241
|
+
commandsCommandDefinition(program, streams);
|
|
5242
|
+
addContractInfo(program, (value) => streams.data(JSON.stringify(value)));
|
|
5243
|
+
const command = program.commands.find((command2) => command2.name() === "commands");
|
|
5244
|
+
if (!command)
|
|
5245
|
+
throw new Error("discovery builder did not install its command");
|
|
5246
|
+
return command;
|
|
5247
|
+
}, SHELL_OVERRIDES.commands);
|
|
5248
|
+
}, "commandsCommand");
|
|
5624
5249
|
|
|
5625
|
-
// dist/
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5250
|
+
// dist/doctor/command.js
|
|
5251
|
+
import { existsSync as existsSync7, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
|
|
5252
|
+
import { homedir } from "node:os";
|
|
5253
|
+
import { dirname, join as join7 } from "node:path";
|
|
5254
|
+
var retiredMailAddresses = /* @__PURE__ */ __name((mail) => {
|
|
5255
|
+
const accounts = mail?.accounts;
|
|
5256
|
+
if (!Array.isArray(accounts))
|
|
5257
|
+
return [];
|
|
5258
|
+
return accounts.map((account2) => account2?.address).filter((address) => typeof address === "string");
|
|
5259
|
+
}, "retiredMailAddresses");
|
|
5260
|
+
var unitPaths = /* @__PURE__ */ __name((unit) => [...(/^ExecStart=(.*)$/m.exec(unit)?.[1] ?? "").matchAll(/"((?:[^"\\]|\\.)*)"/g)].map(([, path]) => path?.replace(/\\(["\\])/g, "$1") ?? "").filter((path) => path.startsWith("/")), "unitPaths");
|
|
5261
|
+
var diagnose = /* @__PURE__ */ __name(async (env, program, { deep = false } = {}) => {
|
|
5262
|
+
const problems = [];
|
|
5263
|
+
const paths = resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env });
|
|
5264
|
+
const { config, ...configReport } = inspectConfig(env, program);
|
|
5265
|
+
const files = privateFiles({
|
|
5266
|
+
files: [configReport.path, ...withSqliteSidecars(storePath(env))],
|
|
5267
|
+
// A folder the owner chose with MESSAGING_STORE may rightly be shared, like the home folder itself.
|
|
5268
|
+
dirs: [dirname(configReport.path), ...env.MESSAGING_STORE ? [] : [dirname(storePath(env))], runsDirFor(APP, env)]
|
|
5269
|
+
});
|
|
5270
|
+
const store = await storeSummary(env, { deep, command: "memo", version: APP.version });
|
|
5271
|
+
if ("damage" in store && store.damage)
|
|
5272
|
+
problems.push({ what: store.damage.what, fix: "memo store recover" });
|
|
5273
|
+
else if ("error" in store && store.error)
|
|
5274
|
+
problems.push({ what: `the store cannot be read: ${store.error}`, fix: "" });
|
|
5275
|
+
if ("writable" in store && store.writable === false)
|
|
5276
|
+
problems.push({ what: "the store is from a newer version than this memo", fix: "memo upgrade" });
|
|
5277
|
+
const folders = noteFolders(config.notes).map(({ path, id }) => ({
|
|
5278
|
+
path,
|
|
5279
|
+
exists: existsSync7(path),
|
|
5280
|
+
bound: id !== null
|
|
5281
|
+
}));
|
|
5282
|
+
for (const folder of folders) {
|
|
5283
|
+
if (!folder.exists)
|
|
5284
|
+
problems.push({
|
|
5285
|
+
what: `the notes folder ${folder.path} is missing`,
|
|
5286
|
+
fix: "connect its disk; if it moved, memo folders update <id> <new path>"
|
|
5287
|
+
});
|
|
5288
|
+
else if (!folder.bound)
|
|
5289
|
+
problems.push({
|
|
5290
|
+
what: `the notes folder ${folder.path} has no folder id`,
|
|
5291
|
+
fix: `memo folders add "${folder.path}"`
|
|
5292
|
+
});
|
|
5643
5293
|
}
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5294
|
+
if (config.mail !== void 0) {
|
|
5295
|
+
const addresses = retiredMailAddresses(config.mail);
|
|
5296
|
+
problems.push({
|
|
5297
|
+
what: `memo no longer imports mail, so the config's mail settings do nothing; the mail CLI syncs ${addresses.length ? addresses.join(", ") : "each mailbox"} into the same store (mail <profile> session start --address <address>, then mail <profile> sync), and the mail already stored stays`,
|
|
5298
|
+
fix: "memo config unset mail"
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
let textModel = DEFAULT_TEXT_MODEL;
|
|
5302
|
+
try {
|
|
5303
|
+
textModel = chosenTextModel(env).id;
|
|
5304
|
+
} catch (error) {
|
|
5305
|
+
problems.push({
|
|
5306
|
+
what: `the embedding model choice cannot be read: ${error instanceof Error ? error.message : String(error)}`,
|
|
5307
|
+
fix: `fix text_models in ${textModelsFile(env)}, or remove it to go back to ${DEFAULT_TEXT_MODEL}`
|
|
5308
|
+
});
|
|
5309
|
+
}
|
|
5310
|
+
const modelDir = join7(sharedModelsDirectory("text", env), textModel);
|
|
5311
|
+
const model = existsSync7(modelDir) && readdirSync5(modelDir).length > 0;
|
|
5312
|
+
const state = autoState(config);
|
|
5313
|
+
const unitFile = join7(env.XDG_CONFIG_HOME ?? join7(env.HOME ?? homedir(), ".config"), "systemd", "user", "memo-import.service");
|
|
5314
|
+
const unit = existsSync7(unitFile) ? readFileSync6(unitFile, "utf8") : void 0;
|
|
5315
|
+
const runs = unit ? unitPaths(unit) : [];
|
|
5316
|
+
const missing = runs.filter((path) => !existsSync7(path));
|
|
5317
|
+
const last = lastAutoRun(env);
|
|
5318
|
+
const failing = last && last.exitCode !== 0 ? { since: last.failingSince ?? last.at, runs: last.failures ?? 1, reason: last.reason ?? null } : null;
|
|
5319
|
+
if (state.enabled && !unit)
|
|
5320
|
+
problems.push({ what: "the timer is on in the config but not installed", fix: "memo jobs start" });
|
|
5321
|
+
if (missing.length > 0)
|
|
5322
|
+
problems.push({ what: `the timer runs a program that is gone: ${missing.join(", ")}`, fix: "memo jobs start" });
|
|
5323
|
+
if (failing)
|
|
5324
|
+
problems.push({ what: `the timer has failed ${failing.runs} runs since ${failing.since}`, fix: "memo jobs status" });
|
|
5325
|
+
const skills = SKILL_TARGETS.map((target) => {
|
|
5326
|
+
const path = skillPath(target, APP.appName, env);
|
|
5327
|
+
const version = existsSync7(path) ? skillVersion(readFileSync6(path, "utf8")) ?? "unknown" : null;
|
|
5328
|
+
return { target, path, version };
|
|
5329
|
+
});
|
|
5330
|
+
if (skills.some(({ version }) => version !== null && version !== VERSION))
|
|
5331
|
+
problems.push({ what: "an installed skill is from another memo version", fix: "memo skill install --for all" });
|
|
5332
|
+
return {
|
|
5333
|
+
memo: { version: VERSION, node: process.version, installed_by: installer() },
|
|
5334
|
+
config: configReport,
|
|
5335
|
+
state: paths.state,
|
|
5336
|
+
cache: paths.cache,
|
|
5337
|
+
store,
|
|
5338
|
+
notes: folders,
|
|
5339
|
+
search_model: { name: textModel, path: modelDir, present: model },
|
|
5340
|
+
timer: { enabled: state.enabled, every: state.every, unit: unit ? unitFile : null, runs, failing },
|
|
5341
|
+
skills,
|
|
5342
|
+
files: files.checked ? { ...files, problems: files.problems.map(({ path, mode, want }) => ({ path, mode, want })) } : files,
|
|
5343
|
+
problems,
|
|
5344
|
+
fixes: files.checked ? files.problems.map(({ fix }) => fix) : []
|
|
5345
|
+
};
|
|
5346
|
+
}, "diagnose");
|
|
5347
|
+
var yes = /* @__PURE__ */ __name((value) => value ? "yes" : "no", "yes");
|
|
5348
|
+
var fileLines = /* @__PURE__ */ __name((d, fixes) => d.files.checked ? d.files.problems.map(({ path, mode, want }, at) => `! ${path} is ${mode}, so others can read it; it should be ${want} \u2014 ${fixes[at]}`) : [], "fileLines");
|
|
5349
|
+
var onlineLine = /* @__PURE__ */ __name(({ version }) => version.latest === null ? "online npm could not be reached" : version.newer ? `online memo ${version.latest} is published (this is ${version.current}) \u2014 memo upgrade` : `online memo ${version.current} is the newest published`, "onlineLine");
|
|
5350
|
+
var doctorText = /* @__PURE__ */ __name((d, fixes = [], online) => [
|
|
5351
|
+
`memo ${d.memo.version} on Node ${d.memo.node}, installed by ${d.memo.installed_by}`,
|
|
5352
|
+
`config ${d.config.path}${d.config.found ? "" : " (none yet)"}`,
|
|
5353
|
+
`state ${d.state}`,
|
|
5354
|
+
`cache ${d.cache}`,
|
|
5355
|
+
`store ${d.store.path}${!d.store.exists ? " (none yet; the first memo sync makes it)" : "schema" in d.store ? ` (schema ${d.store.schema}, memo speaks ${d.store.speaks})` : ""}`,
|
|
5356
|
+
..."health" in d.store && d.store.health ? [
|
|
5357
|
+
`health ${d.store.health.ok ? "ok" : "DAMAGED"}, checked ${d.store.health.covers}${d.store.health.checked === "quick" ? " (memo doctor --deep reads every page)" : ""}`
|
|
5358
|
+
] : [],
|
|
5359
|
+
...d.notes.map((f) => `notes ${f.path} \u2014 exists ${yes(f.exists)}, folder id ${yes(f.bound)}`),
|
|
5360
|
+
`search ${d.search_model.name} ${d.search_model.present ? "present" : "not downloaded \u2014 search is by words"}`,
|
|
5361
|
+
`timer ${d.timer.enabled ? `on, every ${d.timer.every}` : "off"}`,
|
|
5362
|
+
...d.skills.map((s) => `skill ${s.path} ${s.version === null ? "(not installed)" : `(${s.version})`}`),
|
|
5363
|
+
...online ? [onlineLine(online)] : [],
|
|
5364
|
+
"",
|
|
5365
|
+
...d.problems.length + d.config.issues.length + fileLines(d, fixes).length === 0 ? ["nothing needs attention"] : [
|
|
5366
|
+
...d.config.issues.map(({ what, fix }) => `! ${what}${fix ? ` \u2014 ${fix}` : ""}`),
|
|
5367
|
+
...fileLines(d, fixes),
|
|
5368
|
+
...d.problems.map(({ what, fix }) => `! ${what}${fix ? ` \u2014 ${fix}` : ""}`)
|
|
5369
|
+
]
|
|
5370
|
+
].join("\n"), "doctorText");
|
|
5371
|
+
var sharedDoctor = sharedCommandTemplate(APP, "doctor");
|
|
5372
|
+
var ONLINE_FLAGS = "--online";
|
|
5373
|
+
var onlineText = sharedDoctor.options.find((option) => option.long === ONLINE_FLAGS)?.description ?? "";
|
|
5374
|
+
var onlineCheck = /* @__PURE__ */ __name(async () => {
|
|
5375
|
+
const started = Date.now();
|
|
5376
|
+
const newest = await latest();
|
|
5377
|
+
return {
|
|
5378
|
+
ok: true,
|
|
5379
|
+
duration_ms: Date.now() - started,
|
|
5380
|
+
version: { current: VERSION, latest: newest ?? null, newer: newest !== void 0 && isNewer(newest, VERSION) }
|
|
5381
|
+
};
|
|
5382
|
+
}, "onlineCheck");
|
|
5383
|
+
var doctorCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5384
|
+
const { print } = answers(program, streams, env);
|
|
5385
|
+
annotate(program.command("doctor"), { effects: REMOTE_READ }).description(sharedDoctor.description()).option(ONLINE_FLAGS, onlineText).option("--deep", DOCTOR_DEEP_OPTION).option("--json", "print JSON; --json=id,title keeps only those fields").addHelpText("after", "\nReads this computer only, unless --online: the config, the store, the notes folders, the search model, the timer and the agent skill, each problem with the command that fixes it. --online also asks npm whether a newer memo is published, and nothing else leaves this computer. Exits 1 when something other than the config file or a file mode needs attention; problems in the config file are listed in config.issues, and files or folders other users can read in files.problems, and neither changes the exit code.").action(async (options) => {
|
|
5386
|
+
const { fixes, ...diagnosis } = await diagnose(env, program, { deep: options.deep === true });
|
|
5387
|
+
const online = options.online ? await onlineCheck() : void 0;
|
|
5388
|
+
print(options.json, itemAnswer(online ? { ...diagnosis, online } : diagnosis), doctorText(diagnosis, fixes, online));
|
|
5389
|
+
if (options.json)
|
|
5390
|
+
for (const fix of fixes)
|
|
5391
|
+
streams.diagnostic(`to make it private: ${fix}`);
|
|
5392
|
+
if (diagnosis.problems.length > 0)
|
|
5393
|
+
process.exitCode = 1;
|
|
5394
|
+
});
|
|
5395
|
+
}, "doctorCommandDefinition");
|
|
5396
|
+
var doctorCommand = /* @__PURE__ */ __name((...args) => {
|
|
5397
|
+
customizeSharedCommand(sharedCommandTemplate(APP, "doctor"), "Memo diagnoses imported-data paths and stored account configuration without connecting to a messenger or querying a keyring.", () => {
|
|
5398
|
+
doctorCommandDefinition(...args);
|
|
5399
|
+
const command = args[0].commands.find((command2) => command2.name() === "doctor");
|
|
5400
|
+
if (!command)
|
|
5401
|
+
throw new Error("doctor builder did not install its command");
|
|
5402
|
+
return command;
|
|
5403
|
+
}, SHELL_OVERRIDES.doctor);
|
|
5404
|
+
}, "doctorCommand");
|
|
5653
5405
|
|
|
5654
|
-
// dist/
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
var
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
const tool = providerNamed(provider)?.command;
|
|
5665
|
-
const state = tool === void 0 ? void 0 : STATE[tool];
|
|
5666
|
-
return tool === void 0 || state === void 0 ? void 0 : { tool, ...state };
|
|
5667
|
-
}, "messengerToolOf");
|
|
5668
|
-
var syncProfileOf = /* @__PURE__ */ __name((value, previous = {}) => {
|
|
5669
|
-
const [tool, profile] = value.split("=", 2);
|
|
5670
|
-
const tools = Object.keys(STATE);
|
|
5671
|
-
if (!tool || !profile || !tools.includes(tool))
|
|
5672
|
-
throw new InvalidArgumentError(`<tool>=<profile>, where the tool is ${tools.join(", ")}: max=default`);
|
|
5673
|
-
if (previous[tool] !== void 0 && previous[tool] !== profile)
|
|
5674
|
-
throw new InvalidArgumentError(`one profile per tool; ${tool} is already ${previous[tool]}`);
|
|
5675
|
-
return { ...previous, [tool]: profile };
|
|
5676
|
-
}, "syncProfileOf");
|
|
5677
|
-
var accountsDir = /* @__PURE__ */ __name((tool, env) => join4(resolvePaths({ appName: tool.appName, prefix: tool.envPrefix, env }).state, "accounts"), "accountsDir");
|
|
5678
|
-
var signedInAccount = /* @__PURE__ */ __name((tool, profile, env) => {
|
|
5679
|
-
try {
|
|
5680
|
-
return JSON.parse(readFileSync5(join4(accountsDir(tool, env), `${profile}.json`), "utf8"))?.account;
|
|
5681
|
-
} catch {
|
|
5682
|
-
return void 0;
|
|
5683
|
-
}
|
|
5684
|
-
}, "signedInAccount");
|
|
5685
|
-
var profileFor = /* @__PURE__ */ __name((provider, account2, env, chosen = {}) => {
|
|
5686
|
-
const tool = messengerToolOf(provider);
|
|
5687
|
-
if (!tool)
|
|
5406
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/calendar/sync.js
|
|
5407
|
+
var DAY6 = 864e5;
|
|
5408
|
+
var SLOTS_EVERY = 7 * DAY6;
|
|
5409
|
+
var isWindow = /* @__PURE__ */ __name((value) => typeof value?.from === "number" && typeof value.to === "number", "isWindow");
|
|
5410
|
+
var isToken = /* @__PURE__ */ __name((value) => value === null || typeof value === "string", "isToken");
|
|
5411
|
+
var roundOf = /* @__PURE__ */ __name((value) => {
|
|
5412
|
+
if (value === null || value === void 0)
|
|
5413
|
+
return null;
|
|
5414
|
+
const round = value;
|
|
5415
|
+
if (typeof round.full !== "boolean" || !isToken(round.from) || !isWindow(round.window) || typeof round.startedAt !== "number" || typeof round.reset !== "boolean" || !isToken(round.page) || typeof round.listed !== "boolean" || !isToken(round.next) || !Array.isArray(round.series) || round.series.some((id) => typeof id !== "string") || round.everySeries !== void 0 && typeof round.everySeries !== "boolean")
|
|
5688
5416
|
return void 0;
|
|
5689
|
-
const
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5417
|
+
const { full, from, window, startedAt, reset, page, listed: listed2, next, series, everySeries, unchanged } = round;
|
|
5418
|
+
return {
|
|
5419
|
+
full,
|
|
5420
|
+
from,
|
|
5421
|
+
window,
|
|
5422
|
+
startedAt,
|
|
5423
|
+
reset,
|
|
5424
|
+
page,
|
|
5425
|
+
listed: listed2,
|
|
5426
|
+
next,
|
|
5427
|
+
series,
|
|
5428
|
+
...everySeries === false ? { everySeries } : {},
|
|
5429
|
+
...unchanged === true ? { unchanged } : {}
|
|
5430
|
+
};
|
|
5431
|
+
}, "roundOf");
|
|
5432
|
+
var parseCalendarCursor = /* @__PURE__ */ __name((value) => {
|
|
5433
|
+
if (value === null)
|
|
5434
|
+
return null;
|
|
5435
|
+
try {
|
|
5436
|
+
const cursor = JSON.parse(value);
|
|
5437
|
+
if (cursor?.v !== 1 && cursor?.v !== 2 || !isToken(cursor.token) || typeof cursor.fullAt !== "number" || !isWindow(cursor.window))
|
|
5438
|
+
return null;
|
|
5439
|
+
const { token, window, fullAt } = cursor;
|
|
5440
|
+
if (cursor.v === 1)
|
|
5441
|
+
return { v: 2, token, window, fullAt, updatedAt: null, done: 0, round: null };
|
|
5442
|
+
const round = roundOf(cursor.round);
|
|
5443
|
+
if (round === void 0 || cursor.updatedAt !== null && typeof cursor.updatedAt !== "number" || typeof cursor.done !== "number")
|
|
5444
|
+
return null;
|
|
5704
5445
|
return {
|
|
5705
|
-
|
|
5706
|
-
|
|
5446
|
+
v: 2,
|
|
5447
|
+
token,
|
|
5448
|
+
window,
|
|
5449
|
+
fullAt,
|
|
5450
|
+
updatedAt: cursor.updatedAt ?? null,
|
|
5451
|
+
done: cursor.done,
|
|
5452
|
+
round,
|
|
5453
|
+
...cursor.restored === true ? { restored: true } : {},
|
|
5454
|
+
...typeof cursor.slotsTo === "number" ? { slotsTo: cursor.slotsTo } : {}
|
|
5707
5455
|
};
|
|
5708
|
-
return { why: `no ${tool.tool} profile here is signed in to account ${account2}; profiles: ${all}`, profiles: [] };
|
|
5709
|
-
}, "profileFor");
|
|
5710
|
-
var onPath = /* @__PURE__ */ __name((name2, env) => (env.PATH ?? "").split(delimiter).filter(Boolean).map((dir) => join4(dir, name2)).find((path) => {
|
|
5711
|
-
try {
|
|
5712
|
-
return statSync2(path).isFile();
|
|
5713
5456
|
} catch {
|
|
5714
|
-
return
|
|
5457
|
+
return null;
|
|
5715
5458
|
}
|
|
5716
|
-
}
|
|
5717
|
-
var
|
|
5718
|
-
const
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5459
|
+
}, "parseCalendarCursor");
|
|
5460
|
+
var calendarStatus = /* @__PURE__ */ __name(async (store, accountId, { profile, now }) => {
|
|
5461
|
+
const items = [];
|
|
5462
|
+
for (const calendar of await store.calendars(accountId)) {
|
|
5463
|
+
if (!calendar.synced || calendar.deletedAt !== null)
|
|
5464
|
+
continue;
|
|
5465
|
+
const cursor = parseCalendarCursor(await store.cursor(calendar.id));
|
|
5466
|
+
const progress = progressOf({
|
|
5467
|
+
job: `calendar ${calendar.id}`,
|
|
5468
|
+
profile,
|
|
5469
|
+
done: cursor?.done ?? 0,
|
|
5470
|
+
complete: cursor !== null && cursor.round === null,
|
|
5471
|
+
...cursor?.updatedAt == null ? {} : { updatedAt: new Date(cursor.updatedAt).toISOString() },
|
|
5472
|
+
now: new Date(now)
|
|
5473
|
+
});
|
|
5474
|
+
items.push({
|
|
5475
|
+
calendar_id: String(calendar.id),
|
|
5476
|
+
external_id: calendar.externalId,
|
|
5477
|
+
title: calendar.title,
|
|
5478
|
+
round: cursor?.round ? cursor.round.full ? "full" : "changes" : null,
|
|
5479
|
+
...progress,
|
|
5480
|
+
line: progressLine(progress)
|
|
5481
|
+
});
|
|
5482
|
+
}
|
|
5483
|
+
return { items, page: 1, limit: Math.max(1, items.length), hasMore: false };
|
|
5484
|
+
}, "calendarStatus");
|
|
5485
|
+
|
|
5486
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/calendar/feeds.js
|
|
5487
|
+
var FEED_LIMITS = { maxBytes: 10 * 1024 * 1024, timeoutMs: 3e4, redirects: 5 };
|
|
5488
|
+
|
|
5489
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/calendar/reads.js
|
|
5490
|
+
var LIST = "events list";
|
|
5491
|
+
var EVENT_TYPES = [
|
|
5492
|
+
"default",
|
|
5493
|
+
"out-of-office",
|
|
5494
|
+
"focus",
|
|
5495
|
+
"working-location",
|
|
5496
|
+
"birthday",
|
|
5497
|
+
"from-mail",
|
|
5498
|
+
"call"
|
|
5499
|
+
];
|
|
5500
|
+
var oneSided = /* @__PURE__ */ __name((field2, example) => (node) => {
|
|
5501
|
+
if (node.operator !== "range" || node.upper !== "*")
|
|
5502
|
+
queryError("query.unsupported-operator", node.span, `${field2} takes only an earliest moment, such as ${example}`, {
|
|
5503
|
+
command: LIST,
|
|
5504
|
+
guide: LIST_QUERY_GUIDE
|
|
5505
|
+
});
|
|
5506
|
+
}, "oneSided");
|
|
5507
|
+
var EVENTS_QUERY = {
|
|
5508
|
+
entity: "event",
|
|
5509
|
+
backend: "native",
|
|
5510
|
+
fields: queryFieldsOf(event, {
|
|
5511
|
+
native: ["id", "starts_at", "ends_at", "changed_at", "overlapping", "calendar", "person", "event_type"],
|
|
5512
|
+
negatable: ["event_type"],
|
|
5513
|
+
relations: {
|
|
5514
|
+
event_type: {
|
|
5515
|
+
type: "enum",
|
|
5516
|
+
values: EVENT_TYPES,
|
|
5517
|
+
example: "event_type:default",
|
|
5518
|
+
relation: "events with a copy of this kind; -event_type:<kind> leaves out events with one"
|
|
5519
|
+
},
|
|
5520
|
+
calendar: {
|
|
5521
|
+
type: "kw",
|
|
5522
|
+
example: "calendar:3",
|
|
5523
|
+
relation: "one calendar, by its id, the provider's id or its title"
|
|
5524
|
+
},
|
|
5525
|
+
person: {
|
|
5526
|
+
type: "kw",
|
|
5527
|
+
example: "person:ana@example.com",
|
|
5528
|
+
relation: "events one person attends: an address, or a person id from search"
|
|
5529
|
+
}
|
|
5530
|
+
},
|
|
5531
|
+
examples: {
|
|
5532
|
+
id: "id:42",
|
|
5533
|
+
starts_at: "starts_at:[2026-11-02 TO 2026-11-07}",
|
|
5534
|
+
ends_at: "ends_at>=2026-11-02",
|
|
5535
|
+
changed_at: "changed_at>=2026-10-01",
|
|
5536
|
+
overlapping: "overlapping:true"
|
|
5537
|
+
},
|
|
5538
|
+
validate: {
|
|
5539
|
+
ends_at: oneSided("ends_at", "ends_at>=2026-11-02; for the latest, write starts_at<2026-11-07"),
|
|
5540
|
+
changed_at: oneSided("changed_at", "changed_at>=2026-10-01")
|
|
5757
5541
|
}
|
|
5542
|
+
}).map((field2) => field2.native ? {
|
|
5543
|
+
...field2,
|
|
5544
|
+
operators: field2.type === "time" ? ["term", "range"] : field2.type === "bool" ? ["term"] : ["term", "phrase"]
|
|
5545
|
+
} : field2)
|
|
5546
|
+
};
|
|
5547
|
+
var nameOf2 = /* @__PURE__ */ __name(({ provider, account: account2 }) => `${provider}:${account2}`, "nameOf");
|
|
5548
|
+
var accountsMeta = /* @__PURE__ */ __name(async (store, accounts, skipped, now) => {
|
|
5549
|
+
const issues = [...skipped];
|
|
5550
|
+
for (const { id, key } of accounts) {
|
|
5551
|
+
if (isImportedProvider(key.provider))
|
|
5552
|
+
continue;
|
|
5553
|
+
const { items } = await calendarStatus(store, id, { profile: nameOf2(key), now });
|
|
5554
|
+
if (items.length === 0)
|
|
5555
|
+
issues.push({ code: "not_found", reason: "calendar.unsynced", source: nameOf2(key) });
|
|
5556
|
+
else if (items.some(({ state }) => state !== "complete"))
|
|
5557
|
+
issues.push({ code: "not_found", reason: "calendar.sync-incomplete", source: nameOf2(key) });
|
|
5758
5558
|
}
|
|
5759
|
-
const short = onPath(tool.tool, env);
|
|
5760
|
-
if (!short)
|
|
5761
|
-
return void 0;
|
|
5762
|
-
const mark = `@wirecat/${tool.appName}`;
|
|
5763
|
-
const real = realpathSync(short);
|
|
5764
|
-
if (real.includes(`/${mark}/`))
|
|
5765
|
-
return short;
|
|
5766
|
-
return statSync2(real).size < 65536 && readFileSync5(real, "utf8").includes(mark) ? short : void 0;
|
|
5767
|
-
}, "binaryOf");
|
|
5768
|
-
var answerOf = /* @__PURE__ */ __name((stdout) => {
|
|
5769
|
-
try {
|
|
5770
|
-
return JSON.parse(stdout.trim().split("\n").at(-1) ?? "");
|
|
5771
|
-
} catch {
|
|
5772
|
-
return {};
|
|
5773
|
-
}
|
|
5774
|
-
}, "answerOf");
|
|
5775
|
-
var MARGIN_MS = 5e3;
|
|
5776
|
-
var messengerFetcher = /* @__PURE__ */ __name(({ env, note, chosen = {}, run = runChild, now = Date.now }) => {
|
|
5777
|
-
const binaries = /* @__PURE__ */ new Map();
|
|
5778
5559
|
return {
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
return { state: "failed", reason: `no WireCat messenger CLI syncs ${account2.provider}` };
|
|
5783
|
-
const found = profileFor(account2.provider, account2.account, env, chosen);
|
|
5784
|
-
if (!found || !("profile" in found))
|
|
5785
|
-
return { state: "failed", reason: found?.why ?? "no profile" };
|
|
5786
|
-
if (!binaries.has(tool.tool))
|
|
5787
|
-
binaries.set(tool.tool, binaryOf(account2.provider, env, run));
|
|
5788
|
-
const bin = await binaries.get(tool.tool);
|
|
5789
|
-
if (!bin)
|
|
5790
|
-
return { state: "failed", reason: `${tool.tool} is not installed, or the one on PATH is not WireCat's` };
|
|
5791
|
-
const seconds = Math.max(1, Math.floor((until - now() - MARGIN_MS) / 1e3));
|
|
5792
|
-
const args = [
|
|
5793
|
-
found.profile,
|
|
5794
|
-
"messages",
|
|
5795
|
-
"sync",
|
|
5796
|
-
"--since-time",
|
|
5797
|
-
new Date(after).toISOString(),
|
|
5798
|
-
"--limit",
|
|
5799
|
-
"1000000",
|
|
5800
|
-
"--timeout",
|
|
5801
|
-
`${seconds}s`,
|
|
5802
|
-
"--json",
|
|
5803
|
-
chatId
|
|
5804
|
-
];
|
|
5805
|
-
const done = await run(bin, args, {
|
|
5806
|
-
env,
|
|
5807
|
-
signal,
|
|
5808
|
-
onStderr: /* @__PURE__ */ __name((line3) => {
|
|
5809
|
-
if (!isEvent(line3))
|
|
5810
|
-
note(`${tool.tool}: ${line3}`);
|
|
5811
|
-
}, "onStderr")
|
|
5812
|
-
});
|
|
5813
|
-
const answer = answerOf(done.stdout);
|
|
5814
|
-
if (done.code !== 0) {
|
|
5815
|
-
const why = answer.error?.message?.split("\n")[0];
|
|
5816
|
-
const code = answer.error?.code ?? `exit ${done.code ?? "signal"}`;
|
|
5817
|
-
return {
|
|
5818
|
-
state: "partial",
|
|
5819
|
-
reason: `${tool.tool} ${found.profile} messages sync: ${code}${why ? ` \u2014 ${why}` : ""}`
|
|
5820
|
-
};
|
|
5821
|
-
}
|
|
5822
|
-
const item = answer.item ?? {};
|
|
5823
|
-
if (item.issue?.code)
|
|
5824
|
-
return { state: "partial", reason: item.issue.code };
|
|
5825
|
-
if (item.stopped || signal.aborted)
|
|
5826
|
-
return { state: "partial", reason: "fetch-budget" };
|
|
5827
|
-
return item.complete || item.reached_since ? { state: "complete" } : { state: "partial", reason: "limit" };
|
|
5828
|
-
}, "fetch")
|
|
5560
|
+
accounts: accounts.map(({ key }) => nameOf2(key)),
|
|
5561
|
+
complete: issues.length === 0,
|
|
5562
|
+
...issues.length ? { issues } : {}
|
|
5829
5563
|
};
|
|
5830
|
-
}, "
|
|
5831
|
-
var isEvent = /* @__PURE__ */ __name((line3) => {
|
|
5832
|
-
if (!line3.startsWith("{"))
|
|
5833
|
-
return false;
|
|
5834
|
-
try {
|
|
5835
|
-
return typeof JSON.parse(line3)?.event === "string";
|
|
5836
|
-
} catch {
|
|
5837
|
-
return false;
|
|
5838
|
-
}
|
|
5839
|
-
}, "isEvent");
|
|
5840
|
-
var chatCommand = /* @__PURE__ */ __name((chat, words, env, chosen) => {
|
|
5841
|
-
const tool = messengerToolOf(chat.provider);
|
|
5842
|
-
if (!tool)
|
|
5843
|
-
return null;
|
|
5844
|
-
const found = profileFor(chat.provider, chat.account, env, chosen);
|
|
5845
|
-
const line3 = /* @__PURE__ */ __name((profile) => `${tool.tool} ${profile} ${words}`, "line");
|
|
5846
|
-
if (found && "profile" in found)
|
|
5847
|
-
return { command: line3(found.profile) };
|
|
5848
|
-
return { command: null, line: line3("<profile>"), why: found?.why ?? "no profile" };
|
|
5849
|
-
}, "chatCommand");
|
|
5850
|
-
var chatSync = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => (
|
|
5851
|
-
// A negative group id needs no `--`: no WireCat CLI has a digit short option.
|
|
5852
|
-
chatCommand(chat, `messages sync ${chat.chat} --since-time ${since}`, env, chosen)
|
|
5853
|
-
), "chatSync");
|
|
5854
|
-
var chatRead = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => chatCommand(chat, `messages list --compact ${chat.chat} "date>=${since}"`, env, chosen), "chatRead");
|
|
5855
|
-
var syncHint = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => {
|
|
5856
|
-
const sync = chatSync(chat, since, env, chosen);
|
|
5857
|
-
if (!sync)
|
|
5858
|
-
return null;
|
|
5859
|
-
return sync.command ?? `${sync.line} (${sync.why})`;
|
|
5860
|
-
}, "syncHint");
|
|
5564
|
+
}, "accountsMeta");
|
|
5861
5565
|
|
|
5862
|
-
// dist/
|
|
5863
|
-
var
|
|
5864
|
-
var
|
|
5865
|
-
var
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5566
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.618.0_@wirecat+cli-base@0.91.0_commander@15.0.0_esbuild@0.28.2_type_a1c6dd927639f1a41fe5f9c53e24865e/node_modules/@wirecat/cli-core/dist/calendar/writer.js
|
|
5567
|
+
var EVENTS_NOTIFY_KEY = "events.notify";
|
|
5568
|
+
var EVENTS_DELETE_SERIES_KEY = "events.delete.series";
|
|
5569
|
+
var EVENTS_REMIND_HOOK_KEY = "events.remind.hook";
|
|
5570
|
+
var CALENDAR_WRITE_DEFAULTS = {
|
|
5571
|
+
"events.create": "allow",
|
|
5572
|
+
// One import writes a whole file of events, and may change events the calendar already holds under their UIDs.
|
|
5573
|
+
"events.import": "ask",
|
|
5574
|
+
"events.update": "allow",
|
|
5575
|
+
"events.respond": "allow",
|
|
5576
|
+
"events.move": "allow",
|
|
5577
|
+
"events.delete": "ask",
|
|
5578
|
+
[EVENTS_DELETE_SERIES_KEY]: "deny",
|
|
5579
|
+
[EVENTS_NOTIFY_KEY]: "deny",
|
|
5580
|
+
// Not ask: `--yes` answers ask, and anything that can type a gcal command can add it.
|
|
5581
|
+
[EVENTS_REMIND_HOOK_KEY]: "deny"
|
|
5870
5582
|
};
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
var
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
}
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5583
|
+
|
|
5584
|
+
// dist/events/events.js
|
|
5585
|
+
var LIST2 = "events list";
|
|
5586
|
+
var EVENT_TYPES2 = [
|
|
5587
|
+
"default",
|
|
5588
|
+
"out-of-office",
|
|
5589
|
+
"focus",
|
|
5590
|
+
"working-location",
|
|
5591
|
+
"birthday",
|
|
5592
|
+
"from-mail",
|
|
5593
|
+
"call"
|
|
5594
|
+
];
|
|
5595
|
+
var EVENTS_QUERY2 = {
|
|
5596
|
+
entity: "event",
|
|
5597
|
+
backend: "native",
|
|
5598
|
+
fields: [
|
|
5599
|
+
nativeField({
|
|
5600
|
+
name: "starts_at",
|
|
5601
|
+
type: "time",
|
|
5602
|
+
operators: ["term", "range"],
|
|
5603
|
+
example: "starts_at:[2026-11-02 TO 2026-11-07}"
|
|
5604
|
+
}),
|
|
5605
|
+
termField("account", "kw", 'account:"phone:pixel"', {
|
|
5606
|
+
relation: "one calendar account, provider:account, or every account of a provider"
|
|
5607
|
+
}),
|
|
5608
|
+
termField("calendar", "kw", "calendar:Calls", { relation: "one calendar, by its id or its title" }),
|
|
5609
|
+
termField("event_type", "enum", "event_type:call", {
|
|
5610
|
+
values: EVENT_TYPES2,
|
|
5611
|
+
relation: "events with a copy of this kind; a phone's imported calls are call"
|
|
5612
|
+
})
|
|
5613
|
+
]
|
|
5614
|
+
};
|
|
5615
|
+
var RECENT_DAYS = 30;
|
|
5616
|
+
var AHEAD_DAYS = 7;
|
|
5617
|
+
var EVENTS_NOTE = `
|
|
5618
|
+
Every calendar account in the store is read, phone imports included. Without starts_at: the last ${RECENT_DAYS} days and the next ${AHEAD_DAYS}. Latest start first.`;
|
|
5619
|
+
var UNTRUSTED = ["title", "description", "location", "in"];
|
|
5620
|
+
var readAccounts = /* @__PURE__ */ __name(async (store) => {
|
|
5621
|
+
const held = await calendarAccounts(store);
|
|
5622
|
+
const stored = await store.accounts.storedAccounts();
|
|
5623
|
+
const read = [];
|
|
5624
|
+
for (const key of held) {
|
|
5625
|
+
const one2 = stored.find(({ provider, account: account2 }) => provider === key.provider && account2 === key.account);
|
|
5626
|
+
if (one2)
|
|
5627
|
+
read.push({ id: one2.id, key, calendars: await store.calendar.calendars(one2.id) });
|
|
5910
5628
|
}
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
scheduled: runs.length > 0,
|
|
5941
|
-
serving: serving.some((profile) => mine.has(profile)),
|
|
5942
|
-
known: mine.size > 0
|
|
5943
|
-
};
|
|
5629
|
+
return read;
|
|
5630
|
+
}, "readAccounts");
|
|
5631
|
+
var narrowed = /* @__PURE__ */ __name((accounts, value) => {
|
|
5632
|
+
const chosen = accounts.filter(({ key }) => accountName(key) === value || key.provider === value);
|
|
5633
|
+
if (chosen.length === 0)
|
|
5634
|
+
throw new CliError("not_found", `account:${value} names no calendar account \u2014 the store holds ${accounts.map(({ key }) => accountName(key)).join(", ") || "none"}`, { reason: "events.account-unknown" });
|
|
5635
|
+
return chosen;
|
|
5636
|
+
}, "narrowed");
|
|
5637
|
+
var calendarOf = /* @__PURE__ */ __name((accounts, value) => {
|
|
5638
|
+
const all = accounts.flatMap((account2) => account2.calendars.map((calendar) => ({ account: account2, calendar })));
|
|
5639
|
+
const byId = all.filter(({ calendar }) => String(calendar.id) === value);
|
|
5640
|
+
const found = byId.length ? byId : all.filter(({ calendar }) => calendar.title === value);
|
|
5641
|
+
if (found.length === 1)
|
|
5642
|
+
return found[0];
|
|
5643
|
+
if (found.length === 0)
|
|
5644
|
+
throw new CliError("not_found", `calendar:${value} names no calendar in the accounts read`);
|
|
5645
|
+
throw new CliError("validation_error", `calendar:${value} names ${found.length} calendars; give one by its id: ` + found.map(({ account: account2, calendar }) => `calendar:${calendar.id} (${accountName(account2.key)})`).join(", "));
|
|
5646
|
+
}, "calendarOf");
|
|
5647
|
+
var localDate2 = /* @__PURE__ */ __name((at, zone) => new Intl.DateTimeFormat("en-CA", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" }).format(at), "localDate");
|
|
5648
|
+
var plusDays = /* @__PURE__ */ __name((date, days2) => {
|
|
5649
|
+
const [year, month, day2] = date.split("-").map(Number);
|
|
5650
|
+
return new Date(Date.UTC(year, month - 1, day2 + days2)).toISOString().slice(0, 10);
|
|
5651
|
+
}, "plusDays");
|
|
5652
|
+
var midnight = /* @__PURE__ */ __name((date, zone) => dayBoundary(date, zone, false, { start: 0, end: date.length }), "midnight");
|
|
5653
|
+
var startsWindow = /* @__PURE__ */ __name((node, zone, now) => {
|
|
5654
|
+
const range = node.operator === "range" ? dateRange(node.value, node.upper ?? "*", node.lower_inclusive !== false, node.upper_inclusive !== false, zone, node.span, now) : dateRange(node.value, node.value, true, true, zone, node.span, now);
|
|
5655
|
+
return {
|
|
5656
|
+
...range.lower === void 0 ? {} : { lower: range.lower_inclusive ? range.lower : range.lower + 1 },
|
|
5657
|
+
...range.upper === void 0 ? {} : { upper: range.upper_inclusive ? range.upper + 1 : range.upper }
|
|
5944
5658
|
};
|
|
5945
|
-
}, "
|
|
5946
|
-
var
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
return void 0;
|
|
5955
|
-
if (!sync.serving && sync.runs.length > 0 && sync.runs.every((run) => run.exitCode !== 0)) {
|
|
5956
|
-
const first = [...sync.runs].sort((a, b) => (a.failingSince ?? a.at).localeCompare(b.failingSince ?? b.at))[0];
|
|
5957
|
-
const since = first?.failingSince ?? first?.at ?? new Date(now).toISOString();
|
|
5958
|
-
return {
|
|
5959
|
-
reason: "sync-failed",
|
|
5960
|
-
since,
|
|
5961
|
-
staleHours: hours(Date.parse(since), now),
|
|
5962
|
-
...first?.reason ? { failure: first.reason } : {}
|
|
5963
|
-
};
|
|
5659
|
+
}, "startsWindow");
|
|
5660
|
+
var dated = /* @__PURE__ */ __name((filter, zone) => {
|
|
5661
|
+
if (filter.from !== void 0)
|
|
5662
|
+
filter.fromDate = localDate2(filter.from, zone);
|
|
5663
|
+
if (filter.to !== void 0)
|
|
5664
|
+
filter.toDate = plusDays(localDate2(filter.to - 1, zone), 1);
|
|
5665
|
+
if (filter.startsFrom !== void 0) {
|
|
5666
|
+
const date = localDate2(filter.startsFrom, zone);
|
|
5667
|
+
filter.startsFromDate = midnight(date, zone) < filter.startsFrom ? plusDays(date, 1) : date;
|
|
5964
5668
|
}
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5669
|
+
return filter;
|
|
5670
|
+
}, "dated");
|
|
5671
|
+
var windowMeta = /* @__PURE__ */ __name((filter, zone) => {
|
|
5672
|
+
const since = filter.startsFrom ?? filter.from;
|
|
5673
|
+
return {
|
|
5674
|
+
timezone: zone,
|
|
5675
|
+
window: {
|
|
5676
|
+
...since === void 0 ? {} : { since: new Date(since).toISOString() },
|
|
5677
|
+
...filter.to === void 0 ? {} : { until: new Date(filter.to - 1).toISOString() }
|
|
5678
|
+
}
|
|
5679
|
+
};
|
|
5680
|
+
}, "windowMeta");
|
|
5681
|
+
var rowOf = /* @__PURE__ */ __name((details, accounts) => {
|
|
5682
|
+
const live = details.entries.filter(({ deletedAt }) => deletedAt === null);
|
|
5683
|
+
const copies = live.length ? live : details.entries;
|
|
5684
|
+
const held = accounts.flatMap((account2) => account2.calendars.filter(({ id }) => copies.some(({ calendarId }) => calendarId === id)).map((calendar) => ({ account: accountName(account2.key), calendar: calendar.title ?? String(calendar.id) })));
|
|
5685
|
+
return {
|
|
5686
|
+
...eventItem(details.event),
|
|
5687
|
+
ref: `event:${details.event.id}`,
|
|
5688
|
+
event_type: copies.find(({ eventType }) => eventType !== null)?.eventType ?? "default",
|
|
5689
|
+
accounts: [...new Set(held.map(({ account: account2 }) => account2))],
|
|
5690
|
+
in: held.map(({ account: account2, calendar }) => `${account2}/${calendar}`).join(", "),
|
|
5691
|
+
untrusted: UNTRUSTED
|
|
5692
|
+
};
|
|
5693
|
+
}, "rowOf");
|
|
5694
|
+
var listEvents = /* @__PURE__ */ __name(async (store, words, limit, { now = Date.now(), zone = timezoneOf() } = {}) => {
|
|
5695
|
+
const terms2 = nativeTerms(listQuery(typedQuery(words), EVENTS_QUERY2, LIST2), LIST2);
|
|
5696
|
+
const every = await readAccounts(store);
|
|
5697
|
+
const account2 = terms2.get("account");
|
|
5698
|
+
let accounts = account2 ? narrowed(every, account2.value) : every;
|
|
5699
|
+
const filter = { newest: true };
|
|
5700
|
+
const calendar = terms2.get("calendar");
|
|
5701
|
+
if (calendar) {
|
|
5702
|
+
const found = calendarOf(accounts, calendar.value);
|
|
5703
|
+
accounts = [found.account];
|
|
5704
|
+
filter.calendarId = found.calendar.id;
|
|
5970
5705
|
}
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5706
|
+
const kind = terms2.get("event_type");
|
|
5707
|
+
if (kind)
|
|
5708
|
+
filter.eventType = kind.value.toLowerCase();
|
|
5709
|
+
const starts = terms2.get("starts_at");
|
|
5710
|
+
if (starts) {
|
|
5711
|
+
const { lower, upper } = startsWindow(starts, zone, now);
|
|
5712
|
+
if (lower !== void 0)
|
|
5713
|
+
filter.startsFrom = lower;
|
|
5714
|
+
if (upper !== void 0)
|
|
5715
|
+
filter.to = upper;
|
|
5716
|
+
} else {
|
|
5717
|
+
const today2 = localDate2(now, zone);
|
|
5718
|
+
filter.from = midnight(plusDays(today2, -RECENT_DAYS), zone);
|
|
5719
|
+
filter.to = midnight(plusDays(today2, AHEAD_DAYS + 1), zone);
|
|
5720
|
+
}
|
|
5721
|
+
dated(filter, zone);
|
|
5722
|
+
const read = accounts.map(({ id, key }) => ({ id, key }));
|
|
5723
|
+
const events = read.length ? await store.calendar.events({ ...filter, accountIds: read.map(({ id }) => id), limit: limit + 1 }) : [];
|
|
5724
|
+
const rows = [];
|
|
5725
|
+
for (const event2 of events.slice(0, limit)) {
|
|
5726
|
+
const details = await store.calendar.event(event2.id);
|
|
5727
|
+
if (details)
|
|
5728
|
+
rows.push(rowOf(details, accounts));
|
|
5729
|
+
}
|
|
5730
|
+
const body = listAnswer(LIST2, { items: rows, limit, has_more: events.length > limit });
|
|
5731
|
+
body.meta = {
|
|
5732
|
+
...body.meta,
|
|
5733
|
+
...await accountsMeta(store.calendar, read, [], now),
|
|
5734
|
+
...windowMeta(filter, zone)
|
|
5735
|
+
};
|
|
5736
|
+
return body;
|
|
5737
|
+
}, "listEvents");
|
|
5738
|
+
var showEvent = /* @__PURE__ */ __name(async (store, reference2) => {
|
|
5739
|
+
const text3 = reference2.replace(/^event:/u, "");
|
|
5740
|
+
if (!/^[1-9]\d*$/u.test(text3))
|
|
5741
|
+
throw new CliError("validation_error", "an event is event:<id>");
|
|
5742
|
+
const details = await store.calendar.event(Number(text3));
|
|
5743
|
+
const accounts = await readAccounts(store);
|
|
5744
|
+
const row = details && rowOf(details, accounts);
|
|
5745
|
+
if (!details || !row?.accounts.length)
|
|
5746
|
+
throw new CliError("not_found", `no event ${text3} in any calendar account`);
|
|
5747
|
+
return {
|
|
5748
|
+
...row,
|
|
5749
|
+
attendees: details.participants.map(({ email, name: name2, response, organizer }) => ({
|
|
5750
|
+
email,
|
|
5751
|
+
name: name2,
|
|
5752
|
+
response,
|
|
5753
|
+
organizer
|
|
5754
|
+
})),
|
|
5755
|
+
untrusted: [...UNTRUSTED, "attendees.name"]
|
|
5756
|
+
};
|
|
5757
|
+
}, "showEvent");
|
|
5758
|
+
var accountsLine = /* @__PURE__ */ __name((accounts) => accounts.length ? `calendar accounts read: ${accounts.join(", ")}` : "no calendar account in the store", "accountsLine");
|
|
5978
5759
|
|
|
5979
|
-
// dist/
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5760
|
+
// dist/events/command.js
|
|
5761
|
+
var upTo1000 = /* @__PURE__ */ __name((value) => {
|
|
5762
|
+
const number2 = Number(value);
|
|
5763
|
+
if (!Number.isInteger(number2) || number2 < 1 || number2 > 1e3)
|
|
5764
|
+
throw new InvalidArgumentError("a whole number, 1 to 1000");
|
|
5765
|
+
return number2;
|
|
5766
|
+
}, "upTo1000");
|
|
5767
|
+
var eventsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5768
|
+
const { print } = answers(program, streams, env);
|
|
5769
|
+
const events = program.command("events").description("calendar events of every account in the store, phone calls included").summary("calendar events and phone calls of every account");
|
|
5770
|
+
withQuery(annotate(events.command("list"), { effects: LOCAL_READ, partial: true }).description("events of every calendar account in the store, latest start first: calendars and imported phone calls").summary("events and phone calls of every account, latest first"), EVENTS_QUERY2).addHelpText("after", EVENTS_NOTE).option("--limit <n>", "events at most, 1\u20131000", upTo1000, 100).option("--json", "print JSON; --json=ref,title keeps only those fields").action(async (words, { json: json5, limit }, command) => {
|
|
5771
|
+
const body = await withStore(env, (store) => listEvents(store, words, limit));
|
|
5772
|
+
const accounts = body.meta?.accounts ?? [];
|
|
5773
|
+
print(json5, body, `${accountsLine(accounts)}
|
|
5774
|
+
${plainText(body, command)}`);
|
|
5775
|
+
});
|
|
5776
|
+
annotate(events.command("show"), { effects: LOCAL_READ, output: { entity: "event" } }).description("one event: its time, the accounts and calendars that hold it, and its attendees").argument("<ref>", "event:<id>").option("--json", "print JSON; --json=ref,title keeps only those fields").action(async (ref, { json: json5 }) => print(json5, itemAnswer(await withStore(env, (store) => showEvent(store, ref)))));
|
|
5777
|
+
}, "eventsCommand");
|
|
5778
|
+
|
|
5779
|
+
// dist/examples.js
|
|
5780
|
+
var EXAMPLES = {
|
|
5781
|
+
context: ["memo context telegram:'Kai Sample'", "memo context email:kai@example.com --limit 5 --json"],
|
|
5782
|
+
show: [
|
|
5783
|
+
"memo show chat:max/500/-1001 document:413",
|
|
5784
|
+
"memo show note:12 msg:telegram/1/77/42 --json",
|
|
5785
|
+
"memo show contract:2 invoice:4 --json"
|
|
5786
|
+
],
|
|
5787
|
+
"notes show": ["memo notes show note:12", "memo notes show ~/notes/People/Kai.md --json"],
|
|
5788
|
+
"notes list": [
|
|
5789
|
+
`memo notes list 'about:"telegram:Kai Sample"'`,
|
|
5790
|
+
"memo notes list source:internal text:budget --json",
|
|
5791
|
+
"memo notes list source:internal --limit 50"
|
|
5792
|
+
],
|
|
5793
|
+
"notes add": [
|
|
5794
|
+
"memo notes add 'Prefers calls in the morning' --subject telegram:'Kai Sample'",
|
|
5795
|
+
"memo notes add --text-file draft.md --title 'Harbour kickoff' --subject project:2 --subject organization:1"
|
|
5796
|
+
],
|
|
5797
|
+
"notes edit": ["memo notes edit note:12 --revision 2 --text 'Prefers calls after ten'"],
|
|
5798
|
+
"notes remove": ["memo notes remove note:12"],
|
|
5799
|
+
"notes export": ["memo notes export --output-dir ~/notes/memo --format obsidian"],
|
|
5800
|
+
"sources add": [
|
|
5801
|
+
"memo sources add ~/Downloads/runner-notes.pdf --subject project:3 --keep-copy",
|
|
5802
|
+
"memo sources add https://example.org/release-notes --title 'Release notes' --json",
|
|
5803
|
+
"memo sources add - --title 'Call with Kai' --subject person:12"
|
|
5804
|
+
],
|
|
5805
|
+
"sources show": ["memo sources show document:42", "memo sources show document:42 --bytes 65536 --json"],
|
|
5806
|
+
"sources mentions": ["memo sources mentions document:42 --json"],
|
|
5807
|
+
"sources remove": ["memo sources remove document:42"],
|
|
5808
|
+
"folders add": ["memo folders add ~/notes"],
|
|
5809
|
+
"folders update": ["memo folders update 1 ~/notes"],
|
|
5810
|
+
"folders remove": ["memo folders remove 1", "memo folders remove 1 --allow-delete --yes"],
|
|
5811
|
+
"folders list": ["memo folders list --json"],
|
|
5812
|
+
"config show": ["memo config show", "memo config show --json"],
|
|
5813
|
+
"config migrate": ["memo config migrate"],
|
|
5814
|
+
"config unset": ["memo config unset permissions.notes.edit"],
|
|
5815
|
+
"mentions list": [
|
|
5816
|
+
"memo mentions list kind:phone --source notes",
|
|
5817
|
+
"memo mentions list domain:example.com --source email:personal,email:work --json",
|
|
5818
|
+
"memo mentions list kind:place --source mail"
|
|
5819
|
+
],
|
|
5820
|
+
"mentions show": ["memo mentions show 12", "memo mentions show 40 --source email:personal --json"],
|
|
5821
|
+
"mentions confirm": ["memo mentions confirm 12 person:7", "memo mentions confirm 40 --source email:personal"],
|
|
5822
|
+
"mentions reject": ["memo mentions reject 12", "memo mentions reject 40 --source email:personal"],
|
|
5823
|
+
"mail review": [
|
|
5824
|
+
"memo mail review --holder mail-triage --source email:work --json",
|
|
5825
|
+
"memo mail review --unanswered 1d --source email:personal",
|
|
5826
|
+
"memo mail review 'date>2h' --source email:me@example.com"
|
|
5827
|
+
],
|
|
5828
|
+
"messages acknowledge": [
|
|
5829
|
+
"memo messages acknowledge --holder mail-triage --cursor 9123.1762090000000 --source email:work",
|
|
5830
|
+
"memo messages acknowledge --holder mail-triage --cursor 9123.1762090000000 --source email:me@example.com --json",
|
|
5831
|
+
"memo messages acknowledge --holder backfill --cursor 870.1762090000000 --source email:personal"
|
|
5832
|
+
],
|
|
5833
|
+
"messages reset": [
|
|
5834
|
+
"memo messages reset --holder mail-triage --last 8 --dry-run --source email:me@example.com",
|
|
5835
|
+
"memo messages reset --holder mail-triage --since-time 2026-11-04T00:00:00Z --source email:work --json"
|
|
5836
|
+
],
|
|
5837
|
+
"mail findings add": [
|
|
5838
|
+
"memo mail findings add findings.json --source email:work",
|
|
5839
|
+
"memo mail findings add findings.json --source email:work --key mail-triage:9123 --dry-run --json",
|
|
5840
|
+
`memo mail findings add '{"schema_version":1,"key":"mail-triage:9123","extractor":"mail-triage/1","findings":[\u2026]}' --source email:me@example.com --json`
|
|
5841
|
+
],
|
|
5842
|
+
"mail findings show": [
|
|
5843
|
+
"memo mail findings show 41",
|
|
5844
|
+
"memo mail findings show 41 --json",
|
|
5845
|
+
"memo mail findings show 41 --json=id,input.findings"
|
|
5846
|
+
],
|
|
5847
|
+
"mail findings list": [
|
|
5848
|
+
"memo mail findings list status:proposed",
|
|
5849
|
+
"memo mail findings list --source email:work --json",
|
|
5850
|
+
"memo mail findings list status:reviewed --limit 50 --page 2"
|
|
5851
|
+
],
|
|
5852
|
+
"messages show": ["memo messages show 'msg:email/me%40example.com/thread/42' --before-n 2 --after-n 2"],
|
|
5853
|
+
"projects actions add": ["memo projects actions add findings.json"],
|
|
5854
|
+
"projects actions list": [
|
|
5855
|
+
"memo projects actions list SYH",
|
|
5856
|
+
"memo projects actions list SYH status:reviewed --brief --json"
|
|
5857
|
+
],
|
|
5858
|
+
"projects actions confirm": [
|
|
5859
|
+
"memo projects actions confirm SYH 12 budget accountant --fingerprint 3f9a0c --reason 'both are stated plainly'",
|
|
5860
|
+
"memo projects actions confirm SYH key:4"
|
|
5861
|
+
],
|
|
5862
|
+
"projects actions reject": [
|
|
5863
|
+
"memo projects actions reject SYH 12 --fingerprint 3f9a0c --reason 'not about this project'"
|
|
5864
|
+
],
|
|
5865
|
+
"projects evidence": [
|
|
5866
|
+
"memo projects evidence SYH --source telegram:1,email:personal --contact 'Alice Example'",
|
|
5867
|
+
"memo projects evidence SYH --source all --context-query 'crane tender' --since-time 180d --json"
|
|
5868
|
+
],
|
|
5869
|
+
"models list": ["memo models list kind:text --json"],
|
|
5870
|
+
"commands info": ["memo commands info --json"],
|
|
5871
|
+
"models download": ["memo models download e5-small", "memo models download e5-large"],
|
|
5872
|
+
"models set": ["memo models set e5-large"],
|
|
5873
|
+
"models consents show": ["memo models consents show --json"],
|
|
5874
|
+
"models consents set": [
|
|
5875
|
+
"memo models consents set openai --model gpt-4o-mini",
|
|
5876
|
+
"memo models consents set openai --model gpt-4o-mini --yes"
|
|
5877
|
+
],
|
|
5878
|
+
"models consents revoke": ["memo models consents revoke"],
|
|
5879
|
+
"models add": [
|
|
5880
|
+
`memo models add e5-base --payload '{"repository":"Xenova/multilingual-e5-base","onnx":"onnx/model_quantized.onnx","dims":768,"pooling":"mean","prefix":{"query":"query: ","passage":"passage: "}}'`
|
|
5881
|
+
],
|
|
5882
|
+
"notes links show": ["memo notes links show telegram:101 --json"],
|
|
5883
|
+
"notes links add": ["memo notes links add telegram:101 ~/notes/People/Kai.md"],
|
|
5884
|
+
"notes links clear": ["memo notes links clear telegram:101"],
|
|
5885
|
+
"tags add": ["memo tags add follow-up --note note:12", "memo tags add harbour --project HRB"],
|
|
5886
|
+
"tags remove": ["memo tags remove follow-up --note note:12"],
|
|
5887
|
+
"tags list": ["memo tags list tag:follow-up", "memo tags list --source email:me@example.com --json"],
|
|
5888
|
+
"tasks link": ["memo tasks link HRB-2 HRB-1 --kind blocked-by"],
|
|
5889
|
+
"tasks unlink": ["memo tasks unlink HRB-2 HRB-1 --kind blocked-by"],
|
|
5890
|
+
"tasks links": ["memo tasks links HRB-2 --json"],
|
|
5891
|
+
"tasks status": ["memo tasks status HRB-2"],
|
|
5892
|
+
"tasks add": [
|
|
5893
|
+
"memo tasks add 'msg:telegram/1/77/42' --account telegram:1 --type request",
|
|
5894
|
+
"memo tasks add --project HRB --title 'Draft the budget' --type feature",
|
|
5895
|
+
"memo tasks add --project INBOX --title 'Reply on Avito to Ivan' --external-id avito:4512345678 --source-url https://www.avito.ru/4512345678"
|
|
5896
|
+
],
|
|
5897
|
+
"tasks list": [
|
|
5898
|
+
"memo tasks list state:done --source telegram:1",
|
|
5899
|
+
"memo tasks list project:HRB ready:true --json",
|
|
5900
|
+
'memo tasks list project:* priority:[high TO critical] "invoice" --sort due --json'
|
|
5901
|
+
],
|
|
5902
|
+
"tasks counts": ["memo tasks counts project:* --json"],
|
|
5903
|
+
"tasks history": ["memo tasks history HRB-1 --json"],
|
|
5904
|
+
"tasks comments add": ["memo tasks comments add HRB-1 Booked the hall for Friday"],
|
|
5905
|
+
"tasks comments list": ["memo tasks comments list HRB-1 --json"],
|
|
5906
|
+
"tasks move": ["memo tasks move HRB-3 --status in_progress --before HRB-1 --revision 4"],
|
|
5907
|
+
"people list": ["memo people list --json"],
|
|
5908
|
+
"people add": ["memo people add Lena Example"],
|
|
5909
|
+
"tasks agenda": [
|
|
5910
|
+
"memo tasks agenda --source telegram:1",
|
|
5911
|
+
"memo tasks agenda --source max:1 --waiting 3d --within 90d --json"
|
|
5912
|
+
],
|
|
5913
|
+
"tasks claim": ["memo tasks claim HRB-1 --lease 2h --account telegram:1"],
|
|
5914
|
+
"tasks release": ["memo tasks release HRB-1 --account telegram:1"],
|
|
5915
|
+
"tasks show": ["memo tasks show 1a2b3c4d --source telegram:1 --json"],
|
|
5916
|
+
"stats tasks show": [
|
|
5917
|
+
"memo stats tasks show --source telegram:1",
|
|
5918
|
+
"memo stats tasks show --type question --source telegram:1 --json"
|
|
5919
|
+
],
|
|
5920
|
+
"tasks close": ["memo tasks close 7 --account telegram:1 --as dismissed --reason 'answered by phone'"],
|
|
5921
|
+
"tasks update": [
|
|
5922
|
+
"memo tasks update HRB-1 --title 'Send the budget' --priority high --account telegram:1",
|
|
5923
|
+
"memo tasks update 1a2b3c4d --due 2d --title 'Send the revised budget' --account telegram:1"
|
|
5924
|
+
],
|
|
5925
|
+
"tasks assign": ["memo tasks assign 7 person:3", "memo tasks assign HRB-1 person:3 --clear --revision 4"],
|
|
5926
|
+
"organizations add": [
|
|
5927
|
+
"memo organizations add 'Harbour Studio' --kind company --scope work",
|
|
5928
|
+
"memo organizations add 'Harbour Family' --kind family"
|
|
5929
|
+
],
|
|
5930
|
+
"organizations rename": [
|
|
5931
|
+
"memo organizations rename organization:1 'Harbour Studio Ltd'",
|
|
5932
|
+
"memo organizations rename 1 'Harbour Studio Ltd' --json"
|
|
5933
|
+
],
|
|
5934
|
+
"organizations show": ["memo organizations show organization:1"],
|
|
5935
|
+
"organizations list": ["memo organizations list name:*harbour*", "memo organizations list --json"],
|
|
5936
|
+
"organizations context": ["memo organizations context organization:1"],
|
|
5937
|
+
"projects meetings list": ["memo projects meetings list HRB --source zoom:me@example.com"],
|
|
5938
|
+
"projects meetings link": ["memo projects meetings link HRB 31 --account zoom:me@example.com"],
|
|
5939
|
+
"projects add": ["memo projects add 'Harbour' --key HRB --type client --organization 1"],
|
|
5940
|
+
"projects list": ["memo projects list"],
|
|
5941
|
+
"projects context": ["memo projects context HRB", "memo projects context project:2 --json"],
|
|
5942
|
+
"projects status": ["memo projects status HRB --context-query 1C", "memo projects status HRB --compact"],
|
|
5943
|
+
"projects annotations show": ["memo projects annotations show HRB --max-read-bytes 1048576 --json"],
|
|
5944
|
+
"projects annotations export": ["memo projects annotations export HRB --output harbour-annotations.json --json"],
|
|
5945
|
+
"projects annotations check": [
|
|
5946
|
+
"memo projects annotations check harbour-annotations.json --target-store ./trial/wirecat.db --project project:2 --bindings bindings.json --json"
|
|
5947
|
+
],
|
|
5948
|
+
"projects annotations restore": [
|
|
5949
|
+
"memo projects annotations restore harbour-annotations.json --target-store ./trial/wirecat.db --project project:2 --bindings bindings.json --fingerprint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --json"
|
|
5950
|
+
],
|
|
5951
|
+
"projects key-documents add": ["memo projects key-documents add HRB note:12 --reason 'the brief'"],
|
|
5952
|
+
"projects key-documents remove": ["memo projects key-documents remove HRB note:12"],
|
|
5953
|
+
"projects key-documents list": ["memo projects key-documents list HRB"],
|
|
5954
|
+
"relationships update": [
|
|
5955
|
+
"memo relationships update 12 --purpose sales",
|
|
5956
|
+
"memo relationships update 12 --engagement low",
|
|
5957
|
+
"memo relationships update 12 --role approver --role-note 'signs the acts'"
|
|
5958
|
+
],
|
|
5959
|
+
"relationships add": [
|
|
5960
|
+
"memo relationships add person:3 organization:1 --role employee",
|
|
5961
|
+
"memo relationships add person:3 project:1 --role client-contact --engagement low",
|
|
5962
|
+
"memo relationships add project:2 organization:1 --kind related-to --reason 'same client'"
|
|
5963
|
+
],
|
|
5964
|
+
"relationships list": ['memo relationships list about:"person:3"', "memo relationships list confirmed:false"],
|
|
5965
|
+
"relationships remove": ["memo relationships remove 4"],
|
|
5966
|
+
"relationships confirm": ["memo relationships confirm 4"],
|
|
5967
|
+
"relationships scan": [
|
|
5968
|
+
"memo relationships scan HRB --source all",
|
|
5969
|
+
"memo relationships scan HRB --source telegram:1,email:personal --yes",
|
|
5970
|
+
"memo relationships scan --source email:me@example.com"
|
|
5971
|
+
],
|
|
5972
|
+
"reminders add": [
|
|
5973
|
+
"memo reminders add 7 --at-time 2026-10-20T09:00:00+02:00 --timezone Europe/Madrid --account telegram:1"
|
|
5974
|
+
],
|
|
5975
|
+
"reminders list": ["memo reminders list --source telegram:1"],
|
|
5976
|
+
"reminders claim": ["memo reminders claim --account telegram:1 --json"],
|
|
5977
|
+
"reminders acknowledge": ["memo reminders acknowledge 3 3:1 --account telegram:1"],
|
|
5978
|
+
"reminders cancel": ["memo reminders cancel 3 --account telegram:1"],
|
|
5979
|
+
"reminders update": ["memo reminders update 3 --revision 1 --at-time 2026-10-21T09:00:00+02:00 --account telegram:1"],
|
|
5980
|
+
"vocabulary list": ["memo vocabulary list kind:tag"],
|
|
5981
|
+
"vocabulary show": ["memo vocabulary show Harbour --kind project"],
|
|
5982
|
+
"vocabulary check": ["memo vocabulary check on-boarding --kind tag", "memo vocabulary check --limit 20 --json"],
|
|
5983
|
+
"vocabulary inspect": [
|
|
5984
|
+
"memo vocabulary inspect tag:1 tag:2 --fingerprint v1:all:all:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --limit 5 --json"
|
|
5985
|
+
],
|
|
5986
|
+
"vocabulary create": ["memo vocabulary create onboarding --kind tag --fingerprint 3f9a"],
|
|
5987
|
+
"vocabulary aliases add": ["memo vocabulary aliases add project:2 Harbor --fingerprint 3f9a"],
|
|
5988
|
+
"vocabulary aliases remove": ["memo vocabulary aliases remove project:2 5 --fingerprint 3f9a"],
|
|
5989
|
+
"memories add": ["memo memories add 'Kai prefers Friday meetings' --kind preference --scope work --evidence note:12"],
|
|
5990
|
+
"memories list": ["memo memories list status:proposed kind:preference"],
|
|
5991
|
+
"memories show": ["memo memories show memory:4 --sources"],
|
|
5992
|
+
"memories update": ["memo memories update memory:4 --project SYH", "memo memories update memory:4 --project none"],
|
|
5993
|
+
"memories confirm": ["memo memories confirm memory:4"],
|
|
5994
|
+
"memories invalidate": ["memo memories invalidate memory:4"],
|
|
5995
|
+
"memories remove": ["memo memories remove memory:4"],
|
|
5996
|
+
"memories check": ["memo memories check", "memo memories check --limit 2000 --json"],
|
|
5997
|
+
"memories challenge": [
|
|
5998
|
+
"memo memories challenge memory:4 --evidence note:15 --reason 'the later note moves delivery to the 30th'",
|
|
5999
|
+
"memo memories challenge memory:4 --evidence note:15 --reason 'moved' --suggest 'Delivery is on the 30th' --json"
|
|
6000
|
+
],
|
|
6001
|
+
"facts add": [
|
|
6002
|
+
"memo facts add 'We moved the launch to spring' --kind decision --evidence 'msg:telegram/1/77/42' --project HRB"
|
|
6003
|
+
],
|
|
6004
|
+
"facts list": ["memo facts list kind:decision project:HRB"],
|
|
6005
|
+
"orders list": ["memo orders list status:shipped", `memo orders list number:A-1042 'supplier:"Shop One"' --json`],
|
|
6006
|
+
"orders show": ["memo orders show order:3"],
|
|
6007
|
+
"pipelines list": ["memo pipelines list", "memo pipelines list kind:lead --json"],
|
|
6008
|
+
"pipelines show": ["memo pipelines show pipeline:2", "memo pipelines show Sales --since-time 2026-09-01"],
|
|
6009
|
+
"pipelines add": [
|
|
6010
|
+
"memo pipelines add Sales Call Quote Contract won lost",
|
|
6011
|
+
"memo pipelines add Inbound new called --kind lead"
|
|
6012
|
+
],
|
|
6013
|
+
"deals list": ["memo deals list status:open project:HRB", "memo deals list stage:Quote --json"],
|
|
6014
|
+
"deals show": ["memo deals show deal:5"],
|
|
6015
|
+
"deals add": [
|
|
6016
|
+
"memo deals add 'Site for the clinic' Call 500000.00 RUB --organization organization:3 --project HRB",
|
|
6017
|
+
"memo deals add 'Support contract' Sales/Quote --person person:7 --role decision-maker --due 2026-12-01"
|
|
6018
|
+
],
|
|
6019
|
+
"deals move": ["memo deals move deal:5 Quote"],
|
|
6020
|
+
"deals close": ["memo deals close deal:5 won", "memo deals close deal:6 lost --reason 'chose a cheaper studio'"],
|
|
6021
|
+
"leads list": ["memo leads list status:open"],
|
|
6022
|
+
"leads show": ["memo leads show lead:3"],
|
|
6023
|
+
"leads add": ["memo leads add 'Call from the site'", "memo leads add 'Clinic in Kazan' contacted --person person:9"],
|
|
6024
|
+
"leads move": ["memo leads move lead:3 qualified"],
|
|
6025
|
+
"leads close": ["memo leads close lead:3 lost --reason 'no budget'"],
|
|
6026
|
+
"orders add": [
|
|
6027
|
+
"memo orders add 'Shop One' 2499.00 RUB --kind personal --title A-1042",
|
|
6028
|
+
"memo orders add 'Office Supply' --kind client --organization organization:3"
|
|
6029
|
+
],
|
|
6030
|
+
"events list": [
|
|
6031
|
+
"memo events list event_type:call",
|
|
6032
|
+
"memo events list account:phone:pixel 'starts_at:[2026-11-02 TO 2026-11-07}' --json"
|
|
6033
|
+
],
|
|
6034
|
+
"events show": ["memo events show event:42"],
|
|
6035
|
+
"invoices list": ["memo invoices list project:HRB open:true", "memo invoices list review:proposed --json"],
|
|
6036
|
+
"invoices show": ["memo invoices show invoice:4"],
|
|
6037
|
+
"invoices add": [
|
|
6038
|
+
"memo invoices add 50000.00 RUB Bed rental, November --kind receivable --organization organization:3 --project HRB",
|
|
6039
|
+
"memo invoices add 1200.50 EUR Hosting --kind payable --person person:7 --title 2026-118 --due 2026-11-15"
|
|
6040
|
+
],
|
|
6041
|
+
"payments list": ["memo payments list project:HRB direction:in", "memo payments list review:proposed --json"],
|
|
6042
|
+
"payments show": ["memo payments show payment:9"],
|
|
6043
|
+
"payments add": [
|
|
6044
|
+
"memo payments add 25000.00 RUB --kind in --organization organization:3 --occurred-time 2026-11-01 --project HRB",
|
|
6045
|
+
"memo payments add 5000.00 RUB --kind out --organization organization:3 --refund-of payment:9"
|
|
6046
|
+
],
|
|
6047
|
+
"records import": [
|
|
6048
|
+
"memo records import payments.jsonl --account rentals --dry-run",
|
|
6049
|
+
"memo records import envelope.json --account rentals --json",
|
|
6050
|
+
"memo records import contacts.vcf --account phone:pixel --region gb"
|
|
6051
|
+
],
|
|
6052
|
+
"records check": ["memo records check - --account rentals"],
|
|
6053
|
+
"records list": [
|
|
6054
|
+
"memo records list waiting:true --account sheet:rentals",
|
|
6055
|
+
"memo records list type:organization --account sheet:rentals --json",
|
|
6056
|
+
`memo records list 'entity:"organization:3"' deleted:false --account sheet:rentals`
|
|
6057
|
+
],
|
|
6058
|
+
"records link": ["memo records link organization:client organization:3 --account sheet:rentals"],
|
|
6059
|
+
"payments allocate": ["memo payments allocate payment:9 invoice:4 25000.00"],
|
|
6060
|
+
"products list": ["memo products list kind:service", "memo products list archived:true --json"],
|
|
6061
|
+
"products show": ["memo products show product:4"],
|
|
6062
|
+
"products add": [
|
|
6063
|
+
"memo products add 'Bike rental, month' 10000.00 RUB --kind service --unit month",
|
|
6064
|
+
"memo products add 'Helmet' 2500.00 RUB --sku H-12 --supplier organization:3"
|
|
6065
|
+
],
|
|
6066
|
+
"products update": [
|
|
6067
|
+
"memo products update product:4 --amount 12000.00 --currency RUB",
|
|
6068
|
+
"memo products update product:4 --archived on"
|
|
6069
|
+
],
|
|
6070
|
+
"orders lines add": [
|
|
6071
|
+
"memo orders lines add order:3 12 --product product:4",
|
|
6072
|
+
"memo orders lines add order:3 1 Rental, first week --product product:4 --amount 2000.00",
|
|
6073
|
+
"memo orders lines add order:3 2 Helmet --amount 2500.00"
|
|
6074
|
+
],
|
|
6075
|
+
"orders lines remove": ["memo orders lines remove order:3 2"],
|
|
6076
|
+
"invoices lines add": [
|
|
6077
|
+
"memo invoices lines add invoice:4 1 --product product:4",
|
|
6078
|
+
"memo invoices lines add invoice:4 2 Delivery --amount 1500.00"
|
|
6079
|
+
],
|
|
6080
|
+
"invoices lines remove": ["memo invoices lines remove invoice:4 2"],
|
|
6081
|
+
"contracts list": ["memo contracts list status:active", "memo contracts list expires:2026-12-31 --json"],
|
|
6082
|
+
"contracts show": ["memo contracts show contract:2"],
|
|
6083
|
+
"contracts add": [
|
|
6084
|
+
"memo contracts add 'Rental agreement' --kind service --start-date 2026-11-01 --end-date 2027-10-31 --auto-renew on --notice-days 30 --amount 120000.00 --currency RUB",
|
|
6085
|
+
"memo contracts add 'NDA with the studio' --kind nda --project HRB"
|
|
6086
|
+
],
|
|
6087
|
+
"contracts update": [
|
|
6088
|
+
"memo contracts update contract:2 --status terminated",
|
|
6089
|
+
"memo contracts update contract:2 --end-date 2027-12-31"
|
|
6090
|
+
],
|
|
6091
|
+
"subscriptions list": [
|
|
6092
|
+
"memo subscriptions list status:active direction:payable",
|
|
6093
|
+
"memo subscriptions list renews:2026-12-01 --json"
|
|
6094
|
+
],
|
|
6095
|
+
"subscriptions show": ["memo subscriptions show subscription:5"],
|
|
6096
|
+
"subscriptions add": [
|
|
6097
|
+
"memo subscriptions add Hosting 990.00 RUB --kind payable --supplier organization:3 --period 1-month --start-date 2026-11-01",
|
|
6098
|
+
"memo subscriptions add 'Bike rental' 10000.00 RUB --kind receivable --customer organization:3 --period 1-month --trial-end-date 2026-11-14 --status trial"
|
|
6099
|
+
],
|
|
6100
|
+
"subscriptions update": [
|
|
6101
|
+
"memo subscriptions update subscription:5 --status paused",
|
|
6102
|
+
"memo subscriptions update subscription:5 --period 1-year"
|
|
6103
|
+
],
|
|
6104
|
+
"subscriptions cancel": ["memo subscriptions cancel subscription:5 --occurred-time 2026-11-30"],
|
|
6105
|
+
"subscriptions prices add": ["memo subscriptions prices add subscription:5 1190.00 RUB --start-date 2027-01-01"],
|
|
6106
|
+
"wallets list": ["memo wallets list", "memo wallets list kind:card --json"],
|
|
6107
|
+
"wallets show": ["memo wallets show wallet:2", "memo wallets show wallet:2 --until-time 2026-10-31"],
|
|
6108
|
+
"wallets add": ["memo wallets add 'Main card' RUB --kind card --institution 'Bank One'"],
|
|
6109
|
+
"wallets update": ["memo wallets update wallet:2 --opening-balance 15000.00 --opening-date 2026-01-01"],
|
|
6110
|
+
"transactions list": [
|
|
6111
|
+
`memo transactions list 'wallet:"wallet:2"' status:pending`,
|
|
6112
|
+
"memo transactions list uncategorized:true --json"
|
|
6113
|
+
],
|
|
6114
|
+
"transactions show": ["memo transactions show transaction:12"],
|
|
6115
|
+
"transactions add": [
|
|
6116
|
+
"memo transactions add wallet:2 500.00 --kind out --occurred-time 2026-11-14 --description 'Coffee shop'",
|
|
6117
|
+
"memo transactions add wallet:2 10000.00 --kind in --payment payment:9"
|
|
5994
6118
|
],
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6119
|
+
"transactions update": [
|
|
6120
|
+
"memo transactions update transaction:12 --status booked",
|
|
6121
|
+
"memo transactions update transaction:12 --payment payment:9"
|
|
6122
|
+
],
|
|
6123
|
+
"transactions splits add": ["memo transactions splits add transaction:12 300.00 Rent --project HRB"],
|
|
6124
|
+
"transactions splits remove": ["memo transactions splits remove transaction:12 1"],
|
|
6125
|
+
"records show": [
|
|
6126
|
+
"memo records show custom:quote:Q-7 --account example-erp:demo",
|
|
6127
|
+
"memo records show organization:client --account sheet:rentals --json"
|
|
6128
|
+
],
|
|
6129
|
+
"records delete": ["memo records delete payment:sheet-12 --account sheet:rentals"],
|
|
6130
|
+
"records match": ["memo records match --account sheet:rentals"],
|
|
6131
|
+
"payments unlink": ["memo payments unlink payment:9 invoice:4"],
|
|
6132
|
+
"facts show": ["memo facts show fact:4 --sources"],
|
|
6133
|
+
"facts confirm": ["memo facts confirm fact:4"],
|
|
6134
|
+
"facts revoke": ["memo facts revoke fact:4"],
|
|
6135
|
+
"facts reverse": ["memo facts reverse fact:4"],
|
|
6136
|
+
"facts reject": ["memo facts reject fact:4"],
|
|
6137
|
+
"facts remove": ["memo facts remove fact:4"],
|
|
6138
|
+
"facts challenge": ["memo facts challenge fact:4 --evidence 'msg:telegram/1/77/50' --reason 'reversed in chat'"],
|
|
6139
|
+
"actions add": [
|
|
6140
|
+
`memo actions add reply --reason 'Kai asked twice' --account telegram:1 --target 'msg:telegram/1/77/42' --payload '{"text":"Friday works"}'`
|
|
6141
|
+
],
|
|
6142
|
+
"meetings actions add": ["memo meetings actions add findings.json --account zoom:me@example.com"],
|
|
6143
|
+
"meetings passage": [
|
|
6144
|
+
"memo meetings passage meeting:1/1/1/0 --source zoom:me@example.com --before-n 1 --after-n 1 --json"
|
|
6145
|
+
],
|
|
6146
|
+
"meetings prepare": [
|
|
6147
|
+
"memo meetings prepare example-series --source zoom:me@example.com --json",
|
|
6148
|
+
"memo meetings prepare example-series --source zoom:me@example.com --context-source tg.personal --context-query Harbour --json"
|
|
6149
|
+
],
|
|
6150
|
+
"search meetings": [
|
|
6151
|
+
"memo search meetings budget --source zoom:me@example.com --project Harbour --since-time 2026-10-01 --limit 10 --json"
|
|
6152
|
+
],
|
|
6153
|
+
"meetings actions list": ["memo meetings actions list status:proposed --source zoom:me@example.com"],
|
|
6154
|
+
"meetings actions show": ["memo meetings actions show 5 --source zoom:me@example.com"],
|
|
6155
|
+
"meetings actions confirm": [
|
|
6156
|
+
"memo meetings actions confirm 5 decision --fingerprint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --account zoom:me@example.com"
|
|
6157
|
+
],
|
|
6158
|
+
"meetings actions reject": [
|
|
6159
|
+
"memo meetings actions reject 5 --fingerprint aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --account zoom:me@example.com"
|
|
6160
|
+
],
|
|
6161
|
+
"actions list": ["memo actions list status:proposed"],
|
|
6162
|
+
"actions show": ["memo actions show 5"],
|
|
6163
|
+
"actions confirm": ["memo actions confirm 5"],
|
|
6164
|
+
"actions reject": ["memo actions reject 5"],
|
|
6165
|
+
"review list": [
|
|
6166
|
+
"memo review list project:HRB",
|
|
6167
|
+
"memo review list kind:relationship,fact by:agent",
|
|
6168
|
+
"memo review list via:chat:max/1/-100"
|
|
6169
|
+
],
|
|
6170
|
+
"review show": ["memo review show 17079", "memo review show 17080 --brief --json"],
|
|
6171
|
+
"review confirm": [
|
|
6172
|
+
"memo review confirm 17078-17081",
|
|
6173
|
+
"memo review confirm 17080/f1,17080/f3",
|
|
6174
|
+
"memo review confirm close:Q-15"
|
|
6175
|
+
],
|
|
6176
|
+
"review reject": [
|
|
6177
|
+
'memo review reject 17081 --reason "not this project"',
|
|
6178
|
+
"memo review reject close:Q-15 --reason 'still open'"
|
|
6179
|
+
],
|
|
6180
|
+
"review agenda": ["memo review agenda --compact", "memo review agenda --since-time 3d --json"],
|
|
6181
|
+
"review status": ["memo review status", "memo review status --since-time 7d --json"],
|
|
6182
|
+
"schedule command": [
|
|
6183
|
+
"memo schedule command digest --at 08:30 -- review status",
|
|
6184
|
+
"memo schedule command mail-sync --every 1h -- sync --only mail"
|
|
6185
|
+
],
|
|
6186
|
+
"schedule agent": [
|
|
6187
|
+
"memo schedule agent triage claude 'read memo review status and list what needs me today' --at 08:45 --max-cost 1",
|
|
6188
|
+
"memo schedule agent mail-triage claude 'Run memo skill show mail-triage and follow it.' --every 5m --on-new-mail mail-triage --mail-wait 1h --mail-batch 20 --max-cost 1 --max-cost-per-day 5",
|
|
6189
|
+
"memo schedule agent weekly claude 'read memo review status and sum up the week' --at 09:00 --model opus"
|
|
6190
|
+
],
|
|
6191
|
+
"schedule list": ["memo schedule list", "memo schedule list kind:agent --json"],
|
|
6192
|
+
"schedule run": ["memo schedule run digest"],
|
|
6193
|
+
"digest backfill": [
|
|
6194
|
+
"memo digest backfill --from 2026-11-01 --to 2026-11-07",
|
|
6195
|
+
"memo digest backfill --from 2026-11-01 --to 2026-11-07 --yes --json"
|
|
6196
|
+
],
|
|
6197
|
+
"schedule remove": ["memo schedule remove digest"],
|
|
6198
|
+
"schedule exec": ["memo schedule exec ~/.local/state/cli-memo/schedules/digest/schedule.json"],
|
|
6199
|
+
"templates list": ["memo templates list", "memo templates list channel:telegram source:stored --json"],
|
|
6200
|
+
"templates show": [
|
|
6201
|
+
"memo templates show report/morning-digest --channel telegram",
|
|
6202
|
+
"memo templates show report/weekly-gaps --channel email --locale en --json"
|
|
6203
|
+
],
|
|
6204
|
+
"templates edit": [
|
|
6205
|
+
"memo templates edit report/morning-digest --channel telegram",
|
|
6206
|
+
"memo templates edit report/morning-digest --channel text --file digest.text.liquid",
|
|
6207
|
+
"memo templates edit report/morning-digest --channel telegram --undo"
|
|
6208
|
+
],
|
|
6209
|
+
"templates preview": [
|
|
6210
|
+
"memo templates preview report/morning-digest --channel telegram",
|
|
6211
|
+
"memo templates preview report/morning-digest --channel email --locale en --file draft.liquid"
|
|
6212
|
+
],
|
|
6213
|
+
"templates reset": ["memo templates reset report/morning-digest --channel telegram"],
|
|
6214
|
+
"agents list": ["memo agents list agent:claude-code --limit 20"],
|
|
6215
|
+
"mcp serve": ["memo mcp serve", "memo mcp serve --http --public-url https://laptop.example.ts.net"],
|
|
6216
|
+
"mcp revoke": ["memo mcp revoke --json"],
|
|
6217
|
+
"mcp server start": ["memo mcp server start --public-url https://laptop.example.ts.net"],
|
|
6218
|
+
"mcp server status": ["memo mcp server status --json"],
|
|
6219
|
+
"mcp server stop": ["memo mcp server stop"],
|
|
6220
|
+
"search all": [
|
|
6221
|
+
"memo search all 'budget harbour'",
|
|
6222
|
+
"memo search all 'content:invoice' --only mail,notes --json",
|
|
6223
|
+
"memo search all 'Rental agreement' --only business"
|
|
6224
|
+
],
|
|
6225
|
+
"search messages": ["memo search messages 'friday meeting has:voice'"],
|
|
6226
|
+
"search mail": ["memo search mail 'mailbox:important budget' --source email:me@example.com"],
|
|
6227
|
+
"search notes": ["memo search notes budget notes:2", "memo search notes kickoff --project HRB --json"],
|
|
6228
|
+
"search memories": ["memo search memories friday meetings scope:work"],
|
|
6229
|
+
"search people": ["memo search people ana", "memo search people Ana Example --source telegram --json"],
|
|
6230
|
+
"answers create": [
|
|
6231
|
+
"memo answers create 'what did Kai say about the budget?' --all",
|
|
6232
|
+
"memo answers create 'when is the launch?' --source telegram:1"
|
|
6233
|
+
],
|
|
6234
|
+
sync: ["memo sync", "memo sync --only mail", "memo sync --only notes --folder ~/notes --no-embed"],
|
|
6235
|
+
"jobs start": ["memo jobs start --every 10m"],
|
|
6236
|
+
"jobs stop": ["memo jobs stop"],
|
|
6237
|
+
"jobs status": ["memo jobs status --json"],
|
|
6238
|
+
doctor: ["memo doctor", "memo doctor --json"],
|
|
6239
|
+
"runs list": ["memo runs list status:failed --limit 10", "memo runs list --page 2 --json"],
|
|
6240
|
+
"runs show": ["memo runs show 20261025T090000Z-mail-sync-a81f2c --json"],
|
|
6241
|
+
"runs path": ["memo runs path 20261025T090000Z-mail-sync-a81f2c"],
|
|
6242
|
+
"store info": ["memo store info", "memo store info --json"],
|
|
6243
|
+
"store recover": ["memo store recover", "memo store recover --json"],
|
|
6244
|
+
"store recover run": ["memo store recover run"],
|
|
6245
|
+
upgrade: ["memo upgrade --check"],
|
|
6246
|
+
commands: ["memo commands --json", "memo commands tags add --json"],
|
|
6247
|
+
"skill show": ["memo skill show"],
|
|
6248
|
+
"skill install": ["memo skill install --for all"],
|
|
6249
|
+
"skill status": ["memo skill status", "memo skill status --json"],
|
|
6250
|
+
guide: ["memo guide", "memo guide person-brief --json"],
|
|
6251
|
+
help: ["memo help options", "memo help tasks agenda"]
|
|
6252
|
+
};
|
|
6253
|
+
var leaves = /* @__PURE__ */ __name((command, path = []) => command.commands.flatMap((child) => {
|
|
6254
|
+
const at = [...path, child.name()];
|
|
6255
|
+
return child.commands.length ? leaves(child, at) : [[at.join(" "), child]];
|
|
6256
|
+
}), "leaves");
|
|
6257
|
+
var addExamples = /* @__PURE__ */ __name((program) => {
|
|
6258
|
+
for (const [path, command] of leaves(program)) {
|
|
6259
|
+
const examples = EXAMPLES[path];
|
|
6260
|
+
if (!examples || JSON.stringify(metaOf(command).examples) === JSON.stringify(examples))
|
|
6261
|
+
continue;
|
|
6262
|
+
if (hasSharedContract(command))
|
|
6263
|
+
overrideSharedContract(command, "Memo examples use explicit stored-account scope rather than messenger profile words.", (one2) => {
|
|
6264
|
+
annotate(one2, { examples });
|
|
6265
|
+
});
|
|
6266
|
+
else
|
|
6267
|
+
annotate(command, { examples });
|
|
6129
6268
|
}
|
|
6130
|
-
|
|
6131
|
-
throw new CliError("validation_error", "--cursor, --sort and --desc page and order project tasks: add project:");
|
|
6132
|
-
const { state, source } = accountTerms(query);
|
|
6133
|
-
return accountTasks(store, await accounts(), {
|
|
6134
|
-
state,
|
|
6135
|
-
limit: options.limit,
|
|
6136
|
-
...source === void 0 ? {} : { sources: [source] }
|
|
6137
|
-
});
|
|
6138
|
-
}, "listTasks");
|
|
6139
|
-
var countTasks = /* @__PURE__ */ __name(async (store, words) => {
|
|
6140
|
-
const query = listQuery(typedQuery(words), TASKS_LIST_QUERY, "tasks counts", { defaultField: "text" });
|
|
6141
|
-
if (query && walkQuery(query.root).some(({ field: field2 }) => field2 === "source"))
|
|
6142
|
-
throw new CliError("validation_error", "source: narrows an account's tasks; tasks counts counts project tasks");
|
|
6143
|
-
return store.tasks.boardCounts(await resolveProjects(store, query), { zone: timezoneOf() });
|
|
6144
|
-
}, "countTasks");
|
|
6269
|
+
}, "addExamples");
|
|
6145
6270
|
|
|
6146
|
-
// dist/
|
|
6147
|
-
var
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
}
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
const
|
|
6195
|
-
const
|
|
6196
|
-
const
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6271
|
+
// dist/memories/memories.js
|
|
6272
|
+
var addMemory = /* @__PURE__ */ __name(async (store, memory, by) => store.memories.add({
|
|
6273
|
+
kind: memory.kind,
|
|
6274
|
+
body: memory.text,
|
|
6275
|
+
scope: memory.scope,
|
|
6276
|
+
evidence: memory.evidence,
|
|
6277
|
+
author: by,
|
|
6278
|
+
status: by === "owner" ? "confirmed" : "proposed",
|
|
6279
|
+
...memory.subject === void 0 ? {} : { subject: memory.subject },
|
|
6280
|
+
...memory.project === void 0 ? {} : { project: await canonicalProject(store, memory.project) },
|
|
6281
|
+
...memory.supersedes === void 0 ? {} : { supersedes: memory.supersedes }
|
|
6282
|
+
}), "addMemory");
|
|
6283
|
+
|
|
6284
|
+
// dist/memories/memory.js
|
|
6285
|
+
var MEMORY_QUERY = {
|
|
6286
|
+
entity: "memory",
|
|
6287
|
+
backend: "native",
|
|
6288
|
+
fields: [
|
|
6289
|
+
termField("kind", "enum", "kind:preference", { values: MEMORY_KINDS }),
|
|
6290
|
+
termField("status", "enum", "status:proposed", { values: MEMORY_STATUSES }),
|
|
6291
|
+
termField("scope", "enum", "scope:work", { values: MEMORY_SCOPES }),
|
|
6292
|
+
termField("subject", "ref", 'subject:"person:42"'),
|
|
6293
|
+
termField("project", "kw", "project:SYH")
|
|
6294
|
+
]
|
|
6295
|
+
};
|
|
6296
|
+
var memoryItem = /* @__PURE__ */ __name(({ body, ...memory }) => ({
|
|
6297
|
+
ref: memory.ref,
|
|
6298
|
+
id: memory.id,
|
|
6299
|
+
kind: memory.kind,
|
|
6300
|
+
text: body,
|
|
6301
|
+
subject: memory.subject,
|
|
6302
|
+
subjectName: memory.subjectName,
|
|
6303
|
+
subjectIsOwner: memory.subjectIsOwner,
|
|
6304
|
+
project: memory.project,
|
|
6305
|
+
projectName: memory.projectName,
|
|
6306
|
+
author: memory.author,
|
|
6307
|
+
model: memory.model,
|
|
6308
|
+
confidence: memory.confidence,
|
|
6309
|
+
status: memory.status,
|
|
6310
|
+
scope: memory.scope,
|
|
6311
|
+
supersedes: memory.supersedes,
|
|
6312
|
+
evidence: memory.evidence,
|
|
6313
|
+
lastVerifiedAt: memory.lastVerifiedAt,
|
|
6314
|
+
sourceReview: memory.sourceReview,
|
|
6315
|
+
createdAt: memory.createdAt,
|
|
6316
|
+
updatedAt: memory.updatedAt
|
|
6317
|
+
}), "memoryItem");
|
|
6318
|
+
var listMemories = /* @__PURE__ */ __name(async (store, query, limit) => {
|
|
6319
|
+
const terms2 = queryTerms(query, MEMORY_QUERY, "memories list");
|
|
6320
|
+
const project = terms2.get("project");
|
|
6321
|
+
const filters = {
|
|
6322
|
+
...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
|
|
6323
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
6324
|
+
...terms2.has("scope") ? { scope: terms2.get("scope") } : {},
|
|
6325
|
+
...terms2.has("subject") ? { subject: terms2.get("subject") } : {},
|
|
6326
|
+
...project === void 0 ? {} : { project: await canonicalProject(store, project) }
|
|
6327
|
+
};
|
|
6328
|
+
return pageOf("memories list", limit, async (most) => (await store.memories.list({ ...filters, limit: most })).map(memoryItem));
|
|
6329
|
+
}, "listMemories");
|
|
6330
|
+
var SEARCH = { command: "search memories", guide: LIST_QUERY_GUIDE };
|
|
6331
|
+
var MEMORY_FIELDS = /* @__PURE__ */ new Set(["text", ...MEMORY_QUERY.fields.map(({ name: name2 }) => name2)]);
|
|
6332
|
+
var searchMemories = /* @__PURE__ */ __name((store, query, limit) => {
|
|
6333
|
+
const { root } = parseLucene(plainQuery(typedQuery(query), MEMORY_FIELDS), { ...SEARCH, defaultField: "text" });
|
|
6334
|
+
const clauses = [];
|
|
6335
|
+
if (root.kind === "predicate")
|
|
6336
|
+
clauses.push(root);
|
|
6337
|
+
else
|
|
6338
|
+
for (const { occur, node } of root.clauses) {
|
|
6339
|
+
if (occur !== "must" || node.kind !== "predicate")
|
|
6340
|
+
queryError("query.unsupported-operator", node.span, "join words and scope: with AND only", SEARCH);
|
|
6341
|
+
clauses.push(node);
|
|
6342
|
+
}
|
|
6343
|
+
const words = [];
|
|
6344
|
+
let scope;
|
|
6345
|
+
for (const term of clauses) {
|
|
6346
|
+
if (term.field === "text" && (term.operator === "term" || term.operator === "phrase"))
|
|
6347
|
+
words.push(term.value);
|
|
6348
|
+
else if (term.field === "scope" && term.operator === "term" && scope === void 0) {
|
|
6349
|
+
const value = term.value.toLowerCase();
|
|
6350
|
+
if (!MEMORY_SCOPES.includes(value))
|
|
6351
|
+
queryError("query.invalid-value", term.span, `scope is ${MEMORY_SCOPES.join(" or ")}`, SEARCH);
|
|
6352
|
+
scope = value;
|
|
6353
|
+
} else
|
|
6354
|
+
queryError("query.unsupported-field", term.span, "words, and scope:personal or scope:work once", SEARCH);
|
|
6206
6355
|
}
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
if (due === tomorrow)
|
|
6224
|
-
groups.push("tomorrow");
|
|
6225
|
-
if (Date.parse(task.createdAt) >= since)
|
|
6226
|
-
groups.push("new");
|
|
6227
|
-
if (groups.length === 0)
|
|
6356
|
+
return pageOf("search memories", limit, async (most) => (await store.memories.search(words.join(" "), { limit: most, ...scope === void 0 ? {} : { scope } })).map(memoryItem), { fallback: 20, cap: 200 });
|
|
6357
|
+
}, "searchMemories");
|
|
6358
|
+
|
|
6359
|
+
// dist/digest/known.js
|
|
6360
|
+
var knownSenders = /* @__PURE__ */ __name(async (store, accountId, externalIds) => {
|
|
6361
|
+
if (externalIds.length === 0)
|
|
6362
|
+
return /* @__PURE__ */ new Set();
|
|
6363
|
+
const [facts, marks] = await Promise.all([
|
|
6364
|
+
store.mail.emailFacts({ accountId, externalIds }),
|
|
6365
|
+
store.mail.emailMarks(accountId, externalIds)
|
|
6366
|
+
]);
|
|
6367
|
+
const known2 = /* @__PURE__ */ new Set();
|
|
6368
|
+
const unlinked = /* @__PURE__ */ new Map();
|
|
6369
|
+
for (const fact of facts) {
|
|
6370
|
+
const address = fact.fromAddress?.toLowerCase();
|
|
6371
|
+
if (!address)
|
|
6228
6372
|
continue;
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
task,
|
|
6234
|
-
groups,
|
|
6235
|
-
askedBy: await personName(store, await store.tasks.sourceSender(task.id)),
|
|
6236
|
-
for: assignees.filter(Boolean).join(", ") || null
|
|
6237
|
-
});
|
|
6373
|
+
if ((marks.get(fact.externalId)?.senderIdentities ?? 0) > 1)
|
|
6374
|
+
known2.add(fact.externalId);
|
|
6375
|
+
else
|
|
6376
|
+
unlinked.set(address, [...unlinked.get(address) ?? [], fact.externalId]);
|
|
6238
6377
|
}
|
|
6239
|
-
|
|
6240
|
-
|
|
6378
|
+
for (const address of await store.mail.writtenTo([...unlinked.keys()]))
|
|
6379
|
+
for (const id of unlinked.get(address) ?? [])
|
|
6380
|
+
known2.add(id);
|
|
6381
|
+
return known2;
|
|
6382
|
+
}, "knownSenders");
|
|
6241
6383
|
|
|
6242
6384
|
// dist/digest/digest.js
|
|
6243
6385
|
var WATCH_TAG = "watch";
|
|
6244
|
-
var
|
|
6386
|
+
var DAY7 = 864e5;
|
|
6245
6387
|
var MESSENGERS2 = /* @__PURE__ */ new Set(["telegram", "max", "whatsapp"]);
|
|
6246
6388
|
var HEALTH_ORDER = HEALTH_REASONS;
|
|
6247
6389
|
var UNNAMED = "unnamed account";
|
|
@@ -6325,8 +6467,11 @@ var statusLine = /* @__PURE__ */ __name((data) => {
|
|
|
6325
6467
|
return "";
|
|
6326
6468
|
}, "statusLine");
|
|
6327
6469
|
var personal = /* @__PURE__ */ __name((newest) => !newest.bulk && !newest.list && !newest.envelope && !newest.demoted, "personal");
|
|
6328
|
-
var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date.now(), limit, excerpt: excerpt2, owedWithin, newSince }) => {
|
|
6329
|
-
const
|
|
6470
|
+
var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now: clock = Date.now(), until, limit, excerpt: excerpt2, owedWithin, newSince }) => {
|
|
6471
|
+
const now = until ?? clock;
|
|
6472
|
+
const by = /* @__PURE__ */ __name((at) => until === void 0 || at <= until, "by");
|
|
6473
|
+
const upTo = /* @__PURE__ */ __name((found) => found.filter((one2) => by(Date.parse(one2.item.at))), "upTo");
|
|
6474
|
+
const window = (now - since) / DAY7;
|
|
6330
6475
|
const days2 = `${Math.max(1, Math.ceil(window))}d`;
|
|
6331
6476
|
const accounts = await store.accounts.accounts();
|
|
6332
6477
|
const messengers2 = accounts.filter((key) => MESSENGERS2.has(key.provider));
|
|
@@ -6383,14 +6528,14 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6383
6528
|
let mailMoved = 0;
|
|
6384
6529
|
for (const key of messengers2) {
|
|
6385
6530
|
const { chats, storedAt } = await store.chats.chatActivity(key, owedSince);
|
|
6386
|
-
const month = (await store.chats.chatActivity(key, now - 30 *
|
|
6531
|
+
const month = (await store.chats.chatActivity(key, now - 30 * DAY7)).chats;
|
|
6387
6532
|
checkHealth(key, {
|
|
6388
6533
|
newest: month.reduce((most, chat) => Math.max(most ?? 0, Date.parse(chat.lastMessageAt)), null),
|
|
6389
6534
|
moved30d: month.length,
|
|
6390
6535
|
storedAt: storedAt === null ? null : Date.parse(storedAt)
|
|
6391
6536
|
});
|
|
6392
6537
|
const ref = /* @__PURE__ */ __name((chat) => formatReference({ type: "chat", provider: key.provider, account: key.account, chat }), "ref");
|
|
6393
|
-
chatsMoved += chats.filter((chat) => Date.parse(chat.lastMessageAt) >= since).length;
|
|
6538
|
+
chatsMoved += chats.filter((chat) => Date.parse(chat.lastMessageAt) >= since && by(Date.parse(chat.lastMessageAt))).length;
|
|
6394
6539
|
coverage.push({
|
|
6395
6540
|
account: name(key),
|
|
6396
6541
|
storedAt,
|
|
@@ -6410,9 +6555,13 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6410
6555
|
owedHere++;
|
|
6411
6556
|
}
|
|
6412
6557
|
if (owedHere)
|
|
6413
|
-
owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin /
|
|
6558
|
+
owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin / DAY7)}d`);
|
|
6414
6559
|
for (const chatId of watched.chats.get(name(key)) ?? []) {
|
|
6415
|
-
const page = await store.messages.messages(key, chatId, {
|
|
6560
|
+
const page = await store.messages.messages(key, chatId, {
|
|
6561
|
+
limit,
|
|
6562
|
+
since: iso(since),
|
|
6563
|
+
...until === void 0 ? {} : { until }
|
|
6564
|
+
});
|
|
6416
6565
|
for (const message of page.items)
|
|
6417
6566
|
watch.push({
|
|
6418
6567
|
item: {
|
|
@@ -6433,15 +6582,15 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6433
6582
|
}
|
|
6434
6583
|
for (const key of mailboxes) {
|
|
6435
6584
|
const stored = await store.accounts.storedAccount(key);
|
|
6436
|
-
const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS *
|
|
6585
|
+
const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS * DAY7));
|
|
6437
6586
|
const ref = /* @__PURE__ */ __name((thread) => formatReference({ type: "chat", provider: "email", account: key.account, chat: thread }), "ref");
|
|
6438
6587
|
const newest = threads.reduce((most, thread) => Math.max(most, thread.lastEmailAt), 0);
|
|
6439
6588
|
checkHealth(key, {
|
|
6440
6589
|
newest: newest || null,
|
|
6441
|
-
moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 *
|
|
6590
|
+
moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 * DAY7).length,
|
|
6442
6591
|
storedAt: newest || null
|
|
6443
6592
|
});
|
|
6444
|
-
mailMoved += threads.filter((thread) => thread.lastEmailAt >= since && thread.newest !== null && personal(thread.newest)).length;
|
|
6593
|
+
mailMoved += threads.filter((thread) => thread.lastEmailAt >= since && by(thread.lastEmailAt) && thread.newest !== null && personal(thread.newest)).length;
|
|
6445
6594
|
coverage.push({
|
|
6446
6595
|
account: name(key),
|
|
6447
6596
|
storedAt: newest ? iso(newest) : null,
|
|
@@ -6549,7 +6698,8 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6549
6698
|
}
|
|
6550
6699
|
const hot = await gatherTasks(store, [...messengers2, ...mailboxes], {
|
|
6551
6700
|
now,
|
|
6552
|
-
newSince: newSince ?? previousDigestAt(env, now)
|
|
6701
|
+
newSince: newSince ?? (until === void 0 ? previousDigestAt(env, now) : digestRunBefore(env, until)),
|
|
6702
|
+
...until === void 0 ? {} : { until }
|
|
6553
6703
|
});
|
|
6554
6704
|
const tasks = hot.tasks.map(({ task, groups, askedBy, for: doer }) => ({
|
|
6555
6705
|
item: {
|
|
@@ -6587,7 +6737,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6587
6737
|
});
|
|
6588
6738
|
}
|
|
6589
6739
|
const reviews = await listReview(store, env, [`kind:${SOURCE_REVIEW_KIND}`], { limit: 50, page: 1 });
|
|
6590
|
-
const sourceItems = reviews.items.filter((row) => Date.parse(row.createdAt) >= since).map((row) => ({
|
|
6740
|
+
const sourceItems = reviews.items.filter((row) => Date.parse(row.createdAt) >= since && by(Date.parse(row.createdAt))).map((row) => ({
|
|
6591
6741
|
item: {
|
|
6592
6742
|
ref: row.subject,
|
|
6593
6743
|
who: row.proposer,
|
|
@@ -6599,7 +6749,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6599
6749
|
const reviewCount = sourceItems.length;
|
|
6600
6750
|
const reviewed = new Set(reviews.items.flatMap((row) => row.evidence));
|
|
6601
6751
|
for (const changed of await store.knowledge.changedSources({ since }))
|
|
6602
|
-
if (!reviewed.has(changed.ref))
|
|
6752
|
+
if (!reviewed.has(changed.ref) && by(Date.parse(changed.checkedAt)))
|
|
6603
6753
|
sourceItems.push({
|
|
6604
6754
|
item: {
|
|
6605
6755
|
ref: changed.ref,
|
|
@@ -6621,27 +6771,30 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6621
6771
|
}
|
|
6622
6772
|
}));
|
|
6623
6773
|
const sections = [
|
|
6624
|
-
await section("watch", watch, limit, [
|
|
6774
|
+
await section("watch", upTo(watch), limit, [
|
|
6625
6775
|
"memo tags list tag:watch",
|
|
6626
6776
|
...[...watched.people].map((uid) => `memo context person:${uid}`)
|
|
6627
6777
|
]),
|
|
6628
6778
|
{
|
|
6629
|
-
...await section("owed", owed, limit, [
|
|
6779
|
+
...await section("owed", upTo(owed), limit, [
|
|
6630
6780
|
...owedNext,
|
|
6631
6781
|
...olderMail ? [`# ${olderMail} mail threads owed from before the window left out`] : []
|
|
6632
6782
|
]),
|
|
6633
6783
|
...unknown2.count ? { unknown: unknown2 } : {}
|
|
6634
6784
|
},
|
|
6635
|
-
await section("mail", mail, limit, [
|
|
6636
|
-
|
|
6785
|
+
await section("mail", upTo(mail), limit, [
|
|
6786
|
+
...mailNext,
|
|
6787
|
+
...bulk ? [`# ${bulk} bulk or list threads left out`] : []
|
|
6788
|
+
]),
|
|
6789
|
+
await section("meetings", upTo(meetings2), limit, ["memo search meetings <words>"]),
|
|
6637
6790
|
await section("tasks", tasks, limit, ["memo tasks list"]),
|
|
6638
|
-
await section("projects", projects, limit, projectNext),
|
|
6791
|
+
await section("projects", upTo(projects), limit, projectNext),
|
|
6639
6792
|
await section("sources", sourceItems, limit, [
|
|
6640
6793
|
REVIEW_SOURCES,
|
|
6641
6794
|
...reviewCount > 0 ? [`# decide them: ${REVIEW_SOURCES}`] : [],
|
|
6642
6795
|
...sourceItems.length > reviewCount ? [`# read changed sources again: memo memories check --since-time ${days2} --json`] : []
|
|
6643
6796
|
]),
|
|
6644
|
-
await section("proposals", proposals, limit, ["memo review list"], waiting2.total)
|
|
6797
|
+
await section("proposals", upTo(proposals), limit, ["memo review list"], waiting2.total)
|
|
6645
6798
|
];
|
|
6646
6799
|
const providerCount = /* @__PURE__ */ __name((provider) => accounts.filter((key) => key.provider === provider).length, "providerCount");
|
|
6647
6800
|
const meetingAccounts = accounts.filter((key) => kindOf(key.provider) === "meetings").length;
|
|
@@ -6660,7 +6813,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
6660
6813
|
from: iso(since),
|
|
6661
6814
|
to: iso(now),
|
|
6662
6815
|
sources: sources.filter((one2) => one2.accounts > 0),
|
|
6663
|
-
counts: { chats: chatsMoved, mail: mailMoved, tasks: hot.tasks.length, meetings: meetings2.length }
|
|
6816
|
+
counts: { chats: chatsMoved, mail: mailMoved, tasks: hot.tasks.length, meetings: upTo(meetings2).length }
|
|
6664
6817
|
},
|
|
6665
6818
|
tasks: hot.counts,
|
|
6666
6819
|
health: health.sort((a, b) => HEALTH_ORDER.indexOf(a.reason) - HEALTH_ORDER.indexOf(b.reason)),
|
|
@@ -6725,16 +6878,30 @@ var sinceOf = /* @__PURE__ */ __name((value, now = Date.now()) => {
|
|
|
6725
6878
|
});
|
|
6726
6879
|
return since;
|
|
6727
6880
|
}, "sinceOf");
|
|
6881
|
+
var beforeOf = /* @__PURE__ */ __name((value, now = Date.now()) => {
|
|
6882
|
+
const at = /^\d{4}-\d{2}-\d{2}$/.test(value) ? (/* @__PURE__ */ new Date(`${value}T00:00:00`)).getTime() : Date.parse(value);
|
|
6883
|
+
if (!/^\d{4}-\d{2}-\d{2}/.test(value) || Number.isNaN(at))
|
|
6884
|
+
throw new CliError("validation_error", `--before-time takes an ISO time or a date, not "${value}"`, {
|
|
6885
|
+
param: "before-time"
|
|
6886
|
+
});
|
|
6887
|
+
if (at > now)
|
|
6888
|
+
throw new CliError("validation_error", "--before-time is in the future; leave it out for now", {
|
|
6889
|
+
param: "before-time"
|
|
6890
|
+
});
|
|
6891
|
+
return at;
|
|
6892
|
+
}, "beforeOf");
|
|
6728
6893
|
var reviewAgendaCommand = /* @__PURE__ */ __name((review, print, streams, env) => {
|
|
6729
|
-
annotate(review.command("agenda"), { effects: LOCAL_READ }).summary("the morning digest: watch list, owed replies, mail, meetings, tasks, projects").description(`the morning digest, from the store alone with no model call: everything new in what you tagged ${WATCH_TAG} (chats, mail threads, people, projects, a meeting's series), replies you owe to people in messengers and personal mail (not bots or service chats), new personal mail, meetings that ended, tasks, projects that moved, memories and facts whose sources changed (source reviews raised since), proposals waiting. Tasks are the open ones created since the last morning-digest run (a day back when none ran) and those overdue, due today or due tomorrow, each with who asked and who does it. Replies owed reach back 7 days; owed mail lists only senders you know (linked to a person with other identities, or written to before), and mail from new senders is one count with the command that lists it. Each item has its reference, who, when, one line of text and why it is there; a section cut by --limit or --max-output-bytes says how many it left out and the command that reads them. \`scope\` says what was read (the window, sources, counts), \`tasks\` counts each task group and, as \`undated\`, every open task with no due date, and \`health\` names each account whose sync failed, that nothing syncs, or that is quiet for longer than usual, so an unsynced account does not read as a quiet day; an account stored or synced within a day is never named`).option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").option("--limit <n>", "items per section before the size budget", positive, 25).option("--max-output-bytes <bytes>", "the text answer's size budget in bytes; 40000 with --compact, else 80000", positive).option("--compact", "one line per item, shorter excerpts, the smaller budget: for an agent").option("--json", "print JSON").action(async (given2) => {
|
|
6894
|
+
annotate(review.command("agenda"), { effects: LOCAL_READ }).summary("the morning digest: watch list, owed replies, mail, meetings, tasks, projects").description(`the morning digest, from the store alone with no model call: everything new in what you tagged ${WATCH_TAG} (chats, mail threads, people, projects, a meeting's series), replies you owe to people in messengers and personal mail (not bots or service chats), new personal mail, meetings that ended, tasks, projects that moved, memories and facts whose sources changed (source reviews raised since), proposals waiting. Tasks are the open ones created since the last morning-digest run (a day back when none ran) and those overdue, due today or due tomorrow, each with who asked and who does it. Replies owed reach back 7 days; owed mail lists only senders you know (linked to a person with other identities, or written to before), and mail from new senders is one count with the command that lists it. Each item has its reference, who, when, one line of text and why it is there; a section cut by --limit or --max-output-bytes says how many it left out and the command that reads them. \`scope\` says what was read (the window, sources, counts), \`tasks\` counts each task group and, as \`undated\`, every open task with no due date, and \`health\` names each account whose sync failed, that nothing syncs, or that is quiet for longer than usual, so an unsynced account does not read as a quiet day; an account stored or synced within a day is never named`).option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").option("--before-time <time>", "build it as of this past ISO time or date, for a past day's digest: --since-time counts back from it, and what came later is left out; a chat or thread answered since reads as answered").option("--limit <n>", "items per section before the size budget", positive, 25).option("--max-output-bytes <bytes>", "the text answer's size budget in bytes; 40000 with --compact, else 80000", positive).option("--compact", "one line per item, shorter excerpts, the smaller budget: for an agent").option("--json", "print JSON").action(async (given2) => {
|
|
6730
6895
|
if (given2.compact && given2.json)
|
|
6731
6896
|
throw new CliError("validation_error", "--compact and --json ask for different output \u2014 pick one", {
|
|
6732
6897
|
reason: "output.conflict",
|
|
6733
6898
|
param: "--compact"
|
|
6734
6899
|
});
|
|
6735
|
-
const
|
|
6900
|
+
const until = given2.beforeTime === void 0 ? void 0 : beforeOf(given2.beforeTime);
|
|
6901
|
+
const since = sinceOf(given2.sinceTime, until);
|
|
6736
6902
|
const gathered = await withStore(env, (store) => gatherDigest(store, env, {
|
|
6737
6903
|
since,
|
|
6904
|
+
...until === void 0 ? {} : { until },
|
|
6738
6905
|
limit: given2.limit,
|
|
6739
6906
|
excerpt: given2.compact ? 100 : 200,
|
|
6740
6907
|
owedWithin: OWED_WITHIN
|
|
@@ -8278,7 +8445,7 @@ var projectFindings = /* @__PURE__ */ __name(async (store, project, links) => {
|
|
|
8278
8445
|
// dist/knowledge/project-context.js
|
|
8279
8446
|
var projectContext = /* @__PURE__ */ __name(async (store, env, reference2) => {
|
|
8280
8447
|
const project = await projectOf(store, reference2);
|
|
8281
|
-
const relationships = (await store.notes.links({ to: project.ref })).concat(await store.notes.links({ from: project.ref })).filter((link2) => link2.kind !== "about" && link2.kind !== "links-to" && link2.role !== "key");
|
|
8448
|
+
const relationships = byEngagement((await store.notes.links({ to: project.ref })).concat(await store.notes.links({ from: project.ref })).filter((link2) => link2.kind !== "about" && link2.kind !== "links-to" && link2.role !== "key"));
|
|
8282
8449
|
const documents = await keyDocuments(store, project);
|
|
8283
8450
|
const pending2 = /* @__PURE__ */ __name((kind) => proposalRegistry(store).list({ project: project.ref, kinds: [kind], status: "proposed", limit: 50, offset: 0 }), "pending");
|
|
8284
8451
|
const [facts, tasks, findings, keys, links, waiting2] = await Promise.all([
|
|
@@ -8351,7 +8518,7 @@ var projectContextText = /* @__PURE__ */ __name((context) => {
|
|
|
8351
8518
|
}, "projectContextText");
|
|
8352
8519
|
|
|
8353
8520
|
// dist/knowledge/relationships-scan.js
|
|
8354
|
-
var
|
|
8521
|
+
var DAY8 = 864e5;
|
|
8355
8522
|
var SCAN_STEP = {
|
|
8356
8523
|
id: "relationships.scan",
|
|
8357
8524
|
kind: "command",
|
|
@@ -8425,7 +8592,7 @@ var relationshipsScanCommand = /* @__PURE__ */ __name((relations, print, env, wa
|
|
|
8425
8592
|
if (options.limit > 50)
|
|
8426
8593
|
throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
|
|
8427
8594
|
const window = projectWindowOf(options.sinceTime);
|
|
8428
|
-
const since = new Date("days" in window ? Date.now() - window.days *
|
|
8595
|
+
const since = new Date("days" in window ? Date.now() - window.days * DAY8 : window.after).toISOString();
|
|
8429
8596
|
const written2 = options.yes === true;
|
|
8430
8597
|
const { body, text: text3 } = await withStore(env, async (store) => {
|
|
8431
8598
|
const sources = await namedAccounts(store, env, options, warn);
|
|
@@ -8735,7 +8902,7 @@ var listRelationships = /* @__PURE__ */ __name(async (store, words) => {
|
|
|
8735
8902
|
const confirmed = terms2.get("confirmed");
|
|
8736
8903
|
const found = confirmed === "false" ? await pending(store, about) : {
|
|
8737
8904
|
hasMore: false,
|
|
8738
|
-
items: (await store.knowledge.relations(null, about)).filter((one2) => confirmed === void 0 || one2.confirmed).map((one2) => ({ ...one2, status: one2.confirmed ? "confirmed" : "proposed" }))
|
|
8905
|
+
items: byEngagement(await store.knowledge.relations(null, about)).filter((one2) => confirmed === void 0 || one2.confirmed).map((one2) => ({ ...one2, status: one2.confirmed ? "confirmed" : "proposed" }))
|
|
8739
8906
|
};
|
|
8740
8907
|
const label = await labelsFor(store, found.items.flatMap((one2) => [one2.from, one2.to]));
|
|
8741
8908
|
return {
|
|
@@ -8747,7 +8914,13 @@ var listRelationships = /* @__PURE__ */ __name(async (store, words) => {
|
|
|
8747
8914
|
var relationshipsText = /* @__PURE__ */ __name((items) => items.length ? items.map((one2) => [
|
|
8748
8915
|
one2.id,
|
|
8749
8916
|
`${one2.fromTitle} \u2192 ${one2.toTitle}`,
|
|
8750
|
-
[
|
|
8917
|
+
[
|
|
8918
|
+
one2.kind,
|
|
8919
|
+
one2.role && `as ${one2.role}`,
|
|
8920
|
+
"roleNote" in one2 && one2.roleNote && `(${one2.roleNote})`,
|
|
8921
|
+
one2.purpose && `for ${one2.purpose}`,
|
|
8922
|
+
"engagement" in one2 && one2.engagement && `engagement ${one2.engagement}`
|
|
8923
|
+
].filter(Boolean).join(" "),
|
|
8751
8924
|
"proposer" in one2 ? `proposed by ${one2.proposer}` : one2.confirmed ? "" : "suggested"
|
|
8752
8925
|
].filter(Boolean).join(" ")).join("\n") : "no relationships", "relationshipsText");
|
|
8753
8926
|
|
|
@@ -8761,6 +8934,7 @@ var pendingLink = /* @__PURE__ */ __name(async (store, id) => {
|
|
|
8761
8934
|
throw error;
|
|
8762
8935
|
}
|
|
8763
8936
|
}, "pendingLink");
|
|
8937
|
+
var ENGAGEMENT_HELP = "a person on a project: how much you deal with them yourself, not how active they are: none, low, medium or high";
|
|
8764
8938
|
var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
8765
8939
|
const { run, print } = answers(program, streams, env);
|
|
8766
8940
|
const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
|
|
@@ -8838,7 +9012,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
8838
9012
|
return ownedList("projects key-documents list", options, async (store) => keyDocuments(store, await projectOf(store, project), id === void 0 ? {} : { id }));
|
|
8839
9013
|
});
|
|
8840
9014
|
const relations = program.command("relationships").description("relations between people, organizations and projects; never between identities");
|
|
8841
|
-
byOption(annotate(relations.command("add"), { effects: LOCAL_WRITE }).description("state that a person, organization or project belongs to or relates to another, or that a chat is a project's (member-of only); an agent's waits for you to confirm it").summary("state that a person, organization, project or chat belongs or relates to another")).argument("<from>", "the person:, organization: or project: that belongs or relates, or chat:<provider>/<account>/<chat> of a project").argument("<to>", "the person:, organization: or project: it belongs or relates to").option("--json", "print JSON; --json=id,title keeps only those fields").option("--kind <kind>", "member-of or related-to", "member-of").option("--role <role>", "the role it has there; a person's role in an organization or a project is one from its list, such as employee or contributor").option("--reason <text>", "why you think so, in a sentence").action(async (from, to, options, command) => {
|
|
9015
|
+
byOption(annotate(relations.command("add"), { effects: LOCAL_WRITE }).description("state that a person, organization or project belongs to or relates to another, or that a chat is a project's (member-of only); an agent's waits for you to confirm it").summary("state that a person, organization, project or chat belongs or relates to another")).argument("<from>", "the person:, organization: or project: that belongs or relates, or chat:<provider>/<account>/<chat> of a project").argument("<to>", "the person:, organization: or project: it belongs or relates to").option("--json", "print JSON; --json=id,title keeps only those fields").option("--kind <kind>", "member-of or related-to", "member-of").option("--role <role>", "the role it has there; a person's role in an organization or a project is one from its list, such as employee or contributor").option("--role-note <text>", "what the role means here, in your words, beside a role from its list").option("--engagement <level>", ENGAGEMENT_HELP, oneOf(ENGAGEMENT_LEVELS)).option("--reason <text>", "why you think so, in a sentence").action(async (from, to, options, command) => {
|
|
8842
9016
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "state it as yours?" });
|
|
8843
9017
|
return owned(options, async (store) => {
|
|
8844
9018
|
const input = {
|
|
@@ -8846,6 +9020,8 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
8846
9020
|
to: await withOwner(store, to),
|
|
8847
9021
|
kind: options.kind,
|
|
8848
9022
|
...options.role === void 0 ? {} : { role: options.role },
|
|
9023
|
+
...options.roleNote === void 0 ? {} : { roleNote: options.roleNote },
|
|
9024
|
+
...options.engagement === void 0 ? {} : { engagement: options.engagement },
|
|
8849
9025
|
...options.reason === void 0 ? {} : { evidence: options.reason }
|
|
8850
9026
|
};
|
|
8851
9027
|
return by === "owner" ? store.knowledge.relate(null, { ...input, by }) : store.knowledge.relate(null, { ...input, by });
|
|
@@ -8855,15 +9031,18 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
8855
9031
|
const found = await withStore(env, (store) => listRelationships(store, words));
|
|
8856
9032
|
print(options.json, listAnswer("relationships list", { items: found.items, limit: found.limit, has_more: found.hasMore }), relationshipsText(found.items));
|
|
8857
9033
|
});
|
|
8858
|
-
byOption(annotate(relations.command("update"), { effects: LOCAL_WRITE }).description("set what a relationship is: its role, or what a chat is for in a project (work, sales, support, other); an agent's change waits for you in memo review").summary("set a relationship's role or a chat's purpose in a project").argument("<id>", "the relationship's id, as relationships list gives it").option("--role <role>", "the role it has there, from the same list as relationships add; an empty value clears it").option("--purpose <purpose>", "what the chat is for in the project: work, sales, support or other").option("--reason <text>", "why, in a sentence").option("--json", "print JSON; --json=id,title keeps only those fields")).action(async (id, options, command) => {
|
|
9034
|
+
byOption(annotate(relations.command("update"), { effects: LOCAL_WRITE }).description("set what a relationship is: its role and a note beside it, how much you deal with a person on a project, or what a chat is for in a project (work, sales, support, other); an agent's change waits for you in memo review").summary("set a relationship's role, engagement or a chat's purpose in a project").argument("<id>", "the relationship's id, as relationships list gives it").option("--role <role>", "the role it has there, from the same list as relationships add; an empty value clears it").option("--role-note <text>", "what the role means here, in your words; an empty value clears it").option("--engagement <level>", `${ENGAGEMENT_HELP}; an empty value clears it`, (value) => value === "" ? "" : oneOf(ENGAGEMENT_LEVELS)(value)).option("--purpose <purpose>", "what the chat is for in the project: work, sales, support or other").option("--reason <text>", "why, in a sentence").option("--json", "print JSON; --json=id,title keeps only those fields")).action(async (id, options, command) => {
|
|
9035
|
+
const cleared = /* @__PURE__ */ __name((value) => value === "" ? null : value, "cleared");
|
|
8859
9036
|
const change = {
|
|
8860
|
-
...options.role === void 0 ? {} : { role: options.role
|
|
9037
|
+
...options.role === void 0 ? {} : { role: cleared(options.role) },
|
|
9038
|
+
...options.roleNote === void 0 ? {} : { roleNote: cleared(options.roleNote) },
|
|
9039
|
+
...options.engagement === void 0 ? {} : { engagement: cleared(options.engagement) },
|
|
8861
9040
|
...options.purpose === void 0 ? {} : { purpose: options.purpose }
|
|
8862
9041
|
};
|
|
8863
9042
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change relationship ${id}?` });
|
|
8864
9043
|
return owned(options, (store) => {
|
|
8865
|
-
if (
|
|
8866
|
-
throw new CliError("validation_error", "say what to change: --role, --
|
|
9044
|
+
if (!Object.keys(change).length)
|
|
9045
|
+
throw new CliError("validation_error", "say what to change: --role, --role-note, --engagement or --purpose", {
|
|
8867
9046
|
reason: "input.invalid",
|
|
8868
9047
|
param: "--purpose"
|
|
8869
9048
|
});
|
|
@@ -9327,9 +9506,9 @@ var messagesCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9327
9506
|
}, "messagesCommand");
|
|
9328
9507
|
|
|
9329
9508
|
// dist/mcp/command.js
|
|
9330
|
-
import { join as
|
|
9509
|
+
import { join as join8 } from "node:path";
|
|
9331
9510
|
var DEFAULT_PORT = 8767;
|
|
9332
|
-
var httpTokenFile = /* @__PURE__ */ __name((env) =>
|
|
9511
|
+
var httpTokenFile = /* @__PURE__ */ __name((env) => join8(resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env }).state, "mcp-http", "memo.json"), "httpTokenFile");
|
|
9333
9512
|
var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, createProgram2) => {
|
|
9334
9513
|
const out = answers(program, streams, env);
|
|
9335
9514
|
const mcp2 = annotate(program.command("mcp"), { effects: LOCAL_READ, mcp: false }).summary("serve this profile's commands to an AI agent, and set that up").description("serve memo commands over MCP on stdio or authenticated HTTP, limited by saved permissions \u2014 `claude mcp add memo -- memo mcp serve`");
|
|
@@ -9341,10 +9520,10 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
|
|
|
9341
9520
|
}).summary("serve this profile's commands to an AI agent").description("serve memo commands over MCP on stdio or authenticated HTTP, limited by saved permissions").option("--permission <key=level>", "tighten one saved permission for this server; repeat for more keys", (value, previous = []) => [...previous, value]).option("--http", "serve on 127.0.0.1 behind an HTTPS tunnel with an owner access-code login").option("--port <port>", `local HTTP port (default ${DEFAULT_PORT}); requires --http`).option("--public-url <url>", "tunnel's HTTPS address without /mcp, or a path of it such as https://<name>.ts.net/memo; requires --http").action(async (options) => {
|
|
9342
9521
|
if (!options.http && (options.port !== void 0 || options.publicUrl !== void 0))
|
|
9343
9522
|
throw new CliError("validation_error", "--port and --public-url require --http");
|
|
9344
|
-
const { createMemoServer } = await import("./server-
|
|
9523
|
+
const { createMemoServer } = await import("./server-JLPZUC42.js");
|
|
9345
9524
|
const build = /* @__PURE__ */ __name(() => createMemoServer(env, createProgram2, options.permission), "build");
|
|
9346
9525
|
if (options.http) {
|
|
9347
|
-
const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-
|
|
9526
|
+
const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-CFIL7WZU.js");
|
|
9348
9527
|
const publicUrl = publicUrlOf(options.publicUrl, {
|
|
9349
9528
|
missing: "--http",
|
|
9350
9529
|
reaches: "the browser apps reach memo",
|
|
@@ -9396,7 +9575,7 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
|
|
|
9396
9575
|
});
|
|
9397
9576
|
});
|
|
9398
9577
|
annotate(mcp2.command("revoke"), { effects: LOCAL_WRITE, mcp: false, examples: ["memo mcp revoke --json"] }).summary("forget every login given to a browser app").description("forget every login `memo mcp serve --http` gave a browser app; each app must log in again").option("--json", "print JSON").action(async function() {
|
|
9399
|
-
const { revokeAll } = await import("./mcp-
|
|
9578
|
+
const { revokeAll } = await import("./mcp-CFIL7WZU.js");
|
|
9400
9579
|
revokeAll(httpTokenFile(env));
|
|
9401
9580
|
out.print(this.opts().json, itemAnswer({ revoked: true }));
|
|
9402
9581
|
});
|
|
@@ -9725,8 +9904,8 @@ import { resolve as resolve3 } from "node:path";
|
|
|
9725
9904
|
|
|
9726
9905
|
// dist/notes/export.js
|
|
9727
9906
|
import { createHash as createHash3 } from "node:crypto";
|
|
9728
|
-
import { existsSync as
|
|
9729
|
-
import { join as
|
|
9907
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync6, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
9908
|
+
import { join as join9 } from "node:path";
|
|
9730
9909
|
var HASH_LINE = /^memo-hash: .*\r?\n/m;
|
|
9731
9910
|
var PLACEHOLDER = "f".repeat(64);
|
|
9732
9911
|
var UNSAFE = /[\\/:*?"<>|#^[\]\p{Cc}]/gu;
|
|
@@ -9747,10 +9926,10 @@ var fileName = /* @__PURE__ */ __name((title, id, taken) => {
|
|
|
9747
9926
|
}, "fileName");
|
|
9748
9927
|
var exportedIn = /* @__PURE__ */ __name((dir) => {
|
|
9749
9928
|
const found = /* @__PURE__ */ new Map();
|
|
9750
|
-
for (const entry of
|
|
9929
|
+
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
9751
9930
|
if (!entry.isFile() || !/\.(md|markdown)$/i.test(entry.name))
|
|
9752
9931
|
continue;
|
|
9753
|
-
const id = readMemoId(
|
|
9932
|
+
const id = readMemoId(join9(dir, entry.name));
|
|
9754
9933
|
if (id !== null)
|
|
9755
9934
|
found.set(id, entry.name);
|
|
9756
9935
|
}
|
|
@@ -9767,9 +9946,9 @@ var exportNotes = /* @__PURE__ */ __name(({ dir, dialect, notes: notes2 }) => {
|
|
|
9767
9946
|
frontMatter["memo-hash"] = PLACEHOLDER;
|
|
9768
9947
|
const content = withHash(dialect.render({ ...note, frontMatter }));
|
|
9769
9948
|
const known2 = existing.get(id);
|
|
9770
|
-
const name2 = known2 ?? fileName(note.title, id, (candidate) => claimed.has(candidate) ||
|
|
9949
|
+
const name2 = known2 ?? fileName(note.title, id, (candidate) => claimed.has(candidate) || existsSync8(join9(dir, candidate)));
|
|
9771
9950
|
claimed.add(name2);
|
|
9772
|
-
const path =
|
|
9951
|
+
const path = join9(dir, name2);
|
|
9773
9952
|
if (known2 !== void 0) {
|
|
9774
9953
|
const current = readFileSync7(path, "utf8");
|
|
9775
9954
|
if (editedSinceExport(current)) {
|
|
@@ -9781,7 +9960,7 @@ var exportNotes = /* @__PURE__ */ __name(({ dir, dialect, notes: notes2 }) => {
|
|
|
9781
9960
|
continue;
|
|
9782
9961
|
}
|
|
9783
9962
|
}
|
|
9784
|
-
const partial =
|
|
9963
|
+
const partial = join9(dir, `.${name2}.memo-tmp`);
|
|
9785
9964
|
writeFileSync3(partial, content);
|
|
9786
9965
|
renameSync2(partial, path);
|
|
9787
9966
|
result.written.push(path);
|
|
@@ -10038,9 +10217,9 @@ import { statSync as statSync4 } from "node:fs";
|
|
|
10038
10217
|
import { basename as basename2, resolve as resolve4 } from "node:path";
|
|
10039
10218
|
|
|
10040
10219
|
// dist/run/lock.js
|
|
10041
|
-
import { join as
|
|
10220
|
+
import { join as join10 } from "node:path";
|
|
10042
10221
|
var withImportLock = /* @__PURE__ */ __name(async (env, work) => {
|
|
10043
|
-
const lock =
|
|
10222
|
+
const lock = join10(resolvePaths({ appName: "cli-memo", prefix: "MEMO", env }).state, "import.lock");
|
|
10044
10223
|
const holder = takeLock(lock, { pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10045
10224
|
if (holder !== void 0)
|
|
10046
10225
|
throw new CliError("rate_limited", `another memo sync is running (process ${holder.pid}); try again when it ends`, {
|
|
@@ -10171,7 +10350,7 @@ var foldersCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
10171
10350
|
}, "foldersCommand");
|
|
10172
10351
|
|
|
10173
10352
|
// dist/people/command.js
|
|
10174
|
-
import { join as
|
|
10353
|
+
import { join as join11 } from "node:path";
|
|
10175
10354
|
var noteCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
10176
10355
|
const notes2 = program.commands.find((command) => command.name() === "notes") ?? program.command("notes");
|
|
10177
10356
|
const links = notes2.command("links").description("imported note files linked to the person behind an identity");
|
|
@@ -10224,7 +10403,7 @@ var noteCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
10224
10403
|
}
|
|
10225
10404
|
const paths = (await files()).map(({ note }) => {
|
|
10226
10405
|
const folder = folders.find((candidate) => candidate.id === note.folderId);
|
|
10227
|
-
return folder ?
|
|
10406
|
+
return folder ? join11(folder.path, note.path) : note.ref;
|
|
10228
10407
|
});
|
|
10229
10408
|
return { person: to, name: person.name ?? person.uid, files: paths };
|
|
10230
10409
|
});
|
|
@@ -10667,8 +10846,8 @@ ${SOURCE_REVIEW_HELP}`);
|
|
|
10667
10846
|
}, "reviewCommand");
|
|
10668
10847
|
|
|
10669
10848
|
// dist/notes/embed.js
|
|
10670
|
-
import { existsSync as
|
|
10671
|
-
import { join as
|
|
10849
|
+
import { existsSync as existsSync9, readdirSync as readdirSync7 } from "node:fs";
|
|
10850
|
+
import { join as join12 } from "node:path";
|
|
10672
10851
|
var EMBED_PER_RUN = 600;
|
|
10673
10852
|
var SLOWEST_KNOWN = 2;
|
|
10674
10853
|
var embedPerRun = /* @__PURE__ */ __name((env = process.env) => {
|
|
@@ -10685,8 +10864,8 @@ var missingModel = /* @__PURE__ */ __name((error, env) => {
|
|
|
10685
10864
|
}, "missingModel");
|
|
10686
10865
|
var searchModelPresent = /* @__PURE__ */ __name((env) => {
|
|
10687
10866
|
try {
|
|
10688
|
-
const path =
|
|
10689
|
-
return
|
|
10867
|
+
const path = join12(sharedModelsDirectory("text", env), chosenTextModel(env).id);
|
|
10868
|
+
return existsSync9(path) && readdirSync7(path).length > 0;
|
|
10690
10869
|
} catch {
|
|
10691
10870
|
return false;
|
|
10692
10871
|
}
|
|
@@ -11127,10 +11306,12 @@ var mailTriageInput = /* @__PURE__ */ __name((mailboxes) => async (schedule, run
|
|
|
11127
11306
|
}, "mailTriageInput");
|
|
11128
11307
|
|
|
11129
11308
|
// dist/schedule/command.js
|
|
11309
|
+
var MAIL_CLI = { command: "mail", appName: "mail-cli", envPrefix: "MAIL" };
|
|
11130
11310
|
var scheduleCommand = /* @__PURE__ */ __name((env) => {
|
|
11131
11311
|
const schedule = scheduleCommandFor({
|
|
11132
11312
|
app: APP,
|
|
11133
11313
|
context: /* @__PURE__ */ __name((command) => ({ ...outputFor(command), env, profile: "" }), "context"),
|
|
11314
|
+
agentRuns: [MAIL_CLI],
|
|
11134
11315
|
newMail: /* @__PURE__ */ __name((_command, holder) => withStore(env, async (store) => {
|
|
11135
11316
|
const triage = bulkTriage(env);
|
|
11136
11317
|
await advancePastSkipped(store, holder, Date.now(), triage);
|
|
@@ -11144,7 +11325,7 @@ var scheduleCommand = /* @__PURE__ */ __name((env) => {
|
|
|
11144
11325
|
command.option("--json", "print JSON");
|
|
11145
11326
|
});
|
|
11146
11327
|
for (const one2 of schedule.commands.filter((command) => ["run", "exec"].includes(command.name())))
|
|
11147
|
-
overrideSharedContract(one2, "A memo schedule runs memo, which writes to no remote service, or an agent allowed only memo
|
|
11328
|
+
overrideSharedContract(one2, "A memo schedule runs memo, which writes to no remote service, or an agent allowed only memo and mail, each read-only.", (command) => {
|
|
11148
11329
|
annotate(command, { effects: LOCAL_WRITE });
|
|
11149
11330
|
});
|
|
11150
11331
|
return schedule;
|
|
@@ -11587,17 +11768,17 @@ var showCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
11587
11768
|
}, "showCommand");
|
|
11588
11769
|
|
|
11589
11770
|
// dist/sources/command.js
|
|
11590
|
-
import { existsSync as
|
|
11771
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
11591
11772
|
|
|
11592
11773
|
// dist/sources/copy.js
|
|
11593
11774
|
import { randomUUID } from "node:crypto";
|
|
11594
|
-
import { existsSync as
|
|
11595
|
-
import { isAbsolute, join as
|
|
11596
|
-
var copiesDir = /* @__PURE__ */ __name((env) =>
|
|
11597
|
-
var copyPath = /* @__PURE__ */ __name((env, hash) =>
|
|
11775
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
11776
|
+
import { isAbsolute, join as join13, relative as relative2, resolve as resolve5, sep as sep2 } from "node:path";
|
|
11777
|
+
var copiesDir = /* @__PURE__ */ __name((env) => join13(resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env }).state, "sources"), "copiesDir");
|
|
11778
|
+
var copyPath = /* @__PURE__ */ __name((env, hash) => join13(copiesDir(env), hash), "copyPath");
|
|
11598
11779
|
var keepCopy = /* @__PURE__ */ __name((env, hash, bytes) => {
|
|
11599
11780
|
const path = copyPath(env, hash);
|
|
11600
|
-
if (
|
|
11781
|
+
if (existsSync10(path))
|
|
11601
11782
|
return { path, wrote: false };
|
|
11602
11783
|
mkdirSync4(copiesDir(env), { recursive: true, mode: 448 });
|
|
11603
11784
|
const partial = `${path}.${randomUUID()}.part`;
|
|
@@ -11607,7 +11788,7 @@ var keepCopy = /* @__PURE__ */ __name((env, hash, bytes) => {
|
|
|
11607
11788
|
}, "keepCopy");
|
|
11608
11789
|
var dropCopy = /* @__PURE__ */ __name((env, path) => {
|
|
11609
11790
|
const inside2 = relative2(resolve5(copiesDir(env)), resolve5(path));
|
|
11610
|
-
if (!inside2 || isAbsolute(inside2) || inside2.startsWith("..") || inside2.includes(sep2) || !
|
|
11791
|
+
if (!inside2 || isAbsolute(inside2) || inside2.startsWith("..") || inside2.includes(sep2) || !existsSync10(path))
|
|
11611
11792
|
return false;
|
|
11612
11793
|
rmSync2(path);
|
|
11613
11794
|
return true;
|
|
@@ -12003,7 +12184,7 @@ var sourcesCommand = /* @__PURE__ */ __name((program, streams, env, { fetch: fet
|
|
|
12003
12184
|
mime: source?.mime ?? null,
|
|
12004
12185
|
bytes: source?.size ?? null,
|
|
12005
12186
|
// The row says a copy was kept; only the file itself says it still is.
|
|
12006
|
-
kept: source === void 0 ? null : source.copy !== null &&
|
|
12187
|
+
kept: source === void 0 ? null : source.copy !== null && existsSync11(source.copy) ? "copy" : "text",
|
|
12007
12188
|
chars: note.text.length,
|
|
12008
12189
|
text: text3,
|
|
12009
12190
|
textTruncated: truncated,
|
|
@@ -13127,6 +13308,7 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
13127
13308
|
doctorCommand(program, streams, env);
|
|
13128
13309
|
program.addCommand(upgradeCommand(streams));
|
|
13129
13310
|
program.addCommand(scheduleCommand(env));
|
|
13311
|
+
digestCommand(program, streams, env);
|
|
13130
13312
|
commandsCommand(program, streams);
|
|
13131
13313
|
const skill2 = customizeSharedCommand(skillCommand2(APP, new URL("../skills/cli-memo/SKILL.md", new URL("../program.js", import.meta.url).href)), "Memo installs its own stored-data instructions through its environment, prints the packaged primary skill without filesystem effects, and takes --json on each skill command because it has no global one.", () => {
|
|
13132
13314
|
const out = answers(program, streams, env);
|