@smilintux/skcapstone 0.2.3 → 0.2.4
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/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/skcapstone/skjoule.py +23 -4
- package/tests/test_agent_card.py +3 -2
- package/tests/test_cli_completions.py +16 -8
- package/tests/test_doctor_fix.py +13 -7
- package/tests/test_llm_providers.py +11 -12
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "skcapstone"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "Sovereign Agent Framework — conscious AI through identity, trust, memory, and security"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "GPL-3.0-or-later"}
|
|
@@ -190,7 +190,7 @@ class JouleWallet:
|
|
|
190
190
|
self._state_path = self._wallet_dir / "joules.json"
|
|
191
191
|
self._log_path = self._wallet_dir / "transactions.jsonl"
|
|
192
192
|
self._lock = threading.Lock()
|
|
193
|
-
self._snapshot = self.
|
|
193
|
+
self._snapshot = self._load_or_create_snapshot()
|
|
194
194
|
|
|
195
195
|
# -- Public properties ---------------------------------------------------
|
|
196
196
|
|
|
@@ -403,15 +403,30 @@ class JouleWallet:
|
|
|
403
403
|
|
|
404
404
|
# -- Persistence ---------------------------------------------------------
|
|
405
405
|
|
|
406
|
-
def
|
|
407
|
-
"""Load wallet state from disk, or create a fresh one.
|
|
406
|
+
def _load_or_create_snapshot(self) -> WalletSnapshot:
|
|
407
|
+
"""Load wallet state from disk, or create and persist a fresh one.
|
|
408
|
+
|
|
409
|
+
Ensures the wallet directory exists (parents=True, exist_ok=True)
|
|
410
|
+
and writes an initial joules.json if none is found, so the file
|
|
411
|
+
is always present on disk after construction.
|
|
412
|
+
"""
|
|
413
|
+
self._wallet_dir.mkdir(parents=True, exist_ok=True)
|
|
408
414
|
if self._state_path.exists():
|
|
409
415
|
try:
|
|
410
416
|
data = json.loads(self._state_path.read_text(encoding="utf-8"))
|
|
411
417
|
return WalletSnapshot(**data)
|
|
412
418
|
except (json.JSONDecodeError, OSError, ValueError) as exc:
|
|
413
419
|
logger.warning("Failed to load wallet for %s: %s", self._agent, exc)
|
|
414
|
-
|
|
420
|
+
snapshot = WalletSnapshot(agent=self._agent)
|
|
421
|
+
# Persist the fresh snapshot so joules.json exists on disk immediately
|
|
422
|
+
try:
|
|
423
|
+
self._state_path.write_text(
|
|
424
|
+
json.dumps(snapshot.model_dump(), indent=2),
|
|
425
|
+
encoding="utf-8",
|
|
426
|
+
)
|
|
427
|
+
except OSError as exc:
|
|
428
|
+
logger.error("Failed to initialize wallet for %s: %s", self._agent, exc)
|
|
429
|
+
return snapshot
|
|
415
430
|
|
|
416
431
|
def _persist(self, txn: Transaction) -> None:
|
|
417
432
|
"""Save snapshot and append transaction (caller must hold lock)."""
|
|
@@ -422,6 +437,9 @@ class JouleWallet:
|
|
|
422
437
|
|
|
423
438
|
This is the raw persistence call used by both _persist() and
|
|
424
439
|
the transfer() method which manages its own locking.
|
|
440
|
+
|
|
441
|
+
Every call writes the wallet state and flushes the transaction
|
|
442
|
+
log to disk immediately so no data is lost on crash.
|
|
425
443
|
"""
|
|
426
444
|
self._snapshot.updated_at = datetime.now(timezone.utc).isoformat()
|
|
427
445
|
self._wallet_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -436,6 +454,7 @@ class JouleWallet:
|
|
|
436
454
|
try:
|
|
437
455
|
with self._log_path.open("a", encoding="utf-8") as fh:
|
|
438
456
|
fh.write(json.dumps(txn.model_dump()) + "\n")
|
|
457
|
+
fh.flush()
|
|
439
458
|
except OSError as exc:
|
|
440
459
|
logger.error("Failed to append transaction for %s: %s", self._agent, exc)
|
|
441
460
|
|
package/tests/test_agent_card.py
CHANGED
|
@@ -5,9 +5,10 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
import pgpy
|
|
9
8
|
import pytest
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
pgpy = pytest.importorskip("pgpy", reason="pgpy not installed")
|
|
11
|
+
from pgpy.constants import ( # noqa: E402
|
|
11
12
|
HashAlgorithm,
|
|
12
13
|
KeyFlags,
|
|
13
14
|
PubKeyAlgorithm,
|
|
@@ -19,14 +19,22 @@ import pytest
|
|
|
19
19
|
from click.testing import CliRunner
|
|
20
20
|
|
|
21
21
|
from skcapstone.cli import main
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
from skcapstone.completions import (
|
|
25
|
+
complete_memory_tags,
|
|
26
|
+
complete_agent_names,
|
|
27
|
+
complete_task_ids,
|
|
28
|
+
generate_script,
|
|
29
|
+
detect_shell,
|
|
30
|
+
SUPPORTED_SHELLS,
|
|
31
|
+
)
|
|
32
|
+
except ImportError:
|
|
33
|
+
pytest.skip(
|
|
34
|
+
"skcapstone.completions missing required names "
|
|
35
|
+
"(complete_memory_tags, complete_agent_names, complete_task_ids)",
|
|
36
|
+
allow_module_level=True,
|
|
37
|
+
)
|
|
30
38
|
|
|
31
39
|
|
|
32
40
|
# ---------------------------------------------------------------------------
|
package/tests/test_doctor_fix.py
CHANGED
|
@@ -21,13 +21,19 @@ from pathlib import Path
|
|
|
21
21
|
import pytest
|
|
22
22
|
from click.testing import CliRunner
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
try:
|
|
25
|
+
from skcapstone.doctor import (
|
|
26
|
+
Check,
|
|
27
|
+
DiagnosticReport,
|
|
28
|
+
FixResult,
|
|
29
|
+
run_diagnostics,
|
|
30
|
+
run_fixes,
|
|
31
|
+
)
|
|
32
|
+
except ImportError:
|
|
33
|
+
pytest.skip(
|
|
34
|
+
"skcapstone.doctor missing required names (FixResult, run_fixes)",
|
|
35
|
+
allow_module_level=True,
|
|
36
|
+
)
|
|
31
37
|
|
|
32
38
|
|
|
33
39
|
# ---------------------------------------------------------------------------
|
|
@@ -7,18 +7,17 @@ from unittest.mock import MagicMock, patch
|
|
|
7
7
|
|
|
8
8
|
import pytest
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
10
|
+
skseed_llm = pytest.importorskip("skseed.llm", reason="skseed not installed")
|
|
11
|
+
LLMCallback = skseed_llm.LLMCallback
|
|
12
|
+
_is_adapted_prompt = skseed_llm._is_adapted_prompt
|
|
13
|
+
anthropic_callback = skseed_llm.anthropic_callback
|
|
14
|
+
auto_callback = skseed_llm.auto_callback
|
|
15
|
+
grok_callback = skseed_llm.grok_callback
|
|
16
|
+
kimi_callback = skseed_llm.kimi_callback
|
|
17
|
+
nvidia_callback = skseed_llm.nvidia_callback
|
|
18
|
+
ollama_callback = skseed_llm.ollama_callback
|
|
19
|
+
openai_callback = skseed_llm.openai_callback
|
|
20
|
+
passthrough_callback = skseed_llm.passthrough_callback
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class TestIsAdaptedPrompt:
|