@quantiya/codevibe-codex-plugin 2.0.93 → 2.0.94

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
@@ -44,10 +44,18 @@ install the unified `codevibe --agent` interface yet.
44
44
  - **macOS, Linux, or WSL Ubuntu** — Windows without WSL is not supported
45
45
  - **Node.js** 22.0.0+
46
46
  - **tmux** — `brew install tmux` on macOS, `apt install tmux` on Linux/WSL
47
- - **Codex CLI** installed and authenticated
47
+ - **Codex CLI** installed and authenticated (latest recommended)
48
48
 
49
49
  ## How it works
50
50
 
51
+ The own-tmux Companion route uses `--no-daemon` when Codex advertises that
52
+ capability. On current Codex this keeps hooks in the wrapper's environment and
53
+ avoids the shared server's message-size limit on large history resumes. Older
54
+ CLIs without the option retain their previous native handling; there is no new
55
+ minimum-version requirement. Direct tmux/non-TTY passthrough keeps native argv
56
+ unchanged. Current local Companion execution rejects remote mode. Original
57
+ arguments retain their order after an added local-process option.
58
+
51
59
  Codex CLI writes session logs to `~/.codex/sessions/` as JSONL files. A native
52
60
  hook supplies the exact rollout path and session id; CodeVibe never guesses log
53
61
  ownership from timestamps or working directories, so concurrent sessions in the
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const { spawnSync } = require('child_process');
4
+
5
+ /** Companion hooks must execute in this wrapper's native process environment.
6
+ * The shared server also has a 128 MiB WebSocket response limit, which legacy
7
+ * history resumes can exceed. Keep the native in-process path for Companion.
8
+ */
9
+ function localModePolicy(args, help) {
10
+ const delimiter = args.indexOf('--');
11
+ const options = delimiter < 0 ? args : args.slice(0, delimiter);
12
+ // Preserve established handling for older CLIs without this capability.
13
+ // The owner explicitly chose compatibility rather than a new minimum CLI.
14
+ if (!/(?:^|\s)--no-daemon(?:\s|$)/m.test(help)) return 'legacy';
15
+ if (options.some(arg => arg === '--remote' || arg.startsWith('--remote='))) {
16
+ throw new Error('CodeVibe Companion requires local Codex execution; remote Codex sessions cannot provide this wrapper\'s hooks.');
17
+ }
18
+ return options.includes('--no-daemon') ? 'present' : 'add';
19
+ }
20
+
21
+ if (require.main === module) {
22
+ try {
23
+ const result = spawnSync('codex', ['--help'], {
24
+ encoding: 'utf8', timeout: 5_000, maxBuffer: 1024 * 1024,
25
+ });
26
+ if (result.error || result.signal || result.status !== 0) {
27
+ throw new Error('Could not verify Codex local execution support. Run codex --help and retry.');
28
+ }
29
+ process.stdout.write(localModePolicy(process.argv.slice(2), result.stdout) + '\n');
30
+ } catch (error) {
31
+ process.stderr.write(`CodeVibe Companion: ${error.message}\n`);
32
+ process.exitCode = 1;
33
+ }
34
+ }
35
+
36
+ module.exports = { localModePolicy };
@@ -223,6 +223,20 @@ cleanup() {
223
223
  log "Tmux state is ambiguous; preserving daemon and native session"
224
224
  return
225
225
  fi
226
+ # Only an absent session proves native termination. A successful tmux
227
+ # client can still wrap a native error; collect that status here so
228
+ # setup/attach failures after native termination use the same path.
229
+ local native_exit
230
+ native_exit="$(head -c 16 "$_CV_CODEX_EXIT_FILE" 2>/dev/null)" || native_exit=""
231
+ if [[ "$native_exit" =~ ^(0|[1-9][0-9]{0,2})$ ]] && [ "$native_exit" -le 255 ]; then
232
+ log "Native Codex session ended with status $native_exit"
233
+ if [ "$wrapper_exit_code" -ne 130 ] && [ "$wrapper_exit_code" -ne 143 ]; then
234
+ wrapper_exit_code=$native_exit
235
+ fi
236
+ elif [ "$wrapper_exit_code" -eq 0 ]; then
237
+ log "WARN: native session ended without a valid exit status"
238
+ wrapper_exit_code=1
239
+ fi
226
240
  fi
227
241
 
228
242
  # Fire wrapper_exited telemetry BEFORE killing the server so the MCP
@@ -327,6 +341,7 @@ cleanup() {
327
341
  elif [ "$server_exit" -ne 0 ]; then
328
342
  exit "$server_exit"
329
343
  fi
344
+ exit 0
330
345
  }
331
346
 
332
347
  # Set up trap for cleanup
@@ -366,7 +381,10 @@ if [ ! -f "$PLUGIN_DIR/dist/server.js" ]; then
366
381
  exit 1
367
382
  fi
368
383
 
369
- # Generate a unique session name
384
+ # Direct routes retain verbatim native argument handling.
385
+ CODEX_LOCAL_ARGS=()
386
+
387
+ # Generate a unique session name.
370
388
  SESSION_NAME="${TMUX_SESSION_PREFIX}-$$"
371
389
  WORKING_DIR="$(pwd)"
372
390
  export CODEVIBE_CODEX_WRAPPER_PID="$$"
@@ -391,7 +409,7 @@ if [ -n "$TMUX" ]; then
391
409
  # leaves _CV_RC at its 0 default. printf's `|| true` keeps a
392
410
  # disk-full failure from clobbering diagnostics.
393
411
  _CV_RC=0
394
- env -u QUORUM_REVIEWER_SUBPROCESS codex "$@" || _CV_RC=$?
412
+ env -u QUORUM_REVIEWER_SUBPROCESS codex "${CODEX_LOCAL_ARGS[@]}" "$@" || _CV_RC=$?
395
413
  printf '%s' "$_CV_RC" > "$_CV_CODEX_EXIT_FILE" 2>/dev/null || true
396
414
  exit "$_CV_RC"
397
415
  fi
@@ -402,11 +420,23 @@ if [ ! -t 0 ] || [ ! -t 1 ]; then
402
420
  _CV_AGENT_INVOKED="true"
403
421
  _CV_AGENT_STARTED_AT="$(date +%s)"
404
422
  _CV_RC=0
405
- env -u QUORUM_REVIEWER_SUBPROCESS codex "$@" || _CV_RC=$?
423
+ env -u QUORUM_REVIEWER_SUBPROCESS codex "${CODEX_LOCAL_ARGS[@]}" "$@" || _CV_RC=$?
406
424
  printf '%s' "$_CV_RC" > "$_CV_CODEX_EXIT_FILE" 2>/dev/null || true
407
425
  exit "$_CV_RC"
408
426
  fi
409
427
 
428
+ # Select in-process execution only for the own-tmux Companion route, before
429
+ # hook/cloud startup. Older CLIs retain their previous native execution mode.
430
+ if ! _CV_LOCAL_MODE=$(node "$PLUGIN_DIR/libexec/codex-local-mode.js" "$@"); then
431
+ cv_failed "codex_local_execution_unavailable"
432
+ exit 1
433
+ fi
434
+ case "$_CV_LOCAL_MODE" in
435
+ add) CODEX_LOCAL_ARGS=(--no-daemon) ;;
436
+ present|legacy) ;;
437
+ *) cv_failed "codex_local_execution_unavailable"; exit 1 ;;
438
+ esac
439
+
410
440
  # Start the session log watcher server in background
