Skip to content

Feat/ews provider : add Microsoft Exchange (EWS) calendar backend#103

Merged
olivierlambert merged 5 commits into
olivierlambert:mainfrom
DYB-Corp:feat/ews-provider
Jun 4, 2026
Merged

Feat/ews provider : add Microsoft Exchange (EWS) calendar backend#103
olivierlambert merged 5 commits into
olivierlambert:mainfrom
DYB-Corp:feat/ews-provider

Conversation

@huntervcx

Copy link
Copy Markdown
Contributor

Summary

Adds Microsoft Exchange (EWS) as an alternative to CalDAV for connecting on-prem
Exchange 2013/2016/2019 mailboxes. Users can now pick the backend protocol when
adding a calendar source; the rest of the booking flow (sync, write-back,
availability) is unchanged.

  • New ews provider built on a minimal SOAP client (src/ews/): autodiscover,
    GetFolder / FindItem / CreateItem / DeleteItem, iCal ↔ EWS field mapping.
  • Provider factory (src/providers/) abstracts CalDAV vs EWS so the rest of
    the codebase talks to a single trait. CalDAV path is unchanged.
  • Schema: migrations/050_provider_type.sql adds provider_type on
    caldav_sources (defaults to caldav for existing rows — backward compatible).
  • Source-add form: new Backend dropdown (CalDAV / EWS). The Preset
    dropdown is filtered client-side so EWS presets only appear when EWS is
    selected, and vice-versa.
  • SSRF escape hatch: CALRS_ALLOW_PRIVATE_HOSTS=1 opt-in env var to allow
    CalDAV/EWS URLs that resolve to RFC1918 / loopback IPs. Logs a WARN at
    startup when set. Useful for self-hosted Exchange behind private addressing;
    off by default.

Test plan

  • cargo build --release clean
  • cargo fmt --check clean
  • Add a CalDAV source via the dashboard — existing flow still works,
    preset dropdown shows CalDAV options only.
  • Add an EWS source — connection test succeeds, calendar list appears,
    write-back picks the right folder.
  • Create a booking on an EWS-backed event type — event lands in the
    Exchange mailbox, cancellation removes it.
  • Switch the Backend dropdown back and forth — Preset list updates and
    stays consistent (no EWS option while CalDAV is selected).
  • Without CALRS_ALLOW_PRIVATE_HOSTS, adding a source pointing at a
    private IP is rejected with the existing SSRF error.
  • With CALRS_ALLOW_PRIVATE_HOSTS=1, the same URL is accepted and the
    startup log shows the SSRF-disabled warning.

@huntervcx

huntervcx commented May 13, 2026

Copy link
Copy Markdown
Contributor Author
image image

had to create a "backend" selector and set presets on their respective backend, as MS Exchange 2019 does not support caldav without some bridge in between

@olivierlambert olivierlambert left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huntervcx thanks for putting this together! 🙏 First read from me. Big PR, but very approachable: the trait + factory split is sharp, the EWS module is well-organised, and the security work shows real care (RFC1918 + CGNAT + IPv6 ULA SSRF screen, validator re-run on the server-returned EwsUrl, escape() on every user-controlled XML interpolation, SendMeetingInvitations="SendToNone" / HardDelete / SendMeetingCancellations="SendToNone" with comments explaining why). The architecture lands well; most of what follows is polish.

