diff --git a/CLAUDE.md b/CLAUDE.md index cfd28a4..4935aa5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,15 +93,21 @@ When adding a new agent, update all of the following: - `docs/sdk-overview.mdx` - `docs/react-components.mdx` - `docs/session-persistence.mdx` + - `docs/architecture.mdx` - `docs/deploy/local.mdx` - `docs/deploy/cloudflare.mdx` - `docs/deploy/vercel.mdx` - `docs/deploy/daytona.mdx` - `docs/deploy/e2b.mdx` - `docs/deploy/docker.mdx` + - `docs/deploy/boxlite.mdx` + - `docs/deploy/modal.mdx` + - `docs/deploy/computesdk.mdx` - `frontend/packages/website/src/components/GetStarted.tsx` - `.claude/commands/post-release-testing.md` - `examples/cloudflare/Dockerfile` + - `examples/boxlite/Dockerfile` + - `examples/boxlite-python/Dockerfile` - `examples/daytona/src/index.ts` - `examples/shared/src/docker.ts` - `examples/docker/src/index.ts` diff --git a/foundry/packages/frontend/src/components/mock-layout/message-list.tsx b/foundry/packages/frontend/src/components/mock-layout/message-list.tsx index df6d10a..499e6cd 100644 --- a/foundry/packages/frontend/src/components/mock-layout/message-list.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/message-list.tsx @@ -1,8 +1,19 @@ import { AgentTranscript as AgentTranscript_, type AgentTranscriptClassNames, type TranscriptEntry } from "@sandbox-agent/react"; - -// Cast to work around React 18/19 type incompatibility between @sandbox-agent/react and foundry -const AgentTranscript = AgentTranscript_ as unknown as (props: Record) => JSX.Element; import { memo, useEffect, useMemo, type MutableRefObject, type RefObject } from "react"; + +// Cast needed: tsup-generated .d.ts returns react_jsx_runtime.JSX.Element which +// doesn't unify with the consumer's JSX.Element under Bundler moduleResolution. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const AgentTranscript = AgentTranscript_ as any as React.FC<{ + entries: TranscriptEntry[]; + classNames?: Partial; + scrollRef?: RefObject; + scrollToEntryId?: string | null; + virtualize?: boolean; + isThinking?: boolean; + renderMessageText?: (entry: TranscriptEntry) => React.ReactNode; + renderThinkingState?: () => React.ReactNode; +}>; import { useStyletron } from "baseui"; import { LabelSmall, LabelXSmall } from "baseui/typography"; import { Copy } from "lucide-react"; @@ -156,7 +167,7 @@ export const MessageList = memo(function MessageList({ pendingMessage, }: { session: AgentSession | null | undefined; - scrollRef: RefObject; + scrollRef: RefObject; messageRefs: MutableRefObject>; historyEvents: HistoryEvent[]; onSelectHistoryEvent: (event: HistoryEvent) => void; diff --git a/frontend/packages/inspector/package.json b/frontend/packages/inspector/package.json index 45b7224..d17c3a0 100644 --- a/frontend/packages/inspector/package.json +++ b/frontend/packages/inspector/package.json @@ -14,8 +14,8 @@ "devDependencies": { "@sandbox-agent/react": "workspace:*", "sandbox-agent": "workspace:*", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", + "@types/react": "^19.1.12", + "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "^4.3.1", "fake-indexeddb": "^6.2.4", "typescript": "^5.7.3", diff --git a/frontend/packages/inspector/src/components/chat/ChatPanel.tsx b/frontend/packages/inspector/src/components/chat/ChatPanel.tsx index 5afc259..9203105 100644 --- a/frontend/packages/inspector/src/components/chat/ChatPanel.tsx +++ b/frontend/packages/inspector/src/components/chat/ChatPanel.tsx @@ -71,7 +71,7 @@ const ChatPanel = ({ agents: AgentInfo[]; agentsLoading: boolean; agentsError: string | null; - scrollRef: RefObject; + scrollRef: RefObject; agentLabel: string; modelLabel?: string | null; currentAgentVersion?: string | null; diff --git a/frontend/packages/inspector/src/components/chat/InspectorConversation.tsx b/frontend/packages/inspector/src/components/chat/InspectorConversation.tsx index 5d3c007..f14e39e 100644 --- a/frontend/packages/inspector/src/components/chat/InspectorConversation.tsx +++ b/frontend/packages/inspector/src/components/chat/InspectorConversation.tsx @@ -84,7 +84,7 @@ export interface InspectorConversationProps { entries: TranscriptEntry[]; sessionError: string | null; eventError?: string | null; - scrollRef: RefObject; + scrollRef: RefObject; onEventClick?: (eventId: string) => void; isThinking?: boolean; agentId?: string; diff --git a/package.json b/package.json index 41a699f..c10fd76 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,8 @@ }, "pnpm": { "overrides": { - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0" + "@types/react": "^19.1.12", + "@types/react-dom": "^19.1.6" } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46a59b7..8824736 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,8 +5,8 @@ settings: excludeLinksFromLockfile: false overrides: - '@types/react': ^18.3.3 - '@types/react-dom': ^18.3.0 + '@types/react': ^19.1.12 + '@types/react-dom': ^19.1.6 importers: @@ -78,11 +78,11 @@ importers: specifier: latest version: 25.5.0 '@types/react': - specifier: ^18.3.3 - version: 18.3.27 + specifier: ^19.1.12 + version: 19.1.12 '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.7(@types/react@18.3.27) + specifier: ^19.1.6 + version: 19.2.3(@types/react@19.1.12) '@vitejs/plugin-react': specifier: ^4.5.0 version: 4.7.0(vite@6.4.1(@types/node@25.5.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)) @@ -549,8 +549,8 @@ importers: version: link:../../../sdks/typescript devDependencies: '@types/react': - specifier: ^18.3.3 - version: 18.3.27 + specifier: ^19.1.12 + version: 19.1.12 tsup: specifier: ^8.5.0 version: 8.5.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) @@ -577,7 +577,7 @@ importers: version: 3.13.22(react-dom@19.2.4(react@19.2.4))(react@19.2.4) baseui: specifier: ^16.1.1 - version: 16.1.1(@types/react@18.3.27)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styletron-react@6.1.1(react@19.2.4)) + version: 16.1.1(@types/react@19.1.12)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styletron-react@6.1.1(react@19.2.4)) lucide-react: specifier: ^0.542.0 version: 0.542.0(react@19.2.4) @@ -599,19 +599,19 @@ importers: devDependencies: '@react-grab/mcp': specifier: ^0.1.13 - version: 0.1.27(@types/react@18.3.27)(react@19.2.4) + version: 0.1.27(@types/react@19.1.12)(react@19.2.4) '@types/react': - specifier: ^18.3.3 - version: 18.3.27 + specifier: ^19.1.12 + version: 19.1.12 '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.7(@types/react@18.3.27) + specifier: ^19.1.6 + version: 19.2.3(@types/react@19.1.12) '@vitejs/plugin-react': specifier: ^5.0.3 version: 5.1.4(vite@7.3.1(@types/node@25.5.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)) react-grab: specifier: ^0.1.13 - version: 0.1.27(@types/react@18.3.27)(react@19.2.4) + version: 0.1.27(@types/react@19.1.12)(react@19.2.4) tsup: specifier: ^8.5.0 version: 8.5.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) @@ -651,11 +651,11 @@ importers: specifier: workspace:* version: link:../../../sdks/react '@types/react': - specifier: ^18.3.3 - version: 18.3.27 + specifier: ^19.1.12 + version: 19.1.12 '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.7(@types/react@18.3.27) + specifier: ^19.1.6 + version: 19.2.3(@types/react@19.1.12) '@vitejs/plugin-react': specifier: ^4.3.1 version: 4.7.0(vite@5.4.21(@types/node@25.5.0)) @@ -679,7 +679,7 @@ importers: dependencies: '@astrojs/react': specifier: ^4.2.0 - version: 4.4.2(@types/node@25.5.0)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(jiti@1.21.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(tsx@4.21.0)(yaml@2.8.2) + version: 4.4.2(@types/node@25.5.0)(@types/react-dom@19.2.3(@types/react@19.1.12))(@types/react@19.1.12)(jiti@1.21.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(tsx@4.21.0)(yaml@2.8.2) '@astrojs/sitemap': specifier: ^3.2.0 version: 3.7.0 @@ -706,11 +706,11 @@ importers: version: 3.4.19(tsx@4.21.0)(yaml@2.8.2) devDependencies: '@types/react': - specifier: ^18.3.3 - version: 18.3.27 + specifier: ^19.1.12 + version: 19.1.12 '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.7(@types/react@18.3.27) + specifier: ^19.1.6 + version: 19.2.3(@types/react@19.1.12) typescript: specifier: ^5.7.0 version: 5.9.3 @@ -942,17 +942,17 @@ importers: dependencies: '@tanstack/react-virtual': specifier: ^3.13.22 - version: 3.13.22(react-dom@19.2.4(react@18.3.1))(react@18.3.1) + version: 3.13.22(react-dom@19.2.4(react@19.1.1))(react@19.1.1) ghostty-web: specifier: ^0.4.0 version: 0.4.0 devDependencies: '@types/react': - specifier: ^18.3.3 - version: 18.3.27 + specifier: ^19.1.12 + version: 19.1.12 react: - specifier: ^18.3.1 - version: 18.3.1 + specifier: ^19.1.1 + version: 19.1.1 sandbox-agent: specifier: workspace:* version: link:../typescript @@ -1083,8 +1083,8 @@ packages: resolution: {integrity: sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==} engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} peerDependencies: - '@types/react': ^18.3.3 - '@types/react-dom': ^18.3.0 + '@types/react': ^19.1.12 + '@types/react-dom': ^19.1.6 react: ^17.0.2 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.2 || ^18.0.0 || ^19.0.0 @@ -3588,21 +3588,18 @@ packages: '@types/pg@8.18.0': resolution: {integrity: sha512-gT+oueVQkqnj6ajGJXblFR4iavIXWsGAFCk3dP4Kki5+a9R4NMt0JARdk6s8cUKcfUoqP5dAtDSLU8xYUTFV+Q==} - '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - - '@types/react-dom@18.3.7': - resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: - '@types/react': ^18.3.3 + '@types/react': ^19.1.12 '@types/react-reconciler@0.28.9': resolution: {integrity: sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==} peerDependencies: - '@types/react': ^18.3.3 + '@types/react': ^19.1.12 - '@types/react@18.3.27': - resolution: {integrity: sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==} + '@types/react@19.1.12': + resolution: {integrity: sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==} '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} @@ -6076,7 +6073,7 @@ packages: react-focus-lock@2.13.7: resolution: {integrity: sha512-20lpZHEQrXPb+pp1tzd4ULL6DyO5D2KnR0G69tTDdydrmNhU7pdFmbQUYVyHUgp+xN29IuFR0PVuhOmvaZL9Og==} peerDependencies: - '@types/react': ^18.3.3 + '@types/react': ^19.1.12 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -6145,7 +6142,7 @@ packages: resolution: {integrity: sha512-tsPZ77GR0pISGYmpCLHAbZTabKXZ7zBniKPVqVMMfnXFyo39zq5g/psIlD5vLTKkjQEhWOO8JhqcHnxkwNu6eA==} engines: {node: '>=8.5.0'} peerDependencies: - '@types/react': ^18.3.3 + '@types/react': ^19.1.12 react: ^16.8.0 peerDependenciesMeta: '@types/react': @@ -6175,6 +6172,10 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + react@19.1.1: + resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + engines: {node: '>=0.10.0'} + react@19.2.4: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} @@ -6980,7 +6981,7 @@ packages: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^18.3.3 + '@types/react': ^19.1.12 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -6990,7 +6991,7 @@ packages: resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^18.3.3 + '@types/react': ^19.1.12 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -7413,10 +7414,10 @@ snapshots: dependencies: prismjs: 1.30.0 - '@astrojs/react@4.4.2(@types/node@25.5.0)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(jiti@1.21.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(tsx@4.21.0)(yaml@2.8.2)': + '@astrojs/react@4.4.2(@types/node@25.5.0)(@types/react-dom@19.2.3(@types/react@19.1.12))(@types/react@19.1.12)(jiti@1.21.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(tsx@4.21.0)(yaml@2.8.2)': dependencies: - '@types/react': 18.3.27 - '@types/react-dom': 18.3.7(@types/react@18.3.27) + '@types/react': 19.1.12 + '@types/react-dom': 19.2.3(@types/react@19.1.12) '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@25.5.0)(jiti@1.21.7)(tsx@4.21.0)(yaml@2.8.2)) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -9416,11 +9417,11 @@ snapshots: prompts: 2.4.2 smol-toml: 1.6.0 - '@react-grab/mcp@0.1.27(@types/react@18.3.27)(react@19.2.4)': + '@react-grab/mcp@0.1.27(@types/react@19.1.12)(react@19.2.4)': dependencies: '@modelcontextprotocol/sdk': 1.27.1(zod@3.25.76) fkill: 9.0.0 - react-grab: 0.1.27(@types/react@18.3.27)(react@19.2.4) + react-grab: 0.1.27(@types/react@19.1.12)(react@19.2.4) zod: 3.25.76 transitivePeerDependencies: - '@cfworker/json-schema' @@ -10033,11 +10034,11 @@ snapshots: react-dom: 19.2.4(react@19.2.4) use-sync-external-store: 1.6.0(react@19.2.4) - '@tanstack/react-virtual@3.13.22(react-dom@19.2.4(react@18.3.1))(react@18.3.1)': + '@tanstack/react-virtual@3.13.22(react-dom@19.2.4(react@19.1.1))(react@19.1.1)': dependencies: '@tanstack/virtual-core': 3.13.22 - react: 18.3.1 - react-dom: 19.2.4(react@18.3.1) + react: 19.1.1 + react-dom: 19.2.4(react@19.1.1) '@tanstack/react-virtual@3.13.22(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: @@ -10154,19 +10155,16 @@ snapshots: pg-protocol: 1.11.0 pg-types: 2.2.0 - '@types/prop-types@15.7.15': {} - - '@types/react-dom@18.3.7(@types/react@18.3.27)': + '@types/react-dom@19.2.3(@types/react@19.1.12)': dependencies: - '@types/react': 18.3.27 + '@types/react': 19.1.12 - '@types/react-reconciler@0.28.9(@types/react@18.3.27)': + '@types/react-reconciler@0.28.9(@types/react@19.1.12)': dependencies: - '@types/react': 18.3.27 + '@types/react': 19.1.12 - '@types/react@18.3.27': + '@types/react@19.1.12': dependencies: - '@types/prop-types': 15.7.15 csstype: 3.2.3 '@types/retry@0.12.2': {} @@ -10523,7 +10521,7 @@ snapshots: baseline-browser-mapping@2.9.18: {} - baseui@16.1.1(@types/react@18.3.27)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styletron-react@6.1.1(react@19.2.4)): + baseui@16.1.1(@types/react@19.1.12)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styletron-react@6.1.1(react@19.2.4)): dependencies: '@date-io/date-fns': 2.17.0(date-fns@2.30.0) '@date-io/moment': 2.17.0(moment@2.30.1) @@ -10543,7 +10541,7 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) react-dropzone: 9.0.0(react@19.2.4) - react-focus-lock: 2.13.7(@types/react@18.3.27)(react@19.2.4) + react-focus-lock: 2.13.7(@types/react@19.1.12)(react@19.2.4) react-hook-form: 7.71.2(react@19.2.4) react-input-mask: 2.0.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react-is: 17.0.2 @@ -10551,7 +10549,7 @@ snapshots: react-movable: 3.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react-multi-ref: 1.0.2 react-range: 1.10.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react-uid: 2.3.0(@types/react@18.3.27)(react@19.2.4) + react-uid: 2.3.0(@types/react@19.1.12)(react@19.2.4) react-virtualized: 9.22.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react-virtualized-auto-sizer: 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react-window: 1.8.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -10615,9 +10613,9 @@ snapshots: dependencies: file-uri-to-path: 1.0.0 - bippy@0.5.32(@types/react@18.3.27)(react@19.2.4): + bippy@0.5.32(@types/react@19.1.12)(react@19.2.4): dependencies: - '@types/react-reconciler': 0.28.9(@types/react@18.3.27) + '@types/react-reconciler': 0.28.9(@types/react@19.1.12) react: 19.2.4 transitivePeerDependencies: - '@types/react' @@ -13009,9 +13007,9 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-dom@19.2.4(react@18.3.1): + react-dom@19.2.4(react@19.1.1): dependencies: - react: 18.3.1 + react: 19.1.1 scheduler: 0.27.0 react-dom@19.2.4(react@19.2.4): @@ -13027,23 +13025,23 @@ snapshots: prop-types-extra: 1.1.1(react@19.2.4) react: 19.2.4 - react-focus-lock@2.13.7(@types/react@18.3.27)(react@19.2.4): + react-focus-lock@2.13.7(@types/react@19.1.12)(react@19.2.4): dependencies: '@babel/runtime': 7.28.6 focus-lock: 1.3.6 prop-types: 15.8.1 react: 19.2.4 react-clientside-effect: 1.2.8(react@19.2.4) - use-callback-ref: 1.3.3(@types/react@18.3.27)(react@19.2.4) - use-sidecar: 1.1.3(@types/react@18.3.27)(react@19.2.4) + use-callback-ref: 1.3.3(@types/react@19.1.12)(react@19.2.4) + use-sidecar: 1.1.3(@types/react@19.1.12)(react@19.2.4) optionalDependencies: - '@types/react': 18.3.27 + '@types/react': 19.1.12 - react-grab@0.1.27(@types/react@18.3.27)(react@19.2.4): + react-grab@0.1.27(@types/react@19.1.12)(react@19.2.4): dependencies: '@medv/finder': 4.0.2 '@react-grab/cli': 0.1.27 - bippy: 0.5.32(@types/react@18.3.27)(react@19.2.4) + bippy: 0.5.32(@types/react@19.1.12)(react@19.2.4) solid-js: 1.9.11 optionalDependencies: react: 19.2.4 @@ -13097,12 +13095,12 @@ snapshots: react-refresh@0.18.0: {} - react-uid@2.3.0(@types/react@18.3.27)(react@19.2.4): + react-uid@2.3.0(@types/react@19.1.12)(react@19.2.4): dependencies: react: 19.2.4 tslib: 1.14.1 optionalDependencies: - '@types/react': 18.3.27 + '@types/react': 19.1.12 react-virtualized-auto-sizer@1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: @@ -13131,6 +13129,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + react@19.1.1: {} + react@19.2.4: {} read-cache@1.0.0: @@ -14068,20 +14068,20 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - use-callback-ref@1.3.3(@types/react@18.3.27)(react@19.2.4): + use-callback-ref@1.3.3(@types/react@19.1.12)(react@19.2.4): dependencies: react: 19.2.4 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.27 + '@types/react': 19.1.12 - use-sidecar@1.1.3(@types/react@18.3.27)(react@19.2.4): + use-sidecar@1.1.3(@types/react@19.1.12)(react@19.2.4): dependencies: detect-node-es: 1.1.0 react: 19.2.4 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.27 + '@types/react': 19.1.12 use-sync-external-store@1.6.0(react@19.2.4): dependencies: diff --git a/scripts/release/update_version.ts b/scripts/release/update_version.ts index d603156..9d39beb 100644 --- a/scripts/release/update_version.ts +++ b/scripts/release/update_version.ts @@ -2,6 +2,7 @@ import * as fs from "node:fs/promises"; import { join } from "node:path"; import { $ } from "execa"; import { glob } from "glob"; +import * as semver from "semver"; import type { ReleaseOpts } from "./main"; function assert(condition: any, message?: string): asserts condition { @@ -10,13 +11,56 @@ function assert(condition: any, message?: string): asserts condition { } } +// Files containing version references that need channel/image tag updates. +// Keep in sync with CLAUDE.md "Install Version References" section. +const VERSION_REFERENCE_FILES = [ + "README.md", + "docs/acp-http-client.mdx", + "docs/cli.mdx", + "docs/quickstart.mdx", + "docs/sdk-overview.mdx", + "docs/react-components.mdx", + "docs/session-persistence.mdx", + "docs/architecture.mdx", + "docs/deploy/local.mdx", + "docs/deploy/cloudflare.mdx", + "docs/deploy/vercel.mdx", + "docs/deploy/daytona.mdx", + "docs/deploy/e2b.mdx", + "docs/deploy/docker.mdx", + "docs/deploy/boxlite.mdx", + "docs/deploy/modal.mdx", + "docs/deploy/computesdk.mdx", + "frontend/packages/website/src/components/GetStarted.tsx", + ".claude/commands/post-release-testing.md", + "examples/cloudflare/Dockerfile", + "examples/boxlite/Dockerfile", + "examples/boxlite-python/Dockerfile", + "examples/daytona/src/index.ts", + "examples/shared/src/docker.ts", + "examples/docker/src/index.ts", + "examples/e2b/src/index.ts", + "examples/vercel/src/index.ts", + "sdks/typescript/src/providers/shared.ts", + "scripts/release/main.ts", + "scripts/release/promote-artifacts.ts", + "scripts/release/sdk.ts", + "scripts/sandbox-testing/test-sandbox.ts", +]; + export async function updateVersion(opts: ReleaseOpts) { - // 1. Update workspace version and internal crate versions in root Cargo.toml + // 1. Read current version from Cargo.toml before overwriting const cargoTomlPath = join(opts.root, "Cargo.toml"); let cargoContent = await fs.readFile(cargoTomlPath, "utf-8"); + const oldVersionMatch = cargoContent.match(/\[workspace\.package\]\nversion = "([^"]+)"/); + assert(oldVersionMatch, "Could not find workspace.package version in Cargo.toml"); + const oldVersion = oldVersionMatch[1]; + const oldParsed = semver.parse(oldVersion); + assert(oldParsed, `Could not parse old version: ${oldVersion}`); + const oldMinorChannel = `${oldParsed.major}.${oldParsed.minor}.x`; + // Update [workspace.package] version - assert(/\[workspace\.package\]\nversion = ".*"/.test(cargoContent), "Could not find workspace.package version in Cargo.toml"); cargoContent = cargoContent.replace(/\[workspace\.package\]\nversion = ".*"/, `[workspace.package]\nversion = "${opts.version}"`); // Discover internal crates from [workspace.dependencies] by matching @@ -69,4 +113,70 @@ export async function updateVersion(opts: ReleaseOpts) { await fs.writeFile(fullPath, updated); await $({ cwd: opts.root })`git add ${relPath}`; } + + // 3. Update version references across docs, examples, and code + await updateVersionReferences(opts, oldVersion, oldMinorChannel); +} + +async function updateVersionReferences(opts: ReleaseOpts, oldVersion: string, oldMinorChannel: string) { + const newMinorChannel = opts.minorVersionChannel; + + // Find old Docker image tags by scanning for rivetdev/sandbox-agent:-full patterns + // The old version might be a different patch or RC, so we match any version-full tag + const oldDockerTagPattern = /rivetdev\/sandbox-agent:([0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9.]+)?)-full/; + + console.log(`\nUpdating version references:`); + console.log(` Old minor channel: ${oldMinorChannel}`); + console.log(` New minor channel: ${newMinorChannel}`); + console.log(` New Docker tag: ${opts.version}-full`); + + const modifiedFiles: string[] = []; + + for (const relPath of VERSION_REFERENCE_FILES) { + const fullPath = join(opts.root, relPath); + + let content: string; + try { + content = await fs.readFile(fullPath, "utf-8"); + } catch (err: any) { + if (err.code === "ENOENT") { + console.log(` ⚠️ Skipping ${relPath} (file not found)`); + continue; + } + throw err; + } + + const original = content; + + // Replace minor channel references (e.g. sandbox-agent@0.3.x -> sandbox-agent@0.4.x) + content = content.replaceAll(`sandbox-agent@${oldMinorChannel}`, `sandbox-agent@${newMinorChannel}`); + content = content.replaceAll(`@sandbox-agent/cli@${oldMinorChannel}`, `@sandbox-agent/cli@${newMinorChannel}`); + content = content.replaceAll(`@sandbox-agent/react@${oldMinorChannel}`, `@sandbox-agent/react@${newMinorChannel}`); + + // Replace install script URL channel + content = content.replaceAll(`releases.rivet.dev/sandbox-agent/${oldMinorChannel}/`, `releases.rivet.dev/sandbox-agent/${newMinorChannel}/`); + + // Replace Docker image tags (rivetdev/sandbox-agent:-full -> rivetdev/sandbox-agent:-full) + content = content.replaceAll( + new RegExp(`rivetdev/sandbox-agent:[0-9]+\\.[0-9]+\\.[0-9]+(?:-[a-zA-Z0-9.]+)?-full`, "g"), + `rivetdev/sandbox-agent:${opts.version}-full`, + ); + + // Replace standalone version-full references in prose (e.g. "The `0.3.2-full` tag pins...") + // Match backtick-wrapped version-full patterns + content = content.replaceAll(new RegExp("`[0-9]+\\.[0-9]+\\.[0-9]+(?:-[a-zA-Z0-9.]+)?-full`", "g"), `\`${opts.version}-full\``); + + if (content !== original) { + await fs.writeFile(fullPath, content); + modifiedFiles.push(relPath); + console.log(` ✅ ${relPath}`); + } + } + + if (modifiedFiles.length > 0) { + await $({ cwd: opts.root })`git add ${modifiedFiles}`; + console.log(`\nUpdated ${modifiedFiles.length} files with version references.`); + } else { + console.log(`\nNo version reference files needed updates.`); + } } diff --git a/sdks/react/package.json b/sdks/react/package.json index 6bc21ec..b82892a 100644 --- a/sdks/react/package.json +++ b/sdks/react/package.json @@ -24,7 +24,7 @@ "typecheck": "tsc --noEmit" }, "peerDependencies": { - "react": "^18.3.1", + "react": "^18.3.1 || ^19.0.0", "sandbox-agent": "^0.2.2" }, "dependencies": { @@ -32,8 +32,8 @@ "ghostty-web": "^0.4.0" }, "devDependencies": { - "@types/react": "^18.3.3", - "react": "^18.3.1", + "@types/react": "^19.1.12", + "react": "^19.1.1", "sandbox-agent": "workspace:*", "tsup": "^8.0.0", "typescript": "^5.7.0" diff --git a/sdks/react/src/AgentConversation.tsx b/sdks/react/src/AgentConversation.tsx index acc9466..44dd0de 100644 --- a/sdks/react/src/AgentConversation.tsx +++ b/sdks/react/src/AgentConversation.tsx @@ -18,7 +18,7 @@ export interface AgentConversationProps { emptyState?: ReactNode; transcriptClassName?: string; transcriptClassNames?: Partial; - scrollRef?: RefObject; + scrollRef?: RefObject; composerClassName?: string; composerClassNames?: Partial; transcriptProps?: Omit; diff --git a/sdks/react/src/AgentTranscript.tsx b/sdks/react/src/AgentTranscript.tsx index b565081..03fa2dc 100644 --- a/sdks/react/src/AgentTranscript.tsx +++ b/sdks/react/src/AgentTranscript.tsx @@ -98,8 +98,8 @@ export interface AgentTranscriptProps { entries: TranscriptEntry[]; className?: string; classNames?: Partial; - endRef?: RefObject; - scrollRef?: RefObject; + endRef?: RefObject; + scrollRef?: RefObject; scrollToEntryId?: string | null; sessionError?: string | null; eventError?: string | null; diff --git a/sdks/react/src/useTranscriptVirtualizer.ts b/sdks/react/src/useTranscriptVirtualizer.ts index dc52717..a90d75f 100644 --- a/sdks/react/src/useTranscriptVirtualizer.ts +++ b/sdks/react/src/useTranscriptVirtualizer.ts @@ -4,7 +4,7 @@ import type { RefObject } from "react"; import { useEffect, useRef } from "react"; import { useVirtualizer } from "@tanstack/react-virtual"; -export function useTranscriptVirtualizer(items: T[], scrollElementRef?: RefObject, onAtBottomChange?: (atBottom: boolean) => void) { +export function useTranscriptVirtualizer(items: T[], scrollElementRef?: RefObject, onAtBottomChange?: (atBottom: boolean) => void) { const isFollowingRef = useRef(true); const virtualizer = useVirtualizer({ diff --git a/server/packages/agent-management/src/agents.rs b/server/packages/agent-management/src/agents.rs index 1ea051c..fa7e243 100644 --- a/server/packages/agent-management/src/agents.rs +++ b/server/packages/agent-management/src/agents.rs @@ -1090,9 +1090,9 @@ fn write_mock_agent_process_launcher(path: &Path) -> Result<(), AgentError> { fs::create_dir_all(parent)?; } let script = if cfg!(windows) { - "@echo off\r\necho mock agent process is in-process in sandbox-agent\r\nexit /b 1\r\n" + "@echo off\r\nsandbox-agent mock-agent-process %*\r\n" } else { - "#!/usr/bin/env sh\necho 'mock agent process is in-process in sandbox-agent'\nexit 1\n" + "#!/usr/bin/env sh\nexec sandbox-agent mock-agent-process \"$@\"\n" }; write_text_file(path, script) } diff --git a/server/packages/sandbox-agent/src/cli.rs b/server/packages/sandbox-agent/src/cli.rs index 1c12e4b..51757b6 100644 --- a/server/packages/sandbox-agent/src/cli.rs +++ b/server/packages/sandbox-agent/src/cli.rs @@ -83,6 +83,9 @@ pub enum Command { InstallAgent(InstallAgentArgs), /// Inspect locally discovered credentials. Credentials(CredentialsArgs), + /// Internal: stdio JSON-RPC echo agent for the mock agent process. + #[command(hide = true)] + MockAgentProcess, } #[derive(Args, Debug)] @@ -406,6 +409,7 @@ pub fn run_command(command: &Command, cli: &CliConfig) -> Result<(), CliError> { Command::Daemon(subcommand) => run_daemon(&subcommand.command, cli), Command::InstallAgent(args) => install_agent_local(args), Command::Credentials(subcommand) => run_credentials(&subcommand.command), + Command::MockAgentProcess => run_mock_agent_process(), } } @@ -929,6 +933,71 @@ fn run_credentials(command: &CredentialsCommand) -> Result<(), CliError> { } } +fn run_mock_agent_process() -> Result<(), CliError> { + use std::io::BufRead; + + let stdin = std::io::stdin(); + let reader = stdin.lock(); + + for line in reader.lines() { + let line = line.map_err(|e| CliError::Server(format!("stdin read error: {}", e)))?; + if line.trim().is_empty() { + continue; + } + + let msg: Value = match serde_json::from_str(&line) { + Ok(v) => v, + Err(e) => { + let err_notification = json!({ + "jsonrpc": "2.0", + "method": "mock/parse_error", + "params": { + "error": e.to_string(), + "raw": line, + } + }); + write_stdout_line(&serde_json::to_string(&err_notification)?)?; + continue; + } + }; + + // Echo notification for every message + let echo = json!({ + "jsonrpc": "2.0", + "method": "mock/echo", + "params": { "message": msg } + }); + write_stdout_line(&serde_json::to_string(&echo)?)?; + + let has_method = msg.get("method").and_then(|v| v.as_str()).is_some(); + let has_id = msg.get("id").is_some(); + + if has_method && has_id { + // Request -> respond with echo result + let response = json!({ + "jsonrpc": "2.0", + "id": msg["id"], + "result": { "echoed": msg } + }); + write_stdout_line(&serde_json::to_string(&response)?)?; + } else if !has_method && has_id { + // Client response + let notification = json!({ + "jsonrpc": "2.0", + "method": "mock/client_response", + "params": { + "id": msg["id"], + "result": msg.get("result").unwrap_or(&Value::Null), + "error": msg.get("error").unwrap_or(&Value::Null), + } + }); + write_stdout_line(&serde_json::to_string(¬ification)?)?; + } + } + + Ok(()) +} + fn load_json_payload( json_inline: Option<&str>, json_file: Option<&std::path::Path>,