march-cli 0.1.45 → 0.1.46

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.
Files changed (40) hide show
  1. package/package.json +1 -1
  2. package/src/agent/code-search/cache.mjs +13 -5
  3. package/src/agent/code-search/engine.mjs +7 -2
  4. package/src/agent/code-search/retrieval/safetensors.mjs +16 -10
  5. package/src/agent/code-search/scanner.mjs +11 -5
  6. package/src/agent/model-payload-dumper.mjs +1 -1
  7. package/src/agent/runner/payload/provider-payload-transform.mjs +59 -0
  8. package/src/agent/runner/recall/mid-turn-recall-bridge.mjs +23 -0
  9. package/src/agent/runner.mjs +28 -27
  10. package/src/agent/runtime/remote-ui-client.mjs +1 -1
  11. package/src/agent/runtime/resource/context-resource-loader.mjs +17 -0
  12. package/src/agent/runtime/runtime-factory.mjs +5 -1
  13. package/src/agent/runtime/state/runner-state.mjs +10 -3
  14. package/src/agent/runtime/ui-event-bridge.mjs +2 -2
  15. package/src/agent/turn/turn-runner.mjs +20 -16
  16. package/src/cli/fallback-ui.mjs +2 -2
  17. package/src/cli/repl-loop.mjs +5 -4
  18. package/src/cli/startup/app-runtime.mjs +2 -3
  19. package/src/cli/tui/input/mouse-selection-controller.mjs +19 -0
  20. package/src/cli/tui/output/selectable-copy.mjs +3 -3
  21. package/src/cli/tui/output-buffer.mjs +18 -0
  22. package/src/cli/tui/recall-rendering.mjs +30 -8
  23. package/src/cli/tui/selection/ansi-range.mjs +88 -0
  24. package/src/cli/tui/selection-screen.mjs +31 -99
  25. package/src/cli/turn/turn-input-preparer.mjs +9 -2
  26. package/src/cli/ui.mjs +2 -2
  27. package/src/context/engine.mjs +13 -3
  28. package/src/memory/markdown/semantic-preload.mjs +9 -0
  29. package/src/memory/markdown/semantic-recall.mjs +10 -6
  30. package/src/memory/markdown-store.mjs +19 -11
  31. package/src/web-ui/dist/assets/{index-CcbYCcWs.css → index-BG1Pxf1k.css} +1 -1
  32. package/src/web-ui/dist/assets/{index-CBYbNVgs.js → index-C0xOHlDz.js} +1 -1
  33. package/src/web-ui/dist/index.html +2 -2
  34. package/src/web-ui/runtime-host.mjs +15 -3
  35. package/src/web-ui/src/components/timeline/TimelineBlocks.tsx +9 -6
  36. package/src/web-ui/src/model.ts +2 -2
  37. package/src/web-ui/src/runtime/client.ts +1 -1
  38. package/src/web-ui/src/runtime/runtimeTimeline.ts +2 -2
  39. package/src/web-ui/src/styles/shell.css +1 -0
  40. package/src/web-ui/src/timelineAdapter.ts +1 -1
@@ -4,8 +4,8 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
6
  <title>March Web</title>
7
- <script type="module" crossorigin src="/assets/index-CBYbNVgs.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-CcbYCcWs.css">
7
+ <script type="module" crossorigin src="/assets/index-C0xOHlDz.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-BG1Pxf1k.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -5,7 +5,7 @@ import { createMarchAuthStorage } from "../auth/storage.mjs";
5
5
  import { createRuntimeRunner } from "../cli/startup/create-runtime-runner.mjs";
6
6
  import { createCliShellRuntime } from "../shell/cli-runtime.mjs";
7
7
  import { MarkdownMemoryStore } from "../memory/markdown-store.mjs";
8
- import { preloadSemanticMemoryRecall } from "../memory/markdown/semantic-preload.mjs";
8
+ import { startSemanticMemoryRecallPreload } from "../memory/markdown/semantic-preload.mjs";
9
9
  import { resolveMemoryRoot } from "../memory/root.mjs";
10
10
  import { defaultProfilePaths, ensureProfileFiles } from "../context/profiles.mjs";
11
11
  import { loadOrCreateProjectId } from "../cli/startup/startup-session.mjs";
@@ -41,7 +41,6 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
41
41
  const lifecycleManifests = loadProjectLifecycleHookManifests(cwd);
42
42
  const contextDumpRoot = resolve(projectMarchDir, "context-dumps", Date.now().toString(36));
43
43
  const ui = createHeadlessWebUi();
