Skip to content

Commit b9d4aed

Browse files
committed
Release v0.2.0
1 parent 888aed9 commit b9d4aed

8 files changed

Lines changed: 85 additions & 27 deletions

File tree

GITHUB_RELEASE.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Codex Context Proxy v0.1.0
1+
# Codex Context Proxy v0.2.0
22

33
A visual, editable context layer for Codex. Let AI edit AI's context with surgical precision, giving you more control and freedom over what Codex sees.
44

@@ -8,6 +8,8 @@ A visual, editable context layer for Codex. Let AI edit AI's context with surgic
88
- Token overview for current context usage
99
- Manual context inspection and editing panel
1010
- AI-assisted context compression for noisy tool output
11+
- More reliable compact/override handling after Codex `/compact`
12+
- Safer whole-node compression for tool-heavy assistant turns
1113
- Codex CLI support through `codex ctx proxy on/off/status`
1214
- Experimental Codex Desktop support through `codex ctx desktop on/off/status`
1315
- Windows installer with bundled Electron app and Python backend
@@ -17,7 +19,7 @@ A visual, editable context layer for Codex. Let AI edit AI's context with surgic
1719
Download and run:
1820

1921
```text
20-
Codex Context Proxy Setup 0.1.0.exe
22+
Codex Context Proxy Setup 0.2.0.exe
2123
```
2224

2325
After installation, open a new terminal and enable the proxy:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ context window
9797
Download and run the Windows installer:
9898

9999
```text
100-
Codex Context Proxy Setup 0.1.0.exe
100+
Codex Context Proxy Setup 0.2.0.exe
101101
```
102102

103103
After installation, open a new terminal and enable the proxy:
@@ -187,7 +187,7 @@ npm run dist:win
187187
The installer is generated at:
188188

189189
```text
190-
release/Codex Context Proxy Setup 0.1.0.exe
190+
release/Codex Context Proxy Setup 0.2.0.exe
191191
```
192192

193193
## Notes

README.zh-CN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ context window
9797
下载并运行 Windows 安装包:
9898

9999
```text
100-
Codex Context Proxy Setup 0.1.0.exe
100+
Codex Context Proxy Setup 0.2.0.exe
101101
```
102102

103103
安装完成后,重新打开一个终端,然后启用代理:
@@ -187,7 +187,7 @@ npm run dist:win
187187
安装包会生成在:
188188

189189
```text
190-
release/Codex Context Proxy Setup 0.1.0.exe
190+
release/Codex Context Proxy Setup 0.2.0.exe
191191
```
192192

193193
## 说明

RELEASE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ npm run dist:win
1717
生成的安装包在:
1818

1919
```text
20-
release/Codex Context Proxy Setup 0.1.0.exe
20+
release/Codex Context Proxy Setup 0.2.0.exe
2121
```
2222

2323
安装包会带上 Electron 前端、React 构建产物、`web_server.py``proxy_server.py` 以及打包后的 Python exe。用户不需要自己安装 Node 或 Python。
2424

2525
## 用户怎么用
2626

27-
用户安装 `Codex Context Proxy Setup 0.1.0.exe` 后,安装器会自动安装 `codex ctx proxy ...` 控制命令,但不会默认打开代理。
27+
用户安装 `Codex Context Proxy Setup 0.2.0.exe` 后,安装器会自动安装 `codex ctx proxy ...` 控制命令,但不会默认打开代理。
2828

2929
安装完成后,重新打开一个终端,然后使用:
3030

@@ -103,7 +103,7 @@ codex ctx desktop status
103103
把下面这个文件上传到 GitHub Releases、网盘或下载页即可:
104104

105105
```text
106-
release/Codex Context Proxy Setup 0.1.0.exe
106+
release/Codex Context Proxy Setup 0.2.0.exe
107107
```
108108

109109
旧的 `hashcode Setup ...exe` 是历史产物,不要发布。

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hash-context-codex-lab",
3-
"version": "0.1.0",
3+
"version": "0.2.0",
44
"private": true,
55
"description": "Local context proxy and workbench companion for Codex.",
66
"author": "",

