claude-smart 0.2.48 → 0.2.49
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +6 -2
- package/bin/claude-smart.js +289 -56
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/opencode/dist/server.mjs +60 -2
- package/plugin/opencode/server.mts +64 -2
- package/plugin/pyproject.toml +2 -2
- package/plugin/scripts/_lib.sh +58 -6
- package/plugin/scripts/backend-service.sh +15 -10
- package/plugin/scripts/codex-hook.js +16 -4
- package/plugin/scripts/dashboard-service.sh +1 -1
- package/plugin/scripts/ensure-plugin-root.sh +106 -8
- package/plugin/scripts/opencode-claude-compat.js +8 -1
- package/plugin/scripts/smart-install.sh +101 -20
- package/plugin/src/README.md +1 -1
- package/plugin/src/claude_smart/cli.py +79 -29
- package/plugin/src/claude_smart/env_config.py +53 -11
- package/plugin/uv.lock +5 -5
- package/plugin/vendor/reflexio/reflexio/cli/README.md +3 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +40 -6
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +18 -0
- package/plugin/vendor/reflexio/reflexio/server/api.py +15 -4
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_text_generation.py +1 -1
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +183 -1
- package/plugin/vendor/reflexio/reflexio/server/routes/interactions.py +63 -2
- package/plugin/vendor/reflexio/reflexio/server/services/durable_learning/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/durable_learning/scheduler.py +142 -0
- package/plugin/vendor/reflexio/reflexio/server/services/durable_learning/worker.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +1 -3
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +150 -37
- package/plugin/vendor/reflexio/reflexio/server/services/profile/service.py +44 -22
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +140 -2
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_learning_jobs.py +379 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +11 -5
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +8 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/_fts_vec.py +86 -2
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +16 -7
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_source_linkage.py +8 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +12 -5
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_interaction_store.py +52 -7
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_profile_store.py +28 -4
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_commit_scope.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_learning_jobs.py +219 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_interaction_store.py +23 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_profile_store.py +22 -0
|
@@ -85,6 +85,8 @@ write_failure() {
|
|
|
85
85
|
local reason fp_hash
|
|
86
86
|
reason="$1"
|
|
87
87
|
fp_hash="$(claude_smart_install_fingerprint_hash "$PLUGIN_ROOT" "$HERE" 2>/dev/null || true)"
|
|
88
|
+
# bin/claude-smart.js reads this marker too: first line is the user-facing
|
|
89
|
+
# failure reason, and fingerprint=... marks which install attempt produced it.
|
|
88
90
|
{
|
|
89
91
|
printf '%s\n' "$reason"
|
|
90
92
|
if [ -n "$fp_hash" ]; then
|
|
@@ -97,6 +99,22 @@ write_failure() {
|
|
|
97
99
|
exit 0
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
verify_windows_local_embedding_runtime() {
|
|
103
|
+
claude_smart_is_windows || return 0
|
|
104
|
+
[ "${CLAUDE_SMART_USE_LOCAL_EMBEDDING:-1}" = "1" ] || return 0
|
|
105
|
+
if claude_smart_python_imports "$PLUGIN_ROOT" onnxruntime; then
|
|
106
|
+
return 0
|
|
107
|
+
fi
|
|
108
|
+
write_failure "Windows local embedding requires Microsoft Visual C++ Redistributable for onnxruntime; install the x64 redistributable from https://aka.ms/vs/17/release/vc_redist.x64.exe and rerun claude-smart install."
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if [ "${1:-}" = "verify-windows-embedding" ]; then
|
|
112
|
+
# Node bootstrap runs this after uv sync so install-failed markers stay
|
|
113
|
+
# consistent with the shell installer path.
|
|
114
|
+
verify_windows_local_embedding_runtime
|
|
115
|
+
exit 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
100
118
|
install_fingerprint() {
|
|
101
119
|
claude_smart_install_fingerprint "$PLUGIN_ROOT" "$HERE"
|
|
102
120
|
}
|
|
@@ -112,6 +130,7 @@ install_complete() {
|
|
|
112
130
|
grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_USE_LOCAL_CLI=' "$HOME/.claude-smart/.env" || return 1
|
|
113
131
|
grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_USE_LOCAL_EMBEDDING=' "$HOME/.claude-smart/.env" || return 1
|
|
114
132
|
grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_READ_ONLY=' "$HOME/.claude-smart/.env" || return 1
|
|
133
|
+
grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_HOST=' "$HOME/.claude-smart/.env" || return 1
|
|
115
134
|
fi
|
|
116
135
|
if [ -d "$PLUGIN_ROOT/dashboard" ]; then
|
|
117
136
|
[ -d "$PLUGIN_ROOT/dashboard/.next" ] || [ -f "$MARKER_DIR/dashboard-build.pid" ] || [ -f "$(claude_smart_dashboard_unavailable_marker)" ] || return 1
|
|
@@ -196,7 +215,7 @@ install_private_node() {
|
|
|
196
215
|
local NODE_MIN_MAJOR NODE_MIN_MINOR NODE_LTS_MAJOR
|
|
197
216
|
local node_os archive_ext reason node_arch node_platform base_url node_root
|
|
198
217
|
local tmp_dir shasums_path archive_name ext_re install_dir archive_path
|
|
199
|
-
local expected_hash actual_hash archive_win dest_win candidate_path next_link
|
|
218
|
+
local expected_hash actual_hash archive_win dest_win candidate_path next_link old_current
|
|
200
219
|
|
|
201
220
|
NODE_MIN_MAJOR=20
|
|
202
221
|
NODE_MIN_MINOR=9
|
|
@@ -361,19 +380,57 @@ install_private_node() {
|
|
|
361
380
|
return 1
|
|
362
381
|
fi
|
|
363
382
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
383
|
+
if claude_smart_is_windows; then
|
|
384
|
+
# Windows cannot rely on the POSIX symlink swap path; keep current recoverable.
|
|
385
|
+
old_current="$node_root/current.old.$$"
|
|
386
|
+
rm -rf "$old_current" 2>/dev/null || true
|
|
387
|
+
if [ -e "$node_root/current" ] || [ -L "$node_root/current" ]; then
|
|
388
|
+
if ! mv "$node_root/current" "$old_current"; then
|
|
389
|
+
rm -rf "$tmp_dir" "$install_dir"
|
|
390
|
+
reason="could not stage existing private Node.js install for replacement"
|
|
391
|
+
echo "[claude-smart] WARNING: $reason" >&2
|
|
392
|
+
claude_smart_write_dashboard_unavailable "$reason"
|
|
393
|
+
return 1
|
|
394
|
+
fi
|
|
395
|
+
fi
|
|
396
|
+
if mv "$install_dir" "$node_root/current"; then
|
|
397
|
+
rm -rf "$old_current" 2>/dev/null || true
|
|
370
398
|
else
|
|
371
|
-
|
|
372
|
-
|
|
399
|
+
reason="could not activate private Node.js install at $node_root/current"
|
|
400
|
+
if [ -e "$node_root/current" ] || [ -L "$node_root/current" ]; then
|
|
401
|
+
if ! rm -rf "$node_root/current"; then
|
|
402
|
+
reason="could not remove failed private Node.js install at $node_root/current; previous install remains at $old_current for manual recovery"
|
|
403
|
+
rm -rf "$tmp_dir" "$install_dir"
|
|
404
|
+
echo "[claude-smart] WARNING: $reason" >&2
|
|
405
|
+
claude_smart_write_dashboard_unavailable "$reason"
|
|
406
|
+
return 1
|
|
407
|
+
fi
|
|
408
|
+
fi
|
|
409
|
+
if [ -e "$old_current" ] || [ -L "$old_current" ]; then
|
|
410
|
+
if ! mv "$old_current" "$node_root/current"; then
|
|
411
|
+
reason="could not restore previous private Node.js install from $old_current after activation failure; previous install remains at $old_current for manual recovery"
|
|
412
|
+
fi
|
|
413
|
+
fi
|
|
414
|
+
rm -rf "$tmp_dir" "$install_dir"
|
|
415
|
+
echo "[claude-smart] WARNING: $reason" >&2
|
|
416
|
+
claude_smart_write_dashboard_unavailable "$reason"
|
|
417
|
+
return 1
|
|
373
418
|
fi
|
|
374
419
|
else
|
|
375
|
-
|
|
376
|
-
|
|
420
|
+
next_link="$node_root/current.next.$$"
|
|
421
|
+
if ln -s "$install_dir" "$next_link" 2>/dev/null; then
|
|
422
|
+
if mv -Tf "$next_link" "$node_root/current" 2>/dev/null; then
|
|
423
|
+
:
|
|
424
|
+
elif mv -hf "$next_link" "$node_root/current" 2>/dev/null; then
|
|
425
|
+
:
|
|
426
|
+
else
|
|
427
|
+
rm -rf "$node_root/current"
|
|
428
|
+
mv "$next_link" "$node_root/current"
|
|
429
|
+
fi
|
|
430
|
+
else
|
|
431
|
+
rm -rf "$next_link" "$node_root/current"
|
|
432
|
+
mv "$install_dir" "$node_root/current"
|
|
433
|
+
fi
|
|
377
434
|
fi
|
|
378
435
|
|
|
379
436
|
rm -rf "$tmp_dir"
|
|
@@ -399,6 +456,7 @@ fi
|
|
|
399
456
|
preflight_supported_runtime_platform
|
|
400
457
|
|
|
401
458
|
if install_complete; then
|
|
459
|
+
verify_windows_local_embedding_runtime
|
|
402
460
|
start_backend_service
|
|
403
461
|
claude_smart_emit_continue
|
|
404
462
|
exit 0
|
|
@@ -489,7 +547,7 @@ fi
|
|
|
489
547
|
# claude-smart's backend loads ~/.claude-smart/.env (backend-service.sh exports
|
|
490
548
|
# REFLEXIO_ENV_FILE so reflexio's CLI reads it instead of ~/.reflexio/.env);
|
|
491
549
|
# append our opt-in flags there so `reflexio services start` picks them up. Keep
|
|
492
|
-
# this path in sync with env_config.
|
|
550
|
+
# this path in sync with env_config.CLAUDE_SMART_ENV_PATH and backend-service.sh.
|
|
493
551
|
REFLEXIO_ENV="$HOME/.claude-smart/.env"
|
|
494
552
|
mkdir -p "$(dirname "$REFLEXIO_ENV")"
|
|
495
553
|
claude_smart_env_quote() {
|
|
@@ -562,6 +620,9 @@ claude_smart_prune_managed_env_keys_for_local() {
|
|
|
562
620
|
}
|
|
563
621
|
|
|
564
622
|
claude_smart_ensure_local_env_defaults() {
|
|
623
|
+
local local_cli_default local_embedding_default
|
|
624
|
+
local_cli_default="${CLAUDE_SMART_USE_LOCAL_CLI:-1}"
|
|
625
|
+
local_embedding_default="${CLAUDE_SMART_USE_LOCAL_EMBEDDING:-1}"
|
|
565
626
|
[ -z "${REFLEXIO_API_KEY:-}" ] || return 0
|
|
566
627
|
mkdir -p "$(dirname "$REFLEXIO_ENV")"
|
|
567
628
|
touch "$REFLEXIO_ENV"
|
|
@@ -569,23 +630,29 @@ claude_smart_ensure_local_env_defaults() {
|
|
|
569
630
|
claude_smart_prune_managed_env_keys_for_local
|
|
570
631
|
unset REFLEXIO_URL REFLEXIO_API_KEY REFLEXIO_USER_ID CLAUDE_SMART_MANAGED_SETUP
|
|
571
632
|
if ! grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_USE_LOCAL_CLI=' "$REFLEXIO_ENV"; then
|
|
572
|
-
printf '# Route reflexio generation through the local
|
|
573
|
-
claude_smart_env_append_raw_if_missing CLAUDE_SMART_USE_LOCAL_CLI "
|
|
574
|
-
echo "[claude-smart] appended CLAUDE_SMART_USE_LOCAL_CLI
|
|
633
|
+
printf '# Route reflexio generation through the configured local host CLI\n' >> "$REFLEXIO_ENV"
|
|
634
|
+
claude_smart_env_append_raw_if_missing CLAUDE_SMART_USE_LOCAL_CLI "$local_cli_default"
|
|
635
|
+
echo "[claude-smart] appended CLAUDE_SMART_USE_LOCAL_CLI=$local_cli_default to $REFLEXIO_ENV" >&2
|
|
575
636
|
fi
|
|
576
637
|
if ! grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_USE_LOCAL_EMBEDDING=' "$REFLEXIO_ENV"; then
|
|
577
638
|
printf '# Use the in-process ONNX embedder (chromadb) - no API key for semantic search\n' >> "$REFLEXIO_ENV"
|
|
578
|
-
claude_smart_env_append_raw_if_missing CLAUDE_SMART_USE_LOCAL_EMBEDDING "
|
|
579
|
-
echo "[claude-smart] appended CLAUDE_SMART_USE_LOCAL_EMBEDDING
|
|
639
|
+
claude_smart_env_append_raw_if_missing CLAUDE_SMART_USE_LOCAL_EMBEDDING "$local_embedding_default"
|
|
640
|
+
echo "[claude-smart] appended CLAUDE_SMART_USE_LOCAL_EMBEDDING=$local_embedding_default to $REFLEXIO_ENV" >&2
|
|
580
641
|
fi
|
|
581
642
|
if ! grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_READ_ONLY=' "$REFLEXIO_ENV"; then
|
|
582
643
|
claude_smart_env_upsert CLAUDE_SMART_READ_ONLY "0"
|
|
583
644
|
echo "[claude-smart] appended CLAUDE_SMART_READ_ONLY=0 to $REFLEXIO_ENV" >&2
|
|
584
645
|
fi
|
|
646
|
+
if ! grep -qE '^(export[[:space:]]+)?CLAUDE_SMART_HOST=' "$REFLEXIO_ENV"; then
|
|
647
|
+
claude_smart_env_upsert CLAUDE_SMART_HOST "claude-code"
|
|
648
|
+
echo "[claude-smart] appended CLAUDE_SMART_HOST=claude-code to $REFLEXIO_ENV" >&2
|
|
649
|
+
fi
|
|
585
650
|
chmod 600 "$REFLEXIO_ENV"
|
|
586
651
|
}
|
|
587
652
|
|
|
588
653
|
claude_smart_ensure_local_env_defaults
|
|
654
|
+
# No-op outside Git Bash/MSYS/Cygwin; non-Windows installs must not depend on it.
|
|
655
|
+
verify_windows_local_embedding_runtime
|
|
589
656
|
|
|
590
657
|
# Migrate stale REFLEXIO_URL from reflexio's library default (8081) to the
|
|
591
658
|
# plugin backend port (8071). Matches the quoted and unquoted forms but
|
|
@@ -599,9 +666,23 @@ if [ -f "$REFLEXIO_ENV" ] && grep -qE '^REFLEXIO_URL=("http://localhost:8081/?"|
|
|
|
599
666
|
echo "[claude-smart] migrated REFLEXIO_URL 8081 → 8071 in $REFLEXIO_ENV (backup at $REFLEXIO_ENV.bak)" >&2
|
|
600
667
|
fi
|
|
601
668
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
669
|
+
case "${CLAUDE_SMART_HOST:-claude-code}" in
|
|
670
|
+
opencode)
|
|
671
|
+
if [ -z "${CLAUDE_SMART_OPENCODE_PATH:-}" ] && ! command -v opencode >/dev/null 2>&1; then
|
|
672
|
+
echo "[claude-smart] WARNING: 'opencode' CLI not on PATH and CLAUDE_SMART_OPENCODE_PATH is not set — reflexio extractors will have no LLM until OpenCode is installed" >&2
|
|
673
|
+
fi
|
|
674
|
+
;;
|
|
675
|
+
codex)
|
|
676
|
+
if ! command -v codex >/dev/null 2>&1; then
|
|
677
|
+
echo "[claude-smart] WARNING: 'codex' CLI not on PATH — reflexio extractors will have no LLM until Codex is installed" >&2
|
|
678
|
+
fi
|
|
679
|
+
;;
|
|
680
|
+
*)
|
|
681
|
+
if ! command -v claude >/dev/null 2>&1; then
|
|
682
|
+
echo "[claude-smart] WARNING: 'claude' CLI not on PATH — reflexio extractors will have no LLM until Claude Code is installed" >&2
|
|
683
|
+
fi
|
|
684
|
+
;;
|
|
685
|
+
esac
|
|
605
686
|
|
|
606
687
|
LEGACY_CS_CITE="$HOME/.claude-smart/bin/cs-cite"
|
|
607
688
|
if [ -e "$LEGACY_CS_CITE" ]; then
|
package/plugin/src/README.md
CHANGED
|
@@ -28,7 +28,7 @@ Description: Python package powering the claude-smart plugin — hook handlers t
|
|
|
28
28
|
|
|
29
29
|
| File | Purpose |
|
|
30
30
|
|------|---------|
|
|
31
|
-
| `env_config.py` | Parses `~/.claude-smart/.env` (`REFLEXIO_URL`, `REFLEXIO_API_KEY`, `CLAUDE_SMART_READ_ONLY`, local embedding/CLI flags). |
|
|
31
|
+
| `env_config.py` | Parses `~/.claude-smart/.env` (`REFLEXIO_URL`, `REFLEXIO_API_KEY`, `CLAUDE_SMART_READ_ONLY`, `CLAUDE_SMART_HOST`, local embedding/CLI flags). |
|
|
32
32
|
| `runtime.py` | Host detection (Claude Code vs Codex); shared agent version. |
|
|
33
33
|
| `ids.py` | Session / project ID generation and resolution. |
|
|
34
34
|
| `context_inject.py`, `context_format.py`, `query_compose.py`, `cs_cite.py` | Build search queries, format learned skills as markdown, inject into context, format citations. |
|
|
@@ -37,10 +37,14 @@ from pathlib import Path
|
|
|
37
37
|
from urllib.parse import urlparse
|
|
38
38
|
from urllib.request import url2pathname
|
|
39
39
|
|
|
40
|
-
from claude_smart import context_format, cs_cite, env_config, ids, publish, state
|
|
40
|
+
from claude_smart import context_format, cs_cite, env_config, ids, publish, runtime, state
|
|
41
41
|
from claude_smart.reflexio_adapter import Adapter
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
_HOST_CLAUDE_CODE = runtime.HOST_CLAUDE_CODE
|
|
44
|
+
_HOST_CODEX = runtime.HOST_CODEX
|
|
45
|
+
_HOST_OPENCODE = runtime.HOST_OPENCODE
|
|
46
|
+
_HOST_CHOICES = (_HOST_CLAUDE_CODE, _HOST_CODEX, _HOST_OPENCODE)
|
|
47
|
+
_CLAUDE_SMART_ENV_PATH = env_config.CLAUDE_SMART_ENV_PATH
|
|
44
48
|
_MANAGED_REFLEXIO_URL = env_config.MANAGED_REFLEXIO_URL
|
|
45
49
|
_PLUGIN_SPEC = "claude-smart@reflexioai"
|
|
46
50
|
_CODEX_MARKETPLACE_NAME = "reflexioai"
|
|
@@ -99,6 +103,7 @@ _DEFAULT_STORAGE_ROOT = _REFLEXIO_DIR / "data"
|
|
|
99
103
|
_REFLEXIO_ORG_ID = "claude-smart"
|
|
100
104
|
_REFLEXIO_CONFIG_PATH = _REFLEXIO_DIR / "configs" / f"config_{_REFLEXIO_ORG_ID}.json"
|
|
101
105
|
_LOCAL_STORAGE_ENV = "LOCAL_STORAGE_PATH"
|
|
106
|
+
_OPENCODE_PATH_ENV = "CLAUDE_SMART_OPENCODE_PATH"
|
|
102
107
|
_CODEX_REQUIRED_FILES = (
|
|
103
108
|
Path(".agents/plugins/marketplace.json"),
|
|
104
109
|
Path("plugin/.codex-plugin/plugin.json"),
|
|
@@ -927,15 +932,20 @@ def _register_codex_marketplace(root: Path) -> tuple[bool, str]:
|
|
|
927
932
|
return False, output or "Codex CLI does not expose plugin marketplace commands"
|
|
928
933
|
|
|
929
934
|
|
|
930
|
-
def _configure_reflexio_setup() -> bool:
|
|
935
|
+
def _configure_reflexio_setup(host: str = _HOST_CLAUDE_CODE) -> bool:
|
|
931
936
|
"""Load setup state and ensure local defaults when unmanaged.
|
|
932
937
|
|
|
938
|
+
Args:
|
|
939
|
+
host: Host integration being installed. Persisted in local mode so
|
|
940
|
+
later backend restarts can wire the same extraction bridge even
|
|
941
|
+
when the host plugin server is not the process launcher.
|
|
942
|
+
|
|
933
943
|
Returns:
|
|
934
944
|
bool: Whether read-only mode is enabled.
|
|
935
945
|
"""
|
|
936
|
-
env_config.load_reflexio_env(
|
|
946
|
+
env_config.load_reflexio_env(_CLAUDE_SMART_ENV_PATH)
|
|
937
947
|
try:
|
|
938
|
-
env_text =
|
|
948
|
+
env_text = _CLAUDE_SMART_ENV_PATH.read_text()
|
|
939
949
|
except OSError:
|
|
940
950
|
env_text = ""
|
|
941
951
|
read_only_value = ""
|
|
@@ -975,9 +985,9 @@ def _configure_reflexio_setup() -> bool:
|
|
|
975
985
|
os.environ.pop(env_config.REFLEXIO_API_KEY_ENV, None)
|
|
976
986
|
os.environ.pop("REFLEXIO_USER_ID", None)
|
|
977
987
|
os.environ.pop("CLAUDE_SMART_MANAGED_SETUP", None)
|
|
978
|
-
added = env_config.ensure_local_env_defaults(
|
|
988
|
+
added = env_config.ensure_local_env_defaults(_CLAUDE_SMART_ENV_PATH, host=host)
|
|
979
989
|
if added:
|
|
980
|
-
sys.stdout.write(f"Seeded {
|
|
990
|
+
sys.stdout.write(f"Seeded {_CLAUDE_SMART_ENV_PATH} with {', '.join(added)}.\n")
|
|
981
991
|
return read_only
|
|
982
992
|
|
|
983
993
|
|
|
@@ -1174,7 +1184,7 @@ def _patch_opencode_plugin_config(
|
|
|
1174
1184
|
|
|
1175
1185
|
|
|
1176
1186
|
def _has_extraction_provider() -> bool:
|
|
1177
|
-
env_config.load_reflexio_env(
|
|
1187
|
+
env_config.load_reflexio_env(_CLAUDE_SMART_ENV_PATH)
|
|
1178
1188
|
if os.environ.get(env_config.REFLEXIO_API_KEY_ENV, "").strip():
|
|
1179
1189
|
return True
|
|
1180
1190
|
cli_path = os.environ.get("CLAUDE_SMART_CLI_PATH", "").strip()
|
|
@@ -1182,7 +1192,7 @@ def _has_extraction_provider() -> bool:
|
|
|
1182
1192
|
resolved = Path(cli_path).expanduser()
|
|
1183
1193
|
if resolved.is_file() and os.access(resolved, os.X_OK):
|
|
1184
1194
|
return True
|
|
1185
|
-
return bool(shutil.which("claude") or shutil.which("codex") or
|
|
1195
|
+
return bool(shutil.which("claude") or shutil.which("codex") or _resolve_opencode_path())
|
|
1186
1196
|
|
|
1187
1197
|
|
|
1188
1198
|
def _extraction_provider_error() -> str:
|
|
@@ -1193,6 +1203,41 @@ def _extraction_provider_error() -> str:
|
|
|
1193
1203
|
)
|
|
1194
1204
|
|
|
1195
1205
|
|
|
1206
|
+
def _has_opencode_cli() -> bool:
|
|
1207
|
+
return _resolve_opencode_path() is not None
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
def _resolve_opencode_path() -> str | None:
|
|
1211
|
+
opencode_path = os.environ.get(_OPENCODE_PATH_ENV, "").strip()
|
|
1212
|
+
if opencode_path:
|
|
1213
|
+
resolved = Path(opencode_path).expanduser()
|
|
1214
|
+
if resolved.is_file() and os.access(resolved, os.X_OK):
|
|
1215
|
+
return str(resolved)
|
|
1216
|
+
return shutil.which("opencode")
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
def _persist_opencode_path() -> list[str]:
|
|
1220
|
+
resolved = _resolve_opencode_path()
|
|
1221
|
+
if not resolved:
|
|
1222
|
+
return []
|
|
1223
|
+
os.environ[_OPENCODE_PATH_ENV] = resolved
|
|
1224
|
+
return env_config.set_env_vars(_CLAUDE_SMART_ENV_PATH, {_OPENCODE_PATH_ENV: resolved})
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
def _opencode_prerequisite_error() -> str | None:
|
|
1228
|
+
if not _has_opencode_cli():
|
|
1229
|
+
return (
|
|
1230
|
+
"error: OpenCode CLI not found on PATH. Install OpenCode first, "
|
|
1231
|
+
"or set CLAUDE_SMART_OPENCODE_PATH to the OpenCode executable.\n"
|
|
1232
|
+
)
|
|
1233
|
+
if os.name == "nt" and not _resolve_bash():
|
|
1234
|
+
return (
|
|
1235
|
+
"error: Git Bash is required for claude-smart OpenCode support on Windows. "
|
|
1236
|
+
"Install Git for Windows and ensure bash.exe is on PATH, or run OpenCode from WSL.\n"
|
|
1237
|
+
)
|
|
1238
|
+
return None
|
|
1239
|
+
|
|
1240
|
+
|
|
1196
1241
|
def _opencode_install_supported_from_this_package() -> bool:
|
|
1197
1242
|
return (_SCRIPTS_DIR / "smart-install.sh").is_file()
|
|
1198
1243
|
|
|
@@ -1332,7 +1377,12 @@ def cmd_install_opencode(args: argparse.Namespace) -> int:
|
|
|
1332
1377
|
"Run `npx claude-smart install --host opencode`.\n"
|
|
1333
1378
|
)
|
|
1334
1379
|
return 1
|
|
1335
|
-
|
|
1380
|
+
prerequisite_error = _opencode_prerequisite_error()
|
|
1381
|
+
if prerequisite_error:
|
|
1382
|
+
sys.stderr.write(prerequisite_error)
|
|
1383
|
+
return 1
|
|
1384
|
+
read_only = _configure_reflexio_setup(host=_HOST_OPENCODE)
|
|
1385
|
+
_persist_opencode_path()
|
|
1336
1386
|
if not _has_extraction_provider():
|
|
1337
1387
|
sys.stderr.write(_extraction_provider_error())
|
|
1338
1388
|
return 1
|
|
@@ -1387,7 +1437,7 @@ def cmd_install_codex(args: argparse.Namespace) -> int:
|
|
|
1387
1437
|
"error: 'uv' not found on PATH. Install uv or restart your shell.\n"
|
|
1388
1438
|
)
|
|
1389
1439
|
return 1
|
|
1390
|
-
read_only = _configure_reflexio_setup()
|
|
1440
|
+
read_only = _configure_reflexio_setup(host=_HOST_CODEX)
|
|
1391
1441
|
|
|
1392
1442
|
missing = _missing_codex_marketplace_files(_REPO_ROOT)
|
|
1393
1443
|
if missing:
|
|
@@ -1485,9 +1535,9 @@ def cmd_install(args: argparse.Namespace) -> int:
|
|
|
1485
1535
|
Returns:
|
|
1486
1536
|
int: 0 on success, non-zero if the ``claude`` CLI is missing or fails.
|
|
1487
1537
|
"""
|
|
1488
|
-
if getattr(args, "host",
|
|
1538
|
+
if getattr(args, "host", _HOST_CLAUDE_CODE) == _HOST_CODEX:
|
|
1489
1539
|
return cmd_install_codex(args)
|
|
1490
|
-
if getattr(args, "host",
|
|
1540
|
+
if getattr(args, "host", _HOST_CLAUDE_CODE) == _HOST_OPENCODE:
|
|
1491
1541
|
return cmd_install_opencode(args)
|
|
1492
1542
|
|
|
1493
1543
|
if not shutil.which("claude"):
|
|
@@ -1496,7 +1546,7 @@ def cmd_install(args: argparse.Namespace) -> int:
|
|
|
1496
1546
|
"Install Claude Code first: https://claude.com/claude-code\n"
|
|
1497
1547
|
)
|
|
1498
1548
|
return 1
|
|
1499
|
-
read_only = _configure_reflexio_setup()
|
|
1549
|
+
read_only = _configure_reflexio_setup(host=_HOST_CLAUDE_CODE)
|
|
1500
1550
|
|
|
1501
1551
|
refresh_existing = bool(getattr(args, "refresh_existing", False))
|
|
1502
1552
|
for cmd in (
|
|
@@ -1559,16 +1609,16 @@ def cmd_update(args: argparse.Namespace) -> int:
|
|
|
1559
1609
|
Returns:
|
|
1560
1610
|
int: 0 on success, non-zero if the host CLI is missing or install fails.
|
|
1561
1611
|
"""
|
|
1562
|
-
if getattr(args, "host",
|
|
1612
|
+
if getattr(args, "host", _HOST_CLAUDE_CODE) == _HOST_CODEX:
|
|
1563
1613
|
return cmd_update_codex(args)
|
|
1564
|
-
if getattr(args, "host",
|
|
1614
|
+
if getattr(args, "host", _HOST_CLAUDE_CODE) == _HOST_OPENCODE:
|
|
1565
1615
|
return cmd_update_opencode(args)
|
|
1566
1616
|
|
|
1567
1617
|
_run_service(_DASHBOARD_SCRIPT, "stop")
|
|
1568
1618
|
_run_service(_BACKEND_SCRIPT, "stop")
|
|
1569
1619
|
sys.stdout.write("Updating claude-smart by reinstalling from this package...\n")
|
|
1570
1620
|
install_args = argparse.Namespace(**vars(args), refresh_existing=True)
|
|
1571
|
-
install_args.host =
|
|
1621
|
+
install_args.host = _HOST_CLAUDE_CODE
|
|
1572
1622
|
return cmd_install(install_args)
|
|
1573
1623
|
|
|
1574
1624
|
|
|
@@ -1585,7 +1635,7 @@ def cmd_update_codex(_args: argparse.Namespace) -> int:
|
|
|
1585
1635
|
"Updating claude-smart Codex support by reinstalling from this package...\n"
|
|
1586
1636
|
)
|
|
1587
1637
|
install_args = argparse.Namespace(**vars(_args))
|
|
1588
|
-
install_args.host =
|
|
1638
|
+
install_args.host = _HOST_CODEX
|
|
1589
1639
|
return cmd_install_codex(install_args)
|
|
1590
1640
|
|
|
1591
1641
|
|
|
@@ -1596,7 +1646,7 @@ def cmd_update_opencode(args: argparse.Namespace) -> int:
|
|
|
1596
1646
|
"Updating claude-smart OpenCode support by reinstalling from this package...\n"
|
|
1597
1647
|
)
|
|
1598
1648
|
install_args = argparse.Namespace(**vars(args))
|
|
1599
|
-
install_args.host =
|
|
1649
|
+
install_args.host = _HOST_OPENCODE
|
|
1600
1650
|
return cmd_install_opencode(install_args)
|
|
1601
1651
|
|
|
1602
1652
|
|
|
@@ -1612,9 +1662,9 @@ def cmd_uninstall(_args: argparse.Namespace) -> int:
|
|
|
1612
1662
|
Returns:
|
|
1613
1663
|
int: 0 on success, non-zero if the ``claude`` CLI is missing or fails.
|
|
1614
1664
|
"""
|
|
1615
|
-
if getattr(_args, "host",
|
|
1665
|
+
if getattr(_args, "host", _HOST_CLAUDE_CODE) == _HOST_CODEX:
|
|
1616
1666
|
return cmd_uninstall_codex(_args)
|
|
1617
|
-
if getattr(_args, "host",
|
|
1667
|
+
if getattr(_args, "host", _HOST_CLAUDE_CODE) == _HOST_OPENCODE:
|
|
1618
1668
|
return cmd_uninstall_opencode(_args)
|
|
1619
1669
|
|
|
1620
1670
|
if not shutil.which("claude"):
|
|
@@ -1761,7 +1811,7 @@ def _reflexio_show_footer() -> str:
|
|
|
1761
1811
|
str: A leading-separator markdown footer ending in a newline.
|
|
1762
1812
|
"""
|
|
1763
1813
|
return (
|
|
1764
|
-
f"\n---\
|
|
1814
|
+
f"\n---\nclaude-smart is powered by [reflexio]({cs_cite.REFLEXIO_REPO_URL})"
|
|
1765
1815
|
f" — if it helps you, [star it on GitHub]({cs_cite.REFLEXIO_REPO_URL}).\n"
|
|
1766
1816
|
)
|
|
1767
1817
|
|
|
@@ -1949,7 +1999,7 @@ def _resolve_absolute_path(raw_path: str | Path, *, source: str) -> Path:
|
|
|
1949
1999
|
def _effective_storage_root() -> Path:
|
|
1950
2000
|
raw = os.environ.get(_LOCAL_STORAGE_ENV, "").strip()
|
|
1951
2001
|
if not raw:
|
|
1952
|
-
raw = _read_dotenv_value(
|
|
2002
|
+
raw = _read_dotenv_value(_CLAUDE_SMART_ENV_PATH, _LOCAL_STORAGE_ENV) or ""
|
|
1953
2003
|
return _resolve_absolute_path(
|
|
1954
2004
|
raw or _DEFAULT_STORAGE_ROOT, source=_LOCAL_STORAGE_ENV
|
|
1955
2005
|
)
|
|
@@ -2449,8 +2499,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2449
2499
|
inst = sub.add_parser("install", help="Install claude-smart")
|
|
2450
2500
|
inst.add_argument(
|
|
2451
2501
|
"--host",
|
|
2452
|
-
choices=
|
|
2453
|
-
default=
|
|
2502
|
+
choices=_HOST_CHOICES,
|
|
2503
|
+
default=_HOST_CLAUDE_CODE,
|
|
2454
2504
|
help="Install target host",
|
|
2455
2505
|
)
|
|
2456
2506
|
inst.add_argument(
|
|
@@ -2464,8 +2514,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2464
2514
|
upd = sub.add_parser("update", help="Update claude-smart to the latest version")
|
|
2465
2515
|
upd.add_argument(
|
|
2466
2516
|
"--host",
|
|
2467
|
-
choices=
|
|
2468
|
-
default=
|
|
2517
|
+
choices=_HOST_CHOICES,
|
|
2518
|
+
default=_HOST_CLAUDE_CODE,
|
|
2469
2519
|
help="Update target host",
|
|
2470
2520
|
)
|
|
2471
2521
|
upd.add_argument(
|
|
@@ -2479,8 +2529,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2479
2529
|
uni = sub.add_parser("uninstall", help="Remove claude-smart")
|
|
2480
2530
|
uni.add_argument(
|
|
2481
2531
|
"--host",
|
|
2482
|
-
choices=
|
|
2483
|
-
default=
|
|
2532
|
+
choices=_HOST_CHOICES,
|
|
2533
|
+
default=_HOST_CLAUDE_CODE,
|
|
2484
2534
|
help="Uninstall target host",
|
|
2485
2535
|
)
|
|
2486
2536
|
uni.add_argument(
|
|
@@ -13,17 +13,23 @@ from __future__ import annotations
|
|
|
13
13
|
import os
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
from claude_smart import runtime
|
|
17
|
+
|
|
18
|
+
CLAUDE_SMART_ENV_PATH = Path.home() / ".claude-smart" / ".env"
|
|
19
|
+
# Deprecated internal alias kept so older imports do not fail abruptly.
|
|
20
|
+
REFLEXIO_ENV_PATH = CLAUDE_SMART_ENV_PATH
|
|
17
21
|
MANAGED_REFLEXIO_URL = "https://www.reflexio.ai/"
|
|
18
22
|
REFLEXIO_URL_ENV = "REFLEXIO_URL"
|
|
19
23
|
REFLEXIO_API_KEY_ENV = "REFLEXIO_API_KEY"
|
|
20
24
|
CLAUDE_SMART_READ_ONLY_ENV = "CLAUDE_SMART_READ_ONLY"
|
|
21
25
|
CLAUDE_SMART_USE_LOCAL_CLI_ENV = "CLAUDE_SMART_USE_LOCAL_CLI"
|
|
22
26
|
CLAUDE_SMART_USE_LOCAL_EMBEDDING_ENV = "CLAUDE_SMART_USE_LOCAL_EMBEDDING"
|
|
27
|
+
CLAUDE_SMART_HOST_ENV = "CLAUDE_SMART_HOST"
|
|
28
|
+
DEFAULT_CLAUDE_SMART_HOST = runtime.HOST_CLAUDE_CODE
|
|
23
29
|
|
|
24
30
|
_LOCAL_DEFAULT_ENTRIES = (
|
|
25
31
|
(
|
|
26
|
-
"# Route reflexio generation through the local
|
|
32
|
+
"# Route reflexio generation through the configured local host CLI",
|
|
27
33
|
CLAUDE_SMART_USE_LOCAL_CLI_ENV,
|
|
28
34
|
"1",
|
|
29
35
|
),
|
|
@@ -33,7 +39,12 @@ _LOCAL_DEFAULT_ENTRIES = (
|
|
|
33
39
|
"1",
|
|
34
40
|
),
|
|
35
41
|
(None, CLAUDE_SMART_READ_ONLY_ENV, "0"),
|
|
42
|
+
(None, CLAUDE_SMART_HOST_ENV, DEFAULT_CLAUDE_SMART_HOST),
|
|
36
43
|
)
|
|
44
|
+
_ENV_OVERRIDABLE_LOCAL_DEFAULT_KEYS = {
|
|
45
|
+
CLAUDE_SMART_USE_LOCAL_CLI_ENV,
|
|
46
|
+
CLAUDE_SMART_USE_LOCAL_EMBEDDING_ENV,
|
|
47
|
+
}
|
|
37
48
|
_LOCAL_MODE_PRUNE_KEYS = {
|
|
38
49
|
REFLEXIO_URL_ENV,
|
|
39
50
|
REFLEXIO_API_KEY_ENV,
|
|
@@ -69,7 +80,7 @@ def parse_env_line(line: str) -> tuple[str, str] | None:
|
|
|
69
80
|
|
|
70
81
|
def load_reflexio_env(path: Path | None = None) -> None:
|
|
71
82
|
"""Load ``~/.claude-smart/.env`` into ``os.environ`` without overriding values."""
|
|
72
|
-
path = path or
|
|
83
|
+
path = path or CLAUDE_SMART_ENV_PATH
|
|
73
84
|
try:
|
|
74
85
|
text = path.read_text()
|
|
75
86
|
except OSError:
|
|
@@ -118,14 +129,19 @@ def set_env_vars(path: Path, values: dict[str, str]) -> list[str]:
|
|
|
118
129
|
return added
|
|
119
130
|
|
|
120
131
|
|
|
121
|
-
def ensure_local_env_defaults(
|
|
132
|
+
def ensure_local_env_defaults(
|
|
133
|
+
path: Path | None = None,
|
|
134
|
+
host: str = DEFAULT_CLAUDE_SMART_HOST,
|
|
135
|
+
) -> list[str]:
|
|
122
136
|
"""Create or augment ``~/.claude-smart/.env`` for claude-smart local mode.
|
|
123
137
|
|
|
124
|
-
Existing active assignments win
|
|
125
|
-
|
|
126
|
-
|
|
138
|
+
Existing active assignments win except ``CLAUDE_SMART_HOST``, which is
|
|
139
|
+
install-selected state and must follow the host currently being installed.
|
|
140
|
+
This repairs first installs and deleted env files without clobbering
|
|
141
|
+
explicit user overrides such as ``CLAUDE_SMART_READ_ONLY=1``.
|
|
127
142
|
"""
|
|
128
|
-
|
|
143
|
+
install_host = host
|
|
144
|
+
path = path or CLAUDE_SMART_ENV_PATH
|
|
129
145
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
130
146
|
try:
|
|
131
147
|
existing = path.read_text()
|
|
@@ -135,6 +151,8 @@ def ensure_local_env_defaults(path: Path | None = None) -> list[str]:
|
|
|
135
151
|
present: set[str] = set()
|
|
136
152
|
kept_lines: list[str] = []
|
|
137
153
|
pruned = False
|
|
154
|
+
changed = False
|
|
155
|
+
host_written = False
|
|
138
156
|
for line in existing.splitlines():
|
|
139
157
|
parsed = parse_env_line(line)
|
|
140
158
|
if parsed is not None:
|
|
@@ -142,6 +160,19 @@ def ensure_local_env_defaults(path: Path | None = None) -> list[str]:
|
|
|
142
160
|
if key in _LOCAL_MODE_PRUNE_KEYS:
|
|
143
161
|
pruned = True
|
|
144
162
|
continue
|
|
163
|
+
if key == CLAUDE_SMART_HOST_ENV:
|
|
164
|
+
present.add(key)
|
|
165
|
+
if not host_written:
|
|
166
|
+
replacement = (
|
|
167
|
+
f"{CLAUDE_SMART_HOST_ENV}={_escape_env_value(install_host)}"
|
|
168
|
+
)
|
|
169
|
+
kept_lines.append(replacement)
|
|
170
|
+
host_written = True
|
|
171
|
+
if line != replacement or _value != install_host:
|
|
172
|
+
changed = True
|
|
173
|
+
else:
|
|
174
|
+
changed = True
|
|
175
|
+
continue
|
|
145
176
|
present.add(key)
|
|
146
177
|
kept_lines.append(line)
|
|
147
178
|
|
|
@@ -150,15 +181,16 @@ def ensure_local_env_defaults(path: Path | None = None) -> list[str]:
|
|
|
150
181
|
for comment, key, value in _LOCAL_DEFAULT_ENTRIES:
|
|
151
182
|
if key in present:
|
|
152
183
|
continue
|
|
184
|
+
effective_value = _resolve_local_env_default(key, value, install_host)
|
|
153
185
|
if comment:
|
|
154
186
|
additions.append(comment)
|
|
155
187
|
if key == CLAUDE_SMART_READ_ONLY_ENV:
|
|
156
|
-
additions.append(f'{key}="{_escape_env_value(
|
|
188
|
+
additions.append(f'{key}="{_escape_env_value(effective_value)}"')
|
|
157
189
|
else:
|
|
158
|
-
additions.append(f"{key}={_escape_env_value(
|
|
190
|
+
additions.append(f"{key}={_escape_env_value(effective_value)}")
|
|
159
191
|
added_keys.append(key)
|
|
160
192
|
|
|
161
|
-
if additions or pruned:
|
|
193
|
+
if additions or pruned or changed:
|
|
162
194
|
content = "\n".join(kept_lines)
|
|
163
195
|
if additions:
|
|
164
196
|
prefix = "" if not content or content.endswith("\n") else "\n"
|
|
@@ -171,6 +203,16 @@ def ensure_local_env_defaults(path: Path | None = None) -> list[str]:
|
|
|
171
203
|
return added_keys
|
|
172
204
|
|
|
173
205
|
|
|
206
|
+
def _resolve_local_env_default(key: str, fallback: str, install_host: str) -> str:
|
|
207
|
+
if key == CLAUDE_SMART_HOST_ENV:
|
|
208
|
+
return install_host
|
|
209
|
+
if key in _ENV_OVERRIDABLE_LOCAL_DEFAULT_KEYS:
|
|
210
|
+
explicit = os.environ.get(key, "").strip()
|
|
211
|
+
if explicit:
|
|
212
|
+
return explicit
|
|
213
|
+
return fallback
|
|
214
|
+
|
|
215
|
+
|
|
174
216
|
def env_truthy(name: str) -> bool:
|
|
175
217
|
"""Return True when an environment flag is explicitly enabled."""
|
|
176
218
|
return os.environ.get(name, "").strip().lower() in {"1", "true", "yes", "on"}
|
package/plugin/uv.lock
CHANGED
|
@@ -476,7 +476,7 @@ wheels = [
|
|
|
476
476
|
|
|
477
477
|
[[package]]
|
|
478
478
|
name = "claude-smart"
|
|
479
|
-
version = "0.2.
|
|
479
|
+
version = "0.2.49"
|
|
480
480
|
source = { editable = "." }
|
|
481
481
|
dependencies = [
|
|
482
482
|
{ name = "chromadb" },
|
|
@@ -494,7 +494,7 @@ dev = [
|
|
|
494
494
|
requires-dist = [
|
|
495
495
|
{ name = "chromadb", specifier = ">=0.5" },
|
|
496
496
|
{ name = "einops", specifier = ">=0.8.0" },
|
|
497
|
-
{ name = "reflexio-ai", specifier = ">=0.2.
|
|
497
|
+
{ name = "reflexio-ai", specifier = ">=0.2.28" },
|
|
498
498
|
{ name = "sqlite-vec", specifier = ">=0.1.6" },
|
|
499
499
|
]
|
|
500
500
|
|
|
@@ -2760,7 +2760,7 @@ wheels = [
|
|
|
2760
2760
|
|
|
2761
2761
|
[[package]]
|
|
2762
2762
|
name = "reflexio-ai"
|
|
2763
|
-
version = "0.2.
|
|
2763
|
+
version = "0.2.28"
|
|
2764
2764
|
source = { registry = "https://pypi.org/simple" }
|
|
2765
2765
|
dependencies = [
|
|
2766
2766
|
{ name = "aiohttp" },
|
|
@@ -2800,9 +2800,9 @@ dependencies = [
|
|
|
2800
2800
|
{ name = "websocket-client" },
|
|
2801
2801
|
{ name = "xlsxwriter" },
|
|
2802
2802
|
]
|
|
2803
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2803
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2a/e6/a59fc40136b37ea3e9b6878b600ef1f405c1baf7d1431a07e55c8e49c14e/reflexio_ai-0.2.28.tar.gz", hash = "sha256:49a35abf714ae293392277b278b895cde21ca50c14f10c97cbcf27c307e49fae", size = 1155554, upload-time = "2026-07-04T07:01:02.207Z" }
|
|
2804
2804
|
wheels = [
|
|
2805
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2805
|
+
{ url = "https://files.pythonhosted.org/packages/96/a6/c842d5e525f0f561fcd11ecf6543c9c52b3f4b665dbc2a8fe94adce9be1b/reflexio_ai-0.2.28-py3-none-any.whl", hash = "sha256:177e3a740afa2acb5a2a14a1e648c32c2d9e71ef9ff79b8ab2caec7e24ff5d88", size = 1558983, upload-time = "2026-07-04T07:01:00.69Z" },
|
|
2806
2806
|
]
|
|
2807
2807
|
|
|
2808
2808
|
[[package]]
|
|
@@ -78,6 +78,9 @@ When `REFLEXIO_EMBEDDING_PROVIDER=local_service` or
|
|
|
78
78
|
`local/nomic-embed-text-v1.5`, and `local/minilm-l6-v2`. Local embedding
|
|
79
79
|
requests allow extra time for model cold start; override with
|
|
80
80
|
`REFLEXIO_EMBEDDING_SERVICE_TIMEOUT_MS` when needed.
|
|
81
|
+
MiniLM cache corruption is retried once automatically. If recovery still fails,
|
|
82
|
+
delete the cache directory named in the error message, restart Reflexio, and
|
|
83
|
+
retry local embedding.
|
|
81
84
|
|
|
82
85
|
## Publishing interactions
|
|
83
86
|
|