recallx 1.0.8 → 1.2.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 +52 -1
- package/app/cli/src/cli.js +32 -1
- package/app/cli/src/format.js +24 -0
- package/app/mcp/index.js +2 -2
- package/app/mcp/server.js +523 -146
- package/app/server/app.js +413 -5
- package/app/server/config.js +4 -2
- package/app/server/index.js +12 -1
- package/app/server/observability.js +2 -0
- package/app/server/project-graph.js +13 -6
- package/app/server/repositories.js +178 -24
- package/app/server/sqlite-errors.js +10 -0
- package/app/server/workspace-import-helpers.js +161 -0
- package/app/server/workspace-import.js +572 -0
- package/app/server/workspace-ops.js +249 -0
- package/app/server/workspace-session.js +119 -7
- package/app/shared/contracts.js +41 -0
- package/app/shared/version.js +1 -1
- package/dist/renderer/assets/{ProjectGraphCanvas-BLmjIT0R.js → ProjectGraphCanvas-B9-L83dL.js} +1 -1
- package/dist/renderer/assets/index-CNeaY_5l.js +69 -0
- package/dist/renderer/assets/index-Dz33nPCb.css +1 -0
- package/dist/renderer/index.html +2 -2
- package/package.json +1 -1
- package/dist/renderer/assets/index-C2-KXqBO.css +0 -1
- package/dist/renderer/assets/index-CIY8bKYQ.js +0 -69
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ Use the public repo when you want the full source-run surface:
|
|
|
43
43
|
|
|
44
44
|
- local API under `/api/v1`
|
|
45
45
|
- source-run renderer workflow through `npm run dev`
|
|
46
|
-
- stdio MCP bridge through `npm run mcp`
|
|
46
|
+
- stdio MCP bridge through `npm run dev:mcp` during source development
|
|
47
47
|
- runtime workspace create/open switching without restarting the service
|
|
48
48
|
|
|
49
49
|
```bash
|
|
@@ -56,6 +56,13 @@ npm run dev
|
|
|
56
56
|
MCP from source:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
+
npm run dev:mcp
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If you want to run the built MCP entrypoint instead, build the server first:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm run build:server
|
|
59
66
|
npm run mcp
|
|
60
67
|
```
|
|
61
68
|
|
|
@@ -88,6 +95,18 @@ When you are preparing a release, bump from the highest known version instead of
|
|
|
88
95
|
npm run version:bump -- patch
|
|
89
96
|
```
|
|
90
97
|
|
|
98
|
+
Workspace lifecycle and backup commands from the same source checkout:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
recallx workspace current
|
|
102
|
+
recallx workspace backups
|
|
103
|
+
recallx workspace backup --label "before-upgrade"
|
|
104
|
+
recallx workspace export --format markdown
|
|
105
|
+
recallx workspace restore --backup <id> --root /path/to/restore
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The renderer Workspace page exposes the same backup, export, restore, and single-writer safety warnings over the local API.
|
|
109
|
+
|
|
91
110
|
If you want an installable runtime instead of source-run workflows, use one of the npm distribution paths below.
|
|
92
111
|
|
|
93
112
|
## 2. npm Full Runtime (`recallx`)
|
|
@@ -118,6 +137,15 @@ The full npm package includes:
|
|
|
118
137
|
|
|
119
138
|
`recallx mcp install` writes a stable launcher to `~/.recallx/bin/recallx-mcp`, which is the recommended command path for Codex and other editor MCP configs.
|
|
120
139
|
|
|
140
|
+
Workspace backup and recovery commands are available in the packaged CLI too:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
recallx workspace backups
|
|
144
|
+
recallx workspace backup --label "before-upgrade"
|
|
145
|
+
recallx workspace export --format json
|
|
146
|
+
recallx workspace restore --backup <id> --root /path/to/restore
|
|
147
|
+
```
|
|
148
|
+
|
|
121
149
|
If the API is running in bearer mode, set `RECALLX_API_TOKEN` in the MCP client environment. The launcher does not write tokens to disk.
|
|
122
150
|
|
|
123
151
|
Start the packaged runtime with:
|
|
@@ -204,16 +232,38 @@ Use the returned endpoint list and request examples to search nodes and activiti
|
|
|
204
232
|
Reuse the existing local service instead of starting a new one.
|
|
205
233
|
```
|
|
206
234
|
|
|
235
|
+
Recommended instruction for MCP-connected coding agents:
|
|
236
|
+
|
|
237
|
+
```text
|
|
238
|
+
Use my RecallX MCP server as an active local memory layer during this task, not just for final write-back.
|
|
239
|
+
Treat the current workspace as the default scope and do not switch workspaces unless I explicitly ask.
|
|
240
|
+
Before making assumptions or starting meaningful work, read context first: confirm the current workspace, use recallx_search_workspace when the target is still unclear, search for an existing project node when the task is clearly project-shaped, and build a compact recallx_context_bundle once the relevant node or project is known.
|
|
241
|
+
Prefer compact context over repeated broad browsing.
|
|
242
|
+
Once a project is known, append routine work logs to that project instead of writing untargeted workspace captures.
|
|
243
|
+
At the end of meaningful work, write back a concise summary of what changed, what was verified, and any follow-up.
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
MCP result rendering note:
|
|
247
|
+
|
|
248
|
+
- RecallX MCP keeps `structuredContent` as the authoritative machine-readable payload.
|
|
249
|
+
- The mirrored text content may be a compact deterministic summary rather than a pretty-printed JSON dump.
|
|
250
|
+
- For the current rendering policy and compatibility guidance, see `docs/mcp.md`.
|
|
251
|
+
|
|
207
252
|
## MCP Bridge
|
|
208
253
|
|
|
209
254
|
RecallX also ships a stdio MCP adapter for agent clients that prefer tool discovery over raw HTTP calls.
|
|
210
255
|
|
|
256
|
+
MCP tool results keep `structuredContent` as the authoritative machine-readable payload, while `content.text` is rendered as a compact deterministic summary instead of a pretty-printed JSON mirror when the payload shape is known.
|
|
257
|
+
|
|
211
258
|
```bash
|
|
259
|
+
npm run dev:mcp
|
|
212
260
|
npm run mcp
|
|
213
261
|
node dist/server/app/mcp/index.js --api http://127.0.0.1:8787/api/v1
|
|
214
262
|
recallx-mcp --api http://127.0.0.1:8787/api/v1
|
|
215
263
|
```
|
|
216
264
|
|
|
265
|
+
Use `npm run dev:mcp` during source development. `npm run mcp` runs the built entrypoint, so it expects `npm run build:server` to have already created `dist/server/app/mcp/index.js`.
|
|
266
|
+
|
|
217
267
|
For launcher paths, environment variables, and editor-specific setup, see `docs/mcp.md`.
|
|
218
268
|
|
|
219
269
|
## Docs
|
|
@@ -224,6 +274,7 @@ For launcher paths, environment variables, and editor-specific setup, see `docs/
|
|
|
224
274
|
- `docs/api.md` for the local HTTP and CLI contract
|
|
225
275
|
- `docs/mcp.md` for MCP bridge setup
|
|
226
276
|
- `docs/workflows.md` for common usage flows
|
|
277
|
+
- `docs/sync-backup.md` for backup, restore, and single-writer multi-device guidance
|
|
227
278
|
- `docs/schema.md` for storage and data model details
|
|
228
279
|
|
|
229
280
|
## License
|
package/app/cli/src/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
6
6
|
import { getApiBase, getAuthToken, requestJson } from "./http.js";
|
|
7
7
|
import { RECALLX_VERSION } from "../../shared/version.js";
|
|
8
8
|
import { applyCliUpdate, getCliUpdatePlan } from "./update.js";
|
|
9
|
-
import { renderActivitySearchResults, renderBundleMarkdown, renderGovernanceIssues, renderJson, renderNode, renderRelated, renderSearchResults, renderTelemetryErrors, renderTelemetrySummary, renderText, renderUpdateResult, renderWorkspaceSearchResults, renderWorkspaces, } from "./format.js";
|
|
9
|
+
import { renderActivitySearchResults, renderBundleMarkdown, renderGovernanceIssues, renderJson, renderNode, renderRelated, renderSearchResults, renderTelemetryErrors, renderTelemetrySummary, renderText, renderUpdateResult, renderWorkspaceBackups, renderWorkspaceSearchResults, renderWorkspaces, } from "./format.js";
|
|
10
10
|
const DEFAULT_SOURCE = {
|
|
11
11
|
actorType: "human",
|
|
12
12
|
actorLabel: "recallx-cli",
|
|
@@ -465,6 +465,27 @@ async function runWorkspace(apiBase, token, format, args, positionals) {
|
|
|
465
465
|
action,
|
|
466
466
|
rootPath: args.root || args.path || positionals[1],
|
|
467
467
|
});
|
|
468
|
+
case "backups": {
|
|
469
|
+
const data = await requestJson(apiBase, "/workspaces/backups", { token });
|
|
470
|
+
outputData(data, format, "workspace-backups");
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
case "backup":
|
|
474
|
+
return runPostCommand(apiBase, token, format, "/workspaces/backups", "workspace-backup", {
|
|
475
|
+
label: args.label || args.name || positionals[1],
|
|
476
|
+
});
|
|
477
|
+
case "export":
|
|
478
|
+
return runPostCommand(apiBase, token, format, "/workspaces/export", "workspace-export", {
|
|
479
|
+
format: args.format || args.kind || "json",
|
|
480
|
+
});
|
|
481
|
+
case "restore":
|
|
482
|
+
validateRequired(args.backup || args.id || positionals[1], "workspace restore requires --backup");
|
|
483
|
+
validateRequired(args.root || args.path || positionals[2], "workspace restore requires --root");
|
|
484
|
+
return runPostCommand(apiBase, token, format, "/workspaces/restore", "workspace-restore", {
|
|
485
|
+
backupId: args.backup || args.id || positionals[1],
|
|
486
|
+
targetRootPath: args.root || args.path || positionals[2],
|
|
487
|
+
workspaceName: args.name || args.title,
|
|
488
|
+
});
|
|
468
489
|
}
|
|
469
490
|
throw new Error(`Unknown workspace action: ${action}`);
|
|
470
491
|
}
|
|
@@ -547,6 +568,9 @@ function outputData(data, format, command) {
|
|
|
547
568
|
case "workspace-list":
|
|
548
569
|
writeStdout(renderWorkspaces(payload));
|
|
549
570
|
return;
|
|
571
|
+
case "workspace-backups":
|
|
572
|
+
writeStdout(renderWorkspaceBackups(payload));
|
|
573
|
+
return;
|
|
550
574
|
case "append":
|
|
551
575
|
case "create":
|
|
552
576
|
case "link":
|
|
@@ -557,6 +581,9 @@ function outputData(data, format, command) {
|
|
|
557
581
|
case "workspace-current":
|
|
558
582
|
case "workspace-create":
|
|
559
583
|
case "workspace-open":
|
|
584
|
+
case "workspace-backup":
|
|
585
|
+
case "workspace-export":
|
|
586
|
+
case "workspace-restore":
|
|
560
587
|
writeStdout(renderText(payload));
|
|
561
588
|
return;
|
|
562
589
|
case "observability-summary":
|
|
@@ -696,6 +723,10 @@ Usage:
|
|
|
696
723
|
recallx workspace list
|
|
697
724
|
recallx workspace create --root /path/to/workspace [--name "Personal"]
|
|
698
725
|
recallx workspace open --root /path/to/workspace
|
|
726
|
+
recallx workspace backups
|
|
727
|
+
recallx workspace backup [--label "before-upgrade"]
|
|
728
|
+
recallx workspace export [--format json|markdown]
|
|
729
|
+
recallx workspace restore --backup <id> --root /path/to/restore [--name "Recovered"]
|
|
699
730
|
recallx observability summary [--since 24h]
|
|
700
731
|
recallx observability errors [--since 24h] [--surface mcp] [--limit 50]
|
|
701
732
|
|
package/app/cli/src/format.js
CHANGED
|
@@ -144,6 +144,20 @@ export function renderWorkspaces(data) {
|
|
|
144
144
|
.join("\n\n")}\n`;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
export function renderWorkspaceBackups(data) {
|
|
148
|
+
const items = data?.items || [];
|
|
149
|
+
if (!items.length) {
|
|
150
|
+
return "No backups.\n";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return `${items
|
|
154
|
+
.map(
|
|
155
|
+
(item, index) =>
|
|
156
|
+
`${index + 1}. ${item.label || item.id}\n id: ${item.id}\n created: ${item.createdAt}\n path: ${item.backupPath}`,
|
|
157
|
+
)
|
|
158
|
+
.join("\n\n")}\n`;
|
|
159
|
+
}
|
|
160
|
+
|
|
147
161
|
export function renderUpdateResult(data) {
|
|
148
162
|
const lines = [
|
|
149
163
|
`package: ${data?.packageName || ""}`,
|
|
@@ -206,8 +220,18 @@ export function renderTelemetrySummary(data) {
|
|
|
206
220
|
`since: ${data?.since || ""}`,
|
|
207
221
|
`logs: ${data?.logsPath || ""}`,
|
|
208
222
|
`events: ${data?.totalEvents ?? 0}`,
|
|
223
|
+
`slow threshold: ${data?.slowRequestThresholdMs ?? ""}ms`,
|
|
209
224
|
];
|
|
210
225
|
|
|
226
|
+
const hot = Array.isArray(data?.hotOperations) ? data.hotOperations : [];
|
|
227
|
+
if (hot.length > 0) {
|
|
228
|
+
lines.push("");
|
|
229
|
+
lines.push("Hot operations:");
|
|
230
|
+
for (const item of hot.slice(0, 5)) {
|
|
231
|
+
lines.push(`- [${item.surface}] ${item.operation} p95=${item.p95DurationMs ?? ""}ms errors=${item.errorCount}/${item.count}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
211
235
|
const slow = Array.isArray(data?.slowOperations) ? data.slowOperations : [];
|
|
212
236
|
if (slow.length > 0) {
|
|
213
237
|
lines.push("");
|
package/app/mcp/index.js
CHANGED
|
@@ -45,7 +45,7 @@ async function resolveObservabilityState() {
|
|
|
45
45
|
workspaceRoot: typeof workspace.rootPath === "string" ? workspace.rootPath : process.cwd(),
|
|
46
46
|
workspaceName: typeof workspace.workspaceName === "string" ? workspace.workspaceName : "RecallX MCP",
|
|
47
47
|
retentionDays: typeof values["observability.retentionDays"] === "number" ? values["observability.retentionDays"] : 14,
|
|
48
|
-
slowRequestMs: typeof values["observability.slowRequestMs"] === "number" ? values["observability.slowRequestMs"] :
|
|
48
|
+
slowRequestMs: typeof values["observability.slowRequestMs"] === "number" ? values["observability.slowRequestMs"] : 50,
|
|
49
49
|
capturePayloadShape: values["observability.capturePayloadShape"] !== false
|
|
50
50
|
};
|
|
51
51
|
}
|
|
@@ -55,7 +55,7 @@ async function resolveObservabilityState() {
|
|
|
55
55
|
workspaceRoot: process.cwd(),
|
|
56
56
|
workspaceName: "RecallX MCP",
|
|
57
57
|
retentionDays: 14,
|
|
58
|
-
slowRequestMs:
|
|
58
|
+
slowRequestMs: 50,
|
|
59
59
|
capturePayloadShape: true
|
|
60
60
|
};
|
|
61
61
|
}
|