march-cli 0.1.41 → 0.1.45

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 (36) hide show
  1. package/package.json +1 -1
  2. package/src/agent/code-search/cache.mjs +3 -2
  3. package/src/agent/code-search/engine.mjs +2 -0
  4. package/src/agent/code-search/retrieval/resilient-vectorizer.mjs +59 -0
  5. package/src/agent/code-search/tool.mjs +11 -5
  6. package/src/agent/runner.mjs +2 -1
  7. package/src/agent/runtime/remote-ui-client.mjs +1 -1
  8. package/src/agent/runtime/ui-event-bridge.mjs +2 -2
  9. package/src/agent/turn/turn-events.mjs +6 -0
  10. package/src/agent/turn/turn-runner.mjs +110 -23
  11. package/src/cli/fallback-ui.mjs +2 -2
  12. package/src/cli/repl-loop.mjs +7 -7
  13. package/src/cli/startup/app-runtime.mjs +5 -2
  14. package/src/cli/tui/output/timeline-block-restore.mjs +1 -1
  15. package/src/cli/tui/recall-rendering.mjs +14 -7
  16. package/src/cli/turn/turn-input-preparer.mjs +6 -4
  17. package/src/cli/ui.mjs +2 -2
  18. package/src/cli/workspace/tui-timeline-projection.mjs +1 -1
  19. package/src/context/engine.mjs +2 -2
  20. package/src/context/system-core/base.md +1 -1
  21. package/src/memory/markdown/markdown-format.mjs +0 -17
  22. package/src/memory/markdown/markdown-recall.mjs +11 -19
  23. package/src/memory/markdown/semantic-preload.mjs +17 -0
  24. package/src/memory/markdown/semantic-recall.mjs +165 -0
  25. package/src/memory/markdown/sqlite-index.mjs +1 -13
  26. package/src/memory/markdown-store.mjs +24 -52
  27. package/src/web-ui/dist/assets/{index-DrlJis_D.js → index-CBYbNVgs.js} +1 -1
  28. package/src/web-ui/dist/assets/{index-BQtl1uQs.css → index-CcbYCcWs.css} +1 -1
  29. package/src/web-ui/dist/index.html +2 -2
  30. package/src/web-ui/runtime-host.mjs +5 -2
  31. package/src/web-ui/src/components/timeline/TimelineBlocks.tsx +24 -0
  32. package/src/web-ui/src/model.ts +18 -0
  33. package/src/web-ui/src/runtime/client.ts +2 -1
  34. package/src/web-ui/src/runtime/runtimeTimeline.ts +5 -0
  35. package/src/web-ui/src/styles/shell.css +6 -0
  36. package/src/web-ui/src/timelineAdapter.ts +2 -0
@@ -1 +1 @@
1
- @layer theme.palette{:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--font-sans:"Segoe UI Variable Text", "Segoe UI Variable", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, DengXian, "等线", "Microsoft YaHei UI", sans-serif;--font-mono:ui-monospace, "SFMono-Regular", "Cascadia Code", "JetBrains Mono", "Fira Code", Consolas, "Liberation Mono", Menlo, monospace;--font-weight-ui-normal:500;--font-weight-content-normal:600;--font-weight-ui-medium:600;--font-weight-ui-strong:700;--palette-white:#fff;--palette-slate-50:#f8fafc;--palette-slate-100:#f1f5f9;--palette-slate-200:#e2e8f0;--palette-slate-400:#94a3b8;--palette-slate-500:#64748b;--palette-slate-700:#334155;--palette-slate-900:#0f172a;--palette-slate-950:#020617;--palette-blue-400:#60a5fa;--palette-blue-600:#2563eb;--palette-green-700:#15803d;--palette-amber-600:#d97706;--palette-red-600:#dc2626}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}}@layer theme.semantic{:root{--color-bg-page:#f3f4f6;--color-bg-surface:var(--palette-white);--color-bg-sidebar:#ffffffbd;--color-bg-subtle:var(--palette-slate-50);--color-text-primary:var(--palette-slate-900);--color-text-muted:var(--palette-slate-500);--color-text-inverse:var(--palette-white);--color-border-subtle:#0f172a14;--color-border-strong:#0f172a24;--color-accent:var(--palette-blue-600);--color-accent-soft:#2563eb14;--color-success:var(--palette-green-700);--color-warning:var(--palette-amber-600);--color-danger:var(--palette-red-600);--color-hover:#0000000d;--color-shadow-drawer:#00000026;--color-scrim:#0000004d}@media (prefers-color-scheme:dark){:root{--color-bg-page:var(--palette-slate-900);--color-bg-surface:var(--palette-slate-950);--color-bg-sidebar:var(--palette-slate-900);--color-bg-subtle:var(--palette-slate-900);--color-text-primary:var(--palette-slate-50);--color-text-muted:var(--palette-slate-400);--color-border-subtle:#94a3b81f;--color-border-strong:#94a3b833;--color-accent:var(--palette-blue-400);--color-accent-soft:#60a5fa24;--color-hover:#94a3b814}}}@layer theme.component{:root{--shell-left-width:260px;--shell-right-width:280px;--shell-mobile-panel-width:75vw;--header-height:36px;--composer-min-height:46px;--radius-row:6px;--radius-control:8px;--radius-composer:12px;--space-panel:8px;--tree-indent:16px}}@layer base{*{box-sizing:border-box}html,body,#root{height:100%;margin:0;overflow:hidden}body{background:var(--color-bg-page);color:var(--color-text-primary);font-family:var(--font-sans);font-weight:var(--font-weight-ui-normal);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility}button,textarea{font:inherit}button{cursor:pointer}}@layer components{.app-shell{grid-template-columns:var(--shell-left-width) minmax(0, 1fr) var(--shell-right-width);background:var(--color-bg-page);height:100dvh;color:var(--color-text-primary);isolation:isolate;grid-template-rows:minmax(0,1fr) auto;grid-template-areas:"sidebar main right""sidebar footer right";display:grid;overflow:hidden}.panel{background:var(--color-bg-sidebar);min-height:0;overflow:hidden}.left-panel{border-right:1px solid var(--color-border-subtle);grid-area:sidebar}.right-panel{border-left:1px solid var(--color-border-subtle);flex-direction:column;grid-area:right;display:flex}.projects-header,.right-header,.main-header{height:var(--header-height);border-bottom:1px solid var(--color-border-subtle);background:var(--color-bg-sidebar);color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase;justify-content:space-between;align-items:center;padding:0 16px;display:flex}.projects-header h3{font:inherit;letter-spacing:.5px;margin:0}.menu-button{border-radius:var(--radius-control);width:28px;height:28px;color:var(--color-text-muted);background:0 0;border:0;justify-content:center;align-items:center;gap:3px;display:inline-flex}.menu-button span{background:currentColor;border-radius:999px;width:3.6px;height:3.6px}.menu-button:hover,.header-button:hover,.session-row:hover,.activity-row:hover{background:var(--color-hover)}.projects-body{height:calc(100% - var(--header-height));padding:var(--space-panel) 0;overflow:hidden}.project-tree-host{--trees-accent-override:var(--color-accent);--trees-bg-override:var(--color-bg-sidebar);--trees-bg-muted-override:var(--color-hover);--trees-border-color-override:var(--color-border-subtle);--trees-fg-override:var(--color-text-primary);--trees-fg-muted-override:var(--color-text-muted);--trees-selected-bg-override:var(--color-accent-soft);--trees-selected-fg-override:var(--color-accent);--trees-font-family-override:var(--font-sans);--trees-font-size-override:13px;--trees-border-radius-override:var(--radius-row);--trees-item-height:30px;--trees-item-padding-x-override:8px;--trees-item-margin-x-override:8px;--trees-item-row-gap-override:4px;--trees-level-gap-override:var(--tree-indent);--trees-padding-inline-override:0px;--trees-scrollbar-gutter-override:6px;height:100%}.timeline{background:var(--color-bg-surface);flex-direction:column;grid-area:main;min-width:0;min-height:0;display:flex;overflow:hidden}.main-header{background:var(--color-bg-surface)}.runtime-pill{color:var(--color-text-muted);background:var(--color-bg-subtle);border-radius:999px;padding:2px 7px;font-size:12px}.runtime-pill.connected{color:var(--color-accent);background:var(--color-accent-soft)}.timeline-scroll{flex:1;min-height:0;padding:16px 18px 24px;overflow:auto}.session-title{align-items:baseline;gap:8px;margin:0 0 14px 40px;display:flex}.session-title h1{font-size:17px;font-weight:var(--font-weight-ui-strong);letter-spacing:-.01em;margin:0}.session-title span{color:var(--color-text-muted);font-size:12px}.timeline-list{max-width:920px;margin:0 auto}.message-row{grid-template-columns:30px minmax(0,1fr);gap:10px;padding:10px 0;display:grid}.message-row+.message-row{border-top:1px solid var(--color-border-subtle)}.agent-dot{border-radius:var(--radius-control);background:var(--palette-slate-700);width:28px;height:28px;color:var(--color-text-inverse);place-items:center;font-size:12px;font-weight:800;display:grid}.agent-dot.march{background:var(--color-accent)}.message-body{min-width:0;color:var(--color-text-primary);font-size:14px;font-weight:var(--font-weight-content-normal);padding-top:3px;line-height:1.55}.message-body p{margin:0}.message-body time{color:var(--color-text-muted);margin-top:4px;font-size:11px;display:block}.timeline-aux{border:1px solid var(--color-border-subtle);border-radius:var(--radius-control);background:var(--color-bg-subtle);padding:7px 9px}.timeline-aux summary,.aux-title{align-items:center;gap:8px;min-height:20px;display:flex}.timeline-aux summary{cursor:pointer}.timeline-aux span,.timeline-aux em{color:var(--color-text-muted);font-size:12px;font-style:normal}.timeline-aux strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:13px;font-weight:var(--font-weight-ui-medium);overflow:hidden}.timeline-aux p{color:var(--color-text-muted);margin:7px 0 0;font-size:13px}.tool-block span,.diff-inline,.terminal-block pre{font-family:var(--font-mono)}.diff-inline{border-left:2px solid var(--color-border-strong);margin-top:7px;padding-left:10px;font-size:13px}.diff-line{padding:2px 0}.diff-line.add{color:var(--color-success)}.diff-line.remove,.error-block strong{color:var(--color-danger)}.diff-line.keep{color:var(--color-text-muted)}.terminal-block pre{color:var(--color-text-muted);white-space:pre-wrap;margin:7px 0 0;font-size:12px}.right-body{flex:1;min-height:0;padding:12px;overflow:auto}.workspace-picker{gap:7px;padding-bottom:10px;display:grid}.workspace-picker label{color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase}.workspace-input-row{grid-template-columns:minmax(0,1fr) auto;gap:4px;display:grid}.workspace-input-row input{border:1px solid var(--color-border-subtle);border-radius:var(--radius-control);background:var(--color-bg-surface);min-width:0;color:var(--color-text-primary);padding:7px 8px}.workspace-input-row button,.fs-entry-row button,.fs-row{border-radius:var(--radius-control);color:var(--color-text-muted);background:0 0;border:0}.workspace-input-row button{background:var(--color-accent-soft);color:var(--color-accent);padding:0 8px}.workspace-input-row button:disabled{opacity:.45}.workspace-path{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--color-text-muted);font-size:12px;overflow:hidden}.fs-entry-row{grid-template-columns:minmax(0,1fr) auto;gap:4px;display:grid}.fs-entry-row button,.fs-row{text-align:left;min-height:28px;padding:0 7px}.fs-entry-row button:first-child{text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-primary);overflow:hidden}.provider-quota{border-top:1px solid var(--color-border-subtle);gap:9px;margin-top:12px;padding-top:12px;display:grid}.provider-quota-header{justify-content:space-between;align-items:center;gap:8px;font-size:12px;display:flex}.provider-quota-header span{color:var(--color-text-primary);font-weight:var(--font-weight-ui-medium)}.provider-quota-header time,.quota-row em{color:var(--color-text-muted);font-style:normal}.quota-row{gap:5px;font-size:12px;display:grid}.quota-row-main{justify-content:space-between;align-items:center;gap:8px;display:flex}.quota-row-main span{color:var(--color-text-primary)}.quota-row-main strong{color:var(--color-accent);font-size:12px}.quota-bar{background:var(--color-bg-surface);height:6px;box-shadow:inset 0 0 0 1px var(--color-border-subtle);border-radius:999px;overflow:hidden}.quota-bar span{border-radius:inherit;background:linear-gradient(90deg, var(--color-accent), color-mix(in srgb, var(--color-accent) 72%, white));height:100%;display:block}.session-row,.activity-row{border-radius:var(--radius-control);width:100%;min-height:34px;color:var(--color-text-primary);text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:8px;padding:7px 8px;font-size:13px;display:flex}.session-row.active{background:var(--color-accent-soft);color:var(--color-accent);font-weight:var(--font-weight-ui-medium)}.session-row time,.activity-row time{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--color-text-muted);font-size:12px;overflow:hidden}.right-divider{border-top:1px solid var(--color-border-subtle);color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase;margin:12px 0 4px;padding-top:12px}.activity-row{color:var(--color-text-muted)}.composer{background:var(--color-bg-surface);grid-area:footer;grid-template-columns:1fr;align-items:end;min-width:0;padding:0 16px 12px;display:grid}.composer-box{width:100%;min-height:var(--composer-min-height);border:1px solid var(--color-border-strong);border-radius:var(--radius-composer);background:var(--color-bg-sidebar);align-items:center;display:flex;position:relative;overflow:visible}.composer-box:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 1px var(--color-accent-soft)}.composer textarea{resize:none;width:100%;max-height:160px;color:var(--color-text-primary);font-weight:var(--font-weight-content-normal);background:0 0;border:0;outline:0;padding:12px 124px 12px 12px}.composer-actions{align-items:center;gap:2px;display:flex;position:absolute;bottom:8px;right:8px}.session-ring,.chip-button,.icon-action,.send-icon,.mobile-toggle{border-radius:var(--radius-control);width:28px;height:28px;color:var(--color-text-muted);background:0 0;border:0;justify-content:center;align-items:center;display:inline-flex}.session-ring:before{content:"";border:2px solid var(--color-accent);border-radius:999px;width:14px;height:14px}.chip-button{width:auto;padding:0 8px;font-size:12px}.icon-action:hover,.chip-button:hover,.mobile-toggle:hover{background:var(--color-hover)}.send-icon{background:var(--color-accent);color:var(--color-text-inverse);font-size:16px;font-weight:700}.send-icon:disabled{opacity:.45}.mobile-toggle,.overlay{display:none}@media (width<=920px){html,body{width:100%;min-height:0;position:fixed;inset:0}.app-shell{height:100dvh;padding-top:env(safe-area-inset-top,0);flex-direction:column;display:flex}.timeline{flex:1;min-height:0}.composer{padding:0 1px max(2px, env(safe-area-inset-bottom));flex:none;grid-template-columns:30px minmax(0,1fr) 30px;gap:1px}.mobile-toggle{align-self:center;height:44px;display:inline-flex}.composer-box{border-radius:10px;min-height:44px}.composer textarea{padding-right:114px}.left-panel,.right-panel{top:env(safe-area-inset-top,0);z-index:30;width:var(--shell-mobile-panel-width);background:var(--color-bg-sidebar);box-shadow:4px 0 24px var(--color-shadow-drawer);transition:transform .22s cubic-bezier(.2,.8,.2,1);position:fixed;bottom:0;transform:translate(-100%)}.left-panel{border-top-right-radius:14px;border-bottom-right-radius:14px;left:0}.right-panel{box-shadow:-4px 0 24px var(--color-shadow-drawer);border-top-left-radius:14px;border-bottom-left-radius:14px;right:0;transform:translate(100%)}.app-shell[data-left-open=true] .left-panel,.app-shell[data-right-open=true] .right-panel{transform:translate(0)}.app-shell[data-left-open=true] .overlay,.app-shell[data-right-open=true] .overlay{z-index:20;background:var(--color-scrim);display:block;position:fixed;inset:0}}}
1
+ @layer theme.palette{:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--font-sans:"Segoe UI Variable Text", "Segoe UI Variable", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, DengXian, "等线", "Microsoft YaHei UI", sans-serif;--font-mono:ui-monospace, "SFMono-Regular", "Cascadia Code", "JetBrains Mono", "Fira Code", Consolas, "Liberation Mono", Menlo, monospace;--font-weight-ui-normal:500;--font-weight-content-normal:600;--font-weight-ui-medium:600;--font-weight-ui-strong:700;--palette-white:#fff;--palette-slate-50:#f8fafc;--palette-slate-100:#f1f5f9;--palette-slate-200:#e2e8f0;--palette-slate-400:#94a3b8;--palette-slate-500:#64748b;--palette-slate-700:#334155;--palette-slate-900:#0f172a;--palette-slate-950:#020617;--palette-blue-400:#60a5fa;--palette-blue-600:#2563eb;--palette-green-700:#15803d;--palette-amber-600:#d97706;--palette-red-600:#dc2626}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}}@layer theme.semantic{:root{--color-bg-page:#f3f4f6;--color-bg-surface:var(--palette-white);--color-bg-sidebar:#ffffffbd;--color-bg-subtle:var(--palette-slate-50);--color-text-primary:var(--palette-slate-900);--color-text-muted:var(--palette-slate-500);--color-text-inverse:var(--palette-white);--color-border-subtle:#0f172a14;--color-border-strong:#0f172a24;--color-accent:var(--palette-blue-600);--color-accent-soft:#2563eb14;--color-success:var(--palette-green-700);--color-warning:var(--palette-amber-600);--color-danger:var(--palette-red-600);--color-hover:#0000000d;--color-shadow-drawer:#00000026;--color-scrim:#0000004d}@media (prefers-color-scheme:dark){:root{--color-bg-page:var(--palette-slate-900);--color-bg-surface:var(--palette-slate-950);--color-bg-sidebar:var(--palette-slate-900);--color-bg-subtle:var(--palette-slate-900);--color-text-primary:var(--palette-slate-50);--color-text-muted:var(--palette-slate-400);--color-border-subtle:#94a3b81f;--color-border-strong:#94a3b833;--color-accent:var(--palette-blue-400);--color-accent-soft:#60a5fa24;--color-hover:#94a3b814}}}@layer theme.component{:root{--shell-left-width:260px;--shell-right-width:280px;--shell-mobile-panel-width:75vw;--header-height:36px;--composer-min-height:46px;--radius-row:6px;--radius-control:8px;--radius-composer:12px;--space-panel:8px;--tree-indent:16px}}@layer base{*{box-sizing:border-box}html,body,#root{height:100%;margin:0;overflow:hidden}body{background:var(--color-bg-page);color:var(--color-text-primary);font-family:var(--font-sans);font-weight:var(--font-weight-ui-normal);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility}button,textarea{font:inherit}button{cursor:pointer}}@layer components{.app-shell{grid-template-columns:var(--shell-left-width) minmax(0, 1fr) var(--shell-right-width);background:var(--color-bg-page);height:100dvh;color:var(--color-text-primary);isolation:isolate;grid-template-rows:minmax(0,1fr) auto;grid-template-areas:"sidebar main right""sidebar footer right";display:grid;overflow:hidden}.panel{background:var(--color-bg-sidebar);min-height:0;overflow:hidden}.left-panel{border-right:1px solid var(--color-border-subtle);grid-area:sidebar}.right-panel{border-left:1px solid var(--color-border-subtle);flex-direction:column;grid-area:right;display:flex}.projects-header,.right-header,.main-header{height:var(--header-height);border-bottom:1px solid var(--color-border-subtle);background:var(--color-bg-sidebar);color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase;justify-content:space-between;align-items:center;padding:0 16px;display:flex}.projects-header h3{font:inherit;letter-spacing:.5px;margin:0}.menu-button{border-radius:var(--radius-control);width:28px;height:28px;color:var(--color-text-muted);background:0 0;border:0;justify-content:center;align-items:center;gap:3px;display:inline-flex}.menu-button span{background:currentColor;border-radius:999px;width:3.6px;height:3.6px}.menu-button:hover,.header-button:hover,.session-row:hover,.activity-row:hover{background:var(--color-hover)}.projects-body{height:calc(100% - var(--header-height));padding:var(--space-panel) 0;overflow:hidden}.project-tree-host{--trees-accent-override:var(--color-accent);--trees-bg-override:var(--color-bg-sidebar);--trees-bg-muted-override:var(--color-hover);--trees-border-color-override:var(--color-border-subtle);--trees-fg-override:var(--color-text-primary);--trees-fg-muted-override:var(--color-text-muted);--trees-selected-bg-override:var(--color-accent-soft);--trees-selected-fg-override:var(--color-accent);--trees-font-family-override:var(--font-sans);--trees-font-size-override:13px;--trees-border-radius-override:var(--radius-row);--trees-item-height:30px;--trees-item-padding-x-override:8px;--trees-item-margin-x-override:8px;--trees-item-row-gap-override:4px;--trees-level-gap-override:var(--tree-indent);--trees-padding-inline-override:0px;--trees-scrollbar-gutter-override:6px;height:100%}.timeline{background:var(--color-bg-surface);flex-direction:column;grid-area:main;min-width:0;min-height:0;display:flex;overflow:hidden}.main-header{background:var(--color-bg-surface)}.runtime-pill{color:var(--color-text-muted);background:var(--color-bg-subtle);border-radius:999px;padding:2px 7px;font-size:12px}.runtime-pill.connected{color:var(--color-accent);background:var(--color-accent-soft)}.timeline-scroll{flex:1;min-height:0;padding:16px 18px 24px;overflow:auto}.session-title{align-items:baseline;gap:8px;margin:0 0 14px 40px;display:flex}.session-title h1{font-size:17px;font-weight:var(--font-weight-ui-strong);letter-spacing:-.01em;margin:0}.session-title span{color:var(--color-text-muted);font-size:12px}.timeline-list{max-width:920px;margin:0 auto}.message-row{grid-template-columns:30px minmax(0,1fr);gap:10px;padding:10px 0;display:grid}.message-row+.message-row{border-top:1px solid var(--color-border-subtle)}.agent-dot{border-radius:var(--radius-control);background:var(--palette-slate-700);width:28px;height:28px;color:var(--color-text-inverse);place-items:center;font-size:12px;font-weight:800;display:grid}.agent-dot.march{background:var(--color-accent)}.message-body{min-width:0;color:var(--color-text-primary);font-size:14px;font-weight:var(--font-weight-content-normal);padding-top:3px;line-height:1.55}.message-body p{margin:0}.message-body time{color:var(--color-text-muted);margin-top:4px;font-size:11px;display:block}.timeline-aux{border:1px solid var(--color-border-subtle);border-radius:var(--radius-control);background:var(--color-bg-subtle);padding:7px 9px}.timeline-aux summary,.aux-title{align-items:center;gap:8px;min-height:20px;display:flex}.timeline-aux summary{cursor:pointer}.timeline-aux span,.timeline-aux em{color:var(--color-text-muted);font-size:12px;font-style:normal}.timeline-aux strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:13px;font-weight:var(--font-weight-ui-medium);overflow:hidden}.timeline-aux p{color:var(--color-text-muted);margin:7px 0 0;font-size:13px}.tool-block span,.diff-inline,.terminal-block pre{font-family:var(--font-mono)}.diff-inline{border-left:2px solid var(--color-border-strong);margin-top:7px;padding-left:10px;font-size:13px}.diff-line{padding:2px 0}.diff-line.add{color:var(--color-success)}.diff-line.remove,.error-block strong{color:var(--color-danger)}.diff-line.keep{color:var(--color-text-muted)}.terminal-block pre{color:var(--color-text-muted);white-space:pre-wrap;margin:7px 0 0;font-size:12px}.memory-recall-block .memory-recall-warning{color:var(--color-text-muted);margin:7px 0 0}.memory-recall-block ul{gap:4px;margin:7px 0 0;padding:0;list-style:none;display:grid}.memory-recall-block li{align-items:center;gap:7px;min-width:0;display:flex}.memory-recall-block li.recalled span{color:var(--color-success)}.memory-recall-block li.skipped span,.memory-recall-block li.skipped strong{color:var(--color-text-muted)}.right-body{flex:1;min-height:0;padding:12px;overflow:auto}.workspace-picker{gap:7px;padding-bottom:10px;display:grid}.workspace-picker label{color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase}.workspace-input-row{grid-template-columns:minmax(0,1fr) auto;gap:4px;display:grid}.workspace-input-row input{border:1px solid var(--color-border-subtle);border-radius:var(--radius-control);background:var(--color-bg-surface);min-width:0;color:var(--color-text-primary);padding:7px 8px}.workspace-input-row button,.fs-entry-row button,.fs-row{border-radius:var(--radius-control);color:var(--color-text-muted);background:0 0;border:0}.workspace-input-row button{background:var(--color-accent-soft);color:var(--color-accent);padding:0 8px}.workspace-input-row button:disabled{opacity:.45}.workspace-path{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--color-text-muted);font-size:12px;overflow:hidden}.fs-entry-row{grid-template-columns:minmax(0,1fr) auto;gap:4px;display:grid}.fs-entry-row button,.fs-row{text-align:left;min-height:28px;padding:0 7px}.fs-entry-row button:first-child{text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-primary);overflow:hidden}.provider-quota{border-top:1px solid var(--color-border-subtle);gap:9px;margin-top:12px;padding-top:12px;display:grid}.provider-quota-header{justify-content:space-between;align-items:center;gap:8px;font-size:12px;display:flex}.provider-quota-header span{color:var(--color-text-primary);font-weight:var(--font-weight-ui-medium)}.provider-quota-header time,.quota-row em{color:var(--color-text-muted);font-style:normal}.quota-row{gap:5px;font-size:12px;display:grid}.quota-row-main{justify-content:space-between;align-items:center;gap:8px;display:flex}.quota-row-main span{color:var(--color-text-primary)}.quota-row-main strong{color:var(--color-accent);font-size:12px}.quota-bar{background:var(--color-bg-surface);height:6px;box-shadow:inset 0 0 0 1px var(--color-border-subtle);border-radius:999px;overflow:hidden}.quota-bar span{border-radius:inherit;background:linear-gradient(90deg, var(--color-accent), color-mix(in srgb, var(--color-accent) 72%, white));height:100%;display:block}.session-row,.activity-row{border-radius:var(--radius-control);width:100%;min-height:34px;color:var(--color-text-primary);text-align:left;background:0 0;border:0;justify-content:space-between;align-items:center;gap:8px;padding:7px 8px;font-size:13px;display:flex}.session-row.active{background:var(--color-accent-soft);color:var(--color-accent);font-weight:var(--font-weight-ui-medium)}.session-row time,.activity-row time{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--color-text-muted);font-size:12px;overflow:hidden}.right-divider{border-top:1px solid var(--color-border-subtle);color:var(--color-text-muted);font-size:11px;font-weight:var(--font-weight-ui-medium);text-transform:uppercase;margin:12px 0 4px;padding-top:12px}.activity-row{color:var(--color-text-muted)}.composer{background:var(--color-bg-surface);grid-area:footer;grid-template-columns:1fr;align-items:end;min-width:0;padding:0 16px 12px;display:grid}.composer-box{width:100%;min-height:var(--composer-min-height);border:1px solid var(--color-border-strong);border-radius:var(--radius-composer);background:var(--color-bg-sidebar);align-items:center;display:flex;position:relative;overflow:visible}.composer-box:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 1px var(--color-accent-soft)}.composer textarea{resize:none;width:100%;max-height:160px;color:var(--color-text-primary);font-weight:var(--font-weight-content-normal);background:0 0;border:0;outline:0;padding:12px 124px 12px 12px}.composer-actions{align-items:center;gap:2px;display:flex;position:absolute;bottom:8px;right:8px}.session-ring,.chip-button,.icon-action,.send-icon,.mobile-toggle{border-radius:var(--radius-control);width:28px;height:28px;color:var(--color-text-muted);background:0 0;border:0;justify-content:center;align-items:center;display:inline-flex}.session-ring:before{content:"";border:2px solid var(--color-accent);border-radius:999px;width:14px;height:14px}.chip-button{width:auto;padding:0 8px;font-size:12px}.icon-action:hover,.chip-button:hover,.mobile-toggle:hover{background:var(--color-hover)}.send-icon{background:var(--color-accent);color:var(--color-text-inverse);font-size:16px;font-weight:700}.send-icon:disabled{opacity:.45}.mobile-toggle,.overlay{display:none}@media (width<=920px){html,body{width:100%;min-height:0;position:fixed;inset:0}.app-shell{height:100dvh;padding-top:env(safe-area-inset-top,0);flex-direction:column;display:flex}.timeline{flex:1;min-height:0}.composer{padding:0 1px max(2px, env(safe-area-inset-bottom));flex:none;grid-template-columns:30px minmax(0,1fr) 30px;gap:1px}.mobile-toggle{align-self:center;height:44px;display:inline-flex}.composer-box{border-radius:10px;min-height:44px}.composer textarea{padding-right:114px}.left-panel,.right-panel{top:env(safe-area-inset-top,0);z-index:30;width:var(--shell-mobile-panel-width);background:var(--color-bg-sidebar);box-shadow:4px 0 24px var(--color-shadow-drawer);transition:transform .22s cubic-bezier(.2,.8,.2,1);position:fixed;bottom:0;transform:translate(-100%)}.left-panel{border-top-right-radius:14px;border-bottom-right-radius:14px;left:0}.right-panel{box-shadow:-4px 0 24px var(--color-shadow-drawer);border-top-left-radius:14px;border-bottom-left-radius:14px;right:0;transform:translate(100%)}.app-shell[data-left-open=true] .left-panel,.app-shell[data-right-open=true] .right-panel{transform:translate(0)}.app-shell[data-left-open=true] .overlay,.app-shell[data-right-open=true] .overlay{z-index:20;background:var(--color-scrim);display:block;position:fixed;inset: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-DrlJis_D.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-BQtl1uQs.css">
7
+ <script type="module" crossorigin src="/assets/index-CBYbNVgs.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-CcbYCcWs.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 { preloadSemanticMemoryRecall } 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,13 +34,14 @@ 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);
40
41
  const lifecycleManifests = loadProjectLifecycleHookManifests(cwd);
41
42
  const contextDumpRoot = resolve(projectMarchDir, "context-dumps", Date.now().toString(36));
42
43
  const ui = createHeadlessWebUi();
44
+ await preloadSemanticMemoryRecall({ memoryStore, ui, logger });
43
45
  const currentProject = basename(cwd);
44
46
  const namespace = loadOrCreateProjectId(projectMarchDir);
45
47
  const runnerOptions = {
@@ -81,8 +83,9 @@ 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 });
88
+ runner.runtimeUiEvents.emit({ type: "recall", hints: input.userRecallHints, report: input.userRecallReport });
86
89
  return await runner.runTurn(input.fullPrompt, input.userMessage, input.runOptions);
87
90
  } finally {
88
91
  turnRunning = false;
@@ -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,29 @@ 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 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";
97
+ const fallback = item.report?.vectorizerStatus === "fallback" ? " · fallback" : "";
98
+ return (
99
+ <div className="timeline-aux memory-recall-block">
100
+ <div className="aux-title"><span>memory</span><strong>recall · {threshold}{fallback}</strong></div>
101
+ {item.report?.warning ? <p className="memory-recall-warning">! {item.report.warning}</p> : null}
102
+ <ul>
103
+ {candidates.map((hint) => (
104
+ <li key={hint.id} className={hint.recalled === false ? "skipped" : "recalled"}>
105
+ <span>{hint.recalled === false ? "×" : "✓"}</span>
106
+ <strong>{formatRecallScore(hint.score)} {hint.name ?? hint.id}</strong>
107
+ </li>
108
+ ))}
109
+ </ul>
110
+ </div>
111
+ );
112
+ }
92
113
 
114
+ function formatRecallScore(score?: number) {
115
+ return typeof score === "number" && Number.isFinite(score) ? score.toFixed(2) : "--";
116
+ }
93
117
 
94
118
  function ErrorBlock({ item }: { item: Extract<TimelineItem, { kind: "error" }> }) {
95
119
  return (
@@ -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 }
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 }
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 }
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?.candidates?.length ?? 0)) {
31
+ next.push({ id, type: "memory_recall", hints: event.hints ?? [], report: event.report ?? null });
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,12 @@
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 .memory-recall-warning { margin: 7px 0 0; color: var(--color-text-muted); }
99
+ .memory-recall-block ul { margin: 7px 0 0; padding: 0; list-style: none; display: grid; gap: 4px; }
100
+ .memory-recall-block li { display: flex; gap: 7px; align-items: center; min-width: 0; }
101
+ .memory-recall-block li.recalled span { color: var(--color-success); }
102
+ .memory-recall-block li.skipped span { color: var(--color-text-muted); }
103
+ .memory-recall-block li.skipped strong { color: var(--color-text-muted); }
98
104
 
99
105
 
100
106
  .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 };
38
40
 
39
41
  case "error":
40
42
  return { id: event.id, kind: "error", message: event.message, detail: event.detail };