offgrid-ai 0.3.12 → 0.3.14
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/package.json +1 -1
- package/src/cli.mjs +10 -17
- package/src/command.mjs +21 -0
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import { pc, formatBytes, renderRows, renderSection, startInteractive, createPro
|
|
|
13
13
|
import { checkForUpdate, currentPackageVersion, detectInvocation, updateCommand, runUpdateCommand } from "./updates.mjs";
|
|
14
14
|
import { removeInstallerPathEntries } from "./shell-path.mjs";
|
|
15
15
|
import { configureLocalProfile } from "./profile-setup.mjs";
|
|
16
|
+
import { buildPrettyCommand } from "./command.mjs";
|
|
16
17
|
|
|
17
18
|
// ── Entry point ────────────────────────────────────────────────────────────
|
|
18
19
|
|
|
@@ -389,14 +390,12 @@ async function manageProfiles(prompt, profiles) {
|
|
|
389
390
|
label: p.label,
|
|
390
391
|
hint: `${p.modelAlias} · ${p.baseUrl}`,
|
|
391
392
|
}));
|
|
392
|
-
choices.push({ value: "__back", label: "← Back" });
|
|
393
393
|
|
|
394
394
|
const selected = await prompt.choice("Which profile?", choices, choices[0].value);
|
|
395
|
-
if (selected === "__back") return;
|
|
396
|
-
|
|
397
395
|
const profile = await readProfile(selected);
|
|
398
396
|
const backend = backendFor(profile.backend);
|
|
399
397
|
const isManaged = backend.type === "managed-server";
|
|
398
|
+
const piConfigured = await hasPiModel(profile);
|
|
400
399
|
|
|
401
400
|
// Show profile details
|
|
402
401
|
console.log("");
|
|
@@ -411,32 +410,26 @@ async function manageProfiles(prompt, profiles) {
|
|
|
411
410
|
["Memory", existsSync(profile.modelPath) ? formatBytes(statSync(profile.modelPath).size) : "unknown"],
|
|
412
411
|
] : []),
|
|
413
412
|
["Alias", pc.cyan(profile.modelAlias)],
|
|
414
|
-
["Pi",
|
|
413
|
+
["Pi", piConfigured ? pc.green("configured") : pc.yellow("not synced")],
|
|
415
414
|
])));
|
|
416
415
|
|
|
417
416
|
if (!isManaged && profile.commandArgv) {
|
|
418
417
|
console.log("");
|
|
419
|
-
console.log(pc.bold("
|
|
420
|
-
console.log(pc.dim(profile
|
|
418
|
+
console.log(pc.bold("llama-server command"));
|
|
419
|
+
console.log(pc.dim(buildPrettyCommand(profile)));
|
|
421
420
|
}
|
|
422
421
|
|
|
423
422
|
const action = await prompt.choice("Action", [
|
|
424
|
-
{ value: "sync", label: "Sync Pi config", hint: "Update ~/.pi/agent/models.json" },
|
|
423
|
+
{ value: "sync", label: piConfigured ? `${pc.green("✓")} Pi config synced` : "Sync Pi config", hint: piConfigured ? "Already in ~/.pi/agent/models.json" : "Update ~/.pi/agent/models.json" },
|
|
425
424
|
{ value: "run", label: "Run", hint: "Start server + Pi" },
|
|
426
425
|
...(isManaged ? [] : [{ value: "server", label: "Server only", hint: "Start server, no harness" }]),
|
|
427
426
|
{ value: "remove", label: "Remove", hint: "Delete profile + Pi config" },
|
|
428
|
-
{ value: "__back", label: "← Back" },
|
|
429
427
|
], "sync");
|
|
430
428
|
|
|
431
|
-
if (action === "sync")
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
} else if (action === "server") {
|
|
436
|
-
return await runProfile(profile, { with: "server" });
|
|
437
|
-
} else if (action === "remove") {
|
|
438
|
-
await removeProfileInteractive(profile.id);
|
|
439
|
-
}
|
|
429
|
+
if (action === "sync") return await syncPiConfig(profile);
|
|
430
|
+
if (action === "run") return await runProfile(profile);
|
|
431
|
+
if (action === "server") return await runProfile(profile, { with: "server" });
|
|
432
|
+
if (action === "remove") return await removeProfileInteractive(profile.id);
|
|
440
433
|
}
|
|
441
434
|
|
|
442
435
|
async function removeProfileInteractive(id) {
|
package/src/command.mjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function buildPrettyCommand(profile, binary = "llama-server") {
|
|
2
|
+
const argv = profile.commandArgv ?? [];
|
|
3
|
+
const lines = [`${quoteShell(binary)} \\`];
|
|
4
|
+
for (let i = 0; i < argv.length; i++) {
|
|
5
|
+
const arg = argv[i];
|
|
6
|
+
const next = argv[i + 1];
|
|
7
|
+
const hasValue = arg.startsWith("--") && next && !next.startsWith("--");
|
|
8
|
+
if (hasValue) {
|
|
9
|
+
lines.push(` ${arg} ${quoteShell(next)}${i + 2 < argv.length ? " \\" : ""}`);
|
|
10
|
+
i += 1;
|
|
11
|
+
} else {
|
|
12
|
+
lines.push(` ${arg}${i + 1 < argv.length ? " \\" : ""}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return lines.join("\n");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function quoteShell(value) {
|
|
19
|
+
const text = String(value);
|
|
20
|
+
return /^[A-Za-z0-9_/@%+=:,.-]+$/u.test(text) ? text : `'${text.replace(/'/gu, `'"'"'`)}'`;
|
|
21
|
+
}
|