seif-cli 0.3.4__tar.gz → 0.3.5__tar.gz
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.
- {seif_cli-0.3.4/src/seif_cli.egg-info → seif_cli-0.3.5}/PKG-INFO +1 -1
- {seif_cli-0.3.4 → seif_cli-0.3.5}/pyproject.toml +1 -1
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/bridge/native_client.py +71 -22
- {seif_cli-0.3.4 → seif_cli-0.3.5/src/seif_cli.egg-info}/PKG-INFO +1 -1
- {seif_cli-0.3.4 → seif_cli-0.3.5}/LICENSE +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/MANIFEST.in +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/README.md +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/setup.cfg +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/__main__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/analysis/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/analysis/physical_constants.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/analysis/quality_gate.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/analysis/stance_detector.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/analysis/transcompiler.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/bridge/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/bridge/telegram_bot.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/__main__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/chat.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/cli.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/identity.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/main.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/resonance_display.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/serve.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/serve_v2.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/cli/wrapper.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/constants.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/advisor.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/code_compressor.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/context_bridge.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/context_importer.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/context_manager.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/context_qr.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/cycle.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/file_extractor.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/git_context.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/git_hooks.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/ingest.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/nucleus.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/ref.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/registry.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/seif_io.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/sessions.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/context/workspace.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/fingerprint.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/resonance_encoding.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/resonance_gate.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/resonance_signal.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/signing.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/timestamping.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/transfer_function.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/core/triple_gate.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/data/RESONANCE.json +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/data/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/data/defaults/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/data/paths.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/security/__init__.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif/security/mode.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif_cli.egg-info/SOURCES.txt +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif_cli.egg-info/dependency_links.txt +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif_cli.egg-info/entry_points.txt +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif_cli.egg-info/requires.txt +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/src/seif_cli.egg-info/top_level.txt +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_advisor.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_canonical_inputs.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_code_compressor.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_collaborative_seif.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_context_qr.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_context_repo.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_git_context.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_git_hooks.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_init.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_quality_gate.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_ref.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_registry.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_resonance_gate.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_seif_io.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_stance_detector.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_transcompiler.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_transfer_function.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_triple_gate.py +0 -0
- {seif_cli-0.3.4 → seif_cli-0.3.5}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seif-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Measure AI output quality, protect sensitive data, watch your AI environment resonate. Quality Gate, Classification, Sentinel & Auto-Healing, SEIF OS.
|
|
5
5
|
Author: André Cunha Antero de Carvalho
|
|
6
6
|
License: CC-BY-NC-SA-4.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "seif-cli"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.5"
|
|
8
8
|
description = "Measure AI output quality, protect sensitive data, watch your AI environment resonate. Quality Gate, Classification, Sentinel & Auto-Healing, SEIF OS."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "CC-BY-NC-SA-4.0"}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Native AI Client — Direct SDK integration
|
|
2
|
+
Native AI Client — Direct SDK integration with Claude CLI fallback.
|
|
3
3
|
|
|
4
4
|
Supports streaming, multi-backend routing, and context injection from
|
|
5
|
-
the personal nucleus.
|
|
5
|
+
the personal nucleus. When no ANTHROPIC_API_KEY is set, uses Claude CLI
|
|
6
|
+
(compatible with Max Plan via OAuth).
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
+
from dataclasses import dataclass
|
|
9
10
|
from typing import Iterator, Optional
|
|
10
11
|
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
@dataclass
|
|
14
17
|
class ChatConfig:
|
|
15
|
-
backend: str = "auto" # claude, gemini, local, auto
|
|
18
|
+
backend: str = "auto" # claude, claude-cli, gemini, local, auto
|
|
16
19
|
model: str = "" # model override (empty = use default)
|
|
17
20
|
stream: bool = True # streaming responses
|
|
18
21
|
quality_gate: bool = True # measure every response
|
|
@@ -22,12 +25,17 @@ class ChatConfig:
|
|
|
22
25
|
# Default models per backend
|
|
23
26
|
_DEFAULT_MODELS = {
|
|
24
27
|
"claude": "claude-sonnet-4-6",
|
|
28
|
+
"claude-cli": "claude-sonnet-4-6",
|
|
25
29
|
"gemini": "gemini-2.5-flash",
|
|
26
30
|
"grok": "grok-4-1-fast",
|
|
27
31
|
"local": "llama3",
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
|
|
35
|
+
def _has_claude_cli() -> bool:
|
|
36
|
+
return shutil.which("claude") is not None
|
|
37
|
+
|
|
38
|
+
|
|
31
39
|
class NativeClient:
|
|
32
40
|
"""Multi-backend AI client with streaming support."""
|
|
33
41
|
|
|
@@ -48,8 +56,12 @@ class NativeClient:
|
|
|
48
56
|
if profile_default and profile_default != "auto":
|
|
49
57
|
return profile_default
|
|
50
58
|
|
|
59
|
+
# SDK requires API key with credits
|
|
51
60
|
if os.environ.get("ANTHROPIC_API_KEY"):
|
|
52
61
|
return "claude"
|
|
62
|
+
# No API key — prefer Claude CLI (Max Plan compatible)
|
|
63
|
+
if _has_claude_cli():
|
|
64
|
+
return "claude-cli"
|
|
53
65
|
if os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY"):
|
|
54
66
|
return "gemini"
|
|
55
67
|
return "claude"
|
|
@@ -66,6 +78,8 @@ class NativeClient:
|
|
|
66
78
|
"""Send message and return complete response."""
|
|
67
79
|
if self._backend == "claude":
|
|
68
80
|
return self._send_claude(message, history or [], system)
|
|
81
|
+
elif self._backend == "claude-cli":
|
|
82
|
+
return self._send_claude_cli(message, history or [], system)
|
|
69
83
|
elif self._backend == "gemini":
|
|
70
84
|
return self._send_gemini(message, history or [], system)
|
|
71
85
|
elif self._backend == "local":
|
|
@@ -75,12 +89,16 @@ class NativeClient:
|
|
|
75
89
|
|
|
76
90
|
def stream(self, message: str, history: list[dict] = None,
|
|
77
91
|
system: str = "") -> Iterator[str]:
|
|
78
|
-
"""Stream response tokens.
|
|
92
|
+
"""Stream response tokens."""
|
|
79
93
|
if self._backend == "claude":
|
|
80
94
|
yield from self._stream_claude(message, history or [], system)
|
|
95
|
+
elif self._backend == "claude-cli":
|
|
96
|
+
yield from self._stream_claude_cli(message, history or [], system)
|
|
81
97
|
else:
|
|
82
98
|
yield self.send(message, history, system)
|
|
83
99
|
|
|
100
|
+
# -- Claude SDK ------------------------------------------------
|
|
101
|
+
|
|
84
102
|
def _send_claude(self, message: str, history: list[dict],
|
|
85
103
|
system: str) -> str:
|
|
86
104
|
try:
|
|
@@ -94,7 +112,7 @@ class NativeClient:
|
|
|
94
112
|
)
|
|
95
113
|
return response.content[0].text
|
|
96
114
|
except ImportError:
|
|
97
|
-
return self.
|
|
115
|
+
return self._send_claude_cli(message, history, system)
|
|
98
116
|
except Exception as e:
|
|
99
117
|
return f"Error: {e}"
|
|
100
118
|
|
|
@@ -112,10 +130,54 @@ class NativeClient:
|
|
|
112
130
|
for text in stream.text_stream:
|
|
113
131
|
yield text
|
|
114
132
|
except ImportError:
|
|
115
|
-
yield self.
|
|
133
|
+
yield from self._stream_claude_cli(message, history, system)
|
|
116
134
|
except Exception as e:
|
|
117
135
|
yield f"Error: {e}"
|
|
118
136
|
|
|
137
|
+
# -- Claude CLI (Max Plan) -------------------------------------
|
|
138
|
+
|
|
139
|
+
def _send_claude_cli(self, message: str, history: list[dict],
|
|
140
|
+
system: str) -> str:
|
|
141
|
+
try:
|
|
142
|
+
cmd = ["claude", "--print", "--output-format", "text",
|
|
143
|
+
"--no-session-persistence"]
|
|
144
|
+
if system:
|
|
145
|
+
cmd.extend(["--append-system-prompt", system])
|
|
146
|
+
cmd.append(message)
|
|
147
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
|
|
148
|
+
return result.stdout.strip() if result.returncode == 0 else f"CLI error: {result.stderr.strip()}"
|
|
149
|
+
except FileNotFoundError:
|
|
150
|
+
return "Claude CLI not found. Install: https://docs.anthropic.com/claude-code"
|
|
151
|
+
except subprocess.TimeoutExpired:
|
|
152
|
+
return "Claude CLI timeout (300s)."
|
|
153
|
+
except Exception as e:
|
|
154
|
+
return f"CLI error: {e}"
|
|
155
|
+
|
|
156
|
+
def _stream_claude_cli(self, message: str, history: list[dict],
|
|
157
|
+
system: str) -> Iterator[str]:
|
|
158
|
+
"""Stream from Claude CLI via subprocess pipe."""
|
|
159
|
+
try:
|
|
160
|
+
cmd = ["claude", "--print", "--output-format", "text",
|
|
161
|
+
"--no-session-persistence"]
|
|
162
|
+
if system:
|
|
163
|
+
cmd.extend(["--append-system-prompt", system])
|
|
164
|
+
cmd.append(message)
|
|
165
|
+
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
|
166
|
+
stderr=subprocess.PIPE, text=True)
|
|
167
|
+
for line in proc.stdout:
|
|
168
|
+
yield line
|
|
169
|
+
proc.wait()
|
|
170
|
+
if proc.returncode != 0:
|
|
171
|
+
err = proc.stderr.read().strip()
|
|
172
|
+
if err:
|
|
173
|
+
yield f"\nCLI error: {err}"
|
|
174
|
+
except FileNotFoundError:
|
|
175
|
+
yield "Claude CLI not found. Install: https://docs.anthropic.com/claude-code"
|
|
176
|
+
except Exception as e:
|
|
177
|
+
yield f"CLI error: {e}"
|
|
178
|
+
|
|
179
|
+
# -- Gemini ----------------------------------------------------
|
|
180
|
+
|
|
119
181
|
def _send_gemini(self, message: str, history: list[dict],
|
|
120
182
|
system: str) -> str:
|
|
121
183
|
try:
|
|
@@ -134,10 +196,11 @@ class NativeClient:
|
|
|
134
196
|
except Exception as e:
|
|
135
197
|
return f"Gemini error: {e}"
|
|
136
198
|
|
|
199
|
+
# -- Local (Ollama) --------------------------------------------
|
|
200
|
+
|
|
137
201
|
def _send_local(self, message: str, history: list[dict],
|
|
138
202
|
system: str) -> str:
|
|
139
203
|
try:
|
|
140
|
-
import subprocess
|
|
141
204
|
result = subprocess.run(
|
|
142
205
|
["ollama", "run", self._model, message],
|
|
143
206
|
capture_output=True, text=True, timeout=120,
|
|
@@ -147,17 +210,3 @@ class NativeClient:
|
|
|
147
210
|
return "Ollama not installed. https://ollama.ai"
|
|
148
211
|
except Exception as e:
|
|
149
212
|
return f"Local error: {e}"
|
|
150
|
-
|
|
151
|
-
def _fallback_cli(self, message: str, system: str) -> str:
|
|
152
|
-
"""Fall back to Claude CLI subprocess."""
|
|
153
|
-
import subprocess
|
|
154
|
-
try:
|
|
155
|
-
cmd = ["claude", "--print", "--output-format", "text",
|
|
156
|
-
"--no-session-persistence"]
|
|
157
|
-
if system:
|
|
158
|
-
cmd.extend(["--append-system-prompt", system])
|
|
159
|
-
cmd.append(message)
|
|
160
|
-
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
|
161
|
-
return result.stdout.strip() if result.returncode == 0 else f"CLI error: {result.stderr}"
|
|
162
|
-
except FileNotFoundError:
|
|
163
|
-
return "No AI backend available. Set ANTHROPIC_API_KEY or install claude CLI."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seif-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Measure AI output quality, protect sensitive data, watch your AI environment resonate. Quality Gate, Classification, Sentinel & Auto-Healing, SEIF OS.
|
|
5
5
|
Author: André Cunha Antero de Carvalho
|
|
6
6
|
License: CC-BY-NC-SA-4.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|