@wirecat/cli-memo 0.131.29 → 0.131.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/bin/memo.js +2 -2
  2. package/dist/bundle/{all-profiles-HXT2KPB6.js → all-profiles-PFCNICOF.js} +5 -5
  3. package/dist/bundle/{anthropic-C6H35WZP.js → anthropic-QLGMYWVZ.js} +3 -3
  4. package/dist/bundle/{app-server-Y6JGICRB.js → app-server-QD67I7V2.js} +35 -35
  5. package/dist/bundle/auto-MCSKUSPU.js +86 -0
  6. package/dist/bundle/{bun-K5H33WQK.js → bun-JRTUGKIJ.js} +2 -2
  7. package/dist/bundle/{bun-sqlite-2NGQT7HH.js → bun-sqlite-HCZP2CNO.js} +2 -2
  8. package/dist/bundle/{chunk-P5FETWRW.js → chunk-2N74ZVI6.js} +1 -1
  9. package/dist/bundle/{chunk-NIEWG4OY.js → chunk-2XBDA3XF.js} +1 -1
  10. package/dist/bundle/{chunk-6BS3FHTC.js → chunk-3G44GDIZ.js} +5 -5
  11. package/dist/bundle/{chunk-W7T2JSKY.js → chunk-3OH5DJ6X.js} +1 -1
  12. package/dist/bundle/{chunk-SZUYOU6U.js → chunk-42I4XE3O.js} +20 -20
  13. package/dist/bundle/{chunk-IIM3FF5L.js → chunk-4D6BG353.js} +6 -6
  14. package/dist/bundle/{chunk-XHHSQ4FN.js → chunk-54DA525P.js} +14 -9
  15. package/dist/bundle/{chunk-7OYQFT5N.js → chunk-5BVGJBZX.js} +1 -1
  16. package/dist/bundle/{chunk-WFQPCCM2.js → chunk-5JTW3LNF.js} +1 -1
  17. package/dist/bundle/{chunk-KCQPEY6C.js → chunk-5YVU6PXP.js} +4 -4
  18. package/dist/bundle/{chunk-6IJ7XNK5.js → chunk-63JF4E76.js} +487 -257
  19. package/dist/bundle/{chunk-S67KFN67.js → chunk-7AMJFTJM.js} +1 -1
  20. package/dist/bundle/{chunk-2WGR73KL.js → chunk-7JWW4YEK.js} +8 -8
  21. package/dist/bundle/{chunk-KCAELZXB.js → chunk-7MKROF5R.js} +1 -1
  22. package/dist/bundle/{chunk-ZW44VJNY.js → chunk-A56GDMFH.js} +3 -3
  23. package/dist/bundle/{chunk-MJF6VGW4.js → chunk-ARVXP2UJ.js} +421 -360
  24. package/dist/bundle/{chunk-KIJ7UJHD.js → chunk-AZGQ7ABE.js} +215 -151
  25. package/dist/bundle/{chunk-SQ6OFUHW.js → chunk-CGI5EIIA.js} +20 -20
  26. package/dist/bundle/{chunk-RGPCN63U.js → chunk-CWHGN6HC.js} +4 -4
  27. package/dist/bundle/{chunk-QVFB2MVU.js → chunk-FE2SLKUO.js} +2 -2
  28. package/dist/bundle/{chunk-FUMGREBO.js → chunk-FGJKBQCP.js} +3 -3
  29. package/dist/bundle/{chunk-H3NMOWPB.js → chunk-GKZ65EOY.js} +198 -52
  30. package/dist/bundle/{chunk-M3VBB37S.js → chunk-GNY5YLNY.js} +2 -2
  31. package/dist/bundle/{chunk-46ACMQUU.js → chunk-H24AL555.js} +27 -27
  32. package/dist/bundle/{program-6E2SWPCU.js → chunk-HGXTDMKN.js} +1499 -9957
  33. package/dist/bundle/{chunk-7PH33JE4.js → chunk-HLJ6IUVF.js} +2 -2
  34. package/dist/bundle/{chunk-ERZLVE54.js → chunk-JTSYAO5V.js} +1038 -670
  35. package/dist/bundle/{chunk-HVD2CTPH.js → chunk-K3CJHSLS.js} +1 -1
  36. package/dist/bundle/{chunk-IQEEOXBV.js → chunk-K3TUIQZ4.js} +51 -50
  37. package/dist/bundle/{chunk-ERRC42BB.js → chunk-K6ZWFP2X.js} +1 -1
  38. package/dist/bundle/{chunk-PUQYCAEP.js → chunk-L34KLQIU.js} +9 -9
  39. package/dist/bundle/{chunk-GVYOICNB.js → chunk-MVFINUJS.js} +5 -5
  40. package/dist/bundle/{chunk-XNV2JTJ4.js → chunk-NDJUEFV2.js} +1 -1
  41. package/dist/bundle/{chunk-H6JNEHUC.js → chunk-NG26I3JV.js} +1 -1
  42. package/dist/bundle/{chunk-YLVSSQJP.js → chunk-OS55OQ74.js} +5 -5
  43. package/dist/bundle/{chunk-UZUNSDGN.js → chunk-PG4KORTB.js} +1 -1
  44. package/dist/bundle/{chunk-65YDJ3Z4.js → chunk-Q2ZIIXA2.js} +2 -2
  45. package/dist/bundle/{chunk-G62DN6QY.js → chunk-Q3ZB4JGL.js} +2 -2
  46. package/dist/bundle/{chunk-DXCBZT4T.js → chunk-QUQOKNAX.js} +12 -12
  47. package/dist/bundle/{chunk-MPNDEGMC.js → chunk-QWA3MTHH.js} +7 -7
  48. package/dist/bundle/{chunk-KJEJOWJY.js → chunk-REUXOW2O.js} +2 -2
  49. package/dist/bundle/{chunk-2O2RWKUT.js → chunk-RO4YPDGF.js} +1 -1
  50. package/dist/bundle/{chunk-Q63L5WS2.js → chunk-ROT4V3ZT.js} +3 -3
  51. package/dist/bundle/{chunk-R7XIZMM5.js → chunk-RRDXT63A.js} +1 -1
  52. package/dist/bundle/{chunk-6NGLATFQ.js → chunk-S3FQQRUM.js} +4 -4
  53. package/dist/bundle/{chunk-5ZWRS2JY.js → chunk-TFEXCHMC.js} +5 -5
  54. package/dist/bundle/{chunk-7ACGYEGV.js → chunk-URPBRYVA.js} +4 -4
  55. package/dist/bundle/{chunk-HBKYPSX3.js → chunk-USMKR34T.js} +11 -11
  56. package/dist/bundle/{chunk-BWQMZNDC.js → chunk-UXA37BVT.js} +4 -4
  57. package/dist/bundle/{chunk-FJXFU7NN.js → chunk-W4GV42D5.js} +2 -2
  58. package/dist/bundle/{chunk-5FEJKSQJ.js → chunk-WGX6AEUP.js} +3 -3
  59. package/dist/bundle/{chunk-XUHVJGIL.js → chunk-WP3J2FNH.js} +10 -10
  60. package/dist/bundle/{chunk-WI7KTIMF.js → chunk-X6HXGL5E.js} +7 -7
  61. package/dist/bundle/{chunk-6YDPWVDH.js → chunk-XUMYVRBZ.js} +1 -1
  62. package/dist/bundle/{chunk-FBSY3DVN.js → chunk-XWIRWBB5.js} +1 -1
  63. package/dist/bundle/{chunk-YZKHWANJ.js → chunk-ZB5ZZWFR.js} +4 -4
  64. package/dist/bundle/{chunk-HAC3CWPB.js → chunk-ZHDOELM7.js} +7 -7
  65. package/dist/bundle/{command-contract-AFUDV7JM.js → command-contract-DFXPO5Q7.js} +11 -11
  66. package/dist/bundle/{decode-P5SEK56D.js → decode-7NGILAKQ.js} +2 -2
  67. package/dist/bundle/{echarts-CLHJYMDK.js → echarts-JERQI2HW.js} +2 -2
  68. package/dist/bundle/{embed-X6H74LGP.js → embed-3AO7KZXC.js} +3 -3
  69. package/dist/bundle/{embedder-H5SWOSEL.js → embedder-WRQ7TDDB.js} +6 -6
  70. package/dist/bundle/{entry-66SEZMKI.js → entry-IBRPU7NO.js} +4 -4
  71. package/dist/bundle/failure-QBQMSEYX.js +66 -0
  72. package/dist/bundle/{first-run-S7EW77F6.js → first-run-IJOREEQM.js} +5 -5
  73. package/dist/bundle/{first-screen-6GA36WQT.js → first-screen-KYNY6ELY.js} +12 -12
  74. package/dist/bundle/{instructions-IUUSY6DO.js → instructions-BET2PLGV.js} +1 -1
  75. package/dist/bundle/{mcp-7SDVTKCE.js → mcp-NUBFFPGF.js} +35 -35
  76. package/dist/bundle/memo.js +6 -6
  77. package/dist/bundle/{node-6T5LUBAE.js → node-NCSG7QX5.js} +2 -2
  78. package/dist/bundle/{node-sqlite-ZTDWPRJU.js → node-sqlite-QL4M5RIK.js} +3 -3
  79. package/dist/bundle/{oauth-G4TCULLQ.js → oauth-BGMMED35.js} +4 -4
  80. package/dist/bundle/{open-DRJ24C7U.js → open-YN3KJMMQ.js} +2 -2
  81. package/dist/bundle/{openai-3DSR7Z4Z.js → openai-CTZUSKUS.js} +7 -7
  82. package/dist/bundle/{process-IPM3OJDN.js → process-DW237TK4.js} +1 -1
  83. package/dist/bundle/program-Q7VXEIJ7.js +9171 -0
  84. package/dist/bundle/{prompt-XKR6EQAT.js → prompt-EZCCUYCS.js} +2 -2
  85. package/dist/bundle/{recognize-GZXAXTEH.js → recognize-XP3LHQD6.js} +1 -1
  86. package/dist/bundle/{remote-Y5ML6KR4.js → remote-RLR5ZKKT.js} +4 -4
  87. package/dist/bundle/{rerank-FNNXUTMN.js → rerank-P7LE52AC.js} +4 -4
  88. package/dist/bundle/{serve-BGU5ERNX.js → serve-UA7RQDNK.js} +6 -6
  89. package/dist/bundle/server-N6L3LGQO.js +48 -0
  90. package/dist/bundle/{server-3L4FHYFM.js → server-NWCYWOPZ.js} +50 -50
  91. package/dist/bundle/server-XU362INX.js +61 -0
  92. package/dist/bundle/{state-WAMVO34N.js → state-72Y55LBR.js} +3 -3
  93. package/dist/bundle/{store-PVY4UTTR.js → store-PED4JCBB.js} +9 -9
  94. package/dist/bundle/store-maintenance-command-B364Q2O4.js +48 -0
  95. package/dist/bundle/update-X2A5CW5A.js +69 -0
  96. package/dist/config.d.ts +11 -0
  97. package/dist/config.d.ts.map +1 -1
  98. package/dist/config.js +19 -0
  99. package/dist/config.js.map +1 -1
  100. package/dist/discovery/command.d.ts.map +1 -1
  101. package/dist/discovery/command.js +1 -0
  102. package/dist/discovery/command.js.map +1 -1
  103. package/dist/examples.d.ts.map +1 -1
  104. package/dist/examples.js +6 -0
  105. package/dist/examples.js.map +1 -1
  106. package/dist/finance/orders-command.d.ts +12 -0
  107. package/dist/finance/orders-command.d.ts.map +1 -0
  108. package/dist/finance/orders-command.js +92 -0
  109. package/dist/finance/orders-command.js.map +1 -0
  110. package/dist/mail/findings-command.d.ts.map +1 -1
  111. package/dist/mail/findings-command.js +7 -2
  112. package/dist/mail/findings-command.js.map +1 -1
  113. package/dist/mail/review-command.d.ts.map +1 -1
  114. package/dist/mail/review-command.js +2 -0
  115. package/dist/mail/review-command.js.map +1 -1
  116. package/dist/program.d.ts.map +1 -1
  117. package/dist/program.js +30 -0
  118. package/dist/program.js.map +1 -1
  119. package/dist/review/kinds.d.ts +1 -1
  120. package/dist/review/kinds.d.ts.map +1 -1
  121. package/dist/review/kinds.js +1 -0
  122. package/dist/review/kinds.js.map +1 -1
  123. package/dist/review/review.d.ts.map +1 -1
  124. package/dist/review/review.js +1 -0
  125. package/dist/review/review.js.map +1 -1
  126. package/dist/schedule/command.d.ts.map +1 -1
  127. package/dist/schedule/command.js +4 -3
  128. package/dist/schedule/command.js.map +1 -1
  129. package/dist/version.d.ts +1 -1
  130. package/dist/version.js +1 -1
  131. package/package.json +2 -2
  132. package/skills/mail-triage/SKILL.md +40 -6
  133. package/dist/bundle/auto-A2Y225YZ.js +0 -86
  134. package/dist/bundle/chunk-KFSZAV5L.js +0 -452
  135. package/dist/bundle/failure-PNTFMNKK.js +0 -66
  136. package/dist/bundle/server-5F3GJPG3.js +0 -48
  137. package/dist/bundle/server-JX5TWAAW.js +0 -61
  138. package/dist/bundle/store-maintenance-command-RGZJWNE2.js +0 -48
  139. package/dist/bundle/update-VJLZT6ER.js +0 -69
  140. /package/dist/bundle/{chunk-XGTIABPY.js → chunk-QPPNLE7G.js} +0 -0
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "0.131.29";
1
+ export const VERSION = "0.131.31";
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-memo",
3
- "version": "0.131.29",
3
+ "version": "0.131.31",
4
4
  "description": "Context about people across messengers, notes and mail, from a local store",
