@wirecat/cli-core 0.397.0 → 0.398.0

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 (47) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +12 -9
  3. package/dist/cli/bot/admins.js +2 -2
  4. package/dist/cli/bot/command.js +2 -2
  5. package/dist/cli/bot/setup.js +3 -3
  6. package/dist/cli/commands-command.js +1 -1
  7. package/dist/cli/config-command.js +1 -1
  8. package/dist/cli/guide.js +0 -1
  9. package/dist/cli/help/command-help.d.ts +9 -2
  10. package/dist/cli/help/command-help.js +22 -4
  11. package/dist/cli/help/first-screen.js +3 -3
  12. package/dist/cli/messenger/account-command.js +2 -1
  13. package/dist/cli/messenger/archive-commands.js +2 -2
  14. package/dist/cli/messenger/backfill-command.js +3 -3
  15. package/dist/cli/messenger/catch-up-answers.d.ts +2 -0
  16. package/dist/cli/messenger/catch-up-answers.js +5 -1
  17. package/dist/cli/messenger/chats-command.js +2 -1
  18. package/dist/cli/messenger/complete-command.js +5 -1
  19. package/dist/cli/messenger/contacts-command.js +2 -1
  20. package/dist/cli/messenger/context.d.ts +5 -0
  21. package/dist/cli/messenger/doctor-command.js +2 -2
  22. package/dist/cli/messenger/flood-command.js +1 -1
  23. package/dist/cli/messenger/inbox.js +1 -0
  24. package/dist/cli/messenger/lacks.d.ts +7 -0
  25. package/dist/cli/messenger/lacks.js +18 -1
  26. package/dist/cli/messenger/media-archive-move-command.js +0 -1
  27. package/dist/cli/messenger/media-archive-timer-command.js +2 -2
  28. package/dist/cli/messenger/messages-command.js +2 -1
  29. package/dist/cli/messenger/models-command.js +5 -2
  30. package/dist/cli/messenger/replies-command.js +1 -1
  31. package/dist/cli/messenger/review.js +7 -2
  32. package/dist/cli/messenger/schedule-command.js +3 -3
  33. package/dist/cli/messenger/search-command.js +2 -2
  34. package/dist/cli/messenger/serve-command.js +5 -1
  35. package/dist/cli/messenger/serve-relay.d.ts +1 -0
  36. package/dist/cli/messenger/server-command.js +12 -3
  37. package/dist/cli/messenger/store-maintenance-command.js +3 -3
  38. package/dist/cli/messenger/watch-command.js +5 -1
  39. package/dist/cli/runs/command.js +2 -3
  40. package/dist/cli/skill-command.js +1 -1
  41. package/dist/domain/models.d.ts +2 -0
  42. package/dist/services/deps.d.ts +1 -1
  43. package/dist/services/deps.js +1 -1
  44. package/dist/services/inbox.js +5 -5
  45. package/dist/services/search-kind.js +1 -1
  46. package/package.json +2 -2
  47. package/parity.json +66 -192