scripts/test_compact_proxy.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,54 @@ def test_context_workbench_compressed_nodes_stay_independent_after_cleaning() ->
15111511
assert "assistant follow-up" not in json.dumps(cleaned, ensure_ascii=False)
15121512

15131513

1514+
def test_context_workbench_compress_nodes_replaces_tool_heavy_node() -> None:
1515+
tool_output = "very long frontend scan output"
1516+
assistant_items = [
1517+
proxy_server.provider_message("assistant", "I will inspect the frontend."),
1518+
{
1519+
"type": "function_call",
1520+
"call_id": TOOL_CALL_ID,
1521+
"name": "shell_command",
1522+
"arguments": json.dumps({"command": "Get-ChildItem react_app -Force"}),
1523+
},
1524+
{
1525+
"type": "function_call_output",
1526+
"call_id": TOOL_CALL_ID,
1527+
"output": tool_output,
1528+
},
1529+
proxy_server.provider_message("assistant", "Frontend is React + Vite."),
1530+
]
1531+
transcript = [
1532+
proxy_server.transcript_record(
1533+
"user",
1534+
"inspect frontend",
1535+
[proxy_server.provider_message("user", "inspect frontend")],
1536+
),
1537+
proxy_server.transcript_record(
1538+
"assistant",
1539+
"I will inspect the frontend.\n\nFrontend is React + Vite.",
1540+
assistant_items,
1541+
),
1542+
]
1543+
draft = web_server.ContextWorkbenchDraft(web_server.normalize_transcript(transcript), [1])
1544+
nodes = draft._nodes_by_number([2])
1545+
1546+
draft.compress_nodes(
1547+
nodes,
1548+
summary_markdown="Frontend discussion compressed: React + Vite.",
1549+
style="tight summary",
1550+
title="",
1551+
)
1552+
committed = proxy_server.clean_transcript(draft.committed_transcript())
1553+
serialized = json.dumps(committed, ensure_ascii=False)
1554+
1555+
assert [record["role"] for record in committed] == ["user", "user"]
1556+
assert committed[1]["text"] == "Frontend discussion compressed: React + Vite."
1557+
assert "function_call" not in serialized
1558+
assert tool_output not in serialized
1559+
assert "I will inspect the frontend" not in serialized
1560+
1561+
15141562
def test_context_workbench_hides_internal_prefix_nodes_from_editing() -> None:
15151563
transcript = web_server.normalize_transcript(
15161564
[
@@ -1598,6 +1646,7 @@ def main() -> None:
15981646
test_compaction_visible_text_falls_back_to_encrypted_content()
15991647
test_local_compact_response_replaces_transcript_with_readable_summary()
16001648
test_context_workbench_compressed_nodes_stay_independent_after_cleaning()
1649+
test_context_workbench_compress_nodes_replaces_tool_heavy_node()
16011650
test_context_workbench_hides_internal_prefix_nodes_from_editing()
16021651

16031652
with tempfile.TemporaryDirectory() as temp_dir:

web_server.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4774,12 +4774,12 @@ def __init__(self, draft: ContextWorkbenchDraft) -> None:
47744774
self._build_preview_selection_tool(),
47754775
self._build_node_detail_tool(),
47764776
self._build_find_items_tool(),
4777+
self._build_compress_nodes_tool(),
4778+
self._build_delete_nodes_tool(),
47774779
self._build_edit_items_tool(),
47784780
self._build_delete_item_tool(),
47794781
self._build_replace_item_tool(),
47804782
self._build_compress_item_tool(),
4781-
self._build_compress_nodes_tool(),
4782-
self._build_delete_nodes_tool(),
47834783
self._build_set_revision_summary_tool(),
47844784
]
47854785
}
@@ -4809,6 +4809,18 @@ def tool_catalog(cls) -> list[dict[str, str]]:
48094809
"description": "Search provider items using lightweight metadata and previews, without returning full node content.",
48104810
"status": "available",
48114811
},
4812+
{
4813+
"id": "compress_context_nodes",
4814+
"label": "Compress Nodes",
4815+
"description": "Whole-node compression: replace nodes, discussions, topics, or assistant turns with summary nodes, removing text, reasoning, tool calls, and tool outputs.",
4816+
"status": "available",
4817+
},
4818+
{
4819+
"id": "delete_context_nodes",
4820+
"label": "Delete Nodes",
4821+
"description": "Delete one or more nodes from the current working snapshot.",
4822+
"status": "available",
4823+
},
48124824
{
48134825
"id": "edit_context_items",
48144826
"label": "Edit Items",
@@ -4833,18 +4845,6 @@ def tool_catalog(cls) -> list[dict[str, str]]:
48334845
"description": "Replace one item with a shorter version while keeping the same item type.",
48344846
"status": "available",
48354847
},
4836-
{
4837-
"id": "compress_context_nodes",
4838-
"label": "Compress Nodes",
4839-
"description": "Replace one or more nodes with a new summary node inside the current working snapshot.",
4840-
"status": "available",
4841-
},
4842-
{
4843-
"id": "delete_context_nodes",
4844-
"label": "Delete Nodes",
4845-
"description": "Delete one or more nodes from the current working snapshot.",
4846-
"status": "available",
4847-
},
48484848
]
48494849

