@wangxt0223/codex-switcher 0.4.0

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.
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5
+ SW="$ROOT/scripts/codex-sw"
6
+
7
+ bash -n "$SW"
8
+
9
+ TMPBASE="$(mktemp -d /tmp/codex-switcher-test.XXXXXX)"
10
+ STATE="$TMPBASE/state"
11
+ PROFILES="$TMPBASE/profiles"
12
+ BIN="$TMPBASE/bin"
13
+ mkdir -p "$BIN"
14
+
15
+ cleanup() {
16
+ pkill -f "$BIN/fake-codex-app" >/dev/null 2>&1 || true
17
+ rm -rf "$TMPBASE"
18
+ }
19
+ trap cleanup EXIT INT TERM
20
+
21
+ cat > "$BIN/codex" <<'FAKE'
22
+ #!/usr/bin/env bash
23
+ set -euo pipefail
24
+ if [[ "${1:-}" == "login" && "${2:-}" == "status" ]]; then
25
+ if [[ -f "${CODEX_HOME}/auth.json" ]]; then
26
+ echo "Logged in"
27
+ exit 0
28
+ fi
29
+ echo "Not logged in"
30
+ exit 1
31
+ fi
32
+ if [[ "${1:-}" == "login" ]]; then
33
+ mkdir -p "$CODEX_HOME"
34
+ echo '{"auth_mode":"api_key"}' > "$CODEX_HOME/auth.json"
35
+ exit 0
36
+ fi
37
+ if [[ "${1:-}" == "logout" ]]; then
38
+ rm -f "$CODEX_HOME/auth.json"
39
+ exit 0
40
+ fi
41
+ exit 0
42
+ FAKE
43
+ chmod +x "$BIN/codex"
44
+
45
+ cat > "$BIN/fake-codex-app" <<'APP'
46
+ #!/usr/bin/env bash
47
+ set -euo pipefail
48
+ sleep 30
49
+ APP
50
+ chmod +x "$BIN/fake-codex-app"
51
+
52
+ cat > "$BIN/npm" <<'NPM'
53
+ #!/usr/bin/env bash
54
+ set -euo pipefail
55
+ echo "$*" > "${CODEX_SWITCHER_TEST_NPM_LOG:?}"
56
+ exit 0
57
+ NPM
58
+ chmod +x "$BIN/npm"
59
+
60
+ export PATH="$BIN:$PATH"
61
+ export CODEX_SWITCHER_STATE_DIR="$STATE"
62
+ export CODEX_SWITCHER_PROFILES_DIR="$PROFILES"
63
+ export CODEX_SWITCHER_APP_BIN="$BIN/fake-codex-app"
64
+ export CODEX_SWITCHER_LOCK_WAIT_SECONDS=2
65
+ export CODEX_SWITCHER_DEFAULT_HOME="$TMPBASE/default-home"
66
+ export CODEX_SWITCHER_TEST_NPM_LOG="$TMPBASE/npm-args.log"
67
+
68
+ mkdir -p "$CODEX_SWITCHER_DEFAULT_HOME/memories"
69
+ echo '{"auth_mode":"chatgpt"}' > "$CODEX_SWITCHER_DEFAULT_HOME/auth.json"
70
+ echo '{"projects":["demo"]}' > "$CODEX_SWITCHER_DEFAULT_HOME/state_5.sqlite"
71
+ echo '{"memo":"persist"}' > "$CODEX_SWITCHER_DEFAULT_HOME/memories/demo.json"
72
+
73
+ check_out="$("$SW" check)"
74
+ echo "$check_out" | grep -q "check: ok"
75
+ init_out="$("$SW" init --dry-run)"
76
+ echo "$init_out" | grep -q "\[dry-run\]"
77
+ "$SW" upgrade
78
+ grep -q "i -g @wangxt0223/codex-switcher@latest --registry https://registry.npmjs.org/" "$CODEX_SWITCHER_TEST_NPM_LOG"
79
+
80
+ "$SW" add work
81
+ "$SW" add personal
82
+ "$SW" use personal
83
+ [[ "$("$SW" current cli)" == "personal" ]]
84
+
85
+ "$SW" login personal
86
+ "$SW" login sync-login --sync
87
+ [[ -f "$PROFILES/sync-login/state_5.sqlite" ]]
88
+ [[ -f "$PROFILES/sync-login/memories/demo.json" ]]
89
+ [[ -f "$PROFILES/sync-login/auth.json" ]]
90
+
91
+ echo '{"auth_mode":"api_key","owner":"personal"}' > "$PROFILES/personal/auth.json"
92
+ echo '{"auth_mode":"api_key","owner":"work"}' > "$PROFILES/work/auth.json"
93
+ echo "from-personal-newer" > "$PROFILES/personal/history.jsonl"
94
+ echo "from-work-older-baseline" > "$PROFILES/work/history.jsonl"
95
+ "$SW" switch work --sync
96
+ [[ "$("$SW" current cli)" == "work" ]]
97
+ grep -q "from-personal-newer" "$PROFILES/work/history.jsonl"
98
+ grep -q '"owner":"work"' "$PROFILES/work/auth.json"
99
+ grep -q '"owner":"personal"' "$PROFILES/personal/auth.json"
100
+
101
+ "$SW" import-default imported
102
+ [[ -f "$PROFILES/imported/state_5.sqlite" ]]
103
+ [[ -f "$PROFILES/imported/memories/demo.json" ]]
104
+ [[ ! -f "$PROFILES/imported/auth.json" ]]
105
+ set +e
106
+ CODEX_HOME="$PROFILES/imported" codex login status >/tmp/codex_sw_imported_login 2>&1
107
+ imported_login_rc=$?
108
+ set -e
109
+ [[ "$imported_login_rc" -ne 0 ]]
110
+
111
+ "$SW" import-default imported-auth --with-auth
112
+ [[ -f "$PROFILES/imported-auth/auth.json" ]]
113
+ CODEX_HOME="$PROFILES/imported-auth" codex login status >/tmp/codex_sw_imported_auth_login 2>&1
114
+ [[ "$?" -eq 0 ]]
115
+
116
+ "$SW" logout work
117
+
118
+ set +e
119
+ "$SW" app open ghost >/tmp/codex_sw_app_open_missing 2>&1
120
+ app_open_missing_rc=$?
121
+ set -e
122
+ [[ "$app_open_missing_rc" -ne 0 ]]
123
+ grep -q "profile 'ghost' not found" /tmp/codex_sw_app_open_missing
124
+
125
+ set +e
126
+ "$SW" app use work >/tmp/codex_sw_app_use_unauthed 2>&1
127
+ app_use_unauthed_rc=$?
128
+ set -e
129
+ [[ "$app_use_unauthed_rc" -ne 0 ]]
130
+ grep -q "profile 'work' is not logged in" /tmp/codex_sw_app_use_unauthed
131
+
132
+ "$SW" login work
133
+ "$SW" app use work
134
+ [[ "$("$SW" app current)" == "work" ]]
135
+
136
+ set +e
137
+ "$SW" status >/tmp/codex_sw_status_1
138
+ status_rc=$?
139
+ set -e
140
+ [[ "$status_rc" -eq 0 ]]
141
+ grep -q "cli(work): logged-in" /tmp/codex_sw_status_1
142
+ grep -q "app(work): logged-in" /tmp/codex_sw_status_1
143
+
144
+ "$SW" logout work
145
+ set +e
146
+ "$SW" status >/tmp/codex_sw_status_2
147
+ status_rc=$?
148
+ set -e
149
+ [[ "$status_rc" -eq 1 ]]
150
+ grep -q "cli(work): not-logged-in" /tmp/codex_sw_status_2
151
+
152
+ "$SW" app status >/tmp/codex_sw_app_status_1
153
+ [[ "$?" -eq 0 ]]
154
+ grep -q "running" /tmp/codex_sw_app_status_1
155
+
156
+ "$SW" app stop
157
+ set +e
158
+ "$SW" app status >/tmp/codex_sw_app_status_2
159
+ app_status_rc=$?
160
+ set -e
161
+ [[ "$app_status_rc" -eq 1 ]]
162
+
163
+ printf '***bad***\n' > "$STATE/current_cli"
164
+ set +e
165
+ "$SW" status >/tmp/codex_sw_status_3
166
+ status_rc=$?
167
+ set -e
168
+ [[ "$status_rc" -eq 2 ]]
169
+
170
+ "$SW" recover
171
+ validate_cli="$("$SW" current cli)"
172
+ [[ -n "$validate_cli" ]]
173
+
174
+ doctor_out="$("$SW" doctor --fix)"
175
+ echo "$doctor_out" | grep -q "doctor --fix: completed"
176
+ check_out="$("$SW" check)"
177
+ echo "$check_out" | grep -q "check: ok"
178
+
179
+ "$SW" remove work --force
180
+ "$SW" list >/tmp/codex_sw_list
181
+ grep -q "personal" /tmp/codex_sw_list
182
+
183
+ echo "smoke-test: ok"
@@ -0,0 +1,3 @@
1
+ # Skills
2
+
3
+ Place plugin-specific skills here if needed.
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5
+ BIN="$ROOT/plugins/codex-switcher/scripts/codex-sw"
6
+
7
+ [[ -x "$BIN" ]] || { echo "codex-sw binary not executable: $BIN" >&2; exit 1; }
8
+
9
+ mkdir -p "$HOME/.local/bin"
10
+ ln -sf "$BIN" "$HOME/.local/bin/codex-sw"
11
+ ln -sf "$ROOT/plugins/codex-switcher/scripts/codex-switcher" "$HOME/.local/bin/codex-switcher"
12
+
13
+ "$BIN" init --shell "$(basename "${SHELL:-zsh}")"
14
+
15
+ echo "Installed codex-sw. Run: source ~/.zshrc (or your shell rc file)"
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ PURGE="false"
5
+ if [[ "${1:-}" == "--purge" ]]; then
6
+ PURGE="true"
7
+ elif [[ -n "${1:-}" ]]; then
8
+ echo "Usage: $0 [--purge]" >&2
9
+ exit 1
10
+ fi
11
+
12
+ remove_block() {
13
+ local file="$1"
14
+ local start="# >>> codex-sw init >>>"
15
+ local end="# <<< codex-sw init <<<"
16
+ [[ -f "$file" ]] || return 0
17
+
18
+ awk -v s="$start" -v e="$end" '
19
+ $0 == s {skip=1; next}
20
+ $0 == e {skip=0; next}
21
+ skip != 1 {print}
22
+ ' "$file" > "$file.tmp"
23
+ mv "$file.tmp" "$file"
24
+ }
25
+
26
+ rm -f "$HOME/.local/bin/codex-sw" "$HOME/.local/bin/codex-switcher"
27
+ remove_block "$HOME/.zshrc"
28
+ remove_block "$HOME/.bashrc"
29
+
30
+ if [[ "$PURGE" == "true" ]]; then
31
+ rm -rf "$HOME/.codex-switcher" "$HOME/.codex-profiles"
32
+ fi
33
+
34
+ echo "Uninstalled codex-sw."
35
+ if [[ "$PURGE" == "true" ]]; then
36
+ echo "State and profiles removed."
37
+ fi