merge: mem-agent-0509 into mem-agent-0512#1712
Merged
Merged
Conversation
…ding
Two co-located package-layout tidy-ups:
1. Rename `web/` to `viewer/`
- `git mv web viewer`, `tests/unit/web` to `tests/unit/viewer`,
`tsconfig.web.json` to `tsconfig.viewer.json`.
- Updated build/runtime references: `vite.config.ts` (root + alias
`@web` to `@viewer`), `bridge.cts` (staticRoot), `package.json`
(`files`, scripts `build:viewer` / `viewer:dev`),
`adapters/openclaw/index.ts` (resolveViewerStaticRoot
candidates), `tsconfig.json` / `tsconfig.build.json` exclude
entries, `.gitignore` (`viewer/dist/`), and the install
adapter scripts' log lines.
- Updated test import paths and code/doc comments across
`tests/`, `docs/`, `viewer/README.md`, `viewer/ALGORITHMS.md`,
`ARCHITECTURE.md`, `README.md`, etc.
- No public surface change: package name, `main`, `exports`,
HTTP routes (`/ui/`, `/api/v1/*`) all unchanged. Natural-English
uses of "web" (e.g. "web framework", "open web") preserved.
2. Drop unfinished `site/` scaffolding
- Remove `site/**`, `tsconfig.site.json`, `tests/unit/site/`.
- Strip `siteRoot` and `/site/*` route from `server/middleware/static.ts`
and `server/types.ts`.
- Clean up `.npmignore`, `CHANGELOG.md`, `templates/README.user.md`,
and tsconfig include/exclude entries that referenced `site/`.
Verification:
- `npm run lint` (tsc --noEmit) — pass
- `npm run build` + `npm run build:viewer` — pass; `viewer/dist/` produced
- `npm pack --dry-run` — `viewer/dist/*` shipped
- 110 viewer/install/http/e2e tests pass
- Pre-existing failures in reward / memory / migrator suites are
unrelated (verified by re-running on the un-renamed HEAD).
…scaffolding (#1666) ## Summary Two co-located, low-risk package-layout tidy-ups for `apps/memos-local-plugin`: ### 1. Rename `web/` → `viewer/` The directory was named `web/` for historical reasons but everything in it is the **viewer** SPA (Vite + Preact dashboard). Aligning the name with what it actually is. - `git mv` rename of: - `web/` → `viewer/` - `tests/unit/web/` → `tests/unit/viewer/` - `tsconfig.web.json` → `tsconfig.viewer.json` - Build/runtime references updated: - `vite.config.ts` (`root`, alias `@web` → `@viewer`) - `bridge.cts` (`staticRoot: viewer/dist`) - `package.json` (`files`, scripts `build:viewer` / `viewer:dev`) - `adapters/openclaw/index.ts` (`resolveViewerStaticRoot` candidates) - `tsconfig.json` / `tsconfig.build.json` (`exclude`) - `.gitignore` (`viewer/dist/`) - `adapters/{openclaw,hermes}/install.*.sh` log lines - Test imports + code/doc comments updated across `tests/`, `docs/`, `viewer/README.md`, `viewer/ALGORITHMS.md`, `ARCHITECTURE.md`, `README.md`, etc. - **No public surface change**: package name, `main`, `exports`, HTTP routes (`/ui/`, `/api/v1/*`) all unchanged. - Natural-English uses of "web" (e.g. \"web framework\", \"open web\") preserved — only path/identifier references were touched. ### 2. Drop unfinished `site/` scaffolding The `site/` directory was a half-built product website that's no longer used; this removes the leftover scaffolding so it doesn't confuse readers or get accidentally bundled. - Remove `site/**`, `tsconfig.site.json`, `tests/unit/site/`. - Strip `siteRoot` and `/site/*` route from `server/middleware/static.ts` + `server/types.ts`. - Clean up `.npmignore`, `CHANGELOG.md`, `templates/README.user.md`, and tsconfig include/exclude entries that referenced `site/`. ## Test plan - [x] `npm run lint` (tsc --noEmit) — pass - [x] `npm run build` + `npm run build:viewer` — pass; `viewer/dist/` produced - [x] `npm pack --dry-run` — `viewer/dist/*` shipped in the tarball - [x] 110 viewer / install / http / e2e unit tests pass - [x] Verified pre-existing failures in reward / memory / migrator suites are NOT caused by this PR (re-ran on `HEAD` before the rename — same 8 failures). - [ ] Manual smoke on the daemon: `npm run bridge:daemon` and confirm the viewer is served from the renamed path
Add embedding maintenance APIs and viewer controls so imported memories and model changes can repair or rebuild vectors against the active provider. Treat remote embedding dimensions as provider-derived state, not user config, and aggregate explicit feedback corrections consistently.
## Summary - Add embedding maintenance endpoints and viewer controls to repair missing/mismatched vectors or rebuild all vectors after imports/model changes. - Infer remote embedding dimensions from provider responses instead of exposing dimensions as user config, preventing bge-m3 vectors from being truncated to 384. - Aggregate multiple explicit feedback corrections in heuristic reward fallback so later negative feedback can lower trace value and priority. ## Test plan - npm run lint - npm test -- tests/unit/config/load.test.ts tests/unit/config/writer.test.ts tests/unit/embedding/normalize.test.ts - npm test -- tests/unit/reward/human-scorer.test.ts tests/unit/pipeline/memory-core.test.ts -t "heuristic|submitFeedback aggregates|repairs missing" - npm test -- tests/unit/pipeline/memory-core.test.ts tests/unit/reward/human-scorer.test.ts tests/unit/server/http.test.ts tests/unit/bridge/methods.test.ts - npm run build:viewer - npm pack --json
…on and interactive UI - Refactor `install.ps1` to auto-detect OpenClaw/Hermes and add an interactive menu. - Use `npm pack` and tarball extraction for robust package deployment. - Automate configuration patching for `openclaw.json` and `config.yaml`. - Update `postinstall.cjs` banner to drop the hardcoded `-Agent` argument.
## Description This PR significantly improves the Windows PowerShell installation experience for the `memos-local-plugin`. **Key Changes:** 1. **Auto-detection & Interactive UI**: Introduced an interactive menu in `install.ps1` that automatically detects existing OpenClaw (`~/.openclaw`) and Hermes (`~/.hermes`) environments. 2. **Robust Deployment**: Replaced simple file copying with `npm pack` and tarball extraction to ensure a cleaner and more reliable package deployment. 3. **Automated Configuration**: The script now automatically patches the target agent's configuration files (`openclaw.json` for OpenClaw and `config.yaml` for Hermes), reducing manual setup steps. 4. **Postinstall Update**: Removed the hardcoded `-Agent` argument from the `postinstall.cjs` banner, as the PowerShell script now handles agent selection automatically. ## Type of change Please delete options that are not relevant. - [x] New feature (non-breaking change which adds functionality) - [x] Refactor (does not change functionality, e.g. code style improvements, linting) ## How Has This Been Tested? Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration - [x] Test Script Or Test Steps (please provide) **Test Steps:** 1. On a Windows environment, run `powershell -ExecutionPolicy Bypass -File install.ps1`. 2. Verify that the interactive menu correctly displays the auto-detected agent environments. 3. Select an installation option (e.g., OpenClaw, Hermes, or Both). 4. Confirm that the tarball is generated and extracted successfully into the target directory. 5. Verify that the respective configuration files (`openclaw.json` or `config.yaml`) are correctly patched with the plugin details. 6. Verify that the Memory Viewer starts properly. ## Checklist - [x] I have performed a self-review of my own code | 我已自行检查了自己的代码 - [x] I have commented my code in hard-to-understand areas | 我已在难以理解的地方对代码进行了注释 - [ ] I have added tests that prove my fix is effective or that my feature works | 我已添加测试以证明我的修复有效或功能正常 - [ ] I have created related documentation issue/PR in `https://github.com/MemTensor/MemOS-Docs` (if applicable) | 我已在 `https://github.com/MemTensor/MemOS-Docs` 中创建了相关的文档 issue/PR(如果适用) - [ ] I have linked the issue to this PR (if applicable) | 我已将 issue 链接到此 PR(如果适用) - [ ] I have mentioned the person who will review this PR | 我已提及将审查此 PR 的人 (@请在此处@相关人员) ## Reviewer Checklist - [ ] closes #xxxx (Replace xxxx with the GitHub issue number) - [ ] Made sure Checks passed - [ ] Tests have been provided
Keep OpenClaw tool observations available for memory capture and strip retrieval metrics from episode prompt injection so recalled context remains answer-focused.
CI generates this file from secrets via `scripts/generate-telemetry-credentials.cjs` immediately before `npm publish` (see `.github/workflows/hermes-plugin-publish.yml`). Local copies are only useful for development against a personal ARMS workspace and must never be committed. The repo-root `.gitignore` has a blanket `!apps/**/*.json` allow-rule that overrides any per-package ignore for .json files; the closer `apps/memos-local-plugin/.gitignore` wins because git's "closest .gitignore wins" rule applies regardless of polarity. Adding the explicit entry here is therefore sufficient. Co-authored-by: Cursor <cursoragent@cursor.com>
The original v2 telemetry rollout (commit 3600f80) only wired the Hermes-side `bridge.cts`. Three knock-on effects made the `memos_local_hermes_v2` ARMS dashboards drift away from reality: 1. **OpenClaw adapter never emitted any events.** The whole in-process plugin path bypassed the `Telemetry` instance, so `agent_name=openclaw` was silently zero across `plugin_started`, `memory_search`, `memory_ingested`, `feedback_submitted`, and `viewer_opened`. 2. **`daily_active` counted process launches, not days.** The in-memory `dailyPingSent` boolean reset on every `bridge.cts` subprocess spawn (Hermes spawns one per `chat`), so DAU = startup count. 3. **`viewer_opened` only fired on the first `GET /api/v1/overview`** *per process*, then suppressed forever by a closure flag. Background pollers and CLI calls counted as "viewer opens"; restarts re-counted the same operator. 4. **`plugin_error` was declared but never invoked.** The crash visibility the dashboard implied did not exist. Changes ------- - `adapters/openclaw/index.ts`: Construct `Telemetry`, call `bindTelemetry`, emit `trackPluginStarted("openclaw")`, and pass the instance into `startHttpServer` so OpenClaw matches the Hermes surface 1:1. Plugin-root resolution shared with the existing viewer-static-root helper. - `core/telemetry/sender.ts`: Persist the daily-ping date to `<stateDir>/memos-local/.last-daily-ping`. Read on every start; only emit when today's date differs from the file. Read failures degrade gracefully to "first time today" (over-report by ≤1, never under-report). Removed the obsolete in-memory `dailyPingSent` / `dailyPingDate` fields. - `server/routes/telemetry.ts` (new) + `viewer/src/components/App.tsx`: Replace the GET-piggybacking `viewer_opened` with a dedicated `POST /api/v1/telemetry/viewer-opened` invoked once from the SPA's `<App />` mount effect. Endpoint is fire-and-forget on the client and always returns `{ ok: true }`. `server/routes/overview.ts` no longer fires the event. - `core/pipeline/memory-core.ts`: Surface `MemosError.code` (or `unknown`) as the `plugin_error.error_type` when `onTurnStart` / `searchMemory` reject. Never the message — those can contain user/workspace text. - `bridge.cts`: Register `process.on("uncaughtException" | "unhandledRejection")` immediately after binding telemetry. `uncaughtException` exits 1 (preserves supervisor semantics); `unhandledRejection` continues (Node 20+'s "exit by default" is too aggressive for a long-running bridge — log + ARMS event + keep going). New `classifyErrorCode()` reuses Node's `code` (`ENOENT`, `EADDRINUSE`, …), then constructor name, then `unknown`. Only registered on the dedicated bridge process; the OpenClaw adapter must not steal its host's global error hooks. Tests ----- - `tests/unit/telemetry/sender.test.ts` — three new cases covering: first launch emits `daily_active`; second launch same day / same `stateDir` does NOT re-emit; pre-seeded `.last-daily-ping` with yesterday's date triggers a fresh ping and overwrites the file with today's ISO date. - `tests/unit/server/http.test.ts` — POST endpoint invokes `trackViewerOpened`; endpoint stays 200 when telemetry is unbound; GET `/api/v1/overview` no longer triggers the event (regressed deliberately). Verified locally: 945 unit tests pass (+6 vs. baseline). 7 unrelated pre-existing failures in `tests/unit/{reward,memory,storage}/...` are unchanged on this branch and on `upstream/mem-agent-0509` head. Co-authored-by: Cursor <cursoragent@cursor.com>
## Why
ARMS dashboards for the v2 plugin (event group `memos_local_hermes_v2`)
have been reporting suspiciously low volumes since the v2 rewrite.
Tracing through the code surfaced four independent issues that all
reduce or distort metrics:
1. **OpenClaw adapter never emitted any events.**
`adapters/openclaw/index.ts` bootstraps `MemoryCore` and starts the
viewer, but never constructs `Telemetry`. Only `bridge.cts` (the Hermes
path) wires it. So every OpenClaw user — `agent_name=openclaw` — has
been silently invisible across `plugin_started`, `memory_search`,
`memory_ingested`, `feedback_submitted`, `viewer_opened`.
2. **`daily_active` counted process launches, not days.** The dedup flag
(`dailyPingSent`) lived in memory; Hermes spawns one `bridge.cts`
subprocess per `hermes chat`, so DAU ≈ `plugin_started`.
3. **`viewer_opened` was wired to the first GET `/api/v1/overview` per
process.** Background pollers and CLI tooling triggered it; bridge
restarts re-counted the same operator; once-per-process meant active
users showed up once, period.
4. **`plugin_error` was declared but never invoked.** No call sites
existed in core or bridge.
## What
| # | Area | Change |
|---|---|---|
| 1 | `adapters/openclaw/index.ts` | Construct `Telemetry`,
`bindTelemetry`, emit `trackPluginStarted("openclaw")`, pass into
`startHttpServer`. Mirrors `bridge.cts` so OpenClaw and Hermes report
identical surfaces. |
| 2 | `core/telemetry/sender.ts` | `daily_active` dedup persisted to
`<stateDir>/memos-local/.last-daily-ping`. Read failure → "first time
today" (over-report by ≤1, never under-report). Removed the obsolete
`dailyPingSent`/`dailyPingDate` in-memory fields. |
| 3 | `server/routes/telemetry.ts` (new) +
`viewer/src/components/App.tsx` | `viewer_opened` now triggered by `POST
/api/v1/telemetry/viewer-opened` from the SPA's mount effect. Endpoint
is fire-and-forget, always 200. `server/routes/overview.ts` no longer
fires the event. |
| 4 | `core/pipeline/memory-core.ts` + `bridge.cts` | `trackError`
invoked from `onTurnStart` / `searchMemory` catches and from
process-level `uncaughtException` / `unhandledRejection` handlers. New
`classifyErrorCode()` keeps `error_type` to `MemosError.code` / Node
`code` / constructor name — never the message. |
| 5 | `apps/memos-local-plugin/.gitignore` | Defensive entry for
`telemetry.credentials.json` (CI-generated; never to be committed).
Counters the repo-root `!apps/**/*.json` allow-rule. Split out into its
own commit for clean review. |
## Tests
- `tests/unit/telemetry/sender.test.ts` (+3 cases): first launch emits
`daily_active`; second launch same-day same-`stateDir` does NOT re-emit;
pre-seeded `.last-daily-ping=2024-01-01` triggers a fresh ping and
overwrites with today's ISO date.
- `tests/unit/server/http.test.ts` (+3 cases): POST endpoint invokes
`trackViewerOpened`; endpoint returns 200 when telemetry is unbound; GET
`/api/v1/overview` no longer triggers the event.
```
Test Files 113 passed | 5 failed (pre-existing on mem-agent-0509)
Tests 945 passed | 7 failed | 1 skipped (953)
```
The 7 failures are unchanged on baseline `upstream/mem-agent-0509`
(verified by stash + re-run):
`tests/unit/{reward/reward.integration,reward/subscriber,storage/migrator,memory/l2/gain,memory/l3/cluster}.test.ts`
— none touch telemetry.
`npm run lint` (i.e. `tsc --noEmit`) passes clean.
## Risk / compatibility
- **Schema:** no changes. Same event group, same `view.name`, same
property keys. Existing ARMS dashboards keep working — they should just
see more rows starting next release.
- **Privacy:** no new fields carry user content. `error_type` is a
stable code (`ENOENT`, `MemosError.code`, `TypeError`, …), never the raw
message.
- **Behaviour:** `viewer_opened` count will jump because the event now
actually fires per browser tab open instead of once per server-process
lifetime. Expected — this is what the metric was always supposed to
mean.
- **Process semantics:** `uncaughtException` still calls
`process.exit(1)` (preserves supervisor behaviour); `unhandledRejection`
deliberately does not exit (Node 20+'s default-exit is too aggressive
for a long-running bridge — log + ARMS event + continue).
## Commits in this PR
1. `chore(memos-local-plugin): gitignore telemetry.credentials.json` —
single-file, zero-risk.
2. `fix(memos-local-plugin): close v2 ARMS telemetry coverage gaps` —
main change.
## Test plan
- [ ] Manual: `OPENCLAW_AGENT=openclaw memos-local` (or whichever
invocation reproduces an OpenClaw boot), then check ARMS for
`agent_name=openclaw` events on `memos_local_hermes_v2`.
- [ ] Manual: spawn two Hermes `chat` sessions on the same day → confirm
only one `daily_active` reaches ARMS.
- [ ] Manual: open the viewer in two browser tabs → expect two
`viewer_opened` events.
- [ ] Manual: kill the bridge with a forced `throw` → expect a
`plugin_error` with `error_source=uncaught_exception`.
## Summary - Launch the TypeScript bridge through tsx's JS CLI entrypoint so Windows does not run the POSIX shim through node. - Persist a usable Node executable path during Windows installation and decode bridge subprocess output as UTF-8 with replacement. ## Test plan - Not run (not requested).
Automated PR from mem-agent-0509-niu to mem-agent-0509.
Automated PR from mem-agent-0509-niu to mem-agent-0509.
Automated PR from mem-agent-0509-niu to mem-agent-0509.
## Summary - Preserve OpenClaw tool-call observations when `agent_end` transcripts omit tool blocks, so memory capture still records tool activity. - Enable OpenClaw conversation access during install so turns can be captured after recall. - Remove retrieval scores such as `best V` and `goal-sim` from episode prompt injection. ## Test plan - `npm test -- tests/unit/adapters/openclaw-bridge.test.ts tests/unit/install/install-sh.test.ts tests/unit/retrieval/tier2.test.ts tests/unit/retrieval/injector.test.ts` - IDE diagnostics: no linter errors in touched TypeScript test/source files.
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merge
mem-agent-0509line of work into the new integration branchmem-agent-0512.This is part of the 0512 integration: the 0512 branch is freshly cut from
main, and we are landing the 0509 + 0509-magent work plus the latest bug fix on top of it so we can release2.0.0-beta.13.What's included from mem-agent-0509
Notable items beyond
main:Test plan
Made with Cursor