@freesyntax/notch-cli 0.5.20 → 0.5.22

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.
Files changed (40) hide show
  1. package/dist/{apply-patch-D5PDUXUC.js → apply-patch-U6K67CMT.js} +1 -0
  2. package/dist/auth-UAMMP5IJ.js +29 -0
  3. package/dist/chunk-4HPRBCSY.js +167 -0
  4. package/dist/chunk-6NKRMZTX.js +198 -0
  5. package/dist/{chunk-YBYF7L4A.js → chunk-EPSOOCNB.js} +1832 -1331
  6. package/dist/chunk-FZVPGJJW.js +511 -0
  7. package/dist/chunk-GFVLHUSS.js +155 -0
  8. package/dist/chunk-J66N6AFH.js +137 -0
  9. package/dist/chunk-JXQ4HZ47.js +544 -0
  10. package/dist/chunk-KCAR5DOB.js +52 -0
  11. package/dist/chunk-KFQGP6VL.js +33 -0
  12. package/dist/chunk-O6AKZ4OH.js +0 -0
  13. package/dist/{chunk-6M6CXXWR.js → chunk-PKZKVOAN.js} +209 -1
  14. package/dist/{chunk-FIFC4V2R.js → chunk-PPEBWOMJ.js} +91 -7
  15. package/dist/compression-YJLWEHCC.js +33 -0
  16. package/dist/config-set-3IWEVZQ4.js +110 -0
  17. package/dist/{edit-JEFEK43H.js → edit-6QYAXVNU.js} +1 -0
  18. package/dist/{git-5T5TSQTX.js → git-DNQ5EELH.js} +1 -0
  19. package/dist/{github-DWRGWX6U.js → github-34T4QQIH.js} +1 -0
  20. package/dist/{glob-BI3P4C7Q.js → glob-XT43LEJ4.js} +1 -0
  21. package/dist/{grep-VZ3I5GNW.js → grep-T2CXYNRI.js} +1 -0
  22. package/dist/index.js +2606 -960
  23. package/dist/{lsp-UPY6I3L7.js → lsp-JXQVU7NP.js} +1 -0
  24. package/dist/model-download-3NDKS3VM.js +176 -0
  25. package/dist/{notebook-FXJBTSPA.js → notebook-MFODW345.js} +1 -0
  26. package/dist/ollama-bench-5V5CCOCQ.js +194 -0
  27. package/dist/ollama-launch-P5KBK7AJ.js +22 -0
  28. package/dist/ollama-usage-3PROM2WC.js +70 -0
  29. package/dist/{plugins-OG2P75K5.js → plugins-PNGRZLFW.js} +1 -0
  30. package/dist/{read-OVJG2XKW.js → read-B64XE7N3.js} +1 -0
  31. package/dist/{server-W7FRCVRZ.js → server-IGOZHW52.js} +17 -15
  32. package/dist/session-index-7FWEVP6E.js +22 -0
  33. package/dist/{shell-4X545EVN.js → shell-BOZTHQUT.js} +1 -0
  34. package/dist/{task-OS3E5F3X.js → task-67G4KLYC.js} +1 -0
  35. package/dist/{tools-Q7CDHB4K.js → tools-XWKCW4RN.js} +4 -1
  36. package/dist/{web-fetch-KNIV3Z3W.js → web-fetch-OTNDICGJ.js} +1 -0
  37. package/dist/{write-NNHLOTYK.js → write-ZOSB7I4J.js} +1 -0
  38. package/package.json +2 -1
  39. package/dist/auth-JQX6MHJG.js +0 -16
  40. package/dist/compression-UTB2Y4BB.js +0 -16
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  lspTool
3
3
  } from "./chunk-TH6GKC7E.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  lspTool
6
7
  };
