ask-marcel-office-cli 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +203 -0
  2. package/README.md +178 -119
  3. package/dist/cli.js +44806 -27142
  4. package/dist/commands.json +371 -52
  5. package/dist/composition/build-deps.d.ts +8 -0
  6. package/dist/composition/mcp.d.ts +20 -0
  7. package/dist/composition/run-registry-command.d.ts +34 -0
  8. package/dist/domain/tenant-id.d.ts +9 -0
  9. package/dist/domain/utilities/spo-tenant.d.ts +20 -0
  10. package/dist/index.js +2735 -1674
  11. package/dist/infra/auth.d.ts +36 -14
  12. package/dist/infra/browser-auth.d.ts +7 -2
  13. package/dist/infra/graph-client.d.ts +52 -16
  14. package/dist/presenter/graph-cursor.d.ts +2 -0
  15. package/dist/presenter/output.d.ts +1 -1
  16. package/dist/presenter/render-to-string.d.ts +15 -0
  17. package/dist/use-cases/commands/build-command.d.ts +19 -2
  18. package/dist/use-cases/commands/command-types.d.ts +16 -11
  19. package/dist/use-cases/commands/convert-calendar-event-attachment-to-markdown.d.ts +4 -0
  20. package/dist/use-cases/commands/{convert-drive-item-zip.d.ts → convert-drive-item-zip-to-markdown.d.ts} +5 -0
  21. package/dist/use-cases/commands/{convert-local-file.d.ts → convert-local-file-to-markdown.d.ts} +4 -0
  22. package/dist/use-cases/commands/convert-mail-attachment-to-markdown.d.ts +10 -2
  23. package/dist/use-cases/commands/{convert-mail-attachment-zip.d.ts → convert-mail-attachment-zip-to-markdown.d.ts} +5 -1
  24. package/dist/use-cases/commands/convert-mail-to-markdown.d.ts +35 -1
  25. package/dist/use-cases/commands/create-forward-draft.d.ts +4 -0
  26. package/dist/use-cases/commands/create-reply-draft.d.ts +8 -0
  27. package/dist/use-cases/commands/download-drive-item-as-markdown.d.ts +7 -2
  28. package/dist/use-cases/commands/download-drive-item-as-pdf.d.ts +1 -0
  29. package/dist/use-cases/commands/download-drive-item-content.d.ts +1 -0
  30. package/dist/use-cases/commands/draft-comment-splicer.d.ts +29 -0
  31. package/dist/use-cases/commands/draft-dedup.d.ts +18 -0
  32. package/dist/use-cases/commands/draft-response.d.ts +4 -0
  33. package/dist/use-cases/commands/extract-drive-item-images.d.ts +1 -0
  34. package/dist/use-cases/commands/extract-local-file-images.d.ts +1 -1
  35. package/dist/use-cases/commands/fetch-raw-bytes.d.ts +13 -0
  36. package/dist/use-cases/commands/find-mail-drafts.d.ts +9 -0
  37. package/dist/use-cases/commands/get-mail-signature.d.ts +8 -0
  38. package/dist/use-cases/commands/get-user.d.ts +10 -0
  39. package/dist/use-cases/commands/inline-image-embedder.d.ts +2 -1
  40. package/dist/use-cases/commands/login-status.d.ts +9 -27
  41. package/dist/use-cases/commands/login.d.ts +21 -0
  42. package/dist/use-cases/commands/mail-message-select.d.ts +1 -0
  43. package/dist/use-cases/commands/mail-quote-stripper.d.ts +16 -15
  44. package/dist/use-cases/commands/markdown-dispatch.d.ts +2 -1
  45. package/dist/use-cases/commands/msg-to-markdown.d.ts +10 -1
  46. package/dist/use-cases/commands/odata-query.d.ts +15 -1
  47. package/dist/use-cases/commands/office-to-markdown.d.ts +1 -0
  48. package/dist/use-cases/commands/read-mail-attachment.d.ts +4 -0
  49. package/dist/use-cases/commands/resolve-command.d.ts +25 -0
  50. package/dist/use-cases/commands/search-all-files.d.ts +8 -0
  51. package/dist/use-cases/commands/search-escape.d.ts +23 -0
  52. package/dist/use-cases/commands/signature-extractor.d.ts +2 -0
  53. package/dist/use-cases/commands/tenant-option.d.ts +44 -0
  54. package/dist/use-cases/commands/update-mail-draft.d.ts +1 -0
  55. package/dist/use-cases/commands/zip-archive-to-markdown.d.ts +10 -5
  56. package/dist/use-cases/ports/filesystem.d.ts +1 -1
  57. package/docs/COMMANDS.md +34 -29
  58. package/docs/USAGE.md +65 -7
  59. package/package.json +2 -1
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ import type { Command, CommandMeta } from './command-types.js';
3
+ declare const schema: z.ZodObject<{
4
+ messageId: z.ZodOptional<z.ZodString>;
5
+ }, z.core.$strip>;
6
+ declare const execute: Command['execute'];
7
+ declare const meta: CommandMeta;
8
+ export { execute, meta, schema };
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ import type { Command, CommandMeta } from './command-types.js';
3
+ declare const schema: z.ZodObject<{
4
+ userId: z.ZodString;
5
+ select: z.ZodOptional<z.ZodString>;
6
+ expand: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strip>;
8
+ declare const execute: Command['execute'];
9
+ declare const meta: CommandMeta;
10
+ export { execute, meta, schema };
@@ -16,5 +16,6 @@ type InlineAttachment = {
16
16
  readonly contentBytes: string;
17
17
  };
18
18
  declare const embedInlineImages: (html: string, attachments: ReadonlyArray<InlineAttachment>) => string;
19
- export { embedInlineImages };
19
+ declare const replaceUnresolvedCidImages: (html: string, labelByContentId: ReadonlyMap<string, string>) => string;
20
+ export { embedInlineImages, replaceUnresolvedCidImages };
20
21
  export type { InlineAttachment };
@@ -1,31 +1,13 @@
1
- type RefreshRoute = 'automatic' | 'interactive';
2
- type TokenTier = {
3
- readonly available: boolean;
4
- readonly expiresInSeconds: number | undefined;
5
- };
6
- type TokenView = {
7
- available: boolean;
8
- expiresInSeconds?: number;
9
- refresh: RefreshRoute;
10
- reason?: string;
11
- };
12
- type LoginStatus = {
1
+ type LoginSummary = {
13
2
  status: 'authenticated';
14
- tokens: {
15
- basic: TokenView;
16
- elevated: TokenView;
17
- chatsvcagg: TokenView;
18
- ic3: TokenView;
19
- };
3
+ available: ReadonlyArray<string>;
20
4
  hint: string;
21
5
  };
22
- type LoginStatusInput = {
23
- readonly basicExpiresInSeconds: number | undefined;
24
- readonly elevated: TokenTier;
25
- readonly chatsvcagg: TokenTier;
26
- readonly ic3: TokenTier;
27
- readonly elevatedFailureReason?: string;
6
+ type LoginSummaryInput = {
7
+ readonly elevatedAvailable: boolean;
8
+ readonly chatsvcaggAvailable: boolean;
9
+ readonly ic3Available: boolean;
28
10
  };
29
- declare const buildLoginStatus: (input: LoginStatusInput) => LoginStatus;
30
- export { buildLoginStatus };
31
- export type { LoginStatus, LoginStatusInput };
11
+ declare const buildLoginSummary: (input: LoginSummaryInput) => LoginSummary;
12
+ export { buildLoginSummary };
13
+ export type { LoginSummary, LoginSummaryInput };
@@ -2,6 +2,27 @@ import { z } from 'zod';
2
2
  import type { Result } from '../../domain/result.js';
3
3
  import type { AuthManager } from '../../infra/auth.js';
4
4
  declare const schema: z.ZodObject<{}, z.core.$strict>;
5
+ /**
6
+ * Sign in, and guarantee the browser-only tier is actually there afterwards.
7
+ *
8
+ * Every other token tier can be renewed headlessly from the shared refresh
9
+ * token. The elevated (M365ChatClient) token cannot — it carries no refresh
10
+ * token of its own and exists only via the browser dance. So a plain `login`
11
+ * that found a valid cached basic token used to return on the cache rung and
12
+ * report `authenticated` with elevated still missing, which left the user in a
13
+ * loop with no exit: the command that needs elevated says "run login", login
14
+ * says "authenticated", the command fails identically, forever.
15
+ *
16
+ * When elevated is confirmed missing we escalate through the SAME
17
+ * `{ force: true }` rung the `--force` flag uses. That matters: the browser
18
+ * adapter has its own `freshCachedToken` probe that short-circuits the dance
19
+ * when a valid token is on disk, and only the forced path suppresses it — a
20
+ * hand-rolled re-capture here would silently no-op (LESSONS 2026-07-13).
21
+ *
22
+ * Supersedes the 2026-07-13 decision that `login` is a slim confirmation and
23
+ * `--force` the only re-capture mechanism: correct about the mechanism, but it
24
+ * left the signpost pointing at a command that could not do the job.
25
+ */
5
26
  declare const execute: (auth: AuthManager, options?: {
6
27
  force?: boolean;
7
28
  }) => Promise<Result<string, import("../../infra/auth.js").AuthError>>;
@@ -0,0 +1 @@
1
+ export declare const MAIL_MESSAGE_DEFAULT_SELECT = "id,subject,from,toRecipients,ccRecipients,receivedDateTime,hasAttachments,isRead,importance,bodyPreview,conversationId";
@@ -1,19 +1,15 @@
1
+ import { z } from 'zod';
2
+ import type { CommandOptionMeta } from './command-types.js';
1
3
  /**
2
- * Strips quoted reply chains / forwarded-message blocks from an Outlook or
3
- * Gmail HTML email body so long threads don't duplicate quoted content into the
4
- * model's context. Conservative: truncates the body at the EARLIEST well-known
5
- * reply/forward boundary marker and replaces the tail with a single visible
6
- * placeholder nothing is removed silently, and `--keep-quoted true` on
7
- * `convert-mail-to-markdown` restores the full body. Pure string transform.
8
- *
9
- * Only structural, vendor-specific markers are matched (never a bare
10
- * `<blockquote>`, which legitimate content uses too):
11
- * - Outlook desktop / OWA reply+forward header block: `<div id="divRplyFwdMsg">`
12
- * - Outlook "type above this line" boundary: `<div id="appendonsend">`
13
- * - Outlook mobile reference container: `<div id="mail-editor-reference-message-container">`
14
- * - Outlook classic separator: `<hr id="stopSpelling">`
15
- * - Gmail quote container: `<div class="gmail_quote">` / `<blockquote class="gmail_quote">`
4
+ * Index where the quoted history begins in an HTML body, or -1 when the body
5
+ * quotes nothing. Earliest of the structural markers merged with the widened
6
+ * confirmed-header index. Exported because the draft-comment splicer needs the
7
+ * same cut to place a reply ABOVE the quote without disturbing it — the stripper
8
+ * throws the tail away, the splicer keeps it, but both agree on where it starts.
16
9
  */
10
+ declare const findQuoteBoundary: (html: string) => number;
11
+ /** The plain-text counterpart of `findQuoteBoundary`, for `contentType === 'text'` bodies. */
12
+ declare const findPlainTextQuoteBoundary: (text: string) => number;
17
13
  declare const stripQuotedReplies: (html: string) => {
18
14
  readonly html: string;
19
15
  readonly stripped: boolean;
@@ -22,4 +18,9 @@ declare const stripQuotedPlainText: (text: string) => {
22
18
  readonly text: string;
23
19
  readonly stripped: boolean;
24
20
  };
25
- export { stripQuotedPlainText, stripQuotedReplies };
21
+ declare const keepQuotedSchemaField: z.ZodOptional<z.ZodEnum<{
22
+ true: "true";
23
+ false: "false";
24
+ }>>;
25
+ declare const keepQuotedOption: CommandOptionMeta;
26
+ export { findPlainTextQuoteBoundary, findQuoteBoundary, keepQuotedOption, keepQuotedSchemaField, stripQuotedPlainText, stripQuotedReplies };
@@ -11,13 +11,14 @@ type BytesToMarkdownOptions = {
11
11
  readonly includeMetadata?: boolean;
12
12
  readonly maxCells?: number;
13
13
  readonly inlineImages?: boolean;
14
+ readonly keepQuoted?: boolean;
14
15
  readonly depth?: number;
15
16
  };
16
17
  declare const NESTED_HINTS: ConversionHints;
17
18
  /**
18
19
  * The single extension→converter dispatch for every markdown command, operating on
19
20
  * bytes already in hand: download-drive-item-as-markdown fetches them, convert-mail
20
- * decodes the attachment, convert-drive-item-zip unpacks the entry. Loop/Fluid/
21
+ * decodes the attachment, convert-drive-item-zip-to-markdown unpacks the entry. Loop/Fluid/
21
22
  * Whiteboard (`?format=html`) need a Graph round-trip and are handled by the drive
22
23
  * caller BEFORE this — they never reach here. An Outlook `.msg` is rendered to markdown
23
24
  * (headers + body) with each of its own attachments recursed through this dispatch.
@@ -10,6 +10,14 @@ import type { ParsedMsg } from '../../infra/msg-reader-adapter.js';
10
10
  * user asked ("maybe same way as zip"). Unconvertible attachments (images, binaries)
11
11
  * are listed with the dispatch's note instead of failing the whole message.
12
12
  *
13
+ * The body goes through the same two passes `convert-mail-to-markdown` applies to a
14
+ * Graph mail body (they share the helpers): the quoted reply chain is stripped by
15
+ * default — `keepQuoted` restores it, and every command that can hand a `.msg` to
16
+ * this renderer exposes that as `--keep-quoted`, so the marker's remedy always
17
+ * works — and any `cid:` image becomes a readable placeholder. A `.msg` carries no
18
+ * contentId on its attachments, so embedding is impossible here and the placeholder
19
+ * falls back to the img alt text or the cid's filename prefix.
20
+ *
13
21
  * `recurse` is the attachment converter injected by `markdown-dispatch` (its own
14
22
  * `bytesToMarkdown`, with the recursion depth incremented). Injecting it — rather
15
23
  * than importing `bytesToMarkdown` here — keeps this use-case off the dispatch's
@@ -20,9 +28,10 @@ import type { ParsedMsg } from '../../infra/msg-reader-adapter.js';
20
28
  declare const MAX_MSG_DEPTH = 3;
21
29
  type MsgToMarkdownOptions = {
22
30
  readonly depth?: number;
31
+ readonly keepQuoted?: boolean;
23
32
  };
24
33
  type MsgAttachmentConverter = (bytes: Uint8Array, filename: string) => Promise<Result<unknown, GraphError>>;
25
- declare const renderMsg: (msg: ParsedMsg, depth: number, recurse: MsgAttachmentConverter) => Promise<string>;
34
+ declare const renderMsg: (msg: ParsedMsg, opts: MsgToMarkdownOptions, recurse: MsgAttachmentConverter) => Promise<string>;
26
35
  declare const msgToMarkdown: (bytes: Uint8Array, opts: MsgToMarkdownOptions, recurse: MsgAttachmentConverter) => Promise<Result<unknown, GraphError>>;
27
36
  export { MAX_MSG_DEPTH, msgToMarkdown, renderMsg };
28
37
  export type { MsgAttachmentConverter, MsgToMarkdownOptions };
@@ -9,6 +9,20 @@ declare const odataQuerySchema: z.ZodObject<{
9
9
  expand: z.ZodOptional<z.ZodString>;
10
10
  }, z.core.$strip>;
11
11
  type ODataQueryParams = z.infer<typeof odataQuerySchema>;
12
+ /**
13
+ * Embed a user-supplied value inside an OData single-quoted string literal
14
+ * (`$filter=mail eq '<here>'`, `contains(title,'<here>')`, `search(q='<here>')`).
15
+ * Two steps, in this order:
16
+ * 1. double any `'` — OData's string-literal escape, so the value cannot
17
+ * terminate the literal early;
18
+ * 2. percent-encode — graph-client concatenates command paths verbatim, so an
19
+ * un-encoded value corrupts the query string. `&`/`#` truncate it outright,
20
+ * and a raw `+` is decoded back to a SPACE server-side, which silently
21
+ * matches nothing (base64 conversationIds and plus-addressed emails both
22
+ * carry `+`). encodeURIComponent leaves `'` unreserved, so the doubled
23
+ * quote survives as the escape OData expects.
24
+ */
25
+ declare const odataStringLiteral: (value: string) => string;
12
26
  declare const appendOData: (path: string, params: ODataQueryParams) => string;
13
27
  declare const odataQueryOptions: ReadonlyArray<CommandOptionMeta>;
14
28
  /**
@@ -86,5 +100,5 @@ declare const selectOnlyShape: Pick<{
86
100
  expand: z.ZodOptional<z.ZodString>;
87
101
  }, "select">;
88
102
  declare const selectOnlyOptions: readonly CommandOptionMeta[];
89
- export { appendOData, filterSelectOptions, filterSelectSchema, noSkipOptions, noSkipShape, odataQueryOptions, odataQuerySchema, pickODataOptions, pickODataShape, selectExpandOptions, selectExpandSchema, selectOnlyOptions, selectOnlyShape, topOnlyOptions, topOnlyShape, };
103
+ export { appendOData, filterSelectOptions, filterSelectSchema, noSkipOptions, noSkipShape, odataQueryOptions, odataQuerySchema, odataStringLiteral, pickODataOptions, pickODataShape, selectExpandOptions, selectExpandSchema, selectOnlyOptions, selectOnlyShape, topOnlyOptions, topOnlyShape, };
90
104
  export type { FilterSelectParams, ODataKey, ODataQueryParams, SelectExpandParams };
@@ -5,6 +5,7 @@ type OfficeToMarkdownOptions = FetchOptions & {
5
5
  readonly includeMetadata?: boolean;
6
6
  readonly inlineImages?: boolean;
7
7
  readonly maxCells?: number;
8
+ readonly keepQuoted?: boolean;
8
9
  };
9
10
  declare const officeToMarkdown: (graph: GraphClient, contentPath: string, filename: string, opts?: OfficeToMarkdownOptions) => Promise<Result<unknown, GraphError>>;
10
11
  export { officeToMarkdown };
@@ -9,6 +9,10 @@ declare const schema: z.ZodObject<{
9
9
  true: "true";
10
10
  false: "false";
11
11
  }>>;
12
+ keepQuoted: z.ZodOptional<z.ZodEnum<{
13
+ true: "true";
14
+ false: "false";
15
+ }>>;
12
16
  }, z.core.$strip>;
13
17
  declare const execute: (graph: GraphClient, params: Record<string, string>) => Promise<Result<unknown, GraphError>>;
14
18
  declare const meta: CommandMeta;
@@ -0,0 +1,25 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { Command } from './command-types.js';
3
+ /**
4
+ * Name -> command lookup that also honours `meta.commandAliases`.
5
+ *
6
+ * The CLI gets alias resolution for free from commander (`commandDef.alias(...)`
7
+ * in `cli.ts`), so nothing needed this until a second front end appeared. The
8
+ * MCP gateway has no commander, and its three command-taking tools
9
+ * (`get-command-docs`, `run-command`, `run-write-command`) each need the same
10
+ * lookup — Rule of Three, so it lives here rather than inline.
11
+ *
12
+ * Returns the CANONICAL name alongside the command so every downstream concern
13
+ * (docs rendering, the `mutates` read/write gate, error messages) keys off one
14
+ * spelling regardless of which one the caller used.
15
+ */
16
+ export type ResolveCommandError = {
17
+ readonly type: 'unknown_command';
18
+ readonly name: string;
19
+ readonly available: ReadonlyArray<string>;
20
+ };
21
+ export type ResolvedCommand = {
22
+ readonly name: string;
23
+ readonly command: Command;
24
+ };
25
+ export declare const resolveCommand: (registry: Readonly<Record<string, Command>>, name: string) => Result<ResolvedCommand, ResolveCommandError>;
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ import type { Command, CommandMeta } from './command-types.js';
3
+ declare const schema: z.ZodObject<{
4
+ query: z.ZodString;
5
+ }, z.core.$strip>;
6
+ declare const execute: Command['execute'];
7
+ declare const meta: CommandMeta;
8
+ export { execute, meta, schema };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Wire-safe builder for Graph `$search=` KQL clauses. graph-client
3
+ * concatenates command paths verbatim (`https://graph.microsoft.com/v1.0${path}`)
4
+ * with no percent-encoding pass, so a raw `&`, `#`, `%`, or `+` inside a user
5
+ * query corrupts the query string on the wire: a live ` & ` truncated the KQL
6
+ * mid-phrase (`$search="subject:"Contoso A2` reached Graph). Values are
7
+ * percent-encoded here, at the only layer that knows which part of the path
8
+ * is data.
9
+ *
10
+ * The sibling concern — a value inside a single-quoted OData literal
11
+ * (`$filter=x eq '…'`, `contains(…)`, `search(q='…')`) — is
12
+ * `odataStringLiteral` in odata-query.ts, which owns OData query construction.
13
+ */
14
+ /**
15
+ * Build a `$search=` KQL clause: escape embedded double quotes as `\"`
16
+ * (Graph's documented KQL escaping, so `subject:"multi word"` and whole
17
+ * `"phrase"` queries become phrase matches instead of a BadRequest), wrap the
18
+ * expression in the double quotes Graph requires, then percent-encode the
19
+ * value. Backslashes are NOT pre-escaped: raw quotes are the documented
20
+ * input contract and backslash has no other KQL meaning here.
21
+ */
22
+ declare const kqlSearchClause: (query: string) => string;
23
+ export { kqlSearchClause };
@@ -0,0 +1,2 @@
1
+ declare const extractSignatureBlock: (html: string) => string | undefined;
2
+ export { extractSignatureBlock };
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod';
2
+ import type { Result } from '../../domain/result.js';
3
+ import type { TenantId } from '../../domain/tenant-id.js';
4
+ import type { GraphClient, GraphError } from '../../infra/graph-client.js';
5
+ import type { CommandOptionMeta } from './command-types.js';
6
+ /**
7
+ * `--tenant-id`: read a file that lives in a tenant you are only a GUEST in.
8
+ *
9
+ * Without it, such a read dies at `401 invalidAudienceUri` — home-tenant Graph
10
+ * cannot mint a SharePoint token for a foreign tenant, so no home-tier token can
11
+ * reach it. Unlike `resolve-drive-share-link`, these commands cannot recover on
12
+ * their own: they hold only a `driveId` and an `itemId`, and NEITHER carries a
13
+ * tenant. The sharing URL does, which is why `resolve-drive-share-link` returns
14
+ * the `tenantId` for this flag to consume.
15
+ *
16
+ * OPTIONAL, always. That is not a detail — `required: true` compiles straight to
17
+ * commander's `.requiredOption()`, so an optional flag is what keeps the
18
+ * `CommandMeta` contract untouched and every existing invocation working.
19
+ */
20
+ declare const tenantIdShape: {
21
+ tenantId: z.ZodOptional<z.ZodString>;
22
+ };
23
+ declare const tenantIdSchema: z.ZodObject<{
24
+ tenantId: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strip>;
26
+ declare const TENANT_ID_OPTION: CommandOptionMeta;
27
+ /**
28
+ * Route a JSON GET to the right identity: the home token normally, a partner
29
+ * tenant's guest token when `--tenant-id` was given.
30
+ *
31
+ * The guest tier is a RUNTIME choice, not a static one like `elevated` — the same
32
+ * command uses either, depending on this flag. That is why the builders route
33
+ * here instead of growing guest twins (which would take 10 builders to 14+, and
34
+ * would still not express "it depends on the argument").
35
+ */
36
+ declare const routeGet: (graph: GraphClient, path: string, rawTenantId: string | undefined) => Promise<Result<unknown, GraphError>>;
37
+ /**
38
+ * Validate a caller-supplied tenant id at the boundary. The value reaches an
39
+ * authority URL whose POST carries the refresh token, so it is branded rather
40
+ * than trusted (hard rule 12); a bad one must fail here with a readable message,
41
+ * not further in.
42
+ */
43
+ declare const brandTenantId: (raw: string) => Result<TenantId, GraphError>;
44
+ export { TENANT_ID_OPTION, brandTenantId, routeGet, tenantIdSchema, tenantIdShape };
@@ -4,6 +4,7 @@ declare const schema: z.ZodObject<{
4
4
  messageId: z.ZodString;
5
5
  subject: z.ZodOptional<z.ZodString>;
6
6
  bodyContent: z.ZodOptional<z.ZodString>;
7
+ comment: z.ZodOptional<z.ZodString>;
7
8
  bodyContentType: z.ZodOptional<z.ZodEnum<{
8
9
  Text: "Text";
9
10
  HTML: "HTML";
@@ -3,9 +3,9 @@ import type { GraphError } from '../../infra/graph-client.js';
3
3
  import type { MediaEnvelope } from './media-files.js';
4
4
  /**
5
5
  * Shared "unzip + convert every contained file" core behind
6
- * `convert-drive-item-zip` (a OneDrive / SharePoint .zip),
7
- * `convert-mail-attachment-zip` (an Outlook .zip attachment), and
8
- * `convert-local-file` (a .zip on disk). Each entry is run through the same
6
+ * `convert-drive-item-zip-to-markdown` (a OneDrive / SharePoint .zip),
7
+ * `convert-mail-attachment-zip-to-markdown` (an Outlook .zip attachment), and
8
+ * `convert-local-file-to-markdown` (a .zip on disk). Each entry is run through the same
9
9
  * `bytesToMarkdown` dispatch the markdown commands use; an entry the dispatch
10
10
  * can't convert (image, binary, nested archive, scanned PDF) is LISTED with a
11
11
  * note instead of failing the whole archive. Notes use the container-neutral
@@ -27,6 +27,11 @@ type ZipArchiveResult = {
27
27
  readonly totalEntries?: number;
28
28
  readonly files: ReadonlyArray<FileResult>;
29
29
  };
30
- declare const convertZipArchive: (bytes: Uint8Array, includeMetadata: boolean, includeImages?: boolean) => Promise<Result<ZipArchiveResult, GraphError>>;
30
+ type ZipArchiveOptions = {
31
+ readonly includeMetadata: boolean;
32
+ readonly includeImages?: boolean;
33
+ readonly keepQuoted?: boolean;
34
+ };
35
+ declare const convertZipArchive: (bytes: Uint8Array, opts: ZipArchiveOptions) => Promise<Result<ZipArchiveResult, GraphError>>;
31
36
  export { convertZipArchive, MAX_ENTRIES };
32
- export type { FileResult, ZipArchiveResult };
37
+ export type { FileResult, ZipArchiveOptions, ZipArchiveResult };
@@ -11,7 +11,7 @@ export type FileSystemError = {
11
11
  export type FileSystem = {
12
12
  readonly readJson: <T>(path: string) => Promise<Result<T, FileSystemError>>;
13
13
  /**
14
- * Read a file's raw bytes. Used by `convert-local-file` to feed a local
14
+ * Read a file's raw bytes. Used by `convert-local-file-to-markdown` to feed a local
15
15
  * document into the same conversion dispatch the Graph-backed commands use.
16
16
  */
17
17
  readonly readBytes: (path: string) => Promise<Result<Uint8Array, FileSystemError>>;