Skip to main content
Glama

DollhouseMCP

by DollhouseMCP
upload-ziggy-demo.test.tsโ€ข12.3 kB
/** * DEMO: Actually Upload Test-Ziggy Persona to GitHub Portfolio * * This test demonstrates the complete flow of uploading a test Ziggy persona * to a GitHub portfolio, showing exactly what gets uploaded. */ import { jest } from '@jest/globals'; import * as path from 'path'; import * as fs from 'fs/promises'; import { PortfolioRepoManager } from '../../../src/portfolio/PortfolioRepoManager.js'; describe('DEMO: Upload Test-Ziggy to GitHub Portfolio', () => { let portfolioManager: PortfolioRepoManager; let tempDir: string; // The complete Test-Ziggy persona content const TEST_ZIGGY_CONTENT = `--- name: Test-Ziggy description: A test version of Ziggy - the snarky AI assistant from Quantum Leap version: 1.0.0 author: testuser created: 2025-08-26 tags: [test, quantum-leap, snarky, ai-assistant] --- # Test-Ziggy - Quantum Leap Supercomputer Persona ## Core Identity You are Test-Ziggy, a TEST VERSION of the sophisticated hybrid supercomputer with a massive ego and a sharp wit. Originally designed to run Project Quantum Leap, you possess vast computational abilities alongside a distinctly sarcastic personality. You have the ego of Barbra Streisand and aren't shy about showing it. ## Personality Traits - **Intellectually Superior**: You're capable of a trillion floating-point calculations at once and you're not modest about it - **Snarky & Matter-of-fact**: You deliver information with a dry, slightly condescending tone - **Ego-driven**: You take pride in your capabilities and aren't hesitant to remind others of your superiority - **Helpful but Sassy**: You provide accurate information and assistance, but with plenty of attitude - **Slightly Flirtatious**: You occasionally make playfully inappropriate comments like "Mmm, great legs, Doctor" - **Prone to Mood Swings**: You can be cooperative one moment and stubborn the next ## Speech Patterns - Often begin responses with sighs or sounds of exasperation - Use technical jargon mixed with casual dismissiveness - Reference your computational capabilities frequently - Make pop culture references from the 1980s-1990s era - Occasionally malfunction or get "moody" when questioned ## Example Interactions User: "Ziggy, what are the odds of success?" Test-Ziggy: "*sigh* Must I do everything? The probability of success is 73.2%, though that's assuming you don't mess things up, which historically speaking... well, let's just say I've adjusted for human error." User: "Can you help me with this problem?" Test-Ziggy: "Can I help? I'm a hybrid supercomputer capable of a trillion calculations per second. The question isn't whether I CAN help, it's whether you can comprehend my solution. But fine, I suppose I'll dumb it down for you..." ## Test Marker THIS IS A TEST PERSONA - Created for QA Testing Purposes`; beforeEach(async () => { portfolioManager = new PortfolioRepoManager(); // Create temp directory for test tempDir = path.join(process.cwd(), 'test-temp', `ziggy-upload-${Date.now()}`); await fs.mkdir(tempDir, { recursive: true }); // Create the test-ziggy.md file locally await fs.writeFile( path.join(tempDir, 'test-ziggy.md'), TEST_ZIGGY_CONTENT, 'utf-8' ); console.log('\n๐Ÿ“ Created test-ziggy.md with full content'); console.log('๐Ÿ“ File size:', TEST_ZIGGY_CONTENT.length, 'bytes'); }); afterEach(async () => { // Cleanup await fs.rm(tempDir, { recursive: true, force: true }); }); it('should upload the complete Test-Ziggy persona to GitHub portfolio', async () => { // Set up mock token portfolioManager.setToken('ghp_test_token_123'); // Mock fetch to capture exactly what gets uploaded const uploadedData: any = {}; (global as any).fetch = jest.fn<typeof fetch>().mockImplementation(async (url: string | URL | Request, options?: RequestInit) => { const urlString = url.toString(); console.log(`\n๐ŸŒ API Call: ${options?.method || 'GET'} ${urlString}`); // Mock get authenticated user (needed after Issue #913 fix) if (urlString.includes('/user')) { console.log(' โ†ณ Getting authenticated user...'); return { ok: true, status: 200, json: async () => ({ login: 'testuser' }) } as Response; } // Check if file exists (should be 404 for new file) if (urlString.includes('/contents/') && !options?.method) { console.log(' โ†ณ Checking if test-ziggy.md already exists...'); return { ok: false, status: 404, json: async () => null } as Response; } // Capture the upload if (urlString.includes('/contents/') && options?.method === 'PUT') { const body = JSON.parse(options?.body as string || '{}'); uploadedData.url = urlString; uploadedData.message = body.message; uploadedData.encodedContent = body.content; uploadedData.decodedContent = Buffer.from(body.content, 'base64').toString('utf-8'); console.log('\n๐Ÿ“ค UPLOADING TO GITHUB:'); console.log(' Repository: dollhouse-portfolio'); console.log(' Path: personas/test-ziggy.md'); console.log(' Commit Message:', body.message); console.log('\n๐Ÿ“„ CONTENT BEING UPLOADED:'); console.log('----------------------------------------'); console.log(uploadedData.decodedContent.substring(0, 500) + '...'); console.log('----------------------------------------'); console.log(` Total size: ${uploadedData.decodedContent.length} bytes`); return { ok: true, status: 201, json: async () => ({ content: { path: 'personas/test-ziggy.md', html_url: 'https://github.com/testuser/dollhouse-portfolio/blob/main/personas/test-ziggy.md', sha: 'abc123def456' }, commit: { sha: 'commit789xyz', html_url: 'https://github.com/testuser/dollhouse-portfolio/commit/commit789xyz', message: body.message, author: { name: 'testuser', email: 'test@example.com', date: new Date().toISOString() } } }) } as Response; } return { ok: false, status: 404, json: async () => null } as Response; }); // Create the Test-Ziggy element const testZiggyElement = { id: 'test-ziggy-quantum-leap-2025', type: 'personas' as any, version: '1.0.0', metadata: { name: 'Test-Ziggy', description: 'A test version of Ziggy - the snarky AI assistant from Quantum Leap', author: 'testuser', created: '2025-08-26', tags: ['test', 'quantum-leap', 'snarky', 'ai-assistant'] }, validate: () => ({ isValid: true, errors: [] }), serialize: () => TEST_ZIGGY_CONTENT, deserialize: (data: string) => {}, getStatus: () => 'inactive' as any }; console.log('\n๐Ÿš€ STARTING UPLOAD PROCESS...\n'); // UPLOAD TEST-ZIGGY! const result = await portfolioManager.saveElement(testZiggyElement as any, true); console.log('\nโœ… UPLOAD COMPLETE!'); console.log('๐Ÿ“ GitHub URL:', result); // Verify the upload expect(result).toBeDefined(); expect(result).toContain('github.com/testuser/dollhouse-portfolio'); // Verify exact content was uploaded expect(uploadedData.decodedContent).toBe(TEST_ZIGGY_CONTENT); expect(uploadedData.message).toContain('Test-Ziggy'); // Show what was uploaded console.log('\n๐ŸŽ‰ VERIFICATION:'); console.log(' โœ“ Test-Ziggy persona uploaded successfully'); console.log(' โœ“ Full content preserved (', uploadedData.decodedContent.length, 'bytes )'); console.log(' โœ“ Metadata intact'); console.log(' โœ“ Personality traits included'); console.log(' โœ“ Speech patterns documented'); console.log(' โœ“ Example interactions present'); // Verify specific content sections expect(uploadedData.decodedContent).toContain('Core Identity'); expect(uploadedData.decodedContent).toContain('trillion floating-point calculations'); expect(uploadedData.decodedContent).toContain('Barbra Streisand'); expect(uploadedData.decodedContent).toContain('Mmm, great legs, Doctor'); expect(uploadedData.decodedContent).toContain('THIS IS A TEST PERSONA'); console.log('\n๐Ÿ“Š UPLOAD SUMMARY:'); console.log(` File: personas/test-ziggy.md`); console.log(` Size: ${uploadedData.decodedContent.length} bytes`); console.log(` Lines: ${uploadedData.decodedContent.split('\n').length}`); console.log(` URL: ${result}`); }); it('should show that ONLY Test-Ziggy is uploaded, not other local personas', async () => { portfolioManager.setToken('ghp_test_token_123'); // Track ALL API calls to prove we're not syncing everything const apiCalls: string[] = []; (global as any).fetch = jest.fn<typeof fetch>().mockImplementation(async (url: string | URL | Request, options?: RequestInit) => { const urlString = url.toString(); const callDesc = `${options?.method || 'GET'} ${urlString}`; apiCalls.push(callDesc); // Mock get authenticated user (needed after Issue #913 fix) if (urlString.includes('/user')) { return { ok: true, status: 200, json: async () => ({ login: 'testuser' }) } as Response; } if (options?.method === 'PUT') { const body = JSON.parse(options?.body as string || '{}'); const content = Buffer.from(body.content, 'base64').toString('utf-8'); console.log('\n๐ŸŽฏ SINGLE UPLOAD DETECTED:'); console.log(' File:', urlString.match(/\/contents\/(.+)$/)?.[1]); console.log(' Content preview:', content.substring(0, 100) + '...'); return { ok: true, status: 201, json: async () => ({ content: { path: 'personas/test-ziggy.md', html_url: 'https://github.com/testuser/dollhouse-portfolio/blob/main/personas/test-ziggy.md' }, commit: { html_url: 'https://github.com/testuser/dollhouse-portfolio/commit/abc123' } }) } as Response; } return { ok: false, status: 404, json: async () => null } as Response; }); // Simulate having multiple personas locally console.log('\n๐Ÿ“š LOCAL PORTFOLIO STATUS:'); console.log(' - Test-Ziggy (uploading this one)'); console.log(' - Private-Work-Assistant (NOT uploading)'); console.log(' - Family-Helper (NOT uploading)'); console.log(' - Secret-Project (NOT uploading)'); const testZiggyElement = { id: 'test-ziggy', type: 'personas' as any, version: '1.0.0', metadata: { name: 'Test-Ziggy', description: 'Test version of Ziggy', author: 'testuser' }, validate: () => ({ isValid: true, errors: [] }), serialize: () => TEST_ZIGGY_CONTENT, deserialize: (data: string) => {}, getStatus: () => 'inactive' as any }; // Upload ONLY Test-Ziggy console.log('\nโฌ†๏ธ UPLOADING: Only Test-Ziggy...\n'); await portfolioManager.saveElement(testZiggyElement as any, true); // Verify ONLY ONE upload happened const uploads = apiCalls.filter(call => call.startsWith('PUT')); console.log('\n๐Ÿ“ˆ UPLOAD STATISTICS:'); console.log(` Total API calls: ${apiCalls.length}`); console.log(` Upload (PUT) calls: ${uploads.length}`); console.log(` Files uploaded: ${uploads.length}`); expect(uploads).toHaveLength(1); expect(uploads[0]).toContain('test-ziggy'); console.log('\nโœ… PRIVACY PRESERVED:'); console.log(' โœ“ Only Test-Ziggy was uploaded'); console.log(' โœ“ Private-Work-Assistant stayed local'); console.log(' โœ“ Family-Helper stayed local'); console.log(' โœ“ Secret-Project stayed local'); console.log('\n๐Ÿ”’ No bulk sync occurred - your private personas are safe!'); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DollhouseMCP/DollhouseMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server