ask-marcel-office-cli 2.0.0 → 2.1.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/dist/cli.js CHANGED
@@ -2144,7 +2144,7 @@ import updateNotifier from "update-notifier";
2144
2144
  // package.json
2145
2145
  var package_default = {
2146
2146
  name: "ask-marcel-office-cli",
2147
- version: "2.0.0",
2147
+ version: "2.1.0",
2148
2148
  description: "Microsoft Graph CLI + library — typed Bun/TypeScript wrapper around 150+ Graph operations (read + on-the-fly PDF/markdown conversion + federated Microsoft Search) reachable from a Teams browser-OAuth token.",
2149
2149
  license: "MIT",
2150
2150
  author: "Vincent Delacourt <vincent.delacourt@adama-development.com>",
@@ -2677,7 +2677,7 @@ var createBrowserAuthFromApi = (api, config) => {
2677
2677
  logger.info("elevated_token_capture_timeout");
2678
2678
  return { ok: false, reason: "sso_timeout" };
2679
2679
  };
2680
- const acquireBothTokens = async (teamsUrl) => {
2680
+ const acquireBothTokens = async (teamsUrl, options) => {
2681
2681
  const elevatedUrl = M365_CLOUD_URL;
2682
2682
  trace(`[DEBUG] acquireBothTokens: ENTER
2683
2683
  `);
@@ -2860,7 +2860,7 @@ var createBrowserAuthFromApi = (api, config) => {
2860
2860
  const teamsDeadline = Date.now() + pollDeadlineMs;
2861
2861
  let pollCount = 0;
2862
2862
  while (Date.now() < teamsDeadline && !capturedAccess) {
2863
- const concurrent = await freshCachedToken();
2863
+ const concurrent = options?.skipCacheProbe === true ? null : await freshCachedToken();
2864
2864
  if (concurrent !== null) {
2865
2865
  const validated = accessToken(concurrent);
2866
2866
  if (validated.ok) {
@@ -3189,9 +3189,20 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3189
3189
  };
3190
3190
  let lastElevatedOutcome = null;
3191
3191
  let lastChatsvcaggOutcome = null;
3192
- const acquireViaBrowser = async () => {
3192
+ const redeemMissedSubstrateAtLogin = async (chatsvcaggCaptured, ic3Captured) => {
3193
+ if (chatsvcaggCaptured && ic3Captured)
3194
+ return;
3195
+ const fresh = await readCache();
3196
+ if (!fresh?.refresh_token)
3197
+ return;
3198
+ if (!chatsvcaggCaptured)
3199
+ await refreshSubstrateToken(fresh, CHATSVCAGG_RESOURCE, persistChatsvcagg, "auth.chatsvcagg.login_rt_redeem");
3200
+ if (!ic3Captured)
3201
+ await refreshSubstrateToken(fresh, IC3_RESOURCE, persistIc3, "auth.ic3.login_rt_redeem");
3202
+ };
3203
+ const acquireViaBrowser = async (force = false) => {
3193
3204
  try {
3194
- const { teams: result, elevated, chatsvcagg, ic3, fromCache } = await browserAuth.acquireBothTokens(TEAMS_URL);
3205
+ const { teams: result, elevated, chatsvcagg, ic3, fromCache } = await browserAuth.acquireBothTokens(TEAMS_URL, { skipCacheProbe: force });
3195
3206
  if (!result)
3196
3207
  return err({ type: "auth_cancelled" });
3197
3208
  if (fromCache === true) {
@@ -3221,6 +3232,8 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3221
3232
  } else {
3222
3233
  logger.info("auth.ic3.skipped_at_login", { reason: ic3.reason });
3223
3234
  }
3235
+ if (force)
3236
+ await redeemMissedSubstrateAtLogin(chatsvcagg.ok, ic3.ok);
3224
3237
  logger.info("auth.ladder.rung", { rung: "browser" });
3225
3238
  return ok(result.accessToken);
3226
3239
  } catch (e) {
@@ -3229,32 +3242,34 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3229
3242
  }
3230
3243
  };
3231
3244
  let inFlightBrowserAcquire = null;
3232
- const acquireViaBrowserShared = () => {
3245
+ const acquireViaBrowserShared = (force = false) => {
3233
3246
  if (inFlightBrowserAcquire !== null) {
3234
3247
  logger.info("auth.ladder.rung", { rung: "browser_shared_in_flight" });
3235
3248
  return inFlightBrowserAcquire;
3236
3249
  }
3237
- const launched = acquireViaBrowser();
3250
+ const launched = acquireViaBrowser(force);
3238
3251
  inFlightBrowserAcquire = launched.finally(() => {
3239
3252
  inFlightBrowserAcquire = null;
3240
3253
  });
3241
3254
  return inFlightBrowserAcquire;
3242
3255
  };
3243
- const getAccessToken = async () => {
3244
- const cached = await readCache();
3245
- if (cached) {
3246
- const validated = accessToken(cached.access_token);
3247
- if (validated.ok) {
3248
- logger.info("auth.ladder.rung", { rung: "cache" });
3249
- return ok(validated.value);
3256
+ const getAccessToken = async (options) => {
3257
+ if (!options?.force) {
3258
+ const cached = await readCache();
3259
+ if (cached) {
3260
+ const validated = accessToken(cached.access_token);
3261
+ if (validated.ok) {
3262
+ logger.info("auth.ladder.rung", { rung: "cache" });
3263
+ return ok(validated.value);
3264
+ }
3265
+ }
3266
+ if (cached?.refresh_token) {
3267
+ const refreshed = await refreshToken(cached);
3268
+ if (refreshed.ok)
3269
+ return refreshed;
3250
3270
  }
3251
3271
  }
3252
- if (cached?.refresh_token) {
3253
- const refreshed = await refreshToken(cached);
3254
- if (refreshed.ok)
3255
- return refreshed;
3256
- }
3257
- return acquireViaBrowserShared();
3272
+ return acquireViaBrowserShared(options?.force ?? false);
3258
3273
  };
3259
3274
  const ELEVATED_BUFFER_SECONDS = 300;
3260
3275
  const freshElevatedToken = (cached) => {
@@ -3264,6 +3279,12 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3264
3279
  return;
3265
3280
  return cached.elevated_access_token;
3266
3281
  };
3282
+ const getCachedElevatedInfo = async () => {
3283
+ const cached = await readCache();
3284
+ const exp = cached?.elevated_expires_on;
3285
+ const expiresInSeconds = typeof exp === "number" ? Math.floor(exp - Date.now() / 1000) : undefined;
3286
+ return { available: freshElevatedToken(cached) !== undefined, expiresInSeconds };
3287
+ };
3267
3288
  const recoverableElevatedFailureMessage = (reason) => {
3268
3289
  if (reason === "launch_timeout") {
3269
3290
  return "elevated browser launch timed out (15s) — likely a corrupt persistent profile or filesystem lock. Run `ask-marcel-office logout && ask-marcel-office login` to wipe the profile and retry. (Commands that need this token: list-chats, get-chat, the historical-version download / convert commands.)";
@@ -3321,6 +3342,12 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3321
3342
  return;
3322
3343
  return cached.chatsvcagg_access_token;
3323
3344
  };
3345
+ const getCachedChatsvcaggInfo = async () => {
3346
+ const cached = await readCache();
3347
+ const exp = cached?.chatsvcagg_expires_on;
3348
+ const expiresInSeconds = typeof exp === "number" ? Math.floor(exp - Date.now() / 1000) : undefined;
3349
+ return { available: freshChatsvcaggToken(cached) !== undefined, expiresInSeconds };
3350
+ };
3324
3351
  const recoverableChatsvcaggFailureMessage = (reason) => {
3325
3352
  if (reason === "launch_timeout") {
3326
3353
  return "chatsvcagg browser launch timed out (15s) — likely a corrupt persistent profile or filesystem lock. Run `ask-marcel-office logout && ask-marcel-office login` to wipe the profile and retry. (Commands that need this token: list-teams-chats-with-messages, list-teams-chat-messages, get-teams-chat-message, find-chats-with-user.)";
@@ -3389,6 +3416,12 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3389
3416
  return;
3390
3417
  return cached.ic3_access_token;
3391
3418
  };
3419
+ const getCachedIc3Info = async () => {
3420
+ const cached = await readCache();
3421
+ const exp = cached?.ic3_expires_on;
3422
+ const expiresInSeconds = typeof exp === "number" ? Math.floor(exp - Date.now() / 1000) : undefined;
3423
+ return { available: freshIc3Token(cached) !== undefined, expiresInSeconds };
3424
+ };
3392
3425
  const recoverableIc3FailureMessage = (reason) => {
3393
3426
  if (reason === "launch_timeout") {
3394
3427
  return "ic3 browser launch timed out (15s) — likely a corrupt persistent profile or filesystem lock. Run `ask-marcel-office logout && ask-marcel-office login` to wipe the profile and retry. (Commands that need this token: list-teams-chat-history.)";
@@ -3463,7 +3496,10 @@ var createAuthManagerFromApi = (browserAuth, cachePath, browserProfileDir, logge
3463
3496
  getIc3AccessToken,
3464
3497
  logout,
3465
3498
  getLastElevatedOutcome,
3466
- getLastChatsvcaggOutcome
3499
+ getLastChatsvcaggOutcome,
3500
+ getCachedElevatedInfo,
3501
+ getCachedChatsvcaggInfo,
3502
+ getCachedIc3Info
3467
3503
  };
3468
3504
  };
3469
3505
  var defaultFileSystem2 = () => typeof globalThis.Bun !== "undefined" ? createBunFileSystem() : createNodeFileSystem();
@@ -3877,7 +3913,10 @@ var createGraphClient = (auth, fetchFn = globalThis.fetch) => {
3877
3913
  const expRaw = claims["exp"];
3878
3914
  const expiresAt = typeof expRaw === "number" ? new Date(expRaw * 1000).toISOString() : undefined;
3879
3915
  const expiresInSeconds = typeof expRaw === "number" ? Math.floor(expRaw - Date.now() / 1000) : undefined;
3880
- return ok({ scopes, audience, expiresAt, expiresInSeconds });
3916
+ const elevated = auth.getCachedElevatedInfo ? await auth.getCachedElevatedInfo() : { available: false, expiresInSeconds: undefined };
3917
+ const chatsvcagg = auth.getCachedChatsvcaggInfo ? await auth.getCachedChatsvcaggInfo() : { available: false, expiresInSeconds: undefined };
3918
+ const ic3 = auth.getCachedIc3Info ? await auth.getCachedIc3Info() : { available: false, expiresInSeconds: undefined };
3919
+ return ok({ scopes, audience, expiresAt, expiresInSeconds, elevated, chatsvcagg, ic3 });
3881
3920
  };
3882
3921
  return {
3883
3922
  get: (path, extraHeaders) => request("GET", path, undefined, extraHeaders),
@@ -4608,6 +4647,7 @@ var GRAPH_SCOPES_BY_COMMAND = {
4608
4647
  "convert-calendar-event-attachment-to-pdf": ["Calendars.Read", "Files.Read"],
4609
4648
  "extract-mail-attachment-images": ["Mail.Read"],
4610
4649
  "extract-sharepoint-links-in-mail": ["Mail.Read"],
4650
+ "create-forward-draft": ["Mail.ReadWrite"],
4611
4651
  "create-mail-draft": ["Mail.ReadWrite"],
4612
4652
  "create-reply-draft": ["Mail.ReadWrite"],
4613
4653
  "update-mail-draft": ["Mail.ReadWrite"],
@@ -4730,14 +4770,21 @@ var toEntry = (name, cmd) => {
4730
4770
  var LIFECYCLE_ENTRIES = [
4731
4771
  {
4732
4772
  name: "login",
4733
- summary: "Authenticate against Microsoft Graph using the Teams web client (cached token → refresh → browser fallback). Stores tokens at ~/.ask-marcel/token-cache.json (0600). Run before any Graph command.",
4773
+ summary: "Authenticate against Microsoft Graph using the Teams web client (cached token → refresh → browser fallback). Stores tokens at ~/.ask-marcel/token-cache.json (0600). Reports all four cached tokens (basic / elevated / chatsvcagg / ic3) with their time-left and how to refresh each; pass --force to re-capture every token via the browser in one pass. Run before any Graph command.",
4734
4774
  category: "lifecycle",
4735
4775
  graphMethod: "GET",
4736
4776
  graphPathTemplate: "(lifecycle) browser-OAuth via Teams web client; not a Graph endpoint",
4737
4777
  graphDocsUrl: "https://learn.microsoft.com/en-us/graph/auth-v2-user",
4738
- options: [],
4739
- example: "ask-marcel-office login",
4740
- responseShape: '{ status: "authenticated" } on success; envelope error on cancel/failure.'
4778
+ options: [
4779
+ {
4780
+ name: "force",
4781
+ key: "force",
4782
+ required: false,
4783
+ description: "Ignore the cache and re-capture every token via the browser. The only way to refresh the elevated (M365) token while the basic token is still valid; the persistent browser profile is reused, so you are usually not re-prompted for credentials."
4784
+ }
4785
+ ],
4786
+ example: "ask-marcel-office login --force",
4787
+ responseShape: '{ status: "authenticated", tokens: { basic, elevated, chatsvcagg, ic3 }, hint } on success. Each token is { available: boolean, expiresInSeconds?: number, refresh: "automatic" | "interactive", reason? }: basic/chatsvcagg/ic3 refresh automatically from the cached refresh token, the elevated (M365) token is re-captured only on an interactive login. `expiresInSeconds` is omitted when the token is not cached; a failed elevated capture this run adds `reason`. Envelope error on cancel/failure.'
4741
4788
  },
4742
4789
  {
4743
4790
  name: "logout",
@@ -19975,17 +20022,17 @@ var bytesToMarkdown = async (bytes, filename, opts, hints) => {
19975
20022
  if (ext === "doc")
19976
20023
  return docToMarkdown(bytes);
19977
20024
  if (ext === "ppt")
19978
- return err({ type: "api_error", status: 415, message: hints.legacyPpt });
20025
+ return err({ type: "api_error", status: 415, code: "unsupported_legacy_office", message: hints.legacyPpt });
19979
20026
  if (ext === "msg") {
19980
20027
  const depth = opts.depth ?? 0;
19981
20028
  return msgToMarkdown(bytes, { depth }, (childBytes, childName) => bytesToMarkdown(childBytes, childName, { ...opts, depth: depth + 1 }, NESTED_HINTS));
19982
20029
  }
19983
20030
  if (IMAGE_EXTENSIONS.has(ext))
19984
- return err({ type: "api_error", status: 415, message: hints.image(ext) });
20031
+ return err({ type: "api_error", status: 415, code: "unsupported_image", message: hints.image(ext) });
19985
20032
  const text = decodeUtf8Text(bytes);
19986
20033
  if (text !== undefined)
19987
20034
  return ok({ contentType: "text/plain", size: bytes.byteLength, text });
19988
- return err({ type: "api_error", status: 415, message: hints.generic(ext === "" ? "<no-extension>" : ext) });
20035
+ return err({ type: "api_error", status: 415, code: "unsupported_format", message: hints.generic(ext === "" ? "<no-extension>" : ext) });
19989
20036
  };
19990
20037
 
19991
20038
  // src/use-cases/commands/inline-image-embedder.ts
@@ -20259,6 +20306,7 @@ var extractImagesFromBytes = async (bytes, name, fetchHint) => {
20259
20306
  return err({
20260
20307
  type: "api_error",
20261
20308
  status: 415,
20309
+ code: "unsupported_document",
20262
20310
  message: `${ext === "" ? "<no-extension>" : ext} is not a supported document — image extraction supports pdf and docx / xlsx / pptx (and their macro-enabled / template variants). ${fetchHint}`
20263
20311
  });
20264
20312
  }
@@ -24410,19 +24458,27 @@ var openZipEntries = async (bytes) => {
24410
24458
 
24411
24459
  // src/use-cases/commands/zip-archive-to-markdown.ts
24412
24460
  var MAX_ENTRIES = 100;
24413
- var convertEntry = async (entry, includeMetadata) => {
24461
+ var entryImages = async (entry) => {
24462
+ const r = await extractImagesFromBytes(entry.bytes, entry.path, "");
24463
+ return r.ok ? r.value.media : [];
24464
+ };
24465
+ var convertEntry = async (entry, includeMetadata, includeImages) => {
24414
24466
  const r = await bytesToMarkdown(entry.bytes, entry.path, { includeMetadata }, NESTED_HINTS);
24415
24467
  if (!r.ok)
24416
24468
  return { path: entry.path, note: r.error.message };
24417
24469
  const env = r.value;
24418
- return { path: entry.path, contentType: env.contentType, size: env.size, text: env.text };
24470
+ const base = { path: entry.path, contentType: env.contentType, size: env.size, text: env.text };
24471
+ if (!includeImages)
24472
+ return base;
24473
+ const images = await entryImages(entry);
24474
+ return images.length > 0 ? { ...base, images } : base;
24419
24475
  };
24420
- var convertZipArchive = async (bytes, includeMetadata) => {
24476
+ var convertZipArchive = async (bytes, includeMetadata, includeImages = false) => {
24421
24477
  const entries = await openZipEntries(bytes);
24422
24478
  if (!entries.ok)
24423
24479
  return entries;
24424
24480
  const capped = entries.value.slice(0, MAX_ENTRIES);
24425
- const files = await Promise.all(capped.map((entry) => convertEntry(entry, includeMetadata)));
24481
+ const files = await Promise.all(capped.map((entry) => convertEntry(entry, includeMetadata, includeImages)));
24426
24482
  if (entries.value.length > MAX_ENTRIES) {
24427
24483
  return ok({ count: files.length, totalEntries: entries.value.length, truncated: true, files });
24428
24484
  }
@@ -25088,14 +25144,112 @@ var meta91 = {
25088
25144
  producesBytes: true
25089
25145
  };
25090
25146
 
25091
- // src/use-cases/commands/create-mail-draft.ts
25092
- var exports_create_mail_draft = {};
25093
- __export(exports_create_mail_draft, {
25147
+ // src/use-cases/commands/create-forward-draft.ts
25148
+ var exports_create_forward_draft = {};
25149
+ __export(exports_create_forward_draft, {
25094
25150
  schema: () => schema90,
25095
25151
  meta: () => meta92,
25096
25152
  execute: () => execute90
25097
25153
  });
25154
+
25155
+ // src/use-cases/commands/parse-recipients.ts
25156
+ var parseRecipients = (csv) => csv.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map((address) => ({ emailAddress: { address } }));
25157
+
25158
+ // src/use-cases/commands/create-forward-draft.ts
25098
25159
  var schema90 = exports_external.object({
25160
+ forwardMessageId: exports_external.string().min(1),
25161
+ toRecipients: exports_external.string().min(1),
25162
+ ccRecipients: exports_external.string().optional(),
25163
+ bodyContent: exports_external.string().min(1),
25164
+ subject: exports_external.string().optional()
25165
+ });
25166
+ var isUnsentDraft = (value) => typeof value === "object" && value !== null && ("id" in value) && typeof value.id === "string" && ("isDraft" in value) && value.isDraft === true;
25167
+ var execute90 = async (graph, params) => {
25168
+ const parsed = schema90.safeParse(params);
25169
+ if (!parsed.success)
25170
+ return err({
25171
+ type: "validation_error",
25172
+ message: formatZodError(parsed.error)
25173
+ });
25174
+ const { forwardMessageId, toRecipients, ccRecipients, bodyContent, subject } = parsed.data;
25175
+ const created = await graph.post(`/me/messages/${forwardMessageId}/createForward`, {
25176
+ comment: bodyContent,
25177
+ toRecipients: parseRecipients(toRecipients)
25178
+ });
25179
+ if (!created.ok)
25180
+ return created;
25181
+ if (!isUnsentDraft(created.value)) {
25182
+ return err({
25183
+ type: "api_error",
25184
+ status: 500,
25185
+ code: "not_an_unsent_draft",
25186
+ message: `createForward did not return an unsent draft for message ${forwardMessageId} - refusing to patch. Inspect the message id and retry.`
25187
+ });
25188
+ }
25189
+ const patch = {};
25190
+ if (ccRecipients)
25191
+ patch.ccRecipients = parseRecipients(ccRecipients);
25192
+ if (subject)
25193
+ patch.subject = subject;
25194
+ if (Object.keys(patch).length === 0)
25195
+ return created;
25196
+ return graph.patch(`/me/messages/${created.value.id}`, patch);
25197
+ };
25198
+ var meta92 = {
25199
+ summary: "Create an UNSENT forward draft of an existing message. POST /me/messages/{id}/createForward mints the draft (FW: subject, quoted original) with your comment placed above the quote and the recipients set, in one call. Redirects a thread to the right owner without leaving the CLI. The draft is saved in Drafts and can be reviewed, edited, and sent from any Outlook client; the CLI still cannot send.",
25200
+ category: "mail",
25201
+ graphMethod: "POST",
25202
+ graphPathTemplate: "/me/messages/{forward-message-id}/createForward (+ optional body-free PATCH for cc / subject)",
25203
+ graphDocsUrl: "https://learn.microsoft.com/en-us/graph/api/message-createforward",
25204
+ options: [
25205
+ {
25206
+ name: "forward-message-id",
25207
+ key: "forwardMessageId",
25208
+ required: true,
25209
+ aliases: [{ name: "id", key: "id" }],
25210
+ description: "The message being forwarded. Source from list-mail-folder-messages or search-mail-messages. Accepts `--id` as an alias.",
25211
+ argumentHint: { kind: "idOrName" }
25212
+ },
25213
+ {
25214
+ name: "to-recipients",
25215
+ key: "toRecipients",
25216
+ required: true,
25217
+ description: 'Comma-separated list of recipient email addresses to forward to (e.g. "alice@example.com,bob@example.com"). Required: a forward without a recipient is not actionable.'
25218
+ },
25219
+ {
25220
+ name: "cc-recipients",
25221
+ key: "ccRecipients",
25222
+ required: false,
25223
+ description: "Comma-separated list of CC recipient email addresses."
25224
+ },
25225
+ {
25226
+ name: "body-content",
25227
+ key: "bodyContent",
25228
+ required: true,
25229
+ description: "The comment text, placed above the quoted forwarded message by Graph."
25230
+ },
25231
+ {
25232
+ name: "subject",
25233
+ key: "subject",
25234
+ required: false,
25235
+ description: 'Optional subject override. Omit to keep the inherited "FW: ..." subject.'
25236
+ }
25237
+ ],
25238
+ example: 'ask-marcel-office create-forward-draft --forward-message-id "AAMkAD..." --to-recipients "bob@example.com" --body-content "Bob owns this now, forwarding for your action."',
25239
+ bodyTemplate: "POST { comment: '{body-content}', toRecipients: '{to-recipients}' } then optional PATCH { ccRecipients?: '{cc-recipients}', subject?: '{subject}' }",
25240
+ mutates: true,
25241
+ scopesRequired: ["Mail.ReadWrite"],
25242
+ responseShape: "The updated draft message object (or `{ ok: true }` when Graph answers 204): `{ id, subject, body, toRecipients, ccRecipients, isDraft: true, … }`. The `id` is the draft - update further with update-mail-draft, or open Outlook Drafts to review and send."
25243
+ };
25244
+
25245
+ // src/use-cases/commands/create-mail-draft.ts
25246
+ var exports_create_mail_draft = {};
25247
+ __export(exports_create_mail_draft, {
25248
+ schema: () => schema91,
25249
+ meta: () => meta93,
25250
+ execute: () => execute91
25251
+ });
25252
+ var schema91 = exports_external.object({
25099
25253
  subject: exports_external.string().min(1),
25100
25254
  bodyContent: exports_external.string().min(1),
25101
25255
  bodyContentType: exports_external.enum(["Text", "HTML"]).optional(),
@@ -25105,9 +25259,8 @@ var schema90 = exports_external.object({
25105
25259
  importance: exports_external.enum(["Low", "Normal", "High"]).optional(),
25106
25260
  mailFolderId: exports_external.string().optional()
25107
25261
  });
25108
- var parseRecipients = (csv) => csv.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map((address) => ({ emailAddress: { address } }));
25109
- var execute90 = async (graph, params) => {
25110
- const parsed = schema90.safeParse(params);
25262
+ var execute91 = async (graph, params) => {
25263
+ const parsed = schema91.safeParse(params);
25111
25264
  if (!parsed.success)
25112
25265
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25113
25266
  const { subject, bodyContent, bodyContentType, toRecipients, ccRecipients, bccRecipients, importance, mailFolderId } = parsed.data;
@@ -25128,7 +25281,7 @@ var execute90 = async (graph, params) => {
25128
25281
  const path = mailFolderId ? `/me/mailFolders/${mailFolderId}/messages` : "/me/messages";
25129
25282
  return graph.post(path, body);
25130
25283
  };
25131
- var meta92 = {
25284
+ var meta93 = {
25132
25285
  summary: "Create a new mail draft. POST /me/messages (or /me/mailFolders/{id}/messages when --mail-folder-id is set). The draft is saved in the Drafts folder (or the specified folder) and can be sent later via the Outlook client or Graph sendMail. Recipients are comma-separated email addresses. Returns the created message object with its id — use this id with update-mail-draft to modify the draft before sending.",
25133
25286
  category: "mail",
25134
25287
  graphMethod: "POST",
@@ -25197,44 +25350,44 @@ var meta92 = {
25197
25350
  // src/use-cases/commands/create-reply-draft.ts
25198
25351
  var exports_create_reply_draft = {};
25199
25352
  __export(exports_create_reply_draft, {
25200
- schema: () => schema91,
25201
- meta: () => meta93,
25202
- execute: () => execute91
25353
+ schema: () => schema92,
25354
+ meta: () => meta94,
25355
+ execute: () => execute92
25203
25356
  });
25204
- var schema91 = exports_external.object({
25357
+ var schema92 = exports_external.object({
25205
25358
  replyToMessageId: exports_external.string().min(1),
25206
25359
  bodyContent: exports_external.string().min(1),
25207
- bodyContentType: exports_external.enum(["Text", "HTML"]).optional(),
25208
25360
  subject: exports_external.string().optional()
25209
25361
  });
25210
- var isUnsentDraft = (value) => typeof value === "object" && value !== null && ("id" in value) && typeof value.id === "string" && ("isDraft" in value) && value.isDraft === true;
25211
- var execute91 = async (graph, params) => {
25212
- const parsed = schema91.safeParse(params);
25362
+ var isUnsentDraft2 = (value) => typeof value === "object" && value !== null && ("id" in value) && typeof value.id === "string" && ("isDraft" in value) && value.isDraft === true;
25363
+ var execute92 = async (graph, params) => {
25364
+ const parsed = schema92.safeParse(params);
25213
25365
  if (!parsed.success)
25214
25366
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25215
- const { replyToMessageId, bodyContent, bodyContentType, subject } = parsed.data;
25216
- const created = await graph.post(`/me/messages/${replyToMessageId}/createReplyAll`, {});
25367
+ const { replyToMessageId, bodyContent, subject } = parsed.data;
25368
+ const created = await graph.post(`/me/messages/${replyToMessageId}/createReplyAll`, { comment: bodyContent });
25217
25369
  if (!created.ok)
25218
25370
  return created;
25219
- if (!isUnsentDraft(created.value)) {
25371
+ if (!isUnsentDraft2(created.value)) {
25220
25372
  return err({
25221
25373
  type: "api_error",
25222
25374
  status: 500,
25375
+ code: "not_an_unsent_draft",
25223
25376
  message: `createReplyAll did not return an unsent draft for message ${replyToMessageId} - refusing to patch. Inspect the message id and retry.`
25224
25377
  });
25225
25378
  }
25226
- const patch = {
25227
- body: { contentType: bodyContentType ?? "Text", content: bodyContent }
25228
- };
25379
+ const patch = {};
25229
25380
  if (subject)
25230
25381
  patch.subject = subject;
25382
+ if (Object.keys(patch).length === 0)
25383
+ return created;
25231
25384
  return graph.patch(`/me/messages/${created.value.id}`, patch);
25232
25385
  };
25233
- var meta93 = {
25234
- summary: "Create an UNSENT reply-all draft threaded on an existing message. POST /me/messages/{id}/createReplyAll mints the draft (inherited recipients, RE: subject, quoted history), then PATCH places the reply body above the quote. Reply-all by design - dropping recipients is a deliberate act for the human in Outlook, not a default. The draft is saved in Drafts and can be reviewed, edited, and sent from any Outlook client; the CLI still cannot send.",
25386
+ var meta94 = {
25387
+ summary: "Create an UNSENT reply-all draft threaded on an existing message. POST /me/messages/{id}/createReplyAll mints the draft (inherited recipients, RE: subject, quoted history) with your reply text placed above the quote, in one call. Reply-all by design - dropping recipients is a deliberate act for the human in Outlook, not a default. The draft is saved in Drafts and can be reviewed, edited, and sent from any Outlook client; the CLI still cannot send.",
25235
25388
  category: "mail",
25236
25389
  graphMethod: "POST",
25237
- graphPathTemplate: "/me/messages/{reply-to-message-id}/createReplyAll (then PATCH the returned draft)",
25390
+ graphPathTemplate: "/me/messages/{reply-to-message-id}/createReplyAll (+ optional body-free PATCH for subject)",
25238
25391
  graphDocsUrl: "https://learn.microsoft.com/en-us/graph/api/message-createreplyall",
25239
25392
  options: [
25240
25393
  {
@@ -25249,14 +25402,7 @@ var meta93 = {
25249
25402
  name: "body-content",
25250
25403
  key: "bodyContent",
25251
25404
  required: true,
25252
- description: "The reply text, placed above the quoted history. Plain text by default; pass --body-content-type HTML for rich text."
25253
- },
25254
- {
25255
- name: "body-content-type",
25256
- key: "bodyContentType",
25257
- required: false,
25258
- description: "Reply body format: Text (default) or HTML.",
25259
- argumentHint: { kind: "magicValue", values: ["Text", "HTML"] }
25405
+ description: "The reply text, placed above the quoted history by Graph."
25260
25406
  },
25261
25407
  {
25262
25408
  name: "subject",
@@ -25266,7 +25412,7 @@ var meta93 = {
25266
25412
  }
25267
25413
  ],
25268
25414
  example: 'ask-marcel-office create-reply-draft --reply-to-message-id "AAMkAD..." --body-content "Confirmed for Concur, aligned with the group choice."',
25269
- bodyTemplate: "POST {} then PATCH { body: { contentType: '{body-content-type}', content: '{body-content}' }, subject?: '{subject}' }",
25415
+ bodyTemplate: "POST { comment: '{body-content}' } then optional PATCH { subject?: '{subject}' }",
25270
25416
  mutates: true,
25271
25417
  scopesRequired: ["Mail.ReadWrite"],
25272
25418
  responseShape: "The updated draft message object (or `{ ok: true }` when Graph answers 204): `{ id, subject, body, toRecipients, ccRecipients, isDraft: true, … }`. The `id` is the draft - update further with update-mail-draft, or open Outlook Drafts to review and send."
@@ -25275,11 +25421,11 @@ var meta93 = {
25275
25421
  // src/use-cases/commands/update-mail-draft.ts
25276
25422
  var exports_update_mail_draft = {};
25277
25423
  __export(exports_update_mail_draft, {
25278
- schema: () => schema92,
25279
- meta: () => meta94,
25280
- execute: () => execute92
25424
+ schema: () => schema93,
25425
+ meta: () => meta95,
25426
+ execute: () => execute93
25281
25427
  });
25282
- var schema92 = exports_external.object({
25428
+ var schema93 = exports_external.object({
25283
25429
  messageId: exports_external.string().min(1),
25284
25430
  subject: exports_external.string().optional(),
25285
25431
  bodyContent: exports_external.string().optional(),
@@ -25289,9 +25435,8 @@ var schema92 = exports_external.object({
25289
25435
  bccRecipients: exports_external.string().optional(),
25290
25436
  importance: exports_external.enum(["Low", "Normal", "High"]).optional()
25291
25437
  });
25292
- var parseRecipients2 = (csv) => csv.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map((address) => ({ emailAddress: { address } }));
25293
- var execute92 = async (graph, params) => {
25294
- const parsed = schema92.safeParse(params);
25438
+ var execute93 = async (graph, params) => {
25439
+ const parsed = schema93.safeParse(params);
25295
25440
  if (!parsed.success)
25296
25441
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25297
25442
  const { messageId, subject, bodyContent, bodyContentType, toRecipients, ccRecipients, bccRecipients, importance } = parsed.data;
@@ -25307,16 +25452,16 @@ var execute92 = async (graph, params) => {
25307
25452
  if (bodyContent !== undefined)
25308
25453
  body.body = { contentType: bodyContentType ?? "Text", content: bodyContent };
25309
25454
  if (toRecipients)
25310
- body.toRecipients = parseRecipients2(toRecipients);
25455
+ body.toRecipients = parseRecipients(toRecipients);
25311
25456
  if (ccRecipients)
25312
- body.ccRecipients = parseRecipients2(ccRecipients);
25457
+ body.ccRecipients = parseRecipients(ccRecipients);
25313
25458
  if (bccRecipients)
25314
- body.bccRecipients = parseRecipients2(bccRecipients);
25459
+ body.bccRecipients = parseRecipients(bccRecipients);
25315
25460
  if (importance)
25316
25461
  body.importance = importance;
25317
25462
  return graph.patch(`/me/messages/${messageId}`, body);
25318
25463
  };
25319
- var meta94 = {
25464
+ var meta95 = {
25320
25465
  summary: "Update an existing mail draft. PATCH /me/messages/{id} — modifies a draft created by create-mail-draft (or any existing draft in the Drafts folder). Only the fields you pass are updated; omitted fields are left unchanged. At least one field must be provided. Returns the updated message object. Use get-mail-message to verify the final state before sending.",
25321
25466
  category: "mail",
25322
25467
  graphMethod: "PATCH",
@@ -25386,17 +25531,17 @@ var meta94 = {
25386
25531
  // src/use-cases/commands/convert-drive-item-zip.ts
25387
25532
  var exports_convert_drive_item_zip = {};
25388
25533
  __export(exports_convert_drive_item_zip, {
25389
- schema: () => schema93,
25390
- meta: () => meta95,
25391
- execute: () => execute93
25534
+ schema: () => schema94,
25535
+ meta: () => meta96,
25536
+ execute: () => execute94
25392
25537
  });
25393
- var schema93 = exports_external.object({
25538
+ var schema94 = exports_external.object({
25394
25539
  driveId: exports_external.string().min(1),
25395
25540
  itemId: exports_external.string().min(1),
25396
25541
  includeMetadata: exports_external.enum(["true", "false"]).optional()
25397
25542
  });
25398
- var execute93 = async (graph, params) => {
25399
- const parsed = schema93.safeParse(params);
25543
+ var execute94 = async (graph, params) => {
25544
+ const parsed = schema94.safeParse(params);
25400
25545
  if (!parsed.success)
25401
25546
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25402
25547
  const { driveId, itemId } = parsed.data;
@@ -25406,7 +25551,7 @@ var execute93 = async (graph, params) => {
25406
25551
  return bytes;
25407
25552
  return convertZipArchive(bytes.value, includeMetadata);
25408
25553
  };
25409
- var meta95 = {
25554
+ var meta96 = {
25410
25555
  summary: "Unzip a `.zip` from a OneDrive / SharePoint item and convert every contained file in one call — so \"read the handover archive\" doesn't need a separate unzip + per-file conversion. Office files (docx/xlsx/pptx/odt/ods/odp and their macro-enabled / template variants) are converted to markdown via the local pipelines; plain-text entries (txt/md/csv/json/yaml/…) are decoded inline; legacy OLE .xls (sheetjs) and .doc (word-extractor, text only) are extracted; an Outlook .msg entry is rendered to markdown (headers + body, with its own attachments converted recursively); PDFs have their text layer extracted (text/plain); images, binaries, nested archives, legacy .ppt, and scanned/image-only PDFs (no text layer) are listed with a note (not unpacked) so one unsupported entry never fails the whole archive. Pass `--include-metadata true` to append each Office file's side-channel metadata block. Capped at 100 entries (the archive is buffered in memory); beyond that the response is flagged `truncated`.",
25411
25556
  category: "drive",
25412
25557
  graphMethod: "GET",
@@ -25435,16 +25580,17 @@ var meta95 = {
25435
25580
  // src/use-cases/commands/convert-local-file.ts
25436
25581
  var exports_convert_local_file = {};
25437
25582
  __export(exports_convert_local_file, {
25438
- schema: () => schema94,
25439
- meta: () => meta96,
25583
+ schema: () => schema95,
25584
+ meta: () => meta97,
25440
25585
  executeLocal: () => executeLocal,
25441
- execute: () => execute94
25586
+ execute: () => execute95
25442
25587
  });
25443
25588
  import { basename } from "node:path";
25444
- var schema94 = exports_external.object({
25589
+ var schema95 = exports_external.object({
25445
25590
  path: exports_external.string().min(1),
25446
25591
  includeMetadata: exports_external.enum(["true", "false"]).optional(),
25447
25592
  inlineImages: exports_external.enum(["true", "false"]).optional(),
25593
+ includeImages: exports_external.enum(["true", "false"]).optional(),
25448
25594
  maxCells: exports_external.string().regex(/^[1-9]\d*$/, "must be a positive integer").optional()
25449
25595
  });
25450
25596
  var LOCAL_HINTS = {
@@ -25454,12 +25600,13 @@ var LOCAL_HINTS = {
25454
25600
  generic: (ext) => `${ext} is not a convertible Office/text format. For formats Graph can render (rtf, …), upload the file to OneDrive and use \`download-drive-item-as-pdf\`.`
25455
25601
  };
25456
25602
  var executeLocal = async (fs, params) => {
25457
- const parsed = schema94.safeParse(params);
25603
+ const parsed = schema95.safeParse(params);
25458
25604
  if (!parsed.success)
25459
25605
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25460
25606
  const { path } = parsed.data;
25461
25607
  const includeMetadata = parsed.data.includeMetadata === "true";
25462
25608
  const inlineImages = parsed.data.inlineImages === "true";
25609
+ const includeImages = parsed.data.includeImages === "true";
25463
25610
  const maxCells = parsed.data.maxCells === undefined ? undefined : Number(parsed.data.maxCells);
25464
25611
  const bytes = await fs.readBytes(path);
25465
25612
  if (!bytes.ok) {
@@ -25469,15 +25616,15 @@ var executeLocal = async (fs, params) => {
25469
25616
  }
25470
25617
  const name = basename(path);
25471
25618
  if (extensionOf(name) === "zip")
25472
- return convertZipArchive(bytes.value, includeMetadata);
25619
+ return convertZipArchive(bytes.value, includeMetadata, includeImages);
25473
25620
  return bytesToMarkdown(bytes.value, name, { includeMetadata, inlineImages, maxCells }, LOCAL_HINTS);
25474
25621
  };
25475
- var execute94 = async (_graph, _params) => err({
25622
+ var execute95 = async (_graph, _params) => err({
25476
25623
  type: "api_error",
25477
25624
  status: 400,
25478
25625
  message: "convert-local-file reads the local filesystem, not Graph — call executeLocal(fs, params) with a FileSystem (the CLI wires this automatically)."
25479
25626
  });
25480
- var meta96 = {
25627
+ var meta97 = {
25481
25628
  summary: "Convert a file ON DISK to markdown — the only command that never calls Microsoft Graph (works offline, no login). Runs the same local pipelines as `download-drive-item-as-markdown`: docx (mammoth → turndown), xlsx (sheetjs tables, `--max-cells` OOM cap), pptx (per-slide text), odt/ods/odp, csv, pdf (text layer via unpdf), legacy OLE .xls / .doc, Outlook .msg (headers + body, attachments converted recursively), plain-text passthrough — and a `.zip` is unpacked with every contained file converted in one call (legacy GBK / CP437 entry names decoded, not mojibaked). What it canNOT do locally: convert TO pdf, and Loop/Fluid/Whiteboard sources — both need a Graph server round-trip (upload to OneDrive and use the drive-item siblings). Pass `--include-metadata true` for the Office side-channel metadata blocks; `--inline-images true` to embed docx images as base64 data URIs.",
25482
25629
  category: "meta",
25483
25630
  graphMethod: "GET",
@@ -25504,6 +25651,13 @@ var meta96 = {
25504
25651
  description: "Pass `--inline-images true` to embed a docx's images as base64 `data:` URIs. Default `false` — each image becomes an `[image: <alt>]` placeholder. No-op on non-docx sources.",
25505
25652
  argumentHint: { kind: "magicValue", values: ["true", "false"] }
25506
25653
  },
25654
+ {
25655
+ name: "include-images",
25656
+ key: "includeImages",
25657
+ required: false,
25658
+ description: "Pass `--include-images true` (a `.zip` only) to also extract each archive entry’s embedded images (docx/xlsx/pptx OOXML media parts, pdf page images) — every entry gains an `images: [{ path, contentType, sizeBytes, base64 }]` array (the same shape `extract-*-images` returns). Best-effort: an entry that carries no extractable images has no `images` key. Default `false`. Lets a caller OCR a secret pasted as a screenshot inside a zipped document.",
25659
+ argumentHint: { kind: "magicValue", values: ["true", "false"] }
25660
+ },
25507
25661
  {
25508
25662
  name: "max-cells",
25509
25663
  key: "maxCells",
@@ -25512,23 +25666,23 @@ var meta96 = {
25512
25666
  }
25513
25667
  ],
25514
25668
  example: "ask-marcel-office convert-local-file --path ./report.docx",
25515
- responseShape: '`{ contentType: "text/markdown" | "text/plain", size, text }` for a single file; `{ count, files: [{ path, contentType, size, text } | { path, note }] }` for a `.zip` (one entry per contained file, unsupported entries noted). A missing file returns api_error 404 with the path. Pair with the global `--output-path` to land the markdown on disk.',
25669
+ responseShape: '`{ contentType: "text/markdown" | "text/plain", size, text }` for a single file; `{ count, files: [{ path, contentType, size, text } | { path, note }] }` for a `.zip` (one entry per contained file, unsupported entries noted). With `--include-images true` each `.zip` entry also carries `images: [{ path, contentType, sizeBytes, base64 }]` when it has extractable embedded images. A missing file returns api_error 404 with the path. Pair with the global `--output-path` to land the markdown on disk.',
25516
25670
  producesBytes: true
25517
25671
  };
25518
25672
 
25519
25673
  // src/use-cases/commands/extract-local-file-images.ts
25520
25674
  var exports_extract_local_file_images = {};
25521
25675
  __export(exports_extract_local_file_images, {
25522
- schema: () => schema95,
25523
- meta: () => meta97,
25676
+ schema: () => schema96,
25677
+ meta: () => meta98,
25524
25678
  executeLocal: () => executeLocal2,
25525
- execute: () => execute95
25679
+ execute: () => execute96
25526
25680
  });
25527
25681
  import { basename as basename2 } from "node:path";
25528
- var schema95 = exports_external.object({ path: exports_external.string().min(1) });
25682
+ var schema96 = exports_external.object({ path: exports_external.string().min(1) });
25529
25683
  var FETCH_HINT3 = "The file is already on disk — read it directly with a vision-capable model, or convert its body with `convert-local-file`.";
25530
25684
  var executeLocal2 = async (fs, params) => {
25531
- const parsed = schema95.safeParse(params);
25685
+ const parsed = schema96.safeParse(params);
25532
25686
  if (!parsed.success)
25533
25687
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25534
25688
  const { path } = parsed.data;
@@ -25540,12 +25694,12 @@ var executeLocal2 = async (fs, params) => {
25540
25694
  }
25541
25695
  return extractImagesFromBytes(bytes.value, basename2(path), FETCH_HINT3);
25542
25696
  };
25543
- var execute95 = async (_graph, _params) => err({
25697
+ var execute96 = async (_graph, _params) => err({
25544
25698
  type: "api_error",
25545
25699
  status: 400,
25546
25700
  message: "extract-local-file-images reads the local filesystem, not Graph — call executeLocal(fs, params) with a FileSystem (the CLI wires this automatically)."
25547
25701
  });
25548
- var meta97 = {
25702
+ var meta98 = {
25549
25703
  summary: "Extract the embedded images from a file ON DISK — the local sibling of `extract-drive-item-images`, and like `convert-local-file` it never calls Microsoft Graph (works offline, no login). Same per-extension dispatch: docx / xlsx / pptx (and their macro-enabled / template variants) have their OOXML media parts read directly (png/jpg/gif/bmp/tiff/webp/svg — full-resolution originals, including images on hidden slides); a pdf is walked page by page via unpdf with each painted image re-encoded as PNG. Two flows only this command completes: a Graph-rendered PDF saved locally (legacy `.ppt` → `download-drive-item-as-pdf` with the global output-path flag → this command pulls the slide images for OCR), and Office files unpacked from a local archive. Pair with the global output-dir flag to write every image to a folder; otherwise the bytes ride back base64-encoded. Any other extension returns a 415 naming the local ways out.",
25550
25704
  category: "meta",
25551
25705
  graphMethod: "GET",
@@ -25567,17 +25721,17 @@ var meta97 = {
25567
25721
  // src/use-cases/commands/convert-mail-attachment-zip.ts
25568
25722
  var exports_convert_mail_attachment_zip = {};
25569
25723
  __export(exports_convert_mail_attachment_zip, {
25570
- schema: () => schema96,
25571
- meta: () => meta98,
25572
- execute: () => execute96
25724
+ schema: () => schema97,
25725
+ meta: () => meta99,
25726
+ execute: () => execute97
25573
25727
  });
25574
- var schema96 = exports_external.object({
25728
+ var schema97 = exports_external.object({
25575
25729
  messageId: exports_external.string().min(1),
25576
25730
  attachmentId: exports_external.string().min(1),
25577
25731
  includeMetadata: exports_external.enum(["true", "false"]).optional()
25578
25732
  });
25579
- var execute96 = async (graph, params) => {
25580
- const parsed = schema96.safeParse(params);
25733
+ var execute97 = async (graph, params) => {
25734
+ const parsed = schema97.safeParse(params);
25581
25735
  if (!parsed.success)
25582
25736
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25583
25737
  const { messageId, attachmentId } = parsed.data;
@@ -25600,7 +25754,7 @@ var execute96 = async (graph, params) => {
25600
25754
  }
25601
25755
  return convertZipArchive(base64ToBytes(contentBytes), includeMetadata);
25602
25756
  };
25603
- var meta98 = {
25757
+ var meta99 = {
25604
25758
  summary: "Unzip a `.zip` Outlook mail attachment and convert every contained file in one call — the mail-side mirror of `convert-drive-item-zip`, so reading a zipped vendor deck doesn't need `get-mail-attachment` + manual `unzip` + per-file conversion. Pulls the fileAttachment bytes, unzips them (legacy GBK / CP437 entry names — Chinese vendor archives written by WinRAR / Windows Explorer — are decoded correctly, not mojibaked), and runs each file through the local pipelines: Office files (docx/xlsx/pptx/odt/ods/odp and macro-enabled / template variants) → markdown; plain-text entries decoded inline; legacy OLE .xls (sheetjs) and .doc (word-extractor, text only) extracted; an inner Outlook .msg rendered; PDFs have their text layer extracted; images, binaries, nested archives, legacy .ppt, and scanned/image-only PDFs are listed with a note (not unpacked) so one unsupported entry never fails the whole archive. Pass `--include-metadata true` to append each Office file's side-channel metadata block. Capped at 100 entries; beyond that the response is flagged `truncated`. itemAttachment / referenceAttachment are rejected (no inline zip payload).",
25605
25759
  category: "mail",
25606
25760
  graphMethod: "GET",
@@ -25624,13 +25778,13 @@ var meta98 = {
25624
25778
  // src/use-cases/commands/extract-sharepoint-links-in-documents.ts
25625
25779
  var exports_extract_sharepoint_links_in_documents = {};
25626
25780
  __export(exports_extract_sharepoint_links_in_documents, {
25627
- schema: () => schema97,
25628
- meta: () => meta99,
25629
- execute: () => execute97
25781
+ schema: () => schema98,
25782
+ meta: () => meta100,
25783
+ execute: () => execute98
25630
25784
  });
25631
- var schema97 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
25632
- var execute97 = async (graph, params) => {
25633
- const parsed = schema97.safeParse(params);
25785
+ var schema98 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
25786
+ var execute98 = async (graph, params) => {
25787
+ const parsed = schema98.safeParse(params);
25634
25788
  if (!parsed.success)
25635
25789
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25636
25790
  const { driveId, itemId } = parsed.data;
@@ -25652,7 +25806,7 @@ var execute97 = async (graph, params) => {
25652
25806
  const { links, truncated, skippedCount } = await resolveSharepointUrls(graph, extractSharepointUrls(haystack));
25653
25807
  return ok({ driveId, itemId, links, truncated, skippedCount });
25654
25808
  };
25655
- var meta99 = {
25809
+ var meta100 = {
25656
25810
  summary: 'Find every `*.sharepoint.com` URL embedded in a Word / Excel / PowerPoint or OpenDocument file on OneDrive or SharePoint and resolve each one to its driveItem (driveId, itemId, name, webUrl) so the agent can feed those into `download-drive-item-as-pdf` / `-as-markdown` etc. The document sibling of `extract-sharepoint-links-in-mail`. For OOXML (.docx/.xlsx/.pptx) it reads external hyperlinks from the package’s relationship parts (`_rels/*.rels`, `TargetMode="External"`); for OpenDocument (.odt/.ods/.odp) it reads the inline `xlink:href` links in content.xml / styles.xml — either way it catches links wherever they live (body text, headers/footers, cell formulas, slide shapes). Read-only — no conversion happens here. Capped at 25 unique URLs per call (returns `truncated: true` and `skippedCount` when there are more); duplicates are deduplicated; per-link errors are captured inside each entry instead of failing the whole call. Non-zip inputs (pdf/images) return an api_error.',
25657
25811
  category: "drive",
25658
25812
  graphMethod: "GET",
@@ -25679,13 +25833,13 @@ var meta99 = {
25679
25833
  // src/use-cases/commands/extract-sharepoint-links-in-mail.ts
25680
25834
  var exports_extract_sharepoint_links_in_mail = {};
25681
25835
  __export(exports_extract_sharepoint_links_in_mail, {
25682
- schema: () => schema98,
25683
- meta: () => meta100,
25684
- execute: () => execute98
25836
+ schema: () => schema99,
25837
+ meta: () => meta101,
25838
+ execute: () => execute99
25685
25839
  });
25686
- var schema98 = exports_external.object({ messageId: exports_external.string().min(1) });
25687
- var execute98 = async (graph, params) => {
25688
- const parsed = schema98.safeParse(params);
25840
+ var schema99 = exports_external.object({ messageId: exports_external.string().min(1) });
25841
+ var execute99 = async (graph, params) => {
25842
+ const parsed = schema99.safeParse(params);
25689
25843
  if (!parsed.success)
25690
25844
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25691
25845
  const { messageId } = parsed.data;
@@ -25703,7 +25857,7 @@ var execute98 = async (graph, params) => {
25703
25857
  skippedCount
25704
25858
  });
25705
25859
  };
25706
- var meta100 = {
25860
+ var meta101 = {
25707
25861
  summary: "Find every `*.sharepoint.com` URL in the body of a single Outlook email and resolve each one to its driveItem (driveId, itemId, name, webUrl) so the agent can feed those into `download-drive-item-as-pdf` / `-as-markdown` etc. Read-only — no conversion happens here. Capped at 25 unique URLs per call to bound fan-out (returns `truncated: true` and `skippedCount` when the body has more); duplicate URLs are deduplicated. Per-link errors are captured inside each entry instead of failing the whole call.",
25708
25862
  category: "mail",
25709
25863
  graphMethod: "GET",
@@ -25725,15 +25879,15 @@ var meta100 = {
25725
25879
  // src/use-cases/commands/list-chats.ts
25726
25880
  var exports_list_chats = {};
25727
25881
  __export(exports_list_chats, {
25728
- schema: () => schema99,
25729
- meta: () => meta101,
25730
- execute: () => execute99
25882
+ schema: () => schema100,
25883
+ meta: () => meta102,
25884
+ execute: () => execute100
25731
25885
  });
25732
25886
  var DEFAULT_SELECT7 = "id,topic,chatType,createdDateTime,lastUpdatedDateTime";
25733
25887
  var baseSchema49 = exports_external.object({}).strict();
25734
25888
  var CHATS_ODATA_KEYS = ["top", "skip", "select", "filter"];
25735
- var { execute: execute99, schema: schema99 } = buildElevatedPickODataListCommand(() => "/me/chats", baseSchema49, CHATS_ODATA_KEYS, { defaultSelect: DEFAULT_SELECT7 });
25736
- var meta101 = {
25889
+ var { execute: execute100, schema: schema100 } = buildElevatedPickODataListCommand(() => "/me/chats", baseSchema49, CHATS_ODATA_KEYS, { defaultSelect: DEFAULT_SELECT7 });
25890
+ var meta102 = {
25737
25891
  summary: "List the signed-in user's Microsoft Teams chats (1:1, group, and meeting chats). The CLI ships a slim default `--select=id,topic,chatType,createdDateTime,lastUpdatedDateTime`; pass `--select id,topic,webUrl,...` to widen. Returns chat metadata only — reading chat *messages* needs `Chat.Read*` which neither token grants. Requires the M365ChatClient elevated token captured at login (the basic Teams web client token lacks `Chat.ReadBasic`). Graph rejects `$orderby` and hangs on `$expand` for this endpoint, so the CLI advertises only the subset Graph honours (`--top`, `--skip`, `--select`, `--filter`).",
25738
25892
  category: "chats",
25739
25893
  graphMethod: "GET",
@@ -25749,14 +25903,14 @@ var meta101 = {
25749
25903
  // src/use-cases/commands/get-chat.ts
25750
25904
  var exports_get_chat = {};
25751
25905
  __export(exports_get_chat, {
25752
- schema: () => schema100,
25753
- meta: () => meta102,
25754
- execute: () => execute100
25906
+ schema: () => schema101,
25907
+ meta: () => meta103,
25908
+ execute: () => execute101
25755
25909
  });
25756
25910
  var DEFAULT_SELECT8 = "id,topic,chatType,createdDateTime,lastUpdatedDateTime";
25757
25911
  var baseSchema50 = exports_external.object({ chatId: exports_external.string().min(1) });
25758
- var { execute: execute100, schema: schema100 } = buildElevatedSelectableCommand((p) => `/chats/${p.chatId}`, baseSchema50, { defaultSelect: DEFAULT_SELECT8 });
25759
- var meta102 = {
25912
+ var { execute: execute101, schema: schema101 } = buildElevatedSelectableCommand((p) => `/chats/${p.chatId}`, baseSchema50, { defaultSelect: DEFAULT_SELECT8 });
25913
+ var meta103 = {
25760
25914
  summary: "Return metadata for a single Microsoft Teams chat (1:1, group, or meeting). The CLI ships a slim default `--select=id,topic,chatType,createdDateTime,lastUpdatedDateTime`; pass `--select id,topic,webUrl,onlineMeetingInfo` (or any other comma-separated field list) to widen. Pass `--expand members` to inline membership. Returns metadata only — not the messages (which need `Chat.Read*`). Requires the M365ChatClient elevated token captured at login (the basic Teams web client token lacks `Chat.ReadBasic`).",
25761
25915
  category: "chats",
25762
25916
  graphMethod: "GET",
@@ -25780,17 +25934,17 @@ var meta102 = {
25780
25934
  // src/use-cases/commands/list-teams-chats-with-messages.ts
25781
25935
  var exports_list_teams_chats_with_messages = {};
25782
25936
  __export(exports_list_teams_chats_with_messages, {
25783
- schema: () => schema101,
25784
- meta: () => meta103,
25785
- execute: () => execute101
25937
+ schema: () => schema102,
25938
+ meta: () => meta104,
25939
+ execute: () => execute102
25786
25940
  });
25787
- var schema101 = exports_external.object({
25941
+ var schema102 = exports_external.object({
25788
25942
  pageSize: exports_external.string().regex(/^[1-9]\d*$/, "must be a positive integer").optional(),
25789
25943
  continuationToken: exports_external.string().min(1).optional()
25790
25944
  });
25791
25945
  var QUERY_BASE = "enableMembershipSummary=true&supportsAdditionalSystemGeneratedFolders=true&supportsSliceItems=true&enableEngageCommunities=false";
25792
- var execute101 = async (graph, params) => {
25793
- const parsed = schema101.safeParse(params);
25946
+ var execute102 = async (graph, params) => {
25947
+ const parsed = schema102.safeParse(params);
25794
25948
  if (!parsed.success)
25795
25949
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25796
25950
  const pageSize = parsed.data.pageSize ?? "100";
@@ -25799,7 +25953,7 @@ var execute101 = async (graph, params) => {
25799
25953
  qs.set("continuationToken", parsed.data.continuationToken);
25800
25954
  return graph.teamsChat(`/api/v3/teams/users/me/chats?${qs.toString()}&${QUERY_BASE}`);
25801
25955
  };
25802
- var meta103 = {
25956
+ var meta104 = {
25803
25957
  summary: "List the signed-in user's Microsoft Teams chats with the last message body inlined per chat. Uses the chatsvcagg-audience bearer captured at login. Paginated via `continuationToken` (default page size 100; pass the response's `continuationToken` back as `--continuation-token` while `hasMoreData: true`). **Best-effort, may break on Microsoft client updates**: the chat substrate is not part of the public Microsoft Graph API; Microsoft can change route shapes without notice. Caller Graph scopes do NOT matter here; the substrate server gates access on the appid + identity, not on Graph scopes.",
25804
25958
  category: "chats",
25805
25959
  needsSubstrateToken: true,
@@ -25828,21 +25982,21 @@ var meta103 = {
25828
25982
  // src/use-cases/commands/list-teams-chat-messages.ts
25829
25983
  var exports_list_teams_chat_messages = {};
25830
25984
  __export(exports_list_teams_chat_messages, {
25831
- schema: () => schema102,
25832
- meta: () => meta104,
25833
- execute: () => execute102
25985
+ schema: () => schema103,
25986
+ meta: () => meta105,
25987
+ execute: () => execute103
25834
25988
  });
25835
- var schema102 = exports_external.object({
25989
+ var schema103 = exports_external.object({
25836
25990
  chatId: exports_external.string().min(1)
25837
25991
  });
25838
- var execute102 = async (graph, params) => {
25839
- const parsed = schema102.safeParse(params);
25992
+ var execute103 = async (graph, params) => {
25993
+ const parsed = schema103.safeParse(params);
25840
25994
  if (!parsed.success)
25841
25995
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25842
25996
  const { chatId } = parsed.data;
25843
25997
  return graph.teamsChat(`/api/v1/chats/${encodeURIComponent(chatId)}/messages`);
25844
25998
  };
25845
- var meta104 = {
25999
+ var meta105 = {
25846
26000
  summary: "List the most recent messages in a single Microsoft Teams chat via the chat substrate. Companion to `list-teams-chats-with-messages` when the inlined `lastMessage` isn't deep enough. Uses the chatsvcagg-audience bearer captured at login. **Best-effort, may break on Microsoft client updates** — the chat substrate is not in the public Microsoft Graph API. **No pagination**: the route caps at the 200 most recent messages per chat and the CLI cannot reach older history (Teams web itself uses WebSockets for scrollback, and the official `Chat.Read` Graph scope that would enable paginated reads is outside the appid's scope ceiling).",
25847
26001
  category: "chats",
25848
26002
  needsSubstrateToken: true,
@@ -25866,11 +26020,11 @@ var meta104 = {
25866
26020
  // src/use-cases/commands/list-teams-chat-history.ts
25867
26021
  var exports_list_teams_chat_history = {};
25868
26022
  __export(exports_list_teams_chat_history, {
25869
- schema: () => schema103,
25870
- meta: () => meta105,
25871
- execute: () => execute103
26023
+ schema: () => schema104,
26024
+ meta: () => meta106,
26025
+ execute: () => execute104
25872
26026
  });
25873
- var schema103 = exports_external.object({
26027
+ var schema104 = exports_external.object({
25874
26028
  chatId: exports_external.string().min(1),
25875
26029
  syncState: exports_external.url().optional(),
25876
26030
  pageSize: exports_external.string().regex(/^[1-9]\d*$/, "must be a positive integer").optional(),
@@ -25902,8 +26056,8 @@ var toRelativePath = (absoluteUrl) => {
25902
26056
  throw new Error(`unexpected syncState URL shape: ${absoluteUrl}`);
25903
26057
  return m[1];
25904
26058
  };
25905
- var execute103 = async (graph, params) => {
25906
- const parsed = schema103.safeParse(params);
26059
+ var execute104 = async (graph, params) => {
26060
+ const parsed = schema104.safeParse(params);
25907
26061
  if (!parsed.success)
25908
26062
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
25909
26063
  const { chatId } = parsed.data;
@@ -25940,7 +26094,7 @@ var execute103 = async (graph, params) => {
25940
26094
  projection: fullMode ? "full" : "slim"
25941
26095
  });
25942
26096
  };
25943
- var meta105 = {
26097
+ var meta106 = {
25944
26098
  summary: "Deep read of a Microsoft Teams chat's message history via the IC3 substrate (`teams.microsoft.com/api/chatsvc/<region>/v1/...`). Unlike `list-teams-chat-messages` (which caps at the 200 most recent messages with no working pagination cursor), this command follows the server-provided `_metadata.syncState` URL backward through history, fetching up to `--page-size` * `--max-pages` messages per invocation (default 200 * 20 = 4000). Uses the IC3-audience bearer captured at login (same Teams web client identity as the basic Teams token). The CLI ships a slim default projection — each message is reduced to `id, sequenceId, composetime, originalarrivaltime, messagetype, from, imdisplayname, content` and `content` is truncated to 4096 chars (with `truncated: true` and `originalContentChars` set on the affected entries). Pass `--full true` to opt out of projection and truncation; pass `--max-content-chars N` to override the truncation cap. **Best-effort, may break on Microsoft client updates** — the IC3 substrate is not in the public Microsoft Graph API. To page beyond `--max-pages`, take the response's `nextSyncState` and pass it back as `--sync-state` on the next call.",
25945
26099
  category: "chats",
25946
26100
  needsSubstrateToken: true,
@@ -25994,22 +26148,22 @@ var meta105 = {
25994
26148
  // src/use-cases/commands/get-teams-chat-message.ts
25995
26149
  var exports_get_teams_chat_message = {};
25996
26150
  __export(exports_get_teams_chat_message, {
25997
- schema: () => schema104,
25998
- meta: () => meta106,
25999
- execute: () => execute104
26151
+ schema: () => schema105,
26152
+ meta: () => meta107,
26153
+ execute: () => execute105
26000
26154
  });
26001
- var schema104 = exports_external.object({
26155
+ var schema105 = exports_external.object({
26002
26156
  chatId: exports_external.string().min(1),
26003
26157
  messageId: exports_external.string().min(1)
26004
26158
  });
26005
- var execute104 = async (graph, params) => {
26006
- const parsed = schema104.safeParse(params);
26159
+ var execute105 = async (graph, params) => {
26160
+ const parsed = schema105.safeParse(params);
26007
26161
  if (!parsed.success)
26008
26162
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26009
26163
  const { chatId, messageId } = parsed.data;
26010
26164
  return graph.teamsChat(`/api/v1/chats/${encodeURIComponent(chatId)}/messages/${encodeURIComponent(messageId)}`);
26011
26165
  };
26012
- var meta106 = {
26166
+ var meta107 = {
26013
26167
  summary: "Return a single Microsoft Teams chat message by its id via the chat substrate. Uses the chatsvcagg-audience bearer captured at login (same identity as the basic Teams token, different audience). **Best-effort, may break on Microsoft client updates** — the chat substrate is not in the public Microsoft Graph API. Source the chat-id + message-id via `list-teams-chats-with-messages` or `list-teams-chat-messages`.",
26014
26168
  category: "chats",
26015
26169
  needsSubstrateToken: true,
@@ -26028,9 +26182,9 @@ var meta106 = {
26028
26182
  // src/use-cases/commands/resolve-teams-link.ts
26029
26183
  var exports_resolve_teams_link = {};
26030
26184
  __export(exports_resolve_teams_link, {
26031
- schema: () => schema105,
26032
- meta: () => meta107,
26033
- execute: () => execute105
26185
+ schema: () => schema106,
26186
+ meta: () => meta108,
26187
+ execute: () => execute106
26034
26188
  });
26035
26189
 
26036
26190
  // src/use-cases/commands/link-shape.ts
@@ -26057,7 +26211,7 @@ var detectSiblingResolver = (raw) => {
26057
26211
  };
26058
26212
 
26059
26213
  // src/use-cases/commands/resolve-teams-link.ts
26060
- var schema105 = exports_external.object({
26214
+ var schema106 = exports_external.object({
26061
26215
  url: exports_external.url()
26062
26216
  });
26063
26217
  var PREFIX2 = "https://teams.microsoft.com/l/message/";
@@ -26093,8 +26247,8 @@ var parse5 = (raw) => {
26093
26247
  ...optional2
26094
26248
  };
26095
26249
  };
26096
- var execute105 = async (_graph, params) => {
26097
- const parsed = schema105.safeParse(params);
26250
+ var execute106 = async (_graph, params) => {
26251
+ const parsed = schema106.safeParse(params);
26098
26252
  if (!parsed.success)
26099
26253
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26100
26254
  const sibling = detectSiblingResolver(parsed.data.url);
@@ -26128,7 +26282,7 @@ var execute105 = async (_graph, params) => {
26128
26282
  }
26129
26283
  return ok(resolved);
26130
26284
  };
26131
- var meta107 = {
26285
+ var meta108 = {
26132
26286
  summary: "Parse a Microsoft Teams `Copy link` URL (the share link emitted by the message context menu in Teams) into its `chatId` + `messageId` components. Pure transformation — no Graph call. Pipe the result into `get-teams-chat-message` to fetch the message body, or into `list-teams-chat-history` to read the chat that contains it.",
26133
26287
  category: "chats",
26134
26288
  graphMethod: "GET",
@@ -26149,11 +26303,11 @@ var meta107 = {
26149
26303
  // src/use-cases/commands/resolve-mail-link.ts
26150
26304
  var exports_resolve_mail_link = {};
26151
26305
  __export(exports_resolve_mail_link, {
26152
- schema: () => schema106,
26153
- meta: () => meta108,
26154
- execute: () => execute106
26306
+ schema: () => schema107,
26307
+ meta: () => meta109,
26308
+ execute: () => execute107
26155
26309
  });
26156
- var schema106 = exports_external.object({
26310
+ var schema107 = exports_external.object({
26157
26311
  url: exports_external.url()
26158
26312
  });
26159
26313
  var OUTLOOK_HOSTS2 = ["outlook.office.com", "outlook.office365.com", "outlook.live.com"];
@@ -26199,8 +26353,8 @@ var parse6 = (raw) => {
26199
26353
  return { kind: "ok", value: { messageId: decodeURIComponent(pathId) } };
26200
26354
  return { kind: "unknown" };
26201
26355
  };
26202
- var execute106 = async (_graph, params) => {
26203
- const parsed = schema106.safeParse(params);
26356
+ var execute107 = async (_graph, params) => {
26357
+ const parsed = schema107.safeParse(params);
26204
26358
  if (!parsed.success)
26205
26359
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26206
26360
  const outcome = parse6(parsed.data.url);
@@ -26225,7 +26379,7 @@ var execute106 = async (_graph, params) => {
26225
26379
  message: `--url: not an Outlook mail link. Expected shapes: \`https://outlook.office.com/owa/?itemid=AAMkA...\`, \`https://outlook.office.com/mail/inbox/id/AAMkA...\`, or \`https://outlook.office.com/mail/AAMkA...\`. Hosts accepted: ${OUTLOOK_HOSTS2.join(", ")}.`
26226
26380
  });
26227
26381
  };
26228
- var meta108 = {
26382
+ var meta109 = {
26229
26383
  summary: 'Parse a Microsoft Outlook web mail link (the URL emitted by the "Copy link" / address-bar share of an email) into its `messageId`. Pure transformation — no Graph call. Pipe the result into `get-mail-message` to fetch the body, or `convert-mail-to-markdown` to render it. For Outlook calendar links use `resolve-calendar-link` instead — this command rejects them with a pointer.',
26230
26384
  category: "mail",
26231
26385
  graphMethod: "GET",
@@ -26246,11 +26400,11 @@ var meta108 = {
26246
26400
  // src/use-cases/commands/resolve-drive-share-link.ts
26247
26401
  var exports_resolve_drive_share_link = {};
26248
26402
  __export(exports_resolve_drive_share_link, {
26249
- schema: () => schema107,
26250
- meta: () => meta109,
26251
- execute: () => execute107
26403
+ schema: () => schema108,
26404
+ meta: () => meta110,
26405
+ execute: () => execute108
26252
26406
  });
26253
- var schema107 = exports_external.object({
26407
+ var schema108 = exports_external.object({
26254
26408
  url: exports_external.url()
26255
26409
  });
26256
26410
  var ACCEPTED_HOST_PATTERNS = [
@@ -26269,8 +26423,8 @@ var parse7 = (raw) => {
26269
26423
  originalUrl: raw
26270
26424
  };
26271
26425
  };
26272
- var execute107 = async (_graph, params) => {
26273
- const parsed = schema107.safeParse(params);
26426
+ var execute108 = async (_graph, params) => {
26427
+ const parsed = schema108.safeParse(params);
26274
26428
  if (!parsed.success)
26275
26429
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26276
26430
  const sibling = detectSiblingResolver(parsed.data.url);
@@ -26304,7 +26458,7 @@ var execute107 = async (_graph, params) => {
26304
26458
  }
26305
26459
  return ok(resolved);
26306
26460
  };
26307
- var meta109 = {
26461
+ var meta110 = {
26308
26462
  summary: "Encode a OneDrive / SharePoint sharing URL into the Graph `/shares/{token}` share token (`u!<base64url>` per [shares-get](https://learn.microsoft.com/en-us/graph/api/shares-get)). Pure transformation — no Graph call. Pipe the returned `graphPath` (`/shares/{token}/driveItem`) into a sibling lookup (`get-drive-item`, `download-drive-item-content`, `convert-mail-attachment-to-pdf`, etc.) once the file has been resolved to a `driveItem`. Accepts any `*.sharepoint.com` URL (tenant + `*-my.sharepoint.com` personal OneDrive) and Microsoft's short-link host `1drv.ms`.",
26309
26463
  category: "drive",
26310
26464
  graphMethod: "GET",
@@ -26325,11 +26479,11 @@ var meta109 = {
26325
26479
  // src/use-cases/commands/resolve-calendar-link.ts
26326
26480
  var exports_resolve_calendar_link = {};
26327
26481
  __export(exports_resolve_calendar_link, {
26328
- schema: () => schema108,
26329
- meta: () => meta110,
26330
- execute: () => execute108
26482
+ schema: () => schema109,
26483
+ meta: () => meta111,
26484
+ execute: () => execute109
26331
26485
  });
26332
- var schema108 = exports_external.object({
26486
+ var schema109 = exports_external.object({
26333
26487
  url: exports_external.url()
26334
26488
  });
26335
26489
  var OUTLOOK_HOSTS3 = ["outlook.office.com", "outlook.office365.com", "outlook.live.com"];
@@ -26371,8 +26525,8 @@ var parse8 = (raw) => {
26371
26525
  return { kind: "mail" };
26372
26526
  return { kind: "unknown" };
26373
26527
  };
26374
- var execute108 = async (_graph, params) => {
26375
- const parsed = schema108.safeParse(params);
26528
+ var execute109 = async (_graph, params) => {
26529
+ const parsed = schema109.safeParse(params);
26376
26530
  if (!parsed.success)
26377
26531
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26378
26532
  const outcome = parse8(parsed.data.url);
@@ -26390,7 +26544,7 @@ var execute108 = async (_graph, params) => {
26390
26544
  message: `--url: not an Outlook calendar item link. Expected shapes: \`https://outlook.office.com/calendar/item/AAMkA...\` (path-style), or \`https://outlook.office.com/owa/?itemid=AAMkA...&path=/calendar/item\` (OWA query). Hosts accepted: ${OUTLOOK_HOSTS3.join(", ")}.`
26391
26545
  });
26392
26546
  };
26393
- var meta110 = {
26547
+ var meta111 = {
26394
26548
  summary: 'Parse a Microsoft Outlook calendar item link (the URL emitted by the "Copy link" / share action on a calendar event) into its `eventId`. Pure transformation — no Graph call. Pipe the result into `get-calendar-event` to fetch the event body. For Outlook mail message links use `resolve-mail-link` instead — this command rejects them with a pointer.',
26395
26549
  category: "calendar",
26396
26550
  graphMethod: "GET",
@@ -26411,11 +26565,11 @@ var meta110 = {
26411
26565
  // src/use-cases/commands/find-chats-with-user.ts
26412
26566
  var exports_find_chats_with_user = {};
26413
26567
  __export(exports_find_chats_with_user, {
26414
- schema: () => schema109,
26415
- meta: () => meta111,
26416
- execute: () => execute109
26568
+ schema: () => schema110,
26569
+ meta: () => meta112,
26570
+ execute: () => execute110
26417
26571
  });
26418
- var schema109 = exports_external.object({
26572
+ var schema110 = exports_external.object({
26419
26573
  name: exports_external.string().min(1),
26420
26574
  maxPages: exports_external.string().regex(/^[1-9]\d*$/, "must be a positive integer").optional(),
26421
26575
  pageSize: exports_external.string().regex(/^[1-9]\d*$/, "must be a positive integer").optional()
@@ -26532,8 +26686,8 @@ var hydrateBareDirect = async (graph, queryFolded, bareUnmatched, matched) => {
26532
26686
  return { chatsHydrated: direct.length, unresolvedMemberCount };
26533
26687
  };
26534
26688
  var HINT2 = "No chat member matched by name, but at least one chat has a cross-tenant member the Teams roster left unresolved — an externally-homed counterpart often appears only as a bare object-id. Direct 1:1 chats were deep-probed; members in group/meeting chats were not. Retry searching by their object-id (pass it as `--name <object-id>`), or, if you have the chat URL, read it directly with `get-chat` / `list-teams-chat-messages --chat-id 19:<their-oid>_<your-oid>@unq.gbl.spaces`.";
26535
- var execute109 = async (graph, params) => {
26536
- const parsed = schema109.safeParse(params);
26689
+ var execute110 = async (graph, params) => {
26690
+ const parsed = schema110.safeParse(params);
26537
26691
  if (!parsed.success)
26538
26692
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26539
26693
  const queryFolded = fold(parsed.data.name);
@@ -26557,7 +26711,7 @@ var execute109 = async (graph, params) => {
26557
26711
  ...matched.length === 0 && unresolvedMemberCount > 0 ? { hint: HINT2 } : {}
26558
26712
  });
26559
26713
  };
26560
- var meta111 = {
26714
+ var meta112 = {
26561
26715
  summary: 'Find every Microsoft Teams chat that includes a member matching `--name` (substring search across display-name, email, given-name, surname, MRI, and object-id). Both sides are Unicode-folded (NFD + combining-mark strip) and lowercased before comparison, so `--name Alex` matches `Alex Kim` AND `alex.kim@example.com` AND `ALEX` — important because a dual-identity user often carries the accented display-name on one identity and the un-accented email on the other. Walks the paginated chat-list substrate up to `--max-pages` and returns matching chats with their `matchedMembers[]`. Collapses the canonical "all conversations with person X" workflow into a single call AND surfaces dual-identity people (e.g. someone with both an org MRI and a guest-tenant MRI). Cross-tenant resolution: the summary roster returns externally-homed counterparts as a bare object-id (no name/email), which a name search cannot match; for every bare DIRECT (1:1) chat the command hydrates the roster via the per-chat members endpoint and re-matches — so an external counterpart who is bare in your 1:1 is still found, even when they were already resolved in some meeting (the dual-identity case). Bare members in group/meeting chats are not deep-probed; when nothing matches and such members exist it returns a `hint` plus `unresolvedMemberCount` rather than a confident empty result. **Best-effort, may break on Microsoft client updates** — the chat substrate is not in the public Microsoft Graph API.',
26562
26716
  category: "chats",
26563
26717
  needsSubstrateToken: true,
@@ -26592,20 +26746,20 @@ var meta111 = {
26592
26746
  // src/use-cases/commands/list-my-direct-reports.ts
26593
26747
  var exports_list_my_direct_reports = {};
26594
26748
  __export(exports_list_my_direct_reports, {
26595
- schema: () => schema110,
26596
- meta: () => meta112,
26597
- execute: () => execute110
26749
+ schema: () => schema111,
26750
+ meta: () => meta113,
26751
+ execute: () => execute111
26598
26752
  });
26599
- var schema110 = exports_external.object({}).strict().extend(odataQuerySchema.shape);
26600
- var execute110 = async (graph, params) => {
26601
- const parsed = schema110.safeParse(params);
26753
+ var schema111 = exports_external.object({}).strict().extend(odataQuerySchema.shape);
26754
+ var execute111 = async (graph, params) => {
26755
+ const parsed = schema111.safeParse(params);
26602
26756
  if (!parsed.success)
26603
26757
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
26604
26758
  const headers = parsed.data.orderby !== undefined ? { ConsistencyLevel: "eventual" } : {};
26605
26759
  const path = appendOData("/me/directReports", parsed.data);
26606
26760
  return graph.get(path, headers);
26607
26761
  };
26608
- var meta112 = {
26762
+ var meta113 = {
26609
26763
  summary: "List the signed-in user's direct reports (employees who report to them in the directory). When `--orderby` is supplied the CLI auto-injects the `ConsistencyLevel: eventual` header Graph requires on directory endpoints — otherwise Graph rejects the sort with `Request_UnsupportedQuery`.",
26610
26764
  category: "user",
26611
26765
  graphMethod: "GET",
@@ -26620,13 +26774,13 @@ var meta112 = {
26620
26774
  // src/use-cases/commands/list-user-direct-reports.ts
26621
26775
  var exports_list_user_direct_reports = {};
26622
26776
  __export(exports_list_user_direct_reports, {
26623
- schema: () => schema111,
26624
- meta: () => meta113,
26625
- execute: () => execute111
26777
+ schema: () => schema112,
26778
+ meta: () => meta114,
26779
+ execute: () => execute112
26626
26780
  });
26627
26781
  var baseSchema51 = exports_external.object({ userId: exports_external.string().min(1) });
26628
- var { execute: execute111, schema: schema111 } = buildListCommand((p) => `/users/${p.userId}/directReports`, baseSchema51);
26629
- var meta113 = {
26782
+ var { execute: execute112, schema: schema112 } = buildListCommand((p) => `/users/${p.userId}/directReports`, baseSchema51);
26783
+ var meta114 = {
26630
26784
  summary: "List a specific user's direct reports.",
26631
26785
  category: "user",
26632
26786
  graphMethod: "GET",
@@ -26650,13 +26804,13 @@ var meta113 = {
26650
26804
  // src/use-cases/commands/list-recent-files.ts
26651
26805
  var exports_list_recent_files = {};
26652
26806
  __export(exports_list_recent_files, {
26653
- schema: () => schema112,
26654
- meta: () => meta114,
26655
- execute: () => execute112
26807
+ schema: () => schema113,
26808
+ meta: () => meta115,
26809
+ execute: () => execute113
26656
26810
  });
26657
26811
  var baseSchema52 = exports_external.object({}).strict();
26658
- var { execute: execute112, schema: schema112 } = buildNoSkipListCommand(() => "/me/drive/recent", baseSchema52);
26659
- var meta114 = {
26812
+ var { execute: execute113, schema: schema113 } = buildNoSkipListCommand(() => "/me/drive/recent", baseSchema52);
26813
+ var meta115 = {
26660
26814
  summary: "List the signed-in user's most recently used / opened OneDrive and SharePoint files, ranked by Microsoft's recency signal. The strongest single answer to \"what is this user working on right now?\". Note: Graph's recent-files feed is signal-driven and can lag the underlying drive by 24-48 hours — `lastModifiedDateTime` here may be older than the file's true mtime. For \"what is the actual latest version?\" call `list-drive-item-versions` on a specific item.",
26661
26815
  category: "drive",
26662
26816
  graphMethod: "GET",
@@ -26672,13 +26826,13 @@ var meta114 = {
26672
26826
  // src/use-cases/commands/list-shared-with-me.ts
26673
26827
  var exports_list_shared_with_me = {};
26674
26828
  __export(exports_list_shared_with_me, {
26675
- schema: () => schema113,
26676
- meta: () => meta115,
26677
- execute: () => execute113
26829
+ schema: () => schema114,
26830
+ meta: () => meta116,
26831
+ execute: () => execute114
26678
26832
  });
26679
- var schema113 = exports_external.object({}).strict();
26680
- var { execute: execute113 } = buildCommand(() => "/me/drive/sharedWithMe", schema113);
26681
- var meta115 = {
26833
+ var schema114 = exports_external.object({}).strict();
26834
+ var { execute: execute114 } = buildCommand(() => "/me/drive/sharedWithMe", schema114);
26835
+ var meta116 = {
26682
26836
  summary: "List driveItems shared with the signed-in user (typically by colleagues). Each entry includes the original drive + item ID under `remoteItem` so you can chain into `get-drive-item`, `download-drive-item-content`, etc. Note: Graph does NOT honor any OData query parameters on this endpoint (top/select/filter/etc. are all silently ignored), so the CLI does not advertise them. The full collection (~500 items in a typical tenant) is always returned; slice client-side or pair with the global output-path flag to land the raw JSON on disk.",
26683
26837
  category: "drive",
26684
26838
  graphMethod: "GET",
@@ -26692,13 +26846,13 @@ var meta115 = {
26692
26846
  // src/use-cases/commands/list-recently-used-insights.ts
26693
26847
  var exports_list_recently_used_insights = {};
26694
26848
  __export(exports_list_recently_used_insights, {
26695
- schema: () => schema114,
26696
- meta: () => meta116,
26697
- execute: () => execute114
26849
+ schema: () => schema115,
26850
+ meta: () => meta117,
26851
+ execute: () => execute115
26698
26852
  });
26699
26853
  var baseSchema53 = exports_external.object({}).strict();
26700
- var { execute: execute114, schema: schema114 } = buildListCommand(() => "/me/insights/used", baseSchema53);
26701
- var meta116 = {
26854
+ var { execute: execute115, schema: schema115 } = buildListCommand(() => "/me/insights/used", baseSchema53);
26855
+ var meta117 = {
26702
26856
  summary: "List documents the signed-in user has *personally* used recently (Microsoft's machine-learning recency signal — distinct from `list-recent-files` which is the OneDrive recency feed). Each item carries a `lastUsed` (a `usageDetails` object) with `lastAccessedDateTime` + `lastModifiedDateTime`.",
26703
26857
  category: "drive",
26704
26858
  graphMethod: "GET",
@@ -26713,13 +26867,13 @@ var meta116 = {
26713
26867
  // src/use-cases/commands/list-shared-insights.ts
26714
26868
  var exports_list_shared_insights = {};
26715
26869
  __export(exports_list_shared_insights, {
26716
- schema: () => schema115,
26717
- meta: () => meta117,
26718
- execute: () => execute115
26870
+ schema: () => schema116,
26871
+ meta: () => meta118,
26872
+ execute: () => execute116
26719
26873
  });
26720
26874
  var baseSchema54 = exports_external.object({}).strict();
26721
- var { execute: execute115, schema: schema115 } = buildListCommand(() => "/me/insights/shared", baseSchema54);
26722
- var meta117 = {
26875
+ var { execute: execute116, schema: schema116 } = buildListCommand(() => "/me/insights/shared", baseSchema54);
26876
+ var meta118 = {
26723
26877
  summary: "List documents *shared with* the signed-in user, scored by Microsoft's relevance ranking — sibling to `list-shared-with-me` but with sharing-context details (`sharingHistory[]`, `lastShared.sharedBy`, `lastShared.sharingReference`).",
26724
26878
  category: "drive",
26725
26879
  graphMethod: "GET",
@@ -26734,13 +26888,13 @@ var meta117 = {
26734
26888
  // src/use-cases/commands/get-organization.ts
26735
26889
  var exports_get_organization = {};
26736
26890
  __export(exports_get_organization, {
26737
- schema: () => schema116,
26738
- meta: () => meta118,
26739
- execute: () => execute116
26891
+ schema: () => schema117,
26892
+ meta: () => meta119,
26893
+ execute: () => execute117
26740
26894
  });
26741
26895
  var baseSchema55 = exports_external.object({});
26742
- var { execute: execute116, schema: schema116 } = buildSelectableCommand(() => "/organization", baseSchema55);
26743
- var meta118 = {
26896
+ var { execute: execute117, schema: schema117 } = buildSelectableCommand(() => "/organization", baseSchema55);
26897
+ var meta119 = {
26744
26898
  summary: "Return the tenant's organization metadata — display name, country, verified domains, business phones, technical / security notification contacts, assigned Microsoft 365 SKUs / licensing. Graph wraps the single organization resource under `value[]` (— even though only one tenant exists, the endpoint returns a collection). The full resource is ~57 KB; use `--select` to slim it (e.g. `--select id,displayName,verifiedDomains`).",
26745
26899
  category: "user",
26746
26900
  graphMethod: "GET",
@@ -26754,13 +26908,13 @@ var meta118 = {
26754
26908
  // src/use-cases/commands/list-mail-folders-delta.ts
26755
26909
  var exports_list_mail_folders_delta = {};
26756
26910
  __export(exports_list_mail_folders_delta, {
26757
- schema: () => schema117,
26758
- meta: () => meta119,
26759
- execute: () => execute117
26911
+ schema: () => schema118,
26912
+ meta: () => meta120,
26913
+ execute: () => execute118
26760
26914
  });
26761
- var schema117 = exports_external.object({}).strict();
26762
- var { execute: execute117 } = buildCommand(() => "/me/mailFolders/delta()", schema117);
26763
- var meta119 = {
26915
+ var schema118 = exports_external.object({}).strict();
26916
+ var { execute: execute118 } = buildCommand(() => "/me/mailFolders/delta()", schema118);
26917
+ var meta120 = {
26764
26918
  summary: "Track incremental changes to the mail-folder tree itself (folders added / renamed / deleted). The first call returns the current snapshot plus a `@odata.deltaLink`; subsequent calls with that link return only what has changed. Companion to `list-mail-folder-messages-delta` which tracks message changes inside one folder. Note: Graph explicitly rejects `$top`, `$filter`, `$orderby`, and `$search` on this delta endpoint (`ErrorInvalidUrlQuery: not supported with change tracking over the 'Folders' resource`), so the OData passthrough is intentionally NOT exposed here.",
26765
26919
  category: "mail",
26766
26920
  graphMethod: "GET",
@@ -26776,13 +26930,13 @@ var meta119 = {
26776
26930
  // src/use-cases/commands/get-channel-files-folder.ts
26777
26931
  var exports_get_channel_files_folder = {};
26778
26932
  __export(exports_get_channel_files_folder, {
26779
- schema: () => schema118,
26780
- meta: () => meta120,
26781
- execute: () => execute118
26933
+ schema: () => schema119,
26934
+ meta: () => meta121,
26935
+ execute: () => execute119
26782
26936
  });
26783
26937
  var baseSchema56 = exports_external.object({ teamId: exports_external.string().min(1), channelId: exports_external.string().min(1) });
26784
- var { execute: execute118, schema: schema118 } = buildSelectableCommand((p) => `/teams/${p.teamId}/channels/${p.channelId}/filesFolder`, baseSchema56);
26785
- var meta120 = {
26938
+ var { execute: execute119, schema: schema119 } = buildSelectableCommand((p) => `/teams/${p.teamId}/channels/${p.channelId}/filesFolder`, baseSchema56);
26939
+ var meta121 = {
26786
26940
  summary: "Return the SharePoint folder that backs a Teams channel's Files tab. Returned `driveItem` includes `parentReference.driveId` and `id` so you can pivot into `list-folder-files`, `download-drive-item-content`, etc., and treat the channel like any other OneDrive folder. Requires that the signed-in user is a member of the channel — restricted channels return `AccessDenied`.",
26787
26941
  category: "teams",
26788
26942
  graphMethod: "GET",
@@ -26810,13 +26964,13 @@ var meta120 = {
26810
26964
  // src/use-cases/commands/get-drive-item-list-item.ts
26811
26965
  var exports_get_drive_item_list_item = {};
26812
26966
  __export(exports_get_drive_item_list_item, {
26813
- schema: () => schema119,
26814
- meta: () => meta121,
26815
- execute: () => execute119
26967
+ schema: () => schema120,
26968
+ meta: () => meta122,
26969
+ execute: () => execute120
26816
26970
  });
26817
26971
  var baseSchema57 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
26818
- var { execute: execute119, schema: schema119 } = buildSelectableCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/listItem`, baseSchema57);
26819
- var meta121 = {
26972
+ var { execute: execute120, schema: schema120 } = buildSelectableCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/listItem`, baseSchema57);
26973
+ var meta122 = {
26820
26974
  summary: "Return the SharePoint listItem projection of a OneDrive / SharePoint file — exposes the file's library-defined column values (custom metadata: status, due-date, classification, taxonomy tags, etc.) which are NOT present on the plain `driveItem`. Combine with `list-sharepoint-list-columns` to interpret the column schema.",
26821
26975
  category: "sharepoint",
26822
26976
  graphMethod: "GET",
@@ -26844,13 +26998,13 @@ var meta121 = {
26844
26998
  // src/use-cases/commands/get-drive-item-analytics.ts
26845
26999
  var exports_get_drive_item_analytics = {};
26846
27000
  __export(exports_get_drive_item_analytics, {
26847
- schema: () => schema120,
26848
- meta: () => meta122,
26849
- execute: () => execute120
27001
+ schema: () => schema121,
27002
+ meta: () => meta123,
27003
+ execute: () => execute121
26850
27004
  });
26851
- var schema120 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
26852
- var { execute: execute120 } = buildCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/analytics`, schema120);
26853
- var meta122 = {
27005
+ var schema121 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
27006
+ var { execute: execute121 } = buildCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/analytics`, schema121);
27007
+ var meta123 = {
26854
27008
  summary: 'Return view / activity analytics for a OneDrive / SharePoint file — `allTime` totals (views, viewers) and `lastSevenDays` rollup. Useful for ranking files by attention or detecting stale content. **Known empty case**: returns `{ allTime: null, lastSevenDays: null }` on low-traffic items, or when the calling identity (the Teams web client basic token) lacks the analytics scope on the tenant. Do not interpret nulls as "no views" — interpret as "not available for this caller". For active files where you expect data and see nulls, escalate to a token with `Reports.Read.All`.',
26855
27009
  category: "drive",
26856
27010
  graphMethod: "GET",
@@ -26877,13 +27031,13 @@ var meta122 = {
26877
27031
  // src/use-cases/commands/list-team-installed-apps.ts
26878
27032
  var exports_list_team_installed_apps = {};
26879
27033
  __export(exports_list_team_installed_apps, {
26880
- schema: () => schema121,
26881
- meta: () => meta123,
26882
- execute: () => execute121
27034
+ schema: () => schema122,
27035
+ meta: () => meta124,
27036
+ execute: () => execute122
26883
27037
  });
26884
- var schema121 = exports_external.object({ teamId: exports_external.string().min(1) });
26885
- var { execute: execute121 } = buildCommand((p) => `/teams/${p.teamId}/installedApps?$expand=teamsAppDefinition`, schema121);
26886
- var meta123 = {
27038
+ var schema122 = exports_external.object({ teamId: exports_external.string().min(1) });
27039
+ var { execute: execute122 } = buildCommand((p) => `/teams/${p.teamId}/installedApps?$expand=teamsAppDefinition`, schema122);
27040
+ var meta124 = {
26887
27041
  summary: "List the Teams apps installed in a team. The CLI hard-pins `$expand=teamsAppDefinition` so every entry includes `displayName`, `version`, and `distributionMethod` (the bare endpoint returns only opaque IDs). Useful for surfacing which integrations are wired into a given team. Graph rejects user-supplied OData query parameters on this endpoint (`Query option 'Top' is not allowed`) — so the standard OData flags are intentionally NOT exposed here. The response itself is still server-paginated via `@odata.nextLink` when the team has many installed apps; chain with `next-page` to walk subsequent pages.",
26888
27042
  category: "teams",
26889
27043
  graphMethod: "GET",
@@ -26906,13 +27060,13 @@ var meta123 = {
26906
27060
  // src/use-cases/commands/list-calendar-groups.ts
26907
27061
  var exports_list_calendar_groups = {};
26908
27062
  __export(exports_list_calendar_groups, {
26909
- schema: () => schema122,
26910
- meta: () => meta124,
26911
- execute: () => execute122
27063
+ schema: () => schema123,
27064
+ meta: () => meta125,
27065
+ execute: () => execute123
26912
27066
  });
26913
27067
  var baseSchema58 = exports_external.object({}).strict();
26914
- var { execute: execute122, schema: schema122 } = buildListCommand(() => "/me/calendarGroups", baseSchema58);
26915
- var meta124 = {
27068
+ var { execute: execute123, schema: schema123 } = buildListCommand(() => "/me/calendarGroups", baseSchema58);
27069
+ var meta125 = {
26916
27070
  summary: 'List the signed-in user\'s calendar groups — Outlook\'s organizational layer above individual calendars (e.g. "My Calendars", "Other Calendars", "Birthdays"). Use the returned `id` with `list-calendar-group-calendars` to drill in.',
26917
27071
  category: "calendar",
26918
27072
  graphMethod: "GET",
@@ -26927,13 +27081,13 @@ var meta124 = {
26927
27081
  // src/use-cases/commands/list-calendar-group-calendars.ts
26928
27082
  var exports_list_calendar_group_calendars = {};
26929
27083
  __export(exports_list_calendar_group_calendars, {
26930
- schema: () => schema123,
26931
- meta: () => meta125,
26932
- execute: () => execute123
27084
+ schema: () => schema124,
27085
+ meta: () => meta126,
27086
+ execute: () => execute124
26933
27087
  });
26934
27088
  var baseSchema59 = exports_external.object({ calendarGroupId: exports_external.string().min(1) });
26935
- var { execute: execute123, schema: schema123 } = buildListCommand((p) => `/me/calendarGroups/${p.calendarGroupId}/calendars`, baseSchema59);
26936
- var meta125 = {
27089
+ var { execute: execute124, schema: schema124 } = buildListCommand((p) => `/me/calendarGroups/${p.calendarGroupId}/calendars`, baseSchema59);
27090
+ var meta126 = {
26937
27091
  summary: "List the calendars inside one calendar group.",
26938
27092
  category: "calendar",
26939
27093
  graphMethod: "GET",
@@ -26957,13 +27111,13 @@ var meta125 = {
26957
27111
  // src/use-cases/commands/get-my-calendar.ts
26958
27112
  var exports_get_my_calendar = {};
26959
27113
  __export(exports_get_my_calendar, {
26960
- schema: () => schema124,
26961
- meta: () => meta126,
26962
- execute: () => execute124
27114
+ schema: () => schema125,
27115
+ meta: () => meta127,
27116
+ execute: () => execute125
26963
27117
  });
26964
27118
  var baseSchema60 = exports_external.object({});
26965
- var { execute: execute124, schema: schema124 } = buildSelectableCommand(() => "/me/calendar", baseSchema60);
26966
- var meta126 = {
27119
+ var { execute: execute125, schema: schema125 } = buildSelectableCommand(() => "/me/calendar", baseSchema60);
27120
+ var meta127 = {
26967
27121
  summary: "Return metadata for the signed-in user's *primary* calendar — `id`, `name`, `color`, `owner`, `canShare`, `canViewPrivateItems`, `canEdit`, `defaultOnlineMeetingProvider`. Sibling to `list-calendars` which returns every calendar (incl. shared / subscribed). Use `--select` to fetch only the fields you need.",
26968
27122
  category: "calendar",
26969
27123
  graphMethod: "GET",
@@ -26977,13 +27131,13 @@ var meta126 = {
26977
27131
  // src/use-cases/commands/list-site-columns.ts
26978
27132
  var exports_list_site_columns = {};
26979
27133
  __export(exports_list_site_columns, {
26980
- schema: () => schema125,
26981
- meta: () => meta127,
26982
- execute: () => execute125
27134
+ schema: () => schema126,
27135
+ meta: () => meta128,
27136
+ execute: () => execute126
26983
27137
  });
26984
27138
  var baseSchema61 = exports_external.object({ siteId: exports_external.string().min(1) });
26985
- var { execute: execute125, schema: schema125 } = buildSelectableCommand((p) => `/sites/${p.siteId}/columns`, baseSchema61);
26986
- var meta127 = {
27139
+ var { execute: execute126, schema: schema126 } = buildSelectableCommand((p) => `/sites/${p.siteId}/columns`, baseSchema61);
27140
+ var meta128 = {
26987
27141
  summary: "List the *site-level* column definitions — columns reusable across multiple lists in the site. Distinct from `list-sharepoint-list-columns` which returns one specific list's schema. Note: Graph silently ignores `$top` and `$skip` on this endpoint (verified live — passing them returns the full collection regardless), so the CLI exposes only `--select` and `--expand`.",
26988
27142
  category: "sharepoint",
26989
27143
  graphMethod: "GET",
@@ -27006,13 +27160,13 @@ var meta127 = {
27006
27160
  // src/use-cases/commands/list-site-content-types.ts
27007
27161
  var exports_list_site_content_types = {};
27008
27162
  __export(exports_list_site_content_types, {
27009
- schema: () => schema126,
27010
- meta: () => meta128,
27011
- execute: () => execute126
27163
+ schema: () => schema127,
27164
+ meta: () => meta129,
27165
+ execute: () => execute127
27012
27166
  });
27013
27167
  var baseSchema62 = exports_external.object({ siteId: exports_external.string().min(1) });
27014
- var { execute: execute126, schema: schema126 } = buildNoSkipListCommand((p) => `/sites/${p.siteId}/contentTypes`, baseSchema62);
27015
- var meta128 = {
27168
+ var { execute: execute127, schema: schema127 } = buildNoSkipListCommand((p) => `/sites/${p.siteId}/contentTypes`, baseSchema62);
27169
+ var meta129 = {
27016
27170
  summary: "List the content type definitions of a SharePoint site — typed schemas (Document, Page, Item, custom-defined) describing which columns + behaviors apply to items of each type. Useful for understanding a site's information architecture.",
27017
27171
  category: "sharepoint",
27018
27172
  graphMethod: "GET",
@@ -27037,13 +27191,13 @@ var meta128 = {
27037
27191
  // src/use-cases/commands/list-sharepoint-site-pages.ts
27038
27192
  var exports_list_sharepoint_site_pages = {};
27039
27193
  __export(exports_list_sharepoint_site_pages, {
27040
- schema: () => schema127,
27041
- meta: () => meta129,
27042
- execute: () => execute127
27194
+ schema: () => schema128,
27195
+ meta: () => meta130,
27196
+ execute: () => execute128
27043
27197
  });
27044
27198
  var baseSchema63 = exports_external.object({ siteId: exports_external.string().min(1) });
27045
- var { execute: execute127, schema: schema127 } = buildNoSkipListCommand((p) => `/sites/${p.siteId}/pages`, baseSchema63);
27046
- var meta129 = {
27199
+ var { execute: execute128, schema: schema128 } = buildNoSkipListCommand((p) => `/sites/${p.siteId}/pages`, baseSchema63);
27200
+ var meta130 = {
27047
27201
  summary: "List modern SharePoint pages on a site (news posts, dashboards, landing pages). Each `sitePage` has `title`, `description`, `webUrl`, `publishingState`, `lastPublishedDateTime`. Returned items are the read-only listing — fetch the page body via the SharePoint REST API or by opening the `webUrl`.",
27048
27202
  category: "sharepoint",
27049
27203
  graphMethod: "GET",
@@ -27068,15 +27222,15 @@ var meta129 = {
27068
27222
  // src/use-cases/commands/list-excel-defined-names.ts
27069
27223
  var exports_list_excel_defined_names = {};
27070
27224
  __export(exports_list_excel_defined_names, {
27071
- schema: () => schema128,
27072
- meta: () => meta130,
27073
- execute: () => execute128
27225
+ schema: () => schema129,
27226
+ meta: () => meta131,
27227
+ execute: () => execute129
27074
27228
  });
27075
27229
  var baseSchema64 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
27076
27230
  var inner10 = buildListCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/workbook/names`, baseSchema64);
27077
- var execute128 = wrapExcelExecute(inner10.execute);
27078
- var { schema: schema128 } = inner10;
27079
- var meta130 = {
27231
+ var execute129 = wrapExcelExecute(inner10.execute);
27232
+ var { schema: schema129 } = inner10;
27233
+ var meta131 = {
27080
27234
  summary: "List the workbook's defined names (named ranges, named formulas, named constants). Each `workbookNamedItem` has `name`, `value` (the formula or address), `comment`, and `scope` (workbook or worksheet). Useful for understanding workbook structure before reading ranges.",
27081
27235
  category: "excel",
27082
27236
  graphMethod: "GET",
@@ -27105,15 +27259,15 @@ var meta130 = {
27105
27259
  // src/use-cases/commands/list-excel-worksheet-charts.ts
27106
27260
  var exports_list_excel_worksheet_charts = {};
27107
27261
  __export(exports_list_excel_worksheet_charts, {
27108
- schema: () => schema129,
27109
- meta: () => meta131,
27110
- execute: () => execute129
27262
+ schema: () => schema130,
27263
+ meta: () => meta132,
27264
+ execute: () => execute130
27111
27265
  });
27112
27266
  var baseSchema65 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1), worksheetId: exports_external.string().min(1) });
27113
27267
  var inner11 = buildListCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/workbook/worksheets/${p.worksheetId}/charts`, baseSchema65);
27114
- var execute129 = wrapExcelExecute(inner11.execute);
27115
- var { schema: schema129 } = inner11;
27116
- var meta131 = {
27268
+ var execute130 = wrapExcelExecute(inner11.execute);
27269
+ var { schema: schema130 } = inner11;
27270
+ var meta132 = {
27117
27271
  summary: "List the charts on a worksheet. Each `workbookChart` has `id`, `name`, `height`, `width`, `top`, `left`. Use the chart's image endpoint (`.../charts/{id}/image()`) to render the chart as a base64 PNG.",
27118
27272
  category: "excel",
27119
27273
  graphMethod: "GET",
@@ -27149,15 +27303,15 @@ var meta131 = {
27149
27303
  // src/use-cases/commands/microsoft-search-query.ts
27150
27304
  var exports_microsoft_search_query = {};
27151
27305
  __export(exports_microsoft_search_query, {
27152
- schema: () => schema130,
27153
- meta: () => meta132,
27154
- execute: () => execute130
27306
+ schema: () => schema131,
27307
+ meta: () => meta133,
27308
+ execute: () => execute131
27155
27309
  });
27156
27310
  var ALL_ENTITY_TYPES = ["driveItem", "listItem", "site", "message", "event", "person"];
27157
27311
  var PAGE_SIZE2 = 25;
27158
- var schema130 = exports_external.object({ query: exports_external.string().min(1) });
27159
- var execute130 = async (graph, params) => {
27160
- const parsed = schema130.safeParse(params);
27312
+ var schema131 = exports_external.object({ query: exports_external.string().min(1) });
27313
+ var execute131 = async (graph, params) => {
27314
+ const parsed = schema131.safeParse(params);
27161
27315
  if (!parsed.success)
27162
27316
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
27163
27317
  const queryString = parsed.data.query;
@@ -27179,7 +27333,7 @@ var execute130 = async (graph, params) => {
27179
27333
  return err(partialErrors[0]?.error ?? { type: "api_error", status: 500, message: "all entity-type sub-requests failed" });
27180
27334
  return ok({ value: merged, ...partialErrors.length > 0 ? { partialErrors } : {} });
27181
27335
  };
27182
- var meta132 = {
27336
+ var meta133 = {
27183
27337
  summary: "Run a federated KQL search across the signed-in user's mail, files, list items, sites, calendar events, and people. Microsoft Graph v1.0 rejects multi-entity search bodies on most tenants (`Multiple entity search is not supported in v1.0`), so this command issues SIX parallel POSTs — one per entityType — and merges the per-entity `searchHits` containers into a single `value[]`. Each container is identifiable by the resource type inside `hits[].resource`. If a sub-request fails (e.g. tenant lacks the scope for one entity), the others still return; failures show up in `partialErrors[]`. Page size is fixed at 25 per sub-request and `top` is NOT exposed (Graph rejects $top in /search/query bodies). `chatMessage` is excluded since `Chat.Read*` is unavailable. To find Microsoft Loop pages (`.loop`) for markdown conversion, query `filetype:loop`: each `driveItem` hit carries `resource.id` plus `resource.parentReference.driveId`, the exact pair `download-drive-item-as-markdown` needs to render the page via Graph `?format=html`. (`filetype:fluid` returns nothing on this corpus; Loop pages index as `.loop`.)",
27184
27338
  category: "meta",
27185
27339
  graphMethod: "POST",
@@ -27201,14 +27355,14 @@ var meta132 = {
27201
27355
  // src/use-cases/commands/my-quick-context.ts
27202
27356
  var exports_my_quick_context = {};
27203
27357
  __export(exports_my_quick_context, {
27204
- schema: () => schema131,
27205
- meta: () => meta133,
27206
- execute: () => execute131
27358
+ schema: () => schema132,
27359
+ meta: () => meta134,
27360
+ execute: () => execute132
27207
27361
  });
27208
- var schema131 = exports_external.object({}).strict();
27362
+ var schema132 = exports_external.object({}).strict();
27209
27363
  var valueOrUndefined = (r) => r.ok ? r.value : undefined;
27210
- var execute131 = async (graph, params) => {
27211
- const parsed = schema131.safeParse(params);
27364
+ var execute132 = async (graph, params) => {
27365
+ const parsed = schema132.safeParse(params);
27212
27366
  if (!parsed.success)
27213
27367
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
27214
27368
  const [meRes, driveRes, inboxRes, calendarRes, plannerRes, notebooksRes, teamsRes, recentRes, mailboxRes] = await Promise.all([
@@ -27247,7 +27401,7 @@ var execute131 = async (graph, params) => {
27247
27401
  tenantWorkingHours: mailbox?.workingHours?.startTime !== undefined && mailbox.workingHours.endTime !== undefined ? { start: mailbox.workingHours.startTime, end: mailbox.workingHours.endTime, timeZone: mailbox.workingHours.timeZone?.name } : undefined
27248
27402
  });
27249
27403
  };
27250
- var meta133 = {
27404
+ var meta134 = {
27251
27405
  summary: "One-shot discovery for the IDs every other command needs, plus the user's job title and tenant timezone / locale / working-hours. Issues 9 Graph calls in parallel and returns what each succeeded for. Partial-result mode: only `/me` is load-bearing — if any other sub-call fails (missing license, scope, or tenant policy) the corresponding field is `undefined` but the rest are still returned. Replaces the audit's 5-call discovery chain — feed the IDs straight into `list-mail-folder-messages`, `list-folder-files`, `list-planner-tasks`, `list-onenote-notebook-sections`, etc. For Microsoft To Do lists call `list-todo-task-lists` on demand (intentionally dropped from this command's fan-out — the array of {id, displayName, wellknownListName} entries crowded the envelope with IDs an LLM rarely needs on first contact). `tenantTimeZone` lets an LLM stop treating every datetime as UTC on first contact.",
27252
27406
  category: "meta",
27253
27407
  graphMethod: "GET",
@@ -27261,38 +27415,38 @@ var meta133 = {
27261
27415
  // src/use-cases/commands/scopes-check.ts
27262
27416
  var exports_scopes_check = {};
27263
27417
  __export(exports_scopes_check, {
27264
- schema: () => schema132,
27265
- meta: () => meta134,
27266
- execute: () => execute132
27418
+ schema: () => schema133,
27419
+ meta: () => meta135,
27420
+ execute: () => execute133
27267
27421
  });
27268
- var schema132 = exports_external.object({}).strict();
27269
- var execute132 = async (graph, params) => {
27270
- const parsed = schema132.safeParse(params);
27422
+ var schema133 = exports_external.object({}).strict();
27423
+ var execute133 = async (graph, params) => {
27424
+ const parsed = schema133.safeParse(params);
27271
27425
  if (!parsed.success)
27272
27426
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
27273
27427
  return graph.getCachedTokenInfo();
27274
27428
  };
27275
- var meta134 = {
27276
- summary: "Decode the cached Teams web client access token and return its scopes, audience, and expiry without making a Graph call. Use this as a self-test before running a command an LLM expects to fail with `accessDenied` — if the required scope isn't in the returned list, the call will reject regardless of tenant config. Each command's `scopesRequired` field in `help-json` lists the scopes that command needs; intersect with the array returned here for a pre-flight check (pipe both through `jq` and diff). The `expiresInSeconds` field (added ) lets an LLM decide pre-emptively to `login` again — typically worth doing under ~5 minutes (300 s) so a long-running session doesn't hit the wall mid-command.",
27429
+ var meta135 = {
27430
+ summary: "Decode the cached Teams web client access token and return its scopes, audience, and expiry without making a Graph call. Use this as a self-test before running a command an LLM expects to fail with `accessDenied` — if the required scope isn't in the returned list, the call will reject regardless of tenant config. Each command's `scopesRequired` field in `help-json` lists the scopes that command needs; intersect with the array returned here for a pre-flight check (pipe both through `jq` and diff). The `expiresInSeconds` field lets an LLM decide pre-emptively to `login` again — typically worth doing under ~5 minutes (300 s) so a long-running session doesn't hit the wall mid-command. The `elevated` block reports whether the *separate* M365ChatClient-elevated token (needed by the historical-version download / convert commands) is cached and still usable — so a fresh process can pre-flight `deep-scan`-style workloads instead of discovering a 403 mid-run; `available:false` when it is absent, expired, or within the same 5-minute buffer the download path applies. The `chatsvcagg` and `ic3` blocks report the two Teams-chat substrate tokens (used by `list-teams-chat*` / `find-chats-with-user`) the same way; both self-heal from the shared refresh token, so they are informational rather than a preflight gate.",
27277
27431
  category: "meta",
27278
27432
  graphMethod: "GET",
27279
27433
  graphPathTemplate: "(meta) cached-token introspection — no Graph endpoint",
27280
27434
  graphDocsUrl: "https://learn.microsoft.com/en-us/graph/permissions-reference",
27281
27435
  options: [],
27282
27436
  example: "ask-marcel-office scopes-check",
27283
- responseShape: "`{ scopes: string[], audience: string, expiresAt: string (ISO 8601), expiresInSeconds: number }`. `expiresInSeconds` is negative when the cached token has already expired (run `login`); `audience` is the JWT `aud` claim (typically `https://graph.microsoft.com`)."
27437
+ responseShape: "`{ scopes: string[], audience: string, expiresAt: string (ISO 8601), expiresInSeconds: number, elevated: { available: boolean, expiresInSeconds?: number }, chatsvcagg: { available: boolean, expiresInSeconds?: number }, ic3: { available: boolean, expiresInSeconds?: number } }`. `expiresInSeconds` is negative when the cached token has already expired (run `login`); `audience` is the JWT `aud` claim (typically `https://graph.microsoft.com`). `elevated.available` is `true` only when the cached M365ChatClient-elevated token (used by the historical-version commands) is present and beyond the 5-minute buffer; `elevated.expiresInSeconds` is its raw remaining seconds and is omitted (the key is absent) when no elevated token is cached. `chatsvcagg` and `ic3` are the two Teams-chat substrate tokens, same shape as `elevated`; both self-heal from the shared refresh token, so they are informational rather than a preflight gate."
27284
27438
  };
27285
27439
 
27286
27440
  // src/use-cases/commands/get-drive-special-folder.ts
27287
27441
  var exports_get_drive_special_folder = {};
27288
27442
  __export(exports_get_drive_special_folder, {
27289
- schema: () => schema133,
27290
- meta: () => meta135,
27291
- execute: () => execute133
27443
+ schema: () => schema134,
27444
+ meta: () => meta136,
27445
+ execute: () => execute134
27292
27446
  });
27293
27447
  var baseSchema66 = exports_external.object({ folderName: exports_external.enum(["documents", "photos", "cameraroll", "approot", "music", "attachments"]) });
27294
- var { execute: execute133, schema: schema133 } = buildSelectableCommand((p) => `/me/drive/special/${p.folderName}`, baseSchema66);
27295
- var meta135 = {
27448
+ var { execute: execute134, schema: schema134 } = buildSelectableCommand((p) => `/me/drive/special/${p.folderName}`, baseSchema66);
27449
+ var meta136 = {
27296
27450
  summary: "Resolve a OneDrive well-known folder via `--folder-name` (one of `documents`, `photos`, `cameraroll`, `approot`, `music`, `attachments`) without having to navigate from the root. Returns the folder's driveItem (id, name, parentReference, etc.) ready to feed into `list-folder-files` or `download-drive-item-content`.",
27297
27451
  category: "drive",
27298
27452
  graphMethod: "GET",
@@ -27314,13 +27468,13 @@ var meta135 = {
27314
27468
  // src/use-cases/commands/get-drive-root-delta.ts
27315
27469
  var exports_get_drive_root_delta = {};
27316
27470
  __export(exports_get_drive_root_delta, {
27317
- schema: () => schema134,
27318
- meta: () => meta136,
27319
- execute: () => execute134
27471
+ schema: () => schema135,
27472
+ meta: () => meta137,
27473
+ execute: () => execute135
27320
27474
  });
27321
27475
  var baseSchema67 = exports_external.object({}).strict();
27322
- var { execute: execute134, schema: schema134 } = buildNoSkipListCommand(() => "/me/drive/root/delta()", baseSchema67);
27323
- var meta136 = {
27476
+ var { execute: execute135, schema: schema135 } = buildNoSkipListCommand(() => "/me/drive/root/delta()", baseSchema67);
27477
+ var meta137 = {
27324
27478
  summary: "Track incremental changes (added / modified / deleted items) anywhere under the signed-in user's OneDrive root. **Takes zero required arguments** — acts implicitly on the signed-in user's primary OneDrive; use `get-drive-delta` to target a specific drive by ID. The first call returns a snapshot plus `@odata.deltaLink`; subsequent calls with that link return only what has changed since. Cross-folder companion to `get-drive-delta` (which scopes to one specific folder).",
27325
27479
  category: "drive",
27326
27480
  graphMethod: "GET",
@@ -27336,13 +27490,13 @@ var meta136 = {
27336
27490
  // src/use-cases/commands/list-followed-drive-items.ts
27337
27491
  var exports_list_followed_drive_items = {};
27338
27492
  __export(exports_list_followed_drive_items, {
27339
- schema: () => schema135,
27340
- meta: () => meta137,
27341
- execute: () => execute135
27493
+ schema: () => schema136,
27494
+ meta: () => meta138,
27495
+ execute: () => execute136
27342
27496
  });
27343
27497
  var baseSchema68 = exports_external.object({}).strict();
27344
- var { execute: execute135, schema: schema135 } = buildNoSkipListCommand(() => "/me/drive/following", baseSchema68);
27345
- var meta137 = {
27498
+ var { execute: execute136, schema: schema136 } = buildNoSkipListCommand(() => "/me/drive/following", baseSchema68);
27499
+ var meta138 = {
27346
27500
  summary: "List driveItems the signed-in user has explicitly followed (the OneDrive star). A small, hand-curated set of frequently-revisited files, distinct from the algorithmic `list-recent-files` and `list-recently-used-insights`.",
27347
27501
  category: "drive",
27348
27502
  graphMethod: "GET",
@@ -27358,13 +27512,13 @@ var meta137 = {
27358
27512
  // src/use-cases/commands/get-drive-item-created-by-user.ts
27359
27513
  var exports_get_drive_item_created_by_user = {};
27360
27514
  __export(exports_get_drive_item_created_by_user, {
27361
- schema: () => schema136,
27362
- meta: () => meta138,
27363
- execute: () => execute136
27515
+ schema: () => schema137,
27516
+ meta: () => meta139,
27517
+ execute: () => execute137
27364
27518
  });
27365
27519
  var baseSchema69 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
27366
- var { execute: execute136, schema: schema136 } = buildSelectableCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/createdByUser`, baseSchema69);
27367
- var meta138 = {
27520
+ var { execute: execute137, schema: schema137 } = buildSelectableCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/createdByUser`, baseSchema69);
27521
+ var meta139 = {
27368
27522
  summary: "Return the `user` resource for whoever created a OneDrive / SharePoint file — full profile, not just the truncated `createdBy.user` summary embedded in the parent driveItem. Useful when you need title / department / mail of the author. Use `--select` to fetch only the fields you care about (e.g. `--select id,displayName,jobTitle,department,mail`).",
27369
27523
  category: "drive",
27370
27524
  graphMethod: "GET",
@@ -27392,13 +27546,13 @@ var meta138 = {
27392
27546
  // src/use-cases/commands/get-drive-item-last-modified-by-user.ts
27393
27547
  var exports_get_drive_item_last_modified_by_user = {};
27394
27548
  __export(exports_get_drive_item_last_modified_by_user, {
27395
- schema: () => schema137,
27396
- meta: () => meta139,
27397
- execute: () => execute137
27549
+ schema: () => schema138,
27550
+ meta: () => meta140,
27551
+ execute: () => execute138
27398
27552
  });
27399
27553
  var baseSchema70 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
27400
- var { execute: execute137, schema: schema137 } = buildSelectableCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/lastModifiedByUser`, baseSchema70);
27401
- var meta139 = {
27554
+ var { execute: execute138, schema: schema138 } = buildSelectableCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/lastModifiedByUser`, baseSchema70);
27555
+ var meta140 = {
27402
27556
  summary: "Return the full `user` resource for whoever last modified a OneDrive / SharePoint file — sibling to `get-drive-item-created-by-user`. Use `--select` to fetch only specific fields.",
27403
27557
  category: "drive",
27404
27558
  graphMethod: "GET",
@@ -27426,13 +27580,13 @@ var meta139 = {
27426
27580
  // src/use-cases/commands/get-site-analytics.ts
27427
27581
  var exports_get_site_analytics = {};
27428
27582
  __export(exports_get_site_analytics, {
27429
- schema: () => schema138,
27430
- meta: () => meta140,
27431
- execute: () => execute138
27583
+ schema: () => schema139,
27584
+ meta: () => meta141,
27585
+ execute: () => execute139
27432
27586
  });
27433
- var schema138 = exports_external.object({ siteId: exports_external.string().min(1) });
27434
- var { execute: execute138 } = buildCommand((p) => `/sites/${p.siteId}/analytics`, schema138);
27435
- var meta140 = {
27587
+ var schema139 = exports_external.object({ siteId: exports_external.string().min(1) });
27588
+ var { execute: execute139 } = buildCommand((p) => `/sites/${p.siteId}/analytics`, schema139);
27589
+ var meta141 = {
27436
27590
  summary: 'Return view / activity analytics for a SharePoint site — `allTime` totals (visits, viewers) and `lastSevenDays` rollup. Site-level parallel to `get-drive-item-analytics`. Useful for ranking sites by attention or detecting stale workspaces. **Known empty case**: returns `{ allTime: null, lastSevenDays: null }` even on active sites when the calling identity (the Teams web client basic token) lacks the analytics scope. Do not interpret nulls as "no activity" — interpret as "not available for this caller".',
27437
27591
  category: "sharepoint",
27438
27592
  graphMethod: "GET",
@@ -27454,13 +27608,13 @@ var meta140 = {
27454
27608
  // src/use-cases/commands/list-sharepoint-list-item-versions.ts
27455
27609
  var exports_list_sharepoint_list_item_versions = {};
27456
27610
  __export(exports_list_sharepoint_list_item_versions, {
27457
- schema: () => schema139,
27458
- meta: () => meta141,
27459
- execute: () => execute139
27611
+ schema: () => schema140,
27612
+ meta: () => meta142,
27613
+ execute: () => execute140
27460
27614
  });
27461
27615
  var baseSchema71 = exports_external.object({ siteId: exports_external.string().min(1), listId: exports_external.string().min(1), listItemId: exports_external.string().min(1) });
27462
- var { execute: execute139, schema: schema139 } = buildNoSkipListCommand((p) => `/sites/${p.siteId}/lists/${p.listId}/items/${p.listItemId}/versions`, baseSchema71);
27463
- var meta141 = {
27616
+ var { execute: execute140, schema: schema140 } = buildNoSkipListCommand((p) => `/sites/${p.siteId}/lists/${p.listId}/items/${p.listItemId}/versions`, baseSchema71);
27617
+ var meta142 = {
27464
27618
  summary: "List the version history of a SharePoint list item — every change (column edits, status flips, custom-field changes) tracked as a `listItemVersion`. Distinct from `list-drive-item-versions`, which tracks file content versions.",
27465
27619
  category: "sharepoint",
27466
27620
  graphMethod: "GET",
@@ -27497,13 +27651,13 @@ var meta141 = {
27497
27651
  // src/use-cases/commands/get-mail-rule.ts
27498
27652
  var exports_get_mail_rule = {};
27499
27653
  __export(exports_get_mail_rule, {
27500
- schema: () => schema140,
27501
- meta: () => meta142,
27502
- execute: () => execute140
27654
+ schema: () => schema141,
27655
+ meta: () => meta143,
27656
+ execute: () => execute141
27503
27657
  });
27504
- var schema140 = exports_external.object({ mailFolderId: exports_external.string().min(1).default("inbox"), messageRuleId: exports_external.string().min(1) });
27505
- var { execute: execute140 } = buildCommand((p) => `/me/mailFolders/${p.mailFolderId}/messageRules/${p.messageRuleId}`, schema140);
27506
- var meta142 = {
27658
+ var schema141 = exports_external.object({ mailFolderId: exports_external.string().min(1).default("inbox"), messageRuleId: exports_external.string().min(1) });
27659
+ var { execute: execute141 } = buildCommand((p) => `/me/mailFolders/${p.mailFolderId}/messageRules/${p.messageRuleId}`, schema141);
27660
+ var meta143 = {
27507
27661
  summary: "Return a single Outlook message rule by ID, including its conditions and actions. Sibling to `list-mail-rules`. `--mail-folder-id` defaults to `inbox` (the only folder where rules actually live in Graph); the flag is preserved for callers that want to pass a resolved Inbox ID explicitly.",
27508
27662
  category: "mail",
27509
27663
  graphMethod: "GET",
@@ -27534,15 +27688,15 @@ var meta142 = {
27534
27688
  // src/use-cases/commands/list-excel-comments.ts
27535
27689
  var exports_list_excel_comments = {};
27536
27690
  __export(exports_list_excel_comments, {
27537
- schema: () => schema141,
27538
- meta: () => meta143,
27539
- execute: () => execute141
27691
+ schema: () => schema142,
27692
+ meta: () => meta144,
27693
+ execute: () => execute142
27540
27694
  });
27541
27695
  var baseSchema72 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
27542
27696
  var inner12 = buildListCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/workbook/comments`, baseSchema72);
27543
- var execute141 = wrapExcelExecute(inner12.execute);
27544
- var { schema: schema141 } = inner12;
27545
- var meta143 = {
27697
+ var execute142 = wrapExcelExecute(inner12.execute);
27698
+ var { schema: schema142 } = inner12;
27699
+ var meta144 = {
27546
27700
  summary: "List the modern threaded comments anchored to cells in an Excel workbook (the New Comments feature, distinct from legacy notes). Each `workbookComment` has `content`, `contentType`, `task` state, plus replies via the comment's `replies` navigation.",
27547
27701
  category: "excel",
27548
27702
  graphMethod: "GET",
@@ -27571,15 +27725,15 @@ var meta143 = {
27571
27725
  // src/use-cases/commands/list-excel-worksheet-pivot-tables.ts
27572
27726
  var exports_list_excel_worksheet_pivot_tables = {};
27573
27727
  __export(exports_list_excel_worksheet_pivot_tables, {
27574
- schema: () => schema142,
27575
- meta: () => meta144,
27576
- execute: () => execute142
27728
+ schema: () => schema143,
27729
+ meta: () => meta145,
27730
+ execute: () => execute143
27577
27731
  });
27578
27732
  var baseSchema73 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1), worksheetId: exports_external.string().min(1) });
27579
27733
  var inner13 = buildListCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/workbook/worksheets/${p.worksheetId}/pivotTables`, baseSchema73);
27580
- var execute142 = wrapExcelExecute(inner13.execute);
27581
- var { schema: schema142 } = inner13;
27582
- var meta144 = {
27734
+ var execute143 = wrapExcelExecute(inner13.execute);
27735
+ var { schema: schema143 } = inner13;
27736
+ var meta145 = {
27583
27737
  summary: "List the pivot tables on a worksheet. Each `workbookPivotTable` has `name` and a navigation to its source `workbookWorksheet`. Useful for understanding analytical structure inside a workbook.",
27584
27738
  category: "excel",
27585
27739
  graphMethod: "GET",
@@ -27615,13 +27769,13 @@ var meta144 = {
27615
27769
  // src/use-cases/commands/list-sensitivity-labels.ts
27616
27770
  var exports_list_sensitivity_labels = {};
27617
27771
  __export(exports_list_sensitivity_labels, {
27618
- schema: () => schema143,
27619
- meta: () => meta145,
27620
- execute: () => execute143
27772
+ schema: () => schema144,
27773
+ meta: () => meta146,
27774
+ execute: () => execute144
27621
27775
  });
27622
27776
  var baseSchema74 = exports_external.object({}).strict();
27623
- var { execute: execute143, schema: schema143 } = buildListCommand(() => "/me/informationProtection/sensitivityLabels", baseSchema74);
27624
- var meta145 = {
27777
+ var { execute: execute144, schema: schema144 } = buildListCommand(() => "/me/informationProtection/sensitivityLabels", baseSchema74);
27778
+ var meta146 = {
27625
27779
  summary: 'List the Microsoft Information Protection sensitivity labels available to the signed-in user — the labels Outlook / Word / SharePoint surfaces in the "Sensitivity" picker (e.g. Public / Internal / Confidential / Highly Confidential). Each label has `id`, `displayName`, `priority`, `isAppliable`, `tooltip`.',
27626
27780
  category: "user",
27627
27781
  graphMethod: "GET",
@@ -27636,13 +27790,13 @@ var meta145 = {
27636
27790
  // src/use-cases/commands/list-my-transitive-memberships.ts
27637
27791
  var exports_list_my_transitive_memberships = {};
27638
27792
  __export(exports_list_my_transitive_memberships, {
27639
- schema: () => schema144,
27640
- meta: () => meta146,
27641
- execute: () => execute144
27793
+ schema: () => schema145,
27794
+ meta: () => meta147,
27795
+ execute: () => execute145
27642
27796
  });
27643
27797
  var baseSchema75 = exports_external.object({}).strict();
27644
- var { execute: execute144, schema: schema144 } = buildListCommand(() => "/me/transitiveMemberOf", baseSchema75);
27645
- var meta146 = {
27798
+ var { execute: execute145, schema: schema145 } = buildListCommand(() => "/me/transitiveMemberOf", baseSchema75);
27799
+ var meta147 = {
27646
27800
  summary: "List all groups, directory roles, and administrative units the signed-in user is a member of *transitively* — including memberships inherited via nested groups. Sibling to `list-my-memberships` (`/me/memberOf`) which only returns direct memberships.",
27647
27801
  category: "user",
27648
27802
  graphMethod: "GET",
@@ -27657,13 +27811,13 @@ var meta146 = {
27657
27811
  // src/use-cases/commands/get-team-primary-channel.ts
27658
27812
  var exports_get_team_primary_channel = {};
27659
27813
  __export(exports_get_team_primary_channel, {
27660
- schema: () => schema145,
27661
- meta: () => meta147,
27662
- execute: () => execute145
27814
+ schema: () => schema146,
27815
+ meta: () => meta148,
27816
+ execute: () => execute146
27663
27817
  });
27664
27818
  var baseSchema76 = exports_external.object({ teamId: exports_external.string().min(1) });
27665
- var { execute: execute145, schema: schema145 } = buildSelectableCommand((p) => `/teams/${p.teamId}/primaryChannel`, baseSchema76);
27666
- var meta147 = {
27819
+ var { execute: execute146, schema: schema146 } = buildSelectableCommand((p) => `/teams/${p.teamId}/primaryChannel`, baseSchema76);
27820
+ var meta148 = {
27667
27821
  summary: "Return the team's primary (General) channel directly without having to list-then-pick. The returned `channel` has `id`, `displayName`, `webUrl`, `email` — feed `id` into `list-team-channels` siblings or `get-channel-files-folder`.",
27668
27822
  category: "teams",
27669
27823
  graphMethod: "GET",
@@ -27686,13 +27840,13 @@ var meta147 = {
27686
27840
  // src/use-cases/commands/list-todo-tasks-delta.ts
27687
27841
  var exports_list_todo_tasks_delta = {};
27688
27842
  __export(exports_list_todo_tasks_delta, {
27689
- schema: () => schema146,
27690
- meta: () => meta148,
27691
- execute: () => execute146
27843
+ schema: () => schema147,
27844
+ meta: () => meta149,
27845
+ execute: () => execute147
27692
27846
  });
27693
- var schema146 = exports_external.object({ todoTaskListId: exports_external.string().min(1) });
27694
- var { execute: execute146 } = buildCommand((p) => `/me/todo/lists/${p.todoTaskListId}/tasks/delta()`, schema146);
27695
- var meta148 = {
27847
+ var schema147 = exports_external.object({ todoTaskListId: exports_external.string().min(1) });
27848
+ var { execute: execute147 } = buildCommand((p) => `/me/todo/lists/${p.todoTaskListId}/tasks/delta()`, schema147);
27849
+ var meta149 = {
27696
27850
  summary: "Track incremental task changes (added / updated / completed / deleted) within a single Microsoft To Do list. The first call returns the current snapshot plus `@odata.deltaLink`; subsequent calls with that link return only what has changed since. Note: Graph rejects standard OData query parameters on this delta endpoint (the page-cap flag throws `Skip token is not provided`), so the OData passthrough is intentionally NOT exposed here. Use `next-page` with the returned `@odata.nextLink` to walk pages.",
27697
27851
  category: "tasks",
27698
27852
  graphMethod: "GET",
@@ -27720,13 +27874,13 @@ var meta148 = {
27720
27874
  // src/use-cases/commands/list-my-memberships.ts
27721
27875
  var exports_list_my_memberships = {};
27722
27876
  __export(exports_list_my_memberships, {
27723
- schema: () => schema147,
27724
- meta: () => meta149,
27725
- execute: () => execute147
27877
+ schema: () => schema148,
27878
+ meta: () => meta150,
27879
+ execute: () => execute148
27726
27880
  });
27727
27881
  var baseSchema77 = exports_external.object({}).strict();
27728
- var { execute: execute147, schema: schema147 } = buildListCommand(() => "/me/memberOf", baseSchema77);
27729
- var meta149 = {
27882
+ var { execute: execute148, schema: schema148 } = buildListCommand(() => "/me/memberOf", baseSchema77);
27883
+ var meta150 = {
27730
27884
  summary: "List the groups, directory roles, and administrative units the signed-in user is a member of. Each entry's `@odata.type` distinguishes #microsoft.graph.group from #microsoft.graph.directoryRole, etc.",
27731
27885
  category: "user",
27732
27886
  graphMethod: "GET",
@@ -27741,13 +27895,13 @@ var meta149 = {
27741
27895
  // src/use-cases/commands/get-my-manager.ts
27742
27896
  var exports_get_my_manager = {};
27743
27897
  __export(exports_get_my_manager, {
27744
- schema: () => schema148,
27745
- meta: () => meta150,
27746
- execute: () => execute148
27898
+ schema: () => schema149,
27899
+ meta: () => meta151,
27900
+ execute: () => execute149
27747
27901
  });
27748
- var schema148 = exports_external.object({}).extend(selectExpandSchema.shape);
27749
- var execute148 = async (graph, params) => {
27750
- const parsed = schema148.safeParse(params);
27902
+ var schema149 = exports_external.object({}).extend(selectExpandSchema.shape);
27903
+ var execute149 = async (graph, params) => {
27904
+ const parsed = schema149.safeParse(params);
27751
27905
  if (!parsed.success)
27752
27906
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
27753
27907
  const path = appendOData("/me/manager", parsed.data);
@@ -27759,7 +27913,7 @@ var execute148 = async (graph, params) => {
27759
27913
  }
27760
27914
  return result;
27761
27915
  };
27762
- var meta150 = {
27916
+ var meta151 = {
27763
27917
  summary: "Return the signed-in user's manager (a single `user` resource). When no manager is set in the directory, Graph returns 404 `Request_ResourceNotFound`; this command maps that one specific 404 to `{ ok: true, data: { manager: null, note: '...' } }` so an LLM can distinguish 'no manager' from a permission failure without parsing prose. Use `--select` to slim the response (e.g. `--select id,displayName,mail`).",
27764
27918
  category: "user",
27765
27919
  graphMethod: "GET",
@@ -27771,15 +27925,15 @@ var meta150 = {
27771
27925
  };
27772
27926
 
27773
27927
  // src/use-cases/commands/get-user-manager.ts
27774
- var exports_get_user_manager = {};
27775
- __export(exports_get_user_manager, {
27776
- schema: () => schema149,
27777
- meta: () => meta151,
27778
- execute: () => execute149
27928
+ var exports_get_user_manager = {};
27929
+ __export(exports_get_user_manager, {
27930
+ schema: () => schema150,
27931
+ meta: () => meta152,
27932
+ execute: () => execute150
27779
27933
  });
27780
- var schema149 = exports_external.object({ userId: exports_external.string().min(1) }).extend(selectExpandSchema.shape);
27781
- var execute149 = async (graph, params) => {
27782
- const parsed = schema149.safeParse(params);
27934
+ var schema150 = exports_external.object({ userId: exports_external.string().min(1) }).extend(selectExpandSchema.shape);
27935
+ var execute150 = async (graph, params) => {
27936
+ const parsed = schema150.safeParse(params);
27783
27937
  if (!parsed.success)
27784
27938
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
27785
27939
  const path = appendOData(`/users/${parsed.data.userId}/manager`, parsed.data);
@@ -27791,7 +27945,7 @@ var execute149 = async (graph, params) => {
27791
27945
  }
27792
27946
  return result;
27793
27947
  };
27794
- var meta151 = {
27948
+ var meta152 = {
27795
27949
  summary: "Return a specific user's manager (a single `user` resource). When the user has no manager set in the directory, Graph returns 404 `Request_ResourceNotFound`; this command maps that one specific 404 to `{ ok: true, data: { manager: null, note: '...' } }` (same shape as `get-my-manager`) so an LLM can distinguish 'no manager' from 'unknown user' with a single discriminator across both commands. Use `--select` to slim the response.",
27796
27950
  category: "user",
27797
27951
  graphMethod: "GET",
@@ -27814,13 +27968,13 @@ var meta151 = {
27814
27968
  // src/use-cases/commands/list-relevant-people.ts
27815
27969
  var exports_list_relevant_people = {};
27816
27970
  __export(exports_list_relevant_people, {
27817
- schema: () => schema150,
27818
- meta: () => meta152,
27819
- execute: () => execute150
27971
+ schema: () => schema151,
27972
+ meta: () => meta153,
27973
+ execute: () => execute151
27820
27974
  });
27821
27975
  var baseSchema78 = exports_external.object({}).strict();
27822
- var { execute: execute150, schema: schema150 } = buildListCommand(() => "/me/people", baseSchema78);
27823
- var meta152 = {
27976
+ var { execute: execute151, schema: schema151 } = buildListCommand(() => "/me/people", baseSchema78);
27977
+ var meta153 = {
27824
27978
  summary: "List people relevant to the signed-in user — colleagues they email and meet with most. Microsoft's relevance ranking, not the full directory. Returns `displayName`, `emailAddresses`, `jobTitle`, `companyName`, etc.",
27825
27979
  category: "user",
27826
27980
  graphMethod: "GET",
@@ -27835,13 +27989,13 @@ var meta152 = {
27835
27989
  // src/use-cases/commands/list-groups.ts
27836
27990
  var exports_list_groups = {};
27837
27991
  __export(exports_list_groups, {
27838
- schema: () => schema151,
27839
- meta: () => meta153,
27840
- execute: () => execute151
27992
+ schema: () => schema152,
27993
+ meta: () => meta154,
27994
+ execute: () => execute152
27841
27995
  });
27842
27996
  var baseSchema79 = exports_external.object({}).strict();
27843
- var { execute: execute151, schema: schema151 } = buildNoSkipListCommand(() => "/groups", baseSchema79);
27844
- var meta153 = {
27997
+ var { execute: execute152, schema: schema152 } = buildNoSkipListCommand(() => "/groups", baseSchema79);
27998
+ var meta154 = {
27845
27999
  summary: "List Microsoft 365 groups, security groups, and distribution groups in the tenant directory. Use `--top` and `next-page` to paginate over very large directories.",
27846
28000
  category: "user",
27847
28001
  graphMethod: "GET",
@@ -27857,13 +28011,13 @@ var meta153 = {
27857
28011
  // src/use-cases/commands/get-group.ts
27858
28012
  var exports_get_group = {};
27859
28013
  __export(exports_get_group, {
27860
- schema: () => schema152,
27861
- meta: () => meta154,
27862
- execute: () => execute152
28014
+ schema: () => schema153,
28015
+ meta: () => meta155,
28016
+ execute: () => execute153
27863
28017
  });
27864
28018
  var baseSchema80 = exports_external.object({ groupId: exports_external.string().min(1) });
27865
- var { execute: execute152, schema: schema152 } = buildSelectableCommand((p) => `/groups/${p.groupId}`, baseSchema80);
27866
- var meta154 = {
28019
+ var { execute: execute153, schema: schema153 } = buildSelectableCommand((p) => `/groups/${p.groupId}`, baseSchema80);
28020
+ var meta155 = {
27867
28021
  summary: "Return metadata for a single Azure AD / Microsoft 365 group. Use `--select` to slim large group payloads (the full group resource includes 30+ fields).",
27868
28022
  category: "user",
27869
28023
  graphMethod: "GET",
@@ -27886,13 +28040,13 @@ var meta154 = {
27886
28040
  // src/use-cases/commands/list-group-members.ts
27887
28041
  var exports_list_group_members = {};
27888
28042
  __export(exports_list_group_members, {
27889
- schema: () => schema153,
27890
- meta: () => meta155,
27891
- execute: () => execute153
28043
+ schema: () => schema154,
28044
+ meta: () => meta156,
28045
+ execute: () => execute154
27892
28046
  });
27893
28047
  var baseSchema81 = exports_external.object({ groupId: exports_external.string().min(1) });
27894
- var { execute: execute153, schema: schema153 } = buildListCommand((p) => `/groups/${p.groupId}/members`, baseSchema81);
27895
- var meta155 = {
28048
+ var { execute: execute154, schema: schema154 } = buildListCommand((p) => `/groups/${p.groupId}/members`, baseSchema81);
28049
+ var meta156 = {
27896
28050
  summary: "List members of an Azure AD / Microsoft 365 group. Returns users, groups, and other directoryObjects depending on the group's membership.",
27897
28051
  category: "user",
27898
28052
  graphMethod: "GET",
@@ -27916,13 +28070,13 @@ var meta155 = {
27916
28070
  // src/use-cases/commands/list-group-owners.ts
27917
28071
  var exports_list_group_owners = {};
27918
28072
  __export(exports_list_group_owners, {
27919
- schema: () => schema154,
27920
- meta: () => meta156,
27921
- execute: () => execute154
28073
+ schema: () => schema155,
28074
+ meta: () => meta157,
28075
+ execute: () => execute155
27922
28076
  });
27923
28077
  var baseSchema82 = exports_external.object({ groupId: exports_external.string().min(1) });
27924
- var { execute: execute154, schema: schema154 } = buildListCommand((p) => `/groups/${p.groupId}/owners`, baseSchema82);
27925
- var meta156 = {
28078
+ var { execute: execute155, schema: schema155 } = buildListCommand((p) => `/groups/${p.groupId}/owners`, baseSchema82);
28079
+ var meta157 = {
27926
28080
  summary: "List the owners of an Azure AD / Microsoft 365 group.",
27927
28081
  category: "user",
27928
28082
  graphMethod: "GET",
@@ -27946,13 +28100,13 @@ var meta156 = {
27946
28100
  // src/use-cases/commands/list-group-events.ts
27947
28101
  var exports_list_group_events = {};
27948
28102
  __export(exports_list_group_events, {
27949
- schema: () => schema155,
27950
- meta: () => meta157,
27951
- execute: () => execute155
28103
+ schema: () => schema156,
28104
+ meta: () => meta158,
28105
+ execute: () => execute156
27952
28106
  });
27953
28107
  var baseSchema83 = exports_external.object({ groupId: exports_external.string().min(1) });
27954
- var { execute: execute155, schema: schema155 } = buildListCommand((p) => `/groups/${p.groupId}/events`, baseSchema83);
27955
- var meta157 = {
28108
+ var { execute: execute156, schema: schema156 } = buildListCommand((p) => `/groups/${p.groupId}/events`, baseSchema83);
28109
+ var meta158 = {
27956
28110
  summary: "List events from a unified (Microsoft 365) group's calendar. Only Microsoft 365 groups have a calendar — security and distribution groups return an empty `value[]` or 404.",
27957
28111
  category: "calendar",
27958
28112
  graphMethod: "GET",
@@ -27976,13 +28130,13 @@ var meta157 = {
27976
28130
  // src/use-cases/commands/get-group-calendar-view.ts
27977
28131
  var exports_get_group_calendar_view = {};
27978
28132
  __export(exports_get_group_calendar_view, {
27979
- schema: () => schema156,
27980
- meta: () => meta158,
27981
- execute: () => execute156
28133
+ schema: () => schema157,
28134
+ meta: () => meta159,
28135
+ execute: () => execute157
27982
28136
  });
27983
28137
  var baseSchema84 = exports_external.object({ groupId: exports_external.string().min(1), startDateTime: isoDateTimeField, endDateTime: isoDateTimeField });
27984
- var { execute: execute156, schema: schema156 } = buildListCommand((p) => `/groups/${p.groupId}/calendarView?startDateTime=${encodeURIComponent(p.startDateTime)}&endDateTime=${encodeURIComponent(p.endDateTime)}`, baseSchema84);
27985
- var meta158 = {
28138
+ var { execute: execute157, schema: schema157 } = buildListCommand((p) => `/groups/${p.groupId}/calendarView?startDateTime=${encodeURIComponent(p.startDateTime)}&endDateTime=${encodeURIComponent(p.endDateTime)}`, baseSchema84);
28139
+ var meta159 = {
27986
28140
  summary: "Return a date-windowed calendar view from a unified (Microsoft 365) group's calendar. Recurring events are expanded into individual occurrences across the window. Only Microsoft 365 groups have a calendar — security and distribution groups return `MailboxNotEnabledForRESTAPI`.",
27987
28141
  category: "calendar",
27988
28142
  graphMethod: "GET",
@@ -28014,13 +28168,13 @@ var meta158 = {
28014
28168
  // src/use-cases/commands/list-group-conversations.ts
28015
28169
  var exports_list_group_conversations = {};
28016
28170
  __export(exports_list_group_conversations, {
28017
- schema: () => schema157,
28018
- meta: () => meta159,
28019
- execute: () => execute157
28171
+ schema: () => schema158,
28172
+ meta: () => meta160,
28173
+ execute: () => execute158
28020
28174
  });
28021
28175
  var baseSchema85 = exports_external.object({ groupId: exports_external.string().min(1) });
28022
- var { execute: execute157, schema: schema157 } = buildListCommand((p) => `/groups/${p.groupId}/conversations`, baseSchema85);
28023
- var meta159 = {
28176
+ var { execute: execute158, schema: schema158 } = buildListCommand((p) => `/groups/${p.groupId}/conversations`, baseSchema85);
28177
+ var meta160 = {
28024
28178
  summary: "List conversations in a unified (Microsoft 365) group inbox. Each conversation aggregates one or more threads. Only Microsoft 365 groups have a mailbox — security and distribution groups return `MailboxNotEnabledForRESTAPI`. Verify the group is unified before calling.",
28025
28179
  category: "mail",
28026
28180
  graphMethod: "GET",
@@ -28044,13 +28198,13 @@ var meta159 = {
28044
28198
  // src/use-cases/commands/list-group-threads.ts
28045
28199
  var exports_list_group_threads = {};
28046
28200
  __export(exports_list_group_threads, {
28047
- schema: () => schema158,
28048
- meta: () => meta160,
28049
- execute: () => execute158
28201
+ schema: () => schema159,
28202
+ meta: () => meta161,
28203
+ execute: () => execute159
28050
28204
  });
28051
28205
  var baseSchema86 = exports_external.object({ groupId: exports_external.string().min(1) });
28052
- var { execute: execute158, schema: schema158 } = buildListCommand((p) => `/groups/${p.groupId}/threads`, baseSchema86);
28053
- var meta160 = {
28206
+ var { execute: execute159, schema: schema159 } = buildListCommand((p) => `/groups/${p.groupId}/threads`, baseSchema86);
28207
+ var meta161 = {
28054
28208
  summary: "List threads in a unified (Microsoft 365) group inbox. Threads are flatter than conversations — one per topic, useful when conversation-level grouping isn't needed. Only Microsoft 365 groups have a mailbox — security and distribution groups return `MailboxNotEnabledForRESTAPI`.",
28055
28209
  category: "mail",
28056
28210
  graphMethod: "GET",
@@ -28074,18 +28228,18 @@ var meta160 = {
28074
28228
  // src/use-cases/commands/get-mail-message-mime.ts
28075
28229
  var exports_get_mail_message_mime = {};
28076
28230
  __export(exports_get_mail_message_mime, {
28077
- schema: () => schema159,
28078
- meta: () => meta161,
28079
- execute: () => execute159
28231
+ schema: () => schema160,
28232
+ meta: () => meta162,
28233
+ execute: () => execute160
28080
28234
  });
28081
- var schema159 = exports_external.object({ messageId: exports_external.string().min(1) });
28082
- var execute159 = async (graph, params) => {
28083
- const parsed = schema159.safeParse(params);
28235
+ var schema160 = exports_external.object({ messageId: exports_external.string().min(1) });
28236
+ var execute160 = async (graph, params) => {
28237
+ const parsed = schema160.safeParse(params);
28084
28238
  if (!parsed.success)
28085
28239
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
28086
28240
  return inlineBinary(graph, `/me/messages/${parsed.data.messageId}/$value`);
28087
28241
  };
28088
- var meta161 = {
28242
+ var meta162 = {
28089
28243
  summary: "Return the raw RFC 5322 MIME source of a single Outlook message — full headers, every attachment encoded inline. Useful for archiving, full-fidelity forensic inspection, or feeding into a tool that reads MIME directly. For human-readable content prefer `get-mail-message` or `convert-mail-to-markdown`.",
28090
28244
  category: "mail",
28091
28245
  graphMethod: "GET",
@@ -28108,13 +28262,13 @@ var meta161 = {
28108
28262
  // src/use-cases/commands/list-mail-folder-messages-delta.ts
28109
28263
  var exports_list_mail_folder_messages_delta = {};
28110
28264
  __export(exports_list_mail_folder_messages_delta, {
28111
- schema: () => schema160,
28112
- meta: () => meta162,
28113
- execute: () => execute160
28265
+ schema: () => schema161,
28266
+ meta: () => meta163,
28267
+ execute: () => execute161
28114
28268
  });
28115
28269
  var baseSchema87 = exports_external.object({ mailFolderId: exports_external.string().min(1) });
28116
- var { execute: execute160, schema: schema160 } = buildListCommand((p) => `/me/mailFolders/${p.mailFolderId}/messages/delta()`, baseSchema87);
28117
- var meta162 = {
28270
+ var { execute: execute161, schema: schema161 } = buildListCommand((p) => `/me/mailFolders/${p.mailFolderId}/messages/delta()`, baseSchema87);
28271
+ var meta163 = {
28118
28272
  summary: "Track incremental changes (added / updated / deleted messages) within a single mail folder using Microsoft Graph delta tokens. The first call returns the current snapshot plus a `@odata.deltaLink`; subsequent calls with that link return only what has changed since.",
28119
28273
  category: "mail",
28120
28274
  graphMethod: "GET",
@@ -28139,13 +28293,13 @@ var meta162 = {
28139
28293
  // src/use-cases/commands/list-shared-mailbox-messages.ts
28140
28294
  var exports_list_shared_mailbox_messages = {};
28141
28295
  __export(exports_list_shared_mailbox_messages, {
28142
- schema: () => schema161,
28143
- meta: () => meta163,
28144
- execute: () => execute161
28296
+ schema: () => schema162,
28297
+ meta: () => meta164,
28298
+ execute: () => execute162
28145
28299
  });
28146
28300
  var baseSchema88 = exports_external.object({ userId: exports_external.string().min(1) });
28147
- var { execute: execute161, schema: schema161 } = buildListCommand((p) => `/users/${p.userId}/messages`, baseSchema88);
28148
- var meta163 = {
28301
+ var { execute: execute162, schema: schema162 } = buildListCommand((p) => `/users/${p.userId}/messages`, baseSchema88);
28302
+ var meta164 = {
28149
28303
  summary: "List messages from a shared or delegated mailbox the signed-in user has read access to. Same shape as `list-mail-messages` but scoped to a specific mailbox owner. 403 if the signed-in user does not have shared access to that mailbox.",
28150
28304
  category: "mail",
28151
28305
  graphMethod: "GET",
@@ -28169,13 +28323,13 @@ var meta163 = {
28169
28323
  // src/use-cases/commands/list-shared-mailbox-folder-messages.ts
28170
28324
  var exports_list_shared_mailbox_folder_messages = {};
28171
28325
  __export(exports_list_shared_mailbox_folder_messages, {
28172
- schema: () => schema162,
28173
- meta: () => meta164,
28174
- execute: () => execute162
28326
+ schema: () => schema163,
28327
+ meta: () => meta165,
28328
+ execute: () => execute163
28175
28329
  });
28176
28330
  var baseSchema89 = exports_external.object({ userId: exports_external.string().min(1), mailFolderId: exports_external.string().min(1) });
28177
- var { execute: execute162, schema: schema162 } = buildListCommand((p) => `/users/${p.userId}/mailFolders/${p.mailFolderId}/messages`, baseSchema89);
28178
- var meta164 = {
28331
+ var { execute: execute163, schema: schema163 } = buildListCommand((p) => `/users/${p.userId}/mailFolders/${p.mailFolderId}/messages`, baseSchema89);
28332
+ var meta165 = {
28179
28333
  summary: "List messages in a single folder of a shared / delegated mailbox.",
28180
28334
  category: "mail",
28181
28335
  graphMethod: "GET",
@@ -28204,13 +28358,13 @@ var meta164 = {
28204
28358
  // src/use-cases/commands/get-shared-mailbox-message.ts
28205
28359
  var exports_get_shared_mailbox_message = {};
28206
28360
  __export(exports_get_shared_mailbox_message, {
28207
- schema: () => schema163,
28208
- meta: () => meta165,
28209
- execute: () => execute163
28361
+ schema: () => schema164,
28362
+ meta: () => meta166,
28363
+ execute: () => execute164
28210
28364
  });
28211
28365
  var baseSchema90 = exports_external.object({ userId: exports_external.string().min(1), messageId: exports_external.string().min(1) });
28212
- var { execute: execute163, schema: schema163 } = buildSelectableCommand((p) => `/users/${p.userId}/messages/${p.messageId}`, baseSchema90);
28213
- var meta165 = {
28366
+ var { execute: execute164, schema: schema164 } = buildSelectableCommand((p) => `/users/${p.userId}/messages/${p.messageId}`, baseSchema90);
28367
+ var meta166 = {
28214
28368
  summary: "Return a single message from a shared / delegated mailbox. Use `--select` to fetch only specific fields (e.g. `--select id,subject,from,receivedDateTime`) — sibling to `get-mail-message` for /me.",
28215
28369
  category: "mail",
28216
28370
  graphMethod: "GET",
@@ -28238,22 +28392,22 @@ var meta165 = {
28238
28392
  // src/use-cases/commands/list-conversation-messages.ts
28239
28393
  var exports_list_conversation_messages = {};
28240
28394
  __export(exports_list_conversation_messages, {
28241
- schema: () => schema164,
28242
- meta: () => meta166,
28243
- execute: () => execute164
28395
+ schema: () => schema165,
28396
+ meta: () => meta167,
28397
+ execute: () => execute165
28244
28398
  });
28245
28399
  var allowedShape = Object.fromEntries(Object.entries(odataQuerySchema.shape).filter(([key]) => key !== "filter" && key !== "orderby"));
28246
28400
  var allowedOptions = odataQueryOptions.filter((o) => o.name !== "filter" && o.name !== "orderby");
28247
- var schema164 = exports_external.object({ conversationId: exports_external.string().min(1) }).extend(allowedShape);
28248
- var execute164 = async (graph, params) => {
28249
- const parsed = schema164.safeParse(params);
28401
+ var schema165 = exports_external.object({ conversationId: exports_external.string().min(1) }).extend(allowedShape);
28402
+ var execute165 = async (graph, params) => {
28403
+ const parsed = schema165.safeParse(params);
28250
28404
  if (!parsed.success)
28251
28405
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
28252
28406
  const escaped = parsed.data.conversationId.replace(/'/g, "''");
28253
28407
  const path = appendOData(`/me/messages?$filter=conversationId eq '${escaped}'`, parsed.data);
28254
28408
  return graph.get(path);
28255
28409
  };
28256
- var meta166 = {
28410
+ var meta167 = {
28257
28411
  summary: "List every message in a single Outlook conversation (thread) using `$filter=conversationId eq '...'`. Reconstructs a complete thread regardless of which subject lines or folders the replies landed in. Accepts the OData passthrough flags top/skip/select/expand — the filter and orderby passthroughs are intentionally omitted (the path already pins a `$filter`, and Graph rejects this filter combined with `$orderby` as `InefficientFilter` since `conversationId` is not a sortable index). The caller can sort by `receivedDateTime` client-side. KQL `$search` does not index `conversationId`, so `$filter` is the only documented Graph idiom for whole-thread retrieval.",
28258
28412
  category: "mail",
28259
28413
  graphMethod: "GET",
@@ -28277,13 +28431,13 @@ var meta166 = {
28277
28431
  // src/use-cases/commands/list-focused-inbox-overrides.ts
28278
28432
  var exports_list_focused_inbox_overrides = {};
28279
28433
  __export(exports_list_focused_inbox_overrides, {
28280
- schema: () => schema165,
28281
- meta: () => meta167,
28282
- execute: () => execute165
28434
+ schema: () => schema166,
28435
+ meta: () => meta168,
28436
+ execute: () => execute166
28283
28437
  });
28284
28438
  var baseSchema91 = exports_external.object({}).strict();
28285
- var { execute: execute165, schema: schema165 } = buildListCommand(() => "/me/inferenceClassification/overrides", baseSchema91);
28286
- var meta167 = {
28439
+ var { execute: execute166, schema: schema166 } = buildListCommand(() => "/me/inferenceClassification/overrides", baseSchema91);
28440
+ var meta168 = {
28287
28441
  summary: "List the signed-in user's Focused Inbox classification overrides — sender addresses they've manually moved to Focused or Other, which override Microsoft's automatic classifier.",
28288
28442
  category: "mail",
28289
28443
  graphMethod: "GET",
@@ -28298,13 +28452,13 @@ var meta167 = {
28298
28452
  // src/use-cases/commands/list-outlook-categories.ts
28299
28453
  var exports_list_outlook_categories = {};
28300
28454
  __export(exports_list_outlook_categories, {
28301
- schema: () => schema166,
28302
- meta: () => meta168,
28303
- execute: () => execute166
28455
+ schema: () => schema167,
28456
+ meta: () => meta169,
28457
+ execute: () => execute167
28304
28458
  });
28305
- var schema166 = exports_external.object({}).strict();
28306
- var { execute: execute166 } = buildCommand(() => "/me/outlook/masterCategories", schema166);
28307
- var meta168 = {
28459
+ var schema167 = exports_external.object({}).strict();
28460
+ var { execute: execute167 } = buildCommand(() => "/me/outlook/masterCategories", schema167);
28461
+ var meta169 = {
28308
28462
  summary: "List the signed-in user's Outlook color categories — the named tags that can be applied to mail, calendar items, and contacts. Each entry has `displayName` and a `color` from Outlook's preset palette. Note: Graph silently ignores every OData passthrough on this endpoint (`$top`, `$skip`, `$select`, `$filter`, `$orderby`, `$expand`), so the CLI does not expose any of those flags — the full collection is always returned. Slice client-side.",
28309
28463
  category: "mail",
28310
28464
  graphMethod: "GET",
@@ -28318,13 +28472,13 @@ var meta168 = {
28318
28472
  // src/use-cases/commands/list-shared-calendar-events.ts
28319
28473
  var exports_list_shared_calendar_events = {};
28320
28474
  __export(exports_list_shared_calendar_events, {
28321
- schema: () => schema167,
28322
- meta: () => meta169,
28323
- execute: () => execute167
28475
+ schema: () => schema168,
28476
+ meta: () => meta170,
28477
+ execute: () => execute168
28324
28478
  });
28325
28479
  var baseSchema92 = exports_external.object({ userId: exports_external.string().min(1) });
28326
- var { execute: execute167, schema: schema167 } = buildListCommand((p) => `/users/${p.userId}/calendar/events`, baseSchema92);
28327
- var meta169 = {
28480
+ var { execute: execute168, schema: schema168 } = buildListCommand((p) => `/users/${p.userId}/calendar/events`, baseSchema92);
28481
+ var meta170 = {
28328
28482
  summary: "List events from another user's primary calendar (shared / delegated access). 403 without `Calendars.Read.Shared`.",
28329
28483
  category: "calendar",
28330
28484
  graphMethod: "GET",
@@ -28348,13 +28502,13 @@ var meta169 = {
28348
28502
  // src/use-cases/commands/get-shared-calendar-view.ts
28349
28503
  var exports_get_shared_calendar_view = {};
28350
28504
  __export(exports_get_shared_calendar_view, {
28351
- schema: () => schema168,
28352
- meta: () => meta170,
28353
- execute: () => execute168
28505
+ schema: () => schema169,
28506
+ meta: () => meta171,
28507
+ execute: () => execute169
28354
28508
  });
28355
28509
  var baseSchema93 = exports_external.object({ userId: exports_external.string().min(1), startDateTime: isoDateTimeField, endDateTime: isoDateTimeField });
28356
- var { execute: execute168, schema: schema168 } = buildListCommand((p) => `/users/${p.userId}/calendarView?startDateTime=${encodeURIComponent(p.startDateTime)}&endDateTime=${encodeURIComponent(p.endDateTime)}`, baseSchema93);
28357
- var meta170 = {
28510
+ var { execute: execute169, schema: schema169 } = buildListCommand((p) => `/users/${p.userId}/calendarView?startDateTime=${encodeURIComponent(p.startDateTime)}&endDateTime=${encodeURIComponent(p.endDateTime)}`, baseSchema93);
28511
+ var meta171 = {
28358
28512
  summary: "Return a date-windowed calendar view from another user's primary calendar (shared / delegated access). Recurrences expanded into individual occurrences.",
28359
28513
  category: "calendar",
28360
28514
  graphMethod: "GET",
@@ -28380,13 +28534,13 @@ var meta170 = {
28380
28534
  // src/use-cases/commands/list-sharepoint-list-columns.ts
28381
28535
  var exports_list_sharepoint_list_columns = {};
28382
28536
  __export(exports_list_sharepoint_list_columns, {
28383
- schema: () => schema169,
28384
- meta: () => meta171,
28385
- execute: () => execute169
28537
+ schema: () => schema170,
28538
+ meta: () => meta172,
28539
+ execute: () => execute170
28386
28540
  });
28387
28541
  var baseSchema94 = exports_external.object({ siteId: exports_external.string().min(1), listId: exports_external.string().min(1) });
28388
- var { execute: execute169, schema: schema169 } = buildSelectableCommand((p) => `/sites/${p.siteId}/lists/${p.listId}/columns`, baseSchema94);
28389
- var meta171 = {
28542
+ var { execute: execute170, schema: schema170 } = buildSelectableCommand((p) => `/sites/${p.siteId}/lists/${p.listId}/columns`, baseSchema94);
28543
+ var meta172 = {
28390
28544
  summary: "List the column definitions (schema) of a SharePoint list. Useful before reading list items so you know which fields exist and their types. Note: Graph silently ignores `$top` and `$skip` on this endpoint, so the CLI exposes only `--select` and `--expand`.",
28391
28545
  category: "sharepoint",
28392
28546
  graphMethod: "GET",
@@ -28414,13 +28568,13 @@ var meta171 = {
28414
28568
  // src/use-cases/commands/get-sharepoint-list-column.ts
28415
28569
  var exports_get_sharepoint_list_column = {};
28416
28570
  __export(exports_get_sharepoint_list_column, {
28417
- schema: () => schema170,
28418
- meta: () => meta172,
28419
- execute: () => execute170
28571
+ schema: () => schema171,
28572
+ meta: () => meta173,
28573
+ execute: () => execute171
28420
28574
  });
28421
28575
  var baseSchema95 = exports_external.object({ siteId: exports_external.string().min(1), listId: exports_external.string().min(1), columnId: exports_external.string().min(1) });
28422
- var { execute: execute170, schema: schema170 } = buildSelectableCommand((p) => `/sites/${p.siteId}/lists/${p.listId}/columns/${p.columnId}`, baseSchema95);
28423
- var meta172 = {
28576
+ var { execute: execute171, schema: schema171 } = buildSelectableCommand((p) => `/sites/${p.siteId}/lists/${p.listId}/columns/${p.columnId}`, baseSchema95);
28577
+ var meta173 = {
28424
28578
  summary: "Return a single column definition from a SharePoint list.",
28425
28579
  category: "sharepoint",
28426
28580
  graphMethod: "GET",
@@ -28455,9 +28609,9 @@ var meta172 = {
28455
28609
  // src/use-cases/commands/list-sharepoint-site-onenote-notebooks.ts
28456
28610
  var exports_list_sharepoint_site_onenote_notebooks = {};
28457
28611
  __export(exports_list_sharepoint_site_onenote_notebooks, {
28458
- schema: () => schema171,
28459
- meta: () => meta173,
28460
- execute: () => execute171
28612
+ schema: () => schema172,
28613
+ meta: () => meta174,
28614
+ execute: () => execute172
28461
28615
  });
28462
28616
 
28463
28617
  // src/use-cases/commands/onenote-5k-limit.ts
@@ -28480,9 +28634,9 @@ var wrapOnenote5kLimit = (inner14) => async (graph, params) => {
28480
28634
  // src/use-cases/commands/list-sharepoint-site-onenote-notebooks.ts
28481
28635
  var baseSchema96 = exports_external.object({ siteId: exports_external.string().min(1) });
28482
28636
  var inner14 = buildListCommand((p) => `/sites/${p.siteId}/onenote/notebooks`, baseSchema96);
28483
- var execute171 = wrapOnenote5kLimit(inner14.execute);
28484
- var { schema: schema171 } = inner14;
28485
- var meta173 = {
28637
+ var execute172 = wrapOnenote5kLimit(inner14.execute);
28638
+ var { schema: schema172 } = inner14;
28639
+ var meta174 = {
28486
28640
  summary: "List OneNote notebooks attached to a SharePoint site (separate from the personal `list-onenote-notebooks` which targets `/me`).",
28487
28641
  category: "notes",
28488
28642
  graphMethod: "GET",
@@ -28506,15 +28660,15 @@ var meta173 = {
28506
28660
  // src/use-cases/commands/list-sharepoint-site-onenote-notebook-sections.ts
28507
28661
  var exports_list_sharepoint_site_onenote_notebook_sections = {};
28508
28662
  __export(exports_list_sharepoint_site_onenote_notebook_sections, {
28509
- schema: () => schema172,
28510
- meta: () => meta174,
28511
- execute: () => execute172
28663
+ schema: () => schema173,
28664
+ meta: () => meta175,
28665
+ execute: () => execute173
28512
28666
  });
28513
28667
  var baseSchema97 = exports_external.object({ siteId: exports_external.string().min(1), notebookId: exports_external.string().min(1) });
28514
28668
  var inner15 = buildListCommand((p) => `/sites/${p.siteId}/onenote/notebooks/${p.notebookId}/sections`, baseSchema97);
28515
- var execute172 = wrapOnenote5kLimit(inner15.execute);
28516
- var { schema: schema172 } = inner15;
28517
- var meta174 = {
28669
+ var execute173 = wrapOnenote5kLimit(inner15.execute);
28670
+ var { schema: schema173 } = inner15;
28671
+ var meta175 = {
28518
28672
  summary: "List sections inside one OneNote notebook attached to a SharePoint site.",
28519
28673
  category: "notes",
28520
28674
  graphMethod: "GET",
@@ -28543,15 +28697,15 @@ var meta174 = {
28543
28697
  // src/use-cases/commands/list-sharepoint-site-onenote-section-pages.ts
28544
28698
  var exports_list_sharepoint_site_onenote_section_pages = {};
28545
28699
  __export(exports_list_sharepoint_site_onenote_section_pages, {
28546
- schema: () => schema173,
28547
- meta: () => meta175,
28548
- execute: () => execute173
28700
+ schema: () => schema174,
28701
+ meta: () => meta176,
28702
+ execute: () => execute174
28549
28703
  });
28550
28704
  var baseSchema98 = exports_external.object({ siteId: exports_external.string().min(1), onenoteSectionId: exports_external.string().min(1) });
28551
28705
  var inner16 = buildListCommand((p) => `/sites/${p.siteId}/onenote/sections/${p.onenoteSectionId}/pages`, baseSchema98);
28552
- var execute173 = wrapOnenote5kLimit(inner16.execute);
28553
- var { schema: schema173 } = inner16;
28554
- var meta175 = {
28706
+ var execute174 = wrapOnenote5kLimit(inner16.execute);
28707
+ var { schema: schema174 } = inner16;
28708
+ var meta176 = {
28555
28709
  summary: "List pages inside one section of a SharePoint-site OneNote notebook.",
28556
28710
  category: "notes",
28557
28711
  graphMethod: "GET",
@@ -28581,19 +28735,19 @@ var meta175 = {
28581
28735
  // src/use-cases/commands/get-sharepoint-site-onenote-page-content.ts
28582
28736
  var exports_get_sharepoint_site_onenote_page_content = {};
28583
28737
  __export(exports_get_sharepoint_site_onenote_page_content, {
28584
- schema: () => schema174,
28585
- meta: () => meta176,
28586
- execute: () => execute174
28738
+ schema: () => schema175,
28739
+ meta: () => meta177,
28740
+ execute: () => execute175
28587
28741
  });
28588
- var schema174 = exports_external.object({ siteId: exports_external.string().min(1), onenotePageId: exports_external.string().min(1) });
28742
+ var schema175 = exports_external.object({ siteId: exports_external.string().min(1), onenotePageId: exports_external.string().min(1) });
28589
28743
  var innerExecute = async (graph, params) => {
28590
- const parsed = schema174.safeParse(params);
28744
+ const parsed = schema175.safeParse(params);
28591
28745
  if (!parsed.success)
28592
28746
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
28593
28747
  return graph.getBinary(`/sites/${parsed.data.siteId}/onenote/pages/${parsed.data.onenotePageId}/content`);
28594
28748
  };
28595
- var execute174 = wrapOnenote5kLimit(innerExecute);
28596
- var meta176 = {
28749
+ var execute175 = wrapOnenote5kLimit(innerExecute);
28750
+ var meta177 = {
28597
28751
  summary: "Return the HTML content of a single OneNote page from a SharePoint site (parallel to `get-onenote-page-content` for `/me`). The response carries the standard `{contentType: text/html, size, text}` shape so the HTML body is available verbatim under either output format.",
28598
28752
  category: "notes",
28599
28753
  graphMethod: "GET",
@@ -28622,13 +28776,13 @@ var meta176 = {
28622
28776
  // src/use-cases/commands/list-drive-item-thumbnails.ts
28623
28777
  var exports_list_drive_item_thumbnails = {};
28624
28778
  __export(exports_list_drive_item_thumbnails, {
28625
- schema: () => schema175,
28626
- meta: () => meta177,
28627
- execute: () => execute175
28779
+ schema: () => schema176,
28780
+ meta: () => meta178,
28781
+ execute: () => execute176
28628
28782
  });
28629
28783
  var baseSchema99 = exports_external.object({ driveId: exports_external.string().min(1), itemId: exports_external.string().min(1) });
28630
- var { execute: execute175, schema: schema175 } = buildNoSkipListCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/thumbnails`, baseSchema99);
28631
- var meta177 = {
28784
+ var { execute: execute176, schema: schema176 } = buildNoSkipListCommand((p) => `/drives/${p.driveId}/items/${p.itemId}/thumbnails`, baseSchema99);
28785
+ var meta178 = {
28632
28786
  summary: "List thumbnail URLs (small / medium / large) for a OneDrive / SharePoint file. Each thumbnail set has pre-signed CDN URLs you can render in a UI without further auth.",
28633
28787
  category: "drive",
28634
28788
  graphMethod: "GET",
@@ -28658,20 +28812,20 @@ var meta177 = {
28658
28812
  // src/use-cases/commands/get-excel-used-range.ts
28659
28813
  var exports_get_excel_used_range = {};
28660
28814
  __export(exports_get_excel_used_range, {
28661
- schema: () => schema176,
28662
- meta: () => meta178,
28663
- execute: () => execute176
28815
+ schema: () => schema177,
28816
+ meta: () => meta179,
28817
+ execute: () => execute177
28664
28818
  });
28665
28819
  var DEFAULT_MAX_CELLS2 = 50000;
28666
- var schema176 = exports_external.object({
28820
+ var schema177 = exports_external.object({
28667
28821
  driveId: exports_external.string().min(1),
28668
28822
  itemId: exports_external.string().min(1),
28669
28823
  worksheetId: exports_external.string().min(1),
28670
28824
  full: exports_external.enum(["true", "false"]).optional(),
28671
28825
  maxCells: exports_external.string().regex(/^[1-9]\d*$/, "must be a positive integer").optional()
28672
28826
  });
28673
- var execute176 = async (graph, params) => {
28674
- const parsed = schema176.safeParse(params);
28827
+ var execute177 = async (graph, params) => {
28828
+ const parsed = schema177.safeParse(params);
28675
28829
  if (!parsed.success)
28676
28830
  return err({ type: "validation_error", message: formatZodError(parsed.error) });
28677
28831
  const { driveId, itemId, worksheetId } = parsed.data;
@@ -28706,7 +28860,7 @@ var execute176 = async (graph, params) => {
28706
28860
  projection: "slim"
28707
28861
  });
28708
28862
  };
28709
- var meta178 = {
28863
+ var meta179 = {
28710
28864
  summary: 'Return the worksheet\'s used range — the bounding box of every non-empty cell — as a single Excel range. The CLI ships a slim default that strips the redundant `text` / `numberFormat` / `formulas` 2D arrays Graph returns (mostly `"General"` repeated cell-by-cell), keeping `address` / `rowCount` / `columnCount` / `values`. Pass `--full true` to return the raw four-array Graph shape. `--max-cells` (default 50 000) caps the size of the projected `values[]`; oversize ranges drop `values` and surface a hint pointing at `get-excel-range` for band-by-band reads. Avoids fetching the entire 1M × 16K-cell sheet when only a small data island is populated.',
28711
28865
  category: "excel",
28712
28866
  graphMethod: "GET",
@@ -28752,13 +28906,13 @@ var meta178 = {
28752
28906
  // src/use-cases/commands/list-rooms.ts
28753
28907
  var exports_list_rooms = {};
28754
28908
  __export(exports_list_rooms, {
28755
- schema: () => schema177,
28756
- meta: () => meta179,
28757
- execute: () => execute177
28909
+ schema: () => schema178,
28910
+ meta: () => meta180,
28911
+ execute: () => execute178
28758
28912
  });
28759
28913
  var baseSchema100 = exports_external.object({}).strict();
28760
- var { execute: execute177, schema: schema177 } = buildListCommand(() => "/places/microsoft.graph.room", baseSchema100);
28761
- var meta179 = {
28914
+ var { execute: execute178, schema: schema178 } = buildListCommand(() => "/places/microsoft.graph.room", baseSchema100);
28915
+ var meta180 = {
28762
28916
  summary: "List bookable meeting rooms in the tenant. Each `room` has `displayName`, `emailAddress`, `capacity`, `building`, `floorNumber`, and `isWheelChairAccessible`. Use the `emailAddress` as a meeting `attendee` for room booking. Pass `--top 5` to limit the response — large tenants return tens of KB by default.",
28763
28917
  category: "calendar",
28764
28918
  graphMethod: "GET",
@@ -28773,13 +28927,13 @@ var meta179 = {
28773
28927
  // src/use-cases/commands/list-room-lists.ts
28774
28928
  var exports_list_room_lists = {};
28775
28929
  __export(exports_list_room_lists, {
28776
- schema: () => schema178,
28777
- meta: () => meta180,
28778
- execute: () => execute178
28930
+ schema: () => schema179,
28931
+ meta: () => meta181,
28932
+ execute: () => execute179
28779
28933
  });
28780
28934
  var baseSchema101 = exports_external.object({}).strict();
28781
- var { execute: execute178, schema: schema178 } = buildListCommand(() => "/places/microsoft.graph.roomList", baseSchema101);
28782
- var meta180 = {
28935
+ var { execute: execute179, schema: schema179 } = buildListCommand(() => "/places/microsoft.graph.roomList", baseSchema101);
28936
+ var meta181 = {
28783
28937
  summary: "List room lists — usually one per building. Use these to scope a room search by location: a roomList groups the rooms in one office, then `/places/{roomList}/rooms` lists just those rooms. Pass `--top N` to limit the response on large tenants.",
28784
28938
  category: "calendar",
28785
28939
  graphMethod: "GET",
@@ -28794,13 +28948,13 @@ var meta180 = {
28794
28948
  // src/use-cases/commands/list-trending-insights.ts
28795
28949
  var exports_list_trending_insights = {};
28796
28950
  __export(exports_list_trending_insights, {
28797
- schema: () => schema179,
28798
- meta: () => meta181,
28799
- execute: () => execute179
28951
+ schema: () => schema180,
28952
+ meta: () => meta182,
28953
+ execute: () => execute180
28800
28954
  });
28801
28955
  var baseSchema102 = exports_external.object({}).strict();
28802
- var { execute: execute179, schema: schema179 } = buildListCommand(() => "/me/insights/trending", baseSchema102);
28803
- var meta181 = {
28956
+ var { execute: execute180, schema: schema180 } = buildListCommand(() => "/me/insights/trending", baseSchema102);
28957
+ var meta182 = {
28804
28958
  summary: "List documents trending around the signed-in user — files popular in their working network (colleagues' recent edits, shares, opens). Microsoft's relevance ranking, useful for surfacing unfamiliar but related work.",
28805
28959
  category: "drive",
28806
28960
  graphMethod: "GET",
@@ -28872,6 +29026,7 @@ var commands = {
28872
29026
  "extract-sharepoint-links-in-mail": exports_extract_sharepoint_links_in_mail,
28873
29027
  "extract-sharepoint-links-in-documents": exports_extract_sharepoint_links_in_documents,
28874
29028
  "convert-mail-to-markdown": exports_convert_mail_to_markdown,
29029
+ "create-forward-draft": exports_create_forward_draft,
28875
29030
  "create-mail-draft": exports_create_mail_draft,
28876
29031
  "create-reply-draft": exports_create_reply_draft,
28877
29032
  "update-mail-draft": exports_update_mail_draft,
@@ -28996,12 +29151,33 @@ var commands = {
28996
29151
  };
28997
29152
 
28998
29153
  // src/use-cases/commands/login.ts
28999
- var schema180 = exports_external.object({}).strict();
29000
- var execute180 = async (auth) => auth.getAccessToken();
29154
+ var schema181 = exports_external.object({}).strict();
29155
+ var execute181 = async (auth, options) => auth.getAccessToken(options);
29156
+
29157
+ // src/use-cases/commands/login-status.ts
29158
+ var HINT3 = "basic/chatsvcagg/ic3 refresh automatically from the cached refresh token; the elevated (M365) token is re-captured only on an interactive login. Run `ask-marcel-office login --force` to refresh all four now.";
29159
+ var toView = (tier, refresh, reason) => {
29160
+ const view = { available: tier.available, refresh };
29161
+ if (tier.expiresInSeconds !== undefined)
29162
+ view.expiresInSeconds = tier.expiresInSeconds;
29163
+ if (reason !== undefined)
29164
+ view.reason = reason;
29165
+ return view;
29166
+ };
29167
+ var buildLoginStatus = (input) => ({
29168
+ status: "authenticated",
29169
+ tokens: {
29170
+ basic: toView({ available: true, expiresInSeconds: input.basicExpiresInSeconds }, "automatic"),
29171
+ elevated: toView(input.elevated, "interactive", input.elevatedFailureReason),
29172
+ chatsvcagg: toView(input.chatsvcagg, "automatic"),
29173
+ ic3: toView(input.ic3, "automatic")
29174
+ },
29175
+ hint: HINT3
29176
+ });
29001
29177
 
29002
29178
  // src/use-cases/commands/logout.ts
29003
- var schema181 = exports_external.object({}).strict();
29004
- var execute181 = async (auth) => auth.logout();
29179
+ var schema182 = exports_external.object({}).strict();
29180
+ var execute182 = async (auth) => auth.logout();
29005
29181
 
29006
29182
  // src/use-cases/commands/output-path.ts
29007
29183
  import { posix as posix3 } from "node:path";
@@ -29082,8 +29258,8 @@ var persistMediaIfRequested = async (fs, outputDir, data) => {
29082
29258
  // src/use-cases/commands/update.ts
29083
29259
  var PACKAGE = "ask-marcel-office-cli";
29084
29260
  var argsFor = (manager) => manager === "bun" ? ["add", "-g", `${PACKAGE}@latest`] : ["i", "-g", `${PACKAGE}@latest`];
29085
- var schema182 = exports_external.object({}).strict();
29086
- var execute182 = async (runner, manager) => {
29261
+ var schema183 = exports_external.object({}).strict();
29262
+ var execute183 = async (runner, manager) => {
29087
29263
  const result = await runner.runInherit(manager, argsFor(manager));
29088
29264
  if (!result.ok)
29089
29265
  return err({ type: "spawn_failed", message: result.error.message });
@@ -29243,28 +29419,33 @@ var buildCli = (deps) => {
29243
29419
  await writeOrPrintText(JSON.stringify(fullOrTerse), "application/json", "help-json");
29244
29420
  });
29245
29421
  program2.commandsGroup("Lifecycle:");
29246
- const loginCmd = program2.command("login").description("Authenticate against Microsoft Graph using the Teams web client (cached token → refresh → Playwright browser fallback).").action(async () => {
29422
+ const loginCmd = program2.command("login").description("Authenticate against Microsoft Graph via the Teams web client (cached token → refresh → browser). Already signed in? Reports all four cached tokens (basic / elevated / chatsvcagg / ic3) with their time-left and refresh route; --force re-captures every token via the browser.").option("--force", "Ignore the cache and re-capture every token via the browser. The only way to refresh the elevated (M365) token while the basic token is still valid; the persistent browser profile is reused, so you are usually not re-prompted for credentials.").action(async () => {
29423
+ const force = loginCmd.opts().force ?? false;
29247
29424
  const loginAuth = deps.makeLoginAuth ? deps.makeLoginAuth() : auth;
29248
- const result = await execute180(loginAuth);
29425
+ const result = await execute181(loginAuth, { force });
29249
29426
  if (!result.ok) {
29250
29427
  fail(result.error.type === "auth_cancelled" ? "Authentication cancelled" : result.error.message);
29251
29428
  return;
29252
29429
  }
29253
- const outcome = loginAuth.getLastElevatedOutcome();
29254
- const envelope = { status: "authenticated" };
29255
- if (outcome !== null) {
29256
- if (outcome.captured) {
29257
- envelope.elevated = "captured";
29258
- } else {
29259
- envelope.elevated = "failed";
29260
- envelope.elevatedReason = outcome.reason;
29261
- }
29430
+ const info = await graph.getCachedTokenInfo();
29431
+ if (!info.ok) {
29432
+ fail(info.error.message);
29433
+ return;
29262
29434
  }
29263
- renderOut(envelope);
29435
+ const outcome = loginAuth.getLastElevatedOutcome();
29436
+ const elevatedFailureReason = outcome && !outcome.captured ? outcome.reason : undefined;
29437
+ renderOut(buildLoginStatus({
29438
+ basicExpiresInSeconds: info.value.expiresInSeconds,
29439
+ elevated: info.value.elevated,
29440
+ chatsvcagg: info.value.chatsvcagg,
29441
+ ic3: info.value.ic3,
29442
+ elevatedFailureReason
29443
+ }));
29264
29444
  });
29265
29445
  loginCmd.addHelpText("after", [
29266
29446
  "",
29267
- "Example: ask-marcel-office login (opens a Playwright-driven Edge/Chrome window)",
29447
+ "Examples: ask-marcel-office login (sign in the first time, or show all four token statuses if already signed in)",
29448
+ " ask-marcel-office login --force (re-capture every token via the browser, ignoring the cache)",
29268
29449
  "Token cache: ~/.ask-marcel/token-cache.json (access + refresh tokens, JSON, 0600).",
29269
29450
  "Browser data: ~/.ask-marcel/browser-profile/ (Playwright persistent context).",
29270
29451
  "Scopes: granted by Microsoft to the Teams web client (CLIENT_ID 5e3ce6c0-...);",
@@ -29274,7 +29455,7 @@ var buildCli = (deps) => {
29274
29455
  ].join(`
29275
29456
  `));
29276
29457
  const logoutCmd = program2.command("logout").description("Clear the cached Microsoft Graph token so the next command forces a fresh sign-in.").action(async () => {
29277
- const result = await execute181(auth);
29458
+ const result = await execute182(auth);
29278
29459
  if (result.ok)
29279
29460
  renderOut({ status: "logged_out" });
29280
29461
  else
@@ -29290,7 +29471,7 @@ var buildCli = (deps) => {
29290
29471
  `));
29291
29472
  const updateCmd = program2.command("update").description("Re-install the latest published ask-marcel-office from npm, in place. Auto-detects whether you originally installed via npm or bun.").action(async () => {
29292
29473
  const manager = deps.packageManager ?? detectPackageManager(process.argv[1] ?? "");
29293
- const result = await execute182(processRunner, manager);
29474
+ const result = await execute183(processRunner, manager);
29294
29475
  if (result.ok)
29295
29476
  renderOut({ status: "updated", via: manager });
29296
29477
  else if (result.error.type === "spawn_failed")