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
package/dist/infra/auth.d.ts
CHANGED
|
@@ -31,6 +31,30 @@ type AuthManager = {
|
|
|
31
31
|
* via headless Playwright. Used by the 3 historical-version commands.
|
|
32
32
|
*/
|
|
33
33
|
getElevatedAccessToken: () => Promise<Result<AccessToken, AuthError>>;
|
|
34
|
+
/**
|
|
35
|
+
* Returns a chatsvcagg-audience token (same Teams web client identity
|
|
36
|
+
* as `getAccessToken`, but issued for the chatsvcagg resource). Falls
|
|
37
|
+
* through cache → re-capture via headless Playwright. Used by the
|
|
38
|
+
* `list-teams-chats-with-messages` family of commands.
|
|
39
|
+
*/
|
|
40
|
+
getChatsvcaggAccessToken: () => Promise<Result<AccessToken, AuthError>>;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the regional segment used to construct chatsvcagg substrate
|
|
43
|
+
* URLs (`teams.microsoft.com/api/csa/<region>/api/...`). Captured at
|
|
44
|
+
* login from the first such URL the chatsvcagg bearer rides on. Falls
|
|
45
|
+
* back to `DEFAULT_CHATSVCAGG_REGION` ('emea') when the cache is
|
|
46
|
+
* either absent or pre-2026-05-migration. Synchronous on cache; calls
|
|
47
|
+
* `getChatsvcaggAccessToken()` first if no cache exists so a region is
|
|
48
|
+
* available immediately after login.
|
|
49
|
+
*/
|
|
50
|
+
getChatsvcaggRegion: () => Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Returns an IC3-audience bearer (Teams web client identity, aud
|
|
53
|
+
* `https://ic3.teams.office.com`). Falls through cache → re-capture
|
|
54
|
+
* via headless Playwright. Used by `list-teams-chat-history` to walk
|
|
55
|
+
* paginated chat-message history beyond the 200-message chatsvcagg cap.
|
|
56
|
+
*/
|
|
57
|
+
getIc3AccessToken: () => Promise<Result<AccessToken, AuthError>>;
|
|
34
58
|
logout: () => Promise<Result<void, AuthError>>;
|
|
35
59
|
/**
|
|
36
60
|
* Inspect the elevated-capture outcome from the most recent
|
|
@@ -39,13 +63,42 @@ type AuthManager = {
|
|
|
39
63
|
* Login-fix round-1 Wave D.
|
|
40
64
|
*/
|
|
41
65
|
getLastElevatedOutcome: () => ElevatedOutcome | null;
|
|
66
|
+
/**
|
|
67
|
+
* Inspect the chatsvcagg-capture outcome from the most recent
|
|
68
|
+
* `acquireViaBrowser` invocation. Same shape and lifetime semantics
|
|
69
|
+
* as `getLastElevatedOutcome`.
|
|
70
|
+
*/
|
|
71
|
+
getLastChatsvcaggOutcome: () => ElevatedOutcome | null;
|
|
42
72
|
};
|
|
43
|
-
|
|
73
|
+
type SystemBrowserAuthFn = () => Promise<Result<{
|
|
74
|
+
accessToken: AccessToken;
|
|
75
|
+
refreshToken: string | null;
|
|
76
|
+
elevatedAccessToken?: AccessToken | null;
|
|
77
|
+
chatsvcaggAccessToken?: AccessToken | null;
|
|
78
|
+
ic3AccessToken?: AccessToken | null;
|
|
79
|
+
chatsvcaggRegion?: string;
|
|
80
|
+
}, {
|
|
81
|
+
type: string;
|
|
82
|
+
message: string;
|
|
83
|
+
}>>;
|
|
84
|
+
declare const createAuthManagerFromApi: (browserAuth: BrowserAuth, cachePath: string, browserProfileDir: string, logger: Logger, fs: FileSystem, systemBrowserAuthFn?: SystemBrowserAuthFn, usePlaywrightFallback?: boolean, skipSystemBrowser?: boolean) => AuthManager;
|
|
85
|
+
/**
|
|
86
|
+
* QA-010: probe the token cache for a fresh access token. Handed to the
|
|
87
|
+
* browser capture so its poll loop can short-circuit the multi-minute dance
|
|
88
|
+
* when a concurrent process refreshes first (AAD rotates SPA refresh tokens,
|
|
89
|
+
* so the loser of the race cannot refresh and falls into the browser leg).
|
|
90
|
+
* Exported for the composition test; pure read, never writes.
|
|
91
|
+
*/
|
|
92
|
+
declare const createFreshCachedTokenProbe: (fs: FileSystem, cachePath: string) => (() => Promise<string | null>);
|
|
93
|
+
declare const stderrProgress: (line: string) => void;
|
|
44
94
|
declare const createAuthManager: (deps: {
|
|
45
95
|
cachePath: string;
|
|
46
96
|
logger: Logger;
|
|
47
97
|
fs?: FileSystem;
|
|
48
98
|
browserProfileDir?: string;
|
|
99
|
+
systemBrowserAuth?: SystemBrowserAuthFn;
|
|
100
|
+
usePlaywrightFallback?: boolean;
|
|
101
|
+
skipSystemBrowser?: boolean;
|
|
49
102
|
}) => AuthManager;
|
|
50
|
-
export { createAuthManager, createAuthManagerFromApi };
|
|
51
|
-
export type { AuthError, AuthManager, ElevatedOutcome };
|
|
103
|
+
export { createAuthManager, createAuthManagerFromApi, createFreshCachedTokenProbe, stderrProgress };
|
|
104
|
+
export type { AuthError, AuthManager, ElevatedOutcome, SystemBrowserAuthFn };
|
|
@@ -26,19 +26,70 @@ type ElevatedTokenResult = {
|
|
|
26
26
|
readonly reason: ElevatedFailureReason;
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
29
|
+
* chatsvcagg capture result. Carries the same three failure modes as
|
|
30
|
+
* `ElevatedTokenResult` PLUS the parsed regional segment from the URL
|
|
31
|
+
* the bearer rode on (`emea` / `amer` / `apac` / etc.) — the new
|
|
32
|
+
* substrate host (`teams.microsoft.com/api/csa/<region>/api/...`) routes
|
|
33
|
+
* per region, so callers must persist this alongside the token to
|
|
34
|
+
* construct future URLs. See `gotcha_chatsvcagg_substrate_moved` in
|
|
35
|
+
* the project memory for the 2026-05 migration that made this
|
|
36
|
+
* necessary.
|
|
37
|
+
*/
|
|
38
|
+
type ChatsvcaggTokenResult = {
|
|
39
|
+
readonly ok: true;
|
|
40
|
+
readonly token: AccessToken;
|
|
41
|
+
readonly region: string;
|
|
42
|
+
} | {
|
|
43
|
+
readonly ok: false;
|
|
44
|
+
readonly reason: ElevatedFailureReason;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* IC3 capture result. The "next-gen" Teams chat-message substrate at
|
|
48
|
+
* `teams.microsoft.com/api/chatsvc/<region>/v1/users/ME/conversations/{id}/messages`
|
|
49
|
+
* — the path Teams web actually uses for chat scrollback (the existing
|
|
50
|
+
* chatsvcagg substrate at `/api/csa/<region>/api/v1/chats/{id}/messages`
|
|
51
|
+
* is the chat-list aggregator and caps at the 200 most recent messages
|
|
52
|
+
* with no working pagination cursor). The IC3 path supports `syncState`
|
|
53
|
+
* + `startTime` pagination, unlocking arbitrary-depth chat history.
|
|
54
|
+
*
|
|
55
|
+
* Bearer audience: `https://ic3.teams.office.com`. Standard `Bearer`
|
|
56
|
+
* authorization (NOT the purple-teams-documented `skype_token X`
|
|
57
|
+
* header — those forks predate Teams' move to OAuth bearer on this
|
|
58
|
+
* surface). Empirically discovered 2026-05-21 by widening the
|
|
59
|
+
* Playwright capture listener.
|
|
60
|
+
*/
|
|
61
|
+
type Ic3TokenResult = {
|
|
62
|
+
readonly ok: true;
|
|
63
|
+
readonly token: AccessToken;
|
|
64
|
+
readonly region: string;
|
|
65
|
+
} | {
|
|
66
|
+
readonly ok: false;
|
|
67
|
+
readonly reason: ElevatedFailureReason;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Combined outcome of capturing all four tokens (Teams basic / M365
|
|
71
|
+
* elevated / chatsvcagg substrate / IC3 substrate) inside one browser
|
|
72
|
+
* session. Login-fix round-2 introduced this for the basic+elevated
|
|
73
|
+
* pair; chatsvcagg was added next; IC3 is the most recent leg, capturing
|
|
74
|
+
* the bearer Teams web uses for unbounded chat-history reads.
|
|
75
|
+
*
|
|
76
|
+
* All four legs ride on the SAME `teams.microsoft.com` session, so
|
|
77
|
+
* adding capture legs is essentially free — MSAL multiplexes the
|
|
78
|
+
* audience-scoped bearers via silent acquisition.
|
|
38
79
|
*/
|
|
39
80
|
type BothTokensResult = {
|
|
40
81
|
readonly teams: BrowserTokenResult | null;
|
|
41
82
|
readonly elevated: ElevatedTokenResult;
|
|
83
|
+
readonly chatsvcagg: ChatsvcaggTokenResult;
|
|
84
|
+
readonly ic3: Ic3TokenResult;
|
|
85
|
+
/**
|
|
86
|
+
* Set when the Teams poll short-circuited because `freshCachedToken`
|
|
87
|
+
* found a token written by a concurrent process (QA-010). The caller
|
|
88
|
+
* must NOT persist this result — the cache is already the source of
|
|
89
|
+
* truth, and `refreshToken` is null here (persisting would clobber the
|
|
90
|
+
* winner's rotated refresh token).
|
|
91
|
+
*/
|
|
92
|
+
readonly fromCache?: true;
|
|
42
93
|
};
|
|
43
94
|
type BrowserAuth = {
|
|
44
95
|
acquireToken: (scopes: string[], startUrl: string) => Promise<BrowserTokenResult | null>;
|
|
@@ -62,6 +113,28 @@ type BrowserAuth = {
|
|
|
62
113
|
* `acquireBothTokens` instead so the user sees only one browser.
|
|
63
114
|
*/
|
|
64
115
|
acquireElevatedToken: () => Promise<ElevatedTokenResult>;
|
|
116
|
+
/**
|
|
117
|
+
* Capture a chatsvcagg-audience bearer (Teams basic identity, but the
|
|
118
|
+
* `chatsvcagg.teams.microsoft.com` resource instead of Graph) by
|
|
119
|
+
* navigating headless to `teams.microsoft.com/v2/`. The persistent
|
|
120
|
+
* profile's SSO cookies do the auth silently. Used by
|
|
121
|
+
* `getChatsvcaggAccessToken()` when the cached chatsvcagg token has
|
|
122
|
+
* expired and the basic Teams session is still warm.
|
|
123
|
+
*
|
|
124
|
+
* Same failure-mode shape as `acquireElevatedToken` — launch hang,
|
|
125
|
+
* navigation failure, silent SSO timeout — so the auth-manager can
|
|
126
|
+
* reuse the same auto-heal logic.
|
|
127
|
+
*/
|
|
128
|
+
acquireChatsvcaggToken: () => Promise<ChatsvcaggTokenResult>;
|
|
129
|
+
/**
|
|
130
|
+
* Capture an IC3-audience bearer (aud `https://ic3.teams.office.com`,
|
|
131
|
+
* same basic Teams appid). The bearer Teams web client uses to call
|
|
132
|
+
* `teams.microsoft.com/api/chatsvc/<region>/v1/users/ME/conversations/{id}/messages`
|
|
133
|
+
* — the chat-message substrate with proper `syncState` pagination,
|
|
134
|
+
* enabling reads beyond the 200-message chatsvcagg cap. Same failure
|
|
135
|
+
* modes as `acquireChatsvcaggToken`.
|
|
136
|
+
*/
|
|
137
|
+
acquireIc3Token: () => Promise<Ic3TokenResult>;
|
|
65
138
|
/**
|
|
66
139
|
* Login-fix round-2: capture BOTH tokens inside ONE browser session.
|
|
67
140
|
* After the Teams response listener intercepts the Teams token,
|
|
@@ -125,6 +198,21 @@ type BrowserAuthConfig = {
|
|
|
125
198
|
readonly logger: Logger;
|
|
126
199
|
readonly fs: FileSystem;
|
|
127
200
|
readonly trace?: TraceFn;
|
|
201
|
+
/**
|
|
202
|
+
* QA-010 (login hang): probe for a fresh token that landed in the cache
|
|
203
|
+
* WHILE the browser capture is polling. AAD SPA refresh tokens rotate, so
|
|
204
|
+
* when two processes race, the loser's refresh fails and it falls into the
|
|
205
|
+
* full multi-minute browser dance — while the winner's fresh token sits in
|
|
206
|
+
* the cache the whole time. The Teams poll loop calls this every interval
|
|
207
|
+
* and short-circuits (closing the browser) the moment it returns a token.
|
|
208
|
+
*/
|
|
209
|
+
readonly freshCachedToken?: () => Promise<string | null>;
|
|
210
|
+
/**
|
|
211
|
+
* User-visible progress sink (stderr in production). The browser capture
|
|
212
|
+
* can legitimately take minutes (federated SSO, interactive sign-in); these
|
|
213
|
+
* one-liners are what separates "waiting on the user" from "hung" (QA-010).
|
|
214
|
+
*/
|
|
215
|
+
readonly onProgress?: (line: string) => void;
|
|
128
216
|
readonly profileDir?: string;
|
|
129
217
|
readonly initialSettleMs?: number;
|
|
130
218
|
readonly postReloginSettleMs?: number;
|
|
@@ -158,6 +246,8 @@ declare const createBrowserAuthFromApi: (api: BrowserAuthApi, config: BrowserAut
|
|
|
158
246
|
declare const createBrowserAuth: (deps: {
|
|
159
247
|
logger: Logger;
|
|
160
248
|
fs?: FileSystem;
|
|
249
|
+
freshCachedToken?: () => Promise<string | null>;
|
|
250
|
+
onProgress?: (line: string) => void;
|
|
161
251
|
}) => BrowserAuth;
|
|
162
252
|
export { createBrowserAuth, createBrowserAuthFromApi, createPlaywrightApi };
|
|
163
|
-
export type { BothTokensResult, BrowserAuth, BrowserAuthApi, BrowserAuthConfig, BrowserTokenResult, ChromiumLike, ContextLike, ElevatedFailureReason, ElevatedTokenResult, PageLike, PlaywrightLoader, RequestLike, ResponseLike, };
|
|
253
|
+
export type { BothTokensResult, BrowserAuth, BrowserAuthApi, BrowserAuthConfig, BrowserTokenResult, ChatsvcaggTokenResult, Ic3TokenResult, ChromiumLike, ContextLike, ElevatedFailureReason, ElevatedTokenResult, PageLike, PlaywrightLoader, RequestLike, ResponseLike, };
|
|
@@ -5,6 +5,7 @@ type GraphError = {
|
|
|
5
5
|
status: number;
|
|
6
6
|
message: string;
|
|
7
7
|
code?: string;
|
|
8
|
+
retryAfterSeconds?: number;
|
|
8
9
|
} | {
|
|
9
10
|
type: 'auth_failed';
|
|
10
11
|
message: string;
|
|
@@ -35,7 +36,38 @@ type GraphClient = {
|
|
|
35
36
|
* elevated token).
|
|
36
37
|
*/
|
|
37
38
|
getElevated: (path: string) => Promise<Result<unknown, GraphError>>;
|
|
39
|
+
/**
|
|
40
|
+
* JSON-GET against the Teams chat substrate (post-2026-05:
|
|
41
|
+
* `teams.microsoft.com/api/csa/<region>/api/v{N}/...` — see
|
|
42
|
+
* `gotcha_chatsvcagg_substrate_moved` in memory for the migration
|
|
43
|
+
* away from `chatsvcagg.teams.microsoft.com`). Signs the request
|
|
44
|
+
* with the chatsvcagg-audience bearer captured at login (same Teams
|
|
45
|
+
* web client identity as `get`, different audience), and injects the
|
|
46
|
+
* cached substrate region between the host and `path`. Used by
|
|
47
|
+
* commands that need to read chat message BODIES, which the basic
|
|
48
|
+
* Graph token cannot reach (`Chat.Read*` scopes are missing).
|
|
49
|
+
*
|
|
50
|
+
* `path` MUST start with `/api/v{N}/...` — the host + `/api/csa/<region>`
|
|
51
|
+
* prefix are added by this client.
|
|
52
|
+
*/
|
|
53
|
+
teamsChat: (path: string) => Promise<Result<unknown, GraphError>>;
|
|
54
|
+
/**
|
|
55
|
+
* JSON-GET against the Teams IC3 chat-message substrate at
|
|
56
|
+
* `teams.microsoft.com/api/chatsvc/<region>/v1/...`. Same host as
|
|
57
|
+
* `teamsChat` but a DIFFERENT path prefix AND a different bearer
|
|
58
|
+
* audience (`https://ic3.teams.office.com` instead of
|
|
59
|
+
* `https://chatsvcagg.teams.microsoft.com`). The path supports
|
|
60
|
+
* `syncState` + `startTime` pagination — unlocking arbitrary-depth
|
|
61
|
+
* chat-history reads beyond the chatsvcagg 200-message cap (see
|
|
62
|
+
* `gotcha_chatsvcagg_substrate_moved` in memory). Used by
|
|
63
|
+
* `list-teams-chat-history`.
|
|
64
|
+
*
|
|
65
|
+
* `path` MUST start with `/v1/...` (e.g. `/v1/users/ME/conversations/{id}/messages?startTime=...`)
|
|
66
|
+
* — the host + `/api/chatsvc/<region>` prefix are added here.
|
|
67
|
+
*/
|
|
68
|
+
teamsChatIc3: (path: string) => Promise<Result<unknown, GraphError>>;
|
|
38
69
|
post: (path: string, body: unknown) => Promise<Result<unknown, GraphError>>;
|
|
70
|
+
patch: (path: string, body: unknown) => Promise<Result<unknown, GraphError>>;
|
|
39
71
|
getBinary: (path: string) => Promise<Result<unknown, GraphError>>;
|
|
40
72
|
/**
|
|
41
73
|
* Same shape as `getBinary` but signs the request with an "elevated"
|
|
@@ -74,6 +106,14 @@ type TokenInfo = {
|
|
|
74
106
|
readonly scopes: ReadonlyArray<string>;
|
|
75
107
|
readonly audience: string | undefined;
|
|
76
108
|
readonly expiresAt: string | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Seconds remaining until the cached token's `exp` claim — derived from
|
|
111
|
+
* `expiresAt - now`. Negative when the token has already expired. Absent
|
|
112
|
+
* when the JWT did not carry an `exp` claim. Audit Jane-session §4: lets
|
|
113
|
+
* an LLM decide pre-emptively to run `ask-marcel login` (re-auth typically
|
|
114
|
+
* worth doing under ~5 minutes) without parsing the ISO string itself.
|
|
115
|
+
*/
|
|
116
|
+
readonly expiresInSeconds: number | undefined;
|
|
77
117
|
};
|
|
78
118
|
type FetchFn = (url: string, init?: RequestInit) => Promise<Response>;
|
|
79
119
|
declare const createGraphClient: (auth: AuthManager, fetchFn?: FetchFn) => GraphClient;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract the text of a legacy Word .doc — the pre-2007 OLE binary "Compound
|
|
5
|
+
* File" format that mammoth (which only reads the OOXML .docx zip) cannot parse —
|
|
6
|
+
* via word-extractor (pure-JS, walks the WordDocument OLE stream; no native deps).
|
|
7
|
+
* Body text only: legacy .doc carries no structure this CLI surfaces (headings,
|
|
8
|
+
* tables, and styling are lost), so callers return it as text/plain.
|
|
9
|
+
*
|
|
10
|
+
* try/catch is permitted here per the infra-boundary rule: word-extractor throws
|
|
11
|
+
* on a non-.doc / corrupt OLE container, and we translate that into a Result.
|
|
12
|
+
*/
|
|
13
|
+
declare const extractDocText: (bytes: Uint8Array) => Promise<Result<string, GraphError>>;
|
|
14
|
+
export { extractDocText };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parse an Outlook `.msg` file — the OLE Compound File (CFBF) container Outlook
|
|
5
|
+
* writes when you drag an email to disk, same binary family as legacy .doc/.xls —
|
|
6
|
+
* into a clean {@link ParsedMsg} via @kenjiuno/msgreader (pure-JS, no native deps,
|
|
7
|
+
* lazy-imported like word-extractor / unpdf so it stays out of the cold-start path).
|
|
8
|
+
*
|
|
9
|
+
* The adapter is the anti-corruption layer: msgreader returns a wide `FieldsData`
|
|
10
|
+
* (X500 sender addresses, RTF body, hundreds of MAPI props); {@link mapRawMsg}
|
|
11
|
+
* narrows it to the half-dozen fields the markdown renderer needs and resolves the
|
|
12
|
+
* sender SMTP / delivery-time fallbacks. `mapRawMsg` is pure and exported so every
|
|
13
|
+
* fallback branch is unit-tested with plain objects — the binary fixture only
|
|
14
|
+
* exercises one field combination.
|
|
15
|
+
*
|
|
16
|
+
* try/catch is permitted here per the infra-boundary rule: msgreader throws on a
|
|
17
|
+
* non-OLE / corrupt container, and a single unreadable attachment must not sink the
|
|
18
|
+
* whole parse, so attachment reads are individually guarded.
|
|
19
|
+
*/
|
|
20
|
+
type MsgRecipientKind = 'to' | 'cc' | 'bcc' | 'unknown';
|
|
21
|
+
type MsgRecipient = {
|
|
22
|
+
readonly kind: MsgRecipientKind;
|
|
23
|
+
readonly name?: string;
|
|
24
|
+
readonly email?: string;
|
|
25
|
+
};
|
|
26
|
+
type MsgAttachment = {
|
|
27
|
+
readonly fileName?: string;
|
|
28
|
+
readonly content?: Uint8Array;
|
|
29
|
+
};
|
|
30
|
+
type ParsedMsg = {
|
|
31
|
+
readonly subject?: string;
|
|
32
|
+
readonly senderName?: string;
|
|
33
|
+
readonly senderEmail?: string;
|
|
34
|
+
readonly date?: string;
|
|
35
|
+
readonly body?: string;
|
|
36
|
+
readonly bodyHtml?: string;
|
|
37
|
+
readonly recipients: readonly MsgRecipient[];
|
|
38
|
+
readonly attachments: readonly MsgAttachment[];
|
|
39
|
+
};
|
|
40
|
+
type RawRecipient = {
|
|
41
|
+
readonly recipType?: string;
|
|
42
|
+
readonly name?: string;
|
|
43
|
+
readonly smtpAddress?: string;
|
|
44
|
+
readonly email?: string;
|
|
45
|
+
};
|
|
46
|
+
type RawAttachment = {
|
|
47
|
+
readonly fileName?: string;
|
|
48
|
+
};
|
|
49
|
+
type RawMsg = {
|
|
50
|
+
readonly subject?: string;
|
|
51
|
+
readonly senderName?: string;
|
|
52
|
+
readonly senderSmtpAddress?: string;
|
|
53
|
+
readonly senderEmail?: string;
|
|
54
|
+
readonly messageDeliveryTime?: string;
|
|
55
|
+
readonly clientSubmitTime?: string;
|
|
56
|
+
readonly body?: string;
|
|
57
|
+
readonly bodyHtml?: string;
|
|
58
|
+
readonly recipients?: readonly RawRecipient[];
|
|
59
|
+
readonly attachments?: readonly RawAttachment[];
|
|
60
|
+
};
|
|
61
|
+
declare const mapRawMsg: (raw: RawMsg, attachmentContents: readonly (Uint8Array | undefined)[]) => ParsedMsg;
|
|
62
|
+
type AttachmentReader = {
|
|
63
|
+
readonly getAttachment: (index: number) => {
|
|
64
|
+
readonly content?: unknown;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
type MsgReaderInstance = AttachmentReader & {
|
|
68
|
+
readonly getFileData: () => unknown;
|
|
69
|
+
};
|
|
70
|
+
type MsgReaderCtor = new (input: ArrayBuffer | DataView) => MsgReaderInstance;
|
|
71
|
+
declare const readAttachmentContent: (reader: AttachmentReader, index: number) => Uint8Array | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the MsgReader class from the dynamic import's `default`, whichever
|
|
74
|
+
* interop shape it arrives in. msgreader is CJS with `exports.default = class`
|
|
75
|
+
* (+ `__esModule`): Bun's RUNTIME import hands us the class directly, but Bun's
|
|
76
|
+
* BUNDLER (node-mode `__toESM`) sets `default` to the whole exports object —
|
|
77
|
+
* so in `dist/cli.js` the class sits one level deeper at `default.default`
|
|
78
|
+
* ("Object is not a constructor" at runtime, invisible to source-run tests).
|
|
79
|
+
*/
|
|
80
|
+
declare const resolveMsgReaderCtor: (defaultExport: unknown) => MsgReaderCtor;
|
|
81
|
+
declare const extractMsg: (bytes: Uint8Array) => Promise<Result<ParsedMsg, GraphError>>;
|
|
82
|
+
export { extractMsg, mapRawMsg, readAttachmentContent, resolveMsgReaderCtor };
|
|
83
|
+
export type { MsgAttachment, MsgRecipient, MsgRecipientKind, ParsedMsg };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const REQUEST_TIMEOUT_MS = 60000;
|
|
2
|
+
export declare const BINARY_TRANSFER_TIMEOUT_MS: number;
|
|
3
|
+
export declare const REQUEST_TIMEOUT_LABEL = "60s";
|
|
4
|
+
export declare const BINARY_TRANSFER_TIMEOUT_LABEL = "5min";
|
|
5
|
+
export declare const networkErrorMessage: (e: unknown, label: string, timeoutLabel: string) => string;
|
|
6
|
+
export type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
7
|
+
export type TimeoutTier = 'json' | 'binary';
|
|
8
|
+
export declare const timeoutLabelFor: (tier: TimeoutTier) => string;
|
|
9
|
+
export declare const timeoutMsFor: (tier: TimeoutTier) => number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Pulls the image parts out of an OOXML package (.docx / .xlsx /
|
|
5
|
+
* .pptx and their macro-enabled / template variants). Images live as binary
|
|
6
|
+
* parts under `word/media/`, `xl/media/`, or `ppt/media/` — including
|
|
7
|
+
* original full-resolution / un-cropped originals and images on hidden
|
|
8
|
+
* slides that the rendered view never shows.
|
|
9
|
+
*
|
|
10
|
+
* Separate from `ooxml-zip-adapter` on purpose: that adapter pre-decodes
|
|
11
|
+
* every entry as a UTF-8 string (correct for XML, corrupting for binary),
|
|
12
|
+
* whereas media must come back as raw bytes. try/catch is permitted here
|
|
13
|
+
* (src/infra/**, atelier rule 17): a malformed-zip throw becomes a Result.err.
|
|
14
|
+
*
|
|
15
|
+
* Raster formats (png/jpg/gif/bmp/tiff/webp) a vision model can read directly,
|
|
16
|
+
* plus svg — the one vector format a model can use, because its XML source
|
|
17
|
+
* carries the diagram's own text labels (and modern Office embeds it as the
|
|
18
|
+
* high-fidelity original beside a png fallback). Legacy vector (emf/wmf) and
|
|
19
|
+
* audio/video are still excluded — neither a model can use.
|
|
20
|
+
*/
|
|
21
|
+
type MediaPart = {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
readonly bytes: Uint8Array;
|
|
24
|
+
};
|
|
25
|
+
declare const extractOoxmlMedia: (bytes: Uint8Array) => Promise<Result<ReadonlyArray<MediaPart>, GraphError>>;
|
|
26
|
+
export { extractOoxmlMedia };
|
|
27
|
+
export type { MediaPart };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Thin wrapper around JSZip for opening already-fetched OOXML bytes
|
|
5
|
+
* (.docx / .xlsx / .pptx — all ZIP packages with a shared docProps/* core).
|
|
6
|
+
* Pure CPU on bytes already in memory — no IO — so this matches the
|
|
7
|
+
* mammoth-adapter pattern: a Result-returning factory, no port, no fake.
|
|
8
|
+
* Tests work end-to-end against real fixtures built with the `docx` /
|
|
9
|
+
* `xlsx` packages (or hand-rolled JSZip) via test-helpers/office-fixtures.ts.
|
|
10
|
+
*
|
|
11
|
+
* try/catch is permitted under src/infra/** (atelier hard rule 17): any
|
|
12
|
+
* malformed-zip throw from JSZip translates into a Result.err with a
|
|
13
|
+
* GraphError shape so callers stay on the Result rail.
|
|
14
|
+
*
|
|
15
|
+
* The returned reader is synchronous on purpose: callers in the use-case
|
|
16
|
+
* layer are pure XML walkers that don't model async/await internally.
|
|
17
|
+
* Every text entry is pre-decoded once at open time, then served from
|
|
18
|
+
* an in-memory map. `list()` exposes the entry paths so callers can
|
|
19
|
+
* enumerate numbered parts (`xl/comments1.xml`, `ppt/slides/slide*.xml`,
|
|
20
|
+
* every `*.rels`) that can't be hardcoded.
|
|
21
|
+
*/
|
|
22
|
+
type OoxmlZip = {
|
|
23
|
+
readonly read: (path: string) => string | undefined;
|
|
24
|
+
readonly list: () => ReadonlyArray<string>;
|
|
25
|
+
};
|
|
26
|
+
declare const openOoxmlZip: (bytes: Uint8Array) => Promise<Result<OoxmlZip, GraphError>>;
|
|
27
|
+
export { openOoxmlZip };
|
|
28
|
+
export type { OoxmlZip };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
import type { MediaPart } from './ooxml-media-extractor.js';
|
|
4
|
+
/**
|
|
5
|
+
* Extract embedded raster images from a PDF via unpdf (a pure-JS pdfjs build — no
|
|
6
|
+
* native deps, runs under Bun). unpdf walks each page's painted image XObjects and
|
|
7
|
+
* returns *decoded* pixels, which we PNG-encode.
|
|
8
|
+
*
|
|
9
|
+
* Scope note: this is page-oriented — it sees images AS PAINTED on each page. It does
|
|
10
|
+
* NOT reach OCG/layer-hidden images, unpainted/orphan XObjects, or the full uncropped
|
|
11
|
+
* original behind a clipped image; capturing those needs an object-graph walk (a much
|
|
12
|
+
* heavier dependency). All PAGES are always walked (PDF has no "hidden page" concept).
|
|
13
|
+
*
|
|
14
|
+
* `try/catch` is permitted here per the infra-boundary rule: pdfjs throws on malformed
|
|
15
|
+
* input and we translate that into a Result rather than letting it escape.
|
|
16
|
+
*/
|
|
17
|
+
declare const extractPdfImages: (bytes: Uint8Array) => Promise<Result<ReadonlyArray<MediaPart>, GraphError>>;
|
|
18
|
+
export { extractPdfImages };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract a PDF's text layer via unpdf (a pure-JS pdfjs build — no native deps,
|
|
5
|
+
* runs under Bun). Returns the reading-order text of every page merged into one
|
|
6
|
+
* string. A born-digital PDF (exported from Word/LaTeX/Chrome/…) yields its text;
|
|
7
|
+
* a scanned / image-only PDF has no text layer, so the string comes back empty —
|
|
8
|
+
* callers treat that as "needs OCR / a vision model", never as success-with-text.
|
|
9
|
+
*
|
|
10
|
+
* Scope note: this is the embedded text layer, NOT OCR. It also does not preserve
|
|
11
|
+
* layout structure (headings, tables, columns flatten into reading order).
|
|
12
|
+
*
|
|
13
|
+
* `try/catch` is permitted here per the infra-boundary rule: pdfjs throws on
|
|
14
|
+
* malformed input and we translate that into a Result rather than letting it escape.
|
|
15
|
+
*
|
|
16
|
+
* `verbosity: 0` (pdfjs `VerbosityLevel.ERRORS`) silences pdfjs's TrueType
|
|
17
|
+
* font-hinting log spam — `Warning: TT: undefined function: N`, `Required "glyf"
|
|
18
|
+
* table is not found`, `Indexing all PDF objects` — which it emits via its own
|
|
19
|
+
* `console.warn` while parsing a PDF's embedded fonts. Font hinting is sub-pixel
|
|
20
|
+
* glyph rendering, completely irrelevant to text extraction (the text still comes
|
|
21
|
+
* out fine); the default level (WARNINGS) just floods the host app's logs once per
|
|
22
|
+
* quirky font. We lower it at the boundary because the noise originates inside
|
|
23
|
+
* pdfjs — the `no-console` rule keeps us from emitting or intercepting it ourselves.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Map a pdfjs throw to an actionable message. The special case is an encrypted
|
|
27
|
+
* PDF: pdfjs raises `PasswordException` ("No password given") — QA run-1 found a
|
|
28
|
+
* real tenant file surfacing that raw string with zero guidance. Password
|
|
29
|
+
* handling is genuinely unsupported (and Graph's `format=pdf` cannot unlock
|
|
30
|
+
* encrypted sources either), so say that honestly instead of leaking pdfjs
|
|
31
|
+
* internals. Pure and exported: the branch is unit-tested with shaped errors —
|
|
32
|
+
* no encrypted-PDF fixture exists in the toolchain.
|
|
33
|
+
*/
|
|
34
|
+
declare const pdfErrorMessage: (e: unknown) => string;
|
|
35
|
+
type PdfText = {
|
|
36
|
+
readonly text: string;
|
|
37
|
+
readonly pageCount: number;
|
|
38
|
+
};
|
|
39
|
+
declare const extractPdfText: (bytes: Uint8Array) => Promise<Result<PdfText, GraphError>>;
|
|
40
|
+
export { extractPdfText, pdfErrorMessage };
|
|
41
|
+
export type { PdfText };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal, dependency-free PNG encoder for raw 8-bit pixel buffers. unpdf hands
|
|
3
|
+
* back *decoded* pixels (1=grayscale, 3=RGB, 4=RGBA channels), so to write usable
|
|
4
|
+
* image files without a native dep (sharp/canvas) we wrap them in a PNG ourselves:
|
|
5
|
+
* signature + IHDR + a single zlib-compressed IDAT (filter-0 scanlines) + IEND.
|
|
6
|
+
*/
|
|
7
|
+
type RawImage = {
|
|
8
|
+
readonly width: number;
|
|
9
|
+
readonly height: number;
|
|
10
|
+
readonly channels: number;
|
|
11
|
+
readonly data: Uint8Array;
|
|
12
|
+
};
|
|
13
|
+
declare const encodePng: (image: RawImage) => Uint8Array;
|
|
14
|
+
export { encodePng };
|
|
15
|
+
export type { RawImage };
|
|
@@ -4,6 +4,6 @@ type SheetCsv = {
|
|
|
4
4
|
readonly name: string;
|
|
5
5
|
readonly csv: string;
|
|
6
6
|
};
|
|
7
|
-
declare const readSheetsAsCsv: (bytes: Uint8Array) => Result<ReadonlyArray<SheetCsv>, GraphError
|
|
7
|
+
declare const readSheetsAsCsv: (bytes: Uint8Array) => Promise<Result<ReadonlyArray<SheetCsv>, GraphError>>;
|
|
8
8
|
export { readSheetsAsCsv };
|
|
9
9
|
export type { SheetCsv };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AccessToken } from '../domain/access-token.js';
|
|
2
|
+
import type { Result } from '../domain/result.js';
|
|
3
|
+
import type { Logger } from '../use-cases/ports/logger.js';
|
|
4
|
+
type SystemBrowserAuthDeps = {
|
|
5
|
+
readonly logger: Logger;
|
|
6
|
+
readonly timeoutMs?: number;
|
|
7
|
+
readonly extensionTimeoutMs?: number;
|
|
8
|
+
};
|
|
9
|
+
type SystemBrowserTokenResult = {
|
|
10
|
+
readonly accessToken: AccessToken;
|
|
11
|
+
readonly refreshToken: string | null;
|
|
12
|
+
readonly elevatedAccessToken?: AccessToken | null;
|
|
13
|
+
readonly chatsvcaggAccessToken?: AccessToken | null;
|
|
14
|
+
readonly ic3AccessToken?: AccessToken | null;
|
|
15
|
+
readonly chatsvcaggRegion?: string;
|
|
16
|
+
};
|
|
17
|
+
type SystemBrowserAuthError = {
|
|
18
|
+
type: 'server_bind_failed';
|
|
19
|
+
message: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: 'browser_open_failed';
|
|
22
|
+
message: string;
|
|
23
|
+
} | {
|
|
24
|
+
type: 'extension_timeout';
|
|
25
|
+
message: string;
|
|
26
|
+
} | {
|
|
27
|
+
type: 'invalid_token';
|
|
28
|
+
message: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'cancelled';
|
|
31
|
+
message: string;
|
|
32
|
+
};
|
|
33
|
+
declare const authenticateViaSystemBrowser: (deps: SystemBrowserAuthDeps) => Promise<Result<SystemBrowserTokenResult, SystemBrowserAuthError>>;
|
|
34
|
+
export { authenticateViaSystemBrowser };
|
|
35
|
+
export type { SystemBrowserAuthDeps, SystemBrowserAuthError, SystemBrowserTokenResult };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { Logger } from '../use-cases/ports/logger.js';
|
|
3
|
+
type TokenCallbackPayload = {
|
|
4
|
+
readonly access_token: string;
|
|
5
|
+
readonly refresh_token?: string;
|
|
6
|
+
readonly elevated_access_token?: string;
|
|
7
|
+
readonly chatsvcagg_access_token?: string;
|
|
8
|
+
readonly ic3_access_token?: string;
|
|
9
|
+
readonly chatsvcagg_region?: string;
|
|
10
|
+
};
|
|
11
|
+
type TokenCallbackServer = {
|
|
12
|
+
readonly port: number;
|
|
13
|
+
readonly start: () => Promise<Result<TokenCallbackPayload, TokenCallbackError>>;
|
|
14
|
+
readonly stop: () => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
type TokenCallbackError = {
|
|
17
|
+
type: 'bind_failed';
|
|
18
|
+
message: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'timeout';
|
|
21
|
+
message: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: 'invalid_payload';
|
|
24
|
+
message: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: 'server_closed';
|
|
27
|
+
message: string;
|
|
28
|
+
};
|
|
29
|
+
declare const createTokenCallbackServer: (logger: Logger, timeoutMs?: number) => TokenCallbackServer;
|
|
30
|
+
export { createTokenCallbackServer };
|
|
31
|
+
export type { TokenCallbackError, TokenCallbackPayload, TokenCallbackServer };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Result } from '../domain/result.js';
|
|
2
|
+
import type { GraphError } from './graph-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reads every file entry out of an arbitrary `.zip` archive as raw bytes,
|
|
5
|
+
* sorted by path, directories excluded. Generic counterpart to
|
|
6
|
+
* `ooxml-media-extractor` (which matches only media paths) and
|
|
7
|
+
* `ooxml-zip-adapter` (which decodes entries as UTF-8 strings) — used by the
|
|
8
|
+
* zip-conversion commands to fan each contained file out to the right
|
|
9
|
+
* converter. try/catch is permitted here (src/infra/**, atelier rule 17): a
|
|
10
|
+
* malformed-zip throw becomes a Result.err.
|
|
11
|
+
*/
|
|
12
|
+
type ZipEntry = {
|
|
13
|
+
readonly path: string;
|
|
14
|
+
readonly bytes: Uint8Array;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Decode a legacy zip entry name — the raw filename bytes of an entry whose
|
|
18
|
+
* UTF-8 flag (general-purpose bit 11) is NOT set and which carries no Info-ZIP
|
|
19
|
+
* Unicode-path extra field. JSZip's default decoder assumes UTF-8 and mojibakes
|
|
20
|
+
* these (the `unzip -O GBK` case): Chinese vendor archives written by WinRAR /
|
|
21
|
+
* Windows Explorer store names in GBK. Try strict UTF-8 first (some archivers
|
|
22
|
+
* emit UTF-8 bytes without setting the flag), then fall back to GB18030 — a GBK
|
|
23
|
+
* superset whose 0x00–0x7F bytes are plain ASCII, so legacy ASCII/CP437 names
|
|
24
|
+
* survive unchanged while CJK byte sequences decode correctly.
|
|
25
|
+
*
|
|
26
|
+
* Only reached for non-UTF-8-flagged names (JSZip handles UTF-8 names itself),
|
|
27
|
+
* so a UTF-8 archive's path-handling is unchanged.
|
|
28
|
+
*/
|
|
29
|
+
declare const decodeZipFileName: (bytes: Uint8Array) => string;
|
|
30
|
+
declare const openZipEntries: (bytes: Uint8Array) => Promise<Result<ReadonlyArray<ZipEntry>, GraphError>>;
|
|
31
|
+
export { decodeZipFileName, openZipEntries };
|
|
32
|
+
export type { ZipEntry };
|