ask-marcel-office-cli 1.0.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/README.md +153 -384
- package/dist/cli.js +13222 -94112
- package/dist/commands.json +1500 -135
- package/dist/composition/build-deps.d.ts +13 -0
- package/dist/composition/cli.d.ts +8 -0
- package/dist/domain/iso-datetime.d.ts +30 -0
- package/dist/domain/utilities/archive-status.d.ts +18 -0
- package/dist/domain/utilities/site-url-classifier.d.ts +15 -0
- package/dist/index.js +10912 -92275
- package/dist/infra/auth.d.ts +56 -3
- package/dist/infra/browser-auth.d.ts +100 -10
- package/dist/infra/graph-client.d.ts +40 -0
- package/dist/infra/legacy-doc-extractor.d.ts +14 -0
- package/dist/infra/msg-reader-adapter.d.ts +83 -0
- package/dist/infra/network-error.d.ts +9 -0
- package/dist/infra/ooxml-media-extractor.d.ts +27 -0
- package/dist/infra/ooxml-zip-adapter.d.ts +28 -0
- package/dist/infra/pdf-image-extractor.d.ts +18 -0
- package/dist/infra/pdf-text-extractor.d.ts +41 -0
- package/dist/infra/png-encode.d.ts +15 -0
- package/dist/infra/sheetjs-adapter.d.ts +1 -1
- package/dist/infra/system-browser-auth.d.ts +35 -0
- package/dist/infra/system-browser-loader.d.ts +3 -0
- package/dist/infra/token-callback-server.d.ts +31 -0
- package/dist/infra/zip-reader.d.ts +32 -0
- package/dist/presenter/error-hints.d.ts +41 -0
- package/dist/presenter/output.d.ts +2 -1
- package/dist/use-cases/commands/build-command.d.ts +30 -8
- package/dist/use-cases/commands/command-types.d.ts +53 -1
- package/dist/use-cases/commands/convert-calendar-event-attachment-to-markdown.d.ts +15 -0
- package/dist/use-cases/commands/{download-drive-item-version-as-pdf.d.ts → convert-calendar-event-attachment-to-pdf.d.ts} +2 -3
- package/dist/use-cases/commands/convert-drive-item-zip.d.ts +26 -0
- package/dist/use-cases/commands/convert-local-file.d.ts +37 -0
- package/dist/use-cases/commands/convert-mail-attachment-to-markdown.d.ts +7 -1
- package/dist/use-cases/commands/convert-mail-attachment-to-pdf.d.ts +2 -1
- package/dist/use-cases/commands/convert-mail-attachment-zip.d.ts +24 -0
- package/dist/use-cases/commands/convert-mail-to-markdown.d.ts +8 -0
- package/dist/use-cases/commands/create-mail-draft.d.ts +22 -0
- package/dist/use-cases/commands/doc-to-markdown.d.ts +14 -0
- package/dist/use-cases/commands/docs-render.d.ts +7 -2
- package/dist/use-cases/commands/docs.d.ts +44 -1
- package/dist/use-cases/commands/docx-comment-anchors.d.ts +22 -0
- package/dist/use-cases/commands/docx-metadata-to-markdown.d.ts +3 -0
- package/dist/use-cases/commands/docx-metadata.d.ts +69 -0
- package/dist/use-cases/commands/docx-to-markdown.d.ts +8 -3
- package/dist/use-cases/commands/download-drive-item-as-markdown.d.ts +9 -0
- package/dist/use-cases/commands/download-drive-item-version.d.ts +21 -0
- package/dist/use-cases/commands/{download-drive-item-version-as-markdown.d.ts → extract-drive-item-images.d.ts} +0 -1
- package/dist/use-cases/commands/extract-local-file-images.d.ts +21 -0
- package/dist/use-cases/commands/{download-drive-item-version-content.d.ts → extract-mail-attachment-images.d.ts} +2 -3
- package/dist/use-cases/commands/extract-sharepoint-links-in-documents.d.ts +33 -0
- package/dist/use-cases/commands/extract-sharepoint-links-in-mail.d.ts +1 -8
- package/dist/use-cases/commands/fetch-raw-bytes.d.ts +2 -1
- package/dist/use-cases/commands/file-counts.d.ts +7 -0
- package/dist/use-cases/commands/filter-archived-sites.d.ts +17 -0
- package/dist/use-cases/commands/find-chats-with-user.d.ts +10 -0
- package/dist/use-cases/commands/first-sentence.d.ts +12 -0
- package/dist/use-cases/commands/get-chat.d.ts +1 -5
- package/dist/use-cases/commands/get-excel-chart-image.d.ts +20 -0
- package/dist/use-cases/commands/get-excel-used-range.d.ts +7 -2
- package/dist/use-cases/commands/get-onenote-page-as-markdown.d.ts +8 -0
- package/dist/use-cases/commands/get-teams-chat-message.d.ts +9 -0
- package/dist/use-cases/commands/get-todo-task.d.ts +9 -2
- package/dist/use-cases/commands/image-extraction.d.ts +10 -0
- package/dist/use-cases/commands/iso-datetime-schema.d.ts +21 -0
- package/dist/use-cases/commands/link-shape.d.ts +13 -0
- package/dist/use-cases/commands/list-accessible-drives.d.ts +14 -0
- package/dist/use-cases/commands/list-calendar-event-attachments.d.ts +14 -0
- package/dist/use-cases/commands/list-calendar-view-delta.d.ts +2 -2
- package/dist/use-cases/commands/list-teams-chat-history.d.ts +16 -0
- package/dist/use-cases/commands/list-teams-chat-messages.d.ts +8 -0
- package/dist/use-cases/commands/list-teams-chats-with-messages.d.ts +9 -0
- package/dist/use-cases/commands/mail-quote-stripper.d.ts +25 -0
- package/dist/use-cases/commands/markdown-dispatch.d.ts +29 -0
- package/dist/use-cases/commands/markdown-pipeline.d.ts +6 -2
- package/dist/use-cases/commands/media-files.d.ts +20 -0
- package/dist/use-cases/commands/msg-to-markdown.d.ts +28 -0
- package/dist/use-cases/commands/odf-content-to-markdown.d.ts +5 -0
- package/dist/use-cases/commands/odf-metadata-to-markdown.d.ts +3 -0
- package/dist/use-cases/commands/odf-metadata.d.ts +26 -0
- package/dist/use-cases/commands/odf-to-markdown.d.ts +17 -0
- package/dist/use-cases/commands/office-extensions.d.ts +13 -0
- package/dist/use-cases/commands/office-to-markdown.d.ts +6 -2
- package/dist/use-cases/commands/onenote-metadata.d.ts +21 -0
- package/dist/use-cases/commands/onenote-resource-embedder.d.ts +3 -0
- package/dist/use-cases/commands/ooxml-metadata-to-markdown.d.ts +16 -0
- package/dist/use-cases/commands/ooxml-metadata.d.ts +23 -0
- package/dist/use-cases/commands/ooxml-xml-walker.d.ts +36 -0
- package/dist/use-cases/commands/option-descriptions.d.ts +5 -0
- package/dist/use-cases/commands/output-path.d.ts +23 -0
- package/dist/use-cases/commands/pdf-to-markdown.d.ts +19 -0
- package/dist/use-cases/commands/pptx-comments.d.ts +24 -0
- package/dist/use-cases/commands/pptx-metadata-to-markdown.d.ts +3 -0
- package/dist/use-cases/commands/pptx-metadata.d.ts +33 -0
- package/dist/use-cases/commands/pptx-slides.d.ts +17 -0
- package/dist/use-cases/commands/pptx-to-markdown.d.ts +7 -0
- package/dist/use-cases/commands/read-mail-attachment.d.ts +15 -0
- package/dist/use-cases/commands/resolve-calendar-link.d.ts +8 -0
- package/dist/use-cases/commands/resolve-drive-share-link.d.ts +8 -0
- package/dist/use-cases/commands/resolve-mail-link.d.ts +8 -0
- package/dist/use-cases/commands/resolve-teams-link.d.ts +8 -0
- package/dist/use-cases/commands/search-all-accessible-sites.d.ts +12 -0
- package/dist/use-cases/commands/search-index-total.d.ts +3 -0
- package/dist/use-cases/commands/search-sharepoint-sites-by-name.d.ts +3 -2
- package/dist/use-cases/commands/sharepoint-link-extractor.d.ts +17 -12
- package/dist/use-cases/commands/text-passthrough.d.ts +15 -2
- package/dist/use-cases/commands/todo-parse-uri-rewrite.d.ts +7 -0
- package/dist/use-cases/commands/update-mail-draft.d.ts +22 -0
- package/dist/use-cases/commands/version-id.d.ts +7 -6
- package/dist/use-cases/commands/xlsx-comments.d.ts +29 -0
- package/dist/use-cases/commands/xlsx-metadata-to-markdown.d.ts +3 -0
- package/dist/use-cases/commands/xlsx-metadata.d.ts +39 -0
- package/dist/use-cases/commands/xlsx-to-markdown.d.ts +9 -2
- package/dist/use-cases/commands/zip-archive-to-markdown.d.ts +30 -0
- package/dist/use-cases/ports/filesystem.d.ts +10 -0
- package/docs/COMMANDS.md +259 -0
- package/docs/USAGE.md +266 -0
- package/docs/commands.json +1500 -135
- package/package.json +16 -8
- /package/dist/use-cases/commands/{download-onedrive-file-content.d.ts → download-drive-item-content.d.ts} +0 -0
|
@@ -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,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,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,8 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Command, CommandMeta } from './command-types.js';
|
|
3
|
+
declare const schema: z.ZodObject<{
|
|
4
|
+
url: z.ZodURL;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
declare const execute: Command['execute'];
|
|
7
|
+
declare const meta: CommandMeta;
|
|
8
|
+
export { execute, meta, schema };
|
|
@@ -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
|
+
url: z.ZodURL;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
declare const execute: Command['execute'];
|
|
7
|
+
declare const meta: CommandMeta;
|
|
8
|
+
export { execute, meta, schema };
|
|
@@ -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
|
+
url: z.ZodURL;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
declare const execute: Command['execute'];
|
|
7
|
+
declare const meta: CommandMeta;
|
|
8
|
+
export { execute, meta, schema };
|
|
@@ -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
|
+
url: z.ZodURL;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
declare const execute: Command['execute'];
|
|
7
|
+
declare const meta: CommandMeta;
|
|
8
|
+
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 };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CommandMeta } from './command-types.js';
|
|
2
|
-
declare const
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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
|
|
21
|
+
declare const extensionOf: (name: string) => string;
|
|
22
22
|
declare const isPlainTextFilename: (name: string) => boolean;
|
|
23
23
|
declare const isPdfSource: (name: string) => boolean;
|
|
24
|
-
|
|
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 };
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Graph's historical-version endpoints template `{version-id}` as a string
|
|
3
3
|
* that must look like a stringified float (`"79.0"`, `"4.0"`). An LLM
|
|
4
|
-
* (reasonably) types `79`, and
|
|
5
|
-
* the three
|
|
4
|
+
* (reasonably) types `79`, and Graph's response is wildly inconsistent
|
|
5
|
+
* across the three internal pipelines that the consolidated
|
|
6
|
+
* `download-drive-item-version` command dispatches to:
|
|
6
7
|
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
8
|
+
* - --format original → `invalidRequest`
|
|
9
|
+
* - --format markdown → `invalidRequest`
|
|
10
|
+
* - --format pdf → accepts (Graph quirk)
|
|
10
11
|
*
|
|
11
12
|
* Audit round-6 §1.4 caught the inconsistency. Normalize at the CLI
|
|
12
13
|
* boundary: a pure-integer version-id gets `.0` appended before path
|
|
13
|
-
* substitution, so all three
|
|
14
|
+
* substitution, so all three formats accept both spellings.
|
|
14
15
|
*
|
|
15
16
|
* Already-floated values (`79.0`, `12.5`, `4.1`) and non-numeric values
|
|
16
17
|
* (a bad input the schema will then reject) pass through unchanged.
|
|
@@ -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,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
|
|
6
|
-
|
|
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 };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Result } from '../../domain/result.js';
|
|
2
|
+
import type { GraphError } from '../../infra/graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shared "unzip + convert every contained file" core behind
|
|
5
|
+
* `convert-drive-item-zip` (a OneDrive / SharePoint .zip),
|
|
6
|
+
* `convert-mail-attachment-zip` (an Outlook .zip attachment), and
|
|
7
|
+
* `convert-local-file` (a .zip on disk). Each entry is run through the same
|
|
8
|
+
* `bytesToMarkdown` dispatch the markdown commands use; an entry the dispatch
|
|
9
|
+
* can't convert (image, binary, nested archive, scanned PDF) is LISTED with a
|
|
10
|
+
* note instead of failing the whole archive. Notes use the container-neutral
|
|
11
|
+
* NESTED_HINTS (QA-007): entries live INSIDE the zip, so caller-specific
|
|
12
|
+
* sibling-command pointers (`extract-drive-item-images`, …) cannot reach them.
|
|
13
|
+
*/
|
|
14
|
+
declare const MAX_ENTRIES = 100;
|
|
15
|
+
type FileResult = {
|
|
16
|
+
readonly path: string;
|
|
17
|
+
readonly contentType?: string;
|
|
18
|
+
readonly size?: number;
|
|
19
|
+
readonly text?: string;
|
|
20
|
+
readonly note?: string;
|
|
21
|
+
};
|
|
22
|
+
type ZipArchiveResult = {
|
|
23
|
+
readonly count: number;
|
|
24
|
+
readonly truncated?: true;
|
|
25
|
+
readonly totalEntries?: number;
|
|
26
|
+
readonly files: ReadonlyArray<FileResult>;
|
|
27
|
+
};
|
|
28
|
+
declare const convertZipArchive: (bytes: Uint8Array, includeMetadata: boolean) => Promise<Result<ZipArchiveResult, GraphError>>;
|
|
29
|
+
export { convertZipArchive, MAX_ENTRIES };
|
|
30
|
+
export type { FileResult, ZipArchiveResult };
|
|
@@ -10,8 +10,18 @@ export type FileSystemError = {
|
|
|
10
10
|
};
|
|
11
11
|
export type FileSystem = {
|
|
12
12
|
readonly readJson: <T>(path: string) => Promise<Result<T, FileSystemError>>;
|
|
13
|
+
/**
|
|
14
|
+
* Read a file's raw bytes. Used by `convert-local-file` to feed a local
|
|
15
|
+
* document into the same conversion dispatch the Graph-backed commands use.
|
|
16
|
+
*/
|
|
17
|
+
readonly readBytes: (path: string) => Promise<Result<Uint8Array, FileSystemError>>;
|
|
13
18
|
readonly writeText: (path: string, content: string) => Promise<Result<void, FileSystemError>>;
|
|
14
19
|
readonly writeBytes: (path: string, bytes: Uint8Array) => Promise<Result<void, FileSystemError>>;
|
|
20
|
+
/**
|
|
21
|
+
* Restrict a file's permission bits (e.g. 0o600 on the token cache so
|
|
22
|
+
* other local users cannot read cached secrets — QA-001).
|
|
23
|
+
*/
|
|
24
|
+
readonly chmod: (path: string, mode: number) => Promise<Result<void, FileSystemError>>;
|
|
15
25
|
readonly deleteIfExists: (path: string) => Promise<Result<void, FileSystemError>>;
|
|
16
26
|
/**
|
|
17
27
|
* Recursively delete a directory (and all its contents). Used by `logout`
|