Things that look really good

  • Trait shape. Opaque id on RemoteCalendar plus separate change_marker and sync_state is exactly the right abstraction: it lets the CalDAV ctag/sync-token model and EWS ChangeKey/SyncState model coexist without leaking provider details into sync code. The CalDAV adapter is a thin translation layer, so the existing CalDAV behaviour is preserved end-to-end.
  • SSRF defense. validate_caldav_url runs on each candidate autodiscover URL and on the server-supplied EwsUrl before persisting. The honest comment about DNS rebinding and the egress-firewall mitigation is the right framing. CALRS_ALLOW_PRIVATE_HOSTS opt-in plus the WARN log at serve startup (src/main.rs:140) is the right shape too.
  • EWS semantics. SendMeetingInvitations="SendToNone" keeps EWS from firing duplicate invites alongside the SMTP path. DeleteType="HardDelete" avoids the tombstone-in-Trash freebusy issue. SyncScope=NormalItems correctly excludes recurring exceptions. MaxEntriesReturned/MaxChangesReturned are bounded. synth_or_fetch_mime skips a round trip for non-recurring items.
  • iCal synthesis. escape_ical_text is RFC 5545 compliant (\\, \,, \;, \n, strip \r). TRANSP mapping (Free/TentativeTRANSPARENT) is exactly what calrs's availability logic expects, and the STATUS:CANCELLED mapping mirrors the CalDAV path.
  • Tests. Good coverage of the EWS-specific logic: autodiscover parsing (modern + ASUrl fallback + no-match), SOAP fault detection, FindFolder, FindItem with CalendarView, CreateItem id extraction, sync delta with create/update/delete, MIME extraction, iCal synth (basic / all-day / TRANSP / CANCELLED / UID fallback), and the upper-bound math. cargo clippy is clean.

Blockers (small but they need fixing before merge)

1. Two migration tests are failing. cargo test on the branch reports:

db::tests::migrate_is_idempotent
db::tests::migrate_tracks_applied_migrations

Both assert count == 50 at src/db.rs:807 and :830. Migration 051_provider_type.sql brings the total to 51, so the assertions (and their message strings) need bumping. Pre-commit runs cargo test, so this would have been caught locally too.

