ask-marcel-office-cli 2.4.0 → 2.5.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 +153 -0
- package/README.md +5 -5
- package/dist/cli.js +1460 -761
- package/dist/commands.json +300 -23
- package/dist/index.js +566 -210
- package/dist/use-cases/commands/convert-group-post-attachment-to-markdown.d.ts +21 -0
- package/dist/use-cases/commands/convert-group-post-to-markdown.d.ts +20 -0
- package/dist/use-cases/commands/convert-mail-attachment-to-markdown.d.ts +6 -3
- package/dist/use-cases/commands/convert-mail-to-markdown.d.ts +35 -3
- package/dist/use-cases/commands/docx-metadata.d.ts +5 -4
- package/dist/use-cases/commands/get-group-post-attachment.d.ts +13 -0
- package/dist/use-cases/commands/get-group-post.d.ts +4 -0
- package/dist/use-cases/commands/list-group-post-attachments.d.ts +4 -0
- package/dist/use-cases/commands/list-group-thread-posts.d.ts +4 -0
- package/docs/COMMANDS.md +15 -9
- package/docs/USAGE.md +6 -6
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,159 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `ask-marcel-office-cli` are documented here.
|
|
4
4
|
|
|
5
|
+
## 2.5.0
|
|
6
|
+
|
|
7
|
+
### Fixed: `help` costs the same whoever runs it
|
|
8
|
+
|
|
9
|
+
The top-level listing is compacted to fit an LLM's token budget, and then
|
|
10
|
+
Commander sized its description column from `process.stdout.columns`, so the
|
|
11
|
+
budget depended on the reader's terminal. Measured on this surface: 35 KB at 80
|
|
12
|
+
columns, 64 KB at 100, 46 KB at 140, 39 KB at 200. Not even monotonic, so no
|
|
13
|
+
width was safe to assume.
|
|
14
|
+
|
|
15
|
+
The wrap width is now pinned at 80 and the listing is 35 KB everywhere.
|
|
16
|
+
|
|
17
|
+
This also broke `npm publish`. The byte-count guard in `cli.test.ts` asserts the
|
|
18
|
+
listing stays under 45 KB, and under CI or any piped run stdout is not a TTY, so
|
|
19
|
+
Commander fell back to 80 and the guard passed. Run from an ordinary terminal at
|
|
20
|
+
90 to 150 columns it failed, which is where most terminals sit. A new test
|
|
21
|
+
renders the listing at four widths and asserts one size, so the guard can no
|
|
22
|
+
longer measure a different thing for each reader.
|
|
23
|
+
|
|
24
|
+
### Fixed: the group conversation collections stop advertising a filter Graph refuses
|
|
25
|
+
|
|
26
|
+
`list-group-threads` and `list-group-conversations` handed out the full OData
|
|
27
|
+
option set, so both advertised `--filter`. Graph accepts it on neither. Probed
|
|
28
|
+
live on a group the signed-in user belongs to: any predicate on the threads
|
|
29
|
+
collection answers `ConversationFilterOther`, `isLocked eq false` answers
|
|
30
|
+
`ConversationFilterIsLockedEqualsFalse` because the only accepted forms are
|
|
31
|
+
`IsLocked eq true` and `IsLocked ne false`, and a predicate on conversations
|
|
32
|
+
answers `ErrorUnsupportedPathForQuery`.
|
|
33
|
+
|
|
34
|
+
That broke the promise the usage guide makes, that the CLI advertises only the
|
|
35
|
+
flags the endpoint honours so the manifest never lies. An agent reading the
|
|
36
|
+
manifest spent a round trip to find out. `--filter` is dropped from both; the
|
|
37
|
+
flag is now refused locally with the unknown-flag hint and no network call.
|
|
38
|
+
Filtering a group inbox down to its locked threads is not a use this CLI has,
|
|
39
|
+
so the one working predicate did not earn a caveat in its place.
|
|
40
|
+
|
|
41
|
+
`--top`, `--skip`, `--orderby`, `--select` and `--expand` are all honoured on
|
|
42
|
+
both collections and are unchanged.
|
|
43
|
+
|
|
44
|
+
### Added: docx tracked changes cover the table
|
|
45
|
+
|
|
46
|
+
`extractDocxMetadata` reported formatting revisions on runs and paragraphs only,
|
|
47
|
+
so a reviewer who restyled a table left no trace in the metadata block. Word
|
|
48
|
+
records a table, row and cell property change the same way it records a run's,
|
|
49
|
+
the properties as they were BEFORE the edit nested inside a `*Change` element,
|
|
50
|
+
so the same walker reads all five. `formatChanges[].scope` gains `table`, `row`
|
|
51
|
+
and `cell` alongside `run` and `paragraph`.
|
|
52
|
+
|
|
53
|
+
One limit worth knowing: a property whose values hang off child elements rather
|
|
54
|
+
than its own attributes, and `w:tblBorders` is the common table case, compares
|
|
55
|
+
as unchanged. The revision is still reported with its author, date and scope; it
|
|
56
|
+
names no property. Structural revisions (`w:cellIns`, `w:cellDel`, `w:cellMerge`)
|
|
57
|
+
carry no before/after pair and are not reported.
|
|
58
|
+
|
|
59
|
+
### Added: a gate that holds the docs to the registry's numbers
|
|
60
|
+
|
|
61
|
+
Four numeric claims drifted during the 2.4.0 cycle, and one was wrong on main for
|
|
62
|
+
two releases: `docs/USAGE.md` promised "the 180 READ commands" where the registry
|
|
63
|
+
held 188, three sections after `README.md` said 188 correctly. `mcp.ts` already
|
|
64
|
+
derives its counts and carries a comment saying the prose must be derived too;
|
|
65
|
+
nothing enforced it.
|
|
66
|
+
|
|
67
|
+
`bun run check:docs` reads the counts off the command registry and the rendered
|
|
68
|
+
manifest, then holds all ten numeric claims in `README.md`, `docs/USAGE.md` and
|
|
69
|
+
`docs/COMMANDS.md` to them, printing `file:line expected N, found M`. A claim
|
|
70
|
+
whose anchor text no longer matches anything fails too, so rewording a sentence
|
|
71
|
+
cannot silently switch its own check off. It runs in CI behind a `--selftest`
|
|
72
|
+
that proves the matcher rejects both a wrong number and a lost anchor.
|
|
73
|
+
|
|
74
|
+
The stale 188 is corrected in the same change.
|
|
75
|
+
|
|
76
|
+
### Added: read what is attached to a group post
|
|
77
|
+
|
|
78
|
+
`get-group-post --expand attachments` was the only route to a post's attachments,
|
|
79
|
+
and it inlines every one of them at once, which is the shape that times out on a
|
|
80
|
+
post carrying a multi-MB file. Three commands make the group inbox readable
|
|
81
|
+
attachment by attachment, all on the `Group.Read.All` scope the token already has:
|
|
82
|
+
|
|
83
|
+
- `list-group-post-attachments` returns the metadata alone, with the same slim
|
|
84
|
+
default `--select` the mail and calendar siblings use. Graph silently ignores
|
|
85
|
+
`$top`, `$skip`, `$orderby` and `$filter` here (probed live: asking for one
|
|
86
|
+
attachment returned all seven, and `isInline eq false` returned all seven when
|
|
87
|
+
every one was inline), so only `--select` and `--expand` are exposed.
|
|
88
|
+
- `get-group-post-attachment` fetches one attachment, mirroring `contentBytes`
|
|
89
|
+
as `base64` so `--output-path` lands it on disk. This is also the route to an
|
|
90
|
+
image attached to a post.
|
|
91
|
+
- `convert-group-post-attachment-to-markdown` renders one through the shared
|
|
92
|
+
conversion pipeline, the way the mail and calendar siblings do.
|
|
93
|
+
|
|
94
|
+
### Fixed: unconvertible attachments name a command that can reach them
|
|
95
|
+
|
|
96
|
+
The shared conversion pipeline hardcoded the mail remediation wording, so an
|
|
97
|
+
image or scanned PDF attached to a calendar event told the caller to run
|
|
98
|
+
`get-mail-attachment --message-id ...`, which cannot address an event. Each
|
|
99
|
+
caller now supplies its own hints: the calendar converter points at
|
|
100
|
+
`get-calendar-event --expand attachments` and its PDF sibling, and the new post
|
|
101
|
+
converter points at `get-group-post-attachment`.
|
|
102
|
+
|
|
103
|
+
### Fixed: inline-only mail no longer hides its images
|
|
104
|
+
|
|
105
|
+
Graph reports `hasAttachments: false` for a message whose only attachments are
|
|
106
|
+
inline images, and both markdown converters fetched the attachment list only on
|
|
107
|
+
that flag. Such a message rendered its images as unnamed placeholders, left them
|
|
108
|
+
out of the attachments list, and embedded nothing under `--inline-images true`.
|
|
109
|
+
The list is now fetched whenever the body references a `cid:` image as well,
|
|
110
|
+
the guard `get-mail-signature` already uses, so
|
|
111
|
+
`convert-mail-to-markdown` and `convert-group-post-to-markdown` name the
|
|
112
|
+
placeholders, list the images with their ids, and embed them on request. No
|
|
113
|
+
extra call for a message without inline images.
|
|
114
|
+
|
|
115
|
+
### Changed: the shared-mailbox commands say when they will 403
|
|
116
|
+
|
|
117
|
+
`list-shared-mailbox-messages`, `list-shared-mailbox-folder-messages`,
|
|
118
|
+
`list-shared-mailbox-folders`, `list-shared-mailbox-child-folders` and
|
|
119
|
+
`get-shared-mailbox-message` used to promise a 403 only "if the signed-in user
|
|
120
|
+
does not have shared access". The scope they need, `Mail.Read.Shared`, is on
|
|
121
|
+
neither token this CLI can mint, so their summaries now state that any mailbox
|
|
122
|
+
other than your own is expected to answer `ErrorAccessDenied` whatever delegation
|
|
123
|
+
Exchange holds, that your own UPN works, and that a Microsoft 365 group's mailbox
|
|
124
|
+
is the shared-mail path that does.
|
|
125
|
+
|
|
126
|
+
### Added: read the posts of a Microsoft 365 group conversation
|
|
127
|
+
|
|
128
|
+
`list-group-conversations` and `list-group-threads` stopped at Graph's truncated
|
|
129
|
+
`preview`, and a group mailbox cannot be read through the shared-mailbox commands
|
|
130
|
+
(`ErrorGroupIsUsedInNonGroupURI`), so a group's mail was reachable up to its titles
|
|
131
|
+
and no further. Three commands close the gap, all on the `Group.Read.All` scope the
|
|
132
|
+
token already carries:
|
|
133
|
+
|
|
134
|
+
- `list-group-thread-posts --group-id --thread-id` returns every `post` of a thread
|
|
135
|
+
with its HTML body, `from`, `sender`, `receivedDateTime` and `hasAttachments`.
|
|
136
|
+
Graph hands back the whole thread in one call and silently ignores `$top`, `$skip`
|
|
137
|
+
and `$orderby` while rejecting `$filter` (probed live), so only `--select` and
|
|
138
|
+
`--expand` are exposed and there is no page cursor.
|
|
139
|
+
- `get-group-post --group-id --thread-id --post-id` is the `get-mail-message` sibling
|
|
140
|
+
for a group inbox; `--expand attachments` inlines the attachments with their bytes.
|
|
141
|
+
- `convert-group-post-to-markdown` renders one post the way `convert-mail-to-markdown`
|
|
142
|
+
renders a message, with the same `--inline-images` and `--keep-quoted` flags. A post
|
|
143
|
+
arrives from the group's own address with the writer in `sender`, so the author line
|
|
144
|
+
reads `Robin Chen <...> on behalf of Support <...>`; the thread `topic` is the subject
|
|
145
|
+
and is not repeated.
|
|
146
|
+
|
|
147
|
+
The mail-to-markdown pipeline now takes the resource path and the header renderer as
|
|
148
|
+
parameters; the mail command's output is unchanged. `list-group-threads` and
|
|
149
|
+
`list-group-conversations` point at the reader, and at `--expand posts`, which already
|
|
150
|
+
inlined the bodies.
|
|
151
|
+
|
|
152
|
+
### Fixed — deleted text no longer renders in an `.odt` body
|
|
153
|
+
|
|
154
|
+
The body converter walked `text:tracked-changes` like any other block, so the
|
|
155
|
+
paragraphs a reviewer had deleted printed as if they were still in the
|
|
156
|
+
document. The region is skipped, so the body reads as the document stands.
|
|
157
|
+
|
|
5
158
|
## 2.4.0
|
|
6
159
|
|
|
7
160
|
Two community fixes from [@a-tokyo](https://github.com/a-tokyo). Nothing breaks:
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
Outlook · OneDrive · SharePoint · Calendar · Excel · Teams · Planner · To Do · OneNote · People
|
|
14
14
|
|
|
15
|
-
[Install](#install-in-60-seconds) · [See it work](#see-it-work) · [What it reaches](#what-your-agent-can-reach) · [Files to markdown](#any-file-becomes-markdown) · [Library](#embed-it-as-a-typescript-library) · [All
|
|
15
|
+
[Install](#install-in-60-seconds) · [See it work](#see-it-work) · [What it reaches](#what-your-agent-can-reach) · [Files to markdown](#any-file-becomes-markdown) · [Library](#embed-it-as-a-typescript-library) · [All 192 commands](docs/COMMANDS.md)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -61,7 +61,7 @@ Microsoft Graph normally means registering an Azure app, chasing tenant-admin co
|
|
|
61
61
|
|
|
62
62
|
### 🛡️ Safe to hand to an autonomous agent
|
|
63
63
|
|
|
64
|
-
The
|
|
64
|
+
The 192 commands break down as 184 GET, 4 read-only POST (three searches and a free/busy lookup), and 4 mail-draft operations. No `send-mail`. No `create-event`. No `upload-file`. No `delete-anything`. The worst a hallucinated tool call can do is leave an unsent draft in your Drafts folder. That is the entire blast radius, which is why you can let an agent explore a mailbox without reviewing every call. No analytics, either: the only outbound traffic is Microsoft Graph and a periodic npm version check.
|
|
65
65
|
|
|
66
66
|
### 🧠 Responses budgeted for a context window
|
|
67
67
|
|
|
@@ -111,7 +111,7 @@ $ ask-marcel-office download-drive-item-as-markdown --drive-id "b!abc..." --item
|
|
|
111
111
|
|
|
112
112
|
| Surface | Commands | In practice |
|
|
113
113
|
|---|---:|---|
|
|
114
|
-
| 📧 Outlook Mail |
|
|
114
|
+
| 📧 Outlook Mail | 44 | Search and read mail as markdown, convert any attachment (down to nested `.zip` and `.msg`), resolve SharePoint links in bodies, extract your signature, find existing drafts on a thread, prepare reply / forward drafts (the only writes) |
|
|
115
115
|
| 📁 OneDrive + SharePoint | 49 | Discover every drive and site your token can reach, search files, read any document as markdown or PDF, version history, share links resolved even into partner tenants where you're a guest |
|
|
116
116
|
| 📅 Calendar | 24 | "What's on this week" via relative dates (`today`, `start-of-week`, `+7d`), event details, free/busy lookups |
|
|
117
117
|
| 👥 People + directory | 16 | People search, user profiles, the directory around you, your own identity and IDs in one round trip |
|
|
@@ -203,7 +203,7 @@ You get **five gateway tools**, not one per command — a schema per command wou
|
|
|
203
203
|
|:--|:--|
|
|
204
204
|
| `list-commands` | The terse manifest. Start here; `category` narrows it. |
|
|
205
205
|
| `get-command-docs` | Full docs for one command: options, endpoint, example. |
|
|
206
|
-
| `run-command` | The
|
|
206
|
+
| `run-command` | The 188 **read** commands. `readOnlyHint: true`, so clients can auto-approve it. |
|
|
207
207
|
| `run-write-command` | The 4 mail-draft **write** commands. Separate tool so the read tool's promise stays honest. |
|
|
208
208
|
| `login` | Sign in / refresh. Opens a browser on this machine. |
|
|
209
209
|
|
|
@@ -249,7 +249,7 @@ Azure Managed Identity, an on-behalf-of flow, hand-pasted JWTs in tests: the Gra
|
|
|
249
249
|
|
|
250
250
|
## Deep docs
|
|
251
251
|
|
|
252
|
-
- **[All
|
|
252
|
+
- **[All 192 commands](docs/COMMANDS.md)**: per-category tables with required params + Graph endpoint
|
|
253
253
|
- **[Usage guide](docs/USAGE.md)**: output formats, OData passthrough, `--output-path`, pagination, library API, architecture, configuration
|
|
254
254
|
- **[Machine-readable manifest](docs/commands.json)**: JSON for programmatic discovery, also importable via `import manifest from 'ask-marcel-office-cli/commands.json'`
|
|
255
255
|
- **[QA playbook](docs/QA-PLAYBOOK.md)**: the repeatable full-surface health check run before each release
|