claude-smart 0.2.35 → 0.2.37
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 +1 -1
- package/bin/claude-smart.js +145 -115
- package/package.json +2 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +3 -0
- package/plugin/dashboard/app/configure/env/page.tsx +15 -0
- package/plugin/dashboard/lib/config-file.ts +3 -2
- package/plugin/dashboard/lib/types.ts +1 -1
- package/plugin/pyproject.toml +1 -1
- package/plugin/scripts/_lib.sh +6 -6
- package/plugin/scripts/codex-hook.js +1 -0
- package/plugin/scripts/smart-install.sh +1 -39
- package/plugin/src/claude_smart/cli.py +137 -92
- package/plugin/src/claude_smart/env_config.py +6 -1
- package/plugin/src/claude_smart/events/pre_tool.py +1 -1
- package/plugin/src/claude_smart/events/session_end.py +5 -2
- package/plugin/src/claude_smart/events/stop.py +27 -7
- package/plugin/src/claude_smart/events/user_prompt.py +1 -1
- package/plugin/src/claude_smart/hook.py +22 -2
- package/plugin/src/claude_smart/hook_log.py +7 -2
- package/plugin/src/claude_smart/ids.py +23 -26
- package/plugin/src/claude_smart/internal_call.py +6 -6
- package/plugin/src/claude_smart/publish.py +4 -5
- package/plugin/src/claude_smart/reflexio_adapter.py +2 -3
- package/plugin/src/claude_smart/state.py +9 -0
- package/plugin/uv.lock +16 -13
- package/scripts/setup-claude-smart.sh +329 -0
|
@@ -250,9 +250,8 @@ class Adapter:
|
|
|
250
250
|
def fetch_user_playbooks(self, *, project_id: str, top_k: int = 10) -> list[Any]:
|
|
251
251
|
"""Fetch CURRENT user playbooks for ``project_id``.
|
|
252
252
|
|
|
253
|
-
User playbooks are scoped by the resolved
|
|
254
|
-
the
|
|
255
|
-
Filtering mirrors the publish path
|
|
253
|
+
User playbooks are scoped by the resolved project id. Filtering mirrors
|
|
254
|
+
the publish path
|
|
256
255
|
(``publish_interaction(user_id=project_id, …)``).
|
|
257
256
|
|
|
258
257
|
Args:
|
|
@@ -150,6 +150,15 @@ def append(session_id: str, record: dict[str, Any]) -> None:
|
|
|
150
150
|
fh.write(line)
|
|
151
151
|
|
|
152
152
|
|
|
153
|
+
def mark_all_published(session_id: str) -> None:
|
|
154
|
+
"""Advance the watermark over every currently buffered record.
|
|
155
|
+
|
|
156
|
+
Read-only mode still needs to retire any already-buffered interactions so
|
|
157
|
+
they cannot publish later if learning is re-enabled.
|
|
158
|
+
"""
|
|
159
|
+
append(session_id, {"published_up_to": len(read_all(session_id))})
|
|
160
|
+
|
|
161
|
+
|
|
153
162
|
def read_all(session_id: str) -> list[dict[str, Any]]:
|
|
154
163
|
"""Return every record in the buffer as a list of dicts. Missing file → []."""
|
|
155
164
|
path = session_path(session_id)
|
package/plugin/uv.lock
CHANGED
|
@@ -419,7 +419,7 @@ wheels = [
|
|
|
419
419
|
|
|
420
420
|
[[package]]
|
|
421
421
|
name = "claude-smart"
|
|
422
|
-
version = "0.2.
|
|
422
|
+
version = "0.2.37"
|
|
423
423
|
source = { editable = "." }
|
|
424
424
|
dependencies = [
|
|
425
425
|
{ name = "chromadb" },
|
|
@@ -1179,11 +1179,11 @@ wheels = [
|
|
|
1179
1179
|
|
|
1180
1180
|
[[package]]
|
|
1181
1181
|
name = "json-repair"
|
|
1182
|
-
version = "0.59.
|
|
1182
|
+
version = "0.59.10"
|
|
1183
1183
|
source = { registry = "https://pypi.org/simple" }
|
|
1184
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1184
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d3/7c/e95bb03068572146eba37e8175c760f470ea0a6097310e16bbf2bc6e6457/json_repair-0.59.10.tar.gz", hash = "sha256:2e4b85537c752d8a513ea28fdad891e5ede32c83de745366b97f648b8c34ede7", size = 49133, upload-time = "2026-05-14T06:41:51.222Z" }
|
|
1185
1185
|
wheels = [
|
|
1186
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1186
|
+
{ url = "https://files.pythonhosted.org/packages/ee/87/49b20c6b81493d55c311f711ed87319d0fbad8bd0bbfbe36e52103af36bd/json_repair-0.59.10-py3-none-any.whl", hash = "sha256:5468fa3eaadcc9b4a5646776bc4176e2fe5f374b5848a15f468cce3b60e3db0e", size = 47742, upload-time = "2026-05-14T06:41:49.812Z" },
|
|
1187
1187
|
]
|
|
1188
1188
|
|
|
1189
1189
|
[[package]]
|
|
@@ -1711,11 +1711,14 @@ wheels = [
|
|
|
1711
1711
|
|
|
1712
1712
|
[[package]]
|
|
1713
1713
|
name = "nvidia-cublas"
|
|
1714
|
-
version = "13.1.
|
|
1714
|
+
version = "13.1.1.3"
|
|
1715
1715
|
source = { registry = "https://pypi.org/simple" }
|
|
1716
|
+
dependencies = [
|
|
1717
|
+
{ name = "nvidia-cuda-nvrtc" },
|
|
1718
|
+
]
|
|
1716
1719
|
wheels = [
|
|
1717
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1718
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1720
|
+
{ url = "https://files.pythonhosted.org/packages/a7/a1/0bd24ee8c8d03adac032fd2909426a00c88f8c57961b1277ded97f91119f/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5", size = 542848918, upload-time = "2026-04-08T18:46:22.985Z" },
|
|
1721
|
+
{ url = "https://files.pythonhosted.org/packages/3b/cd/154ca20c38269e05eff77c1464e6c1da89f50a6390b565e9d82e06bc11e1/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:37936a16db8fe4ac1f065c2139360608a543a09275cb1a1af612e08cfa065436", size = 423138758, upload-time = "2026-04-08T18:46:58.655Z" },
|
|
1719
1722
|
]
|
|
1720
1723
|
|
|
1721
1724
|
[[package]]
|
|
@@ -3016,7 +3019,7 @@ wheels = [
|
|
|
3016
3019
|
|
|
3017
3020
|
[[package]]
|
|
3018
3021
|
name = "sentence-transformers"
|
|
3019
|
-
version = "5.
|
|
3022
|
+
version = "5.5.1"
|
|
3020
3023
|
source = { registry = "https://pypi.org/simple" }
|
|
3021
3024
|
dependencies = [
|
|
3022
3025
|
{ name = "huggingface-hub" },
|
|
@@ -3028,9 +3031,9 @@ dependencies = [
|
|
|
3028
3031
|
{ name = "transformers" },
|
|
3029
3032
|
{ name = "typing-extensions" },
|
|
3030
3033
|
]
|
|
3031
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
3034
|
+
sdist = { url = "https://files.pythonhosted.org/packages/cf/d4/7ef93157485e978c016f49da05363c1e4e7237beb5343b64b5631101f0f1/sentence_transformers-5.5.1.tar.gz", hash = "sha256:02b7740dfc60bdbbcb6061625f5d97a5c1a4e2d3baac5f9391b912bb5eae2290", size = 445161, upload-time = "2026-05-20T07:37:44.465Z" }
|
|
3032
3035
|
wheels = [
|
|
3033
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
3036
|
+
{ url = "https://files.pythonhosted.org/packages/bf/03/ee99a6b030e7a2e056547729f8a4709dd93e13d9c6f07590f74c395c4017/sentence_transformers-5.5.1-py3-none-any.whl", hash = "sha256:4fe11d433badc5282d32f7fc08bc714216b7a5aca426f9df77a45a554756deb7", size = 588887, upload-time = "2026-05-20T07:37:43.004Z" },
|
|
3034
3037
|
]
|
|
3035
3038
|
|
|
3036
3039
|
[[package]]
|
|
@@ -3281,7 +3284,7 @@ wheels = [
|
|
|
3281
3284
|
|
|
3282
3285
|
[[package]]
|
|
3283
3286
|
name = "transformers"
|
|
3284
|
-
version = "5.
|
|
3287
|
+
version = "5.9.0"
|
|
3285
3288
|
source = { registry = "https://pypi.org/simple" }
|
|
3286
3289
|
dependencies = [
|
|
3287
3290
|
{ name = "huggingface-hub" },
|
|
@@ -3294,9 +3297,9 @@ dependencies = [
|
|
|
3294
3297
|
{ name = "tqdm" },
|
|
3295
3298
|
{ name = "typer" },
|
|
3296
3299
|
]
|
|
3297
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
3300
|
+
sdist = { url = "https://files.pythonhosted.org/packages/51/58/7f843608f2e8421f86bb97060b54649be6239ec612b82bf9d41e65c26c00/transformers-5.9.0.tar.gz", hash = "sha256:25997cb8fa6053533171634b6162d7df54346530ec2aa9b42bb834e63668c842", size = 8642240, upload-time = "2026-05-20T14:50:49.278Z" }
|
|
3298
3301
|
wheels = [
|
|
3299
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
3302
|
+
{ url = "https://files.pythonhosted.org/packages/02/ca/2eaa5359f2ccb8c2e1656bc26305ad0cf438aa392ce4b29ae67a315c186e/transformers-5.9.0-py3-none-any.whl", hash = "sha256:1d19509bcff7028ebc6b277d71caa712e8353778463d38764237d14b42b52788", size = 10787648, upload-time = "2026-05-20T14:50:45.337Z" },
|
|
3300
3303
|
]
|
|
3301
3304
|
|
|
3302
3305
|
[[package]]
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Interactive setup for claude-smart's shared ~/.reflexio/.env.
|
|
3
|
+
#
|
|
4
|
+
# Plain installs stay local and do not need this script. Use this when a user
|
|
5
|
+
# wants managed Reflexio, read-only mode, global sharing, or to switch back to
|
|
6
|
+
# local mode after a managed setup.
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
11
|
+
REPO_ROOT="$(cd "$HERE/.." && pwd)"
|
|
12
|
+
INSTALLER="$REPO_ROOT/bin/claude-smart.js"
|
|
13
|
+
REFLEXIO_ENV="${REFLEXIO_ENV_PATH:-$HOME/.reflexio/.env}"
|
|
14
|
+
MANAGED_REFLEXIO_URL="https://www.reflexio.ai/"
|
|
15
|
+
GLOBAL_USER_ID="global_user"
|
|
16
|
+
|
|
17
|
+
log() { printf '[claude-smart setup] %s\n' "$*" >&2; }
|
|
18
|
+
|
|
19
|
+
env_unquote() {
|
|
20
|
+
local value first last
|
|
21
|
+
value="$1"
|
|
22
|
+
first="${value%"${value#?}"}"
|
|
23
|
+
last="${value#"${value%?}"}"
|
|
24
|
+
if { [ "$first" = '"' ] && [ "$last" = '"' ]; } || { [ "$first" = "'" ] && [ "$last" = "'" ]; }; then
|
|
25
|
+
value="${value#?}"
|
|
26
|
+
value="${value%?}"
|
|
27
|
+
fi
|
|
28
|
+
printf '%s\n' "$value"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
env_quote() {
|
|
32
|
+
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get_env_value() {
|
|
36
|
+
local key line raw_key value
|
|
37
|
+
key="$1"
|
|
38
|
+
[ -f "$REFLEXIO_ENV" ] || return 1
|
|
39
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
40
|
+
line="${line#"${line%%[![:space:]]*}"}"
|
|
41
|
+
line="${line%"${line##*[![:space:]]}"}"
|
|
42
|
+
[ -n "$line" ] || continue
|
|
43
|
+
case "$line" in
|
|
44
|
+
\#*) continue ;;
|
|
45
|
+
export\ *) line="${line#export }" ;;
|
|
46
|
+
esac
|
|
47
|
+
raw_key="${line%%=*}"
|
|
48
|
+
[ "$raw_key" != "$line" ] || continue
|
|
49
|
+
raw_key="${raw_key%"${raw_key##*[![:space:]]}"}"
|
|
50
|
+
[ "$raw_key" = "$key" ] || continue
|
|
51
|
+
value="${line#*=}"
|
|
52
|
+
value="${value#"${value%%[![:space:]]*}"}"
|
|
53
|
+
value="${value%"${value##*[![:space:]]}"}"
|
|
54
|
+
env_unquote "$value"
|
|
55
|
+
return 0
|
|
56
|
+
done < "$REFLEXIO_ENV"
|
|
57
|
+
return 1
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
remove_env_keys() {
|
|
61
|
+
local tmp line key raw_key remove target
|
|
62
|
+
[ -f "$REFLEXIO_ENV" ] || return 0
|
|
63
|
+
tmp="$(mktemp "${REFLEXIO_ENV}.tmp.XXXXXX")"
|
|
64
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
65
|
+
raw_key="$line"
|
|
66
|
+
raw_key="${raw_key#"${raw_key%%[![:space:]]*}"}"
|
|
67
|
+
case "$raw_key" in
|
|
68
|
+
export\ *) raw_key="${raw_key#export }" ;;
|
|
69
|
+
esac
|
|
70
|
+
key="${raw_key%%=*}"
|
|
71
|
+
key="${key%"${key##*[![:space:]]}"}"
|
|
72
|
+
remove=0
|
|
73
|
+
if [ "$key" != "$raw_key" ]; then
|
|
74
|
+
if [ "$#" -gt 0 ]; then
|
|
75
|
+
for target in "$@"; do
|
|
76
|
+
[ "$key" = "$target" ] && remove=1
|
|
77
|
+
done
|
|
78
|
+
else
|
|
79
|
+
case "$key" in
|
|
80
|
+
REFLEXIO_API_KEY|REFLEXIO_URL|REFLEXIO_USER_ID|CLAUDE_SMART_READ_ONLY)
|
|
81
|
+
remove=1
|
|
82
|
+
;;
|
|
83
|
+
esac
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
[ "$remove" = "1" ] || printf '%s\n' "$line" >> "$tmp"
|
|
87
|
+
done < "$REFLEXIO_ENV"
|
|
88
|
+
|
|
89
|
+
if ! grep -q '[^[:space:]]' "$tmp"; then
|
|
90
|
+
rm -f "$tmp" "$REFLEXIO_ENV"
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
mv "$tmp" "$REFLEXIO_ENV"
|
|
94
|
+
chmod 600 "$REFLEXIO_ENV"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
append_env_value() {
|
|
98
|
+
local key value quoted
|
|
99
|
+
key="$1"
|
|
100
|
+
value="$2"
|
|
101
|
+
quoted="$(env_quote "$value")"
|
|
102
|
+
mkdir -p "$(dirname "$REFLEXIO_ENV")"
|
|
103
|
+
touch "$REFLEXIO_ENV"
|
|
104
|
+
chmod 600 "$REFLEXIO_ENV"
|
|
105
|
+
printf '%s="%s"\n' "$key" "$quoted" >> "$REFLEXIO_ENV"
|
|
106
|
+
chmod 600 "$REFLEXIO_ENV"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
mask_secret() {
|
|
110
|
+
local value len suffix
|
|
111
|
+
value="$1"
|
|
112
|
+
len="${#value}"
|
|
113
|
+
if [ "$len" -eq 0 ]; then
|
|
114
|
+
printf '%s\n' ''
|
|
115
|
+
elif [ "$len" -le 4 ]; then
|
|
116
|
+
printf '****%s\n' "$value"
|
|
117
|
+
else
|
|
118
|
+
suffix="${value: -4}"
|
|
119
|
+
printf '****%s\n' "$suffix"
|
|
120
|
+
fi
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
prompt() {
|
|
124
|
+
local message default answer
|
|
125
|
+
message="$1"
|
|
126
|
+
default="$2"
|
|
127
|
+
if [ -n "$default" ]; then
|
|
128
|
+
printf '%s [%s]: ' "$message" "$default" >&2
|
|
129
|
+
else
|
|
130
|
+
printf '%s: ' "$message" >&2
|
|
131
|
+
fi
|
|
132
|
+
IFS= read -r answer
|
|
133
|
+
if [ -z "$answer" ]; then
|
|
134
|
+
answer="$default"
|
|
135
|
+
fi
|
|
136
|
+
printf '%s\n' "$answer"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
prompt_api_key() {
|
|
140
|
+
local existing masked answer
|
|
141
|
+
existing="$1"
|
|
142
|
+
masked="$(mask_secret "$existing")"
|
|
143
|
+
while :; do
|
|
144
|
+
if [ -n "$existing" ]; then
|
|
145
|
+
printf 'Reflexio API key [%s; press Enter to keep]: ' "$masked" >&2
|
|
146
|
+
else
|
|
147
|
+
printf 'Reflexio API key: ' >&2
|
|
148
|
+
fi
|
|
149
|
+
if [ -t 0 ]; then
|
|
150
|
+
IFS= read -rs answer
|
|
151
|
+
printf '\n' >&2
|
|
152
|
+
else
|
|
153
|
+
IFS= read -r answer
|
|
154
|
+
fi
|
|
155
|
+
if [ -z "$answer" ] && [ -n "$existing" ]; then
|
|
156
|
+
answer="$existing"
|
|
157
|
+
fi
|
|
158
|
+
if [ -z "$answer" ]; then
|
|
159
|
+
log "API key is required for managed Reflexio."
|
|
160
|
+
continue
|
|
161
|
+
fi
|
|
162
|
+
case "$answer" in
|
|
163
|
+
*[[:space:]]*)
|
|
164
|
+
log "API key must not contain whitespace."
|
|
165
|
+
continue
|
|
166
|
+
;;
|
|
167
|
+
esac
|
|
168
|
+
printf '%s\n' "$answer"
|
|
169
|
+
return 0
|
|
170
|
+
done
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
normalize_host() {
|
|
174
|
+
case "$1" in
|
|
175
|
+
1|claude|claude-code|Claude*) printf 'claude-code\n' ;;
|
|
176
|
+
2|codex|Codex*) printf 'codex\n' ;;
|
|
177
|
+
3|both|Both*) printf 'both\n' ;;
|
|
178
|
+
*) return 1 ;;
|
|
179
|
+
esac
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
normalize_mode() {
|
|
183
|
+
case "$1" in
|
|
184
|
+
1|local|Local*) printf 'local\n' ;;
|
|
185
|
+
2|managed|remote|Remote*) printf 'managed\n' ;;
|
|
186
|
+
*) return 1 ;;
|
|
187
|
+
esac
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
normalize_yes_no() {
|
|
191
|
+
case "$1" in
|
|
192
|
+
y|Y|yes|Yes|YES|true|1) printf 'yes\n' ;;
|
|
193
|
+
n|N|no|No|NO|false|0) printf 'no\n' ;;
|
|
194
|
+
*) return 1 ;;
|
|
195
|
+
esac
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
normalize_scope() {
|
|
199
|
+
case "$1" in
|
|
200
|
+
1|project|Project*) printf 'project\n' ;;
|
|
201
|
+
2|global|Global*) printf 'global\n' ;;
|
|
202
|
+
*) return 1 ;;
|
|
203
|
+
esac
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
is_local_url() {
|
|
207
|
+
case "$1" in
|
|
208
|
+
http://localhost|http://localhost/|http://localhost:*|http://127.0.0.1|http://127.0.0.1/|http://127.0.0.1:*|http://0.0.0.0|http://0.0.0.0/|http://0.0.0.0:*)
|
|
209
|
+
return 0
|
|
210
|
+
;;
|
|
211
|
+
*)
|
|
212
|
+
return 1
|
|
213
|
+
;;
|
|
214
|
+
esac
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
prompt_normalized() {
|
|
218
|
+
local label default normalizer answer normalized
|
|
219
|
+
label="$1"
|
|
220
|
+
default="$2"
|
|
221
|
+
normalizer="$3"
|
|
222
|
+
while :; do
|
|
223
|
+
answer="$(prompt "$label" "$default")"
|
|
224
|
+
if normalized="$("$normalizer" "$answer")"; then
|
|
225
|
+
printf '%s\n' "$normalized"
|
|
226
|
+
return 0
|
|
227
|
+
fi
|
|
228
|
+
log "Invalid choice: $answer"
|
|
229
|
+
done
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
install_for_host() {
|
|
233
|
+
local host node_bin
|
|
234
|
+
host="$1"
|
|
235
|
+
if [ "${CLAUDE_SMART_SETUP_NO_INSTALL:-}" = "1" ]; then
|
|
236
|
+
log "skipping plugin install because CLAUDE_SMART_SETUP_NO_INSTALL=1"
|
|
237
|
+
return 0
|
|
238
|
+
fi
|
|
239
|
+
node_bin="${NODE:-node}"
|
|
240
|
+
if [ ! -f "$INSTALLER" ]; then
|
|
241
|
+
log "ERROR: installer not found at $INSTALLER"
|
|
242
|
+
exit 1
|
|
243
|
+
fi
|
|
244
|
+
case "$host" in
|
|
245
|
+
claude-code)
|
|
246
|
+
"$node_bin" "$INSTALLER" install
|
|
247
|
+
;;
|
|
248
|
+
codex)
|
|
249
|
+
"$node_bin" "$INSTALLER" install --host codex
|
|
250
|
+
;;
|
|
251
|
+
both)
|
|
252
|
+
"$node_bin" "$INSTALLER" install
|
|
253
|
+
"$node_bin" "$INSTALLER" install --host codex
|
|
254
|
+
;;
|
|
255
|
+
esac
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
main() {
|
|
259
|
+
local existing_api_key existing_url existing_user_id existing_read_only
|
|
260
|
+
local default_mode default_read_only default_scope host mode api_key read_only scope
|
|
261
|
+
local managed_url managed_user_id
|
|
262
|
+
|
|
263
|
+
existing_api_key="$(get_env_value REFLEXIO_API_KEY || true)"
|
|
264
|
+
existing_url="$(get_env_value REFLEXIO_URL || true)"
|
|
265
|
+
existing_user_id="$(get_env_value REFLEXIO_USER_ID || true)"
|
|
266
|
+
existing_read_only="$(get_env_value CLAUDE_SMART_READ_ONLY || true)"
|
|
267
|
+
|
|
268
|
+
default_mode="local"
|
|
269
|
+
if [ -n "$existing_api_key" ] || [ -n "$existing_url" ]; then
|
|
270
|
+
default_mode="managed"
|
|
271
|
+
fi
|
|
272
|
+
default_read_only="no"
|
|
273
|
+
case "$existing_read_only" in
|
|
274
|
+
1|true|yes|on) default_read_only="yes" ;;
|
|
275
|
+
esac
|
|
276
|
+
default_scope="project"
|
|
277
|
+
if [ -n "$existing_user_id" ]; then
|
|
278
|
+
default_scope="global"
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
host="$(prompt_normalized "Host (1=Claude Code, 2=Codex, 3=both)" "claude-code" normalize_host)"
|
|
282
|
+
mode="$(prompt_normalized "Setup mode (1=local, 2=managed Reflexio)" "$default_mode" normalize_mode)"
|
|
283
|
+
|
|
284
|
+
if [ "$mode" = "local" ]; then
|
|
285
|
+
if [ -f "$REFLEXIO_ENV" ]; then
|
|
286
|
+
remove_env_keys
|
|
287
|
+
log "removed managed Reflexio settings from $REFLEXIO_ENV"
|
|
288
|
+
else
|
|
289
|
+
log "local mode selected; no $REFLEXIO_ENV exists, so no env file was created"
|
|
290
|
+
fi
|
|
291
|
+
install_for_host "$host"
|
|
292
|
+
return 0
|
|
293
|
+
fi
|
|
294
|
+
|
|
295
|
+
api_key="$(prompt_api_key "$existing_api_key")"
|
|
296
|
+
read_only="$(prompt_normalized "Read-only mode? (yes/no)" "$default_read_only" normalize_yes_no)"
|
|
297
|
+
scope="$(prompt_normalized "Sharing scope (1=project, 2=global)" "$default_scope" normalize_scope)"
|
|
298
|
+
|
|
299
|
+
managed_url="${existing_url:-$MANAGED_REFLEXIO_URL}"
|
|
300
|
+
if is_local_url "$managed_url"; then
|
|
301
|
+
managed_url="$MANAGED_REFLEXIO_URL"
|
|
302
|
+
fi
|
|
303
|
+
managed_user_id=""
|
|
304
|
+
if [ "$scope" = "global" ]; then
|
|
305
|
+
managed_user_id="${existing_user_id:-$GLOBAL_USER_ID}"
|
|
306
|
+
fi
|
|
307
|
+
|
|
308
|
+
remove_env_keys \
|
|
309
|
+
REFLEXIO_API_KEY \
|
|
310
|
+
REFLEXIO_URL \
|
|
311
|
+
REFLEXIO_USER_ID \
|
|
312
|
+
CLAUDE_SMART_READ_ONLY \
|
|
313
|
+
CLAUDE_SMART_USE_LOCAL_CLI \
|
|
314
|
+
CLAUDE_SMART_USE_LOCAL_EMBEDDING
|
|
315
|
+
append_env_value REFLEXIO_URL "$managed_url"
|
|
316
|
+
append_env_value REFLEXIO_API_KEY "$api_key"
|
|
317
|
+
if [ "$read_only" = "yes" ]; then
|
|
318
|
+
append_env_value CLAUDE_SMART_READ_ONLY "1"
|
|
319
|
+
fi
|
|
320
|
+
if [ -n "$managed_user_id" ]; then
|
|
321
|
+
append_env_value REFLEXIO_USER_ID "$managed_user_id"
|
|
322
|
+
fi
|
|
323
|
+
chmod 600 "$REFLEXIO_ENV"
|
|
324
|
+
log "configured managed Reflexio in $REFLEXIO_ENV"
|
|
325
|
+
log "If a real API key was pasted visibly into a terminal or chat, rotate it in Reflexio."
|
|
326
|
+
install_for_host "$host"
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
main "$@"
|