seif-cli 0.3.2__tar.gz → 0.3.4__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.
Files changed (85) hide show
  1. {seif_cli-0.3.2/src/seif_cli.egg-info → seif_cli-0.3.4}/PKG-INFO +1 -1
  2. {seif_cli-0.3.2 → seif_cli-0.3.4}/pyproject.toml +1 -1
  3. seif_cli-0.3.4/src/seif/bridge/native_client.py +163 -0
  4. seif_cli-0.3.4/src/seif/cli/chat.py +11 -0
  5. {seif_cli-0.3.2 → seif_cli-0.3.4/src/seif_cli.egg-info}/PKG-INFO +1 -1
  6. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif_cli.egg-info/SOURCES.txt +2 -0
  7. {seif_cli-0.3.2 → seif_cli-0.3.4}/LICENSE +0 -0
  8. {seif_cli-0.3.2 → seif_cli-0.3.4}/MANIFEST.in +0 -0
  9. {seif_cli-0.3.2 → seif_cli-0.3.4}/README.md +0 -0
  10. {seif_cli-0.3.2 → seif_cli-0.3.4}/setup.cfg +0 -0
  11. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/__init__.py +0 -0
  12. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/__main__.py +0 -0
  13. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/analysis/__init__.py +0 -0
  14. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/analysis/physical_constants.py +0 -0
  15. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/analysis/quality_gate.py +0 -0
  16. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/analysis/stance_detector.py +0 -0
  17. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/analysis/transcompiler.py +0 -0
  18. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/bridge/__init__.py +0 -0
  19. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/bridge/telegram_bot.py +0 -0
  20. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/__init__.py +0 -0
  21. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/__main__.py +0 -0
  22. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/cli.py +0 -0
  23. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/identity.py +0 -0
  24. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/main.py +0 -0
  25. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/resonance_display.py +0 -0
  26. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/serve.py +0 -0
  27. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/serve_v2.py +0 -0
  28. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/cli/wrapper.py +0 -0
  29. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/constants.py +0 -0
  30. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/__init__.py +0 -0
  31. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/advisor.py +0 -0
  32. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/code_compressor.py +0 -0
  33. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/context_bridge.py +0 -0
  34. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/context_importer.py +0 -0
  35. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/context_manager.py +0 -0
  36. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/context_qr.py +0 -0
  37. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/cycle.py +0 -0
  38. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/file_extractor.py +0 -0
  39. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/git_context.py +0 -0
  40. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/git_hooks.py +0 -0
  41. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/ingest.py +0 -0
  42. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/nucleus.py +0 -0
  43. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/ref.py +0 -0
  44. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/registry.py +0 -0
  45. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/seif_io.py +0 -0
  46. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/sessions.py +0 -0
  47. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/context/workspace.py +0 -0
  48. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/__init__.py +0 -0
  49. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/fingerprint.py +0 -0
  50. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/resonance_encoding.py +0 -0
  51. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/resonance_gate.py +0 -0
  52. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/resonance_signal.py +0 -0
  53. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/signing.py +0 -0
  54. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/timestamping.py +0 -0
  55. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/transfer_function.py +0 -0
  56. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/core/triple_gate.py +0 -0
  57. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/data/RESONANCE.json +0 -0
  58. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/data/__init__.py +0 -0
  59. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/data/defaults/__init__.py +0 -0
  60. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/data/paths.py +0 -0
  61. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/security/__init__.py +0 -0
  62. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif/security/mode.py +0 -0
  63. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif_cli.egg-info/dependency_links.txt +0 -0
  64. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif_cli.egg-info/entry_points.txt +0 -0
  65. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif_cli.egg-info/requires.txt +0 -0
  66. {seif_cli-0.3.2 → seif_cli-0.3.4}/src/seif_cli.egg-info/top_level.txt +0 -0
  67. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_advisor.py +0 -0
  68. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_canonical_inputs.py +0 -0
  69. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_code_compressor.py +0 -0
  70. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_collaborative_seif.py +0 -0
  71. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_context_qr.py +0 -0
  72. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_context_repo.py +0 -0
  73. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_git_context.py +0 -0
  74. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_git_hooks.py +0 -0
  75. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_init.py +0 -0
  76. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_quality_gate.py +0 -0
  77. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_ref.py +0 -0
  78. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_registry.py +0 -0
  79. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_resonance_gate.py +0 -0
  80. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_seif_io.py +0 -0
  81. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_stance_detector.py +0 -0
  82. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_transcompiler.py +0 -0
  83. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_transfer_function.py +0 -0
  84. {seif_cli-0.3.2 → seif_cli-0.3.4}/tests/test_triple_gate.py +0 -0
  85. {seif_cli-0.3.2 → seif_cli-0.3.4}/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.2
