修改
This commit is contained in:
+1
-1
@@ -158,7 +158,7 @@ class AgentRuntimeConfig:
|
||||
cwd: Path
|
||||
max_turns: int = DEFAULT_MAX_TURNS
|
||||
command_timeout_seconds: float = 30.0
|
||||
max_output_chars: int = 12000
|
||||
max_output_chars: int = 50000 # ≈ 20k token (Chinese/code mix ≈ 2.5 chars/token)
|
||||
stream_model_responses: bool = False
|
||||
auto_snip_threshold_tokens: int | None = None
|
||||
auto_compact_threshold_tokens: int | None = None
|
||||
|
||||
@@ -774,6 +774,20 @@ print(f"{'appended' if MODE == 'a' else 'wrote'} {target} ({len(content)} chars)
|
||||
|
||||
def resolve_workspace_path(self, raw_path: str) -> str:
|
||||
value = raw_path.strip() or '.'
|
||||
|
||||
# 系统提示里给的"当前会话目录"通常是本地后端的绝对/相对路径,例如
|
||||
# `.port_sessions/accounts/<acc>/sessions/<sid>/input` 或
|
||||
# `/home/mi/.../.port_sessions/accounts/<acc>/sessions/<sid>/output/foo.csv`。
|
||||
# 远端 Jupyter 没这套目录结构。识别这种 pattern 后,把 input/output/
|
||||
# scratchpad bucket 映射到远端 workspace 的同名目录。
|
||||
bucket_match = self._match_local_session_bucket(value)
|
||||
if bucket_match is not None:
|
||||
bucket, rest = bucket_match
|
||||
tail = f'/{rest}' if rest else ''
|
||||
return normalize_posix_path(
|
||||
f'{self.binding.workspace_cwd}/{bucket}{tail}'
|
||||
)
|
||||
|
||||
if value.startswith('/'):
|
||||
return normalize_posix_path(value)
|
||||
path = PurePosixPath(value)
|
||||
@@ -787,8 +801,34 @@ print(f"{'appended' if MODE == 'a' else 'wrote'} {target} ({len(content)} chars)
|
||||
if path.parts and path.parts[0] in {'scratchpad', 'scratch'}:
|
||||
tail = PurePosixPath(*path.parts[1:]) if len(path.parts) > 1 else PurePosixPath()
|
||||
return normalize_posix_path(f'{self.binding.workspace_cwd}/scratchpad/{tail}')
|
||||
if path.parts and path.parts[0] in {'input', 'inputs'}:
|
||||
tail = PurePosixPath(*path.parts[1:]) if len(path.parts) > 1 else PurePosixPath()
|
||||
return normalize_posix_path(f'{self.binding.workspace_cwd}/input/{tail}')
|
||||
return normalize_posix_path(f'{self.binding.workspace_cwd}/{value}')
|
||||
|
||||
_LOCAL_SESSION_BUCKET_RE = re.compile(
|
||||
r'(?:^|/)\.port_sessions/accounts/[^/]+/sessions/[^/]+/'
|
||||
r'(?P<bucket>input|inputs|output|outputs|scratchpad|scratch)'
|
||||
r'(?:/(?P<rest>.*))?$'
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _match_local_session_bucket(cls, raw: str) -> tuple[str, str] | None:
|
||||
m = cls._LOCAL_SESSION_BUCKET_RE.search(raw)
|
||||
if not m:
|
||||
return None
|
||||
bucket = m.group('bucket')
|
||||
normalized = {
|
||||
'input': 'input',
|
||||
'inputs': 'input',
|
||||
'output': 'output',
|
||||
'outputs': 'output',
|
||||
'scratchpad': 'scratchpad',
|
||||
'scratch': 'scratchpad',
|
||||
}[bucket]
|
||||
rest = m.group('rest') or ''
|
||||
return normalized, rest
|
||||
|
||||
def _remote_env_prefix(self) -> str:
|
||||
exports = {
|
||||
'ZK_AGENT_WORKSPACE': self.binding.workspace_cwd,
|
||||
|
||||
+23
-21
@@ -15,28 +15,28 @@ from .agent_types import (
|
||||
OutputSchemaConfig,
|
||||
UsageStats,
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StoredSession:
|
||||
session_id: str
|
||||
messages: tuple[str, ...]
|
||||
input_tokens: int
|
||||
output_tokens: int
|
||||
|
||||
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StoredSession:
|
||||
session_id: str
|
||||
messages: tuple[str, ...]
|
||||
input_tokens: int
|
||||
output_tokens: int
|
||||
|
||||
|
||||
DEFAULT_SESSION_DIR = Path('.port_sessions')
|
||||
DEFAULT_AGENT_SESSION_DIR = DEFAULT_SESSION_DIR / 'agent'
|
||||
|
||||
|
||||
def save_session(session: StoredSession, directory: Path | None = None) -> Path:
|
||||
target_dir = directory or DEFAULT_SESSION_DIR
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
path = target_dir / f'{session.session_id}.json'
|
||||
path.write_text(json.dumps(asdict(session), indent=2))
|
||||
return path
|
||||
|
||||
|
||||
|
||||
|
||||
def save_session(session: StoredSession, directory: Path | None = None) -> Path:
|
||||
target_dir = directory or DEFAULT_SESSION_DIR
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
path = target_dir / f'{session.session_id}.json'
|
||||
path.write_text(json.dumps(asdict(session), indent=2))
|
||||
return path
|
||||
|
||||
|
||||
def load_session(session_id: str, directory: Path | None = None) -> StoredSession:
|
||||
target_dir = directory or DEFAULT_SESSION_DIR
|
||||
data = json.loads((target_dir / f'{session_id}.json').read_text())
|
||||
@@ -68,6 +68,7 @@ class StoredAgentSession:
|
||||
budget_state: JSONDict
|
||||
plugin_state: JSONDict
|
||||
scratchpad_directory: str | None = None
|
||||
is_training: bool = False
|
||||
|
||||
|
||||
def save_agent_session(session: StoredAgentSession, directory: Path | None = None) -> Path:
|
||||
@@ -118,6 +119,7 @@ def load_agent_session(session_id: str, directory: Path | None = None) -> Stored
|
||||
if isinstance(data.get('scratchpad_directory'), str)
|
||||
else None
|
||||
),
|
||||
is_training=bool(data.get('is_training', False)),
|
||||
)
|
||||
|
||||
|
||||
@@ -222,7 +224,7 @@ def deserialize_runtime_config(payload: JSONDict) -> AgentRuntimeConfig:
|
||||
cwd=Path(str(payload['cwd'])).resolve(),
|
||||
max_turns=int(payload.get('max_turns', DEFAULT_MAX_TURNS)),
|
||||
command_timeout_seconds=float(payload.get('command_timeout_seconds', 30.0)),
|
||||
max_output_chars=int(payload.get('max_output_chars', 12000)),
|
||||
max_output_chars=int(payload.get('max_output_chars', 50000)),
|
||||
stream_model_responses=bool(payload.get('stream_model_responses', False)),
|
||||
auto_snip_threshold_tokens=_optional_int(payload.get('auto_snip_threshold_tokens')),
|
||||
auto_compact_threshold_tokens=_optional_int(payload.get('auto_compact_threshold_tokens')),
|
||||
|
||||
Reference in New Issue
Block a user