ask-marcel-office-cli 1.4.0 → 1.5.1

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 (107) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +68 -24
  3. package/dist/cli.js +7641 -90932
  4. package/dist/commands.json +1230 -70
  5. package/dist/composition/build-deps.d.ts +13 -0
  6. package/dist/composition/cli.d.ts +8 -0
  7. package/dist/domain/iso-datetime.d.ts +1 -1
  8. package/dist/domain/utilities/archive-status.d.ts +18 -0
  9. package/dist/domain/utilities/site-url-classifier.d.ts +15 -0
  10. package/dist/index.js +10431 -93852
  11. package/dist/infra/auth.d.ts +27 -3
  12. package/dist/infra/browser-auth.d.ts +25 -0
  13. package/dist/infra/graph-client.d.ts +3 -1
  14. package/dist/infra/legacy-doc-extractor.d.ts +14 -0
  15. package/dist/infra/msg-reader-adapter.d.ts +83 -0
  16. package/dist/infra/network-error.d.ts +1 -1
  17. package/dist/infra/ooxml-media-extractor.d.ts +27 -0
  18. package/dist/infra/ooxml-zip-adapter.d.ts +28 -0
  19. package/dist/infra/pdf-image-extractor.d.ts +18 -0
  20. package/dist/infra/pdf-text-extractor.d.ts +41 -0
  21. package/dist/infra/png-encode.d.ts +15 -0
  22. package/dist/infra/sheetjs-adapter.d.ts +1 -1
  23. package/dist/infra/system-browser-auth.d.ts +35 -0
  24. package/dist/infra/system-browser-loader.d.ts +3 -0
  25. package/dist/infra/token-callback-server.d.ts +31 -0
  26. package/dist/infra/zip-reader.d.ts +32 -0
  27. package/dist/presenter/error-hints.d.ts +2 -2
  28. package/dist/presenter/output.d.ts +1 -1
  29. package/dist/use-cases/commands/build-command.d.ts +1 -1
  30. package/dist/use-cases/commands/command-types.d.ts +42 -1
  31. package/dist/use-cases/commands/convert-calendar-event-attachment-to-markdown.d.ts +15 -0
  32. package/dist/use-cases/commands/convert-calendar-event-attachment-to-pdf.d.ts +11 -0
  33. package/dist/use-cases/commands/convert-drive-item-zip.d.ts +26 -0
  34. package/dist/use-cases/commands/convert-local-file.d.ts +37 -0
  35. package/dist/use-cases/commands/convert-mail-attachment-to-markdown.d.ts +7 -1
  36. package/dist/use-cases/commands/convert-mail-attachment-to-pdf.d.ts +2 -1
  37. package/dist/use-cases/commands/convert-mail-attachment-zip.d.ts +24 -0
  38. package/dist/use-cases/commands/convert-mail-to-markdown.d.ts +4 -0
  39. package/dist/use-cases/commands/create-mail-draft.d.ts +22 -0
  40. package/dist/use-cases/commands/doc-to-markdown.d.ts +14 -0
  41. package/dist/use-cases/commands/docs-render.d.ts +3 -0
  42. package/dist/use-cases/commands/docs.d.ts +1 -1
  43. package/dist/use-cases/commands/docx-comment-anchors.d.ts +22 -0
  44. package/dist/use-cases/commands/docx-metadata-to-markdown.d.ts +3 -0
  45. package/dist/use-cases/commands/docx-metadata.d.ts +69 -0
  46. package/dist/use-cases/commands/docx-to-markdown.d.ts +8 -3
  47. package/dist/use-cases/commands/download-drive-item-as-markdown.d.ts +9 -0
  48. package/dist/use-cases/commands/download-drive-item-version.d.ts +4 -0
  49. package/dist/use-cases/commands/extract-drive-item-images.d.ts +11 -0
  50. package/dist/use-cases/commands/extract-local-file-images.d.ts +21 -0
  51. package/dist/use-cases/commands/extract-mail-attachment-images.d.ts +11 -0
  52. package/dist/use-cases/commands/extract-sharepoint-links-in-documents.d.ts +33 -0
  53. package/dist/use-cases/commands/extract-sharepoint-links-in-mail.d.ts +1 -8
  54. package/dist/use-cases/commands/fetch-raw-bytes.d.ts +1 -0
  55. package/dist/use-cases/commands/file-counts.d.ts +7 -0
  56. package/dist/use-cases/commands/filter-archived-sites.d.ts +17 -0
  57. package/dist/use-cases/commands/first-sentence.d.ts +12 -0
  58. package/dist/use-cases/commands/get-excel-chart-image.d.ts +20 -0
  59. package/dist/use-cases/commands/get-onenote-page-as-markdown.d.ts +8 -0
  60. package/dist/use-cases/commands/get-todo-task.d.ts +9 -2
  61. package/dist/use-cases/commands/image-extraction.d.ts +10 -0
  62. package/dist/use-cases/commands/iso-datetime-schema.d.ts +1 -1
  63. package/dist/use-cases/commands/list-accessible-drives.d.ts +14 -0
  64. package/dist/use-cases/commands/list-calendar-event-attachments.d.ts +14 -0
  65. package/dist/use-cases/commands/mail-quote-stripper.d.ts +25 -0
  66. package/dist/use-cases/commands/markdown-dispatch.d.ts +29 -0
  67. package/dist/use-cases/commands/markdown-pipeline.d.ts +6 -2
  68. package/dist/use-cases/commands/media-files.d.ts +20 -0
  69. package/dist/use-cases/commands/msg-to-markdown.d.ts +28 -0
  70. package/dist/use-cases/commands/odf-content-to-markdown.d.ts +5 -0
  71. package/dist/use-cases/commands/odf-metadata-to-markdown.d.ts +3 -0
  72. package/dist/use-cases/commands/odf-metadata.d.ts +26 -0
  73. package/dist/use-cases/commands/odf-to-markdown.d.ts +17 -0
  74. package/dist/use-cases/commands/office-extensions.d.ts +13 -0
  75. package/dist/use-cases/commands/office-to-markdown.d.ts +6 -2
  76. package/dist/use-cases/commands/onenote-metadata.d.ts +21 -0
  77. package/dist/use-cases/commands/onenote-resource-embedder.d.ts +3 -0
  78. package/dist/use-cases/commands/ooxml-metadata-to-markdown.d.ts +16 -0
  79. package/dist/use-cases/commands/ooxml-metadata.d.ts +23 -0
  80. package/dist/use-cases/commands/ooxml-xml-walker.d.ts +36 -0
  81. package/dist/use-cases/commands/option-descriptions.d.ts +5 -0
  82. package/dist/use-cases/commands/output-path.d.ts +23 -0
  83. package/dist/use-cases/commands/pdf-to-markdown.d.ts +19 -0
  84. package/dist/use-cases/commands/pptx-comments.d.ts +24 -0
  85. package/dist/use-cases/commands/pptx-metadata-to-markdown.d.ts +3 -0
  86. package/dist/use-cases/commands/pptx-metadata.d.ts +33 -0
  87. package/dist/use-cases/commands/pptx-slides.d.ts +17 -0
  88. package/dist/use-cases/commands/pptx-to-markdown.d.ts +7 -0
  89. package/dist/use-cases/commands/read-mail-attachment.d.ts +15 -0
  90. package/dist/use-cases/commands/search-all-accessible-sites.d.ts +12 -0
  91. package/dist/use-cases/commands/search-index-total.d.ts +3 -0
  92. package/dist/use-cases/commands/search-sharepoint-sites-by-name.d.ts +3 -2
  93. package/dist/use-cases/commands/sharepoint-link-extractor.d.ts +17 -12
  94. package/dist/use-cases/commands/text-passthrough.d.ts +15 -2
  95. package/dist/use-cases/commands/todo-parse-uri-rewrite.d.ts +7 -0
  96. package/dist/use-cases/commands/update-mail-draft.d.ts +22 -0
  97. package/dist/use-cases/commands/xlsx-comments.d.ts +29 -0
  98. package/dist/use-cases/commands/xlsx-metadata-to-markdown.d.ts +3 -0
  99. package/dist/use-cases/commands/xlsx-metadata.d.ts +39 -0
  100. package/dist/use-cases/commands/xlsx-to-markdown.d.ts +9 -2
  101. package/dist/use-cases/commands/zip-archive-to-markdown.d.ts +30 -0
  102. package/dist/use-cases/ports/filesystem.d.ts +10 -0
  103. package/docs/COMMANDS.md +34 -18
  104. package/docs/USAGE.md +25 -8
  105. package/docs/commands.json +1230 -70
  106. package/package.json +14 -8
  107. /package/dist/use-cases/commands/{download-onedrive-file-content.d.ts → download-drive-item-content.d.ts} +0 -0
@@ -0,0 +1,20 @@
1
+ import type { MediaPart } from '../../infra/ooxml-media-extractor.js';
2
+ /**
3
+ * Shapes the raw media parts from the extractor into the inline response
4
+ * envelope `{ count, media: [{ path, contentType, sizeBytes, base64 }] }`.
5
+ * The global `--output-dir` flag recognises this shape and writes each image
6
+ * to disk (see `persistMediaIfRequested`); without it, the base64 rides back
7
+ * in the envelope. Shared by every image-extraction command.
8
+ */
9
+ type MediaEnvelope = {
10
+ readonly count: number;
11
+ readonly media: ReadonlyArray<{
12
+ readonly path: string;
13
+ readonly contentType: string;
14
+ readonly sizeBytes: number;
15
+ readonly base64: string;
16
+ }>;
17
+ };
18
+ declare const buildMediaResponse: (parts: ReadonlyArray<MediaPart>) => MediaEnvelope;
19
+ export { buildMediaResponse };
20
+ export type { MediaEnvelope };
@@ -0,0 +1,28 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ import type { ParsedMsg } from '../../infra/msg-reader-adapter.js';
4
+ /**
5
+ * Render an Outlook `.msg` file to markdown: an H1 subject, a From/To/Cc/Bcc/Date
6
+ * header block, the message body (the plain-text body when present, else the HTML
7
+ * body run through turndown), and an `## Attachments` section where each attachment
8
+ * is converted recursively through the SAME dispatch the zip command uses — so a
9
+ * `.docx`/`.pdf`/`.csv` attached to an email becomes markdown inline, exactly as the
10
+ * user asked ("maybe same way as zip"). Unconvertible attachments (images, binaries)
11
+ * are listed with the dispatch's note instead of failing the whole message.
12
+ *
13
+ * `recurse` is the attachment converter injected by `markdown-dispatch` (its own
14
+ * `bytesToMarkdown`, with the recursion depth incremented). Injecting it — rather
15
+ * than importing `bytesToMarkdown` here — keeps this use-case off the dispatch's
16
+ * import cycle and lets every rendering branch be tested with a plain fake. `depth`
17
+ * caps `.msg`-inside-`.msg` nesting: past {@link MAX_MSG_DEPTH} levels an embedded
18
+ * message's attachments are listed but not expanded.
19
+ */
20
+ declare const MAX_MSG_DEPTH = 3;
21
+ type MsgToMarkdownOptions = {
22
+ readonly depth?: number;
23
+ };
24
+ type MsgAttachmentConverter = (bytes: Uint8Array, filename: string) => Promise<Result<unknown, GraphError>>;
25
+ declare const renderMsg: (msg: ParsedMsg, depth: number, recurse: MsgAttachmentConverter) => Promise<string>;
26
+ declare const msgToMarkdown: (bytes: Uint8Array, opts: MsgToMarkdownOptions, recurse: MsgAttachmentConverter) => Promise<Result<unknown, GraphError>>;
27
+ export { MAX_MSG_DEPTH, msgToMarkdown, renderMsg };
28
+ export type { MsgAttachmentConverter, MsgToMarkdownOptions };
@@ -0,0 +1,5 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ declare const renderOdfContent: (xml: string | undefined) => string;
4
+ declare const odfContentToMarkdown: (bytes: Uint8Array) => Promise<Result<string, GraphError>>;
5
+ export { odfContentToMarkdown, renderOdfContent };
@@ -0,0 +1,3 @@
1
+ import type { OdfMetadata } from './odf-metadata.js';
2
+ declare const formatOdfMetadata: (meta: OdfMetadata) => string;
3
+ export { formatOdfMetadata };
@@ -0,0 +1,26 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ /**
4
+ * Pulls the side-channel content out of an OpenDocument package (.odt / .ods /
5
+ * .odp and their .ot* template variants). OpenDocument is also a ZIP, so the
6
+ * shared `openOoxmlZip` adapter + XML walker apply directly; only the metadata
7
+ * shape differs — it lives in a single `meta.xml` (`office:document-meta >
8
+ * office:meta`) rather than the OOXML `docProps/*` parts.
9
+ *
10
+ * High-value subset: document properties (Dublin Core + ODF meta fields like
11
+ * generator / editing-cycles / creation-date), keyword list, and user-defined
12
+ * custom properties (`meta:user-defined`) — the ODF analog of OOXML custom
13
+ * document properties.
14
+ */
15
+ type UserDefined = {
16
+ readonly name: string;
17
+ readonly value: string;
18
+ };
19
+ type OdfMetadata = {
20
+ readonly properties: Readonly<Record<string, string>>;
21
+ readonly keywords: ReadonlyArray<string>;
22
+ readonly userDefined: ReadonlyArray<UserDefined>;
23
+ };
24
+ declare const extractOdfMetadata: (bytes: Uint8Array) => Promise<Result<OdfMetadata, GraphError>>;
25
+ export { extractOdfMetadata };
26
+ export type { OdfMetadata, UserDefined };
@@ -0,0 +1,17 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ import type { MarkdownEnvelope } from './docx-to-markdown.js';
4
+ /**
5
+ * Converts an OpenDocument (.odt / .ods / .odp) body to markdown by walking
6
+ * `content.xml` (headings / paragraphs / lists / tables for text docs, named
7
+ * sheet-tables for spreadsheets, per-slide text for presentations — including
8
+ * style-hidden content a rendered viewer would suppress). With
9
+ * `--include-metadata true` the side-channel / authored metadata
10
+ * (properties, keywords, user-defined fields) is appended as a trailing block.
11
+ */
12
+ type OdfToMarkdownOptions = {
13
+ readonly includeMetadata?: boolean;
14
+ };
15
+ declare const odfToMarkdown: (bytes: Uint8Array, opts?: OdfToMarkdownOptions) => Promise<Result<MarkdownEnvelope, GraphError>>;
16
+ export { odfToMarkdown };
17
+ export type { OdfToMarkdownOptions };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Single source of truth for the OOXML extension families the markdown
3
+ * dispatchers route together. Each family shares one parser/extractor: the
4
+ * macro-enabled (`*m`) and template (`*tx` / `*tm`) variants are structurally
5
+ * identical to their base format, so they alias onto the same path. Keeping
6
+ * the lists here (not duplicated per dispatcher) means a new variant is added
7
+ * in exactly one place.
8
+ */
9
+ declare const DOCX_FAMILY: ReadonlySet<string>;
10
+ declare const XLSX_FAMILY: ReadonlySet<string>;
11
+ declare const PPTX_FAMILY: ReadonlySet<string>;
12
+ declare const ODF_FAMILY: ReadonlySet<string>;
13
+ export { DOCX_FAMILY, ODF_FAMILY, PPTX_FAMILY, XLSX_FAMILY };
@@ -1,6 +1,10 @@
1
1
  import type { Result } from '../../domain/result.js';
