feat: harden company resume, external sessions, and Office UI i18n

Improve suspend/resume identity continuity and external broker session handling, add Office UI internationalization with rebuilt assets, and expand company org configs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
小东
2026-07-16 09:20:40 +08:00
parent eb934cf2bd
commit cb6b8ed6e1
32 changed files with 2562 additions and 446 deletions
+47 -1
View File
@@ -517,7 +517,28 @@ class ExternalAgentAdapter(abc.ABC):
merged = {**os.environ, **{str(k): str(v) for k, v in extra_env.items()}}
path_value = merged.get("PATH") or merged.get("Path") or merged.get("path") or ""
resolved = shutil.which(executable, path=path_value or None)
if not resolved or resolved == executable:
if not resolved:
return cmd
if os.name == "nt":
resolved = ExternalAgentAdapter._resolve_windows_command_shim(
executable,
resolved,
path_value=path_value,
)
if os.name == "nt" and os.path.splitext(resolved)[1].lower() in {".cmd", ".bat"}:
comspec = str(os.environ.get("COMSPEC") or "").strip()
if not comspec:
comspec = shutil.which("cmd.exe") or "cmd.exe"
wrapped_cmd = [comspec, "/d", "/s", "/c", resolved, *cmd[1:]]
if isinstance(launch_metadata, dict):
launch_metadata.setdefault("configured_binary", executable)
launch_metadata["resolved_binary"] = resolved
launch_metadata["launch_wrapper"] = comspec
return wrapped_cmd
if resolved == executable:
return cmd
resolved_cmd = list(cmd)
resolved_cmd[0] = resolved
@@ -526,6 +547,31 @@ class ExternalAgentAdapter(abc.ABC):
launch_metadata["resolved_binary"] = resolved
return resolved_cmd
@staticmethod
def _resolve_windows_command_shim(
executable: str,
resolved: str,
*,
path_value: str = "",
) -> str:
"""Prefer a Windows-launchable sibling over an extensionless POSIX shim."""
if os.path.splitext(resolved)[1]:
return resolved
for extension in (".exe", ".com", ".cmd", ".bat"):
sibling = f"{resolved}{extension}"
if os.path.isfile(sibling):
return sibling
if os.path.dirname(executable):
return resolved
for extension in (".exe", ".com", ".cmd", ".bat"):
candidate = shutil.which(f"{executable}{extension}", path=path_value or None)
if candidate:
return candidate
return resolved
async def send_process_input(
self,
proc: asyncio.subprocess.Process,
+66 -1
View File
@@ -32,6 +32,8 @@ class CodexAdapter(ExternalAgentAdapter):
"CODEX_SANDBOX_NETWORK_DISABLED",
"CODEX_THREAD_ID",
}
_RUNTIME_SHELL_ENV_KEYS = {"PYTHONPATH"}
_RUNTIME_SHELL_ENV_PREFIXES = ("OPC_",)
_PROMPT_SENTINEL = "-"
_TTY_EOF = b"\x04"
_INTERACTIVE_ARGV_PROMPT_MAX_BYTES = 16 * 1024
@@ -118,6 +120,64 @@ class CodexAdapter(ExternalAgentAdapter):
normalized = key.upper()
return normalized in cls._PARENT_CODEX_RUNTIME_ENV_VARS
@classmethod
def _runtime_shell_environment_config_args(
cls,
extra_env: dict[str, str] | None,
) -> tuple[list[str], list[str]]:
"""Forward only OpenOPC's runtime contract into Codex shell tools.
Codex can intentionally run with ``shell_environment_policy.inherit=core``.
The broker process still receives ``OPC_*`` variables, but commands launched
by Codex do not unless they are added to the policy's ``set`` table.
"""
forwarded: dict[str, str] = {}
for raw_key, raw_value in dict(extra_env or {}).items():
key = str(raw_key).strip()
if not key:
continue
if key not in cls._RUNTIME_SHELL_ENV_KEYS and not key.startswith(
cls._RUNTIME_SHELL_ENV_PREFIXES
):
continue
value = str(raw_value)
if key == "OPC_ALLOWED_COLLAB_TOOLS":
try:
parsed = json.loads(value)
except json.JSONDecodeError:
parsed = None
if isinstance(parsed, list):
value = ",".join(
str(item).strip() for item in parsed if str(item).strip()
)
forwarded[key] = value
args: list[str] = []
for key in sorted(forwarded):
value = forwarded[key]
if "'''" in value:
encoded = json.dumps(value, ensure_ascii=False)
else:
encoded = f"'''{value}'''"
args.extend(["-c", f"shell_environment_policy.set.{key}={encoded}"])
return args, sorted(forwarded)
@classmethod
def _inject_runtime_shell_environment(
cls,
cmd: list[str],
extra_env: dict[str, str] | None,
launch_metadata: dict[str, Any] | None = None,
) -> list[str]:
config_args, forwarded_keys = cls._runtime_shell_environment_config_args(extra_env)
if not config_args or not cmd:
return list(cmd)
insert_at = 2 if len(cmd) > 1 and str(cmd[1]).strip() == "exec" else 1
launch_cmd = [*cmd[:insert_at], *config_args, *cmd[insert_at:]]
if isinstance(launch_metadata, dict):
launch_metadata["runtime_shell_environment_keys"] = forwarded_keys
return launch_cmd
def build_workspace_args(self, workspace_path: str | None = None) -> list[str]:
args: list[str] = []
if workspace_path:
@@ -564,8 +624,13 @@ class CodexAdapter(ExternalAgentAdapter):
prompt_transport = str((launch_metadata or {}).get("prompt_transport") or "").strip().lower()
prompt = self._prompt_text_from_task(task) if prompt_transport == "stdin" else ""
env = self.build_process_env(extra_env)
launch_cmd = self._resolve_launch_command(
runtime_cmd = self._inject_runtime_shell_environment(
cmd,
extra_env,
launch_metadata=launch_metadata,
)
launch_cmd = self._resolve_launch_command(
runtime_cmd,
extra_env=extra_env,
launch_metadata=launch_metadata,
)
+99 -37
View File
@@ -92,11 +92,13 @@ class ExternalAgentBroker:
approval_engine: ApprovalEngine,
task_preparer: Callable[[Task], Coroutine[Any, Any, Task]] | None = None,
communication: CommunicationManager | None = None,
org_engine: Any | None = None,
) -> None:
self.store = store
self.approval_engine = approval_engine
self.task_preparer = task_preparer
self.communication = communication
self.org_engine = org_engine
@staticmethod
def _normalize_external_agent_choice(value: Any) -> str:
@@ -137,19 +139,19 @@ class ExternalAgentBroker:
)
return selected
async def _provider_stream_token_allows_resume(
async def _stored_provider_token_allows_resume(
self,
*,
adapter: ExternalAgentAdapter,
task: Task,
role_session_id: str,
token: str,
) -> bool:
"""Cross-check an early stream token against its latest run status."""
) -> bool | None:
"""Return the latest durable resumability verdict for one provider token."""
list_sessions = getattr(self.store, "list_external_sessions", None)
if not callable(list_sessions):
return False
return None
project_id = str(task.project_id or "default").strip() or "default"
kwargs: dict[str, Any] = {"project_id": project_id, "limit": 100}
if role_session_id:
@@ -160,19 +162,30 @@ class ExternalAgentBroker:
sessions = await list_sessions(**kwargs)
except Exception:
logger.opt(exception=True).debug(
"External resume restore: provider-stream status lookup failed"
"External resume restore: provider-token status lookup failed"
)
return False
for session in sessions:
if str(getattr(session, "agent_type", "") or "").strip() != adapter.agent_type:
continue
if external_session_matches_provider_token(session, token):
return (
external_session_allows_resume(session)
and str(getattr(session, "status", "") or "").strip().lower()
in {"done", "suspended"}
)
return False
return None
matching = [
session
for session in sessions
if str(getattr(session, "agent_type", "") or "").strip()
== adapter.agent_type
and external_session_matches_provider_token(session, token)
]
if not matching:
return None
selected, selected_token = select_best_external_resume_session(
matching,
agent_type=adapter.agent_type,
project_id=project_id,
)
return bool(
selected is not None
and selected_token == token
and external_session_allows_resume(selected)
and str(getattr(selected, "status", "") or "").strip().lower()
in {"done", "suspended"}
)
@classmethod
def _task_explicitly_selected_external_agent(cls, task: Task, agent_type: str) -> bool:
@@ -474,9 +487,12 @@ class ExternalAgentBroker:
return
if str(getattr(config, "session_mode", "") or "").strip().lower() == "new":
return
# Respect already-configured resume state.
if str(getattr(config, "session_mode", "") or "").strip().lower() == "resume" and getattr(config, "session_id", ""):
return
configured_session_token = (
str(getattr(config, "session_id", "") or "").strip()
if str(getattr(config, "session_mode", "") or "").strip().lower()
== "resume"
else ""
)
store = getattr(self, "store", None)
if store is None or not hasattr(store, "get_external_session"):
@@ -494,7 +510,7 @@ class ExternalAgentBroker:
# Fix 5 PR6: canonical source is ``role_runtime_session.adapter_session_state[agent_type]``.
# Check it first; the ExternalSession table is a compatibility
# fallback for legacy rows written before PR6 landed.
session_token = ""
session_token = configured_session_token
if role_session_id and hasattr(store, "get_role_session_adapter_state"):
try:
entry = await store.get_role_session_adapter_state(
@@ -507,28 +523,29 @@ class ExternalAgentBroker:
)
entry = None
if isinstance(entry, dict):
session_token = str(
role_session_token = str(
entry.get("resume_session_id")
or entry.get("provider_session_id")
or ""
).strip()
if not is_provider_session_token(
session_token,
role_session_token,
agent_type=adapter.agent_type,
project_id=project_id,
):
session_token = ""
if (
session_token
and str(entry.get("source", "") or "").strip()
== "provider_stream"
and not await self._provider_stream_token_allows_resume(
role_session_token = ""
session_token = session_token or role_session_token
token_allows_resume = (
await self._stored_provider_token_allows_resume(
adapter=adapter,
task=task,
role_session_id=role_session_id,
token=session_token,
)
):
if session_token
else None
)
if session_token and token_allows_resume is False:
session_token = ""
clear_role_state = getattr(
store,
@@ -544,8 +561,23 @@ class ExternalAgentBroker:
)
except Exception:
logger.opt(exception=True).debug(
"External resume restore: stale provider-stream token clear failed"
"External resume restore: stale provider token clear failed"
)
if hasattr(config, "session_mode"):
config.session_mode = "new"
if hasattr(config, "session_id"):
config.session_id = ""
task.metadata = dict(task.metadata or {})
task.metadata.pop("external_resume_session_id", None)
task.metadata.pop("external_resume_session_scope_id", None)
task.metadata.pop("external_resume_agent_type", None)
task.metadata["external_resume_fallback"] = (
"provider_terminal_failure"
)
if on_progress:
await on_progress(
f"[External resume] {adapter.agent_type} skipped prior failed session"
)
# Do not immediately rediscover the same unfinalized or
# failed stream row through the compatibility fallback.
return
@@ -2552,20 +2584,34 @@ class ExternalAgentBroker:
and hasattr(self.store, "get_role_session_adapter_state")
and hasattr(self.store, "update_role_session_adapter_state")
):
# A stream token is durable early so Stop can retain it. A normal
# terminal failure, however, must not leave that attempt's token
# pinned for a later unrelated turn.
# A stream token is durable early so Stop can retain it. A normal
# terminal failure must clear both a token discovered by this task
# and an older role token that this failed attempt resumed.
try:
current = await self.store.get_role_session_adapter_state(
role_session_id,
adapter.agent_type,
)
current_token = ""
if isinstance(current, dict):
current_token = str(
current.get("resume_session_id")
or current.get("provider_session_id")
or ""
).strip()
failed_token = str(
resume_session_id
or provider_session_id
or getattr(adapter.config, "session_id", "")
or ""
).strip()
if (
isinstance(current, dict)
and str(current.get("last_task_id", "") or "").strip()
== str(task.id or "").strip()
and str(current.get("source", "") or "").strip()
== "provider_stream"
and (
str(current.get("last_task_id", "") or "").strip()
== str(task.id or "").strip()
or bool(failed_token and current_token == failed_token)
)
):
await self.store.update_role_session_adapter_state(
role_session_id,
@@ -2576,3 +2622,19 @@ class ExternalAgentBroker:
logger.opt(exception=True).debug(
"Failed to clear provider-stream role state after terminal failure"
)
if result.status != TaskStatus.DONE:
failed_token = str(
resume_session_id
or provider_session_id
or getattr(adapter.config, "session_id", "")
or ""
).strip()
task_token = str(
(task.metadata or {}).get("external_resume_session_id", "") or ""
).strip()
if failed_token and task_token == failed_token:
task.metadata = dict(task.metadata or {})
task.metadata.pop("external_resume_session_id", None)
task.metadata.pop("external_resume_session_scope_id", None)
task.metadata.pop("external_resume_agent_type", None)
task.metadata["external_resume_fallback"] = "provider_terminal_failure"
+39 -10
View File
@@ -61,6 +61,23 @@ def provider_token_from_external_session(
) -> str:
if not external_session_allows_resume(session):
return ""
return _provider_token_from_session_identity(
session,
agent_type=agent_type,
project_id=project_id,
)
def _provider_token_from_session_identity(
session: Any | None,
*,
agent_type: str,
project_id: str,
) -> str:
"""Extract a provider token without treating its row as resumable."""
if session is None:
return ""
metadata = dict(getattr(session, "metadata", {}) or {})
for candidate in (
metadata.get("resume_session_id"),
@@ -108,7 +125,7 @@ def select_best_external_resume_session(
) -> tuple[Any | None, str]:
"""Select the newest valid provider capability, ignoring placeholders."""
valid: list[tuple[Any, str]] = []
latest_by_token: dict[str, Any] = {}
normalized_agent = str(agent_type or "").strip()
for session in list(sessions or []):
if (
@@ -116,23 +133,35 @@ def select_best_external_resume_session(
!= normalized_agent
):
continue
token = provider_token_from_external_session(
token = _provider_token_from_session_identity(
session,
agent_type=normalized_agent,
project_id=project_id,
)
if token:
valid.append((session, token))
if not token:
continue
current = latest_by_token.get(token)
if current is None or _session_timestamp(session) > _session_timestamp(current):
latest_by_token[token] = session
valid = [
(session, token)
for token, session in latest_by_token.items()
if external_session_allows_resume(session)
]
if not valid:
return None, ""
def _sort_key(item: tuple[Any, str]) -> tuple[float, str]:
session, token = item
updated_at = getattr(session, "updated_at", None)
try:
timestamp = float(updated_at.timestamp())
except Exception:
timestamp = 0.0
return timestamp, token
return _session_timestamp(session), token
return max(valid, key=_sort_key)
def _session_timestamp(session: Any) -> float:
updated_at = getattr(session, "updated_at", None)
try:
return float(updated_at.timestamp())
except Exception:
return 0.0