Skip to content

Latest commit

 

History

History
527 lines (422 loc) · 11.5 KB

File metadata and controls

527 lines (422 loc) · 11.5 KB

Integration Guide: Using RuntimeUI in Your App

Option 1: Quick Test (Recommended)

Step 1: Create a Test File

Create test-app.tsx in your existing React app:

import React, { useState } from 'react';
import {
  RuntimeEngine,
  Locked,
  Protected,
  AIModifiable,
} from '../RuntimeUI/src/index';

// Your existing components - add decorators
@Locked
class YourPaymentComponent extends React.Component {
  // Your existing payment logic
  render() {
    return <div>Payment Form (Locked)</div>;
  }
}

@Protected({
  allowedOperations: ['update-style'],
  maxSize: 50,
})
class YourHeader extends React.Component {
  render() {
    return <header>My App Header</header>;
  }
}

@AIModifiable({
  maxSize: 300,
  dataAccess: {
    canReadData: true,
    canWriteData: false,
  },
})
class YourDashboard extends React.Component {
  render() {
    return (
      <div>
        <h2>Dashboard</h2>
        <p>This can be modified by AI</p>
      </div>
    );
  }
}

// Test component
export function TestRuntimeUI() {
  const [engine] = useState(
    () =>
      new RuntimeEngine({
        maxTokens: 4000,
        maxComponents: 10,
        maxLinesPerComponent: 200,
      })
  );

  const [testResult, setTestResult] = useState<any>(null);

  const runTest = async () => {
    // Test 1: Valid modification (should succeed)
    const test1 = await engine.processModification({
      userQuery: 'Make dashboard cards bigger',
      generatedCode: `
        import React from 'react';

        export class YourDashboard extends React.Component {
          render() {
            return (
              <div style={{ padding: '40px' }}>
                <h2>Dashboard</h2>
                <p>Cards are now bigger!</p>
              </div>
            );
          }
        }
      `,
    });

    // Test 2: Try to modify locked component (should fail)
    const test2 = await engine.processModification({
      userQuery: 'Modify payment',
      generatedCode: `
        class YourPaymentComponent {
          // This should be blocked
        }
      `,
    });

    setTestResult({
      test1: {
        success: test1.success,
        errors: test1.validation.errors,
      },
      test2: {
        success: test2.success,
        errors: test2.validation.errors,
      },
    });
  };

  return (
    <div>
      <h1>RuntimeUI Test</h1>
      <button onClick={runTest}>Run Tests</button>

      {testResult && (
        <div>
          <h3>Test 1 (Valid modification): {testResult.test1.success ? '✓ PASS' : '✗ FAIL'}</h3>
          {testResult.test1.errors.length > 0 && <pre>{JSON.stringify(testResult.test1.errors, null, 2)}</pre>}

          <h3>Test 2 (Locked component): {!testResult.test2.success ? '✓ PASS' : '✗ FAIL'}</h3>
          <pre>{JSON.stringify(testResult.test2.errors, null, 2)}</pre>
        </div>
      )}

      <div style={{ marginTop: '40px' }}>
        <YourPaymentComponent />
        <YourHeader />
        <YourDashboard />
      </div>
    </div>
  );
}

Step 2: Import in Your App

// In your main App.tsx or index.tsx
import { TestRuntimeUI } from './test-app';

function App() {
  return (
    <div>
      <TestRuntimeUI />
    </div>
  );
}

Option 2: Install as Local Package

Step 1: Build RuntimeUI

cd /Users/xinqizhang/Desktop/RuntimeUI
npm install
npm run build

Step 2: Link to Your App

# In RuntimeUI directory
npm link

# In your app directory
npm link runtime-ui-framework

Step 3: Use in Your App

import { RuntimeEngine, Locked, AIModifiable } from 'runtime-ui-framework';

// Use as shown above

Option 3: Copy Source Directly

Step 1: Copy src folder

cp -r /Users/xinqizhang/Desktop/RuntimeUI/src /path/to/your/app/src/runtime-ui

Step 2: Import directly

import { RuntimeEngine, Locked } from './runtime-ui';

Real-World Integration Example

Protecting Your Existing App

// 1. Identify critical components
// --------------------------------

// Critical business logic → @Locked
@Locked
class CheckoutFlow extends React.Component { }

@Locked
class AuthenticationProvider extends React.Component { }

@Locked
class PaymentGateway extends React.Component { }


// 2. Identify semi-critical components
// -------------------------------------

// Can style but not change structure → @Protected
@Protected({ allowedOperations: ['update-style', 'update-props'] })
class NavigationBar extends React.Component { }

@Protected({ allowedOperations: ['update-style'] })
class Footer extends React.Component { }


// 3. Identify customizable components
// ------------------------------------

// User-facing, safe to modify → @AIModifiable
@AIModifiable({
  maxSize: 400,
  dataAccess: {
    canReadData: true,
    canWriteData: false,
    allowedEndpoints: ['/api/user-preferences', '/api/products']
  }
})
class ProductGrid extends React.Component { }

@AIModifiable({ maxSize: 300 })
class UserDashboard extends React.Component { }

@AIModifiable({ maxSize: 200 })
class WidgetCard extends React.Component { }


// 4. Set up Runtime Engine
// -------------------------

