nou-cli 0.0.0-stage → 0.2.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/.env.example +24 -0
- package/README.md +163 -2
- package/dist/grammars/tree-sitter-bash.wasm +0 -0
- package/dist/grammars/tree-sitter-c.wasm +0 -0
- package/dist/grammars/tree-sitter-css.wasm +0 -0
- package/dist/grammars/tree-sitter-go.wasm +0 -0
- package/dist/grammars/tree-sitter-html.wasm +0 -0
- package/dist/grammars/tree-sitter-java.wasm +0 -0
- package/dist/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/grammars/tree-sitter-json.wasm +0 -0
- package/dist/grammars/tree-sitter-python.wasm +0 -0
- package/dist/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/grammars/tree-sitter-toml.wasm +0 -0
- package/dist/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/grammars/tree-sitter-yaml.wasm +0 -0
- package/dist/index.js +84 -0
- package/dist/src/agent/index.js +246 -0
- package/dist/src/commands/index.js +125 -0
- package/dist/src/config/index.js +39 -0
- package/dist/src/context/index.js +53 -0
- package/dist/src/diagnostics/index.js +235 -0
- package/dist/src/diagnostics/process.js +64 -0
- package/dist/src/diagnostics/providers.js +103 -0
- package/dist/src/diagnostics/types.js +1 -0
- package/dist/src/env.js +12 -0
- package/dist/src/git/index.js +94 -0
- package/dist/src/git/tools.js +52 -0
- package/dist/src/history/index.js +113 -0
- package/dist/src/lsp/client.js +169 -0
- package/dist/src/lsp/index.js +169 -0
- package/dist/src/plugins/index.js +134 -0
- package/dist/src/providers/anthropic.js +109 -0
- package/dist/src/providers/ids.js +3 -0
- package/dist/src/providers/index.js +46 -0
- package/dist/src/providers/ollama.js +58 -0
- package/dist/src/providers/openai.js +107 -0
- package/dist/src/providers/types.js +2 -0
- package/dist/src/syntax/index.js +240 -0
- package/dist/src/tools/index.js +100 -0
- package/dist/src/ui/App.js +671 -0
- package/dist/src/ui/Chat.js +97 -0
- package/dist/src/ui/ChatInput.js +128 -0
- package/dist/src/ui/CodeView.js +100 -0
- package/dist/src/ui/Editor.js +234 -0
- package/dist/src/ui/FileTree.js +143 -0
- package/dist/src/ui/Header.js +9 -0
- package/dist/src/ui/Pane.js +8 -0
- package/dist/src/ui/ProblemsView.js +71 -0
- package/dist/src/ui/QuickOpen.js +91 -0
- package/dist/src/ui/Settings.js +165 -0
- package/dist/src/ui/text.js +100 -0
- package/dist/src/ui/theme.js +41 -0
- package/dist/src/update/index.js +102 -0
- package/dist/src/util/index.js +9 -0
- package/package.json +69 -4
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { NOU_HOME } from "../config/index.js";
|
|
6
|
+
export const PACKAGE_NAME = "nou-cli";
|
|
7
|
+
const CACHE = path.join(NOU_HOME, "update.json");
|
|
8
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
9
|
+
/** Nou's own package.json (works from source and from the installed dist build). */
|
|
10
|
+
function ownPackage() {
|
|
11
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
for (let i = 0; i < 5; i++) {
|
|
13
|
+
const file = path.join(dir, "package.json");
|
|
14
|
+
if (existsSync(file)) {
|
|
15
|
+
const pkg = JSON.parse(readFileSync(file, "utf-8"));
|
|
16
|
+
if (pkg.name === PACKAGE_NAME)
|
|
17
|
+
return { version: pkg.version, dir };
|
|
18
|
+
}
|
|
19
|
+
dir = path.dirname(dir);
|
|
20
|
+
}
|
|
21
|
+
return { version: "0.0.0", dir };
|
|
22
|
+
}
|
|
23
|
+
export const currentVersion = () => ownPackage().version;
|
|
24
|
+
/** Running from a git checkout (npm run dev) rather than an npm install: never nag about updates. */
|
|
25
|
+
export const isDevCheckout = () => existsSync(path.join(ownPackage().dir, ".git"));
|
|
26
|
+
/** -1, 0 or 1. Plain x.y.z comparison; pre-release tags sort before the release. */
|
|
27
|
+
export function compareVersions(a, b) {
|
|
28
|
+
const parse = (v) => {
|
|
29
|
+
const [main, pre] = v.replace(/^v/, "").split("-", 2);
|
|
30
|
+
return { nums: main.split(".").map((n) => Number(n) || 0), pre };
|
|
31
|
+
};
|
|
32
|
+
const x = parse(a);
|
|
33
|
+
const y = parse(b);
|
|
34
|
+
for (let i = 0; i < 3; i++) {
|
|
35
|
+
const d = (x.nums[i] ?? 0) - (y.nums[i] ?? 0);
|
|
36
|
+
if (d)
|
|
37
|
+
return Math.sign(d);
|
|
38
|
+
}
|
|
39
|
+
if (x.pre && !y.pre)
|
|
40
|
+
return -1;
|
|
41
|
+
if (!x.pre && y.pre)
|
|
42
|
+
return 1;
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
async function fetchLatest(timeout) {
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { signal: AbortSignal.timeout(timeout) });
|
|
48
|
+
if (!res.ok)
|
|
49
|
+
return null;
|
|
50
|
+
return (await res.json()).version ?? null;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The newer version available on npm, or null. Asks npm at most once a day (cached in ~/.nou/update.json)
|
|
58
|
+
* and never waits more than `timeout` ms, so startup stays fast offline.
|
|
59
|
+
*/
|
|
60
|
+
export async function checkForUpdate({ force = false, timeout = 1500 } = {}) {
|
|
61
|
+
if (!force && (process.env.NOU_NO_UPDATE_CHECK || isDevCheckout()))
|
|
62
|
+
return null;
|
|
63
|
+
let latest = null;
|
|
64
|
+
try {
|
|
65
|
+
const cached = JSON.parse(readFileSync(CACHE, "utf-8"));
|
|
66
|
+
if (!force && Date.now() - cached.checkedAt < DAY)
|
|
67
|
+
latest = cached.latest;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// no cache yet
|
|
71
|
+
}
|
|
72
|
+
if (!latest) {
|
|
73
|
+
latest = await fetchLatest(timeout);
|
|
74
|
+
if (latest) {
|
|
75
|
+
try {
|
|
76
|
+
mkdirSync(NOU_HOME, { recursive: true });
|
|
77
|
+
writeFileSync(CACHE, JSON.stringify({ latest, checkedAt: Date.now() }));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// caching is optional
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return latest && compareVersions(latest, currentVersion()) > 0 ? latest : null;
|
|
85
|
+
}
|
|
86
|
+
/** Runs `npm install -g nou-cli@<version>`, showing npm's output. Resolves to success. */
|
|
87
|
+
export function installUpdate(version = "latest") {
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
// npm is npm.cmd on Windows, which needs a shell; the arguments are fixed, not user input.
|
|
90
|
+
const child = spawn("npm", ["install", "-g", `${PACKAGE_NAME}@${version}`], {
|
|
91
|
+
stdio: "inherit",
|
|
92
|
+
shell: process.platform === "win32",
|
|
93
|
+
});
|
|
94
|
+
child.on("error", () => resolve(false));
|
|
95
|
+
child.on("close", (code) => resolve(code === 0));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** Starts the freshly installed Nou in place of this process. */
|
|
99
|
+
export function relaunch() {
|
|
100
|
+
const child = spawn(process.execPath, process.argv.slice(1).filter((a) => a !== "update"), { stdio: "inherit" });
|
|
101
|
+
child.on("close", (code) => process.exit(code ?? 0));
|
|
102
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const artWork = `
|
|
2
|
+
.__ __. ______ __ __ ______ __ __
|
|
3
|
+
| \\ | | / __ \\ | | | | / || | | |
|
|
4
|
+
| \\| | | | | | | | | | | ,----'| | | |
|
|
5
|
+
| . \` | | | | | | | | | | | | | | |
|
|
6
|
+
| |\\ | | \`--' | | \`--' | | \`----.| \`----.| |
|
|
7
|
+
|__| \\__| \\______/ \\______/ \\______||_______||__|
|
|
8
|
+
|
|
9
|
+
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nou-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Nou: an IDE-style AI coding assistant for your terminal. Local (Ollama, LM Studio) and cloud (Claude, OpenAI, Gemini...) models, live diffs, git-aware, built-in editor.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nou": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
".env.example",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22.12"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "npx tsx index.ts",
|
|
19
|
+
"build": "tsc -p tsconfig.build.json && node scripts/copy-grammars.mjs",
|
|
20
|
+
"start": "node dist/index.js",
|
|
21
|
+
"typecheck": "tsc --noEmit -p .",
|
|
22
|
+
"lint": "eslint index.ts src",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"screenshot": "node -e \"process.env.FORCE_COLOR='3';require('child_process').execSync('npx tsx scripts/screenshot.tsx',{stdio:'inherit'})\"",
|
|
25
|
+
"test": "tsx tests/unit.ts && tsx tests/e2e.tsx"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/JorgeOchoaReyes/nou.git"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/JorgeOchoaReyes/nou#readme",
|
|
32
|
+
"keywords": [
|
|
33
|
+
"ai",
|
|
34
|
+
"cli",
|
|
35
|
+
"tui",
|
|
36
|
+
"coding-assistant",
|
|
37
|
+
"ollama",
|
|
38
|
+
"claude",
|
|
39
|
+
"llm",
|
|
40
|
+
"agent"
|
|
41
|
+
],
|
|
42
|
+
"author": "Jorge Raul Ochoa-Reyes",
|
|
43
|
+
"license": "ISC",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@anthropic-ai/sdk": "^0.133.0",
|
|
46
|
+
"@clack/prompts": "^1.1.0",
|
|
47
|
+
"chalk": "^5.6.2",
|
|
48
|
+
"cli-highlight": "^2.1.11",
|
|
49
|
+
"diff": "^9.0.0",
|
|
50
|
+
"ink": "^8.0.0",
|
|
51
|
+
"ink-text-input": "^6.0.0",
|
|
52
|
+
"ollama": "^0.6.3",
|
|
53
|
+
"openai": "^7.32.0",
|
|
54
|
+
"react": "^19.3.0",
|
|
55
|
+
"web-tree-sitter": "0.25.10",
|
|
56
|
+
"zod": "^4.3.6"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@eslint/js": "^10.0.1",
|
|
60
|
+
"@types/node": "^25.5.0",
|
|
61
|
+
"@types/react": "^19.3.0",
|
|
62
|
+
"eslint": "^10.2.0",
|
|
63
|
+
"globals": "^17.4.0",
|
|
64
|
+
"ink-testing-library": "^4.0.0",
|
|
65
|
+
"jiti": "^2.6.1",
|
|
66
|
+
"tree-sitter-wasms": "0.1.13",
|
|
67
|
+
"tsx": "^4.23.15",
|
|
68
|
+
"typescript": "^6.0.2",
|
|
69
|
+
"typescript-eslint": "^8.58.1"
|
|
70
|
+
}
|
|
71
|
+
}
|