44
- await preloadSemanticMemoryRecall({ memoryStore, ui, logger });
45
44
  const currentProject = basename(cwd);
46
45
  const namespace = loadOrCreateProjectId(projectMarchDir);
47
46
  const runnerOptions = {
@@ -68,6 +67,7 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
68
67
  ui,
69
68
  shellRuntime,
70
69
  });
70
+ startSemanticMemoryRecallPreload({ memoryStore, logger, delayMs: 1000 });
71
71
  let turnRunning = false;
72
72
 
73
73
  return {
@@ -86,7 +86,10 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
86
86
  const input = await prepareTurnInput({ prompt, runner, memoryStore, currentProject });
87
87
  runner.runtimeUiEvents.emit({ type: "web_user_message", text: input.userMessage });
88
88
  runner.runtimeUiEvents.emit({ type: "recall", hints: input.userRecallHints, report: input.userRecallReport });
89
- return await runner.runTurn(input.fullPrompt, input.userMessage, input.runOptions);
89
+ if (input.shouldRenderCarryoverRecall) runner.runtimeUiEvents.emit({ type: "recall", hints: input.carryoverRecallHints, report: input.carryoverRecallReport, variant: "assistant" });
90
+ const result = await runner.runTurn(input.fullPrompt, input.userMessage, input.runOptions);
91
+ emitPendingAssistantRecallPreview(runner);
92
+ return result;
90
93
  } finally {
91
94
  turnRunning = false;
92
95
  memoryStore.endTurn();
@@ -100,6 +103,15 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
100
103
  };
101
104
  }
102
105
 
