@liwu1995/afu-context 0.1.6 → 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 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/@liwu1995/afu-context) · [Install](#install) · [Results](#results) · [Dashboard](#dashboard)
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 @liwu1995/afu-context@0.1.6 install claude` | `claude` |
24
- | Claude Code | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@liwu1995/afu-context@0.1.6" install claude` | `claude` |
25
- | <a id="afu-codex"></a>Codex CLI | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install codex` | `codex` |
26
- | <a id="afu-pi"></a>Pi | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install pi` | `pi` |
27
- | <a id="afu-dsh"></a>DSH | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install dsh --profile YOUR_PROFILE` | `dsh --profile YOUR_PROFILE` |
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 systems are macOS on Apple Silicon (ARM64) and Linux x64. The first `afu` command sets up a private Python environment from your Python 3.11+, which takes about half a minute. On macOS, Claude Code and Codex were tested end to end with real models (install, chat with compaction, upgrade, remove; when endpoint security blocks login autostart, session hooks start the gateway), including Codex sessions with tool calls, pasted images and Codex's own compactions. On Linux, Claude Code was tested with a real model and Codex with a local fixture; user-systemd autostart was not tested. Start a new session for Claude Code or Codex. Pi loads the extension in new sessions. Replace `YOUR_PROFILE` with the DSH profile to integrate, such as `headless` or `web`. For web, you can also launch with `dsh web`. To remove just one profile, run `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 remove dsh --profile YOUR_PROFILE`.
31
+ Supported on macOS (Apple Silicon) and Linux x64. Start a new session after installing.
30
32
 
31
- ¹ On Windows, use PowerShell, Python **3.11+** and a Claude Code version with PowerShell hook support. Native Claude Code is implemented and awaits Windows testing. Native Codex is unsupported, and Pi and DSH are unverified on Windows.
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
- The commands pin **0.1.6** from the public npm registry so installation does not depend on a mirror carrying the latest release. Use 0.1.6 or later; earlier versions lack the fixes in this release. If npm reports `with a date before`, check `before` and `min-release-age`. This version was published at **PUBLISH_TIME_UTC**. Retry after a rolling cooldown expires. For a fixed cutoff, the effective policy must allow that publication date.
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.6 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
- The quickest way to open the dashboard:
57
+ ### Open the dashboard
76
58
 
77
59
  | Where | Type |
78
60
  | --- | --- |
79
- | In a Claude Code session | `/afu:ui` |
80
- | In a Codex session | `$afu-ui` |
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. The terminal `afu` command is placed in `~/.local/bin` by the installer (only when that folder is already on `PATH`; shell startup files are never edited) and is removed with the last integration.
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
- To check compaction for the current session, 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. The in-session commands are added on install and removed on removal.
69
+ ### Check the current session
86
70
 
87
- From a terminal, check the integration status, then open the dashboard and select your session. For another host, replace `codex` with `claude`, `pi` or `dsh`; `--brief` prints the same short lines as the slash commands.
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 @liwu1995/afu-context@0.1.6 status codex --brief
91
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 ui
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
- The dashboard distinguishes **request observed → summary ready → summary applied**. For Claude Code and Codex, application requires a complete successful response to a request carrying the summary. For Pi and DSH it means the host committed the summary to session history. The dashboard also shows summary duration and provider-reported cache usage.
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
+ ![AFU local dashboard overview (dark)](https://code.alipay.com/med_ai/afu_context_liwu/raw/master/docs/assets/dashboard-overview.en.jpg)
95
89
 
96
- **Overview** shows what AFU saved you: tokens saved and how many compactions took effect, followed by your sessions and the state of their latest compaction. Open a **session** to see the context drop after each compaction, how long each one took and what it saved, plus cache hit rates. Integrations, versions and issues live on the **Status** page. The dashboard supports light/dark themes and English/Chinese.
90
+ *Demo data.*
97
91
 
98
92
  ## Models and thresholds
99
93
 
100
- All four integrations reuse the conversation’s model and authentication. The default trigger is **40%** for windows of **1,000,000 tokens or more** and **50%** for smaller windows. Pi and DSH follow the host’s selected model and window. Claude Code reports the model window to its status line command; AFU wraps that command (your own status line keeps running unchanged) to learn the window. Codex windows come from its model catalog cache. If a window is still unknown, chat continues and status says so; `--context-window` sets it manually.
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
- <details>
103
- <summary>Set a window or ratio, or restore automatic settings</summary>
111
+ ### Set the window or ratio manually
104
112
 
105
- For a Codex model with a known 200,000-token window, the first command sets a 30% trigger. The second restores automatic settings.
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
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install codex --context-window 200000 --ratio 0.3
109
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install codex --context-window auto --ratio auto
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
- </details>
113
-
114
- For frequent use, run `npm install -g --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6` 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 @liwu1995/afu-context@0.1.6 upgrade codex
122
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 remove codex
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/@liwu1995/afu-context) · [一键安装](#install) · [评测效果](#results) · [Web 面板](#dashboard)
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 @liwu1995/afu-context@0.1.6 install claude` | `claude` |
24
- | Claude Code | Windows 10/11¹ | `npx.cmd --yes --registry=https://registry.npmjs.org "@liwu1995/afu-context@0.1.6" install claude` | `claude` |
25
- | <a id="afu-codex"></a>Codex CLI | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install codex` | `codex` |
26
- | <a id="afu-pi"></a>Pi | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install pi` | `pi` |
27
- | <a id="afu-dsh"></a>DSH | macOS / Linux | `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install dsh --profile YOUR_PROFILE` | `dsh --profile YOUR_PROFILE` |
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(ARM64)的 macOS 和 x64 Linux。首次执行 `afu` 会用本机 Python 3.11+ 创建专用运行环境,约半分钟。macOS 上 Claude Code 和 Codex 已用真实模型完成端到端验证(安装、对话压缩、升级、移除;终端安全软件拦截开机自启时改由会话 hook 拉起),Codex 覆盖带工具调用、贴图和 Codex 自身压缩过的长会话;Linux 上 Claude Code 用真实模型验证,Codex 用本地模拟服务验证,用户级 systemd 自启尚未验证。Claude Code 和 Codex 安装后新开会话。Pi 扩展在新开的会话自动加载。将 DSH 的 `YOUR_PROFILE` 换成要接入的 profile,例如 `headless` 或 `web`。选择 web 后也可以用 `dsh web` 启动。仅移除某个 profile 时运行 `npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 remove dsh --profile YOUR_PROFILE`。
31
+ 支持 macOS(Apple Silicon)和 x64 Linux;安装后新开会话即可。
30
32
 
31
- ¹ Windows 使用 PowerShell,需本机 Python **3.11+** 和支持 PowerShell Hook 的 Claude Code。Windows 原生 Claude Code 已实现,待实机验收。Codex 未支持,Pi 和 DSH 未验收。
33
+ ¹ Windows:Codex CLI、Pi、DSH 已实现,尚未在 Windows 实机验收。请在 PowerShell 中执行,命令里的 `npx.cmd` 和包名两侧的双引号都不能省。Claude Code 暂不支持 Windows。
32
34
 
33
- 安装命令固定使用公网 npm 上的 **0.1.6**,避免镜像尚未同步最新版本。请使用 0.1.6 或更新版本;更早的版本不含本版修复。如果报错含 `with a date before`,请核对 npm 的 `before` 或 `min-release-age`。此版本发布于 **PUBLISH_TIME_UTC**。若使用滚动冷却期,等该版本满足期限后重试;若设置了固定截止日期,需使用允许安装该版本的策略。
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.6 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:ui` |
80
- | Codex 会话里 | `$afu-ui` |
81
- | 终端里 | `afu` |
61
+ | Claude Code 会话里 | `/afu:ctx-admin` |
62
+ | Codex 会话里 | `$afu-ctx-admin` |
63
+ | 终端里 | `afu-ctx-admin` |
82
64
 
83
- 面板在后台运行,不占用终端;再次打开会复用同一个面板,30 分钟没有页面打开时自动退出。终端里的 `afu` 命令由安装程序放在 `~/.local/bin`(已在 `PATH` 中时才放,不修改 shell 配置),移除最后一个接入时一并删除。
65
+ - 面板在后台运行,不占用终端;再次打开会复用同一个面板,30 分钟没有页面打开时自动退出。
66
+ - 默认暗色主题,右上角可切换亮色、跟随系统和中英文。
67
+ - 终端命令由安装程序放在 `~/.local/bin`(已在 `PATH` 中时才放,不改 shell 配置,不覆盖你已有的同名命令),移除最后一个接入时一并删除。
84
68
 
85
- 查看当前会话的压缩情况:Claude Code 输入 `/afu:status`,Codex 输入 `$afu-status`,终端里运行 `afu status`。可以看到 AFU 是否已接入、当前上下文距离压缩触发线还有多少,以及已经生效的压缩次数。会话里的命令随安装添加、随移除删除。
69
+ ### 查看当前会话
86
70
 
87
- 没有 `afu` 命令时(例如 `~/.local/bin` 不在 `PATH` 中),可以用完整的 npx 命令。以 Codex 为例,其它宿主将 `codex` 换成 `claude`、`pi` 或 `dsh`:
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 @liwu1995/afu-context@0.1.6 status codex --brief
91
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 ui
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
- 面板分别记录**请求已接入 → 摘要已生成 → 摘要已应用**。Claude Code 和 Codex 的应用回执表示替换历史后的请求已收到完整成功响应。Pi 和 DSH 的回执表示宿主已把摘要写入会话历史。面板也展示摘要耗时和模型返回的缓存用量。
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
+ ![AFU 本地面板的总览页(暗色)](https://code.alipay.com/med_ai/afu_context_liwu/raw/master/docs/assets/dashboard-overview.jpg)
95
89
 
96
- **总览**先告诉你 AFU 帮你省了多少:节省的 token 和生效的压缩次数,下方列出每个会话及其最近一次压缩的状态。点进一个**会话**,可以看到上下文在每次压缩后回落、每次压缩的耗时和节省量,以及缓存命中率。接入情况、版本和异常记录在**运行状态**页查看。面板支持亮色/暗色主题和中英文。
90
+ *截图为演示数据。*
97
91
 
98
92
  ## 模型与压缩阈值
99
93
 
100
- 四个平台都复用主对话的模型和认证。模型窗口为 **1,000,000 tokens 或更大** 时,默认在 **40%** 触发,更小的窗口按 **50%** 触发。Pi 和 DSH 跟随宿主选择的模型和窗口。Claude Code 会把模型窗口传给它的状态栏命令,AFU 包装这条命令来获取窗口(你原来的状态栏照常运行、显示不变);Codex 的窗口来自它的模型目录缓存。仍未知时聊天照常进行,状态里会提示,也可以用 `--context-window` 手动指定。
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
- <details>
103
- <summary>手动指定窗口、调整比例或恢复自动设置</summary>
111
+ ### 手动指定窗口和调整比例
104
112
 
105
- 下面以已知窗口为 200,000 tokens 的 Codex 模型为例。第一条将触发比例设为 30%,第二条恢复自动设置。
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
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install codex --context-window 200000 --ratio 0.3
109
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 install codex --context-window auto --ratio auto
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
- </details>
113
-
114
- 如果经常使用 AFU,可运行 `npm install -g --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6`,以后用 `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 @liwu1995/afu-context@0.1.6 upgrade codex
122
- npx --yes --registry=https://registry.npmjs.org @liwu1995/afu-context@0.1.6 remove codex
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('AFU Context: install [claude|codex|pi|dsh], status, remove HOST, gc --dry-run, ui.\nRun npx @liwu1995/afu-context@latest install to detect your installed host. Host login remains managed by the host.');
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 child=spawn(args[0],split<0?[]:args.slice(split+1),{stdio:'inherit',env,shell:false});
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 = process.platform!=='win32' && hostAction && args[0]!=='status';
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;}