onecontext-ai 0.7.10
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 +65 -0
- package/bin/default.js +4 -0
- package/bin/oc.js +4 -0
- package/bin/onecontext.js +4 -0
- package/package.json +33 -0
- package/postinstall.js +140 -0
- package/run.js +101 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# onecontext-ai
|
|
2
|
+
|
|
3
|
+
npm wrapper for [OneContext AI](https://pypi.org/project/aline-ai/) (the `aline-ai` Python package).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g onecontext-ai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This will automatically install the latest `aline-ai` Python package using the best available Python package manager (`uv` > `pipx` > `pip3` > `pip`).
|
|
12
|
+
|
|
13
|
+
### Prerequisites
|
|
14
|
+
|
|
15
|
+
- Node.js >= 16
|
|
16
|
+
- Python 3.8+ with one of: `uv`, `pipx`, `pip3`, or `pip`
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
After installation, the following commands are available:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
onecontext-ai <command> [args...]
|
|
24
|
+
onecontext <command> [args...]
|
|
25
|
+
oc <command> [args...]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
All three commands are equivalent and proxy to the underlying Python CLI.
|
|
29
|
+
|
|
30
|
+
### Examples
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Check version
|
|
34
|
+
onecontext version
|
|
35
|
+
|
|
36
|
+
# Show help
|
|
37
|
+
onecontext --help
|
|
38
|
+
|
|
39
|
+
# Short alias
|
|
40
|
+
oc version
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Updating the Python Package
|
|
44
|
+
|
|
45
|
+
The npm wrapper installs the latest `aline-ai` on `npm install`. To update the Python package independently:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Using pip
|
|
49
|
+
pip install --upgrade aline-ai
|
|
50
|
+
|
|
51
|
+
# Or rebuild the npm package to re-trigger postinstall
|
|
52
|
+
npm rebuild onecontext-ai
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Troubleshooting
|
|
56
|
+
|
|
57
|
+
If the commands aren't found after installation:
|
|
58
|
+
|
|
59
|
+
1. Ensure the Python package is installed: `pip install aline-ai`
|
|
60
|
+
2. Rebuild to re-discover paths: `npm rebuild onecontext-ai`
|
|
61
|
+
3. Check that `onecontext` is on your PATH: `which onecontext`
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
MIT
|
package/bin/default.js
ADDED
package/bin/oc.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "onecontext-ai",
|
|
3
|
+
"version": "0.7.10",
|
|
4
|
+
"description": "OneContext AI - npm wrapper for the aline-ai Python package",
|
|
5
|
+
"bin": {
|
|
6
|
+
"onecontext-ai": "./bin/default.js",
|
|
7
|
+
"onecontext": "./bin/onecontext.js",
|
|
8
|
+
"oc": "./bin/oc.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"postinstall": "node postinstall.js"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=16"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin/",
|
|
18
|
+
"postinstall.js",
|
|
19
|
+
"run.js",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"onecontext",
|
|
24
|
+
"aline",
|
|
25
|
+
"ai",
|
|
26
|
+
"cli"
|
|
27
|
+
],
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/Loke-60000/ReAlign"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { execSync, execFileSync } = require("child_process");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
const PACKAGE = "aline-ai";
|
|
9
|
+
const COMMANDS = ["onecontext", "oc"];
|
|
10
|
+
const PATHS_FILE = path.join(__dirname, ".paths.json");
|
|
11
|
+
|
|
12
|
+
function log(msg) {
|
|
13
|
+
console.log(`[onecontext-ai] ${msg}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function warn(msg) {
|
|
17
|
+
console.warn(`[onecontext-ai] WARNING: ${msg}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Detect available Python package manager: uv > pipx > pip3 > pip
|
|
21
|
+
function detectPkgManager() {
|
|
22
|
+
const candidates = ["uv", "pipx", "pip3", "pip"];
|
|
23
|
+
for (const cmd of candidates) {
|
|
24
|
+
try {
|
|
25
|
+
execFileSync(cmd, ["--version"], { stdio: "ignore" });
|
|
26
|
+
return cmd;
|
|
27
|
+
} catch {
|
|
28
|
+
// not found, try next
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Build install args for the given package manager
|
|
35
|
+
function installArgs(mgr) {
|
|
36
|
+
switch (mgr) {
|
|
37
|
+
case "uv":
|
|
38
|
+
return [["uv", "tool", "install", PACKAGE], ["uv", "tool", "install", "--force", PACKAGE]];
|
|
39
|
+
case "pipx":
|
|
40
|
+
return [["pipx", "install", PACKAGE], ["pipx", "install", "--force", PACKAGE]];
|
|
41
|
+
case "pip3":
|
|
42
|
+
return [["pip3", "install", PACKAGE], ["pip3", "install", "--upgrade", PACKAGE]];
|
|
43
|
+
case "pip":
|
|
44
|
+
return [["pip", "install", PACKAGE], ["pip", "install", "--upgrade", PACKAGE]];
|
|
45
|
+
default:
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Run install, retry with force/upgrade on failure
|
|
51
|
+
function install(mgr) {
|
|
52
|
+
const [primary, fallback] = installArgs(mgr);
|
|
53
|
+
log(`Installing ${PACKAGE} via ${mgr}...`);
|
|
54
|
+
try {
|
|
55
|
+
execFileSync(primary[0], primary.slice(1), { stdio: "inherit" });
|
|
56
|
+
return true;
|
|
57
|
+
} catch {
|
|
58
|
+
log(`Retrying with ${fallback.slice(-1)[0]}...`);
|
|
59
|
+
try {
|
|
60
|
+
execFileSync(fallback[0], fallback.slice(1), { stdio: "inherit" });
|
|
61
|
+
return true;
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Get npm global/local bin directories to exclude from search (avoid recursion)
|
|
69
|
+
function npmBinDirs() {
|
|
70
|
+
const dirs = new Set();
|
|
71
|
+
try {
|
|
72
|
+
dirs.add(execSync("npm bin -g", { encoding: "utf8" }).trim());
|
|
73
|
+
} catch { /* ignore */ }
|
|
74
|
+
try {
|
|
75
|
+
dirs.add(execSync("npm bin", { encoding: "utf8" }).trim());
|
|
76
|
+
} catch { /* ignore */ }
|
|
77
|
+
// Also add the directory where this package's bins will be linked
|
|
78
|
+
try {
|
|
79
|
+
dirs.add(execSync("npm prefix -g", { encoding: "utf8" }).trim() + "/bin");
|
|
80
|
+
} catch { /* ignore */ }
|
|
81
|
+
return dirs;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Discover absolute path for a command, filtering out npm bin directories
|
|
85
|
+
function discoverPath(cmd, excludeDirs) {
|
|
86
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
87
|
+
const whichArgs = process.platform === "win32" ? [cmd] : ["-a", cmd];
|
|
88
|
+
try {
|
|
89
|
+
const output = execFileSync(whichCmd, whichArgs, { encoding: "utf8" });
|
|
90
|
+
const paths = output.split(/\r?\n/).map((p) => p.trim()).filter(Boolean);
|
|
91
|
+
for (const p of paths) {
|
|
92
|
+
const dir = path.dirname(p);
|
|
93
|
+
let skip = false;
|
|
94
|
+
for (const excl of excludeDirs) {
|
|
95
|
+
if (dir === excl || p.startsWith(excl + path.sep)) {
|
|
96
|
+
skip = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!skip) return p;
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
// command not found
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function main() {
|
|
109
|
+
const mgr = detectPkgManager();
|
|
110
|
+
if (!mgr) {
|
|
111
|
+
warn("No Python package manager found (uv, pipx, pip3, pip).");
|
|
112
|
+
warn(`Please install ${PACKAGE} manually and re-run: npm rebuild onecontext-ai`);
|
|
113
|
+
fs.writeFileSync(PATHS_FILE, JSON.stringify({}, null, 2));
|
|
114
|
+
return; // don't exit(1) — report error at runtime instead
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const ok = install(mgr);
|
|
118
|
+
if (!ok) {
|
|
119
|
+
warn(`Failed to install ${PACKAGE} via ${mgr}.`);
|
|
120
|
+
warn(`Please install ${PACKAGE} manually and re-run: npm rebuild onecontext-ai`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Discover command paths
|
|
124
|
+
const excludeDirs = npmBinDirs();
|
|
125
|
+
const paths = {};
|
|
126
|
+
for (const cmd of COMMANDS) {
|
|
127
|
+
const resolved = discoverPath(cmd, excludeDirs);
|
|
128
|
+
if (resolved) {
|
|
129
|
+
paths[cmd] = resolved;
|
|
130
|
+
log(`Found ${cmd} at ${resolved}`);
|
|
131
|
+
} else {
|
|
132
|
+
warn(`Could not find ${cmd} in PATH`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fs.writeFileSync(PATHS_FILE, JSON.stringify(paths, null, 2));
|
|
137
|
+
log("Installation complete.");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
main();
|
package/run.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { spawn, execFileSync } = require("child_process");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
const PATHS_FILE = path.join(__dirname, ".paths.json");
|
|
9
|
+
|
|
10
|
+
// Get npm bin directories to exclude (avoid recursion)
|
|
11
|
+
function npmBinDirs() {
|
|
12
|
+
const dirs = new Set();
|
|
13
|
+
try {
|
|
14
|
+
dirs.add(require("child_process").execSync("npm bin -g", { encoding: "utf8" }).trim());
|
|
15
|
+
} catch { /* ignore */ }
|
|
16
|
+
try {
|
|
17
|
+
dirs.add(require("child_process").execSync("npm bin", { encoding: "utf8" }).trim());
|
|
18
|
+
} catch { /* ignore */ }
|
|
19
|
+
try {
|
|
20
|
+
dirs.add(require("child_process").execSync("npm prefix -g", { encoding: "utf8" }).trim() + "/bin");
|
|
21
|
+
} catch { /* ignore */ }
|
|
22
|
+
return dirs;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Fallback: search PATH for command, excluding npm bin dirs
|
|
26
|
+
function searchPath(cmd) {
|
|
27
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
28
|
+
const whichArgs = process.platform === "win32" ? [cmd] : ["-a", cmd];
|
|
29
|
+
const excludeDirs = npmBinDirs();
|
|
30
|
+
try {
|
|
31
|
+
const output = execFileSync(whichCmd, whichArgs, { encoding: "utf8" });
|
|
32
|
+
const paths = output.split(/\r?\n/).map((p) => p.trim()).filter(Boolean);
|
|
33
|
+
for (const p of paths) {
|
|
34
|
+
const dir = path.dirname(p);
|
|
35
|
+
let skip = false;
|
|
36
|
+
for (const excl of excludeDirs) {
|
|
37
|
+
if (dir === excl || p.startsWith(excl + path.sep)) {
|
|
38
|
+
skip = true;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!skip) return p;
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// not found
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function resolve(cmd) {
|
|
51
|
+
// 1. Try .paths.json
|
|
52
|
+
if (fs.existsSync(PATHS_FILE)) {
|
|
53
|
+
try {
|
|
54
|
+
const data = JSON.parse(fs.readFileSync(PATHS_FILE, "utf8"));
|
|
55
|
+
if (data[cmd]) return data[cmd];
|
|
56
|
+
} catch {
|
|
57
|
+
// corrupted file, fall through
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 2. Fallback: search PATH
|
|
62
|
+
const found = searchPath(cmd);
|
|
63
|
+
if (found) return found;
|
|
64
|
+
|
|
65
|
+
// 3. Not found
|
|
66
|
+
console.error(
|
|
67
|
+
`[onecontext-ai] ERROR: Could not find "${cmd}" command.\n` +
|
|
68
|
+
`Please install the Python package first:\n` +
|
|
69
|
+
` pip install aline-ai\n` +
|
|
70
|
+
`Then re-run: npm rebuild onecontext-ai`
|
|
71
|
+
);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function run(cmd) {
|
|
76
|
+
const binPath = resolve(cmd);
|
|
77
|
+
const args = process.argv.slice(2);
|
|
78
|
+
const child = spawn(binPath, args, { stdio: "inherit" });
|
|
79
|
+
|
|
80
|
+
// Forward signals to child process
|
|
81
|
+
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
82
|
+
process.on(sig, () => {
|
|
83
|
+
child.kill(sig);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
child.on("error", (err) => {
|
|
88
|
+
console.error(`[onecontext-ai] Failed to start ${cmd}: ${err.message}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
child.on("exit", (code, signal) => {
|
|
93
|
+
if (signal) {
|
|
94
|
+
process.kill(process.pid, signal);
|
|
95
|
+
} else {
|
|
96
|
+
process.exit(code ?? 1);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { run };
|