fix(auth): remove fallback gemini oauth client secret

Stop shipping a default Gemini OAuth client secret and require it to
come from the environment instead.

Also tighten proxy fetch typing to avoid any-based undici calls and
move db setup utilities under scripts while removing generated debug
and scratch artifacts.
This commit is contained in:
diegosouzapw
2026-04-08 17:29:28 -03:00
parent d9f4166418
commit 7bd8ace1a2
18 changed files with 31 additions and 5419 deletions

23
scripts/dbsetup.js Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env node
import { spawn } from "node:child_process";
const env = { ...process.env };
await exec("npx next build --experimental-build-mode generate");
// launch application
await exec(process.argv.slice(2).join(" "));
function exec(command) {
const child = spawn(command, { shell: true, stdio: "inherit", env });
return new Promise((resolve, reject) => {
child.on("exit", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`${command} failed rc=${code}`));
}
});
});
}

View File

@@ -0,0 +1,17 @@
import process from "node:process";
import fs from "node:fs";
setTimeout(() => {
const activeHandles = process._getActiveHandles();
console.log("ACTIVE HANDLES: " + activeHandles.length);
activeHandles.forEach((handle, i) => {
console.log(`Handle ${i}:`, handle?.constructor?.name);
// if it's a timer or socket, let's see more
if (handle?.constructor?.name === "Timeout") {
console.log(" Timer wrapper:", handle?._onTimeout?.toString().slice(0, 50));
}
});
process.exit(1);
}, 2000);
await import("./tests/integration/chat-pipeline.test.mjs");

View File

@@ -0,0 +1,14 @@
import process from "node:process";
import("./tests/integration/chat-pipeline.test.mjs").then((mod) => {
setTimeout(() => {
const activeHandles = process._getActiveHandles();
console.log("ACTIVE HANDLES: " + activeHandles.length);
activeHandles.forEach((handle, i) => {
console.log(`Handle ${i}:`, handle?.constructor?.name);
if (handle?.constructor?.name === "Socket") {
console.log("Socket ports:", handle?.localPort, handle?.remotePort);
}
});
process.exit(1);
}, 15000);
});

View File

@@ -0,0 +1,2 @@
const { convertOpenAIContentToParts } = require("./open-sse/translator/helpers/geminiHelper.ts");
// since it's typescript/ESM, we might need a ts-node or vitest

View File

@@ -0,0 +1,38 @@
import { QoderExecutor } from "./open-sse/executors/qoder.ts";
import fs from "fs";
import os from "os";
async function run() {
const credsPath = os.homedir() + "/.qwen/oauth_creds.json";
const creds = JSON.parse(fs.readFileSync(credsPath, "utf8"));
const executor = new QoderExecutor();
const result = await executor.execute({
model: "coder-model",
body: {
messages: [{ role: "user", content: "hello test" }],
stream: true,
max_tokens: 10,
},
credentials: {
accessToken: creds.access_token,
resourceUrl: creds.resource_url,
},
signal: new AbortController().signal,
});
console.log("Status:", result.response.status);
if (result.response.body) {
// If it's a web stream, readable stream
const reader = result.response.body.getReader();
const decoder = new TextDecoder("utf-8");
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(decoder.decode(value));
}
}
}
run().catch(console.error);

View File

@@ -0,0 +1,9 @@
import { convertOpenAIContentToParts } from "./open-sse/translator/helpers/geminiHelper.ts";
const cherryMsg = [
{ type: "text", text: "What runs on this?" },
{ type: "file", file: { data: "ABCDEFG", type: "application/pdf" } },
{ type: "file", file_url: { url: "data:application/pdf;base64,ABCDEFG" } },
];
console.log(convertOpenAIContentToParts(cherryMsg));