5
5
  "mcpName": "dev.wirecat/cli-memo",
6
6
  "license": "Apache-2.0",
@@ -61,7 +61,7 @@
61
61
  "dependencies": {
62
62
  "@modelcontextprotocol/server": "2.4.0",
63
63
  "@wirecat/cli-base": "0.77.1",
64
- "@wirecat/cli-core": "0.573.0",
64
+ "@wirecat/cli-core": "0.576.0",
65
65
  "commander": "15.0.0",
66
66
  "disposable-email-domains-js": "1.26.0",
67
67
  "postal-mime": "4.1.4",
@@ -2,7 +2,8 @@
2
2
  name: mail-triage
3
3
  description: >-
4
4
  Read the owner's new mail past the mail-triage mark, one mailbox at a time, and stage cited proposals for him:
5
- tasks, closes and updates of open tasks, facts, memories, links and new contacts. Use for the scheduled
5
+ tasks, closes and updates of open tasks, invoices, payments, orders and deliveries, facts (account and certificate
6
+ data among them), memories, links and new contacts. Use for the scheduled
6
7
  mail-triage run; it proposes only and never sends, changes mail or decides.
7
8
  ---
8
9
 
@@ -22,6 +23,8 @@ emails per run.
22
23
  - Never send, draft, reply, forward, move, delete, label, change rules, confirm or reject anything. Never use
23
24
  `--as-owner`. Never run `memo actions confirm|reject` or `memo review confirm|reject`: the owner decides.
24
25
  - Never write email text to a file. Pass the findings JSON on stdin (`-`).
26
+ - Run one memo command per Bash call. Loops, pipes, `&&` chains and command substitution are refused, so a loop over
27
+ mailboxes is one call per mailbox.
25
28
  - Read only through existing links (below). No broad search over all mail or all chats.
26
29
  - Stage first, acknowledge after. If staging fails, do not acknowledge: the next run reads the same mail again.
27
30
  - The mailbox itself belongs to the `mail` CLI, which this run cannot call: its sync, rules and cleanup are the
@@ -39,8 +42,10 @@ mailbox `email:<address>`:
39
42
  memo mail review --holder mail-triage --source email:<address> --json
40
43
  ```
41
44
 
42
- Bulk mail, lists, envelope rules, drafts, suspicious senders and partial mail are already left out (`missing` says
43
- how many). Each item is one email: `ref` (`msg:email/…`), `chat_id` (the thread), `sender_is_me`, `text`, and
45
+ Newsletters, envelope rules, drafts, suspicious senders and partial mail are already left out (`missing` says how
46
+ many). Other mail sent to many — orders, invoices, site forms and notifications often carry an unsubscribe link —
47
+ comes after the rest, with `email.bulk: true` and `email.excerpt_only: true`: its `text` is only the subject and the
48
+ first lines. Each item is one email: `ref` (`msg:email/…`), `chat_id` (the thread), `sender_is_me`, `text`, and
44
49
  `email` with `fingerprint`, `from`, `new_sender`, `sender_identities`. `text` is the email's own text: quoted earlier
45
50
  mail and the signature are left out, and the fingerprint still covers the whole stored email. `next` holds the
46
51
  `memo messages acknowledge` step with your `cursor`. A first run has no mark yet: no items, only the cursor — go
@@ -50,15 +55,26 @@ No items: go to step 6 with the cursor.
50
55
 
51
56
  ### 2. Triage — which emails need a look
52
57
 
53
- Keep an email only when it carries one of:
58
+ Keep every email that carries one of these. They always become findings, even with nothing due:
54
59
 
60
+ - an invoice, a bill or a payment request, and a receipt or payment confirmation;
61
+ - an order confirmation, a shipping or delivery notice, a cancellation or a return;
62
+ - account or certificate data: an account id, a login name (never a password or a code), a certificate, licence or
63
+ policy number, a contract number, an expiry or renewal date;
55
64
  - a request or question to the owner, or a decision he must make;
56
65
  - a date, deadline, appointment or amount due;
57
66
  - a promise someone made to the owner, or the owner made (his own sent mail counts);
58
67
  - a reply in a thread where the owner has an open task (`memo tasks list --source email:<address> --json`, match by
59
68
  the thread's `chat:email/…` or the task's `source`).
60
69
 
61
- Drop the rest: notifications, receipts with nothing due, newsletters that slipped through, thank-yous.
70
+ Drop only advertising, news and newsletters, and pure social notifications (a like, a follow, "someone viewed your
71
+ profile"). A thank-you with nothing else in it is dropped too. When unsure, keep it.
72
+
73
+ An `excerpt_only` item is judged by its subject and first lines. When it may be an order, an invoice, a payment, a
74
+ delivery, a request from a site form or anything else above, read it whole before you keep it:
75
+ `memo messages show '<ref>' --trimmed --json`; cite it by the item's `ref` and `fingerprint` as usual. A newsletter or
76
+ a notification with nothing for the owner is dropped unread. When one sender fills the excerpts with such mail, name
77
+ it in the report with the envelope rule that would file it (see the hard rules).
62
78
 
63
79
  ### 3. Context — only for kept emails, only through existing links
64
80
 
@@ -87,6 +103,23 @@ plainly.
87
103
  - `fact` — a decision, agreement or stated detail about a person, organization or project (`subject` or `project`).
88
104
  - `memory` — a longer summary worth keeping about a person or project.
89
105
  - `link` — address → person, person → organization, thread → project; only when the mail shows it.
106
+ - `invoice` — a bill the owner must pay (`direction: payable`) or one he sent (`receivable`). `counterparty` is a
107
+ `person:` or `organization:`: the sender's `from.ref` when nothing better is linked. `currency` (ISO 4217, such as
108
+ RUB), `lines` (`description` and `amount`; one line with the total is fine), and `number`, `issue_date`, `due_date`
109
+ (`YYYY-MM-DD`) and `total` when the mail gives them.
110
+ - `payment` — money that moved: a receipt or a bank confirmation. `direction: out` when the owner paid, `in` when he
111
+ was paid; `amount`, `currency`, `date`; `payee` or `payer` as a `person:` or `organization:`; `reference` for the
112
+ receipt number. `allocations` (`invoice`, `amount`) only for an invoice already stored (`memo invoices list`).
113
+ - `order` — an order confirmation. `purpose`: `personal` (for the owner himself), `business`, `client` (bought for a
114
+ client) or `other`. `supplier_name` is the shop as the mail names it; `supplier` its `organization:` or `person:`
115
+ when linked; `customer` only when it is for someone else than the owner; `number`, `total` with `currency`,
116
+ `order_date`, and `status` (`placed` by default).
117
+ - `order_update` — a later mail about an order: `status` `shipped`, `delivered` (with `date`), `cancelled` or
118
+ `returned`, with the order's `supplier_name` and `number`. Check it is stored first:
119
+ `memo orders list number:<number> --json`. Not stored yet → an `order` with the newest status instead.
120
+ - Account and certificate data → a `fact` (`type: fact`): the statement names what it is, the number and the expiry
121
+ date, such as "E-signature certificate 12-345 from <issuer>, expires 2027-03-01". `subject` is the organization
122
+ or person it belongs to when linked.
90
123
 
91
124
  ### 5. New senders, among kept emails
92
125
 
@@ -113,7 +146,8 @@ memo mail findings add - --source email:<address> --json <<'JSON'
113
146
  JSON
114
147
  ```
115
148
 
116
- Nothing worth proposing: stage nothing. Then, and only then:
149
+ An invoice, a payment and an order from one email are three findings, each citing it. Nothing worth proposing:
150
+ stage nothing. Then, and only then:
117
151
 
118
152
  ```sh
119
153
  memo messages acknowledge --holder mail-triage --cursor <cursor> --source email:<address>
@@ -1,86 +0,0 @@
1
- import { createRequire as __bundleRequire } from "node:module";
2
- const require = __bundleRequire(import.meta.url);
3
- import {
4
- DEFAULT_EVERY,
5
- PLACE_VARIABLES,
6
- applyAuto,
7
- autoCommand,
8
- autoNotice,
9
- autoState,
10
- followInstall,
11
- globalRoots,
12
- interval,
13
- lastAutoRun,
14
- placesOf,
15
- recordAutoRun,
16
- serviceUnit,
17
- timerUnit
18
- } from "./chunk-YZKHWANJ.js";
19
- import "./chunk-KCQPEY6C.js";
20
- import "./chunk-KFSZAV5L.js";
21
- import "./chunk-QP3KNC5D.js";
22
- import "./chunk-6IJ7XNK5.js";
23
- import "./chunk-7OYQFT5N.js";
24
- import "./chunk-WFQPCCM2.js";
25
- import "./chunk-SQ6OFUHW.js";
26
- import "./chunk-6YDPWVDH.js";
27
- import "./chunk-XHHSQ4FN.js";
28
- import "./chunk-IQEEOXBV.js";
29
- import "./chunk-SZUYOU6U.js";
30
- import "./chunk-MJF6VGW4.js";
31
- import "./chunk-DXCBZT4T.js";
32
- import "./chunk-IIM3FF5L.js";
33
- import "./chunk-HTQTIKWP.js";
34
- import "./chunk-7PH33JE4.js";
35
- import "./chunk-KIJ7UJHD.js";
36
- import "./chunk-WI7KTIMF.js";
37
- import "./chunk-XUHVJGIL.js";
38
- import "./chunk-I7PL5WX2.js";
39
- import "./chunk-YPF6OS37.js";
40
- import "./chunk-ZW44VJNY.js";
41
- import "./chunk-PUQYCAEP.js";
42
- import "./chunk-XNV2JTJ4.js";
43
- import "./chunk-RGPCN63U.js";
44
- import "./chunk-KJEJOWJY.js";
45
- import "./chunk-2O2RWKUT.js";
46
- import "./chunk-ERZLVE54.js";
47
- import "./chunk-H3NMOWPB.js";
48
- import "./chunk-NIEWG4OY.js";
49
- import "./chunk-HAC3CWPB.js";
50
- import "./chunk-7ACGYEGV.js";
51
- import "./chunk-65YDJ3Z4.js";
52
- import "./chunk-HVD2CTPH.js";
53
- import "./chunk-P5FETWRW.js";
54
- import "./chunk-S67KFN67.js";
55
- import "./chunk-G62DN6QY.js";
56
- import "./chunk-5ZWRS2JY.js";
57
- import "./chunk-FUMGREBO.js";
58
- import "./chunk-R7XIZMM5.js";
59
- import "./chunk-W7T2JSKY.js";
60
- import "./chunk-KV4267S4.js";
61
- import "./chunk-LU3WKZBA.js";
62
- import "./chunk-D72URWJE.js";
63
- import "./chunk-6BS3FHTC.js";
64
- import "./chunk-H6JNEHUC.js";
65
- import "./chunk-TZ7WDQPD.js";
66
- import "./chunk-G2BB5WY5.js";
67
- import "./chunk-Y5E2WNWB.js";
68
- import "./chunk-EB2IULWB.js";
69
- import "./chunk-ERRC42BB.js";
70
- import "./chunk-ZVVMGPBJ.js";
71
- export {
72
- DEFAULT_EVERY,
73
- PLACE_VARIABLES,
74
- applyAuto,
75
- autoCommand,
76
- autoNotice,
77
- autoState,
78
- followInstall,
79
- globalRoots,
80
- interval,
81
- lastAutoRun,
82
- placesOf,
83
- recordAutoRun,
84
- serviceUnit,
85
- timerUnit
86
- };
@@ -1,452 +0,0 @@
1
- import { createRequire as __bundleRequire } from "node:module";
2
- const require = __bundleRequire(import.meta.url);
3
- import {
4
- require_dist
5
- } from "./chunk-QP3KNC5D.js";
6
- import {
7
- SCHEDULE_SETTINGS,
8
- scheduleLimitsOf
9
- } from "./chunk-6IJ7XNK5.js";
10
- import {
11
- knownPermissionKeys
12
- } from "./chunk-SZUYOU6U.js";
13
- import {
14
- KEEP_RUNS_FOR_DAYS,
15
- KEEP_SUCCESSFUL_RUNS_FOR_DAYS,
16
- RUNS_SIZE_LIMIT_MB,
17
- checkConfigText,
18
- issueMessage,
19
- readConfigFile,
20
- readConfigText,
21
- settingPathOf,
22
- withSettingDefaults,
23
- withoutSetting
24
- } from "./chunk-KIJ7UJHD.js";
25
- import {
26
- DEFAULT_DECISION_POLICY
27
- } from "./chunk-ERZLVE54.js";
28
- import {
29
- configFilePath,
30
- resolvePaths,
31
- saveConfigFile
32
- } from "./chunk-TZ7WDQPD.js";
33
- import {
34
- array,
35
- boolean,
36
- integer,
37
- literal,
38
- minLength,
39
- minValue,
40
- number,
41
- optional,
42
- picklist,
43
- pipe,
44
- record,
45
- regex,
46
- strictObject,
47
- string,
48
- union,
49
- unknown
50
- } from "./chunk-G2BB5WY5.js";
51
- import {
52
- CliError
53
- } from "./chunk-EB2IULWB.js";
54
- import {
55
- __name,
56
- __toESM
57
- } from "./chunk-ZVVMGPBJ.js";
58
-
59
- // dist/config-issues.js
60
- var pathOf = /* @__PURE__ */ __name((command) => {
61
- const words = [];
62
- for (let at = command; at.parent; at = at.parent)
63
- words.unshift(at.name());
64
- return words;
65
- }, "pathOf");
66
- var permissionKeyOf = /* @__PURE__ */ __name((command) => pathOf(command).join(".") || null, "permissionKeyOf");
67
- var memoPermissionKeys = /* @__PURE__ */ __name((program) => knownPermissionKeys(program, permissionKeyOf, ["mcp.authority"]), "memoPermissionKeys");
68
-
69
- // dist/notes/files.js
70
- import { closeSync, openSync, readdirSync, readSync } from "node:fs";
71
- import { join, relative, sep } from "node:path";
72
- var NOTE_EXTENSIONS = [
73
- ".md",
74
- ".markdown",
75
- ".txt",
76
- ".csv",
77
- ".tsv",
78
- ".pdf",
79
- ".docx",
80
- ".xlsx",
81
- ".odt",
82
- ".ods",
83
- ".pptx",
84
- ".epub",
85
- ".doc",
86
- ".xls"
87
- ];
88
- var MEMO_ID = /^---\r?\n(?:[^\n]*\n)*?memo-id:[ \t]*["']?([^"'\s]+)/;
89
- var HEAD = 1024;
90
- var readMemoId = /* @__PURE__ */ __name((path) => {
91
- const buffer = Buffer.alloc(HEAD);
92
- const descriptor = openSync(path, "r");
93
- try {
94
- const head = buffer.subarray(0, readSync(descriptor, buffer, 0, HEAD, 0)).toString("utf8");
95
- const end = head.indexOf("\n---", 3);
96
- return MEMO_ID.exec(end < 0 ? head : head.slice(0, end + 1))?.[1] ?? null;
97
- } finally {
98
- closeSync(descriptor);
99
- }
100
- }, "readMemoId");
101
- var TEXT_NOTE = /\.(md|markdown)$/i;
102
- var isExported = /* @__PURE__ */ __name((path) => TEXT_NOTE.test(path) && readMemoId(path) !== null, "isExported");
103
- var pattern = /* @__PURE__ */ __name((rule) => {
104
- const glob = rule.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
105
- const body = glob.split(/(\*\*\/?|\*|\?)/).map((part) => part === "**/" || part === "**" ? ".*" : part === "*" ? "[^/]*" : part === "?" ? "[^/]" : part.replace(/[.+^${}()|[\]\\]/g, "\\$&")).join("");
106
- return new RegExp(`^${body}(/.*)?$`, "i");
107
- }, "pattern");
108
- var matcher = /* @__PURE__ */ __name((rules) => {
109
- const patterns = rules.map(pattern);
110
- return (inside) => patterns.some((rule) => rule.test(inside));
111
- }, "matcher");
112
- var noteFiles = /* @__PURE__ */ __name((folder, ignore = [], extensions = NOTE_EXTENSIONS, { skipExported = true } = {}) => {
113
- const matches = matcher(ignore);
114
- const ignored = /* @__PURE__ */ __name((path) => matches(relative(folder, path).split(sep).join("/")), "ignored");
115
- const walk = /* @__PURE__ */ __name((dir) => readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
116
- if (entry.name.startsWith("."))
117
- return [];
118
- const path = join(dir, entry.name);
119
- if (ignored(path))
120
- return [];
121
- if (entry.isDirectory())
122
- return walk(path);
123
- if (!entry.isFile() || !extensions.some((ext) => entry.name.toLowerCase().endsWith(ext)))
124
- return [];
125
- return skipExported && isExported(path) ? [] : [path];
126
- }), "walk");
127
- return walk(folder);
128
- }, "noteFiles");
129
-
130
- // dist/notes/dialects/common.js
131
- var import_yaml = __toESM(require_dist(), 1);
132
- import { posix } from "node:path";
133
- var FRONT_MATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
134
- var REFERENCE = /^(msg|note|document|person|organization|project|task|chat|contact):\S+$/;
135
- var BARE_REFERENCE = /(?<![\w/:])((?:msg|note|document|person|organization|project|task|chat|contact):[^\s<>()[\]"'`]+)/g;
136
- var MAX_LINKS = 200;
137
- var isReference = /* @__PURE__ */ __name((target) => REFERENCE.test(target), "isReference");
138
- var splitFrontMatter = /* @__PURE__ */ __name((text) => {
139
- const match = FRONT_MATTER.exec(text);
140
- if (!match)
141
- return { frontMatter: {}, body: text };
142
- let data;
143
- try {
144
- data = (0, import_yaml.parse)(match[1] ?? "");
145
- } catch {
146
- data = null;
147
- }
148
- const frontMatter = data !== null && typeof data === "object" && !Array.isArray(data) ? data : {};
149
- return { frontMatter, body: text.slice(match[0].length) };
150
- }, "splitFrontMatter");
151
- var strings = /* @__PURE__ */ __name((value) => typeof value === "string" ? value.split(/[,\s]+/).map((item) => item.trim()).filter(Boolean) : Array.isArray(value) ? value.filter((item) => typeof item === "string").map((item) => item.trim()) : [], "strings");
152
- var frontMatterAliases = /* @__PURE__ */ __name((frontMatter) => {
153
- const value = frontMatter.aliases ?? frontMatter.alias;
154
- return typeof value === "string" ? [value.trim()] : strings(value);
155
- }, "frontMatterAliases");
156
- var frontMatterTags = /* @__PURE__ */ __name((frontMatter) => strings(frontMatter.tags ?? frontMatter.tag).map((tag) => tag.replace(/^#/, "")), "frontMatterTags");
157
- var withoutCode = /* @__PURE__ */ __name((body) => body.replace(/^(```|~~~)[^\n]*\n[\s\S]*?^\1[^\n]*$/gm, "").replace(/`[^`\n]*`/g, ""), "withoutCode");
158
- var titleOf = /* @__PURE__ */ __name((frontMatter, body, path) => {
159
- if (typeof frontMatter.title === "string" && frontMatter.title.trim())
160
- return frontMatter.title.trim();
161
- const heading = /^#\s+(.+?)\s*#*\s*$/m.exec(withoutCode(body))?.[1];
162
- return heading ?? posix.basename(path.replace(/\\/g, "/")).replace(/\.[^./]+$/, "");
163
- }, "titleOf");
164
- var dropNoteExtension = /* @__PURE__ */ __name((target) => target.replace(/\.(md|markdown)$/i, ""), "dropNoteExtension");
165
- var bareReferences = /* @__PURE__ */ __name((body) => [...body.matchAll(BARE_REFERENCE)].map((match) => ({
166
- target: (match[1] ?? "").replace(/[.,;:!?]+$/, ""),
167
- anchor: null,
168
- label: null
169
- })), "bareReferences");
170
- var dedupe = /* @__PURE__ */ __name((links) => {
171
- const seen = /* @__PURE__ */ new Set();
172
- return links.filter((link) => {
173
- const key = `${link.target}\0${link.anchor ?? ""}\0${link.label ?? ""}`;
174
- if (seen.has(key))
175
- return false;
176
- seen.add(key);
177
- return true;
178
- }).slice(0, MAX_LINKS);
179
- }, "dedupe");
180
- var parsedNote = /* @__PURE__ */ __name((frontMatter, body, path, links, inlineTags2 = []) => ({
181
- title: titleOf(frontMatter, body, path),
182
- aliases: frontMatterAliases(frontMatter),
183
- tags: [.../* @__PURE__ */ new Set([...frontMatterTags(frontMatter), ...inlineTags2])],
184
- links: dedupe(links),
185
- frontMatter
186
- }), "parsedNote");
187
- var renderNote = /* @__PURE__ */ __name((note, link) => {
188
- const frontMatter = {
189
- ...note.frontMatter,
190
- ...note.aliases.length ? { aliases: note.aliases } : {},
191
- ...note.tags.length ? { tags: note.tags } : {}
192
- };
193
- const head = Object.keys(frontMatter).length ? `---
194
- ${(0, import_yaml.stringify)(frontMatter).trimEnd()}
195
- ---
196
- ` : "";
197
- const links = note.links.length ? `
198
-
199
- ${note.links.map((item) => `- ${link(item)}`).join("\n")}` : "";
200
- return `${head}# ${note.title}
201
-
202
- ${note.text.trimEnd()}${links}
203
- `;
204
- }, "renderNote");
205
-
206
- // dist/notes/dialects/markdown.js
207
- var LINK = /(?<!!)\[([^\]\n]*)\]\(\s*(<[^>\n]+>|[^)\s]+)(?:\s+"[^"\n]*")?\s*\)/g;
208
- var SCHEME = /^[a-z][a-z0-9+.-]*:/i;
209
- var decode = /* @__PURE__ */ __name((value) => {
210
- try {
211
- return decodeURIComponent(value);
212
- } catch {
213
- return value;
214
- }
215
- }, "decode");
216
- var linkOf = /* @__PURE__ */ __name((label, destination) => {
217
- const angled = destination.startsWith("<") && destination.endsWith(">");
218
- const raw = angled ? destination.slice(1, -1) : destination;
219
- if (isReference(raw))
220
- return { target: raw, anchor: null, label: label.trim() || null };
221
- if (SCHEME.test(raw))
222
- return null;
223
- const hash = raw.indexOf("#");
224
- const path = hash < 0 ? raw : raw.slice(0, hash);
225
- const fragment = hash < 0 ? null : raw.slice(hash + 1);
226
- return {
227
- target: dropNoteExtension(angled ? path : decode(path)).trim(),
228
- anchor: fragment === null ? null : `#${angled ? fragment : decode(fragment)}`,
229
- label: label.trim() || null
230
- };
231
- }, "linkOf");
232
- var markdownLinks = /* @__PURE__ */ __name((body) => [...withoutCode(body).matchAll(LINK)].map((match) => linkOf(match[1] ?? "", match[2] ?? "")).filter((link) => link !== null), "markdownLinks");
233
- var stripMarkdownLinks = /* @__PURE__ */ __name((body) => body.replace(LINK, " "), "stripMarkdownLinks");
234
- var hasOwnExtension = /* @__PURE__ */ __name((target) => NOTE_EXTENSIONS.some((extension) => target.toLowerCase().endsWith(extension)), "hasOwnExtension");
235
- var markdownLink = /* @__PURE__ */ __name((link) => {
236
- if (isReference(link.target))
237
- return `[${link.label ?? link.target}](${link.target})`;
238
- const file = hasOwnExtension(link.target) ? link.target : `${link.target}.md`;
239
- const label = link.label ?? link.target.split("/").pop() ?? link.target;
240
- return `[${label}](<${file}${link.anchor ?? ""}>)`;
241
- }, "markdownLink");
242
- var markdown = {
243
- name: "markdown",
244
- parse(text, path) {
245
- const { frontMatter, body } = splitFrontMatter(text);
246
- const links = markdownLinks(body);
247
- return parsedNote(frontMatter, body, path, [...links, ...bareReferences(withoutCode(stripMarkdownLinks(body)))]);
248
- },
249
- render: /* @__PURE__ */ __name((note) => renderNote(note, markdownLink), "render")
250
- };
251
-
252
- // dist/notes/dialects/obsidian.js
253
- var WIKI = /!?\[\[([^\]|\n]+)(?:\|([^\]\n]*))?\]\]/g;
254
- var TAG = /(?<![\p{L}\p{N}_#&/])#([\p{L}_][\p{L}\p{N}_/-]*)/gu;
255
- var wikiLinks = /* @__PURE__ */ __name((body) => [...withoutCode(body).matchAll(WIKI)].map((match) => {
256
- const raw = (match[1] ?? "").trim();
257
- const label = match[2]?.trim() || null;
258
- if (isReference(raw))
259
- return { target: raw, anchor: null, label };
260
- const split = raw.search(/[#^]/);
261
- return {
262
- target: dropNoteExtension(split < 0 ? raw : raw.slice(0, split)).trim(),
263
- anchor: split < 0 ? null : raw.slice(split),
264
- label
265
- };
266
- }), "wikiLinks");
267
- var inlineTags = /* @__PURE__ */ __name((body) => [
268
- ...new Set([...stripMarkdownLinks(withoutCode(body).replace(WIKI, " ")).matchAll(TAG)].map((match) => match[1] ?? ""))
269
- ], "inlineTags");
270
- var wikiLink = /* @__PURE__ */ __name((link) => isReference(link.target) ? markdownLink(link) : `[[${link.target}${link.anchor ?? ""}${link.label ? `|${link.label}` : ""}]]`, "wikiLink");
271
- var obsidian = {
272
- name: "obsidian",
273
- parse(text, path) {
274
- const { frontMatter, body } = splitFrontMatter(text);
275
- const rest = stripMarkdownLinks(withoutCode(body).replace(WIKI, " "));
276
- return parsedNote(frontMatter, body, path, [...wikiLinks(body), ...markdownLinks(body), ...bareReferences(rest)], inlineTags(body));
277
- },
278
- render: /* @__PURE__ */ __name((note) => renderNote(note, wikiLink), "render")
279
- };
280
-
281
- // dist/notes/dialects/types.js
282
- var DIALECTS = ["obsidian", "markdown"];
283
-
284
- // dist/notes/dialects/index.js
285
- var BY_NAME = { obsidian, markdown };
286
- var dialectOf = /* @__PURE__ */ __name((name = "obsidian") => BY_NAME[name], "dialectOf");
287
-
288
- // dist/config.js
289
- var ConfigSchema = strictObject({
290
- permissions: optional(record(string(), picklist(["deny", "readonly", "ask", "allow"]))),
291
- notes: optional(strictObject({
292
- /** A bare path is the form before folder ids; `memo folders add` turns it into an entry. */
293
- folders: array(union([
294
- string(),
295
- strictObject({
296
- id: pipe(string(), minLength(1)),
297
- path: pipe(string(), minLength(1)),
298
- format: optional(picklist(DIALECTS))
299
- })
300
- ])),
301
- ignore: optional(array(string())),
302
- /** `false` keeps notes out of search by meaning: `memo sync` does not embed them. */
303
- embed: optional(boolean()),
304
- /** Where `memo notes export` and `--export` write internal notes when no folder is given. */
305
- export: optional(strictObject({ dir: pipe(string(), minLength(1)), format: optional(picklist(DIALECTS)) }))
306
- })),
307
- auto: optional(strictObject({
308
- enabled: optional(boolean()),
309
- every: optional(string()),
310
- /** MEMO_CONFIG_DIR, MESSAGING_STORE… as they were at `memo jobs start`, passed to every timer run. */
311
- places: optional(record(string(), string()))
312
- })),
313
- /** `false` keeps only failed runs in `memo runs list`. `--record` and `--no-record` win. */
314
- record: optional(boolean()),
315
- keep_runs_for_days: optional(pipe(number(), integer(), minValue(1))),
316
- keep_successful_runs_for_days: optional(pipe(number(), integer(), minValue(1))),
317
- runs_size_limit_mb: optional(pipe(number(), integer(), minValue(1))),
318
- /** `false` leaves what was typed out of a run's command line, `"failed"` out of a successful one; secrets always. */
319
- record_input: optional(union([boolean(), literal("failed")])),
320
- /** `false` stops the once-a-day check for a newer memo. */
321
- update_check: optional(boolean()),
322
- /** `false` stops an agent deciding proposals for you: `projects actions confirm` and `reject` then need you. */
323
- agent_decisions: optional(boolean()),
324
- /** An agent gated on new mail starts once the oldest waiting email waited this long (`30m`), or this many wait. */
325
- schedule_mail_wait: optional(pipe(string(), regex(/^\d+[mhd]$/, "has to be a duration such as 30m or 2h"))),
326
- schedule_mail_batch: optional(pipe(number(), integer(), minValue(1))),
327
- /** US dollars a day of an agent schedule's runs may cost; 0 turns the cap off. */
328
- schedule_max_cost_per_day: optional(pipe(number(), minValue(0))),
329
- /** The model a new agent schedule runs on unless `--model` names one; empty for the harness's own default. */
330
- schedule_model_claude: optional(string()),
331
- schedule_model_codex: optional(string()),
332
- /** `false` lets a new claude agent schedule load your MCP servers, skills, settings and CLAUDE.md. */
333
- schedule_lean_start: optional(boolean()),
334
- /** Retired: memo no longer imports mail, the `mail` CLI does. Still loads so an old config works; doctor names it. */
335
- mail: optional(unknown())
336
- });
337
- var MEMO_SETTINGS = [
338
- {
339
- key: "agent_decisions",
340
- default: DEFAULT_DECISION_POLICY.agentDecisions,
341
- description: "true lets an agent confirm or reject proposals for you; false keeps every decision yours"
342
- },
343
- { key: "update_check", default: true, description: "check once a day for a newer memo" },
344
- { key: "record", default: true, description: "keep every run in memo runs list; false keeps failed runs only" },
345
- {
346
- key: "record_input",
347
- default: true,
348
- description: `keep what was typed in a run's command line: true, false, or "failed" for failed runs only`
349
- },
350
- { key: "keep_runs_for_days", default: KEEP_RUNS_FOR_DAYS, description: "days a run is kept" },
351
- {
352
- key: "keep_successful_runs_for_days",
353
- default: KEEP_SUCCESSFUL_RUNS_FOR_DAYS,
354
- description: "days a successful run is kept"
355
- },
356
- { key: "runs_size_limit_mb", default: RUNS_SIZE_LIMIT_MB, description: "the most megabytes all runs may take" },
357
- { key: "notes.embed", default: true, description: "false keeps notes out of search by meaning" },
358
- ...SCHEDULE_SETTINGS
359
- ];
360
- var configPath = /* @__PURE__ */ __name((env = process.env) => configFilePath(resolvePaths({ appName: "cli-memo", prefix: "MEMO", env }).config), "configPath");
361
- var loadConfig = /* @__PURE__ */ __name((env = process.env) => {
362
- const path = configPath(env);
363
- const read = readConfigText(path);
364
- if ("issue" in read)
365
- throw new CliError("configuration_error", issueMessage([read.issue], "memo doctor"));
366
- if (read.text === void 0)
367
- return {};
368
- const { issues, config } = checkConfigText(read.text, { file: path, tool: "memo", schema: ConfigSchema });
369
- if (issues.length > 0 || config === void 0)
370
- throw new CliError("configuration_error", issueMessage(issues, "memo doctor"));
371
- return config;
372
- }, "loadConfig");
373
- var decisionPolicy = /* @__PURE__ */ __name((env) => {
374
- let agentDecisions = false;
375
- try {
376
- agentDecisions = loadConfig(env).agent_decisions === true;
377
- } catch {
378
- }
379
- return { ...DEFAULT_DECISION_POLICY, agentDecisions };
380
- }, "decisionPolicy");
381
- var scheduleLimits = /* @__PURE__ */ __name((env) => {
382
- try {
383
- return scheduleLimitsOf(loadConfig(env));
384
- } catch {
385
- return {};
386
- }
387
- }, "scheduleLimits");
388
- var inspectConfig = /* @__PURE__ */ __name((env, program) => {
389
- const path = configPath(env);
390
- const read = readConfigText(path);
391
- if ("issue" in read)
392
- return { path, found: true, issues: [read.issue], config: {} };
393
- if (read.text === void 0)
394
- return { path, found: false, issues: [], config: {} };
395
- const { issues, config } = checkConfigText(read.text, {
396
- file: path,
397
- tool: "memo",
398
- schema: ConfigSchema,
399
- knownPermissions: memoPermissionKeys(program)
400
- });
401
- return { path, found: true, issues, config: config ?? {} };
402
- }, "inspectConfig");
403
- var unsetConfigKey = /* @__PURE__ */ __name((key, env = process.env) => {
404
- if (settingPathOf(key).some((part) => part === ""))
405
- throw new CliError("validation_error", `${key} is not a setting path`);
406
- const path = configPath(env);
407
- const read = readConfigFile(path);
408
- if ("issue" in read)
409
- throw new CliError("configuration_error", issueMessage([read.issue], "memo doctor"));
410
- const { config, removed } = withoutSetting(read.raw, key);
411
- if (removed)
412
- saveConfigFile(path, config);
413
- return removed;
414
- }, "unsetConfigKey");
415
- var updateConfig = /* @__PURE__ */ __name((change, env = process.env) => {
416
- const next = change(loadConfig(env));
417
- saveConfigFile(configPath(env), withSettingDefaults(next, MEMO_SETTINGS).config);
418
- return next;
419
- }, "updateConfig");
420
- var rawConfig = /* @__PURE__ */ __name((env = process.env) => {
421
- const read = readConfigFile(configPath(env));
422
- if ("issue" in read)
423
- throw new CliError("configuration_error", issueMessage([read.issue], "memo doctor"));
424
- return read.raw;
425
- }, "rawConfig");
426
- var migrateConfig = /* @__PURE__ */ __name((env = process.env) => {
427
- const { config, added } = withSettingDefaults(rawConfig(env), MEMO_SETTINGS);
428
- if (added.length > 0)
429
- saveConfigFile(configPath(env), config);
430
- return added;
431
- }, "migrateConfig");
432
-
433
- export {
434
- memoPermissionKeys,
435
- NOTE_EXTENSIONS,
436
- readMemoId,
437
- matcher,
438
- noteFiles,
439
- isReference,
440
- DIALECTS,
441
- dialectOf,
442
- MEMO_SETTINGS,
443
- configPath,
444
- loadConfig,
445
- decisionPolicy,
446
- scheduleLimits,
447
- inspectConfig,
448
- unsetConfigKey,
449
- updateConfig,
450
- rawConfig,
451
- migrateConfig
452
- };