@@ -0,0 +1,176 @@
1
+ import {
2
+ MODEL_CATALOG
3
+ } from "./chunk-JXQ4HZ47.js";
4
+ import "./chunk-PPEBWOMJ.js";
5
+ import "./chunk-KFQGP6VL.js";
6
+
7
+ // src/commands/model-download.ts
8
+ import { spawn } from "child_process";
9
+ import { statfs, promises as fsp } from "fs";
10
+ import os from "os";
11
+ import path from "path";
12
+ import chalk from "chalk";
13
+ async function probeSystemCapabilities(cacheDir = os.homedir()) {
14
+ const totalRamBytes = os.totalmem();
15
+ const totalRamGb = Number((totalRamBytes / 1024 / 1024 / 1024).toFixed(1));
16
+ const freeDiskGb = await new Promise((resolve) => {
17
+ try {
18
+ statfs(cacheDir, (err, stats) => {
19
+ if (err) return resolve(null);
20
+ const freeBytes = Number(stats.bsize) * Number(stats.bavail);
21
+ resolve(Math.round(freeBytes / 1024 / 1024 / 1024));
22
+ });
23
+ } catch {
24
+ resolve(null);
25
+ }
26
+ });
27
+ const gpu = await probeNvidiaSmi();
28
+ return {
29
+ platform: process.platform,
30
+ totalRamGb,
31
+ freeDiskGb,
32
+ gpuVramGb: gpu?.vramGb ?? null,
33
+ gpuName: gpu?.name ?? null
34
+ };
35
+ }
36
+ function probeNvidiaSmi() {
37
+ return new Promise((resolve) => {
38
+ try {
39
+ const proc = spawn("nvidia-smi", [
40
+ "--query-gpu=name,memory.total",
41
+ "--format=csv,noheader,nounits"
42
+ ], { stdio: ["ignore", "pipe", "ignore"] });
43
+ let buf = "";
44
+ proc.stdout.on("data", (c) => {
45
+ buf += c.toString();
46
+ });
47
+ proc.on("error", () => resolve(null));
48
+ proc.on("close", (code) => {
49
+ if (code !== 0 || !buf.trim()) return resolve(null);
50
+ const first = buf.split("\n")[0]?.trim();
51
+ if (!first) return resolve(null);
52
+ const [name, memStr] = first.split(",").map((s) => s.trim());
53
+ const memMb = Number(memStr);
54
+ if (!name || !Number.isFinite(memMb) || memMb <= 0) return resolve(null);
55
+ resolve({ vramGb: Number((memMb / 1024).toFixed(1)), name });
56
+ });
57
+ } catch {
58
+ resolve(null);
59
+ }
60
+ });
61
+ }
62
+ function evaluateHardware(info, caps) {
63
+ const hw = info.hardware;
64
+ const checks = [];
65
+ checks.push({
66
+ label: "RAM",
67
+ required: `${hw.ramGb} GB`,
68
+ detected: `${caps.totalRamGb} GB`,
69
+ status: caps.totalRamGb >= hw.ramGb ? "pass" : caps.totalRamGb >= hw.ramGb * 0.75 ? "warn" : "fail"
70
+ });
71
+ checks.push({
72
+ label: "Disk",
73
+ required: `${hw.diskGb} GB`,
74
+ detected: caps.freeDiskGb == null ? "unknown" : `${caps.freeDiskGb} GB free`,
75
+ status: caps.freeDiskGb == null ? "unknown" : caps.freeDiskGb >= hw.diskGb ? "pass" : "fail"
76
+ });
77
+ if (caps.gpuVramGb == null) {
78
+ checks.push({
79
+ label: "GPU",
80
+ required: `${hw.vramGb} GB VRAM (${hw.recommendedGpu})`,
81
+ detected: "no CUDA GPU detected",
82
+ // Apple silicon users run well on unified memory with Ollama even
83
+ // without a discrete GPU — don't fail, just warn so the CLI stays
84
+ // usable on Macs.
85
+ status: caps.platform === "darwin" ? "warn" : "warn"
86
+ });
87
+ } else {
88
+ checks.push({
89
+ label: "GPU",
90
+ required: `${hw.vramGb} GB VRAM (${hw.recommendedGpu})`,
91
+ detected: `${caps.gpuVramGb} GB \xB7 ${caps.gpuName ?? "unknown"}`,
92
+ status: caps.gpuVramGb >= hw.vramGb ? "pass" : caps.gpuVramGb >= hw.vramGb * 0.75 ? "warn" : "fail"
93
+ });
94
+ }
95
+ const ok = checks.every((c) => c.status === "pass" || c.status === "warn");
96
+ const failures = checks.filter((c) => c.status === "fail").map((c) => c.label);
97
+ const summary = ok ? `Your system meets the ${hw.tier} tier requirements for ${info.label}.` : `Your system is under-resourced for ${info.label} \u2014 ${failures.join(", ")} below minimum.`;
98
+ return { ok, checks, summary };
99
+ }
100
+ function renderVerdict(info, verdict) {
101
+ const lines = [];
102
+ lines.push(chalk.gray(` \u2500\u2500\u2500 ${info.label} (${info.size}) \xB7 ${info.hardware.tier} tier \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
103
+ for (const c of verdict.checks) {
104
+ const icon = c.status === "pass" ? chalk.green("\u2713") : c.status === "warn" ? chalk.yellow("!") : c.status === "fail" ? chalk.red("\u2717") : chalk.gray("?");
105
+ lines.push(` ${icon} ${c.label.padEnd(5)} required: ${chalk.white(c.required.padEnd(34))} detected: ${chalk.gray(c.detected)}`);
106
+ }
107
+ lines.push("");
108
+ lines.push(verdict.ok ? chalk.green(` ${verdict.summary}`) : chalk.yellow(` ${verdict.summary}`));
109
+ return lines.join("\n");
110
+ }
111
+ var activeDownloads = /* @__PURE__ */ new Map();
112
+ function getDownloadStatus(id) {
113
+ return activeDownloads.get(id) ?? null;
114
+ }
115
+ function listDownloads() {
116
+ return [...activeDownloads.values()];
117
+ }
118
+ function getHuggingFaceCacheDir() {
119
+ const hfHome = process.env.HF_HOME ?? process.env.HUGGINGFACE_HUB_CACHE;
120
+ if (hfHome) return hfHome;
121
+ return path.join(os.homedir(), ".cache", "huggingface", "hub");
122
+ }
123
+ async function startModelDownload(id) {
124
+ const info = MODEL_CATALOG[id];
125
+ if (!info) throw new Error(`Unknown Notch model: ${id}`);
126
+ if (!info.hfRepo) {
127
+ throw new Error(
128
+ `${info.label} is not yet available for local download. Use the hosted Notch API in the meantime \u2014 run \`notch login\` to get a key.`
129
+ );
130
+ }
131
+ const existing = activeDownloads.get(id);
132
+ if (existing && existing.result == null) return existing;
133
+ const cacheDir = getHuggingFaceCacheDir();
134
+ await fsp.mkdir(cacheDir, { recursive: true });
135
+ const handle = {
136
+ modelId: id,
137
+ startedAt: /* @__PURE__ */ new Date(),
138
+ cacheDir,
139
+ pid: 0,
140
+ lastLine: "queued",
141
+ result: null
142
+ };
143
+ const args = ["download", info.hfRepo, "--local-dir-use-symlinks", "False"];
144
+ const proc = spawn("huggingface-cli", args, {
145
+ stdio: ["ignore", "pipe", "pipe"],
146
+ detached: false,
147
+ env: { ...process.env, HF_HUB_ENABLE_HF_TRANSFER: "1" }
148
+ });
149
+ handle.pid = proc.pid ?? 0;
150
+ activeDownloads.set(id, handle);
151
+ const absorb = (buf) => {
152
+ const text = buf.toString();
153
+ const line = text.split(/\r?\n/).filter((l) => l.trim().length > 0).pop();
154
+ if (line) handle.lastLine = line.slice(0, 200);
155
+ };
156
+ proc.stdout?.on("data", absorb);
157
+ proc.stderr?.on("data", absorb);
158
+ proc.on("error", (err) => {
159
+ handle.result = { code: null, error: err.message };
160
+ handle.lastLine = `error: ${err.message}`;
161
+ });
162
+ proc.on("close", (code) => {
163
+ handle.result = { code, error: code === 0 ? null : `exited with code ${code ?? "null"}` };
164
+ if (code === 0) handle.lastLine = "complete";
165
+ });
166
+ return handle;
167
+ }
168
+ export {
169
+ evaluateHardware,
170
+ getDownloadStatus,
171
+ getHuggingFaceCacheDir,
172
+ listDownloads,
173
+ probeSystemCapabilities,
174
+ renderVerdict,
175
+ startModelDownload
176
+ };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  notebookTool
3
3
  } from "./chunk-KZAS754V.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  notebookTool
