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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ jobs:
uses: Swatinem/rust-cache@v2

- name: Format
run: cargo fmt --all -- --check
run: make fmt-check

- name: Cargo check
run: cargo check --workspace
run: make check

- name: Cargo test
run: cargo test --workspace
- name: Validate test suite
run: make test-ci
12 changes: 7 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ jobs:
uses: Swatinem/rust-cache@v2

- name: Format
run: cargo fmt --all -- --check
run: make fmt-check

- name: Cargo check
run: cargo check --workspace
run: make check

- name: Cargo test
run: cargo test --workspace
- name: Validate test suite
run: make test-ci

build:
name: Build ${{ matrix.target }}
Expand Down Expand Up @@ -93,11 +93,12 @@ jobs:
set -eu
STAGE_DIR="dist/memory-bank"
BIN_DIR="${STAGE_DIR}/bin"
CONFIG_DIR="${STAGE_DIR}/config"
OPENCODE_DIR="${STAGE_DIR}/integrations/opencode"
OPENCLAW_DIR="${STAGE_DIR}/integrations/openclaw"

rm -rf dist
mkdir -p "${BIN_DIR}" "${OPENCODE_DIR}" "${OPENCLAW_DIR}"
mkdir -p "${BIN_DIR}" "${CONFIG_DIR}" "${OPENCODE_DIR}" "${OPENCLAW_DIR}"

cp "target/${TARGET}/release/mb" "${BIN_DIR}/mb"
cp "target/${TARGET}/release/memory-bank-server" "${BIN_DIR}/memory-bank-server"
Expand All @@ -111,6 +112,7 @@ jobs:

cp ".opencode/plugins/memory-bank.js" "${OPENCODE_DIR}/memory-bank.js"
cp -R ".openclaw/extensions/memory-bank" "${OPENCLAW_DIR}/memory-bank"
cp "config/setup-model-catalog.json" "${CONFIG_DIR}/setup-model-catalog.json"

tar -C "${STAGE_DIR}" -czf "memory-bank-${TARGET}.tar.gz" .

Expand Down
73 changes: 71 additions & 2 deletions .openclaw/extensions/memory-bank/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { spawnSync } = require("node:child_process");

const DEFAULT_AGENT = "openclaw";
const APP_ROOT_DIR_NAME = ".memory_bank";
const APP_SETTINGS_FILE_NAME = "settings.toml";
const DEFAULT_SERVER_URL = "http://127.0.0.1:3737";
const DEDUPE_CACHE_LIMIT = 2048;
const DUPLICATE_WINDOW_MS = 5_000;
Expand Down Expand Up @@ -315,18 +316,86 @@ function loadAppSettings(platform) {
return null;
}

const settingsPath = path.join(appRoot, "settings.json");
const settingsPath = path.join(appRoot, APP_SETTINGS_FILE_NAME);
if (!platform.fileExists(settingsPath)) {
return null;
}

try {
return JSON.parse(platform.readFile(settingsPath));
return parseAppSettingsToml(platform.readFile(settingsPath));
} catch {
return null;
}
}

function parseAppSettingsToml(contents) {
let currentSection = null;
let port = null;

for (const rawLine of String(contents).replace(/^\uFEFF/, "").split(/\r?\n/u)) {
const line = stripTomlLineComment(rawLine).trim();
if (!line) {
continue;
}

const sectionMatch = line.match(/^\[(.+)\]$/u);
if (sectionMatch) {
currentSection = sectionMatch[1].trim();
continue;
}

if (currentSection !== "service") {
continue;
}

const portMatch = line.match(/^port\s*=\s*(\d+)\s*$/u);
if (!portMatch) {
continue;
}

const parsed = Number.parseInt(portMatch[1], 10);
if (Number.isInteger(parsed) && parsed >= 1 && parsed <= 65535) {
port = parsed;
}
}

return port === null ? null : { service: { port } };
}

function stripTomlLineComment(line) {
let inDoubleQuote = false;
let escaped = false;
let result = "";

for (const char of line) {
if (inDoubleQuote) {
result += char;
if (escaped) {
escaped = false;
} else if (char === "\\") {
escaped = true;
} else if (char === '"') {
inDoubleQuote = false;
}
continue;
}

if (char === '"') {
inDoubleQuote = true;
result += char;
continue;
}

if (char === "#") {
break;
}

result += char;
}

return result;
}

function resolveServerUrlFromSettings(appSettings) {
const port = appSettings?.service?.port;
if (typeof port !== "number" || !Number.isFinite(port)) {
Expand Down
73 changes: 71 additions & 2 deletions .opencode/plugins/memory-bank.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { spawnSync } from "node:child_process";
const LOG_SERVICE = "memory-bank-opencode";
const DEFAULT_AGENT = "opencode";
const APP_ROOT_DIR_NAME = ".memory_bank";
const APP_SETTINGS_FILE_NAME = "settings.toml";
const DEFAULT_SERVER_URL = "http://127.0.0.1:3737";
const DEDUPE_CACHE_LIMIT = 2048;
const IMMEDIATE_ASSISTANT_RETRY_ATTEMPTS = 4;
Expand Down Expand Up @@ -888,19 +889,87 @@ function loadAppSettings(platform) {
return null;
}

const settingsPath = path.join(appRoot, "settings.json");
const settingsPath = path.join(appRoot, APP_SETTINGS_FILE_NAME);
if (!platform.fileExists(settingsPath)) {
return null;
}

try {
const contents = platform.readFile(settingsPath);
return JSON.parse(contents);
return parseAppSettingsToml(contents);
} catch {
return null;
}
}

function parseAppSettingsToml(contents) {
let currentSection = null;
let port = null;

for (const rawLine of String(contents).replace(/^\uFEFF/, "").split(/\r?\n/u)) {
const line = stripTomlLineComment(rawLine).trim();
if (!line) {
continue;
}

const sectionMatch = line.match(/^\[(.+)\]$/u);
if (sectionMatch) {
currentSection = sectionMatch[1].trim();
continue;
}

if (currentSection !== "service") {
continue;
}

const portMatch = line.match(/^port\s*=\s*(\d+)\s*$/u);
if (!portMatch) {
continue;
}

const parsed = Number.parseInt(portMatch[1], 10);
if (Number.isInteger(parsed) && parsed >= 1 && parsed <= 65535) {
port = parsed;
}
}

return port === null ? null : { service: { port } };
}

function stripTomlLineComment(line) {
let inDoubleQuote = false;
let escaped = false;
let result = "";

for (const char of line) {
if (inDoubleQuote) {
result += char;
if (escaped) {
escaped = false;
} else if (char === "\\") {
escaped = true;
} else if (char === '"') {
inDoubleQuote = false;
}
continue;
}

if (char === '"') {
inDoubleQuote = true;
result += char;
continue;
}

if (char === "#") {
break;
}

result += char;
}

return result;
}

function resolveServerUrlFromSettings(appSettings) {
const port = appSettings?.service?.port;
if (typeof port !== "number" || !Number.isFinite(port)) {
Expand Down
Loading