@wirecat/cli-memo 0.131.62 → 0.131.64
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/{app-server-QBJG7OGQ.js → app-server-7KM4MSDA.js} +9 -9
- package/dist/bundle/{auto-Z4MEU5OY.js → auto-V3FUD6RW.js} +16 -16
- package/dist/bundle/{chunk-LK6D26RK.js → chunk-3SCHFNUH.js} +5 -5
- package/dist/bundle/{chunk-HGNWJJDT.js → chunk-3YNJBKGV.js} +13 -1
- package/dist/bundle/{chunk-Q3VEUHC7.js → chunk-6OS7PTOC.js} +3 -3
- package/dist/bundle/{chunk-2UCLF4AO.js → chunk-DXTNBVLV.js} +394 -115
- package/dist/bundle/{chunk-2VDRVJCR.js → chunk-EDBZEHAU.js} +5 -4
- package/dist/bundle/{chunk-H3COKFXP.js → chunk-FHZKHKBJ.js} +1651 -11
- package/dist/bundle/{chunk-TBSWOVM3.js → chunk-FKUA3BTM.js} +14 -14
- package/dist/bundle/{chunk-TSKGEK2S.js → chunk-LVLFLWGY.js} +3 -3
- package/dist/bundle/{chunk-O2NQCWRM.js → chunk-ML46T7UC.js} +8 -8
- package/dist/bundle/{chunk-XX37LSNV.js → chunk-MYXB2T77.js} +25 -1
- package/dist/bundle/{chunk-WDZOEBTE.js → chunk-NH3A5QTW.js} +2 -2
- package/dist/bundle/{chunk-6OZ2WI7Y.js → chunk-NIJZXGJN.js} +1 -1
- package/dist/bundle/{chunk-EGI6JHIA.js → chunk-NRHF7TQ4.js} +2 -2
- package/dist/bundle/{chunk-WDWKG7FJ.js → chunk-PVGK67AJ.js} +17 -0
- package/dist/bundle/{chunk-E5JQFEIQ.js → chunk-QHNAPLVB.js} +4 -4
- package/dist/bundle/{chunk-SJ55SMBE.js → chunk-QTF4ZXOL.js} +2 -1
- package/dist/bundle/chunk-T3LVSUNZ.js +301 -0
- package/dist/bundle/{chunk-OXBETHGN.js → chunk-UXAP7MNL.js} +4 -4
- package/dist/bundle/{chunk-3ZXWLFUG.js → chunk-VLUDHCCX.js} +3 -3
- package/dist/bundle/{chunk-KREN56SX.js → chunk-WINH45XG.js} +4 -4
- package/dist/bundle/{chunk-FD3OQYFL.js → chunk-XPT5PX7H.js} +4 -4
- package/dist/bundle/{chunk-SJ36WSEI.js → chunk-ZX6SWNSR.js} +3 -3
- package/dist/bundle/{command-contract-SIXWLKAS.js → command-contract-PLB2JGFJ.js} +2 -2
- package/dist/bundle/{entry-SFLEGFSN.js → entry-MUE6HWX3.js} +1 -1
- package/dist/bundle/{failure-B33C3BFU.js → failure-6SP64Q66.js} +14 -14
- package/dist/bundle/{first-run-ZKDGFY6P.js → first-run-3JYWLJCH.js} +1 -1
- package/dist/bundle/{first-screen-IQEU7XF2.js → first-screen-QH34AIFV.js} +3 -3
- package/dist/bundle/{mcp-Y4XMDC5Q.js → mcp-QX2D6EXA.js} +6 -6
- package/dist/bundle/memo.js +6 -6
- package/dist/bundle/{program-DSQWICNB.js → program-LXQLWUAG.js} +1789 -422
- package/dist/bundle/{server-IQILK5YP.js → server-L622PMVC.js} +9 -9
- package/dist/bundle/{server-ZHFC3PIP.js → server-MVJU7QG4.js} +19 -19
- package/dist/bundle/{server-NKI7SVK5.js → server-SJVP2XXD.js} +6 -6
- package/dist/bundle/{store-6H4FPFTX.js → store-M5QSIRWJ.js} +1 -1
- package/dist/bundle/{store-maintenance-command-IFVWSQMJ.js → store-maintenance-command-PQCO5ICC.js} +5 -5
- package/dist/bundle/{update-LR5BVLBD.js → update-MQUCCIBB.js} +15 -15
- package/dist/contract-overrides/search.js +2 -2
- package/dist/contract-overrides/search.js.map +1 -1
- package/dist/discovery/command.d.ts.map +1 -1
- package/dist/discovery/command.js +6 -0
- package/dist/discovery/command.js.map +1 -1
- package/dist/events/command.d.ts +4 -0
- package/dist/events/command.d.ts.map +1 -0
- package/dist/events/command.js +35 -0
- package/dist/events/command.js.map +1 -0
- package/dist/events/events.d.ts +52 -0
- package/dist/events/events.d.ts.map +1 -0
- package/dist/events/events.js +199 -0
- package/dist/events/events.js.map +1 -0
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +90 -3
- package/dist/examples.js.map +1 -1
- package/dist/finance/command.d.ts +1 -1
- package/dist/finance/command.d.ts.map +1 -1
- package/dist/finance/command.js +13 -30
- package/dist/finance/command.js.map +1 -1
- package/dist/finance/contracts-command.d.ts +12 -0
- package/dist/finance/contracts-command.d.ts.map +1 -0
- package/dist/finance/contracts-command.js +110 -0
- package/dist/finance/contracts-command.js.map +1 -0
- package/dist/finance/deals-command.d.ts.map +1 -1
- package/dist/finance/deals-command.js +5 -4
- package/dist/finance/deals-command.js.map +1 -1
- package/dist/finance/lines-command.d.ts +37 -0
- package/dist/finance/lines-command.d.ts.map +1 -0
- package/dist/finance/lines-command.js +70 -0
- package/dist/finance/lines-command.js.map +1 -0
- package/dist/finance/orders-command.d.ts.map +1 -1
- package/dist/finance/orders-command.js +5 -2
- package/dist/finance/orders-command.js.map +1 -1
- package/dist/finance/products-command.d.ts +12 -0
- package/dist/finance/products-command.d.ts.map +1 -0
- package/dist/finance/products-command.js +99 -0
- package/dist/finance/products-command.js.map +1 -0
- package/dist/finance/subscriptions-command.d.ts +12 -0
- package/dist/finance/subscriptions-command.d.ts.map +1 -0
- package/dist/finance/subscriptions-command.js +153 -0
- package/dist/finance/subscriptions-command.js.map +1 -0
- package/dist/finance/transactions-command.d.ts +12 -0
- package/dist/finance/transactions-command.d.ts.map +1 -0
- package/dist/finance/transactions-command.js +137 -0
- package/dist/finance/transactions-command.js.map +1 -0
- package/dist/finance/wallets-command.d.ts +12 -0
- package/dist/finance/wallets-command.d.ts.map +1 -0
- package/dist/finance/wallets-command.js +106 -0
- package/dist/finance/wallets-command.js.map +1 -0
- package/dist/finance/written.d.ts +37 -0
- package/dist/finance/written.d.ts.map +1 -0
- package/dist/finance/written.js +36 -0
- package/dist/finance/written.js.map +1 -0
- package/dist/knowledge/command.d.ts.map +1 -1
- package/dist/knowledge/command.js +3 -2
- package/dist/knowledge/command.js.map +1 -1
- package/dist/mcp/permissions.d.ts +1 -1
- package/dist/mcp/permissions.d.ts.map +1 -1
- package/dist/mcp/permissions.js +1 -0
- package/dist/mcp/permissions.js.map +1 -1
- package/dist/options.d.ts +2 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +2 -0
- package/dist/options.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +174 -0
- package/dist/program.js.map +1 -1
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +24 -0
- package/dist/reasons.js.map +1 -1
- package/dist/records/import.d.ts +2 -4
- package/dist/records/import.d.ts.map +1 -1
- package/dist/records/import.js +41 -41
- package/dist/records/import.js.map +1 -1
- package/dist/records/input.d.ts +20 -0
- package/dist/records/input.d.ts.map +1 -0
- package/dist/records/input.js +115 -0
- package/dist/records/input.js.map +1 -0
- package/dist/records/mapping.d.ts +16 -1
- package/dist/records/mapping.d.ts.map +1 -1
- package/dist/records/mapping.js +24 -11
- package/dist/records/mapping.js.map +1 -1
- package/dist/records/record-commands.d.ts +8 -0
- package/dist/records/record-commands.d.ts.map +1 -0
- package/dist/records/record-commands.js +89 -0
- package/dist/records/record-commands.js.map +1 -0
- package/dist/records/sources.d.ts +48 -0
- package/dist/records/sources.d.ts.map +1 -0
- package/dist/records/sources.js +72 -0
- package/dist/records/sources.js.map +1 -0
- package/dist/review/kinds.d.ts +1 -1
- package/dist/review/kinds.d.ts.map +1 -1
- package/dist/review/kinds.js +4 -0
- package/dist/review/kinds.js.map +1 -1
- package/dist/review/review.d.ts.map +1 -1
- package/dist/review/review.js +4 -0
- package/dist/review/review.js.map +1 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +34 -0
- package/dist/rows.js.map +1 -1
- package/dist/search/command.d.ts.map +1 -1
- package/dist/search/command.js +9 -4
- package/dist/search/command.js.map +1 -1
- package/dist/search/lane-gates.d.ts +3 -0
- package/dist/search/lane-gates.d.ts.map +1 -1
- package/dist/search/lane-gates.js +9 -3
- package/dist/search/lane-gates.js.map +1 -1
- package/dist/search/search.d.ts +3 -1
- package/dist/search/search.d.ts.map +1 -1
- package/dist/search/search.js +2 -1
- package/dist/search/search.js.map +1 -1
- package/dist/show/command.d.ts +6 -1
- package/dist/show/command.d.ts.map +1 -1
- package/dist/show/command.js +49 -4
- package/dist/show/command.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/cli-memo/SKILL.md +8 -5
- package/skills/cli-memo/topics/money.md +20 -1
- package/skills/cli-memo/topics/proposals.md +8 -5
- package/skills/cli-memo/topics/search.md +7 -0
- package/dist/bundle/chunk-HMJ3D7XE.js +0 -1901
|
@@ -6,17 +6,17 @@ import {
|
|
|
6
6
|
autoState,
|
|
7
7
|
lastAutoRun,
|
|
8
8
|
recordAutoRun
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XPT5PX7H.js";
|
|
10
10
|
import {
|
|
11
11
|
installer,
|
|
12
12
|
latest,
|
|
13
13
|
upgradeCommand
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WINH45XG.js";
|
|
15
15
|
import {
|
|
16
16
|
mcpOwnerAllowed,
|
|
17
17
|
readOnlyAvailability,
|
|
18
18
|
refuseWritesUnderLock
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-EDBZEHAU.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-T3LVSUNZ.js";
|
|
31
31
|
import {
|
|
32
32
|
ATTACHMENT_CHARS,
|
|
33
33
|
DIALECTS,
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
configPath,
|
|
40
40
|
decisionPolicy,
|
|
41
41
|
dialectOf,
|
|
42
|
+
grantedLevel,
|
|
42
43
|
hitText,
|
|
43
44
|
inspectConfig,
|
|
44
45
|
isReference,
|
|
@@ -58,7 +59,7 @@ import {
|
|
|
58
59
|
showMail,
|
|
59
60
|
unsetConfigKey,
|
|
60
61
|
updateConfig
|
|
61
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-FHZKHKBJ.js";
|
|
62
63
|
import "./chunk-QP3KNC5D.js";
|
|
63
64
|
import "./chunk-FWRBJAQZ.js";
|
|
64
65
|
import "./chunk-MWAXS4BX.js";
|
|
@@ -66,7 +67,7 @@ import "./chunk-PKUBC2ME.js";
|
|
|
66
67
|
import {
|
|
67
68
|
errorObject,
|
|
68
69
|
recognisable
|
|
69
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-ZX6SWNSR.js";
|
|
70
71
|
import {
|
|
71
72
|
AGENT_INPUT_MAX_CHARS,
|
|
72
73
|
DISCOVERY_DESCRIPTIONS,
|
|
@@ -105,7 +106,7 @@ import {
|
|
|
105
106
|
tasksCommand,
|
|
106
107
|
tasksStatsCommand,
|
|
107
108
|
withSqliteSidecars
|
|
108
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-FKUA3BTM.js";
|
|
109
110
|
import "./chunk-RLX5SC2X.js";
|
|
110
111
|
import "./chunk-SIBQ34LX.js";
|
|
111
112
|
import {
|
|
@@ -114,22 +115,23 @@ import {
|
|
|
114
115
|
messageHitItem,
|
|
115
116
|
noteHitItem,
|
|
116
117
|
shownOf
|
|
117
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-3SCHFNUH.js";
|
|
118
119
|
import "./chunk-DKO7WEXJ.js";
|
|
119
120
|
import {
|
|
121
|
+
REASONS as REASONS2,
|
|
120
122
|
SKILL_TARGETS,
|
|
121
123
|
skillCommand,
|
|
122
124
|
skillPath,
|
|
123
125
|
skillVersion
|
|
124
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-QTF4ZXOL.js";
|
|
125
127
|
import {
|
|
126
128
|
recoveryNotes,
|
|
127
129
|
storeInfo,
|
|
128
130
|
storeRecoveryCheck,
|
|
129
131
|
storeRecoveryRun,
|
|
130
132
|
storeSummary
|
|
131
|
-
} from "./chunk-
|
|
132
|
-
import "./chunk-
|
|
133
|
+
} from "./chunk-QHNAPLVB.js";
|
|
134
|
+
import "./chunk-VLUDHCCX.js";
|
|
133
135
|
import {
|
|
134
136
|
LIST_QUERY_GUIDE,
|
|
135
137
|
STATUS_SIGNALS,
|
|
@@ -147,6 +149,10 @@ import {
|
|
|
147
149
|
gatherStoredProject,
|
|
148
150
|
importEngine,
|
|
149
151
|
ingest,
|
|
152
|
+
ingestLines,
|
|
153
|
+
ingestVcard,
|
|
154
|
+
isVcard,
|
|
155
|
+
jsonlLines,
|
|
150
156
|
listQuery,
|
|
151
157
|
mailTurn,
|
|
152
158
|
meaningLane,
|
|
@@ -155,6 +161,8 @@ import {
|
|
|
155
161
|
meetingSearchArguments,
|
|
156
162
|
meetingSearchMeta,
|
|
157
163
|
modelGateway,
|
|
164
|
+
nativeField,
|
|
165
|
+
nativeTerms,
|
|
158
166
|
parseProposalIds,
|
|
159
167
|
personContext,
|
|
160
168
|
pickPerson,
|
|
@@ -181,7 +189,7 @@ import {
|
|
|
181
189
|
termField,
|
|
182
190
|
typedQuery,
|
|
183
191
|
withQuery
|
|
184
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-DXTNBVLV.js";
|
|
185
193
|
import {
|
|
186
194
|
readBoundedUtf8File,
|
|
187
195
|
writeFileAtomic
|
|
@@ -190,9 +198,9 @@ import {
|
|
|
190
198
|
commandsText,
|
|
191
199
|
inSection,
|
|
192
200
|
installHelp
|
|
193
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-NH3A5QTW.js";
|
|
194
202
|
import "./chunk-HTQTIKWP.js";
|
|
195
|
-
import "./chunk-
|
|
203
|
+
import "./chunk-NIJZXGJN.js";
|
|
196
204
|
import {
|
|
197
205
|
Command,
|
|
198
206
|
DEFAULT_TEXT_MODEL,
|
|
@@ -219,6 +227,8 @@ import {
|
|
|
219
227
|
outputFor,
|
|
220
228
|
overrideSharedContract,
|
|
221
229
|
parseDuration,
|
|
230
|
+
progressLine,
|
|
231
|
+
progressOf,
|
|
222
232
|
proposesOnly,
|
|
223
233
|
provide,
|
|
224
234
|
runsDirFor,
|
|
@@ -227,15 +237,15 @@ import {
|
|
|
227
237
|
snakeKeys,
|
|
228
238
|
textModels,
|
|
229
239
|
textModelsFile
|
|
230
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-PVGK67AJ.js";
|
|
231
241
|
import "./chunk-SIJA2UYC.js";
|
|
232
|
-
import "./chunk-
|
|
242
|
+
import "./chunk-LVLFLWGY.js";
|
|
233
243
|
import {
|
|
234
244
|
isNewer
|
|
235
245
|
} from "./chunk-ASWLM74P.js";
|
|
236
246
|
import "./chunk-6G53ZFUT.js";
|
|
237
247
|
import "./chunk-FH4P5UQA.js";
|
|
238
|
-
import "./chunk-
|
|
248
|
+
import "./chunk-NRHF7TQ4.js";
|
|
239
249
|
import "./chunk-RP6VV35S.js";
|
|
240
250
|
import "./chunk-RTLQHLHG.js";
|
|
241
251
|
import {
|
|
@@ -256,6 +266,7 @@ import {
|
|
|
256
266
|
PROJECT_TASK_FIELDS,
|
|
257
267
|
PROJECT_TYPES,
|
|
258
268
|
PROPOSAL_STATUSES,
|
|
269
|
+
RECORDS_SCHEMA_VERSION,
|
|
259
270
|
REMINDERS_QUERY,
|
|
260
271
|
SCOPES,
|
|
261
272
|
TASK_RELATION_KINDS,
|
|
@@ -265,10 +276,11 @@ import {
|
|
|
265
276
|
contextEvidenceFingerprint,
|
|
266
277
|
decodeProjectAnnotationSnapshot,
|
|
267
278
|
entriesOfList,
|
|
268
|
-
|
|
279
|
+
envelopeOfText,
|
|
269
280
|
formatLocator,
|
|
270
281
|
formatReference,
|
|
271
282
|
isFolderProvider,
|
|
283
|
+
isImportedProvider,
|
|
272
284
|
kindOf,
|
|
273
285
|
looksLikeReference,
|
|
274
286
|
mailFindingFieldsHelp,
|
|
@@ -280,8 +292,11 @@ import {
|
|
|
280
292
|
plainQuery,
|
|
281
293
|
providerNamed,
|
|
282
294
|
refLabel
|
|
283
|
-
} from "./chunk-
|
|
295
|
+
} from "./chunk-3YNJBKGV.js";
|
|
284
296
|
import {
|
|
297
|
+
CATALOG_KINDS,
|
|
298
|
+
CONTRACT_KINDS,
|
|
299
|
+
CONTRACT_STATUSES,
|
|
285
300
|
DEAL_KINDS,
|
|
286
301
|
DEAL_ROLES,
|
|
287
302
|
DEAL_STATUSES,
|
|
@@ -298,10 +313,17 @@ import {
|
|
|
298
313
|
ORDER_PURPOSES,
|
|
299
314
|
ORDER_STATUSES,
|
|
300
315
|
PRIORITY_LABELS,
|
|
316
|
+
SUBSCRIPTION_STATUSES,
|
|
301
317
|
TASK_STATES,
|
|
302
318
|
TASK_TYPES,
|
|
319
|
+
TRANSACTION_STATUSES,
|
|
320
|
+
WALLET_KINDS,
|
|
303
321
|
WORK_TASK_TYPES,
|
|
304
322
|
createUpcomingMeetingReader,
|
|
323
|
+
dateRange,
|
|
324
|
+
dayBoundary,
|
|
325
|
+
event,
|
|
326
|
+
eventItem,
|
|
305
327
|
formatMeetingReference,
|
|
306
328
|
isClosedState,
|
|
307
329
|
markStoreDamaged,
|
|
@@ -342,7 +364,7 @@ import {
|
|
|
342
364
|
REASONS,
|
|
343
365
|
STORE_CLIENT,
|
|
344
366
|
VERSION
|
|
345
|
-
} from "./chunk-
|
|
367
|
+
} from "./chunk-MYXB2T77.js";
|
|
346
368
|
import "./chunk-IK6KH3RE.js";
|
|
347
369
|
import "./chunk-SW6C6WH5.js";
|
|
348
370
|
import "./chunk-D72URWJE.js";
|
|
@@ -499,7 +521,7 @@ var messengers = /* @__PURE__ */ __name((entry) => new CliError("validation_erro
|
|
|
499
521
|
var listedOf = /* @__PURE__ */ __name(async (store, value) => {
|
|
500
522
|
const held = await store.accounts.storedAccounts();
|
|
501
523
|
const holdsFiles = await filesAccounts(store);
|
|
502
|
-
const
|
|
524
|
+
const named5 = /* @__PURE__ */ __name(async (entry) => {
|
|
503
525
|
const [provider = "", ...rest] = entry.trim().split(":");
|
|
504
526
|
const account2 = rest.join(":");
|
|
505
527
|
if (isFolderProvider(provider) && account2) {
|
|
@@ -512,7 +534,7 @@ var listedOf = /* @__PURE__ */ __name(async (store, value) => {
|
|
|
512
534
|
return entry.trim();
|
|
513
535
|
return `email:${(await mailboxOf(store, account2)).account}`;
|
|
514
536
|
}, "named");
|
|
515
|
-
const each = /* @__PURE__ */ __name((entries) => Promise.all(entries.filter((one2) => one2.trim()).map(
|
|
537
|
+
const each = /* @__PURE__ */ __name((entries) => Promise.all(entries.filter((one2) => one2.trim()).map(named5)), "each");
|
|
516
538
|
const groups = Object.fromEntries(await Promise.all(Object.entries(await store.accounts.accountGroups()).map(async ([name2, members]) => [name2, await each(members)])));
|
|
517
539
|
return entriesOfList((await each(value.split(","))).join(","), {
|
|
518
540
|
held,
|
|
@@ -522,9 +544,9 @@ var listedOf = /* @__PURE__ */ __name(async (store, value) => {
|
|
|
522
544
|
});
|
|
523
545
|
}, "listedOf");
|
|
524
546
|
var sourceListOf = /* @__PURE__ */ __name(async (store, env, value) => {
|
|
525
|
-
const
|
|
547
|
+
const listed2 = await listedOf(store, value);
|
|
526
548
|
const list = { mail: [], notes: false, documents: false };
|
|
527
|
-
for (const { entry, accounts } of
|
|
549
|
+
for (const { entry, accounts } of listed2) {
|
|
528
550
|
const word = entry.split(":")[0] ?? "";
|
|
529
551
|
if (MESSENGERS.has(word))
|
|
530
552
|
throw messengers(entry);
|
|
@@ -672,6 +694,7 @@ var oneOf = /* @__PURE__ */ __name((values) => (value) => {
|
|
|
672
694
|
var collect = /* @__PURE__ */ __name((value, previous = []) => [...previous, value], "collect");
|
|
673
695
|
var readScope = /* @__PURE__ */ __name((command, help = ONE_ACCOUNT_HELP) => sourceOptions(command, help).option("--json", "print JSON; --json=id,title keeps only those fields"), "readScope");
|
|
674
696
|
var writeScope = /* @__PURE__ */ __name((command, help) => writeOptions(command, help).option("--json", "print JSON; --json=id,title keeps only those fields"), "writeScope");
|
|
697
|
+
var jsonOption = /* @__PURE__ */ __name((command, fields = "ref,title") => command.option("--json", `print JSON; --json=${fields} keeps only those fields`), "jsonOption");
|
|
675
698
|
|
|
676
699
|
// node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/mail/sender-scores.js
|
|
677
700
|
var SCORED = "mail_sender_scores";
|
|
@@ -724,7 +747,11 @@ var REVIEW_KINDS = [
|
|
|
724
747
|
"action",
|
|
725
748
|
"invoice",
|
|
726
749
|
"payment",
|
|
727
|
-
"order"
|
|
750
|
+
"order",
|
|
751
|
+
"contract",
|
|
752
|
+
"subscription",
|
|
753
|
+
"subscription_price",
|
|
754
|
+
"transaction"
|
|
728
755
|
];
|
|
729
756
|
var BY_ACCOUNT = [MEETING_FINDINGS_KIND, MAIL_FINDINGS_KIND];
|
|
730
757
|
var reviewRegistry = /* @__PURE__ */ __name((store) => {
|
|
@@ -761,22 +788,22 @@ var REVIEW_QUERY = {
|
|
|
761
788
|
]
|
|
762
789
|
};
|
|
763
790
|
var filterOf = /* @__PURE__ */ __name(async (store, words) => {
|
|
764
|
-
const
|
|
765
|
-
const project =
|
|
766
|
-
const kinds2 =
|
|
791
|
+
const terms2 = queryTerms(words, REVIEW_QUERY, "review");
|
|
792
|
+
const project = terms2.get("project");
|
|
793
|
+
const kinds2 = terms2.get("kind")?.split(",").map((one2) => one2.trim()).filter(Boolean);
|
|
767
794
|
const unknown2 = kinds2?.find((one2) => !REVIEW_KINDS.includes(one2));
|
|
768
795
|
if (unknown2 !== void 0)
|
|
769
796
|
throw new CliError("validation_error", `no proposal kind ${unknown2}; kinds: ${REVIEW_KINDS.join(", ")}`, {
|
|
770
797
|
param: "kind"
|
|
771
798
|
});
|
|
772
|
-
const by =
|
|
773
|
-
const via =
|
|
799
|
+
const by = terms2.get("by");
|
|
800
|
+
const via = terms2.get("via");
|
|
774
801
|
return {
|
|
775
802
|
...project === void 0 ? {} : { project: await canonicalProject(store, project) },
|
|
776
803
|
...kinds2?.length ? { kinds: kinds2 } : {},
|
|
777
804
|
...by === void 0 ? {} : { by: by === "agent" || by === "rule" ? by : { bot: by } },
|
|
778
805
|
...via === void 0 ? {} : { via },
|
|
779
|
-
status:
|
|
806
|
+
status: terms2.get("status") ?? "proposed"
|
|
780
807
|
};
|
|
781
808
|
}, "filterOf");
|
|
782
809
|
var proposerName = /* @__PURE__ */ __name((proposer) => proposer.type === "bot" ? proposer.name : proposer.type === "person" ? "you" : "unknown", "proposerName");
|
|
@@ -813,6 +840,10 @@ var titleOf = /* @__PURE__ */ __name((row, label) => {
|
|
|
813
840
|
case "invoice":
|
|
814
841
|
case "payment":
|
|
815
842
|
case "order":
|
|
843
|
+
case "contract":
|
|
844
|
+
case "subscription":
|
|
845
|
+
case "subscription_price":
|
|
846
|
+
case "transaction":
|
|
816
847
|
return row.summary ?? subject;
|
|
817
848
|
default:
|
|
818
849
|
return object2 === null ? subject : `${subject} \u2192 ${object2}`;
|
|
@@ -942,8 +973,8 @@ var reviewText = /* @__PURE__ */ __name((items, hasMore) => {
|
|
|
942
973
|
...item.status === "proposed" ? [] : [item.status]
|
|
943
974
|
].join(" ");
|
|
944
975
|
const why = [item.reason && cut(item.reason, 100), item.evidence[0]].filter(Boolean).join(" \xB7 ");
|
|
945
|
-
const
|
|
946
|
-
return [head, ...why ? [`${pad} ${why}`] : [], ...
|
|
976
|
+
const parts2 = (item.parts ?? []).map((part) => `${pad} ${item.id}/${part.id} ${part.kind} ${cut(part.summary, 80)}${part.outcome ? ` ${part.outcome}` : ""}`);
|
|
977
|
+
return [head, ...why ? [`${pad} ${why}`] : [], ...parts2];
|
|
947
978
|
})
|
|
948
979
|
]);
|
|
949
980
|
return [...lines2, `${items.length} shown${hasMore ? ", more with --page" : ""}`].join("\n");
|
|
@@ -1043,19 +1074,19 @@ var partsOf = /* @__PURE__ */ __name((action, targetName) => {
|
|
|
1043
1074
|
const text3 = [payload.text, payload.title].find((one2) => typeof one2 === "string" && one2.trim() !== "");
|
|
1044
1075
|
return { verb: action.kind, targetName, text: text3 ?? null };
|
|
1045
1076
|
}, "partsOf");
|
|
1046
|
-
var summaryOf = /* @__PURE__ */ __name((action,
|
|
1047
|
-
const target =
|
|
1048
|
-
if ("counts" in
|
|
1049
|
-
const { facts, tasks } =
|
|
1077
|
+
var summaryOf = /* @__PURE__ */ __name((action, parts2) => {
|
|
1078
|
+
const target = parts2.targetName ?? action.target;
|
|
1079
|
+
if ("counts" in parts2 && parts2.counts) {
|
|
1080
|
+
const { facts, tasks } = parts2.counts;
|
|
1050
1081
|
const what = [facts && counted(facts, "fact"), tasks && counted(tasks, "task")].filter(Boolean).join(" and ");
|
|
1051
1082
|
const word = action.kind === MEETING_FINDINGS_KIND ? "from" : action.target?.startsWith("project:") ? "in" : "about";
|
|
1052
1083
|
return `Create ${what || "nothing"}${target === null ? "" : ` ${word} ${target}`}`;
|
|
1053
1084
|
}
|
|
1054
|
-
const words =
|
|
1085
|
+
const words = parts2.verb.replaceAll("_", " ");
|
|
1055
1086
|
return [
|
|
1056
1087
|
`${words.charAt(0).toUpperCase()}${words.slice(1)}`,
|
|
1057
1088
|
target === null ? "" : ` ${target}`,
|
|
1058
|
-
|
|
1089
|
+
parts2.text === null ? "" : `: ${clip(parts2.text)}`
|
|
1059
1090
|
].join("");
|
|
1060
1091
|
}, "summaryOf");
|
|
1061
1092
|
var chatOf = /* @__PURE__ */ __name((reference2) => {
|
|
@@ -1118,11 +1149,11 @@ var actionItems = /* @__PURE__ */ __name(async (store, actions, { brief = false
|
|
|
1118
1149
|
const project = batch?.project ?? (action.target?.startsWith("project:") ? action.target : null);
|
|
1119
1150
|
const projectName = project === null ? null : names.get(project) ?? null;
|
|
1120
1151
|
const targetName = action.target === null ? null : names.get(action.target) ?? null;
|
|
1121
|
-
const
|
|
1152
|
+
const parts2 = partsOf(action, targetName);
|
|
1122
1153
|
return {
|
|
1123
1154
|
...action,
|
|
1124
|
-
summary: summaryOf(action,
|
|
1125
|
-
...
|
|
1155
|
+
summary: summaryOf(action, parts2),
|
|
1156
|
+
...parts2,
|
|
1126
1157
|
chatName: action.target === null ? null : chats.get(action.target) ?? null,
|
|
1127
1158
|
project,
|
|
1128
1159
|
projectName,
|
|
@@ -1170,8 +1201,8 @@ var decideBatch = /* @__PURE__ */ __name(async (store, id, decision) => {
|
|
|
1170
1201
|
throw new CliError("validation_error", "the findings changed since they were read; stage a new batch", {
|
|
1171
1202
|
reason: batch.stale
|
|
1172
1203
|
});
|
|
1173
|
-
const
|
|
1174
|
-
const { decided, refused } = await proposalRegistry(store).decide(
|
|
1204
|
+
const parts2 = decision.confirm && decision.accept.length ? decision.accept.map((one2) => `${id}/${one2}`) : [id];
|
|
1205
|
+
const { decided, refused } = await proposalRegistry(store).decide(parts2, decisionOf(decision.confirm, decision.by, decision.reason));
|
|
1175
1206
|
const refusal = refused[0];
|
|
1176
1207
|
if (refusal)
|
|
1177
1208
|
throw new CliError(refusal.code, refusal.message, { reason: refusal.reason });
|
|
@@ -1239,9 +1270,9 @@ var AGENT_LOG_QUERY = {
|
|
|
1239
1270
|
]
|
|
1240
1271
|
};
|
|
1241
1272
|
var listAgentActions = /* @__PURE__ */ __name((store, query, limit) => {
|
|
1242
|
-
const
|
|
1243
|
-
const tool =
|
|
1244
|
-
const agent =
|
|
1273
|
+
const terms2 = queryTerms(query, AGENT_LOG_QUERY, "agents list");
|
|
1274
|
+
const tool = terms2.get("tool");
|
|
1275
|
+
const agent = terms2.get("agent");
|
|
1245
1276
|
return pageOf("agents list", limit, (most) => store.agentActions.list({
|
|
1246
1277
|
...tool === void 0 ? {} : { tool },
|
|
1247
1278
|
...agent === void 0 ? {} : { agent },
|
|
@@ -1670,7 +1701,7 @@ var allowedPage = /* @__PURE__ */ __name(async (ask, limit, shows) => {
|
|
|
1670
1701
|
const { nextOffset: _, ...rest } = first;
|
|
1671
1702
|
return { ...rest, items: items.slice(0, limit), hasMore: items.length > limit || page.hasMore };
|
|
1672
1703
|
}, "allowedPage");
|
|
1673
|
-
var searchEverywhere = /* @__PURE__ */ __name(async (store, env, { text: text3, limit, only, exact, timezone, plainOrder, shows }) => {
|
|
1704
|
+
var searchEverywhere = /* @__PURE__ */ __name(async (store, env, { text: text3, limit, only, crmKinds, exact, timezone, plainOrder, shows }) => {
|
|
1674
1705
|
const accounts = await store.accounts.accounts();
|
|
1675
1706
|
const messenger2 = { app: { ...APP, command: "tg" }, hintCommand: "memo" };
|
|
1676
1707
|
const ask = /* @__PURE__ */ __name((offset) => searchAll(store, MEMO, {
|
|
@@ -1679,6 +1710,7 @@ var searchEverywhere = /* @__PURE__ */ __name(async (store, env, { text: text3,
|
|
|
1679
1710
|
env,
|
|
1680
1711
|
...offset === void 0 ? {} : { offset },
|
|
1681
1712
|
...only === void 0 ? {} : { only },
|
|
1713
|
+
...crmKinds === void 0 ? {} : { crmKinds },
|
|
1682
1714
|
...exact ? { exact: true } : {},
|
|
1683
1715
|
...timezone === void 0 ? {} : { timezone }
|
|
1684
1716
|
}, messenger2, (query) => searchStore(store, MEMO, query, messenger2), meaningLane({ env, store: /* @__PURE__ */ __name(async () => store, "store"), messenger: { app: { command: "memo" } } })), "ask");
|
|
@@ -2008,8 +2040,8 @@ var fileLinks = /* @__PURE__ */ __name((source, links, documents) => links.map((
|
|
|
2008
2040
|
const at = anchor === null ? {} : { anchor };
|
|
2009
2041
|
if (isReference(target))
|
|
2010
2042
|
return { to: target, kind: "links-to", ...at };
|
|
2011
|
-
const
|
|
2012
|
-
return
|
|
2043
|
+
const named5 = notesNamed(source, target, documents);
|
|
2044
|
+
return named5.length === 1 ? { to: `document:${named5[0].id}`, kind: "links-to", ...at } : { targetText: posix.basename(target.replace(/\\/g, "/")) || target, kind: "links-to", ...at };
|
|
2013
2045
|
}), "fileLinks");
|
|
2014
2046
|
|
|
2015
2047
|
// dist/notes/renames.js
|
|
@@ -2143,11 +2175,11 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
|
|
|
2143
2175
|
after.files[id] = `${stamp}${hash}`;
|
|
2144
2176
|
read.push({ id, path, bytes, hash });
|
|
2145
2177
|
}
|
|
2146
|
-
const
|
|
2178
|
+
const listed2 = /* @__PURE__ */ new Set([
|
|
2147
2179
|
...Object.keys(after.files).filter((id) => !after.files[id]?.startsWith(MEMO2)),
|
|
2148
2180
|
...[...held].filter((id) => stored.has(id))
|
|
2149
2181
|
]);
|
|
2150
|
-
const goneHashes = Object.fromEntries([...stored.values()].filter((note) => !
|
|
2182
|
+
const goneHashes = Object.fromEntries([...stored.values()].filter((note) => !listed2.has(note.path) && note.contentHash !== null).map((note) => [note.path, note.contentHash]));
|
|
2151
2183
|
const newHashes = Object.fromEntries(read.filter(({ id }) => !stored.has(id)).map(({ id, hash }) => [id, hash]));
|
|
2152
2184
|
let renamed = 0;
|
|
2153
2185
|
for (const move of detectRenames(goneHashes, newHashes)) {
|
|
@@ -2197,7 +2229,7 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
|
|
|
2197
2229
|
changed++;
|
|
2198
2230
|
}
|
|
2199
2231
|
onFile(files.length, files.length);
|
|
2200
|
-
const gone = [...stored.keys()].filter((id) => !
|
|
2232
|
+
const gone = [...stored.keys()].filter((id) => !listed2.has(id));
|
|
2201
2233
|
let deleted = 0;
|
|
2202
2234
|
let deletionsSkipped;
|
|
2203
2235
|
if (gone.length >= MIN_DELETIONS_CAPPED && gone.length > stored.size * MAX_DELETED_SHARE) {
|
|
@@ -2241,7 +2273,7 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
|
|
|
2241
2273
|
return {
|
|
2242
2274
|
folder: folder.path,
|
|
2243
2275
|
folderId: folder.id,
|
|
2244
|
-
notes:
|
|
2276
|
+
notes: listed2.size - Object.keys(notReadNow).filter((id) => listed2.has(id)).length,
|
|
2245
2277
|
changed,
|
|
2246
2278
|
renamed,
|
|
2247
2279
|
deleted,
|
|
@@ -2439,9 +2471,9 @@ var anchorOf = /* @__PURE__ */ __name(async (store, uid, source) => {
|
|
|
2439
2471
|
throw new CliError(matches2.length === 0 ? "not_found" : "validation_error", matches2.length === 0 ? `no account in the store has seen person:${uid}` : `person:${uid} was seen by ${accounts.length} accounts; give one with --source: ${accounts.join(", ")}`);
|
|
2440
2472
|
}, "anchorOf");
|
|
2441
2473
|
var memoContext = /* @__PURE__ */ __name(async (store, reference2, { limit = 20, source } = {}) => {
|
|
2442
|
-
const
|
|
2443
|
-
if (
|
|
2444
|
-
const anchor = await anchorOf(store,
|
|
2474
|
+
const named5 = (await withOwner(store, reference2)).trim();
|
|
2475
|
+
if (named5.startsWith("person:")) {
|
|
2476
|
+
const anchor = await anchorOf(store, named5.slice("person:".length), source);
|
|
2445
2477
|
return memoContext(store, anchor.reference, { limit, source: anchor });
|
|
2446
2478
|
}
|
|
2447
2479
|
const [, provider, who] = /^([a-z][a-z0-9-]*):(.+)$/.exec(reference2.trim()) ?? [];
|
|
@@ -2507,7 +2539,7 @@ var withOwnMailText = /* @__PURE__ */ __name((context) => {
|
|
|
2507
2539
|
// dist/context/command.js
|
|
2508
2540
|
var MAX_TEXT2 = 160;
|
|
2509
2541
|
var one = /* @__PURE__ */ __name((message) => message === null ? "\u2014" : `${message.timestamp.slice(0, 16).replace("T", " ")} ${message.provider} ${message.chatTitle ?? message.chatId}: ${message.text.replace(/\s+/g, " ").slice(0, MAX_TEXT2)} ${message.locator}`, "one");
|
|
2510
|
-
var eventLine = /* @__PURE__ */ __name((
|
|
2542
|
+
var eventLine = /* @__PURE__ */ __name((event2) => ` ${(event2.allDay ? event2.startsAt?.slice(0, 10) : event2.startsAt?.slice(0, 16).replace("T", " ")) ?? "\u2014"} ${(event2.title ?? "untitled").replace(/\s+/g, " ").slice(0, MAX_TEXT2)}${event2.location ? ` ${event2.location}` : ""} ${event2.ref}`, "eventLine");
|
|
2511
2543
|
var noteLine = /* @__PURE__ */ __name((note) => ` ${note.ref}${note.path ?? note.title ? ` ${note.path ?? note.title}` : ""}`, "noteLine");
|
|
2512
2544
|
var fileLine = /* @__PURE__ */ __name((file) => ` ${file.ref} ${file.role ?? ""} ${file.title ?? ""} ${file.modifiedAt?.slice(0, 16).replace("T", " ") ?? ""} ${file.url ?? ""}`, "fileLine");
|
|
2513
2545
|
var contextText = /* @__PURE__ */ __name(({ messages, events, notes: notes2, notRead, tasks, yourNotes, files, proposals }) => {
|
|
@@ -3495,7 +3527,7 @@ var search = [
|
|
|
3495
3527
|
command: ["search", "all"],
|
|
3496
3528
|
field: "description",
|
|
3497
3529
|
before: "search messenger messages and notes in the local store, calendar events when the store holds a calendar, and a meeting account's transcripts when --source names one \u2014 best match first; not mail (the separate memo CLI searches it: memo search mail), tasks, people, memories or projects. Use it when you do not know where something was written; search messages or notes reads one kind with all its fields",
|
|
3498
|
-
after: "messages, mail, notes
|
|
3530
|
+
after: "messages, mail, notes, calendar events, deals, leads and business data ranked together; not people, memories, projects or decisions. A kind you know reads better with its own search, with all its fields",
|
|
3499
3531
|
reason: "Memo searches imported accounts, mail and native notes without a live messenger; its scope, ranking and output controls are explicit provider differences."
|
|
3500
3532
|
},
|
|
3501
3533
|
{
|
|
@@ -3614,7 +3646,7 @@ var search = [
|
|
|
3614
3646
|
},
|
|
3615
3647
|
{
|
|
3616
3648
|
flags: "--only <resources>",
|
|
3617
|
-
description: "messages,mail,notes,events, separated by commas",
|
|
3649
|
+
description: "messages,mail,notes,events,crm,business, separated by commas",
|
|
3618
3650
|
takes_value: true,
|
|
3619
3651
|
mandatory: false
|
|
3620
3652
|
},
|
|
@@ -4081,6 +4113,7 @@ var SECTIONS = [
|
|
|
4081
4113
|
["notes remove", "write"],
|
|
4082
4114
|
["notes export", "write"],
|
|
4083
4115
|
["mail", "read"],
|
|
4116
|
+
["events", "read"],
|
|
4084
4117
|
["agents", "read"],
|
|
4085
4118
|
["answers", "read"],
|
|
4086
4119
|
["memories", "write"],
|
|
@@ -4095,6 +4128,11 @@ var SECTIONS = [
|
|
|
4095
4128
|
["leads", "organise"],
|
|
4096
4129
|
["pipelines", "organise"],
|
|
4097
4130
|
["payments", "organise"],
|
|
4131
|
+
["products", "organise"],
|
|
4132
|
+
["contracts", "organise"],
|
|
4133
|
+
["subscriptions", "organise"],
|
|
4134
|
+
["wallets", "organise"],
|
|
4135
|
+
["transactions", "organise"],
|
|
4098
4136
|
["records", "organise"],
|
|
4099
4137
|
["projects", "organise"],
|
|
4100
4138
|
["people", "organise"],
|
|
@@ -4283,10 +4321,387 @@ var doctorCommand = /* @__PURE__ */ __name((...args) => {
|
|
|
4283
4321
|
}, SHELL_OVERRIDES.doctor);
|
|
4284
4322
|
}, "doctorCommand");
|
|
4285
4323
|
|
|
4324
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/sync.js
|
|
4325
|
+
var DAY3 = 864e5;
|
|
4326
|
+
var SLOTS_EVERY = 7 * DAY3;
|
|
4327
|
+
var isWindow = /* @__PURE__ */ __name((value) => typeof value?.from === "number" && typeof value.to === "number", "isWindow");
|
|
4328
|
+
var isToken = /* @__PURE__ */ __name((value) => value === null || typeof value === "string", "isToken");
|
|
4329
|
+
var roundOf = /* @__PURE__ */ __name((value) => {
|
|
4330
|
+
if (value === null || value === void 0)
|
|
4331
|
+
return null;
|
|
4332
|
+
const round = value;
|
|
4333
|
+
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")
|
|
4334
|
+
return void 0;
|
|
4335
|
+
const { full, from, window, startedAt, reset, page, listed: listed2, next, series, everySeries, unchanged } = round;
|
|
4336
|
+
return {
|
|
4337
|
+
full,
|
|
4338
|
+
from,
|
|
4339
|
+
window,
|
|
4340
|
+
startedAt,
|
|
4341
|
+
reset,
|
|
4342
|
+
page,
|
|
4343
|
+
listed: listed2,
|
|
4344
|
+
next,
|
|
4345
|
+
series,
|
|
4346
|
+
...everySeries === false ? { everySeries } : {},
|
|
4347
|
+
...unchanged === true ? { unchanged } : {}
|
|
4348
|
+
};
|
|
4349
|
+
}, "roundOf");
|
|
4350
|
+
var parseCalendarCursor = /* @__PURE__ */ __name((value) => {
|
|
4351
|
+
if (value === null)
|
|
4352
|
+
return null;
|
|
4353
|
+
try {
|
|
4354
|
+
const cursor = JSON.parse(value);
|
|
4355
|
+
if (cursor?.v !== 1 && cursor?.v !== 2 || !isToken(cursor.token) || typeof cursor.fullAt !== "number" || !isWindow(cursor.window))
|
|
4356
|
+
return null;
|
|
4357
|
+
const { token, window, fullAt } = cursor;
|
|
4358
|
+
if (cursor.v === 1)
|
|
4359
|
+
return { v: 2, token, window, fullAt, updatedAt: null, done: 0, round: null };
|
|
4360
|
+
const round = roundOf(cursor.round);
|
|
4361
|
+
if (round === void 0 || cursor.updatedAt !== null && typeof cursor.updatedAt !== "number" || typeof cursor.done !== "number")
|
|
4362
|
+
return null;
|
|
4363
|
+
return {
|
|
4364
|
+
v: 2,
|
|
4365
|
+
token,
|
|
4366
|
+
window,
|
|
4367
|
+
fullAt,
|
|
4368
|
+
updatedAt: cursor.updatedAt ?? null,
|
|
4369
|
+
done: cursor.done,
|
|
4370
|
+
round,
|
|
4371
|
+
...cursor.restored === true ? { restored: true } : {},
|
|
4372
|
+
...typeof cursor.slotsTo === "number" ? { slotsTo: cursor.slotsTo } : {}
|
|
4373
|
+
};
|
|
4374
|
+
} catch {
|
|
4375
|
+
return null;
|
|
4376
|
+
}
|
|
4377
|
+
}, "parseCalendarCursor");
|
|
4378
|
+
var calendarStatus = /* @__PURE__ */ __name(async (store, accountId, { profile, now }) => {
|
|
4379
|
+
const items = [];
|
|
4380
|
+
for (const calendar of await store.calendars(accountId)) {
|
|
4381
|
+
if (!calendar.synced || calendar.deletedAt !== null)
|
|
4382
|
+
continue;
|
|
4383
|
+
const cursor = parseCalendarCursor(await store.cursor(calendar.id));
|
|
4384
|
+
const progress = progressOf({
|
|
4385
|
+
job: `calendar ${calendar.id}`,
|
|
4386
|
+
profile,
|
|
4387
|
+
done: cursor?.done ?? 0,
|
|
4388
|
+
complete: cursor !== null && cursor.round === null,
|
|
4389
|
+
...cursor?.updatedAt == null ? {} : { updatedAt: new Date(cursor.updatedAt).toISOString() },
|
|
4390
|
+
now: new Date(now)
|
|
4391
|
+
});
|
|
4392
|
+
items.push({
|
|
4393
|
+
calendar_id: String(calendar.id),
|
|
4394
|
+
external_id: calendar.externalId,
|
|
4395
|
+
title: calendar.title,
|
|
4396
|
+
round: cursor?.round ? cursor.round.full ? "full" : "changes" : null,
|
|
4397
|
+
...progress,
|
|
4398
|
+
line: progressLine(progress)
|
|
4399
|
+
});
|
|
4400
|
+
}
|
|
4401
|
+
return { items, page: 1, limit: Math.max(1, items.length), hasMore: false };
|
|
4402
|
+
}, "calendarStatus");
|
|
4403
|
+
|
|
4404
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/feeds.js
|
|
4405
|
+
var FEED_LIMITS = { maxBytes: 10 * 1024 * 1024, timeoutMs: 3e4, redirects: 5 };
|
|
4406
|
+
|
|
4407
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/reads.js
|
|
4408
|
+
var LIST = "events list";
|
|
4409
|
+
var EVENT_TYPES = [
|
|
4410
|
+
"default",
|
|
4411
|
+
"out-of-office",
|
|
4412
|
+
"focus",
|
|
4413
|
+
"working-location",
|
|
4414
|
+
"birthday",
|
|
4415
|
+
"from-mail",
|
|
4416
|
+
"call"
|
|
4417
|
+
];
|
|
4418
|
+
var oneSided = /* @__PURE__ */ __name((field2, example) => (node) => {
|
|
4419
|
+
if (node.operator !== "range" || node.upper !== "*")
|
|
4420
|
+
queryError("query.unsupported-operator", node.span, `${field2} takes only an earliest moment, such as ${example}`, {
|
|
4421
|
+
command: LIST,
|
|
4422
|
+
guide: LIST_QUERY_GUIDE
|
|
4423
|
+
});
|
|
4424
|
+
}, "oneSided");
|
|
4425
|
+
var EVENTS_QUERY = {
|
|
4426
|
+
entity: "event",
|
|
4427
|
+
backend: "native",
|
|
4428
|
+
fields: queryFieldsOf(event, {
|
|
4429
|
+
native: ["id", "starts_at", "ends_at", "changed_at", "overlapping", "calendar", "person", "event_type"],
|
|
4430
|
+
negatable: ["event_type"],
|
|
4431
|
+
relations: {
|
|
4432
|
+
event_type: {
|
|
4433
|
+
type: "enum",
|
|
4434
|
+
values: EVENT_TYPES,
|
|
4435
|
+
example: "event_type:default",
|
|
4436
|
+
relation: "events with a copy of this kind; -event_type:<kind> leaves out events with one"
|
|
4437
|
+
},
|
|
4438
|
+
calendar: {
|
|
4439
|
+
type: "kw",
|
|
4440
|
+
example: "calendar:3",
|
|
4441
|
+
relation: "one calendar, by its id, the provider's id or its title"
|
|
4442
|
+
},
|
|
4443
|
+
person: {
|
|
4444
|
+
type: "kw",
|
|
4445
|
+
example: "person:ana@example.com",
|
|
4446
|
+
relation: "events one person attends: an address, or a person id from search"
|
|
4447
|
+
}
|
|
4448
|
+
},
|
|
4449
|
+
examples: {
|
|
4450
|
+
id: "id:42",
|
|
4451
|
+
starts_at: "starts_at:[2026-11-02 TO 2026-11-07}",
|
|
4452
|
+
ends_at: "ends_at>=2026-11-02",
|
|
4453
|
+
changed_at: "changed_at>=2026-10-01",
|
|
4454
|
+
overlapping: "overlapping:true"
|
|
4455
|
+
},
|
|
4456
|
+
validate: {
|
|
4457
|
+
ends_at: oneSided("ends_at", "ends_at>=2026-11-02; for the latest, write starts_at<2026-11-07"),
|
|
4458
|
+
changed_at: oneSided("changed_at", "changed_at>=2026-10-01")
|
|
4459
|
+
}
|
|
4460
|
+
}).map((field2) => field2.native ? {
|
|
4461
|
+
...field2,
|
|
4462
|
+
operators: field2.type === "time" ? ["term", "range"] : field2.type === "bool" ? ["term"] : ["term", "phrase"]
|
|
4463
|
+
} : field2)
|
|
4464
|
+
};
|
|
4465
|
+
var nameOf = /* @__PURE__ */ __name(({ provider, account: account2 }) => `${provider}:${account2}`, "nameOf");
|
|
4466
|
+
var accountsMeta = /* @__PURE__ */ __name(async (store, accounts, skipped, now) => {
|
|
4467
|
+
const issues = [...skipped];
|
|
4468
|
+
for (const { id, key } of accounts) {
|
|
4469
|
+
if (isImportedProvider(key.provider))
|
|
4470
|
+
continue;
|
|
4471
|
+
const { items } = await calendarStatus(store, id, { profile: nameOf(key), now });
|
|
4472
|
+
if (items.length === 0)
|
|
4473
|
+
issues.push({ code: "not_found", reason: "calendar.unsynced", source: nameOf(key) });
|
|
4474
|
+
else if (items.some(({ state }) => state !== "complete"))
|
|
4475
|
+
issues.push({ code: "not_found", reason: "calendar.sync-incomplete", source: nameOf(key) });
|
|
4476
|
+
}
|
|
4477
|
+
return {
|
|
4478
|
+
accounts: accounts.map(({ key }) => nameOf(key)),
|
|
4479
|
+
complete: issues.length === 0,
|
|
4480
|
+
...issues.length ? { issues } : {}
|
|
4481
|
+
};
|
|
4482
|
+
}, "accountsMeta");
|
|
4483
|
+
|
|
4484
|
+
// node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/writer.js
|
|
4485
|
+
var EVENTS_NOTIFY_KEY = "events.notify";
|
|
4486
|
+
var EVENTS_DELETE_SERIES_KEY = "events.delete.series";
|
|
4487
|
+
var EVENTS_REMIND_HOOK_KEY = "events.remind.hook";
|
|
4488
|
+
var CALENDAR_WRITE_DEFAULTS = {
|
|
4489
|
+
"events.create": "allow",
|
|
4490
|
+
// One import writes a whole file of events, and may change events the calendar already holds under their UIDs.
|
|
4491
|
+
"events.import": "ask",
|
|
4492
|
+
"events.update": "allow",
|
|
4493
|
+
"events.respond": "allow",
|
|
4494
|
+
"events.move": "allow",
|
|
4495
|
+
"events.delete": "ask",
|
|
4496
|
+
[EVENTS_DELETE_SERIES_KEY]: "deny",
|
|
4497
|
+
[EVENTS_NOTIFY_KEY]: "deny",
|
|
4498
|
+
// Not ask: `--yes` answers ask, and anything that can type a gcal command can add it.
|
|
4499
|
+
[EVENTS_REMIND_HOOK_KEY]: "deny"
|
|
4500
|
+
};
|
|
4501
|
+
|
|
4502
|
+
// dist/events/events.js
|
|
4503
|
+
var LIST2 = "events list";
|
|
4504
|
+
var EVENT_TYPES2 = [
|
|
4505
|
+
"default",
|
|
4506
|
+
"out-of-office",
|
|
4507
|
+
"focus",
|
|
4508
|
+
"working-location",
|
|
4509
|
+
"birthday",
|
|
4510
|
+
"from-mail",
|
|
4511
|
+
"call"
|
|
4512
|
+
];
|
|
4513
|
+
var EVENTS_QUERY2 = {
|
|
4514
|
+
entity: "event",
|
|
4515
|
+
backend: "native",
|
|
4516
|
+
fields: [
|
|
4517
|
+
nativeField({
|
|
4518
|
+
name: "starts_at",
|
|
4519
|
+
type: "time",
|
|
4520
|
+
operators: ["term", "range"],
|
|
4521
|
+
example: "starts_at:[2026-11-02 TO 2026-11-07}"
|
|
4522
|
+
}),
|
|
4523
|
+
termField("account", "kw", 'account:"phone:pixel"', {
|
|
4524
|
+
relation: "one calendar account, provider:account, or every account of a provider"
|
|
4525
|
+
}),
|
|
4526
|
+
termField("calendar", "kw", "calendar:Calls", { relation: "one calendar, by its id or its title" }),
|
|
4527
|
+
termField("event_type", "enum", "event_type:call", {
|
|
4528
|
+
values: EVENT_TYPES2,
|
|
4529
|
+
relation: "events with a copy of this kind; a phone's imported calls are call"
|
|
4530
|
+
})
|
|
4531
|
+
]
|
|
4532
|
+
};
|
|
4533
|
+
var RECENT_DAYS = 30;
|
|
4534
|
+
var AHEAD_DAYS = 7;
|
|
4535
|
+
var EVENTS_NOTE = `
|
|
4536
|
+
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.`;
|
|
4537
|
+
var UNTRUSTED = ["title", "description", "location", "in"];
|
|
4538
|
+
var readAccounts = /* @__PURE__ */ __name(async (store) => {
|
|
4539
|
+
const held = await calendarAccounts(store);
|
|
4540
|
+
const stored = await store.accounts.storedAccounts();
|
|
4541
|
+
const read = [];
|
|
4542
|
+
for (const key of held) {
|
|
4543
|
+
const one2 = stored.find(({ provider, account: account2 }) => provider === key.provider && account2 === key.account);
|
|
4544
|
+
if (one2)
|
|
4545
|
+
read.push({ id: one2.id, key, calendars: await store.calendar.calendars(one2.id) });
|
|
4546
|
+
}
|
|
4547
|
+
return read;
|
|
4548
|
+
}, "readAccounts");
|
|
4549
|
+
var narrowed = /* @__PURE__ */ __name((accounts, value) => {
|
|
4550
|
+
const chosen = accounts.filter(({ key }) => accountName(key) === value || key.provider === value);
|
|
4551
|
+
if (chosen.length === 0)
|
|
4552
|
+
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" });
|
|
4553
|
+
return chosen;
|
|
4554
|
+
}, "narrowed");
|
|
4555
|
+
var calendarOf = /* @__PURE__ */ __name((accounts, value) => {
|
|
4556
|
+
const all = accounts.flatMap((account2) => account2.calendars.map((calendar) => ({ account: account2, calendar })));
|
|
4557
|
+
const byId = all.filter(({ calendar }) => String(calendar.id) === value);
|
|
4558
|
+
const found = byId.length ? byId : all.filter(({ calendar }) => calendar.title === value);
|
|
4559
|
+
if (found.length === 1)
|
|
4560
|
+
return found[0];
|
|
4561
|
+
if (found.length === 0)
|
|
4562
|
+
throw new CliError("not_found", `calendar:${value} names no calendar in the accounts read`);
|
|
4563
|
+
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(", "));
|
|
4564
|
+
}, "calendarOf");
|
|
4565
|
+
var localDate = /* @__PURE__ */ __name((at, zone) => new Intl.DateTimeFormat("en-CA", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" }).format(at), "localDate");
|
|
4566
|
+
var plusDays = /* @__PURE__ */ __name((date, days2) => {
|
|
4567
|
+
const [year, month, day2] = date.split("-").map(Number);
|
|
4568
|
+
return new Date(Date.UTC(year, month - 1, day2 + days2)).toISOString().slice(0, 10);
|
|
4569
|
+
}, "plusDays");
|
|
4570
|
+
var midnight = /* @__PURE__ */ __name((date, zone) => dayBoundary(date, zone, false, { start: 0, end: date.length }), "midnight");
|
|
4571
|
+
var startsWindow = /* @__PURE__ */ __name((node, zone, now) => {
|
|
4572
|
+
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);
|
|
4573
|
+
return {
|
|
4574
|
+
...range.lower === void 0 ? {} : { lower: range.lower_inclusive ? range.lower : range.lower + 1 },
|
|
4575
|
+
...range.upper === void 0 ? {} : { upper: range.upper_inclusive ? range.upper + 1 : range.upper }
|
|
4576
|
+
};
|
|
4577
|
+
}, "startsWindow");
|
|
4578
|
+
var dated = /* @__PURE__ */ __name((filter, zone) => {
|
|
4579
|
+
if (filter.from !== void 0)
|
|
4580
|
+
filter.fromDate = localDate(filter.from, zone);
|
|
4581
|
+
if (filter.to !== void 0)
|
|
4582
|
+
filter.toDate = plusDays(localDate(filter.to - 1, zone), 1);
|
|
4583
|
+
if (filter.startsFrom !== void 0) {
|
|
4584
|
+
const date = localDate(filter.startsFrom, zone);
|
|
4585
|
+
filter.startsFromDate = midnight(date, zone) < filter.startsFrom ? plusDays(date, 1) : date;
|
|
4586
|
+
}
|
|
4587
|
+
return filter;
|
|
4588
|
+
}, "dated");
|
|
4589
|
+
var windowMeta = /* @__PURE__ */ __name((filter, zone) => {
|
|
4590
|
+
const since = filter.startsFrom ?? filter.from;
|
|
4591
|
+
return {
|
|
4592
|
+
timezone: zone,
|
|
4593
|
+
window: {
|
|
4594
|
+
...since === void 0 ? {} : { since: new Date(since).toISOString() },
|
|
4595
|
+
...filter.to === void 0 ? {} : { until: new Date(filter.to - 1).toISOString() }
|
|
4596
|
+
}
|
|
4597
|
+
};
|
|
4598
|
+
}, "windowMeta");
|
|
4599
|
+
var rowOf = /* @__PURE__ */ __name((details, accounts) => {
|
|
4600
|
+
const live = details.entries.filter(({ deletedAt }) => deletedAt === null);
|
|
4601
|
+
const copies = live.length ? live : details.entries;
|
|
4602
|
+
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) })));
|
|
4603
|
+
return {
|
|
4604
|
+
...eventItem(details.event),
|
|
4605
|
+
ref: `event:${details.event.id}`,
|
|
4606
|
+
event_type: copies.find(({ eventType }) => eventType !== null)?.eventType ?? "default",
|
|
4607
|
+
accounts: [...new Set(held.map(({ account: account2 }) => account2))],
|
|
4608
|
+
in: held.map(({ account: account2, calendar }) => `${account2}/${calendar}`).join(", "),
|
|
4609
|
+
untrusted: UNTRUSTED
|
|
4610
|
+
};
|
|
4611
|
+
}, "rowOf");
|
|
4612
|
+
var listEvents = /* @__PURE__ */ __name(async (store, words, limit, { now = Date.now(), zone = timezoneOf() } = {}) => {
|
|
4613
|
+
const terms2 = nativeTerms(listQuery(typedQuery(words), EVENTS_QUERY2, LIST2), LIST2);
|
|
4614
|
+
const every = await readAccounts(store);
|
|
4615
|
+
const account2 = terms2.get("account");
|
|
4616
|
+
let accounts = account2 ? narrowed(every, account2.value) : every;
|
|
4617
|
+
const filter = { newest: true };
|
|
4618
|
+
const calendar = terms2.get("calendar");
|
|
4619
|
+
if (calendar) {
|
|
4620
|
+
const found = calendarOf(accounts, calendar.value);
|
|
4621
|
+
accounts = [found.account];
|
|
4622
|
+
filter.calendarId = found.calendar.id;
|
|
4623
|
+
}
|
|
4624
|
+
const kind = terms2.get("event_type");
|
|
4625
|
+
if (kind)
|
|
4626
|
+
filter.eventType = kind.value.toLowerCase();
|
|
4627
|
+
const starts = terms2.get("starts_at");
|
|
4628
|
+
if (starts) {
|
|
4629
|
+
const { lower, upper } = startsWindow(starts, zone, now);
|
|
4630
|
+
if (lower !== void 0)
|
|
4631
|
+
filter.startsFrom = lower;
|
|
4632
|
+
if (upper !== void 0)
|
|
4633
|
+
filter.to = upper;
|
|
4634
|
+
} else {
|
|
4635
|
+
const today2 = localDate(now, zone);
|
|
4636
|
+
filter.from = midnight(plusDays(today2, -RECENT_DAYS), zone);
|
|
4637
|
+
filter.to = midnight(plusDays(today2, AHEAD_DAYS + 1), zone);
|
|
4638
|
+
}
|
|
4639
|
+
dated(filter, zone);
|
|
4640
|
+
const read = accounts.map(({ id, key }) => ({ id, key }));
|
|
4641
|
+
const events = read.length ? await store.calendar.events({ ...filter, accountIds: read.map(({ id }) => id), limit: limit + 1 }) : [];
|
|
4642
|
+
const rows = [];
|
|
4643
|
+
for (const event2 of events.slice(0, limit)) {
|
|
4644
|
+
const details = await store.calendar.event(event2.id);
|
|
4645
|
+
if (details)
|
|
4646
|
+
rows.push(rowOf(details, accounts));
|
|
4647
|
+
}
|
|
4648
|
+
const body = listAnswer(LIST2, { items: rows, limit, has_more: events.length > limit });
|
|
4649
|
+
body.meta = {
|
|
4650
|
+
...body.meta,
|
|
4651
|
+
...await accountsMeta(store.calendar, read, [], now),
|
|
4652
|
+
...windowMeta(filter, zone)
|
|
4653
|
+
};
|
|
4654
|
+
return body;
|
|
4655
|
+
}, "listEvents");
|
|
4656
|
+
var showEvent = /* @__PURE__ */ __name(async (store, reference2) => {
|
|
4657
|
+
const text3 = reference2.replace(/^event:/u, "");
|
|
4658
|
+
if (!/^[1-9]\d*$/u.test(text3))
|
|
4659
|
+
throw new CliError("validation_error", "an event is event:<id>");
|
|
4660
|
+
const details = await store.calendar.event(Number(text3));
|
|
4661
|
+
const accounts = await readAccounts(store);
|
|
4662
|
+
const row = details && rowOf(details, accounts);
|
|
4663
|
+
if (!details || !row?.accounts.length)
|
|
4664
|
+
throw new CliError("not_found", `no event ${text3} in any calendar account`);
|
|
4665
|
+
return {
|
|
4666
|
+
...row,
|
|
4667
|
+
attendees: details.participants.map(({ email, name: name2, response, organizer }) => ({
|
|
4668
|
+
email,
|
|
4669
|
+
name: name2,
|
|
4670
|
+
response,
|
|
4671
|
+
organizer
|
|
4672
|
+
})),
|
|
4673
|
+
untrusted: [...UNTRUSTED, "attendees.name"]
|
|
4674
|
+
};
|
|
4675
|
+
}, "showEvent");
|
|
4676
|
+
var accountsLine = /* @__PURE__ */ __name((accounts) => accounts.length ? `calendar accounts read: ${accounts.join(", ")}` : "no calendar account in the store", "accountsLine");
|
|
4677
|
+
|
|
4678
|
+
// dist/events/command.js
|
|
4679
|
+
var upTo1000 = /* @__PURE__ */ __name((value) => {
|
|
4680
|
+
const number2 = Number(value);
|
|
4681
|
+
if (!Number.isInteger(number2) || number2 < 1 || number2 > 1e3)
|
|
4682
|
+
throw new InvalidArgumentError("a whole number, 1 to 1000");
|
|
4683
|
+
return number2;
|
|
4684
|
+
}, "upTo1000");
|
|
4685
|
+
var eventsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
4686
|
+
const { print } = answers(program, streams, env);
|
|
4687
|
+
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");
|
|
4688
|
+
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) => {
|
|
4689
|
+
const body = await withStore(env, (store) => listEvents(store, words, limit));
|
|
4690
|
+
const accounts = body.meta?.accounts ?? [];
|
|
4691
|
+
print(json5, body, `${accountsLine(accounts)}
|
|
4692
|
+
${plainText(body, command)}`);
|
|
4693
|
+
});
|
|
4694
|
+
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)))));
|
|
4695
|
+
}, "eventsCommand");
|
|
4696
|
+
|
|
4286
4697
|
// dist/examples.js
|
|
4287
4698
|
var EXAMPLES = {
|
|
4288
4699
|
context: ["memo context telegram:'Kai Sample'", "memo context email:kai@example.com --limit 5 --json"],
|
|
4289
|
-
show: [
|
|
4700
|
+
show: [
|
|
4701
|
+
"memo show chat:max/500/-1001 document:413",
|
|
4702
|
+
"memo show note:12 msg:telegram/1/77/42 --json",
|
|
4703
|
+
"memo show contract:2 invoice:4 --json"
|
|
4704
|
+
],
|
|
4290
4705
|
"notes show": ["memo notes show note:12", "memo notes show ~/notes/People/Kai.md --json"],
|
|
4291
4706
|
"notes list": [
|
|
4292
4707
|
`memo notes list 'about:"telegram:Kai Sample"'`,
|
|
@@ -4451,7 +4866,7 @@ var EXAMPLES = {
|
|
|
4451
4866
|
"memo relationships update 12 --role contractor --reason 'builds the site'"
|
|
4452
4867
|
],
|
|
4453
4868
|
"relationships add": [
|
|
4454
|
-
"memo relationships add person:3 organization:1 --role
|
|
4869
|
+
"memo relationships add person:3 organization:1 --role employee",
|
|
4455
4870
|
"memo relationships add project:2 organization:1 --kind related-to --reason 'same client'"
|
|
4456
4871
|
],
|
|
4457
4872
|
"relationships list": ['memo relationships list about:"person:3"', "memo relationships list confirmed:false"],
|
|
@@ -4515,6 +4930,11 @@ var EXAMPLES = {
|
|
|
4515
4930
|
"memo orders add 'Shop One' 2499.00 RUB --kind personal --title A-1042",
|
|
4516
4931
|
"memo orders add 'Office Supply' --kind client --organization organization:3"
|
|
4517
4932
|
],
|
|
4933
|
+
"events list": [
|
|
4934
|
+
"memo events list event_type:call",
|
|
4935
|
+
"memo events list account:phone:pixel 'starts_at:[2026-11-02 TO 2026-11-07}' --json"
|
|
4936
|
+
],
|
|
4937
|
+
"events show": ["memo events show event:42"],
|
|
4518
4938
|
"invoices list": ["memo invoices list project:HRB open:true", "memo invoices list review:proposed --json"],
|
|
4519
4939
|
"invoices show": ["memo invoices show invoice:4"],
|
|
4520
4940
|
"invoices add": [
|
|
@@ -4524,19 +4944,93 @@ var EXAMPLES = {
|
|
|
4524
4944
|
"payments list": ["memo payments list project:HRB direction:in", "memo payments list review:proposed --json"],
|
|
4525
4945
|
"payments show": ["memo payments show payment:9"],
|
|
4526
4946
|
"payments add": [
|
|
4527
|
-
"memo payments add 25000.00 RUB --kind in --organization organization:3 --occurred-time 2026-11-01 --project HRB"
|
|
4947
|
+
"memo payments add 25000.00 RUB --kind in --organization organization:3 --occurred-time 2026-11-01 --project HRB",
|
|
4948
|
+
"memo payments add 5000.00 RUB --kind out --organization organization:3 --refund-of payment:9"
|
|
4528
4949
|
],
|
|
4529
4950
|
"records import": [
|
|
4530
4951
|
"memo records import payments.jsonl --account rentals --dry-run",
|
|
4531
|
-
"memo records import envelope.json --account rentals --json"
|
|
4952
|
+
"memo records import envelope.json --account rentals --json",
|
|
4953
|
+
"memo records import contacts.vcf --account phone:pixel"
|
|
4532
4954
|
],
|
|
4533
4955
|
"records check": ["memo records check - --account rentals"],
|
|
4534
4956
|
"records list": [
|
|
4535
4957
|
"memo records list waiting:true --account sheet:rentals",
|
|
4536
|
-
"memo records list type:organization --account sheet:rentals --json"
|
|
4958
|
+
"memo records list type:organization --account sheet:rentals --json",
|
|
4959
|
+
`memo records list 'entity:"organization:3"' deleted:false --account sheet:rentals`
|
|
4537
4960
|
],
|
|
4538
4961
|
"records link": ["memo records link organization:client organization:3 --account sheet:rentals"],
|
|
4539
4962
|
"payments allocate": ["memo payments allocate payment:9 invoice:4 25000.00"],
|
|
4963
|
+
"products list": ["memo products list kind:service", "memo products list archived:true --json"],
|
|
4964
|
+
"products show": ["memo products show product:4"],
|
|
4965
|
+
"products add": [
|
|
4966
|
+
"memo products add 'Bike rental, month' 10000.00 RUB --kind service --unit month",
|
|
4967
|
+
"memo products add 'Helmet' 2500.00 RUB --sku H-12 --supplier organization:3"
|
|
4968
|
+
],
|
|
4969
|
+
"products update": [
|
|
4970
|
+
"memo products update product:4 --amount 12000.00 --currency RUB",
|
|
4971
|
+
"memo products update product:4 --archived on"
|
|
4972
|
+
],
|
|
4973
|
+
"orders lines add": [
|
|
4974
|
+
"memo orders lines add order:3 12 --product product:4",
|
|
4975
|
+
"memo orders lines add order:3 1 Rental, first week --product product:4 --amount 2000.00",
|
|
4976
|
+
"memo orders lines add order:3 2 Helmet --amount 2500.00"
|
|
4977
|
+
],
|
|
4978
|
+
"orders lines remove": ["memo orders lines remove order:3 2"],
|
|
4979
|
+
"invoices lines add": [
|
|
4980
|
+
"memo invoices lines add invoice:4 1 --product product:4",
|
|
4981
|
+
"memo invoices lines add invoice:4 2 Delivery --amount 1500.00"
|
|
4982
|
+
],
|
|
4983
|
+
"invoices lines remove": ["memo invoices lines remove invoice:4 2"],
|
|
4984
|
+
"contracts list": ["memo contracts list status:active", "memo contracts list expires:2026-12-31 --json"],
|
|
4985
|
+
"contracts show": ["memo contracts show contract:2"],
|
|
4986
|
+
"contracts add": [
|
|
4987
|
+
"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",
|
|
4988
|
+
"memo contracts add 'NDA with the studio' --kind nda --project HRB"
|
|
4989
|
+
],
|
|
4990
|
+
"contracts update": [
|
|
4991
|
+
"memo contracts update contract:2 --status terminated",
|
|
4992
|
+
"memo contracts update contract:2 --end-date 2027-12-31"
|
|
4993
|
+
],
|
|
4994
|
+
"subscriptions list": [
|
|
4995
|
+
"memo subscriptions list status:active direction:payable",
|
|
4996
|
+
"memo subscriptions list renews:2026-12-01 --json"
|
|
4997
|
+
],
|
|
4998
|
+
"subscriptions show": ["memo subscriptions show subscription:5"],
|
|
4999
|
+
"subscriptions add": [
|
|
5000
|
+
"memo subscriptions add Hosting 990.00 RUB --kind payable --supplier organization:3 --every 1-month --start-date 2026-11-01",
|
|
5001
|
+
"memo subscriptions add 'Bike rental' 10000.00 RUB --kind receivable --customer organization:3 --every 1-month --trial-end-date 2026-11-14 --status trial"
|
|
5002
|
+
],
|
|
5003
|
+
"subscriptions update": [
|
|
5004
|
+
"memo subscriptions update subscription:5 --status paused",
|
|
5005
|
+
"memo subscriptions update subscription:5 --every 1-year"
|
|
5006
|
+
],
|
|
5007
|
+
"subscriptions cancel": ["memo subscriptions cancel subscription:5 --occurred-time 2026-11-30"],
|
|
5008
|
+
"subscriptions prices add": ["memo subscriptions prices add subscription:5 1190.00 RUB --start-date 2027-01-01"],
|
|
5009
|
+
"wallets list": ["memo wallets list", "memo wallets list kind:card --json"],
|
|
5010
|
+
"wallets show": ["memo wallets show wallet:2", "memo wallets show wallet:2 --until-time 2026-10-31"],
|
|
5011
|
+
"wallets add": ["memo wallets add 'Main card' RUB --kind card --institution 'Bank One'"],
|
|
5012
|
+
"wallets update": ["memo wallets update wallet:2 --opening-balance 15000.00 --opening-date 2026-01-01"],
|
|
5013
|
+
"transactions list": [
|
|
5014
|
+
`memo transactions list 'wallet:"wallet:2"' status:pending`,
|
|
5015
|
+
"memo transactions list uncategorized:true --json"
|
|
5016
|
+
],
|
|
5017
|
+
"transactions show": ["memo transactions show transaction:12"],
|
|
5018
|
+
"transactions add": [
|
|
5019
|
+
"memo transactions add wallet:2 500.00 --kind out --occurred-time 2026-11-14 --description 'Coffee shop'",
|
|
5020
|
+
"memo transactions add wallet:2 10000.00 --kind in --payment payment:9"
|
|
5021
|
+
],
|
|
5022
|
+
"transactions update": [
|
|
5023
|
+
"memo transactions update transaction:12 --status booked",
|
|
5024
|
+
"memo transactions update transaction:12 --payment payment:9"
|
|
5025
|
+
],
|
|
5026
|
+
"transactions splits add": ["memo transactions splits add transaction:12 300.00 Rent --project HRB"],
|
|
5027
|
+
"transactions splits remove": ["memo transactions splits remove transaction:12 1"],
|
|
5028
|
+
"records show": [
|
|
5029
|
+
"memo records show custom:quote:Q-7 --account example-erp:demo",
|
|
5030
|
+
"memo records show organization:client --account sheet:rentals --json"
|
|
5031
|
+
],
|
|
5032
|
+
"records delete": ["memo records delete payment:sheet-12 --account sheet:rentals"],
|
|
5033
|
+
"records match": ["memo records match --account sheet:rentals"],
|
|
4540
5034
|
"payments unlink": ["memo payments unlink payment:9 invoice:4"],
|
|
4541
5035
|
"facts show": ["memo facts show fact:4 --sources"],
|
|
4542
5036
|
"facts confirm": ["memo facts confirm fact:4"],
|
|
@@ -4606,7 +5100,11 @@ var EXAMPLES = {
|
|
|
4606
5100
|
"mcp server start": ["memo mcp server start --public-url https://laptop.example.ts.net"],
|
|
4607
5101
|
"mcp server status": ["memo mcp server status --json"],
|
|
4608
5102
|
"mcp server stop": ["memo mcp server stop"],
|
|
4609
|
-
"search all": [
|
|
5103
|
+
"search all": [
|
|
5104
|
+
"memo search all 'budget harbour'",
|
|
5105
|
+
"memo search all 'content:invoice' --only mail,notes --json",
|
|
5106
|
+
"memo search all 'Rental agreement' --only business"
|
|
5107
|
+
],
|
|
4610
5108
|
"search messages": ["memo search messages 'friday meeting has:voice'"],
|
|
4611
5109
|
"search mail": ["memo search mail 'mailbox:important budget' --source email:me@example.com"],
|
|
4612
5110
|
"search notes": ["memo search notes budget notes:2", "memo search notes kickoff --project HRB --json"],
|
|
@@ -4706,13 +5204,13 @@ var memoryItem = /* @__PURE__ */ __name(({ body, ...memory }) => ({
|
|
|
4706
5204
|
updatedAt: memory.updatedAt
|
|
4707
5205
|
}), "memoryItem");
|
|
4708
5206
|
var listMemories = /* @__PURE__ */ __name(async (store, query, limit) => {
|
|
4709
|
-
const
|
|
4710
|
-
const project =
|
|
5207
|
+
const terms2 = queryTerms(query, MEMORY_QUERY, "memories list");
|
|
5208
|
+
const project = terms2.get("project");
|
|
4711
5209
|
const filters = {
|
|
4712
|
-
...
|
|
4713
|
-
...
|
|
4714
|
-
...
|
|
4715
|
-
...
|
|
5210
|
+
...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
|
|
5211
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
5212
|
+
...terms2.has("scope") ? { scope: terms2.get("scope") } : {},
|
|
5213
|
+
...terms2.has("subject") ? { subject: terms2.get("subject") } : {},
|
|
4716
5214
|
...project === void 0 ? {} : { project: await canonicalProject(store, project) }
|
|
4717
5215
|
};
|
|
4718
5216
|
return pageOf("memories list", limit, async (most) => (await store.memories.list({ ...filters, limit: most })).map(memoryItem));
|
|
@@ -4766,7 +5264,7 @@ var memoriesCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
4766
5264
|
...options.supersedes === void 0 ? {} : { supersedes: options.supersedes }
|
|
4767
5265
|
}, await by))));
|
|
4768
5266
|
});
|
|
4769
|
-
withQuery(annotate(memories.command("list"), { effects: LOCAL_READ }).description("memories, newest first"), MEMORY_QUERY).option("--limit <n>", "most memories, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json:
|
|
5267
|
+
withQuery(annotate(memories.command("list"), { effects: LOCAL_READ }).description("memories, newest first"), MEMORY_QUERY).option("--limit <n>", "most memories, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json: json5, limit }) => run(json5, (store) => listMemories(store, words, limit)));
|
|
4770
5268
|
annotate(memories.command("show"), { effects: LOCAL_READ, output: { entity: "memory" } }).description("one memory with its evidence").argument("<ref>", "memory:<id>").option("--sources", "read each piece of evidence back: who, when, a short excerpt, and whether it is gone").option("--json", "print JSON; --json=id,title keeps only those fields").action((ref, options) => run(options.json, async (store) => itemAnswer({
|
|
4771
5269
|
...memoryItem(await store.memories.get(ref)),
|
|
4772
5270
|
...options.sources ? { sources: await store.memories.sources(ref) } : {}
|
|
@@ -4836,13 +5334,13 @@ var factItem = /* @__PURE__ */ __name(({ type, statement, source, confirmedBy, .
|
|
|
4836
5334
|
confirmed_by: confirmedBy
|
|
4837
5335
|
}), "factItem");
|
|
4838
5336
|
var listFacts = /* @__PURE__ */ __name(async (store, query, limit) => {
|
|
4839
|
-
const
|
|
4840
|
-
const project =
|
|
5337
|
+
const terms2 = queryTerms(query, FACT_QUERY, "facts list");
|
|
5338
|
+
const project = terms2.get("project");
|
|
4841
5339
|
const filters = {
|
|
4842
|
-
...
|
|
4843
|
-
...
|
|
5340
|
+
...terms2.has("kind") ? { type: terms2.get("kind") } : {},
|
|
5341
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
4844
5342
|
...project === void 0 ? {} : { project: await canonicalProject(store, project) },
|
|
4845
|
-
...
|
|
5343
|
+
...terms2.has("subject") ? { subject: terms2.get("subject") } : {}
|
|
4846
5344
|
};
|
|
4847
5345
|
return pageOf("facts list", limit, async (most) => (await store.facts.list({ ...filters, limit: most })).map(factItem));
|
|
4848
5346
|
}, "listFacts");
|
|
@@ -4884,7 +5382,7 @@ var factsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
4884
5382
|
...options.supersedes === void 0 ? {} : { supersedes: options.supersedes }
|
|
4885
5383
|
}))));
|
|
4886
5384
|
});
|
|
4887
|
-
withQuery(annotate(facts.command("list"), { effects: LOCAL_READ }).description("facts, latest first"), FACT_QUERY).option("--limit <n>", "most facts, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json:
|
|
5385
|
+
withQuery(annotate(facts.command("list"), { effects: LOCAL_READ }).description("facts, latest first"), FACT_QUERY).option("--limit <n>", "most facts, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json: json5, limit }) => run(json5, (store) => listFacts(store, words, limit)));
|
|
4888
5386
|
annotate(facts.command("show"), { effects: LOCAL_READ, output: { entity: "fact" } }).description("one fact with its evidence").argument("<ref>", "fact:<id>").option("--sources", "read each piece of evidence back: who, when, a short excerpt, and whether it is gone").option("--json", "print JSON; --json=id,title keeps only those fields").action((ref, options) => run(options.json, async (store) => itemAnswer({
|
|
4889
5387
|
...factItem(await store.facts.get(ref)),
|
|
4890
5388
|
...options.sources ? { sources: await store.facts.sources(ref) } : {}
|
|
@@ -4914,6 +5412,67 @@ var factsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
4914
5412
|
${FORGET_HELP.replace("use invalidate", "use reject or reverse")}`);
|
|
4915
5413
|
}, "factsCommand");
|
|
4916
5414
|
|
|
5415
|
+
// dist/records/sources.js
|
|
5416
|
+
var MOST = 100;
|
|
5417
|
+
var READS = {
|
|
5418
|
+
product: /* @__PURE__ */ __name((store, ref) => store.products.get(ref), "product"),
|
|
5419
|
+
contract: /* @__PURE__ */ __name((store, ref) => store.contracts.get(ref), "contract"),
|
|
5420
|
+
subscription: /* @__PURE__ */ __name((store, ref) => store.subscriptions.get(ref), "subscription"),
|
|
5421
|
+
wallet: /* @__PURE__ */ __name((store, ref) => store.wallets.get(ref), "wallet"),
|
|
5422
|
+
transaction: /* @__PURE__ */ __name((store, ref) => store.transactions.get(ref), "transaction"),
|
|
5423
|
+
invoice: /* @__PURE__ */ __name((store, ref) => store.finance.invoice(ref), "invoice"),
|
|
5424
|
+
payment: /* @__PURE__ */ __name((store, ref) => store.finance.payment(ref), "payment"),
|
|
5425
|
+
order: /* @__PURE__ */ __name((store, ref) => store.orders.get(ref), "order"),
|
|
5426
|
+
deal: /* @__PURE__ */ __name((store, ref) => store.deals.get(ref), "deal"),
|
|
5427
|
+
lead: /* @__PURE__ */ __name((store, ref) => store.deals.get(ref), "lead"),
|
|
5428
|
+
pipeline: /* @__PURE__ */ __name((store, ref) => store.deals.pipeline(ref), "pipeline")
|
|
5429
|
+
};
|
|
5430
|
+
var SOURCED = new Set(Object.keys(READS));
|
|
5431
|
+
var readSourced = /* @__PURE__ */ __name((store, kind, ref) => READS[kind]?.(store, ref), "readSourced");
|
|
5432
|
+
var IMPORT = "import:";
|
|
5433
|
+
var imported = /* @__PURE__ */ __name(({ source, account: account2 }) => (account2 ?? null) !== null || !!source?.startsWith(IMPORT), "imported");
|
|
5434
|
+
var sourceAccounts = /* @__PURE__ */ __name(async (store, { source, account: account2 }) => {
|
|
5435
|
+
if (account2)
|
|
5436
|
+
return [account2];
|
|
5437
|
+
if (!source?.startsWith(IMPORT))
|
|
5438
|
+
return [];
|
|
5439
|
+
const provider = source.slice(IMPORT.length);
|
|
5440
|
+
return (await store.accounts.accounts()).filter((key) => key.provider === provider);
|
|
5441
|
+
}, "sourceAccounts");
|
|
5442
|
+
var named2 = /* @__PURE__ */ __name((key) => ({
|
|
5443
|
+
record: `${key.type}:${key.externalId}`,
|
|
5444
|
+
account: `${key.provider}:${key.account}`
|
|
5445
|
+
}), "named");
|
|
5446
|
+
var sourcesOf = /* @__PURE__ */ __name(async (store, entity) => {
|
|
5447
|
+
const { ref } = entity;
|
|
5448
|
+
const records = [];
|
|
5449
|
+
for (const { provider, account: account2 } of await sourceAccounts(store, entity)) {
|
|
5450
|
+
if (records.length > MOST)
|
|
5451
|
+
break;
|
|
5452
|
+
for (const one2 of await store.records.list({ provider, account: account2, entity: ref, limit: MOST + 1 }))
|
|
5453
|
+
records.push({
|
|
5454
|
+
...named2(one2),
|
|
5455
|
+
...one2.flagged ? { flagged: true } : {},
|
|
5456
|
+
...one2.deletedAt === null ? {} : { deleted: true }
|
|
5457
|
+
});
|
|
5458
|
+
}
|
|
5459
|
+
const incoming = await store.records.incoming({ entity: ref }, { limit: MOST + 1 });
|
|
5460
|
+
return {
|
|
5461
|
+
records: { items: records.slice(0, MOST), hasMore: records.length > MOST },
|
|
5462
|
+
incoming: {
|
|
5463
|
+
items: incoming.slice(0, MOST).map(({ record: record2, role, as }) => ({ ...named2(record2), role, as })),
|
|
5464
|
+
hasMore: incoming.length > MOST
|
|
5465
|
+
}
|
|
5466
|
+
};
|
|
5467
|
+
}, "sourcesOf");
|
|
5468
|
+
var sourcesText = /* @__PURE__ */ __name((ref, { records, incoming }, indent = " ") => [
|
|
5469
|
+
...records.items.map((one2) => `${indent}from ${one2.account} ${one2.record}${one2.flagged ? " (flagged)" : ""}${one2.deleted ? " (deleted)" : ""}`),
|
|
5470
|
+
...incoming.items.map((one2) => `${indent}named by ${one2.account} ${one2.record} as ${one2.role}${one2.as === null ? "" : ` (${one2.as})`}`),
|
|
5471
|
+
...records.hasMore || incoming.hasMore ? [`${indent}more: memo records list entity:${ref} --account <account>`] : []
|
|
5472
|
+
], "sourcesText");
|
|
5473
|
+
var recordsHidden = /* @__PURE__ */ __name((command) => grantedLevel(command, "records.show") === "deny", "recordsHidden");
|
|
5474
|
+
var withSources = /* @__PURE__ */ __name(async (command, store, item) => recordsHidden(command) ? item : { ...item, sources: await sourcesOf(store, item) }, "withSources");
|
|
5475
|
+
|
|
4917
5476
|
// dist/finance/finance.js
|
|
4918
5477
|
var INVOICE_QUERY = {
|
|
4919
5478
|
entity: "invoice",
|
|
@@ -4941,25 +5500,25 @@ var PAYMENT_QUERY = {
|
|
|
4941
5500
|
var projectTerm = /* @__PURE__ */ __name(async (store, project) => project === void 0 ? {} : { project: await canonicalProject(store, project) }, "projectTerm");
|
|
4942
5501
|
var reviewTerm = /* @__PURE__ */ __name((review) => review === void 0 ? {} : { review }, "reviewTerm");
|
|
4943
5502
|
var listInvoices = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
4944
|
-
const
|
|
5503
|
+
const terms2 = queryTerms(words, INVOICE_QUERY, "invoices list");
|
|
4945
5504
|
const filter = {
|
|
4946
|
-
...await projectTerm(store,
|
|
4947
|
-
...reviewTerm(
|
|
4948
|
-
...
|
|
4949
|
-
...
|
|
4950
|
-
...
|
|
4951
|
-
...
|
|
4952
|
-
...
|
|
5505
|
+
...await projectTerm(store, terms2.get("project")),
|
|
5506
|
+
...reviewTerm(terms2.get("review")),
|
|
5507
|
+
...terms2.has("direction") ? { direction: terms2.get("direction") } : {},
|
|
5508
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
5509
|
+
...terms2.has("counterparty") ? { counterparty: terms2.get("counterparty") } : {},
|
|
5510
|
+
...terms2.has("number") ? { number: terms2.get("number") } : {},
|
|
5511
|
+
...terms2.has("open") ? { open: terms2.get("open") === "true" } : {}
|
|
4953
5512
|
};
|
|
4954
5513
|
return pageOf("invoices list", limit, (most) => store.finance.invoices({ ...filter, limit: most }));
|
|
4955
5514
|
}, "listInvoices");
|
|
4956
5515
|
var listPayments = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
4957
|
-
const
|
|
5516
|
+
const terms2 = queryTerms(words, PAYMENT_QUERY, "payments list");
|
|
4958
5517
|
const filter = {
|
|
4959
|
-
...await projectTerm(store,
|
|
4960
|
-
...reviewTerm(
|
|
4961
|
-
...
|
|
4962
|
-
...
|
|
5518
|
+
...await projectTerm(store, terms2.get("project")),
|
|
5519
|
+
...reviewTerm(terms2.get("review")),
|
|
5520
|
+
...terms2.has("direction") ? { direction: terms2.get("direction") } : {},
|
|
5521
|
+
...terms2.has("party") ? { party: terms2.get("party") } : {}
|
|
4963
5522
|
};
|
|
4964
5523
|
return pageOf("payments list", limit, (most) => store.finance.payments({ ...filter, limit: most }));
|
|
4965
5524
|
}, "listPayments");
|
|
@@ -5029,14 +5588,21 @@ var financeText = /* @__PURE__ */ __name((block) => block.length === 0 ? [] : [
|
|
|
5029
5588
|
})
|
|
5030
5589
|
], "financeText");
|
|
5031
5590
|
|
|
5032
|
-
// dist/finance/
|
|
5033
|
-
var json = /* @__PURE__ */ __name((command) => command
|
|
5591
|
+
// dist/finance/written.js
|
|
5592
|
+
var json = /* @__PURE__ */ __name((command) => jsonOption(command), "json");
|
|
5034
5593
|
var PROPOSES = "yours is confirmed at once; an agent's waits as proposed for you in memo review";
|
|
5035
|
-
var
|
|
5036
|
-
if (
|
|
5037
|
-
throw new CliError("validation_error",
|
|
5038
|
-
return
|
|
5039
|
-
}, "
|
|
5594
|
+
var choice = /* @__PURE__ */ __name((value, allowed, flag) => {
|
|
5595
|
+
if (value === void 0 || !allowed.includes(value))
|
|
5596
|
+
throw new CliError("validation_error", `${flag} is one of ${allowed.join(", ")}`, { param: flag });
|
|
5597
|
+
return value;
|
|
5598
|
+
}, "choice");
|
|
5599
|
+
var needed = /* @__PURE__ */ __name((value, flag, what) => {
|
|
5600
|
+
if (value === void 0 || value.trim() === "")
|
|
5601
|
+
throw new CliError("validation_error", `name ${what}: ${flag}`, { param: flag });
|
|
5602
|
+
return value;
|
|
5603
|
+
}, "needed");
|
|
5604
|
+
var optionalChoice = /* @__PURE__ */ __name((value, allowed, flag) => value === void 0 ? void 0 : choice(value, allowed, flag), "optionalChoice");
|
|
5605
|
+
var onOff = /* @__PURE__ */ __name((value, flag) => value === void 0 ? void 0 : choice(value, ["on", "off"], flag) === "on", "onOff");
|
|
5040
5606
|
var writtenBy = /* @__PURE__ */ __name(async (store, by, options) => ({
|
|
5041
5607
|
by,
|
|
5042
5608
|
...options.project === void 0 ? {} : { project: await canonicalProject(store, options.project) },
|
|
@@ -5045,23 +5611,71 @@ var writtenBy = /* @__PURE__ */ __name(async (store, by, options) => ({
|
|
|
5045
5611
|
}), "writtenBy");
|
|
5046
5612
|
var party = /* @__PURE__ */ __name((command, what) => command.option("--person <uid>", `the person ${what}: person:<id>`).option("--organization <organization>", `the organization ${what}: organization:<id>`), "party");
|
|
5047
5613
|
var writeMeta = /* @__PURE__ */ __name((command) => byOption(command.option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent proposes it, for the owner who decides").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference")), "writeMeta");
|
|
5614
|
+
var given = /* @__PURE__ */ __name((fields) => Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== void 0)), "given");
|
|
5615
|
+
|
|
5616
|
+
// dist/finance/lines-command.js
|
|
5617
|
+
var LINE_PARENTS = {
|
|
5618
|
+
order: {
|
|
5619
|
+
has: "an order that has a currency (orders add with an amount)",
|
|
5620
|
+
shown: "orders show",
|
|
5621
|
+
add: /* @__PURE__ */ __name((store, ref, line3) => store.orders.addLine(ref, line3), "add"),
|
|
5622
|
+
remove: /* @__PURE__ */ __name((store, ref, input) => store.orders.removeLine(ref, input), "remove")
|
|
5623
|
+
},
|
|
5624
|
+
invoice: {
|
|
5625
|
+
has: "an invoice that is not void; the total never falls below what confirmed payments settled",
|
|
5626
|
+
shown: "invoices show",
|
|
5627
|
+
add: /* @__PURE__ */ __name((store, ref, line3) => store.finance.addInvoiceLine(ref, line3), "add"),
|
|
5628
|
+
remove: /* @__PURE__ */ __name((store, ref, input) => store.finance.removeInvoiceLine(ref, input), "remove")
|
|
5629
|
+
}
|
|
5630
|
+
};
|
|
5631
|
+
var lineCommands = /* @__PURE__ */ __name((parent, kind, run, env) => {
|
|
5632
|
+
const { has, shown: shown2, add, remove } = LINE_PARENTS[kind];
|
|
5633
|
+
const one2 = kind === "order" ? "an order" : "an invoice";
|
|
5634
|
+
const who = `you change any ${kind}'s lines; an agent only those of ${one2} it proposed that is still proposed`;
|
|
5635
|
+
const lines2 = parent.command("lines").description(`the lines of ${one2}, each a quantity at a price; its total is their sum. ${who}`).summary(`the lines of ${one2}`);
|
|
5636
|
+
const asker = /* @__PURE__ */ __name((ref) => `change ${ref}'s lines as yours?`, "asker");
|
|
5637
|
+
json(byOption(annotate(lines2.command("add"), {
|
|
5638
|
+
effects: LOCAL_WRITE,
|
|
5639
|
+
output: { entity: kind },
|
|
5640
|
+
literal_after_dashes: true
|
|
5641
|
+
}).option("--product <product>", "the product or service it is: its name and price are copied onto the line").option("--amount <decimal>", "the price of one, such as 10000.00; the product's when left out with --product"))).description(`add a line at the end of ${has}: quantity \xD7 price, and the total becomes the sum of the lines. With --product its name and price are copied, so a later price change leaves the line as it is, and --amount sets another price; without --product, --amount is needed. ${who}`).summary(`add a line to ${one2}`).argument(`<${kind}>`, `${kind}:<id>`).argument("<quantity>", "how many, a decimal such as 12 or 1.5").argument("[description...]", "what the line is, in a few words; the product's name when left out").action(async (ref, quantity, words, options, command) => {
|
|
5642
|
+
if (options.product === void 0)
|
|
5643
|
+
needed(options.amount, "--amount", "the price of one, or --product");
|
|
5644
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: asker(ref) });
|
|
5645
|
+
await run(options.json, async (store) => itemAnswer(await add(store, ref, {
|
|
5646
|
+
by,
|
|
5647
|
+
quantity,
|
|
5648
|
+
...given({
|
|
5649
|
+
unitPrice: options.amount,
|
|
5650
|
+
description: words.length > 0 ? words.join(" ") : void 0,
|
|
5651
|
+
product: options.product
|
|
5652
|
+
})
|
|
5653
|
+
})));
|
|
5654
|
+
});
|
|
5655
|
+
json(byOption(annotate(lines2.command("remove"), { effects: LOCAL_WRITE, output: { entity: kind } }))).description(`take a line off ${one2}; the others keep their positions, and the last line stays. ${who}`).summary(`take a line off ${one2}`).argument(`<${kind}>`, `${kind}:<id>`).argument("<position>", `the line's position, from 1, as ${shown2} lists it`, positive).action(async (ref, position, options, command) => {
|
|
5656
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: asker(ref) });
|
|
5657
|
+
await run(options.json, async (store) => itemAnswer(await remove(store, ref, { position, by })));
|
|
5658
|
+
});
|
|
5659
|
+
}, "lineCommands");
|
|
5660
|
+
|
|
5661
|
+
// dist/finance/command.js
|
|
5048
5662
|
var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5049
5663
|
const { run } = answers(program, streams, env);
|
|
5050
5664
|
const invoices = program.command("invoices").description("invoices you issued or received, with their lines and what paid them; amounts per currency").summary("invoices you issued or received, and what paid them");
|
|
5051
|
-
withQuery(json(annotate(invoices.command("list"), { effects: LOCAL_READ })).description("invoices, newest first; review:proposed lists what waits for you"), INVOICE_QUERY).option("--limit <n>", "most invoices, up to 500", positive, 100).action((words, { json:
|
|
5052
|
-
json(annotate(invoices.command("show"), { effects: LOCAL_READ, output: { entity: "invoice" } })).description("one invoice with its lines and the payments allocated to it").argument("<ref>", "invoice:<id>").action((ref, options) => run(options.json, async (store) => itemAnswer(await store.finance.invoice(ref))));
|
|
5665
|
+
withQuery(json(annotate(invoices.command("list"), { effects: LOCAL_READ })).description("invoices, newest first; review:proposed lists what waits for you"), INVOICE_QUERY).option("--limit <n>", "most invoices, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listInvoices(store, words, limit)));
|
|
5666
|
+
json(annotate(invoices.command("show"), { effects: LOCAL_READ, output: { entity: "invoice" } })).description("one invoice with its lines and the payments allocated to it").argument("<ref>", "invoice:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.finance.invoice(ref)))));
|
|
5053
5667
|
json(writeMeta(party(annotate(invoices.command("add"), {
|
|
5054
5668
|
effects: LOCAL_WRITE,
|
|
5055
5669
|
output: { entity: "invoice" },
|
|
5056
5670
|
literal_after_dashes: true
|
|
5057
|
-
}), "billed or billing").option("--kind <kind>", "receivable (you bill them) or payable (they bill you)").option("--title <title>", "the invoice's number, as printed on it").option("--occurred-time <time>", "the day it was issued, such as 2026-11-01").option("--due <time>", "the day it is due, such as 2026-11-15"))).description(`record an invoice of one line; ${PROPOSES}`).summary("record an invoice; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").argument("<description...>", "what it bills, in a few words").action(async (amount2, currency, words, options, command) => {
|
|
5671
|
+
}), "billed or billing").option("--kind <kind>", "receivable (you bill them) or payable (they bill you)").option("--title <title>", "the invoice's number, as printed on it").option("--occurred-time <time>", "the day it was issued, such as 2026-11-01").option("--due <time>", "the day it is due, such as 2026-11-15"))).description(`record an invoice of one line, and add more with invoices lines add; ${PROPOSES}`).summary("record an invoice; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").argument("<description...>", "what it bills, in a few words").action(async (amount2, currency, words, options, command) => {
|
|
5058
5672
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this invoice as yours?" });
|
|
5059
5673
|
await run(options.json, async (store) => {
|
|
5060
5674
|
const issueDate = dayOf(options.occurredTime);
|
|
5061
5675
|
const dueDate = dayOf(options.due);
|
|
5062
5676
|
return itemAnswer(await store.finance.addInvoice({
|
|
5063
5677
|
...await writtenBy(store, by, options),
|
|
5064
|
-
direction:
|
|
5678
|
+
direction: choice(options.kind, INVOICE_DIRECTIONS, "--kind"),
|
|
5065
5679
|
counterparty: partyOf(options, true),
|
|
5066
5680
|
currency,
|
|
5067
5681
|
lines: [{ description: words.join(" "), amount: amount2 }],
|
|
@@ -5071,13 +5685,14 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5071
5685
|
}));
|
|
5072
5686
|
});
|
|
5073
5687
|
});
|
|
5688
|
+
lineCommands(invoices, "invoice", run, env);
|
|
5074
5689
|
const payments = program.command("payments").description("money paid to you or by you, and the invoices each payment settles; amounts per currency").summary("money paid to you or by you, and what it settles");
|
|
5075
|
-
withQuery(json(annotate(payments.command("list"), { effects: LOCAL_READ })).description("payments, newest first; review:proposed lists what waits for you"), PAYMENT_QUERY).option("--limit <n>", "most payments, up to 500", positive, 100).action((words, { json:
|
|
5076
|
-
json(annotate(payments.command("show"), { effects: LOCAL_READ, output: { entity: "payment" } })).description("one payment with the invoices it is allocated to").argument("<ref>", "payment:<id>").action((ref, options) => run(options.json, async (store) => itemAnswer(await store.finance.payment(ref))));
|
|
5077
|
-
json(writeMeta(party(annotate(payments.command("add"), { effects: LOCAL_WRITE, output: { entity: "payment" } }), "who paid or was paid").option("--kind <kind>", "in (paid to you) or out (paid by you)").option("--title <title>", "the payment's reference, such as the bank's purpose line").option("--occurred-time <time>", "the day it was paid, such as 2026-11-01; today when left out"))).description(`record a payment; ${PROPOSES}. payments allocate matches it to an invoice`).summary("record a payment; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").action(async (amount2, currency, options, command) => {
|
|
5690
|
+
withQuery(json(annotate(payments.command("list"), { effects: LOCAL_READ })).description("payments, newest first; review:proposed lists what waits for you"), PAYMENT_QUERY).option("--limit <n>", "most payments, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listPayments(store, words, limit)));
|
|
5691
|
+
json(annotate(payments.command("show"), { effects: LOCAL_READ, output: { entity: "payment" } })).description("one payment with the invoices it is allocated to").argument("<ref>", "payment:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.finance.payment(ref)))));
|
|
5692
|
+
json(writeMeta(party(annotate(payments.command("add"), { effects: LOCAL_WRITE, output: { entity: "payment" } }), "who paid or was paid").option("--kind <kind>", "in (paid to you) or out (paid by you)").option("--title <title>", "the payment's reference, such as the bank's purpose line").option("--occurred-time <time>", "the day it was paid, such as 2026-11-01; today when left out").option("--refund-of <payment>", "the payment this one gives money back for, going the other way: payment:<id>"))).description(`record a payment, or with --refund-of a refund of one; ${PROPOSES}. payments allocate matches it to an invoice`).summary("record a payment; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").action(async (amount2, currency, options, command) => {
|
|
5078
5693
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this payment as yours?" });
|
|
5079
5694
|
await run(options.json, async (store) => {
|
|
5080
|
-
const direction =
|
|
5695
|
+
const direction = choice(options.kind, MONEY_DIRECTIONS, "--kind");
|
|
5081
5696
|
const counterparty = partyOf(options, false);
|
|
5082
5697
|
return itemAnswer(await store.finance.addPayment({
|
|
5083
5698
|
...await writtenBy(store, by, options),
|
|
@@ -5086,7 +5701,8 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5086
5701
|
amount: amount2,
|
|
5087
5702
|
currency,
|
|
5088
5703
|
date: dayOf(options.occurredTime) ?? today(),
|
|
5089
|
-
...options.title === void 0 ? {} : { reference: options.title }
|
|
5704
|
+
...options.title === void 0 ? {} : { reference: options.title },
|
|
5705
|
+
...options.refundOf === void 0 ? {} : { refundOf: options.refundOf }
|
|
5090
5706
|
}));
|
|
5091
5707
|
});
|
|
5092
5708
|
});
|
|
@@ -5103,6 +5719,78 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5103
5719
|
});
|
|
5104
5720
|
}, "financeCommands");
|
|
5105
5721
|
|
|
5722
|
+
// dist/finance/contracts-command.js
|
|
5723
|
+
var CONTRACT_QUERY = {
|
|
5724
|
+
entity: "contract",
|
|
5725
|
+
backend: "native",
|
|
5726
|
+
fields: [
|
|
5727
|
+
termField("status", "enum", "status:active", { values: CONTRACT_STATUSES }),
|
|
5728
|
+
termField("kind", "enum", "kind:lease", { values: CONTRACT_KINDS }),
|
|
5729
|
+
termField("project", "kw", "project:PMED"),
|
|
5730
|
+
termField("review", "enum", "review:proposed", { values: FINANCE_REVIEWS }),
|
|
5731
|
+
termField("expires", "time", "expires:2026-12-31")
|
|
5732
|
+
]
|
|
5733
|
+
};
|
|
5734
|
+
var listContracts = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
5735
|
+
const terms2 = queryTerms(words, CONTRACT_QUERY, "contracts list");
|
|
5736
|
+
const project = terms2.get("project");
|
|
5737
|
+
const filter = given({
|
|
5738
|
+
status: terms2.get("status"),
|
|
5739
|
+
kind: terms2.get("kind"),
|
|
5740
|
+
review: terms2.get("review"),
|
|
5741
|
+
expiresBy: dayOf(terms2.get("expires")),
|
|
5742
|
+
project: project === void 0 ? void 0 : await canonicalProject(store, project)
|
|
5743
|
+
});
|
|
5744
|
+
return pageOf("contracts list", limit, (most) => store.contracts.list({ ...filter, limit: most }));
|
|
5745
|
+
}, "listContracts");
|
|
5746
|
+
var days = /* @__PURE__ */ __name((value) => {
|
|
5747
|
+
const number2 = Number(value);
|
|
5748
|
+
if (!Number.isInteger(number2) || number2 < 0)
|
|
5749
|
+
throw new InvalidArgumentError("a whole number of days, 0 or more");
|
|
5750
|
+
return number2;
|
|
5751
|
+
}, "days");
|
|
5752
|
+
var terms = /* @__PURE__ */ __name((command) => command.option("--kind <kind>", `what it is: ${CONTRACT_KINDS.join(", ")}`).option("--status <state>", `${CONTRACT_STATUSES.join(", ")}; active when left out`).option("--start-date <date>", "the first day it is in force, YYYY-MM-DD").option("--end-date <date>", "the last day it is in force, YYYY-MM-DD; left out, it runs until ended").option("--auto-renew <on|off>", "it renews by itself at its end, or it does not").option("--notice-days <days>", "how many days before its end a party must say it will not go on", days).option("--amount <decimal>", "what it is worth, such as 120000.00, in --currency; with it, an agent's waits for you").option("--currency <code>", "an ISO 4217 code, such as RUB"), "terms");
|
|
5753
|
+
var fieldsOf2 = /* @__PURE__ */ __name((options) => given({
|
|
5754
|
+
status: optionalChoice(options.status, CONTRACT_STATUSES, "--status"),
|
|
5755
|
+
effectiveDate: dayOf(options.startDate),
|
|
5756
|
+
expirationDate: dayOf(options.endDate),
|
|
5757
|
+
autoRenew: onOff(options.autoRenew, "--auto-renew"),
|
|
5758
|
+
noticeDays: options.noticeDays,
|
|
5759
|
+
value: options.amount,
|
|
5760
|
+
currency: options.currency
|
|
5761
|
+
}), "fieldsOf");
|
|
5762
|
+
var VALUED = "one with no amount is written as it is, by anyone; with an amount yours is confirmed at once and an agent's waits as proposed for you in memo review";
|
|
5763
|
+
var contractCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5764
|
+
const { run } = answers(program, streams, env);
|
|
5765
|
+
const contracts = program.command("contracts").description("contracts you work under: their kind, dates, renewal, notice and what they are worth").summary("contracts you work under, with their dates and notice");
|
|
5766
|
+
withQuery(json(annotate(contracts.command("list"), { effects: LOCAL_READ })).description("contracts, newest first; expires:2026-12-31 lists those that end by then"), CONTRACT_QUERY).option("--limit <n>", "most contracts, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listContracts(store, words, limit)));
|
|
5767
|
+
json(annotate(contracts.command("show"), { effects: LOCAL_READ, output: { entity: "contract" } })).description("one contract with its dates, renewal and the last day to give notice").argument("<contract>", "contract:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.contracts.get(ref)))));
|
|
5768
|
+
json(writeMeta(terms(annotate(contracts.command("add"), {
|
|
5769
|
+
effects: LOCAL_WRITE,
|
|
5770
|
+
output: { entity: "contract" },
|
|
5771
|
+
literal_after_dashes: true
|
|
5772
|
+
})))).description(`record a contract; ${VALUED}`).summary("record a contract").argument("<name>", "what it is called, such as 'Rental agreement'").action(async (name2, options, command) => {
|
|
5773
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this contract as yours?" });
|
|
5774
|
+
await run(options.json, async (store) => itemAnswer(await store.contracts.add({
|
|
5775
|
+
...await writtenBy(store, by, options),
|
|
5776
|
+
name: name2,
|
|
5777
|
+
kind: choice(options.kind, CONTRACT_KINDS, "--kind"),
|
|
5778
|
+
...fieldsOf2(options)
|
|
5779
|
+
})));
|
|
5780
|
+
});
|
|
5781
|
+
json(byOption(terms(annotate(contracts.command("update"), { effects: LOCAL_WRITE, output: { entity: "contract" } })).option("--title <title>", "its new name"))).description("change a contract's dates, status, terms or worth; you change any, an agent only one it proposed that is still proposed, and a confirmed contract's worth only you").summary("change a contract").argument("<contract>", "contract:<id>").action(async (ref, options, command) => {
|
|
5782
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
|
|
5783
|
+
await run(options.json, async (store) => itemAnswer(await store.contracts.update(ref, {
|
|
5784
|
+
by,
|
|
5785
|
+
...fieldsOf2(options),
|
|
5786
|
+
...given({
|
|
5787
|
+
name: options.title,
|
|
5788
|
+
kind: optionalChoice(options.kind, CONTRACT_KINDS, "--kind")
|
|
5789
|
+
})
|
|
5790
|
+
})));
|
|
5791
|
+
});
|
|
5792
|
+
}, "contractCommands");
|
|
5793
|
+
|
|
5106
5794
|
// dist/finance/deals-command.js
|
|
5107
5795
|
var queryOf = /* @__PURE__ */ __name((entity) => ({
|
|
5108
5796
|
entity,
|
|
@@ -5123,14 +5811,14 @@ var PIPELINE_QUERY = {
|
|
|
5123
5811
|
};
|
|
5124
5812
|
var listDeals = /* @__PURE__ */ __name(async (store, kind, words, limit) => {
|
|
5125
5813
|
const command = `${kind}s list`;
|
|
5126
|
-
const
|
|
5814
|
+
const terms2 = queryTerms(words, QUERIES[kind], command);
|
|
5127
5815
|
const filter = {
|
|
5128
5816
|
kind,
|
|
5129
|
-
...
|
|
5130
|
-
...
|
|
5131
|
-
...
|
|
5132
|
-
...
|
|
5133
|
-
...
|
|
5817
|
+
...terms2.has("project") ? { project: await canonicalProject(store, terms2.get("project")) } : {},
|
|
5818
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
5819
|
+
...terms2.has("stage") ? { stage: terms2.get("stage") } : {},
|
|
5820
|
+
...terms2.has("pipeline") ? { pipeline: terms2.get("pipeline") } : {},
|
|
5821
|
+
...terms2.has("organization") ? { organization: terms2.get("organization") } : {}
|
|
5134
5822
|
};
|
|
5135
5823
|
return pageOf(command, limit, (most) => store.deals.list({ ...filter, limit: most }));
|
|
5136
5824
|
}, "listDeals");
|
|
@@ -5147,7 +5835,6 @@ var stageOf = /* @__PURE__ */ __name((stage) => {
|
|
|
5147
5835
|
const at = stage.lastIndexOf("/");
|
|
5148
5836
|
return at <= 0 ? { stage } : { pipeline: stage.slice(0, at), stage: stage.slice(at + 1) };
|
|
5149
5837
|
}, "stageOf");
|
|
5150
|
-
var json2 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
|
|
5151
5838
|
var WHAT = {
|
|
5152
5839
|
deal: { one: "deal", hope: "what you hope to sell, such as 'Site for the clinic'" },
|
|
5153
5840
|
lead: { one: "lead", hope: "who or what came in, such as 'Call from the site'" }
|
|
@@ -5155,9 +5842,9 @@ var WHAT = {
|
|
|
5155
5842
|
var itemCommands = /* @__PURE__ */ __name((program, kind, run, env) => {
|
|
5156
5843
|
const { one: one2, hope } = WHAT[kind];
|
|
5157
5844
|
const group = program.command(`${kind}s`).description(kind === "deal" ? "deals you hope to win: the client, the expected amount, the stage and whether it was won or lost" : "leads: first contacts in a lead pipeline, before they are deals").summary(kind === "deal" ? "deals in your pipelines, open, won or lost" : "leads in your lead pipelines");
|
|
5158
|
-
withQuery(
|
|
5159
|
-
|
|
5160
|
-
|
|
5845
|
+
withQuery(json(annotate(group.command("list"), { effects: LOCAL_READ })).description(`${one2}s, newest first; status:open is what is still in play`), QUERIES[kind]).summary(`${one2}s, newest first`).option("--limit <n>", `most ${one2}s, up to 500`, positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listDeals(store, kind, words, limit)));
|
|
5846
|
+
json(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: kind } })).description(`one ${one2} with its pipeline, stage, status, amount, the people on it and what it was read from`).summary(`one ${one2} with its stage, status, amount and people`).argument("<ref>", `${kind}:<id>`).action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.deals.get(ref)))));
|
|
5847
|
+
json(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: kind }, literal_after_dashes: true }).option("--organization <organization>", "the client: organization:<id>").option("--person <uid>", `a person on the ${one2}: person:<id>; repeat for another, up to 20`, collect).option("--role <role>", `what those people are on it: ${DEAL_ROLES.join(", ")}; contact by default`).option("--due <time>", "the day you expect it to close, such as 2026-12-01").option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent records it, kept with it").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference")).description(`record a ${one2} in a stage; it is written at once, whoever runs it`).summary(`record a ${one2} in a stage`).argument("<title>", hope).argument(kind === "deal" ? "<stage>" : "[stage]", kind === "deal" ? "the stage it is in; Sales/Quote or pipeline:3/Quote names the pipeline when two have that stage" : "the stage it is in; the first stage of the only lead pipeline when left out").argument("[amount]", "the expected amount, a decimal such as 500000.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action(async (title, stage, amount2, currency, options) => {
|
|
5161
5848
|
const by = authorOf(env);
|
|
5162
5849
|
const role = roleOf(options.role);
|
|
5163
5850
|
await run(options.json, async (store) => {
|
|
@@ -5178,11 +5865,11 @@ var itemCommands = /* @__PURE__ */ __name((program, kind, run, env) => {
|
|
|
5178
5865
|
}));
|
|
5179
5866
|
});
|
|
5180
5867
|
});
|
|
5181
|
-
|
|
5868
|
+
json(annotate(group.command("move"), { effects: LOCAL_WRITE, output: { entity: kind } })).description(`move a ${one2} to another stage of its pipeline; a won or lost stage closes it, an open one reopens it`).summary(`move a ${one2} to another stage`).argument("<ref>", `${kind}:<id>`).argument("<stage>", `a stage of the ${one2}'s pipeline`).action(async (ref, stage, options) => {
|
|
5182
5869
|
const by = authorOf(env);
|
|
5183
5870
|
await run(options.json, async (store) => itemAnswer(await store.deals.move(ref, { stage, by })));
|
|
5184
5871
|
});
|
|
5185
|
-
|
|
5872
|
+
json(annotate(group.command("close"), { effects: LOCAL_WRITE, output: { entity: kind } }).option("--occurred-time <time>", "the day it closed, such as 2026-11-20; today when left out").option("--reason <text>", "why it was won or lost, kept with it")).description(`close a ${one2} as won or lost; it moves to its pipeline's won or lost stage when there is one`).summary(`close a ${one2} as won or lost`).argument("<ref>", `${kind}:<id>`).argument("<outcome>", "won or lost").action(async (ref, outcome, options) => {
|
|
5186
5873
|
if (outcome !== "won" && outcome !== "lost")
|
|
5187
5874
|
throw new CliError("validation_error", `a ${one2} closes as won or lost`, { param: "outcome" });
|
|
5188
5875
|
const by = authorOf(env);
|
|
@@ -5204,19 +5891,19 @@ var funnelText = /* @__PURE__ */ __name((report) => [
|
|
|
5204
5891
|
var dealCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5205
5892
|
const { run, print } = answers(program, streams, env);
|
|
5206
5893
|
const pipelines = program.command("pipelines").description("sales pipelines: the stages a deal or a lead goes through, in order, and how many get through each").summary("sales pipelines, their stages and conversion");
|
|
5207
|
-
withQuery(
|
|
5208
|
-
const
|
|
5209
|
-
const name2 =
|
|
5210
|
-
const kind =
|
|
5894
|
+
withQuery(json(annotate(pipelines.command("list"), { effects: LOCAL_READ })).description("every pipeline with its stages in order and how many open deals or leads stand in each"), PIPELINE_QUERY).summary("every pipeline with its stages").action((words, options) => run(options.json, async (store) => {
|
|
5895
|
+
const terms2 = queryTerms(words, PIPELINE_QUERY, "pipelines list");
|
|
5896
|
+
const name2 = terms2.get("name")?.toLocaleLowerCase();
|
|
5897
|
+
const kind = terms2.get("kind");
|
|
5211
5898
|
const all = await store.deals.pipelines(kind === void 0 ? {} : { kind });
|
|
5212
5899
|
return wholeList("pipelines list", name2 === void 0 ? all : all.filter((one2) => one2.name.toLocaleLowerCase() === name2));
|
|
5213
5900
|
}));
|
|
5214
|
-
|
|
5901
|
+
json(annotate(pipelines.command("show"), { effects: LOCAL_READ, output: { entity: "pipeline" } }).option("--since-time <time>", "count only deals or leads made since this day, such as 2026-09-01")).description("one pipeline's funnel: per stage the open deals or leads in it, how many reached it, and the share that went on to the next stage; then won, lost and the win rate").summary("one pipeline's stages with counts and conversion").argument("<pipeline>", "pipeline:<id>, or a name only one pipeline has").action(async (pipeline, options, command) => {
|
|
5215
5902
|
const since = dayOf(options.sinceTime);
|
|
5216
|
-
const report = await withStore(env, (store) => store.deals.pipeline(pipeline, since === void 0 ? {} : { since }));
|
|
5903
|
+
const report = await withStore(env, async (store) => withSources(command, store, await store.deals.pipeline(pipeline, since === void 0 ? {} : { since })));
|
|
5217
5904
|
print(options.json, itemAnswer(report), funnelText(report));
|
|
5218
5905
|
});
|
|
5219
|
-
|
|
5906
|
+
json(annotate(pipelines.command("add"), { effects: LOCAL_WRITE, literal_after_dashes: true }).option("--kind <kind>", "what it holds: deal or lead; deal by default")).description("make a pipeline with its stages in order; a stage named won or lost (any letter case) ends a deal or lead as that").summary("make a pipeline with its stages").argument("<name>", "the pipeline's name, such as Sales").argument("<stage...>", "its stages in order, such as Call Quote Contract won lost").action(async (name2, stages, options) => {
|
|
5220
5907
|
const kind = options.kind ?? "deal";
|
|
5221
5908
|
if (!DEAL_KINDS.includes(kind))
|
|
5222
5909
|
throw new CliError("validation_error", "--kind is deal or lead", { param: "--kind" });
|
|
@@ -5275,15 +5962,15 @@ var ORDER_QUERY = {
|
|
|
5275
5962
|
]
|
|
5276
5963
|
};
|
|
5277
5964
|
var listOrders = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
5278
|
-
const
|
|
5965
|
+
const terms2 = queryTerms(words, ORDER_QUERY, "orders list");
|
|
5279
5966
|
const filter = {
|
|
5280
|
-
...
|
|
5281
|
-
...
|
|
5282
|
-
...
|
|
5283
|
-
...
|
|
5284
|
-
...
|
|
5285
|
-
...
|
|
5286
|
-
...
|
|
5967
|
+
...terms2.has("project") ? { project: await canonicalProject(store, terms2.get("project")) } : {},
|
|
5968
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
5969
|
+
...terms2.has("purpose") ? { purpose: terms2.get("purpose") } : {},
|
|
5970
|
+
...terms2.has("review") ? { review: terms2.get("review") } : {},
|
|
5971
|
+
...terms2.has("customer") ? { customer: terms2.get("customer") } : {},
|
|
5972
|
+
...terms2.has("supplier") ? { supplierName: terms2.get("supplier") } : {},
|
|
5973
|
+
...terms2.has("number") ? { number: terms2.get("number") } : {}
|
|
5287
5974
|
};
|
|
5288
5975
|
return pageOf("orders list", limit, (most) => store.orders.list({ ...filter, limit: most }));
|
|
5289
5976
|
}, "listOrders");
|
|
@@ -5292,13 +5979,12 @@ var oneOf2 = /* @__PURE__ */ __name((value, allowed, flag) => {
|
|
|
5292
5979
|
throw new CliError("validation_error", `${flag} is one of ${allowed.join(", ")}`, { param: flag });
|
|
5293
5980
|
return value;
|
|
5294
5981
|
}, "oneOf");
|
|
5295
|
-
var json3 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
|
|
5296
5982
|
var orderCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5297
5983
|
const { run } = answers(program, streams, env);
|
|
5298
5984
|
const orders = program.command("orders").description("orders you placed or took, for whom, from which shop, and how far delivery got").summary("orders you placed or took, and how far delivery got");
|
|
5299
|
-
withQuery(
|
|
5300
|
-
|
|
5301
|
-
|
|
5985
|
+
withQuery(json(annotate(orders.command("list"), { effects: LOCAL_READ })).description("orders, newest first; review:proposed is what waits for you"), ORDER_QUERY).option("--limit <n>", "most orders, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listOrders(store, words, limit)));
|
|
5986
|
+
json(annotate(orders.command("show"), { effects: LOCAL_READ, output: { entity: "order" } })).description("one order with its customer, shop, amount, status and the mail it was read from").argument("<ref>", "order:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.orders.get(ref)))));
|
|
5987
|
+
json(byOption(annotate(orders.command("add"), { effects: LOCAL_WRITE, output: { entity: "order" }, literal_after_dashes: true }).option("--kind <kind>", `why it was ordered: ${ORDER_PURPOSES.join(", ")}`).option("--person <uid>", "whom it is for, when not you: person:<id>").option("--organization <organization>", "whom it is for, when not you: organization:<id>").option("--title <title>", "the shop's order number").option("--occurred-time <time>", "the day it was ordered, such as 2026-11-01").option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent proposes it, for the owner who decides").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference"))).description("record a placed order; yours is confirmed at once, an agent's waits as proposed for you in memo review").summary("record an order; an agent's waits for your review").argument("<shop>", "the shop or supplier, as its mail names it").argument("[amount]", "the order's amount, a decimal such as 2499.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action(async (shop, amount2, currency, options, command) => {
|
|
5302
5988
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this order as yours?" });
|
|
5303
5989
|
await run(options.json, async (store) => {
|
|
5304
5990
|
const customer = partyOf(options, false);
|
|
@@ -5318,8 +6004,314 @@ var orderCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5318
6004
|
}));
|
|
5319
6005
|
});
|
|
5320
6006
|
});
|
|
6007
|
+
lineCommands(orders, "order", run, env);
|
|
5321
6008
|
}, "orderCommands");
|
|
5322
6009
|
|
|
6010
|
+
// dist/finance/products-command.js
|
|
6011
|
+
var PRODUCT_QUERY = {
|
|
6012
|
+
entity: "product",
|
|
6013
|
+
backend: "native",
|
|
6014
|
+
fields: [
|
|
6015
|
+
termField("kind", "enum", "kind:service", { values: CATALOG_KINDS }),
|
|
6016
|
+
termField("supplier", "ref", 'supplier:"organization:3"'),
|
|
6017
|
+
termField("archived", "bool", "archived:true"),
|
|
6018
|
+
termField("name", "kw", 'name:"Bike rental"')
|
|
6019
|
+
]
|
|
6020
|
+
};
|
|
6021
|
+
var listProducts = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
6022
|
+
const terms2 = queryTerms(words, PRODUCT_QUERY, "products list");
|
|
6023
|
+
const filter = given({
|
|
6024
|
+
kind: terms2.get("kind"),
|
|
6025
|
+
supplier: terms2.get("supplier"),
|
|
6026
|
+
archived: terms2.has("archived") ? terms2.get("archived") === "true" : void 0,
|
|
6027
|
+
name: terms2.get("name")
|
|
6028
|
+
});
|
|
6029
|
+
return pageOf("products list", limit, (most) => store.products.list({ ...filter, limit: most }));
|
|
6030
|
+
}, "listProducts");
|
|
6031
|
+
var productCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
6032
|
+
const { run } = answers(program, streams, env);
|
|
6033
|
+
const products = program.command("products").description("goods and services you sell or buy, with their prices; a line that names one copies its price, so a later price change leaves the line as it was").summary("goods and services you sell or buy, with their prices");
|
|
6034
|
+
withQuery(json(annotate(products.command("list"), { effects: LOCAL_READ })).description("products and services, by name; archived:true lists those no longer sold"), PRODUCT_QUERY).option("--limit <n>", "most products, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listProducts(store, words, limit)));
|
|
6035
|
+
json(annotate(products.command("show"), { effects: LOCAL_READ, output: { entity: "product" } })).description("one product or service with its price, unit, supplier and stock code").argument("<product>", "product:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.products.get(ref)))));
|
|
6036
|
+
json(annotate(products.command("add"), {
|
|
6037
|
+
effects: LOCAL_WRITE,
|
|
6038
|
+
output: { entity: "product" },
|
|
6039
|
+
literal_after_dashes: true
|
|
6040
|
+
}).option("--kind <kind>", `${CATALOG_KINDS.join(" or ")}; product when left out`).option("--unit <text>", "what one of it is counted in, such as hour or month").option("--sku <code>", "the stock code the seller gives it").option("--supplier <party>", "who supplies it, when not you: person:<uid> or organization:<id>").option("--description <text>", "what it is, in a sentence")).description("add a product or service you sell or buy; anyone adds one directly, as a price feeds no total").summary("add a product or service").argument("<name>", "its name, as an invoice or order line prints it").argument("[amount]", "the price of one unit, a decimal such as 10000.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action((name2, amount2, currency, options) => run(options.json, async (store) => itemAnswer(await store.products.add({
|
|
6041
|
+
by: authorOf(env),
|
|
6042
|
+
name: name2,
|
|
6043
|
+
...given({
|
|
6044
|
+
kind: optionalChoice(options.kind, CATALOG_KINDS, "--kind"),
|
|
6045
|
+
unitPrice: amount2,
|
|
6046
|
+
currency,
|
|
6047
|
+
unit: options.unit,
|
|
6048
|
+
sku: options.sku,
|
|
6049
|
+
supplier: options.supplier,
|
|
6050
|
+
description: options.description
|
|
6051
|
+
})
|
|
6052
|
+
}))));
|
|
6053
|
+
json(annotate(products.command("update"), { effects: LOCAL_WRITE, output: { entity: "product" } }).option("--amount <decimal>", "the new price of one unit, such as 12000.00; give --currency with it").option("--currency <code>", "an ISO 4217 code, such as RUB").option("--title <title>", "its new name").option("--unit <text>", "what one of it is counted in, such as hour or month").option("--description <text>", "what it is, in a sentence").option("--archived <on|off>", "on: no longer sold, and lines and subscriptions keep pointing at it; off: sold again")).description("change a product's price, name, unit or description, or archive it; lines already written keep theirs").summary("change or archive a product").argument("<product>", "product:<id>").action((ref, options) => run(options.json, async (store) => {
|
|
6054
|
+
const archived = onOff(options.archived, "--archived");
|
|
6055
|
+
return itemAnswer(await store.products.update(ref, {
|
|
6056
|
+
by: authorOf(env),
|
|
6057
|
+
...given({
|
|
6058
|
+
name: options.title,
|
|
6059
|
+
unitPrice: options.amount,
|
|
6060
|
+
currency: options.currency,
|
|
6061
|
+
unit: options.unit,
|
|
6062
|
+
description: options.description,
|
|
6063
|
+
archivedDate: archived === void 0 ? void 0 : archived ? today() : null
|
|
6064
|
+
})
|
|
6065
|
+
}));
|
|
6066
|
+
}));
|
|
6067
|
+
}, "productCommands");
|
|
6068
|
+
|
|
6069
|
+
// dist/finance/subscriptions-command.js
|
|
6070
|
+
var SUBSCRIPTION_QUERY = {
|
|
6071
|
+
entity: "subscription",
|
|
6072
|
+
backend: "native",
|
|
6073
|
+
fields: [
|
|
6074
|
+
termField("status", "enum", "status:active", { values: SUBSCRIPTION_STATUSES }),
|
|
6075
|
+
termField("direction", "enum", "direction:payable", { values: INVOICE_DIRECTIONS }),
|
|
6076
|
+
termField("supplier", "ref", 'supplier:"organization:3"'),
|
|
6077
|
+
termField("customer", "ref", 'customer:"organization:3"'),
|
|
6078
|
+
termField("project", "kw", "project:PMED"),
|
|
6079
|
+
termField("review", "enum", "review:proposed", { values: FINANCE_REVIEWS }),
|
|
6080
|
+
termField("renews", "time", "renews:2026-12-01")
|
|
6081
|
+
]
|
|
6082
|
+
};
|
|
6083
|
+
var listSubscriptions = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
6084
|
+
const terms2 = queryTerms(words, SUBSCRIPTION_QUERY, "subscriptions list");
|
|
6085
|
+
const project = terms2.get("project");
|
|
6086
|
+
const filter = given({
|
|
6087
|
+
status: terms2.get("status"),
|
|
6088
|
+
direction: terms2.get("direction"),
|
|
6089
|
+
supplier: terms2.get("supplier"),
|
|
6090
|
+
customer: terms2.get("customer"),
|
|
6091
|
+
review: terms2.get("review"),
|
|
6092
|
+
renewsBy: dayOf(terms2.get("renews")),
|
|
6093
|
+
project: project === void 0 ? void 0 : await canonicalProject(store, project)
|
|
6094
|
+
});
|
|
6095
|
+
return pageOf("subscriptions list", limit, (most) => store.subscriptions.list({ ...filter, limit: most }));
|
|
6096
|
+
}, "listSubscriptions");
|
|
6097
|
+
var parts = /* @__PURE__ */ __name((command) => command.option("--status <state>", `${SUBSCRIPTION_STATUSES.join(", ")}; trial needs --trial-end-date`).option("--supplier <party>", "who supplies it: person:<uid> or organization:<id>; you, when you bill it").option("--customer <party>", "who receives it and pays for it: person:<uid> or organization:<id>; you, when you pay").option("--product <product>", "the product or service it is for: product:<id>").option("--contract <contract>", "the contract it runs under: contract:<id>").option("--every <count-unit>", "how often it is charged: a count and a unit, such as 1-month or 1-year").option("--start-date <date>", "the first day it runs, YYYY-MM-DD").option("--trial-end-date <date>", "the day its free trial ends, YYYY-MM-DD"), "parts");
|
|
6098
|
+
var fieldsOf3 = /* @__PURE__ */ __name((options) => given({
|
|
6099
|
+
status: optionalChoice(options.status, SUBSCRIPTION_STATUSES, "--status"),
|
|
6100
|
+
supplier: options.supplier,
|
|
6101
|
+
customer: options.customer,
|
|
6102
|
+
product: options.product,
|
|
6103
|
+
contract: options.contract,
|
|
6104
|
+
every: options.every,
|
|
6105
|
+
startDate: dayOf(options.startDate),
|
|
6106
|
+
trialEndDate: dayOf(options.trialEndDate),
|
|
6107
|
+
endDate: dayOf(options.endDate)
|
|
6108
|
+
}), "fieldsOf");
|
|
6109
|
+
var subscriptionCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
6110
|
+
const { run } = answers(program, streams, env);
|
|
6111
|
+
const subscriptions = program.command("subscriptions").description("subscriptions you bill or pay: who supplies it, who pays, how often, and every price it had; a price is never changed, a new one is added").summary("subscriptions you bill or pay, and their prices");
|
|
6112
|
+
withQuery(json(annotate(subscriptions.command("list"), { effects: LOCAL_READ })).description("subscriptions, newest first; renews:2026-12-01 lists those that renew by then"), SUBSCRIPTION_QUERY).option("--limit <n>", "most subscriptions, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listSubscriptions(store, words, limit)));
|
|
6113
|
+
json(annotate(subscriptions.command("show"), { effects: LOCAL_READ, output: { entity: "subscription" } })).description("one subscription with its parties, dates, current price and every price it had").argument("<subscription>", "subscription:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.subscriptions.get(ref)))));
|
|
6114
|
+
json(writeMeta(parts(annotate(subscriptions.command("add"), {
|
|
6115
|
+
effects: LOCAL_WRITE,
|
|
6116
|
+
output: { entity: "subscription" },
|
|
6117
|
+
literal_after_dashes: true
|
|
6118
|
+
})).option("--kind <kind>", "receivable (you bill it) or payable (you pay it)"))).description(`record a subscription and its first price; ${PROPOSES}`).summary("record a subscription; an agent's waits for your review").argument("<name>", "what it is, such as Hosting").argument("<amount>", "its price for one period, a decimal such as 990.00").argument("<currency>", "ISO 4217, such as RUB").action(async (name2, amount2, currency, options, command) => {
|
|
6119
|
+
const by = await whoRuns(command, env, {
|
|
6120
|
+
asOwner: options.asOwner,
|
|
6121
|
+
question: "record this subscription as yours?"
|
|
6122
|
+
});
|
|
6123
|
+
await run(options.json, async (store) => {
|
|
6124
|
+
const startDate = dayOf(options.startDate) ?? today();
|
|
6125
|
+
return itemAnswer(await store.subscriptions.add({
|
|
6126
|
+
...await writtenBy(store, by, options),
|
|
6127
|
+
...fieldsOf3(options),
|
|
6128
|
+
name: name2,
|
|
6129
|
+
direction: choice(options.kind, INVOICE_DIRECTIONS, "--kind"),
|
|
6130
|
+
every: needed(options.every, "--every", "how often it is charged, such as 1-month"),
|
|
6131
|
+
startDate,
|
|
6132
|
+
prices: [{ amount: amount2, currency, effectiveFrom: startDate }]
|
|
6133
|
+
}));
|
|
6134
|
+
});
|
|
6135
|
+
});
|
|
6136
|
+
json(byOption(parts(annotate(subscriptions.command("update"), { effects: LOCAL_WRITE, output: { entity: "subscription" } })).option("--title <title>", "its new name").option("--end-date <date>", "the last day it runs, YYYY-MM-DD"))).description("change a subscription's status, schedule, dates or parties; pause it with --status paused. You change any, an agent only one it proposed that is still proposed. A new price is subscriptions prices add").summary("change a subscription").argument("<subscription>", "subscription:<id>").action(async (ref, options, command) => {
|
|
6137
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
|
|
6138
|
+
await run(options.json, async (store) => itemAnswer(await store.subscriptions.update(ref, { by, ...fieldsOf3(options), ...given({ name: options.title }) })));
|
|
6139
|
+
});
|
|
6140
|
+
json(byOption(annotate(subscriptions.command("cancel"), { effects: LOCAL_WRITE, output: { entity: "subscription" } }).option("--occurred-time <time>", "the day it was cancelled, such as 2026-11-01; today when left out"))).description("mark a subscription cancelled on a day; it stays, with its prices").summary("cancel a subscription").argument("<subscription>", "subscription:<id>").action(async (ref, options, command) => {
|
|
6141
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `cancel ${ref} as yours?` });
|
|
6142
|
+
await run(options.json, async (store) => itemAnswer(await store.subscriptions.update(ref, {
|
|
6143
|
+
by,
|
|
6144
|
+
status: "cancelled",
|
|
6145
|
+
cancelledDate: dayOf(options.occurredTime) ?? today()
|
|
6146
|
+
})));
|
|
6147
|
+
});
|
|
6148
|
+
const prices = subscriptions.command("prices").description("the prices a subscription had, each from a day on; one is never changed, a new one is added").summary("a subscription's prices");
|
|
6149
|
+
json(byOption(annotate(prices.command("add"), { effects: LOCAL_WRITE, output: { entity: "subscription_price" } }).option("--start-date <date>", "the first day the price holds, YYYY-MM-DD; the subscription's start when left out").option("--reason <text>", "why an agent proposes it, for the owner who decides"))).description(`add a price from a day on; the earlier ones stay as they were. ${PROPOSES}, and the subscription stays as it is`).summary("add a subscription's new price").argument("<subscription>", "subscription:<id>").argument("<amount>", "the price for one period, a decimal such as 1190.00").argument("<currency>", "ISO 4217, such as RUB").action(async (ref, amount2, currency, options, command) => {
|
|
6150
|
+
const by = await whoRuns(command, env, {
|
|
6151
|
+
asOwner: options.asOwner,
|
|
6152
|
+
question: `add a price to ${ref} as yours?`
|
|
6153
|
+
});
|
|
6154
|
+
await run(options.json, async (store) => itemAnswer(await store.subscriptions.addPrice(ref, {
|
|
6155
|
+
by,
|
|
6156
|
+
amount: amount2,
|
|
6157
|
+
currency,
|
|
6158
|
+
...given({
|
|
6159
|
+
effectiveFrom: dayOf(options.startDate),
|
|
6160
|
+
reason: by === "owner" ? void 0 : options.reason
|
|
6161
|
+
})
|
|
6162
|
+
})));
|
|
6163
|
+
});
|
|
6164
|
+
}, "subscriptionCommands");
|
|
6165
|
+
|
|
6166
|
+
// dist/finance/transactions-command.js
|
|
6167
|
+
var TRANSACTION_QUERY = {
|
|
6168
|
+
entity: "transaction",
|
|
6169
|
+
backend: "native",
|
|
6170
|
+
fields: [
|
|
6171
|
+
termField("wallet", "ref", 'wallet:"wallet:2"'),
|
|
6172
|
+
termField("direction", "enum", "direction:out", { values: MONEY_DIRECTIONS }),
|
|
6173
|
+
termField("status", "enum", "status:pending", { values: TRANSACTION_STATUSES }),
|
|
6174
|
+
termField("category", "kw", "category:Rent"),
|
|
6175
|
+
termField("project", "kw", "project:PMED"),
|
|
6176
|
+
termField("review", "enum", "review:proposed", { values: FINANCE_REVIEWS }),
|
|
6177
|
+
termField("uncategorized", "bool", "uncategorized:true")
|
|
6178
|
+
]
|
|
6179
|
+
};
|
|
6180
|
+
var listTransactions = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
6181
|
+
const terms2 = queryTerms(words, TRANSACTION_QUERY, "transactions list");
|
|
6182
|
+
const project = terms2.get("project");
|
|
6183
|
+
const filter = given({
|
|
6184
|
+
wallet: terms2.get("wallet"),
|
|
6185
|
+
direction: terms2.get("direction"),
|
|
6186
|
+
status: terms2.get("status"),
|
|
6187
|
+
category: terms2.get("category"),
|
|
6188
|
+
review: terms2.get("review"),
|
|
6189
|
+
uncategorized: terms2.has("uncategorized") ? terms2.get("uncategorized") === "true" : void 0,
|
|
6190
|
+
project: project === void 0 ? void 0 : await canonicalProject(store, project)
|
|
6191
|
+
});
|
|
6192
|
+
return pageOf("transactions list", limit, (most) => store.transactions.list({ ...filter, limit: most }));
|
|
6193
|
+
}, "listTransactions");
|
|
6194
|
+
var STATUS_HELP = `${TRANSACTION_STATUSES.join(" or ")}; only a booked one counts in a balance`;
|
|
6195
|
+
var transactionCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
6196
|
+
const { run } = answers(program, streams, env);
|
|
6197
|
+
const transactions = program.command("transactions").description("money a wallet's statement shows moving in or out, the payment it settles, and the categories it is split into").summary("money moving in or out of your wallets");
|
|
6198
|
+
withQuery(json(annotate(transactions.command("list"), { effects: LOCAL_READ })).description("transactions, newest first; uncategorized:true lists those not fully split into categories"), TRANSACTION_QUERY).summary("transactions, newest first").option("--limit <n>", "most transactions, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listTransactions(store, words, limit)));
|
|
6199
|
+
json(annotate(transactions.command("show"), { effects: LOCAL_READ, output: { entity: "transaction" } })).description("one transaction with its wallet, payment, splits and what is not categorized").argument("<transaction>", "transaction:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.transactions.get(ref)))));
|
|
6200
|
+
json(writeMeta(annotate(transactions.command("add"), {
|
|
6201
|
+
effects: LOCAL_WRITE,
|
|
6202
|
+
output: { entity: "transaction" },
|
|
6203
|
+
literal_after_dashes: true
|
|
6204
|
+
}).option("--kind <kind>", "in (money came in) or out (money went out)").option("--occurred-time <time>", "the day the statement shows, such as 2026-11-01; today when left out").option("--description <text>", "what the statement says, as it says it").option("--status <state>", `${STATUS_HELP}; booked when left out`).option("--payment <payment>", "the payment it settles, same amount, currency and direction: payment:<id>"))).description(`record what a wallet's statement shows moved, in the wallet's currency; ${PROPOSES}`).summary("record a transaction; an agent's waits for your review").argument("<wallet>", "wallet:<id>").argument("<amount>", "a decimal above 0, such as 500.00").action(async (wallet, amount2, options, command) => {
|
|
6205
|
+
const by = await whoRuns(command, env, {
|
|
6206
|
+
asOwner: options.asOwner,
|
|
6207
|
+
question: "record this transaction as yours?"
|
|
6208
|
+
});
|
|
6209
|
+
await run(options.json, async (store) => itemAnswer(await store.transactions.add({
|
|
6210
|
+
...await writtenBy(store, by, options),
|
|
6211
|
+
wallet,
|
|
6212
|
+
amount: amount2,
|
|
6213
|
+
direction: choice(options.kind, MONEY_DIRECTIONS, "--kind"),
|
|
6214
|
+
statementDate: dayOf(options.occurredTime) ?? today(),
|
|
6215
|
+
...given({
|
|
6216
|
+
status: optionalChoice(options.status, TRANSACTION_STATUSES, "--status"),
|
|
6217
|
+
description: options.description,
|
|
6218
|
+
payment: options.payment
|
|
6219
|
+
})
|
|
6220
|
+
})));
|
|
6221
|
+
});
|
|
6222
|
+
json(byOption(annotate(transactions.command("update"), { effects: LOCAL_WRITE, output: { entity: "transaction" } }).option("--status <state>", STATUS_HELP).option("--payment <payment>", "the payment it settles, same amount, currency and direction: payment:<id>").option("--description <text>", "what the statement says, as it says it"))).description("book a pending transaction, link it to the payment it settles, or fix its text; you change any, an agent only one it proposed that is still proposed").summary("book a transaction or link it to its payment").argument("<transaction>", "transaction:<id>").action(async (ref, options, command) => {
|
|
6223
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
|
|
6224
|
+
await run(options.json, async (store) => itemAnswer(await store.transactions.update(ref, {
|
|
6225
|
+
by,
|
|
6226
|
+
...given({
|
|
6227
|
+
status: optionalChoice(options.status, TRANSACTION_STATUSES, "--status"),
|
|
6228
|
+
payment: options.payment,
|
|
6229
|
+
description: options.description
|
|
6230
|
+
})
|
|
6231
|
+
})));
|
|
6232
|
+
});
|
|
6233
|
+
const splits = transactions.command("splits").description("the categories a transaction's amount is split into; together never more than the amount, the rest is uncategorized").summary("a transaction's categories");
|
|
6234
|
+
const WHO2 = "you split any transaction; an agent only one it proposed that is still proposed";
|
|
6235
|
+
json(byOption(annotate(splits.command("add"), { effects: LOCAL_WRITE, output: { entity: "transaction" } }).option("--project <project>", "the project this part belongs to: its key or project:<id>"))).description(`put part of a transaction's amount under a category; ${WHO2}`).summary("put part of a transaction under a category").argument("<transaction>", "transaction:<id>").argument("<amount>", "a decimal above 0, such as 120.00").argument("<category...>", "the category, in a word or a few, such as Rent").action(async (ref, amount2, words, options, command) => {
|
|
6236
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `split ${ref} as yours?` });
|
|
6237
|
+
await run(options.json, async (store) => itemAnswer(await store.transactions.addSplit(ref, {
|
|
6238
|
+
by,
|
|
6239
|
+
amount: amount2,
|
|
6240
|
+
category: words.join(" "),
|
|
6241
|
+
...options.project === void 0 ? {} : { project: await canonicalProject(store, options.project) }
|
|
6242
|
+
})));
|
|
6243
|
+
});
|
|
6244
|
+
json(byOption(annotate(splits.command("remove"), { effects: LOCAL_WRITE, output: { entity: "transaction" } }))).description(`take a split off a transaction; its amount is uncategorized again. ${WHO2}`).summary("take a split off a transaction").argument("<transaction>", "transaction:<id>").argument("<position>", "the split's position, from 1, as transactions show lists it", positive).action(async (ref, position, options, command) => {
|
|
6245
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref}'s splits as yours?` });
|
|
6246
|
+
await run(options.json, async (store) => itemAnswer(await store.transactions.removeSplit(ref, { position, by })));
|
|
6247
|
+
});
|
|
6248
|
+
}, "transactionCommands");
|
|
6249
|
+
|
|
6250
|
+
// dist/finance/wallets-command.js
|
|
6251
|
+
var WALLET_QUERY = {
|
|
6252
|
+
entity: "wallet",
|
|
6253
|
+
backend: "native",
|
|
6254
|
+
fields: [
|
|
6255
|
+
termField("kind", "enum", "kind:card", { values: WALLET_KINDS }),
|
|
6256
|
+
termField("currency", "kw", "currency:RUB")
|
|
6257
|
+
]
|
|
6258
|
+
};
|
|
6259
|
+
var listWallets = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
6260
|
+
const terms2 = queryTerms(words, WALLET_QUERY, "wallets list");
|
|
6261
|
+
const filter = given({
|
|
6262
|
+
kind: terms2.get("kind"),
|
|
6263
|
+
currency: terms2.get("currency")
|
|
6264
|
+
});
|
|
6265
|
+
return pageOf("wallets list", limit, (most) => store.wallets.list({ ...filter, limit: most }));
|
|
6266
|
+
}, "listWallets");
|
|
6267
|
+
var sourceSays = /* @__PURE__ */ __name(async (store, wallet) => {
|
|
6268
|
+
if (wallet.openingBalance !== null)
|
|
6269
|
+
return null;
|
|
6270
|
+
for (const { provider, account: account2 } of await sourceAccounts(store, wallet)) {
|
|
6271
|
+
const [record2] = await store.records.list({ provider, account: account2, entity: wallet.ref, limit: 1 });
|
|
6272
|
+
const { opening_balance: balance, opening_date: date } = record2?.fields ?? {};
|
|
6273
|
+
if (record2 && typeof balance === "string")
|
|
6274
|
+
return {
|
|
6275
|
+
openingBalance: balance,
|
|
6276
|
+
openingDate: typeof date === "string" ? date : null,
|
|
6277
|
+
record: `${record2.type}:${record2.externalId}`,
|
|
6278
|
+
account: `${provider}:${account2}`
|
|
6279
|
+
};
|
|
6280
|
+
}
|
|
6281
|
+
return null;
|
|
6282
|
+
}, "sourceSays");
|
|
6283
|
+
var walletCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
6284
|
+
const { run } = answers(program, streams, env);
|
|
6285
|
+
const wallets = program.command("wallets").description("bank accounts, cards and cash you keep money in, one currency each; a balance is the opening balance plus confirmed, booked transactions, computed each time").summary("bank accounts, cards and cash, with their balances");
|
|
6286
|
+
withQuery(json(annotate(wallets.command("list"), { effects: LOCAL_READ })).description("wallets with their balances today; kind:card lists the cards"), WALLET_QUERY).option("--limit <n>", "most wallets, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listWallets(store, words, limit)));
|
|
6287
|
+
json(annotate(wallets.command("show"), { effects: LOCAL_READ, output: { entity: "wallet" } }).option("--until-time <time>", "the balance up to and including this day, such as 2026-10-31; today when left out")).description("one wallet with its balance, and beside it what is pending or proposed and not counted yet; for an imported wallet whose opening balance you have not set, source_says gives the one its source sent").summary("one wallet with its balance and what is pending").argument("<wallet>", "wallet:<id>").action((ref, options, command) => run(options.json, async (store) => {
|
|
6288
|
+
const until = dayOf(options.untilTime);
|
|
6289
|
+
const wallet = await store.wallets.get(ref, until === void 0 ? {} : { until });
|
|
6290
|
+
return itemAnswer(await withSources(command, store, { ...wallet, sourceSays: await sourceSays(store, wallet) }));
|
|
6291
|
+
}));
|
|
6292
|
+
json(annotate(wallets.command("add"), { effects: LOCAL_WRITE, output: { entity: "wallet" }, literal_after_dashes: true }).option("--kind <kind>", `${WALLET_KINDS.join(", ")}; bank when left out`).option("--institution <text>", "the bank or other company that holds it, by name")).description("add a wallet in one currency; anyone adds one directly, and only you set its opening balance, with wallets update").summary("add a bank account, card or cash wallet").argument("<name>", "what you call it, such as 'Main card'").argument("<currency>", "ISO 4217, such as RUB; a bank account in two currencies is two wallets").action((name2, currency, options) => run(options.json, async (store) => itemAnswer(await store.wallets.add({
|
|
6293
|
+
by: authorOf(env),
|
|
6294
|
+
name: name2,
|
|
6295
|
+
currency,
|
|
6296
|
+
...given({
|
|
6297
|
+
kind: optionalChoice(options.kind, WALLET_KINDS, "--kind"),
|
|
6298
|
+
institution: options.institution
|
|
6299
|
+
})
|
|
6300
|
+
}))));
|
|
6301
|
+
json(byOption(annotate(wallets.command("update"), { effects: LOCAL_WRITE, output: { entity: "wallet" } }).option("--title <title>", "its new name").option("--institution <text>", "the bank or other company that holds it, by name").option("--opening-balance <decimal>", "what it held on --opening-date, such as 1500.50; only you set it").option("--opening-date <date>", "the day of the opening balance, YYYY-MM-DD"))).description("rename a wallet, or set the opening balance its balance counts from; the opening balance is yours alone, an agent is refused").summary("rename a wallet or set its opening balance").argument("<wallet>", "wallet:<id>").action(async (ref, options, command) => {
|
|
6302
|
+
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
|
|
6303
|
+
await run(options.json, async (store) => itemAnswer(await store.wallets.update(ref, {
|
|
6304
|
+
by,
|
|
6305
|
+
...given({
|
|
6306
|
+
name: options.title,
|
|
6307
|
+
institution: options.institution,
|
|
6308
|
+
openingBalance: options.openingBalance,
|
|
6309
|
+
openingDate: dayOf(options.openingDate)
|
|
6310
|
+
})
|
|
6311
|
+
})));
|
|
6312
|
+
});
|
|
6313
|
+
}, "walletCommands");
|
|
6314
|
+
|
|
5323
6315
|
// dist/findings-input.js
|
|
5324
6316
|
import { createReadStream, statSync as statSync2 } from "node:fs";
|
|
5325
6317
|
var FINDINGS_INPUT_HELP = "the findings JSON itself (starts with {), a JSON file, or - for stdin; at most 65536 UTF-8 bytes";
|
|
@@ -5349,53 +6341,53 @@ var findingsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5349
6341
|
const group = program.command("meetings").description("stored meeting evidence and reviewed findings").command("actions").description("cited meeting facts and project tasks waiting for owner review");
|
|
5350
6342
|
const { run } = answers(program, streams, env);
|
|
5351
6343
|
const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
|
|
5352
|
-
const scope = /* @__PURE__ */ __name((store,
|
|
5353
|
-
const acting = /* @__PURE__ */ __name((store,
|
|
6344
|
+
const scope = /* @__PURE__ */ __name((store, given2) => theAccount(store, env, given2, warn), "scope");
|
|
6345
|
+
const acting = /* @__PURE__ */ __name((store, given2) => writeAccount(store, env, given2, warn), "acting");
|
|
5354
6346
|
const options = /* @__PURE__ */ __name((command) => sourceOptions(command, MEETING_ACCOUNT_HELP).option("--json", "print JSON; --json=id,status keeps only those fields"), "options");
|
|
5355
6347
|
const writes = /* @__PURE__ */ __name((command) => writeOptions(command, MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,status keeps only those fields"), "writes");
|
|
5356
|
-
writes(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: "meeting_findings" } })).description("stage cited findings; facts and tasks wait for owner confirmation").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind, project and evidence (reference and fingerprint). Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). At most 16 findings, each with 1\u20138 exact cues from Zoom evidence. Optional due_at is a real ISO timestamp with timezone and requires due_evidence; optional assignee is a person reference and requires assignee_evidence. Both support lists cite this finding's cue references.\n").action(async (file,
|
|
6348
|
+
writes(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: "meeting_findings" } })).description("stage cited findings; facts and tasks wait for owner confirmation").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind, project and evidence (reference and fingerprint). Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). At most 16 findings, each with 1\u20138 exact cues from Zoom evidence. Optional due_at is a real ISO timestamp with timezone and requires due_evidence; optional assignee is a person reference and requires assignee_evidence. Both support lists cite this finding's cue references.\n").action(async (file, given2) => {
|
|
5357
6349
|
const text3 = await readFindingsInput(file, environmentOf(program).stdin ?? process.stdin);
|
|
5358
6350
|
const input = parseMeetingFindingsJson(text3);
|
|
5359
6351
|
const author = await whoRuns(program, env, { question: "" });
|
|
5360
6352
|
const agent = author === "owner" ? { bot: "memo-findings" } : author;
|
|
5361
|
-
await run(
|
|
6353
|
+
await run(given2.json, async (store) => itemAnswer(await store.meetingFindings.stage(await acting(store, given2), input, agent)));
|
|
5362
6354
|
});
|
|
5363
|
-
options(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })).description("one findings preview, prior decisions and its review receipt").argument("<id>", "stored findings batch ID").action((id,
|
|
5364
|
-
withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })), FINDINGS_QUERY).description("findings batches in one meeting account, newest first").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words,
|
|
6355
|
+
options(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })).description("one findings preview, prior decisions and its review receipt").argument("<id>", "stored findings batch ID").action((id, given2) => run(given2.json, async (store) => itemAnswer(await store.meetingFindings.get(await scope(store, given2), id))));
|
|
6356
|
+
withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })), FINDINGS_QUERY).description("findings batches in one meeting account, newest first").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words, given2) => run(given2.json, async (store) => {
|
|
5365
6357
|
const status = queryTerms(words, FINDINGS_QUERY, "meetings actions list").get("status");
|
|
5366
|
-
const key = await scope(store,
|
|
6358
|
+
const key = await scope(store, given2);
|
|
5367
6359
|
const found = await store.meetingFindings.list(key, {
|
|
5368
|
-
limit:
|
|
5369
|
-
offset: (
|
|
6360
|
+
limit: given2.limit,
|
|
6361
|
+
offset: (given2.page - 1) * given2.limit,
|
|
5370
6362
|
...status === void 0 ? {} : { status }
|
|
5371
6363
|
});
|
|
5372
6364
|
return listAnswer("meetings actions list", {
|
|
5373
6365
|
items: found.items,
|
|
5374
|
-
limit:
|
|
5375
|
-
page:
|
|
6366
|
+
limit: given2.limit,
|
|
6367
|
+
page: given2.page,
|
|
5376
6368
|
has_more: found.hasMore,
|
|
5377
|
-
args: { query: words.join(" "), source: accountName(key), limit:
|
|
6369
|
+
args: { query: words.join(" "), source: accountName(key), limit: given2.limit }
|
|
5378
6370
|
});
|
|
5379
6371
|
}));
|
|
5380
6372
|
for (const name2 of ["confirm", "reject"]) {
|
|
5381
6373
|
const command = writes(annotate(group.command(name2), { effects: LOCAL_WRITE, output: { entity: "meeting_findings" } })).description(name2 === "confirm" ? "owner only: create selected findings and reject the other new candidates" : "owner only: reject every new candidate in this batch").argument("<id>", "stored findings batch ID").requiredOption("--fingerprint <hash>", "the exact fingerprint shown in the preview");
|
|
5382
6374
|
byOption(command);
|
|
5383
|
-
const review = /* @__PURE__ */ __name(async (id,
|
|
6375
|
+
const review = /* @__PURE__ */ __name(async (id, given2, accept) => {
|
|
5384
6376
|
const key = `meetings.actions.${name2}`;
|
|
5385
|
-
const who = await whoRuns(command, env, { asOwner:
|
|
6377
|
+
const who = await whoRuns(command, env, { asOwner: given2.asOwner, question: `${name2} batch ${id} as you?` });
|
|
5386
6378
|
const by = who === "owner" ? who : mcpOwnerAllowed(env, key) ? { bot: who.bot, reason: `the owner allows ${key}` } : void 0;
|
|
5387
6379
|
if (by === void 0)
|
|
5388
6380
|
throw new CliError("validation_error", "findings confirmation and rejection belong to the owner; agents must leave proposals for review");
|
|
5389
|
-
return run(
|
|
5390
|
-
fingerprint:
|
|
6381
|
+
return run(given2.json, async (store) => itemAnswer(await store.meetingFindings.review(await acting(store, given2), id, {
|
|
6382
|
+
fingerprint: given2.fingerprint,
|
|
5391
6383
|
accept,
|
|
5392
6384
|
by
|
|
5393
6385
|
})));
|
|
5394
6386
|
}, "review");
|
|
5395
6387
|
if (name2 === "confirm")
|
|
5396
|
-
command.argument("<ids...>", "candidate IDs to accept; other new candidates are rejected").action((id, ids,
|
|
6388
|
+
command.argument("<ids...>", "candidate IDs to accept; other new candidates are rejected").action((id, ids, given2) => review(id, given2, ids));
|
|
5397
6389
|
else
|
|
5398
|
-
command.action((id,
|
|
6390
|
+
command.action((id, given2) => review(id, given2, []));
|
|
5399
6391
|
}
|
|
5400
6392
|
}, "findingsCommand");
|
|
5401
6393
|
|
|
@@ -5476,18 +6468,18 @@ var meetingProjectsCommand = /* @__PURE__ */ __name((projects, streams, env) =>
|
|
|
5476
6468
|
const key = await (writes ? writeAccount : theAccount)(store, env, options2, warn);
|
|
5477
6469
|
return work(store, (await canonicalProject(store, project)).slice(8), key);
|
|
5478
6470
|
}), "execute");
|
|
5479
|
-
withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_project" } }).description("meetings linked to a project in one account, or with confirmed:false proposed").argument("<project>", "project reference, key or explicit alias")), MEETING_PROJECTS_QUERY).option("--limit <n>", "meetings per page, at most 500", positive, 50).option("--page <n>", "which page, from 1", positive).action((project, words,
|
|
6471
|
+
withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_project" } }).description("meetings linked to a project in one account, or with confirmed:false proposed").argument("<project>", "project reference, key or explicit alias")), MEETING_PROJECTS_QUERY).option("--limit <n>", "meetings per page, at most 500", positive, 50).option("--page <n>", "which page, from 1", positive).action((project, words, given2) => execute(project, given2, async (store, projectId, key) => {
|
|
5480
6472
|
const confirmed = queryTerms(words, MEETING_PROJECTS_QUERY, "projects meetings list").get("confirmed");
|
|
5481
|
-
const page =
|
|
6473
|
+
const page = given2.page ?? 1;
|
|
5482
6474
|
const found = await store.knowledge.meetingProjects(key, {
|
|
5483
6475
|
projectId,
|
|
5484
6476
|
confirmed: confirmed === "true",
|
|
5485
|
-
limit:
|
|
5486
|
-
offset: (page - 1) *
|
|
6477
|
+
limit: given2.limit,
|
|
6478
|
+
offset: (page - 1) * given2.limit
|
|
5487
6479
|
});
|
|
5488
6480
|
return listAnswer("projects meetings list", {
|
|
5489
6481
|
items: found.items,
|
|
5490
|
-
limit:
|
|
6482
|
+
limit: given2.limit,
|
|
5491
6483
|
has_more: found.hasMore,
|
|
5492
6484
|
page,
|
|
5493
6485
|
args: {
|
|
@@ -5497,10 +6489,10 @@ var meetingProjectsCommand = /* @__PURE__ */ __name((projects, streams, env) =>
|
|
|
5497
6489
|
}
|
|
5498
6490
|
});
|
|
5499
6491
|
}));
|
|
5500
|
-
writeOptions(annotate(group.command("link"), { effects: LOCAL_WRITE }).description("link a stored meeting to a project, or confirm a proposed link").argument("<project>", "project reference, key or explicit alias").argument("<meeting-id>", "positive stored meeting id"), MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,title keeps only those fields").option("--fingerprint <hash>", "required when confirming an existing proposal").option("--reason <text>", "why the reviewed meeting belongs to this project").action((project, meeting,
|
|
6492
|
+
writeOptions(annotate(group.command("link"), { effects: LOCAL_WRITE }).description("link a stored meeting to a project, or confirm a proposed link").argument("<project>", "project reference, key or explicit alias").argument("<meeting-id>", "positive stored meeting id"), MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,title keeps only those fields").option("--fingerprint <hash>", "required when confirming an existing proposal").option("--reason <text>", "why the reviewed meeting belongs to this project").action((project, meeting, given2) => execute(project, given2, async (store, projectId, key) => itemAnswer(await store.knowledge.linkMeetingProject(key, meeting, projectId, {
|
|
5501
6493
|
by: "owner",
|
|
5502
|
-
...
|
|
5503
|
-
...
|
|
6494
|
+
...given2.fingerprint === void 0 ? {} : { expectedFingerprint: given2.fingerprint },
|
|
6495
|
+
...given2.reason === void 0 ? {} : { provenance: given2.reason }
|
|
5504
6496
|
})), true));
|
|
5505
6497
|
}, "meetingProjectsCommand");
|
|
5506
6498
|
|
|
@@ -5588,18 +6580,18 @@ var ACTIONS_QUERY = {
|
|
|
5588
6580
|
fields: [termField("status", "enum", "status:proposed", { values: ["proposed", "reviewed"] })],
|
|
5589
6581
|
defaults: ["status:proposed"]
|
|
5590
6582
|
};
|
|
5591
|
-
var
|
|
6583
|
+
var json2 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
|
|
5592
6584
|
var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
|
|
5593
6585
|
const group = projects.command("actions").description("cited key documents and findings an agent proposed for a project, with the evidence to decide them").summary("an agent's proposals for a project, and deciding them");
|
|
5594
6586
|
const { run } = answers(projects, streams, env);
|
|
5595
|
-
|
|
6587
|
+
json2(annotate(group.command("add"), { effects: LOCAL_WRITE })).description("stage an agent's cited facts and follow-ups about one project for review").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind and evidence: 1\u20138 msg:, document: or note: references with the fingerprint projects evidence or notes show gives. A fact may name a project and a subject (person:, organization:, task: or project:), or neither; a task names its project. Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). A due_at or assignee needs due_evidence or assignee_evidence citing this finding's references. A payment names payment {amount, currency, direction to_us|from_us, state paid|expected|cancelled, counterparty, paid_at}: an expected one becomes an invoice and needs a person: or organization: counterparty; a paid or cancelled one names in supersedes the invoice: it settles or voids. At most one project per batch. The same key and input returns the same batch; actions confirm and reject decide it by its id.\n").action(async (file, given2, command) => {
|
|
5596
6588
|
const input = parseEvidenceFindingsJson(await readFindingsInput(file, environmentOf(projects).stdin ?? process.stdin));
|
|
5597
6589
|
const author = await whoRuns(command, env, { question: "" });
|
|
5598
6590
|
if (author === "owner")
|
|
5599
6591
|
throw new CliError("validation_error", "findings are an agent's proposals; record your own with memo facts add");
|
|
5600
|
-
await run(
|
|
6592
|
+
await run(given2.json, async (store) => itemAnswer(await store.evidenceFindings.stage(input, author)));
|
|
5601
6593
|
});
|
|
5602
|
-
withQuery(
|
|
6594
|
+
withQuery(json2(answerEntity(annotate(group.command("list"), { effects: LOCAL_READ }), "project_action", union([
|
|
5603
6595
|
strictObject({
|
|
5604
6596
|
kind: literal("key_document"),
|
|
5605
6597
|
id: string(),
|
|
@@ -5620,39 +6612,39 @@ var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
|
|
|
5620
6612
|
decision: unknown(),
|
|
5621
6613
|
findings: array(unknown())
|
|
5622
6614
|
})
|
|
5623
|
-
]))).argument("<project>", "the project's id, project:<id>, key, exact name or alias"), ACTIONS_QUERY).summary("a project's proposals with the evidence to decide them").description("a project's proposed key documents and findings, newest first, with source state, cited text and nearby messages or document paragraphs; key-document text is untracked because no fingerprint was saved").option("--limit <n>", "findings batches per page, at most 50", positive, 10).option("--page <n>", "which page, from 1; key documents come on the first", positive, 1).option("--brief", "only references and source state, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the citation, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the citation, at most 5", whole, 2).action((reference2, words,
|
|
6615
|
+
]))).argument("<project>", "the project's id, project:<id>, key, exact name or alias"), ACTIONS_QUERY).summary("a project's proposals with the evidence to decide them").description("a project's proposed key documents and findings, newest first, with source state, cited text and nearby messages or document paragraphs; key-document text is untracked because no fingerprint was saved").option("--limit <n>", "findings batches per page, at most 50", positive, 10).option("--page <n>", "which page, from 1; key documents come on the first", positive, 1).option("--brief", "only references and source state, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the citation, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the citation, at most 5", whole, 2).action((reference2, words, given2) => run(given2.json, async (store) => {
|
|
5624
6616
|
const status = queryTerms(words, ACTIONS_QUERY, "projects actions list").get("status");
|
|
5625
6617
|
const project = await projectOf(store, reference2);
|
|
5626
6618
|
const found = await projectActions(store, project, {
|
|
5627
6619
|
status,
|
|
5628
|
-
limit:
|
|
5629
|
-
page:
|
|
5630
|
-
brief:
|
|
5631
|
-
before: Math.min(
|
|
5632
|
-
after: Math.min(
|
|
6620
|
+
limit: given2.limit,
|
|
6621
|
+
page: given2.page,
|
|
6622
|
+
brief: given2.brief === true,
|
|
6623
|
+
before: Math.min(given2.beforeN, 5),
|
|
6624
|
+
after: Math.min(given2.afterN, 5)
|
|
5633
6625
|
});
|
|
5634
6626
|
return listAnswer("projects actions list", {
|
|
5635
6627
|
items: found.items,
|
|
5636
|
-
limit:
|
|
5637
|
-
page:
|
|
6628
|
+
limit: given2.limit,
|
|
6629
|
+
page: given2.page,
|
|
5638
6630
|
has_more: found.hasMore,
|
|
5639
6631
|
args: { project: reference2, query: words.join(" ") }
|
|
5640
6632
|
});
|
|
5641
6633
|
}));
|
|
5642
6634
|
for (const name2 of ["confirm", "reject"]) {
|
|
5643
|
-
const command = byOption(
|
|
6635
|
+
const command = byOption(json2(annotate(group.command(name2), { effects: LOCAL_WRITE })).description(name2 === "confirm" ? "confirm a suggested key document, or create the named findings of a batch and reject its other new ones; an agent decides for you only when agent_decisions is true, and with --reason" : "reject a suggested key document, or every new finding of a batch").summary(name2 === "confirm" ? "confirm a proposal, yours or an agent's with --reason" : "reject a proposal").argument("<project>", "the project's id, project:<id>, key, exact name or alias").argument("<id>", "key:<id> for a key document, or a findings batch number, as projects actions list gives them"));
|
|
5644
6636
|
if (name2 === "confirm")
|
|
5645
6637
|
command.argument("[findings...]", "the finding IDs of a batch to create");
|
|
5646
6638
|
command.option("--fingerprint <hash>", "a findings batch's fingerprint, as projects actions list gives it").option("--reason <text>", "why, in a few words; required when an agent decides for you").action(async (reference2, id, ...rest) => {
|
|
5647
6639
|
const accept = name2 === "confirm" ? rest[0] : [];
|
|
5648
|
-
const
|
|
5649
|
-
const by = await deciderOf(command, env, { ...
|
|
5650
|
-
await run(
|
|
6640
|
+
const given2 = name2 === "confirm" ? rest[1] : rest[0];
|
|
6641
|
+
const by = await deciderOf(command, env, { ...given2, question: `${name2} ${id} as you, the owner?` });
|
|
6642
|
+
await run(given2.json, async (store) => {
|
|
5651
6643
|
const project = await projectOf(store, reference2);
|
|
5652
6644
|
return itemAnswer(await decideAction(store, project, id, {
|
|
5653
6645
|
confirm: name2 === "confirm",
|
|
5654
|
-
...
|
|
5655
|
-
...
|
|
6646
|
+
...given2.fingerprint === void 0 ? {} : { fingerprint: given2.fingerprint },
|
|
6647
|
+
...given2.reason === void 0 ? {} : { reason: given2.reason },
|
|
5656
6648
|
accept,
|
|
5657
6649
|
by
|
|
5658
6650
|
}));
|
|
@@ -5984,7 +6976,7 @@ var syncHint = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => {
|
|
|
5984
6976
|
}, "syncHint");
|
|
5985
6977
|
|
|
5986
6978
|
// dist/knowledge/relationships-scan.js
|
|
5987
|
-
var
|
|
6979
|
+
var DAY4 = 864e5;
|
|
5988
6980
|
var SCAN_STEP = {
|
|
5989
6981
|
id: "relationships.scan",
|
|
5990
6982
|
kind: "command",
|
|
@@ -6058,7 +7050,7 @@ var relationshipsScanCommand = /* @__PURE__ */ __name((relations, print, env, wa
|
|
|
6058
7050
|
if (options.limit > 50)
|
|
6059
7051
|
throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
|
|
6060
7052
|
const window = projectWindowOf(options.sinceTime);
|
|
6061
|
-
const since = new Date("days" in window ? Date.now() - window.days *
|
|
7053
|
+
const since = new Date("days" in window ? Date.now() - window.days * DAY4 : window.after).toISOString();
|
|
6062
7054
|
const written2 = options.yes === true;
|
|
6063
7055
|
const { body, text: text3 } = await withStore(env, async (store) => {
|
|
6064
7056
|
const sources = await namedAccounts(store, env, options, warn);
|
|
@@ -6106,14 +7098,14 @@ var projectGatherCommand = /* @__PURE__ */ __name((projects, print, env, warn) =
|
|
|
6106
7098
|
});
|
|
6107
7099
|
const since = new Date(found.window.after).toISOString().slice(0, 10);
|
|
6108
7100
|
const syncs = found.linkedChats.map((one2) => one2.completeness === null || one2.completeness.state === "complete" ? null : chatSync(one2, since, env, chosen));
|
|
6109
|
-
const
|
|
7101
|
+
const parts2 = projectAnswerParts(options.sinceTime, found);
|
|
6110
7102
|
const blocked = [...new Set(syncs.flatMap((one2) => one2 && one2.command === null ? [one2.why] : []))];
|
|
6111
|
-
const missing = [...
|
|
6112
|
-
const next = [...
|
|
7103
|
+
const missing = [...parts2.missing ?? [], ...blocked.map((why) => ({ field: "sync_command", why }))];
|
|
7104
|
+
const next = [...parts2.next ?? [], ...scan].slice(0, MAX_NEXT_STEPS);
|
|
6113
7105
|
print(options.json, itemAnswer({
|
|
6114
7106
|
...found,
|
|
6115
7107
|
linkedChats: found.linkedChats.map((one2, i) => ({ ...one2, syncCommand: syncs[i]?.command ?? null }))
|
|
6116
|
-
}, { ...
|
|
7108
|
+
}, { ...parts2, ...missing.length ? { missing } : {}, ...next.length ? { next } : {} }), projectEvidenceText(found, {
|
|
6117
7109
|
sync: /* @__PURE__ */ __name((chat, at) => syncHint(chat, at, env, chosen), "sync"),
|
|
6118
7110
|
showDocument: "memo notes show"
|
|
6119
7111
|
}));
|
|
@@ -6161,7 +7153,7 @@ var projectStatusCommand = /* @__PURE__ */ __name((projects, print, env) => answ
|
|
|
6161
7153
|
param: "--compact"
|
|
6162
7154
|
});
|
|
6163
7155
|
const chosen = options.syncProfile ?? {};
|
|
6164
|
-
const { found, finance, open } = await withStore(env, async (store) => {
|
|
7156
|
+
const { found, finance, open: open2 } = await withStore(env, async (store) => {
|
|
6165
7157
|
const status = await projectStatus(store, {
|
|
6166
7158
|
project,
|
|
6167
7159
|
...projectWindowOf(options.sinceTime),
|
|
@@ -6185,13 +7177,13 @@ var projectStatusCommand = /* @__PURE__ */ __name((projects, print, env) => answ
|
|
|
6185
7177
|
print(options.json, itemOf({
|
|
6186
7178
|
...item,
|
|
6187
7179
|
...finance.length ? { finance } : {},
|
|
6188
|
-
...
|
|
6189
|
-
...
|
|
7180
|
+
...open2.deals.length ? { deals: open2.deals } : {},
|
|
7181
|
+
...open2.more ? { deals_more: open2.more } : {}
|
|
6190
7182
|
}, {
|
|
6191
7183
|
...next.length ? { next: next.map(asAction) } : {},
|
|
6192
7184
|
...gaps.length ? { missing: gaps } : {},
|
|
6193
7185
|
meta
|
|
6194
|
-
}), [projectStatusText(found, hints), ...financeText(finance), ...dealsText(
|
|
7186
|
+
}), [projectStatusText(found, hints), ...financeText(finance), ...dealsText(open2)].join("\n"), options.compact === true);
|
|
6195
7187
|
}), "projectStatusCommand");
|
|
6196
7188
|
|
|
6197
7189
|
// dist/knowledge/project-transfer.js
|
|
@@ -6363,9 +7355,9 @@ var pending = /* @__PURE__ */ __name(async (store, about) => {
|
|
|
6363
7355
|
};
|
|
6364
7356
|
}, "pending");
|
|
6365
7357
|
var listRelationships = /* @__PURE__ */ __name(async (store, words) => {
|
|
6366
|
-
const
|
|
6367
|
-
const about =
|
|
6368
|
-
const confirmed =
|
|
7358
|
+
const terms2 = queryTerms(words, RELATIONSHIP_QUERY, "relationships list");
|
|
7359
|
+
const about = terms2.get("about");
|
|
7360
|
+
const confirmed = terms2.get("confirmed");
|
|
6369
7361
|
const found = confirmed === "false" ? await pending(store, about) : {
|
|
6370
7362
|
hasMore: false,
|
|
6371
7363
|
items: (await store.knowledge.relations(null, about)).filter((one2) => confirmed === void 0 || one2.confirmed).map((one2) => ({ ...one2, status: one2.confirmed ? "confirmed" : "proposed" }))
|
|
@@ -6471,7 +7463,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
6471
7463
|
return ownedList("projects key-documents list", options, async (store) => keyDocuments(store, await projectOf(store, project), id === void 0 ? {} : { id }));
|
|
6472
7464
|
});
|
|
6473
7465
|
const relations = program.command("relationships").description("relations between people, organizations and projects; never between identities");
|
|
6474
|
-
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
|
|
7466
|
+
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) => {
|
|
6475
7467
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "state it as yours?" });
|
|
6476
7468
|
return owned(options, async (store) => {
|
|
6477
7469
|
const input = {
|
|
@@ -6488,7 +7480,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
6488
7480
|
const found = await withStore(env, (store) => listRelationships(store, words));
|
|
6489
7481
|
print(options.json, listAnswer("relationships list", { items: found.items, limit: found.limit, has_more: found.hasMore }), relationshipsText(found.items));
|
|
6490
7482
|
});
|
|
6491
|
-
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,
|
|
7483
|
+
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) => {
|
|
6492
7484
|
const change = {
|
|
6493
7485
|
...options.role === void 0 ? {} : { role: options.role === "" ? null : options.role },
|
|
6494
7486
|
...options.purpose === void 0 ? {} : { purpose: options.purpose }
|
|
@@ -6580,7 +7572,7 @@ var party2 = /* @__PURE__ */ __name((reference2, name2) => [
|
|
|
6580
7572
|
...name2 && fold3(name2) ? [`name:${fold3(name2)}`] : []
|
|
6581
7573
|
], "party");
|
|
6582
7574
|
var text = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim() ? value : void 0, "text");
|
|
6583
|
-
var present = /* @__PURE__ */ __name((
|
|
7575
|
+
var present = /* @__PURE__ */ __name((parts2) => parts2.filter((part) => part !== void 0), "present");
|
|
6584
7576
|
var keysOf = /* @__PURE__ */ __name((finding) => {
|
|
6585
7577
|
const raw = finding ?? {};
|
|
6586
7578
|
const [shop, number2, url, id] = [raw.supplierName, raw.number, raw.sourceUrl, raw.externalId].map(text);
|
|
@@ -6712,7 +7704,7 @@ var oneMailboxOf = /* @__PURE__ */ __name(async (store, env, source) => {
|
|
|
6712
7704
|
throw new CliError("validation_error", `${source} is not a mailbox \u2014 ${MAIL_SOURCES}`, { param: "source" });
|
|
6713
7705
|
return key;
|
|
6714
7706
|
}, "oneMailboxOf");
|
|
6715
|
-
var
|
|
7707
|
+
var named3 = /* @__PURE__ */ __name((commands2, name2) => {
|
|
6716
7708
|
const found = commands2.find((command) => command.name() === name2);
|
|
6717
7709
|
if (!found)
|
|
6718
7710
|
throw new Error(`cli-core's mail commands have no ${name2}`);
|
|
@@ -6732,10 +7724,10 @@ var mailReviewCommands = /* @__PURE__ */ __name((mail, messages, env) => {
|
|
|
6732
7724
|
}
|
|
6733
7725
|
};
|
|
6734
7726
|
const shared = mailReadCommands(reads);
|
|
6735
|
-
const review =
|
|
6736
|
-
const sharedMessages =
|
|
6737
|
-
const acknowledge =
|
|
6738
|
-
const reset =
|
|
7727
|
+
const review = named3(shared, "review");
|
|
7728
|
+
const sharedMessages = named3(shared, "messages").commands;
|
|
7729
|
+
const acknowledge = named3(sharedMessages, "acknowledge");
|
|
7730
|
+
const reset = named3(sharedMessages, "reset");
|
|
6739
7731
|
for (const command of [review, acknowledge, reset])
|
|
6740
7732
|
overrideSharedContract(command, "memo holds several mailboxes and no profile, so --source names the one mailbox; its --json is per command.", (one2) => {
|
|
6741
7733
|
one2.option("--source <accounts>", MAILBOX_HELP).option("--json", "print JSON; --json=id,title keeps only those fields");
|
|
@@ -6790,39 +7782,39 @@ var keyed = /* @__PURE__ */ __name((text3, key) => {
|
|
|
6790
7782
|
}
|
|
6791
7783
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
6792
7784
|
return text3;
|
|
6793
|
-
const
|
|
6794
|
-
if (
|
|
6795
|
-
throw new CliError("validation_error", `the batch's key ${String(
|
|
7785
|
+
const named5 = raw.key;
|
|
7786
|
+
if (named5 !== void 0 && named5 !== key)
|
|
7787
|
+
throw new CliError("validation_error", `the batch's key ${String(named5)} is not --key ${key}; give the key once`, {
|
|
6796
7788
|
reason: "findings.key-mismatch",
|
|
6797
|
-
key: String(
|
|
7789
|
+
key: String(named5),
|
|
6798
7790
|
given: key
|
|
6799
7791
|
});
|
|
6800
7792
|
return JSON.stringify({ ...raw, key });
|
|
6801
7793
|
}, "keyed");
|
|
6802
|
-
var
|
|
7794
|
+
var json3 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
|
|
6803
7795
|
var mailFindingsCommand = /* @__PURE__ */ __name((program, mail, streams, env) => {
|
|
6804
7796
|
const { run } = answers(program, streams, env);
|
|
6805
7797
|
const findings = mail.command("findings").description("cited tasks, task updates, facts, memories, links, contacts, invoices, payments and orders an agent read in new mail").summary("what an agent read in new mail, cited, waiting for the owner");
|
|
6806
|
-
|
|
7798
|
+
json3(proposesOnly(annotate(findings.command("add"), { effects: LOCAL_WRITE, output: { entity: "mail_findings" } }))).description("stage one mailbox's findings for the owner; nothing is created until the owner confirms").summary("stage one mailbox's findings; the owner confirms them").argument("<file>", FINDINGS_INPUT_HELP).option("--source <accounts>", MAILBOX_HELP).option("--key <key>", "the findings key `mail review --holder` gave in its mail-findings.add step").option("--dry-run", "check the batch as staging would, invoices, payments and orders tried and rolled back, and stage nothing; answers valid and every finding's problem at once").addHelpText("after", INPUT_HELP).action(async (file, given2) => {
|
|
6807
7799
|
const read = await readFindingsInput(file, environmentOf(program).stdin ?? process.stdin);
|
|
6808
|
-
const text3 = keyed(read,
|
|
6809
|
-
const input =
|
|
7800
|
+
const text3 = keyed(read, given2.key);
|
|
7801
|
+
const input = given2.dryRun ? readMailFindingsJson(text3) : parseMailFindingsJson(text3);
|
|
6810
7802
|
const author = await whoRuns(program, env, { question: "" });
|
|
6811
7803
|
const agent = author === "owner" ? { bot: "memo-mail-findings" } : author;
|
|
6812
|
-
await run(
|
|
6813
|
-
const mailbox = await oneMailboxOf(store, env,
|
|
7804
|
+
await run(given2.json, async (store) => {
|
|
7805
|
+
const mailbox = await oneMailboxOf(store, env, given2.source);
|
|
6814
7806
|
const { input: kept, duplicates } = await withoutDuplicates(store, input);
|
|
6815
7807
|
const noted = duplicates.length ? { duplicates } : {};
|
|
6816
7808
|
if (duplicates.length > 0 && kept.findings.length === 0)
|
|
6817
7809
|
return itemAnswer({
|
|
6818
|
-
dryRun: Boolean(
|
|
7810
|
+
dryRun: Boolean(given2.dryRun),
|
|
6819
7811
|
valid: true,
|
|
6820
7812
|
staged: false,
|
|
6821
7813
|
findings: 0,
|
|
6822
7814
|
problems: [],
|
|
6823
7815
|
...noted
|
|
6824
7816
|
});
|
|
6825
|
-
if (!
|
|
7817
|
+
if (!given2.dryRun)
|
|
6826
7818
|
return itemAnswer({ ...await store.mailFindings.stage(mailbox, kept, agent), ...noted });
|
|
6827
7819
|
const checked = await store.mailFindings.check(mailbox, kept, agent);
|
|
6828
7820
|
const issues = checked.problems.map((one2) => ({
|
|
@@ -6833,22 +7825,22 @@ var mailFindingsCommand = /* @__PURE__ */ __name((program, mail, streams, env) =
|
|
|
6833
7825
|
return itemAnswer({ dryRun: true, ...checked, ...noted }, issues.length ? { meta: { complete: false, issues } } : void 0);
|
|
6834
7826
|
});
|
|
6835
7827
|
});
|
|
6836
|
-
|
|
6837
|
-
withQuery(
|
|
7828
|
+
json3(annotate(findings.command("show"), { effects: LOCAL_READ, output: { entity: "mail_findings" } })).description("one findings batch: its findings with their evidence, earlier decisions and the review receipt").summary("one findings batch with its evidence and decisions").argument("<id>", "the batch id `mail findings add` or `list` gave").action((id, given2) => run(given2.json, async (store) => itemAnswer(await store.mailFindings.get(id))));
|
|
7829
|
+
withQuery(json3(annotate(findings.command("list"), { effects: LOCAL_READ, output: { entity: "mail_findings" } })), FINDINGS_QUERY2).description("mail findings batches, newest first; status:proposed is what waits for the owner").option("--source <accounts>", "only this mailbox's batches: email:<address>").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words, given2) => run(given2.json, async (store) => {
|
|
6838
7830
|
const status = queryTerms(words, FINDINGS_QUERY2, "mail findings list").get("status");
|
|
6839
|
-
const account2 =
|
|
7831
|
+
const account2 = given2.source ? await oneMailboxOf(store, env, given2.source) : void 0;
|
|
6840
7832
|
const found = await store.mailFindings.list({
|
|
6841
|
-
limit:
|
|
6842
|
-
offset: (
|
|
7833
|
+
limit: given2.limit,
|
|
7834
|
+
offset: (given2.page - 1) * given2.limit,
|
|
6843
7835
|
...account2 === void 0 ? {} : { account: account2 },
|
|
6844
7836
|
...status === void 0 ? {} : { status }
|
|
6845
7837
|
});
|
|
6846
7838
|
return listAnswer("mail findings list", {
|
|
6847
7839
|
items: found.items,
|
|
6848
|
-
limit:
|
|
6849
|
-
page:
|
|
7840
|
+
limit: given2.limit,
|
|
7841
|
+
page: given2.page,
|
|
6850
7842
|
has_more: found.hasMore,
|
|
6851
|
-
args: { query: words.join(" "), ...
|
|
7843
|
+
args: { query: words.join(" "), ...given2.source ? { source: given2.source } : {}, limit: given2.limit }
|
|
6852
7844
|
});
|
|
6853
7845
|
}));
|
|
6854
7846
|
}, "mailFindingsCommand");
|
|
@@ -6974,10 +7966,10 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
|
|
|
6974
7966
|
}).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) => {
|
|
6975
7967
|
if (!options.http && (options.port !== void 0 || options.publicUrl !== void 0))
|
|
6976
7968
|
throw new CliError("validation_error", "--port and --public-url require --http");
|
|
6977
|
-
const { createMemoServer } = await import("./server-
|
|
7969
|
+
const { createMemoServer } = await import("./server-MVJU7QG4.js");
|
|
6978
7970
|
const build = /* @__PURE__ */ __name(() => createMemoServer(env, createProgram2, options.permission), "build");
|
|
6979
7971
|
if (options.http) {
|
|
6980
|
-
const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-
|
|
7972
|
+
const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-QX2D6EXA.js");
|
|
6981
7973
|
const publicUrl = publicUrlOf(options.publicUrl, {
|
|
6982
7974
|
missing: "--http",
|
|
6983
7975
|
reaches: "the browser apps reach memo",
|
|
@@ -7029,7 +8021,7 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
|
|
|
7029
8021
|
});
|
|
7030
8022
|
});
|
|
7031
8023
|
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() {
|
|
7032
|
-
const { revokeAll } = await import("./mcp-
|
|
8024
|
+
const { revokeAll } = await import("./mcp-QX2D6EXA.js");
|
|
7033
8025
|
revokeAll(httpTokenFile(env));
|
|
7034
8026
|
out.print(this.opts().json, itemAnswer({ revoked: true }));
|
|
7035
8027
|
});
|
|
@@ -7092,28 +8084,28 @@ var readStoredMeetingPassage = /* @__PURE__ */ __name(async (store, env, source,
|
|
|
7092
8084
|
// dist/meetings/command.js
|
|
7093
8085
|
var meetingReadCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
7094
8086
|
const { print } = answers(program, streams, env);
|
|
7095
|
-
const source = /* @__PURE__ */ __name((
|
|
8087
|
+
const source = /* @__PURE__ */ __name((given2) => sourceOf(given2, (text3) => streams.diagnostic(text3)), "source");
|
|
7096
8088
|
const output = /* @__PURE__ */ __name((command) => sourceOptions(command, MEETING_ACCOUNT_HELP).option("--json", "print the standard JSON answer"), "output");
|
|
7097
8089
|
const grammar = createMeetingSearchCommand(program);
|
|
7098
8090
|
const search2 = overrideSharedContract(grammar, "Memo selects an explicit stored source and uses native tag: queries instead of a tag flag, with command-local JSON output.", (command) => {
|
|
7099
8091
|
Reflect.set(command, "options", command.options.filter((option) => option.long !== "--tag"));
|
|
7100
8092
|
output(command);
|
|
7101
8093
|
});
|
|
7102
|
-
search2.action(async (query,
|
|
7103
|
-
const input = meetingHitSearchRequest(query,
|
|
7104
|
-
const result = await withStore(env, (store) => searchStoredMeetings(store, env, source(
|
|
7105
|
-
...
|
|
8094
|
+
search2.action(async (query, given2) => {
|
|
8095
|
+
const input = meetingHitSearchRequest(query, given2);
|
|
8096
|
+
const result = await withStore(env, (store) => searchStoredMeetings(store, env, source(given2), query, input, meetingSearchArguments(query, given2), {
|
|
8097
|
+
...given2,
|
|
7106
8098
|
timesReadIn: grammar.getOptionValue("timesReadIn")
|
|
7107
8099
|
}));
|
|
7108
|
-
print(
|
|
8100
|
+
print(given2.json, result);
|
|
7109
8101
|
});
|
|
7110
8102
|
overrideSharedContract(createMeetingPassageCommand(program), "Memo passage reads an explicitly selected stored source and exposes command-local JSON output.", (command) => {
|
|
7111
8103
|
output(command);
|
|
7112
|
-
}).action(async (reference2,
|
|
7113
|
-
const format =
|
|
7114
|
-
const input = meetingPassageRequest(reference2, { ...
|
|
7115
|
-
const result = await withStore(env, (store) => readStoredMeetingPassage(store, env, source(
|
|
7116
|
-
print(
|
|
8104
|
+
}).action(async (reference2, given2) => {
|
|
8105
|
+
const format = given2.json ? "json" : given2.format ?? "text";
|
|
8106
|
+
const input = meetingPassageRequest(reference2, { ...given2, format });
|
|
8107
|
+
const result = await withStore(env, (store) => readStoredMeetingPassage(store, env, source(given2), reference2, input));
|
|
8108
|
+
print(given2.json, itemAnswer(result.packet), result.content);
|
|
7117
8109
|
});
|
|
7118
8110
|
}, "meetingReadCommands");
|
|
7119
8111
|
|
|
@@ -7126,13 +8118,13 @@ var communicationSource = /* @__PURE__ */ __name(async (store, env, id) => {
|
|
|
7126
8118
|
});
|
|
7127
8119
|
const key = await oneAccountOf(store, env, `${id.slice(0, dot)}:${id.slice(dot + 1)}`, "--context-source");
|
|
7128
8120
|
const held = await store.accounts.storedAccount(key);
|
|
7129
|
-
const
|
|
8121
|
+
const listed2 = entriesOfList(accountName(key), {
|
|
7130
8122
|
held: [held],
|
|
7131
8123
|
profiles: {},
|
|
7132
8124
|
groups: {},
|
|
7133
8125
|
running: { provider: "email", command: "memo" }
|
|
7134
8126
|
})[0]?.accounts[0];
|
|
7135
|
-
const kind =
|
|
8127
|
+
const kind = listed2?.kind === "messages" ? "message" : listed2?.kind === "mail" ? "mail" : void 0;
|
|
7136
8128
|
if (kind === void 0)
|
|
7137
8129
|
throw new CliError("validation_error", `${id}: select one stored messenger profile or mailbox`, {
|
|
7138
8130
|
param: "communications.sources"
|
|
@@ -7510,8 +8502,8 @@ var refuseOverMcp = /* @__PURE__ */ __name((options, mcp2) => {
|
|
|
7510
8502
|
param: "export"
|
|
7511
8503
|
});
|
|
7512
8504
|
}, "refuseOverMcp");
|
|
7513
|
-
var textOf = /* @__PURE__ */ __name((options,
|
|
7514
|
-
const sources = [
|
|
8505
|
+
var textOf = /* @__PURE__ */ __name((options, given2) => {
|
|
8506
|
+
const sources = [given2, options.text, options.textFile].filter((value) => value !== void 0);
|
|
7515
8507
|
if (sources.length !== 1)
|
|
7516
8508
|
throw new CliError("validation_error", "give the text once: as an argument, --text or --text-file");
|
|
7517
8509
|
if (options.textFile !== void 0)
|
|
@@ -7575,14 +8567,14 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
7575
8567
|
...answer.backlinks.length ? [`linked from: ${answer.backlinks.map(({ from }) => from).join(", ")}`] : []
|
|
7576
8568
|
].join("\n"));
|
|
7577
8569
|
});
|
|
7578
|
-
withQuery(annotate(notes2.command("list"), { effects: LOCAL_READ }).description("notes, newest first"), NOTES_LIST_QUERY).option("--limit <n>", "most notes, at most 500", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, { json:
|
|
7579
|
-
const
|
|
7580
|
-
const about =
|
|
7581
|
-
const source =
|
|
7582
|
-
const search2 =
|
|
7583
|
-
if (about !== void 0 &&
|
|
8570
|
+
withQuery(annotate(notes2.command("list"), { effects: LOCAL_READ }).description("notes, newest first"), NOTES_LIST_QUERY).option("--limit <n>", "most notes, at most 500", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, { json: json5, ...paging }) => {
|
|
8571
|
+
const terms2 = queryTerms(words, NOTES_LIST_QUERY, "notes list");
|
|
8572
|
+
const about = terms2.get("about");
|
|
8573
|
+
const source = terms2.get("source");
|
|
8574
|
+
const search2 = terms2.get("text");
|
|
8575
|
+
if (about !== void 0 && terms2.size > 1)
|
|
7584
8576
|
throw new CliError("validation_error", "about: stands alone in notes list: its notes are found through links");
|
|
7585
|
-
const options = { ...paging, json:
|
|
8577
|
+
const options = { ...paging, json: json5 };
|
|
7586
8578
|
const page = await withNotes(async (store) => listNotes(store, {
|
|
7587
8579
|
limit: options.limit,
|
|
7588
8580
|
offset: (options.page - 1) * options.limit,
|
|
@@ -7601,9 +8593,9 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
7601
8593
|
output: { entity: "note" },
|
|
7602
8594
|
literal_after_dashes: true
|
|
7603
8595
|
}).description("write a note of your own about messages, people, projects or other notes").argument("[text]", "the note; or --text, or --text-file").option("--text <text>", "the note").option("--text-file <path>", "read the note from a file; - reads stdin").option("--title <title>", "a title").option("--subject <ref>", "what it is about: <messenger>:<name or id>, msg:, chat:, person:, organization:, project:, task:, note:, document:, meeting:; repeat for more", collect).option("--meeting <id>", "also about this meeting, by its store id, with --account");
|
|
7604
|
-
writeOptions(noteAdd, `the account of --meeting: ${MEETING_WRITE_HELP}`).option("--export [dir]", "also write it as a file \u2014 to this folder, or notes.export.dir").option("--format <format>", `the file's format: ${DIALECTS.join(", ")}`, formatOf).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (
|
|
8596
|
+
writeOptions(noteAdd, `the account of --meeting: ${MEETING_WRITE_HELP}`).option("--export [dir]", "also write it as a file \u2014 to this folder, or notes.export.dir").option("--format <format>", `the file's format: ${DIALECTS.join(", ")}`, formatOf).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (given2, options, command) => {
|
|
7605
8597
|
refuseOverMcp(options, isMcpRun(command, env));
|
|
7606
|
-
const body = textOf(options,
|
|
8598
|
+
const body = textOf(options, given2);
|
|
7607
8599
|
const value = writeAccountOf(options, (text3) => streams.diagnostic(text3));
|
|
7608
8600
|
if (options.meeting === void 0 && value !== void 0)
|
|
7609
8601
|
throw new CliError("validation_error", "--account selects the account of --meeting");
|
|
@@ -7884,8 +8876,105 @@ var peopleCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
7884
8876
|
});
|
|
7885
8877
|
}, "peopleCommand");
|
|
7886
8878
|
|
|
7887
|
-
// dist/records/
|
|
7888
|
-
import {
|
|
8879
|
+
// dist/records/input.js
|
|
8880
|
+
import { open } from "node:fs/promises";
|
|
8881
|
+
var PHONE = "phone";
|
|
8882
|
+
var BOM = /^\uFEFF/;
|
|
8883
|
+
var errnoOf = /* @__PURE__ */ __name((error) => typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0, "errnoOf");
|
|
8884
|
+
var linesOf = /* @__PURE__ */ __name(async (file, stdin) => {
|
|
8885
|
+
if (file === "-")
|
|
8886
|
+
return jsonlLines(stdin);
|
|
8887
|
+
try {
|
|
8888
|
+
const handle = await open(file);
|
|
8889
|
+
if (!(await handle.stat()).isFile()) {
|
|
8890
|
+
await handle.close();
|
|
8891
|
+
throw Object.assign(new Error(`${file} is a folder`), { code: "EISDIR" });
|
|
8892
|
+
}
|
|
8893
|
+
return jsonlLines(handle.createReadStream({ encoding: "utf8" }));
|
|
8894
|
+
} catch (error) {
|
|
8895
|
+
if (errnoOf(error) === "ENOENT")
|
|
8896
|
+
throw new CliError("not_found", `no records file ${file}: give a file that exists, or - for stdin`, {
|
|
8897
|
+
reason: "records.file-missing",
|
|
8898
|
+
path: file
|
|
8899
|
+
});
|
|
8900
|
+
const why = errnoOf(error) === "EISDIR" ? "it is a folder" : errnoOf(error) === "EACCES" ? "no permission" : "unreadable";
|
|
8901
|
+
throw new CliError("validation_error", `the records file ${file} cannot be read: ${why}`, {
|
|
8902
|
+
reason: "records.file-unreadable",
|
|
8903
|
+
path: file,
|
|
8904
|
+
why
|
|
8905
|
+
});
|
|
8906
|
+
}
|
|
8907
|
+
}, "linesOf");
|
|
8908
|
+
var headerOf = /* @__PURE__ */ __name((line3) => {
|
|
8909
|
+
try {
|
|
8910
|
+
const value = JSON.parse(line3);
|
|
8911
|
+
return value && typeof value === "object" && !Array.isArray(value) && !("records" in value) ? value : void 0;
|
|
8912
|
+
} catch {
|
|
8913
|
+
return void 0;
|
|
8914
|
+
}
|
|
8915
|
+
}, "headerOf");
|
|
8916
|
+
var accountIn = /* @__PURE__ */ __name((envelope, given2) => {
|
|
8917
|
+
const provider = envelope?.source?.provider;
|
|
8918
|
+
return typeof provider === "string" && given2.startsWith(`${provider}:`) ? given2.slice(provider.length + 1) : given2;
|
|
8919
|
+
}, "accountIn");
|
|
8920
|
+
var deviceOf = /* @__PURE__ */ __name((given2) => {
|
|
8921
|
+
const at = given2.indexOf(":");
|
|
8922
|
+
if (at < 0)
|
|
8923
|
+
return given2;
|
|
8924
|
+
if (given2.slice(0, at) !== PHONE)
|
|
8925
|
+
throw new CliError("validation_error", "a vCard file holds a phone's contacts: --account phone:<device>", {
|
|
8926
|
+
param: "--account"
|
|
8927
|
+
});
|
|
8928
|
+
return given2.slice(at + 1);
|
|
8929
|
+
}, "deviceOf");
|
|
8930
|
+
var importRecords = /* @__PURE__ */ __name(async (store, { file, stdin, account: account2, dryRun, onIssue }) => {
|
|
8931
|
+
const iterator = (await linesOf(file, stdin))[Symbol.asyncIterator]();
|
|
8932
|
+
const before = [];
|
|
8933
|
+
let next = await iterator.next();
|
|
8934
|
+
while (!next.done && next.value.replace(BOM, "").trim() === "") {
|
|
8935
|
+
before.push(next.value);
|
|
8936
|
+
next = await iterator.next();
|
|
8937
|
+
}
|
|
8938
|
+
async function* rest() {
|
|
8939
|
+
for (let line3 = await iterator.next(); !line3.done; line3 = await iterator.next())
|
|
8940
|
+
yield line3.value;
|
|
8941
|
+
}
|
|
8942
|
+
__name(rest, "rest");
|
|
8943
|
+
const whole2 = /* @__PURE__ */ __name(async (first2) => {
|
|
8944
|
+
const lines2 = [...before, ...first2];
|
|
8945
|
+
for await (const line3 of rest())
|
|
8946
|
+
lines2.push(line3);
|
|
8947
|
+
return lines2.join("\n");
|
|
8948
|
+
}, "whole");
|
|
8949
|
+
if (next.done)
|
|
8950
|
+
return ingest(store, envelopeOfText(before.join("\n")), { account: account2, dryRun, onIssue });
|
|
8951
|
+
const first = next.value.replace(BOM, "");
|
|
8952
|
+
if (isVcard(first)) {
|
|
8953
|
+
const { vcard, ...receipt } = await ingestVcard(store, await whole2([first]), {
|
|
8954
|
+
account: deviceOf(account2),
|
|
8955
|
+
provider: PHONE,
|
|
8956
|
+
batchId: `vcard-${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
8957
|
+
dryRun,
|
|
8958
|
+
onIssue
|
|
8959
|
+
});
|
|
8960
|
+
return { ...receipt, vcard: vcard.map((one2) => ({ ...one2, card: one2.card + 1 })) };
|
|
8961
|
+
}
|
|
8962
|
+
const header = headerOf(first);
|
|
8963
|
+
if (header !== void 0) {
|
|
8964
|
+
async function* all() {
|
|
8965
|
+
try {
|
|
8966
|
+
yield first;
|
|
8967
|
+
yield* rest();
|
|
8968
|
+
} finally {
|
|
8969
|
+
await iterator.return?.();
|
|
8970
|
+
}
|
|
8971
|
+
}
|
|
8972
|
+
__name(all, "all");
|
|
8973
|
+
return ingestLines(store, all(), { account: accountIn(header, account2), dryRun, onIssue });
|
|
8974
|
+
}
|
|
8975
|
+
const envelope = envelopeOfText(await whole2([first]));
|
|
8976
|
+
return ingest(store, envelope, { account: accountIn(envelope, account2), dryRun, onIssue });
|
|
8977
|
+
}, "importRecords");
|
|
7889
8978
|
|
|
7890
8979
|
// dist/records/mapping.js
|
|
7891
8980
|
var RECORD_QUERY = {
|
|
@@ -7894,7 +8983,11 @@ var RECORD_QUERY = {
|
|
|
7894
8983
|
fields: [
|
|
7895
8984
|
termField("type", "kw", "type:organization"),
|
|
7896
8985
|
termField("waiting", "bool", "waiting:true"),
|
|
7897
|
-
termField("flagged", "bool", "flagged:true")
|
|
8986
|
+
termField("flagged", "bool", "flagged:true"),
|
|
8987
|
+
termField("unmatched", "bool", "unmatched:true"),
|
|
8988
|
+
termField("entity", "ref", 'entity:"organization:3"'),
|
|
8989
|
+
termField("batch", "kw", "batch:2026-11-07"),
|
|
8990
|
+
termField("deleted", "bool", "deleted:true")
|
|
7898
8991
|
]
|
|
7899
8992
|
};
|
|
7900
8993
|
var sourceOf4 = /* @__PURE__ */ __name((account2) => {
|
|
@@ -7907,84 +9000,149 @@ var sourceOf4 = /* @__PURE__ */ __name((account2) => {
|
|
|
7907
9000
|
return { provider, account: name2 };
|
|
7908
9001
|
}, "sourceOf");
|
|
7909
9002
|
var recordOf = /* @__PURE__ */ __name((record2) => {
|
|
7910
|
-
const
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
});
|
|
9003
|
+
const from = record2.startsWith("custom:") ? "custom:".length : 0;
|
|
9004
|
+
const at = record2.indexOf(":", from);
|
|
9005
|
+
if (at <= from || at === record2.length - 1)
|
|
9006
|
+
throw new CliError("validation_error", `${record2} is not <type>:<external_id>, such as organization:client or custom:quote:Q-7`, { param: "record" });
|
|
7915
9007
|
return { type: record2.slice(0, at), externalId: record2.slice(at + 1) };
|
|
7916
9008
|
}, "recordOf");
|
|
9009
|
+
var RECORD_HELP = "<type>:<external_id> as the source names it, such as organization:client or custom:quote:Q-7";
|
|
7917
9010
|
var ACCOUNT_HELP = "the source, <provider>:<account> as the envelope's source names it, such as sheet:rentals";
|
|
7918
9011
|
var recordMappingCommands = /* @__PURE__ */ __name((records, program, streams, env) => {
|
|
7919
9012
|
const { run } = answers(program, streams, env);
|
|
7920
|
-
withQuery(annotate(records.command("list"), { effects: LOCAL_READ }).description("a source's records, newest first; waiting:true lists those whose
|
|
7921
|
-
const source = sourceOf4(
|
|
7922
|
-
const
|
|
9013
|
+
withQuery(annotate(records.command("list"), { effects: LOCAL_READ }).description("a source's records, newest first; waiting:true lists those that wait for a record they name, unmatched:true the people, organizations and projects whose identifiers fit more than one of yours, entity: those mapped to one of your entries"), RECORD_QUERY).summary("a source's records; waiting:true lists what needs records link").option("--account <account>", ACCOUNT_HELP).option("--limit <n>", "most records, up to 500", positive, 100).option("--json", "print JSON; --json=type,external_id,entity keeps only those fields").action((words, given2) => run(given2.json, async (store) => {
|
|
9014
|
+
const source = sourceOf4(given2.account);
|
|
9015
|
+
const terms2 = queryTerms(words, RECORD_QUERY, "records list");
|
|
7923
9016
|
const filter = {
|
|
7924
9017
|
...source,
|
|
7925
|
-
...
|
|
7926
|
-
...
|
|
7927
|
-
...
|
|
9018
|
+
...terms2.has("type") ? { type: terms2.get("type") } : {},
|
|
9019
|
+
...terms2.get("waiting") === "true" ? { waiting: true } : {},
|
|
9020
|
+
...terms2.get("flagged") === "true" ? { flagged: true } : {},
|
|
9021
|
+
...terms2.get("unmatched") === "true" ? { unmatched: true } : {},
|
|
9022
|
+
...terms2.has("entity") ? { entity: terms2.get("entity") } : {},
|
|
9023
|
+
...terms2.has("batch") ? { batch: terms2.get("batch") } : {},
|
|
9024
|
+
...terms2.has("deleted") ? { deleted: terms2.get("deleted") === "true" } : {}
|
|
7928
9025
|
};
|
|
7929
|
-
return pageOf("records list",
|
|
9026
|
+
return pageOf("records list", given2.limit, (most) => store.records.list({ ...filter, limit: most }));
|
|
7930
9027
|
}));
|
|
7931
|
-
byOption(annotate(records.command("link"), { effects: LOCAL_WRITE, output: { entity: "source_record" } }).description("say which of your entries a source's record is (organization:client is organization:3); never done by name. Records that waited for it become proposals in memo review. Only you link; an agent is refused").summary("say which of your entries a source's record is").argument("<record>",
|
|
7932
|
-
const by = await whoRuns(command, env, { asOwner:
|
|
7933
|
-
await run(
|
|
9028
|
+
byOption(annotate(records.command("link"), { effects: LOCAL_WRITE, output: { entity: "source_record" } }).description("say which of your entries a source's record is (organization:client is organization:3); never done by name. Records that waited for it become proposals in memo review. Only you link; an agent is refused").summary("say which of your entries a source's record is").argument("<record>", RECORD_HELP).argument("<ref>", "your entry of the same type: person:<id>, organization:<id> or project:<id>").option("--account <account>", ACCOUNT_HELP).option("--json", "print JSON; --json=type,external_id,entity keeps only those fields")).action(async (record2, ref, given2, command) => {
|
|
9029
|
+
const by = await whoRuns(command, env, { asOwner: given2.asOwner, question: `link ${record2} to ${ref} as you?` });
|
|
9030
|
+
await run(given2.json, async (store) => itemAnswer(await store.records.map({ ...sourceOf4(given2.account), ...recordOf(record2) }, ref, by)));
|
|
7934
9031
|
});
|
|
7935
9032
|
}, "recordMappingCommands");
|
|
7936
9033
|
|
|
9034
|
+
// dist/records/record-commands.js
|
|
9035
|
+
var INCOMING = 100;
|
|
9036
|
+
var codeOf = /* @__PURE__ */ __name((reason) => {
|
|
9037
|
+
const code = REASONS2.find((one2) => one2.reason === reason)?.code;
|
|
9038
|
+
return code === void 0 || code === "internal_error" ? "validation_error" : code;
|
|
9039
|
+
}, "codeOf");
|
|
9040
|
+
var storedRecord = /* @__PURE__ */ __name(async (store, account2, record2) => {
|
|
9041
|
+
const key = { ...sourceOf4(account2), ...recordOf(record2) };
|
|
9042
|
+
const found = await store.records.get(key);
|
|
9043
|
+
if (found === void 0)
|
|
9044
|
+
throw new CliError("not_found", `no record ${record2} from ${key.provider}:${key.account}; records list shows them`, {
|
|
9045
|
+
reason: "records.not-stored",
|
|
9046
|
+
record: record2
|
|
9047
|
+
});
|
|
9048
|
+
return found;
|
|
9049
|
+
}, "storedRecord");
|
|
9050
|
+
var matchText = /* @__PURE__ */ __name((run) => [
|
|
9051
|
+
`matched ${run.linked}, created ${run.created}`,
|
|
9052
|
+
...run.proposed.length ? [`proposed for your review: ${run.proposed.join(" ")}`] : [],
|
|
9053
|
+
...run.unmatched.map((one2) => `unmatched ${one2.key.type}:${one2.key.externalId}: ${one2.candidates.length ? `could be ${one2.candidates.join(" or ")}` : one2.reason}`),
|
|
9054
|
+
...run.errors.map((one2) => `refused ${one2.pointer} \xB7 ${one2.message} (${one2.code})`),
|
|
9055
|
+
...run.truncated ? ["the lists stop at 1000 entries each; the counts are exact"] : []
|
|
9056
|
+
].join("\n"), "matchText");
|
|
9057
|
+
var recordCommands = /* @__PURE__ */ __name((records, { run, print }, withStore2) => {
|
|
9058
|
+
jsonOption(annotate(records.command("show"), { effects: LOCAL_READ, output: { entity: "source_record" } }).argument("<record>", RECORD_HELP).option("--account <account>", ACCOUNT_HELP), "fields,relations,incoming,entity").description(`one record as its source said it: its fields, the records it names, the records that name it (incoming, the first ${INCOMING}) and the entry made from it`).summary("one record as its source said it").action((record2, given2) => run(given2.json, async (store) => {
|
|
9059
|
+
const found = await storedRecord(store, given2.account, record2);
|
|
9060
|
+
const incoming = await store.records.incoming(found, { limit: INCOMING + 1 });
|
|
9061
|
+
return itemAnswer({
|
|
9062
|
+
...found,
|
|
9063
|
+
incoming: { items: incoming.slice(0, INCOMING), hasMore: incoming.length > INCOMING }
|
|
9064
|
+
});
|
|
9065
|
+
}));
|
|
9066
|
+
jsonOption(annotate(records.command("delete"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).argument("<record>", RECORD_HELP).option("--account <account>", ACCOUNT_HELP), "deleted,flagged,errors").description("say a source no longer has a record, as an import's delete does: the record is kept as deleted, and the entry made from it stays, flagged for you to reject or keep").summary("mark a source's record deleted").action(async (record2, given2) => {
|
|
9067
|
+
const receipt = await withStore2(async (store) => {
|
|
9068
|
+
const found = await storedRecord(store, given2.account, record2);
|
|
9069
|
+
return ingest(store, {
|
|
9070
|
+
schema_version: RECORDS_SCHEMA_VERSION,
|
|
9071
|
+
source: {
|
|
9072
|
+
provider: found.provider,
|
|
9073
|
+
account: found.account,
|
|
9074
|
+
batch_id: `delete-${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
9075
|
+
},
|
|
9076
|
+
records: [
|
|
9077
|
+
{
|
|
9078
|
+
key: "delete",
|
|
9079
|
+
type: found.type,
|
|
9080
|
+
external_id: found.externalId,
|
|
9081
|
+
operation: "delete",
|
|
9082
|
+
...found.revision === null ? {} : { revision: found.revision }
|
|
9083
|
+
}
|
|
9084
|
+
]
|
|
9085
|
+
}, { account: found.account });
|
|
9086
|
+
});
|
|
9087
|
+
const [refused] = receipt.errors;
|
|
9088
|
+
if (refused)
|
|
9089
|
+
throw new CliError(codeOf(refused.code), refused.message, { reason: refused.code });
|
|
9090
|
+
print(given2.json, itemAnswer(receipt), receipt.deleted === 0 ? `${record2} was already deleted` : `deleted ${record2}${receipt.flagged.length ? `; ${receipt.flagged.map((one2) => one2.entity).join(" ")} kept, flagged for you` : ""}`);
|
|
9091
|
+
});
|
|
9092
|
+
jsonOption(annotate(records.command("match"), { effects: LOCAL_WRITE, output: { entity: "records_match" } }).option("--account <account>", ACCOUNT_HELP), "linked,created,unmatched").description("link every waiting person, organization and project of a source to the one entry its e-mail, phone or other identifier names, or make one, as an import does; never by name. Two or more fits wait for records link").summary("match a source's waiting people and organizations").action((given2) => withStore2(async (store) => store.records.match(sourceOf4(given2.account))).then((found) => print(given2.json, itemAnswer(found), matchText(found))));
|
|
9093
|
+
}, "recordCommands");
|
|
9094
|
+
|
|
7937
9095
|
// dist/records/import.js
|
|
7938
|
-
var
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
let text3 = "";
|
|
7942
|
-
stdin.setEncoding("utf8");
|
|
7943
|
-
for await (const chunk of stdin)
|
|
7944
|
-
text3 += chunk;
|
|
7945
|
-
return text3;
|
|
7946
|
-
}, "readAll");
|
|
7947
|
-
var envelopeOf = /* @__PURE__ */ __name((text3) => {
|
|
7948
|
-
try {
|
|
7949
|
-
const whole2 = JSON.parse(text3);
|
|
7950
|
-
if (whole2 && typeof whole2 === "object" && "records" in whole2)
|
|
7951
|
-
return whole2;
|
|
7952
|
-
} catch {
|
|
7953
|
-
}
|
|
7954
|
-
return envelopeOfJsonl(text3);
|
|
7955
|
-
}, "envelopeOf");
|
|
7956
|
-
var accountIn = /* @__PURE__ */ __name((envelope, given) => {
|
|
7957
|
-
const provider = envelope?.source?.provider;
|
|
7958
|
-
return typeof provider === "string" && given.startsWith(`${provider}:`) ? given.slice(provider.length + 1) : given;
|
|
7959
|
-
}, "accountIn");
|
|
9096
|
+
var kindsOf = /* @__PURE__ */ __name((proposed) => [...new Set(proposed.map((ref) => ref.slice(0, ref.indexOf(":"))))], "kindsOf");
|
|
9097
|
+
var pointerOf = /* @__PURE__ */ __name((pointer) => pointer || "/", "pointerOf");
|
|
9098
|
+
var refusedLine = /* @__PURE__ */ __name((one2) => `refused ${pointerOf(one2.pointer)} \xB7 ${one2.message} (${one2.code})`, "refusedLine");
|
|
7960
9099
|
var receiptText = /* @__PURE__ */ __name((receipt) => [
|
|
7961
9100
|
`${receipt.dryRun ? "would import" : "imported"} ${receipt.source?.batchId ?? "nothing"}: ${receipt.created} created, ${receipt.updated} updated, ${receipt.unchanged} unchanged, ${receipt.deleted} deleted, ${receipt.refused} refused`,
|
|
7962
|
-
...receipt.proposed.length ? [
|
|
9101
|
+
...receipt.proposed.length ? [
|
|
9102
|
+
`proposed for your review (memo review list kind:${kindsOf(receipt.proposed).join(",")}): ` + receipt.proposed.join(" ")
|
|
9103
|
+
] : [],
|
|
7963
9104
|
...receipt.waiting.map((one2) => `waiting ${one2.key}: no entity yet for ${one2.missing.join(", ")}`),
|
|
9105
|
+
...receipt.unmatched.map((one2) => `unmatched ${one2.key}: ${one2.candidates.length ? `could be ${one2.candidates.join(" or ")}` : one2.reason}; you say which with memo records link`),
|
|
7964
9106
|
...receipt.flagged.map((one2) => `changed at the source ${one2.key}: ${one2.entity} kept as it was`),
|
|
7965
|
-
...receipt.
|
|
9107
|
+
...receipt.ignored.map((one2) => `kept as data only ${one2.key} ${one2.pointer} (${one2.reason})`),
|
|
9108
|
+
...(receipt.vcard ?? []).map((one2) => `notice card ${one2.card}: ${one2.message}`),
|
|
9109
|
+
...receipt.errors.map(refusedLine),
|
|
9110
|
+
...receipt.truncated ? ["the lists stop at 1000 entries each; the counts are exact"] : []
|
|
7966
9111
|
].join("\n"), "receiptText");
|
|
9112
|
+
var HOLDS_LOCK = "a dry run holds the store's write lock and grows the write-ahead log for its length";
|
|
7967
9113
|
var recordsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
7968
|
-
const
|
|
7969
|
-
const
|
|
7970
|
-
const
|
|
7971
|
-
|
|
9114
|
+
const answered = answers(program, streams, env);
|
|
9115
|
+
const { print } = answered;
|
|
9116
|
+
const records = program.command("records").description("what a source said, kept per account; what it says about money waits for your review").summary("what a source said, kept per account");
|
|
9117
|
+
const importing = /* @__PURE__ */ __name((command, dryRun) => command.argument("<file>", "a records envelope as JSON, JSONL (a header line, then a record per line, read as it streams) or a vCard address book (.vcf, into phone:<device>); - for stdin").option("--account <account>", "the source the envelope is for: <provider>:<account> (sheet:rentals) or its source.account alone; phone:<device> for a vCard file").option("--json", "print JSON; --json=created,errors keeps only those fields").action(async (file, given2) => {
|
|
9118
|
+
const account2 = given2.account?.trim();
|
|
7972
9119
|
if (!account2)
|
|
7973
9120
|
throw new CliError("validation_error", "name the source account the envelope is for: --account <account>", {
|
|
7974
9121
|
param: "--account"
|
|
7975
9122
|
});
|
|
7976
|
-
const
|
|
7977
|
-
|
|
9123
|
+
const receipt = await withStore(env, (store) => importRecords(store, {
|
|
9124
|
+
file,
|
|
9125
|
+
stdin: environmentOf(program).stdin ?? process.stdin,
|
|
9126
|
+
account: account2,
|
|
9127
|
+
dryRun: dryRun ?? given2.dryRun === true,
|
|
9128
|
+
onIssue: /* @__PURE__ */ __name((issue) => streams.diagnostic(`${refusedLine(issue)}
|
|
9129
|
+
`), "onIssue")
|
|
9130
|
+
}));
|
|
7978
9131
|
const issues = receipt.errors.map((one2) => ({
|
|
7979
9132
|
code: "validation_error",
|
|
7980
|
-
source: one2.pointer,
|
|
9133
|
+
source: pointerOf(one2.pointer),
|
|
7981
9134
|
reason: one2.code
|
|
7982
9135
|
}));
|
|
7983
|
-
print(
|
|
9136
|
+
print(given2.json, itemAnswer(receipt, issues.length ? { meta: { complete: false, issues } } : void 0), receiptText(receipt));
|
|
7984
9137
|
}), "importing");
|
|
7985
|
-
importing(annotate(records.command("import"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).description("bring a source's records into the store, once: the same file twice changes nothing, a lower revision is refused, and
|
|
7986
|
-
importing(
|
|
9138
|
+
importing(annotate(records.command("import"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).description("bring a source's records into the store, once: the same file twice changes nothing, a lower revision is refused, and anything that feeds money totals becomes a proposal for you, never confirmed money. Each refusal is also printed on stderr as it happens, one line each, past the receipt's 1000").summary("import a source's records; money waits for your review").option("--dry-run", `check and plan the import; write nothing. ${HOLDS_LOCK}`), void 0);
|
|
9139
|
+
importing(
|
|
9140
|
+
// A dry run holds the write lock for its length, so MCP gates it as a write.
|
|
9141
|
+
annotate(records.command("check"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).description(`what records import would do with the file, as its receipt, writing nothing; ${HOLDS_LOCK}`).summary("check a records file against the store; write nothing"),
|
|
9142
|
+
true
|
|
9143
|
+
);
|
|
7987
9144
|
recordMappingCommands(records, program, streams, env);
|
|
9145
|
+
recordCommands(records, answered, (work) => withStore(env, work));
|
|
7988
9146
|
}, "recordsCommand");
|
|
7989
9147
|
|
|
7990
9148
|
// dist/digest/known.js
|
|
@@ -8084,8 +9242,8 @@ var syncRunsOf = /* @__PURE__ */ __name((env) => {
|
|
|
8084
9242
|
};
|
|
8085
9243
|
}, "syncRunsOf");
|
|
8086
9244
|
var HOUR = 36e5;
|
|
8087
|
-
var
|
|
8088
|
-
var QUIET_AFTER = 3 *
|
|
9245
|
+
var DAY5 = 24 * HOUR;
|
|
9246
|
+
var QUIET_AFTER = 3 * DAY5;
|
|
8089
9247
|
var QUIET_GAPS = 3;
|
|
8090
9248
|
var hours = /* @__PURE__ */ __name((from, now) => Math.max(0, Math.floor((now - from) / HOUR)), "hours");
|
|
8091
9249
|
var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
|
|
@@ -8107,7 +9265,7 @@ var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
|
|
|
8107
9265
|
};
|
|
8108
9266
|
if (activity.newest === null || activity.moved30d === 0)
|
|
8109
9267
|
return void 0;
|
|
8110
|
-
const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 *
|
|
9268
|
+
const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 * DAY5 / activity.moved30d);
|
|
8111
9269
|
if (activity.newest < now - usual)
|
|
8112
9270
|
return { reason: "quiet", since: new Date(activity.newest).toISOString(), staleHours: hours(activity.newest, now) };
|
|
8113
9271
|
return void 0;
|
|
@@ -8282,13 +9440,13 @@ var countTasks = /* @__PURE__ */ __name(async (store, words) => {
|
|
|
8282
9440
|
|
|
8283
9441
|
// dist/digest/tasks.js
|
|
8284
9442
|
var DIGEST_SCHEDULE = "morning-digest";
|
|
8285
|
-
var
|
|
9443
|
+
var DAY6 = 864e5;
|
|
8286
9444
|
var previousDigestAt = /* @__PURE__ */ __name((env, now) => {
|
|
8287
9445
|
const state = resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env }).state;
|
|
8288
9446
|
const digest = schedulesOf(state).find((one2) => one2.name === DIGEST_SCHEDULE || one2.kind === "agent" && one2.argv.join(" ").includes(DIGEST_SCHEDULE));
|
|
8289
9447
|
const last = digest?.last;
|
|
8290
9448
|
if (!last)
|
|
8291
|
-
return new Date(now -
|
|
9449
|
+
return new Date(now - DAY6).toISOString();
|
|
8292
9450
|
return last.exitCode === 0 ? last.at : last.failingSince ?? last.at;
|
|
8293
9451
|
}, "previousDigestAt");
|
|
8294
9452
|
var dayOf2 = /* @__PURE__ */ __name((zone) => {
|
|
@@ -8330,7 +9488,7 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
|
|
|
8330
9488
|
const zone = timezoneOf();
|
|
8331
9489
|
const day2 = dayOf2(zone);
|
|
8332
9490
|
const today2 = day2(now);
|
|
8333
|
-
const tomorrow = day2(now +
|
|
9491
|
+
const tomorrow = day2(now + DAY6);
|
|
8334
9492
|
const since = Date.parse(newSince);
|
|
8335
9493
|
const seen = /* @__PURE__ */ new Map();
|
|
8336
9494
|
let accounts = 0;
|
|
@@ -8376,7 +9534,7 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
|
|
|
8376
9534
|
|
|
8377
9535
|
// dist/digest/digest.js
|
|
8378
9536
|
var WATCH_TAG = "watch";
|
|
8379
|
-
var
|
|
9537
|
+
var DAY7 = 864e5;
|
|
8380
9538
|
var MESSENGERS2 = /* @__PURE__ */ new Set(["telegram", "max", "whatsapp"]);
|
|
8381
9539
|
var HEALTH_ORDER = HEALTH_REASONS;
|
|
8382
9540
|
var UNNAMED = "unnamed account";
|
|
@@ -8405,8 +9563,8 @@ var labelsOf = /* @__PURE__ */ __name(async (store, keys) => {
|
|
|
8405
9563
|
}
|
|
8406
9564
|
const person = await store.people.personOf({ provider: key.provider, id: key.account });
|
|
8407
9565
|
const username = person?.identities.find((one2) => one2.provider === key.provider && one2.id === key.account)?.username;
|
|
8408
|
-
const
|
|
8409
|
-
const label = [
|
|
9566
|
+
const given2 = stored.get(name(key));
|
|
9567
|
+
const label = [given2 && given2 !== key.account ? given2 : null, username ? `@${username}` : null].filter(Boolean).join(" ");
|
|
8410
9568
|
const profile = profileOf(key);
|
|
8411
9569
|
labels.set(name(key), label || (profile ? `profile ${profile}` : UNNAMED));
|
|
8412
9570
|
}
|
|
@@ -8461,8 +9619,8 @@ var statusLine = /* @__PURE__ */ __name((data) => {
|
|
|
8461
9619
|
}, "statusLine");
|
|
8462
9620
|
var personal = /* @__PURE__ */ __name((newest) => !newest.bulk && !newest.list && !newest.envelope && !newest.demoted, "personal");
|
|
8463
9621
|
var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date.now(), limit, excerpt: excerpt2, owedWithin, newSince }) => {
|
|
8464
|
-
const window = (now - since) /
|
|
8465
|
-
const
|
|
9622
|
+
const window = (now - since) / DAY7;
|
|
9623
|
+
const days2 = `${Math.max(1, Math.ceil(window))}d`;
|
|
8466
9624
|
const accounts = await store.accounts.accounts();
|
|
8467
9625
|
const messengers2 = accounts.filter((key) => MESSENGERS2.has(key.provider));
|
|
8468
9626
|
const mailboxes = accounts.filter((key) => key.provider === "email");
|
|
@@ -8518,7 +9676,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8518
9676
|
let mailMoved = 0;
|
|
8519
9677
|
for (const key of messengers2) {
|
|
8520
9678
|
const { chats, storedAt } = await store.chats.chatActivity(key, owedSince);
|
|
8521
|
-
const month = (await store.chats.chatActivity(key, now - 30 *
|
|
9679
|
+
const month = (await store.chats.chatActivity(key, now - 30 * DAY7)).chats;
|
|
8522
9680
|
checkHealth(key, {
|
|
8523
9681
|
newest: month.reduce((most, chat) => Math.max(most ?? 0, Date.parse(chat.lastMessageAt)), null),
|
|
8524
9682
|
moved30d: month.length
|
|
@@ -8544,7 +9702,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8544
9702
|
owedHere++;
|
|
8545
9703
|
}
|
|
8546
9704
|
if (owedHere)
|
|
8547
|
-
owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin /
|
|
9705
|
+
owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin / DAY7)}d`);
|
|
8548
9706
|
for (const chatId of watched.chats.get(name(key)) ?? []) {
|
|
8549
9707
|
const page = await store.messages.messages(key, chatId, { limit, since: iso(since) });
|
|
8550
9708
|
for (const message of page.items)
|
|
@@ -8567,12 +9725,12 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8567
9725
|
}
|
|
8568
9726
|
for (const key of mailboxes) {
|
|
8569
9727
|
const stored = await store.accounts.storedAccount(key);
|
|
8570
|
-
const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS *
|
|
9728
|
+
const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS * DAY7));
|
|
8571
9729
|
const ref = /* @__PURE__ */ __name((thread) => formatReference({ type: "chat", provider: "email", account: key.account, chat: thread }), "ref");
|
|
8572
9730
|
const newest = threads.reduce((most, thread) => Math.max(most, thread.lastEmailAt), 0);
|
|
8573
9731
|
checkHealth(key, {
|
|
8574
9732
|
newest: newest || null,
|
|
8575
|
-
moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 *
|
|
9733
|
+
moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 * DAY7).length
|
|
8576
9734
|
});
|
|
8577
9735
|
mailMoved += threads.filter((thread) => thread.lastEmailAt >= since && thread.newest !== null && personal(thread.newest)).length;
|
|
8578
9736
|
coverage.push({
|
|
@@ -8629,7 +9787,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8629
9787
|
if (strangers.length)
|
|
8630
9788
|
unknown2.next.push(`memo mail review --source ${name(key)} --unanswered 1m bulk:false`);
|
|
8631
9789
|
if (newHere)
|
|
8632
|
-
mailNext.push(`memo mail review --source ${name(key)} date>${
|
|
9790
|
+
mailNext.push(`memo mail review --source ${name(key)} date>${days2} bulk:false`);
|
|
8633
9791
|
}
|
|
8634
9792
|
for (const uid of watched.people) {
|
|
8635
9793
|
const person = await store.people.personByUid(uid);
|
|
@@ -8703,7 +9861,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8703
9861
|
const isWatched = watched.projects.has(project.id) || watched.projects.has(project.ref);
|
|
8704
9862
|
if (fresh.length === 0 && !isWatched)
|
|
8705
9863
|
continue;
|
|
8706
|
-
projectNext.push(`memo projects status ${project.key ?? project.ref} --since-time ${
|
|
9864
|
+
projectNext.push(`memo projects status ${project.key ?? project.ref} --since-time ${days2}`);
|
|
8707
9865
|
if (fresh.length === 0)
|
|
8708
9866
|
projects.push({
|
|
8709
9867
|
item: { ref: project.ref, who: null, at: iso(since), excerpt: project.name, why: "watched project, quiet" }
|
|
@@ -8831,21 +9989,21 @@ var sinceOf = /* @__PURE__ */ __name((value, now = Date.now()) => {
|
|
|
8831
9989
|
return since;
|
|
8832
9990
|
}, "sinceOf");
|
|
8833
9991
|
var reviewAgendaCommand = /* @__PURE__ */ __name((review, print, streams, env) => {
|
|
8834
|
-
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, 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 \`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`).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 (
|
|
8835
|
-
if (
|
|
9992
|
+
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, 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 \`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`).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) => {
|
|
9993
|
+
if (given2.compact && given2.json)
|
|
8836
9994
|
throw new CliError("validation_error", "--compact and --json ask for different output \u2014 pick one", {
|
|
8837
9995
|
reason: "output.conflict",
|
|
8838
9996
|
param: "--compact"
|
|
8839
9997
|
});
|
|
8840
|
-
const since = sinceOf(
|
|
9998
|
+
const since = sinceOf(given2.sinceTime);
|
|
8841
9999
|
const gathered = await withStore(env, (store) => gatherDigest(store, env, {
|
|
8842
10000
|
since,
|
|
8843
|
-
limit:
|
|
8844
|
-
excerpt:
|
|
10001
|
+
limit: given2.limit,
|
|
10002
|
+
excerpt: given2.compact ? 100 : 200,
|
|
8845
10003
|
owedWithin: OWED_WITHIN
|
|
8846
10004
|
}));
|
|
8847
|
-
const digest = fitDigest(gathered,
|
|
8848
|
-
if (
|
|
10005
|
+
const digest = fitDigest(gathered, given2.maxOutputBytes ?? (given2.compact ? COMPACT_BYTES : FULL_BYTES));
|
|
10006
|
+
if (given2.json)
|
|
8849
10007
|
print(true, itemAnswer(digest));
|
|
8850
10008
|
else
|
|
8851
10009
|
streams.data(`${digestText(digest)}
|
|
@@ -8908,32 +10066,32 @@ var ROW = {
|
|
|
8908
10066
|
],
|
|
8909
10067
|
text: ["reason"]
|
|
8910
10068
|
};
|
|
8911
|
-
var
|
|
10069
|
+
var json4 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,title keeps only those fields"), "json");
|
|
8912
10070
|
var reviewCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
8913
10071
|
const { print } = answers(program, streams, env);
|
|
8914
10072
|
const review = program.command("review").description("every proposal waiting for your decision, across projects: links, key documents, facts, invoices, payments and more").summary("every proposal waiting for your decision, across projects");
|
|
8915
|
-
|
|
8916
|
-
if (
|
|
10073
|
+
json4(answerEntity(withQuery(annotate(review.command("list", { isDefault: true }), { effects: LOCAL_READ }).description("what waits for the owner's decision, newest first, with titles, who proposed it, why and the evidence").summary("what waits for your decision, newest first, with titles and evidence"), REVIEW_QUERY), "memo_proposal", PROPOSAL, { row: ROW })).option("--limit <n>", "proposals per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--compact", "one line per proposal").action(async (words, given2) => {
|
|
10074
|
+
if (given2.limit > 50)
|
|
8917
10075
|
throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
|
|
8918
|
-
const found = await withStore(env, (store) => listReview(store, env, words,
|
|
10076
|
+
const found = await withStore(env, (store) => listReview(store, env, words, given2));
|
|
8919
10077
|
const steps = reviewSteps(found.items);
|
|
8920
10078
|
const body = listAnswer("review list", {
|
|
8921
10079
|
items: found.items,
|
|
8922
|
-
limit:
|
|
8923
|
-
page:
|
|
10080
|
+
limit: given2.limit,
|
|
10081
|
+
page: given2.page,
|
|
8924
10082
|
has_more: found.hasMore,
|
|
8925
|
-
args: { query: words.join(" "), limit:
|
|
10083
|
+
args: { query: words.join(" "), limit: given2.limit },
|
|
8926
10084
|
...steps.length ? { next: steps } : {}
|
|
8927
10085
|
});
|
|
8928
|
-
print(
|
|
10086
|
+
print(given2.json, body, reviewText(found.items, found.hasMore), given2.compact);
|
|
8929
10087
|
});
|
|
8930
|
-
|
|
10088
|
+
json4(annotate(review.command("show"), { effects: LOCAL_READ })).description("one proposal with its titles, signals and the text around each piece of evidence").argument("<id>", "the proposal's id, as review lists it: 17070, fact:512, memory:88, link:17, payment:4, close:Q-15").option("--brief", "only references and their titles, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the evidence, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the evidence, at most 5", whole, 2).option("--compact", "one line, as review prints it").action(async (id, given2) => {
|
|
8931
10089
|
const body = await withStore(env, async (store) => {
|
|
8932
10090
|
const shown2 = await showReview(store, env, id);
|
|
8933
10091
|
const window = {
|
|
8934
|
-
brief:
|
|
8935
|
-
before: Math.min(
|
|
8936
|
-
after: Math.min(
|
|
10092
|
+
brief: given2.brief === true,
|
|
10093
|
+
before: Math.min(given2.beforeN, 5),
|
|
10094
|
+
after: Math.min(given2.afterN, 5)
|
|
8937
10095
|
};
|
|
8938
10096
|
const evidence = await Promise.all(shown2.evidence.map(async (one2) => {
|
|
8939
10097
|
const sender = window.brief ? null : await senderOf(store, one2.ref);
|
|
@@ -8946,35 +10104,35 @@ var reviewCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
8946
10104
|
}));
|
|
8947
10105
|
return itemAnswer({ ...shown2, evidence });
|
|
8948
10106
|
});
|
|
8949
|
-
print(
|
|
10107
|
+
print(given2.json, body, void 0, given2.compact);
|
|
8950
10108
|
});
|
|
8951
10109
|
for (const name2 of ["confirm", "reject"]) {
|
|
8952
|
-
const command = byOption(
|
|
10110
|
+
const command = byOption(json4(annotate(review.command(name2), { effects: LOCAL_WRITE }))).description(name2 === "confirm" ? "confirm proposals by id or range (17070-17079,fact:500-502,17080/f1); each is decided on its own, so a refusal leaves the others decided. An agent decides only with --reason, never its own or a scan's" : "turn proposals down by id or range, with why; each is decided on its own").summary(name2 === "confirm" ? "confirm proposals by id or range; each on its own" : "turn proposals down, with why").argument("<ids...>", name2 === "confirm" ? "ids or ranges as review lists them; 17080/f1 accepts that finding and rejects the batch's others" : "ids or ranges as review lists them; a batch is turned down whole");
|
|
8953
10111
|
if (name2 === "confirm")
|
|
8954
10112
|
command.option("--reason <text>", "why, in a few words; required when an agent decides");
|
|
8955
10113
|
else
|
|
8956
10114
|
command.requiredOption("--reason <text>", "why it is turned down, in a few words");
|
|
8957
10115
|
command.option("--compact", "one line per decision");
|
|
8958
|
-
command.action(async (words,
|
|
10116
|
+
command.action(async (words, given2) => {
|
|
8959
10117
|
const ids = parseProposalIds(words);
|
|
8960
10118
|
const by = await deciderOf(command, env, {
|
|
8961
|
-
...
|
|
10119
|
+
...given2,
|
|
8962
10120
|
question: `${name2} ${ids.length} proposal${ids.length === 1 ? "" : "s"} as you, the owner?`
|
|
8963
10121
|
});
|
|
8964
|
-
const result = await withStore(env, (store) => reviewRegistry(store).decide(ids, decisionOf(name2 === "confirm", by,
|
|
10122
|
+
const result = await withStore(env, (store) => reviewRegistry(store).decide(ids, decisionOf(name2 === "confirm", by, given2.reason)));
|
|
8965
10123
|
const issues = result.refused.map((one2) => ({
|
|
8966
10124
|
code: one2.code,
|
|
8967
10125
|
source: one2.id,
|
|
8968
10126
|
...one2.reason.includes(".") ? { reason: one2.reason } : {}
|
|
8969
10127
|
}));
|
|
8970
|
-
print(
|
|
10128
|
+
print(given2.json, itemAnswer(result, issues.length ? { meta: { complete: false, issues } } : void 0), decidedText(result), given2.compact);
|
|
8971
10129
|
});
|
|
8972
10130
|
}
|
|
8973
10131
|
reviewAgendaCommand(review, print, streams, env);
|
|
8974
|
-
|
|
8975
|
-
const since = sinceOf(
|
|
10132
|
+
json4(answerEntity(annotate(review.command("status"), { effects: LOCAL_READ }), "review_status", REVIEW_STATUS)).summary("since yesterday: new mail, what is owed and waiting, what agents proposed").description("the owner's daily look, with no model call: per mail account the threads with new mail, what you owe and wait for, and how far each agent's processing mark has read; then what was proposed and what waits").option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").action(async (given2) => {
|
|
10133
|
+
const since = sinceOf(given2.sinceTime);
|
|
8976
10134
|
const status = await withStore(env, (store) => reviewStatus(store, env, since));
|
|
8977
|
-
print(
|
|
10135
|
+
print(given2.json, itemAnswer(status), reviewStatusText(status));
|
|
8978
10136
|
});
|
|
8979
10137
|
}, "reviewCommand");
|
|
8980
10138
|
|
|
@@ -8988,10 +10146,10 @@ var embedPerRun = /* @__PURE__ */ __name((env = process.env) => {
|
|
|
8988
10146
|
return Math.max(8, Math.min(EMBED_PER_RUN, Math.round(EMBED_PER_RUN * ratio)));
|
|
8989
10147
|
}, "embedPerRun");
|
|
8990
10148
|
var missingModel = /* @__PURE__ */ __name((error, env) => {
|
|
8991
|
-
const
|
|
8992
|
-
const id = typeof
|
|
8993
|
-
const
|
|
8994
|
-
return `the ${id} model is not downloaded \u2014 memo models download ${id}${
|
|
10149
|
+
const named5 = isCliError(error) ? error.details.model : void 0;
|
|
10150
|
+
const id = typeof named5 === "string" ? named5 : chosenTextModel(env).id;
|
|
10151
|
+
const terms2 = textModels(env).find((model) => model.id === id)?.terms;
|
|
10152
|
+
return `the ${id} model is not downloaded \u2014 memo models download ${id}${terms2 ? " --accept-terms" : ""}`;
|
|
8995
10153
|
}, "missingModel");
|
|
8996
10154
|
var isMissingModel = /* @__PURE__ */ __name((error) => isCliError(error) && error.details.reason === "model.not-downloaded", "isMissingModel");
|
|
8997
10155
|
var reportOf = /* @__PURE__ */ __name((run) => {
|
|
@@ -9023,18 +10181,18 @@ var reportOf = /* @__PURE__ */ __name((run) => {
|
|
|
9023
10181
|
...run.reason === void 0 ? {} : { reason: run.reason }
|
|
9024
10182
|
};
|
|
9025
10183
|
}, "reportOf");
|
|
9026
|
-
var combinedEnrichment = /* @__PURE__ */ __name((...
|
|
9027
|
-
const present2 =
|
|
10184
|
+
var combinedEnrichment = /* @__PURE__ */ __name((...parts2) => {
|
|
10185
|
+
const present2 = parts2.filter((part) => part !== void 0);
|
|
9028
10186
|
if (present2.length === 0)
|
|
9029
10187
|
return void 0;
|
|
9030
10188
|
const rank = { done: 0, stopped: 1, failed: 2 };
|
|
9031
10189
|
const worst = present2.reduce((a, b) => rank[b.status] > rank[a.status] ? b : a);
|
|
9032
|
-
const
|
|
10190
|
+
const named5 = present2.find((part) => part.provider !== void 0);
|
|
9033
10191
|
const costs = present2.map((part) => part.costUsd);
|
|
9034
10192
|
return {
|
|
9035
10193
|
status: worst.status,
|
|
9036
|
-
...
|
|
9037
|
-
...
|
|
10194
|
+
...named5?.provider === void 0 ? {} : { provider: named5.provider },
|
|
10195
|
+
...named5?.model === void 0 ? {} : { model: named5.model },
|
|
9038
10196
|
sent: present2.reduce((sum, part) => sum + part.sent, 0),
|
|
9039
10197
|
enriched: present2.reduce((sum, part) => sum + part.enriched, 0),
|
|
9040
10198
|
failed: present2.reduce((sum, part) => sum + part.failed, 0),
|
|
@@ -9098,10 +10256,10 @@ var embedMailChunks = /* @__PURE__ */ __name(async (store, { embed = true, env,
|
|
|
9098
10256
|
|
|
9099
10257
|
// dist/progress.js
|
|
9100
10258
|
var EVERY_MS = 500;
|
|
9101
|
-
var
|
|
10259
|
+
var progressLine2 = /* @__PURE__ */ __name((diagnostic, json5, { step, unit, label }) => {
|
|
9102
10260
|
let last = Number.NEGATIVE_INFINITY;
|
|
9103
10261
|
return (done, total) => {
|
|
9104
|
-
if (!
|
|
10262
|
+
if (!json5)
|
|
9105
10263
|
return;
|
|
9106
10264
|
const now = Date.now();
|
|
9107
10265
|
if (done !== total && now - last < EVERY_MS)
|
|
@@ -9228,7 +10386,7 @@ var syncCommand = /* @__PURE__ */ __name((program, streams, env, signal, keyring
|
|
|
9228
10386
|
const skip = options.ignore ?? [];
|
|
9229
10387
|
for (const folder of folders)
|
|
9230
10388
|
await attempt(`notes ${folder.path}`, async () => {
|
|
9231
|
-
const onFile =
|
|
10389
|
+
const onFile = progressLine2(streams.diagnostic, Boolean(options.json), {
|
|
9232
10390
|
step: "notes",
|
|
9233
10391
|
unit: "files",
|
|
9234
10392
|
label: folder.id
|
|
@@ -9395,20 +10553,20 @@ var mailTriageInput = /* @__PURE__ */ __name((mailboxes) => async (schedule, run
|
|
|
9395
10553
|
if (!holder)
|
|
9396
10554
|
return void 0;
|
|
9397
10555
|
const skill2 = await run(["skill", "show", SKILL]);
|
|
9398
|
-
const
|
|
10556
|
+
const parts2 = [PREAMBLE, "# The skill", skill2.trim(), "# The review"];
|
|
9399
10557
|
const separator = "\n\n";
|
|
9400
|
-
let used =
|
|
10558
|
+
let used = parts2.join(separator).length + separator.length * 2;
|
|
9401
10559
|
let alone = true;
|
|
9402
10560
|
for (const address of await mailboxes()) {
|
|
9403
10561
|
const source = `email:${address}`;
|
|
9404
10562
|
const review = JSON.parse(await run(["mail", "review", "--holder", holder, "--source", source, `--json=${FIELDS}`]));
|
|
9405
10563
|
const block = mailboxBlock(source, review, INPUT_BUDGET - used - separator.length, alone);
|
|
9406
|
-
|
|
10564
|
+
parts2.push(block);
|
|
9407
10565
|
used += block.length + separator.length;
|
|
9408
10566
|
if (block.includes("\nemails, one JSON per line:"))
|
|
9409
10567
|
alone = false;
|
|
9410
10568
|
}
|
|
9411
|
-
return [...
|
|
10569
|
+
return [...parts2, ""].join(separator);
|
|
9412
10570
|
}, "mailTriageInput");
|
|
9413
10571
|
|
|
9414
10572
|
// dist/schedule/command.js
|
|
@@ -9454,7 +10612,7 @@ var BRIEF = ["ref", "chat_title", "timestamp", "sender_name", "excerpt", "score"
|
|
|
9454
10612
|
var briefHit = /* @__PURE__ */ __name((hit) => Object.fromEntries(BRIEF.flatMap((key) => hit[key] === void 0 || hit[key] === null ? [] : [[key, hit[key]]])), "briefHit");
|
|
9455
10613
|
|
|
9456
10614
|
// dist/search/answers.js
|
|
9457
|
-
var
|
|
10615
|
+
var named4 = /* @__PURE__ */ __name((accounts) => [
|
|
9458
10616
|
...new Set(accounts.map(({ provider, account: account2 }) => `${provider}:${account2}`))
|
|
9459
10617
|
], "named");
|
|
9460
10618
|
var metaOf2 = /* @__PURE__ */ __name((accounts, skipped = [], heldInPart = false) => {
|
|
@@ -9465,7 +10623,7 @@ var metaOf2 = /* @__PURE__ */ __name((accounts, skipped = [], heldInPart = false
|
|
|
9465
10623
|
source: one2.source ?? one2.resource ?? ""
|
|
9466
10624
|
}));
|
|
9467
10625
|
return {
|
|
9468
|
-
accounts:
|
|
10626
|
+
accounts: named4(accounts),
|
|
9469
10627
|
...heldInPart ? { complete: false } : {},
|
|
9470
10628
|
...issues.length ? { issues } : {}
|
|
9471
10629
|
};
|
|
@@ -9604,10 +10762,11 @@ var peopleText = /* @__PURE__ */ __name((found) => found.items.map((hit) => [
|
|
|
9604
10762
|
].join("\n")).join("\n") || "nobody found", "peopleText");
|
|
9605
10763
|
|
|
9606
10764
|
// dist/search/command.js
|
|
10765
|
+
var ONLY = ["messages", "mail", "notes", "events", "crm", "business"];
|
|
9607
10766
|
var onlyOf2 = /* @__PURE__ */ __name((value) => {
|
|
9608
10767
|
const selected = value.split(",").map((part) => part.trim());
|
|
9609
|
-
if (!selected.length || selected.some((part) => !
|
|
9610
|
-
throw new InvalidArgumentError(
|
|
10768
|
+
if (!selected.length || selected.some((part) => !ONLY.includes(part)))
|
|
10769
|
+
throw new InvalidArgumentError(`choose ${ONLY.join(",")}, separated by commas`);
|
|
9611
10770
|
return [...new Set(selected)];
|
|
9612
10771
|
}, "onlyOf");
|
|
9613
10772
|
var levelOf = /* @__PURE__ */ __name(({ brief, full }) => {
|
|
@@ -9626,9 +10785,11 @@ var searchCommandDefinition = /* @__PURE__ */ __name((program, streams, env) =>
|
|
|
9626
10785
|
throw new InvalidArgumentError("at most 100");
|
|
9627
10786
|
return limit;
|
|
9628
10787
|
}, 20).option("--exact", "words as written; skip meaning search").option("--timezone <zone>", "IANA timezone for calendar date boundaries").option("--json", "print JSON; --json=id,title keeps only those fields"), "queryOptions");
|
|
9629
|
-
queryOptions(annotate(group.command("all"), { effects: LOCAL_READ, output: { entity: "hit" } }).description("messages, mail, notes
|
|
10788
|
+
queryOptions(annotate(group.command("all"), { effects: LOCAL_READ, output: { entity: "hit" } }).description("messages, mail, notes, calendar events, deals, leads and business data ranked together; not people, memories, projects or decisions. A kind you know reads better with its own search, with all its fields").summary("messages, mail, notes and calendar events ranked together")).option("--only <resources>", `${ONLY.join(",")}, separated by commas`, onlyOf2).option("--plain-order", "best first by the words alone, without moving mail from suspicious senders down").option("--project <project>", PROJECT_ORDER_HELP).addHelpText("after", `
|
|
9630
10789
|
content: narrows a search to the text of files, transcript: to voice transcripts, filename: to file names \u2014 memo search all 'content:invoice'.
|
|
9631
10790
|
Calendar events come from every calendar gcal stored; an event's title, description and place are written by whoever sent the invitation.
|
|
10791
|
+
crm finds deals and leads by the words of their title only.
|
|
10792
|
+
business finds invoices, payments, orders, contracts, subscriptions, products and wallets by the words of their numbers and names.
|
|
9632
10793
|
--json: the list is items, each a hit as in tg search all: ref, kind, title, timestamp, excerpt.`).action(async (words, options, command) => {
|
|
9633
10794
|
const gate = lanesFor(command, options.only);
|
|
9634
10795
|
const answer = await withStore(env, async (store) => {
|
|
@@ -9637,6 +10798,7 @@ Calendar events come from every calendar gcal stored; an event's title, descript
|
|
|
9637
10798
|
limit: options.limit,
|
|
9638
10799
|
...gate.only === void 0 ? {} : { only: gate.only },
|
|
9639
10800
|
...gate.shows === void 0 ? {} : { shows: gate.shows },
|
|
10801
|
+
...gate.crmKinds === void 0 ? {} : { crmKinds: gate.crmKinds },
|
|
9640
10802
|
...options.exact ? { exact: true } : {},
|
|
9641
10803
|
...options.plainOrder ? { plainOrder: true } : {},
|
|
9642
10804
|
...options.timezone === void 0 ? {} : { timezone: options.timezone }
|
|
@@ -9715,8 +10877,8 @@ For an agent: read with --compact, one line per hit with its reference. Never wr
|
|
|
9715
10877
|
for (const { source, reason } of answer.skipped)
|
|
9716
10878
|
streams.diagnostic(`${source} not searched: ${reason}
|
|
9717
10879
|
`);
|
|
9718
|
-
const { limit, page, json:
|
|
9719
|
-
print(
|
|
10880
|
+
const { limit, page, json: json5, ...rest } = options;
|
|
10881
|
+
print(json5, notesAnswer(answer, limit, page, { query: words.join(" "), ...rest }), searchText(answer, (page - 1) * limit));
|
|
9720
10882
|
});
|
|
9721
10883
|
searchMemoriesCommand(group, streams, env);
|
|
9722
10884
|
annotate(group.command("people"), { effects: LOCAL_READ, output: { entity: "person" } }).description("people whose name, username or alias holds every word, in every account unless --source narrows it; each with its person:<id> for --contact and its identities").summary("people by name across every account").argument("<name...>", "parts of the name, username or alias; case and accents do not matter").option("--source <accounts>", ACCOUNTS_HELP).option("--limit <n>", "most people, at most 100", (value) => {
|
|
@@ -9754,16 +10916,39 @@ var LOCAL_OPENS = {
|
|
|
9754
10916
|
task: ["memo", "tasks", "show"],
|
|
9755
10917
|
fact: ["memo", "facts", "show"],
|
|
9756
10918
|
memory: ["memo", "memories", "show"],
|
|
9757
|
-
message: ["memo", "messages", "show"]
|
|
10919
|
+
message: ["memo", "messages", "show"],
|
|
10920
|
+
invoice: ["memo", "invoices", "show"],
|
|
10921
|
+
payment: ["memo", "payments", "show"],
|
|
10922
|
+
order: ["memo", "orders", "show"],
|
|
10923
|
+
deal: ["memo", "deals", "show"],
|
|
10924
|
+
lead: ["memo", "leads", "show"],
|
|
10925
|
+
pipeline: ["memo", "pipelines", "show"],
|
|
10926
|
+
product: ["memo", "products", "show"],
|
|
10927
|
+
contract: ["memo", "contracts", "show"],
|
|
10928
|
+
subscription: ["memo", "subscriptions", "show"],
|
|
10929
|
+
wallet: ["memo", "wallets", "show"],
|
|
10930
|
+
transaction: ["memo", "transactions", "show"],
|
|
10931
|
+
event: ["memo", "events", "show"]
|
|
9758
10932
|
};
|
|
10933
|
+
var openKeyOf = /* @__PURE__ */ __name((kind) => LOCAL_OPENS[kind]?.slice(1).join("."), "openKeyOf");
|
|
10934
|
+
var refuseDenied = /* @__PURE__ */ __name((command, summaries) => {
|
|
10935
|
+
for (const { ref, kind } of summaries) {
|
|
10936
|
+
const key = openKeyOf(kind);
|
|
10937
|
+
if (key !== void 0 && grantedLevel(command, key) === "deny")
|
|
10938
|
+
throw new CliError("permission_error", `${ref}: memo's MCP server denies ${key}`, {
|
|
10939
|
+
reason: "access.denied",
|
|
10940
|
+
permission: key
|
|
10941
|
+
});
|
|
10942
|
+
}
|
|
10943
|
+
}, "refuseDenied");
|
|
9759
10944
|
var OTHERS = /* @__PURE__ */ new Set(["message", "chat", "contact", "email", "email_thread", "document", "event", "meeting", "bot"]);
|
|
9760
10945
|
var ACCOUNT_KEY = /^[a-z][a-z-]*:\S+$/;
|
|
9761
|
-
var taskOpen = /* @__PURE__ */ __name((summary,
|
|
9762
|
-
if (summary.kind !== "task" ||
|
|
9763
|
-
return
|
|
9764
|
-
const argv = [...
|
|
10946
|
+
var taskOpen = /* @__PURE__ */ __name((summary, open2) => {
|
|
10947
|
+
if (summary.kind !== "task" || open2.argv === null)
|
|
10948
|
+
return open2;
|
|
10949
|
+
const argv = [...open2.argv.slice(0, -1), summary.ref.slice("task:".length)];
|
|
9765
10950
|
return {
|
|
9766
|
-
...
|
|
10951
|
+
...open2,
|
|
9767
10952
|
argv: summary.in !== null && ACCOUNT_KEY.test(summary.in) ? [...argv, "--source", summary.in] : argv
|
|
9768
10953
|
};
|
|
9769
10954
|
}, "taskOpen");
|
|
@@ -9773,7 +10958,7 @@ var profilesFor = /* @__PURE__ */ __name((env) => (provider, account2) => {
|
|
|
9773
10958
|
return { why: `${provider} names no account here`, profiles: [] };
|
|
9774
10959
|
return profileFor(provider, account2, env) ?? { why: `memo cannot read which profiles ${provider} has`, profiles: [] };
|
|
9775
10960
|
}, "profilesFor");
|
|
9776
|
-
var showReferences = /* @__PURE__ */ __name(async (store, env, texts) => {
|
|
10961
|
+
var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) => {
|
|
9777
10962
|
if (texts.length > MAX_REFS)
|
|
9778
10963
|
throw new CliError("validation_error", `at most ${MAX_REFS} references at once`);
|
|
9779
10964
|
for (const text3 of texts)
|
|
@@ -9781,8 +10966,10 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts) => {
|
|
|
9781
10966
|
for (const text3 of texts)
|
|
9782
10967
|
parseReference(text3);
|
|
9783
10968
|
const summaries = await store.refs.summaries(texts);
|
|
10969
|
+
if (command !== void 0)
|
|
10970
|
+
refuseDenied(command, [...summaries.values()]);
|
|
9784
10971
|
const ports = { profilesFor: profilesFor(env), local: LOCAL_OPENS };
|
|
9785
|
-
|
|
10972
|
+
const shown2 = texts.map((text3) => {
|
|
9786
10973
|
const summary = summaries.get(text3) ?? {
|
|
9787
10974
|
ref: text3,
|
|
9788
10975
|
kind: "unknown",
|
|
@@ -9794,7 +10981,7 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts) => {
|
|
|
9794
10981
|
tool: null,
|
|
9795
10982
|
state: "unavailable"
|
|
9796
10983
|
};
|
|
9797
|
-
const
|
|
10984
|
+
const open2 = taskOpen(summary, openOf(summary, ports));
|
|
9798
10985
|
return {
|
|
9799
10986
|
ref: summary.ref,
|
|
9800
10987
|
kind: summary.kind,
|
|
@@ -9802,24 +10989,36 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts) => {
|
|
|
9802
10989
|
in: summary.in,
|
|
9803
10990
|
at: summary.at,
|
|
9804
10991
|
provider: summary.provider,
|
|
9805
|
-
tool: summary.tool ??
|
|
10992
|
+
tool: summary.tool ?? open2.argv?.[0] ?? null,
|
|
9806
10993
|
state: summary.state,
|
|
9807
|
-
open: { ...
|
|
10994
|
+
open: { ...open2, line: open2.argv?.map(shellWord).join(" ") ?? null },
|
|
9808
10995
|
...OTHERS.has(summary.kind) ? { untrusted: ["title", "in"] } : {}
|
|
9809
10996
|
};
|
|
9810
10997
|
});
|
|
10998
|
+
const withRecords = command === void 0 || !recordsHidden(command);
|
|
10999
|
+
for (const one2 of shown2) {
|
|
11000
|
+
const entity = one2.state === "available" ? await readSourced(store, one2.kind, one2.ref) : void 0;
|
|
11001
|
+
if (entity === void 0)
|
|
11002
|
+
continue;
|
|
11003
|
+
if (withRecords)
|
|
11004
|
+
one2.sources = await sourcesOf(store, entity);
|
|
11005
|
+
if (imported(entity))
|
|
11006
|
+
one2.untrusted = ["title"];
|
|
11007
|
+
}
|
|
11008
|
+
return shown2;
|
|
9811
11009
|
}, "showReferences");
|
|
9812
11010
|
var minute2 = /* @__PURE__ */ __name((at) => at === null ? null : at.slice(0, 16).replace("T", " "), "minute");
|
|
9813
11011
|
var blockOf = /* @__PURE__ */ __name((one2) => [
|
|
9814
11012
|
`${one2.ref} ${one2.title ?? ""}`.trimEnd(),
|
|
9815
11013
|
` ${[one2.kind, one2.in, one2.state, minute2(one2.at)].filter((part) => part !== null).join(" \xB7 ")}`,
|
|
9816
11014
|
` open: ${one2.open.line ?? "none"}`,
|
|
9817
|
-
...one2.open.why === null ? [] : [` ${one2.open.why}`]
|
|
11015
|
+
...one2.open.why === null ? [] : [` ${one2.open.why}`],
|
|
11016
|
+
...one2.sources === void 0 ? [] : sourcesText(one2.ref, one2.sources)
|
|
9818
11017
|
].join("\n"), "blockOf");
|
|
9819
11018
|
var showCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
9820
11019
|
const { print } = answers(program, streams, env);
|
|
9821
|
-
annotate(program.command("show"), { effects: LOCAL_READ, partial: true }).description("what any reference names, and the command that opens it").argument("<ref...>", "1 to 100 references any WireCat CLI printed: chat:, msg:, note:, document:, person:, task:\u2026").option("--json", "print JSON; --json=ref,title keeps only those fields").action(async (refs, options) => {
|
|
9822
|
-
const items = await withStore(env, (store) => showReferences(store, env, refs));
|
|
11020
|
+
annotate(program.command("show"), { effects: LOCAL_READ, partial: true }).description("what any reference names, and the command that opens it").argument("<ref...>", "1 to 100 references any WireCat CLI printed: chat:, msg:, note:, document:, person:, task:\u2026").option("--json", "print JSON; --json=ref,title keeps only those fields").action(async (refs, options, command) => {
|
|
11021
|
+
const items = await withStore(env, (store) => showReferences(store, env, refs, command));
|
|
9823
11022
|
const gone = items.filter((one2) => one2.state !== "available");
|
|
9824
11023
|
const body = wholeList("show", items);
|
|
9825
11024
|
if (gone.length > 0) {
|
|
@@ -9908,7 +11107,7 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9908
11107
|
const tags = program.command("tags").description("your labels on stored sources and folders or threads");
|
|
9909
11108
|
const { print } = answers(program, streams, env);
|
|
9910
11109
|
const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
|
|
9911
|
-
const mutate = /* @__PURE__ */ __name(async (operation,
|
|
11110
|
+
const mutate = /* @__PURE__ */ __name(async (operation, given2, { account: account2, ...options }) => {
|
|
9912
11111
|
const value = writeAccountOf({ account: account2 }, warn);
|
|
9913
11112
|
const scoped3 = /* @__PURE__ */ __name(async (store) => value === void 0 ? {} : oneAccountOf(store, env, value, "--account"), "scoped");
|
|
9914
11113
|
const target = options.note !== void 0 ? options.note.startsWith("document:") ? { type: "document", id: options.note.slice("document:".length) } : { type: "note", id: options.note.replace(/^note:/, "") } : options.person !== void 0 ? { type: "person", id: options.person.replace(/^person:/, "") } : options.organization !== void 0 ? { type: "organization", id: options.organization.replace(/^organization:/, "") } : options.project !== void 0 ? { type: "project", id: options.project } : options.task !== void 0 ? { type: "task", id: options.task.replace(/^task:/, "") } : options.folder !== void 0 ? { type: "folder", id: options.folder, path: options.subfolder ?? null } : void 0;
|
|
@@ -9924,7 +11123,7 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9924
11123
|
throw new CliError("not_found", `no folder of notes ${target.id}`, { reason: "folder.not-found" });
|
|
9925
11124
|
target.id = id;
|
|
9926
11125
|
}
|
|
9927
|
-
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(null, target,
|
|
11126
|
+
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(null, target, given2);
|
|
9928
11127
|
print(options.json, itemAnswer({ target, [operation === "add" ? "added" : "removed"]: changed }), `${operation}: ${changed.join(", ") || "no labels changed"}`);
|
|
9929
11128
|
});
|
|
9930
11129
|
return;
|
|
@@ -9932,14 +11131,14 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9932
11131
|
if (options.contact !== void 0 || options.meeting !== void 0) {
|
|
9933
11132
|
await withStore(env, async (store) => {
|
|
9934
11133
|
const { key, target: target2 } = await selectTarget(store, { ...options, ...await scoped3(store) });
|
|
9935
|
-
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(key, target2,
|
|
11134
|
+
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(key, target2, given2);
|
|
9936
11135
|
print(options.json, itemAnswer({ ...key, target: target2, [operation === "add" ? "added" : "removed"]: changed }), `${operation}: ${changed.join(", ") || "no labels changed"}`);
|
|
9937
11136
|
});
|
|
9938
11137
|
return;
|
|
9939
11138
|
}
|
|
9940
11139
|
if (options.message !== void 0 && value !== void 0)
|
|
9941
11140
|
throw new CliError("validation_error", "a message locator names its account and chat \u2014 use --message alone");
|
|
9942
|
-
const labels = [...new Set(
|
|
11141
|
+
const labels = [...new Set(given2.map(normalizeTag))];
|
|
9943
11142
|
await withStore(env, async (store) => {
|
|
9944
11143
|
const selected = sourceTarget({ ...options, ...await scoped3(store) });
|
|
9945
11144
|
const changed = await (operation === "add" ? store.tags.addTags : store.tags.removeTags)(selected.key, selected.target, labels);
|
|
@@ -9955,17 +11154,17 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9955
11154
|
});
|
|
9956
11155
|
}, "mutate");
|
|
9957
11156
|
for (const operation of ["add", "remove"])
|
|
9958
|
-
targetOptions(annotate(tags.command(operation), { effects: LOCAL_WRITE }).description(operation === "add" ? "put labels on one source" : "remove labels from one source")).action((
|
|
11157
|
+
targetOptions(annotate(tags.command(operation), { effects: LOCAL_WRITE }).description(operation === "add" ? "put labels on one source" : "remove labels from one source")).action((given2, options) => mutate(operation, given2, options));
|
|
9959
11158
|
const tagsList = withQuery(annotate(tags.command("list"), { effects: LOCAL_READ, output: { entity: "source_tag" } }).description("list source labels, of every account or of the ones --source names"), TAG_QUERY);
|
|
9960
|
-
sourceOptions(tagsList, `only these accounts (default: every one): ${ACCOUNTS_HELP}`).option("--limit <n>", "most labels to show", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words,
|
|
9961
|
-
const
|
|
9962
|
-
const tag =
|
|
9963
|
-
const value = sourceOf(
|
|
11159
|
+
sourceOptions(tagsList, `only these accounts (default: every one): ${ACCOUNTS_HELP}`).option("--limit <n>", "most labels to show", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, given2) => {
|
|
11160
|
+
const terms2 = queryTerms(words, TAG_QUERY, "tags list");
|
|
11161
|
+
const tag = terms2.get("tag");
|
|
11162
|
+
const value = sourceOf(given2, warn);
|
|
9964
11163
|
const options = {
|
|
9965
|
-
limit:
|
|
9966
|
-
...
|
|
11164
|
+
limit: given2.limit,
|
|
11165
|
+
...given2.json === void 0 ? {} : { json: given2.json },
|
|
9967
11166
|
...tag === void 0 ? {} : { tag: normalizeTag(tag) },
|
|
9968
|
-
...
|
|
11167
|
+
...terms2.has("type") ? { type: terms2.get("type") } : {}
|
|
9969
11168
|
};
|
|
9970
11169
|
await withStore(env, async (store) => {
|
|
9971
11170
|
const keys = value === void 0 ? await store.accounts.accounts() : await accountsOf(store, env, value);
|
|
@@ -10040,8 +11239,8 @@ var requireAccount = /* @__PURE__ */ __name((env, warn) => async (_, command) =>
|
|
|
10040
11239
|
return;
|
|
10041
11240
|
if (["show", "update", "claim", "release"].includes(command.name()) && first !== void 0 && await store.tasks.projectTask(first))
|
|
10042
11241
|
return;
|
|
10043
|
-
const
|
|
10044
|
-
throw new CliError("validation_error", `give ${option} \u2014 the stored accounts: ${
|
|
11242
|
+
const listed2 = (await store.accounts.accounts()).map((key) => `${option} ${key.provider}:${key.account}`).join("; ");
|
|
11243
|
+
throw new CliError("validation_error", `give ${option} \u2014 the stored accounts: ${listed2 || "none yet"}`);
|
|
10045
11244
|
} finally {
|
|
10046
11245
|
await store.close();
|
|
10047
11246
|
}
|
|
@@ -10065,7 +11264,7 @@ var sharedTaskCommands = /* @__PURE__ */ __name((program, tasks, streams, env) =
|
|
|
10065
11264
|
|
|
10066
11265
|
// dist/tasks/tasks.js
|
|
10067
11266
|
var personRef = /* @__PURE__ */ __name((person) => person.startsWith("person:") ? person : `person:${person}`, "personRef");
|
|
10068
|
-
var
|
|
11267
|
+
var fieldsOf4 = /* @__PURE__ */ __name((options) => ({
|
|
10069
11268
|
...options.title === void 0 ? {} : { title: options.title },
|
|
10070
11269
|
...options.priority === void 0 ? {} : { priority: options.priority },
|
|
10071
11270
|
...options.parent === void 0 ? {} : { parent: options.parent },
|
|
@@ -10089,7 +11288,7 @@ var addToProject = /* @__PURE__ */ __name(async (store, env, options) => {
|
|
|
10089
11288
|
project: await canonicalProject(store, options.project),
|
|
10090
11289
|
title: options.title,
|
|
10091
11290
|
type,
|
|
10092
|
-
...
|
|
11291
|
+
...fieldsOf4(options),
|
|
10093
11292
|
...options.due === void 0 || options.due === "none" ? {} : { dueAt: options.due },
|
|
10094
11293
|
...options.status === void 0 ? {} : { status: options.status },
|
|
10095
11294
|
...options.agent === void 0 ? {} : { agent: options.agent }
|
|
@@ -10124,7 +11323,7 @@ var addFromSource = /* @__PURE__ */ __name(async (store, env, source, options) =
|
|
|
10124
11323
|
...options.into === void 0 ? {} : { attach: options.into },
|
|
10125
11324
|
...options.new ? { new: true } : {}
|
|
10126
11325
|
}, author);
|
|
10127
|
-
const fields =
|
|
11326
|
+
const fields = fieldsOf4(options);
|
|
10128
11327
|
if (Object.keys(fields).length === 0 && !options.assignee?.length)
|
|
10129
11328
|
return answer;
|
|
10130
11329
|
await store.tasks.edit(answer.task.id, fields, "owner");
|
|
@@ -10153,7 +11352,7 @@ var closeTask = /* @__PURE__ */ __name(async (store, env, id, options) => {
|
|
|
10153
11352
|
});
|
|
10154
11353
|
}, "closeTask");
|
|
10155
11354
|
var updateTask = /* @__PURE__ */ __name(async (store, env, id, options) => {
|
|
10156
|
-
const fields =
|
|
11355
|
+
const fields = fieldsOf4(options);
|
|
10157
11356
|
const times = {
|
|
10158
11357
|
...options.due === void 0 ? {} : { dueAt: options.due },
|
|
10159
11358
|
...options.remindTime === void 0 ? {} : { nextCheckAt: options.remindTime }
|
|
@@ -10195,15 +11394,15 @@ var moveTask = /* @__PURE__ */ __name((store, env, id, options) => {
|
|
|
10195
11394
|
var commentTask = /* @__PURE__ */ __name((store, env, id, text3) => store.tasks.comment(id, text3, authorOf(env)), "commentTask");
|
|
10196
11395
|
var taskHistory = /* @__PURE__ */ __name(async (store, id) => {
|
|
10197
11396
|
const owner = (await store.people.owner())?.uid;
|
|
10198
|
-
return (await store.tasks.events(id)).map((
|
|
10199
|
-
at:
|
|
10200
|
-
kind:
|
|
10201
|
-
by:
|
|
10202
|
-
ref: `${
|
|
10203
|
-
name:
|
|
10204
|
-
owner:
|
|
11397
|
+
return (await store.tasks.events(id)).map((event2) => ({
|
|
11398
|
+
at: event2.at,
|
|
11399
|
+
kind: event2.kind,
|
|
11400
|
+
by: event2.actor && {
|
|
11401
|
+
ref: `${event2.actor.type}:${event2.actor.id}`,
|
|
11402
|
+
name: event2.actor.name,
|
|
11403
|
+
owner: event2.actor.type === "person" && String(event2.actor.id) === String(owner)
|
|
10205
11404
|
},
|
|
10206
|
-
changes:
|
|
11405
|
+
changes: event2.changes
|
|
10207
11406
|
}));
|
|
10208
11407
|
}, "taskHistory");
|
|
10209
11408
|
|
|
@@ -10282,11 +11481,11 @@ var tasksCommand2 = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
10282
11481
|
const description = command.options.find((option) => option.long === "--description");
|
|
10283
11482
|
if (description)
|
|
10284
11483
|
description.description = "the detail, in Markdown; none clears it";
|
|
10285
|
-
command.action(async (id,
|
|
10286
|
-
const raw =
|
|
11484
|
+
command.action(async (id, given2) => {
|
|
11485
|
+
const raw = given2;
|
|
10287
11486
|
const options = {
|
|
10288
|
-
...
|
|
10289
|
-
...typeof
|
|
11487
|
+
...given2,
|
|
11488
|
+
...typeof given2.description === "string" && given2.description.trim().toLowerCase() === "none" ? { description: null } : {},
|
|
10290
11489
|
priority: raw.priority === "none" ? null : raw.priority,
|
|
10291
11490
|
parent: raw.parent === null || raw.parent === "none" ? null : raw.parent,
|
|
10292
11491
|
due: raw.due === "none" ? null : raw.due,
|
|
@@ -10337,10 +11536,10 @@ var VOCABULARY_QUERY = {
|
|
|
10337
11536
|
]
|
|
10338
11537
|
};
|
|
10339
11538
|
var vocabularyFilter = /* @__PURE__ */ __name((query, command) => {
|
|
10340
|
-
const
|
|
11539
|
+
const terms2 = queryTerms(query, VOCABULARY_QUERY, command);
|
|
10341
11540
|
return {
|
|
10342
|
-
...
|
|
10343
|
-
...
|
|
11541
|
+
...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
|
|
11542
|
+
...terms2.has("scope") ? { scope: terms2.get("scope") } : {}
|
|
10344
11543
|
};
|
|
10345
11544
|
}, "vocabularyFilter");
|
|
10346
11545
|
|
|
@@ -10520,6 +11719,10 @@ var OWN_ENTITIES = entityFields({
|
|
|
10520
11719
|
"fulfilled_date",
|
|
10521
11720
|
"invoice",
|
|
10522
11721
|
"payment",
|
|
11722
|
+
"direction",
|
|
11723
|
+
"contract",
|
|
11724
|
+
"deal",
|
|
11725
|
+
"lines",
|
|
10523
11726
|
"review",
|
|
10524
11727
|
"author",
|
|
10525
11728
|
"model",
|
|
@@ -10574,6 +11777,8 @@ var OWN_ENTITIES = entityFields({
|
|
|
10574
11777
|
"reference",
|
|
10575
11778
|
"allocated",
|
|
10576
11779
|
"unallocated",
|
|
11780
|
+
"refund_of",
|
|
11781
|
+
"subscription",
|
|
10577
11782
|
"evidence",
|
|
10578
11783
|
"review",
|
|
10579
11784
|
"author",
|
|
@@ -10596,7 +11801,9 @@ var OWN_ENTITIES = entityFields({
|
|
|
10596
11801
|
"revision",
|
|
10597
11802
|
"fingerprint",
|
|
10598
11803
|
"relations",
|
|
11804
|
+
"incoming",
|
|
10599
11805
|
"entity",
|
|
11806
|
+
"created_entity",
|
|
10600
11807
|
"flagged",
|
|
10601
11808
|
"batch_id",
|
|
10602
11809
|
"created_at",
|
|
@@ -10614,8 +11821,162 @@ var OWN_ENTITIES = entityFields({
|
|
|
10614
11821
|
"proposed",
|
|
10615
11822
|
"waiting",
|
|
10616
11823
|
"flagged",
|
|
10617
|
-
"
|
|
11824
|
+
"unmatched",
|
|
11825
|
+
"ignored",
|
|
11826
|
+
"vcard",
|
|
11827
|
+
"errors",
|
|
11828
|
+
"truncated"
|
|
11829
|
+
],
|
|
11830
|
+
product: [
|
|
11831
|
+
"id",
|
|
11832
|
+
"ref",
|
|
11833
|
+
"title",
|
|
11834
|
+
"kind",
|
|
11835
|
+
"name",
|
|
11836
|
+
"sku",
|
|
11837
|
+
"supplier",
|
|
11838
|
+
"unit",
|
|
11839
|
+
"unit_price",
|
|
11840
|
+
"currency",
|
|
11841
|
+
"description",
|
|
11842
|
+
"archived_date",
|
|
11843
|
+
"author",
|
|
11844
|
+
"model",
|
|
11845
|
+
"source",
|
|
11846
|
+
"created_at",
|
|
11847
|
+
"updated_at"
|
|
11848
|
+
],
|
|
11849
|
+
contract: [
|
|
11850
|
+
"id",
|
|
11851
|
+
"ref",
|
|
11852
|
+
"title",
|
|
11853
|
+
"name",
|
|
11854
|
+
"number",
|
|
11855
|
+
"kind",
|
|
11856
|
+
"status",
|
|
11857
|
+
"signed_date",
|
|
11858
|
+
"effective_date",
|
|
11859
|
+
"expiration_date",
|
|
11860
|
+
"auto_renew",
|
|
11861
|
+
"renewal",
|
|
11862
|
+
"notice_days",
|
|
11863
|
+
"notice_deadline",
|
|
11864
|
+
"terms",
|
|
11865
|
+
"value",
|
|
11866
|
+
"currency",
|
|
11867
|
+
"deal",
|
|
11868
|
+
"review",
|
|
11869
|
+
"author",
|
|
11870
|
+
"model",
|
|
11871
|
+
"confirmed_by",
|
|
11872
|
+
"source",
|
|
11873
|
+
"reason",
|
|
11874
|
+
"evidence",
|
|
11875
|
+
"project",
|
|
11876
|
+
"project_name",
|
|
11877
|
+
"created_at",
|
|
11878
|
+
"updated_at"
|
|
11879
|
+
],
|
|
11880
|
+
subscription: [
|
|
11881
|
+
"id",
|
|
11882
|
+
"ref",
|
|
11883
|
+
"title",
|
|
11884
|
+
"name",
|
|
11885
|
+
"direction",
|
|
11886
|
+
"supplier",
|
|
11887
|
+
"customer",
|
|
11888
|
+
"product",
|
|
11889
|
+
"contract",
|
|
11890
|
+
"status",
|
|
11891
|
+
"interval",
|
|
11892
|
+
"start_date",
|
|
11893
|
+
"trial_end_date",
|
|
11894
|
+
"next_renewal_date",
|
|
11895
|
+
"cancelled_date",
|
|
11896
|
+
"end_date",
|
|
11897
|
+
"current_price",
|
|
11898
|
+
"prices",
|
|
11899
|
+
"review",
|
|
11900
|
+
"author",
|
|
11901
|
+
"model",
|
|
11902
|
+
"confirmed_by",
|
|
11903
|
+
"source",
|
|
11904
|
+
"reason",
|
|
11905
|
+
"evidence",
|
|
11906
|
+
"project",
|
|
11907
|
+
"project_name",
|
|
11908
|
+
"created_at",
|
|
11909
|
+
"updated_at"
|
|
11910
|
+
],
|
|
11911
|
+
subscription_price: [
|
|
11912
|
+
"id",
|
|
11913
|
+
"ref",
|
|
11914
|
+
"title",
|
|
11915
|
+
"subscription",
|
|
11916
|
+
"amount",
|
|
11917
|
+
"currency",
|
|
11918
|
+
"effective_from",
|
|
11919
|
+
"review",
|
|
11920
|
+
"author",
|
|
11921
|
+
"reason",
|
|
11922
|
+
"project",
|
|
11923
|
+
"created_at"
|
|
11924
|
+
],
|
|
11925
|
+
wallet: [
|
|
11926
|
+
"id",
|
|
11927
|
+
"ref",
|
|
11928
|
+
"title",
|
|
11929
|
+
"name",
|
|
11930
|
+
"kind",
|
|
11931
|
+
"currency",
|
|
11932
|
+
"institution",
|
|
11933
|
+
"number_hint",
|
|
11934
|
+
"holder",
|
|
11935
|
+
"opening_balance",
|
|
11936
|
+
"opening_date",
|
|
11937
|
+
"closed_date",
|
|
11938
|
+
"balance",
|
|
11939
|
+
"until",
|
|
11940
|
+
"pending",
|
|
11941
|
+
"source_says",
|
|
11942
|
+
"author",
|
|
11943
|
+
"model",
|
|
11944
|
+
"source",
|
|
11945
|
+
"created_at",
|
|
11946
|
+
"updated_at"
|
|
11947
|
+
],
|
|
11948
|
+
transaction: [
|
|
11949
|
+
"id",
|
|
11950
|
+
"ref",
|
|
11951
|
+
"title",
|
|
11952
|
+
"wallet",
|
|
11953
|
+
"wallet_name",
|
|
11954
|
+
"direction",
|
|
11955
|
+
"amount",
|
|
11956
|
+
"currency",
|
|
11957
|
+
"status",
|
|
11958
|
+
"statement_date",
|
|
11959
|
+
"booked_date",
|
|
11960
|
+
"description",
|
|
11961
|
+
"counterparty_name",
|
|
11962
|
+
"counterparty",
|
|
11963
|
+
"reference",
|
|
11964
|
+
"payment",
|
|
11965
|
+
"splits",
|
|
11966
|
+
"uncategorized",
|
|
11967
|
+
"review",
|
|
11968
|
+
"author",
|
|
11969
|
+
"model",
|
|
11970
|
+
"confirmed_by",
|
|
11971
|
+
"source",
|
|
11972
|
+
"reason",
|
|
11973
|
+
"evidence",
|
|
11974
|
+
"project",
|
|
11975
|
+
"project_name",
|
|
11976
|
+
"created_at",
|
|
11977
|
+
"updated_at"
|
|
10618
11978
|
],
|
|
11979
|
+
records_match: ["linked", "created", "unmatched", "proposed", "errors", "truncated"],
|
|
10619
11980
|
payment_allocation: ["payment", "invoice", "amount", "currency", "created_at"]
|
|
10620
11981
|
});
|
|
10621
11982
|
var SKILL_TOPICS = [
|
|
@@ -10667,6 +12028,11 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
10667
12028
|
financeCommands(program, streams, env);
|
|
10668
12029
|
orderCommands(program, streams, env);
|
|
10669
12030
|
dealCommands(program, streams, env);
|
|
12031
|
+
productCommands(program, streams, env);
|
|
12032
|
+
contractCommands(program, streams, env);
|
|
12033
|
+
subscriptionCommands(program, streams, env);
|
|
12034
|
+
walletCommands(program, streams, env);
|
|
12035
|
+
transactionCommands(program, streams, env);
|
|
10670
12036
|
recordsCommand(program, streams, env);
|
|
10671
12037
|
findingsCommand(program, streams, env);
|
|
10672
12038
|
actionsCommand(program, streams, env);
|
|
@@ -10677,6 +12043,7 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
10677
12043
|
searchCommand(program, streams, env);
|
|
10678
12044
|
meetingReadCommands(program, streams, env);
|
|
10679
12045
|
meetingPreparationCommand(program, streams, env);
|
|
12046
|
+
eventsCommand(program, streams, env);
|
|
10680
12047
|
askCommand(program, streams, env);
|
|
10681
12048
|
syncCommand(program, streams, env, signal, keyring);
|
|
10682
12049
|
storeCommand(program, streams, env);
|
|
@@ -10689,10 +12056,10 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
10689
12056
|
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.", () => {
|
|
10690
12057
|
const out = answers(program, streams, env);
|
|
10691
12058
|
const skill3 = skillCommand(APP, new URL("../skills/cli-memo/SKILL.md", new URL("../program.js", import.meta.url).href), (command) => {
|
|
10692
|
-
const
|
|
10693
|
-
const renderer = createRenderer({ format:
|
|
12059
|
+
const json5 = command.opts().json === true;
|
|
12060
|
+
const renderer = createRenderer({ format: json5 ? "json" : "pretty", color: false, streams });
|
|
10694
12061
|
return {
|
|
10695
|
-
renderer:
|
|
12062
|
+
renderer: json5 ? { ...renderer, result: /* @__PURE__ */ __name((value) => out.print(true, itemAnswer(value)), "result") } : renderer,
|
|
10696
12063
|
streams,
|
|
10697
12064
|
env
|
|
10698
12065
|
};
|