shareAI-lab / shareAI-lab/learn-claude-code

s09: select_relevant_memories 的 "recent" 拼接顺序与切片不合理,不是真正的最近 2k 上下文

Open Beginner friendly
#517 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
77.2k
Forks
12.4k
Avg merge
2d 5h
Merged PRs (30d)
6

Description

问题

s09_memory/code.py:251-261 recent_user_text returns a string claiming to be the most recent user context, but the join + slice order produces an unintuitive result.

def recent_user_text(messages: list, max_turns: int = 3) -> str:
    turns = []
    for message in reversed(messages):
        if message.get("role") != "user":
            continue
        text = message_text(message).strip()
        if text:
            turns.append(text)
        if len(turns) == max_turns:
            break
    return "\n".join(reversed(turns))[:4000]

Actual behavior

  1. reversed(messages) walks backwards; turns accumulates up to max_turns=3 user texts in turns = [latest, prev, prev2] order.
  2. reversed(turns) then flips it back to [prev2, prev, latest].
  3. Joined with \n, sliced to head 4000 chars.

Consequences:

  • If the latest user turn is short (e.g. "ok"), the head-4000 fills with older turns and the latest one is pushed past the slice window — the most relevant signal is dropped.
  • If the latest turn is long, older turns are pushed out entirely and the function degrades to "use only the latest turn" — but that intent is not expressed in the code.
  • The function is named recent_user_text but the implementation is "oldest of the recent few, then head-slice". Order is non-obvious.

Expected behavior

recent_user_text should mean "the last N characters of the most recent user context, in chronological order". A minimal fix:

def recent_user_text(messages: list, max_chars: int = 4000) -> str:
    chunks = []
    for message in messages:
        if message.get("role") != "user":
            continue
        text = message_text(message).strip()
        if text:
            chunks.append(text)
    joined = "\n".join(chunks)
    return joined[-max_chars:] if len(joined) > max_chars else joined

Or, if preserving the per-turn walk is desired, take only the tail of the result rather than the head:

result = "\n".join(reversed(turns))
return result[-4000:] if len(result) > 4000 else result

Either is fine — the important thing is that the slice direction matches the name: "recent" means tail, not head.


中文版本

问题

s09_memory/code.py:251-261 recent_user_text 的字面意思虽然是"最近的用户文本",但 join + 切片的顺序让它产出一个反直觉的结果。

```python
def recent_user_text(messages: list, max_turns: int = 3) -> str:
turns = []
for message in reversed(messages):
if message.get("role") != "user":
continue
text = message_text(message).strip()
if text:
turns.append(text)
if len(turns) == max_turns:
break
return "\n".join(reversed(turns))[:4000]
```

实际行为
  1. `reversed(messages)` 从末尾向前扫描,收集最多 3 条 user 文本,此时 `turns` 顺序为 `[最新, 次新, 更旧]`。
  2. `reversed(turns)` 又翻回 `[更旧, 次新, 最新]`。
  3. 用 `\n` 拼接后取头 4000 字符。

带来的问题:

  • 如果最新那条很短(比如 "ok"),头 4000 字符会被更旧的消息灌满,最新那条反而被切掉——最该被命中的信号反而丢
  • 如果最新那条够长,前面的消息直接被挤出窗口,函数退化成"只用最新一条"——这个意图代码里没体现
  • 函数名叫 `recent_user_text`,实现却是"最近几条里最旧的先出现 + 头切",顺序含义不明
期望行为

`recent_user_text` 应该是"按时间正序排列后,取末尾 N 个字符"。最小修复:

```python
def recent_user_text(messages: list, max_chars: int = 4000) -> str:
chunks = []
for message in messages:
if message.get("role") != "user":
continue
text = message_text(message).strip()
if text:
chunks.append(text)
joined = "\n".join(chunks)
return joined[-max_chars:] if len(joined) > max_chars else joined
```

或者保留逐条遍历的写法,但把切片方向反过来:

```python
result = "\n".join(reversed(turns))
return result[-4000:] if len(result) > 4000 else result
```

任选其一即可,关键是切片方向跟函数名一致——"recent" 是尾部,不是头部。

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in s09_memory/code.py at recent_user_text, especially lines 251-261, and inspect how user messages are collected, joined, and sliced. Verify the chosen behavior with short and long recent turns; done means the returned context preserves chronological order and includes the tail of the most recent 4000 characters.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
ai
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.