@wirecat/cli-core 0.550.0 → 0.551.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.
- package/CHANGELOG.md +176 -0
- package/THIRD_PARTY_NOTICES +41 -0
- package/dist/calendar/ics.d.ts +1 -1
- package/dist/calendar/ics.js +5 -2
- package/dist/calendar/windows-zones.generated.d.ts +1 -0
- package/dist/calendar/windows-zones.generated.js +146 -0
- package/dist/cli/compact.js +2 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/meeting-findings-input.js +4 -3
- package/dist/cli/messenger/backfill-command.js +28 -1
- package/dist/cli/messenger/context.js +1 -0
- package/dist/cli/messenger/history-gaps.js +4 -4
- package/dist/cli/messenger/mcp-command.js +1 -0
- package/dist/cli/messenger/messages-delete-command.js +7 -8
- package/dist/cli/messenger/projects-command.js +47 -2
- package/dist/cli/payment-query.d.ts +8 -0
- package/dist/cli/payment-query.js +27 -0
- package/dist/cli/project-status-rows.d.ts +8 -0
- package/dist/cli/project-status-rows.js +102 -0
- package/dist/cli/project-status.d.ts +132 -0
- package/dist/cli/project-status.js +248 -0
- package/dist/cli/steps.js +4 -1
- package/dist/domain/knowledge.d.ts +1 -1
- package/dist/domain/knowledge.js +1 -1
- package/dist/domain/status-words.d.ts +3 -0
- package/dist/domain/status-words.js +44 -0
- package/dist/entities/fact.d.ts +12 -1
- package/dist/entities/fact.js +13 -0
- package/dist/entities/index.d.ts +18 -2
- package/dist/entities/meeting-findings.d.ts +1 -1
- package/dist/entities/message-transfer.d.ts +16 -0
- package/dist/entities/message-transfer.js +6 -0
- package/dist/mcp/app-server.js +1 -0
- package/dist/mcp/http/oauth.d.ts +2 -1
- package/dist/mcp/http/oauth.js +2 -2
- package/dist/mcp/http/serve.d.ts +2 -0
- package/dist/mcp/http/serve.js +2 -1
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/surface.js +1 -1
- package/dist/meetings/findings-rules.d.ts +14 -3
- package/dist/meetings/findings-rules.js +16 -2
- package/dist/meetings/index.d.ts +3 -2
- package/dist/meetings/index.js +2 -1
- package/dist/meetings/meeting-context.d.ts +2 -3
- package/dist/meetings/meeting-context.js +3 -4
- package/dist/meetings/payment.d.ts +27 -0
- package/dist/meetings/payment.js +81 -0
- package/dist/services/archive.d.ts +13 -0
- package/dist/services/archive.js +56 -5
- package/dist/services/deps.d.ts +3 -0
- package/dist/services/history-limits.d.ts +2 -0
- package/dist/services/index.d.ts +4 -1
- package/dist/services/index.js +4 -1
- package/dist/services/job-query.d.ts +5 -2
- package/dist/services/job-query.js +5 -2
- package/dist/services/link-scorers/alias-hits.d.ts +7 -0
- package/dist/services/link-scorers/alias-hits.js +54 -0
- package/dist/services/link-scorers/chat-senders.d.ts +6 -0
- package/dist/services/link-scorers/chat-senders.js +56 -0
- package/dist/services/link-scorers/chat-title.d.ts +6 -0
- package/dist/services/link-scorers/chat-title.js +44 -0
- package/dist/services/link-scorers/email-domain.d.ts +6 -0
- package/dist/services/link-scorers/email-domain.js +64 -0
- package/dist/services/link-scorers/index.d.ts +9 -0
- package/dist/services/link-scorers/index.js +8 -0
- package/dist/services/link-scorers/mail-thread.d.ts +3 -0
- package/dist/services/link-scorers/mail-thread.js +74 -0
- package/dist/services/link-scorers/member-chats.d.ts +3 -0
- package/dist/services/link-scorers/member-chats.js +40 -0
- package/dist/services/link-scorers/member-dialog.d.ts +3 -0
- package/dist/services/link-scorers/member-dialog.js +34 -0
- package/dist/services/link-scorers/scan.d.ts +41 -0
- package/dist/services/link-scorers/scan.js +244 -0
- package/dist/services/link-scorers/shared.d.ts +26 -0
- package/dist/services/link-scorers/shared.js +48 -0
- package/dist/services/link-scorers/types.d.ts +77 -0
- package/dist/services/link-scorers/types.js +1 -0
- package/dist/services/project-status/index.d.ts +71 -0
- package/dist/services/project-status/index.js +196 -0
- package/dist/services/project-status/items.d.ts +10 -0
- package/dist/services/project-status/items.js +23 -0
- package/dist/services/project-status/signals/amounts.d.ts +20 -0
- package/dist/services/project-status/signals/amounts.js +91 -0
- package/dist/services/project-status/signals/children.d.ts +13 -0
- package/dist/services/project-status/signals/children.js +28 -0
- package/dist/services/project-status/signals/coverage.d.ts +13 -0
- package/dist/services/project-status/signals/coverage.js +30 -0
- package/dist/services/project-status/signals/index.d.ts +3 -0
- package/dist/services/project-status/signals/index.js +21 -0
- package/dist/services/project-status/signals/last-message.d.ts +4 -0
- package/dist/services/project-status/signals/last-message.js +22 -0
- package/dist/services/project-status/signals/payments.d.ts +9 -0
- package/dist/services/project-status/signals/payments.js +24 -0
- package/dist/services/project-status/signals/promises.d.ts +17 -0
- package/dist/services/project-status/signals/promises.js +109 -0
- package/dist/services/project-status/signals/questions.d.ts +8 -0
- package/dist/services/project-status/signals/questions.js +38 -0
- package/dist/services/project-status/signals/reply-next.d.ts +19 -0
- package/dist/services/project-status/signals/reply-next.js +75 -0
- package/dist/services/project-status/signals/topics.d.ts +10 -0
- package/dist/services/project-status/signals/topics.js +50 -0
- package/dist/services/project-status/types.d.ts +84 -0
- package/dist/services/project-status/types.js +1 -0
- package/dist/services/proposals/index.d.ts +1 -0
- package/dist/services/proposals/index.js +1 -0
- package/dist/services/proposals/kinds/findings.d.ts +3 -0
- package/dist/services/proposals/kinds/findings.js +8 -1
- package/dist/store/decisions.d.ts +5 -1
- package/dist/store/decisions.js +5 -1
- package/dist/store/evidence-findings.js +1 -0
- package/dist/store/index.d.ts +2 -1
- package/dist/store/index.js +1 -0
- package/dist/store/project-transfer/request.d.ts +1 -1
- package/dist/store/project-transfer/schema.d.ts +2 -2
- package/dist/store/project-transfer/snapshot-model.d.ts +2 -2
- package/dist/store/sqlite/evidence-findings.js +5 -1
- package/dist/store/sqlite/facts.d.ts +13 -0
- package/dist/store/sqlite/facts.js +64 -6
- package/dist/store/sqlite/findings-core.js +14 -1
- package/dist/store/sqlite/knowledge.d.ts +16 -2
- package/dist/store/sqlite/knowledge.js +1 -0
- package/dist/store/sqlite/project-transfer/snapshot.d.ts +1 -1
- package/dist/store/sqlite/relation-proposals.d.ts +29 -2
- package/dist/store/sqlite/relation-proposals.js +75 -4
- package/dist/store/store.d.ts +1 -0
- package/package.json +3 -3
- package/parity.json +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,182 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.551.0 — 02.11.2026
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`messages sync` keeps to the history limits too**, for every messenger: it does not read a group above
|
|
15
|
+
`history_group_members_max` people and stops a chat at its window (`history_dialog_days`, `history_group_days`). The
|
|
16
|
+
answer says `limited` (`group_too_large`, `older_than_window`; `--all` counts both), the skip is recorded for
|
|
17
|
+
`store status` and the search answers' `missing.history_limits`, and `--full-history` reads past it. Live messages
|
|
18
|
+
are never dropped.
|
|
19
|
+
- **`readClientFile` (from `@wirecat/cli-core/oauth`) reads a user's own Google Desktop OAuth client file** (the
|
|
20
|
+
`{ "installed": { client_id, client_secret } }` JSON from Google's console). It refuses a file other users can read
|
|
21
|
+
(`sign-in.client-file-open`) and a file of the wrong shape (`sign-in.client-file-invalid`), and never puts the file's
|
|
22
|
+
contents in an error. gcal, drive and mail each kept a copy of this reader.
|
|
23
|
+
- **`openBrowser(url, browser?)` is exported from `@wirecat/cli-core/cli`**, so a CLI that does not start through
|
|
24
|
+
`startCli` opens the sign-in page the same way: `open`, `rundll32` or `xdg-open`, or the named browser.
|
|
25
|
+
- **iCalendar feeds as read-only calendars.** With `deps.feeds` (`icsFeeds`), `calendars add <url> [--title]` follows a
|
|
26
|
+
public holiday calendar, a sports schedule or a published `.ics` address, and `calendars remove <calendar>` stops.
|
|
27
|
+
`sync` reads each feed after the provider (`syncWithFeeds`), so its events show in `events list`,
|
|
28
|
+
`search events`, `overlapping:` and `events remind`. Repeating events are expanded here (`expandSeries`: RRULE in
|
|
29
|
+
the event's own zone, RDATE, EXDATE and overrides). The address is a secret input, kept by the CLI and never
|
|
30
|
+
printed; a fetch follows redirects only to https and stops at 10 MB and 30 s. `readIcs` takes
|
|
31
|
+
`{ overrides: true }` and returns the calendar's `name`. See `docs/dev/CALENDARS.md`, "Feeds".
|
|
32
|
+
- **History limits for pushed history, per profile.** A messenger whose history is pushed (`history: "store"`,
|
|
33
|
+
WhatsApp) saves one-to-one chats back `history_dialog_days` (1095 by default), groups of more than two people back
|
|
34
|
+
`history_group_days` (365) and nothing of a group above `history_group_members_max` people (50); at most 1095 days.
|
|
35
|
+
The chat row stays, so the chat is still listed. Live messages, `messages sync` and what the store already holds are
|
|
36
|
+
never dropped. `messages sync <chat> --full-history` fetches a chat and keeps its pushed history in full from then on
|
|
37
|
+
(`history_included` in the answer). `ChatsStore` gains `historySkips`, `historyShapes`, `recordHistorySkips` and
|
|
38
|
+
`setHistoryIncluded`; `Saving` takes `historyLimits`.
|
|
39
|
+
- **Helpers for reading money and questions in a chat, for the project status work.** `amountsOf(text)` returns
|
|
40
|
+
every amount in a text, in order (`amountOf` is its first). `MONEY_REQUEST`, `MONEY_DONE` and `PROMISE` word lists
|
|
41
|
+
(ru, en, es) with `moneyClassesOf(text)` say which a text uses. `questions(messages, { asker: "owner" })` lists the
|
|
42
|
+
owner's own questions and whether anyone but the owner answered them, by a reply or by speaking next; the default,
|
|
43
|
+
`"others"`, is what it did before. `linkedChatsOf` is exported, now with each link's `role`, and so is
|
|
44
|
+
`AGENDA_DEFAULTS`, the silence `tasks agenda` waits before it lists a chat.
|
|
45
|
+
- **A command's own history handler learns whether each batch reached the store**: `HistoryBatchHandler` takes
|
|
46
|
+
`saved`, a promise of the same `true` or `false` the messenger gets, so a link can count only what was kept.
|
|
47
|
+
- **Every messenger command that takes a chat or a message also takes the reference other WireCat CLIs print**:
|
|
48
|
+
`chat:<provider>/<account>/<chat>` wherever a chat is named (`messages list chat:max/34871122/63488582`, bot
|
|
49
|
+
commands too), and `msg:<provider>/<account>/<chat>/<message>` wherever a chat or a message is, online and offline. A person lookup takes `contact:<provider>/<id>`. A reference of another
|
|
50
|
+
account is refused, naming the account it belongs to and the profiles of this CLI the store saw on it; it never
|
|
51
|
+
switches account. One of another messenger is refused with the command that opens it (`open it with tg <profile>
|
|
52
|
+
messages list chat:telegram/…`), and another kind (`document:413` given as a chat) with what the argument takes.
|
|
53
|
+
- **`event:<id>` and `meeting:<account>/<meeting>[/<transcript>[/<cue>]]` parse with `parseReference`** and
|
|
54
|
+
`canonicalReference`, as every other kind: `event:N` was printed by the calendar and person answers and could not be
|
|
55
|
+
read back. The kinds are one table, `REF_KINDS`; `looksLikeReference(text)` tells a reference from a title such as
|
|
56
|
+
`Note: plan`. Reference errors carry a reason: `ref.malformed`, `ref.unknown-kind` (with the kind meant:
|
|
57
|
+
`"doc:413" … did you mean document:413?`), `ref.wrong-kind`, `ref.wrong-provider`, `ref.wrong-account`.
|
|
58
|
+
- **`messages list` reads a window bounded on both sides, offline too.** The query takes a start and an end,
|
|
59
|
+
`'date>=2026-10-01 date<2026-10-20'` or `'date:[2026-10-01 TO 2026-10-19]'`, and `id>` with `date<`. A start reads
|
|
60
|
+
forward, oldest first, and stops at the end; an end alone reads back from it, newest page first, as before.
|
|
61
|
+
`--offline` and a messenger whose history is read from the store (WhatsApp) now answer both ways from the store
|
|
62
|
+
instead of refusing. A forward cursor carries the end, `after:<id>~<epoch ms>`, so the next page stops at the same
|
|
63
|
+
place. `--since`, `--since-time`, `--until`, `--until-time`, `--after-time` and `--before-time` on `messages list`
|
|
64
|
+
fail with the query form to type instead. The store's `messages()` window takes `after` (a message or a moment)
|
|
65
|
+
and `until`.
|
|
66
|
+
- **`projects status <project>`: where a project stands, from the store alone, with no model call.** For each chat
|
|
67
|
+
confirmed as the project's or a child project's, in this profile's account: the last message, who replies next
|
|
68
|
+
(you, them, a member a message names, or nobody), open questions both ways, promises (stored tasks, promise facts,
|
|
69
|
+
and first person future words such as "пришлю" or "I'll send"), amounts with their direction and whether a later
|
|
70
|
+
message says paid, payment facts, how long each `--context-query` (words that all appear in one text) has been
|
|
71
|
+
quiet on their side, and how much of the chat the store holds. Open amounts are summed per direction and currency. Word matches are marked `basis: pattern`;
|
|
72
|
+
a message saying "paid" is `paid-mentioned`, never paid. At most two steps: sync the chat held in part, then read
|
|
73
|
+
the chat that needs you most. The other accounts' linked chats are named in `out_of_scope`. tg and max get it with
|
|
74
|
+
the `projects` group; `--compact` draws each signal with its own row.
|
|
75
|
+
- **For an app: `projectStatus(store, input)`, a list of signals in `STATUS_SIGNALS`.** A signal is one file with an
|
|
76
|
+
id, a version and `read`; one that throws is named in `failed` and the others still answer. Each built in signal
|
|
77
|
+
has its compact row in `STATUS_SIGNAL_ROWS`, also in `SHARED_ROWS`. `projectStatusAnswer` and `projectStatusText`
|
|
78
|
+
build the answer and the human form. `input.purposes` picks which chat purposes are read (`["work"]` until links
|
|
79
|
+
carry one). The `messages.list` step takes a `query`.
|
|
80
|
+
- **`--compact`: one line per item for an agent, from the same answer `--json` prints.** `messages list <chat>
|
|
81
|
+
--compact` prints `#<id> · 10-01 09:12 · Анна · <text>` under one header line that names the shared ref prefix
|
|
82
|
+
(`ref: msg:max/500/-1001/<id>`), what every row has in common (the chat's title), the date span and the zone. Rows
|
|
83
|
+
from several chats keep their whole refs. Text stays on one line with control and direction characters made
|
|
84
|
+
visible, and is cut at 400 characters with `…(+N)`; `--full` keeps it whole. The paging, `missing`, the next steps
|
|
85
|
+
and an incomplete answer follow as `# more:`, `# missing:`, `# next:` and `# complete: false` lines on stdout, and
|
|
86
|
+
each command line in them carries `--compact` again. On 1 000 messages of one chat it is about 48 % of the JSON
|
|
87
|
+
bytes; the texts alone are 40 %. `--compact` with `--json`, `--json=…`, `--jsonl` or `--brief` fails with
|
|
88
|
+
`validation_error` (`output.conflict`); it never prompts, and exits with the code JSON would. MCP keeps JSON.
|
|
89
|
+
- **Every command that answers through `renderAnswer` gets it.** A command draws with its own row
|
|
90
|
+
(`answerEntity(cmd, name, schema, { row })`), its app's (`rows: { name: shape }` in the program definition,
|
|
91
|
+
which also draws an app entity listed inside one thing), the shared one in `SHARED_ROWS` (`message`,
|
|
92
|
+
`message.summary`, `message.hit`, `chat`), or the generic row: key, ref or id · title, name or path · state,
|
|
93
|
+
status or due date · text. A record or a list is never printed as a column's value. `RowShape` is data, and `compactText(body, shape,
|
|
94
|
+
options)` is pure, for an app that prints its own answers.
|
|
95
|
+
- What a command prints without `renderAnswer` stays JSON under `--compact`.
|
|
96
|
+
- **`scanProjectLinks(store, { project, sources, since, write, scorers?, threshold?, limit?, purposes? })` and
|
|
97
|
+
`LinkScorer` (`@wirecat/cli-core/services`): memo proposes a project's chats, mail threads and people itself.**
|
|
98
|
+
Six scorers in `SCORERS` (`chat-title`, `alias-hits`, `member-chats`, `member-dialog`, `chat-senders`,
|
|
99
|
+
`mail-thread`) and the shared mail domain rule as `email-domain` in `PERSON_SCORERS`. Signals combine as
|
|
100
|
+
1 − Π(1 − w); at most 20 new proposals a run by the rule bot `memo-scan`, never confirmed by themselves. Each
|
|
101
|
+
carries `score` and `signals` (scorer, weight, why: ids and counts only). Linked and rejected pairs are skipped,
|
|
102
|
+
a pending one is updated in place; people are matched by identity only, never by name. `write: false` writes nothing.
|
|
103
|
+
- **`knowledge.relationState(scope, { from, to, kind })`** says whether a link joins a pair, whether a proposal for it
|
|
104
|
+
was rejected, and which one is pending; `proposeRelation` takes `score` and `signals`.
|
|
105
|
+
- **Payments are facts of type `payment`.** The amount (text, two decimals), ISO 4217 currency, direction (`to_us` or
|
|
106
|
+
`from_us`), counterparty ref or name, due date, state (`expected`, `paid`, `cancelled`) and item ride in
|
|
107
|
+
`metadata.payment`, read back as `Fact.payment`; no migration. A payment fact cites 1 to 8 references. Paid is a new
|
|
108
|
+
fact that supersedes the expected one, so the history stays. Only the owner accepts or rejects a payment:
|
|
109
|
+
`mayDecide` takes `ownerOnly`. `facts.list({ payment: { open, direction, state } })` filters them; `open` is
|
|
110
|
+
expected and still holding. `paymentTitle(fact)` reads "1 200 EUR to us from Ana, due 31.10 (expected)".
|
|
111
|
+
- **Agents stage payments as findings of kind `payment`** in `projects actions add`; confirming one writes and
|
|
112
|
+
accepts the fact, and a batch holding one is the owner's to decide. The inbox summarises each finding through
|
|
113
|
+
`FACT_SUMMARIES`, one row per kind. `projects status` lists payment facts with their title and adds the expected
|
|
114
|
+
ones to `money.open`, counting an ask the fact cites once.
|
|
115
|
+
- **For an app's `facts list`: `PAYMENT_QUERY_FIELDS` (`open:true`, `direction:to_us`, `state:paid`) and
|
|
116
|
+
`paymentFilterOf(terms)`.**
|
|
117
|
+
|
|
118
|
+
### Changed — may break callers
|
|
119
|
+
|
|
120
|
+
- **An option after `--` is read as the option.** `messages sync -- -100 --json` now syncs `-100` and answers in JSON;
|
|
121
|
+
it failed with "too many arguments". After `--`, a word that is exactly one of the command's options, its own or a
|
|
122
|
+
global one (`--json`, `--limit 5`, `--json=id`), moves in front of `--`; every other word stays a positional. A
|
|
123
|
+
negative id needs no `--` at all. Commands that take free text keep every word after `--` literal: `messages send` and
|
|
124
|
+
`edit` (also the bot's), `polls create`, `topics create`, `chats create`, `chats folders create`, `contacts rename`,
|
|
125
|
+
`contacts aliases set`, `messages press`, `bot commands set`, `schedule command`, `events remind`, `complete`, and the
|
|
126
|
+
notes templates. Mark such a command with `annotate(command, { literal_after_dashes: true })`; MCP calls are never
|
|
127
|
+
lifted. A script that passed the literal word `--json` as a positional of another command now gets the option instead.
|
|
128
|
+
- **A write to a calendar the account may only read refuses before anything is asked or journaled**
|
|
129
|
+
(`calendar.read-only`): create, quick add, import, update, delete, respond and move, for a feed and for a provider's
|
|
130
|
+
`reader` or `free-busy` calendar alike. Before, only the target of a move was checked; the provider refused the rest.
|
|
131
|
+
`calendars busy` and `search --backend server` leave feed calendars out.
|
|
132
|
+
- **A locator of another account or messenger is refused with a new text and a reason.** `messages show`, `context`,
|
|
133
|
+
`link` and `download` said "that locator belongs to another account; select its profile first" or "…belongs to
|
|
134
|
+
another messenger"; they now say `<ref> belongs to account <id>; profile <name> is account <id>` (`ref.wrong-account`)
|
|
135
|
+
or `<ref> is a <messenger> message; open it with …` (`ref.wrong-provider`). A script matching the old text matches
|
|
136
|
+
the reason instead.
|
|
137
|
+
- **A text of the form `<kind>:<no spaces>` given as a chat is read as a reference**, so a chat titled `note:plan` is
|
|
138
|
+
no longer found by that title; give its id or a part of the title.
|
|
139
|
+
- The provider seeds of `telegram`, `max` and `whatsapp` name their CLI (`command: tg`, `max`, `wa`), which a
|
|
140
|
+
provider clash message now shows (`telegram (messages, from tg)`).
|
|
141
|
+
- **cli-core now needs `@wirecat/cli-base` 0.75.0**, which holds the `--full-history` switch's name and the help
|
|
142
|
+
without `OR` for a list its provider filters. A CLI that pins cli-base bumps it to 0.75.0 together with cli-core.
|
|
143
|
+
- **`FACT_TYPES` gains `payment`, and a `Finding` may be a `PaymentFinding`.** A caller that lists facts with a fixed
|
|
144
|
+
type list, or reads `finding.title` on every finding that is not a fact, narrows by `kind` first. A memo older than
|
|
145
|
+
this release refuses a payment fact in `facts list`; ship memo's bump the same day. `MEETING_FACT_TYPES` is gone:
|
|
146
|
+
`FACT_TYPES` is the one list.
|
|
147
|
+
|
|
148
|
+
### Fixed
|
|
149
|
+
|
|
150
|
+
- **`messages delete` with no message id refuses with `validation_error`** before it connects. An empty id (`""`
|
|
151
|
+
or a lone comma) used to reach the messenger as a deletion of nothing and answer success.
|
|
152
|
+
- **An MCP read or write whose answer named a step only the person can take (`user_action`) failed as a bug.** The
|
|
153
|
+
router dropped next steps this server does not offer by their command, and such a step has none. It is kept now;
|
|
154
|
+
a command step this server does not offer is still dropped.
|
|
155
|
+
- **A sum written in groups of three read as the wrong amount: `50 000 ₽` was `0` and `4 300 ₽` was `300`**, because
|
|
156
|
+
only the last group was read. Groups after a space, a no-break or thin space, a dot or a comma (`50 000`,
|
|
157
|
+
`1.200 €`, `$1,200`) are one number now, a decimal part after them is kept (`5 000.50 ₽`), and amounts keep two
|
|
158
|
+
decimals instead of a whole number (`15.5 eur` was 16). This is the amount the duplicate check compares between
|
|
159
|
+
two tasks, so a reminder worded with a grouped sum is no longer compared on the wrong figure.
|
|
160
|
+
- **`page.next` of `messages list` and `messages comments` runs as written.** It repeated the query's `id`/`date`
|
|
161
|
+
bound beside `--cursor`, which the command refuses as two starting points; it now keeps only `topic:` and
|
|
162
|
+
`starred:`.
|
|
163
|
+
- **An inclusive start keeps a message sent exactly at it.** `messages list 'date>=2026-10-01'` skipped a message
|
|
164
|
+
sent at the first millisecond of the day, and `date<="…"` one sent at that moment.
|
|
165
|
+
- **`--brief` now cuts a messenger search hit.** It only knew mail's camelCase hits, so `search messages --brief` in
|
|
166
|
+
tg, max and wa printed every field; it now keeps `ref`, `chat_title`, `timestamp`, `sender_name`, `excerpt` and
|
|
167
|
+
`score`. The default and `--full` answers are unchanged. Commands that print through `outputFor` now honour
|
|
168
|
+
`--brief` and `--full` too, and refuse them together as the others do.
|
|
169
|
+
- **An Outlook or Exchange feed's events are read, no longer skipped.** Those feeds name time zones the Windows way,
|
|
170
|
+
`TZID:W. Europe Standard Time`, and the iCalendar reader took only IANA names (`Europe/Berlin`), so `calendars add`
|
|
171
|
+
and `sync` skipped every timed event of such a feed and counted it under `skipped`. A Windows name is now read as
|
|
172
|
+
the IANA zone Unicode CLDR gives it worldwide (territory `001`), in DTSTART, DTEND, RECURRENCE-ID, and in the TZID of
|
|
173
|
+
RDATE and EXDATE, which are stored with the IANA name. The 142 names are a table generated from CLDR release-49
|
|
174
|
+
(`scripts/windows-zones.ts` regenerates it); no new dependency. A TZID that is neither, such as Outlook's
|
|
175
|
+
`(UTC+01:00) Amsterdam, Berlin, Bern`, is still skipped.
|
|
176
|
+
- **A list whose provider filters it no longer says in `--help` that its query takes `OR`.** With
|
|
177
|
+
`@wirecat/cli-base` 0.74.0 → 0.75.0, its `Syntax:` line names only what it takes: `field:value` terms joined by AND,
|
|
178
|
+
and the phrase, `word*` and range forms where a field takes them. Every CLI picks this up at its next cli-core bump.
|
|
179
|
+
- **The browser login page of `mcp serve --http` names what the app asks to reach and the right command.** It always
|
|
180
|
+
said "reach your messages through `<app> mcp --http`"; a CLI that is not a messenger now says what it serves (gcal:
|
|
181
|
+
"your Google Calendar"), and every CLI names `<app> mcp serve --http`. `HttpOptions` takes `reaches` for the
|
|
182
|
+
wording; unset, the page says "your `<app>` data".
|
|
183
|
+
- **`store jobs list` says in its help and its MCP description that its query takes `OR`.** The list reads every job
|
|
184
|
+
file and takes the whole query language, but its registry said the source filters it (`native`).
|
|
185
|
+
|
|
10
186
|
## 0.550.0 — 02.11.2026
|
|
11
187
|
|
|
12
188
|
### Changed — may break callers
|
package/THIRD_PARTY_NOTICES
CHANGED
|
@@ -758,3 +758,44 @@ Licensed under SIL Open Font License 1.1; see dist/charts/fonts/OFL.txt and SOUR
|
|
|
758
758
|
|
|
759
759
|
PNG rasterization uses @resvg/resvg-js under MPL-2.0. Its original sources are
|
|
760
760
|
available at https://github.com/thx/resvg-js/tree/v2.6.2.
|
|
761
|
+
|
|
762
|
+
Windows time zone names mapped to IANA zones (dist/calendar/windows-zones.generated.js), generated from
|
|
763
|
+
Unicode CLDR release-49, common/supplemental/windowsZones.xml (https://github.com/unicode-org/cldr).
|
|
764
|
+
|
|
765
|
+
Copyright © 2001–2026 Unicode, Inc.
|
|
766
|
+
|
|
767
|
+
NOTICE TO USER: Carefully read the following legal agreement. BY
|
|
768
|
+
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
|
|
769
|
+
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
|
|
770
|
+
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
|
|
771
|
+
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
|
|
772
|
+
|
|
773
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
774
|
+
copy of data files and any associated documentation (the "Data Files") or
|
|
775
|
+
software and any associated documentation (the "Software") to deal in the
|
|
776
|
+
Data Files or Software without restriction, including without limitation
|
|
777
|
+
the rights to use, copy, modify, merge, publish, distribute, and/or sell
|
|
778
|
+
copies of the Data Files or Software, and to permit persons to whom the
|
|
779
|
+
Data Files or Software are furnished to do so, provided that either (a)
|
|
780
|
+
this copyright and permission notice appear with all copies of the Data
|
|
781
|
+
Files or Software, or (b) this copyright and permission notice appear in
|
|
782
|
+
associated Documentation.
|
|
783
|
+
|
|
784
|
+
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
785
|
+
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
786
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
787
|
+
THIRD PARTY RIGHTS.
|
|
788
|
+
|
|
789
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
|
|
790
|
+
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
|
|
791
|
+
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
792
|
+
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
793
|
+
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
|
|
794
|
+
FILES OR SOFTWARE.
|
|
795
|
+
|
|
796
|
+
Except as contained in this notice, the name of a copyright holder shall
|
|
797
|
+
not be used in advertising or otherwise to promote the sale, use or other
|
|
798
|
+
dealings in these Data Files or Software without prior written
|
|
799
|
+
authorization of the copyright holder.
|
|
800
|
+
|
|
801
|
+
SPDX-License-Identifier: Unicode-3.0
|
package/dist/calendar/ics.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { EntryStatus, EntryTransparency, ParticipantResponse } from "../mee
|
|
|
2
2
|
/**
|
|
3
3
|
* The part of iCalendar (RFC 5545, https://www.rfc-editor.org/rfc/rfc5545) the calendar commands read and write: one
|
|
4
4
|
* VCALENDAR of VEVENTs, with no VTIMEZONE. Times are written in UTC; a time read with a TZID keeps that zone's name,
|
|
5
|
-
* which the provider takes as it is.
|
|
5
|
+
* which the provider takes as it is. A Windows zone name, as Outlook and Exchange write it, is read as its IANA zone.
|
|
6
6
|
*/
|
|
7
7
|
export interface IcsEvent {
|
|
8
8
|
uid: string;
|
package/dist/calendar/ics.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { zonedMoment } from "@wirecat/cli-base/query";
|
|
3
|
+
import { WINDOWS_ZONES } from "./windows-zones.generated.js";
|
|
3
4
|
const CRLF = "\r\n";
|
|
4
5
|
const LINE_OCTETS = 75;
|
|
5
6
|
const escapeText = (text) => text
|
|
@@ -129,6 +130,8 @@ const contentLine = (line) => {
|
|
|
129
130
|
const unescapeText = (text) => text.replace(/\\([\\;,nN])/gu, (_match, char) => (char === "n" || char === "N" ? "\n" : char));
|
|
130
131
|
const DATE = /^(\d{4})(\d{2})(\d{2})$/u;
|
|
131
132
|
const DATE_TIME = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z?)$/u;
|
|
133
|
+
/** `W. Europe Standard Time` → `Europe/Berlin`, CLDR's zone for the name worldwide; any other TZID as written. */
|
|
134
|
+
const ianaZone = (tzid) => (Object.hasOwn(WINDOWS_ZONES, tzid) ? WINDOWS_ZONES[tzid] : tzid);
|
|
132
135
|
/** A DATE or DATE-TIME: UTC with `Z`, in its TZID, or floating, read in `zone`. */
|
|
133
136
|
const momentOf = (line, zone) => {
|
|
134
137
|
const value = line.value.trim();
|
|
@@ -146,7 +149,7 @@ const momentOf = (line, zone) => {
|
|
|
146
149
|
if (utc)
|
|
147
150
|
return { at: Date.parse(`${local}Z`), zone: "UTC" };
|
|
148
151
|
const named = line.params.TZID;
|
|
149
|
-
const where = named
|
|
152
|
+
const where = named === undefined ? zone : ianaZone(named);
|
|
150
153
|
try {
|
|
151
154
|
return { at: zonedMoment(local, where, { start: 0, end: local.length }), zone: where };
|
|
152
155
|
}
|
|
@@ -231,7 +234,7 @@ const eventOf = (lines, zone, overrides = false) => {
|
|
|
231
234
|
const recurrence = lines
|
|
232
235
|
.filter(({ name }) => ["RRULE", "RDATE", "EXDATE"].includes(name))
|
|
233
236
|
.map(({ name, params, value }) => {
|
|
234
|
-
const kept = Object.entries(params).map(([key, param]) => `;${key}=${paramValue(param)}`);
|
|
237
|
+
const kept = Object.entries(params).map(([key, param]) => `;${key}=${paramValue(key === "TZID" ? ianaZone(param) : param)}`);
|
|
235
238
|
return `${name}${kept.join("")}:${value.trim()}`;
|
|
236
239
|
});
|
|
237
240
|
if (recurrence.length)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WINDOWS_ZONES: Readonly<Record<string, string>>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Generated by scripts/windows-zones.ts from CLDR release-49 (Unicode License v3, THIRD_PARTY_NOTICES); do not edit by hand.
|
|
2
|
+
// https://raw.githubusercontent.com/unicode-org/cldr/release-49/common/supplemental/windowsZones.xml
|
|
3
|
+
export const WINDOWS_ZONES = {
|
|
4
|
+
"Afghanistan Standard Time": "Asia/Kabul",
|
|
5
|
+
"Alaskan Standard Time": "America/Anchorage",
|
|
6
|
+
"Alberta Standard Time": "America/Edmonton",
|
|
7
|
+
"Aleutian Standard Time": "America/Adak",
|
|
8
|
+
"Altai Standard Time": "Asia/Barnaul",
|
|
9
|
+
"Arab Standard Time": "Asia/Riyadh",
|
|
10
|
+
"Arabian Standard Time": "Asia/Dubai",
|
|
11
|
+
"Arabic Standard Time": "Asia/Baghdad",
|
|
12
|
+
"Argentina Standard Time": "America/Buenos_Aires",
|
|
13
|
+
"Astrakhan Standard Time": "Europe/Astrakhan",
|
|
14
|
+
"Atlantic Standard Time": "America/Halifax",
|
|
15
|
+
"AUS Central Standard Time": "Australia/Darwin",
|
|
16
|
+
"Aus Central W. Standard Time": "Australia/Eucla",
|
|
17
|
+
"AUS Eastern Standard Time": "Australia/Sydney",
|
|
18
|
+
"Azerbaijan Standard Time": "Asia/Baku",
|
|
19
|
+
"Azores Standard Time": "Atlantic/Azores",
|
|
20
|
+
"Bahia Standard Time": "America/Bahia",
|
|
21
|
+
"Bangladesh Standard Time": "Asia/Dhaka",
|
|
22
|
+
"Belarus Standard Time": "Europe/Minsk",
|
|
23
|
+
"Bougainville Standard Time": "Pacific/Bougainville",
|
|
24
|
+
"British Columbia Standard Time": "America/Vancouver",
|
|
25
|
+
"Canada Central Standard Time": "America/Regina",
|
|
26
|
+
"Cape Verde Standard Time": "Atlantic/Cape_Verde",
|
|
27
|
+
"Caucasus Standard Time": "Asia/Yerevan",
|
|
28
|
+
"Cen. Australia Standard Time": "Australia/Adelaide",
|
|
29
|
+
"Central America Standard Time": "America/Guatemala",
|
|
30
|
+
"Central Asia Standard Time": "Asia/Bishkek",
|
|
31
|
+
"Central Brazilian Standard Time": "America/Cuiaba",
|
|
32
|
+
"Central Europe Standard Time": "Europe/Budapest",
|
|
33
|
+
"Central European Standard Time": "Europe/Warsaw",
|
|
34
|
+
"Central Pacific Standard Time": "Pacific/Guadalcanal",
|
|
35
|
+
"Central Standard Time": "America/Chicago",
|
|
36
|
+
"Central Standard Time (Mexico)": "America/Mexico_City",
|
|
37
|
+
"Chatham Islands Standard Time": "Pacific/Chatham",
|
|
38
|
+
"China Standard Time": "Asia/Shanghai",
|
|
39
|
+
"Cuba Standard Time": "America/Havana",
|
|
40
|
+
"Dateline Standard Time": "Etc/GMT+12",
|
|
41
|
+
"E. Africa Standard Time": "Africa/Nairobi",
|
|
42
|
+
"E. Australia Standard Time": "Australia/Brisbane",
|
|
43
|
+
"E. Europe Standard Time": "Europe/Chisinau",
|
|
44
|
+
"E. South America Standard Time": "America/Sao_Paulo",
|
|
45
|
+
"Easter Island Standard Time": "Pacific/Easter",
|
|
46
|
+
"Eastern Standard Time": "America/New_York",
|
|
47
|
+
"Eastern Standard Time (Mexico)": "America/Cancun",
|
|
48
|
+
"Egypt Standard Time": "Africa/Cairo",
|
|
49
|
+
"Ekaterinburg Standard Time": "Asia/Yekaterinburg",
|
|
50
|
+
"Fiji Standard Time": "Pacific/Fiji",
|
|
51
|
+
"FLE Standard Time": "Europe/Kiev",
|
|
52
|
+
"Georgian Standard Time": "Asia/Tbilisi",
|
|
53
|
+
"GMT Standard Time": "Europe/London",
|
|
54
|
+
"Greenland Standard Time": "America/Godthab",
|
|
55
|
+
"Greenwich Standard Time": "Atlantic/Reykjavik",
|
|
56
|
+
"GTB Standard Time": "Europe/Bucharest",
|
|
57
|
+
"Haiti Standard Time": "America/Port-au-Prince",
|
|
58
|
+
"Hawaiian Standard Time": "Pacific/Honolulu",
|
|
59
|
+
"India Standard Time": "Asia/Calcutta",
|
|
60
|
+
"Iran Standard Time": "Asia/Tehran",
|
|
61
|
+
"Israel Standard Time": "Asia/Jerusalem",
|
|
62
|
+
"Jordan Standard Time": "Asia/Amman",
|
|
63
|
+
"Kaliningrad Standard Time": "Europe/Kaliningrad",
|
|
64
|
+
"Korea Standard Time": "Asia/Seoul",
|
|
65
|
+
"Libya Standard Time": "Africa/Tripoli",
|
|
66
|
+
"Line Islands Standard Time": "Pacific/Kiritimati",
|
|
67
|
+
"Lord Howe Standard Time": "Australia/Lord_Howe",
|
|
68
|
+
"Magadan Standard Time": "Asia/Magadan",
|
|
69
|
+
"Magallanes Standard Time": "America/Punta_Arenas",
|
|
70
|
+
"Manitoba Standard Time": "America/Winnipeg",
|
|
71
|
+
"Marquesas Standard Time": "Pacific/Marquesas",
|
|
72
|
+
"Mauritius Standard Time": "Indian/Mauritius",
|
|
73
|
+
"Middle East Standard Time": "Asia/Beirut",
|
|
74
|
+
"Montevideo Standard Time": "America/Montevideo",
|
|
75
|
+
"Morocco Standard Time": "Africa/Casablanca",
|
|
76
|
+
"Mountain Standard Time": "America/Denver",
|
|
77
|
+
"Mountain Standard Time (Mexico)": "America/Mazatlan",
|
|
78
|
+
"Myanmar Standard Time": "Asia/Rangoon",
|
|
79
|
+
"N. Central Asia Standard Time": "Asia/Novosibirsk",
|
|
80
|
+
"Namibia Standard Time": "Africa/Windhoek",
|
|
81
|
+
"Nepal Standard Time": "Asia/Katmandu",
|
|
82
|
+
"New Zealand Standard Time": "Pacific/Auckland",
|
|
83
|
+
"Newfoundland Standard Time": "America/St_Johns",
|
|
84
|
+
"Norfolk Standard Time": "Pacific/Norfolk",
|
|
85
|
+
"North Asia East Standard Time": "Asia/Irkutsk",
|
|
86
|
+
"North Asia Standard Time": "Asia/Krasnoyarsk",
|
|
87
|
+
"North Korea Standard Time": "Asia/Pyongyang",
|
|
88
|
+
"Omsk Standard Time": "Asia/Omsk",
|
|
89
|
+
"Pacific SA Standard Time": "America/Santiago",
|
|
90
|
+
"Pacific Standard Time": "America/Los_Angeles",
|
|
91
|
+
"Pacific Standard Time (Mexico)": "America/Tijuana",
|
|
92
|
+
"Pakistan Standard Time": "Asia/Karachi",
|
|
93
|
+
"Paraguay Standard Time": "America/Asuncion",
|
|
94
|
+
"Qyzylorda Standard Time": "Asia/Qyzylorda",
|
|
95
|
+
"Romance Standard Time": "Europe/Paris",
|
|
96
|
+
"Russia Time Zone 10": "Asia/Srednekolymsk",
|
|
97
|
+
"Russia Time Zone 11": "Asia/Kamchatka",
|
|
98
|
+
"Russia Time Zone 3": "Europe/Samara",
|
|
99
|
+
"Russian Standard Time": "Europe/Moscow",
|
|
100
|
+
"SA Eastern Standard Time": "America/Cayenne",
|
|
101
|
+
"SA Pacific Standard Time": "America/Bogota",
|
|
102
|
+
"SA Western Standard Time": "America/La_Paz",
|
|
103
|
+
"Saint Pierre Standard Time": "America/Miquelon",
|
|
104
|
+
"Sakhalin Standard Time": "Asia/Sakhalin",
|
|
105
|
+
"Samoa Standard Time": "Pacific/Apia",
|
|
106
|
+
"Sao Tome Standard Time": "Africa/Sao_Tome",
|
|
107
|
+
"Saratov Standard Time": "Europe/Saratov",
|
|
108
|
+
"SE Asia Standard Time": "Asia/Bangkok",
|
|
109
|
+
"Singapore Standard Time": "Asia/Singapore",
|
|
110
|
+
"South Africa Standard Time": "Africa/Johannesburg",
|
|
111
|
+
"South Sudan Standard Time": "Africa/Juba",
|
|
112
|
+
"Sri Lanka Standard Time": "Asia/Colombo",
|
|
113
|
+
"Sudan Standard Time": "Africa/Khartoum",
|
|
114
|
+
"Syria Standard Time": "Asia/Damascus",
|
|
115
|
+
"Taipei Standard Time": "Asia/Taipei",
|
|
116
|
+
"Tasmania Standard Time": "Australia/Hobart",
|
|
117
|
+
"Tocantins Standard Time": "America/Araguaina",
|
|
118
|
+
"Tokyo Standard Time": "Asia/Tokyo",
|
|
119
|
+
"Tomsk Standard Time": "Asia/Tomsk",
|
|
120
|
+
"Tonga Standard Time": "Pacific/Tongatapu",
|
|
121
|
+
"Transbaikal Standard Time": "Asia/Chita",
|
|
122
|
+
"Turkey Standard Time": "Europe/Istanbul",
|
|
123
|
+
"Turks And Caicos Standard Time": "America/Grand_Turk",
|
|
124
|
+
"Ulaanbaatar Standard Time": "Asia/Ulaanbaatar",
|
|
125
|
+
"US Eastern Standard Time": "America/Indianapolis",
|
|
126
|
+
"US Mountain Standard Time": "America/Phoenix",
|
|
127
|
+
UTC: "Etc/UTC",
|
|
128
|
+
"UTC-02": "Etc/GMT+2",
|
|
129
|
+
"UTC-08": "Etc/GMT+8",
|
|
130
|
+
"UTC-09": "Etc/GMT+9",
|
|
131
|
+
"UTC-11": "Etc/GMT+11",
|
|
132
|
+
"UTC+12": "Etc/GMT-12",
|
|
133
|
+
"UTC+13": "Etc/GMT-13",
|
|
134
|
+
"Venezuela Standard Time": "America/Caracas",
|
|
135
|
+
"Vladivostok Standard Time": "Asia/Vladivostok",
|
|
136
|
+
"Volgograd Standard Time": "Europe/Volgograd",
|
|
137
|
+
"W. Australia Standard Time": "Australia/Perth",
|
|
138
|
+
"W. Central Africa Standard Time": "Africa/Lagos",
|
|
139
|
+
"W. Europe Standard Time": "Europe/Berlin",
|
|
140
|
+
"W. Mongolia Standard Time": "Asia/Hovd",
|
|
141
|
+
"West Asia Standard Time": "Asia/Tashkent",
|
|
142
|
+
"West Bank Standard Time": "Asia/Hebron",
|
|
143
|
+
"West Pacific Standard Time": "Pacific/Port_Moresby",
|
|
144
|
+
"Yakutsk Standard Time": "Asia/Yakutsk",
|
|
145
|
+
"Yukon Standard Time": "America/Whitehorse",
|
|
146
|
+
};
|
package/dist/cli/compact.js
CHANGED
|
@@ -2,6 +2,7 @@ import { visibleControls } from "@wirecat/cli-base";
|
|
|
2
2
|
import { metaOf } from "@wirecat/cli-base/commands";
|
|
3
3
|
import { ENTITIES } from "../entities/index.js";
|
|
4
4
|
import { answerRow } from "./answer-entity.js";
|
|
5
|
+
import { STATUS_ROWS } from "./project-status-rows.js";
|
|
5
6
|
export const TEXT_CHARS = 400;
|
|
6
7
|
const sender = { field: ["sender_is_me", "sender_name"], tag: "me" };
|
|
7
8
|
const messageRow = {
|
|
@@ -39,6 +40,7 @@ export const SHARED_ROWS = {
|
|
|
39
40
|
{ field: "last_message_at", as: "time" },
|
|
40
41
|
],
|
|
41
42
|
},
|
|
43
|
+
...STATUS_ROWS,
|
|
42
44
|
};
|
|
43
45
|
/** Any record: what names it, what it is called, what state it is in, then what it says. */
|
|
44
46
|
export const GENERIC_ROW = {
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -111,10 +111,13 @@ export { type Saving, stored } from "./messenger/stored.js";
|
|
|
111
111
|
export { dateOrNone } from "./messenger/tasks-command.js";
|
|
112
112
|
export { MODEL_CATALOGUE_QUERY, type ModelCatalogueOptions } from "./model-catalogue-command.js";
|
|
113
113
|
export { positiveCount, window, withPaging } from "./paging.js";
|
|
114
|
+
export { PAYMENT_QUERY_FIELDS, paymentFilterOf } from "./payment-query.js";
|
|
114
115
|
export { type CommandPermissions, commandPathKey, commandPermissions, knownBeside, knownPermissionKeys, type PermissionKeyOf, type PermissionKeySource, refuseUnknownPermissionKeys, unknownPermissionIssues, unknownPermissionKeys, } from "./permission-keys.js";
|
|
115
116
|
export { asFirstWord, commandWords, liftProfile, profileFree, refuseCommandName, rootOf, takesProfile, usableProfileName, } from "./profile.js";
|
|
116
117
|
export { createProgram, type ProgramDefinition, type ProgramOptions, type RunOptions, run } from "./program.js";
|
|
117
118
|
export { type ProjectTextHints, projectAnswerParts, projectCutoffTime, projectEvidenceText, projectWindowOf, withSyncCommands, } from "./project-evidence.js";
|
|
119
|
+
export { type ProjectStatusHints, type ProjectStatusItem, projectStatusAnswer, projectStatusRow, projectStatusSchema, projectStatusText, } from "./project-status.js";
|
|
120
|
+
export { STATUS_ROWS, STATUS_SIGNAL_ROWS } from "./project-status-rows.js";
|
|
118
121
|
export { fieldsOf, projectFields } from "./result-fields.js";
|
|
119
122
|
export type { ScheduleHost } from "./schedule/schedule-command.js";
|
|
120
123
|
export { type Config, type Configuration, count, first, flag, fromFile, type GlobalFlags, NONE_NAMED, namedProfile, type ProfileKind, plain, type ResolveOptions, type Settings, type SettingsExtension, type SettingsExtensionContext, type Source, settingsFor, } from "./settings.js";
|
package/dist/cli/index.js
CHANGED
|
@@ -101,10 +101,13 @@ export { stored } from "./messenger/stored.js";
|
|
|
101
101
|
export { dateOrNone } from "./messenger/tasks-command.js";
|
|
102
102
|
export { MODEL_CATALOGUE_QUERY } from "./model-catalogue-command.js";
|
|
103
103
|
export { positiveCount, window, withPaging } from "./paging.js";
|
|
104
|
+
export { PAYMENT_QUERY_FIELDS, paymentFilterOf } from "./payment-query.js";
|
|
104
105
|
export { commandPathKey, commandPermissions, knownBeside, knownPermissionKeys, refuseUnknownPermissionKeys, unknownPermissionIssues, unknownPermissionKeys, } from "./permission-keys.js";
|
|
105
106
|
export { asFirstWord, commandWords, liftProfile, profileFree, refuseCommandName, rootOf, takesProfile, usableProfileName, } from "./profile.js";
|
|
106
107
|
export { createProgram, run } from "./program.js";
|
|
107
108
|
export { projectAnswerParts, projectCutoffTime, projectEvidenceText, projectWindowOf, withSyncCommands, } from "./project-evidence.js";
|
|
109
|
+
export { projectStatusAnswer, projectStatusRow, projectStatusSchema, projectStatusText, } from "./project-status.js";
|
|
110
|
+
export { STATUS_ROWS, STATUS_SIGNAL_ROWS } from "./project-status-rows.js";
|
|
108
111
|
export { fieldsOf, projectFields } from "./result-fields.js";
|
|
109
112
|
export { count, first, flag, fromFile, NONE_NAMED, namedProfile, plain, settingsFor, } from "./settings.js";
|
|
110
113
|
export { readSetupAnswers, setupPermissionCeiling } from "./setup-answers.js";
|
|
@@ -17,7 +17,8 @@ const parseFindingsJson = (text, label, validate) => {
|
|
|
17
17
|
catch {
|
|
18
18
|
throw new CliError("validation_error", `${label} input must be valid JSON`);
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
// A payment keeps its snake_case fields: it is stored and printed as written.
|
|
21
|
+
const decode = (value, depth = 0, verbatim = false) => {
|
|
21
22
|
if (depth > 16)
|
|
22
23
|
throw new CliError("validation_error", `${label} JSON is nested too deeply`);
|
|
23
24
|
if (Array.isArray(value))
|
|
@@ -28,10 +29,10 @@ const parseFindingsJson = (text, label, validate) => {
|
|
|
28
29
|
for (const [key, item] of Object.entries(value)) {
|
|
29
30
|
if (/[A-Z]/.test(key))
|
|
30
31
|
throw new CliError("validation_error", `${label} JSON fields use snake_case`);
|
|
31
|
-
const name = keys[key] ?? key;
|
|
32
|
+
const name = verbatim ? key : (keys[key] ?? key);
|
|
32
33
|
if (Object.hasOwn(output, name))
|
|
33
34
|
throw new CliError("validation_error", `duplicate ${label} field`);
|
|
34
|
-
Object.defineProperty(output, name, { value: decode(item, depth + 1), enumerable: true });
|
|
35
|
+
Object.defineProperty(output, name, { value: decode(item, depth + 1, key === "payment"), enumerable: true });
|
|
35
36
|
}
|
|
36
37
|
return output;
|
|
37
38
|
};
|
|
@@ -33,6 +33,21 @@ import { stopOnSignal } from "./patience.js";
|
|
|
33
33
|
const ALL_SINCE = "90d";
|
|
34
34
|
/** What a background `--all` job is listed under; no chat argument is spelled like it. */
|
|
35
35
|
const ALL_CHATS = "--all";
|
|
36
|
+
/** Says where the history limits (history_* settings) stopped the read, so an agent does not take it for all. */
|
|
37
|
+
const limitedLine = (result, status) => {
|
|
38
|
+
if ("items" in result) {
|
|
39
|
+
const { groupTooLarge = 0, olderThanWindow = 0 } = result.limited ?? {};
|
|
40
|
+
if (groupTooLarge + olderThanWindow === 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
return (`the history limits (history_* settings) left ${groupTooLarge} big group(s) unread and read ${olderThanWindow} ` +
|
|
43
|
+
`chat(s) only to the window's start — \`${status}\` lists them; \`messages sync <chat> --full-history\` reads one in full`);
|
|
44
|
+
}
|
|
45
|
+
if (result.limited === "group_too_large")
|
|
46
|
+
return "not read: a group above history_group_members_max — `--full-history` reads it and keeps it in full";
|
|
47
|
+
if (result.limited === "older_than_window")
|
|
48
|
+
return "read to the history window's start (history_dialog_days / history_group_days) — `--full-history` reads further";
|
|
49
|
+
return undefined;
|
|
50
|
+
};
|
|
36
51
|
export const syncCommand = (messenger) => {
|
|
37
52
|
const fetching = messenger.fetching ?? FETCHING;
|
|
38
53
|
return annotate(new Command("sync"), {
|
|
@@ -58,7 +73,7 @@ export const syncCommand = (messenger) => {
|
|
|
58
73
|
.option("--catch-up-chunks <n>", "at most this many local vector chunks", wholeNumber)
|
|
59
74
|
.option("--catch-up-messages <n>", "skip a graph rebuild larger than this many messages", wholeNumber)
|
|
60
75
|
.option("--catch-up-time <duration>", "local preparation time budget, 30s by default")
|
|
61
|
-
.option("--full-history", "keep this chat's
|
|
76
|
+
.option("--full-history", "read and keep this chat's history in full from now on, past the history limits (history_* settings)")
|
|
62
77
|
.option("--background", "run as a job that outlives this command; `store jobs show` follows it")
|
|
63
78
|
.option("--dry-run", "only estimate how many messages, requests and minutes a full fetch would still take — from the store, no request")
|
|
64
79
|
.action(async function (chat) {
|
|
@@ -151,6 +166,7 @@ export const syncCommand = (messenger) => {
|
|
|
151
166
|
limit,
|
|
152
167
|
pageSize,
|
|
153
168
|
pauseMs,
|
|
169
|
+
...(include ? { fullHistory: true } : {}),
|
|
154
170
|
catchUp: prepare ? preparation : false,
|
|
155
171
|
...(sinceMs === undefined ? {} : { sinceMs }),
|
|
156
172
|
...(last === undefined ? {} : { last }),
|
|
@@ -191,9 +207,20 @@ export const syncCommand = (messenger) => {
|
|
|
191
207
|
]
|
|
192
208
|
: []),
|
|
193
209
|
...(toReview > 0 ? [nextStep("mentions.review", { args: { new: true }, values: { shown } })] : []),
|
|
210
|
+
...("limited" in result && result.limited && "chat" in result && result.chat
|
|
211
|
+
? [
|
|
212
|
+
{
|
|
213
|
+
...nextStep("messages.sync", { args: { chat: result.chat, full_history: true } }),
|
|
214
|
+
why: "reads this chat past the history limits and keeps it in full from now on",
|
|
215
|
+
},
|
|
216
|
+
]
|
|
217
|
+
: []),
|
|
194
218
|
],
|
|
195
219
|
meta: window.meta,
|
|
196
220
|
}));
|
|
221
|
+
const limitedNote = limitedLine(result, lineOf(this, "store status"));
|
|
222
|
+
if (limitedNote)
|
|
223
|
+
context.renderer.note(limitedNote);
|
|
197
224
|
if (tasks?.held)
|
|
198
225
|
context.renderer.note(`the first sync left ${tasks.held} possible task(s) in ${tasks.heldChats ?? 0} chat(s) unopened ` +
|
|
199
226
|
`(config task_first_pass_per_chat) — ask the owner, then \`${lineOf(this, "tasks scan <chat>")}\``);
|
|
@@ -422,6 +422,7 @@ export const messengerContext = (command, messenger, resolving = {}) => {
|
|
|
422
422
|
// Turning recording off by name (--no-record, or record: false) keeps no search history either.
|
|
423
423
|
history: base.settings.record,
|
|
424
424
|
searchCatchUp: base.settings.searchCatchUp,
|
|
425
|
+
...(base.settings.historyLimits ? { historyLimits: base.settings.historyLimits } : {}),
|
|
425
426
|
pictures: base.settings.pictureSearch,
|
|
426
427
|
reranker: base.settings.searchReranker,
|
|
427
428
|
guard,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { nextStep } from "../steps.js";
|
|
2
2
|
const SHOWN = 5;
|
|
3
3
|
const reasonOf = (skip) => skip.reason === "group_too_large"
|
|
4
|
-
? `a group of ${skip.members ?? "many"} people, not saved`
|
|
4
|
+
? `a group of ${skip.members ?? "many"} people, not ${skip.unread ? "read" : "saved"}`
|
|
5
5
|
: `only from ${skip.keptFrom?.slice(0, 10) ?? "the window's start"}`;
|
|
6
6
|
const nameOf = (skip) => skip.title ?? skip.chatId;
|
|
7
7
|
/**
|
|
@@ -15,7 +15,7 @@ export const historyLimitGaps = (skips) => {
|
|
|
15
15
|
const messages = skips.reduce((sum, skip) => sum + skip.messages, 0);
|
|
16
16
|
const listed = skips
|
|
17
17
|
.slice(0, SHOWN)
|
|
18
|
-
.map((skip) => `${nameOf(skip)} (${skip.messages}, ${reasonOf(skip)})`)
|
|
18
|
+
.map((skip) => `${nameOf(skip)} (${skip.messages > 0 ? `${skip.messages}, ` : ""}${reasonOf(skip)})`)
|
|
19
19
|
.join("; ");
|
|
20
20
|
const more = skips.length > SHOWN ? `; and ${skips.length - SHOWN} more — \`store status\` lists them` : "";
|
|
21
21
|
return {
|
|
@@ -28,8 +28,8 @@ export const historyLimitGaps = (skips) => {
|
|
|
28
28
|
missing: [
|
|
29
29
|
{
|
|
30
30
|
field: "history_limits",
|
|
31
|
-
why: `the history limits (history_* settings) left
|
|
32
|
-
`
|
|
31
|
+
why: `the history limits (history_* settings) left history of ${skips.length} chats out of the store` +
|
|
32
|
+
`${messages > 0 ? ` (${messages} pushed messages counted)` : ""}: ${listed}${more}`,
|
|
33
33
|
step: "messages.sync",
|
|
34
34
|
},
|
|
35
35
|
],
|
|
@@ -355,6 +355,7 @@ const serveProfiles = async (self, context, host, flags, set) => {
|
|
|
355
355
|
tokenFile,
|
|
356
356
|
lockFile: httpLockFile(tokenFile),
|
|
357
357
|
version: app.version,
|
|
358
|
+
reaches: app.messenger === false ? `your ${host.name}` : "your messages",
|
|
358
359
|
onCode: (code, expires) => context.renderer.note(env[mcpHttpMarker(app.envPrefix)] === undefined
|
|
359
360
|
? `login code for a new browser app: ${code} (until ${expires.toTimeString().slice(0, 5)}; a new one after each login)`
|
|
360
361
|
: `a new login code for a browser app: \`${app.command} mcp server status --profiles ${set.option}\``),
|