6
7
  };
@@ -0,0 +1,194 @@
1
+ import {
2
+ printNotReachable,
3
+ renderProgressLine,
4
+ resolveEndpoint
5
+ } from "./chunk-FZVPGJJW.js";
6
+ import {
7
+ detectDaemon,
8
+ listModels,
9
+ pullModel
10
+ } from "./chunk-GFVLHUSS.js";
11
+ import "./chunk-O6AKZ4OH.js";
12
+ import "./chunk-KCAR5DOB.js";
13
+ import {
14
+ resolveByokModel
15
+ } from "./chunk-JXQ4HZ47.js";
16
+ import "./chunk-PPEBWOMJ.js";
17
+ import "./chunk-KFQGP6VL.js";
18
+
19
+ // src/commands/ollama-bench.ts
20
+ import fs from "fs/promises";
21
+ import path from "path";
22
+ import chalk from "chalk";
23
+ import { streamText } from "ai";
24
+ var DEFAULT_PROMPT = "Write a 5-line Python function that returns the n-th Fibonacci number.";
25
+ var DEFAULT_BENCH_MODELS = [
26
+ "qwen3-coder:30b",
27
+ "llama3.2:latest",
28
+ "gpt-oss:20b"
29
+ ];
30
+ function approximateTokens(text) {
31
+ if (!text) return 0;
32
+ return Math.round(text.split(/\s+/).filter(Boolean).length / 0.75);
33
+ }
34
+ async function ensureModelPresent(modelName, baseUrl, apiKey, allowPull) {
35
+ try {
36
+ const installed = await listModels(baseUrl, { apiKey });
37
+ if (installed.some((m) => m.name === modelName)) return true;
38
+ } catch {
39
+ return false;
40
+ }
41
+ if (!allowPull) return false;
42
+ console.log(chalk.gray(`
43
+ Pulling ${modelName} (not installed)...
44
+ `));
45
+ const lastStatus = { label: "" };
46
+ try {
47
+ for await (const ev of pullModel(modelName, baseUrl, { apiKey })) {
48
+ renderProgressLine(ev, lastStatus);
49
+ }
50
+ } catch (err) {
51
+ process.stdout.write("\n");
52
+ console.error(chalk.red(` Pull failed: ${err.message}`));
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ async function runOne(model, prompt, baseUrl, apiKey, isCloud) {
58
+ const providerId = isCloud ? "ollama-cloud" : "ollama";
59
+ const { model: languageModel } = resolveByokModel({
60
+ provider: providerId,
61
+ model,
62
+ apiKey,
63
+ baseUrl
64
+ });
65
+ const messages = [{ role: "user", content: prompt }];
66
+ const started = Date.now();
67
+ let firstTokenAt = 0;
68
+ let output = "";
69
+ try {
70
+ const stream = streamText({ model: languageModel, messages });
71
+ for await (const chunk of stream.textStream) {
72
+ if (!firstTokenAt) firstTokenAt = Date.now();
73
+ output += chunk;
74
+ }
75
+ const finished = Date.now();
76
+ const usage = await stream.usage;
77
+ const promptTokens = usage?.promptTokens ?? approximateTokens(prompt);
78
+ const completionTokens = usage?.completionTokens ?? approximateTokens(output);
79
+ const totalMs = finished - started;
80
+ const firstTokenMs = firstTokenAt ? firstTokenAt - started : totalMs;
81
+ const seconds = Math.max(1e-3, totalMs / 1e3);
82
+ return {
83
+ model,
84
+ firstTokenMs,
85
+ totalMs,
86
+ tokensPerSec: completionTokens / seconds,
87
+ promptTokens,
88
+ completionTokens,
89
+ output
90
+ };
91
+ } catch (err) {
92
+ return {
93
+ model,
94
+ firstTokenMs: 0,
95
+ totalMs: Date.now() - started,
96
+ tokensPerSec: 0,
97
+ promptTokens: 0,
98
+ completionTokens: 0,
99
+ output: "",
100
+ error: err.message
101
+ };
102
+ }
103
+ }
104
+ function formatRow(r) {
105
+ const name = r.model.padEnd(28);
106
+ const ttft = `${r.firstTokenMs.toString().padStart(5)} ms`;
107
+ const total = `${r.totalMs.toString().padStart(6)} ms`;
108
+ const tps = `${r.tokensPerSec.toFixed(1).padStart(6)} tok/s`;
109
+ const toks = `${r.promptTokens}\u2192${r.completionTokens}`;
110
+ if (r.error) {
111
+ return ` ${chalk.red("\u2717")} ${chalk.white(name)} ${chalk.red(r.error.slice(0, 70))}`;
112
+ }
113
+ return ` ${chalk.green("\u2713")} ${chalk.white(name)} ${chalk.gray(ttft)} ${chalk.gray(total)} ${chalk.cyan(tps)} ${chalk.gray(toks.padEnd(12))}`;
114
+ }
115
+ async function persistBench(projectRoot, results, prompt) {
116
+ const outDir = path.join(projectRoot, ".notch");
117
+ await fs.mkdir(outDir, { recursive: true });
118
+ const file = path.join(outDir, "ollama-bench.json");
119
+ const payload = {
120
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
121
+ prompt,
122
+ results: results.map((r) => ({
123
+ model: r.model,
124
+ firstTokenMs: r.firstTokenMs,
125
+ totalMs: r.totalMs,
126
+ tokensPerSec: Number(r.tokensPerSec.toFixed(2)),
127
+ promptTokens: r.promptTokens,
128
+ completionTokens: r.completionTokens,
129
+ error: r.error
130
+ }))
131
+ };
132
+ await fs.writeFile(file, JSON.stringify(payload, null, 2) + "\n", "utf-8");
133
+ return file;
134
+ }
135
+ async function runOllamaBench(flags, opts) {
136
+ const { baseUrl, apiKey, mode } = await resolveEndpoint(flags);
137
+ if (!await detectDaemon(baseUrl, { apiKey })) {
138
+ printNotReachable(baseUrl, mode);
139
+ return 1;
140
+ }
141
+ const modelsArg = flags.model ?? "";
142
+ const fromFlag = modelsArg.split(",").map((s) => s.trim()).filter(Boolean);
143
+ const models = fromFlag.length > 0 ? fromFlag : DEFAULT_BENCH_MODELS;
144
+ const prompt = flags.positional.join(" ").trim() || DEFAULT_PROMPT;
145
+ console.log("");
146
+ console.log(chalk.cyan(` Ollama bench \u2014 ${models.length} model(s) @ ${baseUrl}`));
147
+ console.log(chalk.gray(` Prompt: ${prompt}`));
148
+ console.log("");
149
+ const results = [];
150
+ for (const model of models) {
151
+ if (mode === "local") {
152
+ const present = await ensureModelPresent(model, baseUrl, apiKey, flags.yes);
153
+ if (!present) {
154
+ results.push({
155
+ model,
156
+ firstTokenMs: 0,
157
+ totalMs: 0,
158
+ tokensPerSec: 0,
159
+ promptTokens: 0,
160
+ completionTokens: 0,
161
+ output: "",
162
+ error: "not installed (pass -y to auto-pull)"
163
+ });
164
+ continue;
165
+ }
166
+ }
167
+ process.stdout.write(chalk.gray(` running ${model}... `));
168
+ const result = await runOne(model, prompt, baseUrl, apiKey, mode === "cloud");
169
+ results.push(result);
170
+ process.stdout.write("\r\x1B[K");
171
+ }
172
+ const ranked = [...results].sort((a, b) => {
173
+ if (a.error && !b.error) return 1;
174
+ if (!a.error && b.error) return -1;
175
+ return b.tokensPerSec - a.tokensPerSec;
176
+ });
177
+ const header = ` ${" "}${"model".padEnd(28)} ${"ttft".padStart(8)} ${"total".padStart(9)} ${"throughput".padStart(12)} ${"tokens (p\u2192c)"}`;
178
+ console.log(chalk.gray(header));
179
+ console.log(chalk.gray(` ${"-".repeat(header.length - 2)}`));
180
+ for (const r of ranked) console.log(formatRow(r));
181
+ try {
182
+ const saved = await persistBench(opts.projectRoot, ranked, prompt);
183
+ console.log("");
184
+ console.log(chalk.gray(` Saved: ${saved}`));
185
+ console.log("");
186
+ } catch (err) {
187
+ console.warn(chalk.yellow(` ! Could not persist bench: ${err.message}`));
188
+ }
189
+ const anyFailed = ranked.some((r) => r.error);
190
+ return anyFailed ? 1 : 0;
191
+ }
192
+ export {
193
+ runOllamaBench
194
+ };
@@ -0,0 +1,22 @@
1
+ import {
2
+ parseFlags,
3
+ persistOllamaChoice,
4
+ printNotReachable,
5
+ renderProgressLine,
6
+ resolveEndpoint,
7
+ runOllamaCli
8
+ } from "./chunk-FZVPGJJW.js";
9
+ import "./chunk-GFVLHUSS.js";
10
+ import "./chunk-O6AKZ4OH.js";
11
+ import "./chunk-KCAR5DOB.js";
12
+ import "./chunk-JXQ4HZ47.js";
13
+ import "./chunk-PPEBWOMJ.js";
14
+ import "./chunk-KFQGP6VL.js";
15
+ export {
16
+ parseFlags,
17
+ persistOllamaChoice,
18
+ printNotReachable,
19
+ renderProgressLine,
20
+ resolveEndpoint,
21
+ runOllamaCli
22
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ isCloudModel
3
+ } from "./chunk-GFVLHUSS.js";
4
+ import "./chunk-KFQGP6VL.js";
5
+
6
+ // src/ui/ollama-usage.ts
7
+ import chalk from "chalk";
8
+ var OllamaCloudUsageTracker = class {
9
+ turns = [];
10
+ /**
11
+ * Record a turn. The tracker auto-filters: only entries whose modelId
12
+ * looks like an Ollama Cloud model are kept. Non-cloud turns are
13
+ * silently ignored so callers can fire this once per turn without
14
+ * conditionals.
15
+ */
16
+ record(turn) {
17
+ if (!this.isCloudTurn(turn.modelId)) return;
18
+ this.turns.push(turn);
19
+ }
20
+ isCloudTurn(modelId) {
21
+ if (!modelId) return false;
22
+ if (modelId.startsWith("ollama-cloud:")) return true;
23
+ return isCloudModel(modelId);
24
+ }
25
+ get turnCount() {
26
+ return this.turns.length;
27
+ }
28
+ get sessionTotals() {
29
+ return this.turns.reduce(
30
+ (acc, t) => ({
31
+ promptTokens: acc.promptTokens + t.promptTokens,
32
+ completionTokens: acc.completionTokens + t.completionTokens,
33
+ totalTokens: acc.totalTokens + t.totalTokens,
34
+ toolCalls: acc.toolCalls + t.toolCalls,
35
+ iterations: acc.iterations + t.iterations
36
+ }),
37
+ { promptTokens: 0, completionTokens: 0, totalTokens: 0, toolCalls: 0, iterations: 0 }
38
+ );
39
+ }
40
+ /**
41
+ * One-line footer rendered after every turn when the active model is
42
+ * an Ollama Cloud alias. Kept intentionally short — it sits beside
43
+ * the existing UsageTracker.formatLast() output.
44
+ */
45
+ formatFooter(activeModelId) {
46
+ if (!this.isCloudTurn(activeModelId) || this.turnCount === 0) return "";
47
+ const total = this.sessionTotals;
48
+ const totalK = (total.totalTokens / 1e3).toFixed(1);
49
+ return chalk.gray(` [cloud: ${this.turnCount} turns, ${totalK}K tokens]`);
50
+ }
51
+ /**
52
+ * Multi-line breakdown for `/usage cloud` / `/status` style surfaces.
53
+ */
54
+ formatDetail() {
55
+ if (this.turnCount === 0) {
56
+ return chalk.gray(" No Ollama Cloud traffic this session.");
57
+ }
58
+ const total = this.sessionTotals;
59
+ return [
60
+ chalk.gray(" Ollama Cloud"),
61
+ chalk.gray(` turns ${this.turnCount}`),
62
+ chalk.gray(` prompt ${total.promptTokens.toLocaleString()} tokens`),
63
+ chalk.gray(` completion ${total.completionTokens.toLocaleString()} tokens`),
64
+ chalk.gray(` total ${total.totalTokens.toLocaleString()} tokens`)
65
+ ].join("\n");
66
+ }
67
+ };
68
+ export {
69
+ OllamaCloudUsageTracker
70
+ };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  pluginManager
3
3
  } from "./chunk-3QUV4JEX.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  pluginManager
6
7
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  readTool
3
3
  } from "./chunk-CQMAVWLJ.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  readTool
