Skip to content

fix(harness): sandbox edit generated python3 -c program with literal sequences (SyntaxError) - #3226

Open
aiyili wants to merge 1 commit into
agentscope-ai:mainfrom
aiyili:main
Open

aiyili wants to merge 1 commit into
agentscope-ai:mainfrom
aiyili:main

Conversation

@aiyili

@aiyili aiyili commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Fixes #2571

Problem

BaseSandboxFilesystem.edit(...) failed before reading or modifying the target file. Two defects in the generated shell command:

  1. Literal sequences instead of line feeds. The Java code joined the python3 -c "..." program fragments with \n (a literal backslash + n at runtime). Inside a POSIX double-quoted string the backslash before n is not an escape — the two characters reach python3 unchanged — so the whole program arrived as a single line and the interpreter failed with:

    SyntaxError: unexpected character after line continuation character
    
  2. Exit code ignored. execute's response was parsed without checking the exit code, so the interpreter crash above was masked as unexpected server response instead of the actual cause.

Fix

  • Build the Python program with a Java text block, so its statements are separated by real line feeds. The statements themselves are unchanged. A comment documents why real line feeds are required (regression guard).
  • Check result.isSuccess() right after execute, reusing the existing executeFailureMessage(...) convention from ls/read/grep/glob: execution-layer failures (timeout 124, transport errors, interpreter crash) now surface with their diagnostic output (or exit code fallback) instead of being mislabeled.

Verification

  • Reproduced against a real sh + python3 locally: the old command fails with the SyntaxError above and leaves the file untouched; the fixed command outputs {"count": 1} and performs the replacement.
  • agentscope-harness module test suite: BUILD SUCCESS; BaseSandboxFilesystemTest 19/19 canned tests pass (incl. 3 new ones), 3 new Linux real-shell integration tests run on CI.
  • mvn spotless:check passes.

Tests added

Unit (all platforms):

  • edit_generatedPythonProgram_isSeparatedByRealLineFeeds — the generated command contains real line feeds and no literal sequence
  • edit_executeFailure_shouldFailWithCause — transport failure surfaces with its cause
  • edit_executeFailure_nullOutput_shouldFailWithExitCodeFallback — exit-code fallback message

Linux real-shell integration:

  • edit_singleOccurrence_replacesItreplaceAll=false on a single occurrence replaces it (the scenario from the issue)
  • edit_multipleOccurrencesWithoutReplaceAll_failsAndKeepsFileUnchanged
  • edit_replaceAll_replacesEveryOccurrence

@CLAassistant

CLAassistant commented Sep 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@oss-maintainer oss-maintainer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Well-diagnosed fix. Switching the embedded python3 -c program to a Java text block makes the line feeds real (a literal \\n inside POSIX double quotes reaches python3 unchanged and collapses the program into one line), and the added isSuccess() guard aligns edit() with the existing executeFailureMessage(...) convention used by ls/read/grep/glob. CLA signed; unit + Linux real-shell regression tests are a good addition. LGTM.

One note: this PR currently shows mergeStateStatus=BLOCKED on GitHub — likely pending CI approval/reviews, not a code issue.


Automated review by github-manager-bot

@codecov

codecov Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@oss-maintainer

Copy link
Copy Markdown
Collaborator

CLA Not Signed

The Contributor License Agreement (CLA) check is currently pending on this PR (license/cla: Contributor License Agreement is not signed yet.). This PR cannot be merged until the CLA is signed.

@aiyili please sign the CLA via the CLA assistant badge in the comment above, or visit https://cla-assistant.io/agentscope-ai/agentscope-java. Once signed, the license/cla status will turn green.


Automated check by github-manager-bot

@aiyili

aiyili commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@cla-assistant check

… SyntaxError

- 改用 Java 文本块构建 python3 -c 程序,语句间为真实换行符:POSIX 双引号字符串内
  字面反斜杠+n 序列会原样传给 python3,整个程序被压成一行直接 SyntaxError
- execute 返回后先检查退出码:执行层失败(超时/传输错误/python 崩溃)现在携带
  原始原因返回,不再被掩盖成 unexpected server response
- 新增单元测试(生成命令形态 + 失败响应)与 Linux 真实 shell 集成测试
  (单次替换 / 多处出现拒绝 / replaceAll 全替换)

Fixes agentscope-ai#2571
@aiyili

aiyili commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Cross-referencing the #2571 evaluation's two reviewer asks against this PR:

1. The extra replaceAll=true finding — covered by construction: the fix rewrites the command builder once (text block with real line feeds), and replace_all remains pure payload data, so both edit_file branches share the corrected program. edit_replaceAll_replacesEveryOccurrence exercises the true branch end-to-end on a real shell (Linux CI).

2. Pinning the command constructionedit_generatedPythonProgram_isSeparatedByRealLineFeeds (runs on all platforms) asserts the generated command starts with python3 -c ", is separated by real line feeds, and contains no literal backslash-n sequence anywhere; the base64 heredoc payload is asserted intact by the three Linux real-shell integration tests (edit_singleOccurrence_replacesIt covers the exact issue scenario, plus multiple-occurrence refusal and replaceAll).

Additionally, this PR also fixes the second symptom from the report — the exit code is checked before parsing, so execution-layer failures (timeout / transport / interpreter crash) surface with their cause instead of being masked as unexpected server response (edit_executeFailure_shouldFailWithCause, edit_executeFailure_nullOutput_shouldFailWithExitCodeFallback).

Verified end-to-end against a real sh + python3 before submission (old command: SyntaxError, file untouched; fixed command: replacement applied). The branch is rebased onto current main and clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: BaseSandboxFilesystem.edit fails when replaceAll=false because the generated Python command contains literal \\n sequences`

3 participants