@@ -58,7 +58,7 @@ const modelLine = (item, width) => `${item.default ? "*" : " "} ${item.id.padEnd
58
58
  (item.downloaded ? "downloaded" : "—".padEnd(10));
59
59
  export const modelsCommand = (messenger) => {
60
60
  const tool = `${messenger.app.command} personal`;
61
- const models = annotate(new Command("models"), { mcp: false }).description("models that run on this machine");
61
+ const models = new Command("models").description("models that run on this machine");
62
62
  const audio = models.command("audio").description("speech models for transcribing voice messages");
63
63
  withQuery(annotate(audio.command("list"), { effects: LOCAL_READ, examples: [`${tool} models audio list`] }), MODELS_QUERY)
64
64
  .summary("speech models and their download status")
@@ -76,6 +76,7 @@ export const modelsCommand = (messenger) => {
76
76
  });
77
77
  });
78
78
  reachesOtherService(annotate(audio.command("download"), {
79
+ mcp: false,
79
80
  effects: FETCH,
80
81
  output: { entity: "model" },
81
82
  examples: [`${tool} models audio download parakeet-v3`],
@@ -123,6 +124,7 @@ export const modelsCommand = (messenger) => {
123
124
  });
124
125
  });
125
126
  reachesOtherService(annotate(text.command("download"), {
127
+ mcp: false,
126
128
  effects: FETCH,
127
129
  output: { entity: "model" },
128
130
  examples: [`${tool} models text download ${DEFAULT_TEXT_MODEL}`],
@@ -171,7 +173,7 @@ export const modelsCommand = (messenger) => {
171
173
  /** `images models`: registered with picture search, the only thing these models serve. */
172
174
  export const imageModelsCommand = (messenger) => {
173
175
  const tool = messenger.app.command;
174
- const image = annotate(new Command("models"), { mcp: false }).description("models that read pictures, for `images embed` and picture search");
176
+ const image = new Command("models").description("models that read pictures, for `images embed` and picture search");
175
177
  withQuery(annotate(image.command("list"), { effects: LOCAL_READ, examples: [`${tool} images models list`] }), MODELS_QUERY)
176
178
  .description("the picture models, which are downloaded, and which one is the default")
177
179
  .action(async function (words) {
@@ -187,6 +189,7 @@ export const imageModelsCommand = (messenger) => {
187
189
  });
188
190
  });
189
191
  reachesOtherService(annotate(image.command("download"), {
192
+ mcp: false,
190
193
  effects: FETCH,
191
194
  output: { entity: "model" },
192
195
  examples: [`${tool} images models download ${DEFAULT_IMAGE_MODEL}`],
@@ -14,7 +14,7 @@ import { replyConsentsCommand } from "./replies-consents-command.js";
14
14
  import { addReplyEditors } from "./replies-edit-command.js";
15
15
  /** `replies`: rules that answer messages for the owner, from `serve`, and only to the people and chats the audience allows. */
16
16
  export const repliesCommand = (messenger) => {
17
- const replies = annotate(new Command("replies"), { mcp: false }).description("rules that answer messages for you, kept in a file of this profile");
17
+ const replies = new Command("replies").description("rules that answer messages for you, kept in a file of this profile");
18
18
  if (messenger.autoReplies === false)
19
19
  replies.hook("preAction", () => {
20
20
  throw new CliError("validation_error", `${messenger.name ?? messenger.app.command} cannot send automatic replies`);
@@ -10,7 +10,7 @@ import { REMOTE_READ } from "../effects.js";
10
10
  import { renderAnswer } from "../envelope.js";
11
11
  import { queryHelp } from "../list-query.js";
12
12
  import { pointsOf } from "./catch-up.js";
13
- import { catchUpQuery, REVIEW_QUERY, reviewAnswer } from "./catch-up-answers.js";
13
+ import { catchUpQuery, OFFLINE_REVIEW, REVIEW_QUERY, reviewAnswer } from "./catch-up-answers.js";
14
14
  import { messengerContext } from "./context.js";
15
15
  import { heardItems, hearForCommand, MODEL_OPTION, spokenItems, TRANSCRIBE_OPTION } from "./hearing-command.js";
16
16
  import { PARTIAL_NOTE } from "./inbox.js";
@@ -25,6 +25,7 @@ export const unansweredHours = (value, flag = "--unanswered") => value === true
25
25
  * tasks in the local store from what it read (`../../services/task-rules.ts`); nothing reaches the messenger.
26
26
  */
27
27
  export const reviewCommand = (messenger) => annotate(new Command("review"), {
28
+ examples: [`${messenger.app.command} personal review "date>2h"`],
28
29
  effects: REMOTE_READ,
29
30
  output: { entity: "message", view: "summary" },
30
31
  query: REVIEW_QUERY,
@@ -39,6 +40,7 @@ export const reviewCommand = (messenger) => annotate(new Command("review"), {
39
40
  .option(...TRANSCRIBE_OPTION)
40
41
  .option(...MODEL_OPTION)
41
42
  .option("--new", "what changed since the last `review --new`, a point per chat — for scheduled runs")
43
+ .addHelpText("after", "With --offline it reads the local store: only what was already synced, and --new keeps its point.")
42
44
  .addHelpText("after", "To mark a chat read, use `chats mark-read <chat>`. The other side sees it.")
43
45
  .action(async function (query) {
44
46
  const options = this.opts();
@@ -99,7 +101,8 @@ export const reviewCommand = (messenger) => annotate(new Command("review"), {
99
101
  .sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
100
102
  return read.length === 0 ? "" : renderMessages(spokenItems(read, hearing), viewOf(context, messenger));
101
103
  });
102
- saved?.save(found.checked ?? {});
104
+ if (!found.offline)
105
+ saved?.save(found.checked ?? {});
103
106
  });
104
107
  /** What the answer's steps do not say: a person's context for the review just shown. */
105
108
  const notes = (found, pretty, renderer) => {
@@ -111,6 +114,8 @@ const notes = (found, pretty, renderer) => {
111
114
  (found.tasks.review > 0 ? `, ${found.tasks.review} pair(s) to review — tasks duplicates` : ""));
112
115
  if (found.partial && pretty)
113
116
  renderer.warn(PARTIAL_NOTE);
117
+ if (found.offline && pretty)
118
+ renderer.warn(OFFLINE_REVIEW);
114
119
  if (found.unanswered)
115
120
  renderer.note(`questions from ${found.since} to ${found.until} still open after ${found.unanswered.olderThanHours} hours; ` +
116
121
  "an answer after the review's end is not seen");
@@ -61,7 +61,7 @@ const withWhen = (command) => command
61
61
  */
62
62
  export const scheduleCommand = (messenger) => {
63
63
  const { app } = messenger;
64
- const command = annotate(new Command("schedule"), { mcp: false }).description(`run a ${app.command} command or an agent later or on a timer (systemd, launchd, Task Scheduler); an agent cannot send`);
64
+ const command = new Command("schedule").description(`run a ${app.command} command or an agent later or on a timer (systemd, launchd, Task Scheduler); an agent cannot send`);
65
65
  const prepare = (self) => {
66
66
  const context = messengerContext(self, messenger);
67
67
  const system = environmentOf(self).system ?? thisMachine();
@@ -192,7 +192,7 @@ export const scheduleCommand = (messenger) => {
192
192
  .join("\n");
193
193
  });
194
194
  });
195
- annotate(command.command("run"), { effects: REMOTE_WRITE })
195
+ annotate(command.command("run"), { effects: REMOTE_WRITE, mcp: false })
196
196
  .description("run a schedule now, as its timer would, and wait for it")
197
197
  .argument("<name>")
198
198
  .action(async function (name) {
@@ -216,7 +216,7 @@ export const scheduleCommand = (messenger) => {
216
216
  rmSync(file, { force: true });
217
217
  say({ name, removed: true }, [`Removed ${name}.`]);
218
218
  });
219
- annotate(command.command("exec"), { effects: REMOTE_WRITE })
219
+ annotate(command.command("exec"), { effects: REMOTE_WRITE, mcp: false })
220
220
  .description("what a timer runs, given the schedule's file; to run one by hand, use run")
221
221
  .argument("<file>")
222
222
  .action(async function (file) {
@@ -36,8 +36,8 @@ const allCommand = (messenger) => {
36
36
  const command = annotate(new Command("all"), { effects: REMOTE_READ, partial: true })
37
37
  .summary("search stored messages, notes and selected meeting transcripts")
38
38
  .description((messenger.serverSearch
39
- ? "search messenger messages and notes in the local store, and the messenger's server for messages " +
40
- "(--backend; notes are local only)"
39
+ ? "search messenger messages and notes in the local store, and by default the messenger's server for " +
40
+ "messages too (notes are local only; --backend archive or --offline keeps it to the local store)"
41
41
  : "search messenger messages and notes in the local store") +
42
42
  ", and a meeting account's transcripts when --source names one — best match first; not mail (the separate memo CLI searches it: memo search mail), " +
43
43
  "tasks, people, memories or projects. Use it when you do not know where something was written; search messages " +
@@ -30,7 +30,11 @@ export { lockPath, readLock, servingProfiles } from "../../background/lock.js";
30
30
  * taken over. Started by a person, a service unit or `server start` — never by itself (NEED-9).
31
31
  */
32
32
  export const serveCommand = (messenger) => {
33
- const command = annotate(new Command("serve"), { effects: REMOTE_WRITE, lifetime: "persistent" }).description("keep the local store current until stopped — what a systemd or launchd unit runs");
33
+ const command = annotate(new Command("serve"), {
34
+ effects: REMOTE_WRITE,
35
+ lifetime: "persistent",
36
+ examples: [`${messenger.app.command} personal serve`],
37
+ }).description("keep the local store current until stopped — what a systemd or launchd unit runs");
34
38
  command.action(async function () {
35
39
  const relay = messenger.connection === "exclusive" && process.platform !== "win32" ? serveRelay(this, messenger) : undefined;
36
40
  const context = recordDiagnostics(messengerContext(this, relay?.messenger ?? messenger), messenger.app);
@@ -51,6 +51,7 @@ export declare const serveRelay: (command: Command, messenger: Messenger) => {
51
51
  scheduledSends?: boolean;
52
52
  autoReplies?: boolean;
53
53
  lacks?: readonly (keyof MessengerAdapter)[];
54
+ never?: readonly (keyof MessengerAdapter)[];
54
55
  deleteForMe?: boolean;
55
56
  topics?: boolean;
56
57
  topicShow?: boolean;
@@ -60,7 +60,7 @@ const lockProcess = (app, marker, serveArgv) => (context, system, logPath) => ({
60
60
  */
61
61
  export const serverCommand = (messenger, options = {}) => {
62
62
  const { app } = messenger;
63
- const command = annotate(new Command("server"), { mcp: false })
63
+ const command = new Command("server")
64
64
  .summary("manage this profile's background server")
65
65
  .description(`\`${app.command} serve\` in the background: start, stop, restart, status, logs; install adds a systemd or launchd unit`);
