Skip to content

Self-serve team onboarding for Darwin#58

Open
rajivml wants to merge 41 commits into
feature/darwinfrom
feature/darwin_onboarding
Open

Self-serve team onboarding for Darwin#58
rajivml wants to merge 41 commits into
feature/darwinfrom
feature/darwin_onboarding

Conversation

@rajivml

@rajivml rajivml commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Self-serve team onboarding for Darwin

Adds an end-to-end self-serve onboarding flow: a validated request form → admin
approval → automatic provisioning (connectors, document set, assistant, Slack
bot config) → background finalizer, with Slack notifications throughout.

Highlights

  • Form + validation: inline-validated request form (Slack channel, docs,
    Confluence, Jira, GitHub sources); requester self-edit/cancel of pending
    requests; admin edit-and-approve in the same shared form; SSO-gated.
  • Two-phase provisioning: approve → connectors/cc_pairs + high-priority
    indexing → INDEXING; background finalizer creates the document set, assistant
    (prompt + persona with the SearchTool), and Slack bot config → COMPLETE.
    Idempotent + checkpointed so a pod crash resumes without duplicating artifacts;
    "in-progress wins over failed" so a request never shows FAILED while a source
    is still scraping.
  • Admin queue: status-filter pills + pagination, per-source scrape status
    with connector links, a milestone "journey" stepper, aggregate rollups, and a
    read-only view for finished requests.
  • Slack notifications: internal ops → #darwin-devs (admin link + real
    errors); customer-facing thread → #help-darwin (requester @mentioned on submit,
    lifecycle updates as threaded replies; channel configurable via
    ONBOARDING_CLIENT_CHANNEL).
  • Also folds in the live slack citation-link fixes (feature/slack_link_fix)
    so this branch doesn't regress them.

Ops

  • New table onboarding_request (+ help_thread_ts) — additive migrations.
  • New env: ONBOARDING_NOTIFY_CHANNEL, ONBOARDING_CLIENT_CHANNEL.
  • Deployed to prod as backend vha-220 / web vha-117.

Tests

Onboarding unit tests cover the finalizer state machine (idempotency, resume,
crash-recovery, notify-failure, SearchTool attachment), notifications, provision
builders + off-by-one regression, and frontend client checks.

rajivml and others added 30 commits July 17, 2026 14:49
…auto-provision

Anyone can submit an onboarding request; admins approve. On approval we
auto-provision connectors (web docs all-versions, Confluence, GitHub, Slack),
an assistant (Orchestrator prompt by default, requester-editable), a Slack bot
config (optional SME review / oncall / Jira), and high-priority indexing, then
expose per-source scrape status the requester can monitor.

- backend: OnboardingRequest model + status enum (stored as String to avoid the
  native_enum NAME/value gotcha), migration c40f5a073fc2, db/onboarding.py CRUD,
  onboarding/validation.py (inline Slack channel/group, Confluence space, docs
  root validation) + onboarding/provision.py orchestrator, and the
  /onboarding + /admin/onboarding API.
- security: require an authenticated user on submit/validate/status (reject
  anonymous / API-key service callers) and a Confluence host allowlist so the
  stored Confluence token is only ever sent to a host an existing Confluence
  connector already uses (SSRF / credential-leak guard).
- web: /onboarding request form (inline field validation, cloud+on-prem docs
  roots, editable prompt, SME/oncall/Jira toggles, my-requests + scrape status)
  and /admin/onboarding approval queue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Slack docs were indexed with the workspace stored as its display name
("Product", plus a "Product " space variant), so every citation permalink
pointed at the dead host product.slack.com. ~320k docs (913 channels)
affected; all verified to genuinely live in the uipath-product workspace.

Two layers, no re-index / data migration required:

- Read-time: normalize_slack_link() rewrites the known-bad "product" subdomain
  to "uipath-product" via an explicit allow-map (case/space-insensitive), applied
  in _vespa_hit_to_inference_chunk. Every citation (chat, search, Slack bot)
  derives its link from source_links, so one choke point fixes all three.
  Genuinely different workspaces (uipath-customer-ops, uipath-marketing, ...)
  are left untouched.
- Index-time: get_all_docs now resolves each channel's true workspace subdomain
  once via chat.getPermalink (Grid-correct), so new scrapes are right regardless
  of the configured workspace; the configured value is only a fallback.