2
2
  import type { GraphClient, GraphError } from '../../infra/graph-client.js';
3
3
  import type { FetchOptions } from './fetch-raw-bytes.js';
4
- declare const officeToMarkdown: (graph: GraphClient, contentPath: string, filename: string, opts?: FetchOptions) => Promise<Result<unknown, GraphError>>;
4
+ type OfficeToMarkdownOptions = FetchOptions & {
5
+ readonly includeMetadata?: boolean;
6
+ readonly inlineImages?: boolean;
7
+ readonly maxCells?: number;
8
+ };
9
+ declare const officeToMarkdown: (graph: GraphClient, contentPath: string, filename: string, opts?: OfficeToMarkdownOptions) => Promise<Result<unknown, GraphError>>;
5
10
  export { officeToMarkdown };
6
- export type { FetchOptions };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Renders the `## OneNote metadata` block appended to `get-onenote-page-as-markdown`
3
+ * output under `--include-metadata true`. Mirrors the docx/xlsx/odf metadata-append
4
+ * pattern: a fenced section listing the page's title, created / last-modified
5
+ * timestamps, and the parent section + notebook names (expanded by the command).
6
+ * Pure formatter — every field is optional and omitted when absent.
7
+ */
8
+ type OnenotePage = {
9
+ readonly title?: string;
10
+ readonly createdDateTime?: string;
11
+ readonly lastModifiedDateTime?: string;
12
+ readonly parentSection?: {
13
+ readonly displayName?: string;
14
+ };
15
+ readonly parentNotebook?: {
16
+ readonly displayName?: string;
17
+ };
18
+ };
19
+ declare const formatOnenoteMetadata: (page: OnenotePage) => string;
20
+ export { formatOnenoteMetadata };
21
+ export type { OnenotePage };
@@ -0,0 +1,3 @@
1
+ import type { GraphClient } from '../../infra/graph-client.js';
2
+ declare const embedOnenoteResources: (graph: GraphClient, html: string) => Promise<string>;
3
+ export { embedOnenoteResources };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared markdown render primitives for the per-format metadata blocks
3
+ * (docx, xlsx, …). Sections with no entries emit `_(none)_` so the output
4
+ * stays grep-stable — an LLM can ask "is there a Comments section?" and get
5
+ * a yes/no answer without ambiguity.
6
+ *
7
+ * Pipe characters in cell values are escaped as `\|` so the rendered tables
8
+ * stay valid even when property values or comment bodies contain literal pipes.
9
+ */
10
+ declare const NONE = "_(none)_";
11
+ declare const escapeCell: (s: string) => string;
12
+ declare const renderKv: (props: Readonly<Record<string, string>>) => string;
13
+ declare const renderTable: (rows: ReadonlyArray<ReadonlyArray<string>>, headers: ReadonlyArray<string>) => string;
14
+ declare const renderBullets: (items: ReadonlyArray<string>) => string;
15
+ declare const renderMacros: (macros: ReadonlyArray<string>) => string;
16
+ export { escapeCell, NONE, renderBullets, renderKv, renderMacros, renderTable };
@@ -0,0 +1,23 @@
1
+ import type { OoxmlZip } from '../../infra/ooxml-zip-adapter.js';
2
+ /**
3
+ * The OOXML package-level metadata that is identical across .docx / .xlsx /
4
+ * .pptx: the three `docProps/*` property parts and every external
5
+ * relationship in the package. Per-format modules (docx-metadata,
6
+ * xlsx-metadata, …) compose these with their own body-specific extractors.
7
+ */
8
+ type CustomProp = {
9
+ readonly name: string;
10
+ readonly value: string;
11
+ };
12
+ type ExternalRel = {
13
+ readonly source: string;
14
+ readonly type: string;
15
+ readonly target: string;
16
+ };
17
+ declare const extractCoreProps: (zip: OoxmlZip) => Readonly<Record<string, string>>;
18
+ declare const extractAppProps: (zip: OoxmlZip) => Readonly<Record<string, string>>;
19
+ declare const extractCustomProps: (zip: OoxmlZip) => ReadonlyArray<CustomProp>;
20
+ declare const extractExternalRels: (zip: OoxmlZip) => ReadonlyArray<ExternalRel>;
21
+ declare const extractMacros: (zip: OoxmlZip) => ReadonlyArray<string>;
22
+ export { extractAppProps, extractCoreProps, extractCustomProps, extractExternalRels, extractMacros };
23
+ export type { CustomProp, ExternalRel };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Tiny generic walkers over a fast-xml-parser tree. OOXML is namespace-
3
+ * heavy (`w:`, `cp:`, `dc:`, `dcterms:`, `vt:`, `w15:`, `x:`, `p:`, ...) and
4
+ * the only traversal primitives we need are: find-every-element-by-tag-name,
5
+ * read a single attribute, read the leaf text content. Keeping these here
6
+ * lets the per-format metadata modules focus on what to extract, not how to
7
+ * traverse.
8
+ *
9
+ * fast-xml-parser tree shape:
10
+ * - element names are object keys (with `w:` etc. prefix preserved)
11
+ * - attributes are keys prefixed with `@_` (e.g. `@_w:val`, `@_TargetMode`)
12
+ * - text content sits under `#text` when the element also has attributes,
13
+ * OR directly as a string when the element has only text and no attrs
14
+ * - repeated same-named children come as an array; single occurrences as
15
+ * a bare object — every walker must handle both shapes
16
+ */
17
+ type XmlObject = Record<string, unknown>;
18
+ declare const parseXml: (xml: string | undefined) => unknown;
19
+ declare const findAll: (root: unknown, tagName: string) => ReadonlyArray<XmlObject>;
20
+ declare const textOf: (node: unknown) => string;
21
+ declare const attrOf: (node: XmlObject, name: string) => string;
22
+ /**
23
+ * Yield each occurrence of `tagName` inside `node` as its own text value.
24
+ * Used for leaf-text elements like `<w:instrText>` where each instance is a
25
+ * distinct entry (one MERGEFIELD per occurrence) — unlike collectText, which
26
+ * flattens every match into a single string for "the visible text of this run".
27
+ */
28
+ declare const findAllTexts: (root: unknown, tagName: string) => ReadonlyArray<string>;
29
+ /**
30
+ * Concatenate the text content of every element matching `tagName` inside `node`,
31
+ * regardless of nesting depth. Used to flatten a `<w:p>` (or `<w:ins>` / `<w:comment>`)
32
+ * down to its visible text by gathering every `<w:t>` (or `<w:delText>`) descendant.
33
+ */
34
+ declare const collectText: (node: unknown, tagName: string) => string;
35
+ export { attrOf, collectText, findAll, findAllTexts, parseXml, textOf };
36
+ export type { XmlObject };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * `--drive-id` description for every generic OneDrive / SharePoint drive-item
3
+ * command. Always points the caller at how to obtain a drive id.
4
+ */
5
+ export declare const DRIVE_ID_DESCRIPTION = "Microsoft Graph drive ID. Use `ask-marcel list-drives` for the personal OneDrive, or `ask-marcel list-sharepoint-site-drives --site-id <id>` for a SharePoint document library.";
@@ -33,5 +33,28 @@ export type OutputPathError = {
33
33
  readonly type: 'passthrough_extension_mismatch';
34
34
  readonly contentType: string;
35
35
  readonly requestedExtension: string;
36
+ } | {
37
+ readonly type: 'inline_too_large';
38
+ readonly base64Length: number;
39
+ };
40
+ export type OutputDirError = {
41
+ readonly type: 'no_media';
42
+ } | {
43
+ readonly type: 'empty_path';
44
+ } | {
45
+ readonly type: 'write_failed';
46
+ readonly message: string;
36
47
  };
