impel-cli 0.20.60 → 0.20.62

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/RELEASE_NOTES.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Release notes
2
2
 
3
+ ## 0.20.62 — Silence the Codex apps connector in desktop profiles
4
+
5
+ - Persists `features.apps = false` in the managed ChatGPT desktop `config.toml`
6
+ so the hosted `codex_apps` connector no longer handshakes against the gateway
7
+ passthrough without a credential (HTTP 401 "MCP startup incomplete") when
8
+ the embedded Codex is launched from that profile. 0.20.61 applied this gate
9
+ only as a runtime override on `impel codex`; the desktop writer still set
10
+ `enable_mcp_apps=false` alone, which governs MCP-UI rendering and leaves the
11
+ connector enabled. Bumps the managed config version so existing installs
12
+ rewrite the profile.
13
+
14
+ ## 0.20.61 — Silence the Codex apps connector at startup
15
+
16
+ - Passes `features.apps=false` to tenant Codex CLI sessions so Codex no longer
17
+ contributes its hosted `codex_apps` connector, which handshaked against the
18
+ gateway passthrough without a credential and printed an HTTP 401 "MCP startup
19
+ incomplete" warning on every `impel codex` launch. The 0.20.59 mitigation set
20
+ `enable_mcp_apps=false`, which only governs MCP-UI rendering and left the
21
+ connector enabled.
22
+
3
23
  ## 0.20.60 — Fix managed Codex launch discovery
4
24
 
5
25
  - Fixes `impel codex` failing with "not authenticated and no enrolled managed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impel-cli",
3
- "version": "0.20.60",
3
+ "version": "0.20.62",
4
4
  "description": "Prepare isolated Claude and Codex workspaces for every accessible Impel tenant",
5
5
  "type": "module",