48504850
def execute(self, name: str, arguments: dict[str, Any]) -> ToolExecution:
@@ -5609,7 +5609,11 @@ def handler(arguments: dict[str, Any]) -> ToolExecution:
56095609
return ContextWorkbenchToolDefinition(
56105610
name="compress_context_nodes",
56115611
label="Compress Nodes",
5612-
description="Replace one or more nodes with a new summary node inside the current working snapshot.",
5612+
description=(
5613+
"Whole-node compression. Replace one or more nodes with a new summary node inside the current working snapshot. "
5614+
"Use this when the user asks to compress a node, discussion, topic, or assistant turn; it removes the target nodes' "
5615+
"assistant text, reasoning, tool calls, and tool outputs from the snapshot."
5616+
),
56135617
parameters={
56145618
"type": "object",
56155619
"properties": {
@@ -5894,7 +5898,10 @@ def build_context_chat_runtime(
58945898
"user 节点直接给全文;assistant 节点默认只给上下文地图折叠态同款首句预览,预览后面的内容你并不可见;需要协议层细节或完整内容时,再调用 get_context_node_details。",
58955899
"Node Detail 里会给出 item #1 / item #2 / item #3 这样的当轮可编辑 item 视图。",
58965900
"如果你要定位某类 item(例如所有 tool output、某类 tool call、某个文本片段),优先调用 find_context_items;它只返回预览和元数据,不会把大段内容塞进你的上下文。",
5901+
"用户说压缩某个节点、某段讨论、某个主题或某轮 assistant 内容时,默认是节点级压缩:优先调用 compress_context_nodes,用一个摘要节点替换整个目标节点,包含其中的 assistant 文本、reasoning、工具调用和工具输出。",
5902+
"不要把节点级压缩误做成只压缩 message item;如果目标节点里有工具输出,压缩整个节点通常就是为了移除这些大块工具输出。",
58975903
"如果你要批量删除、改写、压缩 assistant text / tool call / tool output,优先调用 edit_context_items,用 selector 一次选中目标,再用 operation 一次完成;不要逐个 item 反复调用单项工具。",
5904+
"edit_context_items 只用于 item 级编辑:例如用户明确要求只压缩所有 tool output、只删除工具调用、或保留节点结构但缩短某类 item。",
58985905
"edit_context_items 的 replace_content / compress_content 会保留原 item 的 type 和 call_id,只改可编辑内容;delete 会原子删除工具调用/输出配对,保证 Codex 输入仍然合法。",
58995906
"delete_context_item / replace_context_item / compress_context_item 只用于少数精细单点修改,或者当用户明确要求按完整 provider item 改写时使用。",
59005907
"选中只是强提示,不是门槛。显式 node_numbers 优先,其次是当前选中;如果都没有,可以用 target_hint 让系统帮你定位候选节点。",

0 commit comments

Comments
 (0)