Verified on prod (read-only): normalized links matched Slack's authoritative
chat.getPermalink for 40/40 sampled docs, and the real keyword_retrieval path
returned 10/10 uipath-product links.

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

resolve_workspace_subdomain called client.chat_getPermalink raw, bypassing the
make_slack_api_rate_limited / make_slack_api_call_logged wrappers that every
other Slack API call in this connector uses. On a 429 it would fall back to the
configured workspace instead of retrying with Retry-After. Wrap it so a new
workspace's first scrape resolves correctly under rate limiting. Index-time only
(one call per channel); no behavior change to the read-time citation fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tial-access preflight

Server-side validation at the point the credential is actually used, since
submit-time /validate can be bypassed by a direct API call:

- SSRF / credential-leak guards in provision.py `_build_connector_base`:
  * Confluence: only build a connector for a host an existing Confluence
    connector already uses (fail closed) — never send the stored token to an
    arbitrary host.
  * GitHub: require a github.com URL.
  * Web: reject non-http(s) and hosts resolving to private/loopback/link-local/
    reserved addresses (block crawling internal infra with our outbound identity).

- Credential-access preflight: verify the reusable shared credential can actually
  reach each source before provisioning, so we never create a connector that
  silently indexes nothing. New validate_github_repo() (token -> get_repo, sent
  only to the GitHub API, generic errors, no token/payload leakage) wired into
  /validate; provision `_assert_source_accessible` reuses the Confluence/GitHub/
  Slack validators and fails the request with a clear reason.

- Frontend: GitHub sources are now live-validated inline (were format-only).

30 onboarding unit tests (host/SSRF rejects, cred-access success/fallback,
secret-leakage assertion); mypy + pre-commit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"Onboard a Team" link in the chat sidebar (next to Manage Assistants) and a
FiUserPlus icon in the chat top-right, both linking to /onboarding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Form changes (per product review):
- Title -> "Onboarding Darwin to Slack Channel".
- Bot-channel field gets an info tooltip (where the Slack bot is configured).
- Response format is standardized to citations for all channels (selector removed).
- Removed "respond only when tagged" and "enable Jira ticket creation" options.
- Channel message-history indexing is now always on (toggle hidden).
- Docs fields renamed "Docs-URL - Cloud" / "Docs-URL - On-prem"; "Sources
  (priority order)" -> "Sources".
- Removed GitHub from additional sources; added Jira (JQL filter) as a source,
  validated live before submit.

Jira source (backend): validate_jira_filter (JQL run via the stored Jira
credential against an existing connector's base URL only; generic errors, no
token/payload leakage) wired into /validate; provision builds a Jira connector
(reused base URL + JQL) and preflights access. Credential-key + source-type maps
updated.

UI polish (frontend-design): numbered step sections, consistent field component
with inline validation states, refined source rows. Uses only the app's semantic
theme tokens, so the page honors the global light/dark setting automatically.

34 onboarding unit tests; mypy, tsc, next lint, pre-commit all clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…checks + theme toggle

- Channel validation: the old bare-name path scanned conversations_list capped at
  12 pages (~12k channels); on Enterprise Grid a channel can be far deeper
  (help-automation-suite is on page 19), so valid channels read as "not found".
  Slack has no name->channel lookup API and every channel-read needs the ID, but
  provisioning only uses the channel *name* — so instead of enumerating the whole
  org we now search only the channels the bot is a MEMBER of (users.conversations,
  a small set), which is also the real precondition for the bot to operate there.
  Not-found now says to invite the bot rather than "paste a #mention".
