8.2 KiB
Developer Guide
This guide collects day-to-day recipes and reference commands for contributors working on the Nxtscape browser-agent monorepo.
Project bootstrap
# Install all dependencies
yarn
# Start webpack in watch-mode for local development
yarn dev
# Run the full Jest test-suite
yarn test
# Check linting errors
yarn lint
BAML workflow 🛠️
The codebase uses BAML to describe LLM prompts and automatically generate a type-safe client. All BAML-related files live under src/baml_src and the generated SDK is placed in src/baml_client.
Initialise a BAML project
Run the following once when bootstrapping or after cloning the repository:
npx baml-cli init --dest ./src/
• Creates src/baml_src with example .baml specs.
• Adds starter configuration files suited for TypeScript projects.
Regenerate the client
Whenever you modify or add a .baml file, regenerate the SDK:
npx baml-cli generate --from ./src/baml_src/
• Scans every .baml spec under src/baml_src.
• Produces an up-to-date, fully-typed client in src/baml_client.
• Use --no-version-check to skip the online version check when offline.
Note: The generated code is committed to the repository so CI and external consumers do not need BAML installed.
Typical dev loop
- Edit or create a
.bamlspec insidesrc/baml_src. - Run the
generatecommand shown above (consider aliasing it in a local script). - Import the generated function:
import { MyPrompt } from '@/baml_client'
- Call the prompt as you would any other function and enjoy end-to-end type safety!
Useful NPM scripts
| Script | Purpose |
|---|---|
yarn dev |
Run webpack in watch-mode |
yarn build |
Production build |
yarn test |
Execute Jest test-suite |
yarn test:watch |
Re-run tests on file changes |
yarn lint |
Lint the entire codebase |
Coding conventions
The project follows the rules in .cursorrules and the extended "Custom Instructions" section at the root of the repository. That document covers formatting, naming, accessibility, state management and more.
Always run yarn lint (or enable your editor ESLint integration) before committing.
Troubleshooting
• BAML version mismatch – pass --no-version-check to baml-cli generate or bump @boundaryml/baml in package.json.
• Types out of sync – run the generate command; if the problem persists, clean the src/baml_client folder and regenerate.
Happy hacking! 🧑💻
Development Guide
VS Code Debugging Setup
This project includes a comprehensive debugging setup for Chrome extension development. You can set breakpoints in any TypeScript file and debug the extension running in Chrome.
Quick Start
- Open VS Code in the project directory
- Set a breakpoint in any file (e.g.,
src/background/index.tsline 45) - Press F5 or select "🚀 Debug Extension (One-Click)" from the debug dropdown
- Wait for build - VS Code will automatically build the extension first
- Chrome launches with the extension loaded
- Trigger your breakpoint - interact with the extension to hit the breakpoint
Debugging Different Contexts
Chrome extensions run in multiple contexts. After launching the main debug configuration, you can debug different parts:
Background Script (Service Worker)
- File:
src/background/index.ts - Debug Config: "Debug Background Script (Service Worker)"
- Triggers: Extension initialization, message handling, tab events
// Example: Set breakpoint in src/background/index.ts
function handlePortMessage(message: PortMessage, port: chrome.runtime.Port): void {
debugger; // Or set breakpoint here
const { type, payload, id } = message
// Your breakpoint will hit when messages are received
}
Options Page
- Files:
src/options/Options.tsx,src/options/components/* - Debug Config: "Debug Extension Pages (Options)"
- Triggers: Opening options page, clicking buttons, form submissions
// Example: Set breakpoint in src/options/Options.tsx
const handleSubmit = async (e: React.FormEvent): Promise<void> => {
debugger; // Or set breakpoint here
e.preventDefault()
// Your breakpoint will hit when submitting tasks
}
Content Scripts
- Files:
src/content/index.ts - Debug Config: "Debug Content Scripts (Web Pages)"
- Triggers: Loading web pages, DOM interactions
Browser Automation
- Files:
src/lib/langchainbrowser/NxtscapeBrowserContext.ts,src/lib/langchainbrowser/NxtscapePage.ts - Debug Config: "Debug Background Script (Service Worker)"
- Triggers: Running examples, browser automation tasks
// Example: Debug puppeteer-core initialization
async function initializeBrowser() {
LogUtility.log('NxtscapeBrowserContext', 'DEV_MODE detected, enabling verbose logging');
LogUtility.log('NxtscapeBrowserContext', 'Initializing puppeteer-core connection');
try {
const browser = await connect({
transport: await ExtensionTransport.connectTab(tabId),
defaultViewport: null,
protocol: 'cdp'
});
LogUtility.log('NxtscapeBrowserContext', `Successfully connected to tab ${tabId}`);
} catch (error) {
LogUtility.log('NxtscapeBrowserContext', `Connection failed: ${error}`, 'error');
}
}
Common Debugging Scenarios
1. Debug Task Execution
// src/background/index.ts - handleExecuteQueryPort()
async function handleExecuteQueryPort(payload: { query: string }, port: chrome.runtime.Port, id?: string) {
debugger; // Breakpoint 1: When task starts
const { query } = payload
// Execute the query directly with NxtScape
await nxtScape.initialize()
debugger; // Breakpoint 2: After NxtScape initialization
const result = await nxtScape.run(query)
debugger; // Breakpoint 3: After task completion
}
2. Debug UI Interactions
// src/options/Options.tsx - handleRunExample()
const handleRunExample = async (): Promise<void> => {
debugger; // Breakpoint: When "Run Example" is clicked
try {
setIsSubmitting(true)
startExecution()
// ... rest of function
}
}
3. Debug Log Routing
// src/lib/utilities/LogUtility.ts - log()
public static log(source: string, message: string, level: LogLevel = 'info'): void {
debugger; // Breakpoint: Every log message passes through here
// See how logs are routed to options page
}
Debugging Tips
- Source Maps: Breakpoints work in original TypeScript files, not the bundled JavaScript
- Multiple Contexts: You may need multiple debug sessions for different extension parts
- Console Access: Use browser dev tools console for additional debugging
- Network Tab: Check network requests in Chrome dev tools
- Extension Pages: Right-click extension pages → "Inspect" for dev tools
Troubleshooting
Breakpoints Not Hitting
- Check source maps: Make sure
npm run build:devgenerated.mapfiles - Verify paths: Source map paths in launch.json should match webpack output
- Chrome restart: Sometimes Chrome needs restart for debugging changes
Build Errors
- Clean build: Run
npm run clean && npm run build:dev - Dependencies: Run
npm installif packages are missing - TypeScript errors: Fix any TS errors before debugging
Chrome Issues
- Port 9222: Make sure no other Chrome instance is using port 9222
- Extension reload: Reload extension in
chrome://extensions/after code changes - Profile conflicts: Delete
.chrome-debug-profile/if debugging fails
Development Workflow
- Code changes → F5 (debug) → Test in Chrome → Fix issues → Repeat
- Set breakpoints before triggering the functionality you want to debug
- Use multiple debug sessions for different extension contexts
- Check logs in options page for real-time debugging info (when
DEV_MODE: true)
Configuration Files
.vscode/launch.json: VS Code debug configurations.vscode/tasks.json: Build tasks (pre-launch)webpack.config.js: Source map generationsrc/config.ts: DEV_MODE and logging settings