@wirecat/cli-memo 0.131.63 → 0.131.65
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-LGA3VXKQ.js → auto-4KOZDLIU.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-BOMHJR2E.js → chunk-BEMVAPYA.js} +3 -3
- package/dist/bundle/{chunk-K4WCDPDL.js → chunk-C4DJLVJQ.js} +4 -4
- package/dist/bundle/{chunk-2UCLF4AO.js → chunk-DXTNBVLV.js} +394 -115
- package/dist/bundle/{chunk-GNHDE7FH.js → chunk-FHZKHKBJ.js} +9 -9
- package/dist/bundle/{chunk-TBSWOVM3.js → chunk-FKUA3BTM.js} +14 -14
- package/dist/bundle/{chunk-RSG7BRXI.js → chunk-FUIUS3IG.js} +25 -1
- 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-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-5Q534L4I.js → chunk-SIOUPPN7.js} +5 -4
- 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-4BKSE3CG.js → chunk-X5CRFU4E.js} +4 -4
- package/dist/bundle/{chunk-YVJAD5E7.js → chunk-YLG2M2TF.js} +38 -5
- 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-OGSLUNT6.js → failure-CRWMZZBO.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-ZHLCEVWB.js → program-RM2L3LIT.js} +1798 -434
- package/dist/bundle/{server-IQILK5YP.js → server-L622PMVC.js} +9 -9
- package/dist/bundle/{server-NKI7SVK5.js → server-SJVP2XXD.js} +6 -6
- package/dist/bundle/{server-I5BPRS5C.js → server-XKSIHWM2.js} +19 -19
- 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-YMILPFRY.js → update-PQUASMQN.js} +15 -15
- package/dist/digest/command.d.ts.map +1 -1
- package/dist/digest/command.js +4 -3
- package/dist/digest/command.js.map +1 -1
- package/dist/digest/digest.d.ts.map +1 -1
- package/dist/digest/digest.js +2 -0
- package/dist/digest/digest.js.map +1 -1
- package/dist/digest/sync-health.d.ts +6 -3
- package/dist/digest/sync-health.d.ts.map +1 -1
- package/dist/digest/sync-health.js +46 -20
- package/dist/digest/sync-health.js.map +1 -1
- package/dist/digest/tasks.d.ts +2 -0
- package/dist/digest/tasks.d.ts.map +1 -1
- package/dist/digest/tasks.js +3 -1
- package/dist/digest/tasks.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/lane-gates.js +1 -1
- package/dist/search/lane-gates.js.map +1 -1
- package/dist/show/command.d.ts +3 -0
- package/dist/show/command.d.ts.map +1 -1
- package/dist/show/command.js +21 -1
- 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/skills/morning-digest/SKILL.md +2 -1
|
@@ -6,17 +6,17 @@ import {
|
|
|
6
6
|
autoState,
|
|
7
7
|
lastAutoRun,
|
|
8
8
|
recordAutoRun
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-X5CRFU4E.js";
|
|
10
10
|
import {
|
|
11
11
|
installer,
|
|
12
12
|
latest,
|
|
13
13
|
upgradeCommand
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-C4DJLVJQ.js";
|
|
15
15
|
import {
|
|
16
16
|
mcpOwnerAllowed,
|
|
17
17
|
readOnlyAvailability,
|
|
18
18
|
refuseWritesUnderLock
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-SIOUPPN7.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-YLG2M2TF.js";
|
|
31
31
|
import {
|
|
32
32
|
ATTACHMENT_CHARS,
|
|
33
33
|
DIALECTS,
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
showMail,
|
|
60
60
|
unsetConfigKey,
|
|
61
61
|
updateConfig
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-FHZKHKBJ.js";
|
|
63
63
|
import "./chunk-QP3KNC5D.js";
|
|
64
64
|
import "./chunk-FWRBJAQZ.js";
|
|
65
65
|
import "./chunk-MWAXS4BX.js";
|
|
@@ -67,7 +67,7 @@ import "./chunk-PKUBC2ME.js";
|
|
|
67
67
|
import {
|
|
68
68
|
errorObject,
|
|
69
69
|
recognisable
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-BEMVAPYA.js";
|
|
71
71
|
import {
|
|
72
72
|
AGENT_INPUT_MAX_CHARS,
|
|
73
73
|
DISCOVERY_DESCRIPTIONS,
|
|
@@ -106,7 +106,7 @@ import {
|
|
|
106
106
|
tasksCommand,
|
|
107
107
|
tasksStatsCommand,
|
|
108
108
|
withSqliteSidecars
|
|
109
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-FKUA3BTM.js";
|
|
110
110
|
import "./chunk-RLX5SC2X.js";
|
|
111
111
|
import "./chunk-SIBQ34LX.js";
|
|
112
112
|
import {
|
|
@@ -115,22 +115,23 @@ import {
|
|
|
115
115
|
messageHitItem,
|
|
116
116
|
noteHitItem,
|
|
117
117
|
shownOf
|
|
118
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-3SCHFNUH.js";
|
|
119
119
|
import "./chunk-DKO7WEXJ.js";
|
|
120
120
|
import {
|
|
121
|
+
REASONS as REASONS2,
|
|
121
122
|
SKILL_TARGETS,
|
|
122
123
|
skillCommand,
|
|
123
124
|
skillPath,
|
|
124
125
|
skillVersion
|
|
125
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-QTF4ZXOL.js";
|
|
126
127
|
import {
|
|
127
128
|
recoveryNotes,
|
|
128
129
|
storeInfo,
|
|
129
130
|
storeRecoveryCheck,
|
|
130
131
|
storeRecoveryRun,
|
|
131
132
|
storeSummary
|
|
132
|
-
} from "./chunk-
|
|
133
|
-
import "./chunk-
|
|
133
|
+
} from "./chunk-QHNAPLVB.js";
|
|
134
|
+
import "./chunk-VLUDHCCX.js";
|
|
134
135
|
import {
|
|
135
136
|
LIST_QUERY_GUIDE,
|
|
136
137
|
STATUS_SIGNALS,
|
|
@@ -148,6 +149,10 @@ import {
|
|
|
148
149
|
gatherStoredProject,
|
|
149
150
|
importEngine,
|
|
150
151
|
ingest,
|
|
152
|
+
ingestLines,
|
|
153
|
+
ingestVcard,
|
|
154
|
+
isVcard,
|
|
155
|
+
jsonlLines,
|
|
151
156
|
listQuery,
|
|
152
157
|
mailTurn,
|
|
153
158
|
meaningLane,
|
|
@@ -156,6 +161,8 @@ import {
|
|
|
156
161
|
meetingSearchArguments,
|
|
157
162
|
meetingSearchMeta,
|
|
158
163
|
modelGateway,
|
|
164
|
+
nativeField,
|
|
165
|
+
nativeTerms,
|
|
159
166
|
parseProposalIds,
|
|
160
167
|
personContext,
|
|
161
168
|
pickPerson,
|
|
@@ -182,7 +189,7 @@ import {
|
|
|
182
189
|
termField,
|
|
183
190
|
typedQuery,
|
|
184
191
|
withQuery
|
|
185
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-DXTNBVLV.js";
|
|
186
193
|
import {
|
|
187
194
|
readBoundedUtf8File,
|
|
188
195
|
writeFileAtomic
|
|
@@ -191,9 +198,9 @@ import {
|
|
|
191
198
|
commandsText,
|
|
192
199
|
inSection,
|
|
193
200
|
installHelp
|
|
194
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-NH3A5QTW.js";
|
|
195
202
|
import "./chunk-HTQTIKWP.js";
|
|
196
|
-
import "./chunk-
|
|
203
|
+
import "./chunk-NIJZXGJN.js";
|
|
197
204
|
import {
|
|
198
205
|
Command,
|
|
199
206
|
DEFAULT_TEXT_MODEL,
|
|
@@ -220,6 +227,8 @@ import {
|
|
|
220
227
|
outputFor,
|
|
221
228
|
overrideSharedContract,
|
|
222
229
|
parseDuration,
|
|
230
|
+
progressLine,
|
|
231
|
+
progressOf,
|
|
223
232
|
proposesOnly,
|
|
224
233
|
provide,
|
|
225
234
|
runsDirFor,
|
|
@@ -228,15 +237,15 @@ import {
|
|
|
228
237
|
snakeKeys,
|
|
229
238
|
textModels,
|
|
230
239
|
textModelsFile
|
|
231
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-PVGK67AJ.js";
|
|
232
241
|
import "./chunk-SIJA2UYC.js";
|
|
233
|
-
import "./chunk-
|
|
242
|
+
import "./chunk-LVLFLWGY.js";
|
|
234
243
|
import {
|
|
235
244
|
isNewer
|
|
236
245
|
} from "./chunk-ASWLM74P.js";
|
|
237
246
|
import "./chunk-6G53ZFUT.js";
|
|
238
247
|
import "./chunk-FH4P5UQA.js";
|
|
239
|
-
import "./chunk-
|
|
248
|
+
import "./chunk-NRHF7TQ4.js";
|
|
240
249
|
import "./chunk-RP6VV35S.js";
|
|
241
250
|
import "./chunk-RTLQHLHG.js";
|
|
242
251
|
import {
|
|
@@ -257,6 +266,7 @@ import {
|
|
|
257
266
|
PROJECT_TASK_FIELDS,
|
|
258
267
|
PROJECT_TYPES,
|
|
259
268
|
PROPOSAL_STATUSES,
|
|
269
|
+
RECORDS_SCHEMA_VERSION,
|
|
260
270
|
REMINDERS_QUERY,
|
|
261
271
|
SCOPES,
|
|
262
272
|
TASK_RELATION_KINDS,
|
|
@@ -266,10 +276,11 @@ import {
|
|
|
266
276
|
contextEvidenceFingerprint,
|
|
267
277
|
decodeProjectAnnotationSnapshot,
|
|
268
278
|
entriesOfList,
|
|
269
|
-
|
|
279
|
+
envelopeOfText,
|
|
270
280
|
formatLocator,
|
|
271
281
|
formatReference,
|
|
272
282
|
isFolderProvider,
|
|
283
|
+
isImportedProvider,
|
|
273
284
|
kindOf,
|
|
274
285
|
looksLikeReference,
|
|
275
286
|
mailFindingFieldsHelp,
|
|
@@ -281,8 +292,11 @@ import {
|
|
|
281
292
|
plainQuery,
|
|
282
293
|
providerNamed,
|
|
283
294
|
refLabel
|
|
284
|
-
} from "./chunk-
|
|
295
|
+
} from "./chunk-3YNJBKGV.js";
|
|
285
296
|
import {
|
|
297
|
+
CATALOG_KINDS,
|
|
298
|
+
CONTRACT_KINDS,
|
|
299
|
+
CONTRACT_STATUSES,
|
|
286
300
|
DEAL_KINDS,
|
|
287
301
|
DEAL_ROLES,
|
|
288
302
|
DEAL_STATUSES,
|
|
@@ -299,10 +313,17 @@ import {
|
|
|
299
313
|
ORDER_PURPOSES,
|
|
300
314
|
ORDER_STATUSES,
|
|
301
315
|
PRIORITY_LABELS,
|
|
316
|
+
SUBSCRIPTION_STATUSES,
|
|
302
317
|
TASK_STATES,
|
|
303
318
|
TASK_TYPES,
|
|
319
|
+
TRANSACTION_STATUSES,
|
|
320
|
+
WALLET_KINDS,
|
|
304
321
|
WORK_TASK_TYPES,
|
|
305
322
|
createUpcomingMeetingReader,
|
|
323
|
+
dateRange,
|
|
324
|
+
dayBoundary,
|
|
325
|
+
event,
|
|
326
|
+
eventItem,
|
|
306
327
|
formatMeetingReference,
|
|
307
328
|
isClosedState,
|
|
308
329
|
markStoreDamaged,
|
|
@@ -343,7 +364,7 @@ import {
|
|
|
343
364
|
REASONS,
|
|
344
365
|
STORE_CLIENT,
|
|
345
366
|
VERSION
|
|
346
|
-
} from "./chunk-
|
|
367
|
+
} from "./chunk-FUIUS3IG.js";
|
|
347
368
|
import "./chunk-IK6KH3RE.js";
|
|
348
369
|
import "./chunk-SW6C6WH5.js";
|
|
349
370
|
import "./chunk-D72URWJE.js";
|
|
@@ -500,7 +521,7 @@ var messengers = /* @__PURE__ */ __name((entry) => new CliError("validation_erro
|
|
|
500
521
|
var listedOf = /* @__PURE__ */ __name(async (store, value) => {
|
|
501
522
|
const held = await store.accounts.storedAccounts();
|
|
502
523
|
const holdsFiles = await filesAccounts(store);
|
|
503
|
-
const
|
|
524
|
+
const named5 = /* @__PURE__ */ __name(async (entry) => {
|
|
504
525
|
const [provider = "", ...rest] = entry.trim().split(":");
|
|
505
526
|
const account2 = rest.join(":");
|
|
506
527
|
if (isFolderProvider(provider) && account2) {
|
|
@@ -513,7 +534,7 @@ var listedOf = /* @__PURE__ */ __name(async (store, value) => {
|
|
|
513
534
|
return entry.trim();
|
|
514
535
|
return `email:${(await mailboxOf(store, account2)).account}`;
|
|
515
536
|
}, "named");
|
|
516
|
-
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");
|
|
517
538
|
const groups = Object.fromEntries(await Promise.all(Object.entries(await store.accounts.accountGroups()).map(async ([name2, members]) => [name2, await each(members)])));
|
|
518
539
|
return entriesOfList((await each(value.split(","))).join(","), {
|
|
519
540
|
held,
|
|
@@ -523,9 +544,9 @@ var listedOf = /* @__PURE__ */ __name(async (store, value) => {
|
|
|
523
544
|
});
|
|
524
545
|
}, "listedOf");
|
|
525
546
|
var sourceListOf = /* @__PURE__ */ __name(async (store, env, value) => {
|
|
526
|
-
const
|
|
547
|
+
const listed2 = await listedOf(store, value);
|
|
527
548
|
const list = { mail: [], notes: false, documents: false };
|
|
528
|
-
for (const { entry, accounts } of
|
|
549
|
+
for (const { entry, accounts } of listed2) {
|
|
529
550
|
const word = entry.split(":")[0] ?? "";
|
|
530
551
|
if (MESSENGERS.has(word))
|
|
531
552
|
throw messengers(entry);
|
|
@@ -673,6 +694,7 @@ var oneOf = /* @__PURE__ */ __name((values) => (value) => {
|
|
|
673
694
|
var collect = /* @__PURE__ */ __name((value, previous = []) => [...previous, value], "collect");
|
|
674
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");
|
|
675
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");
|
|
676
698
|
|
|
677
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
|
|
678
700
|
var SCORED = "mail_sender_scores";
|
|
@@ -725,7 +747,11 @@ var REVIEW_KINDS = [
|
|
|
725
747
|
"action",
|
|
726
748
|
"invoice",
|
|
727
749
|
"payment",
|
|
728
|
-
"order"
|
|
750
|
+
"order",
|
|
751
|
+
"contract",
|
|
752
|
+
"subscription",
|
|
753
|
+
"subscription_price",
|
|
754
|
+
"transaction"
|
|
729
755
|
];
|
|
730
756
|
var BY_ACCOUNT = [MEETING_FINDINGS_KIND, MAIL_FINDINGS_KIND];
|
|
731
757
|
var reviewRegistry = /* @__PURE__ */ __name((store) => {
|
|
@@ -762,22 +788,22 @@ var REVIEW_QUERY = {
|
|
|
762
788
|
]
|
|
763
789
|
};
|
|
764
790
|
var filterOf = /* @__PURE__ */ __name(async (store, words) => {
|
|
765
|
-
const
|
|
766
|
-
const project =
|
|
767
|
-
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);
|
|
768
794
|
const unknown2 = kinds2?.find((one2) => !REVIEW_KINDS.includes(one2));
|
|
769
795
|
if (unknown2 !== void 0)
|
|
770
796
|
throw new CliError("validation_error", `no proposal kind ${unknown2}; kinds: ${REVIEW_KINDS.join(", ")}`, {
|
|
771
797
|
param: "kind"
|
|
772
798
|
});
|
|
773
|
-
const by =
|
|
774
|
-
const via =
|
|
799
|
+
const by = terms2.get("by");
|
|
800
|
+
const via = terms2.get("via");
|
|
775
801
|
return {
|
|
776
802
|
...project === void 0 ? {} : { project: await canonicalProject(store, project) },
|
|
777
803
|
...kinds2?.length ? { kinds: kinds2 } : {},
|
|
778
804
|
...by === void 0 ? {} : { by: by === "agent" || by === "rule" ? by : { bot: by } },
|
|
779
805
|
...via === void 0 ? {} : { via },
|
|
780
|
-
status:
|
|
806
|
+
status: terms2.get("status") ?? "proposed"
|
|
781
807
|
};
|
|
782
808
|
}, "filterOf");
|
|
783
809
|
var proposerName = /* @__PURE__ */ __name((proposer) => proposer.type === "bot" ? proposer.name : proposer.type === "person" ? "you" : "unknown", "proposerName");
|
|
@@ -814,6 +840,10 @@ var titleOf = /* @__PURE__ */ __name((row, label) => {
|
|
|
814
840
|
case "invoice":
|
|
815
841
|
case "payment":
|
|
816
842
|
case "order":
|
|
843
|
+
case "contract":
|
|
844
|
+
case "subscription":
|
|
845
|
+
case "subscription_price":
|
|
846
|
+
case "transaction":
|
|
817
847
|
return row.summary ?? subject;
|
|
818
848
|
default:
|
|
819
849
|
return object2 === null ? subject : `${subject} \u2192 ${object2}`;
|
|
@@ -943,8 +973,8 @@ var reviewText = /* @__PURE__ */ __name((items, hasMore) => {
|
|
|
943
973
|
...item.status === "proposed" ? [] : [item.status]
|
|
944
974
|
].join(" ");
|
|
945
975
|
const why = [item.reason && cut(item.reason, 100), item.evidence[0]].filter(Boolean).join(" \xB7 ");
|
|
946
|
-
const
|
|
947
|
-
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];
|
|
948
978
|
})
|
|
949
979
|
]);
|
|
950
980
|
return [...lines2, `${items.length} shown${hasMore ? ", more with --page" : ""}`].join("\n");
|
|
@@ -1044,19 +1074,19 @@ var partsOf = /* @__PURE__ */ __name((action, targetName) => {
|
|
|
1044
1074
|
const text3 = [payload.text, payload.title].find((one2) => typeof one2 === "string" && one2.trim() !== "");
|
|
1045
1075
|
return { verb: action.kind, targetName, text: text3 ?? null };
|
|
1046
1076
|
}, "partsOf");
|
|
1047
|
-
var summaryOf = /* @__PURE__ */ __name((action,
|
|
1048
|
-
const target =
|
|
1049
|
-
if ("counts" in
|
|
1050
|
-
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;
|
|
1051
1081
|
const what = [facts && counted(facts, "fact"), tasks && counted(tasks, "task")].filter(Boolean).join(" and ");
|
|
1052
1082
|
const word = action.kind === MEETING_FINDINGS_KIND ? "from" : action.target?.startsWith("project:") ? "in" : "about";
|
|
1053
1083
|
return `Create ${what || "nothing"}${target === null ? "" : ` ${word} ${target}`}`;
|
|
1054
1084
|
}
|
|
1055
|
-
const words =
|
|
1085
|
+
const words = parts2.verb.replaceAll("_", " ");
|
|
1056
1086
|
return [
|
|
1057
1087
|
`${words.charAt(0).toUpperCase()}${words.slice(1)}`,
|
|
1058
1088
|
target === null ? "" : ` ${target}`,
|
|
1059
|
-
|
|
1089
|
+
parts2.text === null ? "" : `: ${clip(parts2.text)}`
|
|
1060
1090
|
].join("");
|
|
1061
1091
|
}, "summaryOf");
|
|
1062
1092
|
var chatOf = /* @__PURE__ */ __name((reference2) => {
|
|
@@ -1119,11 +1149,11 @@ var actionItems = /* @__PURE__ */ __name(async (store, actions, { brief = false
|
|
|
1119
1149
|
const project = batch?.project ?? (action.target?.startsWith("project:") ? action.target : null);
|
|
1120
1150
|
const projectName = project === null ? null : names.get(project) ?? null;
|
|
1121
1151
|
const targetName = action.target === null ? null : names.get(action.target) ?? null;
|
|
1122
|
-
const
|
|
1152
|
+
const parts2 = partsOf(action, targetName);
|
|
1123
1153
|
return {
|
|
1124
1154
|
...action,
|
|
1125
|
-
summary: summaryOf(action,
|
|
1126
|
-
...
|
|
1155
|
+
summary: summaryOf(action, parts2),
|
|
1156
|
+
...parts2,
|
|
1127
1157
|
chatName: action.target === null ? null : chats.get(action.target) ?? null,
|
|
1128
1158
|
project,
|
|
1129
1159
|
projectName,
|
|
@@ -1171,8 +1201,8 @@ var decideBatch = /* @__PURE__ */ __name(async (store, id, decision) => {
|
|
|
1171
1201
|
throw new CliError("validation_error", "the findings changed since they were read; stage a new batch", {
|
|
1172
1202
|
reason: batch.stale
|
|
1173
1203
|
});
|
|
1174
|
-
const
|
|
1175
|
-
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));
|
|
1176
1206
|
const refusal = refused[0];
|
|
1177
1207
|
if (refusal)
|
|
1178
1208
|
throw new CliError(refusal.code, refusal.message, { reason: refusal.reason });
|
|
@@ -1240,9 +1270,9 @@ var AGENT_LOG_QUERY = {
|
|
|
1240
1270
|
]
|
|
1241
1271
|
};
|
|
1242
1272
|
var listAgentActions = /* @__PURE__ */ __name((store, query, limit) => {
|
|
1243
|
-
const
|
|
1244
|
-
const tool =
|
|
1245
|
-
const agent =
|
|
1273
|
+
const terms2 = queryTerms(query, AGENT_LOG_QUERY, "agents list");
|
|
1274
|
+
const tool = terms2.get("tool");
|
|
1275
|
+
const agent = terms2.get("agent");
|
|
1246
1276
|
return pageOf("agents list", limit, (most) => store.agentActions.list({
|
|
1247
1277
|
...tool === void 0 ? {} : { tool },
|
|
1248
1278
|
...agent === void 0 ? {} : { agent },
|
|
@@ -2010,8 +2040,8 @@ var fileLinks = /* @__PURE__ */ __name((source, links, documents) => links.map((
|
|
|
2010
2040
|
const at = anchor === null ? {} : { anchor };
|
|
2011
2041
|
if (isReference(target))
|
|
2012
2042
|
return { to: target, kind: "links-to", ...at };
|
|
2013
|
-
const
|
|
2014
|
-
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 };
|
|
2015
2045
|
}), "fileLinks");
|
|
2016
2046
|
|
|
2017
2047
|
// dist/notes/renames.js
|
|
@@ -2145,11 +2175,11 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
|
|
|
2145
2175
|
after.files[id] = `${stamp}${hash}`;
|
|
2146
2176
|
read.push({ id, path, bytes, hash });
|
|
2147
2177
|
}
|
|
2148
|
-
const
|
|
2178
|
+
const listed2 = /* @__PURE__ */ new Set([
|
|
2149
2179
|
...Object.keys(after.files).filter((id) => !after.files[id]?.startsWith(MEMO2)),
|
|
2150
2180
|
...[...held].filter((id) => stored.has(id))
|
|
2151
2181
|
]);
|
|
2152
|
-
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]));
|
|
2153
2183
|
const newHashes = Object.fromEntries(read.filter(({ id }) => !stored.has(id)).map(({ id, hash }) => [id, hash]));
|
|
2154
2184
|
let renamed = 0;
|
|
2155
2185
|
for (const move of detectRenames(goneHashes, newHashes)) {
|
|
@@ -2199,7 +2229,7 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
|
|
|
2199
2229
|
changed++;
|
|
2200
2230
|
}
|
|
2201
2231
|
onFile(files.length, files.length);
|
|
2202
|
-
const gone = [...stored.keys()].filter((id) => !
|
|
2232
|
+
const gone = [...stored.keys()].filter((id) => !listed2.has(id));
|
|
2203
2233
|
let deleted = 0;
|
|
2204
2234
|
let deletionsSkipped;
|
|
2205
2235
|
if (gone.length >= MIN_DELETIONS_CAPPED && gone.length > stored.size * MAX_DELETED_SHARE) {
|
|
@@ -2243,7 +2273,7 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
|
|
|
2243
2273
|
return {
|
|
2244
2274
|
folder: folder.path,
|
|
2245
2275
|
folderId: folder.id,
|
|
2246
|
-
notes:
|
|
2276
|
+
notes: listed2.size - Object.keys(notReadNow).filter((id) => listed2.has(id)).length,
|
|
2247
2277
|
changed,
|
|
2248
2278
|
renamed,
|
|
2249
2279
|
deleted,
|
|
@@ -2441,9 +2471,9 @@ var anchorOf = /* @__PURE__ */ __name(async (store, uid, source) => {
|
|
|
2441
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(", ")}`);
|
|
2442
2472
|
}, "anchorOf");
|
|
2443
2473
|
var memoContext = /* @__PURE__ */ __name(async (store, reference2, { limit = 20, source } = {}) => {
|
|
2444
|
-
const
|
|
2445
|
-
if (
|
|
2446
|
-
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);
|
|
2447
2477
|
return memoContext(store, anchor.reference, { limit, source: anchor });
|
|
2448
2478
|
}
|
|
2449
2479
|
const [, provider, who] = /^([a-z][a-z0-9-]*):(.+)$/.exec(reference2.trim()) ?? [];
|
|
@@ -2509,7 +2539,7 @@ var withOwnMailText = /* @__PURE__ */ __name((context) => {
|
|
|
2509
2539
|
// dist/context/command.js
|
|
2510
2540
|
var MAX_TEXT2 = 160;
|
|
2511
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");
|
|
2512
|
-
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");
|
|
2513
2543
|
var noteLine = /* @__PURE__ */ __name((note) => ` ${note.ref}${note.path ?? note.title ? ` ${note.path ?? note.title}` : ""}`, "noteLine");
|
|
2514
2544
|
var fileLine = /* @__PURE__ */ __name((file) => ` ${file.ref} ${file.role ?? ""} ${file.title ?? ""} ${file.modifiedAt?.slice(0, 16).replace("T", " ") ?? ""} ${file.url ?? ""}`, "fileLine");
|
|
2515
2545
|
var contextText = /* @__PURE__ */ __name(({ messages, events, notes: notes2, notRead, tasks, yourNotes, files, proposals }) => {
|
|
@@ -4083,6 +4113,7 @@ var SECTIONS = [
|
|
|
4083
4113
|
["notes remove", "write"],
|
|
4084
4114
|
["notes export", "write"],
|
|
4085
4115
|
["mail", "read"],
|
|
4116
|
+
["events", "read"],
|
|
4086
4117
|
["agents", "read"],
|
|
4087
4118
|
["answers", "read"],
|
|
4088
4119
|
["memories", "write"],
|
|
@@ -4097,6 +4128,11 @@ var SECTIONS = [
|
|
|
4097
4128
|
["leads", "organise"],
|
|
4098
4129
|
["pipelines", "organise"],
|
|
4099
4130
|
["payments", "organise"],
|
|
4131
|
+
["products", "organise"],
|
|
4132
|
+
["contracts", "organise"],
|
|
4133
|
+
["subscriptions", "organise"],
|
|
4134
|
+
["wallets", "organise"],
|
|
4135
|
+
["transactions", "organise"],
|
|
4100
4136
|
["records", "organise"],
|
|
4101
4137
|
["projects", "organise"],
|
|
4102
4138
|
["people", "organise"],
|
|
@@ -4285,10 +4321,387 @@ var doctorCommand = /* @__PURE__ */ __name((...args) => {
|
|
|
4285
4321
|
}, SHELL_OVERRIDES.doctor);
|
|
4286
4322
|
}, "doctorCommand");
|
|
4287
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
|
+
|
|
4288
4697
|
// dist/examples.js
|
|
4289
4698
|
var EXAMPLES = {
|
|
4290
4699
|
context: ["memo context telegram:'Kai Sample'", "memo context email:kai@example.com --limit 5 --json"],
|
|
4291
|
-
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
|
+
],
|
|
4292
4705
|
"notes show": ["memo notes show note:12", "memo notes show ~/notes/People/Kai.md --json"],
|
|
4293
4706
|
"notes list": [
|
|
4294
4707
|
`memo notes list 'about:"telegram:Kai Sample"'`,
|
|
@@ -4453,7 +4866,7 @@ var EXAMPLES = {
|
|
|
4453
4866
|
"memo relationships update 12 --role contractor --reason 'builds the site'"
|
|
4454
4867
|
],
|
|
4455
4868
|
"relationships add": [
|
|
4456
|
-
"memo relationships add person:3 organization:1 --role
|
|
4869
|
+
"memo relationships add person:3 organization:1 --role employee",
|
|
4457
4870
|
"memo relationships add project:2 organization:1 --kind related-to --reason 'same client'"
|
|
4458
4871
|
],
|
|
4459
4872
|
"relationships list": ['memo relationships list about:"person:3"', "memo relationships list confirmed:false"],
|
|
@@ -4517,6 +4930,11 @@ var EXAMPLES = {
|
|
|
4517
4930
|
"memo orders add 'Shop One' 2499.00 RUB --kind personal --title A-1042",
|
|
4518
4931
|
"memo orders add 'Office Supply' --kind client --organization organization:3"
|
|
4519
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"],
|
|
4520
4938
|
"invoices list": ["memo invoices list project:HRB open:true", "memo invoices list review:proposed --json"],
|
|
4521
4939
|
"invoices show": ["memo invoices show invoice:4"],
|
|
4522
4940
|
"invoices add": [
|
|
@@ -4526,19 +4944,93 @@ var EXAMPLES = {
|
|
|
4526
4944
|
"payments list": ["memo payments list project:HRB direction:in", "memo payments list review:proposed --json"],
|
|
4527
4945
|
"payments show": ["memo payments show payment:9"],
|
|
4528
4946
|
"payments add": [
|
|
4529
|
-
"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"
|
|
4530
4949
|
],
|
|
4531
4950
|
"records import": [
|
|
4532
4951
|
"memo records import payments.jsonl --account rentals --dry-run",
|
|
4533
|
-
"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"
|
|
4534
4954
|
],
|
|
4535
4955
|
"records check": ["memo records check - --account rentals"],
|
|
4536
4956
|
"records list": [
|
|
4537
4957
|
"memo records list waiting:true --account sheet:rentals",
|
|
4538
|
-
"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`
|
|
4539
4960
|
],
|
|
4540
4961
|
"records link": ["memo records link organization:client organization:3 --account sheet:rentals"],
|
|
4541
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"],
|
|
4542
5034
|
"payments unlink": ["memo payments unlink payment:9 invoice:4"],
|
|
4543
5035
|
"facts show": ["memo facts show fact:4 --sources"],
|
|
4544
5036
|
"facts confirm": ["memo facts confirm fact:4"],
|
|
@@ -4608,7 +5100,11 @@ var EXAMPLES = {
|
|
|
4608
5100
|
"mcp server start": ["memo mcp server start --public-url https://laptop.example.ts.net"],
|
|
4609
5101
|
"mcp server status": ["memo mcp server status --json"],
|
|
4610
5102
|
"mcp server stop": ["memo mcp server stop"],
|
|
4611
|
-
"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
|
+
],
|
|
4612
5108
|
"search messages": ["memo search messages 'friday meeting has:voice'"],
|
|
4613
5109
|
"search mail": ["memo search mail 'mailbox:important budget' --source email:me@example.com"],
|
|
4614
5110
|
"search notes": ["memo search notes budget notes:2", "memo search notes kickoff --project HRB --json"],
|
|
@@ -4708,13 +5204,13 @@ var memoryItem = /* @__PURE__ */ __name(({ body, ...memory }) => ({
|
|
|
4708
5204
|
updatedAt: memory.updatedAt
|
|
4709
5205
|
}), "memoryItem");
|
|
4710
5206
|
var listMemories = /* @__PURE__ */ __name(async (store, query, limit) => {
|
|
4711
|
-
const
|
|
4712
|
-
const project =
|
|
5207
|
+
const terms2 = queryTerms(query, MEMORY_QUERY, "memories list");
|
|
5208
|
+
const project = terms2.get("project");
|
|
4713
5209
|
const filters = {
|
|
4714
|
-
...
|
|
4715
|
-
...
|
|
4716
|
-
...
|
|
4717
|
-
...
|
|
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") } : {},
|
|
4718
5214
|
...project === void 0 ? {} : { project: await canonicalProject(store, project) }
|
|
4719
5215
|
};
|
|
4720
5216
|
return pageOf("memories list", limit, async (most) => (await store.memories.list({ ...filters, limit: most })).map(memoryItem));
|
|
@@ -4768,7 +5264,7 @@ var memoriesCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
4768
5264
|
...options.supersedes === void 0 ? {} : { supersedes: options.supersedes }
|
|
4769
5265
|
}, await by))));
|
|
4770
5266
|
});
|
|
4771
|
-
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)));
|
|
4772
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({
|
|
4773
5269
|
...memoryItem(await store.memories.get(ref)),
|
|
4774
5270
|
...options.sources ? { sources: await store.memories.sources(ref) } : {}
|
|
@@ -4838,13 +5334,13 @@ var factItem = /* @__PURE__ */ __name(({ type, statement, source, confirmedBy, .
|
|
|
4838
5334
|
confirmed_by: confirmedBy
|
|
4839
5335
|
}), "factItem");
|
|
4840
5336
|
var listFacts = /* @__PURE__ */ __name(async (store, query, limit) => {
|
|
4841
|
-
const
|
|
4842
|
-
const project =
|
|
5337
|
+
const terms2 = queryTerms(query, FACT_QUERY, "facts list");
|
|
5338
|
+
const project = terms2.get("project");
|
|
4843
5339
|
const filters = {
|
|
4844
|
-
...
|
|
4845
|
-
...
|
|
5340
|
+
...terms2.has("kind") ? { type: terms2.get("kind") } : {},
|
|
5341
|
+
...terms2.has("status") ? { status: terms2.get("status") } : {},
|
|
4846
5342
|
...project === void 0 ? {} : { project: await canonicalProject(store, project) },
|
|
4847
|
-
...
|
|
5343
|
+
...terms2.has("subject") ? { subject: terms2.get("subject") } : {}
|
|
4848
5344
|
};
|
|
4849
5345
|
return pageOf("facts list", limit, async (most) => (await store.facts.list({ ...filters, limit: most })).map(factItem));
|
|
4850
5346
|
}, "listFacts");
|
|
@@ -4886,7 +5382,7 @@ var factsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
4886
5382
|
...options.supersedes === void 0 ? {} : { supersedes: options.supersedes }
|
|
4887
5383
|
}))));
|
|
4888
5384
|
});
|
|
4889
|
-
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)));
|
|
4890
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({
|
|
4891
5387
|
...factItem(await store.facts.get(ref)),
|
|
4892
5388
|
...options.sources ? { sources: await store.facts.sources(ref) } : {}
|
|
@@ -4916,6 +5412,67 @@ var factsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
4916
5412
|
${FORGET_HELP.replace("use invalidate", "use reject or reverse")}`);
|
|
4917
5413
|
}, "factsCommand");
|
|
4918
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
|
+
|
|
4919
5476
|
// dist/finance/finance.js
|
|
4920
5477
|
var INVOICE_QUERY = {
|
|
4921
5478
|
entity: "invoice",
|
|
@@ -4943,25 +5500,25 @@ var PAYMENT_QUERY = {
|
|
|
4943
5500
|
var projectTerm = /* @__PURE__ */ __name(async (store, project) => project === void 0 ? {} : { project: await canonicalProject(store, project) }, "projectTerm");
|
|
4944
5501
|
var reviewTerm = /* @__PURE__ */ __name((review) => review === void 0 ? {} : { review }, "reviewTerm");
|
|
4945
5502
|
var listInvoices = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
4946
|
-
const
|
|
5503
|
+
const terms2 = queryTerms(words, INVOICE_QUERY, "invoices list");
|
|
4947
5504
|
const filter = {
|
|
4948
|
-
...await projectTerm(store,
|
|
4949
|
-
...reviewTerm(
|
|
4950
|
-
...
|
|
4951
|
-
...
|
|
4952
|
-
...
|
|
4953
|
-
...
|
|
4954
|
-
...
|
|
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" } : {}
|
|
4955
5512
|
};
|
|
4956
5513
|
return pageOf("invoices list", limit, (most) => store.finance.invoices({ ...filter, limit: most }));
|
|
4957
5514
|
}, "listInvoices");
|
|
4958
5515
|
var listPayments = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
4959
|
-
const
|
|
5516
|
+
const terms2 = queryTerms(words, PAYMENT_QUERY, "payments list");
|
|
4960
5517
|
const filter = {
|
|
4961
|
-
...await projectTerm(store,
|
|
4962
|
-
...reviewTerm(
|
|
4963
|
-
...
|
|
4964
|
-
...
|
|
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") } : {}
|
|
4965
5522
|
};
|
|
4966
5523
|
return pageOf("payments list", limit, (most) => store.finance.payments({ ...filter, limit: most }));
|
|
4967
5524
|
}, "listPayments");
|
|
@@ -5031,14 +5588,21 @@ var financeText = /* @__PURE__ */ __name((block) => block.length === 0 ? [] : [
|
|
|
5031
5588
|
})
|
|
5032
5589
|
], "financeText");
|
|
5033
5590
|
|
|
5034
|
-
// dist/finance/
|
|
5035
|
-
var json = /* @__PURE__ */ __name((command) => command
|
|
5591
|
+
// dist/finance/written.js
|
|
5592
|
+
var json = /* @__PURE__ */ __name((command) => jsonOption(command), "json");
|
|
5036
5593
|
var PROPOSES = "yours is confirmed at once; an agent's waits as proposed for you in memo review";
|
|
5037
|
-
var
|
|
5038
|
-
if (
|
|
5039
|
-
throw new CliError("validation_error",
|
|
5040
|
-
return
|
|
5041
|
-
}, "
|
|
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");
|
|
5042
5606
|
var writtenBy = /* @__PURE__ */ __name(async (store, by, options) => ({
|
|
5043
5607
|
by,
|
|
5044
5608
|
...options.project === void 0 ? {} : { project: await canonicalProject(store, options.project) },
|
|
@@ -5047,23 +5611,71 @@ var writtenBy = /* @__PURE__ */ __name(async (store, by, options) => ({
|
|
|
5047
5611
|
}), "writtenBy");
|
|
5048
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");
|
|
5049
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
|
|
5050
5662
|
var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5051
5663
|
const { run } = answers(program, streams, env);
|
|
5052
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");
|
|
5053
|
-
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:
|
|
5054
|
-
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)))));
|
|
5055
5667
|
json(writeMeta(party(annotate(invoices.command("add"), {
|
|
5056
5668
|
effects: LOCAL_WRITE,
|
|
5057
5669
|
output: { entity: "invoice" },
|
|
5058
5670
|
literal_after_dashes: true
|
|
5059
|
-
}), "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) => {
|
|
5060
5672
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this invoice as yours?" });
|
|
5061
5673
|
await run(options.json, async (store) => {
|
|
5062
5674
|
const issueDate = dayOf(options.occurredTime);
|
|
5063
5675
|
const dueDate = dayOf(options.due);
|
|
5064
5676
|
return itemAnswer(await store.finance.addInvoice({
|
|
5065
5677
|
...await writtenBy(store, by, options),
|
|
5066
|
-
direction:
|
|
5678
|
+
direction: choice(options.kind, INVOICE_DIRECTIONS, "--kind"),
|
|
5067
5679
|
counterparty: partyOf(options, true),
|
|
5068
5680
|
currency,
|
|
5069
5681
|
lines: [{ description: words.join(" "), amount: amount2 }],
|
|
@@ -5073,13 +5685,14 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5073
5685
|
}));
|
|
5074
5686
|
});
|
|
5075
5687
|
});
|
|
5688
|
+
lineCommands(invoices, "invoice", run, env);
|
|
5076
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");
|
|
5077
|
-
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:
|
|
5078
|
-
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))));
|
|
5079
|
-
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) => {
|
|
5080
5693
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this payment as yours?" });
|
|
5081
5694
|
await run(options.json, async (store) => {
|
|
5082
|
-
const direction =
|
|
5695
|
+
const direction = choice(options.kind, MONEY_DIRECTIONS, "--kind");
|
|
5083
5696
|
const counterparty = partyOf(options, false);
|
|
5084
5697
|
return itemAnswer(await store.finance.addPayment({
|
|
5085
5698
|
...await writtenBy(store, by, options),
|
|
@@ -5088,7 +5701,8 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5088
5701
|
amount: amount2,
|
|
5089
5702
|
currency,
|
|
5090
5703
|
date: dayOf(options.occurredTime) ?? today(),
|
|
5091
|
-
...options.title === void 0 ? {} : { reference: options.title }
|
|
5704
|
+
...options.title === void 0 ? {} : { reference: options.title },
|
|
5705
|
+
...options.refundOf === void 0 ? {} : { refundOf: options.refundOf }
|
|
5092
5706
|
}));
|
|
5093
5707
|
});
|
|
5094
5708
|
});
|
|
@@ -5105,6 +5719,78 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5105
5719
|
});
|
|
5106
5720
|
}, "financeCommands");
|
|
5107
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
|
+
|
|
5108
5794
|
// dist/finance/deals-command.js
|
|
5109
5795
|
var queryOf = /* @__PURE__ */ __name((entity) => ({
|
|
5110
5796
|
entity,
|
|
@@ -5125,14 +5811,14 @@ var PIPELINE_QUERY = {
|
|
|
5125
5811
|
};
|
|
5126
5812
|
var listDeals = /* @__PURE__ */ __name(async (store, kind, words, limit) => {
|
|
5127
5813
|
const command = `${kind}s list`;
|
|
5128
|
-
const
|
|
5814
|
+
const terms2 = queryTerms(words, QUERIES[kind], command);
|
|
5129
5815
|
const filter = {
|
|
5130
5816
|
kind,
|
|
5131
|
-
...
|
|
5132
|
-
...
|
|
5133
|
-
...
|
|
5134
|
-
...
|
|
5135
|
-
...
|
|
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") } : {}
|
|
5136
5822
|
};
|
|
5137
5823
|
return pageOf(command, limit, (most) => store.deals.list({ ...filter, limit: most }));
|
|
5138
5824
|
}, "listDeals");
|
|
@@ -5149,7 +5835,6 @@ var stageOf = /* @__PURE__ */ __name((stage) => {
|
|
|
5149
5835
|
const at = stage.lastIndexOf("/");
|
|
5150
5836
|
return at <= 0 ? { stage } : { pipeline: stage.slice(0, at), stage: stage.slice(at + 1) };
|
|
5151
5837
|
}, "stageOf");
|
|
5152
|
-
var json2 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
|
|
5153
5838
|
var WHAT = {
|
|
5154
5839
|
deal: { one: "deal", hope: "what you hope to sell, such as 'Site for the clinic'" },
|
|
5155
5840
|
lead: { one: "lead", hope: "who or what came in, such as 'Call from the site'" }
|
|
@@ -5157,9 +5842,9 @@ var WHAT = {
|
|
|
5157
5842
|
var itemCommands = /* @__PURE__ */ __name((program, kind, run, env) => {
|
|
5158
5843
|
const { one: one2, hope } = WHAT[kind];
|
|
5159
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");
|
|
5160
|
-
withQuery(
|
|
5161
|
-
|
|
5162
|
-
|
|
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) => {
|
|
5163
5848
|
const by = authorOf(env);
|
|
5164
5849
|
const role = roleOf(options.role);
|
|
5165
5850
|
await run(options.json, async (store) => {
|
|
@@ -5180,11 +5865,11 @@ var itemCommands = /* @__PURE__ */ __name((program, kind, run, env) => {
|
|
|
5180
5865
|
}));
|
|
5181
5866
|
});
|
|
5182
5867
|
});
|
|
5183
|
-
|
|
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) => {
|
|
5184
5869
|
const by = authorOf(env);
|
|
5185
5870
|
await run(options.json, async (store) => itemAnswer(await store.deals.move(ref, { stage, by })));
|
|
5186
5871
|
});
|
|
5187
|
-
|
|
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) => {
|
|
5188
5873
|
if (outcome !== "won" && outcome !== "lost")
|
|
5189
5874
|
throw new CliError("validation_error", `a ${one2} closes as won or lost`, { param: "outcome" });
|
|
5190
5875
|
const by = authorOf(env);
|
|
@@ -5206,19 +5891,19 @@ var funnelText = /* @__PURE__ */ __name((report) => [
|
|
|
5206
5891
|
var dealCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5207
5892
|
const { run, print } = answers(program, streams, env);
|
|
5208
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");
|
|
5209
|
-
withQuery(
|
|
5210
|
-
const
|
|
5211
|
-
const name2 =
|
|
5212
|
-
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");
|
|
5213
5898
|
const all = await store.deals.pipelines(kind === void 0 ? {} : { kind });
|
|
5214
5899
|
return wholeList("pipelines list", name2 === void 0 ? all : all.filter((one2) => one2.name.toLocaleLowerCase() === name2));
|
|
5215
5900
|
}));
|
|
5216
|
-
|
|
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) => {
|
|
5217
5902
|
const since = dayOf(options.sinceTime);
|
|
5218
|
-
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 })));
|
|
5219
5904
|
print(options.json, itemAnswer(report), funnelText(report));
|
|
5220
5905
|
});
|
|
5221
|
-
|
|
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) => {
|
|
5222
5907
|
const kind = options.kind ?? "deal";
|
|
5223
5908
|
if (!DEAL_KINDS.includes(kind))
|
|
5224
5909
|
throw new CliError("validation_error", "--kind is deal or lead", { param: "--kind" });
|
|
@@ -5277,15 +5962,15 @@ var ORDER_QUERY = {
|
|
|
5277
5962
|
]
|
|
5278
5963
|
};
|
|
5279
5964
|
var listOrders = /* @__PURE__ */ __name(async (store, words, limit) => {
|
|
5280
|
-
const
|
|
5965
|
+
const terms2 = queryTerms(words, ORDER_QUERY, "orders list");
|
|
5281
5966
|
const filter = {
|
|
5282
|
-
...
|
|
5283
|
-
...
|
|
5284
|
-
...
|
|
5285
|
-
...
|
|
5286
|
-
...
|
|
5287
|
-
...
|
|
5288
|
-
...
|
|
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") } : {}
|
|
5289
5974
|
};
|
|
5290
5975
|
return pageOf("orders list", limit, (most) => store.orders.list({ ...filter, limit: most }));
|
|
5291
5976
|
}, "listOrders");
|
|
@@ -5294,13 +5979,12 @@ var oneOf2 = /* @__PURE__ */ __name((value, allowed, flag) => {
|
|
|
5294
5979
|
throw new CliError("validation_error", `${flag} is one of ${allowed.join(", ")}`, { param: flag });
|
|
5295
5980
|
return value;
|
|
5296
5981
|
}, "oneOf");
|
|
5297
|
-
var json3 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
|
|
5298
5982
|
var orderCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
5299
5983
|
const { run } = answers(program, streams, env);
|
|
5300
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");
|
|
5301
|
-
withQuery(
|
|
5302
|
-
|
|
5303
|
-
|
|
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) => {
|
|
5304
5988
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this order as yours?" });
|
|
5305
5989
|
await run(options.json, async (store) => {
|
|
5306
5990
|
const customer = partyOf(options, false);
|
|
@@ -5320,8 +6004,314 @@ var orderCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5320
6004
|
}));
|
|
5321
6005
|
});
|
|
5322
6006
|
});
|
|
6007
|
+
lineCommands(orders, "order", run, env);
|
|
5323
6008
|
}, "orderCommands");
|
|
5324
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
|
+
|
|
5325
6315
|
// dist/findings-input.js
|
|
5326
6316
|
import { createReadStream, statSync as statSync2 } from "node:fs";
|
|
5327
6317
|
var FINDINGS_INPUT_HELP = "the findings JSON itself (starts with {), a JSON file, or - for stdin; at most 65536 UTF-8 bytes";
|
|
@@ -5351,53 +6341,53 @@ var findingsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
5351
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");
|
|
5352
6342
|
const { run } = answers(program, streams, env);
|
|
5353
6343
|
const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
|
|
5354
|
-
const scope = /* @__PURE__ */ __name((store,
|
|
5355
|
-
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");
|
|
5356
6346
|
const options = /* @__PURE__ */ __name((command) => sourceOptions(command, MEETING_ACCOUNT_HELP).option("--json", "print JSON; --json=id,status keeps only those fields"), "options");
|
|
5357
6347
|
const writes = /* @__PURE__ */ __name((command) => writeOptions(command, MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,status keeps only those fields"), "writes");
|
|
5358
|
-
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) => {
|
|
5359
6349
|
const text3 = await readFindingsInput(file, environmentOf(program).stdin ?? process.stdin);
|
|
5360
6350
|
const input = parseMeetingFindingsJson(text3);
|
|
5361
6351
|
const author = await whoRuns(program, env, { question: "" });
|
|
5362
6352
|
const agent = author === "owner" ? { bot: "memo-findings" } : author;
|
|
5363
|
-
await run(
|
|
6353
|
+
await run(given2.json, async (store) => itemAnswer(await store.meetingFindings.stage(await acting(store, given2), input, agent)));
|
|
5364
6354
|
});
|
|
5365
|
-
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,
|
|
5366
|
-
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) => {
|
|
5367
6357
|
const status = queryTerms(words, FINDINGS_QUERY, "meetings actions list").get("status");
|
|
5368
|
-
const key = await scope(store,
|
|
6358
|
+
const key = await scope(store, given2);
|
|
5369
6359
|
const found = await store.meetingFindings.list(key, {
|
|
5370
|
-
limit:
|
|
5371
|
-
offset: (
|
|
6360
|
+
limit: given2.limit,
|
|
6361
|
+
offset: (given2.page - 1) * given2.limit,
|
|
5372
6362
|
...status === void 0 ? {} : { status }
|
|
5373
6363
|
});
|
|
5374
6364
|
return listAnswer("meetings actions list", {
|
|
5375
6365
|
items: found.items,
|
|
5376
|
-
limit:
|
|
5377
|
-
page:
|
|
6366
|
+
limit: given2.limit,
|
|
6367
|
+
page: given2.page,
|
|
5378
6368
|
has_more: found.hasMore,
|
|
5379
|
-
args: { query: words.join(" "), source: accountName(key), limit:
|
|
6369
|
+
args: { query: words.join(" "), source: accountName(key), limit: given2.limit }
|
|
5380
6370
|
});
|
|
5381
6371
|
}));
|
|
5382
6372
|
for (const name2 of ["confirm", "reject"]) {
|
|
5383
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");
|
|
5384
6374
|
byOption(command);
|
|
5385
|
-
const review = /* @__PURE__ */ __name(async (id,
|
|
6375
|
+
const review = /* @__PURE__ */ __name(async (id, given2, accept) => {
|
|
5386
6376
|
const key = `meetings.actions.${name2}`;
|
|
5387
|
-
const who = await whoRuns(command, env, { asOwner:
|
|
6377
|
+
const who = await whoRuns(command, env, { asOwner: given2.asOwner, question: `${name2} batch ${id} as you?` });
|
|
5388
6378
|
const by = who === "owner" ? who : mcpOwnerAllowed(env, key) ? { bot: who.bot, reason: `the owner allows ${key}` } : void 0;
|
|
5389
6379
|
if (by === void 0)
|
|
5390
6380
|
throw new CliError("validation_error", "findings confirmation and rejection belong to the owner; agents must leave proposals for review");
|
|
5391
|
-
return run(
|
|
5392
|
-
fingerprint:
|
|
6381
|
+
return run(given2.json, async (store) => itemAnswer(await store.meetingFindings.review(await acting(store, given2), id, {
|
|
6382
|
+
fingerprint: given2.fingerprint,
|
|
5393
6383
|
accept,
|
|
5394
6384
|
by
|
|
5395
6385
|
})));
|
|
5396
6386
|
}, "review");
|
|
5397
6387
|
if (name2 === "confirm")
|
|
5398
|
-
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));
|
|
5399
6389
|
else
|
|
5400
|
-
command.action((id,
|
|
6390
|
+
command.action((id, given2) => review(id, given2, []));
|
|
5401
6391
|
}
|
|
5402
6392
|
}, "findingsCommand");
|
|
5403
6393
|
|
|
@@ -5478,18 +6468,18 @@ var meetingProjectsCommand = /* @__PURE__ */ __name((projects, streams, env) =>
|
|
|
5478
6468
|
const key = await (writes ? writeAccount : theAccount)(store, env, options2, warn);
|
|
5479
6469
|
return work(store, (await canonicalProject(store, project)).slice(8), key);
|
|
5480
6470
|
}), "execute");
|
|
5481
|
-
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) => {
|
|
5482
6472
|
const confirmed = queryTerms(words, MEETING_PROJECTS_QUERY, "projects meetings list").get("confirmed");
|
|
5483
|
-
const page =
|
|
6473
|
+
const page = given2.page ?? 1;
|
|
5484
6474
|
const found = await store.knowledge.meetingProjects(key, {
|
|
5485
6475
|
projectId,
|
|
5486
6476
|
confirmed: confirmed === "true",
|
|
5487
|
-
limit:
|
|
5488
|
-
offset: (page - 1) *
|
|
6477
|
+
limit: given2.limit,
|
|
6478
|
+
offset: (page - 1) * given2.limit
|
|
5489
6479
|
});
|
|
5490
6480
|
return listAnswer("projects meetings list", {
|
|
5491
6481
|
items: found.items,
|
|
5492
|
-
limit:
|
|
6482
|
+
limit: given2.limit,
|
|
5493
6483
|
has_more: found.hasMore,
|
|
5494
6484
|
page,
|
|
5495
6485
|
args: {
|
|
@@ -5499,10 +6489,10 @@ var meetingProjectsCommand = /* @__PURE__ */ __name((projects, streams, env) =>
|
|
|
5499
6489
|
}
|
|
5500
6490
|
});
|
|
5501
6491
|
}));
|
|
5502
|
-
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, {
|
|
5503
6493
|
by: "owner",
|
|
5504
|
-
...
|
|
5505
|
-
...
|
|
6494
|
+
...given2.fingerprint === void 0 ? {} : { expectedFingerprint: given2.fingerprint },
|
|
6495
|
+
...given2.reason === void 0 ? {} : { provenance: given2.reason }
|
|
5506
6496
|
})), true));
|
|
5507
6497
|
}, "meetingProjectsCommand");
|
|
5508
6498
|
|
|
@@ -5590,18 +6580,18 @@ var ACTIONS_QUERY = {
|
|
|
5590
6580
|
fields: [termField("status", "enum", "status:proposed", { values: ["proposed", "reviewed"] })],
|
|
5591
6581
|
defaults: ["status:proposed"]
|
|
5592
6582
|
};
|
|
5593
|
-
var
|
|
6583
|
+
var json2 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
|
|
5594
6584
|
var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
|
|
5595
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");
|
|
5596
6586
|
const { run } = answers(projects, streams, env);
|
|
5597
|
-
|
|
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) => {
|
|
5598
6588
|
const input = parseEvidenceFindingsJson(await readFindingsInput(file, environmentOf(projects).stdin ?? process.stdin));
|
|
5599
6589
|
const author = await whoRuns(command, env, { question: "" });
|
|
5600
6590
|
if (author === "owner")
|
|
5601
6591
|
throw new CliError("validation_error", "findings are an agent's proposals; record your own with memo facts add");
|
|
5602
|
-
await run(
|
|
6592
|
+
await run(given2.json, async (store) => itemAnswer(await store.evidenceFindings.stage(input, author)));
|
|
5603
6593
|
});
|
|
5604
|
-
withQuery(
|
|
6594
|
+
withQuery(json2(answerEntity(annotate(group.command("list"), { effects: LOCAL_READ }), "project_action", union([
|
|
5605
6595
|
strictObject({
|
|
5606
6596
|
kind: literal("key_document"),
|
|
5607
6597
|
id: string(),
|
|
@@ -5622,39 +6612,39 @@ var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
|
|
|
5622
6612
|
decision: unknown(),
|
|
5623
6613
|
findings: array(unknown())
|
|
5624
6614
|
})
|
|
5625
|
-
]))).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) => {
|
|
5626
6616
|
const status = queryTerms(words, ACTIONS_QUERY, "projects actions list").get("status");
|
|
5627
6617
|
const project = await projectOf(store, reference2);
|
|
5628
6618
|
const found = await projectActions(store, project, {
|
|
5629
6619
|
status,
|
|
5630
|
-
limit:
|
|
5631
|
-
page:
|
|
5632
|
-
brief:
|
|
5633
|
-
before: Math.min(
|
|
5634
|
-
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)
|
|
5635
6625
|
});
|
|
5636
6626
|
return listAnswer("projects actions list", {
|
|
5637
6627
|
items: found.items,
|
|
5638
|
-
limit:
|
|
5639
|
-
page:
|
|
6628
|
+
limit: given2.limit,
|
|
6629
|
+
page: given2.page,
|
|
5640
6630
|
has_more: found.hasMore,
|
|
5641
6631
|
args: { project: reference2, query: words.join(" ") }
|
|
5642
6632
|
});
|
|
5643
6633
|
}));
|
|
5644
6634
|
for (const name2 of ["confirm", "reject"]) {
|
|
5645
|
-
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"));
|
|
5646
6636
|
if (name2 === "confirm")
|
|
5647
6637
|
command.argument("[findings...]", "the finding IDs of a batch to create");
|
|
5648
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) => {
|
|
5649
6639
|
const accept = name2 === "confirm" ? rest[0] : [];
|
|
5650
|
-
const
|
|
5651
|
-
const by = await deciderOf(command, env, { ...
|
|
5652
|
-
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) => {
|
|
5653
6643
|
const project = await projectOf(store, reference2);
|
|
5654
6644
|
return itemAnswer(await decideAction(store, project, id, {
|
|
5655
6645
|
confirm: name2 === "confirm",
|
|
5656
|
-
...
|
|
5657
|
-
...
|
|
6646
|
+
...given2.fingerprint === void 0 ? {} : { fingerprint: given2.fingerprint },
|
|
6647
|
+
...given2.reason === void 0 ? {} : { reason: given2.reason },
|
|
5658
6648
|
accept,
|
|
5659
6649
|
by
|
|
5660
6650
|
}));
|
|
@@ -5986,7 +6976,7 @@ var syncHint = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => {
|
|
|
5986
6976
|
}, "syncHint");
|
|
5987
6977
|
|
|
5988
6978
|
// dist/knowledge/relationships-scan.js
|
|
5989
|
-
var
|
|
6979
|
+
var DAY4 = 864e5;
|
|
5990
6980
|
var SCAN_STEP = {
|
|
5991
6981
|
id: "relationships.scan",
|
|
5992
6982
|
kind: "command",
|
|
@@ -6060,7 +7050,7 @@ var relationshipsScanCommand = /* @__PURE__ */ __name((relations, print, env, wa
|
|
|
6060
7050
|
if (options.limit > 50)
|
|
6061
7051
|
throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
|
|
6062
7052
|
const window = projectWindowOf(options.sinceTime);
|
|
6063
|
-
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();
|
|
6064
7054
|
const written2 = options.yes === true;
|
|
6065
7055
|
const { body, text: text3 } = await withStore(env, async (store) => {
|
|
6066
7056
|
const sources = await namedAccounts(store, env, options, warn);
|
|
@@ -6108,14 +7098,14 @@ var projectGatherCommand = /* @__PURE__ */ __name((projects, print, env, warn) =
|
|
|
6108
7098
|
});
|
|
6109
7099
|
const since = new Date(found.window.after).toISOString().slice(0, 10);
|
|
6110
7100
|
const syncs = found.linkedChats.map((one2) => one2.completeness === null || one2.completeness.state === "complete" ? null : chatSync(one2, since, env, chosen));
|
|
6111
|
-
const
|
|
7101
|
+
const parts2 = projectAnswerParts(options.sinceTime, found);
|
|
6112
7102
|
const blocked = [...new Set(syncs.flatMap((one2) => one2 && one2.command === null ? [one2.why] : []))];
|
|
6113
|
-
const missing = [...
|
|
6114
|
-
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);
|
|
6115
7105
|
print(options.json, itemAnswer({
|
|
6116
7106
|
...found,
|
|
6117
7107
|
linkedChats: found.linkedChats.map((one2, i) => ({ ...one2, syncCommand: syncs[i]?.command ?? null }))
|
|
6118
|
-
}, { ...
|
|
7108
|
+
}, { ...parts2, ...missing.length ? { missing } : {}, ...next.length ? { next } : {} }), projectEvidenceText(found, {
|
|
6119
7109
|
sync: /* @__PURE__ */ __name((chat, at) => syncHint(chat, at, env, chosen), "sync"),
|
|
6120
7110
|
showDocument: "memo notes show"
|
|
6121
7111
|
}));
|
|
@@ -6163,7 +7153,7 @@ var projectStatusCommand = /* @__PURE__ */ __name((projects, print, env) => answ
|
|
|
6163
7153
|
param: "--compact"
|
|
6164
7154
|
});
|
|
6165
7155
|
const chosen = options.syncProfile ?? {};
|
|
6166
|
-
const { found, finance, open } = await withStore(env, async (store) => {
|
|
7156
|
+
const { found, finance, open: open2 } = await withStore(env, async (store) => {
|
|
6167
7157
|
const status = await projectStatus(store, {
|
|
6168
7158
|
project,
|
|
6169
7159
|
...projectWindowOf(options.sinceTime),
|
|
@@ -6187,13 +7177,13 @@ var projectStatusCommand = /* @__PURE__ */ __name((projects, print, env) => answ
|
|
|
6187
7177
|
print(options.json, itemOf({
|
|
6188
7178
|
...item,
|
|
6189
7179
|
...finance.length ? { finance } : {},
|
|
6190
|
-
...
|
|
6191
|
-
...
|
|
7180
|
+
...open2.deals.length ? { deals: open2.deals } : {},
|
|
7181
|
+
...open2.more ? { deals_more: open2.more } : {}
|
|
6192
7182
|
}, {
|
|
6193
7183
|
...next.length ? { next: next.map(asAction) } : {},
|
|
6194
7184
|
...gaps.length ? { missing: gaps } : {},
|
|
6195
7185
|
meta
|
|
6196
|
-
}), [projectStatusText(found, hints), ...financeText(finance), ...dealsText(
|
|
7186
|
+
}), [projectStatusText(found, hints), ...financeText(finance), ...dealsText(open2)].join("\n"), options.compact === true);
|
|
6197
7187
|
}), "projectStatusCommand");
|
|
6198
7188
|
|
|
6199
7189
|
// dist/knowledge/project-transfer.js
|
|
@@ -6365,9 +7355,9 @@ var pending = /* @__PURE__ */ __name(async (store, about) => {
|
|
|
6365
7355
|
};
|
|
6366
7356
|
}, "pending");
|
|
6367
7357
|
var listRelationships = /* @__PURE__ */ __name(async (store, words) => {
|
|
6368
|
-
const
|
|
6369
|
-
const about =
|
|
6370
|
-
const confirmed =
|
|
7358
|
+
const terms2 = queryTerms(words, RELATIONSHIP_QUERY, "relationships list");
|
|
7359
|
+
const about = terms2.get("about");
|
|
7360
|
+
const confirmed = terms2.get("confirmed");
|
|
6371
7361
|
const found = confirmed === "false" ? await pending(store, about) : {
|
|
6372
7362
|
hasMore: false,
|
|
6373
7363
|
items: (await store.knowledge.relations(null, about)).filter((one2) => confirmed === void 0 || one2.confirmed).map((one2) => ({ ...one2, status: one2.confirmed ? "confirmed" : "proposed" }))
|
|
@@ -6473,7 +7463,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
6473
7463
|
return ownedList("projects key-documents list", options, async (store) => keyDocuments(store, await projectOf(store, project), id === void 0 ? {} : { id }));
|
|
6474
7464
|
});
|
|
6475
7465
|
const relations = program.command("relationships").description("relations between people, organizations and projects; never between identities");
|
|
6476
|
-
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) => {
|
|
6477
7467
|
const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "state it as yours?" });
|
|
6478
7468
|
return owned(options, async (store) => {
|
|
6479
7469
|
const input = {
|
|
@@ -6490,7 +7480,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
6490
7480
|
const found = await withStore(env, (store) => listRelationships(store, words));
|
|
6491
7481
|
print(options.json, listAnswer("relationships list", { items: found.items, limit: found.limit, has_more: found.hasMore }), relationshipsText(found.items));
|
|
6492
7482
|
});
|
|
6493
|
-
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) => {
|
|
6494
7484
|
const change = {
|
|
6495
7485
|
...options.role === void 0 ? {} : { role: options.role === "" ? null : options.role },
|
|
6496
7486
|
...options.purpose === void 0 ? {} : { purpose: options.purpose }
|
|
@@ -6582,7 +7572,7 @@ var party2 = /* @__PURE__ */ __name((reference2, name2) => [
|
|
|
6582
7572
|
...name2 && fold3(name2) ? [`name:${fold3(name2)}`] : []
|
|
6583
7573
|
], "party");
|
|
6584
7574
|
var text = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim() ? value : void 0, "text");
|
|
6585
|
-
var present = /* @__PURE__ */ __name((
|
|
7575
|
+
var present = /* @__PURE__ */ __name((parts2) => parts2.filter((part) => part !== void 0), "present");
|
|
6586
7576
|
var keysOf = /* @__PURE__ */ __name((finding) => {
|
|
6587
7577
|
const raw = finding ?? {};
|
|
6588
7578
|
const [shop, number2, url, id] = [raw.supplierName, raw.number, raw.sourceUrl, raw.externalId].map(text);
|
|
@@ -6714,7 +7704,7 @@ var oneMailboxOf = /* @__PURE__ */ __name(async (store, env, source) => {
|
|
|
6714
7704
|
throw new CliError("validation_error", `${source} is not a mailbox \u2014 ${MAIL_SOURCES}`, { param: "source" });
|
|
6715
7705
|
return key;
|
|
6716
7706
|
}, "oneMailboxOf");
|
|
6717
|
-
var
|
|
7707
|
+
var named3 = /* @__PURE__ */ __name((commands2, name2) => {
|
|
6718
7708
|
const found = commands2.find((command) => command.name() === name2);
|
|
6719
7709
|
if (!found)
|
|
6720
7710
|
throw new Error(`cli-core's mail commands have no ${name2}`);
|
|
@@ -6734,10 +7724,10 @@ var mailReviewCommands = /* @__PURE__ */ __name((mail, messages, env) => {
|
|
|
6734
7724
|
}
|
|
6735
7725
|
};
|
|
6736
7726
|
const shared = mailReadCommands(reads);
|
|
6737
|
-
const review =
|
|
6738
|
-
const sharedMessages =
|
|
6739
|
-
const acknowledge =
|
|
6740
|
-
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");
|
|
6741
7731
|
for (const command of [review, acknowledge, reset])
|
|
6742
7732
|
overrideSharedContract(command, "memo holds several mailboxes and no profile, so --source names the one mailbox; its --json is per command.", (one2) => {
|
|
6743
7733
|
one2.option("--source <accounts>", MAILBOX_HELP).option("--json", "print JSON; --json=id,title keeps only those fields");
|
|
@@ -6792,39 +7782,39 @@ var keyed = /* @__PURE__ */ __name((text3, key) => {
|
|
|
6792
7782
|
}
|
|
6793
7783
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
6794
7784
|
return text3;
|
|
6795
|
-
const
|
|
6796
|
-
if (
|
|
6797
|
-
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`, {
|
|
6798
7788
|
reason: "findings.key-mismatch",
|
|
6799
|
-
key: String(
|
|
7789
|
+
key: String(named5),
|
|
6800
7790
|
given: key
|
|
6801
7791
|
});
|
|
6802
7792
|
return JSON.stringify({ ...raw, key });
|
|
6803
7793
|
}, "keyed");
|
|
6804
|
-
var
|
|
7794
|
+
var json3 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
|
|
6805
7795
|
var mailFindingsCommand = /* @__PURE__ */ __name((program, mail, streams, env) => {
|
|
6806
7796
|
const { run } = answers(program, streams, env);
|
|
6807
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");
|
|
6808
|
-
|
|
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) => {
|
|
6809
7799
|
const read = await readFindingsInput(file, environmentOf(program).stdin ?? process.stdin);
|
|
6810
|
-
const text3 = keyed(read,
|
|
6811
|
-
const input =
|
|
7800
|
+
const text3 = keyed(read, given2.key);
|
|
7801
|
+
const input = given2.dryRun ? readMailFindingsJson(text3) : parseMailFindingsJson(text3);
|
|
6812
7802
|
const author = await whoRuns(program, env, { question: "" });
|
|
6813
7803
|
const agent = author === "owner" ? { bot: "memo-mail-findings" } : author;
|
|
6814
|
-
await run(
|
|
6815
|
-
const mailbox = await oneMailboxOf(store, env,
|
|
7804
|
+
await run(given2.json, async (store) => {
|
|
7805
|
+
const mailbox = await oneMailboxOf(store, env, given2.source);
|
|
6816
7806
|
const { input: kept, duplicates } = await withoutDuplicates(store, input);
|
|
6817
7807
|
const noted = duplicates.length ? { duplicates } : {};
|
|
6818
7808
|
if (duplicates.length > 0 && kept.findings.length === 0)
|
|
6819
7809
|
return itemAnswer({
|
|
6820
|
-
dryRun: Boolean(
|
|
7810
|
+
dryRun: Boolean(given2.dryRun),
|
|
6821
7811
|
valid: true,
|
|
6822
7812
|
staged: false,
|
|
6823
7813
|
findings: 0,
|
|
6824
7814
|
problems: [],
|
|
6825
7815
|
...noted
|
|
6826
7816
|
});
|
|
6827
|
-
if (!
|
|
7817
|
+
if (!given2.dryRun)
|
|
6828
7818
|
return itemAnswer({ ...await store.mailFindings.stage(mailbox, kept, agent), ...noted });
|
|
6829
7819
|
const checked = await store.mailFindings.check(mailbox, kept, agent);
|
|
6830
7820
|
const issues = checked.problems.map((one2) => ({
|
|
@@ -6835,22 +7825,22 @@ var mailFindingsCommand = /* @__PURE__ */ __name((program, mail, streams, env) =
|
|
|
6835
7825
|
return itemAnswer({ dryRun: true, ...checked, ...noted }, issues.length ? { meta: { complete: false, issues } } : void 0);
|
|
6836
7826
|
});
|
|
6837
7827
|
});
|
|
6838
|
-
|
|
6839
|
-
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) => {
|
|
6840
7830
|
const status = queryTerms(words, FINDINGS_QUERY2, "mail findings list").get("status");
|
|
6841
|
-
const account2 =
|
|
7831
|
+
const account2 = given2.source ? await oneMailboxOf(store, env, given2.source) : void 0;
|
|
6842
7832
|
const found = await store.mailFindings.list({
|
|
6843
|
-
limit:
|
|
6844
|
-
offset: (
|
|
7833
|
+
limit: given2.limit,
|
|
7834
|
+
offset: (given2.page - 1) * given2.limit,
|
|
6845
7835
|
...account2 === void 0 ? {} : { account: account2 },
|
|
6846
7836
|
...status === void 0 ? {} : { status }
|
|
6847
7837
|
});
|
|
6848
7838
|
return listAnswer("mail findings list", {
|
|
6849
7839
|
items: found.items,
|
|
6850
|
-
limit:
|
|
6851
|
-
page:
|
|
7840
|
+
limit: given2.limit,
|
|
7841
|
+
page: given2.page,
|
|
6852
7842
|
has_more: found.hasMore,
|
|
6853
|
-
args: { query: words.join(" "), ...
|
|
7843
|
+
args: { query: words.join(" "), ...given2.source ? { source: given2.source } : {}, limit: given2.limit }
|
|
6854
7844
|
});
|
|
6855
7845
|
}));
|
|
6856
7846
|
}, "mailFindingsCommand");
|
|
@@ -6976,10 +7966,10 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
|
|
|
6976
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) => {
|
|
6977
7967
|
if (!options.http && (options.port !== void 0 || options.publicUrl !== void 0))
|
|
6978
7968
|
throw new CliError("validation_error", "--port and --public-url require --http");
|
|
6979
|
-
const { createMemoServer } = await import("./server-
|
|
7969
|
+
const { createMemoServer } = await import("./server-XKSIHWM2.js");
|
|
6980
7970
|
const build = /* @__PURE__ */ __name(() => createMemoServer(env, createProgram2, options.permission), "build");
|
|
6981
7971
|
if (options.http) {
|
|
6982
|
-
const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-
|
|
7972
|
+
const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-QX2D6EXA.js");
|
|
6983
7973
|
const publicUrl = publicUrlOf(options.publicUrl, {
|
|
6984
7974
|
missing: "--http",
|
|
6985
7975
|
reaches: "the browser apps reach memo",
|
|
@@ -7031,7 +8021,7 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
|
|
|
7031
8021
|
});
|
|
7032
8022
|
});
|
|
7033
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() {
|
|
7034
|
-
const { revokeAll } = await import("./mcp-
|
|
8024
|
+
const { revokeAll } = await import("./mcp-QX2D6EXA.js");
|
|
7035
8025
|
revokeAll(httpTokenFile(env));
|
|
7036
8026
|
out.print(this.opts().json, itemAnswer({ revoked: true }));
|
|
7037
8027
|
});
|
|
@@ -7094,28 +8084,28 @@ var readStoredMeetingPassage = /* @__PURE__ */ __name(async (store, env, source,
|
|
|
7094
8084
|
// dist/meetings/command.js
|
|
7095
8085
|
var meetingReadCommands = /* @__PURE__ */ __name((program, streams, env) => {
|
|
7096
8086
|
const { print } = answers(program, streams, env);
|
|
7097
|
-
const source = /* @__PURE__ */ __name((
|
|
8087
|
+
const source = /* @__PURE__ */ __name((given2) => sourceOf(given2, (text3) => streams.diagnostic(text3)), "source");
|
|
7098
8088
|
const output = /* @__PURE__ */ __name((command) => sourceOptions(command, MEETING_ACCOUNT_HELP).option("--json", "print the standard JSON answer"), "output");
|
|
7099
8089
|
const grammar = createMeetingSearchCommand(program);
|
|
7100
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) => {
|
|
7101
8091
|
Reflect.set(command, "options", command.options.filter((option) => option.long !== "--tag"));
|
|
7102
8092
|
output(command);
|
|
7103
8093
|
});
|
|
7104
|
-
search2.action(async (query,
|
|
7105
|
-
const input = meetingHitSearchRequest(query,
|
|
7106
|
-
const result = await withStore(env, (store) => searchStoredMeetings(store, env, source(
|
|
7107
|
-
...
|
|
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,
|
|
7108
8098
|
timesReadIn: grammar.getOptionValue("timesReadIn")
|
|
7109
8099
|
}));
|
|
7110
|
-
print(
|
|
8100
|
+
print(given2.json, result);
|
|
7111
8101
|
});
|
|
7112
8102
|
overrideSharedContract(createMeetingPassageCommand(program), "Memo passage reads an explicitly selected stored source and exposes command-local JSON output.", (command) => {
|
|
7113
8103
|
output(command);
|
|
7114
|
-
}).action(async (reference2,
|
|
7115
|
-
const format =
|
|
7116
|
-
const input = meetingPassageRequest(reference2, { ...
|
|
7117
|
-
const result = await withStore(env, (store) => readStoredMeetingPassage(store, env, source(
|
|
7118
|
-
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);
|
|
7119
8109
|
});
|
|
7120
8110
|
}, "meetingReadCommands");
|
|
7121
8111
|
|
|
@@ -7128,13 +8118,13 @@ var communicationSource = /* @__PURE__ */ __name(async (store, env, id) => {
|
|
|
7128
8118
|
});
|
|
7129
8119
|
const key = await oneAccountOf(store, env, `${id.slice(0, dot)}:${id.slice(dot + 1)}`, "--context-source");
|
|
7130
8120
|
const held = await store.accounts.storedAccount(key);
|
|
7131
|
-
const
|
|
8121
|
+
const listed2 = entriesOfList(accountName(key), {
|
|
7132
8122
|
held: [held],
|
|
7133
8123
|
profiles: {},
|
|
7134
8124
|
groups: {},
|
|
7135
8125
|
running: { provider: "email", command: "memo" }
|
|
7136
8126
|
})[0]?.accounts[0];
|
|
7137
|
-
const kind =
|
|
8127
|
+
const kind = listed2?.kind === "messages" ? "message" : listed2?.kind === "mail" ? "mail" : void 0;
|
|
7138
8128
|
if (kind === void 0)
|
|
7139
8129
|
throw new CliError("validation_error", `${id}: select one stored messenger profile or mailbox`, {
|
|
7140
8130
|
param: "communications.sources"
|
|
@@ -7512,8 +8502,8 @@ var refuseOverMcp = /* @__PURE__ */ __name((options, mcp2) => {
|
|
|
7512
8502
|
param: "export"
|
|
7513
8503
|
});
|
|
7514
8504
|
}, "refuseOverMcp");
|
|
7515
|
-
var textOf = /* @__PURE__ */ __name((options,
|
|
7516
|
-
const sources = [
|
|
8505
|
+
var textOf = /* @__PURE__ */ __name((options, given2) => {
|
|
8506
|
+
const sources = [given2, options.text, options.textFile].filter((value) => value !== void 0);
|
|
7517
8507
|
if (sources.length !== 1)
|
|
7518
8508
|
throw new CliError("validation_error", "give the text once: as an argument, --text or --text-file");
|
|
7519
8509
|
if (options.textFile !== void 0)
|
|
@@ -7577,14 +8567,14 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
7577
8567
|
...answer.backlinks.length ? [`linked from: ${answer.backlinks.map(({ from }) => from).join(", ")}`] : []
|
|
7578
8568
|
].join("\n"));
|
|
7579
8569
|
});
|
|
7580
|
-
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:
|
|
7581
|
-
const
|
|
7582
|
-
const about =
|
|
7583
|
-
const source =
|
|
7584
|
-
const search2 =
|
|
7585
|
-
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)
|
|
7586
8576
|
throw new CliError("validation_error", "about: stands alone in notes list: its notes are found through links");
|
|
7587
|
-
const options = { ...paging, json:
|
|
8577
|
+
const options = { ...paging, json: json5 };
|
|
7588
8578
|
const page = await withNotes(async (store) => listNotes(store, {
|
|
7589
8579
|
limit: options.limit,
|
|
7590
8580
|
offset: (options.page - 1) * options.limit,
|
|
@@ -7603,9 +8593,9 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
7603
8593
|
output: { entity: "note" },
|
|
7604
8594
|
literal_after_dashes: true
|
|
7605
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");
|
|
7606
|
-
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) => {
|
|
7607
8597
|
refuseOverMcp(options, isMcpRun(command, env));
|
|
7608
|
-
const body = textOf(options,
|
|
8598
|
+
const body = textOf(options, given2);
|
|
7609
8599
|
const value = writeAccountOf(options, (text3) => streams.diagnostic(text3));
|
|
7610
8600
|
if (options.meeting === void 0 && value !== void 0)
|
|
7611
8601
|
throw new CliError("validation_error", "--account selects the account of --meeting");
|
|
@@ -7886,8 +8876,105 @@ var peopleCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
7886
8876
|
});
|
|
7887
8877
|
}, "peopleCommand");
|
|
7888
8878
|
|
|
7889
|
-
// dist/records/
|
|
7890
|
-
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");
|
|
7891
8978
|
|
|
7892
8979
|
// dist/records/mapping.js
|
|
7893
8980
|
var RECORD_QUERY = {
|
|
@@ -7896,7 +8983,11 @@ var RECORD_QUERY = {
|
|
|
7896
8983
|
fields: [
|
|
7897
8984
|
termField("type", "kw", "type:organization"),
|
|
7898
8985
|
termField("waiting", "bool", "waiting:true"),
|
|
7899
|
-
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")
|
|
7900
8991
|
]
|
|
7901
8992
|
};
|
|
7902
8993
|
var sourceOf4 = /* @__PURE__ */ __name((account2) => {
|
|
@@ -7909,84 +9000,149 @@ var sourceOf4 = /* @__PURE__ */ __name((account2) => {
|
|
|
7909
9000
|
return { provider, account: name2 };
|
|
7910
9001
|
}, "sourceOf");
|
|
7911
9002
|
var recordOf = /* @__PURE__ */ __name((record2) => {
|
|
7912
|
-
const
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
});
|
|
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" });
|
|
7917
9007
|
return { type: record2.slice(0, at), externalId: record2.slice(at + 1) };
|
|
7918
9008
|
}, "recordOf");
|
|
9009
|
+
var RECORD_HELP = "<type>:<external_id> as the source names it, such as organization:client or custom:quote:Q-7";
|
|
7919
9010
|
var ACCOUNT_HELP = "the source, <provider>:<account> as the envelope's source names it, such as sheet:rentals";
|
|
7920
9011
|
var recordMappingCommands = /* @__PURE__ */ __name((records, program, streams, env) => {
|
|
7921
9012
|
const { run } = answers(program, streams, env);
|
|
7922
|
-
withQuery(annotate(records.command("list"), { effects: LOCAL_READ }).description("a source's records, newest first; waiting:true lists those whose
|
|
7923
|
-
const source = sourceOf4(
|
|
7924
|
-
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");
|
|
7925
9016
|
const filter = {
|
|
7926
9017
|
...source,
|
|
7927
|
-
...
|
|
7928
|
-
...
|
|
7929
|
-
...
|
|
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" } : {}
|
|
7930
9025
|
};
|
|
7931
|
-
return pageOf("records list",
|
|
9026
|
+
return pageOf("records list", given2.limit, (most) => store.records.list({ ...filter, limit: most }));
|
|
7932
9027
|
}));
|
|
7933
|
-
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>",
|
|
7934
|
-
const by = await whoRuns(command, env, { asOwner:
|
|
7935
|
-
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)));
|
|
7936
9031
|
});
|
|
7937
9032
|
}, "recordMappingCommands");
|
|
7938
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
|
+
|
|
7939
9095
|
// dist/records/import.js
|
|
7940
|
-
var
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
let text3 = "";
|
|
7944
|
-
stdin.setEncoding("utf8");
|
|
7945
|
-
for await (const chunk of stdin)
|
|
7946
|
-
text3 += chunk;
|
|
7947
|
-
return text3;
|
|
7948
|
-
}, "readAll");
|
|
7949
|
-
var envelopeOf = /* @__PURE__ */ __name((text3) => {
|
|
7950
|
-
try {
|
|
7951
|
-
const whole2 = JSON.parse(text3);
|
|
7952
|
-
if (whole2 && typeof whole2 === "object" && "records" in whole2)
|
|
7953
|
-
return whole2;
|
|
7954
|
-
} catch {
|
|
7955
|
-
}
|
|
7956
|
-
return envelopeOfJsonl(text3);
|
|
7957
|
-
}, "envelopeOf");
|
|
7958
|
-
var accountIn = /* @__PURE__ */ __name((envelope, given) => {
|
|
7959
|
-
const provider = envelope?.source?.provider;
|
|
7960
|
-
return typeof provider === "string" && given.startsWith(`${provider}:`) ? given.slice(provider.length + 1) : given;
|
|
7961
|
-
}, "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");
|
|
7962
9099
|
var receiptText = /* @__PURE__ */ __name((receipt) => [
|
|
7963
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`,
|
|
7964
|
-
...receipt.proposed.length ? [
|
|
9101
|
+
...receipt.proposed.length ? [
|
|
9102
|
+
`proposed for your review (memo review list kind:${kindsOf(receipt.proposed).join(",")}): ` + receipt.proposed.join(" ")
|
|
9103
|
+
] : [],
|
|
7965
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`),
|
|
7966
9106
|
...receipt.flagged.map((one2) => `changed at the source ${one2.key}: ${one2.entity} kept as it was`),
|
|
7967
|
-
...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"] : []
|
|
7968
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";
|
|
7969
9113
|
var recordsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
7970
|
-
const
|
|
7971
|
-
const
|
|
7972
|
-
const
|
|
7973
|
-
|
|
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();
|
|
7974
9119
|
if (!account2)
|
|
7975
9120
|
throw new CliError("validation_error", "name the source account the envelope is for: --account <account>", {
|
|
7976
9121
|
param: "--account"
|
|
7977
9122
|
});
|
|
7978
|
-
const
|
|
7979
|
-
|
|
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
|
+
}));
|
|
7980
9131
|
const issues = receipt.errors.map((one2) => ({
|
|
7981
9132
|
code: "validation_error",
|
|
7982
|
-
source: one2.pointer,
|
|
9133
|
+
source: pointerOf(one2.pointer),
|
|
7983
9134
|
reason: one2.code
|
|
7984
9135
|
}));
|
|
7985
|
-
print(
|
|
9136
|
+
print(given2.json, itemAnswer(receipt, issues.length ? { meta: { complete: false, issues } } : void 0), receiptText(receipt));
|
|
7986
9137
|
}), "importing");
|
|
7987
|
-
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
|
|
7988
|
-
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
|
+
);
|
|
7989
9144
|
recordMappingCommands(records, program, streams, env);
|
|
9145
|
+
recordCommands(records, answered, (work) => withStore(env, work));
|
|
7990
9146
|
}, "recordsCommand");
|
|
7991
9147
|
|
|
7992
9148
|
// dist/digest/known.js
|
|
@@ -8049,25 +9205,38 @@ var schedulesOf = /* @__PURE__ */ __name((state) => {
|
|
|
8049
9205
|
}
|
|
8050
9206
|
});
|
|
8051
9207
|
}, "schedulesOf");
|
|
8052
|
-
var
|
|
9208
|
+
var signedIn = /* @__PURE__ */ __name((dir) => existsSync6(dir) ? readdirSync4(dir).filter((name2) => name2.endsWith(".json")).map((name2) => name2.slice(0, -".json".length)) : [], "signedIn");
|
|
9209
|
+
var profilesOf = /* @__PURE__ */ __name((provider, tool, env) => {
|
|
9210
|
+
if (provider !== "email")
|
|
9211
|
+
return new Map(signedIn(join9(stateDirs(tool, env).state, "accounts")).map((profile) => [
|
|
9212
|
+
profile,
|
|
9213
|
+
signedInAccount(tool, profile, env)
|
|
9214
|
+
]));
|
|
8053
9215
|
try {
|
|
8054
9216
|
const config = JSON.parse(readFileSync8(configFilePath(stateDirs(MAIL2, env).config), "utf8"));
|
|
8055
|
-
return config?.profiles
|
|
9217
|
+
return new Map(Object.entries(config?.profiles ?? {}).map(([profile, one2]) => [
|
|
9218
|
+
profile,
|
|
9219
|
+
one2?.address
|
|
9220
|
+
]));
|
|
8056
9221
|
} catch {
|
|
8057
|
-
return
|
|
9222
|
+
return /* @__PURE__ */ new Map();
|
|
8058
9223
|
}
|
|
8059
|
-
}, "
|
|
8060
|
-
var
|
|
9224
|
+
}, "profilesOf");
|
|
9225
|
+
var profileRun = /* @__PURE__ */ __name((schedule, tool, profiles) => {
|
|
9226
|
+
const first = schedule.argv[0];
|
|
9227
|
+
return first !== void 0 && profiles.has(first) ? first : schedule.environment[`${tool.envPrefix}_PROFILE`] ?? "default";
|
|
9228
|
+
}, "profileRun");
|
|
8061
9229
|
var syncRunsOf = /* @__PURE__ */ __name((env) => {
|
|
8062
9230
|
const cache = /* @__PURE__ */ new Map();
|
|
8063
|
-
const read = /* @__PURE__ */ __name((tool) => {
|
|
9231
|
+
const read = /* @__PURE__ */ __name((provider, tool) => {
|
|
8064
9232
|
const known2 = cache.get(tool.appName);
|
|
8065
9233
|
if (known2)
|
|
8066
9234
|
return known2;
|
|
8067
9235
|
const app = { ...APP, appName: tool.appName, envPrefix: tool.envPrefix };
|
|
8068
9236
|
const fresh = {
|
|
8069
9237
|
schedules: schedulesOf(stateDirs(tool, env).state).filter((one2) => one2.kind === "command" && one2.argv.includes("sync")),
|
|
8070
|
-
serving: servingProfiles(app, env)
|
|
9238
|
+
serving: servingProfiles(app, env),
|
|
9239
|
+
profiles: profilesOf(provider, tool, env)
|
|
8071
9240
|
};
|
|
8072
9241
|
cache.set(tool.appName, fresh);
|
|
8073
9242
|
return fresh;
|
|
@@ -8075,22 +9244,27 @@ var syncRunsOf = /* @__PURE__ */ __name((env) => {
|
|
|
8075
9244
|
return (key) => {
|
|
8076
9245
|
const tool = toolOf(key.provider);
|
|
8077
9246
|
if (!tool)
|
|
8078
|
-
return { runs: [], scheduled: false, serving: false };
|
|
8079
|
-
const { schedules, serving } = read(tool);
|
|
8080
|
-
const mine =
|
|
9247
|
+
return { runs: [], scheduled: false, serving: false, known: false };
|
|
9248
|
+
const { schedules, serving, profiles } = read(key.provider, tool);
|
|
9249
|
+
const mine = new Set([...profiles].filter(([, account2]) => account2 === key.account).map(([profile]) => profile));
|
|
9250
|
+
const runs = schedules.filter((one2) => mine.has(profileRun(one2, tool, profiles)));
|
|
8081
9251
|
return {
|
|
8082
|
-
runs:
|
|
8083
|
-
scheduled:
|
|
8084
|
-
serving: serving.some((profile) =>
|
|
9252
|
+
runs: runs.flatMap((one2) => one2.last ? [one2.last] : []),
|
|
9253
|
+
scheduled: runs.length > 0,
|
|
9254
|
+
serving: serving.some((profile) => mine.has(profile)),
|
|
9255
|
+
known: mine.size > 0
|
|
8085
9256
|
};
|
|
8086
9257
|
};
|
|
8087
9258
|
}, "syncRunsOf");
|
|
8088
9259
|
var HOUR = 36e5;
|
|
8089
|
-
var
|
|
8090
|
-
var QUIET_AFTER = 3 *
|
|
9260
|
+
var DAY5 = 24 * HOUR;
|
|
9261
|
+
var QUIET_AFTER = 3 * DAY5;
|
|
8091
9262
|
var QUIET_GAPS = 3;
|
|
8092
9263
|
var hours = /* @__PURE__ */ __name((from, now) => Math.max(0, Math.floor((now - from) / HOUR)), "hours");
|
|
8093
9264
|
var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
|
|
9265
|
+
const recent = /* @__PURE__ */ __name((at) => at !== null && at >= now - DAY5, "recent");
|
|
9266
|
+
if (recent(activity.storedAt) || sync.runs.some((run) => run.exitCode === 0 && recent(Date.parse(run.at))))
|
|
9267
|
+
return void 0;
|
|
8094
9268
|
if (!sync.serving && sync.runs.length > 0 && sync.runs.every((run) => run.exitCode !== 0)) {
|
|
8095
9269
|
const first = [...sync.runs].sort((a, b) => (a.failingSince ?? a.at).localeCompare(b.failingSince ?? b.at))[0];
|
|
8096
9270
|
const since = first?.failingSince ?? first?.at ?? new Date(now).toISOString();
|
|
@@ -8101,15 +9275,15 @@ var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
|
|
|
8101
9275
|
...first?.reason ? { failure: first.reason } : {}
|
|
8102
9276
|
};
|
|
8103
9277
|
}
|
|
8104
|
-
if (!sync.scheduled && !sync.serving)
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
9278
|
+
if (!sync.scheduled && !sync.serving) {
|
|
9279
|
+
if (!sync.known)
|
|
9280
|
+
return void 0;
|
|
9281
|
+
const last = activity.newest ?? activity.storedAt;
|
|
9282
|
+
return { reason: "no-schedule", since: null, staleHours: last === null ? 0 : hours(last, now) };
|
|
9283
|
+
}
|
|
8110
9284
|
if (activity.newest === null || activity.moved30d === 0)
|
|
8111
9285
|
return void 0;
|
|
8112
|
-
const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 *
|
|
9286
|
+
const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 * DAY5 / activity.moved30d);
|
|
8113
9287
|
if (activity.newest < now - usual)
|
|
8114
9288
|
return { reason: "quiet", since: new Date(activity.newest).toISOString(), staleHours: hours(activity.newest, now) };
|
|
8115
9289
|
return void 0;
|
|
@@ -8284,13 +9458,13 @@ var countTasks = /* @__PURE__ */ __name(async (store, words) => {
|
|
|
8284
9458
|
|
|
8285
9459
|
// dist/digest/tasks.js
|
|
8286
9460
|
var DIGEST_SCHEDULE = "morning-digest";
|
|
8287
|
-
var
|
|
9461
|
+
var DAY6 = 864e5;
|
|
8288
9462
|
var previousDigestAt = /* @__PURE__ */ __name((env, now) => {
|
|
8289
9463
|
const state = resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env }).state;
|
|
8290
9464
|
const digest = schedulesOf(state).find((one2) => one2.name === DIGEST_SCHEDULE || one2.kind === "agent" && one2.argv.join(" ").includes(DIGEST_SCHEDULE));
|
|
8291
9465
|
const last = digest?.last;
|
|
8292
9466
|
if (!last)
|
|
8293
|
-
return new Date(now -
|
|
9467
|
+
return new Date(now - DAY6).toISOString();
|
|
8294
9468
|
return last.exitCode === 0 ? last.at : last.failingSince ?? last.at;
|
|
8295
9469
|
}, "previousDigestAt");
|
|
8296
9470
|
var dayOf2 = /* @__PURE__ */ __name((zone) => {
|
|
@@ -8332,7 +9506,7 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
|
|
|
8332
9506
|
const zone = timezoneOf();
|
|
8333
9507
|
const day2 = dayOf2(zone);
|
|
8334
9508
|
const today2 = day2(now);
|
|
8335
|
-
const tomorrow = day2(now +
|
|
9509
|
+
const tomorrow = day2(now + DAY6);
|
|
8336
9510
|
const since = Date.parse(newSince);
|
|
8337
9511
|
const seen = /* @__PURE__ */ new Map();
|
|
8338
9512
|
let accounts = 0;
|
|
@@ -8348,11 +9522,13 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
|
|
|
8348
9522
|
accounts++;
|
|
8349
9523
|
for (const task of projects)
|
|
8350
9524
|
seen.set(task.id, task);
|
|
8351
|
-
const counts = { overdue: 0, today: 0, tomorrow: 0, new: 0, newSince };
|
|
9525
|
+
const counts = { overdue: 0, today: 0, tomorrow: 0, new: 0, newSince, undated: 0 };
|
|
8352
9526
|
const tasks = [];
|
|
8353
9527
|
for (const task of seen.values()) {
|
|
8354
9528
|
const groups = [];
|
|
8355
9529
|
const due = task.dueAt === null ? null : day2(Date.parse(task.dueAt));
|
|
9530
|
+
if (due === null)
|
|
9531
|
+
counts.undated++;
|
|
8356
9532
|
if (due !== null && due < today2)
|
|
8357
9533
|
groups.push("overdue");
|
|
8358
9534
|
if (due === today2)
|
|
@@ -8378,7 +9554,7 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
|
|
|
8378
9554
|
|
|
8379
9555
|
// dist/digest/digest.js
|
|
8380
9556
|
var WATCH_TAG = "watch";
|
|
8381
|
-
var
|
|
9557
|
+
var DAY7 = 864e5;
|
|
8382
9558
|
var MESSENGERS2 = /* @__PURE__ */ new Set(["telegram", "max", "whatsapp"]);
|
|
8383
9559
|
var HEALTH_ORDER = HEALTH_REASONS;
|
|
8384
9560
|
var UNNAMED = "unnamed account";
|
|
@@ -8407,8 +9583,8 @@ var labelsOf = /* @__PURE__ */ __name(async (store, keys) => {
|
|
|
8407
9583
|
}
|
|
8408
9584
|
const person = await store.people.personOf({ provider: key.provider, id: key.account });
|
|
8409
9585
|
const username = person?.identities.find((one2) => one2.provider === key.provider && one2.id === key.account)?.username;
|
|
8410
|
-
const
|
|
8411
|
-
const label = [
|
|
9586
|
+
const given2 = stored.get(name(key));
|
|
9587
|
+
const label = [given2 && given2 !== key.account ? given2 : null, username ? `@${username}` : null].filter(Boolean).join(" ");
|
|
8412
9588
|
const profile = profileOf(key);
|
|
8413
9589
|
labels.set(name(key), label || (profile ? `profile ${profile}` : UNNAMED));
|
|
8414
9590
|
}
|
|
@@ -8463,8 +9639,8 @@ var statusLine = /* @__PURE__ */ __name((data) => {
|
|
|
8463
9639
|
}, "statusLine");
|
|
8464
9640
|
var personal = /* @__PURE__ */ __name((newest) => !newest.bulk && !newest.list && !newest.envelope && !newest.demoted, "personal");
|
|
8465
9641
|
var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date.now(), limit, excerpt: excerpt2, owedWithin, newSince }) => {
|
|
8466
|
-
const window = (now - since) /
|
|
8467
|
-
const
|
|
9642
|
+
const window = (now - since) / DAY7;
|
|
9643
|
+
const days2 = `${Math.max(1, Math.ceil(window))}d`;
|
|
8468
9644
|
const accounts = await store.accounts.accounts();
|
|
8469
9645
|
const messengers2 = accounts.filter((key) => MESSENGERS2.has(key.provider));
|
|
8470
9646
|
const mailboxes = accounts.filter((key) => key.provider === "email");
|
|
@@ -8520,10 +9696,11 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8520
9696
|
let mailMoved = 0;
|
|
8521
9697
|
for (const key of messengers2) {
|
|
8522
9698
|
const { chats, storedAt } = await store.chats.chatActivity(key, owedSince);
|
|
8523
|
-
const month = (await store.chats.chatActivity(key, now - 30 *
|
|
9699
|
+
const month = (await store.chats.chatActivity(key, now - 30 * DAY7)).chats;
|
|
8524
9700
|
checkHealth(key, {
|
|
8525
9701
|
newest: month.reduce((most, chat) => Math.max(most ?? 0, Date.parse(chat.lastMessageAt)), null),
|
|
8526
|
-
moved30d: month.length
|
|
9702
|
+
moved30d: month.length,
|
|
9703
|
+
storedAt: storedAt === null ? null : Date.parse(storedAt)
|
|
8527
9704
|
});
|
|
8528
9705
|
const ref = /* @__PURE__ */ __name((chat) => formatReference({ type: "chat", provider: key.provider, account: key.account, chat }), "ref");
|
|
8529
9706
|
chatsMoved += chats.filter((chat) => Date.parse(chat.lastMessageAt) >= since).length;
|
|
@@ -8546,7 +9723,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8546
9723
|
owedHere++;
|
|
8547
9724
|
}
|
|
8548
9725
|
if (owedHere)
|
|
8549
|
-
owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin /
|
|
9726
|
+
owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin / DAY7)}d`);
|
|
8550
9727
|
for (const chatId of watched.chats.get(name(key)) ?? []) {
|
|
8551
9728
|
const page = await store.messages.messages(key, chatId, { limit, since: iso(since) });
|
|
8552
9729
|
for (const message of page.items)
|
|
@@ -8569,12 +9746,13 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8569
9746
|
}
|
|
8570
9747
|
for (const key of mailboxes) {
|
|
8571
9748
|
const stored = await store.accounts.storedAccount(key);
|
|
8572
|
-
const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS *
|
|
9749
|
+
const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS * DAY7));
|
|
8573
9750
|
const ref = /* @__PURE__ */ __name((thread) => formatReference({ type: "chat", provider: "email", account: key.account, chat: thread }), "ref");
|
|
8574
9751
|
const newest = threads.reduce((most, thread) => Math.max(most, thread.lastEmailAt), 0);
|
|
8575
9752
|
checkHealth(key, {
|
|
8576
9753
|
newest: newest || null,
|
|
8577
|
-
moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 *
|
|
9754
|
+
moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 * DAY7).length,
|
|
9755
|
+
storedAt: newest || null
|
|
8578
9756
|
});
|
|
8579
9757
|
mailMoved += threads.filter((thread) => thread.lastEmailAt >= since && thread.newest !== null && personal(thread.newest)).length;
|
|
8580
9758
|
coverage.push({
|
|
@@ -8631,7 +9809,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8631
9809
|
if (strangers.length)
|
|
8632
9810
|
unknown2.next.push(`memo mail review --source ${name(key)} --unanswered 1m bulk:false`);
|
|
8633
9811
|
if (newHere)
|
|
8634
|
-
mailNext.push(`memo mail review --source ${name(key)} date>${
|
|
9812
|
+
mailNext.push(`memo mail review --source ${name(key)} date>${days2} bulk:false`);
|
|
8635
9813
|
}
|
|
8636
9814
|
for (const uid of watched.people) {
|
|
8637
9815
|
const person = await store.people.personByUid(uid);
|
|
@@ -8705,7 +9883,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
|
|
|
8705
9883
|
const isWatched = watched.projects.has(project.id) || watched.projects.has(project.ref);
|
|
8706
9884
|
if (fresh.length === 0 && !isWatched)
|
|
8707
9885
|
continue;
|
|
8708
|
-
projectNext.push(`memo projects status ${project.key ?? project.ref} --since-time ${
|
|
9886
|
+
projectNext.push(`memo projects status ${project.key ?? project.ref} --since-time ${days2}`);
|
|
8709
9887
|
if (fresh.length === 0)
|
|
8710
9888
|
projects.push({
|
|
8711
9889
|
item: { ref: project.ref, who: null, at: iso(since), excerpt: project.name, why: "watched project, quiet" }
|
|
@@ -8833,21 +10011,21 @@ var sinceOf = /* @__PURE__ */ __name((value, now = Date.now()) => {
|
|
|
8833
10011
|
return since;
|
|
8834
10012
|
}, "sinceOf");
|
|
8835
10013
|
var reviewAgendaCommand = /* @__PURE__ */ __name((review, print, streams, env) => {
|
|
8836
|
-
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 (
|
|
8837
|
-
if (
|
|
10014
|
+
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, as \`undated\`, every open task with no due date, and \`health\` names each account whose sync failed, that nothing syncs, or that is quiet for longer than usual, so an unsynced account does not read as a quiet day; an account stored or synced within a day is never named`).option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").option("--limit <n>", "items per section before the size budget", positive, 25).option("--max-output-bytes <bytes>", "the text answer's size budget in bytes; 40000 with --compact, else 80000", positive).option("--compact", "one line per item, shorter excerpts, the smaller budget: for an agent").option("--json", "print JSON").action(async (given2) => {
|
|
10015
|
+
if (given2.compact && given2.json)
|
|
8838
10016
|
throw new CliError("validation_error", "--compact and --json ask for different output \u2014 pick one", {
|
|
8839
10017
|
reason: "output.conflict",
|
|
8840
10018
|
param: "--compact"
|
|
8841
10019
|
});
|
|
8842
|
-
const since = sinceOf(
|
|
10020
|
+
const since = sinceOf(given2.sinceTime);
|
|
8843
10021
|
const gathered = await withStore(env, (store) => gatherDigest(store, env, {
|
|
8844
10022
|
since,
|
|
8845
|
-
limit:
|
|
8846
|
-
excerpt:
|
|
10023
|
+
limit: given2.limit,
|
|
10024
|
+
excerpt: given2.compact ? 100 : 200,
|
|
8847
10025
|
owedWithin: OWED_WITHIN
|
|
8848
10026
|
}));
|
|
8849
|
-
const digest = fitDigest(gathered,
|
|
8850
|
-
if (
|
|
10027
|
+
const digest = fitDigest(gathered, given2.maxOutputBytes ?? (given2.compact ? COMPACT_BYTES : FULL_BYTES));
|
|
10028
|
+
if (given2.json)
|
|
8851
10029
|
print(true, itemAnswer(digest));
|
|
8852
10030
|
else
|
|
8853
10031
|
streams.data(`${digestText(digest)}
|
|
@@ -8910,32 +10088,32 @@ var ROW = {
|
|
|
8910
10088
|
],
|
|
8911
10089
|
text: ["reason"]
|
|
8912
10090
|
};
|
|
8913
|
-
var
|
|
10091
|
+
var json4 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,title keeps only those fields"), "json");
|
|
8914
10092
|
var reviewCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
8915
10093
|
const { print } = answers(program, streams, env);
|
|
8916
10094
|
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");
|
|
8917
|
-
|
|
8918
|
-
if (
|
|
10095
|
+
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) => {
|
|
10096
|
+
if (given2.limit > 50)
|
|
8919
10097
|
throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
|
|
8920
|
-
const found = await withStore(env, (store) => listReview(store, env, words,
|
|
10098
|
+
const found = await withStore(env, (store) => listReview(store, env, words, given2));
|
|
8921
10099
|
const steps = reviewSteps(found.items);
|
|
8922
10100
|
const body = listAnswer("review list", {
|
|
8923
10101
|
items: found.items,
|
|
8924
|
-
limit:
|
|
8925
|
-
page:
|
|
10102
|
+
limit: given2.limit,
|
|
10103
|
+
page: given2.page,
|
|
8926
10104
|
has_more: found.hasMore,
|
|
8927
|
-
args: { query: words.join(" "), limit:
|
|
10105
|
+
args: { query: words.join(" "), limit: given2.limit },
|
|
8928
10106
|
...steps.length ? { next: steps } : {}
|
|
8929
10107
|
});
|
|
8930
|
-
print(
|
|
10108
|
+
print(given2.json, body, reviewText(found.items, found.hasMore), given2.compact);
|
|
8931
10109
|
});
|
|
8932
|
-
|
|
10110
|
+
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) => {
|
|
8933
10111
|
const body = await withStore(env, async (store) => {
|
|
8934
10112
|
const shown2 = await showReview(store, env, id);
|
|
8935
10113
|
const window = {
|
|
8936
|
-
brief:
|
|
8937
|
-
before: Math.min(
|
|
8938
|
-
after: Math.min(
|
|
10114
|
+
brief: given2.brief === true,
|
|
10115
|
+
before: Math.min(given2.beforeN, 5),
|
|
10116
|
+
after: Math.min(given2.afterN, 5)
|
|
8939
10117
|
};
|
|
8940
10118
|
const evidence = await Promise.all(shown2.evidence.map(async (one2) => {
|
|
8941
10119
|
const sender = window.brief ? null : await senderOf(store, one2.ref);
|
|
@@ -8948,35 +10126,35 @@ var reviewCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
8948
10126
|
}));
|
|
8949
10127
|
return itemAnswer({ ...shown2, evidence });
|
|
8950
10128
|
});
|
|
8951
|
-
print(
|
|
10129
|
+
print(given2.json, body, void 0, given2.compact);
|
|
8952
10130
|
});
|
|
8953
10131
|
for (const name2 of ["confirm", "reject"]) {
|
|
8954
|
-
const command = byOption(
|
|
10132
|
+
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");
|
|
8955
10133
|
if (name2 === "confirm")
|
|
8956
10134
|
command.option("--reason <text>", "why, in a few words; required when an agent decides");
|
|
8957
10135
|
else
|
|
8958
10136
|
command.requiredOption("--reason <text>", "why it is turned down, in a few words");
|
|
8959
10137
|
command.option("--compact", "one line per decision");
|
|
8960
|
-
command.action(async (words,
|
|
10138
|
+
command.action(async (words, given2) => {
|
|
8961
10139
|
const ids = parseProposalIds(words);
|
|
8962
10140
|
const by = await deciderOf(command, env, {
|
|
8963
|
-
...
|
|
10141
|
+
...given2,
|
|
8964
10142
|
question: `${name2} ${ids.length} proposal${ids.length === 1 ? "" : "s"} as you, the owner?`
|
|
8965
10143
|
});
|
|
8966
|
-
const result = await withStore(env, (store) => reviewRegistry(store).decide(ids, decisionOf(name2 === "confirm", by,
|
|
10144
|
+
const result = await withStore(env, (store) => reviewRegistry(store).decide(ids, decisionOf(name2 === "confirm", by, given2.reason)));
|
|
8967
10145
|
const issues = result.refused.map((one2) => ({
|
|
8968
10146
|
code: one2.code,
|
|
8969
10147
|
source: one2.id,
|
|
8970
10148
|
...one2.reason.includes(".") ? { reason: one2.reason } : {}
|
|
8971
10149
|
}));
|
|
8972
|
-
print(
|
|
10150
|
+
print(given2.json, itemAnswer(result, issues.length ? { meta: { complete: false, issues } } : void 0), decidedText(result), given2.compact);
|
|
8973
10151
|
});
|
|
8974
10152
|
}
|
|
8975
10153
|
reviewAgendaCommand(review, print, streams, env);
|
|
8976
|
-
|
|
8977
|
-
const since = sinceOf(
|
|
10154
|
+
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) => {
|
|
10155
|
+
const since = sinceOf(given2.sinceTime);
|
|
8978
10156
|
const status = await withStore(env, (store) => reviewStatus(store, env, since));
|
|
8979
|
-
print(
|
|
10157
|
+
print(given2.json, itemAnswer(status), reviewStatusText(status));
|
|
8980
10158
|
});
|
|
8981
10159
|
}, "reviewCommand");
|
|
8982
10160
|
|
|
@@ -8990,10 +10168,10 @@ var embedPerRun = /* @__PURE__ */ __name((env = process.env) => {
|
|
|
8990
10168
|
return Math.max(8, Math.min(EMBED_PER_RUN, Math.round(EMBED_PER_RUN * ratio)));
|
|
8991
10169
|
}, "embedPerRun");
|
|
8992
10170
|
var missingModel = /* @__PURE__ */ __name((error, env) => {
|
|
8993
|
-
const
|
|
8994
|
-
const id = typeof
|
|
8995
|
-
const
|
|
8996
|
-
return `the ${id} model is not downloaded \u2014 memo models download ${id}${
|
|
10171
|
+
const named5 = isCliError(error) ? error.details.model : void 0;
|
|
10172
|
+
const id = typeof named5 === "string" ? named5 : chosenTextModel(env).id;
|
|
10173
|
+
const terms2 = textModels(env).find((model) => model.id === id)?.terms;
|
|
10174
|
+
return `the ${id} model is not downloaded \u2014 memo models download ${id}${terms2 ? " --accept-terms" : ""}`;
|
|
8997
10175
|
}, "missingModel");
|
|
8998
10176
|
var isMissingModel = /* @__PURE__ */ __name((error) => isCliError(error) && error.details.reason === "model.not-downloaded", "isMissingModel");
|
|
8999
10177
|
var reportOf = /* @__PURE__ */ __name((run) => {
|
|
@@ -9025,18 +10203,18 @@ var reportOf = /* @__PURE__ */ __name((run) => {
|
|
|
9025
10203
|
...run.reason === void 0 ? {} : { reason: run.reason }
|
|
9026
10204
|
};
|
|
9027
10205
|
}, "reportOf");
|
|
9028
|
-
var combinedEnrichment = /* @__PURE__ */ __name((...
|
|
9029
|
-
const present2 =
|
|
10206
|
+
var combinedEnrichment = /* @__PURE__ */ __name((...parts2) => {
|
|
10207
|
+
const present2 = parts2.filter((part) => part !== void 0);
|
|
9030
10208
|
if (present2.length === 0)
|
|
9031
10209
|
return void 0;
|
|
9032
10210
|
const rank = { done: 0, stopped: 1, failed: 2 };
|
|
9033
10211
|
const worst = present2.reduce((a, b) => rank[b.status] > rank[a.status] ? b : a);
|
|
9034
|
-
const
|
|
10212
|
+
const named5 = present2.find((part) => part.provider !== void 0);
|
|
9035
10213
|
const costs = present2.map((part) => part.costUsd);
|
|
9036
10214
|
return {
|
|
9037
10215
|
status: worst.status,
|
|
9038
|
-
...
|
|
9039
|
-
...
|
|
10216
|
+
...named5?.provider === void 0 ? {} : { provider: named5.provider },
|
|
10217
|
+
...named5?.model === void 0 ? {} : { model: named5.model },
|
|
9040
10218
|
sent: present2.reduce((sum, part) => sum + part.sent, 0),
|
|
9041
10219
|
enriched: present2.reduce((sum, part) => sum + part.enriched, 0),
|
|
9042
10220
|
failed: present2.reduce((sum, part) => sum + part.failed, 0),
|
|
@@ -9100,10 +10278,10 @@ var embedMailChunks = /* @__PURE__ */ __name(async (store, { embed = true, env,
|
|
|
9100
10278
|
|
|
9101
10279
|
// dist/progress.js
|
|
9102
10280
|
var EVERY_MS = 500;
|
|
9103
|
-
var
|
|
10281
|
+
var progressLine2 = /* @__PURE__ */ __name((diagnostic, json5, { step, unit, label }) => {
|
|
9104
10282
|
let last = Number.NEGATIVE_INFINITY;
|
|
9105
10283
|
return (done, total) => {
|
|
9106
|
-
if (!
|
|
10284
|
+
if (!json5)
|
|
9107
10285
|
return;
|
|
9108
10286
|
const now = Date.now();
|
|
9109
10287
|
if (done !== total && now - last < EVERY_MS)
|
|
@@ -9230,7 +10408,7 @@ var syncCommand = /* @__PURE__ */ __name((program, streams, env, signal, keyring
|
|
|
9230
10408
|
const skip = options.ignore ?? [];
|
|
9231
10409
|
for (const folder of folders)
|
|
9232
10410
|
await attempt(`notes ${folder.path}`, async () => {
|
|
9233
|
-
const onFile =
|
|
10411
|
+
const onFile = progressLine2(streams.diagnostic, Boolean(options.json), {
|
|
9234
10412
|
step: "notes",
|
|
9235
10413
|
unit: "files",
|
|
9236
10414
|
label: folder.id
|
|
@@ -9397,20 +10575,20 @@ var mailTriageInput = /* @__PURE__ */ __name((mailboxes) => async (schedule, run
|
|
|
9397
10575
|
if (!holder)
|
|
9398
10576
|
return void 0;
|
|
9399
10577
|
const skill2 = await run(["skill", "show", SKILL]);
|
|
9400
|
-
const
|
|
10578
|
+
const parts2 = [PREAMBLE, "# The skill", skill2.trim(), "# The review"];
|
|
9401
10579
|
const separator = "\n\n";
|
|
9402
|
-
let used =
|
|
10580
|
+
let used = parts2.join(separator).length + separator.length * 2;
|
|
9403
10581
|
let alone = true;
|
|
9404
10582
|
for (const address of await mailboxes()) {
|
|
9405
10583
|
const source = `email:${address}`;
|
|
9406
10584
|
const review = JSON.parse(await run(["mail", "review", "--holder", holder, "--source", source, `--json=${FIELDS}`]));
|
|
9407
10585
|
const block = mailboxBlock(source, review, INPUT_BUDGET - used - separator.length, alone);
|
|
9408
|
-
|
|
10586
|
+
parts2.push(block);
|
|
9409
10587
|
used += block.length + separator.length;
|
|
9410
10588
|
if (block.includes("\nemails, one JSON per line:"))
|
|
9411
10589
|
alone = false;
|
|
9412
10590
|
}
|
|
9413
|
-
return [...
|
|
10591
|
+
return [...parts2, ""].join(separator);
|
|
9414
10592
|
}, "mailTriageInput");
|
|
9415
10593
|
|
|
9416
10594
|
// dist/schedule/command.js
|
|
@@ -9456,7 +10634,7 @@ var BRIEF = ["ref", "chat_title", "timestamp", "sender_name", "excerpt", "score"
|
|
|
9456
10634
|
var briefHit = /* @__PURE__ */ __name((hit) => Object.fromEntries(BRIEF.flatMap((key) => hit[key] === void 0 || hit[key] === null ? [] : [[key, hit[key]]])), "briefHit");
|
|
9457
10635
|
|
|
9458
10636
|
// dist/search/answers.js
|
|
9459
|
-
var
|
|
10637
|
+
var named4 = /* @__PURE__ */ __name((accounts) => [
|
|
9460
10638
|
...new Set(accounts.map(({ provider, account: account2 }) => `${provider}:${account2}`))
|
|
9461
10639
|
], "named");
|
|
9462
10640
|
var metaOf2 = /* @__PURE__ */ __name((accounts, skipped = [], heldInPart = false) => {
|
|
@@ -9467,7 +10645,7 @@ var metaOf2 = /* @__PURE__ */ __name((accounts, skipped = [], heldInPart = false
|
|
|
9467
10645
|
source: one2.source ?? one2.resource ?? ""
|
|
9468
10646
|
}));
|
|
9469
10647
|
return {
|
|
9470
|
-
accounts:
|
|
10648
|
+
accounts: named4(accounts),
|
|
9471
10649
|
...heldInPart ? { complete: false } : {},
|
|
9472
10650
|
...issues.length ? { issues } : {}
|
|
9473
10651
|
};
|
|
@@ -9721,8 +10899,8 @@ For an agent: read with --compact, one line per hit with its reference. Never wr
|
|
|
9721
10899
|
for (const { source, reason } of answer.skipped)
|
|
9722
10900
|
streams.diagnostic(`${source} not searched: ${reason}
|
|
9723
10901
|
`);
|
|
9724
|
-
const { limit, page, json:
|
|
9725
|
-
print(
|
|
10902
|
+
const { limit, page, json: json5, ...rest } = options;
|
|
10903
|
+
print(json5, notesAnswer(answer, limit, page, { query: words.join(" "), ...rest }), searchText(answer, (page - 1) * limit));
|
|
9726
10904
|
});
|
|
9727
10905
|
searchMemoriesCommand(group, streams, env);
|
|
9728
10906
|
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) => {
|
|
@@ -9766,7 +10944,13 @@ var LOCAL_OPENS = {
|
|
|
9766
10944
|
order: ["memo", "orders", "show"],
|
|
9767
10945
|
deal: ["memo", "deals", "show"],
|
|
9768
10946
|
lead: ["memo", "leads", "show"],
|
|
9769
|
-
pipeline: ["memo", "pipelines", "show"]
|
|
10947
|
+
pipeline: ["memo", "pipelines", "show"],
|
|
10948
|
+
product: ["memo", "products", "show"],
|
|
10949
|
+
contract: ["memo", "contracts", "show"],
|
|
10950
|
+
subscription: ["memo", "subscriptions", "show"],
|
|
10951
|
+
wallet: ["memo", "wallets", "show"],
|
|
10952
|
+
transaction: ["memo", "transactions", "show"],
|
|
10953
|
+
event: ["memo", "events", "show"]
|
|
9770
10954
|
};
|
|
9771
10955
|
var openKeyOf = /* @__PURE__ */ __name((kind) => LOCAL_OPENS[kind]?.slice(1).join("."), "openKeyOf");
|
|
9772
10956
|
var refuseDenied = /* @__PURE__ */ __name((command, summaries) => {
|
|
@@ -9781,12 +10965,12 @@ var refuseDenied = /* @__PURE__ */ __name((command, summaries) => {
|
|
|
9781
10965
|
}, "refuseDenied");
|
|
9782
10966
|
var OTHERS = /* @__PURE__ */ new Set(["message", "chat", "contact", "email", "email_thread", "document", "event", "meeting", "bot"]);
|
|
9783
10967
|
var ACCOUNT_KEY = /^[a-z][a-z-]*:\S+$/;
|
|
9784
|
-
var taskOpen = /* @__PURE__ */ __name((summary,
|
|
9785
|
-
if (summary.kind !== "task" ||
|
|
9786
|
-
return
|
|
9787
|
-
const argv = [...
|
|
10968
|
+
var taskOpen = /* @__PURE__ */ __name((summary, open2) => {
|
|
10969
|
+
if (summary.kind !== "task" || open2.argv === null)
|
|
10970
|
+
return open2;
|
|
10971
|
+
const argv = [...open2.argv.slice(0, -1), summary.ref.slice("task:".length)];
|
|
9788
10972
|
return {
|
|
9789
|
-
...
|
|
10973
|
+
...open2,
|
|
9790
10974
|
argv: summary.in !== null && ACCOUNT_KEY.test(summary.in) ? [...argv, "--source", summary.in] : argv
|
|
9791
10975
|
};
|
|
9792
10976
|
}, "taskOpen");
|
|
@@ -9807,7 +10991,7 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) =
|
|
|
9807
10991
|
if (command !== void 0)
|
|
9808
10992
|
refuseDenied(command, [...summaries.values()]);
|
|
9809
10993
|
const ports = { profilesFor: profilesFor(env), local: LOCAL_OPENS };
|
|
9810
|
-
|
|
10994
|
+
const shown2 = texts.map((text3) => {
|
|
9811
10995
|
const summary = summaries.get(text3) ?? {
|
|
9812
10996
|
ref: text3,
|
|
9813
10997
|
kind: "unknown",
|
|
@@ -9819,7 +11003,7 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) =
|
|
|
9819
11003
|
tool: null,
|
|
9820
11004
|
state: "unavailable"
|
|
9821
11005
|
};
|
|
9822
|
-
const
|
|
11006
|
+
const open2 = taskOpen(summary, openOf(summary, ports));
|
|
9823
11007
|
return {
|
|
9824
11008
|
ref: summary.ref,
|
|
9825
11009
|
kind: summary.kind,
|
|
@@ -9827,19 +11011,31 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) =
|
|
|
9827
11011
|
in: summary.in,
|
|
9828
11012
|
at: summary.at,
|
|
9829
11013
|
provider: summary.provider,
|
|
9830
|
-
tool: summary.tool ??
|
|
11014
|
+
tool: summary.tool ?? open2.argv?.[0] ?? null,
|
|
9831
11015
|
state: summary.state,
|
|
9832
|
-
open: { ...
|
|
11016
|
+
open: { ...open2, line: open2.argv?.map(shellWord).join(" ") ?? null },
|
|
9833
11017
|
...OTHERS.has(summary.kind) ? { untrusted: ["title", "in"] } : {}
|
|
9834
11018
|
};
|
|
9835
11019
|
});
|
|
11020
|
+
const withRecords = command === void 0 || !recordsHidden(command);
|
|
11021
|
+
for (const one2 of shown2) {
|
|
11022
|
+
const entity = one2.state === "available" ? await readSourced(store, one2.kind, one2.ref) : void 0;
|
|
11023
|
+
if (entity === void 0)
|
|
11024
|
+
continue;
|
|
11025
|
+
if (withRecords)
|
|
11026
|
+
one2.sources = await sourcesOf(store, entity);
|
|
11027
|
+
if (imported(entity))
|
|
11028
|
+
one2.untrusted = ["title"];
|
|
11029
|
+
}
|
|
11030
|
+
return shown2;
|
|
9836
11031
|
}, "showReferences");
|
|
9837
11032
|
var minute2 = /* @__PURE__ */ __name((at) => at === null ? null : at.slice(0, 16).replace("T", " "), "minute");
|
|
9838
11033
|
var blockOf = /* @__PURE__ */ __name((one2) => [
|
|
9839
11034
|
`${one2.ref} ${one2.title ?? ""}`.trimEnd(),
|
|
9840
11035
|
` ${[one2.kind, one2.in, one2.state, minute2(one2.at)].filter((part) => part !== null).join(" \xB7 ")}`,
|
|
9841
11036
|
` open: ${one2.open.line ?? "none"}`,
|
|
9842
|
-
...one2.open.why === null ? [] : [` ${one2.open.why}`]
|
|
11037
|
+
...one2.open.why === null ? [] : [` ${one2.open.why}`],
|
|
11038
|
+
...one2.sources === void 0 ? [] : sourcesText(one2.ref, one2.sources)
|
|
9843
11039
|
].join("\n"), "blockOf");
|
|
9844
11040
|
var showCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
9845
11041
|
const { print } = answers(program, streams, env);
|
|
@@ -9933,7 +11129,7 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9933
11129
|
const tags = program.command("tags").description("your labels on stored sources and folders or threads");
|
|
9934
11130
|
const { print } = answers(program, streams, env);
|
|
9935
11131
|
const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
|
|
9936
|
-
const mutate = /* @__PURE__ */ __name(async (operation,
|
|
11132
|
+
const mutate = /* @__PURE__ */ __name(async (operation, given2, { account: account2, ...options }) => {
|
|
9937
11133
|
const value = writeAccountOf({ account: account2 }, warn);
|
|
9938
11134
|
const scoped3 = /* @__PURE__ */ __name(async (store) => value === void 0 ? {} : oneAccountOf(store, env, value, "--account"), "scoped");
|
|
9939
11135
|
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;
|
|
@@ -9949,7 +11145,7 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9949
11145
|
throw new CliError("not_found", `no folder of notes ${target.id}`, { reason: "folder.not-found" });
|
|
9950
11146
|
target.id = id;
|
|
9951
11147
|
}
|
|
9952
|
-
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(null, target,
|
|
11148
|
+
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(null, target, given2);
|
|
9953
11149
|
print(options.json, itemAnswer({ target, [operation === "add" ? "added" : "removed"]: changed }), `${operation}: ${changed.join(", ") || "no labels changed"}`);
|
|
9954
11150
|
});
|
|
9955
11151
|
return;
|
|
@@ -9957,14 +11153,14 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9957
11153
|
if (options.contact !== void 0 || options.meeting !== void 0) {
|
|
9958
11154
|
await withStore(env, async (store) => {
|
|
9959
11155
|
const { key, target: target2 } = await selectTarget(store, { ...options, ...await scoped3(store) });
|
|
9960
|
-
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(key, target2,
|
|
11156
|
+
const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(key, target2, given2);
|
|
9961
11157
|
print(options.json, itemAnswer({ ...key, target: target2, [operation === "add" ? "added" : "removed"]: changed }), `${operation}: ${changed.join(", ") || "no labels changed"}`);
|
|
9962
11158
|
});
|
|
9963
11159
|
return;
|
|
9964
11160
|
}
|
|
9965
11161
|
if (options.message !== void 0 && value !== void 0)
|
|
9966
11162
|
throw new CliError("validation_error", "a message locator names its account and chat \u2014 use --message alone");
|
|
9967
|
-
const labels = [...new Set(
|
|
11163
|
+
const labels = [...new Set(given2.map(normalizeTag))];
|
|
9968
11164
|
await withStore(env, async (store) => {
|
|
9969
11165
|
const selected = sourceTarget({ ...options, ...await scoped3(store) });
|
|
9970
11166
|
const changed = await (operation === "add" ? store.tags.addTags : store.tags.removeTags)(selected.key, selected.target, labels);
|
|
@@ -9980,17 +11176,17 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
9980
11176
|
});
|
|
9981
11177
|
}, "mutate");
|
|
9982
11178
|
for (const operation of ["add", "remove"])
|
|
9983
|
-
targetOptions(annotate(tags.command(operation), { effects: LOCAL_WRITE }).description(operation === "add" ? "put labels on one source" : "remove labels from one source")).action((
|
|
11179
|
+
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));
|
|
9984
11180
|
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);
|
|
9985
|
-
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,
|
|
9986
|
-
const
|
|
9987
|
-
const tag =
|
|
9988
|
-
const value = sourceOf(
|
|
11181
|
+
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) => {
|
|
11182
|
+
const terms2 = queryTerms(words, TAG_QUERY, "tags list");
|
|
11183
|
+
const tag = terms2.get("tag");
|
|
11184
|
+
const value = sourceOf(given2, warn);
|
|
9989
11185
|
const options = {
|
|
9990
|
-
limit:
|
|
9991
|
-
...
|
|
11186
|
+
limit: given2.limit,
|
|
11187
|
+
...given2.json === void 0 ? {} : { json: given2.json },
|
|
9992
11188
|
...tag === void 0 ? {} : { tag: normalizeTag(tag) },
|
|
9993
|
-
...
|
|
11189
|
+
...terms2.has("type") ? { type: terms2.get("type") } : {}
|
|
9994
11190
|
};
|
|
9995
11191
|
await withStore(env, async (store) => {
|
|
9996
11192
|
const keys = value === void 0 ? await store.accounts.accounts() : await accountsOf(store, env, value);
|
|
@@ -10065,8 +11261,8 @@ var requireAccount = /* @__PURE__ */ __name((env, warn) => async (_, command) =>
|
|
|
10065
11261
|
return;
|
|
10066
11262
|
if (["show", "update", "claim", "release"].includes(command.name()) && first !== void 0 && await store.tasks.projectTask(first))
|
|
10067
11263
|
return;
|
|
10068
|
-
const
|
|
10069
|
-
throw new CliError("validation_error", `give ${option} \u2014 the stored accounts: ${
|
|
11264
|
+
const listed2 = (await store.accounts.accounts()).map((key) => `${option} ${key.provider}:${key.account}`).join("; ");
|
|
11265
|
+
throw new CliError("validation_error", `give ${option} \u2014 the stored accounts: ${listed2 || "none yet"}`);
|
|
10070
11266
|
} finally {
|
|
10071
11267
|
await store.close();
|
|
10072
11268
|
}
|
|
@@ -10090,7 +11286,7 @@ var sharedTaskCommands = /* @__PURE__ */ __name((program, tasks, streams, env) =
|
|
|
10090
11286
|
|
|
10091
11287
|
// dist/tasks/tasks.js
|
|
10092
11288
|
var personRef = /* @__PURE__ */ __name((person) => person.startsWith("person:") ? person : `person:${person}`, "personRef");
|
|
10093
|
-
var
|
|
11289
|
+
var fieldsOf4 = /* @__PURE__ */ __name((options) => ({
|
|
10094
11290
|
...options.title === void 0 ? {} : { title: options.title },
|
|
10095
11291
|
...options.priority === void 0 ? {} : { priority: options.priority },
|
|
10096
11292
|
...options.parent === void 0 ? {} : { parent: options.parent },
|
|
@@ -10114,7 +11310,7 @@ var addToProject = /* @__PURE__ */ __name(async (store, env, options) => {
|
|
|
10114
11310
|
project: await canonicalProject(store, options.project),
|
|
10115
11311
|
title: options.title,
|
|
10116
11312
|
type,
|
|
10117
|
-
...
|
|
11313
|
+
...fieldsOf4(options),
|
|
10118
11314
|
...options.due === void 0 || options.due === "none" ? {} : { dueAt: options.due },
|
|
10119
11315
|
...options.status === void 0 ? {} : { status: options.status },
|
|
10120
11316
|
...options.agent === void 0 ? {} : { agent: options.agent }
|
|
@@ -10149,7 +11345,7 @@ var addFromSource = /* @__PURE__ */ __name(async (store, env, source, options) =
|
|
|
10149
11345
|
...options.into === void 0 ? {} : { attach: options.into },
|
|
10150
11346
|
...options.new ? { new: true } : {}
|
|
10151
11347
|
}, author);
|
|
10152
|
-
const fields =
|
|
11348
|
+
const fields = fieldsOf4(options);
|
|
10153
11349
|
if (Object.keys(fields).length === 0 && !options.assignee?.length)
|
|
10154
11350
|
return answer;
|
|
10155
11351
|
await store.tasks.edit(answer.task.id, fields, "owner");
|
|
@@ -10178,7 +11374,7 @@ var closeTask = /* @__PURE__ */ __name(async (store, env, id, options) => {
|
|
|
10178
11374
|
});
|
|
10179
11375
|
}, "closeTask");
|
|
10180
11376
|
var updateTask = /* @__PURE__ */ __name(async (store, env, id, options) => {
|
|
10181
|
-
const fields =
|
|
11377
|
+
const fields = fieldsOf4(options);
|
|
10182
11378
|
const times = {
|
|
10183
11379
|
...options.due === void 0 ? {} : { dueAt: options.due },
|
|
10184
11380
|
...options.remindTime === void 0 ? {} : { nextCheckAt: options.remindTime }
|
|
@@ -10220,15 +11416,15 @@ var moveTask = /* @__PURE__ */ __name((store, env, id, options) => {
|
|
|
10220
11416
|
var commentTask = /* @__PURE__ */ __name((store, env, id, text3) => store.tasks.comment(id, text3, authorOf(env)), "commentTask");
|
|
10221
11417
|
var taskHistory = /* @__PURE__ */ __name(async (store, id) => {
|
|
10222
11418
|
const owner = (await store.people.owner())?.uid;
|
|
10223
|
-
return (await store.tasks.events(id)).map((
|
|
10224
|
-
at:
|
|
10225
|
-
kind:
|
|
10226
|
-
by:
|
|
10227
|
-
ref: `${
|
|
10228
|
-
name:
|
|
10229
|
-
owner:
|
|
11419
|
+
return (await store.tasks.events(id)).map((event2) => ({
|
|
11420
|
+
at: event2.at,
|
|
11421
|
+
kind: event2.kind,
|
|
11422
|
+
by: event2.actor && {
|
|
11423
|
+
ref: `${event2.actor.type}:${event2.actor.id}`,
|
|
11424
|
+
name: event2.actor.name,
|
|
11425
|
+
owner: event2.actor.type === "person" && String(event2.actor.id) === String(owner)
|
|
10230
11426
|
},
|
|
10231
|
-
changes:
|
|
11427
|
+
changes: event2.changes
|
|
10232
11428
|
}));
|
|
10233
11429
|
}, "taskHistory");
|
|
10234
11430
|
|
|
@@ -10307,11 +11503,11 @@ var tasksCommand2 = /* @__PURE__ */ __name((program, streams, env) => {
|
|
|
10307
11503
|
const description = command.options.find((option) => option.long === "--description");
|
|
10308
11504
|
if (description)
|
|
10309
11505
|
description.description = "the detail, in Markdown; none clears it";
|
|
10310
|
-
command.action(async (id,
|
|
10311
|
-
const raw =
|
|
11506
|
+
command.action(async (id, given2) => {
|
|
11507
|
+
const raw = given2;
|
|
10312
11508
|
const options = {
|
|
10313
|
-
...
|
|
10314
|
-
...typeof
|
|
11509
|
+
...given2,
|
|
11510
|
+
...typeof given2.description === "string" && given2.description.trim().toLowerCase() === "none" ? { description: null } : {},
|
|
10315
11511
|
priority: raw.priority === "none" ? null : raw.priority,
|
|
10316
11512
|
parent: raw.parent === null || raw.parent === "none" ? null : raw.parent,
|
|
10317
11513
|
due: raw.due === "none" ? null : raw.due,
|
|
@@ -10362,10 +11558,10 @@ var VOCABULARY_QUERY = {
|
|
|
10362
11558
|
]
|
|
10363
11559
|
};
|
|
10364
11560
|
var vocabularyFilter = /* @__PURE__ */ __name((query, command) => {
|
|
10365
|
-
const
|
|
11561
|
+
const terms2 = queryTerms(query, VOCABULARY_QUERY, command);
|
|
10366
11562
|
return {
|
|
10367
|
-
...
|
|
10368
|
-
...
|
|
11563
|
+
...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
|
|
11564
|
+
...terms2.has("scope") ? { scope: terms2.get("scope") } : {}
|
|
10369
11565
|
};
|
|
10370
11566
|
}, "vocabularyFilter");
|
|
10371
11567
|
|
|
@@ -10545,6 +11741,10 @@ var OWN_ENTITIES = entityFields({
|
|
|
10545
11741
|
"fulfilled_date",
|
|
10546
11742
|
"invoice",
|
|
10547
11743
|
"payment",
|
|
11744
|
+
"direction",
|
|
11745
|
+
"contract",
|
|
11746
|
+
"deal",
|
|
11747
|
+
"lines",
|
|
10548
11748
|
"review",
|
|
10549
11749
|
"author",
|
|
10550
11750
|
"model",
|
|
@@ -10599,6 +11799,8 @@ var OWN_ENTITIES = entityFields({
|
|
|
10599
11799
|
"reference",
|
|
10600
11800
|
"allocated",
|
|
10601
11801
|
"unallocated",
|
|
11802
|
+
"refund_of",
|
|
11803
|
+
"subscription",
|
|
10602
11804
|
"evidence",
|
|
10603
11805
|
"review",
|
|
10604
11806
|
"author",
|
|
@@ -10621,7 +11823,9 @@ var OWN_ENTITIES = entityFields({
|
|
|
10621
11823
|
"revision",
|
|
10622
11824
|
"fingerprint",
|
|
10623
11825
|
"relations",
|
|
11826
|
+
"incoming",
|
|
10624
11827
|
"entity",
|
|
11828
|
+
"created_entity",
|
|
10625
11829
|
"flagged",
|
|
10626
11830
|
"batch_id",
|
|
10627
11831
|
"created_at",
|
|
@@ -10639,8 +11843,162 @@ var OWN_ENTITIES = entityFields({
|
|
|
10639
11843
|
"proposed",
|
|
10640
11844
|
"waiting",
|
|
10641
11845
|
"flagged",
|
|
10642
|
-
"
|
|
11846
|
+
"unmatched",
|
|
11847
|
+
"ignored",
|
|
11848
|
+
"vcard",
|
|
11849
|
+
"errors",
|
|
11850
|
+
"truncated"
|
|
11851
|
+
],
|
|
11852
|
+
product: [
|
|
11853
|
+
"id",
|
|
11854
|
+
"ref",
|
|
11855
|
+
"title",
|
|
11856
|
+
"kind",
|
|
11857
|
+
"name",
|
|
11858
|
+
"sku",
|
|
11859
|
+
"supplier",
|
|
11860
|
+
"unit",
|
|
11861
|
+
"unit_price",
|
|
11862
|
+
"currency",
|
|
11863
|
+
"description",
|
|
11864
|
+
"archived_date",
|
|
11865
|
+
"author",
|
|
11866
|
+
"model",
|
|
11867
|
+
"source",
|
|
11868
|
+
"created_at",
|
|
11869
|
+
"updated_at"
|
|
11870
|
+
],
|
|
11871
|
+
contract: [
|
|
11872
|
+
"id",
|
|
11873
|
+
"ref",
|
|
11874
|
+
"title",
|
|
11875
|
+
"name",
|
|
11876
|
+
"number",
|
|
11877
|
+
"kind",
|
|
11878
|
+
"status",
|
|
11879
|
+
"signed_date",
|
|
11880
|
+
"effective_date",
|
|
11881
|
+
"expiration_date",
|
|
11882
|
+
"auto_renew",
|
|
11883
|
+
"renewal",
|
|
11884
|
+
"notice_days",
|
|
11885
|
+
"notice_deadline",
|
|
11886
|
+
"terms",
|
|
11887
|
+
"value",
|
|
11888
|
+
"currency",
|
|
11889
|
+
"deal",
|
|
11890
|
+
"review",
|
|
11891
|
+
"author",
|
|
11892
|
+
"model",
|
|
11893
|
+
"confirmed_by",
|
|
11894
|
+
"source",
|
|
11895
|
+
"reason",
|
|
11896
|
+
"evidence",
|
|
11897
|
+
"project",
|
|
11898
|
+
"project_name",
|
|
11899
|
+
"created_at",
|
|
11900
|
+
"updated_at"
|
|
11901
|
+
],
|
|
11902
|
+
subscription: [
|
|
11903
|
+
"id",
|
|
11904
|
+
"ref",
|
|
11905
|
+
"title",
|
|
11906
|
+
"name",
|
|
11907
|
+
"direction",
|
|
11908
|
+
"supplier",
|
|
11909
|
+
"customer",
|
|
11910
|
+
"product",
|
|
11911
|
+
"contract",
|
|
11912
|
+
"status",
|
|
11913
|
+
"interval",
|
|
11914
|
+
"start_date",
|
|
11915
|
+
"trial_end_date",
|
|
11916
|
+
"next_renewal_date",
|
|
11917
|
+
"cancelled_date",
|
|
11918
|
+
"end_date",
|
|
11919
|
+
"current_price",
|
|
11920
|
+
"prices",
|
|
11921
|
+
"review",
|
|
11922
|
+
"author",
|
|
11923
|
+
"model",
|
|
11924
|
+
"confirmed_by",
|
|
11925
|
+
"source",
|
|
11926
|
+
"reason",
|
|
11927
|
+
"evidence",
|
|
11928
|
+
"project",
|
|
11929
|
+
"project_name",
|
|
11930
|
+
"created_at",
|
|
11931
|
+
"updated_at"
|
|
11932
|
+
],
|
|
11933
|
+
subscription_price: [
|
|
11934
|
+
"id",
|
|
11935
|
+
"ref",
|
|
11936
|
+
"title",
|
|
11937
|
+
"subscription",
|
|
11938
|
+
"amount",
|
|
11939
|
+
"currency",
|
|
11940
|
+
"effective_from",
|
|
11941
|
+
"review",
|
|
11942
|
+
"author",
|
|
11943
|
+
"reason",
|
|
11944
|
+
"project",
|
|
11945
|
+
"created_at"
|
|
11946
|
+
],
|
|
11947
|
+
wallet: [
|
|
11948
|
+
"id",
|
|
11949
|
+
"ref",
|
|
11950
|
+
"title",
|
|
11951
|
+
"name",
|
|
11952
|
+
"kind",
|
|
11953
|
+
"currency",
|
|
11954
|
+
"institution",
|
|
11955
|
+
"number_hint",
|
|
11956
|
+
"holder",
|
|
11957
|
+
"opening_balance",
|
|
11958
|
+
"opening_date",
|
|
11959
|
+
"closed_date",
|
|
11960
|
+
"balance",
|
|
11961
|
+
"until",
|
|
11962
|
+
"pending",
|
|
11963
|
+
"source_says",
|
|
11964
|
+
"author",
|
|
11965
|
+
"model",
|
|
11966
|
+
"source",
|
|
11967
|
+
"created_at",
|
|
11968
|
+
"updated_at"
|
|
11969
|
+
],
|
|
11970
|
+
transaction: [
|
|
11971
|
+
"id",
|
|
11972
|
+
"ref",
|
|
11973
|
+
"title",
|
|
11974
|
+
"wallet",
|
|
11975
|
+
"wallet_name",
|
|
11976
|
+
"direction",
|
|
11977
|
+
"amount",
|
|
11978
|
+
"currency",
|
|
11979
|
+
"status",
|
|
11980
|
+
"statement_date",
|
|
11981
|
+
"booked_date",
|
|
11982
|
+
"description",
|
|
11983
|
+
"counterparty_name",
|
|
11984
|
+
"counterparty",
|
|
11985
|
+
"reference",
|
|
11986
|
+
"payment",
|
|
11987
|
+
"splits",
|
|
11988
|
+
"uncategorized",
|
|
11989
|
+
"review",
|
|
11990
|
+
"author",
|
|
11991
|
+
"model",
|
|
11992
|
+
"confirmed_by",
|
|
11993
|
+
"source",
|
|
11994
|
+
"reason",
|
|
11995
|
+
"evidence",
|
|
11996
|
+
"project",
|
|
11997
|
+
"project_name",
|
|
11998
|
+
"created_at",
|
|
11999
|
+
"updated_at"
|
|
10643
12000
|
],
|
|
12001
|
+
records_match: ["linked", "created", "unmatched", "proposed", "errors", "truncated"],
|
|
10644
12002
|
payment_allocation: ["payment", "invoice", "amount", "currency", "created_at"]
|
|
10645
12003
|
});
|
|
10646
12004
|
var SKILL_TOPICS = [
|
|
@@ -10692,6 +12050,11 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
10692
12050
|
financeCommands(program, streams, env);
|
|
10693
12051
|
orderCommands(program, streams, env);
|
|
10694
12052
|
dealCommands(program, streams, env);
|
|
12053
|
+
productCommands(program, streams, env);
|
|
12054
|
+
contractCommands(program, streams, env);
|
|
12055
|
+
subscriptionCommands(program, streams, env);
|
|
12056
|
+
walletCommands(program, streams, env);
|
|
12057
|
+
transactionCommands(program, streams, env);
|
|
10695
12058
|
recordsCommand(program, streams, env);
|
|
10696
12059
|
findingsCommand(program, streams, env);
|
|
10697
12060
|
actionsCommand(program, streams, env);
|
|
@@ -10702,6 +12065,7 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
10702
12065
|
searchCommand(program, streams, env);
|
|
10703
12066
|
meetingReadCommands(program, streams, env);
|
|
10704
12067
|
meetingPreparationCommand(program, streams, env);
|
|
12068
|
+
eventsCommand(program, streams, env);
|
|
10705
12069
|
askCommand(program, streams, env);
|
|
10706
12070
|
syncCommand(program, streams, env, signal, keyring);
|
|
10707
12071
|
storeCommand(program, streams, env);
|
|
@@ -10714,10 +12078,10 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
|
|
|
10714
12078
|
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.", () => {
|
|
10715
12079
|
const out = answers(program, streams, env);
|
|
10716
12080
|
const skill3 = skillCommand(APP, new URL("../skills/cli-memo/SKILL.md", new URL("../program.js", import.meta.url).href), (command) => {
|
|
10717
|
-
const
|
|
10718
|
-
const renderer = createRenderer({ format:
|
|
12081
|
+
const json5 = command.opts().json === true;
|
|
12082
|
+
const renderer = createRenderer({ format: json5 ? "json" : "pretty", color: false, streams });
|
|
10719
12083
|
return {
|
|
10720
|
-
renderer:
|
|
12084
|
+
renderer: json5 ? { ...renderer, result: /* @__PURE__ */ __name((value) => out.print(true, itemAnswer(value)), "result") } : renderer,
|
|
10721
12085
|
streams,
|
|
10722
12086
|
env
|
|
10723
12087
|
};
|