37
48
  export declare const persistIfRequested: (fs: FileSystem, outputPath: string | undefined, data: unknown) => Promise<Result<unknown, OutputPathError>>;
49
+ /**
50
+ * Sibling of `persistIfRequested` for the global `--output-dir` flag. When a
51
+ * command returns a `media` array (`{ count, media: [{ path, base64, ... }] }`,
52
+ * from the image-extraction commands) and `--output-dir` is set, write each
53
+ * image to `<dir>/<flattened-path>` and replace its `base64` with `savedTo`.
54
+ * The media `path` is flattened (`pdf/page2/Im0.png` → `pdf_page2_Im0.png`)
55
+ * rather than reduced to its basename, because PDF page-image keys (`Im0`, …)
56
+ * repeat across pages — `basename` alone would collide and silently overwrite.
57
+ * The filesystem port auto-creates the directory. Anything without a media
58
+ * array returns `no_media` so the CLI can surface a clear error.
59
+ */
60
+ export declare const persistMediaIfRequested: (fs: FileSystem, outputDir: string | undefined, data: unknown) => Promise<Result<unknown, OutputDirError>>;
@@ -0,0 +1,19 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ type PdfTextEnvelope = {
4
+ readonly contentType: 'text/plain';
5
+ readonly size: number;
6
+ readonly text: string;
7
+ readonly pageCount: number;
8
+ };
9
+ /**
10
+ * Convert a PDF to a plain-text envelope by extracting its text layer (via unpdf).
11
+ * A born-digital PDF yields its reading-order text; a scanned / image-only PDF has
12
+ * no text layer, so the caller's `noTextHint` (pointing at the matching *-as-pdf
13
+ * command + a vision model) is returned as a 415 rather than an empty body. Output
14
+ * is text/plain, not structured markdown — pdfjs flattens layout into reading order.
15
+ * `size` is the byte length of the produced text (what `--output-path` writes),
16
+ * consistent with the other converters — NOT the source PDF's byte count.
17
+ */
18
+ declare const pdfToMarkdown: (bytes: Uint8Array, noTextHint: string) => Promise<Result<PdfTextEnvelope, GraphError>>;
19
+ export { pdfToMarkdown };
@@ -0,0 +1,24 @@
1
+ import type { OoxmlZip } from '../../infra/ooxml-zip-adapter.js';
2
+ /**
3
+ * PowerPoint comments come in two formats: legacy (`ppt/commentAuthors.xml`
4
+ * authors by integer id + `ppt/comments/comment*.xml` `<p:cm authorId dt>`
5
+ * with `<p:text>` body) and modern (`ppt/authors.xml` authors by GUID +
6
+ * `ppt/comments/*.xml` `<p188:cm authorId created>` with DrawingML `<a:t>`
7
+ * body). Both are scanned; authors are resolved by id in either scheme.
8
+ * Modern-comment support is best-effort against the p188 (2018/8) schema.
9
+ */
10
+ type CommentAuthor = {
11
+ readonly id: string;
12
+ readonly name: string;
13
+ readonly initials: string;
14
+ };
15
+ type PptxComment = {
16
+ readonly author: string;
17
+ readonly date: string;
18
+ readonly text: string;
19
+ readonly slide?: string;
20
+ };
21
+ declare const extractCommentAuthors: (zip: OoxmlZip) => ReadonlyArray<CommentAuthor>;
22
+ declare const extractComments: (zip: OoxmlZip, authors: ReadonlyArray<CommentAuthor>) => ReadonlyArray<PptxComment>;
23
+ export { extractCommentAuthors, extractComments };
24
+ export type { CommentAuthor, PptxComment };
@@ -0,0 +1,3 @@
1
+ import type { PptxMetadata } from './pptx-metadata.js';
2
+ declare const formatPptxMetadata: (meta: PptxMetadata) => string;
3
+ export { formatPptxMetadata };
@@ -0,0 +1,33 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ import type { CustomProp, ExternalRel } from './ooxml-metadata.js';
4
+ import type { CommentAuthor, PptxComment } from './pptx-comments.js';
5
+ import type { Slide } from './pptx-slides.js';
6
+ /**
7
+ * Pulls the side-channel content out of a .pptx zip — everything a user can
8
+ * author that the rendered slide PDF never shows: core / app / custom doc
9
+ * properties, external relationships, slide tags (key/value), comment authors
10
+ * and comments (legacy + modern), and per-slide title / speaker notes / hidden
11
+ * flag. Package-level parts come from the shared ooxml-metadata module; this
12
+ * file owns the presentation-specific parts.
13
+ */
14
+ type PropMap = Readonly<Record<string, string>>;
15
+ type SlideTag = {
16
+ readonly source: string;
17
+ readonly name: string;
18
+ readonly value: string;
19
+ };
20
+ type PptxMetadata = {
21
+ readonly core: PropMap;
22
+ readonly app: PropMap;
23
+ readonly custom: ReadonlyArray<CustomProp>;
24
+ readonly externalRels: ReadonlyArray<ExternalRel>;
25
+ readonly slideTags: ReadonlyArray<SlideTag>;
26
+ readonly commentAuthors: ReadonlyArray<CommentAuthor>;
27
+ readonly comments: ReadonlyArray<PptxComment>;
28
+ readonly slides: ReadonlyArray<Slide>;
29
+ readonly macros: ReadonlyArray<string>;
30
+ };
31
+ declare const extractPptxMetadata: (bytes: Uint8Array) => Promise<Result<PptxMetadata, GraphError>>;
32
+ export { extractPptxMetadata };
33
+ export type { CommentAuthor, PptxComment, PptxMetadata, Slide, SlideTag };
@@ -0,0 +1,17 @@
1
+ import type { OoxmlZip } from '../../infra/ooxml-zip-adapter.js';
2
+ /**
3
+ * Per-slide extraction: the hidden flag (`<p:sld show="0">`), the title
4
+ * placeholder text, and the speaker notes resolved through the slide's
5
+ * relationship part. Speaker notes are the headline pptx side-channel —
6
+ * presenter-authored text that never appears on the rendered slide.
7
+ */
8
+ type Slide = {
9
+ readonly name: string;
10
+ readonly hidden: boolean;
11
+ readonly title: string;
12
+ readonly notes: string;
13
+ readonly text: string;
14
+ };
15
+ declare const extractSlides: (zip: OoxmlZip) => ReadonlyArray<Slide>;
16
+ export { extractSlides };
17
+ export type { Slide };
@@ -0,0 +1,7 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ import type { MarkdownEnvelope } from './docx-to-markdown.js';
4
+ declare const pptxToMarkdown: (bytes: Uint8Array, options?: {
5
+ readonly includeMetadata?: boolean;
6
+ }) => Promise<Result<MarkdownEnvelope, GraphError>>;
7
+ export { pptxToMarkdown };
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ import type { Result } from '../../domain/result.js';
3
+ import type { GraphClient, GraphError } from '../../infra/graph-client.js';
4
+ import type { CommandMeta } from './command-types.js';
5
+ declare const schema: z.ZodObject<{
6
+ messageId: z.ZodString;
7
+ attachmentId: z.ZodString;
8
+ includeMetadata: z.ZodOptional<z.ZodEnum<{
9
+ true: "true";
10
+ false: "false";
11
+ }>>;
12
+ }, z.core.$strip>;
13
+ declare const execute: (graph: GraphClient, params: Record<string, string>) => Promise<Result<unknown, GraphError>>;
14
+ declare const meta: CommandMeta;
15
+ export { execute, meta, schema };
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import type { Command, CommandMeta } from './command-types.js';
3
+ declare const schema: z.ZodObject<{
4
+ query: z.ZodOptional<z.ZodString>;
5
+ countFiles: z.ZodOptional<z.ZodEnum<{
6
+ true: "true";
7
+ false: "false";
8
+ }>>;
9
+ }, z.core.$strip>;
10
+ declare const execute: Command['execute'];
11
+ declare const meta: CommandMeta;
12
+ export { execute, meta, schema };
@@ -0,0 +1,3 @@
1
+ import type { GraphClient } from '../../infra/graph-client.js';
2
+ declare const searchIndexTotal: (graph: GraphClient, entityType: string, queryString?: string) => Promise<number | undefined>;
3
+ export { searchIndexTotal };
@@ -1,4 +1,5 @@
1
- import type { CommandMeta } from './command-types.js';
2
- declare const execute: import("./command-types.js").CommandExecute, schema: import("./command-types.js").CommandSchema;
1
+ import type { Command, CommandMeta } from './command-types.js';
2
+ declare const schema: import("./command-types.js").CommandSchema;
3
+ declare const execute: Command['execute'];
3
4
  declare const meta: CommandMeta;
