dumbtv
dumbtv가 ADB로 Fire TV에서 광고·추적·업데이트 알림을 제거, 루트·앱 변경 없이, 무료 오픈소스
하나의 AI만 믿지 말고 다섯으로 검증하세요. 다중 모델 연구·주장 검증·영상 진위·거버넌스와 감사 로그 제공
Don't trust one AI. Verify with five. Multi-model research, claim verification, video authenticity, and governance — with audit trails.
보안TypeScript · JavaScriptGitHub @yasinwarsame온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
ConvergePanel is a production-ready MVP web application that sends one user question to multiple AI models in parallel, then synthesizes a unified answer while explicitly highlighting where models agree or disagree.README 전문 보기 ↗Multi-LLM Expert Panel Research Tool
ConvergePanel is a production-ready MVP web application that sends one user question to multiple AI models in parallel, then synthesizes a unified answer while explicitly highlighting where models agree or disagree.
git clone <repository-url>
cd ConvergePanel
npm install
# or
yarn install
# or
pnpm install
.env.local file in the root directory:cp .env.example .env.local
Set up Firebase:
convergepanel (or update env vars)Get Firebase Service Account Credentials (REQUIRED for Admin SDK):
client_email → FIREBASE_CLIENT_EMAILprivate_key → FIREBASE_PRIVATE_KEY (keep the quotes and \n characters)\nAdd environment variables to .env.local:
# Firebase Client Config (from Firebase Console)
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=convergepanel.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=convergepanel
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=convergepanel.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=907484474744
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
# Firebase Admin SDK (Service Account) - REQUIRED
# Get these from Firebase Console > Project Settings > Service Accounts > Generate new private key
FIREBASE_PROJECT_ID=convergepanel
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@convergepanel.iam.gserviceaccount.com
# IMPORTANT: Keep the quotes and \n characters exactly as they appear in the JSON file
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...\n-----END PRIVATE KEY-----\n"
# Admin Secret (for setting first admin)
ADMIN_SECRET=your-long-random-secret-string
# Optional: API keys can be set here or via Admin UI
# Firestore keys take precedence over environment variables
OPENAI_API_KEY=your_openai_api_key_here
ANTHROPIC_API_KEY=your_anthropic_api_key_here
XAI_API_KEY=your_xai_api_key_here
PERPLEXITY_API_KEY=your_perplexity_api_key_here
firestore.rules (see below)Note:
npm run dev
# or
yarn dev
# or
pnpm dev
Open http://localhost:3000 in your browser
Enter a question, select models (minimum 2), and click "Run Panel"
ConvergePanel/
├── app/
│ ├── admin/
│ │ ├── login/
│ │ │ └── page.tsx # Admin login page
│ │ └── page.tsx # Admin dashboard
│ ├── about/
│ │ └── page.tsx # About page
│ ├── help/
│ │ └── page.tsx # Help page
│ ├── contact/
│ │ └── page.tsx # Contact page
│ ├── api/
│ │ ├── admin/
│ │ │ ├── login/
│ │ │ │ └── route.ts # Admin login API
│ │ │ ├── logout/
│ │ │ │ └── route.ts # Admin logout API
│ │ │ └── keys/
│ │ │ └── route.ts # Admin keys API
│ │ └── run-panel/
│ │ └── route.ts # API endpoint for running panels
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ └── page.tsx # Main page component
├── components/
│ ├── ModelPicker.tsx # Model selection UI
│ ├── StatusPill.tsx # Status indicator component
│ ├── ResultsDisplay.tsx # Results display component
│ └── TopNav.tsx # Top navigation component
├── lib/
│ ├── keyStore.ts # Server-side key storage
│ ├── types.ts # TypeScript type definitions
│ ├── consensus.ts # Consensus engine and synthesis
│ └── connectors/
│ ├── base.ts # Base connector class
│ ├── chatgpt.ts # OpenAI GPT 5.2 connector
│ ├── claude.ts # Anthropic Claude Opus 4.5 connector
│ ├── grok.ts # X.AI Grok 4 connector
│ ├── perplexity.ts # Perplexity Pro connector
│ ├── gemini.ts # Google Gemini 3 Pro connector
│ └── index.ts # Connector exports
├── middleware.ts # Route protection middleware
├── package.json
├── tsconfig.json
├── tailwind.config.ts
└── README.md
Each AI model has a dedicated connector that implements the ModelConnector interface:
interface ModelConnector {
id: "chatgpt" | "claude" | "grok" | "perplexity" | "gemini";
displayName: string;
sendPrompt(question: string, systemWrapper: string): Promise<{
status: "ok" | "error" | "timeout" | "refused";
rawText: string | null;
latencyMs: number;
}>;
}
The /api/run-panel endpoint:
The consensus engine:
To add a new model connector:
lib/connectors/ (e.g., gemini.ts):import { BaseConnector } from "./base";
export class GeminiConnector extends BaseConnector {
id = "gemini" as const;
displayName = "Gemini 3 Pro";
async sendPrompt(question: string, systemWrapper: string) {
const startTime = Date.now();
const apiKey = this.getApiKey();
if (!apiKey) {
return this.getMockResponse();
}
try {
// Implement your API call here
// ...
return {
status: "ok" as const,
rawText: responseText,
latencyMs: Date.now() - startTime,
};
} catch (error) {
// Handle errors
return {
status: "error" as const,
rawText: null,
latencyMs: Date.now() - startTime,
};
}
}
}
lib/types.ts to include the new model ID:export type ModelId = "chatgpt" | "claude" | "grok" | "perplexity" | "gemini";
lib/connectors/index.ts:import { GeminiConnector } from "./gemini";
const connectors: Record<ModelId, ModelConnector> = {
// ... existing connectors
gemini: new GeminiConnector(),
};
.env.local:GEMINI_API_KEY=your_gemini_api_key_here
getApiKey() method to include the new key mapping.ConvergePanel uses Firebase Authentication with role-based access control.
ADMIN_EMAILS address or the admin: true custom claim; a broad read/monitoring tier over runs and user records. SYSTEM_ADMIN — the admin: true claim only; API keys, role minting, purge, destructive user/billing mutation. GOVERNANCE_ADMIN — a verified, enabled GOVERNANCE_ADMIN_EMAILS address only. See docs/operations/admin-authority-tiers.md.Sign up a user account through the app (/signup)
Get the user's UID from Firebase Console or from the user's profile page
Call the admin setter endpoint. MINTS-AUTHORITY — this grants SYSTEM_ADMIN to the named uid:
curl -X POST http://localhost:3000/api/admin/set-admin \
-H "Content-Type: application/json" \
-d '{"uid": "USER_UID_HERE", "secret": "YOUR_ADMIN_SECRET"}'
Never reuse this request to check whether an old secret still works. The secret is validated before the uid, so a still-live old secret does not report a failure here — it mints the claim again, with no audit record and no log. To verify a rotation or removal, use the uid-less probe in
docs/operations/admin-authority-tiers.md§B.6 — send{"secret": "..."}with no uid.A standalone
401is NOT Production containment proof. On its own it says only that the origin you contacted rejected the string you supplied, which is also what a preview deploy with no secret set, or a shell-mangled secret, returns. A single response is an OBSERVATION:400+ the accepted marker = credential accepted,401+ the rejected marker = credential rejected, anything else = inconclusive. Containment requires the two-phase proof at the canonical Production origin — pre-check accepted, then rotate and deploy, then the SAME process observing that credential rejected.
Note: This endpoint is not linked in the UI for security. It's a one-time setup endpoint.
ConvergePanel includes an admin-only dashboard for managing API keys and users.
/admin (link appears in TopNav for admins only)admin: true custom claim for SYSTEM_ADMIN routes, and the claim or a verified, enabled ADMIN_EMAILS address for the ADMIN_PORTAL read tierappConfig/modelKeys documentImportant Security Notes:
/admin route is not linked in public navigationadmin custom claim or a verified ADMIN_EMAILS member; see docs/operations/admin-authority-tiers.md). There is no password-based admin login.ConvergePanel uses PostgreSQL with Prisma ORM for data persistence.
npm install
.env.local:DATABASE_URL="postgresql://user:password@localhost:5432/convergepanel?schema=public"
npx prisma migrate dev --name init
npx prisma generate
The database includes:
To create a new migration:
npx prisma migrate dev --name your_migration_name
To apply migrations in production:
npx prisma migrate deploy
View and edit data in a GUI:
npx prisma studio
Copy and paste these rules into Firebase Console > Firestore Database > Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users collection - users can read/write only their own doc
// Admins can list all users
match /users/{uid} {
allow read, write: if request.auth != null && request.auth.uid == uid;
allow list: if request.auth != null && request.auth.token.admin == true;
}
// App config - only admins can read/write model keys
match /appConfig/modelKeys {
allow read, write: if request.auth != null && request.auth.token.admin == true;
}
// Default deny all other documents
match /{document=**} {
allow read, write: if false;
}
}
}
| Variable | Description | Required |
|---|---|---|
NEXT_PUBLIC_FIREBASE_API_KEY | Firebase API key | Yes |
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN | Firebase auth domain | Yes |
NEXT_PUBLIC_FIREBASE_PROJECT_ID | Firebase project ID | Yes |
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET | Firebase storage bucket | Yes |
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID | Firebase messaging sender ID | Yes |
NEXT_PUBLIC_FIREBASE_APP_ID | Firebase app ID | Yes |
| Variable | Description | Required |
|---|---|---|
FIREBASE_PROJECT_ID | Firebase project ID | Yes |
FIREBASE_CLIENT_EMAIL | Service account email | Yes |
FIREBASE_PRIVATE_KEY | Service account private key | Yes |
ADMIN_SECRET | Secret for setting first admin | Yes |
| Variable | Description | Required |
|---|---|---|
OPENAI_API_KEY | OpenAI API key for GPT 5.2 | No (uses mock if missing) |
ANTHROPIC_API_KEY | Anthropic API key for Claude Opus 4.5 | No (uses mock if missing) |
XAI_API_KEY | X.AI API key for Grok 4 | No (uses mock if missing) |
PERPLEXITY_API_KEY | Perplexity API key for Perplexity Pro | No (uses mock if missing) |
GEMINI_API_KEY | Google API key for Gemini 3 Pro | No (uses mock if missing) |
Note:
npm run build
npm start
npm run lint
If you encounter a ChunkLoadError in development (e.g., "Loading chunk app/layout failed"):
Clear Next.js cache:
rm -rf .next
Clear browser cache and service workers:
Restart the dev server:
npm run dev
Hard refresh the browser:
Note: Service workers are automatically unregistered in development mode to prevent caching issues. If you still see errors, ensure no service workers are registered in your browser.
MIT
For issues or questions, please open an issue on the repository.