- Client-side validation: instant format hints (no #, lowercase, https://, JQL),
  debounced backend validation (no need to blur), and Submit disabled until the
  bot channel resolves.
- Theme: added a light/dark toggle to the page (it already honored the global
  theme, but rendered outside the app chrome so had no control). Mirrors
  UserDropdown — same darwin-theme key + .dark class.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bot is only added to the channel DURING onboarding (connector auto-join on
index), so a brand-new channel legitimately isn't a member yet — requiring
membership would reject exactly the channels being onboarded. Since Slack has no
name->channel lookup and provisioning uses the channel name (not id), the channel
check no longer blocks on existence: the membership check is a positive signal
only ("bot is already in this channel"), and any well-formed name is accepted
with a "the bot will be added during onboarding" note.

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

A bare channel name can't be verified reliably (Slack has no name lookup), but a
channel link carries the channel id, so conversations_info verifies it exactly in
one call — even for a public channel the bot isn't a member of yet. So the bot
channel now requires a link:

- backend: parse a pasted channel URL (/archives/C…) to extract the id and verify
  via conversations_info (alongside the existing <#…> mention and raw-id paths).
- frontend: the bot-channel field requires a link (client check rejects a bare
  name before any round-trip, so the field can't resolve until a link is given),
  with visible steps: open the channel -> ⋯ (More) -> Copy -> Copy link.

Additional Slack *source* rows still accept names (the connector auto-joins by
name on index); only the bot channel is link-gated.

Verified live: a pasted link resolves to the correct channel via conversations_info.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…default scraping

Label "Bot channel link" -> "Slack Channel"; info tooltip now states the channel
is scraped by default and kept updated so its knowledge stays current.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The on-call option now accepts Slack user-group handles (e.g. @as-dri), not just
an OpsGenie schedule. Handles are stored in the channel's follow_up_tags, which
the "I need more help" button already resolves (emails->users, names/@handles->
user-groups) and @-mentions. OpsGenie schedule remains as an optional/additional
source of the current DRI.

- models: OncallOption.handles (comma-separated).
- provision: _build_channel_config sets follow_up_tags from the handles.
- validation: validate_slack_group now validates a comma-separated list, matching
  either group name or @handle, and reports which ones don't resolve (also fixes
  the SME multi-group field).
- frontend: "DRI Slack handle(s)" field (validated live) under the on-call option.

mypy, 34 tests, tsc, eslint, pre-commit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On submit, post a best-effort Slack message to the ops channel (default
"darwin-devs", override via ONBOARDING_NOTIFY_CHANNEL) with the requester, team,
target channel, sources, and a link to the admin review console. Wrapped so a
Slack failure never fails the submission.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
darwin-devs is a private channel in a different Grid workspace; the DanswerBot
app token (fetch_tokens, which notify uses) is a member, but a private/
cross-workspace channel must be addressed by ID, not name. Default
ONBOARDING_NOTIFY_CHANNEL to the channel ID (C07B2V8E99S), and accept an id,
name, or pasted channel link (id parsed out) via env/configmap.

Verified: the DanswerBot token resolves C07B2V8E99S (#darwin-devs, is_member=True).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Darwin now goes live in a channel only once its knowledge is actually scraped.

Phase 1 (on approval, provision_onboarding): create connectors + cc_pairs and
kick off high-priority indexing; status INDEXING. No doc set / assistant / Slack
config yet.

Phase 2 (background sweep, finalize_ready_onboarding_requests, ~every 60s in the
indexing scheduler loop): once every source's latest index attempt succeeds,
create the document set over the cc_pairs, the assistant (prompt + persona) tied
to it, and the Slack bot config — making Darwin live — then mark COMPLETE and
notify #darwin-devs. Source failures flip the request to FAILED and notify once.

Recovery needs no restart: the sweep also re-checks FAILED requests, so fixing +
re-indexing a failed source lets it finalize automatically on a later tick.

Also:
- Per-source scrape cadence: Slack/Confluence/Jira daily, docs (web) monthly.
- Confluence parent/child dedup: a whole-space URL supersedes its pages, and a
  parent page supersedes descendant pages (best-effort via the ancestry API) —
  keeping the parent alone, since the connector already recurses child pages.
- Status endpoint no longer auto-advances; the finalizer owns transitions.

45 onboarding unit tests; mypy + pre-commit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Positive + negative paths for _source_index_state (all-success, one-failed,
in-progress, no-attempt-yet, no-cc-pairs) and finalize_ready_onboarding_requests
(finalize on success, flag failure once, don't re-notify an already-FAILED
request, recover a previously-FAILED request once sources succeed, no-op while
still indexing, and per-request error isolation).

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

Backend (mocked bot/atlassian clients — no live API):
- validate_slack_channel: link / <#…> mention / id -> conversations_info,
  bad id rejected, bare name that the bot is in vs not-yet-in (accepted), empty.
- validate_slack_group: comma-separated handles all-found vs some-missing, empty.
- validate_confluence_url: bad host rejected, unverified without creds, space
  accessible, space inaccessible (+ asserts no token/exception leakage).

Frontend: extracted the form's client-side format checks into
lib/onboarding/clientChecks.ts (checkChannelLink/checkChannel/checkUrl/checkJql +
SOURCE_CLIENT_CHECK) and added a vitest suite (positive + negative for each).

69 backend onboarding tests + 11 frontend tests; mypy, tsc, eslint, pre-commit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The requester page rendered without an auth check (only the backend APIs were
gated), so a signed-out user saw a form whose every action 401s. Add the app's
standard server-side gate (getCurrentUserSS + redirect to /auth/login), matching
search/chat and the admin Layout. Allowlist /onboarding for the post-login
`next` redirect so users land back on the form after SSO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Light mode uses white cards (bg-background-weak #fff) on a near-white canvas
(bg-background #f1f3f7); with only a hairline border and no shadow the cards
didn't separate and the page read as one flat, over-bright expanse. Add shadow-sm
to the section + request cards so they lift off the canvas. No effect in dark
mode (shadows are invisible there; the border already defines the cards).

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

Scraping needs the bot in the channel. The connector auto-joins PUBLIC channels
on scrape but can't self-join PRIVATE ones — those must be invited. Reflect that
in the channel validation message using is_member / is_private from
conversations_info:
- member -> "the bot is already in this channel"
- public, not member -> "the bot will auto-join this public channel when it scrapes"
- private, not member -> "invite @darwin — private channels can't be auto-joined"
- conversations_info error -> hint to invite the bot for private channels
Bare-name (source rows) note now says public auto-join / invite-if-private.

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

The message said "Space '<id>' (existence unverified)" even for a PAGE url,
wrongly implying a whole-space scrape. Mirror the connector's actual behavior:
- page url  -> "Will scrape this page and all its child pages"
- space url -> "Will scrape the whole '<space>' space"
Also verify the actual target (get_page_by_id for a page url, get_space for a
space url) instead of always checking the space. resolved now includes page_id.

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

- On-prem docs field now shows an automation-suite reference URL
  (https://docs.uipath.com/<product>/automation-suite/<latest-version>) alongside
  the standalone example.
- Help text: for automation-suite docs the version is stripped and Darwin scrapes
  the latest 3 versions automatically — no need to list each version URL.
- Provision now sets max_versions=3 (was 2) to match, so the latest 3 concrete
  versions are crawled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"The bot channel's own message history is always indexed" was under the docs
URLs, where it's confusing — it's about the Slack channel, not docs. That fact is
already stated in the Slack Channel field's info tooltip, so remove the duplicate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Admins couldn't find the onboarding review page. Add "Onboarding requests" to the
admin sidebar (Custom Assistants group, next to Slack Bots) -> /admin/onboarding,
which lists all requests with status and approve/reject actions. So approval is a
UI action, not only a Slack thing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The page rendered only the form, so there was no nav — an admin couldn't reach
the Admin Panel, and there was no logo/user menu. Render the standard <Header>
(logo -> chat, UserDropdown with Admin Panel for admins + theme toggle + logout).
Removed the now-redundant inline theme toggle from the form (the header provides
it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds GET /admin/onboarding/{id} (full payload) and PATCH /admin/onboarding/{id}
(replace payload, pending-only) plus update_onboarding_payload, so an admin can
open a request in the form, fix gaps, and approve. Additive; wired to UI next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…av link

- Onboarding page now has top tabs: "Submit a request" and "My requests (N)", so
  status isn't buried at the bottom.
- On the "My requests" tab, each request's per-source scrape status auto-loads and
  re-polls every 15s (no manual "refresh" needed) so the requester sees work
  happening — plus an empty state when they have none.
- Left nav: added "My onboarding requests" to the chat sidebar, deep-linking to
  the requests tab (/onboarding?view=requests). OnboardingForm wrapped in Suspense
  for the useSearchParams read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reuse OnboardingForm for both flows via an optional initialRequest prop:
- requester create mode (unchanged), and
- admin edit mode — prefilled from the request; tabs/"my requests"/default-prompt
  fetch are suppressed; submit becomes "Save & approve" (PATCH the payload, then
  approve+provision, redirect to the queue), plus "Save changes" (PATCH only) and
  "Cancel".

New admin route /admin/onboarding/[id] loads the request (GET admin endpoint) and
renders the form in edit mode (Suspense-wrapped for useSearchParams). The admin
queue table gets an "Open / edit" action on pending rows.

Channel prefills from the stored channel id (re-validates via the link path);
sources round-trip (docs + extras editable as rows, channel history re-derived).

tsc, eslint, pre-commit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Requesters can now fix details on a still-pending request (shared form,
editMode="requester") or withdraw it. Cancel is a soft cancel: status
flips to CANCELLED (kept for the audit trail, greyed in the list); edit
and cancel are pending-only and owner-or-admin scoped server-side.
Approved/indexing requests stay admin-only. No DB migration (status is a
plain String column).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rajivml and others added 11 commits July 17, 2026 22:30
… its connector

Admins can click a source name under "Refresh scrape status" to jump
straight to /admin/connector/{cc_pair_id} for full indexing status and
error detail, instead of reading the summarized row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…otify links

- provision_onboarding: record the real cc_pair id (this fork's
  add_credential_to_connector returns connector_id, not the pair id) so the
  finalizer/status track the correct sources.
- finalize_onboarding: idempotent + incremental — create doc set / assistant /
  Slack config only if not already recorded, persist each id immediately as a
  checkpoint, and drop the finalizer's read txn before insert_document_set's
  begin(). A pod crash mid-finalize now resumes instead of duplicating
  artifacts. Notification failure no longer fails finalize.
- finalizer sweep: in-progress wins over failed (never show FAILED while a
  source is still scraping); recover FAILED -> INDEXING on re-index.
- notify: submitted -> request form; complete -> status queue; drop sources line.
- tests: idempotency/resume/crash-recovery/notify-failure + state-machine.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
start_playwright honors WEB_CONNECTOR_BROWSER_CHANNEL (unset in prod, so the
pinned bundled Chromium is used as before). Local dev sets it to "chrome" because
the chromium-1097 build for playwright 1.41.2 SIGSEGVs on recent macOS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y completed form

- OnboardingJourney: milestone stepper (submitted -> approved -> indexed ->
  document set -> assistant -> slack bot -> live) derived from request state,
  with links to each artifact once created. Shown in admin queue + My requests.
- SourceStatusSummary: aggregate rollup (e.g. "4/6 succeeded"); shown by status.
- Admin queue: status filter pills (default hides finished) + pagination (10);
  auto-load per-source status; connector hyperlinks; aligned wrapping columns.
- Completed/non-pending requests: form shown read-only (Save & approve disabled).
- Slack bot config: selected document sets visually distinct (accent + check).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Post a single root message to the customer channel on submit (@mention the
requester + tracking link), then reply IN THAT THREAD on approval / complete /
failure — never new top-level messages, so a large channel isn't spammed.

- onboarding_request.help_thread_ts column (+ migration a1b2c3d4e5f6) stores the
  root message ts so later updates thread under it.
- notify: ONBOARDING_CLIENT_CHANNEL (defaults to darwin-devs for testing; set to
  #help-darwin in prod), notify_client_submitted/approved/complete/failed.
  @mention via users.lookupByEmail with email fallback; self-joins public
  channels; skips replies entirely when no thread ts (never posts top-level).
- wired into submit endpoint (root + persist ts), provision_onboarding
  (approved), and the finalizer (complete/failed). Best-effort; never fails the
  request. Internal #darwin-devs ops notifications unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Annotate the _wire `state` param and add type: ignores for the SimpleNamespace
fixtures passed where OnboardingRequest is expected — keeps the new tests clean
under the PR-gate `mypy .`.

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

Roll out the self-serve onboarding feature (+ merged slack citation fixes):
- images backend vha-218 -> vha-219, web vha-116 -> vha-117
- env-configmap: ONBOARDING_CLIENT_CHANNEL=#help-darwin (customer thread),
  ONBOARDING_NOTIFY_CHANNEL=#darwin-devs (internal ops)

Applied + validated: alembic head a1b2c3d4e5f6, routes mounted, scheduler clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
finalize_onboarding created the persona with the document set but no tools, so
upsert_persona never enabled search — the assistant had the doc set but couldn't
search it. Look up the built-in SearchTool (in_code_tool_id="SearchTool") and
pass tool_ids so search is enabled. The startup auto-add migration doesn't cover
personas created later at finalize time. Test asserts the persona gets tool_ids.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploy the fix so provisioned onboarding assistants get the built-in SearchTool.
Backend-only; web stays vha-117.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Satisfies the CI-pinned prettier (the file was committed with a different
prettier version). Formatting only — no behavior change.

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.

1 participant