@rubytech/create-maxy-code 0.1.458 → 0.1.460
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/package.json +1 -1
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +298 -3
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.js +79 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/object-limits.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.js +41 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/resource-limits.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +13 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.js +165 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/house-credential.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/house-credential.js +4 -2
- package/payload/platform/lib/storage-broker/dist/house-credential.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/index.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/index.js +2 -0
- package/payload/platform/lib/storage-broker/dist/index.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/object-limits.d.ts +80 -0
- package/payload/platform/lib/storage-broker/dist/object-limits.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/object-limits.js +92 -0
- package/payload/platform/lib/storage-broker/dist/object-limits.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/resource-limits.d.ts +102 -0
- package/payload/platform/lib/storage-broker/dist/resource-limits.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/resource-limits.js +105 -0
- package/payload/platform/lib/storage-broker/dist/resource-limits.js.map +1 -0
- package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +334 -5
- package/payload/platform/lib/storage-broker/src/__tests__/object-limits.test.ts +106 -0
- package/payload/platform/lib/storage-broker/src/__tests__/resource-limits.test.ts +49 -0
- package/payload/platform/lib/storage-broker/src/cf-exec.ts +221 -6
- package/payload/platform/lib/storage-broker/src/house-credential.ts +4 -2
- package/payload/platform/lib/storage-broker/src/index.ts +2 -0
- package/payload/platform/lib/storage-broker/src/object-limits.ts +95 -0
- package/payload/platform/lib/storage-broker/src/resource-limits.ts +105 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +7 -6
- package/payload/platform/plugins/cloudflare/PLUGIN.md +3 -1
- package/payload/platform/plugins/cloudflare/bin/cf-token.sh +4 -3
- package/payload/platform/plugins/cloudflare/mcp/__tests__/auth-route.test.ts +206 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/authorize.test.ts +201 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/file-routes.test.ts +178 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/harness.test.ts +32 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/passcode.test.ts +74 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/ratelimit.test.ts +77 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/skill-contract.test.ts +46 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +55 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/upload-route.test.ts +255 -0
- package/payload/platform/plugins/cloudflare/mcp/package.json +5 -2
- package/payload/platform/plugins/cloudflare/references/api.md +1 -1
- package/payload/platform/plugins/cloudflare/references/r2-object-storage.md +46 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +123 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/authorize.ts +32 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/log.ts +12 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/passcode.ts +73 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/ratelimit.ts +55 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/session.ts +85 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/types.ts +44 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/auth.ts +113 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/delete.ts +89 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/download.ts +70 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/files.ts +41 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/upload.ts +151 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/public/index.html +42 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/public/portal.css +113 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/public/portal.js +155 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/schema.sql +64 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +21 -0
- package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +8 -0
- package/payload/platform/plugins/docs/references/outlook-guide.md +5 -5
- package/payload/platform/plugins/docs/references/voice-mirror-guide.md +1 -0
- package/payload/platform/plugins/filesystem/PLUGIN.md +0 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +14 -10
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +14 -10
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +3 -5
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.js +138 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/attach.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.js +75 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/detach.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.js +121 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-attachments.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.js +102 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-attachments.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.js +187 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit-removal.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.js +209 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-send-attachments.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.js +12 -8
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/attach.d.ts +37 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attach.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attach.js +79 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attach.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.d.ts +43 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.js +65 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/attachment-list.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/detach.d.ts +65 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/detach.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/detach.js +99 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/detach.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts +8 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.js +4 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts +36 -8
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js +40 -13
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.d.ts +9 -5
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.js +12 -8
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts +49 -4
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js +82 -13
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts +8 -2
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +13 -4
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.d.ts +15 -16
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.js +8 -41
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-attachment.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js +3 -20
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts +27 -3
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js +53 -8
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js.map +1 -1
- package/payload/platform/plugins/outlook/references/auth.md +1 -1
- package/payload/platform/plugins/outlook/references/graph-surfaces.md +33 -6
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +22 -5
- package/payload/platform/plugins/storage-broker/PLUGIN.md +41 -2
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.d.ts +2 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.js +85 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/confine-path.test.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.d.ts +2 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.js +77 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/put-source.test.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts +12 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js +107 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js +86 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/storage-broker/mcp/dist/put-source.d.ts +11 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/put-source.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/put-source.js +35 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/put-source.js.map +1 -0
- package/payload/platform/plugins/voice-mirror/PLUGIN.md +19 -7
- package/payload/platform/plugins/voice-mirror/mcp/dist/index.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/index.js +35 -16
- package/payload/platform/plugins/voice-mirror/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.d.ts +31 -0
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.d.ts.map +1 -0
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.js +87 -0
- package/payload/platform/plugins/voice-mirror/mcp/dist/lib/admin-user.js.map +1 -0
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js +13 -3
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-distil-profile.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-ingest-session-text.js +2 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-ingest-session-text.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-record-feedback.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-record-feedback.js +2 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-record-feedback.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.d.ts +2 -2
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.d.ts.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.js +12 -3
- package/payload/platform/plugins/voice-mirror/mcp/dist/tools/voice-tag-content.js.map +1 -1
- package/payload/platform/plugins/voice-mirror/mcp/scripts/smoke.mjs +334 -0
- package/payload/platform/plugins/voice-mirror/skills/voice-mirror/SKILL.md +13 -0
- package/payload/platform/scripts/logs-read-jsonl.test.sh +118 -0
- package/payload/platform/scripts/logs-read.sh +63 -9
- package/payload/platform/scripts/voice-author-key-audit.sh +155 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +4 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.d.ts +17 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.js +88 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-descriptor-resolve.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +0 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +34 -23
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/server/{chunk-64FGYKNZ.js → chunk-JXWFVE5X.js} +148 -0
- package/payload/server/{chunk-F4D35LKL.js → chunk-POBXIHOF.js} +34 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/server.js +412 -37
- package/payload/server/{src-S7C4P6TT.js → src-4F37OHLK.js} +19 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts +0 -2
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js +0 -215
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/lib/message.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/lib/message.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;0DAEsD;IACtD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,UAAU,SAAS;IACjB,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,SAAS,EAAE,CAAC;CAC7B;AASD,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAe9D"}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Build a Microsoft Graph message resource from the tool input shape shared by
|
|
3
3
|
* outlook-mail-send and outlook-draft. Graph stores one body with a single
|
|
4
4
|
* contentType, so `isHtml` chooses HTML vs Text for the whole message.
|
|
5
|
+
*
|
|
6
|
+
* `MessageInput` is the TOOL INPUT shape, not the Graph message shape —
|
|
7
|
+
* `GraphMessage` below is the latter. That is why `attachments` lives here but
|
|
8
|
+
* never reaches `buildMessage`'s output.
|
|
5
9
|
*/
|
|
6
10
|
function toRecipients(addrs) {
|
|
7
11
|
return (addrs ?? [])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/lib/message.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/lib/message.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2BH,SAAS,YAAY,CAAC,KAA2B;IAC/C,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;SACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAmB;IAC9C,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAiB;QAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE;QAC1E,YAAY,EAAE,EAAE;KACjB,CAAC;IACF,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,YAAY,GAAG,EAAE,CAAC;IAC7C,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,aAAa,GAAG,GAAG,CAAC;IAChD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Outbound attachment resolver
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Outbound attachment resolver, shared by every tool that can send a file:
|
|
3
|
+
* outlook-mail-reply, outlook-mail-send, outlook-draft, and outlook-draft-edit.
|
|
4
|
+
* Mirrors the email plugin's account-scope check (realpath under the account
|
|
5
|
+
* directory, regular file, size cap), then classifies each file by how it must
|
|
6
|
+
* reach the draft:
|
|
6
7
|
*
|
|
7
8
|
* - `inline` — at or under Graph's ~3 MB fileAttachment limit; sent as a
|
|
8
9
|
* single base64 `POST /messages/{id}/attachments`.
|
|
@@ -10,12 +11,16 @@
|
|
|
10
11
|
* through a Graph upload session (see `upload-session.ts`).
|
|
11
12
|
*
|
|
12
13
|
* The account cap (25 MB) matches the email plugin's outbound cap, so an
|
|
13
|
-
* Outlook
|
|
14
|
+
* Outlook message and the equivalent IMAP message carry the same maximum.
|
|
14
15
|
*
|
|
15
16
|
* Resolution reads no bytes — it returns per-file metadata (path, size, mode)
|
|
16
|
-
* so
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* so the caller can choose the path. Path validation happens before any Graph
|
|
18
|
+
* write, so a bad path leaves no orphan draft; bytes are read at send time by
|
|
19
|
+
* `toInlineAttachment` (inline) or the upload session (session).
|
|
20
|
+
*
|
|
21
|
+
* This module stays pure node:fs on purpose — the Graph-side attach loop lives
|
|
22
|
+
* in `attach.ts` so this boundary carries no client, no network, and no I/O
|
|
23
|
+
* beyond the filesystem.
|
|
19
24
|
*/
|
|
20
25
|
/** Graph fileAttachment inline limit for POST /messages/{id}/attachments. */
|
|
21
26
|
export declare const OUTLOOK_ATTACHMENT_INLINE_MAX_BYTES: number;
|
|
@@ -27,6 +32,29 @@ export interface GraphFileAttachment {
|
|
|
27
32
|
contentType: string;
|
|
28
33
|
contentBytes: string;
|
|
29
34
|
}
|
|
35
|
+
/** Why a single path was refused. Carried as a field so callers classify a
|
|
36
|
+
* refusal on a field, never by parsing its message. */
|
|
37
|
+
/**
|
|
38
|
+
* `bad-path` / `oversize` are outbound path validation (attach). `not-on-draft`
|
|
39
|
+
* / `ambiguous-name` are removal resolution (detach). All four are carried as a
|
|
40
|
+
* field so callers classify on `reason` and never parse the message.
|
|
41
|
+
*/
|
|
42
|
+
export type RefusalReason = "bad-path" | "oversize" | "not-on-draft" | "ambiguous-name";
|
|
43
|
+
/**
|
|
44
|
+
* A per-path refusal, raised before any Graph write. Carries the fields the
|
|
45
|
+
* `op: "refuse"` log line names.
|
|
46
|
+
*
|
|
47
|
+
* Account-context failures (ACCOUNT_DIR unset, account directory unreadable)
|
|
48
|
+
* are NOT refusals: they name no file and no per-file cause, so they stay plain
|
|
49
|
+
* Errors and emit no refuse line.
|
|
50
|
+
*/
|
|
51
|
+
export declare class AttachmentRefusedError extends Error {
|
|
52
|
+
readonly reason: RefusalReason;
|
|
53
|
+
readonly file: string;
|
|
54
|
+
readonly bytes?: number | undefined;
|
|
55
|
+
readonly cap?: number | undefined;
|
|
56
|
+
constructor(message: string, reason: RefusalReason, file: string, bytes?: number | undefined, cap?: number | undefined);
|
|
57
|
+
}
|
|
30
58
|
/** A validated, account-scoped file and the Graph path it must take. */
|
|
31
59
|
export interface OutboundAttachment {
|
|
32
60
|
/** realpath, verified under the account directory. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound-attachments.d.ts","sourceRoot":"","sources":["../../src/lib/outbound-attachments.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"outbound-attachments.d.ts","sourceRoot":"","sources":["../../src/lib/outbound-attachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,6EAA6E;AAC7E,eAAO,MAAM,mCAAmC,QAAkB,CAAC;AACnE,yEAAyE;AACzE,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,iCAAiC,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;wDACwD;AACxD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAExF;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAG7C,QAAQ,CAAC,MAAM,EAAE,aAAa;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM;gBAJrB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,YAAA,EACd,GAAG,CAAC,EAAE,MAAM,YAAA;CAKxB;AAED,wEAAwE;AACxE,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAqBD;wEACwE;AACxE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlE;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,GAC1B,kBAAkB,EAAE,CA4DtB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,mBAAmB,CAO/E;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAGlD"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Outbound attachment resolver
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Outbound attachment resolver, shared by every tool that can send a file:
|
|
3
|
+
* outlook-mail-reply, outlook-mail-send, outlook-draft, and outlook-draft-edit.
|
|
4
|
+
* Mirrors the email plugin's account-scope check (realpath under the account
|
|
5
|
+
* directory, regular file, size cap), then classifies each file by how it must
|
|
6
|
+
* reach the draft:
|
|
6
7
|
*
|
|
7
8
|
* - `inline` — at or under Graph's ~3 MB fileAttachment limit; sent as a
|
|
8
9
|
* single base64 `POST /messages/{id}/attachments`.
|
|
@@ -10,12 +11,16 @@
|
|
|
10
11
|
* through a Graph upload session (see `upload-session.ts`).
|
|
11
12
|
*
|
|
12
13
|
* The account cap (25 MB) matches the email plugin's outbound cap, so an
|
|
13
|
-
* Outlook
|
|
14
|
+
* Outlook message and the equivalent IMAP message carry the same maximum.
|
|
14
15
|
*
|
|
15
16
|
* Resolution reads no bytes — it returns per-file metadata (path, size, mode)
|
|
16
|
-
* so
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* so the caller can choose the path. Path validation happens before any Graph
|
|
18
|
+
* write, so a bad path leaves no orphan draft; bytes are read at send time by
|
|
19
|
+
* `toInlineAttachment` (inline) or the upload session (session).
|
|
20
|
+
*
|
|
21
|
+
* This module stays pure node:fs on purpose — the Graph-side attach loop lives
|
|
22
|
+
* in `attach.ts` so this boundary carries no client, no network, and no I/O
|
|
23
|
+
* beyond the filesystem.
|
|
19
24
|
*/
|
|
20
25
|
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
21
26
|
import { basename, extname, join } from "node:path";
|
|
@@ -23,6 +28,28 @@ import { basename, extname, join } from "node:path";
|
|
|
23
28
|
export const OUTLOOK_ATTACHMENT_INLINE_MAX_BYTES = 3 * 1024 * 1024;
|
|
24
29
|
/** Per-file account cap; parity with the email plugin's outbound cap. */
|
|
25
30
|
export const OUTLOOK_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
31
|
+
/**
|
|
32
|
+
* A per-path refusal, raised before any Graph write. Carries the fields the
|
|
33
|
+
* `op: "refuse"` log line names.
|
|
34
|
+
*
|
|
35
|
+
* Account-context failures (ACCOUNT_DIR unset, account directory unreadable)
|
|
36
|
+
* are NOT refusals: they name no file and no per-file cause, so they stay plain
|
|
37
|
+
* Errors and emit no refuse line.
|
|
38
|
+
*/
|
|
39
|
+
export class AttachmentRefusedError extends Error {
|
|
40
|
+
reason;
|
|
41
|
+
file;
|
|
42
|
+
bytes;
|
|
43
|
+
cap;
|
|
44
|
+
constructor(message, reason, file, bytes, cap) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.reason = reason;
|
|
47
|
+
this.file = file;
|
|
48
|
+
this.bytes = bytes;
|
|
49
|
+
this.cap = cap;
|
|
50
|
+
this.name = "AttachmentRefusedError";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
26
53
|
const MIME = {
|
|
27
54
|
".pdf": "application/pdf",
|
|
28
55
|
".png": "image/png",
|
|
@@ -81,19 +108,19 @@ export function resolveOutboundAttachments(accountId, paths) {
|
|
|
81
108
|
}
|
|
82
109
|
catch (err) {
|
|
83
110
|
if (err.code === "ENOENT") {
|
|
84
|
-
throw new
|
|
111
|
+
throw new AttachmentRefusedError(`Attachment not found: ${p}`, "bad-path", basename(p));
|
|
85
112
|
}
|
|
86
|
-
throw new
|
|
113
|
+
throw new AttachmentRefusedError(`Cannot read attachment ${p}: ${err instanceof Error ? err.message : String(err)}`, "bad-path", basename(p));
|
|
87
114
|
}
|
|
88
115
|
if (!rp.startsWith(accountResolved + "/")) {
|
|
89
|
-
throw new
|
|
116
|
+
throw new AttachmentRefusedError(`Attachment ${p} is outside the account directory and cannot be sent.`, "bad-path", basename(rp));
|
|
90
117
|
}
|
|
91
118
|
const st = statSync(rp);
|
|
92
119
|
if (!st.isFile()) {
|
|
93
|
-
throw new
|
|
120
|
+
throw new AttachmentRefusedError(`Attachment ${p} is not a regular file.`, "bad-path", basename(rp));
|
|
94
121
|
}
|
|
95
122
|
if (st.size > OUTLOOK_ATTACHMENT_MAX_BYTES) {
|
|
96
|
-
throw new
|
|
123
|
+
throw new AttachmentRefusedError(`Attachment ${basename(rp)} is ${(st.size / 1024 / 1024).toFixed(1)} MB; Outlook reply attachments are capped at 25 MB per file.`, "oversize", basename(rp), st.size, OUTLOOK_ATTACHMENT_MAX_BYTES);
|
|
97
124
|
}
|
|
98
125
|
out.push({
|
|
99
126
|
path: rp,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbound-attachments.js","sourceRoot":"","sources":["../../src/lib/outbound-attachments.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"outbound-attachments.js","sourceRoot":"","sources":["../../src/lib/outbound-attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Graph upload-session path for
|
|
2
|
+
* Graph upload-session path for outbound attachments above the inline limit.
|
|
3
|
+
* Shared by every tool that attaches a file; `tool` names the caller for the
|
|
4
|
+
* Graph call tag and the error prefixes, so a stalled session is greppable back
|
|
5
|
+
* to the tool that started it.
|
|
3
6
|
*
|
|
4
7
|
* Two steps, distinct in auth and host:
|
|
5
8
|
* 1. `POST /me/messages/{draftId}/attachments/createUploadSession` — through
|
|
@@ -20,9 +23,10 @@ import type { OutboundAttachment } from "./outbound-attachments.js";
|
|
|
20
23
|
* Graph requires for every chunk except the final remainder. */
|
|
21
24
|
export declare const UPLOAD_CHUNK_BYTES: number;
|
|
22
25
|
/**
|
|
23
|
-
* Upload one large attachment to an existing
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* Upload one large attachment to an existing draft via a Graph upload session.
|
|
27
|
+
* Returns the number of chunks PUT (for observability). The draft must already
|
|
28
|
+
* exist; the attachment must have passed `resolveOutboundAttachments`. `tool`
|
|
29
|
+
* names the calling tool for the Graph call tag and the error prefixes.
|
|
26
30
|
*/
|
|
27
|
-
export declare function uploadAttachmentSession(config: GraphClientConfig, draftId: string, att: OutboundAttachment): Promise<number>;
|
|
31
|
+
export declare function uploadAttachmentSession(config: GraphClientConfig, draftId: string, att: OutboundAttachment, tool: string): Promise<number>;
|
|
28
32
|
//# sourceMappingURL=upload-session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-session.d.ts","sourceRoot":"","sources":["../../src/lib/upload-session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"upload-session.d.ts","sourceRoot":"","sources":["../../src/lib/upload-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE;iEACiE;AACjE,eAAO,MAAM,kBAAkB,QAAkB,CAAC;AAMlD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Graph upload-session path for
|
|
2
|
+
* Graph upload-session path for outbound attachments above the inline limit.
|
|
3
|
+
* Shared by every tool that attaches a file; `tool` names the caller for the
|
|
4
|
+
* Graph call tag and the error prefixes, so a stalled session is greppable back
|
|
5
|
+
* to the tool that started it.
|
|
3
6
|
*
|
|
4
7
|
* Two steps, distinct in auth and host:
|
|
5
8
|
* 1. `POST /me/messages/{draftId}/attachments/createUploadSession` — through
|
|
@@ -20,15 +23,16 @@ import { postGraph } from "./graph-client.js";
|
|
|
20
23
|
* Graph requires for every chunk except the final remainder. */
|
|
21
24
|
export const UPLOAD_CHUNK_BYTES = 320 * 1024 * 10;
|
|
22
25
|
/**
|
|
23
|
-
* Upload one large attachment to an existing
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* Upload one large attachment to an existing draft via a Graph upload session.
|
|
27
|
+
* Returns the number of chunks PUT (for observability). The draft must already
|
|
28
|
+
* exist; the attachment must have passed `resolveOutboundAttachments`. `tool`
|
|
29
|
+
* names the calling tool for the Graph call tag and the error prefixes.
|
|
26
30
|
*/
|
|
27
|
-
export async function uploadAttachmentSession(config, draftId, att) {
|
|
28
|
-
const { json } = await postGraph(config, `/me/messages/${encodeURIComponent(draftId)}/attachments/createUploadSession`, { AttachmentItem: { attachmentType: "file", name: att.name, size: att.size, contentType: att.contentType } }, { tool
|
|
31
|
+
export async function uploadAttachmentSession(config, draftId, att, tool) {
|
|
32
|
+
const { json } = await postGraph(config, `/me/messages/${encodeURIComponent(draftId)}/attachments/createUploadSession`, { AttachmentItem: { attachmentType: "file", name: att.name, size: att.size, contentType: att.contentType } }, { tool });
|
|
29
33
|
const uploadUrl = json?.uploadUrl;
|
|
30
34
|
if (!uploadUrl) {
|
|
31
|
-
throw new Error(`outlook
|
|
35
|
+
throw new Error(`outlook-${tool}: createUploadSession for ${att.name} returned no uploadUrl.`);
|
|
32
36
|
}
|
|
33
37
|
const buf = readFileSync(att.path);
|
|
34
38
|
const total = buf.length;
|
|
@@ -44,7 +48,7 @@ export async function uploadAttachmentSession(config, draftId, att) {
|
|
|
44
48
|
});
|
|
45
49
|
if (!res.ok) {
|
|
46
50
|
const text = await res.text().catch(() => "");
|
|
47
|
-
throw new Error(`outlook
|
|
51
|
+
throw new Error(`outlook-${tool}: upload session PUT ${res.status} for ${att.name} (bytes ${start}-${end - 1}/${total}): ${text.slice(0, 300) || "no response body"}`);
|
|
48
52
|
}
|
|
49
53
|
chunks += 1;
|
|
50
54
|
start = end;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-session.js","sourceRoot":"","sources":["../../src/lib/upload-session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"upload-session.js","sourceRoot":"","sources":["../../src/lib/upload-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C;iEACiE;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;AAMlD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,MAAyB,EACzB,OAAe,EACf,GAAuB,EACvB,IAAY;IAEZ,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAC9B,MAAM,EACN,gBAAgB,kBAAkB,CAAC,OAAO,CAAC,kCAAkC,EAC7E,EAAE,cAAc,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,EAC5G,EAAE,IAAI,EAAE,CACT,CAAC;IACF,MAAM,SAAS,GAAI,IAA6B,EAAE,SAAS,CAAC;IAC5D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,WAAW,IAAI,6BAA6B,GAAG,CAAC,IAAI,yBAAyB,CAC9E,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC;IACzB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO,KAAK,GAAG,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;YACjC,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,eAAe,EAAE,SAAS,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,EAAE,EAAE;YAClE,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CACb,WAAW,IAAI,wBAAwB,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,WAAW,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,kBAAkB,EAAE,CACtJ,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,CAAC,CAAC;QACZ,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -7,12 +7,46 @@ export interface DraftEditArgs {
|
|
|
7
7
|
subject?: string;
|
|
8
8
|
body?: string;
|
|
9
9
|
isHtml?: boolean;
|
|
10
|
+
/** Absolute paths inside the account directory. Added to whatever the draft
|
|
11
|
+
* already carries; pair with `removeAttachments` to replace a file. */
|
|
12
|
+
attachments?: string[];
|
|
13
|
+
/** Attachment names or ids to take off the draft, resolved against its
|
|
14
|
+
* pre-call state. */
|
|
15
|
+
removeAttachments?: string[];
|
|
10
16
|
}
|
|
11
17
|
/**
|
|
12
|
-
* Update an existing draft in place via PATCH /me/messages/{draftId}
|
|
13
|
-
* drafts are mutable, so no delete-and-reappend.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
18
|
+
* Update an existing draft in place via PATCH /me/messages/{draftId}, and/or add
|
|
19
|
+
* and remove its attachments. Graph drafts are mutable, so no delete-and-reappend.
|
|
20
|
+
* Only the supplied fields are patched. Graph rejects a PATCH on a sent
|
|
21
|
+
* (non-draft) message — that error is surfaced to the caller unchanged.
|
|
22
|
+
*
|
|
23
|
+
* Attachments edit in place like every other field: `attachments` adds files,
|
|
24
|
+
* `removeAttachments` takes them off by name or by attachment id, and the two
|
|
25
|
+
* together are a replace.
|
|
26
|
+
*
|
|
27
|
+
* ORDER (Task 1696). Local path validation, then the listing + removal
|
|
28
|
+
* resolution, then PATCH, then the DELETEs, then the attaches. Two properties
|
|
29
|
+
* fall out of resolving removals up front:
|
|
30
|
+
*
|
|
31
|
+
* - Removals resolve against the draft's PRE-CALL state, so "swap a.pdf for a
|
|
32
|
+
* newer a.pdf" pins the old file's id before the new one exists and cannot
|
|
33
|
+
* match the file it is meant to replace.
|
|
34
|
+
* - A removal naming a file the draft does not carry, or a name carried twice,
|
|
35
|
+
* refuses before the PATCH. Listing is a GET, so the draft is untouched.
|
|
36
|
+
*
|
|
37
|
+
* "At least one change" counts attachments and removals as well as patchable
|
|
38
|
+
* fields, so an attachment-only or removal-only call is valid; either issues no
|
|
39
|
+
* PATCH at all.
|
|
40
|
+
*
|
|
41
|
+
* A Graph-side failure is a different matter: the PATCH, the DELETEs and the
|
|
42
|
+
* attaches are separate calls and Graph has no transaction across them, so a
|
|
43
|
+
* DELETE or attach that fails AFTER a successful PATCH leaves the field edits
|
|
44
|
+
* applied while this function throws. The caller is told the edit failed; the
|
|
45
|
+
* subject/recipients it asked for are nonetheless changed. Re-running with the
|
|
46
|
+
* same arguments is safe for the fields (PATCH is idempotent) but WILL duplicate
|
|
47
|
+
* any attachment that already landed, because attaching is additive. A removal
|
|
48
|
+
* that already landed re-runs as a `not-on-draft` refusal, because the file it
|
|
49
|
+
* names is gone. Only path validation and removal resolution are all-or-nothing.
|
|
16
50
|
*
|
|
17
51
|
* The id in the PATCH response is authoritative for where the draft now lives,
|
|
18
52
|
* so it is returned rather than the caller's `draftId` — mirroring `runDraft`,
|
|
@@ -20,9 +54,20 @@ export interface DraftEditArgs {
|
|
|
20
54
|
* plugin-wide (IMMUTABLE_ID_PREFER), so the two normally match; returning the
|
|
21
55
|
* reported id means the tool never asserts a handle it has not confirmed, and
|
|
22
56
|
* `rotated=true` in the log makes any divergence visible (Task 1688).
|
|
57
|
+
*
|
|
58
|
+
* That is also why the DELETEs and attaches target the REPORTED id, not the
|
|
59
|
+
* caller's: if the id rotated, the caller's handle no longer addresses the draft
|
|
60
|
+
* and writing to it would 404 or, worse, hit a stale item. The listing is
|
|
61
|
+
* necessarily read from the caller's id, since it must precede the PATCH that
|
|
62
|
+
* reports the authoritative one. Under a rotation — which IMMUTABLE_ID_PREFER
|
|
63
|
+
* makes effectively impossible — the resolved attachment ids would belong to the
|
|
64
|
+
* pre-rotation item and the DELETE would fail loudly rather than silently remove
|
|
65
|
+
* the wrong file. That is the accepted consequence, not a handled path.
|
|
23
66
|
*/
|
|
24
67
|
export declare function runDraftEdit(config: GraphClientConfig, args: DraftEditArgs): Promise<{
|
|
25
68
|
draftId: string;
|
|
26
69
|
updated: true;
|
|
70
|
+
attachments: string[];
|
|
71
|
+
removed: string[];
|
|
27
72
|
}>;
|
|
28
73
|
//# sourceMappingURL=draft-edit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft-edit.d.ts","sourceRoot":"","sources":["../../src/tools/draft-edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"draft-edit.d.ts","sourceRoot":"","sources":["../../src/tools/draft-edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQhE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;4EACwE;IACxE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;0BACsB;IACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiEvF"}
|
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
import { patchGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { attachFilesToDraft, resolveAttachmentsOrRefuse } from "../lib/attach.js";
|
|
3
|
+
import { listMessageAttachments } from "../lib/attachment-list.js";
|
|
4
|
+
import { detachFromDraft, resolveRemovalsOrRefuse } from "../lib/detach.js";
|
|
2
5
|
import { log } from "../lib/log.js";
|
|
3
6
|
function recip(list) {
|
|
4
7
|
return list.map((address) => ({ emailAddress: { address } }));
|
|
5
8
|
}
|
|
6
9
|
/**
|
|
7
|
-
* Update an existing draft in place via PATCH /me/messages/{draftId}
|
|
8
|
-
* drafts are mutable, so no delete-and-reappend.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* Update an existing draft in place via PATCH /me/messages/{draftId}, and/or add
|
|
11
|
+
* and remove its attachments. Graph drafts are mutable, so no delete-and-reappend.
|
|
12
|
+
* Only the supplied fields are patched. Graph rejects a PATCH on a sent
|
|
13
|
+
* (non-draft) message — that error is surfaced to the caller unchanged.
|
|
14
|
+
*
|
|
15
|
+
* Attachments edit in place like every other field: `attachments` adds files,
|
|
16
|
+
* `removeAttachments` takes them off by name or by attachment id, and the two
|
|
17
|
+
* together are a replace.
|
|
18
|
+
*
|
|
19
|
+
* ORDER (Task 1696). Local path validation, then the listing + removal
|
|
20
|
+
* resolution, then PATCH, then the DELETEs, then the attaches. Two properties
|
|
21
|
+
* fall out of resolving removals up front:
|
|
22
|
+
*
|
|
23
|
+
* - Removals resolve against the draft's PRE-CALL state, so "swap a.pdf for a
|
|
24
|
+
* newer a.pdf" pins the old file's id before the new one exists and cannot
|
|
25
|
+
* match the file it is meant to replace.
|
|
26
|
+
* - A removal naming a file the draft does not carry, or a name carried twice,
|
|
27
|
+
* refuses before the PATCH. Listing is a GET, so the draft is untouched.
|
|
28
|
+
*
|
|
29
|
+
* "At least one change" counts attachments and removals as well as patchable
|
|
30
|
+
* fields, so an attachment-only or removal-only call is valid; either issues no
|
|
31
|
+
* PATCH at all.
|
|
32
|
+
*
|
|
33
|
+
* A Graph-side failure is a different matter: the PATCH, the DELETEs and the
|
|
34
|
+
* attaches are separate calls and Graph has no transaction across them, so a
|
|
35
|
+
* DELETE or attach that fails AFTER a successful PATCH leaves the field edits
|
|
36
|
+
* applied while this function throws. The caller is told the edit failed; the
|
|
37
|
+
* subject/recipients it asked for are nonetheless changed. Re-running with the
|
|
38
|
+
* same arguments is safe for the fields (PATCH is idempotent) but WILL duplicate
|
|
39
|
+
* any attachment that already landed, because attaching is additive. A removal
|
|
40
|
+
* that already landed re-runs as a `not-on-draft` refusal, because the file it
|
|
41
|
+
* names is gone. Only path validation and removal resolution are all-or-nothing.
|
|
11
42
|
*
|
|
12
43
|
* The id in the PATCH response is authoritative for where the draft now lives,
|
|
13
44
|
* so it is returned rather than the caller's `draftId` — mirroring `runDraft`,
|
|
@@ -15,6 +46,15 @@ function recip(list) {
|
|
|
15
46
|
* plugin-wide (IMMUTABLE_ID_PREFER), so the two normally match; returning the
|
|
16
47
|
* reported id means the tool never asserts a handle it has not confirmed, and
|
|
17
48
|
* `rotated=true` in the log makes any divergence visible (Task 1688).
|
|
49
|
+
*
|
|
50
|
+
* That is also why the DELETEs and attaches target the REPORTED id, not the
|
|
51
|
+
* caller's: if the id rotated, the caller's handle no longer addresses the draft
|
|
52
|
+
* and writing to it would 404 or, worse, hit a stale item. The listing is
|
|
53
|
+
* necessarily read from the caller's id, since it must precede the PATCH that
|
|
54
|
+
* reports the authoritative one. Under a rotation — which IMMUTABLE_ID_PREFER
|
|
55
|
+
* makes effectively impossible — the resolved attachment ids would belong to the
|
|
56
|
+
* pre-rotation item and the DELETE would fail loudly rather than silently remove
|
|
57
|
+
* the wrong file. That is the accepted consequence, not a handled path.
|
|
18
58
|
*/
|
|
19
59
|
export async function runDraftEdit(config, args) {
|
|
20
60
|
const patch = {};
|
|
@@ -29,24 +69,53 @@ export async function runDraftEdit(config, args) {
|
|
|
29
69
|
patch.ccRecipients = recip(args.cc);
|
|
30
70
|
if (args.bcc !== undefined)
|
|
31
71
|
patch.bccRecipients = recip(args.bcc);
|
|
32
|
-
|
|
33
|
-
|
|
72
|
+
const hasAttachments = (args.attachments?.length ?? 0) > 0;
|
|
73
|
+
const hasRemovals = (args.removeAttachments?.length ?? 0) > 0;
|
|
74
|
+
if (Object.keys(patch).length === 0 && !hasAttachments && !hasRemovals) {
|
|
75
|
+
throw new Error("outlook-draft-edit: pass at least one field to change (to, cc, bcc, subject, body, attachments, or removeAttachments).");
|
|
76
|
+
}
|
|
77
|
+
// Before any Graph write: a bad path must leave the draft untouched.
|
|
78
|
+
const files = resolveAttachmentsOrRefuse(config.accountId, args.attachments, "draft-edit");
|
|
79
|
+
// Also before any Graph write: resolve removals against the draft's pre-call
|
|
80
|
+
// state. The listing is a GET, so an unresolvable removal still refuses with
|
|
81
|
+
// the draft untouched.
|
|
82
|
+
let removals = [];
|
|
83
|
+
if (hasRemovals) {
|
|
84
|
+
const { items } = await listMessageAttachments(config, args.draftId, "draft-edit");
|
|
85
|
+
removals = resolveRemovalsOrRefuse(items, args.removeAttachments ?? [], "draft-edit");
|
|
34
86
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
87
|
+
let draftId = args.draftId;
|
|
88
|
+
let rotated = false;
|
|
89
|
+
if (Object.keys(patch).length > 0) {
|
|
90
|
+
const path = `/me/messages/${encodeURIComponent(args.draftId)}`;
|
|
91
|
+
const { json } = await patchGraph(config, path, patch, { tool: "draft-edit", target: path });
|
|
92
|
+
const reported = json?.id;
|
|
93
|
+
if (!reported) {
|
|
94
|
+
throw new Error("outlook-draft-edit: Graph accepted the edit but returned no id.");
|
|
95
|
+
}
|
|
96
|
+
rotated = reported !== args.draftId;
|
|
97
|
+
draftId = reported;
|
|
40
98
|
}
|
|
99
|
+
// Remove before adding, so a replace reads as one in the log as well as in the
|
|
100
|
+
// call.
|
|
101
|
+
await detachFromDraft(config, draftId, removals, "draft-edit");
|
|
102
|
+
await attachFilesToDraft(config, draftId, files, "draft-edit");
|
|
41
103
|
log({
|
|
42
104
|
event: "draft-edit",
|
|
43
105
|
op: "draft-edit",
|
|
44
106
|
account: config.accountId,
|
|
45
107
|
idIn: args.draftId,
|
|
46
108
|
idOut: draftId,
|
|
47
|
-
rotated
|
|
109
|
+
rotated,
|
|
48
110
|
fields: Object.keys(patch).join(","),
|
|
111
|
+
attachments: files.length,
|
|
112
|
+
removed: removals.length,
|
|
49
113
|
});
|
|
50
|
-
return {
|
|
114
|
+
return {
|
|
115
|
+
draftId,
|
|
116
|
+
updated: true,
|
|
117
|
+
attachments: files.map((f) => f.name),
|
|
118
|
+
removed: removals.map((r) => r.name),
|
|
119
|
+
};
|
|
51
120
|
}
|
|
52
121
|
//# sourceMappingURL=draft-edit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft-edit.js","sourceRoot":"","sources":["../../src/tools/draft-edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"draft-edit.js","sourceRoot":"","sources":["../../src/tools/draft-edit.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,15 +2,21 @@ import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
|
2
2
|
import { type MessageInput } from "../lib/message.js";
|
|
3
3
|
export interface DraftResult {
|
|
4
4
|
draftId: string;
|
|
5
|
+
attachments: string[];
|
|
5
6
|
}
|
|
6
7
|
/**
|
|
7
|
-
* Create a draft via Graph `POST /me/messages
|
|
8
|
-
*
|
|
8
|
+
* Create a draft via Graph `POST /me/messages`, then attach any files to it, so
|
|
9
|
+
* the returned id names a Drafts-folder message that already carries them and is
|
|
10
|
+
* ready for outlook-draft-send.
|
|
9
11
|
*
|
|
10
12
|
* That id is durable only because the plugin opts into immutable ids
|
|
11
13
|
* (IMMUTABLE_ID_PREFER in graph-client). A regular Outlook id is NOT stable — it
|
|
12
14
|
* rotates when the item is moved or re-saved, including by the operator's own
|
|
13
15
|
* mail client, and the old value then 404s (Task 1688).
|
|
16
|
+
*
|
|
17
|
+
* Attachment paths validate BEFORE the create, so a bad path leaves no orphan
|
|
18
|
+
* draft. An attach failing Graph-side after the create does leave one; it is
|
|
19
|
+
* operator-visible in the Drafts folder — the same exposure mail-reply carries.
|
|
14
20
|
*/
|
|
15
21
|
export declare function runDraft(config: GraphClientConfig, input: MessageInput): Promise<DraftResult>;
|
|
16
22
|
//# sourceMappingURL=draft.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/tools/draft.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/tools/draft.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,WAAW,CAAC,CAmBtB"}
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { postGraph } from "../lib/graph-client.js";
|
|
2
2
|
import { buildMessage } from "../lib/message.js";
|
|
3
|
+
import { attachFilesToDraft, resolveAttachmentsOrRefuse } from "../lib/attach.js";
|
|
3
4
|
import { log } from "../lib/log.js";
|
|
4
5
|
/**
|
|
5
|
-
* Create a draft via Graph `POST /me/messages
|
|
6
|
-
*
|
|
6
|
+
* Create a draft via Graph `POST /me/messages`, then attach any files to it, so
|
|
7
|
+
* the returned id names a Drafts-folder message that already carries them and is
|
|
8
|
+
* ready for outlook-draft-send.
|
|
7
9
|
*
|
|
8
10
|
* That id is durable only because the plugin opts into immutable ids
|
|
9
11
|
* (IMMUTABLE_ID_PREFER in graph-client). A regular Outlook id is NOT stable — it
|
|
10
12
|
* rotates when the item is moved or re-saved, including by the operator's own
|
|
11
13
|
* mail client, and the old value then 404s (Task 1688).
|
|
14
|
+
*
|
|
15
|
+
* Attachment paths validate BEFORE the create, so a bad path leaves no orphan
|
|
16
|
+
* draft. An attach failing Graph-side after the create does leave one; it is
|
|
17
|
+
* operator-visible in the Drafts folder — the same exposure mail-reply carries.
|
|
12
18
|
*/
|
|
13
19
|
export async function runDraft(config, input) {
|
|
14
20
|
const account = config.accountId;
|
|
15
21
|
log({ event: "draft-request", account });
|
|
22
|
+
// Before any Graph write: a bad path must leave nothing behind.
|
|
23
|
+
const files = resolveAttachmentsOrRefuse(account, input.attachments, "draft");
|
|
16
24
|
const message = buildMessage(input);
|
|
17
25
|
try {
|
|
18
26
|
const { json } = await postGraph(config, "/me/messages", message, { tool: "draft" });
|
|
@@ -20,8 +28,9 @@ export async function runDraft(config, input) {
|
|
|
20
28
|
if (!draftId) {
|
|
21
29
|
throw new Error("outlook-draft: Graph created the draft but returned no id.");
|
|
22
30
|
}
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
await attachFilesToDraft(config, draftId, files, "draft");
|
|
32
|
+
log({ event: "draft-created", account, id: draftId, attachments: files.length });
|
|
33
|
+
return { draftId, attachments: files.map((f) => f.name) };
|
|
25
34
|
}
|
|
26
35
|
catch (err) {
|
|
27
36
|
log({ event: "draft-failed", account, error: err.message });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft.js","sourceRoot":"","sources":["../../src/tools/draft.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"draft.js","sourceRoot":"","sources":["../../src/tools/draft.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAOpC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAyB,EACzB,KAAmB;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;IACjC,GAAG,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC;IACzC,gEAAgE;IAChE,MAAM,KAAK,GAAG,0BAA0B,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrF,MAAM,OAAO,GAAI,IAA+B,EAAE,EAAE,CAAC;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QACD,MAAM,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1D,GAAG,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|