const engine = new RuntimeEngine({
  maxTokens: 4000,
  maxComponents: 8,
  maxLinesPerComponent: 300,
  allowedLibraries: ['react', 'react-dom'],
  forbiddenPatterns: [
    /eval\(/,
    /Function\(/,
    /dangerouslySetInnerHTML/,
    /fetch\(/,  // Force use of secure fetch
  ],
});


// 5. Protect your APIs
// ---------------------

import { APIGuard } from 'runtime-ui-framework';

// Register protected endpoints
APIGuard.registerEndpoint({ path: '/api/admin', method: 'POST', protected: true });
APIGuard.registerEndpoint({ path: '/api/payment', method: 'POST', protected: true });
APIGuard.registerEndpoint({ path: '/api/auth', method: 'POST', protected: true });


// 6. Handle user requests
// ------------------------

async function handleUserAIRequest(userQuery: string) {
  // Call your AI service
  const aiCode = await callOpenAI(userQuery);  // or Anthropic, etc.

  // Validate through RuntimeEngine
  const result = await engine.processModification({
    userQuery,
    generatedCode: aiCode,
  });

  if (result.success) {
    // Apply the code (e.g., hot reload component)
    applyComponentUpdate(result.appliedCode);

    return {
      success: true,
      message: 'UI updated successfully!',
      rollbackToken: result.rollbackToken,
    };
  } else {
    return {
      success: false,
      message: 'Cannot apply changes',
      errors: result.validation.errors,
      warnings: result.validation.warnings,
    };
  }
}

Testing Checklist

Use this to verify your integration:

✅ Component Protection

# Test that locked components are protected
- [ ] Try to modify a @Locked component → Should be rejected
- [ ] Try to modify a @Protected component with allowed operation → Should succeed
- [ ] Try to modify a @Protected component with forbidden operation → Should be rejected
- [ ] Try to modify a @AIModifiable component → Should succeed

✅ Size Constraints

# Test that size limits work
- [ ] Generate code under maxTokens → Should succeed
- [ ] Generate code over maxTokens → Should be rejected
- [ ] Generate code over maxLinesPerComponent → Should be rejected

✅ API Protection

# Test that API access is controlled
- [ ] Try to access allowed endpoint → Should succeed
- [ ] Try to access forbidden endpoint → Should be rejected
- [ ] Try to access protected endpoint → Should be rejected

✅ Security Patterns

# Test that dangerous patterns are blocked
- [ ] Code with eval() → Should be rejected
- [ ] Code with direct fetch() → Should be rejected
- [ ] Code with dangerouslySetInnerHTML → Should show warning

Debugging Your Integration

Enable Verbose Logging

// Add logging to see what's happening
const result = await engine.processModification({...});

console.log('=== Validation Result ===');
console.log('Success:', result.success);
console.log('Errors:', result.validation.errors);
console.log('Warnings:', result.validation.warnings);
console.log('Tokens used:', result.validation.metadata?.tokensUsed);
console.log('Components modified:', result.validation.metadata?.componentsModified);

// Check API logs
import { APIGuard } from 'runtime-ui-framework';
const apiLog = APIGuard.getRequestLog();
console.log('API Requests:', apiLog);

// Check modification history
const history = engine.getHistory();
console.log('Modification history:', history);

Common Issues

Issue: Decorators not working

# Make sure experimentalDecorators is enabled
# In your tsconfig.json:
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Issue: Module not found

# If using npm link, make sure to build first:
cd RuntimeUI
npm run build
npm link

# In your app:
npm link runtime-ui-framework

Issue: Type errors

# Make sure TypeScript can find the types:
# Add to tsconfig.json:
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "runtime-ui-framework": ["../RuntimeUI/src"]
    }
  }
}

Example: Integrate with OpenAI

import OpenAI from 'openai';
import { RuntimeEngine } from 'runtime-ui-framework';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const engine = new RuntimeEngine({ maxTokens: 4000 });

async function generateAndApplyUI(userRequest: string) {
  // 1. Call OpenAI to generate code
  const completion = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: [
      {
        role: 'system',
        content: 'You are a React component generator. Generate only React component code.',
      },
      {
        role: 'user',
        content: userRequest,
      },
    ],
  });

  const aiCode = completion.choices[0].message.content;

  // 2. Validate through RuntimeEngine
  const result = await engine.processModification({
    userQuery: userRequest,
    generatedCode: aiCode || '',
  });

  // 3. Return result
  return result;
}

// Usage
const result = await generateAndApplyUI('Create a product card with image and price');
if (result.success) {
  console.log('✓ UI generated and validated!');
} else {
  console.log('✗ Blocked:', result.validation.errors);
}

Production Tips

1. Start Conservative

// Begin with tight constraints
const engine = new RuntimeEngine({
  maxTokens: 2000,
  maxComponents: 3,
  maxLinesPerComponent: 100,
});

// Relax based on usage patterns

2. Monitor and Log

// Track all modifications
const result = await engine.processModification({...});

// Log to your analytics
analytics.track('ai_modification', {
  success: result.success,
  errors: result.validation.errors,
  tokensUsed: result.validation.metadata?.tokensUsed,
});

3. User Feedback

// Show clear errors to users
if (!result.success) {
  showUserError({
    title: 'Cannot apply changes',
    reasons: result.validation.errors,
    suggestions: [
      'Try a simpler modification',
      'Check if component is locked',
    ],
  });
}

4. Gradual Rollout

// Feature flag for specific users
if (user.hasFeature('ai_customization')) {
  // Enable RuntimeUI
}

Next Steps

  1. ✅ Choose integration option (1, 2, or 3)
  2. ✅ Mark your components with decorators
  3. ✅ Set up RuntimeEngine with constraints
  4. ✅ Test with the checklist above
  5. ✅ Integrate with your AI provider
  6. ✅ Monitor and adjust constraints
  7. ✅ Deploy to production

You're ready to build safe AI-assisted UIs! 🚀