claude-multiacc 2.0.64 → 2.0.65
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/bin/claude-accounts +4 -4
- package/bin/codex +25 -7
- package/bin/codex-accounts +16 -3
- package/docs/AUTORESUME.md +10 -1
- package/docs/CODEX.md +39 -0
- package/lib/__pycache__/audit.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume_cross.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume_cross_dispatch.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume_cross_receipt.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume_handoff.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume_probe.cpython-314.pyc +0 -0
- package/lib/__pycache__/autoresume_receipt.cpython-314.pyc +0 -0
- package/lib/__pycache__/claude_client_error.cpython-314.pyc +0 -0
- package/lib/__pycache__/claude_reset.cpython-314.pyc +0 -0
- package/lib/__pycache__/claude_token_identity.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_autoresume_mode.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_config_edit.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_credit_controls.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_credit_local_scope.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_credit_selection.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_credits.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_limits_lock.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_mcp_oauth.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_python.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_resume_cwd.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_speed.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_trust.cpython-314.pyc +0 -0
- package/lib/__pycache__/codex_usage_fetch.cpython-314.pyc +0 -0
- package/lib/__pycache__/keychain.cpython-314.pyc +0 -0
- package/lib/__pycache__/mcp_mirror.cpython-314.pyc +0 -0
- package/lib/__pycache__/mcp_oauth.cpython-314.pyc +0 -0
- package/lib/__pycache__/mcp_registry.cpython-314.pyc +0 -0
- package/lib/__pycache__/model_catalog.cpython-314.pyc +0 -0
- package/lib/__pycache__/model_match.cpython-314.pyc +0 -0
- package/lib/__pycache__/report.cpython-314.pyc +0 -0
- package/lib/__pycache__/selector_credit_scope.cpython-314.pyc +0 -0
- package/lib/__pycache__/selector_credits.cpython-314.pyc +0 -0
- package/lib/__pycache__/selector_funding.cpython-314.pyc +0 -0
- package/lib/__pycache__/selector_policy.cpython-314.pyc +0 -0
- package/lib/__pycache__/selector_primitives.cpython-314.pyc +0 -0
- package/lib/__pycache__/session_settings.cpython-314.pyc +0 -0
- package/lib/__pycache__/shim_path.cpython-314.pyc +0 -0
- package/lib/autoresume.py +28 -8
- package/lib/codex_speed.py +351 -0
- package/lib/codex_speed.sh +39 -0
- package/lib/common.sh +13 -3
- package/lib/model_match.py +4 -1
- package/lib/session_settings.py +25 -6
- package/lib/shim_path.py +6 -0
- package/package.json +2 -2
- package/tests/__pycache__/autoresume_cross_receipt_support.cpython-314.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_tmux_environment.cpython-314.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_tmux_support.cpython-314.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_unit_support.cpython-314.pyc +0 -0
- package/tests/__pycache__/autoresume_tmux_support.cpython-314.pyc +0 -0
- package/tests/__pycache__/packaged_command_support.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_catalog.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_catalog_cli.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_codex_records.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_codex_trust.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_claude_holders.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_guards.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_holders.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_origin.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_policy.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_receipt.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_tmux.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_tmux_races.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_tokens.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cursor.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd_handoff.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd_reader.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd_tmux.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_fallback.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_handoff_argv.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_handoff_history.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_handoff_origins.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_memory.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_memory_tmux.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_mode.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_probe.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_receipt.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_relaunch_settings.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_settings.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_sidechain.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_sidechain_tmux.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_tmux.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_tmux_modes.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_autoresume_trust_tmux.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_claude_reset.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_claude_token_identity.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_exec_stdin.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_mcp_oauth.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_credits.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_credits_polling.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_credits_report.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_fetch.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_polling.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_reporting.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_windows.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_mcp_mirror.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_mcp_mirror_args.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_mcp_oauth.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_mcp_registry.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_selector.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_selector_cached_credits.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_selector_credit_scope.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_selector_credit_shim.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_selector_credits.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_selector_spread.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_token_identity_ceremony.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_token_identity_integration.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_token_identity_retry.cpython-314.pyc +0 -0
- package/tests/__pycache__/test_token_identity_sync.cpython-314.pyc +0 -0
- package/tests/run-tests.sh +23 -7
- package/tests/test_codex_speed.py +236 -0
- package/tests/test_mutate_lock.py +107 -0
- package/tests/test_shim_path.py +44 -4
- package/lib/__pycache__/audit.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume_cross.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume_cross_dispatch.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume_cross_receipt.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume_handoff.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume_probe.cpython-312.pyc +0 -0
- package/lib/__pycache__/autoresume_receipt.cpython-312.pyc +0 -0
- package/lib/__pycache__/claude_client_error.cpython-312.pyc +0 -0
- package/lib/__pycache__/claude_reset.cpython-312.pyc +0 -0
- package/lib/__pycache__/claude_token_identity.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_autoresume_mode.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_config_edit.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_credit_controls.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_credit_local_scope.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_credit_selection.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_credits.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_limits_lock.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_mcp_oauth.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_python.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_resume_cwd.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_trust.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_usage_fetch.cpython-312.pyc +0 -0
- package/lib/__pycache__/keychain.cpython-312.pyc +0 -0
- package/lib/__pycache__/mcp_mirror.cpython-312.pyc +0 -0
- package/lib/__pycache__/mcp_oauth.cpython-312.pyc +0 -0
- package/lib/__pycache__/mcp_registry.cpython-312.pyc +0 -0
- package/lib/__pycache__/model_catalog.cpython-312.pyc +0 -0
- package/lib/__pycache__/model_match.cpython-312.pyc +0 -0
- package/lib/__pycache__/report.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_credit_scope.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_credits.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_funding.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_policy.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_primitives.cpython-312.pyc +0 -0
- package/lib/__pycache__/session_settings.cpython-312.pyc +0 -0
- package/lib/__pycache__/shim_path.cpython-312.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_receipt_support.cpython-312.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_tmux_environment.cpython-312.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_tmux_support.cpython-312.pyc +0 -0
- package/tests/__pycache__/autoresume_cross_unit_support.cpython-312.pyc +0 -0
- package/tests/__pycache__/autoresume_tmux_support.cpython-312.pyc +0 -0
- package/tests/__pycache__/packaged_command_support.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_catalog.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_catalog_cli.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_codex_records.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_codex_trust.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_claude_holders.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_guards.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_holders.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_origin.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_policy.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_receipt.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_tmux.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_tmux_races.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cross_tokens.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cursor.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd_handoff.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd_reader.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_cwd_tmux.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_fallback.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_handoff_argv.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_handoff_history.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_handoff_origins.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_memory.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_memory_tmux.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_mode.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_probe.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_receipt.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_relaunch_settings.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_settings.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_sidechain.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_sidechain_tmux.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_tmux.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_tmux_modes.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_autoresume_trust_tmux.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_claude_reset.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_claude_token_identity.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_exec_stdin.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_mcp_oauth.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_credits.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_credits_polling.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_credits_report.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_fetch.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_polling.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_reporting.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_windows.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_mcp_mirror.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_mcp_mirror_args.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_mcp_oauth.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_mcp_registry.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_selector.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_selector_cached_credits.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_selector_credit_scope.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_selector_credit_shim.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_selector_credits.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_selector_spread.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_token_identity_ceremony.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_token_identity_integration.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_token_identity_retry.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_token_identity_sync.cpython-312.pyc +0 -0
package/bin/claude-accounts
CHANGED
|
@@ -1708,7 +1708,7 @@ token_identity_receipt() { # Unknown results must never overwrite a peer's prove
|
|
|
1708
1708
|
limits_distribute_now() {
|
|
1709
1709
|
local lock="$ACC_ROOT/tmp/limits-push.lock"
|
|
1710
1710
|
mkdir -p "$ACC_ROOT/tmp" 2>/dev/null || return 0
|
|
1711
|
-
if !
|
|
1711
|
+
if ! atomic_mkdir "$lock" 2>/dev/null; then
|
|
1712
1712
|
# A DETACHED push that is killed (logout, reboot, pkill) never runs its EXIT trap,
|
|
1713
1713
|
# and mkdir can never take a lock dir nobody will remove: one stranded lock
|
|
1714
1714
|
# silently stopped ALL telemetry distribution on the live pool from 2026-09-03
|
|
@@ -1721,7 +1721,7 @@ limits_distribute_now() {
|
|
|
1721
1721
|
# exactly as before.
|
|
1722
1722
|
[ $(( $(epoch_now) - $(file_mtime "$lock") )) -gt 600 ] || return 0
|
|
1723
1723
|
rm -rf "$lock" 2>/dev/null
|
|
1724
|
-
|
|
1724
|
+
atomic_mkdir "$lock" 2>/dev/null || return 0
|
|
1725
1725
|
log_to sync.log "stale limits-push lock broken (older than 600s); distributing"
|
|
1726
1726
|
fi
|
|
1727
1727
|
trap 'rmdir "$lock" 2>/dev/null || true' EXIT
|
|
@@ -1792,7 +1792,7 @@ cmd_limits() {
|
|
|
1792
1792
|
done
|
|
1793
1793
|
local lock="$ACC_ROOT/.locks/limits"
|
|
1794
1794
|
mkdir -p "$ACC_ROOT/.locks"
|
|
1795
|
-
if !
|
|
1795
|
+
if ! atomic_mkdir "$lock" 2>/dev/null; then
|
|
1796
1796
|
local age=$(( $(epoch_now) - $(file_mtime "$lock") ))
|
|
1797
1797
|
if [ "$age" -lt 120 ]; then
|
|
1798
1798
|
# A --json caller still gets the document (built from the state on disk) —
|
|
@@ -1802,7 +1802,7 @@ cmd_limits() {
|
|
|
1802
1802
|
return 0
|
|
1803
1803
|
fi
|
|
1804
1804
|
rm -rf "$lock"
|
|
1805
|
-
if !
|
|
1805
|
+
if ! atomic_mkdir "$lock" 2>/dev/null; then
|
|
1806
1806
|
if [ "$json" = "1" ]; then emit_report_json limits; return $?; fi
|
|
1807
1807
|
return 0
|
|
1808
1808
|
fi
|
package/bin/codex
CHANGED
|
@@ -156,6 +156,20 @@ cli_positional_at() { # argv -> prints the index of its first positional argumen
|
|
|
156
156
|
return 1
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
# Account/model capabilities are resolved only after the serving account is known.
|
|
160
|
+
# The helper is optional so a damaged install retains the shim's fail-open contract.
|
|
161
|
+
codex_native_argv() {
|
|
162
|
+
CODEX_SPEED_ARGV=("$@")
|
|
163
|
+
if [ -f "$SELF_DIR/../lib/codex_speed.sh" ]; then
|
|
164
|
+
. "$SELF_DIR/../lib/codex_speed.sh"
|
|
165
|
+
codex_speed_prepare "$@" || return $?
|
|
166
|
+
fi
|
|
167
|
+
}
|
|
168
|
+
codex_native_exec() {
|
|
169
|
+
codex_native_argv "$@" || exit $?
|
|
170
|
+
exec "$REAL" ${CODEX_SPEED_ARGV[@]+"${CODEX_SPEED_ARGV[@]}"}
|
|
171
|
+
}
|
|
172
|
+
|
|
159
173
|
# Whether argv is `codex [global options] mcp add|remove …`.
|
|
160
174
|
mcp_mutation_argv() {
|
|
161
175
|
local i j
|
|
@@ -252,7 +266,7 @@ if [ -n "${CODEX_HOME:-}" ] \
|
|
|
252
266
|
mcp_oauth_ensure "$CODEX_HOME"
|
|
253
267
|
fi
|
|
254
268
|
mcp_nested_mirror "$@" || true
|
|
255
|
-
|
|
269
|
+
codex_native_exec "$@"
|
|
256
270
|
fi
|
|
257
271
|
|
|
258
272
|
now="$(date +%s)"
|
|
@@ -1074,6 +1088,9 @@ ar_argv_ok() { # the argv codex is about to get
|
|
|
1074
1088
|
model:*) case "$a" in ''|-*) return 1 ;; esac ;;
|
|
1075
1089
|
effort:model_reasoning_effort=?*)
|
|
1076
1090
|
case "${a#model_reasoning_effort=}" in *[!$AR_LOWER]*) return 1 ;; esac ;;
|
|
1091
|
+
effort:service_tier=*)
|
|
1092
|
+
case "${a#service_tier=}" in default|fast|priority|ultrafast|'"default"'|'"fast"'|'"priority"'|'"ultrafast"'|"'default'"|"'fast'"|"'priority'"|"'ultrafast'") ;; *) return 1 ;; esac ;;
|
|
1093
|
+
effort:features.fast_mode=true) ;;
|
|
1077
1094
|
*) return 1 ;;
|
|
1078
1095
|
esac
|
|
1079
1096
|
want=""
|
|
@@ -1272,7 +1289,7 @@ if [ -n "${CODEX_ACCOUNT:-}" ] && [ "$AR_PROBE" != "1" ]; then
|
|
|
1272
1289
|
mcp_ensure "$d"
|
|
1273
1290
|
mcp_oauth_ensure "$d"
|
|
1274
1291
|
mcp_mirror_run "$d" "$@" || true
|
|
1275
|
-
|
|
1292
|
+
codex_native_exec "$@"
|
|
1276
1293
|
fi
|
|
1277
1294
|
sel_log "pin-invalid account=$CODEX_ACCOUNT (no such dir; random fallback)"
|
|
1278
1295
|
fi
|
|
@@ -1343,7 +1360,7 @@ if [ "${#valid[@]}" -eq 0 ]; then
|
|
|
1343
1360
|
[ -t 2 ] && printf 'codex-multiacc: no pool account is usable (%s) — see: codex-accounts expired, then: codex-accounts relogin\n' \
|
|
1344
1361
|
"${ids# }" >&2
|
|
1345
1362
|
fi
|
|
1346
|
-
|
|
1363
|
+
codex_native_exec "$@"
|
|
1347
1364
|
fi
|
|
1348
1365
|
|
|
1349
1366
|
# ---- rotation ----------------------------------------------------------------
|
|
@@ -1657,14 +1674,14 @@ if [ "$wants_retry" = "0" ]; then
|
|
|
1657
1674
|
fi
|
|
1658
1675
|
ar_scrub_env
|
|
1659
1676
|
[ "$AR_NO_DAEMON" != 1 ] || set -- --no-daemon "$@"
|
|
1660
|
-
|
|
1677
|
+
codex_native_exec "$@"
|
|
1661
1678
|
fi
|
|
1662
1679
|
|
|
1663
1680
|
# Retry path: buffer stdio so a retried call never double-emits partial output.
|
|
1664
1681
|
mkdir -p "$ACC_ROOT/tmp" 2>/dev/null || true
|
|
1665
1682
|
tmpd="$(mktemp -d "$ACC_ROOT/tmp/shim.XXXXXX" 2>/dev/null)" || {
|
|
1666
1683
|
export CODEX_HOME="$pick"
|
|
1667
|
-
|
|
1684
|
+
codex_native_exec "$@"
|
|
1668
1685
|
}
|
|
1669
1686
|
trap 'rm -rf "$tmpd"' EXIT
|
|
1670
1687
|
|
|
@@ -1673,7 +1690,7 @@ trap 'rm -rf "$tmpd"' EXIT
|
|
|
1673
1690
|
# nonzero — a hard failure. Verify now, fall back to plain exec if we cannot.
|
|
1674
1691
|
if ! : > "$tmpd/out" 2>/dev/null || ! : > "$tmpd/err" 2>/dev/null; then
|
|
1675
1692
|
export CODEX_HOME="$pick"
|
|
1676
|
-
|
|
1693
|
+
codex_native_exec "$@"
|
|
1677
1694
|
fi
|
|
1678
1695
|
|
|
1679
1696
|
stdin_file=""
|
|
@@ -1708,8 +1725,9 @@ cur="$pick"
|
|
|
1708
1725
|
rc=0
|
|
1709
1726
|
while :; do
|
|
1710
1727
|
if [ -n "$stdin_file" ]; then exec 3< "$stdin_file"; else exec 3< /dev/null; fi
|
|
1728
|
+
CODEX_HOME="$cur" codex_native_argv "$@" || exit $?
|
|
1711
1729
|
CODEX_HOME="$cur" CODEX_MULTIACC_SELECTED_HOME="$cur" \
|
|
1712
|
-
codex_retry_run "$REAL" "
|
|
1730
|
+
codex_retry_run "$REAL" ${CODEX_SPEED_ARGV[@]+"${CODEX_SPEED_ARGV[@]}"} <&3 > "$tmpd/out" 2> "$tmpd/err"
|
|
1713
1731
|
rc=$?
|
|
1714
1732
|
exec 3<&-
|
|
1715
1733
|
if [ "$rc" -ne 0 ] && [ "$attempt" -eq 1 ] \
|
package/bin/codex-accounts
CHANGED
|
@@ -106,6 +106,10 @@ USAGE
|
|
|
106
106
|
every install and self-update runs it, and each limits pass refreshes its own pool's
|
|
107
107
|
copy once it is an hour old. --if-stale leaves a younger copy alone; --quiet prints
|
|
108
108
|
nothing. show prints the merged catalog.
|
|
109
|
+
codex-accounts speed --account-dir DIR --model MODEL --speed normal|fast|ultrafast [--json]
|
|
110
|
+
resolve speed from this account's native model catalog. Ultrafast verifies
|
|
111
|
+
account access through native model/list without inference; unknown or
|
|
112
|
+
unavailable access falls back to Fast. Never changes account configuration.
|
|
109
113
|
codex-accounts post-sync (server side) seed dirs, fix perms, quick verify
|
|
110
114
|
codex-accounts mcp add <name> [--provider claude|codex|both] [--scope user]
|
|
111
115
|
[-e KEY=VAL]... [-H 'Header: v']... [--transport stdio|http]
|
|
@@ -144,6 +148,8 @@ ENV
|
|
|
144
148
|
'none' = local-only, nothing is pushed anywhere
|
|
145
149
|
CODEX_MULTIACC_SYNC_ROOT / _SYNC_REPO remote pool root / addon repo for it
|
|
146
150
|
CODEX_ACCOUNT pin the shim to one account
|
|
151
|
+
CODEX_SPEED normal|fast|ultrafast for this launch; unavailable Ultrafast uses Fast
|
|
152
|
+
CODEX_SPEED_MODEL model hint for app-server launches that choose their model over RPC
|
|
147
153
|
CODEX_SHIM_RETRY=0 disable the `codex exec` auto-retry
|
|
148
154
|
CODEX_MULTIACC_DISABLE=1 bypass the shim entirely
|
|
149
155
|
CODEX_MULTIACC_AUTO_RESET=0 disable automatic usage-reset redemption
|
|
@@ -156,6 +162,12 @@ EOF
|
|
|
156
162
|
|
|
157
163
|
require_manifest() { [ -f "$MANIFEST" ] || die "no manifest at $MANIFEST — run claude-multiacc install first"; }
|
|
158
164
|
|
|
165
|
+
cmd_speed() {
|
|
166
|
+
local native
|
|
167
|
+
native="$(find_real_codex "$_self" 2>/dev/null)" || native=""
|
|
168
|
+
"$PYBIN" "$LIB_DIR/codex_speed.py" --native-cli "$native" "$@"
|
|
169
|
+
}
|
|
170
|
+
|
|
159
171
|
cmd_configure() {
|
|
160
172
|
require_manifest
|
|
161
173
|
local apply=0 check=0 arg rc
|
|
@@ -257,11 +269,11 @@ PYEOF
|
|
|
257
269
|
# later contender legitimately re-took.
|
|
258
270
|
login_lock_acquire() { # $1 = lock dir; nonzero when someone else holds it
|
|
259
271
|
local L="$1"
|
|
260
|
-
if !
|
|
272
|
+
if ! atomic_mkdir "$L" 2>/dev/null; then
|
|
261
273
|
[ $(( $(epoch_now) - $(file_mtime "$L") )) -gt 1800 ] || return 1
|
|
262
274
|
mv "$L" "$L.stale.$$" 2>/dev/null || return 1
|
|
263
275
|
rm -rf "$L.stale.$$" 2>/dev/null
|
|
264
|
-
|
|
276
|
+
atomic_mkdir "$L" 2>/dev/null || return 1
|
|
265
277
|
fi
|
|
266
278
|
: > "$L/owner.$$" 2>/dev/null || true
|
|
267
279
|
return 0
|
|
@@ -2477,7 +2489,7 @@ PYEOF
|
|
|
2477
2489
|
# distribution for as long as the arg loops rejected the flag. An UNKNOWN verb must still
|
|
2478
2490
|
# FAIL, or the probe stops meaning what it says — so this list must hold exactly the verbs
|
|
2479
2491
|
# the dispatcher below implements, and a test pins that both ways.
|
|
2480
|
-
_KNOWN_VERBS="list status add import export-credential export-cred import-credential import-cred adopt dedupe remove login expired relogin re-login sync configure verify limits post-sync health self-update init-pool mcp model-catalog"
|
|
2492
|
+
_KNOWN_VERBS="list status add import export-credential export-cred import-credential import-cred adopt dedupe remove login expired relogin re-login sync configure verify limits post-sync health self-update init-pool mcp model-catalog speed"
|
|
2481
2493
|
case " $_KNOWN_VERBS " in
|
|
2482
2494
|
*" ${1:-help} "*)
|
|
2483
2495
|
# ...but never past a literal `--`: from there on the words belong to an MCP
|
|
@@ -2510,6 +2522,7 @@ case "${1:-help}" in
|
|
|
2510
2522
|
init-pool) shift; cmd_init_pool "$@" ;;
|
|
2511
2523
|
mcp) shift; cmd_mcp "$@" ;;
|
|
2512
2524
|
model-catalog) shift; cmd_model_catalog "$@" ;;
|
|
2525
|
+
speed) shift; cmd_speed "$@" ;;
|
|
2513
2526
|
help|--help|-h) usage ;;
|
|
2514
2527
|
*) usage; exit 1 ;;
|
|
2515
2528
|
esac
|
package/docs/AUTORESUME.md
CHANGED
|
@@ -225,7 +225,16 @@ The prompt is submitted automatically:
|
|
|
225
225
|
- **To replace the whole text**, set `CLAUDE_MULTIACC_AUTORESUME_PROMPT` or
|
|
226
226
|
`CODEX_MULTIACC_AUTORESUME_PROMPT`.
|
|
227
227
|
|
|
228
|
-
### Model and
|
|
228
|
+
### Model, effort, and Codex speed
|
|
229
|
+
|
|
230
|
+
Codex relaunches also carry the most recently saved `service_tier` from the
|
|
231
|
+
thread's own settings or turn context. Normal, Fast, and Ultrafast remain the same
|
|
232
|
+
across account rotation; Ultrafast becomes Fast when the selected destination
|
|
233
|
+
account/model does not advertise it. Claude receives no speed flag. The shim
|
|
234
|
+
updates the named thread's tier through native `thread/resume` before launching
|
|
235
|
+
the CLI, because native resume restores a saved tier ahead of `-c` configuration.
|
|
236
|
+
See [Session speed](CODEX.md#session-speed) for capability discovery and the
|
|
237
|
+
`CODEX_SPEED` launch override.
|
|
229
238
|
|
|
230
239
|
The watcher reads the model and effort from the session's own history when it decides to
|
|
231
240
|
relaunch, so a `/model` or `/effort` switch made after the launch is honoured:
|
package/docs/CODEX.md
CHANGED
|
@@ -92,6 +92,45 @@ Codex-specific notes:
|
|
|
92
92
|
- **API-key logins are rejected** — ChatGPT subscription accounts only, matching the
|
|
93
93
|
addon's no-API-keys rule.
|
|
94
94
|
|
|
95
|
+
## Session speed
|
|
96
|
+
|
|
97
|
+
Set `CODEX_SPEED=normal`, `fast`, or `ultrafast` for a Codex launch. Normal explicitly
|
|
98
|
+
uses the standard tier, even when an account's configuration defaults to Fast.
|
|
99
|
+
The setting also works with `CODEX_ACCOUNT` and `CODEX_HOME` pins. Explicit native
|
|
100
|
+
`-c service_tier=...` overrides take precedence. Claude has no corresponding option.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
CODEX_SPEED=fast codex
|
|
104
|
+
CODEX_SPEED=ultrafast codex exec -m gpt-6.1-sol 'Review the changed code'
|
|
105
|
+
codex-accounts speed --account-dir ~/.codex-accounts/acct-18 --model gpt-6.1-sol --speed ultrafast --json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The shim reads **the selected account's** native model catalog, never an e-mail or
|
|
109
|
+
a plan-name guess. Ultrafast falls back to Fast when that account/model does not
|
|
110
|
+
advertise it. Every Ultrafast launch verifies the native account's `model/list`
|
|
111
|
+
with no inference, so even a copied cache cannot grant another account access;
|
|
112
|
+
an inconclusive read falls back to Fast.
|
|
113
|
+
Catalog probes use a temporary SQLite index, preserving the account's normal
|
|
114
|
+
session-index work. The inspection command above uses the same native check for
|
|
115
|
+
Ultrafast.
|
|
116
|
+
|
|
117
|
+
Quota retries resolve the speed again for the next account. Automatic quota
|
|
118
|
+
resumes carry the speed recorded in the session history. For those resumes and
|
|
119
|
+
explicit speed requests on a named session UUID, the shim applies the resolved
|
|
120
|
+
tier through native `thread/resume` before launching the resumed CLI: Codex
|
|
121
|
+
currently restores its saved tier ahead of process configuration. That
|
|
122
|
+
preparation sends no turn and preserves the conversation. A failed preparation
|
|
123
|
+
stops the launch instead of silently selecting another speed.
|
|
124
|
+
|
|
125
|
+
App-server callers may supply `CODEX_SPEED_MODEL` when their model is chosen over
|
|
126
|
+
RPC. Read the resolved `config.service_tier` with native `config/read` and pass it
|
|
127
|
+
as `serviceTier` on `thread/start`, `thread/resume`, and `turn/start`; otherwise
|
|
128
|
+
saved thread settings can override the process configuration.
|
|
129
|
+
|
|
130
|
+
The [official speed documentation](https://learn.chatgpt.com/docs/agent-configuration/speed)
|
|
131
|
+
describes Fast's higher usage and Ultrafast access for Pro $500 and eligible
|
|
132
|
+
Enterprise/Edu plans. Actual account/model capabilities remain authoritative.
|
|
133
|
+
|
|
95
134
|
## Spendable Codex credits
|
|
96
135
|
|
|
97
136
|
The existing authenticated usage GET also supplies the account's spendable Codex
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/autoresume.py
CHANGED
|
@@ -1214,6 +1214,14 @@ def codex_effort_ok(val):
|
|
|
1214
1214
|
and EFFORT_VALUE_RE.match(val[len(CODEX_EFFORT_KEY):]) is not None
|
|
1215
1215
|
|
|
1216
1216
|
|
|
1217
|
+
def codex_speed_ok(val):
|
|
1218
|
+
"""Only known speed choices, never arbitrary config, may cross a relaunch."""
|
|
1219
|
+
if val == "features.fast_mode=true":
|
|
1220
|
+
return True
|
|
1221
|
+
return isinstance(val, str) and re.fullmatch(
|
|
1222
|
+
r'''service_tier=(?:default|fast|priority|ultrafast|"(?:default|fast|priority|ultrafast)"|'(?:default|fast|priority|ultrafast)')''', val) is not None
|
|
1223
|
+
|
|
1224
|
+
|
|
1217
1225
|
def codex_argv_parse(argv):
|
|
1218
1226
|
"""The argv shapes a codex relaunch can rebuild (mirrors bin/codex's ar_argv_ok) ->
|
|
1219
1227
|
(kept options, resume target or None), or None for anything else."""
|
|
@@ -1231,7 +1239,7 @@ def codex_argv_parse(argv):
|
|
|
1231
1239
|
kept += [arg, expected]
|
|
1232
1240
|
i += 1
|
|
1233
1241
|
elif arg in ("-m", "--model", "-c"):
|
|
1234
|
-
value_ok = codex_effort_ok if arg == "-c" else _value_ok
|
|
1242
|
+
value_ok = (lambda value: codex_effort_ok(value) or codex_speed_ok(value)) if arg == "-c" else _value_ok
|
|
1235
1243
|
if i + 1 >= len(argv) or not value_ok(argv[i + 1]):
|
|
1236
1244
|
return None
|
|
1237
1245
|
kept += [arg, argv[i + 1]]
|
|
@@ -1315,7 +1323,11 @@ def settings_argv(provider, settings):
|
|
|
1315
1323
|
(anything else counts as unknown). [] when nothing is known."""
|
|
1316
1324
|
effort = settings.get("effort") if isinstance(settings, dict) else None
|
|
1317
1325
|
effort = effort if isinstance(effort, str) and EFFORT_VALUE_RE.match(effort) else None
|
|
1318
|
-
|
|
1326
|
+
flags = settings_flags(provider, history_model(settings), effort)
|
|
1327
|
+
if provider == "codex" and isinstance(settings, dict) and settings.get("speed") in ("normal", "fast", "ultrafast"):
|
|
1328
|
+
flags += ["-c", "service_tier=" + {"normal": "default", "fast": "fast",
|
|
1329
|
+
"ultrafast": "ultrafast"}[settings["speed"]]]
|
|
1330
|
+
return flags
|
|
1319
1331
|
|
|
1320
1332
|
|
|
1321
1333
|
def argv_settings(provider, argv):
|
|
@@ -1336,6 +1348,10 @@ def argv_settings(provider, argv):
|
|
|
1336
1348
|
elif provider == "codex" and arg == "-c" and codex_effort_ok(val):
|
|
1337
1349
|
found["effort"] = val[len(CODEX_EFFORT_KEY):]
|
|
1338
1350
|
i += 1
|
|
1351
|
+
elif provider == "codex" and arg == "-c" and val.startswith("service_tier=") and codex_speed_ok(val):
|
|
1352
|
+
from codex_speed import speed
|
|
1353
|
+
found["speed"] = speed(val.split("=", 1)[1].strip("\"'"))
|
|
1354
|
+
i += 1
|
|
1339
1355
|
i += 1
|
|
1340
1356
|
return found
|
|
1341
1357
|
|
|
@@ -1355,14 +1371,16 @@ def claude_model_left(launch, served):
|
|
|
1355
1371
|
return family is not None and family != launch
|
|
1356
1372
|
|
|
1357
1373
|
|
|
1358
|
-
def without_settings(kept, model, effort):
|
|
1374
|
+
def without_settings(kept, model, effort, speed=False):
|
|
1359
1375
|
"""``kept`` without its model options (-m V, --model V, --model=V) when ``model`` and its
|
|
1360
1376
|
effort options (--effort V, codex's -c model_reasoning_effort=V) when ``effort``. Both
|
|
1361
1377
|
parsers refuse a value that starts with "-", so no value is ever taken for an option."""
|
|
1362
1378
|
out, i = [], 0
|
|
1363
1379
|
while i < len(kept):
|
|
1364
1380
|
arg = kept[i]
|
|
1365
|
-
|
|
1381
|
+
val = kept[i + 1] if i + 1 < len(kept) else ""
|
|
1382
|
+
if ((model and arg in ("-m", "--model")) or (effort and arg == "--effort")
|
|
1383
|
+
or (arg == "-c" and ((effort and codex_effort_ok(val)) or (speed and codex_speed_ok(val))))):
|
|
1366
1384
|
i += 2
|
|
1367
1385
|
continue
|
|
1368
1386
|
if not (model and arg.startswith("--model=")):
|
|
@@ -1407,10 +1425,12 @@ def relaunch_argv(provider, argv, sid, cls, prompt=None, settings=None, detail=N
|
|
|
1407
1425
|
left = claude_model_left(argv_settings("claude", kept).get("model"), settings.get("model"))
|
|
1408
1426
|
settings = {"effort": settings.get("effort")}
|
|
1409
1427
|
flags = settings_argv(provider, settings)
|
|
1410
|
-
model
|
|
1411
|
-
|
|
1428
|
+
model = left or "--model" in flags or "-m" in flags
|
|
1429
|
+
effort = "--effort" in flags or any(codex_effort_ok(value) for value in flags)
|
|
1430
|
+
speed = provider == "codex" and settings.get("speed") in ("normal", "fast", "ultrafast")
|
|
1431
|
+
if provider == "codex" and not model and history_model(settings):
|
|
1412
1432
|
model = effort = True # no launch -m or -c alone: neither, and the thread restores both
|
|
1413
|
-
return head + without_settings(kept, model, effort) + flags + tail
|
|
1433
|
+
return head + without_settings(kept, model, effort, speed) + flags + tail
|
|
1414
1434
|
|
|
1415
1435
|
|
|
1416
1436
|
# ---- relaunch / state files ---------------------------------------------------------
|
|
@@ -2721,7 +2741,7 @@ class Watcher:
|
|
|
2721
2741
|
try:
|
|
2722
2742
|
found = session_settings(self.provider, self.transcript)
|
|
2723
2743
|
self.served_model = history_model(found)
|
|
2724
|
-
if not found.get("model") and not found.get("effort"):
|
|
2744
|
+
if not found.get("model") and not found.get("effort") and not found.get("speed"):
|
|
2725
2745
|
return None
|
|
2726
2746
|
# The catalog only clamps an effort to the model and supplies Codex's default
|
|
2727
2747
|
# one: this pool's copy and caches, the other pool's only when the chain named it.
|