@konglx/rotom 2.21.0
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 +417 -0
- package/bin/mesh-master.sh +439 -0
- package/bin/rotom +29 -0
- package/bin/rotom-link.sh +136 -0
- package/bin/rotom-send-with-status +57 -0
- package/bin/rotom-up.sh +428 -0
- package/dist/cli/ask.js +62 -0
- package/dist/cli/common.js +321 -0
- package/dist/cli/config.js +65 -0
- package/dist/cli/directory.js +17 -0
- package/dist/cli/executor.js +58 -0
- package/dist/cli/fed.js +91 -0
- package/dist/cli/group.js +273 -0
- package/dist/cli/identity.js +62 -0
- package/dist/cli/init.js +268 -0
- package/dist/cli/issue.js +202 -0
- package/dist/cli/join.js +170 -0
- package/dist/cli/link.js +47 -0
- package/dist/cli/master.js +51 -0
- package/dist/cli/memory.js +307 -0
- package/dist/cli/note.js +68 -0
- package/dist/cli/repo.js +77 -0
- package/dist/cli/rotom.js +277 -0
- package/dist/cli/routes.js +118 -0
- package/dist/cli/run.js +45 -0
- package/dist/cli/schedule.js +237 -0
- package/dist/cli/skill.js +173 -0
- package/dist/cli/team.js +106 -0
- package/dist/executor/claude-code-hook.cjs +80 -0
- package/dist/executor/cli-executor.js +8 -0
- package/dist/executor/executors/claude-code.js +780 -0
- package/dist/executor/executors/codex.js +719 -0
- package/dist/executor/executors/hermes-cli.js +855 -0
- package/dist/executor/executors/openclaw.js +467 -0
- package/dist/executor/executors/pi.js +514 -0
- package/dist/executor/index.js +269 -0
- package/dist/executor/jsonrpc-transport.js +125 -0
- package/dist/executor/process-runner.js +101 -0
- package/dist/executor/reasoning-status.js +83 -0
- package/dist/executor/repo-cache.js +502 -0
- package/dist/executor/session-store.js +188 -0
- package/dist/executor/worker-chat.js +257 -0
- package/dist/executor/worker-connection.js +89 -0
- package/dist/executor/worker-issue.js +264 -0
- package/dist/executor/worker.js +877 -0
- package/dist/link/pending-requests.js +72 -0
- package/dist/link/server.js +233 -0
- package/dist/link/visibility-store.js +58 -0
- package/dist/master/api/agents.js +333 -0
- package/dist/master/api/artifacts.js +271 -0
- package/dist/master/api/domains.js +64 -0
- package/dist/master/api/groups.js +635 -0
- package/dist/master/api/guidance-templates.js +147 -0
- package/dist/master/api/index.js +89 -0
- package/dist/master/api/issues-patrol.js +172 -0
- package/dist/master/api/issues.js +663 -0
- package/dist/master/api/links-patrol.js +168 -0
- package/dist/master/api/links.js +114 -0
- package/dist/master/api/memory.js +259 -0
- package/dist/master/api/messages.js +157 -0
- package/dist/master/api/notes.js +77 -0
- package/dist/master/api/schedule-patterns.js +133 -0
- package/dist/master/api/schedules.js +272 -0
- package/dist/master/api/sessions.js +158 -0
- package/dist/master/api/share.js +269 -0
- package/dist/master/api/skills.js +190 -0
- package/dist/master/api/teams.js +122 -0
- package/dist/master/api/uploads.js +245 -0
- package/dist/master/auth.js +134 -0
- package/dist/master/dashboard/animations/calico-dozing.apng +0 -0
- package/dist/master/dashboard/animations/calico-error.apng +0 -0
- package/dist/master/dashboard/animations/calico-happy.apng +0 -0
- package/dist/master/dashboard/animations/calico-notification.apng +0 -0
- package/dist/master/dashboard/animations/calico-sleeping.apng +0 -0
- package/dist/master/dashboard/animations/calico-thinking.apng +0 -0
- package/dist/master/dashboard/animations/calico-waking.apng +0 -0
- package/dist/master/dashboard/assets/ApprovalCard-C38VV6ko.css +1 -0
- package/dist/master/dashboard/assets/ApprovalCard-CHPh2dmE.js +17 -0
- package/dist/master/dashboard/assets/ArtifactPanel-P_2gAP7v.js +1 -0
- package/dist/master/dashboard/assets/ArtifactPanel-aGHySny5.css +1 -0
- package/dist/master/dashboard/assets/css.worker-DaIe3gwK.js +84 -0
- package/dist/master/dashboard/assets/editor.worker-BCzxt1at.js +12 -0
- package/dist/master/dashboard/assets/html.worker-CKrFyw_2.js +461 -0
- package/dist/master/dashboard/assets/index-CChrTn81.css +32 -0
- package/dist/master/dashboard/assets/index-Dhu4SN1z.js +181 -0
- package/dist/master/dashboard/assets/json.worker-B7c_PmGb.js +49 -0
- package/dist/master/dashboard/assets/markdown-CeN5IgdF.js +29 -0
- package/dist/master/dashboard/assets/monaco-core-DyX1CsEw.css +1 -0
- package/dist/master/dashboard/assets/monaco-core-oQiQUisy.js +833 -0
- package/dist/master/dashboard/assets/monaco-setup-CiOPQdmo.js +1 -0
- package/dist/master/dashboard/assets/react-vendor-C8IxlyCR.js +67 -0
- package/dist/master/dashboard/assets/ts.worker-BhkL8olL.js +51334 -0
- package/dist/master/dashboard/assets/useMonaco-ILb4vyPh.js +12 -0
- package/dist/master/dashboard/assets/vite-preload-CxJPbCTl.js +1 -0
- package/dist/master/dashboard/debug-auth.html +197 -0
- package/dist/master/dashboard/favicon.ico +0 -0
- package/dist/master/dashboard/index.html +20 -0
- package/dist/master/dashboard/rotom-avatar.png +0 -0
- package/dist/master/db/agent-sessions.js +60 -0
- package/dist/master/db/agent-visibility.js +64 -0
- package/dist/master/db/agents.js +119 -0
- package/dist/master/db/ask-bridges.js +157 -0
- package/dist/master/db/build-update.js +59 -0
- package/dist/master/db/core.js +82 -0
- package/dist/master/db/domains.js +80 -0
- package/dist/master/db/groups.js +316 -0
- package/dist/master/db/guidance-templates.js +58 -0
- package/dist/master/db/index.js +12 -0
- package/dist/master/db/internal.js +45 -0
- package/dist/master/db/issues-patrol.js +81 -0
- package/dist/master/db/issues.js +373 -0
- package/dist/master/db/links.js +221 -0
- package/dist/master/db/master-node.js +43 -0
- package/dist/master/db/memory.js +272 -0
- package/dist/master/db/messages.js +210 -0
- package/dist/master/db/notes.js +55 -0
- package/dist/master/db/schedule-patterns.js +56 -0
- package/dist/master/db/schedules.js +135 -0
- package/dist/master/db/skills.js +144 -0
- package/dist/master/db/team.js +88 -0
- package/dist/master/db/types.js +10 -0
- package/dist/master/db.js +12 -0
- package/dist/master/embedded.js +133 -0
- package/dist/master/federation/client.js +283 -0
- package/dist/master/federation/identity.js +133 -0
- package/dist/master/federation/manager.js +267 -0
- package/dist/master/federation/publisher.js +87 -0
- package/dist/master/federation/self-publisher.js +69 -0
- package/dist/master/federation/server.js +487 -0
- package/dist/master/group-paths.js +208 -0
- package/dist/master/offline-queue.js +38 -0
- package/dist/master/opc-bootstrap.js +245 -0
- package/dist/master/patrol-terminal.js +275 -0
- package/dist/master/repo-scan.js +188 -0
- package/dist/master/router.js +214 -0
- package/dist/master/scheduler-handlers.js +510 -0
- package/dist/master/scheduler.js +201 -0
- package/dist/master/server.js +203 -0
- package/dist/master/services/link-collector.js +82 -0
- package/dist/master/services/link-patrol-bootstrap.js +50 -0
- package/dist/master/services/memory-extract-prompt.js +34 -0
- package/dist/master/services/patrol-bootstrap.js +63 -0
- package/dist/master/share-tokens.js +56 -0
- package/dist/master/terminal-hub.js +300 -0
- package/dist/master/uploads.js +108 -0
- package/dist/master/util/fs.js +100 -0
- package/dist/master/util/paths.js +50 -0
- package/dist/master/util/persona.js +10 -0
- package/dist/master/ws-hub/connection.js +928 -0
- package/dist/master/ws-hub/conversation.js +290 -0
- package/dist/master/ws-hub/directory.js +70 -0
- package/dist/master/ws-hub/dispatch-enrich.js +34 -0
- package/dist/master/ws-hub/hub.js +136 -0
- package/dist/master/ws-hub/index.js +9 -0
- package/dist/master/ws-hub/internal.js +35 -0
- package/dist/master/ws-hub/routing.js +295 -0
- package/dist/master/ws-hub/sessions.js +130 -0
- package/dist/master/ws-hub.js +11 -0
- package/dist/shared/agent-profile.js +44 -0
- package/dist/shared/constants.js +55 -0
- package/dist/shared/dedup.js +33 -0
- package/dist/shared/group-context.js +62 -0
- package/dist/shared/json-codec.js +33 -0
- package/dist/shared/logger.js +136 -0
- package/dist/shared/mention.js +22 -0
- package/dist/shared/network.js +40 -0
- package/dist/shared/parse.js +18 -0
- package/dist/shared/prompt-composer.js +171 -0
- package/dist/shared/protocol/client-messages.js +8 -0
- package/dist/shared/protocol/enums.js +6 -0
- package/dist/shared/protocol/federation.js +62 -0
- package/dist/shared/protocol/guards.js +87 -0
- package/dist/shared/protocol/server-messages.js +8 -0
- package/dist/shared/protocol/types.js +8 -0
- package/dist/shared/protocol.js +19 -0
- package/dist/shared/readonly-allowlist.js +122 -0
- package/dist/shared/rotom-cli-prompt.js +23 -0
- package/dist/shared/skill-context.js +19 -0
- package/dist/shared/skill-md.js +43 -0
- package/dist/shared/slash-commands.js +50 -0
- package/dist/shared/time.js +80 -0
- package/dist/shared/title.js +46 -0
- package/dist/shared/url-extractor.js +99 -0
- package/migrations/001-schema.sql +942 -0
- package/package.json +68 -0
- package/scripts/fix-node-pty-perms.mjs +46 -0
- package/skill/rotom-a2a-communicate/SKILL.md +257 -0
- package/skill/rotom-bus-host/SKILL.md +78 -0
- package/skill/rotom-bus-host/scripts/poll-replies.sh +148 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rotom memory — 记忆管理子命令。
|
|
3
|
+
*
|
|
4
|
+
* agent_memory 表的 CLI。note(agent_visible=0)用 `--type note` 查询/创建;
|
|
5
|
+
* memory(agent_visible=1)是默认。旧 `rotom note` 命令保留兼容,转调本模块。
|
|
6
|
+
*/
|
|
7
|
+
import { api, printJson, printTable, fail, flagStr, flagInt, requireFlag, } from "./common.js";
|
|
8
|
+
import { route, qs, usage } from "./routes.js";
|
|
9
|
+
import { createLogger } from "../shared/logger.js";
|
|
10
|
+
const log = createLogger("mesh-cli-memory", { stream: "stderr" });
|
|
11
|
+
const CATEGORIES = ["fact", "decision", "convention", "pitfall", "todo", "playbook", "note"];
|
|
12
|
+
function parseTags(flags) {
|
|
13
|
+
const v = flagStr(flags, "tags");
|
|
14
|
+
if (!v)
|
|
15
|
+
return undefined;
|
|
16
|
+
if (v.startsWith("[")) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(v);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
fail(`--tags invalid JSON array: ${v}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return v.split(",").map(t => t.trim()).filter(Boolean);
|
|
25
|
+
}
|
|
26
|
+
function fmtPreview(s, len = 60) {
|
|
27
|
+
if (!s)
|
|
28
|
+
return "";
|
|
29
|
+
const flat = s.replace(/\n/g, " ");
|
|
30
|
+
return flat.length > len ? flat.slice(0, len) + "…" : flat;
|
|
31
|
+
}
|
|
32
|
+
export async function cmdMemory(agent, rest, flags) {
|
|
33
|
+
const sub = rest[0];
|
|
34
|
+
const scope = flagStr(flags, "scope") === "global" ? "global" : "group";
|
|
35
|
+
// ── search ───────────────────────────────────────────────────────────
|
|
36
|
+
if (sub === "search") {
|
|
37
|
+
const keyword = rest[1];
|
|
38
|
+
if (!keyword)
|
|
39
|
+
usage("memory search", "<keyword> [--scope group|global] [groupId] [--category <c>]");
|
|
40
|
+
const category = flagStr(flags, "category");
|
|
41
|
+
const limit = flagInt(flags, "limit") ?? 20;
|
|
42
|
+
let url;
|
|
43
|
+
if (scope === "global") {
|
|
44
|
+
url = `${route("/memory/search")}${qs({ q: keyword, limit, category })}`;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const groupId = rest[2];
|
|
48
|
+
if (!groupId)
|
|
49
|
+
usage("memory search", "<keyword> <groupId> (group scope needs groupId)");
|
|
50
|
+
url = `${route("/groups/:groupId/memory/search", groupId)}${qs({ q: keyword, limit, category })}`;
|
|
51
|
+
}
|
|
52
|
+
const data = await api(agent, "GET", url);
|
|
53
|
+
// group search 返回 {group, global}; global search 返回数组
|
|
54
|
+
const rows = Array.isArray(data) ? data : [...(data.group || []), ...(data.global || [])];
|
|
55
|
+
printTable(rows.map((m) => ({
|
|
56
|
+
id: m.id,
|
|
57
|
+
scope: m.scope,
|
|
58
|
+
category: m.category,
|
|
59
|
+
key: m.key,
|
|
60
|
+
summary: fmtPreview(m.summary, 50),
|
|
61
|
+
by: m.created_by ?? "",
|
|
62
|
+
})), ["id", "scope", "category", "key", "summary", "by"]);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// ── list ─────────────────────────────────────────────────────────────
|
|
66
|
+
if (sub === "list") {
|
|
67
|
+
const type = flagStr(flags, "type");
|
|
68
|
+
const category = flagStr(flags, "category");
|
|
69
|
+
const tags = parseTags(flags);
|
|
70
|
+
const includePending = flags["include-pending"] === true || flags["include-pending"] === "true";
|
|
71
|
+
let url;
|
|
72
|
+
if (scope === "global") {
|
|
73
|
+
url = route("/memory/global");
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const groupId = rest[1];
|
|
77
|
+
if (!groupId)
|
|
78
|
+
usage("memory list", "<groupId> [--scope group|global] [--type note|memory|all]");
|
|
79
|
+
url = route("/groups/:groupId/memory", groupId);
|
|
80
|
+
}
|
|
81
|
+
url += qs({
|
|
82
|
+
type: type && type !== "all" ? type : undefined,
|
|
83
|
+
category,
|
|
84
|
+
tags: tags && tags.length ? tags.join(",") : undefined,
|
|
85
|
+
includePending: includePending ? "true" : undefined,
|
|
86
|
+
});
|
|
87
|
+
const data = await api(agent, "GET", url);
|
|
88
|
+
printTable(data.map((m) => ({
|
|
89
|
+
id: m.id.slice(0, 8),
|
|
90
|
+
cat: m.category,
|
|
91
|
+
av: m.agent_visible ? "M" : "N", // M=memory N=note
|
|
92
|
+
key: m.key,
|
|
93
|
+
summary: fmtPreview(m.summary, 50),
|
|
94
|
+
by: m.created_by ?? "",
|
|
95
|
+
viewed: "",
|
|
96
|
+
})), ["id", "cat", "av", "key", "summary", "by"]);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// ── get ──────────────────────────────────────────────────────────────
|
|
100
|
+
if (sub === "get") {
|
|
101
|
+
const id = rest[1];
|
|
102
|
+
if (!id)
|
|
103
|
+
usage("memory get", "<memoryId>");
|
|
104
|
+
const data = await api(agent, "GET", route("/memory/:id", id));
|
|
105
|
+
printJson(data);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// ── add ──────────────────────────────────────────────────────────────
|
|
109
|
+
if (sub === "add") {
|
|
110
|
+
const key = requireFlag(flags, "key");
|
|
111
|
+
const value = requireFlag(flags, "value");
|
|
112
|
+
const category = flagStr(flags, "category");
|
|
113
|
+
if (!category || !CATEGORIES.includes(category)) {
|
|
114
|
+
fail(`--category required, one of: ${CATEGORIES.join(", ")}`);
|
|
115
|
+
}
|
|
116
|
+
const summary = flagStr(flags, "summary");
|
|
117
|
+
const tags = parseTags(flags) ?? [];
|
|
118
|
+
const visibility = flagStr(flags, "visibility");
|
|
119
|
+
// parseArgs: --no-agent-visible → flags["agent-visible"]=false;--agent-visible → true
|
|
120
|
+
const agentVisible = flags["agent-visible"] !== false;
|
|
121
|
+
const pendingReview = flags["pending"] === true;
|
|
122
|
+
const expiresAt = flagStr(flags, "expires");
|
|
123
|
+
const createdBy = flagStr(flags, "created-by") ?? agent.name;
|
|
124
|
+
let url;
|
|
125
|
+
let body = {
|
|
126
|
+
key, value, category, tags,
|
|
127
|
+
agentVisible,
|
|
128
|
+
createdBy,
|
|
129
|
+
};
|
|
130
|
+
if (summary)
|
|
131
|
+
body.summary = summary;
|
|
132
|
+
if (visibility)
|
|
133
|
+
body.visibility = visibility;
|
|
134
|
+
if (expiresAt)
|
|
135
|
+
body.expiresAt = expiresAt;
|
|
136
|
+
if (pendingReview)
|
|
137
|
+
body.pendingReview = true;
|
|
138
|
+
if (scope === "global") {
|
|
139
|
+
url = route("/memory/global");
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const groupId = rest[1];
|
|
143
|
+
if (!groupId)
|
|
144
|
+
usage("memory add", "<groupId> --key K --value V --category C [--scope global]");
|
|
145
|
+
url = route("/groups/:groupId/memory", groupId);
|
|
146
|
+
}
|
|
147
|
+
const data = await api(agent, "POST", url, body);
|
|
148
|
+
printJson(data);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// ── update ────────────────────────────────────────────────────────────
|
|
152
|
+
if (sub === "update") {
|
|
153
|
+
const id = rest[1];
|
|
154
|
+
if (!id)
|
|
155
|
+
usage("memory update", "<memoryId> [--value V] [--summary S] [--tags t1,t2] [--category C] [--visibility V] [--agent-visible|--no-agent-visible]");
|
|
156
|
+
const body = {};
|
|
157
|
+
const value = flagStr(flags, "value");
|
|
158
|
+
const summary = flagStr(flags, "summary");
|
|
159
|
+
const tags = parseTags(flags);
|
|
160
|
+
const category = flagStr(flags, "category");
|
|
161
|
+
const visibility = flagStr(flags, "visibility");
|
|
162
|
+
if (value !== undefined)
|
|
163
|
+
body.value = value;
|
|
164
|
+
if (summary !== undefined)
|
|
165
|
+
body.summary = summary;
|
|
166
|
+
if (tags !== undefined)
|
|
167
|
+
body.tags = tags;
|
|
168
|
+
if (category) {
|
|
169
|
+
if (!CATEGORIES.includes(category))
|
|
170
|
+
fail(`--category one of: ${CATEGORIES.join(", ")}`);
|
|
171
|
+
body.category = category;
|
|
172
|
+
}
|
|
173
|
+
if (visibility)
|
|
174
|
+
body.visibility = visibility;
|
|
175
|
+
if (flags["agent-visible"] === true)
|
|
176
|
+
body.agentVisible = true;
|
|
177
|
+
if (flags["agent-visible"] === false)
|
|
178
|
+
body.agentVisible = false;
|
|
179
|
+
if (Object.keys(body).length === 0)
|
|
180
|
+
fail("no fields to update");
|
|
181
|
+
await api(agent, "PATCH", route("/memory/:id", id), body);
|
|
182
|
+
printJson({ ok: true });
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// ── remove / expire / promote ────────────────────────────────────────
|
|
186
|
+
if (sub === "remove") {
|
|
187
|
+
const id = rest[1];
|
|
188
|
+
if (!id)
|
|
189
|
+
usage("memory remove", "<memoryId>");
|
|
190
|
+
await api(agent, "DELETE", route("/memory/:id", id));
|
|
191
|
+
printJson({ ok: true });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (sub === "expire") {
|
|
195
|
+
const id = rest[1];
|
|
196
|
+
if (!id)
|
|
197
|
+
usage("memory expire", "<memoryId>");
|
|
198
|
+
await api(agent, "POST", route("/memory/:id/expire", id));
|
|
199
|
+
printJson({ ok: true });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (sub === "promote") {
|
|
203
|
+
const id = rest[1];
|
|
204
|
+
if (!id)
|
|
205
|
+
usage("memory promote", "<memoryId> --visibility global");
|
|
206
|
+
const visibility = flagStr(flags, "visibility");
|
|
207
|
+
if (visibility !== "global" && visibility !== "private" && visibility !== "group") {
|
|
208
|
+
fail("--visibility required: global | private | group");
|
|
209
|
+
}
|
|
210
|
+
await api(agent, "POST", route("/memory/:id/promote", id), { visibility });
|
|
211
|
+
printJson({ ok: true });
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
// ── promote-to-skill(playbook memory → 全局 skill)────────────────────
|
|
215
|
+
if (sub === "promote-to-skill") {
|
|
216
|
+
const id = rest[1];
|
|
217
|
+
if (!id)
|
|
218
|
+
usage("memory promote-to-skill", "<memoryId> [--name N] [--description D]");
|
|
219
|
+
const name = flagStr(flags, "name");
|
|
220
|
+
const description = flagStr(flags, "description");
|
|
221
|
+
const body = { createdBy: agent.name };
|
|
222
|
+
if (name)
|
|
223
|
+
body.name = name;
|
|
224
|
+
if (description)
|
|
225
|
+
body.description = description;
|
|
226
|
+
const data = await api(agent, "POST", route("/memory/:id/promote-to-skill", id), body);
|
|
227
|
+
printJson(data);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// ── 审核 ──────────────────────────────────────────────────────────────
|
|
231
|
+
if (sub === "pending") {
|
|
232
|
+
let url;
|
|
233
|
+
if (scope === "global") {
|
|
234
|
+
url = `${route("/memory/pending")}${qs({ scope: "global" })}`;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const groupId = rest[1];
|
|
238
|
+
if (!groupId)
|
|
239
|
+
usage("memory pending", "<groupId> [--scope global]");
|
|
240
|
+
url = route("/groups/:groupId/memory/pending", groupId);
|
|
241
|
+
}
|
|
242
|
+
const data = await api(agent, "GET", url);
|
|
243
|
+
printTable(data.map((m) => ({
|
|
244
|
+
id: m.id.slice(0, 8),
|
|
245
|
+
cat: m.category,
|
|
246
|
+
key: m.key,
|
|
247
|
+
summary: fmtPreview(m.summary, 50),
|
|
248
|
+
by: m.created_by ?? "",
|
|
249
|
+
})), ["id", "cat", "key", "summary", "by"]);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (sub === "approve") {
|
|
253
|
+
const id = rest[1];
|
|
254
|
+
if (!id)
|
|
255
|
+
usage("memory approve", "<memoryId>");
|
|
256
|
+
await api(agent, "POST", route("/memory/:id/approve", id));
|
|
257
|
+
printJson({ ok: true });
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (sub === "reject") {
|
|
261
|
+
const id = rest[1];
|
|
262
|
+
if (!id)
|
|
263
|
+
usage("memory reject", "<memoryId>");
|
|
264
|
+
await api(agent, "POST", route("/memory/:id/reject", id));
|
|
265
|
+
printJson({ ok: true });
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
// ── stats ────────────────────────────────────────────────────────────
|
|
269
|
+
if (sub === "stats") {
|
|
270
|
+
let url;
|
|
271
|
+
if (scope === "global") {
|
|
272
|
+
url = `${route("/memory/stats")}${qs({ scope: "global" })}`;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const groupId = rest[1];
|
|
276
|
+
if (!groupId)
|
|
277
|
+
usage("memory stats", "<groupId> [--scope global] [--stale]");
|
|
278
|
+
url = route("/groups/:groupId/memory/stats", groupId);
|
|
279
|
+
}
|
|
280
|
+
const data = await api(agent, "GET", url);
|
|
281
|
+
printJson(data);
|
|
282
|
+
if (flags["stale"] === true || flags["stale"] === "true") {
|
|
283
|
+
const minAge = flagInt(flags, "min-age") ?? 30;
|
|
284
|
+
// listMemory 不直接支持 stale,这里复用 stats 拿到的 topViewed 反推不够,
|
|
285
|
+
// 改用 list 接口 + 客户端过滤太重。直接走专用接口更合适,但未实现。
|
|
286
|
+
// 留作 TODO:加 /memory/stale 端点。当前用 stats 的 topViewed 近似。
|
|
287
|
+
log.warn(`stale 列表需 /memory/stale 端点,当前未实现;min-age=${minAge}`);
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
fail(`unknown memory subcommand: ${sub || "(none)"}
|
|
292
|
+
usage:
|
|
293
|
+
memory search <keyword> <groupId> [--scope group|global] [--category <c>]
|
|
294
|
+
memory list <groupId> [--scope group|global] [--type note|memory|all] [--category <c>] [--tags t1,t2]
|
|
295
|
+
memory get <memoryId>
|
|
296
|
+
memory add <groupId> --key K --value V --category C [--scope global] [--summary S] [--tags t1,t2]
|
|
297
|
+
[--visibility group|global|private] [--no-agent-visible] [--pending] [--expires 7d]
|
|
298
|
+
memory update <id> [--value V] [--summary S] [--tags t1,t2] [--category C] [--visibility V] [--agent-visible|--no-agent-visible]
|
|
299
|
+
memory remove <id>
|
|
300
|
+
memory expire <id>
|
|
301
|
+
memory promote <id> --visibility global
|
|
302
|
+
memory promote-to-skill <memoryId> [--name N] [--description D] # playbook → 全局 skill
|
|
303
|
+
memory pending <groupId> [--scope global]
|
|
304
|
+
memory approve <id>
|
|
305
|
+
memory reject <id>
|
|
306
|
+
memory stats <groupId> [--scope global]`);
|
|
307
|
+
}
|
package/dist/cli/note.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rotom note — note list/show/create/update/delete.
|
|
3
|
+
*/
|
|
4
|
+
import { api, printJson, printTable, fail, flagStr, requireFlag, } from "./common.js";
|
|
5
|
+
import { route, usage, unknownSubcommand } from "./routes.js";
|
|
6
|
+
export async function cmdNote(agent, rest, flags) {
|
|
7
|
+
const sub = rest[0];
|
|
8
|
+
if (sub === "list") {
|
|
9
|
+
const groupId = rest[1];
|
|
10
|
+
if (!groupId)
|
|
11
|
+
usage("note list", "<groupId>");
|
|
12
|
+
const data = await api(agent, "GET", route("/groups/:groupId/notes", groupId));
|
|
13
|
+
printTable(data.map((n) => ({
|
|
14
|
+
id: n.id,
|
|
15
|
+
title: (n.title || "").slice(0, 60),
|
|
16
|
+
created_by: n.created_by,
|
|
17
|
+
updated_at: n.updated_at,
|
|
18
|
+
})), ["id", "title", "created_by", "updated_at"]);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (sub === "show") {
|
|
22
|
+
const id = rest[1];
|
|
23
|
+
if (!id)
|
|
24
|
+
usage("note show", "<noteId>");
|
|
25
|
+
const data = await api(agent, "GET", route("/notes/:id", id));
|
|
26
|
+
printJson(data);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (sub === "create") {
|
|
30
|
+
const groupId = rest[1];
|
|
31
|
+
if (!groupId)
|
|
32
|
+
usage("note create", "<groupId> --title T [--description D]");
|
|
33
|
+
const title = requireFlag(flags, "title");
|
|
34
|
+
const description = flagStr(flags, "description") || "";
|
|
35
|
+
const data = await api(agent, "POST", route("/groups/:groupId/notes", groupId), {
|
|
36
|
+
title, description, createdBy: agent.name,
|
|
37
|
+
});
|
|
38
|
+
printJson(data);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (sub === "update") {
|
|
42
|
+
const id = rest[1];
|
|
43
|
+
if (!id)
|
|
44
|
+
usage("note update", "<noteId> [--title T] [--description D]");
|
|
45
|
+
const title = flagStr(flags, "title");
|
|
46
|
+
const description = flagStr(flags, "description");
|
|
47
|
+
const body = {};
|
|
48
|
+
if (title !== undefined)
|
|
49
|
+
body.title = title;
|
|
50
|
+
if (description !== undefined)
|
|
51
|
+
body.description = description;
|
|
52
|
+
if (Object.keys(body).length === 0) {
|
|
53
|
+
fail("no fields to update — pass at least one of --title, --description");
|
|
54
|
+
}
|
|
55
|
+
const data = await api(agent, "PUT", route("/notes/:id", id), body);
|
|
56
|
+
printJson(data);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (sub === "delete") {
|
|
60
|
+
const id = rest[1];
|
|
61
|
+
if (!id)
|
|
62
|
+
usage("note delete", "<noteId>");
|
|
63
|
+
const data = await api(agent, "DELETE", route("/notes/:id", id));
|
|
64
|
+
printJson(data);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
unknownSubcommand("note", sub);
|
|
68
|
+
}
|
package/dist/cli/repo.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rotom repo — 内置 repo bare clone + git worktree 缓存管理。
|
|
3
|
+
*
|
|
4
|
+
* 所有命令在本机 FS 操作(`~/.rotom/repos/<repo-id>.git/`),不需要 agent。
|
|
5
|
+
* 与 master/executor 一样属于 "本机维护命令"。
|
|
6
|
+
*
|
|
7
|
+
* 子命令:
|
|
8
|
+
* list 列出所有 bare clone + 各自 worktree 数 + 磁盘占用
|
|
9
|
+
* prune [--remove-orphans] 清理孤儿 worktree 元数据,可选删除无引用的 bare clone
|
|
10
|
+
* fetch <repo-id> 显式 git fetch --prune 某 bare clone
|
|
11
|
+
* remove <repo-id> 删除 bare clone(要求无活跃 worktree)
|
|
12
|
+
*/
|
|
13
|
+
import { fail } from "./common.js";
|
|
14
|
+
import { listBareClones, fetchBareClone, removeBareClone, pruneRepoCache, REPOS_ROOT, } from "../executor/repo-cache.js";
|
|
15
|
+
function humanBytes(n) {
|
|
16
|
+
if (n < 1024)
|
|
17
|
+
return `${n}B`;
|
|
18
|
+
if (n < 1024 * 1024)
|
|
19
|
+
return `${(n / 1024).toFixed(1)}K`;
|
|
20
|
+
if (n < 1024 * 1024 * 1024)
|
|
21
|
+
return `${(n / 1024 / 1024).toFixed(1)}M`;
|
|
22
|
+
return `${(n / 1024 / 1024 / 1024).toFixed(2)}G`;
|
|
23
|
+
}
|
|
24
|
+
export function cmdRepo(rest, flags) {
|
|
25
|
+
const sub = rest[0];
|
|
26
|
+
const args = rest.slice(1);
|
|
27
|
+
switch (sub) {
|
|
28
|
+
case "list": return cmdList(flags);
|
|
29
|
+
case "prune": return cmdPrune(args, flags);
|
|
30
|
+
case "fetch": return cmdFetch(args, flags);
|
|
31
|
+
case "remove": return cmdRemove(args, flags);
|
|
32
|
+
default:
|
|
33
|
+
fail(`unknown repo subcommand: ${sub ?? "(none)"}\nUsage: rotom repo <list|prune|fetch|remove>`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function cmdList(_flags) {
|
|
37
|
+
const clones = listBareClones();
|
|
38
|
+
if (clones.length === 0) {
|
|
39
|
+
process.stdout.write(`No bare clones in ${REPOS_ROOT}\n`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
process.stdout.write(`Bare clone cache: ${REPOS_ROOT}\n\n`);
|
|
43
|
+
for (const c of clones) {
|
|
44
|
+
process.stdout.write(`${c.repoId} (${humanBytes(c.sizeBytes)}, ${c.worktrees.length} worktree${c.worktrees.length === 1 ? "" : "s"})\n`);
|
|
45
|
+
for (const w of c.worktrees) {
|
|
46
|
+
process.stdout.write(` - ${w.branch || "(detached)"} ${w.path}\n`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function cmdPrune(args, _flags) {
|
|
51
|
+
const removeOrphans = args.includes("--remove-orphans");
|
|
52
|
+
const r = pruneRepoCache({ removeOrphans });
|
|
53
|
+
process.stdout.write(`Pruned ${r.prunedWorktrees} orphan worktree(s).\n`);
|
|
54
|
+
if (r.removedClones.length > 0) {
|
|
55
|
+
process.stdout.write(`Removed orphan bare clones:\n`);
|
|
56
|
+
for (const id of r.removedClones)
|
|
57
|
+
process.stdout.write(` - ${id}\n`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function cmdFetch(args, _flags) {
|
|
61
|
+
const repoId = args[0];
|
|
62
|
+
if (!repoId)
|
|
63
|
+
fail("rotom repo fetch <repo-id>: missing repo-id");
|
|
64
|
+
const r = fetchBareClone(repoId);
|
|
65
|
+
if (!r.ok)
|
|
66
|
+
fail(`fetch failed: ${r.output}`);
|
|
67
|
+
process.stdout.write(r.output || `repo ${repoId} fetched.\n`);
|
|
68
|
+
}
|
|
69
|
+
function cmdRemove(args, _flags) {
|
|
70
|
+
const repoId = args[0];
|
|
71
|
+
if (!repoId)
|
|
72
|
+
fail("rotom repo remove <repo-id>: missing repo-id");
|
|
73
|
+
const r = removeBareClone(repoId);
|
|
74
|
+
if (!r.ok)
|
|
75
|
+
fail(r.error || `remove failed for ${repoId}`);
|
|
76
|
+
process.stdout.write(`Removed bare clone ${repoId}.\n`);
|
|
77
|
+
}
|