fixed init

This commit is contained in:
redshift
2026-03-03 11:12:34 +00:00
parent 7b90f356c0
commit 1590417061
3 changed files with 59 additions and 13 deletions
+2 -3
View File
@@ -1,12 +1,11 @@
{
"lockfileVersion": 1,
"configVersion": 1,
"workspaces": {
"": {
"name": "routstrd",
"dependencies": {
"@cashu/cashu-ts": "^3.1.1",
"@routstr/sdk": "^0.1.2",
"@routstr/sdk": "^0.1.4",
"applesauce-core": "^5.1.0",
"applesauce-relay": "^5.1.0",
"better-sqlite3": "^11.7.2",
@@ -31,7 +30,7 @@
"@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="],
"@routstr/sdk": ["@routstr/sdk@0.1.2", "", { "dependencies": { "@cashu/cashu-ts": "^3.1.1", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "rxjs": "^7.8.1", "zustand": "^5.0.5" }, "optionalDependencies": { "better-sqlite3": "^11.7.2" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-KzcEVAPaQTV9V/AKpAJLQ0YiCjXX4t2Ebz1t+id5dSl/YqTPHZZXm2HA+mT2xKlqcf8GK7hTdj312WxVji1nWQ=="],
"@routstr/sdk": ["@routstr/sdk@0.1.4", "", { "dependencies": { "@cashu/cashu-ts": "^3.1.1", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "rxjs": "^7.8.1", "zustand": "^5.0.5" }, "optionalDependencies": { "better-sqlite3": "^11.7.2" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-4NQV7IcB1UkiO2HQa0as5OBu0v3pZ7TO265oTjMNYPtYMdYOSXjF+uPBcHCRJLfVhnTN4OOCmUQnnhYM0gR6Zw=="],
"@scure/base": ["@scure/base@2.0.0", "", {}, "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w=="],
+44 -9
View File
@@ -251,13 +251,29 @@ async function main(): Promise<void> {
const discoveryAdapter = createDiscoveryAdapterFromStore(store);
const providerRegistry = createProviderRegistryFromStore(store);
const storageAdapter = createStorageAdapterFromStore(store);
logger.log("Bootstrapping providers...");
const modelManager = new ModelManager(discoveryAdapter);
const providers = await modelManager.bootstrapProviders(false);
logger.log(`Bootstrapped ${providers.length} providers`);
await modelManager.fetchModels(providers);
logger.log("Provider bootstrap complete.");
let providerBootstrapPromise: Promise<void> | null = null;
const ensureProvidersBootstrapped = (): Promise<void> => {
if (!providerBootstrapPromise) {
providerBootstrapPromise = (async () => {
logger.log("Bootstrapping providers...");
const providers = await modelManager.bootstrapProviders(false);
logger.log(`Bootstrapped ${providers.length} providers`);
await modelManager.fetchModels(providers);
logger.log("Provider bootstrap complete.");
})().catch((error) => {
logger.error("Provider bootstrap failed:", error);
throw error;
});
}
return providerBootstrapPromise;
};
// Start bootstrap in background so daemon can become healthy quickly.
void ensureProvidersBootstrapped().catch(() => {
// Error is already logged; keep daemon alive for troubleshooting/retries.
});
let activeMintUrl: string | null = null;
let mintUnits: Record<string, "sat" | "msat"> = {};
@@ -378,6 +394,7 @@ async function main(): Promise<void> {
if (req.method === "GET" && url.pathname === "/models") {
try {
await ensureProvidersBootstrapped();
await modelManager.fetchRoutstr21Models();
const models = discoveryAdapter.getRoutstr21Models();
res.writeHead(200, { "Content-Type": "application/json" });
@@ -581,6 +598,7 @@ async function main(): Promise<void> {
undefined;
try {
await ensureProvidersBootstrapped();
const response = await routeRequests({
modelId,
requestBody,
@@ -665,6 +683,8 @@ async function main(): Promise<void> {
export async function startDaemon(options: { port?: string; provider?: string } = {}): Promise<void> {
const args: string[] = [];
const port = options.port || "8008";
const pollIntervalMs = 250;
const startupTimeoutMs = 10 * 60 * 1000;
try {
const existing = await fetch(`http://localhost:${port}/health`);
@@ -697,9 +717,22 @@ export async function startDaemon(options: { port?: string; provider?: string }
proc.unref();
let exitCode: number | null = null;
proc.exited.then((code) => {
exitCode = code;
});
// Poll until the daemon is healthy
for (let i = 0; i < 100; i++) {
await new Promise((resolve) => setTimeout(resolve, 200));
const maxPolls = Math.ceil(startupTimeoutMs / pollIntervalMs);
for (let i = 0; i < maxPolls; i++) {
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
if (exitCode !== null) {
throw new Error(
`Daemon process exited early with code ${exitCode}. Check logs at ${LOG_FILE}`
);
}
try {
const res = await fetch(`http://localhost:${port}/health`);
if (res.ok) {
@@ -711,7 +744,9 @@ export async function startDaemon(options: { port?: string; provider?: string }
}
}
throw new Error("Daemon failed to start within 20 seconds");
throw new Error(
`Daemon failed to start within ${Math.round(startupTimeoutMs / 1000)} seconds. Check logs at ${LOG_FILE}`
);
}
// Only auto-run main() when this file is executed directly (not imported)
+13 -1
View File
@@ -16,7 +16,19 @@ async function writeLog(level: string, ...args: unknown[]) {
await ensureLogDir();
const timestamp = new Date().toISOString();
const message = args
.map((a) => (typeof a === "object" ? JSON.stringify(a) : String(a)))
.map((a) => {
if (a instanceof Error) {
return `${a.message}${a.stack ? `\n${a.stack}` : ""}`;
}
if (typeof a === "object") {
try {
return JSON.stringify(a);
} catch {
return String(a);
}
}
return String(a);
})
.join(" ");
const line = `[${timestamp}] [${level}] ${message}\n`;
try {