mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-21 06:10:53 +08:00
@openmaic/generation@0.3.13
13
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
67584fe9e8 | fix(whiteboard): correct the inverted viewportRatio so boards render 16:9 landscape (#1257) | ||
|
|
2cbe4ae293 |
feat(pi): add Native Child whiteboard tools (#1152)
* feat(pi): add native whiteboard tools * style(pi): format native whiteboard tests * fix(pi): clarify whiteboard CAS handoff * fix(whiteboard): reconcile runtime projection on open |
||
|
|
7cb129183d |
chore(packages): publish the @openmaic/* SDK family to npm (#778) (#780)
* chore(packages): publish the @openmaic/* SDK family to npm (#778) Prepares the @openmaic/{dsl,renderer,importer} family for its first npm publish, and moves the SDK packages onto the @openmaic scope. Why the scope move: the @maic org name is unavailable on npm (an unscoped `maic` package already holds the name), so @maic/* is not claimable. @openmaic matches the project name, the scope is free, and the repo already ships an @openmaic/docs package — so the SDK family now lines up with that convention. - rename @maic/{dsl,renderer,importer} -> @openmaic/* across packages, the workspace glob, the package dir, and all import sites; lockfile regenerated - renderer: add publishConfig (public, registry.npmjs.org) — was missing, so a scoped publish would default to the wrong registry / restricted access - importer: add a files allowlist (dist, README, LICENSE) and drop the fragile .npmignore blacklist that shipped src; add an exports map so ESM consumers resolve dist/index.js instead of falling back to the .cjs main - all three: add a prepublishOnly build (+ test/typecheck) guard so a publish can never ship a stale or empty dist - add a tag-triggered publish workflow with npm provenance, pinned by name to the three @openmaic packages so the vendored forks (mathml2omml, pptxgenjs) are never published Refs #778, #720 (Phase 1). * fix(packages): address cross-review on the @openmaic publish prep Cross-review (Claude /code-review + codex) on this PR surfaced: - renderer's advertised CJS entry was broken: it keeps @openmaic/dsl external and imports a runtime enum from it, but dsl is ESM-only (no `require` condition), so `require('@openmaic/renderer')` would throw ERR_PACKAGE_PATH_NOT_EXPORTED. Make renderer ESM-only: drop the `.cjs` rollup output, `main` now points at the ESM build, and the `require` conditions are removed from `exports`. (importer is unaffected — it bundles dsl, so its CJS build still works.) - prepublishOnly re-ran the test suite during `pnpm -r publish`, so a flaky test after dsl had already published gave a non-atomic partial release. Reduce prepublishOnly to a build-only guard (never ship stale/empty dist) and move the real test/typecheck gate into the workflow, before any publish. - document that an @openmaic/* tag publishes the whole family via `pnpm -r` (pnpm skips already-published versions); the tag is a release marker, not a per-package gate. Verified: dsl + renderer + importer build; renderer emits ESM only (0 .cjs), all exports entries resolve; `npm pack` ships dist + README + LICENSE with no src leak; frozen-lockfile passes. Refs #778. * style: reflow @openmaic/dsl type imports past print-width after rename The @maic -> @openmaic rename lengthened two single-line type imports past prettier's 100-col width; prettier --check flagged them. Pure formatting. Refs #778. * docs(importer): mark @openmaic/importer browser-only (cr-loop accepted limitation) codex cross-review flagged that the published @openmaic/importer throws `XMLHttpRequest is not a constructor` when loaded in a pure Node process — its rollup build is browser-targeted (`nodeResolve({browser:true})` + a browser pdf.js build). The app only consumes it client-side ('use client'), so this is by design. Document it as an accepted limitation: prominent browser-only note in the README and a `browser` field in the manifest. Refs #778. |
||
|
|
4dce1f7414 |
refactor(types): import the slide DSL directly from @maic/dsl; drop the shim (#738)
#707 left lib/types/slides.ts as a thin `export * from '@maic/dsl'` shim so the ~100 existing `@/lib/types/slides` import sites kept working unchanged. Point them at `@maic/dsl` directly and delete the shim, so the app consumes the package contract with no indirection and the legacy module path is gone. Pure module-specifier migration — every symbol imported from `@/lib/types/slides` was already a re-export of the same `@maic/dsl` symbol, so behavior is identical. Also redirects the two `lib/types` relative importers (`./slides`), the e2e fixture's relative import, and the dynamic `import('../types/slides').Slide` type alias in stage-storage; merges the now same-module import pair in slide-edit-elements. Verified: tsc --noEmit clean, eslint clean, vitest 804/804, next build OK, e2e (Playwright) 19/19. Part of #720 (Phase 1). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
45929cf5d5 |
fix(whiteboard): code element captures internal scroll/drag (#530) (#544)
* fix(whiteboard): code element captures internal scroll/drag (#530) Wheel inside the code element no longer reaches the whiteboard zoom handler, and pointer-down drag inside the code body now scrolls the content vertically and horizontally instead of triggering whiteboard pan. Native listeners are used to bypass React event delegation races with the parent's pointer/wheel handlers, and the rows are wrapped in a max-content container so horizontal overflow is reachable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(whiteboard): keep code element content in sync during pan Memoize the whiteboard's AnimatedElement wrapper and drop the per-line `layout="position"` motion prop. Together these stop Framer Motion's projection system from remeasuring code line positions against the panning parent transform and animating the diff, which was making the inner code lag behind the surrounding element box during a pan. Line insert/remove animations still play via height/opacity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(whiteboard): tighten code element gesture handling Address review feedback: - Collapse the wrapper's native pointer/mouse/click listeners into a React `onPointerDown` / `onClick` (whiteboard pan is itself a React handler, so synthetic stopPropagation suffices). - Merge the body drag-scroll and wheel listeners into a single effect. - Handle `lostpointercapture` so an interrupted drag (alt-tab, devtools) releases capture, resets cursor, and clears the dragging flag. - Run the same cleanup on unmount so a captured pointer is released and the cursor does not leak. - Clarify the `AnimatedElement` memo comment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
ad9e0ee7c6 |
refactor(i18n): migrate to i18next framework (#331)
* refactor(i18n): migrate to i18next framework Replace hand-rolled i18n with i18next + react-i18next so that adding a new language only requires dropping a JSON file in lib/i18n/locales/. - Add i18next, react-i18next, i18next-browser-languagedetector deps - Generate zh-CN.json / en-US.json from existing TS translation modules - Rewrite lib/i18n/index.ts as a thin wrapper around i18n.t() - Rewrite use-i18n hook to delegate to useTranslation(); external API (locale, setLocale, t) is unchanged so consumers need no changes - SSR-safe: LanguageDetector only loaded on client side Closes #327 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(i18n): use interpolation for greeting to support natural phrasing Replace string concatenation (greeting + displayName) with two i18next keys: greetingWithName (with {{name}} interpolation) and greetingDefault (standalone, no name). This lets each locale choose natural phrasing independently: - zh-CN: "嗨,同学" / "嗨,Alice" - en-US: "Hi there" / "Hi, Alice" - Future locales can avoid gender issues by choosing genderless defaults Also widen the t() type signature to accept interpolation options. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(i18n): auto-discover locale files via dynamic import Replace hardcoded zh-CN/en-US imports with i18next-resources-to-backend and dynamic import(`./locales/${language}.json`). Bundler scans the locales/ directory at build time, so adding a new language now requires only dropping a JSON file — zero changes to existing code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(i18n): resolve hydration mismatch by deferring language detection LanguageDetector ran during i18next init(), detecting browser language before React hydrated — server rendered zh-CN while client switched to en-US immediately, causing a hydration mismatch. Fix: remove i18next-browser-languagedetector; init with a fixed lng (zh-CN) so server and client agree on the first render. Language detection is now done in I18nProvider's useEffect after hydration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(i18n): remove hardcoded locale list from language detection Replace manual locale validation and startsWith('zh') prefix matching with i18next's built-in fallback mechanism. Now changeLanguage() is called with navigator.language directly — if the exact locale has no JSON file, i18next automatically falls back to fallbackLng. Also widen Locale type from union to string so adding new languages doesn't require modifying types.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(i18n): add course language config with 11 languages and UI linkage - Add lib/i18n/course-languages.ts with curated language list (zh-CN, zh-TW, en-US, ja, ko, fr, de, es, pt, ru, ar) including native labels and English prompt names - Course language defaults to UI locale on first visit; once user explicitly picks a language, that choice persists across sessions - Replace toggle button with dropdown selector showing native labels - Widen language types from 'zh-CN'|'en-US' to string throughout - Fix hardcoded language ternaries in LLM prompt injection: - prompt-builder.ts: use getCourseLanguagePromptName() - classroom-generation.ts: remove normalizeLanguage() that forced all non-English to zh-CN - PBL system prompt, agent templates, generate-pbl: append language instruction for non-zh/en languages - quiz-grade API: add language suffix for grading feedback Closes #327 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(quiz): use course language instead of UI locale for grading quiz-view was passing the UI locale to the grading API, causing AI feedback to follow the student's answer language instead of the course language. Now reads stage.language from the store. Also strengthen the grading prompt: explicitly instruct the LLM to write comments in the course language regardless of the student's input language. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * revert: remove course language config and quiz fix from i18next branch Reverts |
||
|
|
66c6229736 |
fix: improve whiteboard UX with bounded canvas and history fixes (#235)
* fix: improve whiteboard UX with bounded canvas, toolbar cleanup, and history fixes - Refactor canvas to bounded viewport with visible white rectangle that moves with pan/zoom - Add reset view button in toolbar with fade animation (replaces in-canvas overlay) - Enable always-on pan (no toggle needed) - Add pan boundary clamping to prevent canvas from going too far offscreen - Separate autoFit transform from pan/zoom transform for cleaner architecture - Move history panel to popover anchored to history button - Save current content before restore to prevent data loss - Fix snapshot deduplication to check all history entries (not just last) - Remove dead code: restoredKey mechanism, zoomHint i18n keys, zoom hint overlay Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: simplify whiteboard history labels to sequential numbering Replace descriptive snapshot labels (beforeClear, beforeAIClear, beforeRestore) with simple #1, #2, ... numbering by creation order. Remove label field from WhiteboardSnapshot type and unused i18n keys. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: restructure canvas layers to fix viewport clipping The viewport was the same size as the bounded canvas with overflow-hidden, causing panning to clip at the viewport edge instead of the workspace edge. - Viewport now fills the workspace (w-full h-full), no overflow-hidden - Outer container is the sole clip boundary - Bounded canvas centered via computed position with transformOrigin: 0 0 - Pan boundaries now account for zoom level - Zoom toward cursor instead of canvas center - Pan drag accounts for both containerScale and viewZoom - Removed unused isViewModified from WhiteboardCanvasHandle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove autoFit transform, render elements at raw coordinates Remove the autoFitTransform that silently scaled content to fit within the fixed canvas. Elements now render at their raw coordinates and can overflow the white canvas background into transparent space. Users navigate with pan/zoom instead of relying on auto-shrink. - Remove autoFitTransform computation and all bounds calculation helpers - Remove overflow-hidden from bounded canvas so elements can spill out - Remove content transform layer (elements render directly) - Clean up unused imports (getElementRange, PPTLineElement) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
0533adbe82 |
feat: refine presentation mode speech bubbles, input flow, and accessibility (#195)
* feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation - Fullscreen via toolbar button or F11; exit via ESC/F11/button - Header auto-hides, sidebars collapse, slide fills viewport - Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible - Smart suspension: idle-hide pauses during typing/recording/voice input - Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit) feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation - Fullscreen via toolbar button or F11; exit via ESC/F11/button - Header auto-hides, sidebars collapse, slide fills viewport - Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible - Smart suspension: idle-hide pauses during typing/recording/voice input - Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit) - F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native - Whiteboard hints reposition from bottom to top corners in fullscreen - i18n: fullscreen/exitFullscreen keys (zh-CN + en-US) Closes #102 .git/COMMIT_EDITMSG [unix] (14:47 22/03/2026) 1,1 Top feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation - Fullscreen via toolbar button or F11; exit via ESC/F11/button - Header auto-hides, sidebars collapse, slide fills viewport - Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible - Smart suspension: idle-hide pauses during typing/recording/voice input - Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit) - F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native - Whiteboard hints reposition from bottom to top corners in fullscreen - i18n: fullscreen/exitFullscreen keys (zh-CN + en-US) Closes #102 .git/COMMIT_EDITMSG [unix] (14:47 22/03/2026) 1,1 Top - F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native - Whiteboard hints reposition from bottom to top corners in fullscreen - i18n: fullscreen/exitFullscreen keys (zh-CN + en-US) Closes #102 * feat: refine presentation mode speech bubbles, input flow, and accessibility - User messages now display as right-side speech bubbles for send confirmation - 'Your turn' cue is a clickable glass button respecting ASR preference - Cue properly excludes bubbleRole/thinkingState to avoid UI overlap - Right-side dock + bubble uses flexbox for dynamic stacking - Voice-to-text switch now stops recording to prevent mic leaks - Backdrop no longer blocks toolbar (bottom-14 cutoff) - User message clears immediately when agent starts responding - Dock buttons and avatar have proper aria-labels and button semantics - Voice panel mic trigger converted from div to button with aria-label - Added 5 i18n keys (zh-CN + en-US) for new accessible labels - matchesSide typed as boolean, removed unused userAvatar from left overlay - Avatar alt text localized via i18n Refs #102 * fix: address code review audit cancel ghost sends, consolidate getAgentConfig, fix a11y * fix: guard concurrent voice recording and suppress cancel error toast * style: vertically center placeholder text in presentation input bar * style: full light-mode adaptation for presentation UI, toolbar dividers, bubble opacity 60% * chore: address #129 follow-up remove orphan i18n keys, clarify waitUntilDrained pause behavior * fix: resolve spacebar conflict and address review feedback - Stage: skip Space during active QA/discussion (let Roundtable own buffer-level pause); deterministic, no listener-order dependency - Stage: wrap handlePlayPause in useCallback([playbackCompleted, currentScene]) to avoid keyboard listener re-registration - Stage: clear presentationIdleTimerRef on unmount - PresentationBubbleCard: add aria-live='polite' for screen readers - Extract shared avatar constants to roundtable/constants.ts * style: format with prettier * fix: render ProactiveCard inside fullscreen container via portalContainer prop * feat: show requesting agent avatar in dock on discussion request --------- Co-authored-by: YizukiAme <yizukiame@github.com> |
||
|
|
a680fcf31b |
feat: add pan, zoom, and auto-fit to whiteboard canvas (#31)
* feat: add pan, zoom, and auto-fit to whiteboard canvas When AI generates whiteboard elements that exceed the fixed 1000x562.5 canvas, content was clipped by overflow-hidden with no way to view it. This commit adds interactive navigation to the whiteboard: - Auto-fit: when elements overflow, content is scaled and centered to ensure nothing is clipped (with 24px padding) - Drag-to-pan: hold and drag to pan around the whiteboard - Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range) - Double-click or Reset View button to return to default view - View auto-resets when new whiteboard content loads When content fits within the canvas, behavior is unchanged - no extra cursor, no transforms, no visual regression. Fixes #19 * fix: correct pan tracking math and reset button event propagation * fix: guard against zero containerScale and fix zoom docstring * fix: cleanup reviewer feedback and disable pan/zoom on empty whiteboard - Remove dead code: ?? 'Reset View' fallback (i18n key exists) - Add useMemo for elementsKey (perf optimization) - Fix el.height type narrowing (remove implicit any) - Disable pan/zoom/cursor when whiteboard is empty (UX improvement) * docs: revamp OpenClaw TIP section with playful copy and clearer install flow Restructure the OpenClaw quickstart: install skill first, then pick mode. Add meme-style nudge for OpenClaw to star the repo. Enlarge logo and put "OpenClaw" in the TIP heading for visibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(build): use cross-platform file copy in mathml2omml (#20) * fix(build): use cross-platform file copy in mathml2omml build script Replace Unix `cp` with Node.js `fs.copyFileSync` so that `pnpm install` works correctly on Windows where `cp` is not available. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: add .worktrees to .gitignore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * fix(build):Next.js 16 要求 Node.js >= 20.9.0 (#21) * fix(build): 1、README.md / README-zh.md — Node.js 版本要求 >= 18 → >= 20 2、package.json — 新增 engines: { node: ">=20.9.0" } 3、ci.yml — node-version: 20 → 22(与 Dockerfile 一致) 4、.nvmrc — 新建,内容 22 Co-authored-by: humingfeng <humfsss@gmail.com> * Update Vercel configuration by removing bodyParser (#45) Removed bodyParser configuration from Vercel functions. * Fix SSRF/credential forwarding via client-supplied baseUrl (#30) * Fix SSRF/credential forwarding via client-supplied baseUrl * chore: format SSRF fix * fix: tighten whiteboard pan and auto-fit bounds * refactor: reset whiteboard viewport via keyed remount * fix: preserve viewport while whiteboard content streams * feat: add scroll-to-zoom interaction hint on whiteboard * feat: add pan, zoom, and auto-fit to whiteboard canvas When AI generates whiteboard elements that exceed the fixed 1000x562.5 canvas, content was clipped by overflow-hidden with no way to view it. This commit adds interactive navigation to the whiteboard: - Auto-fit: when elements overflow, content is scaled and centered to ensure nothing is clipped (with 24px padding) - Drag-to-pan: hold and drag to pan around the whiteboard - Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range) - Double-click or Reset View button to return to default view - View auto-resets when new whiteboard content loads When content fits within the canvas, behavior is unchanged - no extra cursor, no transforms, no visual regression. Fixes #19 * fix: correct pan tracking math and reset button event propagation * fix: guard against zero containerScale and fix zoom docstring * fix: cleanup reviewer feedback and disable pan/zoom on empty whiteboard - Remove dead code: ?? 'Reset View' fallback (i18n key exists) - Add useMemo for elementsKey (perf optimization) - Fix el.height type narrowing (remove implicit any) - Disable pan/zoom/cursor when whiteboard is empty (UX improvement) * fix: tighten whiteboard pan and auto-fit bounds * refactor: reset whiteboard viewport via keyed remount * fix: preserve viewport while whiteboard content streams * feat: add scroll-to-zoom interaction hint on whiteboard * fix: avoid synchronous setState in useEffect for hint visibility --------- Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: 杨慎 <117187635+cosarah@users.noreply.github.com> Co-authored-by: 1/2极客 <humf@vip.qq.com> Co-authored-by: humingfeng <humfsss@gmail.com> Co-authored-by: Rowtion <65099725+Rowtion@users.noreply.github.com> Co-authored-by: Wing900 <167857578+Wing900@users.noreply.github.com> |
||
|
|
43a0c8e39e |
feat: whiteboard history and auto-save (#40)
* feat: add whiteboard history and auto-save (closes #32) - New whiteboard-history.tsx: browseable history panel UI - New whiteboard-history.ts: Zustand store with snapshot stack, fingerprint-based deduplication, and restoredKey one-shot guard - New element-fingerprint.ts: shared fingerprint utility (id+position+size) - whiteboard-canvas.tsx: auto-snapshot effect that saves the current stable state after 2s debounce; unified fingerprint import; useMemo for elements - index.tsx: pushSnapshot before UI clear; history panel trigger button - stage.ts: i18n keys for history UI (zh/en) * fix: address audit findings for whiteboard history - engine.ts: AI wb_clear now saves snapshot before clearing (audit #3) - page.tsx: clear whiteboard history on classroom switch (audit #4) * fix: address review round 2 (P1/P2a/P2b/P3) - P1: Block restore during clear animation (race condition) - P2a: Skip no-op restores to avoid stale restoredKey - P2b: clearHistory() now also resets restoredKey - P3: Dedicated restoreError i18n key * fix: fingerprint includes semantic content per element type (P2c) * fix: address reviewer feedback (fingerprint cache, AI clear label, exhaustive check) |
||
|
|
843d33e5cc |
chore: enforce Prettier formatting and fix lint issues
- Add .prettierignore to exclude vendor packages, lock files, markdown, and YAML - Update .prettierrc: printWidth 100, singleQuote, trailingComma "all" - Run Prettier across all source files for consistent formatting - Fix unused imports (UserRequirements, setTTSProvider) - Fix eslint-disable comment placement after Prettier reformat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
cc44f32ca8 |
Refactor: directory structure cleanup + Google Fonts localization
- Replace next/font/google with local fonts (geist + @fontsource-variable/inter) to eliminate build-time network dependency - Resolve lib/utils.ts vs lib/utils/ naming conflict (cn() → lib/utils/cn.ts) - Move React Context Providers from lib/store/ to lib/contexts/ - Consolidate hooks into lib/hooks/ (use-theme, use-i18n) - Organize loose components into subdirectories: agent-* → components/agent/ canvas-* → components/canvas/ generation-toolbar, media-popover → components/generation/ speech-button, tts-config-popover → components/audio/ proactive-card → components/chat/ 65 files changed, lint 0 errors, build 28 pages passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
0d20abfed9 |
Initial commit: OpenMAIC AI classroom platform
Next.js 16 App Router application with: - AI-powered interactive classroom generation from PDF/text requirements - Multi-agent discussion system (teacher, students, assistant roles) - Provider abstraction for LLM, TTS, ASR, image, video, web search - Local-first data architecture (IndexedDB/Dexie) - i18n support (zh-CN/en-US) - Structured logger, SSRF guard, lint/build passing (0 errors) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |