@wirecat/cli-core 0.495.0 → 0.497.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 (44) hide show
  1. package/CHANGELOG.md +89 -1
  2. package/dist/calendar/cli/answers.d.ts +277 -0
  3. package/dist/calendar/cli/answers.js +257 -0
  4. package/dist/calendar/cli/index.d.ts +10 -1
  5. package/dist/calendar/cli/index.js +78 -47
  6. package/dist/calendar/index.d.ts +1 -1
  7. package/dist/calendar/reads.d.ts +7 -0
  8. package/dist/calendar/server-search.d.ts +31 -0
  9. package/dist/calendar/server-search.js +41 -0
  10. package/dist/calendar/source.d.ts +14 -0
  11. package/dist/calendar/testing/answers.d.ts +6 -0
  12. package/dist/calendar/testing/answers.js +37 -0
  13. package/dist/calendar/testing/source.d.ts +2 -0
  14. package/dist/calendar/testing/source.js +9 -0
  15. package/dist/cli/commands-command.js +10 -2
  16. package/dist/cli/config-command.js +18 -8
  17. package/dist/cli/messenger/conversation-answers.d.ts +1 -1
  18. package/dist/cli/messenger/message-answers.d.ts +1 -1
  19. package/dist/cli/messenger/message-writes.d.ts +2 -2
  20. package/dist/cli/messenger/search-answers.js +2 -2
  21. package/dist/cli/messenger/search-command.js +4 -2
  22. package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
  23. package/dist/cli/program.js +2 -1
  24. package/dist/entities/conversation-results.d.ts +2 -2
  25. package/dist/entities/evidence.d.ts +8 -8
  26. package/dist/entities/index.d.ts +26 -19
  27. package/dist/entities/listener.d.ts +4 -4
  28. package/dist/entities/message-context.d.ts +3 -3
  29. package/dist/entities/message-write.d.ts +4 -4
  30. package/dist/entities/message.d.ts +2 -2
  31. package/dist/entities/message.js +2 -2
  32. package/dist/entities/store-records.d.ts +1 -1
  33. package/dist/errors/reasons.js +4 -0
  34. package/dist/meetings/read-answers.d.ts +10 -0
  35. package/dist/meetings/read-answers.js +7 -0
  36. package/dist/services/document-source.d.ts +2 -3
  37. package/dist/services/document-source.js +2 -7
  38. package/dist/services/messages-discovery.js +7 -2
  39. package/dist/services/notes-search.d.ts +13 -3
  40. package/dist/services/notes-search.js +93 -19
  41. package/dist/store/sqlite/note-search.d.ts +5 -0
  42. package/dist/store/sqlite/note-search.js +11 -2
  43. package/package.json +1 -1
  44. package/parity.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,7 +5,95 @@ Notable changes to `@wirecat/cli-core` (`@wirecat/cli-messaging` up to 0.261.0,
5
5
  minor version may break callers, and says how under "Changed — may break callers". `pnpm docs:check` checks the
6
6
  shape of this file.
7
7
 
8
- ## Unreleased
8
+ ## 0.497.0 — 31.10.2026
9
+
10
+ ### Added
11
+
12
+ - **A calendar source can offer its provider's own search, and the shared `search` uses it.** `CalendarSource.search(calendar,
13
+ { query, limit })` is optional and answers `{ entries, more }` (new type `SearchPage`). With `serverSearch: true` in
14
+ `CalendarCommandDeps` (a flag, as `freeBusy`, so the source can stay unbuilt until a profile is open), `search` takes
15
+ `--backend <archive|server|both>`: `archive`, the default, is the stored search as before; `server` asks the provider
16
+ over each synced calendar and answers `{ query, by: "server", hits, has_more, untrusted }`, earliest first, cancelled
17
+ events left out, each hit with `provider`, `account`, `calendar`, `external_id`, `title`, `starts_at`, `ends_at`,
18
+ `all_day`, `status`, `location`, `url` when there is one, and `found_by: ["server"]`; `both` is refused. New reasons:
19
+ `search.offline`, `search.no-calendars`, `search.server-options`, `search.one-backend`. `fakeCalendarSource({ search:
20
+ true })` answers it in tests. A CLI that replaced the shared `search` to reach its provider can drop that
21
+ ([WC-ARCH-6](https://github.com/WireCatLabs/cli-base/blob/main/docs/standards/architecture.md#wc-arch-6--replace-a-use-case-not-a-command)).
22
+ - **Every shared calendar command declares the entity it answers with, with its schema**
23
+ ([WC-CMD-19](https://github.com/WireCatLabs/cli-base/blob/main/docs/standards/commands.md#wc-cmd-19--declare-the-entity-a-command-answers-with)),
24
+ so `commands --json` names it, `commands info --json` exports it and `--fields` can project it: `calendar`
25
+ (`calendars list`, `sync`, `unsync`), `calendar_busy`, `calendar_sync`, `calendar_sync_progress` (`status`), `event`
26
+ (`events list`, as before), `calendar_event` (`events show`), `calendar_event_write` (every `events` write),
27
+ `calendar_search_hit` (a stored or a server hit), `calendar_attendee` (`people list`), `calendar_linked_person`
28
+ (`people link`), `calendar_link_review` and `calendar_link_resolution`. Each describes the item a host prints, keys
29
+ in snake_case. The shared `event` entity takes the optional `change`, `changed_at`, `was` and `overlaps` that
30
+ `events list changed:` and `overlapping` add.
31
+ - **`calendars list` takes a query over the `calendar` entity**: `synced:`, `primary:` and `access_role:` narrow the
32
+ whole list the provider answered, as `[query...]` after the options
33
+ ([WC-CMD-20](https://github.com/WireCatLabs/cli-base/blob/main/docs/standards/commands.md#wc-cmd-20--give-a-list-one-query-over-its-entitys-fields-as-its-last-argument)).
34
+ `events list` keeps its words for now.
35
+ - **The shared `config show --json` names the profile's `kind`, `permissions` and `permission_sources` at the top**,
36
+ as a messenger's own `config show` does, so an agent reads one shape from every CLI.
37
+
38
+ ### Changed — may break callers
39
+
40
+ - **The shared calendar commands no longer add their own `--json` and `--jsonl`.** They read the host program's global
41
+ flags, as every other command does ([WC-CMD-14](https://github.com/WireCatLabs/cli-base/blob/main/docs/standards/commands.md#wc-cmd-14--keep-the-shared-global-flags-at-their-meaning)).
42
+ The per-command copies showed up in `commands --json` and as `json` and `jsonl` inputs of every calendar MCP tool,
43
+ and an agent that sent `jsonl: true` was refused with "choose --json or --jsonl", because the MCP runner always adds
44
+ `--json`. A host that mounts `addCalendarCommands` on a program without global `--json`/`--jsonl` must define them.
45
+ - **`people list` takes `[query...]` instead of `[event]`**: one event's attendees are `people list event:42`, and a
46
+ bare `people list 42` is now refused as a word with no field. Its MCP tool's input is `query` (`"event:42"`), no
47
+ longer `event` (WC-CMD-20).
48
+ - **`CalendarCommandDeps.embed` returns `{ model, embedded, left }`**, which `embedEvents` already answers, so
49
+ `calendar_sync` can describe `embeddings`. It was `Promise<unknown>`.
50
+
51
+ ### Fixed
52
+
53
+ - **`commands <path>` names the CLI's own groups when the path is unknown.** Its example of one path per call was
54
+ always `commands messages --json` and `commands chats --json`, even in a calendar CLI that has neither; it now names
55
+ the groups the caller typed, then the CLI's first groups.
56
+ - **A group given no subcommand points a script at its own help.** In machine mode `tg chats` answered "run `tg
57
+ --help` for the commands"; it now says `tg chats --help`
58
+ ([WC-CMD-3](https://github.com/WireCatLabs/cli-base/blob/main/docs/standards/commands.md#wc-cmd-3--give-a-group-without-a-leaf-only-its-help-never-a-hidden-default-action)).
59
+ - **A CLI that is not a messenger (`messenger: false`) no longer shows `config show --bot` or `config set|unset
60
+ --personal|--bot`.** Only a messenger has bots, and with them the file's personal and bot sections; a calendar or
61
+ notes CLI listed the options in its help, `commands --json` and its MCP tools with nothing behind them. They are
62
+ hidden there and still accepted, so a script that passes one keeps working.
63
+ - **`config show` with moved folders no longer says a session made without them reads as none.** That was true
64
+ before cli-base 0.65.5; a moved run now reads the usual keyring entry, and keeps a sign-in it makes in a temporary
65
+ entry that `session end` removes. The note says so.
66
+
67
+ ## 0.496.0 — 31.10.2026
68
+
69
+ ### Changed — may break callers
70
+
71
+ - **A discovery follow-up carries an `excerpt` of up to 240 characters, as the hit itself, instead of its whole
72
+ `text`.** On a real archive one follow-up (a pasted long write-up) added 7 KB to a five-hit answer, a sixth of it.
73
+ `items[].follow_ups[].text` is now `items[].follow_ups[].excerpt`; `messages context <ref>` shows the whole message.
74
+ The terminal output is unchanged.
75
+
76
+ ### Fixed
77
+
78
+ - **Discovery search keeps the colons of a quoted timestamp in a date filter.** 0.492.0 turned a colon between digits
79
+ into a space so that "22:00" in a question would not fail, but it also did so inside quotes, and
80
+ `date:["2026-08-21T21:30:00Z" TO "…"]` failed with `query.invalid-date` under `discover`. Quoted text is now left as is.
81
+ - **`search notes`, the notes of `search all` and drive's `search` keep the query's fields for hits found by
82
+ meaning.** `date:today` or `tag:work` without `--exact` returned about 20 notes that matched neither: the meaning
83
+ half embedded the whole query, fields included, and checked only `--filter`. Now only the query's words and phrases
84
+ are searched by meaning, and every field and every excluded word (`-draft`) holds for every hit; a field joined to
85
+ the words by `OR` narrows nothing. A query of fields alone is not searched by meaning and lists the matching notes,
86
+ newest first. `--filter` also checks every meaning candidate: before, it kept only the newest 500 notes it matched,
87
+ so an older note found by meaning was dropped.
88
+ - **A Drive document's `date:` and its shown `updated_at` are one time.** `date:` read when the store's copy changed,
89
+ while the hit showed the document's edit time on Drive, so of 20 hits for `date>=30d` 16 showed an older date. Both
90
+ are now the edit time on Drive when the store has it, and the store's copy otherwise, as `context` evidence already
91
+ reads it. `date:` on a Drive document therefore matches by its edit time, and the time is always written as
92
+ `2026-01-01T00:00:00.000Z`, as every other time is, where a front-matter time was shown as written.
93
+
94
+ ### Added
95
+
96
+ - **`NoteQuery.refs` checks a list of notes against a query, and `NoteHit.at` is the time `date:` read.**
9
97
 
10
98
  ## 0.495.0 — 31.10.2026
11
99
 
@@ -0,0 +1,277 @@
1
+ import { type QueryRegistry } from "@wirecat/cli-base/query";
2
+ import type { Command } from "commander";
3
+ import * as v from "valibot";
4
+ export declare const calendar: v.StrictObjectSchema<{
5
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
6
+ readonly external_id: v.StringSchema<undefined>;
7
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
8
+ readonly timezone: v.NullableSchema<v.StringSchema<undefined>, undefined>;
9
+ readonly access_role: v.NullableSchema<v.StringSchema<undefined>, undefined>;
10
+ readonly primary: v.BooleanSchema<undefined>;
11
+ readonly synced: v.BooleanSchema<undefined>;
12
+ readonly seen_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
13
+ }, undefined>;
14
+ export declare const calendarBusy: v.StrictObjectSchema<{
15
+ readonly start: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
16
+ readonly end: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
17
+ readonly timezone: v.StringSchema<undefined>;
18
+ readonly calendars: v.ArraySchema<v.StrictObjectSchema<{
19
+ /** One of the account's calendars, by its id; or `person`, by the address asked. */
20
+ readonly calendar: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
21
+ readonly person: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
22
+ readonly id: v.StringSchema<undefined>;
23
+ readonly busy: v.ArraySchema<v.StrictObjectSchema<{
24
+ readonly start: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
25
+ readonly end: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
26
+ }, undefined>, undefined>;
27
+ readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
28
+ }, undefined>, undefined>;
29
+ readonly slots: v.OptionalSchema<v.ArraySchema<v.StrictObjectSchema<{
30
+ readonly start: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
31
+ readonly end: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
32
+ }, undefined>, undefined>, undefined>;
33
+ readonly unknown: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
34
+ }, undefined>;
35
+ export declare const calendarSync: v.StrictObjectSchema<{
36
+ readonly provider: v.StringSchema<undefined>;
37
+ readonly account_id: v.NumberSchema<undefined>;
38
+ readonly window: v.StrictObjectSchema<{
39
+ readonly from: v.NumberSchema<undefined>;
40
+ readonly to: v.NumberSchema<undefined>;
41
+ }, undefined>;
42
+ readonly calendars: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
43
+ readonly synced: v.ArraySchema<v.StrictObjectSchema<{
44
+ readonly calendar_id: v.NumberSchema<undefined>;
45
+ readonly external_id: v.StringSchema<undefined>;
46
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
47
+ readonly round: v.PicklistSchema<["full", "changes"], undefined>;
48
+ readonly reset: v.BooleanSchema<undefined>;
49
+ readonly state: v.PicklistSchema<["partial", "complete"], undefined>;
50
+ readonly saved: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
51
+ readonly removed: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
52
+ readonly occurrences: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
53
+ readonly unseen: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
54
+ readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
55
+ }, undefined>, undefined>;
56
+ readonly not_synced: v.ArraySchema<v.StrictObjectSchema<{
57
+ readonly calendar_id: v.NumberSchema<undefined>;
58
+ readonly external_id: v.StringSchema<undefined>;
59
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
60
+ }, undefined>, undefined>;
61
+ readonly complete: v.BooleanSchema<undefined>;
62
+ readonly state: v.PicklistSchema<["partial", "complete"], undefined>;
63
+ readonly stopped: v.OptionalSchema<v.PicklistSchema<["requests", "deadline", "cancelled"], undefined>, undefined>;
64
+ readonly progress: v.StrictObjectSchema<{
65
+ readonly calendars: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
66
+ readonly calendars_done: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
67
+ readonly requests: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
68
+ readonly saved: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
69
+ readonly steps: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
70
+ }, undefined>;
71
+ readonly hint: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
72
+ /** What `sync --embed` embedded: `embedEvents`' answer. */
73
+ readonly embeddings: v.OptionalSchema<v.StrictObjectSchema<{
74
+ readonly model: v.StringSchema<undefined>;
75
+ readonly embedded: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
76
+ readonly left: v.BooleanSchema<undefined>;
77
+ }, undefined>, undefined>;
78
+ }, undefined>;
79
+ export declare const calendarSyncProgress: v.StrictObjectSchema<{
80
+ readonly calendar_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
81
+ readonly external_id: v.StringSchema<undefined>;
82
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
83
+ readonly round: v.NullableSchema<v.PicklistSchema<["full", "changes"], undefined>, undefined>;
84
+ readonly job: v.StringSchema<undefined>;
85
+ readonly profile: v.StringSchema<undefined>;
86
+ readonly done: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
87
+ readonly total: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
88
+ readonly remaining: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
89
+ readonly state: v.PicklistSchema<["partial", "complete"], undefined>;
90
+ readonly updated_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
91
+ readonly cursor_age_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
92
+ readonly line: v.StringSchema<undefined>;
93
+ }, undefined>;
94
+ export declare const calendarEvent: v.StrictObjectSchema<{
95
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
96
+ readonly event_series_id: v.NullableSchema<v.StringSchema<undefined>, undefined>;
97
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
98
+ readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
99
+ readonly location: v.NullableSchema<v.StringSchema<undefined>, undefined>;
100
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
101
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
102
+ readonly timezone: v.NullableSchema<v.StringSchema<undefined>, undefined>;
103
+ readonly origin: v.PicklistSchema<["auto", "owner", "calendar"], undefined>;
104
+ readonly status: v.NullableSchema<v.StringSchema<undefined>, undefined>;
105
+ readonly all_day: v.BooleanSchema<undefined>;
106
+ readonly source_deleted_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
107
+ readonly deleted_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
108
+ readonly created_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
109
+ readonly updated_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
110
+ readonly change: v.OptionalSchema<v.PicklistSchema<["new", "moved", "cancelled"], undefined>, undefined>;
111
+ readonly changed_at: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>, undefined>;
112
+ readonly was: v.OptionalSchema<v.StrictObjectSchema<{
113
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
114
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
115
+ }, undefined>, undefined>;
116
+ readonly overlaps: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
117
+ readonly ref: v.StringSchema<undefined>;
118
+ readonly entries: v.ArraySchema<v.StrictObjectSchema<{
119
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
120
+ readonly calendar_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
121
+ readonly external_id: v.StringSchema<undefined>;
122
+ readonly kind: v.StringSchema<undefined>;
123
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
124
+ readonly status: v.StringSchema<undefined>;
125
+ readonly event_type: v.NullableSchema<v.StringSchema<undefined>, undefined>;
126
+ readonly own_response: v.NullableSchema<v.StringSchema<undefined>, undefined>;
127
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
128
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
129
+ readonly join_url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
130
+ readonly url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
131
+ readonly deleted_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
132
+ }, undefined>, undefined>;
133
+ readonly attendees: v.ArraySchema<v.StrictObjectSchema<{
134
+ email: v.StringSchema<undefined>;
135
+ name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
136
+ response: v.NullableSchema<v.StringSchema<undefined>, undefined>;
137
+ organizer: v.BooleanSchema<undefined>;
138
+ optional: v.BooleanSchema<undefined>;
139
+ resource: v.BooleanSchema<undefined>;
140
+ self: v.BooleanSchema<undefined>;
141
+ /** `person:<id>` when the shared store knows the address. */
142
+ person: v.NullableSchema<v.StringSchema<undefined>, undefined>;
143
+ }, undefined>, undefined>;
144
+ readonly attachments: v.ArraySchema<v.StrictObjectSchema<{
145
+ readonly file_id: v.StringSchema<undefined>;
146
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
147
+ readonly document: v.NullableSchema<v.StringSchema<undefined>, undefined>;
148
+ }, undefined>, undefined>;
149
+ readonly history: v.ArraySchema<v.StrictObjectSchema<{
150
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
151
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
152
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
153
+ readonly location: v.NullableSchema<v.StringSchema<undefined>, undefined>;
154
+ readonly status: v.NullableSchema<v.StringSchema<undefined>, undefined>;
155
+ readonly changed_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
156
+ }, undefined>, undefined>;
157
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
158
+ }, undefined>;
159
+ /** A hit of the stored search, or with `--backend server` one the provider's own search found and nothing stored. */
160
+ export declare const calendarSearchHit: v.UnionSchema<[v.StrictObjectSchema<{
161
+ readonly provider: v.NullableSchema<v.StringSchema<undefined>, undefined>;
162
+ readonly account: v.NullableSchema<v.StringSchema<undefined>, undefined>;
163
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
164
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
165
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
166
+ readonly all_day: v.BooleanSchema<undefined>;
167
+ readonly status: v.NullableSchema<v.StringSchema<undefined>, undefined>;
168
+ readonly location: v.NullableSchema<v.StringSchema<undefined>, undefined>;
169
+ readonly url: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
170
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
171
+ readonly ref: v.StringSchema<undefined>;
172
+ readonly excerpt: v.StringSchema<undefined>;
173
+ readonly occurrences: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
174
+ readonly updated_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
175
+ readonly found_by: v.ArraySchema<v.PicklistSchema<["words", "meaning"], undefined>, undefined>;
176
+ }, undefined>, v.StrictObjectSchema<{
177
+ readonly provider: v.NullableSchema<v.StringSchema<undefined>, undefined>;
178
+ readonly account: v.NullableSchema<v.StringSchema<undefined>, undefined>;
179
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
180
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
181
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
182
+ readonly all_day: v.BooleanSchema<undefined>;
183
+ readonly status: v.NullableSchema<v.StringSchema<undefined>, undefined>;
184
+ readonly location: v.NullableSchema<v.StringSchema<undefined>, undefined>;
185
+ readonly url: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
186
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
187
+ readonly calendar: v.StringSchema<undefined>;
188
+ readonly external_id: v.StringSchema<undefined>;
189
+ readonly found_by: v.ArraySchema<v.LiteralSchema<"server", undefined>, undefined>;
190
+ }, undefined>], undefined>;
191
+ export declare const calendarEventWrite: v.StrictObjectSchema<{
192
+ readonly operation_id: v.StringSchema<undefined>;
193
+ readonly event: v.NullableSchema<v.StringSchema<undefined>, undefined>;
194
+ readonly entry: v.OptionalSchema<v.NullableSchema<v.StrictObjectSchema<{
195
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
196
+ readonly calendar_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
197
+ readonly external_id: v.StringSchema<undefined>;
198
+ readonly kind: v.StringSchema<undefined>;
199
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
200
+ readonly status: v.StringSchema<undefined>;
201
+ readonly event_type: v.NullableSchema<v.StringSchema<undefined>, undefined>;
202
+ readonly own_response: v.NullableSchema<v.StringSchema<undefined>, undefined>;
203
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
204
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
205
+ readonly join_url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
206
+ readonly url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
207
+ readonly deleted_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
208
+ }, undefined>, undefined>, undefined>;
209
+ /** `this`, `series` or `following`. */
210
+ readonly scope: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
211
+ /** Copies the store marked deleted. */
212
+ readonly removed: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
213
+ /** The series a `--following` change ended before the occurrence. */
214
+ readonly ended: v.OptionalSchema<v.NullableSchema<v.StrictObjectSchema<{
215
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
216
+ readonly calendar_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
217
+ readonly external_id: v.StringSchema<undefined>;
218
+ readonly kind: v.StringSchema<undefined>;
219
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
220
+ readonly status: v.StringSchema<undefined>;
221
+ readonly event_type: v.NullableSchema<v.StringSchema<undefined>, undefined>;
222
+ readonly own_response: v.NullableSchema<v.StringSchema<undefined>, undefined>;
223
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
224
+ readonly ends_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
225
+ readonly join_url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
226
+ readonly url: v.NullableSchema<v.StringSchema<undefined>, undefined>;
227
+ readonly deleted_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
228
+ }, undefined>, undefined>, undefined>;
229
+ readonly converted: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
230
+ readonly from_calendar: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
231
+ readonly calendar: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
232
+ readonly hint: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
233
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
234
+ }, undefined>;
235
+ export declare const calendarAttendee: v.StrictObjectSchema<{
236
+ readonly email: v.StringSchema<undefined>;
237
+ readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
238
+ readonly response: v.NullableSchema<v.StringSchema<undefined>, undefined>;
239
+ readonly organizer: v.BooleanSchema<undefined>;
240
+ readonly optional: v.BooleanSchema<undefined>;
241
+ readonly resource: v.BooleanSchema<undefined>;
242
+ readonly self: v.BooleanSchema<undefined>;
243
+ readonly person: v.NullableSchema<v.StringSchema<undefined>, undefined>;
244
+ /** How many of the listed events the person attends; only on the week's list. */
245
+ readonly events: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
246
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
247
+ }, undefined>;
248
+ export declare const calendarLinkedPerson: v.StrictObjectSchema<{
249
+ readonly person: v.StringSchema<undefined>;
250
+ readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
251
+ readonly identities: v.ArraySchema<v.StringSchema<undefined>, undefined>;
252
+ }, undefined>;
253
+ export declare const calendarLinkReview: v.StrictObjectSchema<{
254
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
255
+ readonly entry_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
256
+ readonly reason: v.StringSchema<undefined>;
257
+ readonly candidates: v.ArraySchema<v.StrictObjectSchema<{
258
+ readonly ref: v.StringSchema<undefined>;
259
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
260
+ readonly starts_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
261
+ }, undefined>, undefined>;
262
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
263
+ }, undefined>;
264
+ export declare const calendarLinkResolution: v.StrictObjectSchema<{
265
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
266
+ readonly status: v.StringSchema<undefined>;
267
+ readonly chosen: v.NullableSchema<v.StringSchema<undefined>, undefined>;
268
+ }, undefined>;
269
+ /**
270
+ * Each command's answer entity: one item of a list, or the one value. They describe what a host prints, with the
271
+ * keys in snake_case, though a command hands its host some keys in camelCase (`notSynced`, `hasMore`).
272
+ */
273
+ export declare const declareCalendarAnswers: (program: Command, commands: readonly Command[]) => void;
274
+ export declare const CALENDAR_ANSWER_PATHS: string[];
275
+ /** The provider answers the whole list, never a page, so the terms narrow every calendar it has. */
276
+ export declare const CALENDARS_QUERY: QueryRegistry;
277
+ export declare const PEOPLE_QUERY: QueryRegistry;
@@ -0,0 +1,257 @@
1
+ import { annotate } from "@wirecat/cli-base/commands";
2
+ import { queryFieldsOf } from "@wirecat/cli-base/query";
3
+ import * as v from "valibot";
4
+ import { answerEntity } from "../../cli/answer-entity.js";
5
+ import { count, id, text, time, untrusted } from "../../entities/fields.js";
6
+ import { event } from "../../meetings/index.js";
7
+ const nullableText = v.nullable(text);
8
+ const nullableTime = v.nullable(time);
9
+ const stretch = v.strictObject({ start: time, end: time });
10
+ const epochWindow = v.strictObject({ from: v.number(), to: v.number() });
11
+ export const calendar = v.strictObject({
12
+ id,
13
+ external_id: text,
14
+ title: nullableText,
15
+ timezone: nullableText,
16
+ access_role: nullableText,
17
+ primary: v.boolean(),
18
+ synced: v.boolean(),
19
+ seen_at: nullableTime,
20
+ });
21
+ const busyRow = v.strictObject({
22
+ /** One of the account's calendars, by its id; or `person`, by the address asked. */
23
+ calendar: v.optional(id),
24
+ person: v.optional(text),
25
+ id: text,
26
+ busy: v.array(stretch),
27
+ error: v.optional(text),
28
+ });
29
+ export const calendarBusy = v.strictObject({
30
+ start: time,
31
+ end: time,
32
+ timezone: text,
33
+ calendars: v.array(busyRow),
34
+ slots: v.optional(v.array(stretch)),
35
+ unknown: v.optional(v.array(text)),
36
+ });
37
+ const syncedCalendar = v.strictObject({
38
+ calendar_id: v.number(),
39
+ external_id: text,
40
+ title: nullableText,
41
+ round: v.picklist(["full", "changes"]),
42
+ reset: v.boolean(),
43
+ state: v.picklist(["partial", "complete"]),
44
+ saved: count,
45
+ removed: count,
46
+ occurrences: count,
47
+ unseen: count,
48
+ error: v.optional(text),
49
+ });
50
+ export const calendarSync = v.strictObject({
51
+ provider: text,
52
+ account_id: v.number(),
53
+ window: epochWindow,
54
+ calendars: count,
55
+ synced: v.array(syncedCalendar),
56
+ not_synced: v.array(v.strictObject({ calendar_id: v.number(), external_id: text, title: nullableText })),
57
+ complete: v.boolean(),
58
+ state: v.picklist(["partial", "complete"]),
59
+ stopped: v.optional(v.picklist(["requests", "deadline", "cancelled"])),
60
+ progress: v.strictObject({
61
+ calendars: count,
62
+ calendars_done: count,
63
+ requests: count,
64
+ saved: count,
65
+ steps: count,
66
+ }),
67
+ hint: v.optional(text),
68
+ /** What `sync --embed` embedded: `embedEvents`' answer. */
69
+ embeddings: v.optional(v.strictObject({ model: text, embedded: count, left: v.boolean() })),
70
+ });
71
+ export const calendarSyncProgress = v.strictObject({
72
+ calendar_id: id,
73
+ external_id: text,
74
+ title: nullableText,
75
+ round: v.nullable(v.picklist(["full", "changes"])),
76
+ job: text,
77
+ profile: text,
78
+ done: count,
79
+ total: v.nullable(count),
80
+ remaining: v.nullable(count),
81
+ state: v.picklist(["partial", "complete"]),
82
+ updated_at: nullableTime,
83
+ cursor_age_ms: v.nullable(count),
84
+ line: text,
85
+ });
86
+ const entry = v.strictObject({
87
+ id,
88
+ calendar_id: id,
89
+ external_id: text,
90
+ kind: text,
91
+ title: nullableText,
92
+ status: text,
93
+ event_type: nullableText,
94
+ own_response: nullableText,
95
+ starts_at: nullableTime,
96
+ ends_at: nullableTime,
97
+ join_url: nullableText,
98
+ url: nullableText,
99
+ deleted_at: nullableTime,
100
+ });
101
+ const attendee = {
102
+ email: text,
103
+ name: nullableText,
104
+ response: nullableText,
105
+ organizer: v.boolean(),
106
+ optional: v.boolean(),
107
+ resource: v.boolean(),
108
+ self: v.boolean(),
109
+ /** `person:<id>` when the shared store knows the address. */
110
+ person: nullableText,
111
+ };
112
+ const { untrusted: _eventMarker, ...eventFields } = event.entries;
113
+ export const calendarEvent = v.strictObject({
114
+ ...eventFields,
115
+ ref: text,
116
+ entries: v.array(entry),
117
+ attendees: v.array(v.strictObject(attendee)),
118
+ attachments: v.array(v.strictObject({ file_id: text, title: nullableText, document: nullableText })),
119
+ history: v.array(v.strictObject({
120
+ title: nullableText,
121
+ starts_at: nullableTime,
122
+ ends_at: nullableTime,
123
+ location: nullableText,
124
+ status: nullableText,
125
+ changed_at: time,
126
+ })),
127
+ untrusted,
128
+ });
129
+ const hitFields = {
130
+ provider: nullableText,
131
+ account: nullableText,
132
+ title: nullableText,
133
+ starts_at: nullableTime,
134
+ ends_at: nullableTime,
135
+ all_day: v.boolean(),
136
+ status: nullableText,
137
+ location: nullableText,
138
+ url: v.optional(text),
139
+ untrusted,
140
+ };
141
+ /** A hit of the stored search, or with `--backend server` one the provider's own search found and nothing stored. */
142
+ export const calendarSearchHit = v.union([
143
+ v.strictObject({
144
+ ...hitFields,
145
+ ref: text,
146
+ excerpt: text,
147
+ occurrences: count,
148
+ updated_at: time,
149
+ found_by: v.array(v.picklist(["words", "meaning"])),
150
+ }),
151
+ v.strictObject({
152
+ ...hitFields,
153
+ calendar: text,
154
+ external_id: text,
155
+ found_by: v.array(v.literal("server")),
156
+ }),
157
+ ]);
158
+ export const calendarEventWrite = v.strictObject({
159
+ operation_id: text,
160
+ event: nullableText,
161
+ entry: v.optional(v.nullable(entry)),
162
+ /** `this`, `series` or `following`. */
163
+ scope: v.optional(text),
164
+ /** Copies the store marked deleted. */
165
+ removed: v.optional(count),
166
+ /** The series a `--following` change ended before the occurrence. */
167
+ ended: v.optional(v.nullable(entry)),
168
+ converted: v.optional(text),
169
+ from_calendar: v.optional(id),
170
+ calendar: v.optional(id),
171
+ hint: v.optional(text),
172
+ untrusted,
173
+ });
174
+ export const calendarAttendee = v.strictObject({
175
+ ...attendee,
176
+ /** How many of the listed events the person attends; only on the week's list. */
177
+ events: v.optional(count),
178
+ untrusted,
179
+ });
180
+ export const calendarLinkedPerson = v.strictObject({ person: text, name: nullableText, identities: v.array(text) });
181
+ export const calendarLinkReview = v.strictObject({
182
+ id,
183
+ entry_id: id,
184
+ reason: text,
185
+ candidates: v.array(v.strictObject({ ref: text, title: nullableText, starts_at: nullableTime })),
186
+ untrusted,
187
+ });
188
+ export const calendarLinkResolution = v.strictObject({ id, status: text, chosen: nullableText });
189
+ const ANSWERS = {
190
+ "calendars list": { name: "calendar", schema: calendar },
191
+ "calendars sync": { name: "calendar", schema: calendar },
192
+ "calendars unsync": { name: "calendar", schema: calendar },
193
+ "calendars busy": { name: "calendar_busy", schema: calendarBusy },
194
+ sync: { name: "calendar_sync", schema: calendarSync },
195
+ status: { name: "calendar_sync_progress", schema: calendarSyncProgress },
196
+ "events list": { name: "event" },
197
+ "events show": { name: "calendar_event", schema: calendarEvent },
198
+ "events create": { name: "calendar_event_write", schema: calendarEventWrite },
199
+ "events update": { name: "calendar_event_write", schema: calendarEventWrite },
200
+ "events delete": { name: "calendar_event_write", schema: calendarEventWrite },
201
+ "events move": { name: "calendar_event_write", schema: calendarEventWrite },
202
+ "events respond": { name: "calendar_event_write", schema: calendarEventWrite },
203
+ search: { name: "calendar_search_hit", schema: calendarSearchHit },
204
+ "people list": { name: "calendar_attendee", schema: calendarAttendee },
205
+ "people link": { name: "calendar_linked_person", schema: calendarLinkedPerson },
206
+ "links review": { name: "calendar_link_review", schema: calendarLinkReview },
207
+ "links resolve": { name: "calendar_link_resolution", schema: calendarLinkResolution },
208
+ };
209
+ /**
210
+ * Each command's answer entity: one item of a list, or the one value. They describe what a host prints, with the
211
+ * keys in snake_case, though a command hands its host some keys in camelCase (`notSynced`, `hasMore`).
212
+ */
213
+ export const declareCalendarAnswers = (program, commands) => {
214
+ const pathOf = (command) => {
215
+ const words = [];
216
+ for (let at = command; at && at !== program; at = at.parent)
217
+ words.unshift(at.name());
218
+ return words.join(" ");
219
+ };
220
+ for (const command of commands) {
221
+ const answer = ANSWERS[pathOf(command)];
222
+ if (!answer)
223
+ continue;
224
+ if (answer.schema)
225
+ answerEntity(command, answer.name, answer.schema);
226
+ else
227
+ annotate(command, { output: { entity: answer.name } });
228
+ }
229
+ };
230
+ export const CALENDAR_ANSWER_PATHS = Object.keys(ANSWERS);
231
+ const wholeValues = (registry) => ({
232
+ ...registry,
233
+ fields: registry.fields.map((field) => field.native ? { ...field, operators: field.operators.filter((one) => one === "term" || one === "phrase") } : field),
234
+ });
235
+ /** The provider answers the whole list, never a page, so the terms narrow every calendar it has. */
236
+ export const CALENDARS_QUERY = wholeValues({
237
+ entity: "calendar",
238
+ backend: "native",
239
+ fields: queryFieldsOf(calendar, {
240
+ native: ["synced", "primary", "access_role"],
241
+ examples: { synced: "synced:true", primary: "primary:true", access_role: "access_role:owner" },
242
+ }),
243
+ });
244
+ export const PEOPLE_QUERY = wholeValues({
245
+ entity: "calendar_attendee",
246
+ backend: "native",
247
+ fields: queryFieldsOf(calendarAttendee, {
248
+ native: ["event"],
249
+ relations: {
250
+ event: {
251
+ type: "kw",
252
+ example: "event:42",
253
+ relation: "one event's attendees, by its id; without it, everyone in this week's events",
254
+ },
255
+ },
256
+ }),
257
+ });