@mmmbuto/anthmorph 0.1.0 → 0.1.1
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/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/LICENSE +1 -1
- package/README.md +10 -8
- package/bin/anthmorph +12 -1
- package/package.json +2 -1
- package/prebuilt/anthmorph +0 -0
- package/scripts/anthmorphctl +46 -19
- package/scripts/postinstall.js +64 -10
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AnthMorph
|
|
2
2
|
|
|
3
|
-
[](#project-status)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://www.rust-lang.org)
|
|
6
6
|
[](https://termux.dev)
|
|
@@ -15,15 +15,15 @@ Core capabilities:
|
|
|
15
15
|
- `openai_generic` profile for conservative compatibility with generic OpenAI-style providers
|
|
16
16
|
- Streaming SSE translation with fragmented tool-call handling
|
|
17
17
|
- Local control CLI for init, start, stop, restart, status, and logs
|
|
18
|
-
- Termux-
|
|
18
|
+
- Termux-first npm distribution with bundled prebuilt binary and local self-build on Linux/macOS
|
|
19
19
|
|
|
20
20
|
## Project Status
|
|
21
21
|
|
|
22
|
-
- Current line: `0.1.
|
|
22
|
+
- Current line: `0.1.1`
|
|
23
23
|
- Primary target: `chutes.ai`
|
|
24
24
|
- Secondary target: generic OpenAI-compatible endpoints
|
|
25
25
|
- Tested locally against Chutes, MiniMax, and Alibaba Coding Plan rejection handling
|
|
26
|
-
- Distribution paths:
|
|
26
|
+
- Distribution paths: Termux-first npm package with bundled prebuilt binary, plus source builds
|
|
27
27
|
- Repository metadata is aligned for GitHub and npm publication
|
|
28
28
|
|
|
29
29
|
## Quickstart
|
|
@@ -65,7 +65,8 @@ anthmorphctl stop
|
|
|
65
65
|
## CLI Control
|
|
66
66
|
|
|
67
67
|
`anthmorphctl` is the operator entrypoint.
|
|
68
|
-
|
|
68
|
+
By default it stores runtime state under `.anthmorph/` inside the installed package root.
|
|
69
|
+
For shell wrappers and daily usage, prefer setting `ANTHMORPH_STATE_DIR` to a dedicated writable path.
|
|
69
70
|
|
|
70
71
|
Common commands:
|
|
71
72
|
|
|
@@ -135,8 +136,9 @@ This repository already includes npm packaging files:
|
|
|
135
136
|
|
|
136
137
|
Packaging behavior:
|
|
137
138
|
- `npm install -g @mmmbuto/anthmorph` exposes `anthmorph` and `anthmorphctl`
|
|
138
|
-
-
|
|
139
|
-
-
|
|
139
|
+
- Termux uses the bundled `prebuilt/anthmorph` from the npm tarball
|
|
140
|
+
- Linux and macOS use `postinstall` to build locally with Cargo
|
|
141
|
+
- if no binary is available later, the `anthmorph` shim still falls back to a local release build
|
|
140
142
|
|
|
141
143
|
## Build And Test
|
|
142
144
|
|
|
@@ -179,6 +181,6 @@ tests/ protocol and real-backend integration tests
|
|
|
179
181
|
|
|
180
182
|
MIT License
|
|
181
183
|
<p>
|
|
182
|
-
Copyright (c) 2026
|
|
184
|
+
Copyright (c) 2026 Davide A. Guglielmi<br>
|
|
183
185
|
Made in Italy
|
|
184
186
|
</p>
|
package/bin/anthmorph
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
SCRIPT_PATH=$(readlink -f -- "$0" 2>/dev/null || printf "%s" "$0")
|
|
5
|
+
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")/.." && pwd)
|
|
6
|
+
PREBUILT_BIN=$ROOT_DIR/prebuilt/anthmorph
|
|
5
7
|
RELEASE_BIN=$ROOT_DIR/target/release/anthmorph
|
|
6
8
|
DEBUG_BIN=$ROOT_DIR/target/debug/anthmorph
|
|
9
|
+
IS_TERMUX=0
|
|
10
|
+
|
|
11
|
+
if [ -n "${TERMUX_VERSION:-}" ] || [ "${PREFIX:-}" = "/data/data/com.termux/files/usr" ]; then
|
|
12
|
+
IS_TERMUX=1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
if [ "$IS_TERMUX" -eq 1 ] && [ -x "$PREBUILT_BIN" ]; then
|
|
16
|
+
exec "$PREBUILT_BIN" "$@"
|
|
17
|
+
fi
|
|
7
18
|
|
|
8
19
|
if [ -x "$RELEASE_BIN" ]; then
|
|
9
20
|
exec "$RELEASE_BIN" "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmmbuto/anthmorph",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Chutes-first Anthropic /v1/messages proxy for Chutes and OpenAI-compatible backends",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "DioNanos <noreply@github.com>",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"bin/",
|
|
13
|
+
"prebuilt/",
|
|
13
14
|
"scripts/anthmorphctl",
|
|
14
15
|
"scripts/postinstall.js",
|
|
15
16
|
"scripts/smoke_test.sh",
|
|
Binary file
|
package/scripts/anthmorphctl
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
SCRIPT_PATH=$(readlink -f -- "$0" 2>/dev/null || printf "%s" "$0")
|
|
5
|
+
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")/.." && pwd)
|
|
5
6
|
STATE_DIR=${ANTHMORPH_STATE_DIR:-$ROOT_DIR/.anthmorph}
|
|
6
7
|
CONFIG_FILE=$STATE_DIR/config.env
|
|
7
8
|
PID_FILE=$STATE_DIR/anthmorph.pid
|
|
8
9
|
LOG_FILE=$STATE_DIR/anthmorph.log
|
|
9
|
-
|
|
10
|
+
PREBUILT_BIN=$ROOT_DIR/prebuilt/anthmorph
|
|
11
|
+
BIN_PATH_DEFAULT=${PREBUILT_BIN:-$ROOT_DIR/target/release/anthmorph}
|
|
10
12
|
|
|
11
13
|
mkdir -p "$STATE_DIR"
|
|
12
14
|
|
|
13
15
|
usage() {
|
|
14
16
|
cat <<USAGE
|
|
15
17
|
usage:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
anthmorphctl init chutes [options]
|
|
19
|
+
anthmorphctl init minimax [options]
|
|
20
|
+
anthmorphctl init openai --backend-url URL --model MODEL [options]
|
|
21
|
+
anthmorphctl set key-env ENV_NAME
|
|
22
|
+
anthmorphctl set key VALUE --save
|
|
23
|
+
anthmorphctl unset key
|
|
24
|
+
anthmorphctl start
|
|
25
|
+
anthmorphctl stop
|
|
26
|
+
anthmorphctl restart
|
|
27
|
+
anthmorphctl status
|
|
28
|
+
anthmorphctl logs
|
|
29
|
+
anthmorphctl print-config
|
|
30
|
+
anthmorphctl help
|
|
29
31
|
|
|
30
32
|
options for init:
|
|
31
33
|
--port PORT
|
|
@@ -46,7 +48,7 @@ USAGE
|
|
|
46
48
|
|
|
47
49
|
ensure_config() {
|
|
48
50
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|
49
|
-
echo "missing config: run '
|
|
51
|
+
echo "missing config: run 'anthmorphctl init ...' first" >&2
|
|
50
52
|
exit 1
|
|
51
53
|
fi
|
|
52
54
|
}
|
|
@@ -102,6 +104,33 @@ health_on_port() {
|
|
|
102
104
|
curl -fsS "http://127.0.0.1:$1/health" 2>/dev/null
|
|
103
105
|
}
|
|
104
106
|
|
|
107
|
+
bin_supports_profile() {
|
|
108
|
+
[ -x "$1" ] || return 1
|
|
109
|
+
"$1" --help 2>&1 | grep -q -- '--backend-profile'
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
ensure_bin_ready() {
|
|
113
|
+
if bin_supports_profile "$BIN_PATH"; then
|
|
114
|
+
return 0
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
if bin_supports_profile "$PREBUILT_BIN"; then
|
|
118
|
+
BIN_PATH="$PREBUILT_BIN"
|
|
119
|
+
save_config
|
|
120
|
+
return 0
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
if ! command -v cargo >/dev/null 2>&1; then
|
|
124
|
+
echo "cargo not found and anthmorph binary is missing or outdated" >&2
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
(cd "$ROOT_DIR" && cargo build --release --quiet) || return 1
|
|
129
|
+
BIN_PATH=$ROOT_DIR/target/release/anthmorph
|
|
130
|
+
save_config
|
|
131
|
+
bin_supports_profile "$BIN_PATH"
|
|
132
|
+
}
|
|
133
|
+
|
|
105
134
|
join_allow_origin() {
|
|
106
135
|
value=$1
|
|
107
136
|
if [ -z "${ALLOWED_ORIGINS:-}" ]; then
|
|
@@ -297,9 +326,7 @@ start_cmd() {
|
|
|
297
326
|
exit 1
|
|
298
327
|
fi
|
|
299
328
|
|
|
300
|
-
|
|
301
|
-
(cd "$ROOT_DIR" && cargo build --release --quiet)
|
|
302
|
-
fi
|
|
329
|
+
ensure_bin_ready || exit 1
|
|
303
330
|
|
|
304
331
|
api_key=$(resolve_api_key || true)
|
|
305
332
|
if [ -z "$api_key" ]; then
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,23 +1,77 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const os = require("node:os");
|
|
2
3
|
const path = require("node:path");
|
|
4
|
+
const { spawnSync } = require("node:child_process");
|
|
5
|
+
const packageJson = require("../package.json");
|
|
3
6
|
|
|
4
7
|
const root = path.resolve(__dirname, "..");
|
|
8
|
+
const prebuiltDir = path.join(root, "prebuilt");
|
|
9
|
+
const prebuiltBin = path.join(prebuiltDir, "anthmorph");
|
|
10
|
+
const releaseBin = path.join(root, "target", "release", "anthmorph");
|
|
11
|
+
const expectedVersion = packageJson.version;
|
|
12
|
+
const isTermux =
|
|
13
|
+
process.env.TERMUX_VERSION !== undefined ||
|
|
14
|
+
process.env.PREFIX === "/data/data/com.termux/files/usr";
|
|
5
15
|
|
|
6
16
|
function hasCargo() {
|
|
7
17
|
const probe = spawnSync("cargo", ["--version"], { stdio: "ignore" });
|
|
8
18
|
return probe.status === 0;
|
|
9
19
|
}
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
function isExecutable(file) {
|
|
22
|
+
try {
|
|
23
|
+
fs.accessSync(file, fs.constants.X_OK);
|
|
24
|
+
return true;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function binaryVersion(file) {
|
|
31
|
+
try {
|
|
32
|
+
const out = spawnSync(file, ["--version"], { encoding: "utf8" });
|
|
33
|
+
if (out.status !== 0) return null;
|
|
34
|
+
const match = out.stdout.trim().match(/(\d+\.\d+\.\d+)$/);
|
|
35
|
+
return match ? match[1] : null;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function ensurePrebuiltPermissions() {
|
|
42
|
+
if (fs.existsSync(prebuiltBin)) {
|
|
43
|
+
fs.chmodSync(prebuiltBin, 0o755);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function buildRelease() {
|
|
48
|
+
if (!hasCargo()) {
|
|
49
|
+
console.error("[anthmorph] cargo not found; cannot build local binary");
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const build = spawnSync("cargo", ["build", "--release", "--quiet"], {
|
|
54
|
+
cwd: root,
|
|
55
|
+
stdio: "inherit",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (build.status !== 0) {
|
|
59
|
+
process.exit(build.status || 1);
|
|
60
|
+
}
|
|
14
61
|
}
|
|
15
62
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
63
|
+
fs.mkdirSync(prebuiltDir, { recursive: true });
|
|
64
|
+
ensurePrebuiltPermissions();
|
|
65
|
+
|
|
66
|
+
if (isTermux && isExecutable(prebuiltBin) && binaryVersion(prebuiltBin) === expectedVersion) {
|
|
67
|
+
console.log(`[anthmorph] using packaged Termux prebuilt ${expectedVersion}`);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
20
70
|
|
|
21
|
-
if (
|
|
22
|
-
|
|
71
|
+
if (os.platform() === "linux" || os.platform() === "darwin") {
|
|
72
|
+
console.log("[anthmorph] building local release binary for this platform");
|
|
73
|
+
buildRelease();
|
|
74
|
+
process.exit(0);
|
|
23
75
|
}
|
|
76
|
+
|
|
77
|
+
console.log("[anthmorph] unsupported platform for automatic setup; packaged files kept as-is");
|