@geravant/sinain 1.12.0 → 1.14.0

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 (71) hide show
  1. package/.env.example +4 -2
  2. package/config-shared.js +1 -0
  3. package/package.json +4 -1
  4. package/sinain-agent/run.sh +36 -4
  5. package/sinain-core/package-lock.json +963 -0
  6. package/sinain-core/package.json +1 -0
  7. package/sinain-core/src/buffers/feed-buffer.ts +34 -0
  8. package/sinain-core/src/embedding/service.ts +66 -0
  9. package/sinain-core/src/index.ts +65 -17
  10. package/sinain-core/src/learning/local-curation.ts +137 -7
  11. package/sinain-core/src/server.ts +31 -0
  12. package/sinain-memory/README.md +105 -0
  13. package/sinain-memory/embed_client.py +117 -0
  14. package/sinain-memory/graph_query.py +269 -18
  15. package/sinain-memory/knowledge_integrator.py +551 -74
  16. package/sinain-memory/memory-config.json +1 -1
  17. package/sinain-memory/session_distiller.py +43 -19
  18. package/sinain-memory/triplestore.py +60 -0
  19. package/sinain-memory/__pycache__/common.cpython-312.pyc +0 -0
  20. package/sinain-memory/__pycache__/graph_query.cpython-312.pyc +0 -0
  21. package/sinain-memory/__pycache__/knowledge_integrator.cpython-312.pyc +0 -0
  22. package/sinain-memory/__pycache__/session_distiller.cpython-312.pyc +0 -0
  23. package/sinain-memory/__pycache__/triplestore.cpython-312.pyc +0 -0
  24. package/sinain-memory/eval/__init__.py +0 -0
  25. package/sinain-memory/eval/__pycache__/__init__.cpython-312.pyc +0 -0
  26. package/sinain-memory/eval/assertions.py +0 -267
  27. package/sinain-memory/eval/benchmarks/__init__.py +0 -0
  28. package/sinain-memory/eval/benchmarks/__pycache__/__init__.cpython-312.pyc +0 -0
  29. package/sinain-memory/eval/benchmarks/__pycache__/base_adapter.cpython-312.pyc +0 -0
  30. package/sinain-memory/eval/benchmarks/__pycache__/config.cpython-312.pyc +0 -0
  31. package/sinain-memory/eval/benchmarks/__pycache__/evaluate.cpython-312.pyc +0 -0
  32. package/sinain-memory/eval/benchmarks/__pycache__/ingest.cpython-312.pyc +0 -0
  33. package/sinain-memory/eval/benchmarks/__pycache__/longmemeval_adapter.cpython-312.pyc +0 -0
  34. package/sinain-memory/eval/benchmarks/__pycache__/query.cpython-312.pyc +0 -0
  35. package/sinain-memory/eval/benchmarks/__pycache__/report.cpython-312.pyc +0 -0
  36. package/sinain-memory/eval/benchmarks/__pycache__/runner.cpython-312.pyc +0 -0
  37. package/sinain-memory/eval/benchmarks/base_adapter.py +0 -43
  38. package/sinain-memory/eval/benchmarks/config.py +0 -23
  39. package/sinain-memory/eval/benchmarks/evaluate.py +0 -146
  40. package/sinain-memory/eval/benchmarks/ingest.py +0 -152
  41. package/sinain-memory/eval/benchmarks/judges/__init__.py +0 -0
  42. package/sinain-memory/eval/benchmarks/judges/__pycache__/__init__.cpython-312.pyc +0 -0
  43. package/sinain-memory/eval/benchmarks/judges/__pycache__/qa_judge.cpython-312.pyc +0 -0
  44. package/sinain-memory/eval/benchmarks/judges/qa_judge.py +0 -81
  45. package/sinain-memory/eval/benchmarks/longmemeval_adapter.py +0 -177
  46. package/sinain-memory/eval/benchmarks/query.py +0 -172
  47. package/sinain-memory/eval/benchmarks/report.py +0 -87
  48. package/sinain-memory/eval/benchmarks/runner.py +0 -276
  49. package/sinain-memory/eval/judges/__init__.py +0 -0
  50. package/sinain-memory/eval/judges/base_judge.py +0 -61
  51. package/sinain-memory/eval/judges/curation_judge.py +0 -46
  52. package/sinain-memory/eval/judges/insight_judge.py +0 -48
  53. package/sinain-memory/eval/judges/mining_judge.py +0 -42
  54. package/sinain-memory/eval/judges/signal_judge.py +0 -45
  55. package/sinain-memory/eval/retrieval_benchmark.jsonl +0 -12
  56. package/sinain-memory/eval/retrieval_evaluator.py +0 -186
  57. package/sinain-memory/eval/schemas.py +0 -247
  58. package/sinain-memory/tests/__init__.py +0 -0
  59. package/sinain-memory/tests/conftest.py +0 -189
  60. package/sinain-memory/tests/test_curator_helpers.py +0 -94
  61. package/sinain-memory/tests/test_embedder.py +0 -210
  62. package/sinain-memory/tests/test_extract_json.py +0 -124
  63. package/sinain-memory/tests/test_feedback_computation.py +0 -121
  64. package/sinain-memory/tests/test_miner_helpers.py +0 -71
  65. package/sinain-memory/tests/test_module_management.py +0 -458
  66. package/sinain-memory/tests/test_parsers.py +0 -96
  67. package/sinain-memory/tests/test_tick_evaluator.py +0 -430
  68. package/sinain-memory/tests/test_triple_extractor.py +0 -255
  69. package/sinain-memory/tests/test_triple_ingest.py +0 -191
  70. package/sinain-memory/tests/test_triple_migrate.py +0 -138
  71. package/sinain-memory/tests/test_triplestore.py +0 -248
