raysurfer 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- raysurfer-0.2.2/.github/workflows/ci.yml +38 -0
- raysurfer-0.2.2/.gitignore +27 -0
- raysurfer-0.2.2/CLAUDE.md +217 -0
- raysurfer-0.2.2/PKG-INFO +130 -0
- raysurfer-0.2.2/README.md +102 -0
- raysurfer-0.2.2/demo/before_after_comparison.md +135 -0
- raysurfer-0.2.2/demo/cache_speedup_demo.py +173 -0
- raysurfer-0.2.2/demo/real_comparison_test.py +221 -0
- raysurfer-0.2.2/demo/test_variety.py +199 -0
- raysurfer-0.2.2/examples/README.md +68 -0
- raysurfer-0.2.2/examples/email-agent/.env.example +20 -0
- raysurfer-0.2.2/examples/email-agent/.gitignore +136 -0
- raysurfer-0.2.2/examples/email-agent/.releaserc.json +51 -0
- raysurfer-0.2.2/examples/email-agent/ACTIONS_SPEC.md +1334 -0
- raysurfer-0.2.2/examples/email-agent/CHANGELOG.md +38 -0
- raysurfer-0.2.2/examples/email-agent/CLAUDE.md +2 -0
- raysurfer-0.2.2/examples/email-agent/LISTENERS_SPEC.md +1443 -0
- raysurfer-0.2.2/examples/email-agent/README.md +92 -0
- raysurfer-0.2.2/examples/email-agent/README_LISTENER.md +213 -0
- raysurfer-0.2.2/examples/email-agent/UI_STATE_COMPONENTS_SPEC.md +1049 -0
- raysurfer-0.2.2/examples/email-agent/UI_STATE_SYSTEM.md +338 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/agents/inbox-searcher.md +424 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/action-creator/SKILL.md +360 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/action-creator/templates/archive-old-newsletters.ts +93 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/action-creator/templates/forward-bug-report.ts +143 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/action-creator/templates/send-payment-reminder.ts +92 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/listener-creator/SKILL.md +303 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/listener-creator/templates/ai-classifier.ts +100 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/listener-creator/templates/auto-archive.ts +49 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/listener-creator/templates/package-tracker.ts +101 -0
- raysurfer-0.2.2/examples/email-agent/agent/.claude/skills/listener-creator/templates/urgent-watcher.ts +72 -0
- raysurfer-0.2.2/examples/email-agent/agent/CLAUDE.MD +48 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/add-expense.ts +117 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/add-income.ts +102 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/archive-old-newsletters.ts +71 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/create-task.ts +106 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/forward-bugs-to-engineering.ts +132 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/label-urgent-customer-support.ts +97 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/actions/update-task-status.ts +92 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/listeners/.gitkeep +0 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/listeners/example-listener.ts +129 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/listeners/finance-email-labeler.ts +100 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/listeners/finance-email-tracker.ts +180 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/listeners/todo-extractor.ts +140 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/types.ts +421 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/ui-states/financial-dashboard.ts +53 -0
- raysurfer-0.2.2/examples/email-agent/agent/custom_scripts/ui-states/task-board.ts +42 -0
- raysurfer-0.2.2/examples/email-agent/agent/data/PROFILE.MD +1 -0
- raysurfer-0.2.2/examples/email-agent/agent/email-api.d.ts +197 -0
- raysurfer-0.2.2/examples/email-agent/agent/email-api.ts +200 -0
- raysurfer-0.2.2/examples/email-agent/architecture.png +0 -0
- raysurfer-0.2.2/examples/email-agent/bun.lock +1592 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/actions-manager.ts +229 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/ai-client.ts +114 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/component-manager.ts +193 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/custom-tools.ts +170 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/email-agent-prompt.ts +36 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/listeners-manager.ts +518 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/log-writer.ts +142 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/message-queue.ts +48 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/session.ts +207 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/types.ts +32 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/ui-state-manager.ts +257 -0
- raysurfer-0.2.2/examples/email-agent/ccsdk/websocket-handler.ts +666 -0
- raysurfer-0.2.2/examples/email-agent/client/App.tsx +161 -0
- raysurfer-0.2.2/examples/email-agent/client/components/ActionButton.tsx +43 -0
- raysurfer-0.2.2/examples/email-agent/client/components/ActiveListenersPanel.tsx +206 -0
- raysurfer-0.2.2/examples/email-agent/client/components/ChatInterface.tsx +246 -0
- raysurfer-0.2.2/examples/email-agent/client/components/EmailDisplay.tsx +303 -0
- raysurfer-0.2.2/examples/email-agent/client/components/EmailHTMLRenderer.tsx +136 -0
- raysurfer-0.2.2/examples/email-agent/client/components/EmailViewer.tsx +166 -0
- raysurfer-0.2.2/examples/email-agent/client/components/InboxView.tsx +180 -0
- raysurfer-0.2.2/examples/email-agent/client/components/ListenerDisplay.tsx +163 -0
- raysurfer-0.2.2/examples/email-agent/client/components/ScreenshotModeToggle.tsx +43 -0
- raysurfer-0.2.2/examples/email-agent/client/components/TabNavigation.tsx +46 -0
- raysurfer-0.2.2/examples/email-agent/client/components/custom/ComponentRegistry.ts +54 -0
- raysurfer-0.2.2/examples/email-agent/client/components/custom/FinancialDashboard.tsx +249 -0
- raysurfer-0.2.2/examples/email-agent/client/components/custom/TaskBoard.tsx +167 -0
- raysurfer-0.2.2/examples/email-agent/client/components/message/AssistantMessage.tsx +514 -0
- raysurfer-0.2.2/examples/email-agent/client/components/message/ComponentRenderer.tsx +142 -0
- raysurfer-0.2.2/examples/email-agent/client/components/message/MessageRenderer.tsx +41 -0
- raysurfer-0.2.2/examples/email-agent/client/components/message/SystemMessage.tsx +58 -0
- raysurfer-0.2.2/examples/email-agent/client/components/message/UserMessage.tsx +60 -0
- raysurfer-0.2.2/examples/email-agent/client/components/message/types.ts +103 -0
- raysurfer-0.2.2/examples/email-agent/client/components/views/FinancialDashboardView.tsx +107 -0
- raysurfer-0.2.2/examples/email-agent/client/components/views/TaskBoardView.tsx +109 -0
- raysurfer-0.2.2/examples/email-agent/client/context/ScreenshotModeContext.tsx +32 -0
- raysurfer-0.2.2/examples/email-agent/client/globals.css +244 -0
- raysurfer-0.2.2/examples/email-agent/client/hooks/useComponentTabs.tsx +36 -0
- raysurfer-0.2.2/examples/email-agent/client/hooks/useListenerLogs.ts +120 -0
- raysurfer-0.2.2/examples/email-agent/client/hooks/useListeners.ts +69 -0
- raysurfer-0.2.2/examples/email-agent/client/hooks/useUIState.ts +169 -0
- raysurfer-0.2.2/examples/email-agent/client/hooks/useWebSocket.ts +132 -0
- raysurfer-0.2.2/examples/email-agent/client/index.html +13 -0
- raysurfer-0.2.2/examples/email-agent/client/index.tsx +9 -0
- raysurfer-0.2.2/examples/email-agent/client/store/screenshotMode.ts +3 -0
- raysurfer-0.2.2/examples/email-agent/client/utils/placeholders.ts +68 -0
- raysurfer-0.2.2/examples/email-agent/database/config.ts +11 -0
- raysurfer-0.2.2/examples/email-agent/database/database-manager.ts +845 -0
- raysurfer-0.2.2/examples/email-agent/database/email-db.ts +538 -0
- raysurfer-0.2.2/examples/email-agent/database/email-search.ts +296 -0
- raysurfer-0.2.2/examples/email-agent/database/email-sync.ts +389 -0
- raysurfer-0.2.2/examples/email-agent/database/imap-manager.ts +723 -0
- raysurfer-0.2.2/examples/email-agent/database/migrations/README.md +52 -0
- raysurfer-0.2.2/examples/email-agent/database/migrations/add-imap-uid.sql +12 -0
- raysurfer-0.2.2/examples/email-agent/database/migrations/add-ui-state-tables.sql +43 -0
- raysurfer-0.2.2/examples/email-agent/database/schema.sql +237 -0
- raysurfer-0.2.2/examples/email-agent/package-lock.json +9609 -0
- raysurfer-0.2.2/examples/email-agent/package.json +81 -0
- raysurfer-0.2.2/examples/email-agent/recursive-code-generation.md +178 -0
- raysurfer-0.2.2/examples/email-agent/requirements.txt +4 -0
- raysurfer-0.2.2/examples/email-agent/server/endpoints/emails.ts +301 -0
- raysurfer-0.2.2/examples/email-agent/server/endpoints/index.ts +11 -0
- raysurfer-0.2.2/examples/email-agent/server/endpoints/listeners.ts +105 -0
- raysurfer-0.2.2/examples/email-agent/server/endpoints/sync.ts +139 -0
- raysurfer-0.2.2/examples/email-agent/server/endpoints/ui-states.ts +292 -0
- raysurfer-0.2.2/examples/email-agent/server/index.ts +6 -0
- raysurfer-0.2.2/examples/email-agent/server/server.ts +342 -0
- raysurfer-0.2.2/examples/email-agent/tailwind.config.js +53 -0
- raysurfer-0.2.2/examples/email-agent/tsconfig.json +33 -0
- raysurfer-0.2.2/examples/excel-demo/.editorconfig +12 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/.eslintrc +7 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.base.ts +54 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.eslint.ts +3 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.main.dev.ts +63 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.main.prod.ts +83 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.preload.dev.ts +71 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.renderer.dev.dll.ts +77 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.renderer.dev.ts +214 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.config.renderer.prod.ts +147 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/configs/webpack.paths.ts +42 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/img/erb-banner.svg +32 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/img/erb-logo.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/img/palette-sponsor-banner.svg +6 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/mocks/fileMock.js +1 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/.eslintrc +8 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/check-build-exists.ts +34 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/check-native-dep.ts +54 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/check-node-env.js +16 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/check-port-in-use.js +16 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/clean.js +13 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/delete-source-maps.js +15 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/electron-rebuild.js +20 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/link-modules.ts +14 -0
- raysurfer-0.2.2/examples/excel-demo/.erb/scripts/notarize.js +38 -0
- raysurfer-0.2.2/examples/excel-demo/.eslintignore +33 -0
- raysurfer-0.2.2/examples/excel-demo/.eslintrc.js +37 -0
- raysurfer-0.2.2/examples/excel-demo/.gitattributes +12 -0
- raysurfer-0.2.2/examples/excel-demo/.gitignore +33 -0
- raysurfer-0.2.2/examples/excel-demo/LICENSE +21 -0
- raysurfer-0.2.2/examples/excel-demo/README.md +121 -0
- raysurfer-0.2.2/examples/excel-demo/agent/.claude/skills/xlsx/LICENSE.txt +30 -0
- raysurfer-0.2.2/examples/excel-demo/agent/.claude/skills/xlsx/SKILL.md +289 -0
- raysurfer-0.2.2/examples/excel-demo/agent/.claude/skills/xlsx/recalc.py +178 -0
- raysurfer-0.2.2/examples/excel-demo/agent/CLAUDE.MD +60 -0
- raysurfer-0.2.2/examples/excel-demo/agent/README.md +85 -0
- raysurfer-0.2.2/examples/excel-demo/agent/requirements.txt +2 -0
- raysurfer-0.2.2/examples/excel-demo/assets/assets.d.ts +35 -0
- raysurfer-0.2.2/examples/excel-demo/assets/entitlements.mac.plist +8 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icon.icns +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icon.ico +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icon.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icon.svg +23 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/1024x1024.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/128x128.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/16x16.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/24x24.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/256x256.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/32x32.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/48x48.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/512x512.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/64x64.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/assets/icons/96x96.png +0 -0
- raysurfer-0.2.2/examples/excel-demo/package.json +275 -0
- raysurfer-0.2.2/examples/excel-demo/postcss.config.js +6 -0
- raysurfer-0.2.2/examples/excel-demo/release/app/package.json +18 -0
- raysurfer-0.2.2/examples/excel-demo/src/__tests__/App.test.tsx +9 -0
- raysurfer-0.2.2/examples/excel-demo/src/main/main.ts +363 -0
- raysurfer-0.2.2/examples/excel-demo/src/main/menu.ts +290 -0
- raysurfer-0.2.2/examples/excel-demo/src/main/preload.ts +37 -0
- raysurfer-0.2.2/examples/excel-demo/src/main/util.ts +13 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/App.css +72 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/App.tsx +13 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/ChatInterface.tsx +211 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/Message.tsx +216 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/MessageInput.tsx +323 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/MessageList.tsx +68 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/ThinkingDisplay.tsx +55 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/TodoListDisplay.tsx +120 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/ToolUseDisplay.tsx +87 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/types.ts +39 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/utils/todoDetection.ts +73 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/components/utils/toolMetadata.ts +233 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/index.ejs +14 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/index.tsx +13 -0
- raysurfer-0.2.2/examples/excel-demo/src/renderer/preload.d.ts +10 -0
- raysurfer-0.2.2/examples/excel-demo/tailwind.config.js +11 -0
- raysurfer-0.2.2/examples/excel-demo/tsconfig.json +18 -0
- raysurfer-0.2.2/examples/hello-world/README.md +151 -0
- raysurfer-0.2.2/examples/hello-world/hello-world.ts +69 -0
- raysurfer-0.2.2/examples/hello-world/package-lock.json +782 -0
- raysurfer-0.2.2/examples/hello-world/package.json +11 -0
- raysurfer-0.2.2/examples/hello-world/tsconfig.json +12 -0
- raysurfer-0.2.2/examples/hello-world-v2/README.md +36 -0
- raysurfer-0.2.2/examples/hello-world-v2/package.json +15 -0
- raysurfer-0.2.2/examples/hello-world-v2/tsconfig.json +13 -0
- raysurfer-0.2.2/examples/hello-world-v2/v2-examples.ts +128 -0
- raysurfer-0.2.2/examples/research-agent/.claude/commands/competitive-analysis.md +54 -0
- raysurfer-0.2.2/examples/research-agent/.claude/commands/fact-check.md +65 -0
- raysurfer-0.2.2/examples/research-agent/.claude/commands/market-trends.md +64 -0
- raysurfer-0.2.2/examples/research-agent/.claude/commands/research.md +37 -0
- raysurfer-0.2.2/examples/research-agent/.claude/commands/summarize.md +46 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/executive-briefing/SKILL.md +100 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/FORMS.md +205 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/LICENSE.txt +21 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/REFERENCE.md +225 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/SKILL.md +294 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/check_bounding_boxes.py +69 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/check_bounding_boxes_test.py +227 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/check_fillable_fields.py +12 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/convert_pdf_to_images.py +34 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/create_validation_image.py +40 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/extract_form_field_info.py +151 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/fill_fillable_fields.py +112 -0
- raysurfer-0.2.2/examples/research-agent/.claude/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- raysurfer-0.2.2/examples/research-agent/.env.example +1 -0
- raysurfer-0.2.2/examples/research-agent/.gitignore +59 -0
- raysurfer-0.2.2/examples/research-agent/README.md +110 -0
- raysurfer-0.2.2/examples/research-agent/pyproject.toml +16 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/agent.py +162 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/prompts/data_analyst.txt +216 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/prompts/lead_agent.txt +177 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/prompts/report_writer.txt +112 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/prompts/researcher.txt +179 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/utils/message_handler.py +52 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/utils/subagent_tracker.py +276 -0
- raysurfer-0.2.2/examples/research-agent/research_agent/utils/transcript.py +60 -0
- raysurfer-0.2.2/examples/resume-generator/.claude/skills/docx/SKILL.md +197 -0
- raysurfer-0.2.2/examples/resume-generator/.claude/skills/docx/docx-js.md +350 -0
- raysurfer-0.2.2/examples/resume-generator/.gitignore +5 -0
- raysurfer-0.2.2/examples/resume-generator/README.md +27 -0
- raysurfer-0.2.2/examples/resume-generator/package.json +17 -0
- raysurfer-0.2.2/examples/resume-generator/resume-generator.ts +97 -0
- raysurfer-0.2.2/examples/simple-chatapp/.gitignore +27 -0
- raysurfer-0.2.2/examples/simple-chatapp/CLAUDE.md +81 -0
- raysurfer-0.2.2/examples/simple-chatapp/README.md +46 -0
- raysurfer-0.2.2/examples/simple-chatapp/client/App.tsx +208 -0
- raysurfer-0.2.2/examples/simple-chatapp/client/components/ChatList.tsx +82 -0
- raysurfer-0.2.2/examples/simple-chatapp/client/components/ChatWindow.tsx +185 -0
- raysurfer-0.2.2/examples/simple-chatapp/client/globals.css +3 -0
- raysurfer-0.2.2/examples/simple-chatapp/client/index.html +12 -0
- raysurfer-0.2.2/examples/simple-chatapp/client/index.tsx +10 -0
- raysurfer-0.2.2/examples/simple-chatapp/demo.gif +0 -0
- raysurfer-0.2.2/examples/simple-chatapp/diagram.png +0 -0
- raysurfer-0.2.2/examples/simple-chatapp/package-lock.json +5312 -0
- raysurfer-0.2.2/examples/simple-chatapp/package.json +41 -0
- raysurfer-0.2.2/examples/simple-chatapp/postcss.config.js +6 -0
- raysurfer-0.2.2/examples/simple-chatapp/server/ai-client.ts +107 -0
- raysurfer-0.2.2/examples/simple-chatapp/server/chat-store.ts +81 -0
- raysurfer-0.2.2/examples/simple-chatapp/server/server.ts +165 -0
- raysurfer-0.2.2/examples/simple-chatapp/server/session.ts +143 -0
- raysurfer-0.2.2/examples/simple-chatapp/server/types.ts +38 -0
- raysurfer-0.2.2/examples/simple-chatapp/tailwind.config.js +8 -0
- raysurfer-0.2.2/examples/simple-chatapp/tsconfig.json +16 -0
- raysurfer-0.2.2/examples/simple-chatapp/vite.config.ts +19 -0
- raysurfer-0.2.2/github_trending.py +88 -0
- raysurfer-0.2.2/pyproject.toml +57 -0
- raysurfer-0.2.2/src/raysurfer/__init__.py +55 -0
- raysurfer-0.2.2/src/raysurfer/client.py +564 -0
- raysurfer-0.2.2/src/raysurfer/exceptions.py +21 -0
- raysurfer-0.2.2/src/raysurfer/sdk_client.py +432 -0
- raysurfer-0.2.2/src/raysurfer/sdk_types.py +30 -0
- raysurfer-0.2.2/src/raysurfer/types.py +191 -0
- raysurfer-0.2.2/tests/__init__.py +1 -0
- raysurfer-0.2.2/tests/conftest.py +215 -0
- raysurfer-0.2.2/tests/test_cache_hits.py +535 -0
- raysurfer-0.2.2/tests/test_client.py +702 -0
- raysurfer-0.2.2/tests/test_sdk_client.py +790 -0
- raysurfer-0.2.2/uv.lock +955 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Setup Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v4
|
|
28
|
+
with:
|
|
29
|
+
version: latest
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv pip install -e ".[dev]" --system
|
|
33
|
+
|
|
34
|
+
- name: Run linter
|
|
35
|
+
run: uv run ruff check .
|
|
36
|
+
|
|
37
|
+
- name: Run tests
|
|
38
|
+
run: uv run pytest tests/ -v --tb=short
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
build/
|
|
7
|
+
develop-eggs/
|
|
8
|
+
dist/
|
|
9
|
+
downloads/
|
|
10
|
+
eggs/
|
|
11
|
+
.eggs/
|
|
12
|
+
lib/
|
|
13
|
+
lib64/
|
|
14
|
+
parts/
|
|
15
|
+
sdist/
|
|
16
|
+
var/
|
|
17
|
+
wheels/
|
|
18
|
+
*.egg-info/
|
|
19
|
+
.installed.cfg
|
|
20
|
+
*.egg
|
|
21
|
+
.env
|
|
22
|
+
.venv
|
|
23
|
+
env/
|
|
24
|
+
venv/
|
|
25
|
+
.pytest_cache/
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
.mypy_cache/
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Raysurfer Python SDK
|
|
2
|
+
|
|
3
|
+
Python SDK for Raysurfer - code block caching and retrieval for AI agents with Claude Agent SDK integration.
|
|
4
|
+
|
|
5
|
+
## Project Goal
|
|
6
|
+
|
|
7
|
+
**Make AI agents 20-30x faster by reusing cached code instead of regenerating it every time.**
|
|
8
|
+
|
|
9
|
+
The problem: When an AI agent encounters a task like "fetch GitHub user data", it typically:
|
|
10
|
+
1. Thinks about the approach (2-5s)
|
|
11
|
+
2. Generates code from scratch (5-15s)
|
|
12
|
+
3. Writes the file (0.5s)
|
|
13
|
+
4. Runs and iterates (variable)
|
|
14
|
+
|
|
15
|
+
This happens **every single time**, even for identical or similar tasks.
|
|
16
|
+
|
|
17
|
+
The solution: RaySurfer caches proven code blocks and retrieves them via semantic search:
|
|
18
|
+
1. Check cache for matching code (50-200ms)
|
|
19
|
+
2. If hit: return ready-to-run code instantly
|
|
20
|
+
3. If miss: generate with agent, then cache for next time
|
|
21
|
+
|
|
22
|
+
**Measured Results:**
|
|
23
|
+
- Without RaySurfer: 34.2s, 11 iterations, 2 tool calls
|
|
24
|
+
- With RaySurfer: 1.4s, 1 iteration, 0 tool calls
|
|
25
|
+
- **Speedup: 24x faster**
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
|
|
29
|
+
- **Backend**: FastAPI on Railway, uses Pinecone for vector storage, Fireworks for embeddings
|
|
30
|
+
- **SDK**: This Python package - async/sync clients for store/retrieve operations
|
|
31
|
+
- **Integration**: Drop-in enhancement for Claude Agent SDK workflows
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install raysurfer
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### Basic Client (Store/Retrieve Code Blocks)
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from raysurfer import AsyncRaySurfer
|
|
45
|
+
|
|
46
|
+
async with AsyncRaySurfer(api_key="rs_...") as client:
|
|
47
|
+
# Store a code block
|
|
48
|
+
result = await client.store_code_block(
|
|
49
|
+
name="GitHub User Fetcher",
|
|
50
|
+
source="def fetch_user(username): ...",
|
|
51
|
+
entrypoint="fetch_user",
|
|
52
|
+
language="python",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Retrieve code blocks for a task
|
|
56
|
+
response = await client.retrieve(task="Fetch GitHub user data")
|
|
57
|
+
for match in response.code_blocks:
|
|
58
|
+
print(match.code_block.name, match.verdict_score)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Claude Agent SDK Integration
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from raysurfer import RaysurferClient, RaysurferAgentOptions
|
|
65
|
+
|
|
66
|
+
options = RaysurferAgentOptions(
|
|
67
|
+
raysurfer_api_key="rs_...",
|
|
68
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
69
|
+
system_prompt="You are a helpful assistant.",
|
|
70
|
+
model="claude-opus-4-5", # Default
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
async with RaysurferClient(options=options) as client:
|
|
74
|
+
# Pre-fetches code files, downloads to sandbox, injects into prompt
|
|
75
|
+
await client.query("Fetch user data from GitHub API")
|
|
76
|
+
|
|
77
|
+
# Agent sees code files in system prompt and can execute with Bash
|
|
78
|
+
async for msg in client.receive_response():
|
|
79
|
+
print(msg)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## RaysurferAgentOptions
|
|
83
|
+
|
|
84
|
+
Drop-in replacement options for `ClaudeAgentOptions` with Raysurfer-specific settings:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
@dataclass
|
|
88
|
+
class RaysurferAgentOptions:
|
|
89
|
+
# Raysurfer-specific
|
|
90
|
+
raysurfer_api_key: str | None = None
|
|
91
|
+
raysurfer_base_url: str = "https://api.raysurfer.com"
|
|
92
|
+
prefetch_count: int = 5
|
|
93
|
+
min_verdict_score: float = 0.3
|
|
94
|
+
prefer_complete: bool = True
|
|
95
|
+
sandbox_dir: Path = ~/.raysurfer/sandbox
|
|
96
|
+
|
|
97
|
+
# Standard ClaudeAgentOptions (all passed through)
|
|
98
|
+
allowed_tools: list[str] | None = None
|
|
99
|
+
model: str = "claude-opus-4-5"
|
|
100
|
+
system_prompt: str | dict | None = None
|
|
101
|
+
sandbox: dict | None = None
|
|
102
|
+
# ... all other ClaudeAgentOptions fields
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## How It Works
|
|
106
|
+
|
|
107
|
+
1. **On `query()`**: RaysurferClient calls the backend to get relevant code files
|
|
108
|
+
2. **Downloads to sandbox**: Files are written to `~/.raysurfer/sandbox/`
|
|
109
|
+
3. **Injects into prompt**: Code snippets are added to the system prompt
|
|
110
|
+
4. **Agent executes**: Agent can run the code using the Bash tool within the sandbox
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
# Claude Agent SDK Python Reference
|
|
115
|
+
|
|
116
|
+
## Core Classes
|
|
117
|
+
|
|
118
|
+
### `ClaudeSDKClient`
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
async with ClaudeSDKClient(options=options) as client:
|
|
122
|
+
await client.query("Hello Claude")
|
|
123
|
+
async for message in client.receive_response():
|
|
124
|
+
print(message)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `ClaudeAgentOptions`
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
ClaudeAgentOptions(
|
|
131
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
132
|
+
disallowed_tools=[],
|
|
133
|
+
permission_mode="acceptEdits", # or "default", "plan", "bypassPermissions"
|
|
134
|
+
system_prompt="You are helpful.",
|
|
135
|
+
model="claude-opus-4-5",
|
|
136
|
+
cwd="/path/to/project",
|
|
137
|
+
sandbox={"enabled": True},
|
|
138
|
+
max_turns=10,
|
|
139
|
+
# ... more options
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Key parameters:
|
|
144
|
+
- `allowed_tools`: Tools the agent can use
|
|
145
|
+
- `permission_mode`: How permissions are handled
|
|
146
|
+
- `model`: Claude model to use
|
|
147
|
+
- `sandbox`: Enable sandboxed execution
|
|
148
|
+
- `setting_sources`: `["user", "project", "local"]` to load CLAUDE.md files
|
|
149
|
+
|
|
150
|
+
### `SandboxSettings`
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
sandbox={
|
|
154
|
+
"enabled": True,
|
|
155
|
+
"autoAllowBashIfSandboxed": True,
|
|
156
|
+
"excludedCommands": ["docker"],
|
|
157
|
+
"network": {
|
|
158
|
+
"allowLocalBinding": True,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Message Types
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from claude_agent_sdk import (
|
|
167
|
+
AssistantMessage,
|
|
168
|
+
TextBlock,
|
|
169
|
+
ToolUseBlock,
|
|
170
|
+
ResultMessage,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
async for message in client.receive_response():
|
|
174
|
+
if isinstance(message, AssistantMessage):
|
|
175
|
+
for block in message.content:
|
|
176
|
+
if isinstance(block, TextBlock):
|
|
177
|
+
print(block.text)
|
|
178
|
+
elif isinstance(block, ToolUseBlock):
|
|
179
|
+
print(f"Using tool: {block.name}")
|
|
180
|
+
elif isinstance(message, ResultMessage):
|
|
181
|
+
print(f"Done! Cost: ${message.total_cost_usd}")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Custom Tools
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from claude_agent_sdk import tool, create_sdk_mcp_server
|
|
188
|
+
|
|
189
|
+
@tool("greet", "Greet a user", {"name": str})
|
|
190
|
+
async def greet(args):
|
|
191
|
+
return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}
|
|
192
|
+
|
|
193
|
+
server = create_sdk_mcp_server("my-tools", tools=[greet])
|
|
194
|
+
|
|
195
|
+
options = ClaudeAgentOptions(
|
|
196
|
+
mcp_servers={"tools": server},
|
|
197
|
+
allowed_tools=["mcp__tools__greet"],
|
|
198
|
+
)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Error Handling
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from claude_agent_sdk import (
|
|
205
|
+
CLINotFoundError,
|
|
206
|
+
ProcessError,
|
|
207
|
+
CLIConnectionError,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
async for message in query(prompt="Hello"):
|
|
212
|
+
print(message)
|
|
213
|
+
except CLINotFoundError:
|
|
214
|
+
print("Install Claude Code: npm install -g @anthropic-ai/claude-code")
|
|
215
|
+
except ProcessError as e:
|
|
216
|
+
print(f"Process failed: {e.exit_code}")
|
|
217
|
+
```
|
raysurfer-0.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: raysurfer
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Python SDK for RaySurfer - code block caching and retrieval for AI agents with Claude Agent SDK integration
|
|
5
|
+
Project-URL: Homepage, https://raysurfer.com
|
|
6
|
+
Project-URL: Repository, https://github.com/raymondxu/raysurfer-python
|
|
7
|
+
Author: Raymond Xu
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: agents,ai,anthropic,claude,code-blocks,embeddings,retrieval
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: claude-agent-sdk>=0.1.0
|
|
20
|
+
Requires-Dist: httpx>=0.25.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# RaySurfer Python SDK
|
|
30
|
+
|
|
31
|
+
Drop-in replacement for Claude Agent SDK with automatic code caching. Same API, 20-30x faster.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install raysurfer
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
Swap `ClaudeSDKClient` for `RaysurferClient` - everything else stays the same:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
# from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
|
|
45
|
+
from raysurfer import RaysurferClient, RaysurferAgentOptions
|
|
46
|
+
|
|
47
|
+
options = RaysurferAgentOptions(
|
|
48
|
+
raysurfer_api_key="your-api-key",
|
|
49
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
50
|
+
model="claude-sonnet-4-20250514",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# async with ClaudeSDKClient(options) as client:
|
|
54
|
+
async with RaysurferClient(options) as client:
|
|
55
|
+
await client.query("Generate quarterly sales report")
|
|
56
|
+
async for msg in client.receive_response():
|
|
57
|
+
print(msg)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
That's it. Your agent now automatically:
|
|
61
|
+
- Pre-fetches relevant cached code before each task
|
|
62
|
+
- Injects proven code snippets into the system prompt
|
|
63
|
+
- Stores successful outputs for future reuse
|
|
64
|
+
|
|
65
|
+
## How It Works
|
|
66
|
+
|
|
67
|
+
1. **On `query()`**: Retrieves cached code blocks matching your task
|
|
68
|
+
2. **Downloads to sandbox**: Files ready for the agent to execute
|
|
69
|
+
3. **Injects into prompt**: Agent sees proven code snippets
|
|
70
|
+
4. **After success**: New code is cached for next time
|
|
71
|
+
|
|
72
|
+
**Measured Results:**
|
|
73
|
+
- Without RaySurfer: 34.2s, 11 iterations, 2 tool calls
|
|
74
|
+
- With RaySurfer: 1.4s, 1 iteration, 0 tool calls
|
|
75
|
+
- **Speedup: 24x faster**
|
|
76
|
+
|
|
77
|
+
## RaysurferAgentOptions
|
|
78
|
+
|
|
79
|
+
All `ClaudeAgentOptions` fields are supported, plus:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
RaysurferAgentOptions(
|
|
83
|
+
# Raysurfer-specific
|
|
84
|
+
raysurfer_api_key="your-api-key",
|
|
85
|
+
prefetch_count=5, # Code files to pre-fetch
|
|
86
|
+
min_verdict_score=0.3, # Quality threshold
|
|
87
|
+
|
|
88
|
+
# Standard Claude Agent SDK options
|
|
89
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
90
|
+
model="claude-sonnet-4-20250514",
|
|
91
|
+
system_prompt="You are helpful.",
|
|
92
|
+
permission_mode="acceptEdits",
|
|
93
|
+
# ... all other ClaudeAgentOptions
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Low-Level API
|
|
98
|
+
|
|
99
|
+
For direct code block storage and retrieval:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from raysurfer import RaySurfer
|
|
103
|
+
|
|
104
|
+
rs = RaySurfer(api_key="your-api-key")
|
|
105
|
+
|
|
106
|
+
# Store a code block
|
|
107
|
+
rs.store_code_block(
|
|
108
|
+
name="fetch_weather",
|
|
109
|
+
source="def fetch_weather(city): ...",
|
|
110
|
+
entrypoint="fetch_weather",
|
|
111
|
+
language="python",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Retrieve by task
|
|
115
|
+
results = rs.retrieve("get weather data")
|
|
116
|
+
for match in results.code_blocks:
|
|
117
|
+
print(f"{match.code_block.name}: {match.score}")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Verdict System
|
|
121
|
+
|
|
122
|
+
RaySurfer learns which code actually works through thumbs up/down verdicts:
|
|
123
|
+
- A technical error can be thumbs up (correct validation)
|
|
124
|
+
- A successful run can be thumbs down (useless output)
|
|
125
|
+
|
|
126
|
+
The system learns usefulness, not just whether code runs.
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
See [examples/](./examples) for complete demos.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# RaySurfer Python SDK
|
|
2
|
+
|
|
3
|
+
Drop-in replacement for Claude Agent SDK with automatic code caching. Same API, 20-30x faster.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install raysurfer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Swap `ClaudeSDKClient` for `RaysurferClient` - everything else stays the same:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
# from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
|
|
17
|
+
from raysurfer import RaysurferClient, RaysurferAgentOptions
|
|
18
|
+
|
|
19
|
+
options = RaysurferAgentOptions(
|
|
20
|
+
raysurfer_api_key="your-api-key",
|
|
21
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
22
|
+
model="claude-sonnet-4-20250514",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# async with ClaudeSDKClient(options) as client:
|
|
26
|
+
async with RaysurferClient(options) as client:
|
|
27
|
+
await client.query("Generate quarterly sales report")
|
|
28
|
+
async for msg in client.receive_response():
|
|
29
|
+
print(msg)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
That's it. Your agent now automatically:
|
|
33
|
+
- Pre-fetches relevant cached code before each task
|
|
34
|
+
- Injects proven code snippets into the system prompt
|
|
35
|
+
- Stores successful outputs for future reuse
|
|
36
|
+
|
|
37
|
+
## How It Works
|
|
38
|
+
|
|
39
|
+
1. **On `query()`**: Retrieves cached code blocks matching your task
|
|
40
|
+
2. **Downloads to sandbox**: Files ready for the agent to execute
|
|
41
|
+
3. **Injects into prompt**: Agent sees proven code snippets
|
|
42
|
+
4. **After success**: New code is cached for next time
|
|
43
|
+
|
|
44
|
+
**Measured Results:**
|
|
45
|
+
- Without RaySurfer: 34.2s, 11 iterations, 2 tool calls
|
|
46
|
+
- With RaySurfer: 1.4s, 1 iteration, 0 tool calls
|
|
47
|
+
- **Speedup: 24x faster**
|
|
48
|
+
|
|
49
|
+
## RaysurferAgentOptions
|
|
50
|
+
|
|
51
|
+
All `ClaudeAgentOptions` fields are supported, plus:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
RaysurferAgentOptions(
|
|
55
|
+
# Raysurfer-specific
|
|
56
|
+
raysurfer_api_key="your-api-key",
|
|
57
|
+
prefetch_count=5, # Code files to pre-fetch
|
|
58
|
+
min_verdict_score=0.3, # Quality threshold
|
|
59
|
+
|
|
60
|
+
# Standard Claude Agent SDK options
|
|
61
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
62
|
+
model="claude-sonnet-4-20250514",
|
|
63
|
+
system_prompt="You are helpful.",
|
|
64
|
+
permission_mode="acceptEdits",
|
|
65
|
+
# ... all other ClaudeAgentOptions
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Low-Level API
|
|
70
|
+
|
|
71
|
+
For direct code block storage and retrieval:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from raysurfer import RaySurfer
|
|
75
|
+
|
|
76
|
+
rs = RaySurfer(api_key="your-api-key")
|
|
77
|
+
|
|
78
|
+
# Store a code block
|
|
79
|
+
rs.store_code_block(
|
|
80
|
+
name="fetch_weather",
|
|
81
|
+
source="def fetch_weather(city): ...",
|
|
82
|
+
entrypoint="fetch_weather",
|
|
83
|
+
language="python",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Retrieve by task
|
|
87
|
+
results = rs.retrieve("get weather data")
|
|
88
|
+
for match in results.code_blocks:
|
|
89
|
+
print(f"{match.code_block.name}: {match.score}")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Verdict System
|
|
93
|
+
|
|
94
|
+
RaySurfer learns which code actually works through thumbs up/down verdicts:
|
|
95
|
+
- A technical error can be thumbs up (correct validation)
|
|
96
|
+
- A successful run can be thumbs down (useless output)
|
|
97
|
+
|
|
98
|
+
The system learns usefulness, not just whether code runs.
|
|
99
|
+
|
|
100
|
+
## Examples
|
|
101
|
+
|
|
102
|
+
See [examples/](./examples) for complete demos.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# RaySurfer: Before & After
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Every time an AI agent encounters a common task, it regenerates code from scratch:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
User: "Fetch my GitHub profile"
|
|
9
|
+
|
|
10
|
+
🐌 WITHOUT RAYSURFER:
|
|
11
|
+
├── Agent thinks... (2s)
|
|
12
|
+
├── Claude generates code... (5s)
|
|
13
|
+
├── Agent writes file... (0.5s)
|
|
14
|
+
├── Agent runs code... (1s)
|
|
15
|
+
└── Total: ~8.5 seconds + 1,500 tokens ($0.05)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## The Solution
|
|
19
|
+
|
|
20
|
+
RaySurfer caches proven code and retrieves it instantly:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
User: "Fetch my GitHub profile"
|
|
24
|
+
|
|
25
|
+
⚡ WITH RAYSURFER:
|
|
26
|
+
├── Semantic search for matching code... (100ms)
|
|
27
|
+
├── Return cached, tested code... (50ms)
|
|
28
|
+
├── Agent runs code... (1s)
|
|
29
|
+
└── Total: ~1.2 seconds + 0 tokens ($0.0001)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Code Comparison
|
|
35
|
+
|
|
36
|
+
### ❌ Before: Manual Agent Code
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from anthropic import Anthropic
|
|
40
|
+
|
|
41
|
+
client = Anthropic()
|
|
42
|
+
|
|
43
|
+
def run_agent(task: str):
|
|
44
|
+
"""Agent regenerates code every single time."""
|
|
45
|
+
response = client.messages.create(
|
|
46
|
+
model="claude-sonnet-4-20250514",
|
|
47
|
+
messages=[{"role": "user", "content": task}],
|
|
48
|
+
# Agent generates fresh code each time
|
|
49
|
+
# Even for tasks it's done 100 times before
|
|
50
|
+
)
|
|
51
|
+
return response.content[0].text
|
|
52
|
+
|
|
53
|
+
# Every call = new tokens, new latency, inconsistent output
|
|
54
|
+
result = run_agent("fetch github user octocat")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Problems:**
|
|
58
|
+
- 3-10 seconds per generation
|
|
59
|
+
- 500-2000 tokens consumed each time
|
|
60
|
+
- Code quality varies run-to-run
|
|
61
|
+
- No learning from past successes
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### ✅ After: RaySurfer-Powered Agent
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from raysurfer import RaySurfer
|
|
69
|
+
|
|
70
|
+
rs = RaySurfer()
|
|
71
|
+
|
|
72
|
+
def run_agent(task: str):
|
|
73
|
+
"""Agent retrieves proven code instantly."""
|
|
74
|
+
# Check cache first - 50ms
|
|
75
|
+
result = rs.retrieve_best(task)
|
|
76
|
+
|
|
77
|
+
if result.best_match and result.retrieval_confidence > 0.7:
|
|
78
|
+
# Cache hit! Return proven code instantly
|
|
79
|
+
return result.best_match.code_block.source
|
|
80
|
+
|
|
81
|
+
# Cache miss - generate new code and store it
|
|
82
|
+
code = generate_with_llm(task)
|
|
83
|
+
rs.store_code_block(
|
|
84
|
+
name=task[:50],
|
|
85
|
+
source=code,
|
|
86
|
+
entrypoint="main",
|
|
87
|
+
language="python"
|
|
88
|
+
)
|
|
89
|
+
return code
|
|
90
|
+
|
|
91
|
+
# First call: generates + caches
|
|
92
|
+
# All future calls: instant retrieval
|
|
93
|
+
result = run_agent("fetch github user octocat")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Benefits:**
|
|
97
|
+
- 50-200ms retrieval (30x faster)
|
|
98
|
+
- Zero tokens for cache hits
|
|
99
|
+
- Consistent, proven code quality
|
|
100
|
+
- Learns which code works via verdicts
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Integration: 3 Lines of Code
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# Before
|
|
108
|
+
response = claude.generate(task)
|
|
109
|
+
|
|
110
|
+
# After
|
|
111
|
+
from raysurfer import RaySurfer
|
|
112
|
+
rs = RaySurfer()
|
|
113
|
+
cached = rs.retrieve_best(task)
|
|
114
|
+
response = cached.best_match.code_block.source if cached.best_match else claude.generate(task)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Real Numbers
|
|
120
|
+
|
|
121
|
+
| Metric | Without RaySurfer | With RaySurfer | Improvement |
|
|
122
|
+
|--------|-------------------|----------------|-------------|
|
|
123
|
+
| Latency | 5,000ms | 150ms | **33x faster** |
|
|
124
|
+
| Tokens | 1,200 | 0 | **100% saved** |
|
|
125
|
+
| Cost | $0.04 | $0.0001 | **400x cheaper** |
|
|
126
|
+
| Consistency | Variable | Proven | **Reliable** |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Try It Now
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install raysurfer
|
|
134
|
+
python -c "from raysurfer import RaySurfer; print('Ready!')"
|
|
135
|
+
```
|