recallx-headless 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 CHANGED
@@ -154,8 +154,10 @@ recallx workspace open --root /Users/name/Documents/RecallX-Test
154
154
  - Default API base: `http://127.0.0.1:8787/api/v1`
155
155
  - `recallx serve` starts the local RecallX API in-process from the installed package
156
156
  - The CLI stays thin for day-to-day API operations and defers behavior to the HTTP API contract
157
+ - MCP tool results keep `structuredContent` as the authoritative payload; when possible the text mirror is a compact deterministic summary rather than a pretty JSON dump
157
158
  - `--format json` is useful when scripting, while `--format markdown` is best for `context`
158
159
  - `workspace open` switches the active workspace in the running local RecallX service without restarting the server
159
160
  - `recallx-mcp` is the direct stdio MCP entrypoint from the npm package
161
+ - MCP tool results keep `structuredContent` authoritative and may render `content.text` as a compact deterministic summary instead of a pretty JSON mirror
160
162
  - See the root [`README.md`](../../README.md) for source-run usage and install paths
161
163
  - See [`docs/mcp.md`](../../docs/mcp.md) for editor MCP wiring details
@@ -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
 
@@ -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"] : 250,
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: 250,
58
+ slowRequestMs: 50,
59
59
  capturePayloadShape: true
60
60
  };
61
61
  }