@openexpert/opencore 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +46 -15
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -93,6 +93,9 @@ function secretsAsEnv(cwd = process.cwd()) {
|
|
|
93
93
|
for (const [k, v] of Object.entries(s)) if (v) out[k] = v;
|
|
94
94
|
return out;
|
|
95
95
|
}
|
|
96
|
+
function localServerEnv(env = process.env) {
|
|
97
|
+
return { HOST: env["OPENEXPERT_HOST"] || env["HOST"] || "127.0.0.1" };
|
|
98
|
+
}
|
|
96
99
|
async function httpGetJson(url, opts = {}) {
|
|
97
100
|
try {
|
|
98
101
|
const res = await fetch(url, {
|
|
@@ -173,13 +176,13 @@ function cmdVersion() {
|
|
|
173
176
|
console.log(`OpenExpert ${packageVersion()}`);
|
|
174
177
|
return 0;
|
|
175
178
|
}
|
|
176
|
-
function configuredProvider() {
|
|
177
|
-
const raw = process.env["OPENEXPERT_MODEL_PROVIDER"] || readConfig().modelProvider;
|
|
179
|
+
function configuredProvider(cwd = process.cwd()) {
|
|
180
|
+
const raw = process.env["OPENEXPERT_MODEL_PROVIDER"] || readConfig(cwd).modelProvider;
|
|
178
181
|
if (raw === "ollama" || raw === "openai-compatible") return raw;
|
|
179
182
|
return "google";
|
|
180
183
|
}
|
|
181
184
|
function cmdDoctor(cwd = process.cwd()) {
|
|
182
|
-
const provider = configuredProvider();
|
|
185
|
+
const provider = configuredProvider(cwd);
|
|
183
186
|
const dataDir = resolvedDataDir(cwd);
|
|
184
187
|
const secrets = readSecrets(cwd);
|
|
185
188
|
console.log("OpenExpert doctor");
|
|
@@ -246,7 +249,7 @@ async function cmdFix(cwd = process.cwd()) {
|
|
|
246
249
|
return 0;
|
|
247
250
|
}
|
|
248
251
|
async function cmdModels(cwd = process.cwd()) {
|
|
249
|
-
const provider = configuredProvider();
|
|
252
|
+
const provider = configuredProvider(cwd);
|
|
250
253
|
const secrets = readSecrets(cwd);
|
|
251
254
|
const cfg = readConfig(cwd);
|
|
252
255
|
if (provider === "ollama") {
|
|
@@ -301,10 +304,18 @@ async function cmdServe(cwd = process.cwd()) {
|
|
|
301
304
|
);
|
|
302
305
|
return 1;
|
|
303
306
|
}
|
|
304
|
-
|
|
307
|
+
const serverEnv = {
|
|
308
|
+
...env,
|
|
309
|
+
...localServerEnv(),
|
|
310
|
+
PORT: process.env["PORT"] || "3000"
|
|
311
|
+
};
|
|
312
|
+
const customEndpoint = serverEnv["HOST"] !== "127.0.0.1" || serverEnv["PORT"] !== "3000";
|
|
313
|
+
console.log(
|
|
314
|
+
"Arrancando OpenExpert en http://127.0.0.1:3000 \u2026" + (customEndpoint ? " (host o puerto personalizados: mira OPENEXPERT_HOST y PORT)" : "")
|
|
315
|
+
);
|
|
305
316
|
return run(process.execPath, [join(app, ".output", "server", "index.mjs")], {
|
|
306
317
|
cwd: app,
|
|
307
|
-
env:
|
|
318
|
+
env: serverEnv
|
|
308
319
|
});
|
|
309
320
|
}
|
|
310
321
|
function cmdUpdate() {
|
|
@@ -323,18 +334,24 @@ function port() {
|
|
|
323
334
|
function appUrl() {
|
|
324
335
|
return `http://localhost:${port()}`;
|
|
325
336
|
}
|
|
326
|
-
|
|
337
|
+
function looksLikeOpenExpert(status, headers) {
|
|
338
|
+
return status < 500 && headers.has("x-request-id") && headers.has("x-frame-options");
|
|
339
|
+
}
|
|
340
|
+
async function probeServer(timeoutMs = 1500) {
|
|
327
341
|
try {
|
|
328
|
-
const res = await fetch(appUrl(), {
|
|
329
|
-
|
|
342
|
+
const res = await fetch(appUrl(), {
|
|
343
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
344
|
+
redirect: "manual"
|
|
345
|
+
});
|
|
346
|
+
return looksLikeOpenExpert(res.status, res.headers) ? "openexpert" : "other";
|
|
330
347
|
} catch {
|
|
331
|
-
return
|
|
348
|
+
return "none";
|
|
332
349
|
}
|
|
333
350
|
}
|
|
334
351
|
async function waitForServer(timeoutMs = 12e4) {
|
|
335
352
|
const start = Date.now();
|
|
336
353
|
while (Date.now() - start < timeoutMs) {
|
|
337
|
-
if (await
|
|
354
|
+
if (await probeServer() === "openexpert") return true;
|
|
338
355
|
await new Promise((r) => setTimeout(r, 400));
|
|
339
356
|
}
|
|
340
357
|
return false;
|
|
@@ -375,20 +392,24 @@ async function spawnServer(cwd, env) {
|
|
|
375
392
|
if (existsSync(built) && buildIsFresh(repo)) {
|
|
376
393
|
return spawn(process.execPath, [built], {
|
|
377
394
|
cwd: repo,
|
|
378
|
-
env: { ...env, NODE_ENV: "production", PORT: port() },
|
|
395
|
+
env: { ...env, ...localServerEnv(), NODE_ENV: "production", PORT: port() },
|
|
379
396
|
stdio: "inherit"
|
|
380
397
|
});
|
|
381
398
|
}
|
|
382
399
|
console.log(
|
|
383
400
|
existsSync(built) ? "La build est\xE1 desactualizada; arrancando en modo desarrollo\u2026" : "Arrancando el servidor en modo desarrollo (no hay build)\u2026"
|
|
384
401
|
);
|
|
385
|
-
return spawn("npm", ["run", "dev"], {
|
|
402
|
+
return spawn("npm", ["run", "dev"], {
|
|
403
|
+
cwd: repo,
|
|
404
|
+
env: { ...env, ...localServerEnv() },
|
|
405
|
+
stdio: "inherit"
|
|
406
|
+
});
|
|
386
407
|
}
|
|
387
408
|
const app = await ensureStandaloneApp(packageVersion(), { log: (m) => console.log(` ${m}`) });
|
|
388
409
|
if (!app) return null;
|
|
389
410
|
return spawn(process.execPath, [join(app, ".output", "server", "index.mjs")], {
|
|
390
411
|
cwd: app,
|
|
391
|
-
env: { ...env, NODE_ENV: "production", PORT: port() },
|
|
412
|
+
env: { ...env, ...localServerEnv(), NODE_ENV: "production", PORT: port() },
|
|
392
413
|
stdio: "inherit"
|
|
393
414
|
});
|
|
394
415
|
}
|
|
@@ -416,8 +437,18 @@ async function cmdDesktop(cwd = process.cwd()) {
|
|
|
416
437
|
}
|
|
417
438
|
let server = null;
|
|
418
439
|
let startedServer = false;
|
|
419
|
-
|
|
440
|
+
const probe = await probeServer();
|
|
441
|
+
if (probe === "openexpert") {
|
|
420
442
|
console.log(`\u2022 Usando el servidor ya activo en ${appUrl()}`);
|
|
443
|
+
} else if (probe === "other") {
|
|
444
|
+
console.error(
|
|
445
|
+
`El puerto ${port()} est\xE1 ocupado por otra aplicaci\xF3n, no por OpenExpert.
|
|
446
|
+
La ventana apunta siempre a ${appUrl()}, as\xED que mostrar\xEDa esa otra aplicaci\xF3n.
|
|
447
|
+
Mira qui\xE9n lo ocupa, lib\xE9ralo (o cambia el puerto de ese programa) y vuelve a intentarlo:
|
|
448
|
+
ss -ltnp | grep :${port()} # o: lsof -i :${port()}
|
|
449
|
+
`
|
|
450
|
+
);
|
|
451
|
+
return 1;
|
|
421
452
|
} else {
|
|
422
453
|
console.log("Arrancando el servidor local\u2026");
|
|
423
454
|
server = await spawnServer(cwd, env);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/model-provider.ts","../src/cli/lib.ts","../src/cli/commands.ts","../src/cli/desktop.ts","../src/cli/wizard.ts","../src/cli.ts"],"names":["p","mkdirSync","existsSync","join","writeFileSync","spawn","homedir","resolve","ollama","config","run"],"mappings":"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","file":"cli.js","sourcesContent":["// SPDX-License-Identifier: MIT\n// OpenCore — which model to use. The harness is stable; the model is configuration.\n//\n// Providers:\n// - google: Gemini via GOOGLE_API_KEY (free API key).\n// - ollama: Local model via Ollama's OpenAI-compatible endpoint.\n// - openai-compatible: Any OpenAI-compatible endpoint with your own key.\n\nexport type ModelProviderId = \"google\" | \"ollama\" | \"openai-compatible\";\n\nexport type ModelSelection = {\n provider: ModelProviderId;\n modelId: string;\n /** Where the key comes from, without exposing the value. */\n keySource: \"GOOGLE_API_KEY\" | \"OPENEXPERT_MODEL_KEY\" | \"none (local)\";\n};\n\nexport function selectModel(env: NodeJS.ProcessEnv = process.env): ModelSelection {\n const raw = env[\"OPENEXPERT_MODEL_PROVIDER\"];\n const provider: ModelProviderId =\n raw === \"ollama\" || raw === \"openai-compatible\" ? raw : \"google\";\n\n if (provider === \"ollama\") {\n return {\n provider,\n modelId: env[\"OPENEXPERT_MODEL_ID\"] || \"llama3.1\",\n keySource: \"none (local)\",\n };\n }\n if (provider === \"openai-compatible\") {\n return {\n provider,\n modelId: env[\"OPENEXPERT_MODEL_ID\"] || \"gpt-4o-mini\",\n keySource: \"OPENEXPERT_MODEL_KEY\",\n };\n }\n return {\n provider: \"google\",\n modelId: env[\"OPENEXPERT_MODEL_ID\"] || \"gemini-2.5-flash\",\n keySource: \"GOOGLE_API_KEY\",\n };\n}\n\n/**\n * Ollama exposes two surfaces: the native API at the server root (`/api/*`)\n * and an OpenAI-compatible API under `/v1`. Callers may configure either\n * shape, so normalise before using it.\n *\n * Trailing slashes are removed with a loop, not with `/\\/+$/`: a regex has to\n * retry at every position of a long run of slashes, which is what CodeQL\n * reports as a polynomial ReDoS on `baseUrl`.\n */\nfunction stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\nexport function ollamaApiBaseUrl(baseUrl: string): string {\n const base = stripTrailingSlashes(baseUrl.trim());\n return base.endsWith(\"/v1\") ? base.slice(0, -3) : base;\n}\n\nexport function ollamaChatBaseUrl(baseUrl: string): string {\n return `${ollamaApiBaseUrl(baseUrl)}/v1`;\n}\n\nexport function missingKeyHint(\n sel: ModelSelection,\n env: NodeJS.ProcessEnv = process.env,\n): string | null {\n if (sel.provider === \"ollama\") return null;\n if (sel.provider === \"google\" && !env[\"GOOGLE_API_KEY\"]) {\n return \"Falta GOOGLE_API_KEY (o usa OPENEXPERT_MODEL_PROVIDER=ollama para modelo local).\";\n }\n if (sel.provider === \"openai-compatible\" && !env[\"OPENEXPERT_MODEL_KEY\"]) {\n return \"Falta OPENEXPERT_MODEL_KEY para tu endpoint OpenAI-compatible.\";\n }\n return null;\n}\n","// SPDX-License-Identifier: MIT\n// Shared helpers for the OpenCore CLI: paths, config/secrets I/O, HTTP\n// detection, and release download with checksum verification.\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ollamaApiBaseUrl } from \"../model-provider.js\";\n\nexport type Provider = \"google\" | \"ollama\" | \"openai-compatible\";\n\nexport type FileConfig = {\n modelProvider?: Provider;\n modelId?: string;\n ollamaBaseUrl?: string;\n dataDir?: string;\n};\n\nexport type Secrets = {\n GOOGLE_API_KEY?: string;\n GOOGLE_CLIENT_ID?: string;\n GOOGLE_CLIENT_SECRET?: string;\n OPENEXPERT_MODEL_KEY?: string;\n OPENEXPERT_BASE_URL?: string;\n};\n\nexport const DEFAULT_OLLAMA_URL = \"http://localhost:11434\";\nexport const DEFAULT_DATA_DIR = \"~/.openexpert\";\n\nexport function expandHome(p: string): string {\n if (p === \"~\") return homedir();\n if (p.startsWith(\"~/\")) return join(homedir(), p.slice(2));\n return p;\n}\n\nexport function packageRoot(): string {\n // dist/cli.js -> package root is one level up.\n return resolve(dirname(fileURLToPath(import.meta.url)), \"..\");\n}\n\nexport function packageVersion(): string {\n try {\n const pkg = JSON.parse(readFileSync(join(packageRoot(), \"package.json\"), \"utf8\")) as {\n version?: string;\n };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\n/** Walk up from `start` to find a checkout (package.json + packages/opencore). */\nexport function findRepoRoot(start = process.cwd()): string | null {\n let dir = resolve(start);\n for (let i = 0; i < 8; i++) {\n if (\n existsSync(join(dir, \"package.json\")) &&\n existsSync(join(dir, \"packages\", \"opencore\")) &&\n existsSync(join(dir, \"vite.config.ts\"))\n ) {\n return dir;\n }\n const parent = resolve(dir, \"..\");\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nexport function configPath(cwd = process.cwd()): string {\n return join(cwd, \"openexpert.json\");\n}\n\nexport function readConfig(cwd = process.cwd()): FileConfig {\n try {\n const p = configPath(cwd);\n if (!existsSync(p)) return {};\n return JSON.parse(readFileSync(p, \"utf8\")) as FileConfig;\n } catch {\n return {};\n }\n}\n\nexport function writeConfig(cfg: FileConfig, cwd = process.cwd()): void {\n writeFileSync(configPath(cwd), JSON.stringify(cfg, null, 2) + \"\\n\");\n}\n\nexport function resolvedDataDir(cwd = process.cwd()): string {\n const cfg = readConfig(cwd);\n const raw = process.env[\"OPENEXPERT_DATA_DIR\"] || cfg.dataDir || DEFAULT_DATA_DIR;\n return expandHome(raw);\n}\n\nexport function secretsPath(cwd = process.cwd()): string {\n return join(resolvedDataDir(cwd), \"secrets.json\");\n}\n\nexport function readSecrets(cwd = process.cwd()): Secrets {\n try {\n const p = secretsPath(cwd);\n if (!existsSync(p)) return {};\n return JSON.parse(readFileSync(p, \"utf8\")) as Secrets;\n } catch {\n return {};\n }\n}\n\nexport function writeSecrets(secrets: Secrets, cwd = process.cwd()): string {\n const dir = resolvedDataDir(cwd);\n mkdirSync(dir, { recursive: true });\n const p = join(dir, \"secrets.json\");\n writeFileSync(p, JSON.stringify(secrets, null, 2), { mode: 0o600 });\n return p;\n}\n\n/** Merge stored secrets into the current environment for the child server. */\nexport function secretsAsEnv(cwd = process.cwd()): Record<string, string> {\n const s = readSecrets(cwd);\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(s)) if (v) out[k] = v;\n return out;\n}\n\nexport async function httpGetJson<T>(\n url: string,\n opts: { headers?: Record<string, string>; timeoutMs?: number } = {},\n): Promise<T | null> {\n try {\n const res = await fetch(url, {\n ...(opts.headers ? { headers: opts.headers } : {}),\n signal: AbortSignal.timeout(opts.timeoutMs ?? 2500),\n });\n if (!res.ok) return null;\n return (await res.json()) as T;\n } catch {\n return null;\n }\n}\n\nexport async function detectOllama(\n baseUrl = DEFAULT_OLLAMA_URL,\n timeoutMs = 1500,\n): Promise<{ up: boolean; models: string[] }> {\n const root = ollamaApiBaseUrl(baseUrl);\n const data = await httpGetJson<{ models?: { name: string }[] }>(`${root}/api/tags`, {\n timeoutMs,\n });\n if (!data) return { up: false, models: [] };\n return { up: true, models: (data.models ?? []).map((m) => m.name) };\n}\n\nexport function appCacheDir(version: string): string {\n return join(expandHome(DEFAULT_DATA_DIR), \"app\", version);\n}\n\n/**\n * Ensure a standalone server build exists for `version`. Downloads the\n * release tarball published by the CI workflow and verifies its checksum.\n * Returns the directory containing `.output/server/index.mjs`, or null.\n */\nexport async function ensureStandaloneApp(\n version: string,\n opts: { repo?: string; log?: (m: string) => void } = {},\n): Promise<string | null> {\n const dir = appCacheDir(version);\n const entry = join(dir, \".output\", \"server\", \"index.mjs\");\n if (existsSync(entry)) return dir;\n\n const repo = opts.repo ?? \"OpenExpert-ai/OpenExpert\";\n const log = opts.log ?? (() => {});\n const tarball = `openexpert-server-${version}.tar.gz`;\n // Different tools tag releases differently; try the common shapes.\n const tags = [`v${version}`, `@openexpert/opencore@${version}`, version];\n\n for (const tag of tags) {\n const base = `https://github.com/${repo}/releases/download/${tag}`;\n const url = `${base}/${tarball}`;\n log(`downloading ${url}`);\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(60_000) });\n if (!res.ok) continue;\n const buf = Buffer.from(await res.arrayBuffer());\n\n // Verify checksum when the .sha256 asset is available.\n try {\n const shaRes = await fetch(`${base}/${tarball}.sha256`, {\n signal: AbortSignal.timeout(15_000),\n });\n if (shaRes.ok) {\n const expected = (await shaRes.text()).trim().split(/\\s+/)[0];\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (expected && expected !== actual) {\n log(\"checksum mismatch, aborting\");\n return null;\n }\n }\n } catch {\n // No checksum asset: continue (release is fetched over HTTPS).\n }\n\n mkdirSync(dir, { recursive: true });\n const tmp = join(dir, tarball);\n writeFileSync(tmp, buf);\n const r = spawnSync(\"tar\", [\"-xzf\", tmp, \"-C\", dir], { stdio: \"ignore\" });\n if (r.status !== 0) return null;\n return existsSync(entry) ? dir : null;\n } catch {\n // try the next tag\n }\n }\n return null;\n}\n\nexport function run(\n cmd: string,\n args: string[],\n opts: { cwd?: string; env?: NodeJS.ProcessEnv } = {},\n): Promise<number> {\n return new Promise((res) => {\n const child = spawn(cmd, args, { stdio: \"inherit\", cwd: opts.cwd, env: opts.env });\n const forward = (sig: NodeJS.Signals) => () => child.kill(sig);\n process.on(\"SIGINT\", forward(\"SIGINT\"));\n process.on(\"SIGTERM\", forward(\"SIGTERM\"));\n child.on(\"exit\", (code) => res(code ?? 0));\n });\n}\n","// SPDX-License-Identifier: MIT\n// Non-interactive CLI commands: doctor, fix, models, serve, version, update.\n\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { ollamaApiBaseUrl } from \"../model-provider.js\";\nimport {\n DEFAULT_OLLAMA_URL,\n appCacheDir,\n detectOllama,\n ensureStandaloneApp,\n findRepoRoot,\n httpGetJson,\n packageVersion,\n readConfig,\n readSecrets,\n resolvedDataDir,\n run,\n secretsAsEnv,\n writeConfig,\n type Provider,\n} from \"./lib.js\";\n\nexport function cmdVersion(): number {\n console.log(`OpenExpert ${packageVersion()}`);\n return 0;\n}\n\nfunction configuredProvider(): Provider {\n const raw = process.env[\"OPENEXPERT_MODEL_PROVIDER\"] || readConfig().modelProvider;\n if (raw === \"ollama\" || raw === \"openai-compatible\") return raw;\n return \"google\";\n}\n\nexport function cmdDoctor(cwd = process.cwd()): number {\n const provider = configuredProvider();\n const dataDir = resolvedDataDir(cwd);\n const secrets = readSecrets(cwd);\n\n console.log(\"OpenExpert doctor\");\n console.log(` provider: ${provider}`);\n console.log(` data dir: ${dataDir}`);\n\n const problems: string[] = [];\n\n if (provider === \"google\" && !process.env[\"GOOGLE_API_KEY\"] && !secrets.GOOGLE_API_KEY) {\n problems.push(\"Falta GOOGLE_API_KEY. Ejecuta `openexpert init` o usa Ollama.\");\n }\n if (provider === \"openai-compatible\") {\n if (!process.env[\"OPENEXPERT_MODEL_KEY\"] && !secrets.OPENEXPERT_MODEL_KEY) {\n problems.push(\"Falta OPENEXPERT_MODEL_KEY.\");\n }\n if (!process.env[\"OPENEXPERT_BASE_URL\"] && !secrets.OPENEXPERT_BASE_URL) {\n problems.push(\"Falta OPENEXPERT_BASE_URL.\");\n }\n }\n if (provider === \"ollama\") {\n console.log(` ollama: ${process.env[\"OLLAMA_BASE_URL\"] || DEFAULT_OLLAMA_URL}`);\n }\n if (!process.env[\"GOOGLE_CLIENT_ID\"] && !secrets.GOOGLE_CLIENT_ID) {\n console.log(\" note: sin Google OAuth el chat funciona; Drive queda desconectado.\");\n }\n try {\n mkdirSync(dataDir, { recursive: true });\n } catch {\n problems.push(`No se puede escribir en ${dataDir}.`);\n }\n\n if (!problems.length) {\n console.log(\" OK: listo para arrancar.\");\n return 0;\n }\n console.log(\" pendiente:\");\n for (const x of problems) console.log(` - ${x}`);\n return 1;\n}\n\nexport async function cmdFix(cwd = process.cwd()): Promise<number> {\n const dataDir = resolvedDataDir(cwd);\n mkdirSync(dataDir, { recursive: true });\n\n if (!existsSync(join(cwd, \"openexpert.json\"))) {\n const ollama = await detectOllama();\n writeConfig(\n {\n modelProvider: \"ollama\",\n modelId: ollama.models[0] ?? \"llama3.1\",\n ollamaBaseUrl: DEFAULT_OLLAMA_URL,\n dataDir: \"~/.openexpert\",\n },\n cwd,\n );\n console.log(\"✓ openexpert.json creado (Ollama).\");\n } else {\n console.log(\"• openexpert.json ya existe.\");\n }\n\n const secrets = readSecrets(cwd);\n if (Object.keys(secrets).length) {\n const p = join(dataDir, \"secrets.json\");\n writeFileSync(p, JSON.stringify(secrets, null, 2), { mode: 0o600 });\n console.log(`✓ permisos de ${p} normalizados (0600).`);\n }\n\n console.log(\"✓ directorio de datos listo:\", dataDir);\n cmdDoctor(cwd);\n console.log(\"\\nSiguiente paso: `openexpert serve` (o `openexpert init` para elegir modelo).\");\n return 0;\n}\n\nexport async function cmdModels(cwd = process.cwd()): Promise<number> {\n const provider = configuredProvider();\n const secrets = readSecrets(cwd);\n const cfg = readConfig(cwd);\n\n if (provider === \"ollama\") {\n const base = ollamaApiBaseUrl(\n process.env[\"OLLAMA_BASE_URL\"] || cfg.ollamaBaseUrl || DEFAULT_OLLAMA_URL,\n );\n const { up, models } = await detectOllama(base);\n if (!up) {\n console.log(`No se puede contactar con Ollama en ${base}.`);\n console.log(\"Instálalo con: curl -fsSL https://ollama.com/install.sh | sh\");\n return 1;\n }\n console.log(`Modelos en Ollama (${base}):`);\n for (const m of models) console.log(` ${m === cfg.modelId ? \"*\" : \" \"} ${m}`);\n if (!models.length) console.log(\" (ninguno; prueba `ollama pull llama3.1`)\");\n return 0;\n }\n\n if (provider === \"openai-compatible\") {\n const base = process.env[\"OPENEXPERT_BASE_URL\"] || secrets.OPENEXPERT_BASE_URL;\n const key = process.env[\"OPENEXPERT_MODEL_KEY\"] || secrets.OPENEXPERT_MODEL_KEY;\n if (!base || !key) {\n console.log(\"Configura OPENEXPERT_BASE_URL y OPENEXPERT_MODEL_KEY (openexpert init).\");\n return 1;\n }\n const data = await httpGetJson<{ data?: { id: string }[] }>(\n `${base.replace(/\\/+$/, \"\")}/models`,\n { headers: { Authorization: `Bearer ${key}` } },\n );\n if (!data) {\n console.log(\"No se pudo listar modelos del endpoint.\");\n return 1;\n }\n console.log(\"Modelos disponibles:\");\n for (const m of data.data ?? []) console.log(` ${m.id === cfg.modelId ? \"*\" : \" \"} ${m.id}`);\n return 0;\n }\n\n console.log(\"Proveedor google: usa `gemini-2.5-flash` o consulta Google AI Studio.\");\n return 0;\n}\n\nexport async function cmdServe(cwd = process.cwd()): Promise<number> {\n const env = { ...process.env, ...secretsAsEnv(cwd) } as NodeJS.ProcessEnv;\n\n const repo = findRepoRoot(cwd);\n if (repo) {\n console.log(\"Arrancando OpenExpert (desde el código fuente)…\");\n return run(\"npm\", [\"run\", \"dev\"], { cwd: repo, env });\n }\n\n const version = packageVersion();\n const app = await ensureStandaloneApp(version, { log: (m) => console.log(` ${m}`) });\n if (!app) {\n console.error(\n \"No hay un servidor preconstruido disponible y no se pudo descargar.\\n\" +\n \"Opciones:\\n\" +\n \" • Usa Docker: docker run -p 3000:3000 -v openexpert-data:/data ghcr.io/openexpert-ai/openexpert:local\\n\" +\n \" • O clona el repositorio y ejecuta `npm ci && npm run dev`.\",\n );\n return 1;\n }\n console.log(\"Arrancando OpenExpert en http://localhost:3000 …\");\n return run(process.execPath, [join(app, \".output\", \"server\", \"index.mjs\")], {\n cwd: app,\n env: { ...env, PORT: process.env[\"PORT\"] || \"3000\" },\n });\n}\n\nexport function cmdUpdate(): number {\n const dir = appCacheDir(packageVersion());\n if (existsSync(dir)) {\n rmSync(dir, { recursive: true, force: true });\n console.log(`✓ caché del servidor eliminada (${dir}).`);\n } else {\n console.log(\"No hay servidor descargado que actualizar.\");\n }\n return 0;\n}\n","// SPDX-License-Identifier: MIT\n// `opencore desktop` — start the local server (unless it is already running)\n// and open the native OpenExpert window (the Tauri shell). This command owns\n// the server lifecycle so it can stop the server when the window closes.\n//\n// The repository is located from the CLI installation itself (not the current\n// directory), so `OpenExpert` works from anywhere.\n\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n ensureStandaloneApp,\n findRepoRoot,\n packageRoot,\n packageVersion,\n secretsAsEnv,\n} from \"./lib.js\";\n\nfunction port(): string {\n return process.env[\"PORT\"] || \"3000\";\n}\n\nfunction appUrl(): string {\n return `http://localhost:${port()}`;\n}\n\nasync function isServerUp(timeoutMs = 1500): Promise<boolean> {\n try {\n const res = await fetch(appUrl(), { signal: AbortSignal.timeout(timeoutMs) });\n return res.status < 500;\n } catch {\n return false;\n }\n}\n\nasync function waitForServer(timeoutMs = 120_000): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isServerUp()) return true;\n await new Promise((r) => setTimeout(r, 400));\n }\n return false;\n}\n\n/**\n * Find the source checkout, in order of confidence:\n * 1. OPENEXPERT_DESKTOP_REPO (baked by the installer),\n * 2. relative to the CLI installation (packages/opencore → repo root),\n * 3. walking up from the current directory.\n */\nfunction resolveRepo(cwd: string): string | null {\n const fromEnv = process.env[\"OPENEXPERT_DESKTOP_REPO\"];\n if (fromEnv) {\n const r = findRepoRoot(fromEnv);\n if (r) return r;\n }\n return findRepoRoot(packageRoot()) ?? findRepoRoot(cwd);\n}\n\n/** Newest modification time (ms) under a directory, or 0 if unreadable. */\nfunction newestMtime(dir: string): number {\n let newest = 0;\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) newest = Math.max(newest, newestMtime(full));\n else if (entry.isFile()) newest = Math.max(newest, statSync(full).mtimeMs);\n }\n } catch {\n // ignore unreadable paths\n }\n return newest;\n}\n\n/** True when the production build exists and is not older than src/. */\nfunction buildIsFresh(repo: string): boolean {\n const built = join(repo, \".output\", \"server\", \"index.mjs\");\n if (!existsSync(built)) return false;\n try {\n return statSync(built).mtimeMs >= newestMtime(join(repo, \"src\"));\n } catch {\n return true;\n }\n}\n\n/** Start the local server, reusing the source checkout when available. */\nasync function spawnServer(cwd: string, env: NodeJS.ProcessEnv): Promise<ChildProcess | null> {\n const repo = resolveRepo(cwd);\n if (repo) {\n const built = join(repo, \".output\", \"server\", \"index.mjs\");\n if (existsSync(built) && buildIsFresh(repo)) {\n return spawn(process.execPath, [built], {\n cwd: repo,\n env: { ...env, NODE_ENV: \"production\", PORT: port() },\n stdio: \"inherit\",\n });\n }\n console.log(\n existsSync(built)\n ? \"La build está desactualizada; arrancando en modo desarrollo…\"\n : \"Arrancando el servidor en modo desarrollo (no hay build)…\",\n );\n return spawn(\"npm\", [\"run\", \"dev\"], { cwd: repo, env, stdio: \"inherit\" });\n }\n\n const app = await ensureStandaloneApp(packageVersion(), { log: (m) => console.log(` ${m}`) });\n if (!app) return null;\n return spawn(process.execPath, [join(app, \".output\", \"server\", \"index.mjs\")], {\n cwd: app,\n env: { ...env, NODE_ENV: \"production\", PORT: port() },\n stdio: \"inherit\",\n });\n}\n\nfunction findDesktopBinary(cwd: string): string | null {\n const fromEnv = process.env[\"OPENEXPERT_DESKTOP_BIN\"];\n if (fromEnv && existsSync(fromEnv)) return fromEnv;\n\n const candidates = [join(homedir(), \".local\", \"bin\", \"openexpert-desktop\")];\n const repo = resolveRepo(cwd);\n if (repo) {\n candidates.push(\n join(repo, \"src-tauri\", \"target\", \"release\", \"openexpert-desktop\"),\n join(repo, \"src-tauri\", \"target\", \"debug\", \"openexpert-desktop\"),\n );\n }\n return candidates.find((c) => existsSync(c)) ?? null;\n}\n\nexport async function cmdDesktop(cwd = process.cwd()): Promise<number> {\n const env = { ...process.env, ...secretsAsEnv(cwd) } as NodeJS.ProcessEnv;\n\n const bin = findDesktopBinary(cwd);\n if (!bin) {\n console.error(\n \"No se encontró la ventana de escritorio (openexpert-desktop).\\n\" +\n \"Compílala con `npx tauri build` o usa `npm run desktop:install`.\",\n );\n return 1;\n }\n\n let server: ChildProcess | null = null;\n let startedServer = false;\n\n if (await isServerUp()) {\n console.log(`• Usando el servidor ya activo en ${appUrl()}`);\n } else {\n console.log(\"Arrancando el servidor local…\");\n server = await spawnServer(cwd, env);\n if (!server) {\n console.error(\n \"No se pudo arrancar el servidor.\\n\" +\n \"Si usas el código fuente, entra en el repositorio y ejecuta:\\n\" +\n \" npm ci && npm run build && npm run desktop:install\",\n );\n return 1;\n }\n startedServer = true;\n if (!(await waitForServer())) {\n console.error(\"El servidor no respondió a tiempo.\");\n server.kill(\"SIGTERM\");\n return 1;\n }\n }\n\n const stopServer = (): void => {\n if (startedServer && server && !server.killed) {\n try {\n server.kill(\"SIGTERM\");\n } catch {\n // already gone\n }\n }\n };\n\n const onSignal = (): void => {\n stopServer();\n process.exit(0);\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n\n console.log(\"Abriendo la ventana de OpenExpert…\");\n const code = await new Promise<number>((resolve) => {\n const win = spawn(bin, [], { stdio: \"inherit\", env });\n win.on(\"exit\", (c) => resolve(c ?? 0));\n });\n\n stopServer();\n return code;\n}\n","// SPDX-License-Identifier: MIT\n// Interactive setup wizard: pick a model provider, write config + secrets.\n\nimport * as p from \"@clack/prompts\";\nimport {\n DEFAULT_OLLAMA_URL,\n detectOllama,\n readConfig,\n writeConfig,\n writeSecrets,\n type FileConfig,\n type Provider,\n type Secrets,\n} from \"./lib.js\";\n\nexport type WizardResult = {\n config: FileConfig;\n secrets: Secrets;\n provider: Provider;\n modelId: string;\n started: boolean;\n};\n\nfunction bail(): never {\n p.cancel(\"Configuración cancelada.\");\n process.exit(1);\n}\n\nexport async function runWizard(\n opts: { cwd?: string; assumeYes?: boolean } = {},\n): Promise<WizardResult> {\n const cwd = opts.cwd ?? process.cwd();\n const existing = readConfig(cwd);\n const nonInteractive = opts.assumeYes || !process.stdin.isTTY;\n\n if (nonInteractive) {\n const ollama = await detectOllama();\n const config: FileConfig = {\n modelProvider: \"ollama\",\n modelId: ollama.models[0] ?? \"llama3.1\",\n ollamaBaseUrl: DEFAULT_OLLAMA_URL,\n dataDir: \"~/.openexpert\",\n };\n writeConfig(config, cwd);\n return { config, secrets: {}, provider: \"ollama\", modelId: config.modelId!, started: false };\n }\n\n p.intro(\"OpenExpert — configuración\");\n\n const spin = p.spinner();\n spin.start(\"Buscando Ollama local…\");\n const ollama = await detectOllama();\n spin.stop(\n ollama.up\n ? `Ollama detectado (${ollama.models.length} modelo(s))`\n : \"No se ha detectado Ollama\",\n );\n\n const choice = await p.select({\n message: \"¿Qué modelo quieres usar?\",\n options: [\n ...(ollama.up\n ? [\n {\n value: \"ollama\" as const,\n label: \"Modelo local (Ollama)\",\n hint: \"sin claves, datos en tu equipo\",\n },\n ]\n : []),\n { value: \"google\" as const, label: \"Google Gemini (clave gratuita)\", hint: \"AI Studio\" },\n { value: \"openai-compatible\" as const, label: \"Otro endpoint compatible\", hint: \"BYOK\" },\n ...(!ollama.up\n ? [{ value: \"install-ollama\" as const, label: \"Instalar Ollama\", hint: \"te muestro cómo\" }]\n : []),\n ],\n });\n if (p.isCancel(choice)) bail();\n\n if (choice === \"install-ollama\") {\n p.note(\n \"Instala Ollama y descarga un modelo:\\n\\n\" +\n \" curl -fsSL https://ollama.com/install.sh | sh\\n\" +\n \" ollama pull llama3.1\\n\\n\" +\n \"Vuelve a ejecutar `openexpert init` cuando esté listo.\",\n \"Instalar Ollama\",\n );\n p.outro(\"Sin cambios.\");\n process.exit(0);\n }\n\n const config: FileConfig = { dataDir: \"~/.openexpert\" };\n const secrets: Secrets = {};\n let modelId = \"llama3.1\";\n\n if (choice === \"ollama\") {\n const models = ollama.models.length ? ollama.models : [\"llama3.1\"];\n const picked = await p.select({\n message: \"Modelo de Ollama\",\n options: models.map((m) => ({ value: m, label: m })),\n });\n if (p.isCancel(picked)) bail();\n modelId = String(picked);\n config.modelProvider = \"ollama\";\n config.modelId = modelId;\n config.ollamaBaseUrl = DEFAULT_OLLAMA_URL;\n } else if (choice === \"google\") {\n const apiKey = await p.password({ message: \"GOOGLE_API_KEY (AI Studio)\" });\n if (p.isCancel(apiKey)) bail();\n const id = await p.text({ message: \"Modelo\", initialValue: \"gemini-2.5-flash\" });\n if (p.isCancel(id)) bail();\n modelId = String(id) || \"gemini-2.5-flash\";\n config.modelProvider = \"google\";\n config.modelId = modelId;\n secrets.GOOGLE_API_KEY = String(apiKey);\n } else if (choice === \"openai-compatible\") {\n const baseURL = await p.text({ message: \"Base URL (…/v1)\", initialValue: \"\" });\n if (p.isCancel(baseURL)) bail();\n const apiKey = await p.password({ message: \"API key\" });\n if (p.isCancel(apiKey)) bail();\n const id = await p.text({ message: \"Modelo\", initialValue: \"gpt-4o-mini\" });\n if (p.isCancel(id)) bail();\n modelId = String(id) || \"gpt-4o-mini\";\n config.modelProvider = \"openai-compatible\";\n config.modelId = modelId;\n secrets.OPENEXPERT_BASE_URL = String(baseURL);\n secrets.OPENEXPERT_MODEL_KEY = String(apiKey);\n }\n\n writeConfig({ ...existing, ...config }, cwd);\n if (Object.keys(secrets).length) writeSecrets({ ...secrets }, cwd);\n\n p.outro(\n `Configuración guardada en openexpert.json (modelo: ${config.modelProvider}:${modelId}).`,\n );\n\n const go = await p.confirm({ message: \"¿Arrancar ahora?\", initialValue: true });\n if (p.isCancel(go)) bail();\n\n return {\n config: { ...existing, ...config },\n secrets,\n provider: config.modelProvider as Provider,\n modelId,\n started: Boolean(go),\n };\n}\n","// SPDX-License-Identifier: MIT\n// OpenCore CLI entry point. Dispatches subcommands. See `run`.\n\nimport { cmdDoctor, cmdFix, cmdModels, cmdServe, cmdUpdate, cmdVersion } from \"./cli/commands.js\";\nimport { cmdDesktop } from \"./cli/desktop.js\";\nimport { runWizard } from \"./cli/wizard.js\";\n\nfunction help(): void {\n console.log(`OpenExpert — motor local\n\nUso:\n openexpert asistente de configuración y arranque\n openexpert init igual que sin argumentos\n openexpert serve arranca la edición local en http://localhost:3000\n openexpert desktop arranca el servidor y abre la ventana de escritorio\n openexpert doctor revisa tu configuración\n openexpert fix auto-configura lo que falte\n openexpert models lista los modelos del proveedor actual\n openexpert update limpia la caché del servidor descargado\n openexpert version muestra la versión\n\nEjemplos:\n npx @openexpert/opencore\n npx @openexpert/opencore serve\n\nDocker (sin Node):\n docker run -p 3000:3000 -v openexpert-data:/data ghcr.io/openexpert-ai/openexpert`);\n}\n\nexport async function run(argv: string[]): Promise<void> {\n const cmd = argv[0] ?? \"\";\n switch (cmd) {\n case \"\":\n case \"init\":\n case \"setup\": {\n const res = await runWizard({});\n if (res.started) process.exit(await cmdServe());\n return;\n }\n case \"doctor\":\n return process.exit(cmdDoctor());\n case \"fix\":\n return process.exit(await cmdFix());\n case \"models\":\n return process.exit(await cmdModels());\n case \"serve\":\n case \"dev\":\n return process.exit(await cmdServe());\n case \"desktop\":\n case \"app\": {\n const code = await cmdDesktop();\n return process.exit(code);\n }\n case \"update\":\n return process.exit(cmdUpdate());\n case \"version\":\n case \"--version\":\n case \"-v\":\n return process.exit(cmdVersion());\n case \"help\":\n case \"--help\":\n case \"-h\":\n help();\n return;\n default:\n console.error(`Comando desconocido: ${cmd}\\n`);\n help();\n return process.exit(1);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/model-provider.ts","../src/cli/lib.ts","../src/cli/commands.ts","../src/cli/desktop.ts","../src/cli/wizard.ts","../src/cli.ts"],"names":["p","mkdirSync","existsSync","join","writeFileSync","spawn","homedir","resolve","ollama","config","run"],"mappings":"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","file":"cli.js","sourcesContent":["// SPDX-License-Identifier: MIT\n// OpenCore — which model to use. The harness is stable; the model is configuration.\n//\n// Providers:\n// - google: Gemini via GOOGLE_API_KEY (free API key).\n// - ollama: Local model via Ollama's OpenAI-compatible endpoint.\n// - openai-compatible: Any OpenAI-compatible endpoint with your own key.\n\nexport type ModelProviderId = \"google\" | \"ollama\" | \"openai-compatible\";\n\nexport type ModelSelection = {\n provider: ModelProviderId;\n modelId: string;\n /** Where the key comes from, without exposing the value. */\n keySource: \"GOOGLE_API_KEY\" | \"OPENEXPERT_MODEL_KEY\" | \"none (local)\";\n};\n\nexport function selectModel(env: NodeJS.ProcessEnv = process.env): ModelSelection {\n const raw = env[\"OPENEXPERT_MODEL_PROVIDER\"];\n const provider: ModelProviderId =\n raw === \"ollama\" || raw === \"openai-compatible\" ? raw : \"google\";\n\n if (provider === \"ollama\") {\n return {\n provider,\n modelId: env[\"OPENEXPERT_MODEL_ID\"] || \"llama3.1\",\n keySource: \"none (local)\",\n };\n }\n if (provider === \"openai-compatible\") {\n return {\n provider,\n modelId: env[\"OPENEXPERT_MODEL_ID\"] || \"gpt-4o-mini\",\n keySource: \"OPENEXPERT_MODEL_KEY\",\n };\n }\n return {\n provider: \"google\",\n modelId: env[\"OPENEXPERT_MODEL_ID\"] || \"gemini-2.5-flash\",\n keySource: \"GOOGLE_API_KEY\",\n };\n}\n\n/**\n * Ollama exposes two surfaces: the native API at the server root (`/api/*`)\n * and an OpenAI-compatible API under `/v1`. Callers may configure either\n * shape, so normalise before using it.\n *\n * Trailing slashes are removed with a loop, not with `/\\/+$/`: a regex has to\n * retry at every position of a long run of slashes, which is what CodeQL\n * reports as a polynomial ReDoS on `baseUrl`.\n */\nfunction stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\nexport function ollamaApiBaseUrl(baseUrl: string): string {\n const base = stripTrailingSlashes(baseUrl.trim());\n return base.endsWith(\"/v1\") ? base.slice(0, -3) : base;\n}\n\nexport function ollamaChatBaseUrl(baseUrl: string): string {\n return `${ollamaApiBaseUrl(baseUrl)}/v1`;\n}\n\nexport function missingKeyHint(\n sel: ModelSelection,\n env: NodeJS.ProcessEnv = process.env,\n): string | null {\n if (sel.provider === \"ollama\") return null;\n if (sel.provider === \"google\" && !env[\"GOOGLE_API_KEY\"]) {\n return \"Falta GOOGLE_API_KEY (o usa OPENEXPERT_MODEL_PROVIDER=ollama para modelo local).\";\n }\n if (sel.provider === \"openai-compatible\" && !env[\"OPENEXPERT_MODEL_KEY\"]) {\n return \"Falta OPENEXPERT_MODEL_KEY para tu endpoint OpenAI-compatible.\";\n }\n return null;\n}\n","// SPDX-License-Identifier: MIT\n// Shared helpers for the OpenCore CLI: paths, config/secrets I/O, HTTP\n// detection, and release download with checksum verification.\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ollamaApiBaseUrl } from \"../model-provider.js\";\n\nexport type Provider = \"google\" | \"ollama\" | \"openai-compatible\";\n\nexport type FileConfig = {\n modelProvider?: Provider;\n modelId?: string;\n ollamaBaseUrl?: string;\n dataDir?: string;\n};\n\nexport type Secrets = {\n GOOGLE_API_KEY?: string;\n GOOGLE_CLIENT_ID?: string;\n GOOGLE_CLIENT_SECRET?: string;\n OPENEXPERT_MODEL_KEY?: string;\n OPENEXPERT_BASE_URL?: string;\n};\n\nexport const DEFAULT_OLLAMA_URL = \"http://localhost:11434\";\nexport const DEFAULT_DATA_DIR = \"~/.openexpert\";\n\nexport function expandHome(p: string): string {\n if (p === \"~\") return homedir();\n if (p.startsWith(\"~/\")) return join(homedir(), p.slice(2));\n return p;\n}\n\nexport function packageRoot(): string {\n // dist/cli.js -> package root is one level up.\n return resolve(dirname(fileURLToPath(import.meta.url)), \"..\");\n}\n\nexport function packageVersion(): string {\n try {\n const pkg = JSON.parse(readFileSync(join(packageRoot(), \"package.json\"), \"utf8\")) as {\n version?: string;\n };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\n/** Walk up from `start` to find a checkout (package.json + packages/opencore). */\nexport function findRepoRoot(start = process.cwd()): string | null {\n let dir = resolve(start);\n for (let i = 0; i < 8; i++) {\n if (\n existsSync(join(dir, \"package.json\")) &&\n existsSync(join(dir, \"packages\", \"opencore\")) &&\n existsSync(join(dir, \"vite.config.ts\"))\n ) {\n return dir;\n }\n const parent = resolve(dir, \"..\");\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nexport function configPath(cwd = process.cwd()): string {\n return join(cwd, \"openexpert.json\");\n}\n\nexport function readConfig(cwd = process.cwd()): FileConfig {\n try {\n const p = configPath(cwd);\n if (!existsSync(p)) return {};\n return JSON.parse(readFileSync(p, \"utf8\")) as FileConfig;\n } catch {\n return {};\n }\n}\n\nexport function writeConfig(cfg: FileConfig, cwd = process.cwd()): void {\n writeFileSync(configPath(cwd), JSON.stringify(cfg, null, 2) + \"\\n\");\n}\n\nexport function resolvedDataDir(cwd = process.cwd()): string {\n const cfg = readConfig(cwd);\n const raw = process.env[\"OPENEXPERT_DATA_DIR\"] || cfg.dataDir || DEFAULT_DATA_DIR;\n return expandHome(raw);\n}\n\nexport function secretsPath(cwd = process.cwd()): string {\n return join(resolvedDataDir(cwd), \"secrets.json\");\n}\n\nexport function readSecrets(cwd = process.cwd()): Secrets {\n try {\n const p = secretsPath(cwd);\n if (!existsSync(p)) return {};\n return JSON.parse(readFileSync(p, \"utf8\")) as Secrets;\n } catch {\n return {};\n }\n}\n\nexport function writeSecrets(secrets: Secrets, cwd = process.cwd()): string {\n const dir = resolvedDataDir(cwd);\n mkdirSync(dir, { recursive: true });\n const p = join(dir, \"secrets.json\");\n writeFileSync(p, JSON.stringify(secrets, null, 2), { mode: 0o600 });\n return p;\n}\n\n/** Merge stored secrets into the current environment for the child server. */\nexport function secretsAsEnv(cwd = process.cwd()): Record<string, string> {\n const s = readSecrets(cwd);\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(s)) if (v) out[k] = v;\n return out;\n}\n\n/**\n * Environment for the local server child process.\n *\n * The bundled server (Nitro) reads `NITRO_HOST`/`HOST` and defaults to every\n * interface, which would publish the dashboard — no authentication, read and\n * write access to the folders the owner granted — to whoever shares the\n * network. Bind loopback unless the operator asks for something else through\n * `OPENEXPERT_HOST` (or a `HOST` of their own).\n */\nexport function localServerEnv(env: NodeJS.ProcessEnv = process.env): Record<string, string> {\n return { HOST: env[\"OPENEXPERT_HOST\"] || env[\"HOST\"] || \"127.0.0.1\" };\n}\n\nexport async function httpGetJson<T>(\n url: string,\n opts: { headers?: Record<string, string>; timeoutMs?: number } = {},\n): Promise<T | null> {\n try {\n const res = await fetch(url, {\n ...(opts.headers ? { headers: opts.headers } : {}),\n signal: AbortSignal.timeout(opts.timeoutMs ?? 2500),\n });\n if (!res.ok) return null;\n return (await res.json()) as T;\n } catch {\n return null;\n }\n}\n\nexport async function detectOllama(\n baseUrl = DEFAULT_OLLAMA_URL,\n timeoutMs = 1500,\n): Promise<{ up: boolean; models: string[] }> {\n const root = ollamaApiBaseUrl(baseUrl);\n const data = await httpGetJson<{ models?: { name: string }[] }>(`${root}/api/tags`, {\n timeoutMs,\n });\n if (!data) return { up: false, models: [] };\n return { up: true, models: (data.models ?? []).map((m) => m.name) };\n}\n\nexport function appCacheDir(version: string): string {\n return join(expandHome(DEFAULT_DATA_DIR), \"app\", version);\n}\n\n/**\n * Ensure a standalone server build exists for `version`. Downloads the\n * release tarball published by the CI workflow and verifies its checksum.\n * Returns the directory containing `.output/server/index.mjs`, or null.\n */\nexport async function ensureStandaloneApp(\n version: string,\n opts: { repo?: string; log?: (m: string) => void } = {},\n): Promise<string | null> {\n const dir = appCacheDir(version);\n const entry = join(dir, \".output\", \"server\", \"index.mjs\");\n if (existsSync(entry)) return dir;\n\n const repo = opts.repo ?? \"OpenExpert-ai/OpenExpert\";\n const log = opts.log ?? (() => {});\n const tarball = `openexpert-server-${version}.tar.gz`;\n // Different tools tag releases differently; try the common shapes.\n const tags = [`v${version}`, `@openexpert/opencore@${version}`, version];\n\n for (const tag of tags) {\n const base = `https://github.com/${repo}/releases/download/${tag}`;\n const url = `${base}/${tarball}`;\n log(`downloading ${url}`);\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(60_000) });\n if (!res.ok) continue;\n const buf = Buffer.from(await res.arrayBuffer());\n\n // Verify checksum when the .sha256 asset is available.\n try {\n const shaRes = await fetch(`${base}/${tarball}.sha256`, {\n signal: AbortSignal.timeout(15_000),\n });\n if (shaRes.ok) {\n const expected = (await shaRes.text()).trim().split(/\\s+/)[0];\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (expected && expected !== actual) {\n log(\"checksum mismatch, aborting\");\n return null;\n }\n }\n } catch {\n // No checksum asset: continue (release is fetched over HTTPS).\n }\n\n mkdirSync(dir, { recursive: true });\n const tmp = join(dir, tarball);\n writeFileSync(tmp, buf);\n const r = spawnSync(\"tar\", [\"-xzf\", tmp, \"-C\", dir], { stdio: \"ignore\" });\n if (r.status !== 0) return null;\n return existsSync(entry) ? dir : null;\n } catch {\n // try the next tag\n }\n }\n return null;\n}\n\nexport function run(\n cmd: string,\n args: string[],\n opts: { cwd?: string; env?: NodeJS.ProcessEnv } = {},\n): Promise<number> {\n return new Promise((res) => {\n const child = spawn(cmd, args, { stdio: \"inherit\", cwd: opts.cwd, env: opts.env });\n const forward = (sig: NodeJS.Signals) => () => child.kill(sig);\n process.on(\"SIGINT\", forward(\"SIGINT\"));\n process.on(\"SIGTERM\", forward(\"SIGTERM\"));\n child.on(\"exit\", (code) => res(code ?? 0));\n });\n}\n","// SPDX-License-Identifier: MIT\n// Non-interactive CLI commands: doctor, fix, models, serve, version, update.\n\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { ollamaApiBaseUrl } from \"../model-provider.js\";\nimport {\n DEFAULT_OLLAMA_URL,\n appCacheDir,\n detectOllama,\n ensureStandaloneApp,\n findRepoRoot,\n httpGetJson,\n localServerEnv,\n packageVersion,\n readConfig,\n readSecrets,\n resolvedDataDir,\n run,\n secretsAsEnv,\n writeConfig,\n type Provider,\n} from \"./lib.js\";\n\nexport function cmdVersion(): number {\n console.log(`OpenExpert ${packageVersion()}`);\n return 0;\n}\n\n// Takes the directory the command was given: reading the config from\n// process.cwd() made `doctor` and `models` ignore an `openexpert.json` in the\n// directory they were pointed at, while everything around them honoured it.\nfunction configuredProvider(cwd = process.cwd()): Provider {\n const raw = process.env[\"OPENEXPERT_MODEL_PROVIDER\"] || readConfig(cwd).modelProvider;\n if (raw === \"ollama\" || raw === \"openai-compatible\") return raw;\n return \"google\";\n}\n\nexport function cmdDoctor(cwd = process.cwd()): number {\n const provider = configuredProvider(cwd);\n const dataDir = resolvedDataDir(cwd);\n const secrets = readSecrets(cwd);\n\n console.log(\"OpenExpert doctor\");\n console.log(` provider: ${provider}`);\n console.log(` data dir: ${dataDir}`);\n\n const problems: string[] = [];\n\n if (provider === \"google\" && !process.env[\"GOOGLE_API_KEY\"] && !secrets.GOOGLE_API_KEY) {\n problems.push(\"Falta GOOGLE_API_KEY. Ejecuta `openexpert init` o usa Ollama.\");\n }\n if (provider === \"openai-compatible\") {\n if (!process.env[\"OPENEXPERT_MODEL_KEY\"] && !secrets.OPENEXPERT_MODEL_KEY) {\n problems.push(\"Falta OPENEXPERT_MODEL_KEY.\");\n }\n if (!process.env[\"OPENEXPERT_BASE_URL\"] && !secrets.OPENEXPERT_BASE_URL) {\n problems.push(\"Falta OPENEXPERT_BASE_URL.\");\n }\n }\n if (provider === \"ollama\") {\n console.log(` ollama: ${process.env[\"OLLAMA_BASE_URL\"] || DEFAULT_OLLAMA_URL}`);\n }\n if (!process.env[\"GOOGLE_CLIENT_ID\"] && !secrets.GOOGLE_CLIENT_ID) {\n console.log(\" note: sin Google OAuth el chat funciona; Drive queda desconectado.\");\n }\n try {\n mkdirSync(dataDir, { recursive: true });\n } catch {\n problems.push(`No se puede escribir en ${dataDir}.`);\n }\n\n if (!problems.length) {\n console.log(\" OK: listo para arrancar.\");\n return 0;\n }\n console.log(\" pendiente:\");\n for (const x of problems) console.log(` - ${x}`);\n return 1;\n}\n\nexport async function cmdFix(cwd = process.cwd()): Promise<number> {\n const dataDir = resolvedDataDir(cwd);\n mkdirSync(dataDir, { recursive: true });\n\n if (!existsSync(join(cwd, \"openexpert.json\"))) {\n const ollama = await detectOllama();\n writeConfig(\n {\n modelProvider: \"ollama\",\n modelId: ollama.models[0] ?? \"llama3.1\",\n ollamaBaseUrl: DEFAULT_OLLAMA_URL,\n dataDir: \"~/.openexpert\",\n },\n cwd,\n );\n console.log(\"✓ openexpert.json creado (Ollama).\");\n } else {\n console.log(\"• openexpert.json ya existe.\");\n }\n\n const secrets = readSecrets(cwd);\n if (Object.keys(secrets).length) {\n const p = join(dataDir, \"secrets.json\");\n writeFileSync(p, JSON.stringify(secrets, null, 2), { mode: 0o600 });\n console.log(`✓ permisos de ${p} normalizados (0600).`);\n }\n\n console.log(\"✓ directorio de datos listo:\", dataDir);\n cmdDoctor(cwd);\n console.log(\"\\nSiguiente paso: `openexpert serve` (o `openexpert init` para elegir modelo).\");\n return 0;\n}\n\nexport async function cmdModels(cwd = process.cwd()): Promise<number> {\n const provider = configuredProvider(cwd);\n const secrets = readSecrets(cwd);\n const cfg = readConfig(cwd);\n\n if (provider === \"ollama\") {\n const base = ollamaApiBaseUrl(\n process.env[\"OLLAMA_BASE_URL\"] || cfg.ollamaBaseUrl || DEFAULT_OLLAMA_URL,\n );\n const { up, models } = await detectOllama(base);\n if (!up) {\n console.log(`No se puede contactar con Ollama en ${base}.`);\n console.log(\"Instálalo con: curl -fsSL https://ollama.com/install.sh | sh\");\n return 1;\n }\n console.log(`Modelos en Ollama (${base}):`);\n for (const m of models) console.log(` ${m === cfg.modelId ? \"*\" : \" \"} ${m}`);\n if (!models.length) console.log(\" (ninguno; prueba `ollama pull llama3.1`)\");\n return 0;\n }\n\n if (provider === \"openai-compatible\") {\n const base = process.env[\"OPENEXPERT_BASE_URL\"] || secrets.OPENEXPERT_BASE_URL;\n const key = process.env[\"OPENEXPERT_MODEL_KEY\"] || secrets.OPENEXPERT_MODEL_KEY;\n if (!base || !key) {\n console.log(\"Configura OPENEXPERT_BASE_URL y OPENEXPERT_MODEL_KEY (openexpert init).\");\n return 1;\n }\n const data = await httpGetJson<{ data?: { id: string }[] }>(\n `${base.replace(/\\/+$/, \"\")}/models`,\n { headers: { Authorization: `Bearer ${key}` } },\n );\n if (!data) {\n console.log(\"No se pudo listar modelos del endpoint.\");\n return 1;\n }\n console.log(\"Modelos disponibles:\");\n for (const m of data.data ?? []) console.log(` ${m.id === cfg.modelId ? \"*\" : \" \"} ${m.id}`);\n return 0;\n }\n\n console.log(\"Proveedor google: usa `gemini-2.5-flash` o consulta Google AI Studio.\");\n return 0;\n}\n\nexport async function cmdServe(cwd = process.cwd()): Promise<number> {\n const env = { ...process.env, ...secretsAsEnv(cwd) } as NodeJS.ProcessEnv;\n\n const repo = findRepoRoot(cwd);\n if (repo) {\n console.log(\"Arrancando OpenExpert (desde el código fuente)…\");\n return run(\"npm\", [\"run\", \"dev\"], { cwd: repo, env });\n }\n\n const version = packageVersion();\n const app = await ensureStandaloneApp(version, { log: (m) => console.log(` ${m}`) });\n if (!app) {\n console.error(\n \"No hay un servidor preconstruido disponible y no se pudo descargar.\\n\" +\n \"Opciones:\\n\" +\n \" • Usa Docker: docker run -p 3000:3000 -v openexpert-data:/data ghcr.io/openexpert-ai/openexpert:local\\n\" +\n \" • O clona el repositorio y ejecuta `npm ci && npm run dev`.\",\n );\n return 1;\n }\n const serverEnv: Record<string, string> = {\n ...(env as Record<string, string>),\n ...localServerEnv(),\n PORT: process.env[\"PORT\"] || \"3000\",\n };\n // Print constants, never values read from the environment: CodeQL flags an\n // environment value written to a log as clear-text logging of sensitive data.\n const customEndpoint = serverEnv[\"HOST\"] !== \"127.0.0.1\" || serverEnv[\"PORT\"] !== \"3000\";\n console.log(\n \"Arrancando OpenExpert en http://127.0.0.1:3000 …\" +\n (customEndpoint ? \" (host o puerto personalizados: mira OPENEXPERT_HOST y PORT)\" : \"\"),\n );\n return run(process.execPath, [join(app, \".output\", \"server\", \"index.mjs\")], {\n cwd: app,\n env: serverEnv,\n });\n}\n\nexport function cmdUpdate(): number {\n const dir = appCacheDir(packageVersion());\n if (existsSync(dir)) {\n rmSync(dir, { recursive: true, force: true });\n console.log(`✓ caché del servidor eliminada (${dir}).`);\n } else {\n console.log(\"No hay servidor descargado que actualizar.\");\n }\n return 0;\n}\n","// SPDX-License-Identifier: MIT\n// `opencore desktop` — start the local server (unless it is already running)\n// and open the native OpenExpert window (the Tauri shell). This command owns\n// the server lifecycle so it can stop the server when the window closes.\n//\n// The repository is located from the CLI installation itself (not the current\n// directory), so `OpenExpert` works from anywhere.\n\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n ensureStandaloneApp,\n findRepoRoot,\n localServerEnv,\n packageRoot,\n packageVersion,\n secretsAsEnv,\n} from \"./lib.js\";\n\nfunction port(): string {\n return process.env[\"PORT\"] || \"3000\";\n}\n\nfunction appUrl(): string {\n return `http://localhost:${port()}`;\n}\n\n/**\n * Does this HTTP response come from the OpenExpert server? Every response\n * carries `x-request-id` (src/server.ts) and the security headers\n * (src/lib/http.server.ts). Any other app squatting the port (an unrelated\n * Express service, a dev server…) must NOT be reused: the window always points\n * at http://localhost:3000 and would show that other app instead (\"Cannot GET /\").\n */\nexport function looksLikeOpenExpert(status: number, headers: Headers): boolean {\n return status < 500 && headers.has(\"x-request-id\") && headers.has(\"x-frame-options\");\n}\n\ntype ServerProbe = \"openexpert\" | \"other\" | \"none\";\n\n/** Classify whatever is listening on the app port (if anything). */\nasync function probeServer(timeoutMs = 1500): Promise<ServerProbe> {\n try {\n const res = await fetch(appUrl(), {\n signal: AbortSignal.timeout(timeoutMs),\n redirect: \"manual\",\n });\n return looksLikeOpenExpert(res.status, res.headers) ? \"openexpert\" : \"other\";\n } catch {\n return \"none\";\n }\n}\n\nasync function waitForServer(timeoutMs = 120_000): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if ((await probeServer()) === \"openexpert\") return true;\n await new Promise((r) => setTimeout(r, 400));\n }\n return false;\n}\n\n/**\n * Find the source checkout, in order of confidence:\n * 1. OPENEXPERT_DESKTOP_REPO (baked by the installer),\n * 2. relative to the CLI installation (packages/opencore → repo root),\n * 3. walking up from the current directory.\n */\nfunction resolveRepo(cwd: string): string | null {\n const fromEnv = process.env[\"OPENEXPERT_DESKTOP_REPO\"];\n if (fromEnv) {\n const r = findRepoRoot(fromEnv);\n if (r) return r;\n }\n return findRepoRoot(packageRoot()) ?? findRepoRoot(cwd);\n}\n\n/** Newest modification time (ms) under a directory, or 0 if unreadable. */\nfunction newestMtime(dir: string): number {\n let newest = 0;\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) newest = Math.max(newest, newestMtime(full));\n else if (entry.isFile()) newest = Math.max(newest, statSync(full).mtimeMs);\n }\n } catch {\n // ignore unreadable paths\n }\n return newest;\n}\n\n/** True when the production build exists and is not older than src/. */\nfunction buildIsFresh(repo: string): boolean {\n const built = join(repo, \".output\", \"server\", \"index.mjs\");\n if (!existsSync(built)) return false;\n try {\n return statSync(built).mtimeMs >= newestMtime(join(repo, \"src\"));\n } catch {\n return true;\n }\n}\n\n/** Start the local server, reusing the source checkout when available. */\nasync function spawnServer(cwd: string, env: NodeJS.ProcessEnv): Promise<ChildProcess | null> {\n const repo = resolveRepo(cwd);\n if (repo) {\n const built = join(repo, \".output\", \"server\", \"index.mjs\");\n if (existsSync(built) && buildIsFresh(repo)) {\n return spawn(process.execPath, [built], {\n cwd: repo,\n env: { ...env, ...localServerEnv(), NODE_ENV: \"production\", PORT: port() },\n stdio: \"inherit\",\n });\n }\n console.log(\n existsSync(built)\n ? \"La build está desactualizada; arrancando en modo desarrollo…\"\n : \"Arrancando el servidor en modo desarrollo (no hay build)…\",\n );\n return spawn(\"npm\", [\"run\", \"dev\"], {\n cwd: repo,\n env: { ...env, ...localServerEnv() },\n stdio: \"inherit\",\n });\n }\n\n const app = await ensureStandaloneApp(packageVersion(), { log: (m) => console.log(` ${m}`) });\n if (!app) return null;\n return spawn(process.execPath, [join(app, \".output\", \"server\", \"index.mjs\")], {\n cwd: app,\n env: { ...env, ...localServerEnv(), NODE_ENV: \"production\", PORT: port() },\n stdio: \"inherit\",\n });\n}\n\nfunction findDesktopBinary(cwd: string): string | null {\n const fromEnv = process.env[\"OPENEXPERT_DESKTOP_BIN\"];\n if (fromEnv && existsSync(fromEnv)) return fromEnv;\n\n const candidates = [join(homedir(), \".local\", \"bin\", \"openexpert-desktop\")];\n const repo = resolveRepo(cwd);\n if (repo) {\n candidates.push(\n join(repo, \"src-tauri\", \"target\", \"release\", \"openexpert-desktop\"),\n join(repo, \"src-tauri\", \"target\", \"debug\", \"openexpert-desktop\"),\n );\n }\n return candidates.find((c) => existsSync(c)) ?? null;\n}\n\nexport async function cmdDesktop(cwd = process.cwd()): Promise<number> {\n const env = { ...process.env, ...secretsAsEnv(cwd) } as NodeJS.ProcessEnv;\n\n const bin = findDesktopBinary(cwd);\n if (!bin) {\n console.error(\n \"No se encontró la ventana de escritorio (openexpert-desktop).\\n\" +\n \"Compílala con `npx tauri build` o usa `npm run desktop:install`.\",\n );\n return 1;\n }\n\n let server: ChildProcess | null = null;\n let startedServer = false;\n\n const probe = await probeServer();\n if (probe === \"openexpert\") {\n console.log(`• Usando el servidor ya activo en ${appUrl()}`);\n } else if (probe === \"other\") {\n console.error(\n `El puerto ${port()} está ocupado por otra aplicación, no por OpenExpert.\\n` +\n `La ventana apunta siempre a ${appUrl()}, así que mostraría esa otra aplicación.\\n` +\n `Mira quién lo ocupa, libéralo (o cambia el puerto de ese programa) y vuelve a intentarlo:\\n` +\n ` ss -ltnp | grep :${port()} # o: lsof -i :${port()}\\n`,\n );\n return 1;\n } else {\n console.log(\"Arrancando el servidor local…\");\n server = await spawnServer(cwd, env);\n if (!server) {\n console.error(\n \"No se pudo arrancar el servidor.\\n\" +\n \"Si usas el código fuente, entra en el repositorio y ejecuta:\\n\" +\n \" npm ci && npm run build && npm run desktop:install\",\n );\n return 1;\n }\n startedServer = true;\n if (!(await waitForServer())) {\n console.error(\"El servidor no respondió a tiempo.\");\n server.kill(\"SIGTERM\");\n return 1;\n }\n }\n\n const stopServer = (): void => {\n if (startedServer && server && !server.killed) {\n try {\n server.kill(\"SIGTERM\");\n } catch {\n // already gone\n }\n }\n };\n\n const onSignal = (): void => {\n stopServer();\n process.exit(0);\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n\n console.log(\"Abriendo la ventana de OpenExpert…\");\n const code = await new Promise<number>((resolve) => {\n const win = spawn(bin, [], { stdio: \"inherit\", env });\n win.on(\"exit\", (c) => resolve(c ?? 0));\n });\n\n stopServer();\n return code;\n}\n","// SPDX-License-Identifier: MIT\n// Interactive setup wizard: pick a model provider, write config + secrets.\n\nimport * as p from \"@clack/prompts\";\nimport {\n DEFAULT_OLLAMA_URL,\n detectOllama,\n readConfig,\n writeConfig,\n writeSecrets,\n type FileConfig,\n type Provider,\n type Secrets,\n} from \"./lib.js\";\n\nexport type WizardResult = {\n config: FileConfig;\n secrets: Secrets;\n provider: Provider;\n modelId: string;\n started: boolean;\n};\n\nfunction bail(): never {\n p.cancel(\"Configuración cancelada.\");\n process.exit(1);\n}\n\nexport async function runWizard(\n opts: { cwd?: string; assumeYes?: boolean } = {},\n): Promise<WizardResult> {\n const cwd = opts.cwd ?? process.cwd();\n const existing = readConfig(cwd);\n const nonInteractive = opts.assumeYes || !process.stdin.isTTY;\n\n if (nonInteractive) {\n const ollama = await detectOllama();\n const config: FileConfig = {\n modelProvider: \"ollama\",\n modelId: ollama.models[0] ?? \"llama3.1\",\n ollamaBaseUrl: DEFAULT_OLLAMA_URL,\n dataDir: \"~/.openexpert\",\n };\n writeConfig(config, cwd);\n return { config, secrets: {}, provider: \"ollama\", modelId: config.modelId!, started: false };\n }\n\n p.intro(\"OpenExpert — configuración\");\n\n const spin = p.spinner();\n spin.start(\"Buscando Ollama local…\");\n const ollama = await detectOllama();\n spin.stop(\n ollama.up\n ? `Ollama detectado (${ollama.models.length} modelo(s))`\n : \"No se ha detectado Ollama\",\n );\n\n const choice = await p.select({\n message: \"¿Qué modelo quieres usar?\",\n options: [\n ...(ollama.up\n ? [\n {\n value: \"ollama\" as const,\n label: \"Modelo local (Ollama)\",\n hint: \"sin claves, datos en tu equipo\",\n },\n ]\n : []),\n { value: \"google\" as const, label: \"Google Gemini (clave gratuita)\", hint: \"AI Studio\" },\n { value: \"openai-compatible\" as const, label: \"Otro endpoint compatible\", hint: \"BYOK\" },\n ...(!ollama.up\n ? [{ value: \"install-ollama\" as const, label: \"Instalar Ollama\", hint: \"te muestro cómo\" }]\n : []),\n ],\n });\n if (p.isCancel(choice)) bail();\n\n if (choice === \"install-ollama\") {\n p.note(\n \"Instala Ollama y descarga un modelo:\\n\\n\" +\n \" curl -fsSL https://ollama.com/install.sh | sh\\n\" +\n \" ollama pull llama3.1\\n\\n\" +\n \"Vuelve a ejecutar `openexpert init` cuando esté listo.\",\n \"Instalar Ollama\",\n );\n p.outro(\"Sin cambios.\");\n process.exit(0);\n }\n\n const config: FileConfig = { dataDir: \"~/.openexpert\" };\n const secrets: Secrets = {};\n let modelId = \"llama3.1\";\n\n if (choice === \"ollama\") {\n const models = ollama.models.length ? ollama.models : [\"llama3.1\"];\n const picked = await p.select({\n message: \"Modelo de Ollama\",\n options: models.map((m) => ({ value: m, label: m })),\n });\n if (p.isCancel(picked)) bail();\n modelId = String(picked);\n config.modelProvider = \"ollama\";\n config.modelId = modelId;\n config.ollamaBaseUrl = DEFAULT_OLLAMA_URL;\n } else if (choice === \"google\") {\n const apiKey = await p.password({ message: \"GOOGLE_API_KEY (AI Studio)\" });\n if (p.isCancel(apiKey)) bail();\n const id = await p.text({ message: \"Modelo\", initialValue: \"gemini-2.5-flash\" });\n if (p.isCancel(id)) bail();\n modelId = String(id) || \"gemini-2.5-flash\";\n config.modelProvider = \"google\";\n config.modelId = modelId;\n secrets.GOOGLE_API_KEY = String(apiKey);\n } else if (choice === \"openai-compatible\") {\n const baseURL = await p.text({ message: \"Base URL (…/v1)\", initialValue: \"\" });\n if (p.isCancel(baseURL)) bail();\n const apiKey = await p.password({ message: \"API key\" });\n if (p.isCancel(apiKey)) bail();\n const id = await p.text({ message: \"Modelo\", initialValue: \"gpt-4o-mini\" });\n if (p.isCancel(id)) bail();\n modelId = String(id) || \"gpt-4o-mini\";\n config.modelProvider = \"openai-compatible\";\n config.modelId = modelId;\n secrets.OPENEXPERT_BASE_URL = String(baseURL);\n secrets.OPENEXPERT_MODEL_KEY = String(apiKey);\n }\n\n writeConfig({ ...existing, ...config }, cwd);\n if (Object.keys(secrets).length) writeSecrets({ ...secrets }, cwd);\n\n p.outro(\n `Configuración guardada en openexpert.json (modelo: ${config.modelProvider}:${modelId}).`,\n );\n\n const go = await p.confirm({ message: \"¿Arrancar ahora?\", initialValue: true });\n if (p.isCancel(go)) bail();\n\n return {\n config: { ...existing, ...config },\n secrets,\n provider: config.modelProvider as Provider,\n modelId,\n started: Boolean(go),\n };\n}\n","// SPDX-License-Identifier: MIT\n// OpenCore CLI entry point. Dispatches subcommands. See `run`.\n\nimport { cmdDoctor, cmdFix, cmdModels, cmdServe, cmdUpdate, cmdVersion } from \"./cli/commands.js\";\nimport { cmdDesktop } from \"./cli/desktop.js\";\nimport { runWizard } from \"./cli/wizard.js\";\n\nfunction help(): void {\n console.log(`OpenExpert — motor local\n\nUso:\n openexpert asistente de configuración y arranque\n openexpert init igual que sin argumentos\n openexpert serve arranca la edición local en http://localhost:3000\n openexpert desktop arranca el servidor y abre la ventana de escritorio\n openexpert doctor revisa tu configuración\n openexpert fix auto-configura lo que falte\n openexpert models lista los modelos del proveedor actual\n openexpert update limpia la caché del servidor descargado\n openexpert version muestra la versión\n\nEjemplos:\n npx @openexpert/opencore\n npx @openexpert/opencore serve\n\nDocker (sin Node):\n docker run -p 3000:3000 -v openexpert-data:/data ghcr.io/openexpert-ai/openexpert`);\n}\n\nexport async function run(argv: string[]): Promise<void> {\n const cmd = argv[0] ?? \"\";\n switch (cmd) {\n case \"\":\n case \"init\":\n case \"setup\": {\n const res = await runWizard({});\n if (res.started) process.exit(await cmdServe());\n return;\n }\n case \"doctor\":\n return process.exit(cmdDoctor());\n case \"fix\":\n return process.exit(await cmdFix());\n case \"models\":\n return process.exit(await cmdModels());\n case \"serve\":\n case \"dev\":\n return process.exit(await cmdServe());\n case \"desktop\":\n case \"app\": {\n const code = await cmdDesktop();\n return process.exit(code);\n }\n case \"update\":\n return process.exit(cmdUpdate());\n case \"version\":\n case \"--version\":\n case \"-v\":\n return process.exit(cmdVersion());\n case \"help\":\n case \"--help\":\n case \"-h\":\n help();\n return;\n default:\n console.error(`Comando desconocido: ${cmd}\\n`);\n help();\n return process.exit(1);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openexpert/opencore",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "OpenCore — open-source engine of OpenExpert (MIT). Config, model provider selector (Google / Ollama / OpenAI-compatible), storage and secrets interfaces, tool catalog, and CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
"typecheck": "tsc --noEmit"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@ai-sdk/openai": "^4.0.
|
|
87
|
+
"@ai-sdk/openai": "^4.0.91",
|
|
88
88
|
"@clack/prompts": "^1.8.1",
|
|
89
89
|
"ai": "^7.0.0"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
|
-
"@types/node": "^
|
|
92
|
+
"@types/node": "^26.6.5",
|
|
93
93
|
"tsup": "^8.3.5",
|
|
94
94
|
"typescript": "^5.8.3",
|
|
95
95
|
"vitest": "^5.0.3"
|