Skip to content
Merged
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
7 changes: 7 additions & 0 deletions examples/openclaw-plugin/memory-ranking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export function pickMemoriesForInjection(
items: FindResultItem[],
limit: number,
queryText: string,
scoreThreshold: number = 0,
): FindResultItem[] {
if (items.length === 0 || limit <= 0) {
return [];
Expand Down Expand Up @@ -254,6 +255,12 @@ export function pickMemoriesForInjection(
if (used.has(item.uri)) {
continue;
}
// Respect score threshold when supplementing leaf memories with
// non-leaf items. Without this check, low-scoring memories bypass
// the threshold configured in recallScoreThreshold (see #1106).
if (clampScore(item.score) < scoreThreshold) {
continue;
}
picked.push(item);
}
return picked;
Expand Down
10 changes: 10 additions & 0 deletions openviking/session/compressor.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,16 @@ async def _merge_into_existing(
target_memory.set_vectorize(Vectorize(text=payload.content))
await self._index_memory(target_memory, ctx, change_type="modified")
return True
except FileNotFoundError:
logger.warning(
"Target memory %s no longer exists — removing orphaned reference", target_memory.uri
)
# Clean up vector record for the missing file so it's not retried
try:
await self.vikingdb.delete_uris(ctx, [target_memory.uri])
except Exception:
pass
return False
except Exception as e:
logger.error(f"Failed to merge memory {target_memory.uri}: {e}")
return False
Expand Down
33 changes: 22 additions & 11 deletions openviking/utils/process_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,37 @@ def _is_pid_alive(pid: int) -> bool:
return False
try:
os.kill(pid, 0)
return True
except ProcessLookupError:
return False
except PermissionError:
# Process exists but we can't signal it.
return True
pass
except (OSError, SystemError):
if sys.platform == "win32":
# On Windows, os.kill(pid, 0) raises OSError for stale or invalid
# PIDs instead of ProcessLookupError. In some environments it can
# also bubble up as SystemError from the underlying Win32 wrapper.
# Common failures include:
# - WinError 87 "The parameter is incorrect"
# - WinError 11 "An attempt was made to load a program with an
# incorrect format"
# Treat these as "not alive" so stale lock files are correctly
# reclaimed on Windows.
return False
raise

# PID exists, but on Linux PIDs are recycled. Verify this is actually
# an OpenViking process by checking /proc/{pid}/cmdline to avoid false
# positives from PID reuse (see issue #1088).
if sys.platform.startswith("linux"):
try:
with open(f"/proc/{pid}/cmdline", "rb") as f:
cmdline = f.read().decode("utf-8", errors="replace").lower()
if "openviking" not in cmdline and "openviking-server" not in cmdline:
logger.info(
"PID %d is alive but not an OpenViking process (cmdline: %.100s). "
"Assuming stale lock from recycled PID.",
pid,
cmdline[:100],
)
return False
except OSError:
# /proc not available or process exited between kill and open
pass

return True


def acquire_data_dir_lock(data_dir: str) -> str:
"""Acquire an advisory PID lock on *data_dir*.
Expand Down
Loading