create-openclaw-bot 5.13.8 → 5.13.9

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.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  *Run one command → open the dashboard → your bot is live. Windows · macOS · Linux · VPS — Docker-powered, auto-installed for you.*
8
8
 
9
9
  <p align="center">
10
- <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.13.8-0EA5E9?style=for-the-badge" alt="Version 5.13.8" /></a>
10
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.13.9-0EA5E9?style=for-the-badge" alt="Version 5.13.9" /></a>
11
11
  <a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
12
12
  <a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
13
13
  <a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
@@ -37,11 +37,19 @@
37
37
 
38
38
  ---
39
39
 
40
- ## 🆕 What's New in v5.13.8
40
+ ## 🆕 What's New in v5.13.9
41
+
42
+ - 🧠 **Always-on memory for every bot (learning-memory)**: a new context-engine plugin injects your curated `MEMORY.md` + `USER.md` into **every** turn — including group chats, which the default recall skips. Bots stop forgetting context and rules over time: no more chiming in when nobody called them, or re-asking things you already told them. Auto-installed for new bots + a 1-click card in the dashboard.
43
+ - 🧹 **Retired TencentDB Agent Memory** in favor of the always-on engine above (no external service needed). Existing bots are auto-migrated on update — the old learning-memory *skill* and the TencentDB plugin are removed automatically.
44
+
45
+ <details>
46
+ <summary><b>Previous: What's new in v5.13.4</b></summary>
41
47
 
42
48
  - ⚙️ **New Settings page**: pick your theme (light/dark toggle), language (VI/EN) and timezone right from the dashboard — available in both the sidebar and the mobile nav bar.
43
49
  - 🕒 **Schedules & cron run in the correct local time**: newly created bots carry an explicit timezone, so reminders/cron no longer drift a day off around midnight (a UTC-vs-local bug that could schedule into the past). Scheduling guidance was hardened end-to-end (local time + timezone, explicit delivery target, raw group id).
44
50
 
51
+ </details>
52
+
45
53
  <details>
46
54
  <summary><b>Previous: What's new in v5.13.0</b></summary>
47
55
 
