@wirecat/cli-memo 0.131.21 → 0.131.22

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 (55) hide show
  1. package/README.md +3 -3
  2. package/dist/bin/memo.js +2 -2
  3. package/dist/bundle/{app-server-26YPLJ7M.js → app-server-PRQVGA5X.js} +5 -5
  4. package/dist/bundle/{auto-QHTPHGNA.js → auto-S3AYMAGB.js} +11 -11
  5. package/dist/bundle/{chunk-JXH22ZGA.js → chunk-3B645KUY.js} +2 -2
  6. package/dist/bundle/{chunk-7NEWBM2O.js → chunk-4SGCOUQ6.js} +2 -2
  7. package/dist/bundle/{chunk-J4GC33JU.js → chunk-5UOOH7VG.js} +1 -1
  8. package/dist/bundle/{chunk-UXCSNSUU.js → chunk-6JOT5KWM.js} +9 -9
  9. package/dist/bundle/{chunk-ZCKU6WMX.js → chunk-7W3RCCRR.js} +1 -1
  10. package/dist/bundle/{chunk-JJ3C5AYK.js → chunk-CBYZW5CC.js} +2 -2
  11. package/dist/bundle/{chunk-TMNHNZVA.js → chunk-HXRIV2TV.js} +2 -2
  12. package/dist/bundle/{chunk-EAYYWS67.js → chunk-IFWBFYXN.js} +1 -1
  13. package/dist/bundle/{chunk-YUFUUQUO.js → chunk-ILC7NFS2.js} +1 -1
  14. package/dist/bundle/{chunk-B3YV6Z7Y.js → chunk-J35OGOCI.js} +1 -1
  15. package/dist/bundle/{chunk-INURBEAO.js → chunk-KXERKAID.js} +1 -1
  16. package/dist/bundle/{chunk-FFWK5NEZ.js → chunk-OFYKXQMS.js} +3 -3
  17. package/dist/bundle/{chunk-NOG5O2NS.js → chunk-SO2YVKBK.js} +4 -4
  18. package/dist/bundle/{chunk-NWB5NAGB.js → chunk-UCINAEIA.js} +2 -2
  19. package/dist/bundle/{chunk-PO5C7VNC.js → chunk-UG2V7BQY.js} +1 -1
  20. package/dist/bundle/{chunk-R26CXR5Z.js → chunk-VDBFSLHP.js} +3 -3
  21. package/dist/bundle/{chunk-CRZSJHAK.js → chunk-XW4KGSAA.js} +1 -1
  22. package/dist/bundle/{chunk-J55Z6EJ3.js → chunk-ZKWE5MCA.js} +605 -9
  23. package/dist/bundle/{entry-DO6ZBFIS.js → entry-L42C5CHF.js} +1 -1
  24. package/dist/bundle/{failure-LHMJNFY6.js → failure-TQJGSWRU.js} +9 -9
  25. package/dist/bundle/{first-run-BXFQN6M5.js → first-run-TT6KMHKA.js} +1 -1
  26. package/dist/bundle/{mcp-A4HPKQK5.js → mcp-PNC3TI7O.js} +3 -3
  27. package/dist/bundle/memo.js +6 -6
  28. package/dist/bundle/{program-3ZTQ5FEM.js → program-ZIRYOO2T.js} +141 -94
  29. package/dist/bundle/{server-NQK5EX7P.js → server-F2PSE6LG.js} +3 -3
  30. package/dist/bundle/{server-UN43Y6BY.js → server-K5JYA3ZT.js} +5 -5
  31. package/dist/bundle/{server-BMQBWBBN.js → server-VO5SXU5A.js} +14 -14
  32. package/dist/bundle/{setup-FGSVWQ32.js → setup-X6OJ3K4F.js} +9 -9
  33. package/dist/bundle/{store-maintenance-command-QTEWWDST.js → store-maintenance-command-R4CP6AZN.js} +3 -3
  34. package/dist/bundle/{update-XC6KAVCK.js → update-M6AIJ2SZ.js} +10 -10
  35. package/dist/examples.d.ts.map +1 -1
  36. package/dist/examples.js +5 -1
  37. package/dist/examples.js.map +1 -1
  38. package/dist/knowledge/command.d.ts.map +1 -1
  39. package/dist/knowledge/command.js +8 -52
  40. package/dist/knowledge/command.js.map +1 -1
  41. package/dist/knowledge/project-gather-command.d.ts.map +1 -1
  42. package/dist/knowledge/project-gather-command.js +32 -19
  43. package/dist/knowledge/project-gather-command.js.map +1 -1
  44. package/dist/knowledge/relationships-scan.d.ts +8 -0
  45. package/dist/knowledge/relationships-scan.d.ts.map +1 -0
  46. package/dist/knowledge/relationships-scan.js +95 -0
  47. package/dist/knowledge/relationships-scan.js.map +1 -0
  48. package/dist/store/source-list.d.ts +2 -0
  49. package/dist/store/source-list.d.ts.map +1 -1
  50. package/dist/store/source-list.js +6 -0
  51. package/dist/store/source-list.js.map +1 -1
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.js +1 -1
  54. package/package.json +1 -1
  55. package/skills/cli-memo/SKILL.md +1 -1
@@ -6,27 +6,27 @@ import {
6
6
  recognisable,
7
7
  reportFailure,
8
8
  throwParseFailures
9
- } from "./chunk-YUFUUQUO.js";
10
- import "./chunk-UXCSNSUU.js";
9
+ } from "./chunk-ILC7NFS2.js";
10
+ import "./chunk-6JOT5KWM.js";
11
11
  import "./chunk-ZD3STMY7.js";
12
12
  import "./chunk-DNGHE2Q4.js";
13
- import "./chunk-TMNHNZVA.js";
13
+ import "./chunk-HXRIV2TV.js";
14
14
  import "./chunk-XA6YO24S.js";
