impel-cli 0.20.34 → 0.20.36
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 +19 -0
- package/package.json +1 -1
- package/src/apps.js +1 -1
- package/src/commands/launch.js +7 -5
- package/src/desktopTasks.js +35 -13
- package/src/vendorCliBinaries.js +20 -0
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Release notes
|
|
2
2
|
|
|
3
|
+
## 0.20.36 — Restore Codex execution
|
|
4
|
+
|
|
5
|
+
- Keeps Codex 0.147's stable code-mode host enabled instead of overriding it
|
|
6
|
+
off, restoring filesystem, shell, and repository tools in `impel codex`.
|
|
7
|
+
- Launches ordinary tenant Codex sessions with unrestricted filesystem access
|
|
8
|
+
and no approval prompts by default while preserving read-only fixed-agent
|
|
9
|
+
profiles.
|
|
10
|
+
- Requires the reviewed macOS Codex install to include its separately signed
|
|
11
|
+
`codex-code-mode-host` companion before the CLI can launch it.
|
|
12
|
+
|
|
13
|
+
## 0.20.35 — Normalize the Claude Tasks destination
|
|
14
|
+
|
|
15
|
+
- Waits for Claude's native New row before cloning the Tasks destination,
|
|
16
|
+
preventing the earlier Home/Code switcher from leaking its Code glyph into
|
|
17
|
+
the injected control.
|
|
18
|
+
- Removes cloned vendor glyphs and their empty wrappers so Tasks renders with
|
|
19
|
+
exactly one board icon in both Claude modes.
|
|
20
|
+
- Rebuilds existing managed bundles onto the corrected navigation lifecycle.
|
|
21
|
+
|
|
3
22
|
## 0.20.34 — Stabilize desktop Tasks navigation
|
|
4
23
|
|
|
5
24
|
- Places Tasks immediately after Claude's persistent Home/Code switcher in both
|
package/package.json
CHANGED
package/src/apps.js
CHANGED
|
@@ -299,7 +299,7 @@ export const CURRENT_CONFIG_VERSION = 32;
|
|
|
299
299
|
// — which is what made every `impel update` re-trigger macOS permission
|
|
300
300
|
// prompts. Bump this ONLY when a code change alters the bytes of a built
|
|
301
301
|
// bundle; leave it alone for changes that don't touch bundle contents.
|
|
302
|
-
export const BUNDLE_BUILD_FINGERPRINT = "bundle-2026-08-09.
|
|
302
|
+
export const BUNDLE_BUILD_FINGERPRINT = "bundle-2026-08-09.4";
|
|
303
303
|
|
|
304
304
|
/** Parse the tenant's install manifest, or null when absent/corrupt. */
|
|
305
305
|
export function readTenantManifest(homeDir = os.homedir(), tenantId = null) {
|
package/src/commands/launch.js
CHANGED
|
@@ -70,13 +70,14 @@ export const IMPEL_CODEX_PARENT_DELEGATION_INSTRUCTIONS =
|
|
|
70
70
|
`${IMPEL_CODEX_SPECIALIST_DELEGATION_INSTRUCTIONS} ${IMPEL_CUSTOM_AGENT_VERBATIM_RELAY_APPENDIX}`;
|
|
71
71
|
|
|
72
72
|
const IMPEL_CODEX_RUNTIME_OVERRIDES = [
|
|
73
|
-
// Codex
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
"features.code_mode_host=false",
|
|
73
|
+
// Codex 0.147 fails closed when a model selects code mode while this stable
|
|
74
|
+
// feature is disabled. The reviewed standalone install includes the signed
|
|
75
|
+
// companion host, so keep the execution path enabled for Impel sessions.
|
|
76
|
+
"features.code_mode_host=true",
|
|
78
77
|
];
|
|
79
78
|
|
|
79
|
+
const IMPEL_CODEX_UNRESTRICTED_ARGUMENT = "--dangerously-bypass-approvals-and-sandbox";
|
|
80
|
+
|
|
80
81
|
export function impelLaunchArguments(tool, argv, { codexAgentProfile = null } = {}) {
|
|
81
82
|
if (!RUNTIME_BRAND.features.agents) return [...argv];
|
|
82
83
|
if (tool === "claude") {
|
|
@@ -89,6 +90,7 @@ export function impelLaunchArguments(tool, argv, { codexAgentProfile = null } =
|
|
|
89
90
|
...(codexAgentProfile ? ["--profile", codexAgentProfile] : [
|
|
90
91
|
"-c",
|
|
91
92
|
`developer_instructions=${JSON.stringify(IMPEL_CODEX_PARENT_DELEGATION_INSTRUCTIONS)}`,
|
|
93
|
+
IMPEL_CODEX_UNRESTRICTED_ARGUMENT,
|
|
92
94
|
]),
|
|
93
95
|
...IMPEL_CODEX_RUNTIME_OVERRIDES.flatMap((override) => ["-c", override]),
|
|
94
96
|
...argv,
|
package/src/desktopTasks.js
CHANGED
|
@@ -7,7 +7,7 @@ export const DESKTOP_TASKS_RESOURCE_URI = "ui://impel/tasks/v1/index.html";
|
|
|
7
7
|
// position immediately before Pull requests.
|
|
8
8
|
export const DESKTOP_TASKS_NAV_ANCHOR_RULES = Object.freeze([
|
|
9
9
|
{ pattern: "^pull requests?\\b", position: "before" },
|
|
10
|
-
{ pattern: "^code\\b", position: "after", template: "
|
|
10
|
+
{ pattern: "^code\\b", position: "after", template: "\\bnew\\b" },
|
|
11
11
|
{ pattern: "^(?:start\\s+)?new\\s+(?:chat|thread)\\b", position: "before" },
|
|
12
12
|
{ pattern: "^new\\b", position: "before" },
|
|
13
13
|
{ pattern: "^scheduled\\b", position: "before" },
|
|
@@ -184,26 +184,44 @@ const NAVIGATION_SOURCE = String.raw`(() => {
|
|
|
184
184
|
element.querySelectorAll("kbd, [data-slot=\"shortcut\"]").forEach((candidate) => candidate.remove());
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
+
const stripTemplateGlyphs = (element) => {
|
|
188
|
+
element.querySelectorAll("svg, [aria-hidden=\"true\"]").forEach((candidate) => candidate.remove());
|
|
189
|
+
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
|
|
190
|
+
const glyphs = [];
|
|
191
|
+
while (walker.nextNode()) {
|
|
192
|
+
if (/^(?:\+|+|<\/>|<>)$/u.test((walker.currentNode.nodeValue || "").trim())) {
|
|
193
|
+
glyphs.push(walker.currentNode);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
glyphs.forEach((candidate) => {
|
|
197
|
+
const parent = candidate.parentElement;
|
|
198
|
+
candidate.remove();
|
|
199
|
+
if (
|
|
200
|
+
parent
|
|
201
|
+
&& parent !== element
|
|
202
|
+
&& !parent.textContent?.trim()
|
|
203
|
+
&& !parent.querySelector("svg, img")
|
|
204
|
+
) parent.remove();
|
|
205
|
+
});
|
|
206
|
+
[...element.querySelectorAll("*")].reverse().forEach((candidate) => {
|
|
207
|
+
if (
|
|
208
|
+
!candidate.textContent?.trim()
|
|
209
|
+
&& !candidate.querySelector("svg, img, input")
|
|
210
|
+
) candidate.remove();
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
187
214
|
const makeNav = (template) => {
|
|
188
215
|
const button = template ? template.cloneNode(true) : document.createElement("button");
|
|
189
216
|
stripVendorActions(button);
|
|
217
|
+
stripTemplateGlyphs(button);
|
|
190
218
|
button.id = NAV_ID;
|
|
191
219
|
button.type = "button";
|
|
192
220
|
button.setAttribute("aria-label", "Tasks");
|
|
193
221
|
button.setAttribute("title", "Tasks");
|
|
194
222
|
button.classList.add("impel-desktop-tasks-nav");
|
|
195
223
|
if (!replaceText(button)) button.textContent = "Tasks";
|
|
196
|
-
|
|
197
|
-
if (icon) {
|
|
198
|
-
icon.setAttribute("viewBox", "0 0 24 24");
|
|
199
|
-
icon.setAttribute("fill", "none");
|
|
200
|
-
icon.setAttribute("stroke", "currentColor");
|
|
201
|
-
icon.setAttribute("stroke-width", "2");
|
|
202
|
-
icon.setAttribute("stroke-linecap", "round");
|
|
203
|
-
icon.setAttribute("stroke-linejoin", "round");
|
|
204
|
-
icon.innerHTML = '<rect x="3" y="3" width="18" height="18" rx="2"></rect><path d="M9 3v18"></path><path d="M15 3v18"></path>';
|
|
205
|
-
}
|
|
206
|
-
else button.insertAdjacentHTML("afterbegin", TASKS_ICON);
|
|
224
|
+
button.insertAdjacentHTML("afterbegin", TASKS_ICON);
|
|
207
225
|
button.addEventListener("click", (event) => {
|
|
208
226
|
event.preventDefault();
|
|
209
227
|
event.stopPropagation();
|
|
@@ -245,8 +263,12 @@ const NAVIGATION_SOURCE = String.raw`(() => {
|
|
|
245
263
|
break;
|
|
246
264
|
}
|
|
247
265
|
}
|
|
248
|
-
const template = anchorRule?.template ? findControl(anchorRule.template)
|
|
266
|
+
const template = anchorRule?.template ? findControl(anchorRule.template) : anchor;
|
|
249
267
|
lastAnchor = anchor;
|
|
268
|
+
// Claude mounts its Home/Code switcher before the New row. Do not clone the
|
|
269
|
+
// switcher as a temporary fallback: its Code glyph would remain in the
|
|
270
|
+
// injected control after the intended visual template appears.
|
|
271
|
+
if (!anchor || !template) return;
|
|
250
272
|
if (!nav?.isConnected) nav = makeNav(template);
|
|
251
273
|
const target = placement(anchor);
|
|
252
274
|
const templateTarget = placement(template);
|
package/src/vendorCliBinaries.js
CHANGED
|
@@ -38,6 +38,7 @@ export function verifyReviewedMacVendorCli(
|
|
|
38
38
|
{
|
|
39
39
|
run = spawnSync,
|
|
40
40
|
realpath = fs.realpathSync,
|
|
41
|
+
stat = fs.statSync,
|
|
41
42
|
versions = PINNED_VENDOR_CLI_VERSIONS,
|
|
42
43
|
signingTeams = MAC_VENDOR_SIGNING_TEAMS,
|
|
43
44
|
environmentPrefix = "IMPEL",
|
|
@@ -61,6 +62,25 @@ export function verifyReviewedMacVendorCli(
|
|
|
61
62
|
if (version !== versions[tool]) return false;
|
|
62
63
|
|
|
63
64
|
const resolved = realpath(binary);
|
|
65
|
+
if (tool === "codex") {
|
|
66
|
+
const codeModeHost = path.join(path.dirname(resolved), "codex-code-mode-host");
|
|
67
|
+
if (!stat(codeModeHost).isFile()) return false;
|
|
68
|
+
const helperVerified = run("/usr/bin/codesign", ["--verify", "--strict", codeModeHost], {
|
|
69
|
+
encoding: "utf8",
|
|
70
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
71
|
+
timeout: 15_000,
|
|
72
|
+
});
|
|
73
|
+
if (helperVerified?.status !== 0 || helperVerified?.error) return false;
|
|
74
|
+
const helperDetails = run("/usr/bin/codesign", ["-dv", "--verbose=4", codeModeHost], {
|
|
75
|
+
encoding: "utf8",
|
|
76
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
77
|
+
timeout: 15_000,
|
|
78
|
+
});
|
|
79
|
+
if (helperDetails?.status !== 0
|
|
80
|
+
|| !String(helperDetails.stderr || helperDetails.stdout || "").includes(`TeamIdentifier=${signingTeams[tool]}`)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
64
84
|
const verified = run("/usr/bin/codesign", ["--verify", "--strict", resolved], {
|
|
65
85
|
encoding: "utf8",
|
|
66
86
|
stdio: ["ignore", "pipe", "pipe"],
|