66
66
  const marker = (profile) => `${app.envPrefix}_SERVER=${profile}`;
@@ -183,17 +183,26 @@ export const serverCommand = (messenger, options = {}) => {
183
183
  return ["--idle", idle];
184
184
  };
185
185
  const withIdle = (sub) => options.idle ? sub.option("--idle <duration>", "stop after this long with nobody using it — 15m, 1h") : sub;
186
- withIdle(destroysNothing(annotate(command.command("start"), { effects: LOCAL_WRITE, examples: [`${app.command} personal server start`] }))
186
+ withIdle(destroysNothing(annotate(command.command("start"), {
187
+ effects: LOCAL_WRITE,
188
+ mcp: false,
189
+ examples: [`${app.command} personal server start`],
190
+ }))
187
191
  .summary("start this profile's background server")
188
192
  .description("start serve in the background — through the unit if one is installed — and answer once it connects")).action(async function () {
189
193
  await start(prepare(this), idleArgs(this));
190
194
  });
191
- destroysNothing(annotate(command.command("stop"), { effects: LOCAL_WRITE, examples: [`${app.command} personal server stop`] }))
195
+ destroysNothing(annotate(command.command("stop"), {
196
+ effects: LOCAL_WRITE,
197
+ mcp: false,
198
+ examples: [`${app.command} personal server stop`],
199
+ }))
192
200
  .description("stop this profile's serve — through the unit if it runs under one")
193
201
  .action(async function () {
194
202
  await stop(prepare(this));
195
203
  });
196
204
  withIdle(destroysNothing(annotate(command.command("restart"), {
205
+ mcp: false,
197
206
  effects: LOCAL_WRITE,
198
207
  examples: [`${app.command} personal server restart`],
199
208
  })).description("stop it and start it again")).action(async function () {
@@ -152,7 +152,7 @@ const copiesCommand = () => new Command("copies").description("the tables `store
152
152
  const deleted = await reading(path, (database) => deleteCopy(database, name));
153
153
  result(this, { path, deleted });
154
154
  }));
155
- const infoCommand = () => annotate(new Command("info"), { effects: LOCAL_READ, mcp: false })
155
+ const infoCommand = () => annotate(new Command("info"), { effects: LOCAL_READ })
156
156
  .summary("the local archive's format, size and contents")
157
157
  .description("the store file: where it is, its size, its schema and how many rows it holds; changes nothing")
158
158
  .action(async function () {
@@ -182,7 +182,7 @@ const infoCommand = () => annotate(new Command("info"), { effects: LOCAL_READ, m
182
182
  * fetched" (NEED-399 A). Times are the chat's newest message by the messenger's list against the
183
183
  * newest message held, not `sync_ranges`: those are in message ids, which a chat list does not give.
184
184
  */
185
- const checkCommand = (messenger) => annotate(new Command("check"), { effects: LOCAL_READ, mcp: false })
185
+ const checkCommand = (messenger) => annotate(new Command("check"), { effects: LOCAL_READ })
186
186
  .summary("check the local archive for problems")
187
187
  .description("whether the store is healthy — integrity, search indexes, disk, and which chats are behind")
188
188
  .action(async function () {
@@ -431,7 +431,7 @@ const buildNoteIndex = (database, note, { reset = false } = {}) => {
431
431
  note(`indexing ${pending} notes`);
432
432
  return { notesIndexed: drainNoteIndex(database, stemmerCache()) };
433
433
  };
434
- const reindexCommand = (messenger) => destroysNothing(annotate(new Command("reindex"), { effects: LOCAL_WRITE, mcp: false }))
434
+ const reindexCommand = (messenger) => destroysNothing(annotate(new Command("reindex"), { effects: LOCAL_WRITE }))
435
435
  .summary("rebuild the local archive's search indexes")
436
436
  .description("rebuild the word index, its typo vocabulary, the stems, the files' word index, the notes' indexes and who took part in what, from what is stored; loses nothing")
437
437
  .action(async function () {
@@ -11,7 +11,11 @@ import { messengerContext } from "./context.js";
11
11
  * for a minute is a complete answer. One `MessageHit` per line with `--jsonl`; `--json` is refused,
12
12
  * because a stream is not one value. Nothing is marked read.
13
13
  */
14
- export const watchCommand = (messenger) => annotate(new Command("watch"), { effects: REMOTE_READ, lifetime: "persistent" })
14
+ export const watchCommand = (messenger) => annotate(new Command("watch"), {
15
+ effects: REMOTE_READ,
16
+ lifetime: "persistent",
17
+ examples: [`${messenger.app.command} personal watch --jsonl --timeout 30s`],
18
+ })
15
19
  .summary("stream new messages until interrupted or timed out")
16
20
  .description("print new messages as they arrive, until Ctrl-C or --timeout (either ends it normally)")
17
21
  .option("--events", "also edits, deletions, reactions, poll votes and chat events; every line then names its event")
@@ -20,7 +20,6 @@ export const runsCommand = (app) => {
20
20
  };
21
21
  annotate(command.command("list"), {
22
22
  effects: LOCAL_READ,
23
- mcp: false,
24
23
  examples: [`${app.command} runs list --limit 10`],
25
24
  })
26
25
  .description("recorded runs, newest first")
@@ -36,7 +35,7 @@ export const runsCommand = (app) => {
36
35
  if (runs.length === 0)
37
36
  renderer.note("nothing recorded — a run is kept with `--record`, or when it fails");
38
37
  });
39
- annotate(command.command("show"), { effects: LOCAL_READ, mcp: false, examples: [`${app.command} runs show run-101`] })
38
+ annotate(command.command("show"), { effects: LOCAL_READ, examples: [`${app.command} runs show run-101`] })
40
39
  .argument("<run-id>", `an id from \`${app.command} runs list\``)
41
40
  .description("one run: what it was, how it ended, and every event it logged")
42
41
  .option("--problems", "only failed responses, warnings and crashes")
@@ -86,7 +85,7 @@ export const runsCommand = (app) => {
86
85
  since_time: options.sinceTime,
87
86
  }));
88
87
  });
89
- annotate(command.command("path"), { effects: NO_EFFECTS, mcp: false, examples: [`${app.command} runs path run-101`] })
88
+ annotate(command.command("path"), { effects: NO_EFFECTS, examples: [`${app.command} runs path run-101`] })
90
89
  .argument("<run-id>", `an id from \`${app.command} runs list\``)
91
90
  .description("the directory holding one run")
92
91
  .action(function (id) {
@@ -20,7 +20,7 @@ export const skillCommand = (app, skill) => {
20
20
  const show = command.commands.find((sub) => sub.name() === "show");
21
21
  if (show)
22
22
  annotate(show, { examples: [`${app.command} skill show`, `${app.command} skill show follow-ups`] });
23
- return annotate(command, { mcp: false });
23
+ return command;
24
24
  };
25
25
  /** Skills this package ships for every CLI on it, printed by `skill show <name>`: `skills/` beside `dist/` and `src/`. */
26
26
  const SHARED_SKILLS = {
@@ -506,6 +506,8 @@ export interface Review {
506
506
  closed: number;
507
507
  review: number;
508
508
  };
509
+ /** `--offline`: read from the local store, so it holds only what was already synced. */
510
+ offline?: true;
509
511
  }
510
512
  /** One change to who is in a chat, or to the chat itself, read from a service message. */
511
513
  export interface ChatEvent {
@@ -70,7 +70,7 @@ export declare const fromStore: (deps: Pick<ServiceDeps, "offline" | "reads">) =
70
70
  export declare const nothingStored: (messenger: MessengerTraits) => string;
71
71
  /** Where a store-mode messenger's history comes from, for what it cannot do. */
72
72
  export declare const PUSHED = "this messenger's history is read from the local store";
73
- export declare const OFFLINE = "--offline answers only from what is kept locally: `chats list|show`, `messages list|show|context` and `contacts list|show`";
73
+ export declare const OFFLINE = "--offline answers only from what is kept locally: `chats list|show`, `messages list|show|context`, `contacts list|show` and `review`";
74
74
  /** Over a connection that is already open — an MCP session holds one for minutes. */
75
75
  export declare const onlineDeps: (messenger: ServiceMessenger, adapter: MessengerAdapter, guard: SendGuard, where?: {
76
76
  profile?: string;
@@ -55,7 +55,7 @@ export const fromStore = (deps) => deps.offline || deps.reads === "store";
55
55
  export const nothingStored = (messenger) => `nothing stored for this chat yet — keep \`${typedCommand(messenger.app.command, "serve")}\` running`;
56
56
  /** Where a store-mode messenger's history comes from, for what it cannot do. */
57
57
  export const PUSHED = "this messenger's history is read from the local store";
58
- export const OFFLINE = "--offline answers only from what is kept locally: `chats list|show`, `messages list|show|context` and `contacts list|show`";
58
+ export const OFFLINE = "--offline answers only from what is kept locally: `chats list|show`, `messages list|show|context`, `contacts list|show` and `review`";
59
59
  /** Over a connection that is already open — an MCP session holds one for minutes. */
60
60
  export const onlineDeps = (messenger, adapter, guard, where = {}) => ({
61
61
  messenger,
@@ -234,7 +234,7 @@ export const reviewIn = async (adapter, { since, points, chat, kinds, all = fals
234
234
  };
235
235
  export const inboxService = (deps) => {
236
236
  const reader = async () => {
237
- if (deps.reads === "store")
237
+ if (deps.reads === "store" || deps.offline)
238
238
  return storeReader(deps, await deps.store(), await deps.account());
239
239
  const connection = await deps.connection();
240
240
  return {
@@ -256,9 +256,7 @@ export const inboxService = (deps) => {
256
256
  : newIn(from, { since, limit, all, ...only, ...(points === undefined ? {} : { points }) });
257
257
  },
258
258
  review: async (options) => {
259
- if (deps.offline && deps.reads !== "store") {
260
- throw new CliError("validation_error", "`review` asks the messenger what changed; with `--offline` nothing did");
261
- }
259
+ const synced = deps.offline && deps.reads !== "store";
262
260
  let tasks;
263
261
  const found = await reviewIn(await reader(), {
264
262
  ...options,
@@ -272,7 +270,9 @@ export const inboxService = (deps) => {
272
270
  });
273
271
  },
274
272
  });
275
- return tasks ? { ...found, tasks } : found;
273
+ // What was never synced may sit before `until`, so the next review must not start there.
274
+ const offline = synced ? { complete: false, offline: true } : {};
275
+ return { ...found, ...offline, ...(tasks ? { tasks } : {}) };
276
276
  },
277
277
  };
278
278
  };
@@ -50,7 +50,7 @@ export const accountsOfKind = (kind, chosen, held, explicit, command = undefined
50
50
  throw new CliError("validation_error", `search mail reads mail only — \`${command === undefined ? "" : `${command} `}search messages\` searches ${explicit}`);
51
51
  const mail = (listed ? chosen : held).filter(({ provider }) => kindOf(provider) === "mail");
52
52
  if (mail.length === 0)
53
- throw new CliError("not_found", "no mail in the store yet — `memo sync --mail --since-time <time>` imports it", {
53
+ throw new CliError("not_found", "no mail in the store yet — `memo sync --only mail --since-time <time>` imports it", {
54
54
  reason: NO_MAIL,
55
55
  });
56
56
  const address = mailAccount?.trim().toLowerCase();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.397.0",
3
+ "version": "0.398.0",
4
4
  "description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",
@@ -165,7 +165,7 @@
165
165
  "@anthropic-ai/sdk": "0.131.0",
166
166
  "@bomb.sh/tab": "0.0.22",
167
167
  "@huggingface/tokenizers": "0.2.0",
168
- "@modelcontextprotocol/server": "2.1.0",
168
+ "@modelcontextprotocol/server": "2.3.0",
169
169
  "@resvg/resvg-js": "2.6.2",
170
170
  "@valibot/to-json-schema": "1.8.0",
171
171
  "@wirecat/cli-core-onnx": "1.0.1",