6
7
  };
@@ -1,3 +1,5 @@
1
+ import "./chunk-KFQGP6VL.js";
2
+
1
3
  // src/mcp/server.ts
2
4
  import readline from "readline";
3
5
 
@@ -1315,8 +1317,8 @@ function toolsToMcpList(tools) {
1315
1317
  }));
1316
1318
  }
1317
1319
  async function runMcpServer(opts) {
1318
- const toolsModule = await import("./tools-Q7CDHB4K.js");
1319
- const { pluginManager } = await import("./plugins-OG2P75K5.js");
1320
+ const toolsModule = await import("./tools-XWKCW4RN.js");
1321
+ const { pluginManager } = await import("./plugins-PNGRZLFW.js");
1320
1322
  if (opts.includePlugins !== false) {
1321
1323
  try {
1322
1324
  await pluginManager.init(opts.cwd, (m) => logStderr(m));
@@ -1325,19 +1327,19 @@ async function runMcpServer(opts) {
1325
1327
  }
1326
1328
  }
1327
1329
  const getTools = () => toolsModule.listToolNames().map((name) => ({ name, desc: toolsModule.describeTools() })).filter(() => true);
1328
- const { readTool } = await import("./read-OVJG2XKW.js");
1329
- const { writeTool } = await import("./write-NNHLOTYK.js");
1330
- const { editTool } = await import("./edit-JEFEK43H.js");
1331
- const { applyPatchTool } = await import("./apply-patch-D5PDUXUC.js");
1332
- const { shellTool } = await import("./shell-4X545EVN.js");
1333
- const { gitTool } = await import("./git-5T5TSQTX.js");
1334
- const { githubTool } = await import("./github-DWRGWX6U.js");
1335
- const { grepTool } = await import("./grep-VZ3I5GNW.js");
1336
- const { globTool } = await import("./glob-BI3P4C7Q.js");
1337
- const { webFetchTool } = await import("./web-fetch-KNIV3Z3W.js");
1338
- const { lspTool } = await import("./lsp-UPY6I3L7.js");
1339
- const { notebookTool } = await import("./notebook-FXJBTSPA.js");
1340
- const { taskTool } = await import("./task-OS3E5F3X.js");
1330
+ const { readTool } = await import("./read-B64XE7N3.js");
1331
+ const { writeTool } = await import("./write-ZOSB7I4J.js");
1332
+ const { editTool } = await import("./edit-6QYAXVNU.js");
1333
+ const { applyPatchTool } = await import("./apply-patch-U6K67CMT.js");
1334
+ const { shellTool } = await import("./shell-BOZTHQUT.js");
1335
+ const { gitTool } = await import("./git-DNQ5EELH.js");
1336
+ const { githubTool } = await import("./github-34T4QQIH.js");
1337
+ const { grepTool } = await import("./grep-T2CXYNRI.js");
1338
+ const { globTool } = await import("./glob-XT43LEJ4.js");
1339
+ const { webFetchTool } = await import("./web-fetch-OTNDICGJ.js");
1340
+ const { lspTool } = await import("./lsp-JXQVU7NP.js");
1341
+ const { notebookTool } = await import("./notebook-MFODW345.js");
1342
+ const { taskTool } = await import("./task-67G4KLYC.js");
1341
1343
  const exposed = [
1342
1344
  readTool,
1343
1345
  writeTool,
@@ -0,0 +1,22 @@
1
+ import {
2
+ deriveEntryFromRollout,
3
+ forgetSession,
4
+ getSession,
5
+ indexFilePath,
6
+ querySessions,
7
+ rebuildIndex,
8
+ tagSession,
9
+ upsertSessionIndexEntry
10
+ } from "./chunk-4HPRBCSY.js";
11
+ import "./chunk-6NKRMZTX.js";
12
+ import "./chunk-KFQGP6VL.js";
13
+ export {
14
+ deriveEntryFromRollout,
15
+ forgetSession,
16
+ getSession,
17
+ indexFilePath,
18
+ querySessions,
19
+ rebuildIndex,
20
+ tagSession,
21
+ upsertSessionIndexEntry
22
+ };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  shellTool
3
3
  } from "./chunk-W4FAGQFL.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  shellTool
6
7
  };
@@ -3,6 +3,7 @@ import {
3
3
  getAllTasks,
4
4
  taskTool
5
5
  } from "./chunk-UR4XL6OM.js";
6
+ import "./chunk-KFQGP6VL.js";
6
7
  export {
7
8
  formatTasksDisplay,
8
9
  getAllTasks,
@@ -5,7 +5,8 @@ import {
5
5
  initMCPServers,
6
6
  listToolNames,
7
7
  mcpToolCount
8
- } from "./chunk-YBYF7L4A.js";
8
+ } from "./chunk-EPSOOCNB.js";
9
+ import "./chunk-6NKRMZTX.js";
9
10
  import "./chunk-6CZCFY6H.js";
10
11
  import "./chunk-6U3ZAGYA.js";
11
12
  import "./chunk-FFB7GK3Y.js";
@@ -14,12 +15,14 @@ import "./chunk-TH6GKC7E.js";
14
15
  import "./chunk-KZAS754V.js";
15
16
  import "./chunk-UR4XL6OM.js";
16
17
  import "./chunk-3QUV4JEX.js";
18
+ import "./chunk-PPEBWOMJ.js";
17
19
  import "./chunk-CQMAVWLJ.js";
18
20
  import "./chunk-O3WZW7GS.js";
19
21
  import "./chunk-YAYPQTOU.js";
20
22
  import "./chunk-C4CPDDMN.js";
21
23
  import "./chunk-W4FAGQFL.js";
22
24
  import "./chunk-FAULT7VE.js";
25
+ import "./chunk-KFQGP6VL.js";
23
26
  export {
24
27
  buildToolMap,
25
28
  describeTools,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  webFetchTool
3
3
  } from "./chunk-FFB7GK3Y.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  webFetchTool
6
7
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  writeTool
3
3
  } from "./chunk-O3WZW7GS.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  writeTool
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freesyntax/notch-cli",
3
- "version": "0.5.20",
3
+ "version": "0.5.22",
4
4
  "description": "Notch CLI — AI-powered coding assistant by Driftrail",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,6 +20,7 @@
20
20
  "prepublishOnly": "npm run build:publish"
21
21
  },
22
22
  "dependencies": {
23
+ "@ai-sdk/anthropic": "^1.2.12",
23
24
  "@ai-sdk/openai": "^1.2.0",
24
25
  "ai": "^4.3.2",
25
26
  "chalk": "^5.3.0",
@@ -1,16 +0,0 @@
1
- import {
2
- clearCredentials,
3
- getConfigDir,
4
- getCredentialsPath,
5
- loadCredentials,
6
- login,
7
- saveCredentials
8
- } from "./chunk-FIFC4V2R.js";
9
- export {
10
- clearCredentials,
11
- getConfigDir,
12
- getCredentialsPath,
13
- loadCredentials,
14
- login,
15
- saveCredentials
16
- };
@@ -1,16 +0,0 @@
1
- import {
2
- autoCompactSummarize,
3
- autoCompress,
4
- compressHistory,
5
- estimateTokens,
6
- fullCompact,
7
- microCompact
8
- } from "./chunk-6M6CXXWR.js";
9
- export {
10
- autoCompactSummarize,
11
- autoCompress,
12
- compressHistory,
13
- estimateTokens,
14
- fullCompact,
15
- microCompact
16
- };