Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
fa122d8
fix: improve Node.js v25 compatibility for better-sqlite3
Mar 11, 2026
3474379
fix(memory): normalize auto-recall query for /new startup prompts
orion Mar 14, 2026
659e9bf
fix(openclaw-plugin): add memory search logging to viewer and fix ins…
hijzy Mar 31, 2026
d04a21f
Fix multi-agent memory display issue
Mar 31, 2026
f119113
Fix overlapping retrieval content in multi-agent mode
Mar 31, 2026
e694888
Fix compilation errors
Mar 31, 2026
d409db8
Merge branch 'refs/heads/openclaw-local-plugin-20260331' into update_…
Mar 31, 2026
593106e
fix: skip tools.allow patching when wildcard '*' is present
muwb Apr 1, 2026
9c1e492
revert: remove context engine registration, restore before_prompt_bui…
hijzy Apr 1, 2026
4c5c489
fix viewer agent memory list
Apr 1, 2026
78c09e5
fix(install): handle postinstall node_modules cleanup and stale config
hijzy Apr 1, 2026
c876c82
Merge branch 'fix-revert-jiang' into update_local_plugin_code
Apr 1, 2026
fae9450
Update local plugin code (#1396)
Hun-ger Apr 1, 2026
aafb773
Merge branch 'openclaw-local-plugin-20260331' into main
Hun-ger Apr 1, 2026
1d0932f
add skill delete func
Apr 1, 2026
7da91ca
feat(viewer): add configurable page size for memories, skills, and tasks
Apr 1, 2026
63fe3cf
Merge remote-tracking branch 'upstream/fix-revert-jiang' into update_…
Apr 1, 2026
79cc383
Update local plugin code (#1397)
Hun-ger Apr 1, 2026
abd319d
fix: improve Node.js v25 compatibility for better-sqlite3 (#1212)
Hun-ger Apr 1, 2026
87e8af8
Merge branch 'openclaw-local-plugin-20260331' into fix/normalize-auto…
Hun-ger Apr 1, 2026
9ddf887
fix(memory): normalize auto-recall query for /new startup prompts (#1…
Hun-ger Apr 1, 2026
d20c05e
fix: skip tools.allow patching when wildcard '*' is present (#1393)
Hun-ger Apr 1, 2026
9d07560
feat(viewer): add session filter and bulk delete for tasks/skills
Apr 2, 2026
a423fa7
feat(viewer): add session filter and bulk delete for tasks/skills (#1…
Hun-ger Apr 2, 2026
56afdc5
feat(memos-local): structured topic classifier, agent tracking, task …
tangbotony Apr 3, 2026
ce7c58b
fix(openclaw-plugin): self-start viewer when service.start() is not c…
hijzy Apr 3, 2026
dac3bbf
fix(openclaw-plugin): self-start viewer + install script improvements…
hijzy Apr 3, 2026
1399e45
fix(install): full plugin registration, daemonized gateway, and start…
hijzy Apr 3, 2026
0e5f61e
fix(viewer): fix concurrency select arrow overlap and restrict taskAu…
hijzy Apr 3, 2026
8463aa2
fix(viewer): fix concurrency select arrow overlap and restrict taskAu…
hijzy Apr 3, 2026
e8edc18
fix(memos-local-openclaw): viewer sharing, import layout, hub team se…
Apr 3, 2026
f70ee00
fix(memos-local-openclaw): admin shared task chunk label (x段记忆片段)
Apr 3, 2026
760620c
fix(memos-local-openclaw): viewer skills, hub list, and admin UI polish
Apr 3, 2026
11fa25d
feat(viewer): add owner badge, unified session key format, and improv…
tangbotony Apr 3, 2026
8391b3f
release: openclaw-plugin v1.0.8-beta.8
github-actions[bot] Apr 3, 2026
caee910
fix(memos-local-openclaw): memory card session badge label and copy f…
Apr 3, 2026
219e51d
merge(upstream): integrate release v1.0.8-beta.8, keep plugin at 1.0.…
Apr 3, 2026
cc0c999
ci(openclaw-plugin): allow npm version when package already at target
Apr 3, 2026
56675d8
ci(openclaw-plugin): push release tag only, not protected main
Apr 3, 2026
f0f9030
revert(ci): restore openclaw-plugin-publish.yml before workflow_dispa…
Apr 3, 2026
3259aff
ci(openclaw-plugin): allow-same-version + skip empty release commit
Apr 3, 2026
f62fd66
release: openclaw-plugin v1.0.8-beta.10
github-actions[bot] Apr 3, 2026
47f46b1
chore(memos-local-openclaw): bump to 1.0.8-beta.11, session badge age…
Apr 3, 2026
d5e846b
merge(upstream): resolve package.json to 1.0.8-beta.11
Apr 3, 2026
f91003b
fix(viewer): shorten session badge for IM bindings (agent:agentId)
Apr 3, 2026
7cf62c9
release: openclaw-plugin v1.0.8-beta.12
github-actions[bot] Apr 3, 2026
9994e5a
release: openclaw-plugin v1.0.8-beta.13
github-actions[bot] Apr 3, 2026
d590392
release: openclaw-plugin v1.0.8
github-actions[bot] Apr 3, 2026
bf9a476
merge(main): resolve install.sh / install.ps1 conflicts (PR 1435)
Apr 8, 2026
0f4105d
merge(upstream): sync openclaw-local-plugin-20260331 before push
Apr 8, 2026
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: 5 additions & 2 deletions .github/workflows/openclaw-plugin-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ jobs:
MEMOS_ARMS_ENV: ${{ secrets.MEMOS_ARMS_ENV }}

- name: Bump version
run: npm version ${{ inputs.version }} --no-git-tag-version
# Branch may already have this version in package.json (e.g. after a prior merge); npm errors without this flag.
run: npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version

- name: Publish to npm
run: npm publish --access public --tag ${{ inputs.tag }}
Expand All @@ -113,6 +114,8 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add apps/memos-local-openclaw/package.json
git commit -m "release: openclaw-plugin v${{ inputs.version }}"
if ! git diff --staged --quiet; then
git commit -m "release: openclaw-plugin v${{ inputs.version }}"
fi
git tag "openclaw-plugin-v${{ inputs.version }}"
git push origin HEAD --tags
725 changes: 391 additions & 334 deletions apps/memos-local-openclaw/index.ts

Large diffs are not rendered by default.

56 changes: 51 additions & 5 deletions apps/memos-local-openclaw/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ if (!config.plugins.allow.includes(pluginId)) {
// Clean up stale contextEngine slot from previous versions
if (config.plugins.slots && config.plugins.slots.contextEngine) {
delete config.plugins.slots.contextEngine;
if (Object.keys(config.plugins.slots).length === 0) {
delete config.plugins.slots;
}
}

// Register plugin in memory slot
Expand All @@ -209,25 +212,27 @@ if (!config.plugins.entries[pluginId] || typeof config.plugins.entries[pluginId]
}
config.plugins.entries[pluginId].enabled = true;

// Register plugin in installs so gateway auto-loads it on restart
// Register plugin in installs so gateway auto-loads it on restart (pinned spec when package.json exists)
if (!config.plugins.installs || typeof config.plugins.installs !== "object") {
config.plugins.installs = {};
}
let resolvedName = "";
let resolvedVersion = "";
const pkgJsonPath = path.join(installPath, "package.json");
let resolvedName, resolvedVersion;
if (fs.existsSync(pkgJsonPath)) {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
resolvedName = pkg.name;
resolvedVersion = pkg.version;
}
const pinnedSpec = resolvedName && resolvedVersion ? `${resolvedName}@${resolvedVersion}` : spec;
config.plugins.installs[pluginId] = {
source: "npm",
spec,
spec: pinnedSpec,
installPath,
...(resolvedVersion ? { version: resolvedVersion } : {}),
...(resolvedName ? { resolvedName } : {}),
...(resolvedVersion ? { resolvedVersion } : {}),
...(resolvedName && resolvedVersion ? { resolvedSpec: `${resolvedName}@${resolvedVersion}` } : {}),
...(resolvedName && resolvedVersion ? { resolvedSpec: pinnedSpec } : {}),
installedAt: new Date().toISOString(),
};

Expand Down Expand Up @@ -359,6 +364,38 @@ if (-not (Test-Path $ExtensionDir)) {
exit 1
}

$NodeModulesDir = Join-Path $ExtensionDir "node_modules"
if (-not (Test-Path $NodeModulesDir)) {
Write-Warn "node_modules missing after install (postinstall may have cleaned it). Reinstalling..."
Push-Location $ExtensionDir
try {
& npm install --omit=dev --no-fund --no-audit --ignore-scripts --loglevel=error 2>&1
}
finally {
Pop-Location
}
}

$SqliteDir = Join-Path $ExtensionDir "node_modules\better-sqlite3"
if (-not (Test-Path $SqliteDir)) {
Write-Warn "better-sqlite3 missing, attempting rebuild..."
Push-Location $ExtensionDir
try {
& npm rebuild better-sqlite3 2>&1
}
catch {
Write-Warn "better-sqlite3 rebuild returned an error. Continuing..."
}
finally {
Pop-Location
}
}

if (-not (Test-Path $NodeModulesDir)) {
Write-Err "Dependencies installation failed. Run manually: cd $ExtensionDir && npm install --omit=dev"
exit 1
}

Update-OpenClawConfig -OpenClawHome $OpenClawHome -ConfigPath $OpenClawConfigPath -PluginId $PluginId -InstallPath $ExtensionDir -Spec $PackageSpec

Write-Info "Installing OpenClaw Gateway service..."
Expand All @@ -368,9 +405,18 @@ if (-not $?) { Write-Warn "Gateway service install returned a warning; continuin
Write-Success "Starting OpenClaw Gateway service..."
& npx openclaw gateway start 2>&1

Write-Info "Starting Memory Viewer, 正在启动记忆面板..."
for ($i = 1; $i -le 5; $i++) {
$listening = Get-NetTCPConnection -LocalPort 18799 -State Listen -ErrorAction SilentlyContinue
if ($listening) { break }
Write-Host "." -NoNewline
Start-Sleep -Seconds 1
}
Write-Host ""

Write-Host ""
Write-Success "=========================================="
Write-Success " Installation complete!"
Write-Success " Installation complete! 安装完成!"
Write-Success "=========================================="
Write-Host ""
Write-Info " OpenClaw Web UI: http://localhost:$Port"
Expand Down
45 changes: 41 additions & 4 deletions apps/memos-local-openclaw/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ if (!config.plugins.allow.includes(pluginId)) {
// Clean up stale contextEngine slot from previous versions
if (config.plugins.slots && config.plugins.slots.contextEngine) {
delete config.plugins.slots.contextEngine;
if (Object.keys(config.plugins.slots).length === 0) {
delete config.plugins.slots;
}
}
// Register plugin in memory slot
Expand All @@ -269,25 +272,27 @@ if (!config.plugins.entries[pluginId] || typeof config.plugins.entries[pluginId]
}
config.plugins.entries[pluginId].enabled = true;
// Register plugin in installs so gateway auto-loads it on restart
// Register plugin in installs so gateway auto-loads it on restart (pinned spec when package.json exists)
if (!config.plugins.installs || typeof config.plugins.installs !== 'object') {
config.plugins.installs = {};
}
let resolvedName = '';
let resolvedVersion = '';
const pkgJsonPath = path.join(installPath, 'package.json');
let resolvedName, resolvedVersion;
if (fs.existsSync(pkgJsonPath)) {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
resolvedName = pkg.name;
resolvedVersion = pkg.version;
}
const pinnedSpec = resolvedName && resolvedVersion ? `${resolvedName}@${resolvedVersion}` : spec;
config.plugins.installs[pluginId] = {
source: 'npm',
spec,
spec: pinnedSpec,
installPath,
...(resolvedVersion ? { version: resolvedVersion } : {}),
...(resolvedName ? { resolvedName } : {}),
...(resolvedVersion ? { resolvedVersion } : {}),
...(resolvedName && resolvedVersion ? { resolvedSpec: `${resolvedName}@${resolvedVersion}` } : {}),
...(resolvedName && resolvedVersion ? { resolvedSpec: pinnedSpec } : {}),
installedAt: new Date().toISOString(),
};
Expand Down Expand Up @@ -358,6 +363,28 @@ if [[ ! -d "$EXTENSION_DIR" ]]; then
exit 1
fi

if [[ ! -d "${EXTENSION_DIR}/node_modules" ]]; then
warn "node_modules missing after install (postinstall may have cleaned it), 安装后 node_modules 缺失,正在重新安装..."
(
cd "${EXTENSION_DIR}"
npm install --omit=dev --no-fund --no-audit --ignore-scripts --loglevel=error 2>&1
)
fi

if [[ ! -d "${EXTENSION_DIR}/node_modules/better-sqlite3" ]]; then
warn "better-sqlite3 missing, attempting rebuild, better-sqlite3 缺失,尝试重新编译..."
(
cd "${EXTENSION_DIR}"
npm rebuild better-sqlite3 2>&1 || true
)
fi

if [[ ! -d "${EXTENSION_DIR}/node_modules" ]]; then
error "Dependencies installation failed. Run manually: cd ${EXTENSION_DIR} && npm install --omit=dev"
error "依赖安装失败,请手动运行: cd ${EXTENSION_DIR} && npm install --omit=dev"
exit 1
fi

update_openclaw_config

info "Install OpenClaw Gateway service, 安装 OpenClaw Gateway 服务..."
Expand All @@ -366,6 +393,16 @@ npx openclaw gateway install --port "${PORT}" --force 2>&1 || true
success "Start OpenClaw Gateway service, 启动 OpenClaw Gateway 服务..."
npx openclaw gateway start 2>&1

info "Starting Memory Viewer, 正在启动记忆面板..."
for i in 1 2 3 4 5; do
if command -v lsof >/dev/null 2>&1 && lsof -i :18799 -t >/dev/null 2>&1; then
break
fi
printf "."
sleep 1
done
echo ""

echo ""
success "=========================================="
success " Installation complete! 安装完成!"
Expand Down
2 changes: 1 addition & 1 deletion apps/memos-local-openclaw/openclaw.plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "MemOS Local Memory",
"description": "Full-write local conversation memory with hybrid search (RRF + MMR + recency), task summarization, skill evolution, and team sharing (Hub-Client). Provides memory_search, memory_get, task_summary, skill_search, task_share, network_skill_pull, network_team_info, memory_viewer for layered retrieval and team collaboration.",
"kind": "memory",
"version": "1.0.6-beta.11",
"version": "1.0.8",
"skills": [
"skill/memos-memory-guide"
],
Expand Down
7 changes: 4 additions & 3 deletions apps/memos-local-openclaw/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@memtensor/memos-local-openclaw-plugin",
"version": "1.0.7-beta.1",
"version": "1.0.8",
"description": "MemOS Local memory plugin for OpenClaw — full-write, hybrid-recall, progressive retrieval",
"type": "module",
"main": "index.ts",
Expand Down Expand Up @@ -45,12 +45,13 @@
],
"license": "MIT",
"engines": {
"node": ">=22.0.0"
"node": ">=18.0.0 <25.0.0"
},
"dependencies": {
"@huggingface/transformers": "^3.8.0",
"@sinclair/typebox": "^0.34.48",
"better-sqlite3": "^12.6.2",
"better-sqlite3": "^12.6.3",
"posthog-node": "^5.28.0",
"puppeteer": "^24.38.0",
"semver": "^7.7.4",
"uuid": "^10.0.0"
Expand Down
84 changes: 59 additions & 25 deletions apps/memos-local-openclaw/scripts/postinstall.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,23 @@ function normalizePathForMatch(p) {
return path.resolve(p).replace(/^\\\\\?\\/, "").replace(/\\/g, "/").toLowerCase();
}

const nodeVersion = process.version;
const nodeMajor = parseInt(nodeVersion.slice(1).split('.')[0], 10);

console.log(`
${CYAN}${BOLD}┌──────────────────────────────────────────────────┐
│ MemOS Local Memory — postinstall setup │
└──────────────────────────────────────────────────┘${RESET}
`);

log(`Plugin dir: ${DIM}${pluginDir}${RESET}`);
log(`Node: ${process.version} Platform: ${process.platform}-${process.arch}`);
log(`Node: ${GREEN}${nodeVersion}${RESET} Platform: ${process.platform}-${process.arch}`);

if (nodeMajor >= 25) {
warn(`Node.js ${nodeVersion} detected. This version may have compatibility issues with native modules.`);
log(`Recommended: Use Node.js LTS (v20 or v22) for best compatibility.`);
log(`You can use nvm to switch versions: ${CYAN}nvm use 22${RESET}`);
}

/* ═══════════════════════════════════════════════════════════
* Pre-phase: Clean stale build artifacts on upgrade
Expand All @@ -61,21 +70,30 @@ function cleanStaleArtifacts() {
installedVer = pkg.version || "unknown";
} catch { /* ignore */ }

const nodeMajor = process.versions.node.split(".")[0];
const currentFingerprint = `${installedVer}+node${nodeMajor}`;

const markerPath = path.join(pluginDir, ".installed-version");
let prevVer = "";
try { prevVer = fs.readFileSync(markerPath, "utf-8").trim(); } catch { /* first install */ }
let prevFingerprint = "";
try { prevFingerprint = fs.readFileSync(markerPath, "utf-8").trim(); } catch { /* first install */ }

const writeMarker = () => {
try { fs.writeFileSync(markerPath, currentFingerprint + "\n", "utf-8"); } catch { /* ignore */ }
};

if (prevVer === installedVer) {
log(`Version unchanged (${installedVer}), skipping artifact cleanup.`);
if (prevFingerprint === currentFingerprint) {
log(`Version unchanged (${currentFingerprint}), skipping artifact cleanup.`);
return;
}

if (prevVer) {
log(`Upgrade detected: ${DIM}${prevVer}${RESET} → ${GREEN}${installedVer}${RESET}`);
} else {
log(`Fresh install: ${GREEN}${installedVer}${RESET}`);
if (!prevFingerprint) {
log(`Fresh install: ${GREEN}${currentFingerprint}${RESET}`);
writeMarker();
return;
}

log(`Environment changed: ${DIM}${prevFingerprint}${RESET} → ${GREEN}${currentFingerprint}${RESET}`);

const dirsToClean = ["dist", "node_modules"];
let cleaned = 0;
for (const dir of dirsToClean) {
Expand All @@ -99,7 +117,7 @@ function cleanStaleArtifacts() {
}
}

try { fs.writeFileSync(markerPath, installedVer + "\n", "utf-8"); } catch { /* ignore */ }
writeMarker();

if (cleaned > 0) {
ok(`Cleaned ${cleaned} stale artifact(s). Fresh install will follow.`);
Expand Down Expand Up @@ -418,23 +436,39 @@ if (sqliteBindingsExist()) {
else { fail(`Rebuild completed but bindings still missing (${elapsed}s).`); fail(`Looked in: ${sqliteModulePath}/build/`); }
console.log(`
${YELLOW}${BOLD} ╔══════════════════════════════════════════════════════════════╗
║ ✖ better-sqlite3 native module build failed ║
║ ✖ better-sqlite3 native module build failed
╠══════════════════════════════════════════════════════════════╣${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} This plugin requires C/C++ build tools to compile ${YELLOW}║${RESET}
${YELLOW} ║${RESET} the SQLite native module on first install. ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${BOLD}Install build tools:${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}macOS:${RESET} xcode-select --install ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}Ubuntu:${RESET} sudo apt install build-essential python3 ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}Windows:${RESET} npm install -g windows-build-tools ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${BOLD}Then retry:${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} This plugin requires C/C++ build tools to compile ${YELLOW}║${RESET}
${YELLOW} ║${RESET} the SQLite native module on first install. ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${BOLD}Install build tools:${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}macOS:${RESET} xcode-select --install ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}Ubuntu:${RESET} sudo apt install build-essential python3 ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}Windows:${RESET} npm install -g windows-build-tools ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}`);

if (nodeMajor >= 25) {
console.log(`${YELLOW} ║${RESET} ${BOLD}${RED}Node.js v25+ compatibility issue detected:${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} better-sqlite3 may not have prebuilt binaries for Node 25. ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${BOLD}Recommended solutions:${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} 1. Use Node.js LTS (v20 or v22): ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${GREEN}nvm install 22 && nvm use 22${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} 2. Or use MemOS Cloud version instead: ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${CYAN}https://github.com/MemTensor/MemOS/tree/main/apps/memos-cloud${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}`);
}

console.log(`${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${BOLD}Then retry:${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${GREEN}cd ${pluginDir}${RESET}
${YELLOW} ║${RESET} ${GREEN}npm rebuild better-sqlite3${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${GREEN}openclaw gateway stop && openclaw gateway start${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${GREEN}npm rebuild better-sqlite3${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${GREEN}openclaw gateway stop && openclaw gateway start${RESET} ${YELLOW}║${RESET}
${YELLOW} ║${RESET} ${YELLOW}║${RESET}
${YELLOW}${BOLD} ╚══════════════════════════════════════════════════════════════╝${RESET}
`);
}
Expand Down
11 changes: 11 additions & 0 deletions apps/memos-local-openclaw/src/client/hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,26 @@ function getClientIp(): string {
return "";
}

const HUB_FETCH_TIMEOUT_MS = 25_000;

export async function hubRequestJson(
hubUrl: string,
userToken: string,
route: string,
init: RequestInit = {},
): Promise<unknown> {
const clientIp = getClientIp();
const timeoutSignal =
typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function"
? AbortSignal.timeout(HUB_FETCH_TIMEOUT_MS)
: undefined;
const mergedSignal =
timeoutSignal && init.signal
? AbortSignal.any([timeoutSignal, init.signal])
: (timeoutSignal ?? init.signal);
const res = await fetch(`${normalizeHubUrl(hubUrl)}${route}`, {
...init,
...(mergedSignal ? { signal: mergedSignal } : {}),
headers: {
authorization: `Bearer ${userToken}`,
...(clientIp ? { "x-client-ip": clientIp } : {}),
Expand Down
Loading
Loading