4
5
  export { execute, meta, schema };
@@ -1,14 +1,19 @@
1
- /**
2
- * Pure helpers for `extract-sharepoint-links-in-mail`.
3
- *
4
- * `extractSharepointUrls(htmlBody)` finds every `https://*.sharepoint.com/...`
5
- * URL inside an HTML mail body — both `<a href=...>` and bare-text
6
- * occurrences — and returns the deduplicated list.
7
- *
8
- * `buildShareToken(url)` encodes a URL for Graph's `/shares/{token}`
9
- * resolver per [shares-get](https://learn.microsoft.com/en-us/graph/api/shares-get):
10
- * `u!` + base64url(url) with no padding.
11
- */
1
+ import type { GraphClient } from '../../infra/graph-client.js';
2
+ type ResolvedLink = {
3
+ readonly url: string;
4
+ readonly driveId?: string;
5
+ readonly itemId?: string;
6
+ readonly name?: string;
7
+ readonly webUrl?: string;
8
+ readonly error?: string;
9
+ };
10
+ type ResolvedLinks = {
11
+ readonly links: ReadonlyArray<ResolvedLink>;
12
+ readonly truncated: boolean;
13
+ readonly skippedCount: number;
14
+ };
12
15
  declare const extractSharepointUrls: (htmlBody: string) => ReadonlyArray<string>;