15
15
  import "./chunk-RG6ITTLQ.js";
16
- import "./chunk-JJ3C5AYK.js";
17
- import "./chunk-PO5C7VNC.js";
18
- import "./chunk-J55Z6EJ3.js";
16
+ import "./chunk-CBYZW5CC.js";
17
+ import "./chunk-UG2V7BQY.js";
18
+ import "./chunk-ZKWE5MCA.js";
19
19
  import "./chunk-SXGAIQ5X.js";
20
20
  import "./chunk-GV2FSWFS.js";
21
21
  import "./chunk-HTQTIKWP.js";
22
22
  import "./chunk-WEOFWTWZ.js";
23
23
  import "./chunk-VQM3H422.js";
24
24
  import "./chunk-RC7TIYUZ.js";
25
- import "./chunk-EAYYWS67.js";
25
+ import "./chunk-IFWBFYXN.js";
26
26
  import "./chunk-3V4WIGWC.js";
27
27
  import "./chunk-PQLBPYJR.js";
28
28
  import "./chunk-SMDWUPXE.js";
29
- import "./chunk-ZCKU6WMX.js";
29
+ import "./chunk-7W3RCCRR.js";
30
30
  import "./chunk-NELE7AIX.js";
31
31
  import "./chunk-CP5N3KH3.js";
32
32
  import "./chunk-RHJC4PHV.js";
@@ -45,7 +45,7 @@ import "./chunk-LGNS4JVK.js";
45
45
  import "./chunk-LR5EY5JY.js";
46
46
  import "./chunk-VXHN3SWW.js";
47
47
  import "./chunk-BPGYTJNB.js";
48
- import "./chunk-B3YV6Z7Y.js";
48
+ import "./chunk-J35OGOCI.js";
49
49
  import "./chunk-ILHTNOIV.js";
50
50
  import "./chunk-NUN6OGOV.js";
51
51
  import "./chunk-D72URWJE.js";
@@ -5,7 +5,7 @@ import {
5
5
  asksAtStart,
6
6
  setupAtStart,
7
7
  systemLanguage
8
- } from "./chunk-EAYYWS67.js";
8
+ } from "./chunk-IFWBFYXN.js";
9
9
  import "./chunk-3V4WIGWC.js";
10
10
  import "./chunk-PQLBPYJR.js";
11
11
  import "./chunk-SMDWUPXE.js";
@@ -3,7 +3,7 @@ const require = __bundleRequire(import.meta.url);
3
3
  import "./chunk-YYQN5ES2.js";
4
4
  import {
5
5
  createBotServer
6
- } from "./chunk-JXH22ZGA.js";
6
+ } from "./chunk-3B645KUY.js";
7
7
  import "./chunk-ZD3STMY7.js";