6
6
  "bin": {
package/src/apps.js CHANGED
@@ -1589,7 +1589,7 @@ function mergeManagedChatGPTToml(current, managed) {
1589
1589
  * as staleness so the profile heals immediately instead of waiting out the
1590
1590
  * manifest TTL.
1591
1591
  */
1592
- export function managedChatGPTConfigDrifted(paths) {
1592
+ export function managedChatGPTConfigDrifted(paths, platform = process.platform) {
1593
1593
  let current;
1594
1594
  try {
1595
1595
  current = fs.readFileSync(path.join(paths.chatgpt.codexHome, "config.toml"), "utf8");
@@ -1603,6 +1603,12 @@ export function managedChatGPTConfigDrifted(paths) {
1603
1603
  // out the refresh TTL. Configs from generations before the key existed are
1604
1604
  // merely stale (the manifest version bump rewrites them), never drift —
1605
1605
  // require it only once this install's manifest proves it was written.
1606
+ //
1607
+ // Only macOS demands the enabled value. The impel-apps profile generator
1608
+ // deliberately emits `false` off macOS, where no companion check proves
1609
+ // codex-code-mode-host shipped; requiring `true` there would flag every
1610
+ // generated Windows profile as drifted and regenerate it on each refresh.
1611
+ // Off macOS, require only that the key survives the vendor settings writer.
1606
1612
  let manifestConfigVersion = 0;
1607
1613
  try {
1608
1614
  manifestConfigVersion = Number(JSON.parse(
@@ -1612,8 +1618,11 @@ export function managedChatGPTConfigDrifted(paths) {
1612
1618
  // Without a readable manifest the version gate stays closed.
1613
1619
  }
1614
1620
  const featuresTable = current.match(/^\[features\]\n(?:[^[\n][^\n]*\n|\n)*/mu)?.[0] || "";
1621
+ const requiredCodeModeHost = platform === "darwin"
1622
+ ? /^code_mode_host = true$/mu
1623
+ : /^code_mode_host = (?:true|false)$/mu;
1615
1624
  const featureKeysDropped = manifestConfigVersion >= 35
1616
- && !/^code_mode_host = true$/mu.test(featuresTable);
1625
+ && !requiredCodeModeHost.test(featuresTable);
1617
1626
  return !current.includes(CHATGPT_CONFIG_START)
1618
1627
  || readTopLevelTomlString(current, "model_provider") !== RUNTIME_BRAND.cli.providerId
1619
1628
  || !readTopLevelTomlString(current, "chatgpt_base_url")
@@ -169,17 +169,26 @@ export function enableManagedCodexDesktopCodeModeHost(
169
169
  "true",
170
170
  configPath,
171
171
  );
172
- // Managed desktop profiles do not ship the native Codex Apps companion and
173
- // must not eagerly initialize the vendor `codex_apps` MCP client. That
174
- // client expects OpenAI account credentials, while Impel routes inference
175
- // through the gateway and intentionally has no native account token.
176
- return upsertManagedScalar(
172
+ // Codex contributes the hosted `codex_apps` connector whenever the stable
173
+ // `apps` feature is on. It handshakes against chatgpt_base_url with the
174
+ // native OpenAI account credential, which a gateway-routed profile does not
175
+ // have, so the gateway answers HTTP 401 at every startup. `enable_mcp_apps`
176
+ // only governs MCP-UI rendering and does not gate the connector; keep it
177
+ // off as well since the managed desktop never renders apps.
178
+ const withoutMcpApps = upsertManagedScalar(
177
179
  withCodeModeHost,
178
180
  "features",
179
181
  "enable_mcp_apps",
180
182
  "false",
181
183
  configPath,
182
184
  );
185
+ return upsertManagedScalar(
186
+ withoutMcpApps,
187
+ "features",
188
+ "apps",
189
+ "false",
190
+ configPath,
191
+ );
183
192
  }
184
193
 
185
194
  function assertSafeManagedPath(target, expectedType) {
@@ -79,20 +79,37 @@ export const IMPEL_CODEX_SPECIALIST_DELEGATION_INSTRUCTIONS =
79
79
  export const IMPEL_CODEX_PARENT_DELEGATION_INSTRUCTIONS =
80
80
  `${IMPEL_CODEX_SPECIALIST_DELEGATION_INSTRUCTIONS} ${IMPEL_CUSTOM_AGENT_VERBATIM_RELAY_APPENDIX}`;
81
81
 
82
- const IMPEL_CODEX_RUNTIME_OVERRIDES = [
83
- // The standalone companion is optional and is not shipped by every native
84
- // Codex distribution (notably some Windows/macOS CLI packages). Disable the
85
- // launcher path for tenant CLI sessions so a missing helper cannot abort
86
- // startup. Desktop bundles that include the helper enable it explicitly.
87
- "features.code_mode_host=false",
88
- // Headless CLI sessions do not render MCP Apps. Disabling the connector
89
- // avoids an eager codex_apps initialize against the vendor gateway, which
90
- // otherwise fails with HTTP 401 when no native account credential exists.
91
- "features.enable_mcp_apps=false",
92
- // CLI profiles do not load desktop/plugin lifecycle bundles. Plugin hooks
93
- // are user-layer code and newer Codex versions review every one at startup.
94
- "features.plugins=false",
95
- ];
82
+ function impelCodexRuntimeOverrides(platform) {
83
+ return [
84
+ // Pinned Codex ships `code_mode_host` as a stable, default-on feature and
85
+ // fails closed when a code_mode_only model is selected while it is off —
86
+ // which is every 5.6-family model in the managed catalog. The flag is
87
+ // therefore derived from the platform rather than pinned to one value: the
88
+ // two failure modes it sits between are platform-specific, and forcing
89
+ // either answer onto both platforms regresses the other.
90
+ //
91
+ // macOS: resolveReviewedVendorCliBinary already refuses to launch a Codex
92
+ // whose codex-code-mode-host companion is missing, unsigned, or from the
93
+ // wrong team (see verifyReviewedMacVendorCli in ../vendorCliBinaries.js).
94
+ // Reaching launch proves the helper is present, so disabling the feature is
95
+ // pure loss.
96
+ //
97
+ // Other platforms: verifyReviewedWindowsVendorCli gates on version only and
98
+ // cannot prove the companion shipped, so keep the feature off rather than
99
+ // risk aborting startup on a distribution that omits it.
100
+ `features.code_mode_host=${platform === "darwin" ? "true" : "false"}`,
101
+ // Codex contributes the hosted codex_apps connector whenever the stable
102
+ // `apps` feature is on. It handshakes against chatgpt_base_url with no
103
+ // gateway credential, so headless tenant sessions get an HTTP 401 at
104
+ // startup. `enable_mcp_apps` only governs MCP-UI rendering and does not
105
+ // gate the connector; keep it off as well since the CLI never renders apps.
106
+ "features.apps=false",
107
+ "features.enable_mcp_apps=false",
108
+ // CLI profiles do not load desktop/plugin lifecycle bundles. Plugin hooks
109
+ // are user-layer code and newer Codex versions review every one at startup.
110
+ "features.plugins=false",
111
+ ];
112
+ }
96
113
 
97
114
  const IMPEL_CODEX_UNRESTRICTED_ARGUMENT = "--dangerously-bypass-approvals-and-sandbox";
98
115
  const IMPEL_CLAUDE_MANAGED_AGENT_ARGUMENTS = [
@@ -109,6 +126,7 @@ const IMPEL_CLAUDE_MANAGED_AGENT_ARGUMENTS = [
109
126
  export function impelLaunchArguments(tool, argv, {
110
127
  claudeManagedAgent = null,
111
128
  codexAgentProfile = null,
129
+ platform = process.platform,
112
130
  } = {}) {
113
131
  if (!RUNTIME_BRAND.features.agents) return [...argv];
114
132
  if (tool === "claude") {
@@ -169,7 +187,7 @@ export function impelLaunchArguments(tool, argv, {
169
187
  `developer_instructions=${JSON.stringify(IMPEL_CODEX_PARENT_DELEGATION_INSTRUCTIONS)}`,
170
188
  IMPEL_CODEX_UNRESTRICTED_ARGUMENT,
171
189
  ]),
172
- ...IMPEL_CODEX_RUNTIME_OVERRIDES.flatMap((override) => ["-c", override]),
190
+ ...impelCodexRuntimeOverrides(platform).flatMap((override) => ["-c", override]),
173
191
  ...argv,
174
192
  ];
175
193
  }
@@ -14,4 +14,7 @@
14
14
  // reasserting the FALLBACK_MODELS floor, records provenance in
15
15
  // models-manifest.json, and (with cross-app models enabled) routes the CLI
16
16
  // provider through the experimental OpenAI-compatible gateway path.
17
- export const CURRENT_CONFIG_VERSION = 46;
17
+ // v47 persists `features.apps = false` in the managed ChatGPT desktop profile
18
+ // so the hosted codex_apps connector stops handshaking against the gateway
19
+ // without a credential (the same gate 0.20.61 passed to CLI sessions).
20
+ export const CURRENT_CONFIG_VERSION = 47;