impel-cli 0.20.38 → 0.20.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.
@@ -445,10 +445,18 @@ function resumedHandleForState(state, incomingHandle) {
445
445
  function normalizeHandle(value) {
446
446
  if (value?.schema === NATIVE_AGENT_CONTINUATION_SCHEMA) {
447
447
  exactObject(value, ["schema", "invocationId"], "native-agent continuation");
448
- if (typeof value.invocationId !== "string" || !SAFE_INVOCATION_RE.test(value.invocationId)) {
449
- throw new Error("native-agent continuation invocationId is invalid");
448
+ // Minted ids are lowercase UUIDs; tolerate a case-drifting reserialization
449
+ // but nothing that changes the id's shape.
450
+ const invocationId = typeof value.invocationId === "string"
451
+ ? value.invocationId.toLowerCase()
452
+ : null;
453
+ if (!invocationId || !SAFE_INVOCATION_RE.test(invocationId)) {
454
+ throw new Error(
455
+ "native-agent continuation invocationId is invalid; pass the exact continuation object "
456
+ + "returned by the answer call, or call the answer tool again if none was returned",
457
+ );
450
458
  }
451
- return { ...value };
459
+ return { ...value, invocationId };
452
460
  }
453
461
  exactObject(value, [
454
462
  "schema",
@@ -1854,7 +1862,7 @@ export class NativeAgentCompositeTransport {
1854
1862
  }
1855
1863
  }
1856
1864
 
1857
- async answer(args, { signal } = {}) {
1865
+ async answer(args, { signal, onProgress } = {}) {
1858
1866
  throwIfAborted(signal);
1859
1867
  const attachment = boundedAttachmentSignal(signal, this.attachmentWindowMs);
1860
1868
  let state = null;
@@ -1880,6 +1888,7 @@ export class NativeAgentCompositeTransport {
1880
1888
  if (!lock) return continuationForState(state);
1881
1889
  const result = await this.attach(state, prepared, {
1882
1890
  signal: attachment.signal,
1891
+ onProgress,
1883
1892
  lock,
1884
1893
  });
1885
1894
  if (result?.schema === NATIVE_AGENT_RESULT_SCHEMA && result.status === "succeeded") {
@@ -111,16 +111,45 @@ export function findReviewedVendorCliBinary(
111
111
  {
112
112
  find = findNativeBinary,
113
113
  verify = verifyReviewedMacVendorCli,
114
+ realpath = fs.realpathSync,
115
+ stat = fs.statSync,
114
116
  } = {},
115
117
  ) {
116
118
  if (platform !== "darwin") return find(tool, environment, platform, environmentPrefix);
117
- return find(
118
- tool,
119
- environment,
120
- platform,
121
- environmentPrefix,
122
- (binary) => verify(tool, binary, environment, { environmentPrefix }),
123
- );
119
+ const accept = (binary) => verify(tool, binary, environment, { environmentPrefix });
120
+ const reviewed = find(tool, environment, platform, environmentPrefix, accept);
121
+ if (reviewed || tool !== "claude") return reviewed;
122
+ // An explicit override remains authoritative even while unusable: callers
123
+ // asked for exactly that binary, so never substitute another install.
124
+ const override = vendorOverrideName(tool, environmentPrefix);
125
+ if (override && environmentValue(environment, override)) return null;
126
+
127
+ // The standalone Claude installer keeps releases side by side under
128
+ // versions/<release> and its auto-updater only moves the launcher symlink.
129
+ // When the symlink drifts past the reviewed release, resolve the exact
130
+ // reviewed release directly instead of failing the launch; every candidate
131
+ // still passes the full version + signature + team verification.
132
+ const candidates = [];
133
+ const drifted = find(tool, environment, platform, environmentPrefix);
134
+ if (drifted) {
135
+ try {
136
+ candidates.push(path.join(path.dirname(realpath(drifted)), PINNED_VENDOR_CLI_VERSIONS.claude));
137
+ } catch {
138
+ // An unresolvable shim only forfeits the sibling candidate.
139
+ }
140
+ }
141
+ const home = environmentValue(environment, "HOME");
142
+ if (home) {
143
+ candidates.push(path.join(home, ".local", "share", "claude", "versions", PINNED_VENDOR_CLI_VERSIONS.claude));
144
+ }
145
+ for (const candidate of candidates) {
146
+ try {
147
+ if (stat(candidate).isFile() && accept(candidate)) return candidate;
148
+ } catch {
149
+ // A missing side-by-side release keeps resolution fail-closed.
150
+ }
151
+ }
152
+ return null;
124
153
  }
125
154
 
126
155
  /**
@@ -1,5 +1,13 @@
1
+ import { CODEX_NATIVE_AGENT_ATTACHMENT_WINDOW_MS } from "./selfInvocation.js";
2
+
1
3
  export const VERBATIM_RELAY_OPT_IN_MARKER = "verbatimRelay enabled";
2
4
 
5
+ // The parent's single blocking wait must outlast the Codex child's bounded
6
+ // native-agent attachment window or the parent's visible working span
7
+ // truncates while the child is still running. Deriving it keeps the two
8
+ // contracts linked when the window moves again.
9
+ export const VERBATIM_RELAY_PARENT_WAIT_MS = CODEX_NATIVE_AGENT_ATTACHMENT_WINDOW_MS + 20_000;
10
+
3
11
  export const VERBATIM_SPAWN_REQUIREMENT = 'fork_turns="none"';
4
12
 
5
13
  export const VERBATIM_FINAL_TEXT_CONSTRAINTS =
@@ -14,7 +22,7 @@ export function parentVerbatimRelayAppendix() {
14
22
  `When an explicit custom agent's catalog-derived description declares ${VERBATIM_RELAY_OPT_IN_MARKER}, ` +
15
23
  `spawn it with ${VERBATIM_SPAWN_REQUIREMENT} and relay its finalText verbatim with ${VERBATIM_FINAL_TEXT_CONSTRAINTS}; ` +
16
24
  "preserve Sources sections and citations exactly. Start one child, then use one blocking wait sized for the child budget; " +
17
- "on Codex, call wait_agent exactly once with timeout_ms=60000. Do not send follow-ups, short-poll the child, or synthesize while it is running. " +
25
+ `on Codex, call wait_agent exactly once with timeout_ms=${VERBATIM_RELAY_PARENT_WAIT_MS}. Do not send follow-ups, short-poll the child, or synthesize while it is running. ` +
18
26
  "Custom agents without that declaration keep the default delegation behavior."
19
27
  );
20
28
  }