@@ -336,7 +344,7 @@ Companion repos to build a complete, self-running AI assistant:
336
344
  - [openclaw-n8n-facebook-poster](https://github.com/tuanminhhole/openclaw-n8n-facebook-poster) — Auto-post to Facebook via n8n
337
345
 
338
346
  **🧩 Skills**
339
- - [openclaw-skill-learning-memory](https://github.com/tuanminhhole/openclaw-skill-learning-memory) — Self-evolving long-term memory for agents
347
+ - [openclaw-learning-memory](https://github.com/tuanminhhole/openclaw-learning-memory) — Always-on memory context engine (injects curated MEMORY.md + USER.md into every turn, incl. groups)
340
348
  - [openclaw-skill-infographic](https://github.com/tuanminhhole/openclaw-skill-infographic) — Infographic generation
341
349
 
342
350
  ---
package/README.vi.md CHANGED
@@ -7,7 +7,7 @@
7
7
  *Chạy một lệnh → mở dashboard → bot lên sóng. Windows · macOS · Linux · VPS — chạy trên Docker, tự cài giúp bạn.*
8
8
 
9
9
  <p align="center">
10
- <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.13.8-0EA5E9?style=for-the-badge" alt="Version 5.13.8" /></a>
10
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.13.9-0EA5E9?style=for-the-badge" alt="Version 5.13.9" /></a>
11
11
  <a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
12
12
  <a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
13
13
  <a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
@@ -37,11 +37,19 @@
37
37
 
38
38
  ---
39
39
 
40
- ## 🆕 Có gì mới trong v5.13.8
40
+ ## 🆕 Có gì mới trong v5.13.9
41
+
42
+ - 🧠 **Trí nhớ always-on cho mọi bot (learning-memory)**: plugin context-engine mới nạp `MEMORY.md` + `USER.md` đã chắt lọc vào **MỌI lượt** — kể cả trong nhóm (điều recall mặc định bỏ qua). Bot hết quên ngữ cảnh/quy tắc theo thời gian: không còn "nói leo" khi không ai gọi, không hỏi lại điều bạn đã dặn. Tự cài cho bot mới + có card 1-chạm trên dashboard.
43
+ - 🧹 **Bỏ TencentDB Agent Memory**, thay bằng engine always-on ở trên (không cần dịch vụ ngoài). Bot cũ tự migrate khi cập nhật — *skill* learning-memory cũ và plugin TencentDB được gỡ tự động.
44
+
45
+ <details>
46
+ <summary><b>Trước đó: Có gì mới trong v5.13.4</b></summary>
41
47
 
42
48
  - ⚙️ **Trang Cài đặt mới**: chọn giao diện (nút gạt Sáng/Tối), ngôn ngữ (VI/EN) và múi giờ ngay trong dashboard — có ở cả sidebar lẫn thanh điều hướng mobile.
43
49
  - 🕒 **Lịch & cron chạy đúng giờ địa phương**: bot tạo mới nhận múi giờ rõ ràng, nên nhắc hẹn/cron không còn lệch 1 ngày quanh nửa đêm (lỗi UTC-vs-local có thể đặt lịch vào quá khứ). Đã siết hướng dẫn lập lịch toàn diện (giờ local + múi giờ, nơi gửi rõ ràng, ID nhóm dạng thô).
44
50
 
51
+ </details>
52
+
45
53
  <details>
46
54
  <summary><b>Trước đó: Có gì mới trong v5.13.0</b></summary>
47
55
 
@@ -336,7 +344,7 @@ Các repo đi kèm để bạn dựng một trợ lý AI "tự vận hành" hoà
336
344
  - [openclaw-n8n-facebook-poster](https://github.com/tuanminhhole/openclaw-n8n-facebook-poster) — Tự động đăng Facebook qua n8n
337
345
 
338
346
  **🧩 Skill**
339
- - [openclaw-skill-learning-memory](https://github.com/tuanminhhole/openclaw-skill-learning-memory) — Bộ nhớ dài hạn tự tiến hoá cho agent
347
+ - [openclaw-learning-memory](https://github.com/tuanminhhole/openclaw-learning-memory) — Context engine trí nhớ always-on (nạp MEMORY.md + USER.md vào mọi lượt, kể cả nhóm)
340
348
  - [openclaw-skill-infographic](https://github.com/tuanminhhole/openclaw-skill-infographic) — Tạo infographic
341
349
 
342
350
  ---
@@ -1032,14 +1032,16 @@ function ensureZaloModPluginConfig(entry, cfg) {
1032
1032
  const gwPort = Number(cfg.gateway?.port) || state.gatewayPort || 18789;
1033
1033
  entry.config.dashboardPort = gwPort + 1;
1034
1034
  }
1035
- // Auto-assign botName from first agent name
1036
- if (!entry.config.botName) {
1037
- const agentName = cfg.agents?.list?.[0]?.name;
1038
- if (agentName) entry.config.botName = agentName;
1039
- }
1040
- // Auto-assign zaloDisplayNames from botName
1041
- if ((!entry.config.zaloDisplayNames || entry.config.zaloDisplayNames.length === 0) && entry.config.botName) {
1042
- entry.config.zaloDisplayNames = [entry.config.botName];
1035
+ // Seed the default bot's identity under bots.default (per-bot shape). zalo-mod
1036
+ // treats bots.<profile> as the canonical source — do NOT write legacy top-level
1037
+ // botName/zaloDisplayNames (they get stripped by the plugin's normalizer anyway).
1038
+ const firstAgentName = cfg.agents?.list?.[0]?.name;
1039
+ if (firstAgentName) {
1040
+ entry.config.bots = entry.config.bots || {};
1041
+ const def = entry.config.bots.default = entry.config.bots.default || {};
1042
+ if (!def.botName) def.botName = firstAgentName;
1043
+ if (!Array.isArray(def.zaloDisplayNames) || def.zaloDisplayNames.length === 0) def.zaloDisplayNames = [firstAgentName];
1044
+ if (!def.slashPrefix) def.slashPrefix = String(firstAgentName).toLowerCase().replace(/[^a-z0-9-]/g, '') || 'bot';
1043
1045
  }
1044
1046
  }
1045
1047
 
@@ -3126,8 +3128,8 @@ async function applyFeatureToggle(projectDir, agentId, kind, id, enabled) {
3126
3128
  // from <workspace>/skills, so each bot's copy is independent. Toggling here affects ONLY the
3127
3129
  // active bot's workspace folder. The global skills.entries[id].enabled flag is kept true
3128
3130
  // while ANY bot still has the folder (openclaw needs it true to load the skill at all).
3129
- if (kind === 'skill' && (id === 'image-gen' || id === 'learning-memory')) {
3130
- const slugMap = { 'image-gen': 'infographic-generator', 'learning-memory': 'learning-memory' };
3131
+ if (kind === 'skill' && id === 'image-gen') {
3132
+ const slugMap = { 'image-gen': 'infographic-generator' };
3131
3133
  const slug = slugMap[id];
3132
3134
  const rel = workspaceRelForAgent(agent, cfg, projectDir) || `workspace-${agent.id}`;
3133
3135
  const folder = join(projectDir, '.openclaw', rel, 'skills', slug);
@@ -3284,7 +3286,9 @@ async function applyFeatureToggle(projectDir, agentId, kind, id, enabled) {
3284
3286
  // Most plugins are ClawHub packages (installed as `clawhub:<id>`). A few ship as plain npm
3285
3287
  // packages and need their real package spec instead. Map id → install spec here.
3286
3288
  const PLUGIN_NPM_SPEC = {
3287
- 'memory-tencentdb': '@tencentdb-agent-memory/memory-tencentdb',
3289
+ // learning-memory ships on ClawHub as `openclaw-learning-memory` (manifest id is
3290
+ // `learning-memory`, used as the config key). Install by the full package spec.
3291
+ 'learning-memory': 'clawhub:openclaw-learning-memory',
3288
3292
  };
3289
3293
  const pluginInstallSpec = (id) => PLUGIN_NPM_SPEC[id] || `clawhub:${id}`;
3290
3294
 
@@ -3292,7 +3296,6 @@ async function installFeature(projectDir, agentId, kind, id) {
3292
3296
  if (kind === 'skill') {
3293
3297
  const skillSlugMap = {
3294
3298
  'image-gen': 'infographic-generator',
3295
- 'learning-memory': 'learning-memory',
3296
3299
  };
3297
3300
  const slug = skillSlugMap[id] || id;
3298
3301
 
@@ -3379,6 +3382,11 @@ async function installFeature(projectDir, agentId, kind, id) {
3379
3382
  sendLog('[zalo-connect] Restarting container to apply...');
3380
3383
  await run('docker', ['restart', getBotContainerName(projectDir)], { shell: false }).catch(() => {});
3381
3384
  }
3385
+ // Drop cached container extension versions so the card reflects the just-installed
3386
+ // version immediately (extver cache lives until explicitly cleared, like the
3387
+ // general install path below does).
3388
+ probeCacheClear(`extver:${projectDir}`);
3389
+ probeCacheClear(`runtime:${projectDir}`);
3382
3390
  return { ok: true, id: 'zalo-connect' };
3383
3391
  }
3384
3392
  const installSpec = pluginInstallSpec(id);
@@ -3675,14 +3683,13 @@ async function getFeatureFlags(projectDir, agentId = '') {
3675
3683
  // THIS agent's workspace (not the global skills.entries flag, which would leak across bots).
3676
3684
  const imageGenOn = isSkillFolderExists(projectDir, aid, 'infographic-generator', cfg);
3677
3685
  const webSearchOn = isEnabled(['duckduckgo']);
3678
- const learningMemoryOn = isSkillFolderExists(projectDir, aid, 'learning-memory', cfg);
3679
3686
  const aliases = {
3680
3687
  browser: ['openclaw-browser-automation', 'browser-automation'],
3681
3688
  zalo: ['openclaw-zalo-mod', 'zalo-mod'],
3682
3689
  crawler: ['openclaw-facebook-crawler', 'openclaw-n8n-facebook-crawler', 'n8n-facebook-crawler'],
3683
3690
  poster: ['openclaw-n8n-facebook-poster', 'openclaw-facebook-poster', 'facebook-poster'],
3684
3691
  fbMessenger: ['openclaw-fb-messenger', 'fb-messenger'],
3685
- tencentMemory: ['memory-tencentdb'],
3692
+ learningMemory: ['learning-memory', 'openclaw-learning-memory'],
3686
3693
  zaloConnect: ['zalo-connect', 'openclaw-zalo-connect'],
3687
3694
  };
3688
3695
  const flags = {
@@ -3690,13 +3697,12 @@ async function getFeatureFlags(projectDir, agentId = '') {
3690
3697
  'skill:cron': cronOn,
3691
3698
  'skill:image-gen': imageGenOn,
3692
3699
  'skill:web-search': webSearchOn,
3693
- 'skill:learning-memory': learningMemoryOn,
3694
3700
  'plugin:openclaw-browser-automation': isEnabled(aliases.browser),
3695
3701
  'plugin:openclaw-zalo-mod': isEnabled(aliases.zalo),
3696
3702
  'plugin:openclaw-facebook-crawler': isEnabled(aliases.crawler),
3697
3703
  'plugin:openclaw-n8n-facebook-poster': isEnabled(aliases.poster),
3698
3704
  'plugin:openclaw-fb-messenger': isEnabled(aliases.fbMessenger),
3699
- 'plugin:memory-tencentdb': isEnabled(aliases.tencentMemory),
3705
+ 'plugin:learning-memory': isEnabled(aliases.learningMemory),
3700
3706
  'plugin:zalo-connect': isEnabled(aliases.zaloConnect),
3701
3707
  };
3702
3708
  const extensionsDir = join(projectDir || '', '.openclaw', 'extensions');
@@ -3706,7 +3712,6 @@ async function getFeatureFlags(projectDir, agentId = '') {
3706
3712
  extensionDirExists(aliases) || isInstalledByRecord(aliases);
3707
3713
  const installed = {
3708
3714
  'skill:image-gen': isSkillFolderExists(projectDir, aid, 'infographic-generator', cfg),
3709
- 'skill:learning-memory': isSkillFolderExists(projectDir, aid, 'learning-memory', cfg),
3710
3715
  'plugin:openclaw-browser-automation': isActuallyInstalled(aliases.browser),
3711
3716
  'plugin:openclaw-zalo-mod': isActuallyInstalled(aliases.zalo),
3712
3717
  'plugin:openclaw-facebook-crawler': isActuallyInstalled(aliases.crawler),
@@ -3715,31 +3720,34 @@ async function getFeatureFlags(projectDir, agentId = '') {
3715
3720
  // proof of install — require a real extension dir or an install record instead.
3716
3721
  'plugin:openclaw-fb-messenger': extensionDirExists(aliases.fbMessenger)
3717
3722
  || aliases.fbMessenger.some((a) => installedKeys.has(a) || Array.from(installedSpecs).some((spec) => spec.includes(a))),
3718
- 'plugin:memory-tencentdb': isActuallyInstalled(aliases.tencentMemory),
3723
+ 'plugin:learning-memory': isActuallyInstalled(aliases.learningMemory),
3719
3724
  'plugin:zalo-connect': isActuallyInstalled(aliases.zaloConnect),
3720
3725
  };
3721
3726
  const versions = {
3722
3727
  'skill:image-gen': await getInstalledSkillVersion(projectDir, aid, 'infographic-generator', cfg),
3723
- 'skill:learning-memory': await getInstalledSkillVersion(projectDir, aid, 'learning-memory', cfg),
3724
3728
  'plugin:openclaw-browser-automation': await getInstalledPluginVersion(projectDir, aliases.browser),
3725
3729
  'plugin:openclaw-zalo-mod': await getInstalledPluginVersion(projectDir, aliases.zalo),
3726
3730
  'plugin:openclaw-facebook-crawler': await getInstalledPluginVersion(projectDir, aliases.crawler),
3727
3731
  'plugin:openclaw-n8n-facebook-poster': await getInstalledPluginVersion(projectDir, aliases.poster),
3728
3732
  'plugin:openclaw-fb-messenger': await getInstalledPluginVersion(projectDir, aliases.fbMessenger),
3729
- 'plugin:memory-tencentdb': await getInstalledPluginVersion(projectDir, aliases.tencentMemory),
3733
+ 'plugin:learning-memory': await getInstalledPluginVersion(projectDir, aliases.learningMemory),
3730
3734
  'plugin:zalo-connect': await getInstalledPluginVersion(projectDir, aliases.zaloConnect),
3731
3735
  };
3732
- // Docker: fill any plugin version still empty from the container's extensions volume
3733
- // (e.g. bundled/clawhub plugins like zalo-mod that aren't on the host). One docker exec.
3736
+ // Docker: the container's extensions volume is the SOURCE OF TRUTH for installed
3737
+ // plugin versions — clawhub/plugin installs run inside the container, so a host copy
3738
+ // (bind-mounted .openclaw or a stale installs.json) can lag behind after an update.
3739
+ // When the container reports a version, it OVERRIDES the host value (not just fills
3740
+ // empties) so the card shows the actually-installed version, not a stale one. Native
3741
+ // installs return {} here, so host values are kept.
3734
3742
  const containerExtVersions = await getContainerExtensionVersions(projectDir);
3735
3743
  if (Object.keys(containerExtVersions).length) {
3736
- const fillVer = (key, names) => { if (!versions[key]) { for (const n of names) { if (containerExtVersions[n]) { versions[key] = containerExtVersions[n]; break; } } } };
3744
+ const fillVer = (key, names) => { for (const n of names) { if (containerExtVersions[n]) { versions[key] = containerExtVersions[n]; break; } } };
3737
3745
  fillVer('plugin:openclaw-browser-automation', aliases.browser);
3738
3746
  fillVer('plugin:openclaw-zalo-mod', aliases.zalo);
3739
3747
  fillVer('plugin:openclaw-facebook-crawler', aliases.crawler);
3740
3748
  fillVer('plugin:openclaw-n8n-facebook-poster', aliases.poster);
3741
3749
  fillVer('plugin:openclaw-fb-messenger', aliases.fbMessenger);
3742
- fillVer('plugin:memory-tencentdb', aliases.tencentMemory);
3750
+ fillVer('plugin:learning-memory', aliases.learningMemory);
3743
3751
  fillVer('plugin:zalo-connect', aliases.zaloConnect);
3744
3752
  }
3745
3753
  const zaloBackend = fresh.channels?.['zalo-connect']?.enabled ? 'zalo-connect' : '';
@@ -371,6 +371,12 @@
371
371
 
372
372
  const allow = ['memory-core'];
373
373
 
374
+ // Always-on memory: the learning-memory context engine injects the curated
375
+ // MEMORY.md + USER.md into every turn (including group sessions, which the default
376
+ // recall excludes). Enabled for every bot; the plugin is installed at creation time.
377
+ entries['learning-memory'] = { enabled: true };
378
+ allow.push('learning-memory');
379
+
374
380
  // Zalo Personal → zalo-connect channel plugin (pinned install happens in the
375
381
  // entrypoint / creation flow). openclaw-zalo-mod stays a separate opt-in plugin.
376
382
  if (isZaloPersonal(channelKey)) {
@@ -395,6 +401,8 @@
395
401
 
396
402
  const plugins = { entries };
397
403
  plugins.allow = allow;
404
+ // Select learning-memory as the active context engine (always-on memory).
405
+ plugins.slots = { contextEngine: 'learning-memory' };
398
406
  if (allow.length) plugins.bundledDiscovery = 'compat';
399
407
 
400
408
  return { plugins };
@@ -256,6 +256,11 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
256
256
  const backupConfigScript = `const fs=require('fs'),path=require('path'),p=path.join(process.cwd(),'.openclaw','openclaw.json'),b=p.replace('openclaw.json','.openclaw-config-backup.json');if(fs.existsSync(p)){fs.copyFileSync(p,b);}`;
257
257
 
258
258
  const restoreConfigScript = `const fs=require('fs'),os=require('os'),path=require('path'),p=path.join(process.cwd(),'.openclaw','openclaw.json'),b=p.replace('openclaw.json','.openclaw-config-backup.json');if(fs.existsSync(p)&&fs.existsSync(b)){const c=JSON.parse(fs.readFileSync(p,'utf8'));const bk=JSON.parse(fs.readFileSync(b,'utf8'));const keep=['agents','channels','bindings','commands','models','browser','skills','plugins','tools'];for(const k of keep){if(bk[k]&&!c[k])c[k]=bk[k];}const gp=Number(process.env.OPENCLAW_GATEWAY_PORT||process.env.OPENCLAW_PORT)||c.gateway?.port||bk.gateway?.port||18789;const a=new Set(['http://localhost:'+gp,'http://127.0.0.1:'+gp,'http://0.0.0.0:'+gp]);for(const entries of Object.values(os.networkInterfaces()||{})){for(const entry of entries||[]){if(!entry||entry.internal||entry.family!=='IPv4'||!entry.address)continue;a.add('http://'+entry.address+':'+gp);}}c.tools=Object.assign({},c.tools,{profile:'full',exec:{host:'gateway',security:'full',ask:'off'}});c.gateway=Object.assign({},c.gateway,{port:gp,bind:'custom',customBindHost:'0.0.0.0',mode:c.gateway?.mode||bk.gateway?.mode||'local',controlUi:Object.assign({},c.gateway?.controlUi,{allowedOrigins:Array.from(a).filter(Boolean)})});fs.writeFileSync(p,JSON.stringify(c,null,2));fs.unlinkSync(b);}`;
259
+ // One-shot migration for projects created by an older setup: the learning-memory
260
+ // SKILL and the memory-tencentdb plugin are deprecated (replaced by the learning-memory
261
+ // context-engine plugin). Drop their config entries so they stop loading; the skill
262
+ // folders + tencentdb install are removed by the shell steps that follow.
263
+ const deprecatedCleanupScript = `const fs=require('fs'),path=require('path');const p=path.join(process.cwd(),'.openclaw','openclaw.json');if(fs.existsSync(p)){const c=JSON.parse(fs.readFileSync(p,'utf8'));let ch=false;if(c.plugins&&c.plugins.entries&&c.plugins.entries['memory-tencentdb']){delete c.plugins.entries['memory-tencentdb'];ch=true;}if(c.plugins&&Array.isArray(c.plugins.allow)){const n=c.plugins.allow.filter(x=>x!=='memory-tencentdb'&&x!=='@tencentdb-agent-memory/memory-tencentdb');if(n.length!==c.plugins.allow.length){c.plugins.allow=n;ch=true;}}if(c.skills&&c.skills.entries&&c.skills.entries['learning-memory']){delete c.skills.entries['learning-memory'];ch=true;}if(ch)fs.writeFileSync(p,JSON.stringify(c,null,2));}`;
259
264
  const securityCompatScript = `const fs=require('fs'),path=require('path');const scopes=['operator.admin','operator.pairing','operator.approvals'];function uniq(a){return Array.from(new Set([...(Array.isArray(a)?a:[]),...scopes]));}function walk(v){if(!v||typeof v!=='object')return;if(Array.isArray(v)){v.forEach(walk);return;}if(Array.isArray(v.scopes)||Array.isArray(v.approvedScopes)){v.scopes=uniq(v.scopes);v.approvedScopes=uniq(v.approvedScopes);}Object.values(v).forEach(walk);}const home=process.env.OPENCLAW_HOME||path.join(process.cwd(),'.openclaw');const state=process.env.OPENCLAW_STATE_DIR||home;const cfgPath=path.join(process.cwd(),'.openclaw','openclaw.json');if(fs.existsSync(cfgPath)){const c=JSON.parse(fs.readFileSync(cfgPath,'utf8'));const p=c.models&&c.models.providers&&c.models.providers['9router'];if(p){p.request=Object.assign({},p.request,{allowPrivateNetwork:true});}fs.writeFileSync(cfgPath,JSON.stringify(c,null,2));}for(const root of Array.from(new Set([home,state]))){const f=path.join(root,'devices','paired.json');if(fs.existsSync(f)){const d=JSON.parse(fs.readFileSync(f,'utf8'));walk(d);fs.writeFileSync(f,JSON.stringify(d,null,2));}}`;
260
265
 
261
266
  const runtimeParts = runtimeCommandParts.filter(Boolean);
@@ -323,6 +328,13 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
323
328
  const zaloConnectSpec = common.ZALO_CONNECT_PLUGIN_SPEC || 'clawhub:openclaw-zalo-connect';
324
329
  runtimeParts.push(`ensure_plugin zalo-connect "${zaloConnectSpec}"`);
325
330
  }
331
+ // Always-on memory context engine for every bot (see bot-config-gen: plugins.slots
332
+ // .contextEngine = "learning-memory"). ensure_plugin skips if already installed.
333
+ runtimeParts.push('ensure_plugin learning-memory "clawhub:openclaw-learning-memory"');
334
+ // Migrate off the deprecated learning-memory SKILL + memory-tencentdb plugin (older setups).
335
+ runtimeParts.push(`node - <<'NODE'\n${deprecatedCleanupScript}\nNODE`);
336
+ runtimeParts.push('find "$OPENCLAW_HOME" -maxdepth 4 -type d -path "*/skills/learning-memory" -exec rm -rf {} + 2>/dev/null || true');
337
+ runtimeParts.push('if [ -d "$OPENCLAW_HOME/extensions/memory-tencentdb" ] || openclaw plugins list 2>/dev/null | grep -q memory-tencentdb; then openclaw plugins uninstall memory-tencentdb --force 2>/dev/null || true; fi');
326
338
  runtimeParts.push('openclaw gateway run');
327
339
  const runtimeScript = ['#!/bin/sh', 'set -e', ...runtimeParts].join('\n');
328
340
  let browserInstall = '';
package/dist/web/app.js CHANGED
@@ -1061,11 +1061,10 @@ function botSkillsPanel() {
1061
1061
  { id: 'cron', title: 'Cron', desc: 'Native scheduler (SQLite) — cron guide in TOOLS.md' },
1062
1062
  { id: 'image-gen', title: 'Tạo ảnh Infographic', desc: 'Tạo ảnh infographic, poster tự động qua 9Router' },
1063
1063
  { id: 'web-search', title: 'Web Search', desc: 'Tìm kiếm web thời gian thực (DuckDuckGo)' },
1064
- { id: 'learning-memory', title: 'Siêu Trí Nhớ Dài Hạn (learning-memory)', desc: 'Tự động ghi nhớ bài học vào MEMORY.md, tự đóng gói và tiến hóa kỹ năng mới vào skills/' },
1065
1064
  ];
1066
1065
  const plugins = [
1067
1066
  { id: 'zalo-connect', title: 'OpenClaw Zalo Connect', desc: t('Kênh Zalo cá nhân (zca-js) — BẮT BUỘC cho bot Zalo. Tự cài khi tạo bot Zalo đầu tiên; bấm Cập nhật để lên bản mới nhất.', 'Personal Zalo channel (zca-js) — REQUIRED for Zalo bots. Auto-installed with your first Zalo bot; click Update for the latest version.'), channels: ['zalo-personal'] },
1068
- { id: 'memory-tencentdb', title: 'TencentDB Agent Memory', desc: 'Bộ nhớ phân tầng L0–L3 + nén ngữ cảnh: nhớ tốt session dài, tiết kiệm ~61% token (local SQLite, không cần API)' },
1067
+ { id: 'learning-memory', title: 'Siêu Trí Nhớ Dài Hạn (learning-memory)', desc: t('Bộ nhớ always-on: nạp MEMORY.md + USER.md đã chắt lọc vào MỌI lượt — kể cả trong nhóm — nên bot không quên ngữ cảnh/quy tắc. Tự cài khi tạo bot.', 'Always-on memory: injects a curated MEMORY.md + USER.md into every turn — including group chats — so the bot stops forgetting context and rules. Auto-installed on bot creation.') },
1069
1068
  { id: 'openclaw-browser-automation', title: 'openclaw-browser-automation', desc: 'Smart Search + Browser (headless & Chrome thật)' },
1070
1069
  { id: 'openclaw-zalo-mod', title: 'openclaw-zalo-mod', desc: 'Zalo group helpers', channels: ['zalo-personal'], openWebPort: 18790, openWebPath: '/dashboard' },
1071
1070
  { id: 'openclaw-fb-messenger', title: 'openclaw-fb-messenger', desc: t('Kênh Facebook Messenger — webhook + Graph API (bắt buộc cho bot Messenger)', 'Facebook Messenger channel — webhook + Graph API (required for Messenger bots)'), channels: ['fb-messenger'] },
@@ -1085,7 +1084,7 @@ function botSkillsPanel() {
1085
1084
  const key = `${group}:${item.id}`;
1086
1085
  const loading = !!state.featureLoading[key];
1087
1086
  const locked = !!state.featureLocked?.[key];
1088
- const requiresInstall = group === 'plugin' || (group === 'skill' && (item.id === 'image-gen' || item.id === 'learning-memory'));
1087
+ const requiresInstall = group === 'plugin' || (group === 'skill' && item.id === 'image-gen');
1089
1088
  const isInstalled = !requiresInstall || !!state.featureInstalled?.[key] || locked;
1090
1089
 
1091
1090
  const version = requiresInstall && isInstalled ? (state.featureVersions?.[key] || '') : '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "5.13.8",
3
+ "version": "5.13.9",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {