Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,55 @@ def _bridge_command(*, daemon: bool) -> list[str]:
return [node, "--import", "tsx", *bridge_args]


def _rebuild_if_stale() -> bool:
"""Run `npm run build` if any TypeScript source is newer than dist/bridge.cjs.

Returns True if the binary is current or the build succeeded.
Returns False if the build failed — caller should continue with
the existing binary rather than blocking gateway startup.
"""
plugin_root = _plugin_root()
compiled = plugin_root / "dist" / "bridge.cjs"

if compiled.exists():
compiled_mtime = compiled.stat().st_mtime
newest_source = max(
(p.stat().st_mtime for p in plugin_root.rglob("*.ts")),
default=0.0,
)
if newest_source <= compiled_mtime:
return True

logger.info("MemOS: TypeScript source newer than dist/bridge.cjs — rebuilding...")
npm = shutil.which("npm")
if not npm:
logger.warning("MemOS: npm not found on PATH; skipping bridge rebuild")
return False
try:
result = subprocess.run(
[npm, "run", "build"],
cwd=str(plugin_root),
check=True,
timeout=120,
capture_output=True,
text=True,
)
logger.info("MemOS: bridge daemon rebuilt successfully")
if result.stderr:
logger.debug("MemOS: build stderr: %s", result.stderr.strip())
return True
except subprocess.CalledProcessError as e:
logger.error("MemOS: bridge rebuild failed:\n%s", e.stderr)
return False
except subprocess.TimeoutExpired:
logger.error("MemOS: bridge rebuild timed out after 120s")
return False
except Exception as e:
logger.error("MemOS: bridge rebuild error: %s", e)
return False



def ensure_bridge_running(*, probe_only: bool = False) -> bool:
"""Return True when the bridge is (or can be) operational.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
-- Add explicit metadata for feedback-derived experiences.
-- Existing policies are treated as success-backed procedural experience so
-- skill crystallization keeps its legacy behavior for old rows.
ALTER TABLE policies ADD COLUMN experience_type TEXT NOT NULL DEFAULT 'success_pattern'
CHECK (experience_type IN ('success_pattern','repair_validated','failure_avoidance','repair_instruction','preference','verifier_feedback','procedural'));
ALTER TABLE policies ADD COLUMN evidence_polarity TEXT NOT NULL DEFAULT 'positive'
CHECK (evidence_polarity IN ('positive','negative','neutral','mixed'));
ALTER TABLE policies ADD COLUMN salience REAL NOT NULL DEFAULT 0;
ALTER TABLE policies ADD COLUMN confidence REAL NOT NULL DEFAULT 0.5;
ALTER TABLE policies ADD COLUMN source_feedback_ids_json TEXT NOT NULL DEFAULT '[]'
CHECK (json_valid(source_feedback_ids_json));
ALTER TABLE policies ADD COLUMN source_trace_ids_json TEXT NOT NULL DEFAULT '[]'
CHECK (json_valid(source_trace_ids_json));
ALTER TABLE policies ADD COLUMN verifier_meta_json TEXT NOT NULL DEFAULT 'null'
CHECK (json_valid(verifier_meta_json));
ALTER TABLE policies ADD COLUMN skill_eligible INTEGER NOT NULL DEFAULT 1
CHECK (skill_eligible IN (0,1));
-- All ALTER TABLE columns backported into 001-initial.sql; only indexes remain here.

CREATE INDEX IF NOT EXISTS idx_policies_experience
ON policies(experience_type, evidence_polarity, updated_at DESC);
Expand Down