106
+ function emitPendingAssistantRecallPreview(runner) {
107
+ if (runner.engine.hasRenderedPendingAssistantRecallHints?.()) return;
108
+ const hints = runner.engine.peekPendingAssistantRecallHints?.() ?? [];
109
+ const report = runner.engine.peekPendingAssistantRecallReport?.() ?? null;
110
+ if (hints.length === 0 && !report) return;
111
+ runner.runtimeUiEvents.emit({ type: "recall", hints, report, variant: "assistant" });
112
+ runner.engine.markPendingAssistantRecallHintsRendered?.();
113
+ }
114
+
103
115
  export function createHeadlessWebUi() {
104
116
  return {
105
117
  readline: () => Promise.resolve(null), write: () => {}, writeln: () => {},
@@ -92,20 +92,23 @@ function TerminalBlock({ item }: { item: Extract<TimelineItem, { kind: "terminal
92
92
  }
93
93
 
94
94
  function MemoryRecallBlock({ item }: { item: Extract<TimelineItem, { kind: "memoryRecall" }> }) {
95
- const candidates = item.report?.candidates?.length ? item.report.candidates : item.hints.map((hint) => ({ ...hint, recalled: true }));
96
- const threshold = typeof item.report?.threshold === "number" ? `threshold ${item.report.threshold.toFixed(2)}` : "semantic recall";
95
+ const isAssistant = item.variant === "assistant";
96
+ const reportCandidates = item.report?.candidates ?? [];
97
+ const candidates = (reportCandidates.length ? reportCandidates : item.hints.map((hint) => ({ ...hint, recalled: true }))).slice(0, isAssistant ? 3 : undefined);
98
+ const summary = `${item.hints.length} recalled · ${reportCandidates.length || candidates.length} ${(reportCandidates.length || candidates.length) === 1 ? "candidate" : "candidates"}`;
99
+ const threshold = typeof item.report?.threshold === "number" ? ` · threshold ${item.report.threshold.toFixed(2)}` : "";
97
100
  const fallback = item.report?.vectorizerStatus === "fallback" ? " · fallback" : "";
98
101
  return (
99
- <div className="timeline-aux memory-recall-block">
100
- <div className="aux-title"><span>memory</span><strong>recall · {threshold}{fallback}</strong></div>
102
+ <div className={`timeline-aux memory-recall-block${isAssistant ? " compact" : ""}`}>
103
+ <div className="aux-title"><span>memory</span><strong>recall · {summary}{threshold}{fallback}</strong></div>
101
104
  {item.report?.warning ? <p className="memory-recall-warning">! {item.report.warning}</p> : null}
102
105
  <ul>
103
- {candidates.map((hint) => (
106
+ {candidates.length ? candidates.map((hint) => (
104
107
  <li key={hint.id} className={hint.recalled === false ? "skipped" : "recalled"}>
105
108
  <span>{hint.recalled === false ? "×" : "✓"}</span>
106
109
  <strong>{formatRecallScore(hint.score)} {hint.name ?? hint.id}</strong>
107
110
  </li>
108
- ))}
111
+ )) : <li className="skipped"><span>·</span><strong>no candidates</strong></li>}
109
112
  </ul>
110
113
  </div>
111
114
  );
@@ -33,7 +33,7 @@ export type MarchTimelineEvent =
33
33
  | { id: string; type: "tool_result"; tool: string; summary: string; status: "done" | "failed" }
34
34
  | { id: string; type: "file_diff"; path: string; lines: Array<{ kind: "add" | "remove" | "keep"; text: string }> }
35
35
  | { id: string; type: "terminal_output"; command: string; output: string; status: "running" | "done" | "failed" }
36
- | { id: string; type: "memory_recall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null }
36
+ | { id: string; type: "memory_recall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null; variant?: "assistant" | "user" }
37
37
  | { id: string; type: "error"; message: string; detail?: string };
38
38
 
39
39
  export type TimelineItem =
@@ -42,7 +42,7 @@ export type TimelineItem =
42
42
  | { id: string; kind: "tool"; tool: string; target: string; status: "running" | "done" | "failed"; summary?: string }
43
43
  | { id: string; kind: "diff"; path: string; lines: Array<{ kind: "add" | "remove" | "keep"; text: string }> }
44
44
  | { id: string; kind: "terminal"; command: string; output: string; status: "running" | "done" | "failed" }
45
- | { id: string; kind: "memoryRecall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null }
45
+ | { id: string; kind: "memoryRecall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null; variant?: "assistant" | "user" }
46
46
  | { id: string; kind: "error"; message: string; detail?: string };
47
47
 
48
48
  export type SessionSummary = {
@@ -13,7 +13,7 @@ export type RuntimeUiEvent =
13
13
  | { type: "tool_end"; name: string; isError?: boolean; result?: unknown }
14
14
  | { type: "edit_diff"; path: string; diffLines?: Array<{ type?: string; text?: string }> }
15
15
  | { type: "provider_quota_snapshot"; snapshot: ProviderQuotaSnapshot | null }
16
- | { type: "recall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null }
16
+ | { type: "recall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null; variant?: "assistant" | "user" }
17
17
  | { type: "status"; text: string }
18
18
  | { type: "retry_start"; errorMessage?: string }
19
19
  | { type: "retry_end"; success?: boolean; finalError?: string };
@@ -27,8 +27,8 @@ export function applyRuntimeEvent(events: MarchTimelineEvent[], event: RuntimeUi
27
27
  next.push({ id, type: "file_diff", path: event.path, lines: toDiffLines(event.diffLines) });
28
28
  return next;
29
29
  case "recall":
30
- if ((event.hints?.length ?? 0) || (event.report?.candidates?.length ?? 0)) {
31
- next.push({ id, type: "memory_recall", hints: event.hints ?? [], report: event.report ?? null });
30
+ if ((event.hints?.length ?? 0) || event.report) {
31
+ next.push({ id, type: "memory_recall", hints: event.hints ?? [], report: event.report ?? null, variant: event.variant });
32
32
  }
33
33
  return next;
34
34
 
@@ -95,6 +95,7 @@
95
95
  .diff-line.remove, .error-block strong { color: var(--color-danger); }
96
96
  .diff-line.keep { color: var(--color-text-muted); }
97
97
  .terminal-block pre { margin: 7px 0 0; color: var(--color-text-muted); font-size: 12px; white-space: pre-wrap; }
98
+ .memory-recall-block.compact { opacity: 0.62; }
98
99
  .memory-recall-block .memory-recall-warning { margin: 7px 0 0; color: var(--color-text-muted); }
99
100
  .memory-recall-block ul { margin: 7px 0 0; padding: 0; list-style: none; display: grid; gap: 4px; }
100
101
  .memory-recall-block li { display: flex; gap: 7px; align-items: center; min-width: 0; }
@@ -36,7 +36,7 @@ function toTimelineItem(event: MarchTimelineEvent): TimelineItem {
36
36
  case "terminal_output":
37
37
  return { id: event.id, kind: "terminal", command: event.command, output: event.output, status: event.status };
38
38
  case "memory_recall":
39
- return { id: event.id, kind: "memoryRecall", hints: event.hints, report: event.report };
39
+ return { id: event.id, kind: "memoryRecall", hints: event.hints, report: event.report, variant: event.variant };
40
40
 
41
41
  case "error":
42
42
  return { id: event.id, kind: "error", message: event.message, detail: event.detail };