fix(s08): support recursive glob and conditional micro compact
@@ -117,7 +117,7 @@ messages = [*messages[:head_end], marker, *messages[tail_start:]]
|
|||||||
|
|
||||||
## ステップ 3:micro_compact
|
## ステップ 3:micro_compact
|
||||||
|
|
||||||
`micro_compact` は直近の assistant 応答より後に追加されたすべての `tool_result` を完全に保持し、モデルが各結果を少なくとも 1 回は完全な形で読めるようにします。モデルがすでに読んだ結果については最新 3 件を残し、それより古く 120 文字を超える結果を短くします。保存済みの結果にはファイルパスを残し、それ以外はプレースホルダーに置き換えます。
|
最初の 2 ステップの後、`prepare` は残りのコンテキストサイズを推定し、`CONTEXT_CHAR_LIMIT` を超えている場合にだけ `micro_compact` を実行します。`micro_compact` は直近の assistant 応答より後に追加されたすべての `tool_result` を完全に保持し、モデルが各結果を少なくとも 1 回は完全な形で読めるようにします。モデルがすでに読んだ結果については最新 3 件を残し、それより古く 120 文字を超える結果を短くします。保存済みの結果にはファイルパスを残し、それ以外はプレースホルダーに置き換えます。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -142,12 +142,12 @@ for _, _, block in consumed[:-self.KEEP_RECENT_RESULTS]:
|
|||||||
|
|
||||||
保存していない古い結果にはプレースホルダーだけが残ります。ステップ 1 で保存した結果には、完全な出力を読み直すためのパスが残ります。
|
保存していない古い結果にはプレースホルダーだけが残ります。ステップ 1 で保存した結果には、完全な出力を読み直すためのパスが残ります。
|
||||||
|
|
||||||
最初の 3 ステップは、決定的なテキスト処理と構造操作です。追加の API 呼び出しは発生しません。
|
最初の 2 ステップは毎ラウンド実行され、ステップ 3 はコンテキストが上限を超えた場合にだけ実行されます。3 ステップとも決定的なテキスト処理と構造操作であり、追加の API 呼び出しは発生しません。
|
||||||
|
|
||||||
|
|
||||||
## ステップ 4:compact_history
|
## ステップ 4:compact_history
|
||||||
|
|
||||||
最初の 3 ステップの後、コードは `estimate_chars(messages)` で現在のメッセージに含まれる文字数を数えます。
|
`micro_compact` の後、コードは `estimate_chars(messages)` でコンテキストを再び推定します。
|
||||||
|
|
||||||
```python
|
```python
|
||||||
CONTEXT_CHAR_LIMIT = 50000
|
CONTEXT_CHAR_LIMIT = 50000
|
||||||
@@ -156,7 +156,7 @@ def estimate_chars(messages):
|
|||||||
return len(json.dumps(messages, default=str, ensure_ascii=False))
|
return len(json.dumps(messages, default=str, ensure_ascii=False))
|
||||||
```
|
```
|
||||||
|
|
||||||
文字数が `CONTEXT_CHAR_LIMIT` を超えると、`compact_history` は 4 つの処理を行います。
|
文字数がまだ `CONTEXT_CHAR_LIMIT` を超えている場合、`compact_history` は 4 つの処理を行います。
|
||||||
|
|
||||||
1. 完全なメッセージ履歴を `.transcripts/` に書き込みます。
|
1. 完全なメッセージ履歴を `.transcripts/` に書き込みます。
|
||||||
2. モデルに事実だけの状態要約を依頼します。
|
2. モデルに事実だけの状態要約を依頼します。
|
||||||
@@ -181,18 +181,20 @@ def compact_history(messages, active_request):
|
|||||||
|
|
||||||
## 順序を固定する理由
|
## 順序を固定する理由
|
||||||
|
|
||||||
パイプラインは常に次の順序で実行されます。
|
パイプラインは次の順序で処理し、必要な場合にだけ情報を失う圧縮へ進みます。
|
||||||
|
|
||||||
```text
|
```python
|
||||||
tool_result_budget
|
messages = self.tool_result_budget(messages)
|
||||||
→ snip_compact
|
messages = self.snip_compact(messages)
|
||||||
→ micro_compact
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
→ compact_history(上限を超えた場合)
|
messages = self.micro_compact(messages)
|
||||||
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
|
messages = self.compact_history(messages, active_request)
|
||||||
```
|
```
|
||||||
|
|
||||||
この順序には 2 つの条件があります。
|
この順序には 2 つの条件があります。
|
||||||
|
|
||||||
1. 最初の 3 ステップはモデルを呼び出しません。ステップ 4 だけが API リクエストを追加します。
|
1. ステップ 1 と 2 は毎ラウンド実行され、ステップ 3 は上限を超えた場合だけ実行されます。API リクエストを追加するのはステップ 4 だけです。
|
||||||
2. `tool_result_budget` は `micro_compact` より先に動く必要があります。古い結果をプレースホルダーにする前に、大きな結果をディスクへ保存します。
|
2. `tool_result_budget` は `micro_compact` より先に動く必要があります。古い結果をプレースホルダーにする前に、大きな結果をディスクへ保存します。
|
||||||
|
|
||||||
各ラウンドは、コストが低く情報を再取得しやすい処理から始まります。
|
各ラウンドは、コストが低く情報を再取得しやすい処理から始まります。
|
||||||
@@ -243,7 +245,7 @@ def agent_loop(messages, active_request):
|
|||||||
raise
|
raise
|
||||||
```
|
```
|
||||||
|
|
||||||
すべてのモデル呼び出しが同じパイプラインを通ります。CLI は `query` を追加した後に `agent_loop(history, query)` を呼ぶため、圧縮を繰り返しても現在の要求は失われません。最初の 3 ステップ後も上限を超える場合、または API が拒否した場合にだけ、コードはモデルへ要約を依頼します。
|
すべてのモデル呼び出しが同じパイプラインを通ります。CLI は `query` を追加した後に `agent_loop(history, query)` を呼ぶため、圧縮を繰り返しても現在の要求は失われません。`micro_compact` の後も上限を超える場合、または API が拒否した場合にだけ、コードはモデルへ要約を依頼します。
|
||||||
|
|
||||||
|
|
||||||
## compact ツール
|
## compact ツール
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ This step controls the number of messages. Tool results inside the retained mess
|
|||||||
|
|
||||||
## Step 3: micro_compact
|
## Step 3: micro_compact
|
||||||
|
|
||||||
`micro_compact` preserves every `tool_result` added after the most recent assistant response, so the model sees each new result in full once. Among results the model has already consumed, it keeps the latest 3 and shortens older results longer than 120 characters. Persisted results keep their file path; the rest become placeholders:
|
After the first two steps, `prepare` estimates the remaining context size and runs `micro_compact` only when it is above `CONTEXT_CHAR_LIMIT`. `micro_compact` preserves every `tool_result` added after the most recent assistant response, so the model sees each new result in full once. Among results the model has already consumed, it keeps the latest 3 and shortens older results longer than 120 characters. Persisted results keep their file path; the rest become placeholders:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -142,12 +142,12 @@ for _, _, block in consumed[:-self.KEEP_RECENT_RESULTS]:
|
|||||||
|
|
||||||
An old result that was not persisted keeps only a placeholder. Results saved in Step 1 retain the path to their complete output.
|
An old result that was not persisted keeps only a placeholder. Results saved in Step 1 retain the path to their complete output.
|
||||||
|
|
||||||
The first three steps are deterministic text and structure operations. They do not add API calls.
|
The first two steps run every round. Step 3 runs only when the context is above the limit. All three are deterministic text and structure operations; they do not add API calls.
|
||||||
|
|
||||||
|
|
||||||
## Step 4: compact_history
|
## Step 4: compact_history
|
||||||
|
|
||||||
After the first three steps, the code counts the characters in the current messages with `estimate_chars(messages)`:
|
After `micro_compact`, the code estimates the context again with `estimate_chars(messages)`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
CONTEXT_CHAR_LIMIT = 50000
|
CONTEXT_CHAR_LIMIT = 50000
|
||||||
@@ -156,7 +156,7 @@ def estimate_chars(messages):
|
|||||||
return len(json.dumps(messages, default=str, ensure_ascii=False))
|
return len(json.dumps(messages, default=str, ensure_ascii=False))
|
||||||
```
|
```
|
||||||
|
|
||||||
When the count exceeds `CONTEXT_CHAR_LIMIT`, `compact_history` does four things:
|
When the count still exceeds `CONTEXT_CHAR_LIMIT`, `compact_history` does four things:
|
||||||
|
|
||||||
1. Writes the complete message history to `.transcripts/`.
|
1. Writes the complete message history to `.transcripts/`.
|
||||||
2. Asks the model for a factual state summary.
|
2. Asks the model for a factual state summary.
|
||||||
@@ -181,18 +181,20 @@ This lesson uses character count as its trigger, and all related thresholds use
|
|||||||
|
|
||||||
## Why the Order Is Fixed
|
## Why the Order Is Fixed
|
||||||
|
|
||||||
The pipeline always runs in this order:
|
The pipeline uses this order and only enters the lossy steps when necessary:
|
||||||
|
|
||||||
```text
|
```python
|
||||||
tool_result_budget
|
messages = self.tool_result_budget(messages)
|
||||||
→ snip_compact
|
messages = self.snip_compact(messages)
|
||||||
→ micro_compact
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
→ compact_history (only above the limit)
|
messages = self.micro_compact(messages)
|
||||||
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
|
messages = self.compact_history(messages, active_request)
|
||||||
```
|
```
|
||||||
|
|
||||||
This order satisfies two constraints:
|
This order satisfies two constraints:
|
||||||
|
|
||||||
1. The first three steps do not call the model. Only Step 4 adds an API request.
|
1. Steps 1 and 2 run every round. Step 3 runs only above the limit, and only Step 4 adds an API request.
|
||||||
2. `tool_result_budget` must run before `micro_compact`. Large results need to reach disk before older results can become placeholders.
|
2. `tool_result_budget` must run before `micro_compact`. Large results need to reach disk before older results can become placeholders.
|
||||||
|
|
||||||
Each round therefore starts with the lowest-cost operation whose information is easiest to recover.
|
Each round therefore starts with the lowest-cost operation whose information is easiest to recover.
|
||||||
@@ -243,7 +245,7 @@ def agent_loop(messages, active_request):
|
|||||||
raise
|
raise
|
||||||
```
|
```
|
||||||
|
|
||||||
Every model call enters through the same pipeline. After appending `query`, the CLI calls `agent_loop(history, query)`, so repeated compaction cannot lose the current request. The code asks for a summary only when the first three steps leave the context above the limit or when the API rejects it.
|
Every model call enters through the same pipeline. After appending `query`, the CLI calls `agent_loop(history, query)`, so repeated compaction cannot lose the current request. The code asks for a summary only when `micro_compact` still leaves the context above the limit or when the API rejects it.
|
||||||
|
|
||||||
|
|
||||||
## The compact Tool
|
## The compact Tool
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ messages = [*messages[:head_end], marker, *messages[tail_start:]]
|
|||||||
|
|
||||||
## 第三步:micro_compact
|
## 第三步:micro_compact
|
||||||
|
|
||||||
`micro_compact` 会完整保留最近一次 assistant 响应之后新增的所有 `tool_result`,确保模型至少完整读取每条新结果一次。对于模型已经读取过的结果,它保留最近 3 条,并缩短其余超过 120 个字符的旧结果。已经转存的结果保留文件路径,其他结果只留下占位符:
|
前两步完成后,`prepare` 会估算剩余上下文的大小,只有超过 `CONTEXT_CHAR_LIMIT` 时才执行 `micro_compact`。`micro_compact` 会完整保留最近一次 assistant 响应之后新增的所有 `tool_result`,确保模型至少完整读取每条新结果一次。对于模型已经读取过的结果,它保留最近 3 条,并缩短其余超过 120 个字符的旧结果。已经转存的结果保留文件路径,其他结果只留下占位符:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -142,12 +142,12 @@ for _, _, block in consumed[:-self.KEEP_RECENT_RESULTS]:
|
|||||||
|
|
||||||
未转存的旧结果只保留占位符。第一步保存过的完整结果仍能通过路径读取,不会在第三步丢失位置。
|
未转存的旧结果只保留占位符。第一步保存过的完整结果仍能通过路径读取,不会在第三步丢失位置。
|
||||||
|
|
||||||
前三步都是确定性的结构和文本操作,不产生额外 API 调用。
|
前两步每轮都会执行,第三步只在上下文超限时执行。三步都是确定性的结构和文本操作,不产生额外 API 调用。
|
||||||
|
|
||||||
|
|
||||||
## 第四步:compact_history
|
## 第四步:compact_history
|
||||||
|
|
||||||
前三步执行后,代码用 `estimate_chars(messages)` 计算当前消息的字符数:
|
`micro_compact` 执行后,代码会再次用 `estimate_chars(messages)` 估算上下文:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
CONTEXT_CHAR_LIMIT = 50000
|
CONTEXT_CHAR_LIMIT = 50000
|
||||||
@@ -156,7 +156,7 @@ def estimate_chars(messages):
|
|||||||
return len(json.dumps(messages, default=str, ensure_ascii=False))
|
return len(json.dumps(messages, default=str, ensure_ascii=False))
|
||||||
```
|
```
|
||||||
|
|
||||||
字符数超过 `CONTEXT_CHAR_LIMIT` 时,`compact_history` 完成四件事:
|
字符数仍然超过 `CONTEXT_CHAR_LIMIT` 时,`compact_history` 完成四件事:
|
||||||
|
|
||||||
1. 将完整消息历史写入 `.transcripts/`。
|
1. 将完整消息历史写入 `.transcripts/`。
|
||||||
2. 请求模型生成只包含事实的状态摘要。
|
2. 请求模型生成只包含事实的状态摘要。
|
||||||
@@ -181,18 +181,20 @@ def compact_history(messages, active_request):
|
|||||||
|
|
||||||
## 为什么顺序固定
|
## 为什么顺序固定
|
||||||
|
|
||||||
四步管线的执行顺序是:
|
管线按以下顺序执行,并且只在必要时进入有损压缩步骤:
|
||||||
|
|
||||||
```text
|
```python
|
||||||
tool_result_budget
|
messages = self.tool_result_budget(messages)
|
||||||
→ snip_compact
|
messages = self.snip_compact(messages)
|
||||||
→ micro_compact
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
→ compact_history(超过阈值时)
|
messages = self.micro_compact(messages)
|
||||||
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
|
messages = self.compact_history(messages, active_request)
|
||||||
```
|
```
|
||||||
|
|
||||||
这个顺序同时满足两个条件:
|
这个顺序同时满足两个条件:
|
||||||
|
|
||||||
1. 前三步不调用模型,第四步才产生额外 API 请求。
|
1. 第一步和第二步每轮执行,第三步只在超限时执行,只有第四步会增加 API 请求。
|
||||||
2. `tool_result_budget` 必须早于 `micro_compact`。大结果先落盘,之后才允许旧结果变成占位符。
|
2. `tool_result_budget` 必须早于 `micro_compact`。大结果先落盘,之后才允许旧结果变成占位符。
|
||||||
|
|
||||||
顺序固定后,每一轮都从成本更低、信息更容易恢复的操作开始。
|
顺序固定后,每一轮都从成本更低、信息更容易恢复的操作开始。
|
||||||
@@ -243,7 +245,7 @@ def agent_loop(messages, active_request):
|
|||||||
raise
|
raise
|
||||||
```
|
```
|
||||||
|
|
||||||
每次调用模型前都会经过同一条管线。CLI 在追加 `query` 后调用 `agent_loop(history, query)`,所以压缩多少次都不会丢失本轮请求。前三步处理后仍超过阈值,或者 API 明确拒绝上下文时,代码才会请求模型生成摘要。
|
每次调用模型前都会经过同一条管线。CLI 在追加 `query` 后调用 `agent_loop(history, query)`,所以压缩多少次都不会丢失本轮请求。只有 `micro_compact` 处理后仍超过阈值,或者 API 明确拒绝上下文时,代码才会请求模型生成摘要。
|
||||||
|
|
||||||
|
|
||||||
## compact 工具
|
## compact 工具
|
||||||
|
|||||||
@@ -11,18 +11,21 @@ s08_context_compact.py - Context Compact
|
|||||||
v
|
v
|
||||||
+--------------------+
|
+--------------------+
|
||||||
| snip_compact | archive the old middle -> .transcripts/
|
| snip_compact | archive the old middle -> .transcripts/
|
||||||
+--------------------+
|
|
||||||
|
|
|
||||||
v
|
|
||||||
+--------------------+
|
|
||||||
| micro_compact | shorten old tool results
|
|
||||||
+--------------------+
|
+--------------------+
|
||||||
|
|
|
|
||||||
v
|
v
|
||||||
context over limit?
|
context over limit?
|
||||||
| no | yes
|
| no | yes
|
||||||
v v
|
| v
|
||||||
model call compact_history -> model call
|
| +--------------------+
|
||||||
|
| | micro_compact | shorten old tool results
|
||||||
|
| +--------------------+
|
||||||
|
| |
|
||||||
|
| v
|
||||||
|
| still over limit?
|
||||||
|
| | no | yes
|
||||||
|
v v v
|
||||||
|
model call compact_history -> model call
|
||||||
|
|
||||||
Other entry points:
|
Other entry points:
|
||||||
|
|
||||||
@@ -116,7 +119,7 @@ def run_edit(path: str, old_text: str, new_text: str) -> str:
|
|||||||
def run_glob(pattern: str) -> str:
|
def run_glob(pattern: str) -> str:
|
||||||
try:
|
try:
|
||||||
matches = [
|
matches = [
|
||||||
match for match in glob.glob(pattern, root_dir=WORKDIR)
|
match for match in glob.glob(pattern, root_dir=WORKDIR, recursive=True)
|
||||||
if (WORKDIR / match).resolve().is_relative_to(WORKDIR)
|
if (WORKDIR / match).resolve().is_relative_to(WORKDIR)
|
||||||
]
|
]
|
||||||
return "\n".join(matches) if matches else "(no matches)"
|
return "\n".join(matches) if matches else "(no matches)"
|
||||||
@@ -419,10 +422,11 @@ class ContextCompactor:
|
|||||||
def prepare(self, messages: list, active_request: str) -> list:
|
def prepare(self, messages: list, active_request: str) -> list:
|
||||||
messages = self.tool_result_budget(messages)
|
messages = self.tool_result_budget(messages)
|
||||||
messages = self.snip_compact(messages)
|
messages = self.snip_compact(messages)
|
||||||
messages = self.micro_compact(messages)
|
|
||||||
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
print("[auto compact]")
|
messages = self.micro_compact(messages)
|
||||||
messages = self.compact_history(messages, active_request)
|
if self.estimate_chars(messages) > self.CONTEXT_CHAR_LIMIT:
|
||||||
|
print("[auto compact]")
|
||||||
|
messages = self.compact_history(messages, active_request)
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<!-- Trigger Condition -->
|
<!-- Trigger Condition -->
|
||||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">Trigger Condition</text>
|
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">Trigger Condition</text>
|
||||||
<text x="140" y="70" fill="#991b1b" font-size="11">After Steps 1–3, estimate_chars(messages) > CONTEXT_CHAR_LIMIT.</text>
|
<text x="140" y="70" fill="#991b1b" font-size="11">After micro_compact, estimate_chars(messages) > CONTEXT_CHAR_LIMIT.</text>
|
||||||
<text x="140" y="86" fill="#991b1b" font-size="10">The current CONTEXT_CHAR_LIMIT is 50,000 characters.</text>
|
<text x="140" y="86" fill="#991b1b" font-size="10">The current CONTEXT_CHAR_LIMIT is 50,000 characters.</text>
|
||||||
|
|
||||||
<!-- Steps -->
|
<!-- Steps -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
@@ -16,7 +16,7 @@
|
|||||||
<!-- トリガー条件 -->
|
<!-- トリガー条件 -->
|
||||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">トリガー条件</text>
|
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">トリガー条件</text>
|
||||||
<text x="115" y="70" fill="#991b1b" font-size="11">Step 1~3 の後、estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
<text x="115" y="70" fill="#991b1b" font-size="11">micro_compact の後、estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
||||||
<text x="115" y="86" fill="#991b1b" font-size="10">現在の CONTEXT_CHAR_LIMIT は 50,000 文字。</text>
|
<text x="115" y="86" fill="#991b1b" font-size="10">現在の CONTEXT_CHAR_LIMIT は 50,000 文字。</text>
|
||||||
|
|
||||||
<!-- ステップ -->
|
<!-- ステップ -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.8 KiB |
@@ -16,7 +16,7 @@
|
|||||||
<!-- 触发条件 -->
|
<!-- 触发条件 -->
|
||||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">触发条件</text>
|
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">触发条件</text>
|
||||||
<text x="105" y="70" fill="#991b1b" font-size="11">前三步执行后,estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
<text x="105" y="70" fill="#991b1b" font-size="11">micro_compact 后,estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
||||||
<text x="105" y="86" fill="#991b1b" font-size="10">当前实现的 CONTEXT_CHAR_LIMIT 为 50,000 个字符。</text>
|
<text x="105" y="86" fill="#991b1b" font-size="10">当前实现的 CONTEXT_CHAR_LIMIT 为 50,000 个字符。</text>
|
||||||
|
|
||||||
<!-- 步骤 -->
|
<!-- 步骤 -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -45,9 +45,9 @@
|
|||||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Compression Pipeline</text>
|
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Compression Pipeline</text>
|
||||||
|
|
||||||
<!-- ── ① Every Turn Auto ── -->
|
<!-- ── ① Pre-processing ── -->
|
||||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Every Turn · Unconditional · 0 API</text>
|
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Steps 1–2 Every Turn · 0 API</text>
|
||||||
|
|
||||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
||||||
|
|
||||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact</text>
|
<text x="270" y="202" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">Step 3 micro_compact (over limit)</text>
|
||||||
|
|
||||||
<!-- ↓ → ◇ -->
|
<!-- ↓ → ◇ -->
|
||||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
<!-- ◇ Decision Diamond -->
|
<!-- ◇ Decision Diamond -->
|
||||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">Over threshold?</text>
|
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">Still over?</text>
|
||||||
|
|
||||||
<!-- No: right annotation -->
|
<!-- No: right annotation -->
|
||||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → Pass</text>
|
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → Pass</text>
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
<text x="94" y="414" fill="#334155" font-size="10">Shared: loop, hooks, permissions, five base tools</text>
|
<text x="94" y="414" fill="#334155" font-size="10">Shared: loop, hooks, permissions, five base tools</text>
|
||||||
|
|
||||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="94" y="436" fill="#334155" font-size="10">① Every Turn: Steps 1→2→3 run before each LLM call, 0 API</text>
|
<text x="94" y="436" fill="#334155" font-size="10">① Pre-process: Steps 1→2 every turn; Step 3 only over the limit, 0 API</text>
|
||||||
|
|
||||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||||
<text x="94" y="458" fill="#334155" font-size="10">② Conditional: size remains over the limit after Step 3 → compact_history, 1 API</text>
|
<text x="94" y="458" fill="#334155" font-size="10">② Conditional: still over the limit after Step 3 → compact_history, 1 API</text>
|
||||||
|
|
||||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||||
<text x="94" y="480" fill="#334155" font-size="10">③ Recovery: API returns prompt_too_long → reactive_compact → retry once</text>
|
<text x="94" y="480" fill="#334155" font-size="10">③ Recovery: API returns prompt_too_long → reactive_compact → retry once</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
@@ -45,9 +45,9 @@
|
|||||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">圧縮パイプライン</text>
|
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">圧縮パイプライン</text>
|
||||||
|
|
||||||
<!-- ── ① 毎ターン自動 ── -->
|
<!-- ── ① 前処理 ── -->
|
||||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① 毎ターン自動 · 無条件 · 0 API</text>
|
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Step 1–2 は毎ターン · 0 API</text>
|
||||||
|
|
||||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
||||||
|
|
||||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact</text>
|
<text x="270" y="202" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">Step 3 micro_compact(上限超過時)</text>
|
||||||
|
|
||||||
<!-- ↓ → ◇ -->
|
<!-- ↓ → ◇ -->
|
||||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
<!-- ◇ 判定ダイヤモンド -->
|
<!-- ◇ 判定ダイヤモンド -->
|
||||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">推定値超過?</text>
|
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">まだ超過?</text>
|
||||||
|
|
||||||
<!-- いいえ:右側注釈 -->
|
<!-- いいえ:右側注釈 -->
|
||||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → 通過</text>
|
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → 通過</text>
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
<text x="94" y="414" fill="#334155" font-size="10">共通:ループ、フック、権限確認、5 個の基本ツール</text>
|
<text x="94" y="414" fill="#334155" font-size="10">共通:ループ、フック、権限確認、5 個の基本ツール</text>
|
||||||
|
|
||||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="94" y="436" fill="#334155" font-size="10">① 毎ターン:Step 1→2→3 を各 LLM 呼び出し前に実行、0 API</text>
|
<text x="94" y="436" fill="#334155" font-size="10">① 前処理:Step 1→2 は毎ターン、Step 3 は上限超過時のみ、0 API</text>
|
||||||
|
|
||||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||||
<text x="94" y="458" fill="#334155" font-size="10">② 条件:Step 3 後もサイズ上限超過 → compact_history、1 API</text>
|
<text x="94" y="458" fill="#334155" font-size="10">② 条件:Step 3 後も上限超過 → compact_history、1 API</text>
|
||||||
|
|
||||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||||
<text x="94" y="480" fill="#334155" font-size="10">③ 回復:API が prompt_too_long を返す → reactive_compact → 1 回リトライ</text>
|
<text x="94" y="480" fill="#334155" font-size="10">③ 回復:API が prompt_too_long を返す → reactive_compact → 1 回リトライ</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -45,9 +45,9 @@
|
|||||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">压缩管线</text>
|
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">压缩管线</text>
|
||||||
|
|
||||||
<!-- ── ① 每轮自动 ── -->
|
<!-- ── ① 预处理 ── -->
|
||||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① 每轮自动 · 无条件 · 0 API</text>
|
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Step 1–2 每轮 · 0 API</text>
|
||||||
|
|
||||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
||||||
|
|
||||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact</text>
|
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact(超限时)</text>
|
||||||
|
|
||||||
<!-- ↓ → ◇ -->
|
<!-- ↓ → ◇ -->
|
||||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
<!-- ◇ 判断菱形(紧凑) -->
|
<!-- ◇ 判断菱形(紧凑) -->
|
||||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">估算超限?</text>
|
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">仍超限?</text>
|
||||||
|
|
||||||
<!-- 否:右侧文字标注 -->
|
<!-- 否:右侧文字标注 -->
|
||||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">否 → 通过</text>
|
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">否 → 通过</text>
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
<text x="94" y="414" fill="#334155" font-size="10">共同骨架:循环、hook、权限检查、5 个基础工具</text>
|
<text x="94" y="414" fill="#334155" font-size="10">共同骨架:循环、hook、权限检查、5 个基础工具</text>
|
||||||
|
|
||||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="94" y="436" fill="#334155" font-size="10">① 每轮自动:Step 1→2→3 在每次 LLM 调用前执行,0 API</text>
|
<text x="94" y="436" fill="#334155" font-size="10">① 预处理:Step 1→2 每轮执行;超限时再执行 Step 3,0 API</text>
|
||||||
|
|
||||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||||
<text x="94" y="458" fill="#334155" font-size="10">② 条件触发:前三步后 size 仍超阈值 → compact_history,1 API</text>
|
<text x="94" y="458" fill="#334155" font-size="10">② 条件触发:Step 3 后 size 仍超阈值 → compact_history,1 API</text>
|
||||||
|
|
||||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||||
<text x="94" y="480" fill="#334155" font-size="10">③ 异常触发:API 返回 prompt_too_long → reactive_compact → 重试一次</text>
|
<text x="94" y="480" fill="#334155" font-size="10">③ 异常触发:API 返回 prompt_too_long → reactive_compact → 重试一次</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<!-- ===== Pre-processing pipeline title ===== -->
|
<!-- ===== Pre-processing pipeline title ===== -->
|
||||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">Pre-processing (Step 1 → Step 2 → Step 3 before every LLM call, 0 API)</text>
|
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">Pre-processing (Steps 1 → 2 every turn; Step 3 only over the limit, 0 API)</text>
|
||||||
|
|
||||||
<!-- Step 1: tool_result_budget -->
|
<!-- Step 1: tool_result_budget -->
|
||||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||||
@@ -69,11 +69,11 @@
|
|||||||
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
||||||
<text x="260" y="320" fill="#1e40af" font-size="11">old tool_result → placeholder (keep latest 3)</text>
|
<text x="260" y="320" fill="#1e40af" font-size="11">old tool_result → placeholder (keep latest 3)</text>
|
||||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">compact old</text>
|
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">compact old</text>
|
||||||
<text x="155" y="338" fill="#2563eb" font-size="9">Runs every turn and keeps the latest 3 results complete</text>
|
<text x="155" y="338" fill="#2563eb" font-size="9">Runs over the context limit and keeps the latest 3 results complete</text>
|
||||||
|
|
||||||
<!-- ===== Auto-compact title ===== -->
|
<!-- ===== Auto-compact title ===== -->
|
||||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">Auto-compact Decision (triggered when pre-processing is insufficient, 1 API call)</text>
|
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">Auto-compact Decision (triggered when still over after Step 3, 1 API call)</text>
|
||||||
|
|
||||||
<!-- Step 4: compact_history -->
|
<!-- Step 4: compact_history -->
|
||||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<!-- ===== 前処理パイプラインタイトル ===== -->
|
<!-- ===== 前処理パイプラインタイトル ===== -->
|
||||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">前処理(Step 1 → Step 2 → Step 3、各 LLM 呼び出し前、0 API)</text>
|
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">前処理(Step 1 → 2 は毎ターン、Step 3 は上限超過時のみ、0 API)</text>
|
||||||
|
|
||||||
<!-- Step 1: tool_result_budget -->
|
<!-- Step 1: tool_result_budget -->
|
||||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||||
@@ -69,11 +69,11 @@
|
|||||||
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
||||||
<text x="260" y="320" fill="#1e40af" font-size="11">古い tool_result → プレースホルダー(最新 3 件保持)</text>
|
<text x="260" y="320" fill="#1e40af" font-size="11">古い tool_result → プレースホルダー(最新 3 件保持)</text>
|
||||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">旧結果を圧縮</text>
|
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">旧結果を圧縮</text>
|
||||||
<text x="155" y="338" fill="#2563eb" font-size="9">毎ターン実行し、最新 3 件は完全に保持</text>
|
<text x="155" y="338" fill="#2563eb" font-size="9">上限超過時に実行し、最新 3 件は完全に保持</text>
|
||||||
|
|
||||||
<!-- ===== 自動圧縮タイトル ===== -->
|
<!-- ===== 自動圧縮タイトル ===== -->
|
||||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自動圧縮判定(前処理で不足時にトリガー、1 API 呼び出し)</text>
|
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自動圧縮判定(Step 3 後も上限超過時にトリガー、1 API 呼び出し)</text>
|
||||||
|
|
||||||
<!-- Step 4: compact_history -->
|
<!-- Step 4: compact_history -->
|
||||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.9 KiB |
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<!-- ===== 预处理管线标题 ===== -->
|
<!-- ===== 预处理管线标题 ===== -->
|
||||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">预处理管线(执行顺序:Step 1 → Step 2 → Step 3,每轮调用前执行,0 API)</text>
|
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">预处理管线(Step 1 → Step 2 每轮执行;超限时执行 Step 3,0 API)</text>
|
||||||
|
|
||||||
<!-- Step 1: tool_result_budget -->
|
<!-- Step 1: tool_result_budget -->
|
||||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||||
@@ -69,11 +69,11 @@
|
|||||||
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
||||||
<text x="260" y="320" fill="#1e40af" font-size="11">旧 tool_result → 占位符(保留最近 3 条)</text>
|
<text x="260" y="320" fill="#1e40af" font-size="11">旧 tool_result → 占位符(保留最近 3 条)</text>
|
||||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">压旧结果</text>
|
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">压旧结果</text>
|
||||||
<text x="155" y="338" fill="#2563eb" font-size="9">每轮执行,最近 3 条结果保持完整</text>
|
<text x="155" y="338" fill="#2563eb" font-size="9">上下文超限时执行,最近 3 条结果保持完整</text>
|
||||||
|
|
||||||
<!-- ===== 自动压缩标题 ===== -->
|
<!-- ===== 自动压缩标题 ===== -->
|
||||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自动压缩决策(预处理不够时触发,1 API 调用)</text>
|
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自动压缩决策(Step 3 后仍超限时触发,1 API 调用)</text>
|
||||||
|
|
||||||
<!-- Step 4: compact_history -->
|
<!-- Step 4: compact_history -->
|
||||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
110
tests/test_s08_context_compact.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import runpy
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
LESSON = ROOT / "s08_context_compact" / "code.py"
|
||||||
|
|
||||||
|
|
||||||
|
def load_lesson(monkeypatch, workdir: Path):
|
||||||
|
fake_anthropic = types.ModuleType("anthropic")
|
||||||
|
fake_dotenv = types.ModuleType("dotenv")
|
||||||
|
|
||||||
|
class FakeAnthropic:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.messages = types.SimpleNamespace(create=None)
|
||||||
|
|
||||||
|
fake_anthropic.Anthropic = FakeAnthropic
|
||||||
|
fake_dotenv.load_dotenv = lambda override=True: None
|
||||||
|
monkeypatch.setitem(sys.modules, "anthropic", fake_anthropic)
|
||||||
|
monkeypatch.setitem(sys.modules, "dotenv", fake_dotenv)
|
||||||
|
monkeypatch.setenv("MODEL_ID", "test-model")
|
||||||
|
monkeypatch.setenv("ANTHROPIC_API_KEY", "test-key")
|
||||||
|
monkeypatch.chdir(workdir)
|
||||||
|
return runpy.run_path(str(LESSON))
|
||||||
|
|
||||||
|
|
||||||
|
def test_glob_double_star_matches_files_at_any_depth(tmp_path, monkeypatch):
|
||||||
|
(tmp_path / "root.py").write_text("")
|
||||||
|
(tmp_path / "one").mkdir()
|
||||||
|
(tmp_path / "one" / "one.py").write_text("")
|
||||||
|
(tmp_path / "one" / "two").mkdir()
|
||||||
|
(tmp_path / "one" / "two" / "deep.py").write_text("")
|
||||||
|
lesson = load_lesson(monkeypatch, tmp_path)
|
||||||
|
|
||||||
|
matches = set(lesson["run_glob"]("**/*.py").splitlines())
|
||||||
|
|
||||||
|
assert matches == {"root.py", "one/one.py", "one/two/deep.py"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_preserves_tool_results_while_context_is_within_limit(
|
||||||
|
tmp_path, monkeypatch):
|
||||||
|
lesson = load_lesson(monkeypatch, tmp_path)
|
||||||
|
messages = []
|
||||||
|
expected_results = []
|
||||||
|
for index in range(5):
|
||||||
|
tool_id = f"tool-{index}"
|
||||||
|
result = f"result-{index}:" + "x" * 200
|
||||||
|
expected_results.append(result)
|
||||||
|
messages.extend([
|
||||||
|
{"role": "assistant", "content": [
|
||||||
|
{"type": "tool_use", "id": tool_id, "name": "bash", "input": {}}
|
||||||
|
]},
|
||||||
|
{"role": "user", "content": [
|
||||||
|
{"type": "tool_result", "tool_use_id": tool_id, "content": result}
|
||||||
|
]},
|
||||||
|
])
|
||||||
|
messages.append({"role": "assistant", "content": [
|
||||||
|
{"type": "text", "text": "continue"}
|
||||||
|
]})
|
||||||
|
|
||||||
|
prepared = lesson["COMPACTOR"].prepare(messages, "inspect the repository")
|
||||||
|
actual_results = [
|
||||||
|
block["content"]
|
||||||
|
for message in prepared
|
||||||
|
if message["role"] == "user"
|
||||||
|
for block in message["content"]
|
||||||
|
if block["type"] == "tool_result"
|
||||||
|
]
|
||||||
|
|
||||||
|
assert actual_results == expected_results
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_micro_compacts_tool_results_after_context_exceeds_limit(
|
||||||
|
tmp_path, monkeypatch):
|
||||||
|
lesson = load_lesson(monkeypatch, tmp_path)
|
||||||
|
messages = []
|
||||||
|
for index in range(5):
|
||||||
|
tool_id = f"tool-{index}"
|
||||||
|
messages.extend([
|
||||||
|
{"role": "assistant", "content": [
|
||||||
|
{"type": "tool_use", "id": tool_id, "name": "bash", "input": {}}
|
||||||
|
]},
|
||||||
|
{"role": "user", "content": [
|
||||||
|
{"type": "tool_result", "tool_use_id": tool_id,
|
||||||
|
"content": f"result-{index}:" + "x" * 1000}
|
||||||
|
]},
|
||||||
|
])
|
||||||
|
messages.append({"role": "assistant", "content": [
|
||||||
|
{"type": "text", "text": "continue"}
|
||||||
|
]})
|
||||||
|
compactor = lesson["COMPACTOR"]
|
||||||
|
compactor.CONTEXT_CHAR_LIMIT = 4500
|
||||||
|
|
||||||
|
prepared = compactor.prepare(messages, "inspect the repository")
|
||||||
|
actual_results = [
|
||||||
|
block["content"]
|
||||||
|
for message in prepared
|
||||||
|
if message["role"] == "user"
|
||||||
|
for block in message["content"]
|
||||||
|
if block["type"] == "tool_result"
|
||||||
|
]
|
||||||
|
|
||||||
|
assert actual_results[:2] == [
|
||||||
|
"[Earlier tool result omitted.]",
|
||||||
|
"[Earlier tool result omitted.]",
|
||||||
|
]
|
||||||
|
assert all(result.startswith(f"result-{index}:")
|
||||||
|
for index, result in enumerate(actual_results[2:], start=2))
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<!-- Trigger Condition -->
|
<!-- Trigger Condition -->
|
||||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">Trigger Condition</text>
|
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">Trigger Condition</text>
|
||||||
<text x="140" y="70" fill="#991b1b" font-size="11">After Steps 1–3, estimate_chars(messages) > CONTEXT_CHAR_LIMIT.</text>
|
<text x="140" y="70" fill="#991b1b" font-size="11">After micro_compact, estimate_chars(messages) > CONTEXT_CHAR_LIMIT.</text>
|
||||||
<text x="140" y="86" fill="#991b1b" font-size="10">The current CONTEXT_CHAR_LIMIT is 50,000 characters.</text>
|
<text x="140" y="86" fill="#991b1b" font-size="10">The current CONTEXT_CHAR_LIMIT is 50,000 characters.</text>
|
||||||
|
|
||||||
<!-- Steps -->
|
<!-- Steps -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
@@ -16,7 +16,7 @@
|
|||||||
<!-- トリガー条件 -->
|
<!-- トリガー条件 -->
|
||||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">トリガー条件</text>
|
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">トリガー条件</text>
|
||||||
<text x="115" y="70" fill="#991b1b" font-size="11">Step 1~3 の後、estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
<text x="115" y="70" fill="#991b1b" font-size="11">micro_compact の後、estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
||||||
<text x="115" y="86" fill="#991b1b" font-size="10">現在の CONTEXT_CHAR_LIMIT は 50,000 文字。</text>
|
<text x="115" y="86" fill="#991b1b" font-size="10">現在の CONTEXT_CHAR_LIMIT は 50,000 文字。</text>
|
||||||
|
|
||||||
<!-- ステップ -->
|
<!-- ステップ -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.8 KiB |
@@ -16,7 +16,7 @@
|
|||||||
<!-- 触发条件 -->
|
<!-- 触发条件 -->
|
||||||
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
<rect x="20" y="54" width="680" height="44" rx="6" fill="#fef2f2" stroke="#fca5a5" stroke-width="1"/>
|
||||||
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">触发条件</text>
|
<text x="35" y="70" fill="#991b1b" font-size="11" font-weight="600">触发条件</text>
|
||||||
<text x="105" y="70" fill="#991b1b" font-size="11">前三步执行后,estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
<text x="105" y="70" fill="#991b1b" font-size="11">micro_compact 后,estimate_chars(messages) > CONTEXT_CHAR_LIMIT。</text>
|
||||||
<text x="105" y="86" fill="#991b1b" font-size="10">当前实现的 CONTEXT_CHAR_LIMIT 为 50,000 个字符。</text>
|
<text x="105" y="86" fill="#991b1b" font-size="10">当前实现的 CONTEXT_CHAR_LIMIT 为 50,000 个字符。</text>
|
||||||
|
|
||||||
<!-- 步骤 -->
|
<!-- 步骤 -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -45,9 +45,9 @@
|
|||||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Compression Pipeline</text>
|
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">Compression Pipeline</text>
|
||||||
|
|
||||||
<!-- ── ① Every Turn Auto ── -->
|
<!-- ── ① Pre-processing ── -->
|
||||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Every Turn · Unconditional · 0 API</text>
|
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Steps 1–2 Every Turn · 0 API</text>
|
||||||
|
|
||||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
||||||
|
|
||||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact</text>
|
<text x="270" y="202" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">Step 3 micro_compact (over limit)</text>
|
||||||
|
|
||||||
<!-- ↓ → ◇ -->
|
<!-- ↓ → ◇ -->
|
||||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
<!-- ◇ Decision Diamond -->
|
<!-- ◇ Decision Diamond -->
|
||||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">Over threshold?</text>
|
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">Still over?</text>
|
||||||
|
|
||||||
<!-- No: right annotation -->
|
<!-- No: right annotation -->
|
||||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → Pass</text>
|
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → Pass</text>
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
<text x="94" y="414" fill="#334155" font-size="10">Shared: loop, hooks, permissions, five base tools</text>
|
<text x="94" y="414" fill="#334155" font-size="10">Shared: loop, hooks, permissions, five base tools</text>
|
||||||
|
|
||||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="94" y="436" fill="#334155" font-size="10">① Every Turn: Steps 1→2→3 run before each LLM call, 0 API</text>
|
<text x="94" y="436" fill="#334155" font-size="10">① Pre-process: Steps 1→2 every turn; Step 3 only over the limit, 0 API</text>
|
||||||
|
|
||||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||||
<text x="94" y="458" fill="#334155" font-size="10">② Conditional: size remains over the limit after Step 3 → compact_history, 1 API</text>
|
<text x="94" y="458" fill="#334155" font-size="10">② Conditional: still over the limit after Step 3 → compact_history, 1 API</text>
|
||||||
|
|
||||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||||
<text x="94" y="480" fill="#334155" font-size="10">③ Recovery: API returns prompt_too_long → reactive_compact → retry once</text>
|
<text x="94" y="480" fill="#334155" font-size="10">③ Recovery: API returns prompt_too_long → reactive_compact → retry once</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
@@ -45,9 +45,9 @@
|
|||||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">圧縮パイプライン</text>
|
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">圧縮パイプライン</text>
|
||||||
|
|
||||||
<!-- ── ① 毎ターン自動 ── -->
|
<!-- ── ① 前処理 ── -->
|
||||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① 毎ターン自動 · 無条件 · 0 API</text>
|
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Step 1–2 は毎ターン · 0 API</text>
|
||||||
|
|
||||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
||||||
|
|
||||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact</text>
|
<text x="270" y="202" fill="#92400e" font-size="9" font-weight="600" text-anchor="middle">Step 3 micro_compact(上限超過時)</text>
|
||||||
|
|
||||||
<!-- ↓ → ◇ -->
|
<!-- ↓ → ◇ -->
|
||||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
<!-- ◇ 判定ダイヤモンド -->
|
<!-- ◇ 判定ダイヤモンド -->
|
||||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">推定値超過?</text>
|
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">まだ超過?</text>
|
||||||
|
|
||||||
<!-- いいえ:右側注釈 -->
|
<!-- いいえ:右側注釈 -->
|
||||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → 通過</text>
|
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">No → 通過</text>
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
<text x="94" y="414" fill="#334155" font-size="10">共通:ループ、フック、権限確認、5 個の基本ツール</text>
|
<text x="94" y="414" fill="#334155" font-size="10">共通:ループ、フック、権限確認、5 個の基本ツール</text>
|
||||||
|
|
||||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="94" y="436" fill="#334155" font-size="10">① 毎ターン:Step 1→2→3 を各 LLM 呼び出し前に実行、0 API</text>
|
<text x="94" y="436" fill="#334155" font-size="10">① 前処理:Step 1→2 は毎ターン、Step 3 は上限超過時のみ、0 API</text>
|
||||||
|
|
||||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||||
<text x="94" y="458" fill="#334155" font-size="10">② 条件:Step 3 後もサイズ上限超過 → compact_history、1 API</text>
|
<text x="94" y="458" fill="#334155" font-size="10">② 条件:Step 3 後も上限超過 → compact_history、1 API</text>
|
||||||
|
|
||||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||||
<text x="94" y="480" fill="#334155" font-size="10">③ 回復:API が prompt_too_long を返す → reactive_compact → 1 回リトライ</text>
|
<text x="94" y="480" fill="#334155" font-size="10">③ 回復:API が prompt_too_long を返す → reactive_compact → 1 回リトライ</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -45,9 +45,9 @@
|
|||||||
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
<rect x="170" y="82" width="200" height="252" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
|
||||||
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">压缩管线</text>
|
<text x="270" y="102" fill="#92400e" font-size="11" font-weight="700" text-anchor="middle">压缩管线</text>
|
||||||
|
|
||||||
<!-- ── ① 每轮自动 ── -->
|
<!-- ── ① 预处理 ── -->
|
||||||
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
<rect x="186" y="110" width="168" height="16" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="0.8"/>
|
||||||
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① 每轮自动 · 无条件 · 0 API</text>
|
<text x="270" y="122" fill="#92400e" font-size="8" font-weight="700" text-anchor="middle">① Step 1–2 每轮 · 0 API</text>
|
||||||
|
|
||||||
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="130" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
<text x="270" y="146" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 1 tool_result_budget</text>
|
||||||
@@ -56,14 +56,14 @@
|
|||||||
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
<text x="270" y="174" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 2 snip_compact</text>
|
||||||
|
|
||||||
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
<rect x="186" y="186" width="168" height="24" rx="4" fill="#fef3c7" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact</text>
|
<text x="270" y="202" fill="#92400e" font-size="10" font-weight="600" text-anchor="middle">Step 3 micro_compact(超限时)</text>
|
||||||
|
|
||||||
<!-- ↓ → ◇ -->
|
<!-- ↓ → ◇ -->
|
||||||
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
<line x1="270" y1="210" x2="270" y2="222" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
<!-- ◇ 判断菱形(紧凑) -->
|
<!-- ◇ 判断菱形(紧凑) -->
|
||||||
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
<polygon points="270,226 300,244 270,262 240,244" fill="#f0f4ff" stroke="#ea580c" stroke-width="1.5"/>
|
||||||
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">估算超限?</text>
|
<text x="270" y="247" fill="#9a3412" font-size="7" font-weight="600" text-anchor="middle">仍超限?</text>
|
||||||
|
|
||||||
<!-- 否:右侧文字标注 -->
|
<!-- 否:右侧文字标注 -->
|
||||||
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">否 → 通过</text>
|
<text x="306" y="240" fill="#16a34a" font-size="9" font-weight="700">否 → 通过</text>
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
<text x="94" y="414" fill="#334155" font-size="10">共同骨架:循环、hook、权限检查、5 个基础工具</text>
|
<text x="94" y="414" fill="#334155" font-size="10">共同骨架:循环、hook、权限检查、5 个基础工具</text>
|
||||||
|
|
||||||
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
<rect x="70" y="426" width="16" height="12" rx="3" fill="#fde68a" stroke="#d97706" stroke-width="1"/>
|
||||||
<text x="94" y="436" fill="#334155" font-size="10">① 每轮自动:Step 1→2→3 在每次 LLM 调用前执行,0 API</text>
|
<text x="94" y="436" fill="#334155" font-size="10">① 预处理:Step 1→2 每轮执行;超限时再执行 Step 3,0 API</text>
|
||||||
|
|
||||||
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
<rect x="70" y="448" width="16" height="12" rx="3" fill="#fed7aa" stroke="#ea580c" stroke-width="1"/>
|
||||||
<text x="94" y="458" fill="#334155" font-size="10">② 条件触发:前三步后 size 仍超阈值 → compact_history,1 API</text>
|
<text x="94" y="458" fill="#334155" font-size="10">② 条件触发:Step 3 后 size 仍超阈值 → compact_history,1 API</text>
|
||||||
|
|
||||||
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
<rect x="70" y="470" width="16" height="12" rx="3" fill="#fef2f2" stroke="#dc2626" stroke-width="1" stroke-dasharray="3,2"/>
|
||||||
<text x="94" y="480" fill="#334155" font-size="10">③ 异常触发:API 返回 prompt_too_long → reactive_compact → 重试一次</text>
|
<text x="94" y="480" fill="#334155" font-size="10">③ 异常触发:API 返回 prompt_too_long → reactive_compact → 重试一次</text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<!-- ===== Pre-processing pipeline title ===== -->
|
<!-- ===== Pre-processing pipeline title ===== -->
|
||||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">Pre-processing (Step 1 → Step 2 → Step 3 before every LLM call, 0 API)</text>
|
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">Pre-processing (Steps 1 → 2 every turn; Step 3 only over the limit, 0 API)</text>
|
||||||
|
|
||||||
<!-- Step 1: tool_result_budget -->
|
<!-- Step 1: tool_result_budget -->
|
||||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||||
@@ -69,11 +69,11 @@
|
|||||||
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
||||||
<text x="260" y="320" fill="#1e40af" font-size="11">old tool_result → placeholder (keep latest 3)</text>
|
<text x="260" y="320" fill="#1e40af" font-size="11">old tool_result → placeholder (keep latest 3)</text>
|
||||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">compact old</text>
|
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">compact old</text>
|
||||||
<text x="155" y="338" fill="#2563eb" font-size="9">Runs every turn and keeps the latest 3 results complete</text>
|
<text x="155" y="338" fill="#2563eb" font-size="9">Runs over the context limit and keeps the latest 3 results complete</text>
|
||||||
|
|
||||||
<!-- ===== Auto-compact title ===== -->
|
<!-- ===== Auto-compact title ===== -->
|
||||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">Auto-compact Decision (triggered when pre-processing is insufficient, 1 API call)</text>
|
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">Auto-compact Decision (triggered when still over after Step 3, 1 API call)</text>
|
||||||
|
|
||||||
<!-- Step 4: compact_history -->
|
<!-- Step 4: compact_history -->
|
||||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<!-- ===== 前処理パイプラインタイトル ===== -->
|
<!-- ===== 前処理パイプラインタイトル ===== -->
|
||||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">前処理(Step 1 → Step 2 → Step 3、各 LLM 呼び出し前、0 API)</text>
|
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">前処理(Step 1 → 2 は毎ターン、Step 3 は上限超過時のみ、0 API)</text>
|
||||||
|
|
||||||
<!-- Step 1: tool_result_budget -->
|
<!-- Step 1: tool_result_budget -->
|
||||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||||
@@ -69,11 +69,11 @@
|
|||||||
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
||||||
<text x="260" y="320" fill="#1e40af" font-size="11">古い tool_result → プレースホルダー(最新 3 件保持)</text>
|
<text x="260" y="320" fill="#1e40af" font-size="11">古い tool_result → プレースホルダー(最新 3 件保持)</text>
|
||||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">旧結果を圧縮</text>
|
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">旧結果を圧縮</text>
|
||||||
<text x="155" y="338" fill="#2563eb" font-size="9">毎ターン実行し、最新 3 件は完全に保持</text>
|
<text x="155" y="338" fill="#2563eb" font-size="9">上限超過時に実行し、最新 3 件は完全に保持</text>
|
||||||
|
|
||||||
<!-- ===== 自動圧縮タイトル ===== -->
|
<!-- ===== 自動圧縮タイトル ===== -->
|
||||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自動圧縮判定(前処理で不足時にトリガー、1 API 呼び出し)</text>
|
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自動圧縮判定(Step 3 後も上限超過時にトリガー、1 API 呼び出し)</text>
|
||||||
|
|
||||||
<!-- Step 4: compact_history -->
|
<!-- Step 4: compact_history -->
|
||||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.9 KiB |
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<!-- ===== 预处理管线标题 ===== -->
|
<!-- ===== 预处理管线标题 ===== -->
|
||||||
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="146" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">预处理管线(执行顺序:Step 1 → Step 2 → Step 3,每轮调用前执行,0 API)</text>
|
<text x="55" y="163" fill="#64748b" font-size="11" font-weight="600">预处理管线(Step 1 → Step 2 每轮执行;超限时执行 Step 3,0 API)</text>
|
||||||
|
|
||||||
<!-- Step 1: tool_result_budget -->
|
<!-- Step 1: tool_result_budget -->
|
||||||
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
<rect x="80" y="180" width="600" height="46" rx="7" fill="url(#pre)" stroke="#2563eb" stroke-width="1.5"/>
|
||||||
@@ -69,11 +69,11 @@
|
|||||||
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
<text x="155" y="320" fill="#1e40af" font-size="13" font-weight="700">micro_compact</text>
|
||||||
<text x="260" y="320" fill="#1e40af" font-size="11">旧 tool_result → 占位符(保留最近 3 条)</text>
|
<text x="260" y="320" fill="#1e40af" font-size="11">旧 tool_result → 占位符(保留最近 3 条)</text>
|
||||||
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">压旧结果</text>
|
<text x="650" y="320" fill="#1e40af" font-size="10" text-anchor="end">压旧结果</text>
|
||||||
<text x="155" y="338" fill="#2563eb" font-size="9">每轮执行,最近 3 条结果保持完整</text>
|
<text x="155" y="338" fill="#2563eb" font-size="9">上下文超限时执行,最近 3 条结果保持完整</text>
|
||||||
|
|
||||||
<!-- ===== 自动压缩标题 ===== -->
|
<!-- ===== 自动压缩标题 ===== -->
|
||||||
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
<rect x="20" y="358" width="720" height="24" rx="4" fill="#f1f5f9"/>
|
||||||
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自动压缩决策(预处理不够时触发,1 API 调用)</text>
|
<text x="70" y="375" fill="#64748b" font-size="11" font-weight="600">自动压缩决策(Step 3 后仍超限时触发,1 API 调用)</text>
|
||||||
|
|
||||||
<!-- Step 4: compact_history -->
|
<!-- Step 4: compact_history -->
|
||||||
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
<rect x="80" y="390" width="600" height="58" rx="7" fill="url(#auto)" stroke="#dc2626" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |