mirror of
https://github.com/andrewyng/openworker.git
synced 2026-11-04 05:17:09 +00:00
Findings from a long multi-task Kimi K3 session: ten long tasks used 57% of 451 M tokens, tool results were 31% of the final context and whole-file write_file bodies 14%, and compaction fired once. Three harness changes: 1. Tool-result cap. Every tool result is bounded on arrival at 10,000 bytes, head + tail, with a marker naming the spill file that holds the full text (coworker/toolresult.py; engine `_record_result`; config `tool_result_max_bytes`, env COWORKER_TOOL_RESULT_MAX_BYTES, 0 = off). The spill folder is the session's scratch root when there is one, else it joins the session's directories read-only so read_file can open it. shell.py's own 20k-char tail cut becomes a 2M safety net. 2. Edit steering. write_file, replace_in_file, apply_patch and apply_unified_diff describe WHEN to use each (catalog.EDIT_TOOL_GUIDANCE), and the Cowork prompt says to edit in place rather than rewrite. 3. Compaction. `compaction_cap_tokens` (config / env COWORKER_COMPACTION_CAP_TOKENS) lowers the trigger; each compaction writes the verbatim transcript of the compacted turns (no reasoning) to the spill folder and the compacted block names the file (CompactionState.transcript_path, compaction.render_transcript). Trial on 15 long tasks x 3 attempts (Kimi K3 via Together, cap 60,000): 33/45 passed vs 54/75 for the unchanged harness on the same tasks, tokens per attempt 3.30 M -> 1.40 M, cost down 44%. Observed and left for a follow-up: Kimi's summariser reply lands mostly in reasoning within the 3,000-token summary budget (7 proper summaries in 103 calls), and the trial had 16 timeouts vs 9 in the baseline. Tests: tests/test_tool_result_cap.py, tests/test_edit_tool_guidance.py, tests/test_compaction_transcript.py; full suite unchanged against the Windows baseline.
43 lines
1.8 KiB
Python
43 lines
1.8 KiB
Python
"""OPE-186 change 2: the file tools tell the model WHEN to use each (rewrite vs edit in
|
|
place), and the Cowork prompt says the same. The schema the model sees is built from the
|
|
tool's docstring by the registry, so that is what is checked here."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from coworker.agents import AgentContext
|
|
from coworker.agents.cowork import COWORK_INSTRUCTIONS
|
|
from coworker.catalog import EDIT_TOOL_GUIDANCE, expand
|
|
from coworker.tools import ToolRegistry
|
|
|
|
|
|
def _descriptions(capability: str, tmp_path) -> dict[str, str]:
|
|
context = AgentContext(workspace=str(tmp_path), executor=None, todo=None, roots=None)
|
|
registry = ToolRegistry()
|
|
registry.register_all(expand([capability], context))
|
|
return {
|
|
name: registry.get(name).schema["function"]["description"] # type: ignore[union-attr]
|
|
for name in registry.names()
|
|
}
|
|
|
|
|
|
def test_files_capability_describes_when_to_rewrite_and_when_to_edit(tmp_path):
|
|
d = _descriptions("files", tmp_path)
|
|
assert "NEW file" in d["write_file"] and "replace_in_file" in d["write_file"]
|
|
assert "in place" in d["replace_in_file"] and "Prefer this over write_file" in d["replace_in_file"]
|
|
assert "*** Begin Patch" in d["apply_patch"]
|
|
assert "unified diff" in d["apply_unified_diff"]
|
|
# The generic aisuite one-liner is gone from every edit tool.
|
|
for name in EDIT_TOOL_GUIDANCE:
|
|
assert d[name] != "Write a UTF-8 text file under the configured root."
|
|
|
|
|
|
def test_code_files_capability_gets_the_same_guidance(tmp_path):
|
|
d = _descriptions("code_files", tmp_path)
|
|
for name, text in EDIT_TOOL_GUIDANCE.items():
|
|
assert d[name] == text
|
|
|
|
|
|
def test_cowork_prompt_steers_edits_to_in_place_tools():
|
|
assert "edit it in place with replace_in_file or apply_patch" in COWORK_INSTRUCTIONS
|
|
assert "reserve write_file for new files or full rewrites" in COWORK_INSTRUCTIONS
|