2. Migration number collision with main. 1.11.0 shipped migrations/051_per_member_frequency_limit.sql to main (#118), which collides with this PR's 051_provider_type.sql. Same dance as #99: rebase on main, rename to migrations/052_provider_type.sql, update the migrations array in src/db.rs, and bump the test count to 52 once you do.

Substantive but not blocking

3. EWS delta sync never seeds a cursor. In EwsProvider::sync_delta, sync_state = None returns DeltaResult::default() early (with the well-reasoned "SyncFolderItems-from-zero walks the entire folder" comment). The implication is that sync_source never gets a new_sync_state to store for EWS sources, so stored_sync_state stays None forever and EWS sources always take the full-fetch path. The code is correct, but the trade-off is more permanent than the comment suggests. Two options:

  • Acknowledge it explicitly: rename the comment from "the next background full sync will bootstrap the cursor naturally on the first incremental call" to something like "EWS sources rely on full fetches", and file a follow-up issue for a CalendarView-based incremental.
  • Wire the cursor seed properly: have sync_delta(_, None) issue an empty SyncFolderItems just to grab the initial SyncState (no items returned thanks to MaxChangesReturned=0 if you set it small), then the next sync can use the cursor.

Either is fine; I'd prefer the first since it preserves the perf reasoning.

4. fetch_events_since is dead code in the application. Defined on the trait, implemented by both providers, but nothing in src/commands/sync.rs or src/web/mod.rs actually calls it. Not a regression from this PR, but the trait surface now formalises it. Two options: wire it up to sync_if_stale (the on-demand path) for the perf win on both CalDAV and EWS, or drop it from the trait until something needs it. The EWS CalendarView implementation is good, it would be a shame to leave it idle.

5. Autodiscover redirect target isn't validated. Policy::limited(2) follows up to two redirects, but only the initial URL goes through validate_caldav_url. A malicious or misconfigured autodiscover responder could redirect to a private hostname mid-chain. Severity is low (the chain is HTTPS, the attacker would need to also serve a valid TLS cert for the private host), but a custom redirect policy that re-runs the validator per hop would close the gap. Optional; a comment marking it as a known limitation would also be fine.

6. EWS synth omits DTSTAMP. RFC 5545 requires DTSTAMP on every VEVENT. The icalendar crate is lenient about this in calrs's parsing path, but a stricter consumer (or future static analysis) would balk. Three lines to add in synth_vcalendar.

7. EWS naive-local datetimes are floated. format_dt emits the value without TZID when there's no trailing Z. EWS by default returns UTC, but if a tenant has a non-UTC default and emits naive locals, the synthesised iCal will be interpreted as floating and slot computation could drift. The MIME path is the proper escape hatch (and the code does fall through to it for recurrences), so this only bites non-recurring naive-local events. Worth a TODO + tracking issue.

8. sync_folder_items outer loop has no safety cap. loop { ...; if page.includes_last { break; } } — a buggy or pathological server that never sets IncludesLastItemInRange=true will spin until something else kills the request. A for _ in 0..MAX_ITERS cap (say 200, given MaxChangesReturned=512) would be cheap insurance.

9. Schema columns are reused but lie about their names. calendars.href now holds EWS ItemId values, calendars.ctag holds EWS ChangeKey values. The code is correct (and you've added comments noting this), but the column names will misdirect anyone reading the schema cold. Either rename (more work, requires a migration) or add a -- See providers/mod.rs::RemoteCalendar comment on the schema. Pragmatic to leave, just worth flagging.

Minor nits

  • One em-dash slipped through in templates/source_form.html line 69 (the new EWS help text). The project convention is no em-dashes (feedback_em_dashes.md). Trivial replace with a comma or period.
  • CLAUDE.md was updated to add 051 to the migrations index. After renumbering to 052 you'll need to update CLAUDE.md too.
  • extract_vcalendar line-unfolding strips \r\n and \r\n\t — that's actually RFC 5545 line continuation, not "stray indentation" as the comment says. Behaviourally fine since iCal consumers expect unfolded text; just a comment-vs-code mismatch.

On compatibility

You called out that "MS Exchange 2019 does not support caldav without some bridge" in the inline comment, which matches what the PR docs say. Worth folding that note into the doc that ships with this (the module mentions "see docs/ews.md (planned)") so operators know to look for EWS, not CalDAV, when they hit a 2019 server.


Overall this is a strong piece of work and the security posture is excellent. Fix the two blocking items (test counts + migration renumber + rebase) and at least pick a path on #3 (EWS delta sync), and I'm happy to come back for a final pass and merge. The substantive items #4-#9 we can either fold into this PR or take as fast follow-ups, your call.

Thanks again for the EWS work, calrs is going to reach a lot more on-prem operators because of it 🙂

@olivierlambert olivierlambert left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flipping to Changes Requested per the review above so the badge reflects state. Two concrete blockers, both small:

  1. Two failing migration tests (migrate_is_idempotent, migrate_tracks_applied_migrations) still assert the old count at src/db.rs:807 / :830. Bump to match the new total.
  2. Migration 051_provider_type.sql collides with main's 051_per_member_frequency_limit.sql (shipped in 1.11.0). Rebase + renumber to 052_provider_type.sql plus update the src/db.rs entry.

The substantive items #3 to #9 from the review can ride along in this PR or land as follow-ups, your call. Architecture and security work are solid 🙂

@huntervcx huntervcx force-pushed the feat/ews-provider branch from cd1dcdd to 04884ec Compare June 3, 2026 20:18
@huntervcx huntervcx marked this pull request as draft June 3, 2026 20:21
Arthur Perrot and others added 5 commits June 3, 2026 22:27
Introduces a generic CalendarProvider trait so calrs is no longer
hard-wired to CalDAV. Adds an EWS implementation targeting on-prem
Exchange 2019 (also compatible with 2016/2013) with Autodiscover,
calendar listing, full + windowed event fetch, create/delete, and
SyncFolderItems delta sync.

The CalDAV path is preserved unchanged behind a thin adapter; sync,
source management, and write-back now dispatch on a new provider_type
column (migration 050). HTTPS-only and SSRF-safe URL validation is
shared across both providers, and Autodiscover candidate URLs are
re-validated before they get hit.

Layout:
  src/providers/     trait + factory + caldav adapter
  src/ews/           soap, autodiscover, operations, parse, ical synth

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
            duplicate connection-check arms, rustfmt

Cargo.lock is updated by Cargo's first compile after a fresh dependency
add (async-trait); committing it so a clean checkout doesn't churn it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Blockers (from review):
- Migration 050_provider_type renumbered to 054_provider_type to avoid
  collision with upstream main's 051-053. src/db.rs migration array +
  CLAUDE.md index updated.
- Migration-count assertions in db.rs tests bumped from 50 to 54.

Substantive review items folded in:
- sync_folder_items now caps at 200 SOAP iterations; a server that
  never sets IncludesLastItemInRange=true returns partial results and
  is resumed from the latest cursor next sync. (olivierlambert#8)
- synth_vcalendar emits DTSTAMP per RFC 5545; EWS doesn't expose a
  stable last-modified, so we use Utc::now(). (olivierlambert#6)
- EWS sync_delta comment rewritten to acknowledge "EWS sources rely
  on full fetches" rather than claiming the cursor gets bootstrapped.
  (olivierlambert#3, option A)
- fetch_events_since wired into sync_ews_source with the same 90-day
  lookback used by the CalDAV path. The EWS impl uses CalendarView
  (server-side window). remove_orphaned_ews_events now takes the same
  since_prefix scoping as the CalDAV variant so events outside the
  window are not flagged as orphans. (olivierlambert#4)
- format_dt TODO documenting naive-local TZID drift on non-recurring
  items. (olivierlambert#7)
- Autodiscover redirect policy now carries an explicit comment about
  the SSRF residual risk on intermediate Location headers. (olivierlambert#5)
- 054_provider_type.sql explains the calendars.href / calendars.ctag
  reuse for EWS folder ItemId / ChangeKey. (olivierlambert#9)
- extract_vcalendar comment corrected: the \r\n /\r\n\t replacements
  are RFC 5545 §3.1 line-fold unfolding, not "stray indentation".

Rebase side-effects:
- SSRF guard now uses upstream's CALRS_ALLOW_PRIVATE_HOSTS allowlist
  (hostname-scoped) instead of the previous boolean toggle. private_
  host_allowlist() is exposed for the serve startup WARN log.
- Sources flow (commands/source.rs, commands/sync.rs, web/mod.rs)
  reconciled with upstream's OAuth2 dispatch + orphan-cancel work:
  EWS sources go through the provider trait, CalDAV sources keep the
  CaldavClient path (basic-auth or OAuth2 unchanged).
- new sync_ews_source/upsert_calendar_provider/upsert_provider_events
  helpers in commands/sync.rs to keep the EWS path off the CalDAV
  CaldavClient signature.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@huntervcx huntervcx force-pushed the feat/ews-provider branch from 04884ec to 2bf4c52 Compare June 3, 2026 21:52
@huntervcx huntervcx marked this pull request as ready for review June 3, 2026 21:53
@huntervcx

huntervcx commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Hi @olivierlambert
Thanks for the thorough review! pushed with all the blockers fixed and the substantive items folded in:

Blockers

Substantive items

  • 3 EWS delta sync: kept the "no cursor seed on None" behaviour and rewrote the comment to honestly state "EWS sources rely on full fetches", as you suggested.
  • 4 fetch_events_since is no longer dead code: wired into the EWS sync path with the same 90-day lookback as the CalDAV side (commands::sync::sync_ews_source). remove_orphaned_ews_events now takes a since_prefix so events outside the window aren't flagged as orphans, matching the CalDAV variant.
  • 5 Autodiscover redirect: added an explicit comment about the residual SSRF risk on intermediate Location headers + the egress-firewall mitigation. The final EwsUrl is still revalidated post-redirect chain.
  • 6 DTSTAMP added to synth_vcalendar (RFC 5545). EWS doesn't expose a stable last-modified so it's Utc::now().
  • 7 TODO on format_dt documenting the naive-local TZID drift on non-recurring items, scoped to that path since the MIME path is unaffected.
  • 8 sync_folder_items capped at 200 iterations (~102k items at MaxChangesReturned=512). Returns partial result + cursor on cap-hit so the next sync resumes cleanly, with a WARN log.
  • 9 Comment added to 055_provider_type.sql calling out the calendars.href / calendars.ctag reuse for EWS ItemId / ChangeKey.

Nits

  • Em-dash gone from the EWS preset help text (sorry for that).
  • extract_vcalendar comment now correctly identifies the unfolding as RFC 5545 §3.1 line-fold, not "stray indentation".
  • CALRS_ALLOW_PRIVATE_HOSTS switched from the previous boolean to your allowlist design from 2830f96. The serve startup warn fires when the allowlist is non-empty.

Smoke test
Ran a live smoke against an on-prem Exchange 2019 : everything was ok
i don't have anymore a ex2007 server to test, but EOL of it so won't bother imo

cargo fmt --check / cargo clippy --all-targets -- -D warnings / cargo test all green (728 tests, including the new captcha additions).

Sorry if some things are not compliant, i'm not an expert in rust, but still ready for another pass when you have a moment.

@olivierlambert olivierlambert left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fast turnaround, this revision checks out on every point.

Verified locally on the rebased head:

  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, and cargo test (728 passed) all green
  • Migration 055_provider_type.sql registered in src/db.rs, both count assertions at 55
  • fetch_events_since wired into sync_ews_source, and remove_orphaned_ews_events mirrors the CalDAV variant's window scoping and empty-response guard exactly
  • sync_folder_items cap, DTSTAMP, autodiscover redirect comment, format_dt TODO, and the allowlist-based CALRS_ALLOW_PRIVATE_HOSTS all landed as described
  • Nice bonus cleanup removing the smoke-test scaffolding

No worries about Exchange 2007, it has been EOL since 2017 and not worth supporting. Merging, and thanks for the contribution!

@olivierlambert olivierlambert merged commit 43daec3 into olivierlambert:main Jun 4, 2026
@huntervcx huntervcx deleted the feat/ews-provider branch June 4, 2026 13:27
olivierlambert added a commit that referenced this pull request Jun 6, 2026
The provider-expansion release: connecting a calendar no longer means
CalDAV with basic auth. Microsoft Exchange (EWS) joins as a second
backend behind a new provider trait, Google Calendar connects via
OAuth2 with encrypted token storage, confirmed bookings can
auto-generate video meeting links (Jitsi pattern or bring-your-own
webhook), booking pages gain an opt-in self-hosted proof-of-work
captcha, and an embed system lets you put your booking page on any
website. Two headline features are community contributions.

Highlights:

- Microsoft Exchange (EWS) calendar backend (#103, #127)
- Google Calendar (OAuth2) sources (#99)
- Auto-generated video meeting links: Jitsi + webhook (#128)
- Self-hosted proof-of-work booking captcha (#122, @florian-SV)
- Embed code generator: inline, floating button, element click (#125)
- calrs config dump CLI command (#112, @mvalois)
- CALRS_ALLOW_PRIVATE_HOSTS for private CalDAV/EWS hosts (#124)
- Fixed: Google forward-window sync truncation, CalDAV write-back
  no longer gated on SMTP (#99), friendly booking email validation (#129)
- Migrations 053-056; translations update (#131); 758 tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
huntervcx added a commit to DYB-Corp/calrs that referenced this pull request Jun 25, 2026
…ert#103)

* feat(providers): add Microsoft Exchange (EWS) calendar provider

Introduces a generic CalendarProvider trait so calrs is no longer
hard-wired to CalDAV. Adds an EWS implementation targeting on-prem
Exchange 2019 (also compatible with 2016/2013) with Autodiscover,
calendar listing, full + windowed event fetch, create/delete, and
SyncFolderItems delta sync.

The CalDAV path is preserved unchanged behind a thin adapter; sync,
source management, and write-back now dispatch on a new provider_type
column (migration 050). HTTPS-only and SSRF-safe URL validation is
shared across both providers, and Autodiscover candidate URLs are
re-validated before they get hit.

Layout:
  src/providers/     trait + factory + caldav adapter
  src/ews/           soap, autodiscover, operations, parse, ical synth

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fixup(ews): drop unused Context import + dead summary_view, collapse
            duplicate connection-check arms, rustfmt

Cargo.lock is updated by Cargo's first compile after a fresh dependency
add (async-trait); committing it so a clean checkout doesn't churn it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* wip: save ews provider work

* feat: clean sources presets filtered via backend

* fixup(ews): address review blockers + substantive items

Blockers (from review):
- Migration 050_provider_type renumbered to 054_provider_type to avoid
  collision with upstream main's 051-053. src/db.rs migration array +
  CLAUDE.md index updated.
- Migration-count assertions in db.rs tests bumped from 50 to 54.

Substantive review items folded in:
- sync_folder_items now caps at 200 SOAP iterations; a server that
  never sets IncludesLastItemInRange=true returns partial results and
  is resumed from the latest cursor next sync. (olivierlambert#8)
- synth_vcalendar emits DTSTAMP per RFC 5545; EWS doesn't expose a
  stable last-modified, so we use Utc::now(). (olivierlambert#6)
- EWS sync_delta comment rewritten to acknowledge "EWS sources rely
  on full fetches" rather than claiming the cursor gets bootstrapped.
  (olivierlambert#3, option A)
- fetch_events_since wired into sync_ews_source with the same 90-day
  lookback used by the CalDAV path. The EWS impl uses CalendarView
  (server-side window). remove_orphaned_ews_events now takes the same
  since_prefix scoping as the CalDAV variant so events outside the
  window are not flagged as orphans. (olivierlambert#4)
- format_dt TODO documenting naive-local TZID drift on non-recurring
  items. (olivierlambert#7)
- Autodiscover redirect policy now carries an explicit comment about
  the SSRF residual risk on intermediate Location headers. (olivierlambert#5)
- 054_provider_type.sql explains the calendars.href / calendars.ctag
  reuse for EWS folder ItemId / ChangeKey. (olivierlambert#9)
- extract_vcalendar comment corrected: the \r\n /\r\n\t replacements
  are RFC 5545 §3.1 line-fold unfolding, not "stray indentation".

Rebase side-effects:
- SSRF guard now uses upstream's CALRS_ALLOW_PRIVATE_HOSTS allowlist
  (hostname-scoped) instead of the previous boolean toggle. private_
  host_allowlist() is exposed for the serve startup WARN log.
- Sources flow (commands/source.rs, commands/sync.rs, web/mod.rs)
  reconciled with upstream's OAuth2 dispatch + orphan-cancel work:
  EWS sources go through the provider trait, CalDAV sources keep the
  CaldavClient path (basic-auth or OAuth2 unchanged).
- new sync_ews_source/upsert_calendar_provider/upsert_provider_events
  helpers in commands/sync.rs to keep the EWS path off the CalDAV
  CaldavClient signature.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Arthur Perrot <aperrot@dyb.fr>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
huntervcx pushed a commit to DYB-Corp/calrs that referenced this pull request Jun 25, 2026
The provider-expansion release: connecting a calendar no longer means
CalDAV with basic auth. Microsoft Exchange (EWS) joins as a second
backend behind a new provider trait, Google Calendar connects via
OAuth2 with encrypted token storage, confirmed bookings can
auto-generate video meeting links (Jitsi pattern or bring-your-own
webhook), booking pages gain an opt-in self-hosted proof-of-work
captcha, and an embed system lets you put your booking page on any
website. Two headline features are community contributions.

Highlights:

- Microsoft Exchange (EWS) calendar backend (olivierlambert#103, olivierlambert#127)
- Google Calendar (OAuth2) sources (olivierlambert#99)
- Auto-generated video meeting links: Jitsi + webhook (olivierlambert#128)
- Self-hosted proof-of-work booking captcha (olivierlambert#122, @florian-SV)
- Embed code generator: inline, floating button, element click (olivierlambert#125)
- calrs config dump CLI command (olivierlambert#112, @mvalois)
- CALRS_ALLOW_PRIVATE_HOSTS for private CalDAV/EWS hosts (olivierlambert#124)
- Fixed: Google forward-window sync truncation, CalDAV write-back
  no longer gated on SMTP (olivierlambert#99), friendly booking email validation (olivierlambert#129)
- Migrations 053-056; translations update (olivierlambert#131); 758 tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants