march-cli 0.1.42 → 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.
- package/package.json +1 -1
- package/src/agent/code-search/cache.mjs +16 -7
- package/src/agent/code-search/engine.mjs +9 -2
- package/src/agent/code-search/retrieval/resilient-vectorizer.mjs +59 -0
- package/src/agent/code-search/retrieval/safetensors.mjs +16 -10
- package/src/agent/code-search/scanner.mjs +11 -5
- package/src/agent/code-search/tool.mjs +11 -5
- package/src/agent/model-payload-dumper.mjs +1 -1
- package/src/agent/runner/payload/provider-payload-transform.mjs +59 -0
- package/src/agent/runner/recall/mid-turn-recall-bridge.mjs +23 -0
- package/src/agent/runner.mjs +28 -27
- package/src/agent/runtime/remote-ui-client.mjs +1 -1
- package/src/agent/runtime/resource/context-resource-loader.mjs +17 -0
- package/src/agent/runtime/runtime-factory.mjs +5 -1
- package/src/agent/runtime/state/runner-state.mjs +10 -3
- package/src/agent/runtime/ui-event-bridge.mjs +2 -2
- package/src/agent/turn/turn-runner.mjs +35 -24
- package/src/cli/fallback-ui.mjs +2 -2
- package/src/cli/repl-loop.mjs +9 -8
- package/src/cli/startup/app-runtime.mjs +4 -2
- package/src/cli/tui/input/mouse-selection-controller.mjs +19 -0
- package/src/cli/tui/output/selectable-copy.mjs +3 -3
- package/src/cli/tui/output/timeline-block-restore.mjs +1 -1
- package/src/cli/tui/output-buffer.mjs +18 -0
- package/src/cli/tui/recall-rendering.mjs +38 -9
- package/src/cli/tui/selection/ansi-range.mjs +88 -0
- package/src/cli/tui/selection-screen.mjs +31 -99
- package/src/cli/turn/turn-input-preparer.mjs +15 -6
- package/src/cli/ui.mjs +2 -2
- package/src/cli/workspace/tui-timeline-projection.mjs +1 -1
- package/src/context/engine.mjs +15 -5
- package/src/context/system-core/base.md +1 -1
- package/src/memory/markdown/markdown-format.mjs +0 -17
- package/src/memory/markdown/markdown-recall.mjs +11 -19
- package/src/memory/markdown/semantic-preload.mjs +26 -0
- package/src/memory/markdown/semantic-recall.mjs +169 -0
- package/src/memory/markdown/sqlite-index.mjs +1 -13
- package/src/memory/markdown-store.mjs +34 -54
- package/src/web-ui/dist/assets/{index-BQtl1uQs.css → index-BG1Pxf1k.css} +1 -1
- package/src/web-ui/dist/assets/{index-DrlJis_D.js → index-C0xOHlDz.js} +1 -1
- package/src/web-ui/dist/index.html +2 -2
- package/src/web-ui/runtime-host.mjs +18 -3
- package/src/web-ui/src/components/timeline/TimelineBlocks.tsx +27 -0
- package/src/web-ui/src/model.ts +18 -0
- package/src/web-ui/src/runtime/client.ts +2 -1
- package/src/web-ui/src/runtime/runtimeTimeline.ts +5 -0
- package/src/web-ui/src/styles/shell.css +7 -0
- package/src/web-ui/src/timelineAdapter.ts +2 -0
|
@@ -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-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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,6 +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 { startSemanticMemoryRecallPreload } from "../memory/markdown/semantic-preload.mjs";
|
|
8
9
|
import { resolveMemoryRoot } from "../memory/root.mjs";
|
|
9
10
|
import { defaultProfilePaths, ensureProfileFiles } from "../context/profiles.mjs";
|
|
10
11
|
import { loadOrCreateProjectId } from "../cli/startup/startup-session.mjs";
|
|
@@ -33,7 +34,7 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
|
|
|
33
34
|
const profilePaths = defaultProfilePaths();
|
|
34
35
|
ensureProfileFiles(profilePaths);
|
|
35
36
|
|
|
36
|
-
const memoryStore = new MarkdownMemoryStore({ root: memoryRoot });
|
|
37
|
+
const memoryStore = new MarkdownMemoryStore({ root: memoryRoot, stateRoot });
|
|
37
38
|
const remoteMemorySources = normalizeRemoteMemorySources(config);
|
|
38
39
|
const shellRuntime = args.shellRuntime ? createCliShellRuntime({ cwd }) : null;
|
|
39
40
|
const extensionPaths = discoverProjectExtensionPaths(cwd);
|
|
@@ -66,6 +67,7 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
|
|
|
66
67
|
ui,
|
|
67
68
|
shellRuntime,
|
|
68
69
|
});
|
|
70
|
+
startSemanticMemoryRecallPreload({ memoryStore, logger, delayMs: 1000 });
|
|
69
71
|
let turnRunning = false;
|
|
70
72
|
|
|
71
73
|
return {
|
|
@@ -81,9 +83,13 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
|
|
|
81
83
|
turnRunning = true;
|
|
82
84
|
memoryStore.beginTurn();
|
|
83
85
|
try {
|
|
84
|
-
const input = prepareTurnInput({ prompt, runner, memoryStore, currentProject });
|
|
86
|
+
const input = await prepareTurnInput({ prompt, runner, memoryStore, currentProject });
|
|
85
87
|
runner.runtimeUiEvents.emit({ type: "web_user_message", text: input.userMessage });
|
|
86
|
-
|
|
88
|
+
runner.runtimeUiEvents.emit({ type: "recall", hints: input.userRecallHints, report: input.userRecallReport });
|
|
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;
|
|
87
93
|
} finally {
|
|
88
94
|
turnRunning = false;
|
|
89
95
|
memoryStore.endTurn();
|
|
@@ -97,6 +103,15 @@ export async function createWebRuntimeHost({ args, config, cwd, stateRoot } = {}
|
|
|
97
103
|
};
|
|
98
104
|
}
|
|
99
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
|
+
|
|
100
115
|
export function createHeadlessWebUi() {
|
|
101
116
|
return {
|
|
102
117
|
readline: () => Promise.resolve(null), write: () => {}, writeln: () => {},
|
|
@@ -39,6 +39,8 @@ function AuxBlock({ item }: { item: Exclude<TimelineItem, { kind: "message" }> }
|
|
|
39
39
|
return <DiffBlock item={item} />;
|
|
40
40
|
case "terminal":
|
|
41
41
|
return <TerminalBlock item={item} />;
|
|
42
|
+
case "memoryRecall":
|
|
43
|
+
return <MemoryRecallBlock item={item} />;
|
|
42
44
|
|
|
43
45
|
case "error":
|
|
44
46
|
return <ErrorBlock item={item} />;
|
|
@@ -89,7 +91,32 @@ function TerminalBlock({ item }: { item: Extract<TimelineItem, { kind: "terminal
|
|
|
89
91
|
);
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
function MemoryRecallBlock({ item }: { item: Extract<TimelineItem, { kind: "memoryRecall" }> }) {
|
|
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)}` : "";
|
|
100
|
+
const fallback = item.report?.vectorizerStatus === "fallback" ? " · fallback" : "";
|
|
101
|
+
return (
|
|
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>
|
|
104
|
+
{item.report?.warning ? <p className="memory-recall-warning">! {item.report.warning}</p> : null}
|
|
105
|
+
<ul>
|
|
106
|
+
{candidates.length ? candidates.map((hint) => (
|
|
107
|
+
<li key={hint.id} className={hint.recalled === false ? "skipped" : "recalled"}>
|
|
108
|
+
<span>{hint.recalled === false ? "×" : "✓"}</span>
|
|
109
|
+
<strong>{formatRecallScore(hint.score)} {hint.name ?? hint.id}</strong>
|
|
110
|
+
</li>
|
|
111
|
+
)) : <li className="skipped"><span>·</span><strong>no candidates</strong></li>}
|
|
112
|
+
</ul>
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
92
116
|
|
|
117
|
+
function formatRecallScore(score?: number) {
|
|
118
|
+
return typeof score === "number" && Number.isFinite(score) ? score.toFixed(2) : "--";
|
|
119
|
+
}
|
|
93
120
|
|
|
94
121
|
function ErrorBlock({ item }: { item: Extract<TimelineItem, { kind: "error" }> }) {
|
|
95
122
|
return (
|
package/src/web-ui/src/model.ts
CHANGED
|
@@ -9,6 +9,22 @@ export type FileNode = {
|
|
|
9
9
|
children?: FileNode[];
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
export type MemoryRecallHint = {
|
|
13
|
+
id: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
score?: number;
|
|
17
|
+
recalled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type MemoryRecallReport = {
|
|
21
|
+
threshold?: number;
|
|
22
|
+
hints?: MemoryRecallHint[];
|
|
23
|
+
candidates?: MemoryRecallHint[];
|
|
24
|
+
vectorizerStatus?: string;
|
|
25
|
+
warning?: string | null;
|
|
26
|
+
};
|
|
27
|
+
|
|
12
28
|
export type MarchTimelineEvent =
|
|
13
29
|
| { id: string; type: "user_message"; text: string; time?: string }
|
|
14
30
|
| { id: string; type: "assistant_message"; text: string; time?: string }
|
|
@@ -17,6 +33,7 @@ export type MarchTimelineEvent =
|
|
|
17
33
|
| { id: string; type: "tool_result"; tool: string; summary: string; status: "done" | "failed" }
|
|
18
34
|
| { id: string; type: "file_diff"; path: string; lines: Array<{ kind: "add" | "remove" | "keep"; text: string }> }
|
|
19
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; variant?: "assistant" | "user" }
|
|
20
37
|
| { id: string; type: "error"; message: string; detail?: string };
|
|
21
38
|
|
|
22
39
|
export type TimelineItem =
|
|
@@ -25,6 +42,7 @@ export type TimelineItem =
|
|
|
25
42
|
| { id: string; kind: "tool"; tool: string; target: string; status: "running" | "done" | "failed"; summary?: string }
|
|
26
43
|
| { id: string; kind: "diff"; path: string; lines: Array<{ kind: "add" | "remove" | "keep"; text: string }> }
|
|
27
44
|
| { id: string; kind: "terminal"; command: string; output: string; status: "running" | "done" | "failed" }
|
|
45
|
+
| { id: string; kind: "memoryRecall"; hints: MemoryRecallHint[]; report?: MemoryRecallReport | null; variant?: "assistant" | "user" }
|
|
28
46
|
| { id: string; kind: "error"; message: string; detail?: string };
|
|
29
47
|
|
|
30
48
|
export type SessionSummary = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ProviderQuotaSnapshot, SessionSummary, WebUiModel } from "../model";
|
|
1
|
+
import type { MemoryRecallHint, MemoryRecallReport, ProviderQuotaSnapshot, SessionSummary, WebUiModel } from "../model";
|
|
2
2
|
|
|
3
3
|
export type RuntimeUiEvent =
|
|
4
4
|
| { type: "web_user_message"; text: string }
|
|
@@ -13,6 +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; variant?: "assistant" | "user" }
|
|
16
17
|
| { type: "status"; text: string }
|
|
17
18
|
| { type: "retry_start"; errorMessage?: string }
|
|
18
19
|
| { type: "retry_end"; success?: boolean; finalError?: string };
|
|
@@ -26,6 +26,11 @@ export function applyRuntimeEvent(events: MarchTimelineEvent[], event: RuntimeUi
|
|
|
26
26
|
case "edit_diff":
|
|
27
27
|
next.push({ id, type: "file_diff", path: event.path, lines: toDiffLines(event.diffLines) });
|
|
28
28
|
return next;
|
|
29
|
+
case "recall":
|
|
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
|
+
}
|
|
33
|
+
return next;
|
|
29
34
|
|
|
30
35
|
case "status":
|
|
31
36
|
next.push({ id, type: "terminal_output", command: "status", output: event.text, status: "done" });
|
|
@@ -95,6 +95,13 @@
|
|
|
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; }
|
|
99
|
+
.memory-recall-block .memory-recall-warning { margin: 7px 0 0; color: var(--color-text-muted); }
|
|
100
|
+
.memory-recall-block ul { margin: 7px 0 0; padding: 0; list-style: none; display: grid; gap: 4px; }
|
|
101
|
+
.memory-recall-block li { display: flex; gap: 7px; align-items: center; min-width: 0; }
|
|
102
|
+
.memory-recall-block li.recalled span { color: var(--color-success); }
|
|
103
|
+
.memory-recall-block li.skipped span { color: var(--color-text-muted); }
|
|
104
|
+
.memory-recall-block li.skipped strong { color: var(--color-text-muted); }
|
|
98
105
|
|
|
99
106
|
|
|
100
107
|
.right-body { flex: 1; min-height: 0; overflow: auto; padding: 12px; }
|
|
@@ -35,6 +35,8 @@ function toTimelineItem(event: MarchTimelineEvent): TimelineItem {
|
|
|
35
35
|
return { id: event.id, kind: "diff", path: event.path, lines: event.lines };
|
|
36
36
|
case "terminal_output":
|
|
37
37
|
return { id: event.id, kind: "terminal", command: event.command, output: event.output, status: event.status };
|
|
38
|
+
case "memory_recall":
|
|
39
|
+
return { id: event.id, kind: "memoryRecall", hints: event.hints, report: event.report, variant: event.variant };
|
|
38
40
|
|
|
39
41
|
case "error":
|
|
40
42
|
return { id: event.id, kind: "error", message: event.message, detail: event.detail };
|