3
+ Version: 0.3.4
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.2"
7
+ version = "0.3.4"
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"}
@@ -0,0 +1,163 @@
1
+ """
2
+ Native AI Client — Direct SDK integration replacing CLI wrapper.
3
+
4
+ Supports streaming, multi-backend routing, and context injection from
5
+ the personal nucleus. Falls back to CLI subprocess if SDK unavailable.
6
+ """
7
+
8
+ from dataclasses import dataclass, field
9
+ from typing import Iterator, Optional
10
+ import os
11
+
12
+
13
+ @dataclass
14
+ class ChatConfig:
15
+ backend: str = "auto" # claude, gemini, local, auto
16
+ model: str = "" # model override (empty = use default)
17
+ stream: bool = True # streaming responses
18
+ quality_gate: bool = True # measure every response
19
+ max_tokens: int = 4096
20
+
21
+
22
+ # Default models per backend
23
+ _DEFAULT_MODELS = {
24
+ "claude": "claude-sonnet-4-6",
25
+ "gemini": "gemini-2.5-flash",
26
+ "grok": "grok-4-1-fast",
27
+ "local": "llama3",
28
+ }
29
+
30
+
31
+ class NativeClient:
32
+ """Multi-backend AI client with streaming support."""
33
+
34
+ def __init__(self, config: Optional[ChatConfig] = None,
35
+ profile: Optional[dict] = None):
36
+ self.config = config or ChatConfig()
37
+ self.profile = profile or {}
38
+ self._backend = self._resolve_backend()
39
+ self._model = self.config.model or _DEFAULT_MODELS.get(self._backend, "")
40
+ self._client = None
41
+
42
+ def _resolve_backend(self) -> str:
43
+ """Resolve 'auto' to the best available backend."""
44
+ if self.config.backend != "auto":
45
+ return self.config.backend
46
+
47
+ profile_default = self.profile.get("default_backend", "")
48
+ if profile_default and profile_default != "auto":
49
+ return profile_default
50
+
51
+ if os.environ.get("ANTHROPIC_API_KEY"):
52
+ return "claude"
53
+ if os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY"):
54
+ return "gemini"
55
+ return "claude"
56
+
57
+ def _get_anthropic_client(self):
58
+ """Lazy-init Anthropic client."""
59
+ if self._client is None:
60
+ import anthropic
61
+ self._client = anthropic.Anthropic()
62
+ return self._client
63
+
64
+ def send(self, message: str, history: list[dict] = None,
65
+ system: str = "") -> str:
66
+ """Send message and return complete response."""
67
+ if self._backend == "claude":
68
+ return self._send_claude(message, history or [], system)
69
+ elif self._backend == "gemini":
70
+ return self._send_gemini(message, history or [], system)
71
+ elif self._backend == "local":
72
+ return self._send_local(message, history or [], system)
73
+ else:
74
+ return f"Backend '{self._backend}' not supported."
75
+
76
+ def stream(self, message: str, history: list[dict] = None,
77
+ system: str = "") -> Iterator[str]:
78
+ """Stream response tokens. Falls back to send() if streaming unavailable."""
79
+ if self._backend == "claude":
80
+ yield from self._stream_claude(message, history or [], system)
81
+ else:
82
+ yield self.send(message, history, system)
83
+
84
+ def _send_claude(self, message: str, history: list[dict],
85
+ system: str) -> str:
86
+ try:
87
+ client = self._get_anthropic_client()
88
+ messages = history + [{"role": "user", "content": message}]
89
+ response = client.messages.create(
90
+ model=self._model,
91
+ max_tokens=self.config.max_tokens,
92
+ system=system,
93
+ messages=messages,
94
+ )
95
+ return response.content[0].text
96
+ except ImportError:
97
+ return self._fallback_cli(message, system)
98
+ except Exception as e:
99
+ return f"Error: {e}"
100
+
101
+ def _stream_claude(self, message: str, history: list[dict],
102
+ system: str) -> Iterator[str]:
103
+ try:
104
+ client = self._get_anthropic_client()
105
+ messages = history + [{"role": "user", "content": message}]
106
+ with client.messages.stream(
107
+ model=self._model,
108
+ max_tokens=self.config.max_tokens,
109
+ system=system,
110
+ messages=messages,
111
+ ) as stream:
112
+ for text in stream.text_stream:
113
+ yield text
114
+ except ImportError:
115
+ yield self._fallback_cli(message, system)
116
+ except Exception as e:
117
+ yield f"Error: {e}"
118
+
119
+ def _send_gemini(self, message: str, history: list[dict],
120
+ system: str) -> str:
121
+ try:
122
+ import google.generativeai as genai
123
+ genai.configure()
124
+ model = genai.GenerativeModel(self._model,
125
+ system_instruction=system)
126
+ chat = model.start_chat(history=[
127
+ {"role": h["role"], "parts": [h["content"]]}
128
+ for h in history
129
+ ] if history else [])
130
+ response = chat.send_message(message)
131
+ return response.text
132
+ except ImportError:
133
+ return "Gemini SDK not installed. pip install google-generativeai"
134
+ except Exception as e:
135
+ return f"Gemini error: {e}"
136
+
137
+ def _send_local(self, message: str, history: list[dict],
138
+ system: str) -> str:
139
+ try:
140
+ import subprocess
141
+ result = subprocess.run(
142
+ ["ollama", "run", self._model, message],
143
+ capture_output=True, text=True, timeout=120,
144
+ )
145
+ return result.stdout.strip() if result.returncode == 0 else f"Error: {result.stderr}"
146
+ except FileNotFoundError:
147
+ return "Ollama not installed. https://ollama.ai"
148
+ except Exception as e:
149
+ 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."
@@ -0,0 +1,11 @@
1
+ """
2
+ Bridge to seif-engine native chat.
3
+
4
+ This module exists in seif-cli so that
5
+ works when seif-engine is installed. The actual implementation lives in
6
+ seif_engine.api.chat (proprietary / Pro tier).
7
+ """
8
+
9
+ from seif_engine.api.chat import run_chat # noqa: F401
10
+
11
+ __all__ = ["run_chat"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seif-cli
3
- Version: 0.3.2
3
+ Version: 0.3.4
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
@@ -11,9 +11,11 @@ src/seif/analysis/quality_gate.py
11
11
  src/seif/analysis/stance_detector.py
12
12
  src/seif/analysis/transcompiler.py
13
13
  src/seif/bridge/__init__.py
14
+ src/seif/bridge/native_client.py
14
15
  src/seif/bridge/telegram_bot.py
15
16
  src/seif/cli/__init__.py
16
17
  src/seif/cli/__main__.py
18
+ src/seif/cli/chat.py
17
19
  src/seif/cli/cli.py
18
20
  src/seif/cli/identity.py
19
21
  src/seif/cli/main.py
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