411
441
  log "Starting session log watcher server..."
412
442
  export CODEX_WORKING_DIRECTORY="$WORKING_DIR"
@@ -664,9 +694,11 @@ log "Creating tmux session: $SESSION_NAME"
664
694
 
665
695
  # Build the codex command with proper escaping
666
696
  CODEX_CMD="codex"
667
- for arg in "$@"; do
668
- # Escape single quotes in arguments
669
- escaped_arg=$(printf '%s' "$arg" | sed "s/'/'\\\\''/g")
697
+ for arg in "${CODEX_LOCAL_ARGS[@]}" "$@"; do
698
+ # The sentinel prevents command substitution from stripping trailing
699
+ # newlines belonging to the argument. Remove only the appended sentinel.
700
+ escaped_arg=$(printf '%s' "$arg" | sed "s/'/'\\\\''/g"; printf x)
701
+ escaped_arg=${escaped_arg%x}
670
702
  CODEX_CMD="$CODEX_CMD '$escaped_arg'"
671
703
  done
672
704
 
@@ -705,8 +737,8 @@ echo "$SESSION_NAME" > "${CODEVIBE_TMPDIR}/codevibe-codex-tmux-session-$$"
705
737
 
706
738
  log "Attaching to tmux session: $SESSION_NAME"
707
739
 
708
- # Attach to the session
740
+ # Attach reports the client status. Cleanup collects native status only after
741
+ # this exact session is absent; a detach keeps the daemon and native alive.
709
742
  tmux attach-session -t "$SESSION_NAME"
710
743
 
711
- # After tmux exits, cleanup is handled by trap
712
- log "Tmux session ended"
744
+ log "Tmux client returned"
@@ -61,7 +61,12 @@ function wrapperCommand(session, command) {
61
61
  && typeof s[1] === 'string' && s[1].startsWith('ENVIRONMENT='));
62
62
  const codex = statements.filter((s) => s[0] === 'codex');
63
63
  if (!environment || codex.length !== 1 || !codex[0].every((w) => typeof w === 'string')) return null;
64
- return { session, environment: environmentFor(environment[1].slice('ENVIRONMENT='.length)), args: codex[0].slice(1) };
64
+ const args = codex[0].slice(1);
65
+ // The launcher adds this global flag before the original vendor arguments.
66
+ // Remove only that leading option when recognizing an explicit resume; never
67
+ // normalize flags or prompt text elsewhere in the argument list.
68
+ if (args[0] === '--no-daemon') args.shift();
69
+ return { session, environment: environmentFor(environment[1].slice('ENVIRONMENT='.length)), args };
65
70
  }
66
71
 
67
72
  function resolveHookSession(nativeId, inheritedSession, inventory, inheritedEnvironment) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-codex-plugin",
3
- "version": "2.0.93",
3
+ "version": "2.0.94",
4
4
  "description": "Control OpenAI Codex CLI from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "codevibe": {