package/.env.example CHANGED
@@ -23,9 +23,11 @@ PRIVACY_MODE=standard # off | standard | strict | paranoid
23
23
  # paranoid: almost nothing leaves your machine
24
24
 
25
25
  # ── Agent ────────────────────────────────────────────────────────────────────
26
- SINAIN_AGENT=claude # claude | codex | junie | goose | aider | <custom command>
27
- # MCP agents (claude, codex, junie, goose) call sinain tools directly
26
+ SINAIN_AGENT=claude # claude | openclaude | codex | junie | goose | aider | <custom command>
27
+ # MCP agents (claude, openclaude, codex, junie, goose) call sinain tools directly
28
28
  # Pipe agents (aider, custom) receive escalation text on stdin
29
+ # openclaude: set OPENAI_BASE_URL=http://localhost:11434/v1 + OPENAI_MODEL=<ollama-model>
30
+ # to route through local Ollama. Run.sh auto-warms the model on startup.
29
31
  SINAIN_CORE_URL=http://localhost:9500
30
32
  SINAIN_POLL_INTERVAL=5 # seconds between escalation polls
31
33
  SINAIN_HEARTBEAT_INTERVAL=900 # seconds between heartbeat ticks (15 min)
package/config-shared.js CHANGED
@@ -459,6 +459,7 @@ export async function stepAgent(existing, label = "Bare agent") {
459
459
  message: label,
460
460
  options: [
461
461
  { value: "claude", label: "Claude Code", hint: "Calls sinain tools directly — recommended" },
462
+ { value: "openclaude", label: "OpenClaude", hint: "Claude Code clone, local-first (Ollama/OpenAI-compat)" },
462
463
  { value: "codex", label: "Codex", hint: "Calls sinain tools directly" },
463
464
  { value: "goose", label: "Goose", hint: "Calls sinain tools directly" },
464
465
  { value: "junie", label: "Junie", hint: "JetBrains IDE agent" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geravant/sinain",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "Ambient intelligence that sees what you see, hears what you hear, and acts on your behalf",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,6 +25,9 @@
25
25
  "index.ts",
26
26
  "openclaw.plugin.json",
27
27
  "sinain-memory",
28
+ "!sinain-memory/eval",
29
+ "!sinain-memory/tests",
30
+ "!sinain-memory/**/__pycache__",
28
31
  "sinain-knowledge",
29
32
  "sinain-core/src",
30
33
  "sinain-core/package.json",
@@ -55,7 +55,7 @@ fi
55
55
  JUNIE_HAS_MCP=false # set during startup checks
56
56
  agent_has_mcp() {
57
57
  case "$AGENT" in
58
- claude|codex|goose) return 0 ;;
58
+ claude|openclaude|codex|goose) return 0 ;;
59
59
  junie) $JUNIE_HAS_MCP ;;
60
60
  *) return 1 ;;
61
61
  esac