8
8
  import {
9
9
  MCP_PATH,
@@ -17,7 +17,7 @@ import {
17
17
  registerCommands,
18
18
  runCommandForAgent,
19
19
  toolsFromCommands
20
- } from "./chunk-INURBEAO.js";
20
+ } from "./chunk-KXERKAID.js";
21
21
  import {
22
22
  mcpUrlOf,
23
23
  portOf,
@@ -36,7 +36,7 @@ import {
36
36
  import "./chunk-MM5NVP7F.js";
37
37
  import "./chunk-3X4JM3ZR.js";
38
38
  import "./chunk-H3ZN4YLB.js";
39
- import "./chunk-J55Z6EJ3.js";
39
+ import "./chunk-ZKWE5MCA.js";
40
40
  import "./chunk-SXGAIQ5X.js";
41
41
  import "./chunk-VQM3H422.js";
42
42
  import "./chunk-RC7TIYUZ.js";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-BPGYTJNB.js";
7
7
  import {
8
8
  APP
9
- } from "./chunk-B3YV6Z7Y.js";
9
+ } from "./chunk-J35OGOCI.js";
10
10
  import {
11
11
  installerOf
12
12
  } from "./chunk-ILHTNOIV.js";
@@ -164,7 +164,7 @@ var wcat = await wcatStart({
164
164
  if (wcat.code !== void 0) {
165
165
  process.exitCode = wcat.code;
166
166
  } else {
167
- const { startCli } = await import("./entry-DO6ZBFIS.js");
167
+ const { startCli } = await import("./entry-L42C5CHF.js");
168
168
  let program;
169
169
  let failure;
170
170
  await startCli({
@@ -173,15 +173,15 @@ if (wcat.code !== void 0) {
173
173
  interactive: interactiveOf,
174
174
  reasons: APP.errors.reasons,
175
175
  run: /* @__PURE__ */ __name(async (entry) => {
176
- failure = await import("./failure-LHMJNFY6.js");
177
- const { createProgram, refuseJoinedPath } = await import("./program-3ZTQ5FEM.js");
178
- const { autoNotice, followInstall } = await import("./auto-QHTPHGNA.js");
176
+ failure = await import("./failure-TQJGSWRU.js");
177
+ const { createProgram, refuseJoinedPath } = await import("./program-ZIRYOO2T.js");
178
+ const { autoNotice, followInstall } = await import("./auto-S3AYMAGB.js");
179
179
  if (entry.args[0] !== "jobs") {
180
180
  const notice2 = autoNotice(entry.env);
181
181
  if (notice2)
182
182
  processStreams.diagnostic(notice2);
183
183
  }
184
- const { updateNotice } = await import("./update-XC6KAVCK.js");
184
+ const { updateNotice } = await import("./update-M6AIJ2SZ.js");
185
185
  const notice = updateNotice(entry.args);
186
186
  program = createProgram({ signal: entry.signal });
187
187
  program.hook("preAction", (_root, command) => entry.atStart(command));
@@ -6,22 +6,22 @@ import {
6
6
  autoState,
7
7
  lastAutoRun,
8
8
  recordAutoRun
9
- } from "./chunk-R26CXR5Z.js";
9
+ } from "./chunk-VDBFSLHP.js";
10
10
  import {
11
11
  installer,
12
12
  latest,
13
13
  upgradeCommand
14
- } from "./chunk-FFWK5NEZ.js";
14
+ } from "./chunk-OFYKXQMS.js";
15
15
  import {
16
16
  himalaya,
17
17
  isThrottled,
18
18
  throttledError
19
- } from "./chunk-J4GC33JU.js";
19
+ } from "./chunk-5UOOH7VG.js";
20
20
  import {
21
21
  mcpOwnerAllowed,
22
22
  readOnlyAvailability,
23
23
  refuseWritesUnderLock
24
- } from "./chunk-NWB5NAGB.js";
24
+ } from "./chunk-UCINAEIA.js";
25
25
  import {
26
26
  answers,
27
27
  atDetail as atDetail2,
@@ -31,7 +31,7 @@ import {
31
31
  trackAnswers,
32
32
  wholeList,
33
33
  withStore
34
- } from "./chunk-7NEWBM2O.js";
34
+ } from "./chunk-4SGCOUQ6.js";
35
35
  import {
36
36
  DIALECTS,
37
37
  NOTE_EXTENSIONS,
@@ -46,7 +46,7 @@ import {
46
46
  readMemoId,
47
47
  unsetConfigKey,
48
48
  updateConfig
49
- } from "./chunk-CRZSJHAK.js";
49
+ } from "./chunk-XW4KGSAA.js";
50
50
  import "./chunk-QP3KNC5D.js";
51
51
  import "./chunk-VECICKTE.js";
52
52
  import "./chunk-MHDLZCEO.js";
@@ -54,7 +54,7 @@ import "./chunk-BB2MGFOZ.js";
54
54
  import {
55
55
  errorObject,
56
56
  recognisable
57
- } from "./chunk-YUFUUQUO.js";
57
+ } from "./chunk-ILC7NFS2.js";
58
58
  import {
59
59
  DISCOVERY_DESCRIPTIONS,
60
60
  acknowledgeMark,
@@ -99,7 +99,7 @@ import {
99
99
  tasksStatsCommand,
100
100
  unansweredHours,
101
101
  withSqliteSidecars
102
- } from "./chunk-UXCSNSUU.js";
102
+ } from "./chunk-6JOT5KWM.js";
103
103
  import "./chunk-ZD3STMY7.js";
104
104
  import "./chunk-DNGHE2Q4.js";
105
105
  import {
@@ -110,7 +110,7 @@ import {
110
110
  noteHitItem,
111
111
  offsetOf,
112
112
  shownOf
113
- } from "./chunk-TMNHNZVA.js";
113
+ } from "./chunk-HXRIV2TV.js";
114
114
  import "./chunk-XA6YO24S.js";
115
115
  import {
116
116
  SKILL_TARGETS,
@@ -123,8 +123,8 @@ import {
123
123
  modelGateway,
124
124
  storeInfo,
125
125
  storeSummary
126
- } from "./chunk-JJ3C5AYK.js";
127
- import "./chunk-PO5C7VNC.js";
126
+ } from "./chunk-CBYZW5CC.js";
127
+ import "./chunk-UG2V7BQY.js";
128
128
  import {
129
129
  AGENDA_DEFAULTS,
130
130
  DEFAULT_BACKEND,
@@ -178,6 +178,7 @@ import {
178
178
  readMail,
179
179
  readMeetingPassage,
180
180
  reviewStart,
181
+ scanProjectLinks,
181
182
  searchAll,
182
183
  searchMeetingHits,
183
184
  searchNotesOf,
@@ -193,7 +194,7 @@ import {
193
194
  termField,
194
195
  typedQuery,
195
196
  withQuery
196
- } from "./chunk-J55Z6EJ3.js";
197
+ } from "./chunk-ZKWE5MCA.js";
197
198
  import {
198
199
  readBoundedUtf8File,
199
200
  writeFileAtomic
@@ -246,13 +247,13 @@ import {
246
247
  untrusted
247
248
  } from "./chunk-VQM3H422.js";
248
249
  import "./chunk-RC7TIYUZ.js";
249
- import "./chunk-EAYYWS67.js";
250
+ import "./chunk-IFWBFYXN.js";
250
251
  import {
251
252
  isNewer
252
253
  } from "./chunk-3V4WIGWC.js";
253
254
  import "./chunk-PQLBPYJR.js";
254
255
  import "./chunk-SMDWUPXE.js";
255
- import "./chunk-ZCKU6WMX.js";
256
+ import "./chunk-7W3RCCRR.js";
256
257
  import "./chunk-NELE7AIX.js";
257
258
  import "./chunk-CP5N3KH3.js";
258
259
  import {
@@ -353,7 +354,7 @@ import {
353
354
  REASONS,
354
355
  STORE_CLIENT,
355
356
  VERSION
356
- } from "./chunk-B3YV6Z7Y.js";
357
+ } from "./chunk-J35OGOCI.js";
357
358
  import "./chunk-ILHTNOIV.js";
358
359
  import "./chunk-NUN6OGOV.js";
359
360
  import "./chunk-D72URWJE.js";
@@ -370,6 +371,7 @@ import {
370
371
  resolvePaths
371
372
  } from "./chunk-CDZZ2DZO.js";
372
373
  import {
374
+ MAX_NEXT_STEPS,
373
375
  array,
374
376
  boolean,
375
377
  defineSteps,
@@ -10408,6 +10410,11 @@ var theAccounts = /* @__PURE__ */ __name(async (store, env, options, warn) => {
10408
10410
  throw noStoredAccount(value);
10409
10411
  return keys;
10410
10412
  }, "theAccounts");
10413
+ var namedAccounts = /* @__PURE__ */ __name(async (store, env, options, warn) => {
10414
+ if (sourceOf(options, warn) === void 0)
10415
+ throw await unnamed(store);
10416
+ return theAccounts(store, env, options, warn);
10417
+ }, "namedAccounts");
10411
10418
  var accountName = /* @__PURE__ */ __name(({ provider, account: account2 }) => `${provider}:${account2}`, "accountName");
10412
10419
  var WRITE_HELP = "the account it acts as: provider:account, such as telegram:1 or email:personal";
10413
10420
  var writeOptions = /* @__PURE__ */ __name((command, help = WRITE_HELP) => command.option("--account <account>", help), "writeOptions");
@@ -18400,11 +18407,11 @@ var syncRound = /* @__PURE__ */ __name(async (source, store, { account: account2
18400
18407
  if (labelsOf.size && !snapshot) {
18401
18408
  const known2 = (await store.mail.mailboxes(accountId)).filter(({ kind }) => kind === "label");
18402
18409
  const seen = [...labelsOf.values()].flatMap(({ labels }) => labels ?? []);
18403
- const scanned = new Map([
18410
+ const scanned2 = new Map([
18404
18411
  ...known2.map(({ name }) => [name, label(name)]),
18405
18412
  ...seen.map((name) => [name, label(name)])
18406
18413
  ]);
18407
- await store.mail.setMailboxes(accountId, [...scanned.values()], new Map([...labelsOf].map(([id, { labels }]) => [id, (labels ?? []).map((name) => label(name).externalId)])), startedAt);
18414
+ await store.mail.setMailboxes(accountId, [...scanned2.values()], new Map([...labelsOf].map(([id, { labels }]) => [id, (labels ?? []).map((name) => label(name).externalId)])), startedAt);
18408
18415
  }
18409
18416
  const attachments = [];
18410
18417
  let saved = 0;
@@ -22696,7 +22703,11 @@ var EXAMPLES = {
22696
22703
  "relationships list": ['memo relationships list about:"person:3"', "memo relationships list confirmed:false"],
22697
22704
  "relationships remove": ["memo relationships remove 4"],
22698
22705
  "relationships confirm": ["memo relationships confirm 4"],
22699
- "relationships scan": ["memo relationships scan --source email:me@example.com --limit 10"],
22706
+ "relationships scan": [
22707
+ "memo relationships scan HRB --source all",
22708
+ "memo relationships scan HRB --source telegram:1,email:personal --yes",
22709
+ "memo relationships scan --source email:me@example.com"
22710
+ ],
22700
22711
  "reminders add": [
22701
22712
  "memo reminders add 7 --at-time 2026-10-20T09:00:00+02:00 --timezone Europe/Madrid --account telegram:1"
22702
22713
  ],
@@ -23943,6 +23954,77 @@ var syncHint = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => {
23943
23954
  return sync.command ?? `${sync.line} (${sync.why})`;
23944
23955
  }, "syncHint");
23945
23956
 
23957
+ // dist/knowledge/relationships-scan.js
23958
+ var DAY5 = 864e5;
23959
+ var SCAN_STEP = {
23960
+ id: "relationships.scan",
23961
+ kind: "command",
23962
+ command: "relationships scan",
23963
+ args: [
23964
+ { name: "project", required: true },
23965
+ { name: "source", required: true }
23966
+ ],
23967
+ why: "{count} confirmed chats: a scan lists the chats and people that look like the project's; --yes proposes them"
23968
+ };
23969
+ var confirmedChats = /* @__PURE__ */ __name(async (store, ref) => (await store.knowledge.relations(null, ref)).filter((one2) => one2.confirmed && one2.kind === "member-of" && one2.to === ref && one2.from.startsWith("chat:")).length, "confirmedChats");
23970
+ var scanStep = /* @__PURE__ */ __name(async (store, project, source) => {
23971
+ const count2 = await confirmedChats(store, project.ref);
23972
+ return count2 >= 2 ? [] : [stepOf(SCAN_STEP, { args: { project: project.key, source }, values: { count: count2 } })];
23973
+ }, "scanStep");
23974
+ var projectsOf = /* @__PURE__ */ __name(async (store, reference3) => {
23975
+ if (reference3 === void 0)
23976
+ return [null];
23977
+ if (reference3 === "all")
23978
+ return (await store.knowledge.projects()).map((one2) => one2.ref);
23979
+ return [(await projectOf(store, reference3)).ref];
23980
+ }, "projectsOf");
23981
+ var scanned = /* @__PURE__ */ __name(async (store, scans, written2) => {
23982
+ const label = await labelsFor(store, scans.flatMap((scan2) => [scan2.project, ...scan2.proposals.flatMap((one2) => [one2.from, one2.to])]));
23983
+ return {
23984
+ written: written2,
23985
+ scans: scans.map((scan2) => ({
23986
+ project: scan2.project,
23987
+ title: label(scan2.project),
23988
+ proposals: scan2.proposals.map((one2) => ({
23989
+ id: one2.id,
23990
+ state: one2.state,
23991
+ from: one2.from,
23992
+ to: one2.to,
23993
+ kind: one2.kind,
23994
+ title: `${label(one2.from) ?? one2.from} \u2192 ${label(one2.to) ?? one2.to}`,
23995
+ score: one2.score,
23996
+ ...one2.purpose ? { purpose: one2.purpose } : {},
23997
+ signals: one2.signals,
23998
+ evidence: one2.evidence
23999
+ })),
24000
+ skipped: scan2.skipped
24001
+ }))
24002
+ };
24003
+ }, "scanned");
24004
+ var scanText = /* @__PURE__ */ __name(({ written: written2, scans }) => [
24005
+ written2 ? "Proposed for your review (memo review):" : "Nothing written; --yes proposes these for your review:",
24006
+ ...scans.flatMap(({ project, title, proposals, skipped }) => [
24007
+ `${title ?? project ?? "people by shared mail domain"}: ${proposals.length} to propose; skipped ${skipped.confirmed} linked, ${skipped.rejected} rejected, ${skipped.belowThreshold} weak, ${skipped.overLimit} over the limit`,
24008
+ ...proposals.map((one2) => ` ${one2.score.toFixed(2)} ${one2.title}${one2.id === null ? "" : ` ${one2.id}`} ${one2.state}`)
24009
+ ])
24010
+ ].join("\n"), "scanText");
24011
+ var relationshipsScanCommand = /* @__PURE__ */ __name((relations, print, env, warn) => annotate(relations.command("scan"), { effects: LOCAL_WRITE }).description("chats, mail threads and people that look like a project's, scored from the store: its name and aliases in titles and messages, its confirmed members' chats and threads. With no project, people who share a company mail domain. Lists them and writes nothing; --yes writes them as proposals by memo-scan for you to decide in memo review. Never confirms, and never proposes again what you rejected").summary("propose chats and people for a project; nothing is written without --yes").argument("[project]", "a project's id, key, exact name or alias, or all; left out, people by mail domain").option("--source <accounts>", `where to look, or all: ${ACCOUNTS_HELP}`).option("--since-time <time>", "how far back messages count: days (90d, at most 730d) or a date", "90d").option("--limit <n>", "new proposals per project at most, up to 50", positive, 20).option("--yes", "write the proposals; without it nothing is written").option("--json", "print JSON; --json=id,title keeps only those fields").action(async (project, options) => {
24012
+ if (options.limit > 50)
24013
+ throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
24014
+ const window = projectWindowOf(options.sinceTime);
24015
+ const since = new Date("days" in window ? Date.now() - window.days * DAY5 : window.after).toISOString();
24016
+ const written2 = options.yes === true;
24017
+ const { body, text: text3 } = await withStore(env, async (store) => {
24018
+ const sources = await namedAccounts(store, env, options, warn);
24019
+ const scans = [];
24020
+ for (const one2 of await projectsOf(store, project))
24021
+ scans.push(await scanProjectLinks(store, { project: one2, sources, since, write: written2, limit: options.limit }));
24022
+ const answer = await scanned(store, scans, written2);
24023
+ return { body: itemAnswer(answer, { meta: { accounts: sources.map(accountName) } }), text: scanText(answer) };
24024
+ });
24025
+ print(options.json, body, text3);
24026
+ }), "relationshipsScanCommand");
24027
+
23946
24028
  // dist/knowledge/project-gather-command.js
23947
24029
  var cliOnly = /* @__PURE__ */ __name((option) => annotateOption(option, { mcp: false }), "cliOnly");
23948
24030
  var projectGatherCommand = /* @__PURE__ */ __name((projects, print, env, warn) => (
@@ -23950,33 +24032,42 @@ var projectGatherCommand = /* @__PURE__ */ __name((projects, print, env, warn) =
23950
24032
  annotate(projects.command("evidence"), { effects: FETCH, partial: true }).description("cited references about a project in stored messages, mail, meeting transcripts and imported notes folders. The project's name, its key, each of its aliases and each --alias, each --context-query and each --contact name is its own search: every word of it must appear in one text, in any order, as whole words; their hits are joined. Every message of a chat confirmed as the project's (memo relationships add chat:<provider>/<account>/<chat> project:<id>) is read too, when --source holds its account, and so is everything a confirmed person member of the project wrote (as --contact person:<id>, without aliases). New mail and documents are indexed for search first, unless --no-catch-up. Reads what the store holds; with --sync-first it first syncs the linked chats the store lacks for the window by running their messenger CLI (tg, max, wa) with the profile signed in to each chat's account, or the one --sync-profile names when several are; proposes and confirms nothing. A partial answer exits 0 with meta.complete false").summary("find what the store holds about a project: names, words, people, linked chats").argument("<project>", "an existing project's id, key, exact name or alias, or a new project's name").requiredOption("--source <accounts>", `where to look, or all: ${ACCOUNTS_HELP}`).option("--alias <name>", "another name of the project, searched on its own; repeat for more", collect, []).option("--context-query <words>", "more words that all appear in one text; repeat for another search", collect, []).option("--contact <person>", "a name to search, or person:<id> to read what that person's stored identities wrote and search the aliases you gave them; what only names them or comes from them is context, not the project", collect, []).option("--since-time <time>", "how far back: days (90d, at most 730d) or a start date (2026-09-01)", "60d").option("--before-time <time>", "fixed exclusive end: ISO 8601 timestamp with UTC offset; days back count from it").option("--limit <n>", "new references at most, up to 500", positive, 100).option("--max-pages <pages>", "store pages read at most this run, up to 512", positive).option("--cursor <cursor>", "continue a stopped search from its checkpoint, with the same options").option("--before-n <n>", "messages before each message hit, shown as its context, at most 5", whole, 2).option("--after-n <n>", "messages after each message hit, shown as its context, at most 5", whole, 2).option("--no-catch-up", "read the search index as it is, without indexing new mail and documents first").addOption(cliOnly(new Option("--sync-first", "first sync the linked chats the store does not hold back to --since-time, through their messenger CLI; off by default"))).addOption(cliOnly(new Option("--sync-time <duration>", "time for all of --sync-first's syncs together").default("3m"))).addOption(cliOnly(new Option("--sync-profile <tool=profile>", "the messenger profile to sync as when several are signed in to a chat's account, such as max=default; repeat for another tool. It must be signed in to that account").argParser(syncProfileOf))).option("--purpose <purpose>", "the linked chats' purposes to read, comma-separated: work, sales, support, other, or all; default work", purposeList).option("--include-proposed", "also read chats and members proposed for the project, after the confirmed ones").option("--json", "print JSON; --json=id,title keeps only those fields").action(async (project, options) => {
23951
24033
  const maxFetchMs = parseDuration(options.syncTime, "--sync-time");
23952
24034
  const chosen = options.syncProfile ?? {};
23953
- const found = await withStore(env, async (store) => gatherStoredProject(store, {
23954
- project,
23955
- sources: await contextSourcesOf(store, env, options.source),
23956
- ...projectWindowOf(options.sinceTime),
23957
- ...options.beforeTime === void 0 ? {} : { asOf: projectCutoffTime(options.beforeTime) },
23958
- limit: options.limit,
23959
- catchUp: options.catchUp,
23960
- beforeN: options.beforeN,
23961
- afterN: options.afterN,
23962
- ...options.alias ? { aliases: options.alias } : {},
23963
- ...options.contextQuery ? { keywords: options.contextQuery } : {},
23964
- ...options.contact ? { people: options.contact } : {},
23965
- ...options.maxPages === void 0 ? {} : { maxReads: options.maxPages },
23966
- ...options.cursor === void 0 ? {} : { checkpoint: options.cursor },
23967
- ...options.purpose ? { purposes: options.purpose } : {},
23968
- ...options.includeProposed ? { includeProposed: true } : {},
23969
- ...options.syncFirst ? { fetcher: messengerFetcher({ env, note: warn, chosen }), maxFetchMs } : {}
23970
- }));
24035
+ const { found, scan: scan2 } = await withStore(env, async (store) => {
24036
+ const found2 = await gatherStoredProject(store, {
24037
+ project,
24038
+ sources: await contextSourcesOf(store, env, options.source),
24039
+ ...projectWindowOf(options.sinceTime),
24040
+ ...options.beforeTime === void 0 ? {} : { asOf: projectCutoffTime(options.beforeTime) },
24041
+ limit: options.limit,
24042
+ catchUp: options.catchUp,
24043
+ beforeN: options.beforeN,
24044
+ afterN: options.afterN,
24045
+ ...options.alias ? { aliases: options.alias } : {},
24046
+ ...options.contextQuery ? { keywords: options.contextQuery } : {},
24047
+ ...options.contact ? { people: options.contact } : {},
24048
+ ...options.maxPages === void 0 ? {} : { maxReads: options.maxPages },
24049
+ ...options.cursor === void 0 ? {} : { checkpoint: options.cursor },
24050
+ ...options.purpose ? { purposes: options.purpose } : {},
24051
+ ...options.includeProposed ? { includeProposed: true } : {},
24052
+ ...options.syncFirst ? { fetcher: messengerFetcher({ env, note: warn, chosen }), maxFetchMs } : {}
24053
+ });
24054
+ const known = await projectOf(store, project).catch((error) => {
24055
+ if (error instanceof CliError && error.code === "not_found")
24056
+ return void 0;
24057
+ throw error;
24058
+ });
24059
+ return { found: found2, scan: known ? await scanStep(store, known, options.source) : [] };
24060
+ });
23971
24061
  const since = new Date(found.window.after).toISOString().slice(0, 10);
23972
24062
  const syncs = found.linkedChats.map((one2) => one2.completeness === null || one2.completeness.state === "complete" ? null : chatSync(one2, since, env, chosen));
23973
24063
  const parts = projectAnswerParts(options.sinceTime, found);
23974
24064
  const blocked = [...new Set(syncs.flatMap((one2) => one2 && one2.command === null ? [one2.why] : []))];
23975
24065
  const missing = [...parts.missing ?? [], ...blocked.map((why) => ({ field: "sync_command", why }))];
24066
+ const next = [...parts.next ?? [], ...scan2].slice(0, MAX_NEXT_STEPS);
23976
24067
  print(options.json, itemAnswer({
23977
24068
  ...found,
23978
24069
  linkedChats: found.linkedChats.map((one2, i) => ({ ...one2, syncCommand: syncs[i]?.command ?? null }))
23979
- }, { ...parts, ...missing.length ? { missing } : {} }), projectEvidenceText(found, {
24070
+ }, { ...parts, ...missing.length ? { missing } : {}, ...next.length ? { next } : {} }), projectEvidenceText(found, {
23980
24071
  sync: /* @__PURE__ */ __name((chat, at) => syncHint(chat, at, env, chosen), "sync"),
23981
24072
  showDocument: "memo notes show"
23982
24073
  }));
@@ -24263,7 +24354,6 @@ var pendingLink = /* @__PURE__ */ __name(async (store, id) => {
24263
24354
  var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
24264
24355
  const { run, print } = answers(program, streams, env);
24265
24356
  const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
24266
- const execute = /* @__PURE__ */ __name((options, work) => run(options.json, async (store) => work(store, await theAccount(store, env, options, warn))), "execute");
24267
24357
  const act = /* @__PURE__ */ __name((options, work) => run(options.json, async (store) => work(store, await writeAccount(store, env, options, warn))), "act");
24268
24358
  const owned = /* @__PURE__ */ __name((options, work) => run(options.json, async (store) => itemAnswer(await work(store))), "owned");
24269
24359
  const ownedList = /* @__PURE__ */ __name((command, options, work) => run(options.json, async (store) => wholeList(command, await work(store))), "ownedList");
@@ -24306,8 +24396,11 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
24306
24396
  return ownedList("projects list", options, (store) => store.knowledge.projects(query));
24307
24397
  });
24308
24398
  annotate(projects.command("context"), { effects: LOCAL_READ }).description("one project by its id, project:<id>, key, exact name or alias: its key documents first, then its relationships, notes, tags, pending findings and open tasks. Review proposals together; nothing is confirmed").summary("one project: key documents, pending findings and open tasks; start work here").argument("<project>", "its id, project:<id>, key, exact name or alias").option("--json", "print JSON; --json=id,title keeps only those fields").action(async (reference3, options) => {
24309
- const context = await withStore(env, (store) => projectContext(store, env, reference3));
24310
- print(options.json, itemAnswer(context), projectContextText(context));
24399
+ const { context, next } = await withStore(env, async (store) => {
24400
+ const context2 = await projectContext(store, env, reference3);
24401
+ return { context: context2, next: await scanStep(store, context2.project, "all") };
24402
+ });
24403
+ print(options.json, itemAnswer(context, next.length ? { next } : {}), projectContextText(context));
24311
24404
  });
24312
24405
  projectGatherCommand(projects, print, env, warn);
24313
24406
  projectStatusCommand(projects, print, env);
@@ -24384,53 +24477,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
24384
24477
  return (await store.knowledge.relations(null, suggestion.subject)).find((one2) => one2.id === id);
24385
24478
  });
24386
24479
  });
24387
- readScope(annotate(relations.command("scan"), { effects: LOCAL_READ }).description("suggest relationships between email contacts of one domain; you confirm each")).option("--limit <n>", "most suggestions, at most 100", positive, 20).action((options) => execute(options, async (store, key) => {
24388
- if (key.provider !== "email" || options.limit > 100)
24389
- throw new CliError("validation_error", "suggestions require an email account and limit 1\u2013100");
24390
- const contacts = await store.people.contacts(key, { order: "name", limit: 500, offset: 0 });
24391
- const domains = /* @__PURE__ */ new Map();
24392
- const free = /* @__PURE__ */ new Set([
24393
- "gmail.com",
24394
- "outlook.com",
24395
- "hotmail.com",
24396
- "yahoo.com",
24397
- "icloud.com",
24398
- "proton.me",
24399
- "protonmail.com"
24400
- ]);
24401
- for (const contact of contacts.items) {
24402
- const domain = contact.id.split("@")[1]?.toLowerCase();
24403
- if (!domain || free.has(domain))
24404
- continue;
24405
- const person = await store.people.personOf({ provider: key.provider, id: contact.id });
24406
- if (person)
24407
- domains.set(domain, [.../* @__PURE__ */ new Set([...domains.get(domain) ?? [], person.uid])]);
24408
- }
24409
- const suggestions = [];
24410
- for (const [domain, people] of domains)
24411
- for (let left = 0; left < people.length; left++)
24412
- for (let right = left + 1; right < people.length; right++) {
24413
- if (suggestions.length >= options.limit)
24414
- return listAnswer("relationships scan", { items: suggestions, limit: options.limit, has_more: true });
24415
- suggestions.push(
24416
- // An unconfirmed suggestion only the owner decides, as before scan writes rule proposals (D7).
24417
- await store.knowledge.relate(key, {
24418
- by: "owner",
24419
- from: `person:${people[left]}`,
24420
- to: `person:${people[right]}`,
24421
- kind: "related-to",
24422
- confirmed: false,
24423
- evidence: `Shared email domain ${domain}; this does not prove organization membership`,
24424
- provenance: "rule:email-domain-v1;confidence:weak"
24425
- })
24426
- );
24427
- }
24428
- return listAnswer("relationships scan", {
24429
- items: suggestions,
24430
- limit: options.limit,
24431
- has_more: contacts.hasMore
24432
- });
24433
- }));
24480
+ relationshipsScanCommand(relations, print, env, warn);
24434
24481
  const reminders = program.command("reminders").description("durable local reminders; poll hands one out and ack confirms it was shown");
24435
24482
  writeScope(annotate(reminders.command("add"), { effects: LOCAL_WRITE }).description("add a reminder for an open task").argument("<task>", "the task's id")).requiredOption("--at-time <time>", "when to remind: an ISO 8601 time with its UTC offset").option("--timezone <zone>", "IANA timezone; the computer's when not given").action((task, options) => act(options, async (store, key) => {
24436
24483
  if (await store.tasks.get(task) === void 0 && await store.tasks.projectTask(task))
@@ -25361,7 +25408,7 @@ var mailSetupCommand = /* @__PURE__ */ __name((mail, streams, env) => {
25361
25408
  effects: LOCAL_WRITE,
25362
25409
  examples: ["memo mail add work you@example.test --kind imap"]
25363
25410
  })).description("add an explicit account after matching its Himalaya email").argument("[account]", "one Himalaya account name; omission lists choices and changes nothing").argument("[address]", "must match the email configured for this Himalaya account").option("--kind <kind>", "gmail or imap", oneOf(["gmail", "imap"]), "gmail").option("--folder <folder>", "mail folder to import; repeat for several", collect).option("--json", "print the added account as JSON").action(async (account2, address, given) => {
25364
- const { addMailAccount } = await import("./setup-FGSVWQ32.js");
25411
+ const { addMailAccount } = await import("./setup-X6OJ3K4F.js");
25365
25412
  print(given.json, itemAnswer(await addMailAccount(env, {
25366
25413
  ...account2 ? { name: account2 } : {},
25367
25414
  ...address ? { address } : {},
@@ -25374,7 +25421,7 @@ var mailSetupCommand = /* @__PURE__ */ __name((mail, streams, env) => {
25374
25421
  const saved = accounts.find((one2) => one2.name === account2);
25375
25422
  if (!saved)
25376
25423
  throw new CliError("validation_error", `name one Memo account explicitly; choices: ${accounts.map((one2) => one2.name).join(", ") || "none"}`);
25377
- const { checkMailAccount } = await import("./setup-FGSVWQ32.js");
25424
+ const { checkMailAccount } = await import("./setup-X6OJ3K4F.js");
25378
25425
  print(given.json, itemAnswer(await checkMailAccount(env, { name: saved.name, address: saved.address })));
25379
25426
  });
25380
25427
  }, "mailSetupCommand");
@@ -25513,10 +25560,10 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
25513
25560
  }).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) => {
25514
25561
  if (!options.http && (options.port !== void 0 || options.publicUrl !== void 0))
25515
25562
  throw new CliError("validation_error", "--port and --public-url require --http");
25516
- const { createMemoServer } = await import("./server-BMQBWBBN.js");
25563
+ const { createMemoServer } = await import("./server-VO5SXU5A.js");
25517
25564
  const build = /* @__PURE__ */ __name(() => createMemoServer(env, createProgram2, options.permission), "build");
25518
25565
  if (options.http) {
25519
- const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-A4HPKQK5.js");
25566
+ const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-PNC3TI7O.js");
25520
25567
  const publicUrl = publicUrlOf(options.publicUrl, {
25521
25568
  missing: "--http",
25522
25569
  reaches: "the browser apps reach memo",
@@ -25568,7 +25615,7 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
25568
25615
  });
25569
25616
  });
25570
25617
  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() {
25571
- const { revokeAll } = await import("./mcp-A4HPKQK5.js");
25618
+ const { revokeAll } = await import("./mcp-PNC3TI7O.js");
25572
25619
  revokeAll(httpTokenFile(env));
25573
25620
  out.print(this.opts().json, itemAnswer({ revoked: true }));
25574
25621
  });
@@ -26906,7 +26953,7 @@ var withImportLock = /* @__PURE__ */ __name(async (env, work) => {
26906
26953
  }, "withImportLock");
26907
26954
 
26908
26955
  // dist/run/import.js
26909
- var DAY5 = 864e5;
26956
+ var DAY6 = 864e5;
26910
26957
  var MAIL_WINDOW_DAYS = 30;
26911
26958
  var LARGE_IMPORT_HELP = "Large first import: mail is read at about 10 emails (~1 MB) a second, and Gmail caps IMAP downloads (2,500 MB a day for Workspace, https://knowledge.workspace.google.com/admin/gmail/gmail-bandwidth-limits; the consumer limit is not published), so a mailbox of many GB takes days: raise --limit gradually and let each run continue where the last stopped.\n\nResuming: a run lists only the mail no earlier run finished, so a large mailbox is not listed again each time. A whole listing, which marks deleted mail and refreshes labels and read state, runs at least once a day, after any change to the rules, and with --rescan.\n\nRules: an email a skip rule (`mail <profile> rules`) matches is never read or stored, and is counted as skipped; mail stored before the rule stays.\n\nAn mbox account (a Google Takeout file, mode mbox) syncs only when named with --source: each run reads the whole file, its mail is old so it needs a --since-time far back, and a large --limit. It only adds mail; nothing missing from the file is marked deleted.";
26912
26959
  var issuesOf = /* @__PURE__ */ __name((failed) => failed.flatMap(({ code, source }) => errorCodes.includes(code) ? [{ code, source }] : []), "issuesOf");
@@ -26985,7 +27032,7 @@ ${LARGE_IMPORT_HELP}`).action(async (options, command) => {
26985
27032
  return;
26986
27033
  }
26987
27034
  const window = dateWindow({ sinceTime: options.sinceTime });
26988
- const since = new Date(window.since ?? Date.now() - MAIL_WINDOW_DAYS * DAY5);
27035
+ const since = new Date(window.since ?? Date.now() - MAIL_WINDOW_DAYS * DAY6);
26989
27036
  const wanted3 = synced.has("mail") ? mailAccounts(config.mail?.accounts ?? [], named5).filter((account2) => account2.mode !== "mbox" || named5 !== void 0) : [];
26990
27037
  const accounts = wanted3.filter((account2) => account2.import !== false);
26991
27038
  const handed = wanted3.filter((account2) => account2.import === false);
@@ -3,15 +3,15 @@ const require = __bundleRequire(import.meta.url);
3
3
  import {
4
4
  createBotServer,
5
5
  serveBotOverStdio
6
- } from "./chunk-JXH22ZGA.js";
6
+ } from "./chunk-3B645KUY.js";
7
7
  import "./chunk-ZD3STMY7.js";
8
- import "./chunk-INURBEAO.js";
8
+ import "./chunk-KXERKAID.js";
9
9
  import "./chunk-RG6ITTLQ.js";
10
10
  import "./chunk-CCOYC6HL.js";
11
11
  import "./chunk-MM5NVP7F.js";
12
12
  import "./chunk-3X4JM3ZR.js";
13
13
  import "./chunk-H3ZN4YLB.js";
14
- import "./chunk-J55Z6EJ3.js";
14
+ import "./chunk-ZKWE5MCA.js";
15
15
  import "./chunk-SXGAIQ5X.js";
16
16
  import "./chunk-VQM3H422.js";
17
17
  import "./chunk-RC7TIYUZ.js";
@@ -6,9 +6,9 @@ import {
6
6
  envelope,
7
7
  serveOverHttpUntilStopped,
8
8
  serveOverStdio
9
- } from "./chunk-NOG5O2NS.js";
10
- import "./chunk-INURBEAO.js";
11
- import "./chunk-TMNHNZVA.js";
9
+ } from "./chunk-SO2YVKBK.js";
10
+ import "./chunk-KXERKAID.js";
11
+ import "./chunk-HXRIV2TV.js";
12
12
  import "./chunk-XA6YO24S.js";
13
13
  import "./chunk-RG6ITTLQ.js";
14
14
  import "./chunk-OJRLTJRS.js";
@@ -17,8 +17,8 @@ import "./chunk-CCOYC6HL.js";
17
17
  import "./chunk-MM5NVP7F.js";
18
18
  import "./chunk-3X4JM3ZR.js";
19
19
  import "./chunk-H3ZN4YLB.js";
20
- import "./chunk-PO5C7VNC.js";
21
- import "./chunk-J55Z6EJ3.js";
20
+ import "./chunk-UG2V7BQY.js";
21
+ import "./chunk-ZKWE5MCA.js";
22
22
  import "./chunk-SXGAIQ5X.js";
23
23
  import "./chunk-WEOFWTWZ.js";
24
24
  import "./chunk-VQM3H422.js";