@oneciel-ai/ciel-runtime 0.2.38 → 0.2.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/ciel_runtime_support/managed_tool_injection.py +53 -5
- package/ciel_runtime_support/runtime_constants.py +1 -1
- package/ciel_runtime_support/runtime_launch.py +10 -2
- package/docs/journal/2026/09/07/fixes/codex/native-web-transport.okf +39 -0
- package/docs/journal/2026/09/07/release/stable/0.2.39.okf +10 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ capability, followed by the complete commit ledger merged into each release.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.2.39 — 2026-09-07
|
|
9
|
+
|
|
10
|
+
- Fix native Codex startup failing with `invalid transport` when DuckDuckGo or
|
|
11
|
+
web_fetch is not registered. Inspect the effective workspace configuration
|
|
12
|
+
before adding process-only disabling overrides; never modify global or
|
|
13
|
+
workspace TOML. Concurrent non-native sessions retain their MCP settings.
|
|
14
|
+
|
|
8
15
|
## 0.2.38 — 2026-09-07
|
|
9
16
|
|
|
10
17
|
- Disable inherited DuckDuckGo and web_fetch MCP servers with per-launch
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
"""Launch-mode policy for Ciel-owned tools, never user MCP definitions."""
|
|
2
2
|
from collections.abc import Mapping
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import subprocess
|
|
7
|
+
from subprocess import run as run_codex_config_probe
|
|
3
8
|
from typing import Any
|
|
4
9
|
|
|
5
10
|
|
|
@@ -9,14 +14,57 @@ def should_inject_tool(*, native: bool, mode: str = "always") -> bool:
|
|
|
9
14
|
return mode == "always" or (mode == "native") == native
|
|
10
15
|
|
|
11
16
|
|
|
12
|
-
def codex_native_web_tool_overrides(
|
|
17
|
+
def codex_native_web_tool_overrides(
|
|
18
|
+
*, native: bool, passthrough: list[str] | None = None,
|
|
19
|
+
env: dict[str, str] | None = None, cwd: Path | None = None,
|
|
20
|
+
codex: str = "codex",
|
|
21
|
+
) -> list[str]:
|
|
13
22
|
"""Disable inherited replacement web MCPs for this launch, not on disk."""
|
|
14
23
|
if not native:
|
|
15
24
|
return []
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
# An enabled-only table is NOT a valid Codex MCP transport, even when
|
|
26
|
+
# disabled. Never manufacture such a table on a fresh installation.
|
|
27
|
+
# Ask the same executable to resolve its effective configuration. Merely
|
|
28
|
+
# scanning project TOML is unsafe: Codex can ignore untrusted projects,
|
|
29
|
+
# which would turn our enabled override into another transport-less table.
|
|
30
|
+
# `mcp list` reads configuration; it does not connect to MCP servers.
|
|
31
|
+
arguments = passthrough or []
|
|
32
|
+
configuration_args = []
|
|
33
|
+
index = 0
|
|
34
|
+
while index < len(arguments):
|
|
35
|
+
argument = arguments[index]
|
|
36
|
+
if argument == "--":
|
|
37
|
+
break
|
|
38
|
+
if argument in ("-c", "--config", "-p", "--profile", "-C", "--cd") and index + 1 < len(arguments):
|
|
39
|
+
configuration_args.extend([argument, arguments[index + 1]])
|
|
40
|
+
index += 1
|
|
41
|
+
elif argument.startswith(("--config=", "--profile=", "--cd=")):
|
|
42
|
+
configuration_args.append(argument)
|
|
43
|
+
index += 1
|
|
44
|
+
try:
|
|
45
|
+
completed = run_codex_config_probe(
|
|
46
|
+
[codex, *configuration_args, "mcp", "list", "--json"],
|
|
47
|
+
env=env, cwd=cwd, capture_output=True, text=True, encoding="utf-8",
|
|
48
|
+
errors="replace", timeout=5, check=False,
|
|
49
|
+
)
|
|
50
|
+
if completed.returncode != 0:
|
|
51
|
+
raise ValueError("configuration probe failed")
|
|
52
|
+
entries = json.loads(completed.stdout)
|
|
53
|
+
if not isinstance(entries, list):
|
|
54
|
+
raise ValueError("unexpected MCP list shape")
|
|
55
|
+
except (OSError, subprocess.TimeoutExpired, ValueError):
|
|
56
|
+
# Never print probe output: MCP configuration can contain credentials.
|
|
57
|
+
logging.getLogger(__name__).warning(
|
|
58
|
+
"Could not inspect Codex MCP configuration; skipping native web MCP overrides"
|
|
59
|
+
)
|
|
60
|
+
return []
|
|
61
|
+
names = {entry.get("name") for entry in entries if isinstance(entry, dict)
|
|
62
|
+
and isinstance(entry.get("name"), str)}
|
|
63
|
+
result = []
|
|
64
|
+
for name in ("duckduckgo", "web_fetch"):
|
|
65
|
+
if name in names:
|
|
66
|
+
result.extend(["-c", f"mcp_servers.{name}.enabled=false"])
|
|
67
|
+
return result
|
|
20
68
|
|
|
21
69
|
|
|
22
70
|
def select_managed_tools(
|
|
@@ -927,7 +927,11 @@ def run_codex(
|
|
|
927
927
|
)
|
|
928
928
|
if workspace_mcp_launch is not None:
|
|
929
929
|
codex_mcp_compat_args.extend(workspace_mcp_launch.codex_args)
|
|
930
|
-
codex_mcp_compat_args.extend(codex_native_web_tool_overrides(
|
|
930
|
+
codex_mcp_compat_args.extend(codex_native_web_tool_overrides(
|
|
931
|
+
native=native_codex_enabled(provider),
|
|
932
|
+
codex=codex,
|
|
933
|
+
passthrough=[*codex_passthrough, *codex_mcp_compat_args], env=env, cwd=launch_cwd,
|
|
934
|
+
))
|
|
931
935
|
codex_yolo_args = codex_yolo_launch_args(codex_passthrough)
|
|
932
936
|
if not use_native_codex and not use_codex_routed:
|
|
933
937
|
env[CODEX_RUNTIME_API_KEY_ENV] = env.get(CODEX_RUNTIME_API_KEY_ENV) or "ciel-runtime-router-local-key"
|
|
@@ -1260,7 +1264,11 @@ def run_codex_app_server(
|
|
|
1260
1264
|
try:
|
|
1261
1265
|
if workspace_mcp_launch is not None:
|
|
1262
1266
|
codex_mcp_compat_args.extend(workspace_mcp_launch.codex_args)
|
|
1263
|
-
codex_mcp_compat_args.extend(codex_native_web_tool_overrides(
|
|
1267
|
+
codex_mcp_compat_args.extend(codex_native_web_tool_overrides(
|
|
1268
|
+
native=native_codex_enabled(provider),
|
|
1269
|
+
codex=codex,
|
|
1270
|
+
passthrough=[*passthrough, *config_args, *codex_mcp_compat_args], env=env, cwd=launch_cwd,
|
|
1271
|
+
))
|
|
1264
1272
|
config_args = [*config_args, *codex_mcp_compat_args]
|
|
1265
1273
|
listen_url = codex_app_server_default_listen_url()
|
|
1266
1274
|
app_server_args = codex_app_server_launch_args(
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
title: Codex native web MCP overrides without cross-session configuration writes
|
|
2
|
+
date: 2026-09-07
|
|
3
|
+
status: source fixed and locally verified; not installed or published
|
|
4
|
+
request:
|
|
5
|
+
symptom: Codex 0.153.4 fails with invalid transport in mcp_servers.duckduckgo.
|
|
6
|
+
isolation: Do not change global TOML; isolate workspace/provider sessions.
|
|
7
|
+
evidence:
|
|
8
|
+
reproduction:
|
|
9
|
+
environment: Real Windows codex-cli 0.153.4 with temporary empty CODEX_HOME.
|
|
10
|
+
arguments: -c mcp_servers.duckduckgo.enabled=false mcp list --json
|
|
11
|
+
exit_code: 1
|
|
12
|
+
stderr: "Error: failed to load bootstrap configuration; invalid transport in mcp_servers.duckduckgo"
|
|
13
|
+
cause: The unconditional native override creates an enabled-only server table without command or URL when the server is absent.
|
|
14
|
+
official_documentation: https://learn.chatgpt.com/docs/extend/mcp?surface=cli
|
|
15
|
+
documented_constraints: STDIO requires command; HTTP requires url; project configuration applies only to trusted projects.
|
|
16
|
+
implementation:
|
|
17
|
+
discovery: Run the same Codex executable's mcp list --json with the launch environment, cwd, and configuration arguments.
|
|
18
|
+
isolation: Apply enabled=false only in this process's arguments, only for servers in the effective list; no TOML writes.
|
|
19
|
+
workspace: Codex resolves workspace trust/configuration itself; no independent TOML parser or global edits.
|
|
20
|
+
native: Disable existing duckduckgo and web_fetch entries for CLI and app-server launches.
|
|
21
|
+
nonnative: No discovery process and no disabling overrides.
|
|
22
|
+
failure_policy: Five-second bounded probe; if unavailable/invalid, log a credential-free warning and skip overrides.
|
|
23
|
+
limitation: If discovery fails, replacement MCPs may remain enabled; this must not be described as successful suppression.
|
|
24
|
+
verification:
|
|
25
|
+
real_cli_command: "$env:CIEL_TEST_CODEX_EXE='C:/Users/djlov/AppData/Local/Programs/OpenAI/Codex/bin/codex.exe'; python -m unittest discover -s tests -p test_codex_native_web_cli.py -v"
|
|
26
|
+
real_cli_output: "Ran 4 tests in 0.667s; OK"
|
|
27
|
+
real_cli_cases:
|
|
28
|
+
empty_home: No overrides; mcp list exits 0 instead of invalid transport.
|
|
29
|
+
concurrent_shared_home_different_workspaces: native false/false; nonnative true/true for duckduckgo/web_fetch.
|
|
30
|
+
concurrent_shared_home_same_workspace: native false/false; nonnative true/true for duckduckgo/web_fetch.
|
|
31
|
+
file_integrity: Shared test config SHA256 unchanged; no workspace config created by override logic.
|
|
32
|
+
project_configuration: Trusted and untrusted project cases match Codex's effective server list; project TOML bytes unchanged.
|
|
33
|
+
generated_transport: Native disabled; nonnative enabled; no MCP connection needed.
|
|
34
|
+
policy_tests: "python -m unittest discover -s tests -p test_managed_tool_injection.py -v: Ran 9 tests; OK"
|
|
35
|
+
runtime_group: "python scripts/run_test_group.py runtime: Ran 280 tests; OK (skipped=12), real CLI checks enabled"
|
|
36
|
+
static_checks: py_compile successful; ruff All checks passed; git diff --check clean.
|
|
37
|
+
boundaries:
|
|
38
|
+
unchanged: Real user global/project TOML, active sessions, installation, npm registry, git remotes.
|
|
39
|
+
tested: Configuration loading and launch argument policy, not a paid model inference or remote user's TUI.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
title: Publish native Codex transport regression fix as stable 0.2.39
|
|
2
|
+
date: 2026-09-07
|
|
3
|
+
authorization: User requested continuing through main branch deployment.
|
|
4
|
+
version: 0.2.39
|
|
5
|
+
scope: Commit verified fix and version increment, push main, verify CI and npm latest package.
|
|
6
|
+
verification_plan:
|
|
7
|
+
local: Lint, isolated runtime tests, real Codex config-loader regression checks.
|
|
8
|
+
remote: Publish workflow runs all test groups before publishing.
|
|
9
|
+
artifact: Download published package and verify runtime version and fixed helper behavior.
|
|
10
|
+
exclusions: No user configuration edits or active session restart.
|
package/package.json
CHANGED