distil-llm 1.25.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 +62 -0
- package/bin/distil.js +29 -0
- package/index.d.ts +15 -0
- package/index.js +38 -0
- package/lib/runner.js +41 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# distil-llm
|
|
2
|
+
|
|
3
|
+
**Compress your AI agent's context — and prove its decisions don't change.**
|
|
4
|
+
|
|
5
|
+
[distil](https://github.com/dshakes/distil) is a cache-aware, **reversible**
|
|
6
|
+
context-compression layer for LLM agents. Unlike every other compressor, it
|
|
7
|
+
certifies — per request — that the agent's *next action* is unchanged
|
|
8
|
+
(decision-equivalence), with calibrated, honest savings numbers.
|
|
9
|
+
|
|
10
|
+
This npm package is the JS/TS bridge: a thin CLI shim + proxy helpers. The
|
|
11
|
+
compression runs in the distil proxy; your SDK just points its `baseURL` at it.
|
|
12
|
+
|
|
13
|
+
## Use it (no pip required)
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
# route your agent through distil — resolves uv/pipx/pip automatically
|
|
17
|
+
npx distil-llm wrap -- claude
|
|
18
|
+
|
|
19
|
+
# or start the proxy and point any SDK at it
|
|
20
|
+
npx distil-llm proxy # http://127.0.0.1:8788
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`npx distil-llm` bridges to the distil CLI via `uvx`/`pipx` (install
|
|
24
|
+
[uv](https://docs.astral.sh/uv/) once and it just works) — or `pip install
|
|
25
|
+
distil-llm` for a permanent install.
|
|
26
|
+
|
|
27
|
+
## Point your SDK at the proxy
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
31
|
+
import { distilBaseURL } from "distil-llm";
|
|
32
|
+
|
|
33
|
+
const client = new Anthropic({ baseURL: distilBaseURL() });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
38
|
+
import { distilBaseURL } from "distil-llm";
|
|
39
|
+
|
|
40
|
+
const anthropic = createAnthropic({ baseURL: distilBaseURL() });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import OpenAI from "openai";
|
|
45
|
+
import { distilOpenAIBaseURL } from "distil-llm";
|
|
46
|
+
|
|
47
|
+
const openai = new OpenAI({ baseURL: distilOpenAIBaseURL() }); // adds /v1
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`distilBaseURL()` honors `DISTIL_BASE_URL` / `DISTIL_PORT` (defaults
|
|
51
|
+
`http://127.0.0.1:8788`).
|
|
52
|
+
|
|
53
|
+
## Why distil
|
|
54
|
+
|
|
55
|
+
- **Reversible** — Tier-0 lossless + Tier-1 digests the model can expand back on
|
|
56
|
+
demand. Nothing is silently lost.
|
|
57
|
+
- **Proven, per request** — a live decision-equivalence shadow gate, not just
|
|
58
|
+
offline benchmarks.
|
|
59
|
+
- **Honest** — savings are calibrated to your billed usage; the community board
|
|
60
|
+
publishes real, auditable numbers.
|
|
61
|
+
|
|
62
|
+
Full docs: <https://dshakes.github.io/distil/> · License: Apache-2.0
|
package/bin/distil.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `npx distil-llm <args>` — thin bridge to the distil CLI (Python), so JS/TS
|
|
3
|
+
// developers get distil without touching pip. All args pass straight through.
|
|
4
|
+
//
|
|
5
|
+
// npx distil-llm wrap -- claude # route your agent through distil
|
|
6
|
+
// npx distil-llm proxy # start the proxy for any SDK baseURL
|
|
7
|
+
// npx distil-llm stats # your genuine savings
|
|
8
|
+
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
const { spawn } = require("node:child_process");
|
|
12
|
+
const { resolveRunner, NO_RUNNER_HELP } = require("../lib/runner.js");
|
|
13
|
+
|
|
14
|
+
const runner = resolveRunner();
|
|
15
|
+
if (!runner) {
|
|
16
|
+
process.stderr.write(NO_RUNNER_HELP + "\n");
|
|
17
|
+
process.exit(127);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const args = runner.prefixArgs.concat(process.argv.slice(2));
|
|
21
|
+
const child = spawn(runner.cmd, args, { stdio: "inherit" });
|
|
22
|
+
child.on("exit", (code, signal) => {
|
|
23
|
+
if (signal) process.kill(process.pid, signal);
|
|
24
|
+
else process.exit(code == null ? 1 : code);
|
|
25
|
+
});
|
|
26
|
+
child.on("error", (err) => {
|
|
27
|
+
process.stderr.write(`distil: failed to launch ${runner.cmd}: ${err.message}\n`);
|
|
28
|
+
process.exit(127);
|
|
29
|
+
});
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface DistilURLOptions {
|
|
2
|
+
/** Proxy host. Default "127.0.0.1". */
|
|
3
|
+
host?: string;
|
|
4
|
+
/** Proxy port. Default 8788 (or DISTIL_PORT). */
|
|
5
|
+
port?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Base URL of a local distil proxy (honors DISTIL_BASE_URL). */
|
|
9
|
+
export function distilBaseURL(opts?: DistilURLOptions): string;
|
|
10
|
+
|
|
11
|
+
/** distil proxy base URL with the OpenAI `/v1` segment appended. */
|
|
12
|
+
export function distilOpenAIBaseURL(opts?: DistilURLOptions): string;
|
|
13
|
+
|
|
14
|
+
export const DEFAULT_PORT: number;
|
|
15
|
+
export const DEFAULT_HOST: string;
|
package/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// distil-llm — TS/JS helpers for routing any SDK through the distil proxy.
|
|
2
|
+
//
|
|
3
|
+
// distil compresses at the network layer: start the proxy once
|
|
4
|
+
// (`npx distil-llm proxy`, default http://127.0.0.1:8788) and point your SDK's
|
|
5
|
+
// baseURL at it — no code changes to your calls, cache-aware reversible
|
|
6
|
+
// compression, per-request decision-equivalence proof.
|
|
7
|
+
//
|
|
8
|
+
// import Anthropic from "@anthropic-ai/sdk";
|
|
9
|
+
// import { distilBaseURL } from "distil-llm";
|
|
10
|
+
// const client = new Anthropic({ baseURL: distilBaseURL() });
|
|
11
|
+
//
|
|
12
|
+
// import { createAnthropic } from "@ai-sdk/anthropic";
|
|
13
|
+
// const anthropic = createAnthropic({ baseURL: distilBaseURL() });
|
|
14
|
+
//
|
|
15
|
+
// Zero dependencies. The proxy itself is the integration; these are just the
|
|
16
|
+
// tiny glue so you don't hardcode the URL.
|
|
17
|
+
|
|
18
|
+
"use strict";
|
|
19
|
+
|
|
20
|
+
const DEFAULT_PORT = 8788;
|
|
21
|
+
const DEFAULT_HOST = "127.0.0.1";
|
|
22
|
+
|
|
23
|
+
/** Base URL of a local distil proxy. Reads DISTIL_BASE_URL if set, else builds
|
|
24
|
+
* http://<host>:<port> (defaults 127.0.0.1:8788). */
|
|
25
|
+
function distilBaseURL(opts) {
|
|
26
|
+
opts = opts || {};
|
|
27
|
+
if (process.env.DISTIL_BASE_URL) return process.env.DISTIL_BASE_URL;
|
|
28
|
+
const host = opts.host || DEFAULT_HOST;
|
|
29
|
+
const port = opts.port || Number(process.env.DISTIL_PORT) || DEFAULT_PORT;
|
|
30
|
+
return `http://${host}:${port}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** OpenAI-style clients expect the base URL to include the API version segment. */
|
|
34
|
+
function distilOpenAIBaseURL(opts) {
|
|
35
|
+
return distilBaseURL(opts).replace(/\/+$/, "") + "/v1";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = { distilBaseURL, distilOpenAIBaseURL, DEFAULT_PORT, DEFAULT_HOST };
|
package/lib/runner.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Resolve how to run the (Python) distil CLI from Node, in preference order:
|
|
2
|
+
// 1. an already-installed `distil` on PATH (pipx/pip install)
|
|
3
|
+
// 2. `uvx --from distil-llm distil` (ephemeral, no install — the happy path)
|
|
4
|
+
// 3. `pipx run --spec distil-llm distil`
|
|
5
|
+
// 4. `python3 -m distil` (if the package is importable)
|
|
6
|
+
// Pure Node, zero dependencies. Exported for testing.
|
|
7
|
+
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
const { spawnSync } = require("node:child_process");
|
|
11
|
+
|
|
12
|
+
function has(cmd) {
|
|
13
|
+
const probe = process.platform === "win32" ? "where" : "which";
|
|
14
|
+
return spawnSync(probe, [cmd], { stdio: "ignore" }).status === 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Return {cmd, prefixArgs} for invoking distil, or null if no runner exists. */
|
|
18
|
+
function resolveRunner(env) {
|
|
19
|
+
env = env || process.env;
|
|
20
|
+
if (env.DISTIL_NPM_RUNNER) {
|
|
21
|
+
// escape hatch for tests / custom setups: "cmd arg1 arg2"
|
|
22
|
+
const parts = env.DISTIL_NPM_RUNNER.split(" ").filter(Boolean);
|
|
23
|
+
return { cmd: parts[0], prefixArgs: parts.slice(1) };
|
|
24
|
+
}
|
|
25
|
+
if (has("distil")) return { cmd: "distil", prefixArgs: [] };
|
|
26
|
+
if (has("uvx")) return { cmd: "uvx", prefixArgs: ["--from", "distil-llm", "distil"] };
|
|
27
|
+
if (has("pipx")) return { cmd: "pipx", prefixArgs: ["run", "--spec", "distil-llm", "distil"] };
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const NO_RUNNER_HELP = [
|
|
32
|
+
"distil-llm (npm) bridges to the distil CLI, which runs on Python.",
|
|
33
|
+
"No runner found. Install one of:",
|
|
34
|
+
" • uv → https://docs.astral.sh/uv/ (then `npx distil-llm …` just works via uvx)",
|
|
35
|
+
" • pipx → pipx install distil-llm",
|
|
36
|
+
" • pip → pip install distil-llm",
|
|
37
|
+
"",
|
|
38
|
+
"Then, e.g.: npx distil-llm wrap -- claude",
|
|
39
|
+
].join("\n");
|
|
40
|
+
|
|
41
|
+
module.exports = { resolveRunner, has, NO_RUNNER_HELP };
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "distil-llm",
|
|
3
|
+
"version": "1.25.0",
|
|
4
|
+
"description": "Compress your AI agent's context and prove its decisions don't change — cache-aware, reversible, certified. JS/TS bridge to the distil CLI + proxy helpers.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"llm",
|
|
7
|
+
"ai-agent",
|
|
8
|
+
"context-compression",
|
|
9
|
+
"prompt-compression",
|
|
10
|
+
"token-savings",
|
|
11
|
+
"anthropic",
|
|
12
|
+
"openai",
|
|
13
|
+
"proxy",
|
|
14
|
+
"claude",
|
|
15
|
+
"mcp"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://dshakes.github.io/distil/",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/dshakes/distil.git",
|
|
21
|
+
"directory": "packaging/npm"
|
|
22
|
+
},
|
|
23
|
+
"license": "Apache-2.0",
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"main": "index.js",
|
|
26
|
+
"types": "index.d.ts",
|
|
27
|
+
"bin": {
|
|
28
|
+
"distil": "bin/distil.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"bin/",
|
|
32
|
+
"lib/",
|
|
33
|
+
"index.js",
|
|
34
|
+
"index.d.ts",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"test": "node --test test/"
|
|
42
|
+
}
|
|
43
|
+
}
|