@@ -67,11 +67,11 @@ agent_has_mcp() {
67
67
  invoke_agent() {
68
68
  local prompt="$1"
69
69
  case "$AGENT" in
70
- claude)
70
+ claude|openclaude)
71
71
  local turns="${2:-$AGENT_MAX_TURNS}"
72
72
  if [ -n "${SINAIN_SPAWN:-}" ]; then
73
73
  # Spawn: PreToolUse hook routes permission prompts to overlay HUD
74
- claude \
74
+ "$AGENT" \
75
75
  --mcp-config "$MCP_CONFIG" \
76
76
  --settings "$SCRIPT_DIR/.claude/settings.json" \
77
77
  ${ALLOWED_TOOLS:+--allowedTools $ALLOWED_TOOLS} \
@@ -79,7 +79,7 @@ invoke_agent() {
79
79
  -p "$prompt"
80
80
  else
81
81
  # Escalation: auto-approve for speed (short-lived, read-heavy)
82
- claude --enable-auto-mode \
82
+ "$AGENT" --enable-auto-mode \
83
83
  --mcp-config "$MCP_CONFIG" \
84
84
  ${ALLOWED_TOOLS:+--allowedTools $ALLOWED_TOOLS} \
85
85
  --max-turns "$turns" --output-format text \
@@ -227,6 +227,38 @@ print(' sinain extension added to ' + config_path)
227
227
  fi
228
228
  fi
229
229
 
230
+ # Ollama warmup — pin the backing model so each agent invocation hits hot weights.
231
+ # openclaude + Ollama via the OpenAI-compat endpoint does NOT forward keep_alive,
232
+ # so we ping Ollama's native /api/generate once with keep_alive=-1 (persistent).
233
+ # Applies to any agent pointed at an Ollama-compatible endpoint via OPENAI_BASE_URL.
234
+ OLLAMA_WARMUP="${OLLAMA_WARMUP:-true}"
235
+ if [ "$OLLAMA_WARMUP" = "true" ] && [ -n "${OPENAI_BASE_URL:-}" ]; then
236
+ if [[ "$OPENAI_BASE_URL" == *"11434"* ]] || [[ "$OPENAI_BASE_URL" == *"ollama"* ]]; then
237
+ # Derive Ollama host by stripping /v1 suffix from OPENAI_BASE_URL
238
+ OLLAMA_HOST="${OLLAMA_HOST:-${OPENAI_BASE_URL%/v1*}}"
239
+ OLLAMA_MODEL="${OLLAMA_MODEL:-${OPENAI_MODEL:-}}"
240
+ OLLAMA_KEEP_ALIVE="${OLLAMA_KEEP_ALIVE:--1}" # -1 = persistent, or "24h", "30m", etc.
241
+ if [ -n "$OLLAMA_MODEL" ]; then
242
+ echo "Warming Ollama model $OLLAMA_MODEL at $OLLAMA_HOST (keep_alive=$OLLAMA_KEEP_ALIVE)..."
243
+ # Ollama accepts keep_alive as int (-1 = persistent) or duration string ("24h", "30m").
244
+ if [[ "$OLLAMA_KEEP_ALIVE" =~ ^-?[0-9]+$ ]]; then
245
+ WARMUP_PAYLOAD="{\"model\":\"$OLLAMA_MODEL\",\"prompt\":\"\",\"keep_alive\":$OLLAMA_KEEP_ALIVE,\"stream\":false}"
246
+ else
247
+ WARMUP_PAYLOAD="{\"model\":\"$OLLAMA_MODEL\",\"prompt\":\"\",\"keep_alive\":\"$OLLAMA_KEEP_ALIVE\",\"stream\":false}"
248
+ fi
249
+ if curl -sf -m 60 -X POST "$OLLAMA_HOST/api/generate" \
250
+ -H 'Content-Type: application/json' \
251
+ -d "$WARMUP_PAYLOAD" >/dev/null 2>&1; then
252
+ echo " ✓ Model pinned in memory"
253
+ else
254
+ echo " ⚠ Warmup failed — first request will cold-start the model"
255
+ fi
256
+ else
257
+ echo " ⚠ OLLAMA_WARMUP=true but OPENAI_MODEL not set — skipping warmup"
258
+ fi
259
+ fi
260
+ fi
261
+
230
262
  # Agent mode label
231
263
  if agent_has_mcp; then
232
264
  AGENT_MODE="MCP"