13
16
  declare const buildShareToken: (url: string) => string;
14
- export { buildShareToken, extractSharepointUrls };
17
+ declare const resolveSharepointUrls: (graph: GraphClient, urls: ReadonlyArray<string>) => Promise<ResolvedLinks>;
18
+ export { buildShareToken, extractSharepointUrls, resolveSharepointUrls };
19
+ export type { ResolvedLink, ResolvedLinks };
@@ -18,7 +18,20 @@
18
18
  * The user wanted a PDF and the source IS a PDF, so return its
19
19
  * bytes directly.
20
20
  */
21
- declare const PLAIN_TEXT_EXTENSIONS: ReadonlySet<string>;
21
+ declare const extensionOf: (name: string) => string;
22
22
  declare const isPlainTextFilename: (name: string) => boolean;
23
23
  declare const isPdfSource: (name: string) => boolean;
24
- export { isPdfSource, isPlainTextFilename, PLAIN_TEXT_EXTENSIONS };
24
+ /**
25
+ * Content-sniff for text — decode bytes STRICTLY as UTF-8. Returns the decoded
26
+ * string when the bytes are valid UTF-8, `undefined` when they are not (i.e.
27
+ * binary). The conversion / content commands use this instead of trusting a
28
+ * file extension: it detects any text file regardless of name AND can never
29
+ * mangle binary into `�` (the non-fatal decoder's silent corruption — the bug
30
+ * a binary file named `.txt` triggered). Non-UTF-8-encoded text (UTF-16, etc.)
31
+ * is reported as binary, which is faithful (base64) rather than lossy.
32
+ *
33
+ * `{ fatal: true }` makes `decode` throw on the first invalid sequence; the
34
+ * try/catch is a pure-domain fallback around a native synchronous thrower.
35
+ */
36
+ declare const decodeUtf8Text: (bytes: Uint8Array) => string | undefined;
37
+ export { decodeUtf8Text, extensionOf, isPdfSource, isPlainTextFilename };
@@ -0,0 +1,7 @@
1
+ import type { GraphError } from '../../infra/graph-client.js';
2
+ type TodoQuirkParams = {
3
+ readonly select?: string;
4
+ readonly orderby?: string;
5
+ };
6
+ declare const rewriteTodoTitleQuirk: (error: GraphError, params: TodoQuirkParams) => GraphError | undefined;
7
+ export { rewriteTodoTitleQuirk };
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ import type { Command, CommandMeta } from './command-types.js';
3
+ declare const schema: z.ZodObject<{
4
+ messageId: z.ZodString;
5
+ subject: z.ZodOptional<z.ZodString>;
6
+ bodyContent: z.ZodOptional<z.ZodString>;
7
+ bodyContentType: z.ZodOptional<z.ZodEnum<{
8
+ Text: "Text";
9
+ HTML: "HTML";
10
+ }>>;
11
+ toRecipients: z.ZodOptional<z.ZodString>;
12
+ ccRecipients: z.ZodOptional<z.ZodString>;
13
+ bccRecipients: z.ZodOptional<z.ZodString>;
14
+ importance: z.ZodOptional<z.ZodEnum<{
15
+ Low: "Low";
16
+ Normal: "Normal";
17
+ High: "High";
18
+ }>>;
19
+ }, z.core.$strip>;
20
+ declare const execute: Command['execute'];
21
+ declare const meta: CommandMeta;
22
+ export { execute, meta, schema };
@@ -0,0 +1,29 @@
1
+ import type { OoxmlZip } from '../../infra/ooxml-zip-adapter.js';
2
+ /**
3
+ * Workbook annotations + the identities behind them. xlsx has two comment
4
+ * formats: legacy cell comments (xl/comments*.xml, author by index into an
5
+ * <authors> list) and modern threaded comments (xl/threadedComments/*, author
6
+ * by personId resolved through xl/persons/person.xml). Both are user-authored
7
+ * and invisible in the value-rendered body.
8
+ */
9
+ type CellComment = {
10
+ readonly cell: string;
11
+ readonly author: string;
12
+ readonly text: string;
13
+ };
14
+ type ThreadedComment = {
15
+ readonly cell: string;
16
+ readonly author: string;
17
+ readonly date: string;
18
+ readonly text: string;
19
+ };
20
+ type Person = {
21
+ readonly id: string;
22
+ readonly displayName: string;
23
+ readonly userId: string;
24
+ };
25
+ declare const extractPeople: (zip: OoxmlZip) => ReadonlyArray<Person>;
26
+ declare const extractLegacyComments: (zip: OoxmlZip) => ReadonlyArray<CellComment>;
27
+ declare const extractThreadedComments: (zip: OoxmlZip, people: ReadonlyArray<Person>) => ReadonlyArray<ThreadedComment>;
28
+ export { extractLegacyComments, extractPeople, extractThreadedComments };
29
+ export type { CellComment, Person, ThreadedComment };
@@ -0,0 +1,3 @@
1
+ import type { XlsxMetadata } from './xlsx-metadata.js';
2
+ declare const formatXlsxMetadata: (meta: XlsxMetadata) => string;
3
+ export { formatXlsxMetadata };
@@ -0,0 +1,39 @@
1
+ import type { Result } from '../../domain/result.js';
2
+ import type { GraphError } from '../../infra/graph-client.js';
3
+ import type { CustomProp, ExternalRel } from './ooxml-metadata.js';
4
+ import type { CellComment, Person, ThreadedComment } from './xlsx-comments.js';
5
+ /**
6
+ * Pulls the side-channel content out of a .xlsx zip — everything a user can
7
+ * author that the value-rendered markdown body (cells per sheet) never shows:
8
+ * core / app / custom doc properties, external relationships, defined names
9
+ * (named ranges & formulas), hidden / very-hidden sheets, legacy cell
10
+ * comments, threaded comments, and the persons registry behind them.
11
+ *
12
+ * Package-level parts (docProps/*, every *.rels) come from the shared
13
+ * ooxml-metadata module; this file owns the workbook-specific parts.
14
+ */
15
+ type PropMap = Readonly<Record<string, string>>;
16
+ type DefinedName = {
17
+ readonly name: string;
18
+ readonly refersTo: string;
19
+ readonly hidden: boolean;
20
+ };
21
+ type Sheet = {
22
+ readonly name: string;
23
+ readonly state: string;
24
+ };
25
+ type XlsxMetadata = {
26
+ readonly core: PropMap;
27
+ readonly app: PropMap;
28
+ readonly custom: ReadonlyArray<CustomProp>;
29
+ readonly externalRels: ReadonlyArray<ExternalRel>;
30
+ readonly definedNames: ReadonlyArray<DefinedName>;
31
+ readonly hiddenSheets: ReadonlyArray<Sheet>;
32
+ readonly comments: ReadonlyArray<CellComment>;
33
+ readonly threadedComments: ReadonlyArray<ThreadedComment>;
34
+ readonly people: ReadonlyArray<Person>;
35
+ readonly macros: ReadonlyArray<string>;
36
+ };
37
+ declare const extractXlsxMetadata: (bytes: Uint8Array) => Promise<Result<XlsxMetadata, GraphError>>;
38
+ export { extractXlsxMetadata };
39
+ export type { CellComment, DefinedName, Person, Sheet, ThreadedComment, XlsxMetadata };
@@ -1,6 +1,13 @@
1
1
  import type { Result } from '../../domain/result.js';
2
2
  import type { GraphError } from '../../infra/graph-client.js';
3
3
  import type { MarkdownEnvelope } from './docx-to-markdown.js';
4
+ type XlsxToMarkdownOptions = {
5
+ readonly includeMetadata?: boolean;
6
+ readonly maxCells?: number;
7
+ };
4
8
  declare const csvToMarkdownTable: (csv: string) => string;
5
- declare const xlsxToMarkdown: (bytes: Uint8Array) => Result<MarkdownEnvelope, GraphError>;
6
- export { csvToMarkdownTable, xlsxToMarkdown };
9
+ declare const renderCsvCapped: (csv: string, maxCells?: number) => string;
10
+ declare const csvToMarkdownSection: (name: string, csv: string, maxCells?: number) => string;
11
+ declare const xlsxToMarkdown: (bytes: Uint8Array, opts?: XlsxToMarkdownOptions) => Promise<Result<MarkdownEnvelope, GraphError>>;
12
+ export { csvToMarkdownSection, csvToMarkdownTable, renderCsvCapped, xlsxToMarkdown };
13
+ export type { XlsxToMarkdownOptions };