polymath-agent 0.4.0 → 0.5.0
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/README.md +21 -1
- package/dist/cli.js +283 -3
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -42,7 +42,25 @@ beats a pricey generalist at edits. Polymath assigns the cheapest model that gen
|
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
npm install -g polymath-agent
|
|
45
|
-
poly
|
|
45
|
+
poly setup # guided: optionally install a local LLM (Ollama) + connect models
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`poly setup` asks whether to install a local LLM, or skip the prompt with a flag:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
poly setup --local # install Ollama + pull a model (RAM-aware default)
|
|
52
|
+
poly setup --local -m qwen2.5-coder:7b # choose the model
|
|
53
|
+
poly setup --no-local # cloud only — just connect an OpenRouter key
|
|
54
|
+
poly setup --local -y # non-interactive (accept defaults / auto-install)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Keep everything current with `poly update` (the CLI via npm, the Ollama runtime, and
|
|
58
|
+
your local models) — add `--check` to only report what's available:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
poly update # update CLI + Ollama + re-pull local models
|
|
62
|
+
poly update --check # report-only
|
|
63
|
+
poly update --self # just the CLI (also --ollama, --models)
|
|
46
64
|
```
|
|
47
65
|
|
|
48
66
|
**From source** (no npm publish needed):
|
|
@@ -88,6 +106,8 @@ poly usage # cost by date + model
|
|
|
88
106
|
|
|
89
107
|
| Command | What it does |
|
|
90
108
|
|---|---|
|
|
109
|
+
| `poly setup` | First-run: optionally install a local LLM (Ollama) + connect models. `--local` / `--no-local` / `-m <model>` / `-y`. |
|
|
110
|
+
| `poly update` | Update the CLI (npm), the Ollama runtime, and local models. `--check`, `--self`, `--ollama`, `--models`. |
|
|
91
111
|
| `poly login` | Connect/replace your OpenRouter API key (Claude-Code-style onboarding). |
|
|
92
112
|
| `poly run [goal]` | Launch the interactive agent. Shows the recommended routing, then executes. |
|
|
93
113
|
| `poly recommend <goal>` | Pre-run recommendation: cheapest / best-value / best-quality model combos + savings. |
|
package/dist/cli.js
CHANGED
|
@@ -2180,6 +2180,274 @@ function logCompletion(result, taskType, sessionId, command = "run") {
|
|
|
2180
2180
|
return entry;
|
|
2181
2181
|
}
|
|
2182
2182
|
|
|
2183
|
+
// src/setup/commands.ts
|
|
2184
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
2185
|
+
|
|
2186
|
+
// src/util/prompt.ts
|
|
2187
|
+
import readline2 from "node:readline";
|
|
2188
|
+
function interactive() {
|
|
2189
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
2190
|
+
}
|
|
2191
|
+
function ask2(question) {
|
|
2192
|
+
return new Promise((resolve2) => {
|
|
2193
|
+
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
2194
|
+
rl.question(question, (a) => {
|
|
2195
|
+
rl.close();
|
|
2196
|
+
resolve2(a.trim());
|
|
2197
|
+
});
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2200
|
+
async function confirm(question, def = true) {
|
|
2201
|
+
if (!interactive()) return def;
|
|
2202
|
+
const hint = def ? "[Y/n]" : "[y/N]";
|
|
2203
|
+
const a = (await ask2(`${question} ${hint} `)).toLowerCase();
|
|
2204
|
+
if (!a) return def;
|
|
2205
|
+
return /^y/.test(a);
|
|
2206
|
+
}
|
|
2207
|
+
async function select(question, items, render2) {
|
|
2208
|
+
if (!interactive() || items.length <= 1) return items[0];
|
|
2209
|
+
console.log(question);
|
|
2210
|
+
items.forEach((it, i) => console.log(` ${i + 1}) ${render2(it)}`));
|
|
2211
|
+
const a = await ask2(`Choose [1-${items.length}] (default 1): `);
|
|
2212
|
+
const n = parseInt(a, 10);
|
|
2213
|
+
return Number.isInteger(n) && n >= 1 && n <= items.length ? items[n - 1] : items[0];
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
// src/setup/localllm.ts
|
|
2217
|
+
import { execSync, spawn } from "node:child_process";
|
|
2218
|
+
import os2 from "node:os";
|
|
2219
|
+
function suggestModels() {
|
|
2220
|
+
const ramGb = Math.round(os2.totalmem() / 1024 ** 3);
|
|
2221
|
+
const list = [];
|
|
2222
|
+
if (ramGb >= 13) list.push({ id: "qwen2.5-coder:7b", label: "Qwen2.5 Coder 7B", sizeGb: 4.7, note: "best coding pick for ~16GB" });
|
|
2223
|
+
list.push({ id: "llama3.2:3b", label: "Llama 3.2 3B", sizeGb: 2, note: "fast, light; great for cheap tasks" });
|
|
2224
|
+
if (ramGb >= 30) list.push({ id: "qwen2.5-coder:14b", label: "Qwen2.5 Coder 14B", sizeGb: 9, note: "stronger coding for 32GB+" });
|
|
2225
|
+
return list;
|
|
2226
|
+
}
|
|
2227
|
+
function totalRamGb() {
|
|
2228
|
+
return Math.round(os2.totalmem() / 1024 ** 3);
|
|
2229
|
+
}
|
|
2230
|
+
function which(cmd) {
|
|
2231
|
+
try {
|
|
2232
|
+
execSync(process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`, { stdio: "ignore" });
|
|
2233
|
+
return true;
|
|
2234
|
+
} catch {
|
|
2235
|
+
return false;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
function ollamaInstalled() {
|
|
2239
|
+
return which("ollama");
|
|
2240
|
+
}
|
|
2241
|
+
function ollamaVersion() {
|
|
2242
|
+
try {
|
|
2243
|
+
return execSync("ollama --version", { encoding: "utf8" }).trim();
|
|
2244
|
+
} catch {
|
|
2245
|
+
return null;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
async function ollamaServerUp(baseUrl = "http://localhost:11434") {
|
|
2249
|
+
try {
|
|
2250
|
+
const res = await fetch(`${baseUrl.replace(/\/v1\/?$/, "")}/api/version`);
|
|
2251
|
+
return res.ok;
|
|
2252
|
+
} catch {
|
|
2253
|
+
return false;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
async function installedModels(baseUrl = "http://localhost:11434") {
|
|
2257
|
+
try {
|
|
2258
|
+
const res = await fetch(`${baseUrl.replace(/\/v1\/?$/, "")}/api/tags`);
|
|
2259
|
+
if (!res.ok) return [];
|
|
2260
|
+
const json = await res.json();
|
|
2261
|
+
return (json.models ?? []).map((m) => m.name);
|
|
2262
|
+
} catch {
|
|
2263
|
+
return [];
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
function run(cmd, args) {
|
|
2267
|
+
return new Promise((resolve2) => {
|
|
2268
|
+
const child = spawn(cmd, args, { stdio: "inherit" });
|
|
2269
|
+
child.on("error", () => resolve2(false));
|
|
2270
|
+
child.on("exit", (code) => resolve2(code === 0));
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2273
|
+
function ollamaInstallPlan() {
|
|
2274
|
+
const platform = process.platform;
|
|
2275
|
+
if (platform === "darwin") {
|
|
2276
|
+
if (which("brew")) return { canAuto: true, command: { cmd: "brew", args: ["install", "ollama"] }, manual: "brew install ollama" };
|
|
2277
|
+
return { canAuto: false, manual: "Install Homebrew (https://brew.sh) then `brew install ollama`, or download https://ollama.com/download" };
|
|
2278
|
+
}
|
|
2279
|
+
if (platform === "linux") {
|
|
2280
|
+
return { canAuto: true, command: { cmd: "sh", args: ["-c", "curl -fsSL https://ollama.com/install.sh | sh"] }, manual: "curl -fsSL https://ollama.com/install.sh | sh" };
|
|
2281
|
+
}
|
|
2282
|
+
if (platform === "win32") {
|
|
2283
|
+
if (which("winget")) return { canAuto: true, command: { cmd: "winget", args: ["install", "-e", "--id", "Ollama.Ollama"] }, manual: "winget install Ollama.Ollama" };
|
|
2284
|
+
return { canAuto: false, manual: "Download the installer from https://ollama.com/download" };
|
|
2285
|
+
}
|
|
2286
|
+
return { canAuto: false, manual: "See https://ollama.com/download" };
|
|
2287
|
+
}
|
|
2288
|
+
async function ensureServer(baseUrl = "http://localhost:11434") {
|
|
2289
|
+
if (await ollamaServerUp(baseUrl)) return true;
|
|
2290
|
+
if (process.platform === "darwin" && which("brew")) {
|
|
2291
|
+
await run("brew", ["services", "start", "ollama"]);
|
|
2292
|
+
} else {
|
|
2293
|
+
try {
|
|
2294
|
+
const child = spawn("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
2295
|
+
child.unref();
|
|
2296
|
+
} catch {
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
for (let i = 0; i < 10; i++) {
|
|
2300
|
+
if (await ollamaServerUp(baseUrl)) return true;
|
|
2301
|
+
await delay(500);
|
|
2302
|
+
}
|
|
2303
|
+
return false;
|
|
2304
|
+
}
|
|
2305
|
+
function delay(ms) {
|
|
2306
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
// src/setup/commands.ts
|
|
2310
|
+
async function runSetup(opts) {
|
|
2311
|
+
console.log(c.bold("\n\u{1F527} Polymath setup\n"));
|
|
2312
|
+
const config = loadConfig();
|
|
2313
|
+
let wantLocal = opts.local;
|
|
2314
|
+
if (wantLocal === void 0) {
|
|
2315
|
+
wantLocal = await confirm(
|
|
2316
|
+
`Install a local LLM (Ollama) for $0, offline, no-API-key runs? (RAM detected: ${totalRamGb()}GB)`,
|
|
2317
|
+
true
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
if (wantLocal) {
|
|
2321
|
+
await setupLocal(opts, config);
|
|
2322
|
+
} else {
|
|
2323
|
+
config.local.enabled = false;
|
|
2324
|
+
saveConfig(config);
|
|
2325
|
+
console.log(c.dim("Skipping local LLM. (You can run `poly setup --local` later.)"));
|
|
2326
|
+
}
|
|
2327
|
+
const freshConfig = loadConfig();
|
|
2328
|
+
if (!resolveApiKey(freshConfig)) {
|
|
2329
|
+
const wantKey = opts.yes ? false : await confirm("Connect an OpenRouter API key for cloud models (300+ models)?", !wantLocal);
|
|
2330
|
+
if (wantKey) await runLogin();
|
|
2331
|
+
else if (!wantLocal) console.log(c.yellow("No models configured yet \u2014 run `poly login` or `poly setup --local`."));
|
|
2332
|
+
}
|
|
2333
|
+
console.log(c.green("\n\u2713 Setup complete.") + c.dim(' Try: poly recommend "add a dark-mode toggle" \xB7 poly run -w "..."'));
|
|
2334
|
+
}
|
|
2335
|
+
async function setupLocal(opts, config) {
|
|
2336
|
+
if (!ollamaInstalled()) {
|
|
2337
|
+
const plan = ollamaInstallPlan();
|
|
2338
|
+
console.log(c.cyan("Local LLM runtime: Ollama is not installed."));
|
|
2339
|
+
if (plan.canAuto && plan.command) {
|
|
2340
|
+
const go = opts.yes || await confirm(`Install Ollama via \`${plan.command.cmd} ${plan.command.args.join(" ")}\`?`, true);
|
|
2341
|
+
if (go) {
|
|
2342
|
+
const ok = await run(plan.command.cmd, plan.command.args);
|
|
2343
|
+
if (!ok) console.log(c.yellow("Auto-install failed. Manual: " + plan.manual));
|
|
2344
|
+
} else {
|
|
2345
|
+
console.log(c.dim("Manual install: " + plan.manual));
|
|
2346
|
+
}
|
|
2347
|
+
} else {
|
|
2348
|
+
console.log(c.yellow("Install manually: " + plan.manual));
|
|
2349
|
+
}
|
|
2350
|
+
} else {
|
|
2351
|
+
console.log(c.green("\u2713 Ollama present ") + c.dim(ollamaVersion() ?? ""));
|
|
2352
|
+
}
|
|
2353
|
+
if (!ollamaInstalled()) {
|
|
2354
|
+
console.log(c.yellow("Ollama still not on PATH \u2014 re-run `poly setup --local` after installing."));
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2357
|
+
process.stdout.write("Starting Ollama server\u2026 ");
|
|
2358
|
+
const up = await ensureServer(config.local.baseUrl);
|
|
2359
|
+
console.log(up ? c.green("ok") : c.yellow("could not confirm (start it with `ollama serve`)"));
|
|
2360
|
+
const have = await installedModels(config.local.baseUrl);
|
|
2361
|
+
let modelId = opts.model;
|
|
2362
|
+
if (!modelId) {
|
|
2363
|
+
const suggestions = suggestModels().filter((s) => !have.includes(s.id));
|
|
2364
|
+
if (have.length && !suggestions.length) {
|
|
2365
|
+
modelId = have[0];
|
|
2366
|
+
console.log(c.dim(`Using already-installed model ${modelId}.`));
|
|
2367
|
+
} else {
|
|
2368
|
+
const pick = opts.yes ? suggestModels()[0] : await select(
|
|
2369
|
+
"Pick a model to download:",
|
|
2370
|
+
suggestModels(),
|
|
2371
|
+
(s) => `${s.label} (~${s.sizeGb}GB) \u2014 ${s.note}${have.includes(s.id) ? " [installed]" : ""}`
|
|
2372
|
+
);
|
|
2373
|
+
modelId = pick.id;
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
if (!have.includes(modelId)) {
|
|
2377
|
+
console.log(c.cyan(`Downloading ${modelId}\u2026`));
|
|
2378
|
+
const ok = await run("ollama", ["pull", modelId]);
|
|
2379
|
+
if (!ok) {
|
|
2380
|
+
console.log(c.yellow(`Could not pull ${modelId}. Run \`ollama pull ${modelId}\` manually.`));
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
config.local.enabled = true;
|
|
2385
|
+
saveConfig(config);
|
|
2386
|
+
console.log(c.green(`\u2713 Local LLM ready: ${modelId} \u2192 local/${modelId} ($0). `) + c.dim("Enabled in config."));
|
|
2387
|
+
}
|
|
2388
|
+
function cmp(a, b) {
|
|
2389
|
+
const pa = a.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
2390
|
+
const pb = b.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
2391
|
+
for (let i = 0; i < 3; i++) {
|
|
2392
|
+
if ((pa[i] ?? 0) !== (pb[i] ?? 0)) return (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
2393
|
+
}
|
|
2394
|
+
return 0;
|
|
2395
|
+
}
|
|
2396
|
+
async function runUpdate(currentVersion, opts) {
|
|
2397
|
+
const all = !opts.self && !opts.ollama && !opts.models;
|
|
2398
|
+
console.log(c.bold("\n\u2B06\uFE0F Polymath update") + (opts.check ? c.dim(" (check only)") : "") + "\n");
|
|
2399
|
+
if (all || opts.self) {
|
|
2400
|
+
let latest = "";
|
|
2401
|
+
try {
|
|
2402
|
+
latest = execSync2("npm view polymath-agent version", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
2403
|
+
} catch {
|
|
2404
|
+
latest = "";
|
|
2405
|
+
}
|
|
2406
|
+
if (!latest) {
|
|
2407
|
+
console.log(c.dim("CLI: could not reach npm registry."));
|
|
2408
|
+
} else if (cmp(latest, currentVersion) > 0) {
|
|
2409
|
+
console.log(c.yellow(`CLI: ${currentVersion} \u2192 ${latest} available.`));
|
|
2410
|
+
if (!opts.check) {
|
|
2411
|
+
const ok = await run("npm", ["install", "-g", `polymath-agent@${latest}`]);
|
|
2412
|
+
console.log(ok ? c.green(`\u2713 Updated to ${latest}.`) : c.red("npm update failed (try: sudo npm i -g polymath-agent@latest)."));
|
|
2413
|
+
} else {
|
|
2414
|
+
console.log(c.dim(" Run `poly update` to install."));
|
|
2415
|
+
}
|
|
2416
|
+
} else {
|
|
2417
|
+
console.log(c.green(`\u2713 CLI is up to date (${currentVersion}).`));
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
if (all || opts.ollama) {
|
|
2421
|
+
if (!ollamaInstalled()) {
|
|
2422
|
+
console.log(c.dim("Ollama: not installed (run `poly setup --local`)."));
|
|
2423
|
+
} else if (opts.check) {
|
|
2424
|
+
console.log(c.dim(`Ollama: ${ollamaVersion() ?? "present"} (update with \`poly update --ollama\`).`));
|
|
2425
|
+
} else if (process.platform === "darwin") {
|
|
2426
|
+
console.log(c.cyan("Updating Ollama\u2026"));
|
|
2427
|
+
await run("brew", ["upgrade", "ollama"]).then((ok) => !ok && console.log(c.dim(" (brew upgrade skipped/failed)")));
|
|
2428
|
+
} else if (process.platform === "linux") {
|
|
2429
|
+
await run("sh", ["-c", "curl -fsSL https://ollama.com/install.sh | sh"]);
|
|
2430
|
+
} else {
|
|
2431
|
+
console.log(c.dim("Ollama: update via your installer (winget upgrade Ollama.Ollama)."));
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
if (all || opts.models) {
|
|
2435
|
+
const config = loadConfig();
|
|
2436
|
+
const models = await installedModels(config.local.baseUrl);
|
|
2437
|
+
if (!models.length) {
|
|
2438
|
+
console.log(c.dim("Models: none installed."));
|
|
2439
|
+
} else if (opts.check) {
|
|
2440
|
+
console.log(c.dim(`Models: ${models.join(", ")} (re-pull to update).`));
|
|
2441
|
+
} else {
|
|
2442
|
+
for (const m of models) {
|
|
2443
|
+
console.log(c.cyan(`Updating ${m}\u2026`));
|
|
2444
|
+
await run("ollama", ["pull", m]);
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
console.log("");
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2183
2451
|
// src/tui/App.tsx
|
|
2184
2452
|
import { useState, useEffect, useCallback } from "react";
|
|
2185
2453
|
import { Box, Text, useApp, useInput } from "ink";
|
|
@@ -2189,7 +2457,7 @@ import Spinner from "ink-spinner";
|
|
|
2189
2457
|
// src/agent/tools.ts
|
|
2190
2458
|
import fs4 from "node:fs";
|
|
2191
2459
|
import path2 from "node:path";
|
|
2192
|
-
import { execSync } from "node:child_process";
|
|
2460
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
2193
2461
|
var TOOL_SCHEMAS = [
|
|
2194
2462
|
{
|
|
2195
2463
|
type: "function",
|
|
@@ -2332,7 +2600,7 @@ function executeTool(name, argsJson, ctx) {
|
|
|
2332
2600
|
}
|
|
2333
2601
|
case "run_command": {
|
|
2334
2602
|
if (!ctx.allowCommands) return { result: "Denied: run_command is disabled." };
|
|
2335
|
-
const out =
|
|
2603
|
+
const out = execSync3(String(args.command), {
|
|
2336
2604
|
cwd: ctx.cwd,
|
|
2337
2605
|
encoding: "utf8",
|
|
2338
2606
|
env: scrubbedEnv(),
|
|
@@ -3013,8 +3281,9 @@ function truncate2(s, n) {
|
|
|
3013
3281
|
}
|
|
3014
3282
|
|
|
3015
3283
|
// src/index.ts
|
|
3284
|
+
var VERSION = "0.5.0";
|
|
3016
3285
|
var program = new Command();
|
|
3017
|
-
program.name("poly").description("Polymath \u2014 cost-optimized, multi-model TUI coding agent").version(
|
|
3286
|
+
program.name("poly").description("Polymath \u2014 cost-optimized, multi-model TUI coding agent").version(VERSION);
|
|
3018
3287
|
function client(config) {
|
|
3019
3288
|
return new OpenRouterClient({
|
|
3020
3289
|
apiKey: resolveApiKey(config),
|
|
@@ -3085,6 +3354,14 @@ async function loadCatalog(config, refresh = false) {
|
|
|
3085
3354
|
}
|
|
3086
3355
|
return models;
|
|
3087
3356
|
}
|
|
3357
|
+
program.command("setup").description("First-run setup: optionally install a local LLM (Ollama) and connect models").option("--local", "install a local LLM (Ollama) \u2014 skips the prompt").option("--no-local", "skip the local LLM \u2014 skips the prompt").option("-m, --model <id>", "local model to pull (e.g. qwen2.5-coder:7b)").option("-y, --yes", "accept defaults / auto-install without prompts", false).action(async (opts) => {
|
|
3358
|
+
const argv = process.argv;
|
|
3359
|
+
const local = argv.includes("--local") ? true : argv.includes("--no-local") ? false : void 0;
|
|
3360
|
+
await runSetup({ local, model: opts.model, yes: !!opts.yes });
|
|
3361
|
+
});
|
|
3362
|
+
program.command("update").description("Update Polymath, the Ollama runtime, and local models").option("--check", "report available updates without installing", false).option("--self", "only the Polymath CLI", false).option("--ollama", "only the Ollama runtime", false).option("--models", "only the local models", false).action(async (opts) => {
|
|
3363
|
+
await runUpdate(VERSION, { check: !!opts.check, self: !!opts.self, ollama: !!opts.ollama, models: !!opts.models });
|
|
3364
|
+
});
|
|
3088
3365
|
program.command("login").description("Connect Polymath to OpenRouter (set/replace your API key)").action(async () => {
|
|
3089
3366
|
await runLogin();
|
|
3090
3367
|
});
|
|
@@ -3294,3 +3571,6 @@ program.parseAsync().catch((err) => {
|
|
|
3294
3571
|
console.error(c.red(err?.message ?? String(err)));
|
|
3295
3572
|
process.exit(1);
|
|
3296
3573
|
});
|
|
3574
|
+
export {
|
|
3575
|
+
VERSION
|
|
3576
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polymath-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Polymath — a cost-optimized, multi-model TUI coding agent. Decomposes work into typed tasks, routes each task to the cheapest capable model via OpenRouter, and logs real usage/cost by date + model.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"dev": "tsx src/index.ts",
|
|
19
19
|
"start": "node dist/cli.js",
|
|
20
20
|
"prepare": "node esbuild.config.mjs",
|
|
21
|
-
"prepublishOnly": "npm run typecheck && npm run build"
|
|
21
|
+
"prepublishOnly": "npm run typecheck && npm run build",
|
|
22
|
+
"postinstall": "node -e \"process.stdout.isTTY && console.log('\\n\\u2728 Polymath ready. Run: poly setup (connect models / optionally install a local LLM)\\n')\" || true"
|
|
22
23
|
},
|
|
23
24
|
"keywords": [
|
|
24
25
|
"ai",
|