diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000000..ead803af35 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,15 @@ +# Security and Cleanliness Rules for AI Assistants + +## 1. File Placement & Organization + +- **Test Files**: ALL unit tests, integration tests, ecosystem tests, or Vitest files MUST strictly be placed within the `tests/` directory (e.g., `tests/unit/`, `tests/integration/`). NEVER create test files in the project root (`/`). +- **Scripts and Utilities**: ALL maintenance, debugging, generation, or experimental scripts (`.cjs`, `.mjs`, `.js`, `.ts`) MUST be placed strictly inside the `scripts/` directory or `scripts/scratch/` for temporary one-offs. NEVER dump loose scripts in the project root (`/`). + +**The Project Root MUST ONLY CONTAIN:** + +- Configuration files (`vitest.config.ts`, `next.config.mjs`, `eslint.config.mjs`, etc.) +- Dependency files (`package.json`, `package-lock.json`) +- Documentation files (`README.md`, `CHANGELOG.md`, `AGENTS.md`) +- CI/CD files and ignore definitions (`.gitignore`, `.dockerignore`) + +When creating _any_ validation tests or one-off logic scripts, default to using `scripts/scratch/` or the `tests/unit/` directories according to your goals. Do not pollute the `/` root context. diff --git a/scripts/scratch/delete_iflow.cjs b/scripts/scratch/delete_iflow.cjs new file mode 100644 index 0000000000..2d80bbf4db --- /dev/null +++ b/scripts/scratch/delete_iflow.cjs @@ -0,0 +1,7 @@ +const Database = require('better-sqlite3'); +const db = new Database(process.env.HOME + '/.omniroute/storage.sqlite'); + +console.log("Deleting iflow connections..."); +const stmt = db.prepare("DELETE FROM provider_connections WHERE provider = 'iflow'"); +const info = stmt.run(); +console.log(`Deleted ${info.changes} rows.`); diff --git a/scripts/scratch/dump-auth-groups.ts b/scripts/scratch/dump-auth-groups.ts new file mode 100644 index 0000000000..f598461d4f --- /dev/null +++ b/scripts/scratch/dump-auth-groups.ts @@ -0,0 +1,23 @@ +import { + APIKEY_PROVIDERS, + SEARCH_PROVIDERS, + AUDIO_ONLY_PROVIDERS, + WEB_COOKIE_PROVIDERS, +} from "./src/shared/constants/providers"; + +console.log("SEARCH_PROVIDERS", !!SEARCH_PROVIDERS, Object.keys(SEARCH_PROVIDERS || {})); +console.log("AUDIO_ONLY", !!AUDIO_ONLY_PROVIDERS); +console.log("WEB_COOKIE", !!WEB_COOKIE_PROVIDERS); + +// Determine auth type group for a provider id +function getAuthGroup(providerId: string) { + if (WEB_COOKIE_PROVIDERS && WEB_COOKIE_PROVIDERS[providerId]) return "web-cookie"; + if (SEARCH_PROVIDERS && SEARCH_PROVIDERS[providerId]) return "search"; + if (AUDIO_ONLY_PROVIDERS && AUDIO_ONLY_PROVIDERS[providerId]) return "audio"; + if (APIKEY_PROVIDERS && APIKEY_PROVIDERS[providerId]) return "apikey"; + return "apikey"; +} + +console.log("grok-web returns:", getAuthGroup("grok-web")); +console.log("perplexity-search returns:", getAuthGroup("perplexity-search")); +console.log("openai returns:", getAuthGroup("openai")); diff --git a/fix-tests.js b/scripts/scratch/fix-tests.js similarity index 100% rename from fix-tests.js rename to scripts/scratch/fix-tests.js diff --git a/scripts/scratch/overlap.js b/scripts/scratch/overlap.js new file mode 100644 index 0000000000..93ac1df151 --- /dev/null +++ b/scripts/scratch/overlap.js @@ -0,0 +1,21 @@ +import { + APIKEY_PROVIDERS, + SEARCH_PROVIDERS, + AUDIO_ONLY_PROVIDERS, + WEB_COOKIE_PROVIDERS, +} from "./src/shared/constants/providers.ts"; + +const apiKeys = Object.keys(APIKEY_PROVIDERS); +console.log("Searching overlap in APIKEY_PROVIDERS:"); +console.log( + "Search overlap:", + Object.keys(SEARCH_PROVIDERS).filter((k) => apiKeys.includes(k)) +); +console.log( + "Audio overlap:", + Object.keys(AUDIO_ONLY_PROVIDERS).filter((k) => apiKeys.includes(k)) +); +console.log( + "Web Cookie overlap:", + Object.keys(WEB_COOKIE_PROVIDERS).filter((k) => apiKeys.includes(k)) +); diff --git a/scripts/scratch/overlap.ts b/scripts/scratch/overlap.ts new file mode 100644 index 0000000000..ceb10a0aad --- /dev/null +++ b/scripts/scratch/overlap.ts @@ -0,0 +1,8 @@ +import { APIKEY_PROVIDERS, SEARCH_PROVIDERS } from "./src/shared/constants/providers.ts"; + +const apiKeys = Object.keys(APIKEY_PROVIDERS); +console.log( + "Overlap:", + Object.keys(SEARCH_PROVIDERS).filter((k) => apiKeys.includes(k)) +); +console.log("Is perplexity-search in APIKEY?", "perplexity-search" in APIKEY_PROVIDERS); diff --git a/scripts/scratch/query_db.cjs b/scripts/scratch/query_db.cjs new file mode 100644 index 0000000000..3bc7a75efd --- /dev/null +++ b/scripts/scratch/query_db.cjs @@ -0,0 +1,18 @@ +const Database = require('better-sqlite3'); +const db = new Database(process.env.HOME + '/.omniroute/storage.sqlite'); + +const providers = db.prepare("SELECT * FROM provider_connections").all(); +console.log("=== provider_connections ==="); +console.log(providers.filter(p => JSON.stringify(p).toLowerCase().includes('iflow'))); + +const combos = db.prepare("SELECT * FROM combos").all(); +console.log("=== combos ==="); +console.log(combos.filter(c => JSON.stringify(c).toLowerCase().includes('iflow'))); + +const settings = db.prepare("SELECT * FROM settings").all(); +console.log("=== settings ==="); +console.log(settings.filter(s => JSON.stringify(s).toLowerCase().includes('iflow'))); + +const apiKeys = db.prepare("SELECT * FROM api_keys").all(); +console.log("=== api_keys ==="); +console.log(apiKeys.filter(k => JSON.stringify(k).toLowerCase().includes('iflow'))); diff --git a/scripts/scratch/query_db.js b/scripts/scratch/query_db.js new file mode 100644 index 0000000000..7f94c56e1c --- /dev/null +++ b/scripts/scratch/query_db.js @@ -0,0 +1,10 @@ +const Database = require("better-sqlite3"); +const db = new Database(process.env.HOME + "/.omniroute/storage.sqlite"); +console.log("=== provider_connections containing iflow ==="); +console.log( + db + .prepare( + "SELECT id, provider_id, alias, account_id FROM provider_connections WHERE provider_id LIKE '%iflow%' OR alias LIKE '%iflow%' OR account_id LIKE '%iflow%'" + ) + .all() +);