@matelink/cli 2026.4.15 → 2026.4.17
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/bin/matecli.mjs +190 -2
- package/package.json +1 -1
package/bin/matecli.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import fs from "node:fs";
|
|
|
14
14
|
import os from "node:os";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import process from "node:process";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
18
|
|
|
19
19
|
const NUMERIC_CODE_LENGTH = 4;
|
|
20
20
|
const GROUP_SIZE = 4;
|
|
@@ -51,6 +51,7 @@ const DEFAULT_GATEWAY_SCOPES = [
|
|
|
51
51
|
"operator.approvals",
|
|
52
52
|
"operator.pairing",
|
|
53
53
|
].join(",");
|
|
54
|
+
const SESSION_CONTEXT_MIN_TOKENS = 1024;
|
|
54
55
|
const CLI_ENTRY = fileURLToPath(import.meta.url);
|
|
55
56
|
const CLI_LANGUAGE = detectCliLanguage();
|
|
56
57
|
const CLI_I18N = {
|
|
@@ -446,6 +447,18 @@ function resolveOpenClawConfigPath() {
|
|
|
446
447
|
return path.join(resolveOpenClawHome(), "openclaw.json");
|
|
447
448
|
}
|
|
448
449
|
|
|
450
|
+
function resolveOpenClawDistPath(fileName) {
|
|
451
|
+
return path.join(
|
|
452
|
+
resolveOpenClawHome(),
|
|
453
|
+
"extensions",
|
|
454
|
+
"memory-tdai",
|
|
455
|
+
"node_modules",
|
|
456
|
+
"openclaw",
|
|
457
|
+
"dist",
|
|
458
|
+
fileName,
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
|
|
449
462
|
function resolveTestNextIMStatePath() {
|
|
450
463
|
return path.join(resolveOpenClawHome(), "testnextim.state.json");
|
|
451
464
|
}
|
|
@@ -546,6 +559,21 @@ function resolveConfiguredWorkspaceRoot() {
|
|
|
546
559
|
return path.resolve(resolved);
|
|
547
560
|
}
|
|
548
561
|
|
|
562
|
+
let sessionStoreHelpersPromise = null;
|
|
563
|
+
|
|
564
|
+
async function loadSessionStoreHelpers() {
|
|
565
|
+
if (!sessionStoreHelpersPromise) {
|
|
566
|
+
sessionStoreHelpersPromise = Promise.all([
|
|
567
|
+
import(pathToFileURL(resolveOpenClawDistPath("session-utils-PHKOUUva.js")).href),
|
|
568
|
+
import(pathToFileURL(resolveOpenClawDistPath("store-DACjypj4.js")).href),
|
|
569
|
+
]).then(([sessionUtilsMod, storeMod]) => ({
|
|
570
|
+
loadSessionEntry: sessionUtilsMod.s,
|
|
571
|
+
updateSessionStoreEntry: storeMod.f,
|
|
572
|
+
}));
|
|
573
|
+
}
|
|
574
|
+
return sessionStoreHelpersPromise;
|
|
575
|
+
}
|
|
576
|
+
|
|
549
577
|
function normalizeWorkspaceRelativePath(rawName) {
|
|
550
578
|
const value = String(rawName ?? "").trim();
|
|
551
579
|
if (!value) {
|
|
@@ -663,11 +691,104 @@ function listWorkspaceFiles(workspaceRoot) {
|
|
|
663
691
|
return files;
|
|
664
692
|
}
|
|
665
693
|
|
|
694
|
+
const FIXED_MEMORY_FILES = new Set([
|
|
695
|
+
"AGENTS.md",
|
|
696
|
+
"HEARTBEAT.md",
|
|
697
|
+
"IDENTITY.md",
|
|
698
|
+
"MEMORY.md",
|
|
699
|
+
"SOUL.md",
|
|
700
|
+
"TOOLS.md",
|
|
701
|
+
"USER.md",
|
|
702
|
+
]);
|
|
703
|
+
|
|
704
|
+
function normalizeFixedMemoryFileName(rawName) {
|
|
705
|
+
const normalized = String(rawName ?? "").trim().toUpperCase();
|
|
706
|
+
for (const fileName of FIXED_MEMORY_FILES) {
|
|
707
|
+
if (fileName.toUpperCase() === normalized) {
|
|
708
|
+
return fileName;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
throw new Error(`unsupported memory file: ${String(rawName ?? "").trim()}`);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function listFixedMemoryFiles(workspaceRoot) {
|
|
715
|
+
return Array.from(FIXED_MEMORY_FILES)
|
|
716
|
+
.sort((a, b) => a.localeCompare(b))
|
|
717
|
+
.map((name) => {
|
|
718
|
+
const { relativePath, absolutePath } = resolveWorkspaceFilePath(workspaceRoot, name);
|
|
719
|
+
if (!fs.existsSync(absolutePath)) {
|
|
720
|
+
return buildWorkspaceFileMeta({
|
|
721
|
+
workspaceRoot,
|
|
722
|
+
relativePath,
|
|
723
|
+
absolutePath,
|
|
724
|
+
missing: true,
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
return buildWorkspaceFileMeta({
|
|
728
|
+
workspaceRoot,
|
|
729
|
+
relativePath,
|
|
730
|
+
absolutePath,
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
|
|
666
735
|
async function callWorkspaceRpcLocal({
|
|
667
736
|
method,
|
|
668
737
|
params,
|
|
669
738
|
}) {
|
|
670
739
|
const workspaceRoot = resolveConfiguredWorkspaceRoot();
|
|
740
|
+
if (method === "memory.files.list") {
|
|
741
|
+
return {
|
|
742
|
+
ok: true,
|
|
743
|
+
workspace: workspaceRoot,
|
|
744
|
+
files: listFixedMemoryFiles(workspaceRoot),
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
if (method === "memory.files.get") {
|
|
749
|
+
const fixedName = normalizeFixedMemoryFileName(params?.name);
|
|
750
|
+
const { relativePath, absolutePath } = resolveWorkspaceFilePath(workspaceRoot, fixedName);
|
|
751
|
+
if (!fs.existsSync(absolutePath)) {
|
|
752
|
+
return {
|
|
753
|
+
ok: true,
|
|
754
|
+
workspace: workspaceRoot,
|
|
755
|
+
file: buildWorkspaceFileMeta({
|
|
756
|
+
workspaceRoot,
|
|
757
|
+
relativePath,
|
|
758
|
+
absolutePath,
|
|
759
|
+
missing: true,
|
|
760
|
+
}),
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
return {
|
|
764
|
+
ok: true,
|
|
765
|
+
workspace: workspaceRoot,
|
|
766
|
+
file: buildWorkspaceFileMeta({
|
|
767
|
+
workspaceRoot,
|
|
768
|
+
relativePath,
|
|
769
|
+
absolutePath,
|
|
770
|
+
includeContent: true,
|
|
771
|
+
}),
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (method === "memory.files.set") {
|
|
776
|
+
const fixedName = normalizeFixedMemoryFileName(params?.name);
|
|
777
|
+
const { relativePath, absolutePath } = resolveWorkspaceFilePath(workspaceRoot, fixedName);
|
|
778
|
+
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
|
|
779
|
+
fs.writeFileSync(absolutePath, String(params?.content ?? ""), "utf8");
|
|
780
|
+
return {
|
|
781
|
+
ok: true,
|
|
782
|
+
workspace: workspaceRoot,
|
|
783
|
+
file: buildWorkspaceFileMeta({
|
|
784
|
+
workspaceRoot,
|
|
785
|
+
relativePath,
|
|
786
|
+
absolutePath,
|
|
787
|
+
includeContent: true,
|
|
788
|
+
}),
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
|
|
671
792
|
if (method === "agents.files.list") {
|
|
672
793
|
return {
|
|
673
794
|
ok: true,
|
|
@@ -721,6 +842,62 @@ async function callWorkspaceRpcLocal({
|
|
|
721
842
|
return null;
|
|
722
843
|
}
|
|
723
844
|
|
|
845
|
+
async function callSessionContextRpcLocal({
|
|
846
|
+
method,
|
|
847
|
+
params,
|
|
848
|
+
}) {
|
|
849
|
+
const sessionKey = String(params?.sessionKey ?? params?.key ?? "").trim();
|
|
850
|
+
if (!sessionKey) {
|
|
851
|
+
throw new Error("session key is required");
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
const { loadSessionEntry, updateSessionStoreEntry } = await loadSessionStoreHelpers();
|
|
855
|
+
const loaded = loadSessionEntry(sessionKey);
|
|
856
|
+
const resolvedSessionKey = String(loaded?.canonicalKey ?? sessionKey).trim() || sessionKey;
|
|
857
|
+
|
|
858
|
+
if (method === "session.context.get") {
|
|
859
|
+
return {
|
|
860
|
+
ok: true,
|
|
861
|
+
sessionKey: resolvedSessionKey,
|
|
862
|
+
contextTokens: Number.isFinite(loaded?.entry?.contextTokens)
|
|
863
|
+
? Math.max(0, Math.floor(loaded.entry.contextTokens))
|
|
864
|
+
: null,
|
|
865
|
+
storePath: loaded?.storePath ?? "",
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
if (method === "session.context.set") {
|
|
870
|
+
if (!loaded?.entry || !String(loaded?.storePath ?? "").trim()) {
|
|
871
|
+
throw new Error(`session not found: ${sessionKey}`);
|
|
872
|
+
}
|
|
873
|
+
const contextTokens = Math.max(
|
|
874
|
+
SESSION_CONTEXT_MIN_TOKENS,
|
|
875
|
+
Math.floor(Number(params?.contextTokens ?? 0) || 0),
|
|
876
|
+
);
|
|
877
|
+
const updated = await updateSessionStoreEntry({
|
|
878
|
+
storePath: loaded.storePath,
|
|
879
|
+
sessionKey: resolvedSessionKey,
|
|
880
|
+
update: async (existing) => ({
|
|
881
|
+
contextTokens,
|
|
882
|
+
updatedAt: Math.max(existing?.updatedAt ?? 0, Date.now()),
|
|
883
|
+
}),
|
|
884
|
+
});
|
|
885
|
+
if (!updated) {
|
|
886
|
+
throw new Error(`session not found: ${sessionKey}`);
|
|
887
|
+
}
|
|
888
|
+
return {
|
|
889
|
+
ok: true,
|
|
890
|
+
sessionKey: resolvedSessionKey,
|
|
891
|
+
contextTokens: Number.isFinite(updated?.contextTokens)
|
|
892
|
+
? Math.max(0, Math.floor(updated.contextTokens))
|
|
893
|
+
: contextTokens,
|
|
894
|
+
storePath: loaded.storePath,
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
return null;
|
|
899
|
+
}
|
|
900
|
+
|
|
724
901
|
function commandToString(command, args) {
|
|
725
902
|
return [command, ...args]
|
|
726
903
|
.map((part) => {
|
|
@@ -2944,13 +3121,24 @@ async function callGatewayRpcLocal({
|
|
|
2944
3121
|
return {
|
|
2945
3122
|
ok: true,
|
|
2946
3123
|
methods: ["sessions.list", "sessions.abort", "sessions.delete", "sessions.usage", "sessions.patch",
|
|
2947
|
-
"usage.cost", "
|
|
3124
|
+
"usage.cost", "session.context.get", "session.context.set",
|
|
3125
|
+
"memory.files.list", "memory.files.get", "memory.files.set", "agents.files.list", "agents.files.get", "agents.files.set",
|
|
2948
3126
|
"skills.status", "models.list", "chat.history", "chat.abort",
|
|
2949
3127
|
"config.get", "config.patch"],
|
|
2950
3128
|
};
|
|
2951
3129
|
}
|
|
2952
3130
|
|
|
2953
3131
|
if (
|
|
3132
|
+
method === "session.context.get" ||
|
|
3133
|
+
method === "session.context.set"
|
|
3134
|
+
) {
|
|
3135
|
+
return callSessionContextRpcLocal({ method, params });
|
|
3136
|
+
}
|
|
3137
|
+
|
|
3138
|
+
if (
|
|
3139
|
+
method === "memory.files.list" ||
|
|
3140
|
+
method === "memory.files.get" ||
|
|
3141
|
+
method === "memory.files.set" ||
|
|
2954
3142
|
method === "agents.files.list" ||
|
|
2955
3143
|
method === "agents.files.get" ||
|
|
2956
3144
|
method === "agents.files.set"
|