@4xeoz/re-entry 0.2.16 → 0.2.17

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/README.md CHANGED
@@ -132,7 +132,10 @@ npx --yes --package=@4xeoz/re-entry re-entry test "Reply with: Re-entry is worki
132
132
  ```
133
133
 
134
134
  This starts one fresh local Codex process through the same adapter seam used by real deliveries. It
135
- does not create a Grant, claim Receiver work, or prove the browser/WebMCP return path.
135
+ forwards Codex output when run in an interactive terminal, so the smoke test behaves like the
136
+ underlying direct `codex exec` command. It does not create a Grant, claim Receiver work, or prove a
137
+ Desktop UI thread, browser, or WebMCP return path. If it times out, run the equivalent direct
138
+ `codex exec` command to inspect Codex's own output; the test does not contact the Receiver.
136
139
 
137
140
  To pause or remove the local Connector:
138
141
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4xeoz/re-entry",
3
- "version": "0.2.16",
3
+ "version": "0.2.17",
4
4
  "type": "module",
5
5
  "description": "Outbound Local Connector process for Re-entry Core; uses the Cloud Receiver v2 preview by default with an explicit override for other accepted origins.",
6
6
  "publishConfig": {
@@ -59,6 +59,7 @@ export function createCodexExecAdapter(options) {
59
59
  executable,
60
60
  workingDirectory,
61
61
  prompt: buildContinuationPrompt(activation),
62
+ stdio: ["ignore", "ignore", "ignore"],
62
63
  commandTimeoutMs,
63
64
  spawnCommand,
64
65
  });
@@ -79,7 +80,7 @@ export function createCodexExecAdapter(options) {
79
80
  export async function runCodexPrompt(options) {
80
81
  requireExactRecord(
81
82
  options,
82
- ["workingDirectory", "prompt", "executable", "commandTimeoutMs", "spawnCommand"],
83
+ ["workingDirectory", "prompt", "executable", "commandTimeoutMs", "spawnCommand", "stdio"],
83
84
  ["workingDirectory", "prompt"],
84
85
  "Codex prompt options",
85
86
  );
@@ -93,7 +94,8 @@ export async function runCodexPrompt(options) {
93
94
  if (typeof spawnCommand !== "function") {
94
95
  throw new TypeError("Codex prompt spawnCommand must be a function");
95
96
  }
96
- await runCodexExec({ executable, workingDirectory, prompt, timeoutMs, spawnCommand });
97
+ const stdio = requireStdio(options.stdio ?? "inherit");
98
+ await runCodexExec({ executable, workingDirectory, prompt, timeoutMs, spawnCommand, stdio });
97
99
  }
98
100
 
99
101
  function buildContinuationPrompt(activation) {
@@ -114,7 +116,7 @@ function buildContinuationPrompt(activation) {
114
116
  ].join("\n");
115
117
  }
116
118
 
117
- function runCodexExec({ executable, workingDirectory, prompt, timeoutMs, spawnCommand }) {
119
+ function runCodexExec({ executable, workingDirectory, prompt, timeoutMs, spawnCommand, stdio }) {
118
120
  return new Promise((resolve, reject) => {
119
121
  let child;
120
122
  let settled = false;
@@ -131,15 +133,25 @@ function runCodexExec({ executable, workingDirectory, prompt, timeoutMs, spawnCo
131
133
  child = spawnCommand(
132
134
  executable,
133
135
  ["exec", "--cd", workingDirectory, prompt],
134
- { stdio: ["ignore", "ignore", "ignore"] },
136
+ { stdio },
135
137
  );
136
138
  } catch (error) {
137
- finish(reject, error);
139
+ finish(
140
+ reject,
141
+ codexExecError(
142
+ "connector_codex_exec_start_failed",
143
+ "Codex exec could not be started",
144
+ error,
145
+ ),
146
+ );
138
147
  return;
139
148
  }
140
149
 
141
150
  if (!child || typeof child.once !== "function") {
142
- finish(reject, new Error("Codex exec process is invalid"));
151
+ finish(
152
+ reject,
153
+ codexExecError("connector_codex_exec_invalid", "Codex exec returned an invalid process"),
154
+ );
143
155
  return;
144
156
  }
145
157
 
@@ -149,16 +161,36 @@ function runCodexExec({ executable, workingDirectory, prompt, timeoutMs, spawnCo
149
161
  } catch {
150
162
  // The activation remains unknown even if the process cannot be terminated.
151
163
  }
152
- finish(reject, new Error("Codex exec process timed out"));
164
+ finish(
165
+ reject,
166
+ codexExecError(
167
+ "connector_codex_exec_timeout",
168
+ `Codex exec process timed out after ${timeoutMs} milliseconds`,
169
+ ),
170
+ );
153
171
  }, timeoutMs);
154
172
 
155
- child.once("error", (error) => finish(reject, error));
173
+ child.once("error", (error) => finish(
174
+ reject,
175
+ codexExecError("connector_codex_exec_start_failed", "Codex exec process failed to start", error),
176
+ ));
156
177
  child.once("close", (code, signal) => {
157
178
  if (code === 0 && signal === null) {
158
179
  finish(resolve);
159
180
  return;
160
181
  }
161
- finish(reject, new Error("Codex exec process did not complete successfully"));
182
+ const detail = signal
183
+ ? ` (signal ${signal})`
184
+ : code === null
185
+ ? ""
186
+ : ` (exit code ${code})`;
187
+ finish(
188
+ reject,
189
+ codexExecError(
190
+ "connector_codex_exec_failed",
191
+ `Codex exec process did not complete successfully${detail}`,
192
+ ),
193
+ );
162
194
  });
163
195
  });
164
196
  }
@@ -221,6 +253,24 @@ function requirePrompt(value) {
221
253
  return value;
222
254
  }
223
255
 
256
+ function requireStdio(value) {
257
+ if (value === "inherit") return value;
258
+ if (
259
+ Array.isArray(value) &&
260
+ value.length === 3 &&
261
+ value.every((entry) => entry === "ignore" || entry === "inherit" || entry === "pipe")
262
+ ) {
263
+ return value;
264
+ }
265
+ throw new TypeError("Codex prompt stdio is invalid");
266
+ }
267
+
268
+ function codexExecError(code, message, cause = undefined) {
269
+ const error = cause === undefined ? new Error(message) : new Error(message, { cause });
270
+ error.code = code;
271
+ return error;
272
+ }
273
+
224
274
  function requireExactRecord(value, allowedFields, requiredFields, label) {
225
275
  if (!value || typeof value !== "object" || Array.isArray(value)) {
226
276
  throw new TypeError(`${label} must be an object`);
package/src/main.mjs CHANGED
@@ -514,10 +514,14 @@ async function testCodex(flags, positionals, ui) {
514
514
  ui.info("Prompt", prompt);
515
515
  ui.wait("Starting a fresh Codex session…");
516
516
  }
517
+ if (ui.interactive) {
518
+ ui.stopWait("Codex", "running the local prompt; Codex output follows below", "info");
519
+ }
517
520
  await runCodexPrompt({
518
521
  workingDirectory: readiness.workingDirectory,
519
522
  executable: readiness.installation.executable,
520
523
  prompt,
524
+ stdio: ui.interactive ? "inherit" : ["ignore", "ignore", "ignore"],
521
525
  commandTimeoutMs: readBoundedNumber(
522
526
  flags["activation-timeout"] ?? 60_000,
523
527
  100,
@@ -1114,6 +1118,10 @@ function errorHint(error) {
1114
1118
  pairing_expired: "ask the Host backend for a new pairing code",
1115
1119
  pairing_request_timeout: "the Receiver took too long to answer; check your connection and run the command again",
1116
1120
  pairing_network_error: "check your internet connection and the Receiver address, then try again",
1121
+ connector_codex_exec_timeout: "Codex did not finish in time; run the same codex exec command directly to inspect its output",
1122
+ connector_codex_exec_failed: "run the same codex exec command directly and confirm that Codex is signed in and the workspace is accessible",
1123
+ connector_codex_exec_start_failed: "open Codex, complete login if needed, then run the command again",
1124
+ connector_codex_exec_invalid: "the installed Codex executable returned an invalid process; run doctor and try again",
1117
1125
  workspace_directory_unavailable: "choose a readable folder or pass --codex-cd /absolute/path",
1118
1126
  workspace_selection_cancelled: "run the command again when you are ready to choose a workspace",
1119
1127
  device_authorization_expired: `run \`${cliCommand("connect")}\` again and approve within ten minutes`,
@@ -1127,7 +1135,7 @@ function errorHint(error) {
1127
1135
  connector_test_prompt_invalid: "use one short, single-line prompt inside quotes",
1128
1136
  connector_activation_timeout_invalid: "use an activation timeout between 100 and 60000 milliseconds",
1129
1137
  };
1130
- return hints[error?.code] ?? "check the Receiver address and try again";
1138
+ return hints[error?.code] ?? "check the command output and try again";
1131
1139
  }
1132
1140
 
1133
1141
  await main();