@liwu1995/afu-context 0.1.5 → 0.1.11
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 +80 -51
- package/README.zh-CN.md +80 -51
- package/bin/afu.mjs +54 -7
- package/bin/host-autoload.py +89 -25
- package/bin/install-guide.mjs +25 -3
- package/bin/platform.mjs +4 -4
- package/bin/runtime.mjs +5 -1
- package/package.json +1 -1
- package/python/{afu_context_local-0.1.5-py3-none-any.whl → afu_context_local-0.1.11-py3-none-any.whl} +0 -0
- package/release.json +3 -3
- package/scripts/dsh-overlay.mjs +8 -3
- package/src/afu_host_integrations/dsh/dist/index.js +29 -4
- package/src/afu_host_integrations/pi/dist/index.js +214 -10
- package/src/afu_host_integrations/shared/runtime-client/dist/host-worker.js +6 -3
- package/src/afu_host_integrations/shared/runtime-client/dist/index.js +1 -1
- package/src/afu_host_integrations/shared/runtime-client/dist/telemetry.js +25 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AFU Context · Local asynchronous context compression
|
|
2
2
|
|
|
3
|
-
**English** · [简体中文](README.zh-CN.md) · [npm](https://www.npmjs.com/package/@
|
|
3
|
+
**English** · [简体中文](README.zh-CN.md) · [npm](https://www.npmjs.com/package/@afu_context/afu-context) · [Install](#install) · [Results](#results) · [Dashboard](#dashboard)
|
|
4
4
|
|
|
5
5
|
In a long session, the same tool output can travel with every model request. AFU uses the host’s selected model to summarize completed history in the background. Once ready, the summary can replace that history on a later request while preserving newer tool calls and messages.
|
|
6
6
|
|
|
@@ -20,37 +20,19 @@ Install and sign in to your host first. You need npm, Node.js **22.19+ (22.x) or
|
|
|
20
20
|
|
|
21
21
|
| Host | System | Install | Launch after installation |
|
|
22
22
|
| --- | --- | --- | --- |
|
|
23
|
-
| <a id="afu-claude"></a>Claude Code | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
| <a id="afu-pi"></a>Pi | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @
|
|
27
|
-
|
|
|
23
|
+
| <a id="afu-claude"></a>Claude Code | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install claude` | `claude` |
|
|
24
|
+
| <a id="afu-codex"></a>Codex CLI | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install codex` | `codex` |
|
|
25
|
+
| Codex CLI | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@afu_context/afu-context@0.1.11" install codex` | `codex` |
|
|
26
|
+
| <a id="afu-pi"></a>Pi | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install pi` | `pi` |
|
|
27
|
+
| Pi | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@afu_context/afu-context@0.1.11" install pi` | `pi` |
|
|
28
|
+
| <a id="afu-dsh"></a>DSH | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install dsh --profile YOUR_PROFILE` | `dsh --profile YOUR_PROFILE` |
|
|
29
|
+
| DSH | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@afu_context/afu-context@0.1.11" install dsh --profile YOUR_PROFILE` | `dsh --profile YOUR_PROFILE` |
|
|
28
30
|
|
|
29
|
-
Supported
|
|
31
|
+
Supported on macOS (Apple Silicon) and Linux x64. Start a new session after installing.
|
|
30
32
|
|
|
31
|
-
¹
|
|
33
|
+
¹ Windows: Codex CLI, Pi and DSH are implemented but not yet tested on Windows hardware. Run the commands in PowerShell; `npx.cmd` and the quotes around the package name are required there. Claude Code on Windows is not supported yet.
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<details>
|
|
36
|
-
<summary>Startup after reboot and Pi / DSH launch options</summary>
|
|
37
|
-
|
|
38
|
-
Claude Code and Codex start the AFU gateway from their session hooks, so it comes back with the first session after a reboot. Installation also registers a login service when the system allows it. If system policy refuses it (for example an endpoint-security rule on `~/Library/LaunchAgents`, or Linux without user systemd), installation continues and prints a notice; no reinstall is needed after reboot. Codex runs only hooks you have trusted: open `codex` once after installing and trust the AFU hooks when asked.
|
|
39
|
-
|
|
40
|
-
For Pi **0.84.4**, pass `--provider` and `--model` on the Pi command line. DSH was tested with **0.1.2-rc.1** and Cordis **4.0.2**. If a web profile reports an incompatible HMR API, run `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.5 dsh --web-compat -- --profile web`.
|
|
41
|
-
|
|
42
|
-
</details>
|
|
43
|
-
|
|
44
|
-
<details>
|
|
45
|
-
<summary>Known issues and network notes</summary>
|
|
46
|
-
|
|
47
|
-
- npm prints `EBADENGINE` on Node.js 22.18 or older. The requirement is 22.19+ (22.x) or 24+; upgrade Node.js before installing.
|
|
48
|
-
- If the host reaches its model through a proxy, start the host with its usual `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY`. AFU records the proxy seen by the installer or by the host's session hook and the gateway uses it for later requests. If `/afu:status` reports the upstream as unreachable, start the host from a shell with the proxy set.
|
|
49
|
-
- Codex through AFU occasionally stalls for about three minutes before reconnecting. The cause is not yet confirmed.
|
|
50
|
-
- Codex conversations keep working across install and removal: AFU routes Codex's built-in OpenAI provider (`openai_base_url`) instead of adding a provider. Upgrading from 0.1.2 rebinds the conversations created under its `afu_native` provider to `openai` so they can be resumed again (in the CLI and Codex Desktop); a conversation still open is skipped and handled on the next upgrade or install.
|
|
51
|
-
- Removal restores your original file byte for byte when you made no other change. If you edited the file after installing, removal reverts only the AFU entries and keeps your edits.
|
|
52
|
-
|
|
53
|
-
</details>
|
|
35
|
+
See [Installation notes](https://code.alipay.com/med_ai/afu_context_liwu/blob/master/docs/install-notes.md) for verification scope, versions and mirrors, startup after reboot, Pi / DSH options and known issues.
|
|
54
36
|
|
|
55
37
|
<a id="results"></a>
|
|
56
38
|
|
|
@@ -72,54 +54,101 @@ In a LongBench V2 replay of 39 history questions (20 agent histories and 19 dial
|
|
|
72
54
|
|
|
73
55
|
## Web dashboard
|
|
74
56
|
|
|
75
|
-
|
|
57
|
+
### Open the dashboard
|
|
76
58
|
|
|
77
59
|
| Where | Type |
|
|
78
60
|
| --- | --- |
|
|
79
|
-
| In a Claude Code session | `/afu:
|
|
80
|
-
| In a Codex session | `$afu-
|
|
81
|
-
| In a terminal | `afu` |
|
|
61
|
+
| In a Claude Code session | `/afu:ctx-admin` |
|
|
62
|
+
| In a Codex session | `$afu-ctx-admin` |
|
|
63
|
+
| In a terminal | `afu-ctx-admin` |
|
|
82
64
|
|
|
83
|
-
The dashboard runs in the background and does not occupy a terminal; opening it again reuses the same one, and it exits after 30 minutes without an open page.
|
|
65
|
+
- The dashboard runs in the background and does not occupy a terminal; opening it again reuses the same one, and it exits after 30 minutes without an open page.
|
|
66
|
+
- It opens in the dark theme; switch to light, follow-system or English/Chinese in the top-right corner.
|
|
67
|
+
- The terminal commands are placed in `~/.local/bin` by the installer (only when that folder is already on `PATH`; shell startup files are never edited and existing commands of the same name are kept) and are removed with the last integration.
|
|
84
68
|
|
|
85
|
-
|
|
69
|
+
### Check the current session
|
|
86
70
|
|
|
87
|
-
|
|
71
|
+
Type `/afu:status` in Claude Code, `$afu-status` in Codex, or run `afu status` in a terminal. It shows whether AFU is connected, the current context against the compaction threshold, and how many compactions have been applied.
|
|
72
|
+
|
|
73
|
+
Without the terminal commands (for example when `~/.local/bin` is not on `PATH`), use the full npx commands. For Codex; for another host replace `codex` with `claude`, `pi` or `dsh`:
|
|
88
74
|
|
|
89
75
|
```sh
|
|
90
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
91
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
76
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 status codex --brief
|
|
77
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 ui
|
|
92
78
|
```
|
|
93
79
|
|
|
94
|
-
|
|
80
|
+
### What the dashboard shows
|
|
81
|
+
|
|
82
|
+
- **Overview**: tokens saved and compactions applied, plus conversation input, cache hit rate, compaction cost and active sessions; below, one row per conversation with its title, compaction state and a bar showing how far the context is from the compaction trigger.
|
|
83
|
+
- **Session detail**: the context drop after each compaction, how long each one took and what it saved, and cache hit rates. A conversation the host split into segments (sub-agents, title requests, its own compaction) lists them here.
|
|
84
|
+
- **Status**: integrations, versions and issues.
|
|
85
|
+
|
|
86
|
+
Each compaction is recorded in three steps: **request observed → summary ready → summary applied**. For Claude Code and Codex, "applied" means a request carrying the summary received a complete successful response; for Pi it means a model request was sent with the summary in place of the history it covers; for DSH it means the host committed the summary to session history. Summaries run in the background and never delay the conversation. Unreported cache usage is shown as unknown; savings are calibrated against the token counts the model service reports for requests sent without a summary, and like costs they are estimates, not provider bills. To estimate cost, supply per-session input, output and cache prices; see [Dashboard and costs](https://code.alipay.com/med_ai/afu_context_liwu/blob/master/docs/local-dashboard.md).
|
|
87
|
+
|
|
88
|
+

|
|
95
89
|
|
|
96
|
-
|
|
90
|
+
*Demo data.*
|
|
97
91
|
|
|
98
92
|
## Models and thresholds
|
|
99
93
|
|
|
100
|
-
All four integrations reuse the conversation’s model and authentication.
|
|
94
|
+
All four integrations reuse the conversation’s model and authentication. When the context passes the trigger, AFU summarizes earlier messages in the background with the current model, and later requests use the compacted history. Trigger = model window × trigger ratio. Defaults:
|
|
95
|
+
|
|
96
|
+
| Model window | Default ratio | Example trigger |
|
|
97
|
+
| --- | --- | --- |
|
|
98
|
+
| 1,000,000 tokens or more | 50% | 1,000,000 window → 500,000 |
|
|
99
|
+
| Under 1,000,000 tokens | 60% | 272,000 window → 163,200; 200,000 window → 120,000 |
|
|
100
|
+
|
|
101
|
+
The model window is detected automatically:
|
|
102
|
+
|
|
103
|
+
| Host | Where the window comes from |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| Claude Code | The window Claude Code passes to its status line command. AFU wraps that command to read it; your own status line keeps running unchanged |
|
|
106
|
+
| Codex | Codex's local model catalog cache |
|
|
107
|
+
| Pi / DSH | The model and window the host has selected |
|
|
108
|
+
|
|
109
|
+
If a window is still unknown, chat continues and `/afu:status` or `$afu-status` says so.
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
<summary>Set a window or ratio, or restore automatic settings</summary>
|
|
111
|
+
### Set the window or ratio manually
|
|
104
112
|
|
|
105
|
-
|
|
113
|
+
Run the same install command with options, then start a new session. For Codex; for another host replace `codex` with `claude`, `pi` or `dsh`.
|
|
114
|
+
|
|
115
|
+
| To | Option |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| Compact earlier or later | `--ratio 0.3` (between 0 and 1) |
|
|
118
|
+
| Set the model window | `--context-window 200000` |
|
|
119
|
+
| Restore automatic settings | `--context-window auto --ratio auto` |
|
|
106
120
|
|
|
107
121
|
```sh
|
|
108
|
-
|
|
109
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
122
|
+
# Trigger at 30% of a manually set 200,000-token window (60,000 tokens)
|
|
123
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install codex --context-window 200000 --ratio 0.3
|
|
124
|
+
# Restore automatic settings
|
|
125
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install codex --context-window auto --ratio auto
|
|
110
126
|
```
|
|
111
127
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
For frequent use, run `npm install -g --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.5` and use `afu` in place of the full `npx` invocation. For example, `afu ui` opens the dashboard, and `afu ui --prices ./afu-prices.json` uses your price file to estimate costs.
|
|
128
|
+
For frequent use, run `npm install -g --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11` and use `afu` in place of the full `npx` invocation. For example, `afu ui --prices ./afu-prices.json` opens the dashboard with your price file to estimate costs.
|
|
115
129
|
|
|
116
130
|
## Upgrade and remove
|
|
117
131
|
|
|
118
132
|
After upgrading a Claude Code or Codex integration, start a new session to use the new gateway. To uninstall, remove the host integration first, then restart the host. Use the appropriate command below.
|
|
119
133
|
|
|
134
|
+
To move every installed integration (Claude Code, Codex, Pi and each DSH profile) to the latest release in one step, run `update` with `@latest`. It upgrades them one by one with the settings they were installed with and prints the version change for each:
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@latest update
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
To check which version you have, run `--version` (the launcher), or `status --brief`, which shows the installed version of each host:
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@latest --version
|
|
144
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@latest status --brief
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
To upgrade or remove one host:
|
|
148
|
+
|
|
120
149
|
```sh
|
|
121
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
122
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
150
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 upgrade codex
|
|
151
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 remove codex
|
|
123
152
|
```
|
|
124
153
|
|
|
125
154
|
Use `remove pi` or `remove dsh` for those integrations. In Windows PowerShell, use `npx.cmd` and double-quote the package name.
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AFU Context · 本地异步上下文压缩
|
|
2
2
|
|
|
3
|
-
[English](README.md) · **简体中文** · [npm](https://www.npmjs.com/package/@
|
|
3
|
+
[English](README.md) · **简体中文** · [npm](https://www.npmjs.com/package/@afu_context/afu-context) · [一键安装](#install) · [评测效果](#results) · [Web 面板](#dashboard)
|
|
4
4
|
|
|
5
5
|
长对话里,同一段工具输出可能随每次请求反复发送。AFU 用宿主当前的模型在后台整理已经结束的对话。摘要就绪后,下一次合适的请求可以用摘要替换旧历史,同时保留之后发生的工具调用和新消息。
|
|
6
6
|
|
|
@@ -20,37 +20,19 @@
|
|
|
20
20
|
|
|
21
21
|
| 宿主 | 系统 | 一键安装 | 安装后启动 |
|
|
22
22
|
| --- | --- | --- | --- |
|
|
23
|
-
| <a id="afu-claude"></a>Claude Code | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
| <a id="afu-pi"></a>Pi | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @
|
|
27
|
-
|
|
|
23
|
+
| <a id="afu-claude"></a>Claude Code | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install claude` | `claude` |
|
|
24
|
+
| <a id="afu-codex"></a>Codex CLI | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install codex` | `codex` |
|
|
25
|
+
| Codex CLI | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@afu_context/afu-context@0.1.11" install codex` | `codex` |
|
|
26
|
+
| <a id="afu-pi"></a>Pi | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install pi` | `pi` |
|
|
27
|
+
| Pi | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@afu_context/afu-context@0.1.11" install pi` | `pi` |
|
|
28
|
+
| <a id="afu-dsh"></a>DSH | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install dsh --profile YOUR_PROFILE` | `dsh --profile YOUR_PROFILE` |
|
|
29
|
+
| DSH | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@afu_context/afu-context@0.1.11" install dsh --profile YOUR_PROFILE` | `dsh --profile YOUR_PROFILE` |
|
|
28
30
|
|
|
29
|
-
支持 Apple Silicon
|
|
31
|
+
支持 macOS(Apple Silicon)和 x64 Linux;安装后新开会话即可。
|
|
30
32
|
|
|
31
|
-
¹ Windows
|
|
33
|
+
¹ Windows:Codex CLI、Pi、DSH 已实现,尚未在 Windows 实机验收。请在 PowerShell 中执行,命令里的 `npx.cmd` 和包名两侧的双引号都不能省。Claude Code 暂不支持 Windows。
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<details>
|
|
36
|
-
<summary>重启后的启动方式与 Pi / DSH 启动参数</summary>
|
|
37
|
-
|
|
38
|
-
Claude Code 和 Codex 会在会话启动时通过 hook 拉起 AFU 网关,重启电脑后打开第一个会话即可恢复。系统允许时,安装还会注册开机自启;若被系统策略拒绝(例如终端安全软件禁止写入 `~/Library/LaunchAgents`,或 Linux 没有用户级 systemd),安装会继续并给出提示,重启后无需重新安装。Codex 只执行你信任过的 hook:安装后打开一次 `codex`,在提示中信任 AFU 的 hook。
|
|
39
|
-
|
|
40
|
-
Pi **0.84.4** 可直接传 `--provider` 和 `--model`。DSH 已适配 **0.1.2-rc.1** 和 Cordis **4.0.2**。若 Web profile 提示 HMR API 不兼容,可使用 `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.5 dsh --web-compat -- --profile web`。
|
|
41
|
-
|
|
42
|
-
</details>
|
|
43
|
-
|
|
44
|
-
<details>
|
|
45
|
-
<summary>已知问题与网络说明</summary>
|
|
46
|
-
|
|
47
|
-
- Node.js 22.18 及更早版本安装时 npm 会提示 `EBADENGINE`。要求为 22.19+(22.x)或 24+,请先升级 Node.js。
|
|
48
|
-
- 宿主需要通过代理访问模型时,照常在设置了 `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` 的终端启动宿主即可。AFU 会记录安装命令或宿主会话 hook 看到的代理,网关之后的请求都会使用它。若 `/afu:status` 提示上游不可达,请在设置了代理的终端重新启动宿主。
|
|
49
|
-
- 经 AFU 使用 Codex 时,偶尔会停顿约三分钟后重连,原因尚未确认。
|
|
50
|
-
- Codex 的历史会话在安装和移除前后都能继续:AFU 改的是 Codex 内置 OpenAI provider 的地址(`openai_base_url`),不再新增 provider。从 0.1.2 升级时,会把 0.1.2 在 `afu_native` provider 下创建的会话改回 `openai`,CLI 和 Codex Desktop 都能重新打开;仍在使用的会话会跳过,下次升级或安装时再处理。
|
|
51
|
-
- 移除时若你没有改过配置文件,会逐字节恢复原文件;若安装后改过,只撤销 AFU 的条目,保留你的修改。
|
|
52
|
-
|
|
53
|
-
</details>
|
|
35
|
+
验证范围、版本与镜像、重启后的启动方式、Pi / DSH 参数和已知问题见 [安装说明](https://code.alipay.com/med_ai/afu_context_liwu/blob/master/docs/install-notes.zh-CN.md)。
|
|
54
36
|
|
|
55
37
|
<a id="results"></a>
|
|
56
38
|
|
|
@@ -72,54 +54,101 @@ Pi **0.84.4** 可直接传 `--provider` 和 `--model`。DSH 已适配 **0.1.2-rc
|
|
|
72
54
|
|
|
73
55
|
## Web 面板:查看压缩是否生效
|
|
74
56
|
|
|
75
|
-
|
|
57
|
+
### 打开面板
|
|
76
58
|
|
|
77
59
|
| 在哪里 | 输入 |
|
|
78
60
|
| --- | --- |
|
|
79
|
-
| Claude Code 会话里 | `/afu:
|
|
80
|
-
| Codex 会话里 | `$afu-
|
|
81
|
-
| 终端里 | `afu` |
|
|
61
|
+
| Claude Code 会话里 | `/afu:ctx-admin` |
|
|
62
|
+
| Codex 会话里 | `$afu-ctx-admin` |
|
|
63
|
+
| 终端里 | `afu-ctx-admin` |
|
|
82
64
|
|
|
83
|
-
面板在后台运行,不占用终端;再次打开会复用同一个面板,30
|
|
65
|
+
- 面板在后台运行,不占用终端;再次打开会复用同一个面板,30 分钟没有页面打开时自动退出。
|
|
66
|
+
- 默认暗色主题,右上角可切换亮色、跟随系统和中英文。
|
|
67
|
+
- 终端命令由安装程序放在 `~/.local/bin`(已在 `PATH` 中时才放,不改 shell 配置,不覆盖你已有的同名命令),移除最后一个接入时一并删除。
|
|
84
68
|
|
|
85
|
-
|
|
69
|
+
### 查看当前会话
|
|
86
70
|
|
|
87
|
-
|
|
71
|
+
Claude Code 输入 `/afu:status`,Codex 输入 `$afu-status`,终端里运行 `afu status`。会显示 AFU 是否已接入、当前上下文距离压缩触发线还有多少,以及已经生效的压缩次数。
|
|
72
|
+
|
|
73
|
+
没有上面的终端命令时(例如 `~/.local/bin` 不在 `PATH` 中),可以用完整的 npx 命令。以 Codex 为例,其它宿主将 `codex` 换成 `claude`、`pi` 或 `dsh`:
|
|
88
74
|
|
|
89
75
|
```sh
|
|
90
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
91
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
76
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 status codex --brief
|
|
77
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 ui
|
|
92
78
|
```
|
|
93
79
|
|
|
94
|
-
|
|
80
|
+
### 面板内容
|
|
81
|
+
|
|
82
|
+
- **总览**:节省的 token 和生效的压缩次数,以及对话输入、缓存命中率、压缩消耗和活跃会话;下方每个对话一行,显示标题、压缩状态,以及距离触发压缩还差多少的进度条。
|
|
83
|
+
- **会话详情**:上下文在每次压缩后的回落、每次压缩的耗时和节省量,以及缓存命中率。宿主把一个对话分成多段时(子代理、起标题请求、宿主自己压缩后),这里会列出各段。
|
|
84
|
+
- **运行状态**:接入情况、版本和异常记录。
|
|
85
|
+
|
|
86
|
+
每次压缩分三步记录:**请求已接入 → 摘要已生成 → 摘要已应用**。Claude Code 和 Codex 的“已应用”表示替换历史后的请求已收到完整成功响应;Pi 表示已有模型请求用摘要替换了它覆盖的历史;DSH 表示宿主已把摘要写入会话历史。摘要在后台生成,不影响对话。模型未返回的缓存用量显示为未知;节省量按模型服务对未压缩请求报告的实际 token 数校准,与费用一样都是估算,不是供应商账单。需要估算费用时,可按会话提供输入、输出和缓存单价,见[面板与费用](https://code.alipay.com/med_ai/afu_context_liwu/blob/master/docs/local-dashboard.zh-CN.md)。
|
|
87
|
+
|
|
88
|
+

|
|
95
89
|
|
|
96
|
-
|
|
90
|
+
*截图为演示数据。*
|
|
97
91
|
|
|
98
92
|
## 模型与压缩阈值
|
|
99
93
|
|
|
100
|
-
|
|
94
|
+
四个平台都复用主对话的模型和认证。上下文超过触发线时,AFU 在后台用当前模型生成摘要,之后的请求改用压缩后的历史。触发线 = 模型窗口 × 触发比例,默认如下:
|
|
95
|
+
|
|
96
|
+
| 模型窗口 | 默认触发比例 | 触发线示例 |
|
|
97
|
+
| --- | --- | --- |
|
|
98
|
+
| 1,000,000 tokens 及以上 | 50% | 1,000,000 窗口 → 500,000 |
|
|
99
|
+
| 小于 1,000,000 tokens | 60% | 272,000 窗口 → 163,200;200,000 窗口 → 120,000 |
|
|
100
|
+
|
|
101
|
+
模型窗口自动获取,不需要手动配置:
|
|
102
|
+
|
|
103
|
+
| 宿主 | 窗口从哪来 |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| Claude Code | Claude Code 传给状态栏命令的模型窗口。AFU 包装这条命令来读取,你原来的状态栏照常运行、显示不变 |
|
|
106
|
+
| Codex | Codex 本地的模型目录缓存 |
|
|
107
|
+
| Pi / DSH | 宿主当前选择的模型和窗口 |
|
|
108
|
+
|
|
109
|
+
窗口仍未知时聊天照常进行,`/afu:status` 或 `$afu-status` 会提示。
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
<summary>手动指定窗口、调整比例或恢复自动设置</summary>
|
|
111
|
+
### 手动指定窗口和调整比例
|
|
104
112
|
|
|
105
|
-
|
|
113
|
+
用同一条安装命令加参数即可,改完后新开会话生效。下面以 Codex 为例,其它宿主将 `codex` 换成 `claude`、`pi` 或 `dsh`。
|
|
114
|
+
|
|
115
|
+
| 想做的事 | 参数 |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| 提前或推迟压缩 | `--ratio 0.3`(取值 0 到 1 之间) |
|
|
118
|
+
| 手动指定模型窗口 | `--context-window 200000` |
|
|
119
|
+
| 恢复自动 | `--context-window auto --ratio auto` |
|
|
106
120
|
|
|
107
121
|
```sh
|
|
108
|
-
|
|
109
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
122
|
+
# 在 30% 触发,并手动指定 200,000 的窗口(即 60,000 触发)
|
|
123
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install codex --context-window 200000 --ratio 0.3
|
|
124
|
+
# 恢复自动设置
|
|
125
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 install codex --context-window auto --ratio auto
|
|
110
126
|
```
|
|
111
127
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
如果经常使用 AFU,可运行 `npm install -g --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.5`,以后用 `afu` 代替完整的 `npx` 命令。例如,`afu ui` 打开面板,`afu ui --prices ./afu-prices.json` 使用自己的单价文件估算费用。
|
|
128
|
+
如果经常使用 AFU,可运行 `npm install -g --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11`,以后用 `afu` 代替完整的 `npx` 命令。例如,`afu ui --prices ./afu-prices.json` 用自己的单价文件打开面板估算费用。
|
|
115
129
|
|
|
116
130
|
## 升级与移除
|
|
117
131
|
|
|
118
132
|
升级 Claude Code 或 Codex 接入后,新开会话即可使用新版网关。需要移除时,先撤销对应宿主的接入,再重启宿主。以下两条命令分别用于升级和移除。
|
|
119
133
|
|
|
134
|
+
想把已装的所有接入(Claude Code、Codex、Pi 和每个 DSH profile)一次升级到最新版,用 `@latest` 执行 `update`。它会按安装时的设置逐个升级,并打印每个接入从哪个版本升到哪个版本:
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@latest update
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
查看版本:`--version` 显示启动器版本,`status --brief` 显示每个宿主当前装的版本:
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@latest --version
|
|
144
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@latest status --brief
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
只升级或移除某一个宿主:
|
|
148
|
+
|
|
120
149
|
```sh
|
|
121
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
122
|
-
npx --yes --registry=https://registry.npmjs.org @
|
|
150
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 upgrade codex
|
|
151
|
+
npx --yes --registry=https://registry.npmjs.org @afu_context/afu-context@0.1.11 remove codex
|
|
123
152
|
```
|
|
124
153
|
|
|
125
154
|
Pi 和 DSH 可分别用 `remove pi` 或 `remove dsh` 撤销。Windows PowerShell 请使用 `npx.cmd` 并将包名放在双引号中。
|
package/bin/afu.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/** No postinstall side effects; recover only our versioned runtime cache. */
|
|
3
|
-
import {spawn} from 'node:child_process';
|
|
4
|
-
import {readFileSync} from 'node:fs';
|
|
3
|
+
import {spawn,spawnSync} from 'node:child_process';
|
|
4
|
+
import {readFileSync,readdirSync} from 'node:fs';
|
|
5
5
|
import {dirname,join,resolve} from 'node:path';
|
|
6
6
|
import {homedir,constants} from 'node:os';
|
|
7
7
|
import {fileURLToPath} from 'node:url';
|
|
8
|
-
import {guide} from './install-guide.mjs';
|
|
8
|
+
import {guide,hostCommand} from './install-guide.mjs';
|
|
9
9
|
import {prepareRuntime} from './runtime.mjs';
|
|
10
10
|
import {holdCache} from './cache-lease.mjs';
|
|
11
11
|
import {preparePlatform} from './platform.mjs';
|
|
@@ -29,13 +29,58 @@ function exitCode(code,signal){
|
|
|
29
29
|
if(code!==null&&code!==undefined)return code;
|
|
30
30
|
return signal&&constants.signals[signal]?128+constants.signals[signal]:1;
|
|
31
31
|
}
|
|
32
|
+
/** Installed integrations, with what each upgrade needs (config dir, host home, profile). */
|
|
33
|
+
function installedHosts(state){
|
|
34
|
+
const read=f=>{try{return JSON.parse(readFileSync(f,'utf8'));}catch{return null;}};
|
|
35
|
+
const found=[];let names=[];
|
|
36
|
+
try{names=readdirSync(join(state,'integrations')).filter(n=>n.endsWith('.json'));}catch{return found;}
|
|
37
|
+
for(const name of names){
|
|
38
|
+
const record=read(join(state,'integrations',name));
|
|
39
|
+
if(!record)continue;
|
|
40
|
+
if(typeof record.location==='string'&&!/[\\/]/.test(record.location)){
|
|
41
|
+
const receipt=read(join(state,'native',record.location,'install.json'));
|
|
42
|
+
if(receipt&&!receipt.removed&&['claude','codex'].includes(receipt.host))
|
|
43
|
+
found.push({host:receipt.host,version:receipt.version,args:receipt.directory?['--config-dir',receipt.directory]:[],env:{}});
|
|
44
|
+
}else if(['pi','dsh'].includes(record.host)&&!record.removed){
|
|
45
|
+
for(const [key,entry] of Object.entries(record.autoload||{})){
|
|
46
|
+
if(record.host==='pi'){
|
|
47
|
+
const agent=entry.entry?dirname(dirname(entry.entry)):null;
|
|
48
|
+
found.push({host:'pi',version:record.version,args:[],env:agent?{PI_CODING_AGENT_DIR:agent}:{}});
|
|
49
|
+
}else{
|
|
50
|
+
const home=entry.manifest?dirname(dirname(dirname(entry.manifest))):null;
|
|
51
|
+
found.push({host:'dsh',version:record.version,args:['--profile',key],env:home?{DSH_HOME:home}:{}});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return found;
|
|
57
|
+
}
|
|
58
|
+
/** Upgrade every installed host to this launcher's version, one after another. */
|
|
59
|
+
function updateAll(extra){
|
|
60
|
+
const at=extra.indexOf('--state');
|
|
61
|
+
const state=at>=0&&extra[at+1]?resolve(extra[at+1]):(env.AFU_STATE_DIR||join(homedir(),'.local/share/afu-context'));
|
|
62
|
+
const hosts=installedHosts(state);
|
|
63
|
+
if(!hosts.length){console.error('AFU: nothing installed to update; run install HOST first');return 1;}
|
|
64
|
+
let failed=0;
|
|
65
|
+
for(const item of hosts){
|
|
66
|
+
const label=item.host+(item.args[0]==='--profile'?` (profile ${item.args[1]})`:'');
|
|
67
|
+
console.error(`AFU: updating ${label}: ${item.version||'unknown'} -> ${manifest.version}`);
|
|
68
|
+
// COSEC: this launcher's own script, argv array, no shell.
|
|
69
|
+
const run=spawnSync(process.execPath,[fileURLToPath(import.meta.url),'upgrade',item.host,...item.args,...extra],{stdio:'inherit',env:{...env,...item.env}});
|
|
70
|
+
if(run.status!==0){failed++;console.error(`AFU: update of ${label} failed; it keeps its current version`);}
|
|
71
|
+
}
|
|
72
|
+
console.error(failed?`AFU: ${hosts.length-failed} of ${hosts.length} updated to ${manifest.version}`:`AFU: all ${hosts.length} integrations are on ${manifest.version}. Open new host sessions to use it.`);
|
|
73
|
+
return failed?1:0;
|
|
74
|
+
}
|
|
32
75
|
try{
|
|
33
76
|
// Only the bare launcher prints its own banner; "afu ui --help" and
|
|
34
77
|
// "afu claude --help" belong to the subcommand or the host.
|
|
35
78
|
if(!args.length || (['--help','-h'].includes(args[0]))){
|
|
36
|
-
console.log(
|
|
79
|
+
console.log(`AFU Context ${manifest.version}: install [claude|codex|pi|dsh], update, status, remove HOST, gc --dry-run, ui, --version.\nRun npx @afu_context/afu-context@latest install to detect your installed host; npx @afu_context/afu-context@latest update upgrades every installed host. Host login remains managed by the host.`);
|
|
37
80
|
process.exit(0);
|
|
38
81
|
}
|
|
82
|
+
if(['--version','-v','version'].includes(args[0])){console.log(manifest.version);process.exit(0);}
|
|
83
|
+
if(args[0]==='update'){process.exitCode=updateAll(args.slice(1));process.exit();}
|
|
39
84
|
args=await guide(args,env);
|
|
40
85
|
if(['install','upgrade'].includes(args[0])&&args.includes('--dry-run')){
|
|
41
86
|
console.log(JSON.stringify({preflight:'passed',host:args[1],configuration_changed:false,request_observed:false}));process.exit(0);
|
|
@@ -49,7 +94,8 @@ try{
|
|
|
49
94
|
const split=args.indexOf('--');
|
|
50
95
|
if(split<0 && args.length>1)throw Error('PLUGIN_REMOVED: pass host arguments after --');
|
|
51
96
|
// COSEC: fixed host executable, argv array, no shell; no runtime downloads.
|
|
52
|
-
const
|
|
97
|
+
const [binary,...prefix]=hostCommand(args[0],env);
|
|
98
|
+
const child=spawn(binary,[...prefix,...(split<0?[]:args.slice(split+1))],{stdio:'inherit',env,shell:false});
|
|
53
99
|
relaySignals(child);
|
|
54
100
|
child.on('error',()=>{console.error('AFU: HOST_EXECUTABLE_UNAVAILABLE');process.exitCode=1;});
|
|
55
101
|
child.on('exit',(code,signal)=>{process.exitCode=exitCode(code,signal);});
|
|
@@ -57,12 +103,13 @@ try{
|
|
|
57
103
|
const hostAction = ['pi','dsh'].includes(args[1]) && ['install','upgrade','remove','status'].includes(args[0]);
|
|
58
104
|
// Status always goes through one reporter (it understands autoload receipts,
|
|
59
105
|
// --json and --state); only Pi/DSH install/upgrade/remove need host-autoload.
|
|
60
|
-
const directHost =
|
|
106
|
+
const directHost = hostAction && args[0]!=='status';
|
|
61
107
|
if (directHost && ['install','upgrade'].includes(args[0])) {
|
|
62
108
|
// Autoload paths must outlive npx eviction and the ordinary launcher cache GC.
|
|
63
109
|
const state = env.AFU_STATE_DIR || join(homedir(), '.local/share/afu-context');
|
|
64
110
|
env.AFU_RUNTIME_DIR = join(state, 'autoload', 'runtimes');
|
|
65
111
|
}
|
|
112
|
+
env.AFU_NODE = process.execPath;
|
|
66
113
|
if (args[0] === 'pi') env.AFU_EXPLICIT_EXTENSION = 'pi';
|
|
67
114
|
release=await holdCache(manifest.build,env);
|
|
68
115
|
const location=await prepareRuntime(root,manifest,env);
|
|
@@ -72,6 +119,6 @@ try{
|
|
|
72
119
|
const child=spawn(python,[...entry,...args],{stdio:'inherit',env});
|
|
73
120
|
relaySignals(child);
|
|
74
121
|
child.on('error',()=>{release?.();console.error('AFU failed to start');process.exitCode=1;});
|
|
75
|
-
child.on('exit',(code,signal)=>{release?.();if(code===0&&['install','upgrade'].includes(args[0]))console.error(`AFU: installed ${args[1]}; ${['claude','codex'].includes(args[1])?'service checked; open a new '+args[1]+' session':directHost?'open a new host session':'launch with afu '+args[1]}. Waiting for the first observed request; compression is not yet verified.`);process.exitCode=exitCode(code,signal);});
|
|
122
|
+
child.on('exit',(code,signal)=>{release?.();if(code===0&&['install','upgrade'].includes(args[0]))console.error(`AFU: installed ${args[1]} ${manifest.version}; ${['claude','codex'].includes(args[1])?'service checked; open a new '+args[1]+' session':directHost?'open a new host session':'launch with afu '+args[1]}. Waiting for the first observed request; compression is not yet verified.`);process.exitCode=exitCode(code,signal);});
|
|
76
123
|
}
|
|
77
124
|
}catch(error){release?.();console.error('AFU: '+error.message);process.exitCode=1;}
|