claude-mem-lite 6.23.1 → 6.23.3

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.
@@ -9,7 +9,7 @@
9
9
  "plugins": [
10
10
  {
11
11
  "name": "claude-mem-lite",
12
- "version": "6.23.1",
12
+ "version": "6.23.3",
13
13
  "source": "./",
14
14
  "homepage": "https://github.com/sdsrss/claude-mem-lite",
15
15
  "description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. FTS5 BM25 keyword search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark)."
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "6.23.1",
3
+ "version": "6.23.3",
4
4
  "description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. FTS5 BM25 keyword search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
5
5
  "author": {
6
6
  "name": "sdsrss"
package/README.md CHANGED
@@ -189,7 +189,7 @@ cd claude-mem-lite
189
189
  node install.mjs install
190
190
  ```
191
191
 
192
- Source files stay in the cloned repo. Update via `git pull && node install.mjs install`.
192
+ `install` copies the source files to `~/.claude-mem-lite/`, as the npx method does. Update with `node install.mjs update`, which installs the latest signed release. `git pull && node install.mjs install` installs the checked-out branch instead: it can be ahead of the latest release, and no signature is checked.
193
193
 
194
194
  ### What happens during installation
195
195
 
@@ -812,7 +812,8 @@ npx claude-mem-lite doctor # Diagnose issues
812
812
  > around a dozen static imports before its first line runs — one missing file and it exits
813
813
  > with a Node stack instead of telling you which file. `cli.mjs` has no static local imports
814
814
  > and catches that, naming the file and a repair command. Everything else in the list is
815
- > unaffected either way.
815
+ > unaffected either way, except `update`: through `cli.mjs` (and the `claude-mem-lite`
816
+ > command) `update <id>` edits a memory, and the updater is `self-update`.
816
817
 
817
818
  Notes:
818
819
  - Plugin mode only reports available updates; it does not self-update plugin files.
@@ -822,7 +823,8 @@ Notes:
822
823
  /plugin install claude-mem-lite@sdsrss
823
824
  ```
824
825
  (The first command refreshes the local marketplace clone; the second reinstalls from it. Without the first command, `/plugin install` reuses the stale local clone and you stay on whichever version you originally pulled.)
825
- - Direct install / npx mode keeps auto-update enabled and uses staged replacement with rollback on install failure.
826
+ - Direct install / npx mode checks GitHub Releases once a day (every 6 hours while GitHub is rate-limiting), from a session start, and shows a notice about a newer version at the next session start; the check does not install it. `npx claude-mem-lite self-update` (from a git clone, `node install.mjs update`) installs it, with staged replacement and rollback on install failure. Two things install without a command: when a hook finds a module or dependency missing, a session start runs `repair` (at most once per 6 hours), which installs the latest release if its signature verifies; and when the plugin is installed too, a session start copies a newer plugin version into the direct install (that copy is not signature-checked).
827
+ - `CLAUDE_MEM_SKIP_UPDATE` turns off the check, the notice, and `self-update` / `install.mjs update` as well, so unset it before updating. It stops neither of the two installs above.
826
828
  - If you disabled the plugin but still have old mem hooks in `~/.claude/settings.json`, run `node install.mjs cleanup-hooks`.
827
829
 
828
830
  #### Trust model per install path
@@ -831,7 +833,7 @@ The three install paths do **not** carry the same supply-chain guarantees — pi
831
833
 
832
834
  | Path | Update mechanism | Ed25519 release-signature verification |
833
835
  |------|------------------|----------------------------------------|
834
- | npm / npx / git-clone direct install | auto-update from GitHub Releases | **Yes** — every runtime file (140 entries incl. hook scripts, MCP launcher, plugin declaration files) is hash-pinned in a signed manifest; verification is fail-closed |
836
+ | npm / npx / git-clone direct install | daily check announces; `self-update` installs from GitHub Releases, and `repair` reinstalls the latest release when a hook finds a module or dependency missing. With the plugin also installed, a session start copies a newer plugin version in without a signature check | **Yes** — every runtime file (hook scripts, MCP launcher and plugin declaration files included) is hash-pinned in a signed manifest; verification is fail-closed |
835
837
  | `/plugin install` (marketplace) | manual `/plugin marketplace update` + reinstall | **No** — Claude Code installs from a git clone of the marketplace repo; the plugin's own signature chain is not consulted on this path. You are trusting GitHub + the repo's branch protection, not the release signing key |
836
838
 
837
839
  **Rollback recipe (plugin path).** If an update misbehaves, pin the marketplace clone to the previous release tag and reinstall from it:
@@ -866,7 +868,7 @@ Shows MCP registration, hook configuration, plugin disabled state, and database
866
868
 
867
869
  ### Recovery (stuck install / hook errors)
868
870
 
869
- If you see `ERR_MODULE_NOT_FOUND` on PreToolUse:Read/Edit hooks, or `claude-mem-lite` commands crash with import errors, you're likely hit by a partial auto-update — the updater copied new scripts but missed a sibling `lib/*` file, breaking the hook chain (and the next auto-update that would have healed it).
871
+ If you see `ERR_MODULE_NOT_FOUND` on PreToolUse:Read/Edit hooks, or `claude-mem-lite` commands crash with import errors, you're likely hit by a partial update — an updater copied new scripts but missed a sibling `lib/*` file, breaking the hook chain.
870
872
 
871
873
  **v2.84.0+** ships a `repair` subcommand that re-syncs from the latest GitHub release:
872
874
 
@@ -1089,7 +1091,7 @@ claude-mem-lite.
1089
1091
  | `CLAUDE_MEM_DIR` | Custom data directory. All databases, runtime files, and managed resources are stored here. | `~/.claude-mem-lite/` |
1090
1092
  | `CLAUDE_MEM_MODEL` | LLM model for background calls (episode extraction, session summaries). Accepts `haiku` or `sonnet`. | `haiku` |
1091
1093
  | `ANTHROPIC_API_KEY` | Anthropic API key. When set, all background LLM calls go directly to the Anthropic Messages API (with prompt caching) - or to the `ANTHROPIC_BASE_URL` gateway when that is set. Highest priority. | _(unset → CLI)_ |
1092
- | `ANTHROPIC_BASE_URL` | Base URL for the direct Messages API when an Anthropic-compatible gateway serves the models (Azure AI Foundry, LiteLLM, Bedrock/Vertex proxies). No `/v1` suffix — the endpoint path is appended. The `claude -p` fallback reads the same variable, so one value covers both transports. Plain `http://` is accepted only for a loopback host; anything else would send the API key unencrypted. A value that is set but unusable skips the direct API leg, so background calls fall back to the `claude -p` CLI, and doctor warns. | `https://api.anthropic.com` |
1094
+ | `ANTHROPIC_BASE_URL` | Base URL for the direct Messages API when an Anthropic-compatible gateway serves the models (Azure AI Foundry, LiteLLM, Bedrock/Vertex proxies). No `/v1` suffix — the endpoint path is appended. The `claude -p` fallback reads the same variable, so one value covers both transports. Plain `http://` is accepted only for a loopback host; anything else would send the API key unencrypted. That request always goes straight to the loopback host, even when `NODE_USE_ENV_PROXY=1` sends other requests through `HTTP_PROXY`. A value that is set but unusable skips the direct API leg, so background calls fall back to the `claude -p` CLI, and doctor warns. | `https://api.anthropic.com` |
1093
1095
  | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Model ID or gateway deployment name for the `haiku` tier, honored on the direct API **only when `ANTHROPIC_BASE_URL` is set**. Without a base URL it stays CLI-only, so the Bedrock/Vertex form of this alias is never sent to `api.anthropic.com`. Use it when the gateway routes on deployment names rather than Anthropic model IDs (Azure Foundry deployments). The `claude -p` fallback resolves its `--model haiku` alias through it too. | built-in `claude-haiku-4-5-…` |
1094
1096
  | `ANTHROPIC_DEFAULT_SONNET_MODEL` | Same as above for the `sonnet` tier. | built-in `claude-sonnet-4-5-…` |
1095
1097
  | `OPENROUTER_API_KEY` | OpenRouter API key (OpenAI-compatible). Used for background LLM calls when `ANTHROPIC_API_KEY` is **not** set. If neither key is set, calls fall back to the `claude -p` CLI. | _(unset)_ |
@@ -1192,7 +1194,7 @@ what is already stored — only whether new work runs.
1192
1194
  | `CLAUDE_MEM_SKIP_OPTIMIZE` | Skip the LLM optimization pass (re-enrich, normalize, cluster-merge). | _(runs)_ |
1193
1195
  | `CLAUDE_MEM_SKIP_AUTO_DEDUP_FUZZY` | Skip the MinHash near-duplicate pass, keeping exact dedup. | _(runs)_ |
1194
1196
  | `CLAUDE_MEM_SKIP_MARKER_GC` | Skip the runtime-marker sweep. **Must be exactly `1`** — unlike the other `CLAUDE_MEM_SKIP_*` flags, which accept any truthy value, this one compares against the string `1`. That is deliberate: a truthy check makes `=0` mean "skip", which is the opposite of what anyone typing it intends. | _(runs)_ |
1195
- | `CLAUDE_MEM_SKIP_UPDATE` | Skip the 24h auto-update check against GitHub Releases. | _(runs)_ |
1197
+ | `CLAUDE_MEM_SKIP_UPDATE` | Skip the 24h update check against GitHub Releases, its session-start notice, and `self-update` / `install.mjs update` (unset it to update). A `repair` triggered by a missing module or dependency still runs. | _(runs)_ |
1196
1198
  | `CLAUDE_MEM_SKIP_SIG_VERIFY` | Skip Ed25519 signature verification of a downloaded update. **Escape hatch — leaves updates unauthenticated.** | _(verifies)_ |
1197
1199
  | `CLAUDE_MEM_NO_LESSON_RETRY` | `1` disables the one-shot retry that re-asks for a missing `lesson_learned`. | _(retries)_ |
1198
1200
  | `CLAUDE_MEM_FLUSH_TIMEOUT` | Seconds the Stop hook waits for pending episode flushes. | `15` |
package/README.zh-CN.md CHANGED
@@ -147,7 +147,7 @@ cd claude-mem-lite
147
147
  node install.mjs install
148
148
  ```
149
149
 
150
- 源文件保留在克隆的仓库中。通过 `git pull && node install.mjs install` 更新。
150
+ `install` 会把源文件复制到 `~/.claude-mem-lite/`,与 npx 方式相同。用 `node install.mjs update` 更新,它安装最新的已签名发布。`git pull && node install.mjs install` 安装的则是当前检出的分支:可能领先于最新发布,也不校验签名。
151
151
 
152
152
  ### 安装过程
153
153
 
@@ -661,9 +661,11 @@ npx claude-mem-lite doctor # 诊断问题
661
661
  已经坏掉时才会用到的命令,而 `install.mjs` 在执行第一行代码之前要解析十几个静态
662
662
  import——少一个文件就直接吐一段 Node 栈,而不是告诉你少了哪个文件。`cli.mjs` 没有
663
663
  任何本地静态 import,会捕获这种失败并说出缺失的文件和修复命令。列表中其余命令两种
664
- 写法都一样。
664
+ 写法都一样,唯独 `update`:经 `cli.mjs`(以及 `claude-mem-lite` 命令)调用时,
665
+ `update <id>` 是编辑一条记忆,更新器要写 `self-update`。
665
666
  - 插件模式只提示可用更新,不会自更新插件文件。
666
- - direct install / npx 模式保留自动更新,并使用 staged replacement;若依赖安装失败会回滚。
667
+ - direct install / npx 模式每天检查一次 GitHub Releases(GitHub 限流期间每 6 小时一次,都在会话开始时触发),发现新版本会在下一次会话开始时提示;检查本身不安装。运行 `npx claude-mem-lite self-update`(git clone 安装用 `node install.mjs update`)才安装,使用 staged replacement,若依赖安装失败会回滚。有两种情况不经命令就会安装:hook 发现缺少模块或依赖时,会在会话开始时运行 `repair`(每 6 小时最多一次),签名校验通过才安装最新发布;同时装了插件时,会话开始会把更新的插件版本拷进 direct install(这次拷贝不做签名校验)。
668
+ - `CLAUDE_MEM_SKIP_UPDATE` 会同时关掉检查、提示以及 `self-update` / `install.mjs update`,更新前要先取消它;上面两种自动安装它都不阻止。
667
669
  - 如果你禁用了插件,但 `~/.claude/settings.json` 里还有旧的 mem hooks,可运行 `node install.mjs cleanup-hooks`。
668
670
 
669
671
  ### doctor
@@ -680,7 +682,7 @@ npx claude-mem-lite doctor # 诊断问题
680
682
 
681
683
  ### 故障恢复(安装卡死 / hook 报错)
682
684
 
683
- 如果你看到 PreToolUse:Read/Edit hook 报 `ERR_MODULE_NOT_FOUND`,或者 `claude-mem-lite` 命令本身因为 import 错误崩溃,多半是被部分自动更新坑了——更新器复制了新脚本但漏了配套的 `lib/*` 文件,hook 链就此断掉(连下一次本可自愈的自动更新也跑不了)。
685
+ 如果你看到 PreToolUse:Read/Edit hook 报 `ERR_MODULE_NOT_FOUND`,或者 `claude-mem-lite` 命令本身因为 import 错误崩溃,多半是被一次不完整的更新坑了——更新器复制了新脚本但漏了配套的 `lib/*` 文件,hook 链就此断掉。
684
686
 
685
687
  **v2.84.0+** 提供 `repair` 子命令,从 GitHub 最新 release 重新同步:
686
688
 
@@ -831,7 +833,7 @@ npm run benchmark:gate # CI 门控:指标回退超过 5% 容差时失败
831
833
  | `CLAUDE_MEM_DIR` | 自定义数据目录。所有数据库与运行时文件均存储在此。 | `~/.claude-mem-lite/` |
832
834
  | `CLAUDE_MEM_MODEL` | 后台 LLM 调用模型(Episode 提取、会话总结、调度)。可选 `haiku` 或 `sonnet`。 | `haiku` |
833
835
  | `ANTHROPIC_API_KEY` | Anthropic API key。设置后所有后台 LLM 调用直连 Anthropic Messages API(带 prompt caching);设了 `ANTHROPIC_BASE_URL` 时改发往那个网关。优先级最高。 | _(未设 → CLI)_ |
834
- | `ANTHROPIC_BASE_URL` | 由兼容 Anthropic 的网关(Azure AI Foundry、LiteLLM、Bedrock/Vertex 代理)提供模型时,直连 Messages API 使用的基础 URL。不要带 `/v1` 后缀,端点路径会自动拼上。`claude -p` 兜底读取同一个变量,所以一个值同时作用于两条路径。明文 `http://` 只接受回环主机,否则 API key 会以明文发送。设了但不可用的值会跳过直连这一路,后台调用改走 `claude -p`,doctor 会提示。 | `https://api.anthropic.com` |
836
+ | `ANTHROPIC_BASE_URL` | 由兼容 Anthropic 的网关(Azure AI Foundry、LiteLLM、Bedrock/Vertex 代理)提供模型时,直连 Messages API 使用的基础 URL。不要带 `/v1` 后缀,端点路径会自动拼上。`claude -p` 兜底读取同一个变量,所以一个值同时作用于两条路径。明文 `http://` 只接受回环主机,否则 API key 会以明文发送。这个请求总是直连回环主机,即使 `NODE_USE_ENV_PROXY=1` 让其他请求走 `HTTP_PROXY`。设了但不可用的值会跳过直连这一路,后台调用改走 `claude -p`,doctor 会提示。 | `https://api.anthropic.com` |
835
837
  | `ANTHROPIC_DEFAULT_HAIKU_MODEL` | `haiku` 档的模型 ID 或网关部署名,**仅在设了 `ANTHROPIC_BASE_URL` 时**用于直连 API。没有基础 URL 时只给 CLI 用,所以这个别名的 Bedrock/Vertex 写法不会被发往 `api.anthropic.com`。网关按部署名而不是 Anthropic 模型 ID 路由时(Azure Foundry 部署)使用。`claude -p` 兜底的 `--model haiku` 别名也经由它解析。 | 内置 `claude-haiku-4-5-…` |
836
838
  | `ANTHROPIC_DEFAULT_SONNET_MODEL` | 同上,用于 `sonnet` 档。 | 内置 `claude-sonnet-4-5-…` |
837
839
  | `OPENROUTER_API_KEY` | OpenRouter API key(OpenAI 兼容)。当**未设** `ANTHROPIC_API_KEY` 时用于后台 LLM 调用;两者都未设则回退到 `claude -p` CLI。 | _(未设)_ |
package/haiku-client.mjs CHANGED
@@ -20,7 +20,7 @@ import { randomUUID } from 'crypto';
20
20
  import { debugLog, debugCatch, parseJsonFromLLM } from './utils.mjs';
21
21
  import { DB_DIR } from './schema.mjs';
22
22
  import { resolveRuntimeDir } from './lib/resolve-data-dir.mjs';
23
- import { httpConnectProxyFor, postViaConnectProxy } from './lib/proxy-fetch.mjs';
23
+ import { httpConnectProxyFor, postViaConnectProxy, postDirectHttp } from './lib/proxy-fetch.mjs';
24
24
  import { resolveAnthropicBaseUrl } from './lib/anthropic-base-url.mjs';
25
25
 
26
26
  /**
@@ -553,8 +553,20 @@ async function callModelAPI(prompt, model, { timeout, maxTokens, temperature = D
553
553
  'x-api-key': apiKey,
554
554
  'anthropic-version': '2023-06-01',
555
555
  };
556
+ // Plain http is loopback-only (resolveAnthropicBaseUrl), and loopback must stay on this
557
+ // machine: native fetch would hand it, x-api-key in cleartext, to HTTP_PROXY under
558
+ // NODE_USE_ENV_PROXY=1. (D#250) Parsed, not a prefix test: the resolver accepts the scheme
559
+ // in any case (`HTTP://127.0.0.1`) and returns the raw text.
560
+ const plainHttp = new URL(apiUrl).protocol === 'http:';
556
561
  const send = (payload) => {
557
562
  const json = JSON.stringify(payload);
563
+ if (plainHttp) {
564
+ return postDirectHttp(apiUrl, {
565
+ headers: apiHeaders,
566
+ body: json,
567
+ timeout: Math.max(1, deadline - Date.now()),
568
+ });
569
+ }
558
570
  const apiProxy = httpConnectProxyFor(apiUrl);
559
571
  return apiProxy
560
572
  ? postViaConnectProxy(apiProxy, apiUrl, {
package/hook-update.mjs CHANGED
@@ -1,6 +1,7 @@
1
- // claude-mem-lite: Auto-update via GitHub Releases
2
- // Checks for new versions on SessionStart, downloads and installs automatically.
3
- // Skips in dev mode (symlinked installs). Silent on network failure.
1
+ // claude-mem-lite: update check and installer via GitHub Releases
2
+ // The SessionStart check (hook.mjs, allowInstall:false) only records and announces a newer
3
+ // release; `self-update` and `repair` install one, signature-verified. Skips a dev install
4
+ // (a git checkout or symlinks) and under CLAUDE_MEM_SKIP_UPDATE. Silent on network failure.
4
5
 
5
6
  import { isOurMcpRegistration } from './lib/mcp-ownership.mjs';
6
7
  import { execSync, execFileSync } from 'node:child_process';
@@ -67,12 +68,17 @@ const NPM_INSTALL_CMD = 'npm install --omit=dev --no-audit --no-fund';
67
68
 
68
69
  // ── Main Entry ─────────────────────────────────────────────
69
70
  export async function checkForUpdate(options = {}) {
71
+ // A failed lookup returns null by default, which a background caller wants (silent on
72
+ // network failure). `self-update` printed that null as "Already up to date", so a caller
73
+ // that reports to a person asks for the failure instead. (D#251)
74
+ const failed = (rateLimited) =>
75
+ options.reportFailure ? { updateAvailable: false, updated: false, checkFailed: true, rateLimited } : null;
70
76
  try {
71
77
  const pluginMode = isPluginMode();
72
78
  const force = Boolean(options.force);
73
79
  const allowInstall = options.allowInstall ?? !pluginMode;
74
80
 
75
- if (isDevMode() || process.env.CLAUDE_MEM_SKIP_UPDATE) return null;
81
+ if (updateCheckDisabledReason()) return null;
76
82
 
77
83
  const state = readState();
78
84
  if (!force && !shouldCheck(state)) {
@@ -99,7 +105,7 @@ export async function checkForUpdate(options = {}) {
99
105
  // rate-limit mechanism is dead. Re-reading preserves the freshly-written flag.
100
106
  const fresh = readState();
101
107
  saveState({ ...fresh, lastCheck: new Date().toISOString() });
102
- return null;
108
+ return failed(lastLookupRateLimited);
103
109
  }
104
110
 
105
111
  const currentVersion = getCurrentVersion();
@@ -147,7 +153,7 @@ export async function checkForUpdate(options = {}) {
147
153
  const s = readState();
148
154
  saveState({ ...s, lastCheck: new Date().toISOString(), lastError: err.message });
149
155
  } catch {}
150
- return null;
156
+ return failed(false);
151
157
  }
152
158
  }
153
159
 
@@ -160,7 +166,7 @@ export async function checkForUpdate(options = {}) {
160
166
  // Banner string from cached update-state (≤24h stale), or null. No network I/O.
161
167
  export function getCachedUpdateBanner() {
162
168
  try {
163
- if (isDevMode() || process.env.CLAUDE_MEM_SKIP_UPDATE) return null;
169
+ if (updateCheckDisabledReason()) return null;
164
170
  const state = readState();
165
171
  const running = pendingCachedUpdate(state);
166
172
  if (running) {
@@ -193,7 +199,7 @@ export function pendingCachedUpdate(state) {
193
199
  // Caller spawns the refresh in the background so this session doesn't wait.
194
200
  export function isUpdateCheckDue() {
195
201
  try {
196
- if (isDevMode() || process.env.CLAUDE_MEM_SKIP_UPDATE) return false;
202
+ if (updateCheckDisabledReason()) return false;
197
203
  return shouldCheck(readState());
198
204
  } catch {
199
205
  return false;
@@ -203,7 +209,7 @@ export function isUpdateCheckDue() {
203
209
  // D#187. `CLAUDE_PLUGIN_ROOT` is set in every hook and MCP process Claude Code
204
210
  // spawns, so inside those the env var answers "am I a plugin install?" perfectly —
205
211
  // which is why v3.84.1's fix, which reads it, was enough THERE. It is not set in a
206
- // plain terminal, and a plugin-only user typing `claude-mem-lite update` therefore
212
+ // plain terminal, and a plugin-only user typing `claude-mem-lite self-update` therefore
207
213
  // fell off both plugin paths at once: getCurrentVersion() returned '0.0.0' (so every
208
214
  // release compares as newer, forever), and isPluginMode() was false, so allowInstall
209
215
  // defaulted to true and downloadAndInstall laid a full managed tree into
@@ -252,6 +258,19 @@ function isPluginMode() {
252
258
  // never a command that would overwrite its working tree. Re-implementing the check at the
253
259
  // call site would make it the second copy of a predicate this file has already had to get
254
260
  // right twice (whole-dir symlink, then per-file drift) — the twin-drift class.
261
+ /**
262
+ * Why the update check will not look at all, or null when it will. checkForUpdate returns
263
+ * null both for "nothing newer" and for "never looked", so a caller that reports to a
264
+ * person asks this first: `self-update` used to print "Already up to date" under
265
+ * CLAUDE_MEM_SKIP_UPDATE without a single request (D#251).
266
+ * @returns {'dev-install'|'CLAUDE_MEM_SKIP_UPDATE'|null}
267
+ */
268
+ export function updateCheckDisabledReason() {
269
+ if (isDevMode()) return 'dev-install';
270
+ if (process.env.CLAUDE_MEM_SKIP_UPDATE) return 'CLAUDE_MEM_SKIP_UPDATE';
271
+ return null;
272
+ }
273
+
255
274
  export function isDevMode() {
256
275
  try {
257
276
  // A dev checkout always carries a .git dir. This catches a whole-directory
@@ -285,7 +304,13 @@ function shouldCheck(state) {
285
304
 
286
305
  // ── GitHub API ─────────────────────────────────────────────
287
306
  // Try releases/latest first, fallback to tags (some repos only use tags)
307
+ // Whether the most recent fetchLatestRelease call was refused with 403/429. The persisted
308
+ // `rateLimited` flag is not that: only a successful lookup clears it, so reading it after a
309
+ // network failure blamed a rate limit from an earlier call. (pre-tag review of cd9f1ab7)
310
+ let lastLookupRateLimited = false;
311
+
288
312
  export async function fetchLatestRelease() {
313
+ lastLookupRateLimited = false;
289
314
  const headers = {
290
315
  Accept: 'application/vnd.github+json',
291
316
  'User-Agent': 'claude-mem-lite-updater/1.0',
@@ -347,6 +372,7 @@ async function fetchWithTimeout(url, headers) {
347
372
  const state = readState();
348
373
  saveState({ ...state, rateLimited: true });
349
374
  debugLog('DEBUG', 'hook-update', 'GitHub API rate limited; will retry on the 6h rate-limit cadence');
375
+ lastLookupRateLimited = true;
350
376
  return 'rate-limited';
351
377
  }
352
378
  if (!res.ok) return null;
@@ -412,7 +438,7 @@ export function getCurrentVersion() {
412
438
  }
413
439
  // D#187: no env var in a plain terminal, so ask the filesystem which plugin
414
440
  // version this machine actually runs. Without this a plugin-only user's
415
- // `claude-mem-lite update` reads 0.0.0 and every release compares as newer.
441
+ // `claude-mem-lite self-update` reads 0.0.0 and every release compares as newer.
416
442
  const active = installShape()?.activePluginVersion;
417
443
  if (active) {
418
444
  try {
package/install.mjs CHANGED
@@ -3213,14 +3213,36 @@ function cleanup() {
3213
3213
  // ─── Manual Update ───────────────────────────────────────────────────────────
3214
3214
 
3215
3215
  async function manualUpdate() {
3216
- console.log('\nclaude-mem-lite update\n');
3216
+ // `self-update`, not `update`: through cli.mjs `update <id>` is the memory editor.
3217
+ console.log('\nclaude-mem-lite self-update\n');
3217
3218
 
3218
3219
  // Force check by importing hook-update (bypasses throttle for manual use)
3219
- const { checkForUpdate, getCurrentVersion } = await import('./hook-update.mjs');
3220
+ const { checkForUpdate, getCurrentVersion, updateCheckDisabledReason } = await import('./hook-update.mjs');
3221
+ // checkForUpdate returns null without looking in these two cases, and the branch at the
3222
+ // bottom would then report "Already up to date" for a check that never ran. (D#251)
3223
+ const disabled = updateCheckDisabledReason();
3224
+ if (disabled === 'CLAUDE_MEM_SKIP_UPDATE') {
3225
+ warn('Not checked: CLAUDE_MEM_SKIP_UPDATE is set, which turns off update checks and installs.');
3226
+ log(' Unset it and run this command again to update.');
3227
+ console.log('');
3228
+ return;
3229
+ }
3230
+ if (disabled === 'dev-install') {
3231
+ warn(`Not checked: ${INSTALL_DIR} is a development install (a git checkout or symlinks).`);
3232
+ log(' Update the checkout it points to with git instead.');
3233
+ console.log('');
3234
+ return;
3235
+ }
3220
3236
  log('Checking for updates...');
3221
- const result = await checkForUpdate({ force: true, allowInstall: true });
3237
+ const result = await checkForUpdate({ force: true, allowInstall: true, reportFailure: true });
3222
3238
 
3223
- if (result?.updated) {
3239
+ if (result?.checkFailed) {
3240
+ warn(
3241
+ result.rateLimited
3242
+ ? 'Not checked: GitHub is rate-limiting requests from this address. Try again later.'
3243
+ : 'Not checked: could not reach GitHub Releases (network, proxy or DNS). Nothing was installed.',
3244
+ );
3245
+ } else if (result?.updated) {
3224
3246
  ok(`Updated: v${result.from} → v${result.to}`);
3225
3247
  } else if (result?.updateAvailable && result?.installDeferred) {
3226
3248
  warn(`v${result.to} available — plugin mode only checks for updates.`);
@@ -1,7 +1,8 @@
1
1
  // lib/proxy-fetch.mjs — HTTPS over an HTTP CONNECT tunnel, using node: built-ins only.
2
2
  //
3
- // Node's global fetch (undici) does NOT honour HTTP(S)_PROXY, and undici's
4
- // ProxyAgent is not importable without adding a dependency (this package ships
3
+ // Node's global fetch (undici) does NOT honour HTTP(S)_PROXY unless the user opts in with
4
+ // NODE_USE_ENV_PROXY=1 (which then proxies plain http:// too; see postDirectHttp), and
5
+ // undici's ProxyAgent is not importable without adding a dependency (this package ships
5
6
  // three: @modelcontextprotocol/sdk, better-sqlite3, zod — a proxy shim is not
6
7
  // worth a fourth). In an environment where external hosts are only reachable
7
8
  // through a local proxy, a direct fetch hangs or dies instantly, so every
@@ -43,18 +44,54 @@ export function httpConnectProxyFor(targetUrl) {
43
44
  // caller's try/catch, and takes the process (MCP server included) down.
44
45
  // Native fetch handles http directly, so the caller keeps that path.
45
46
  if (target.protocol !== 'https:') return null;
46
- const host = target.hostname;
47
- const noProxy = (process.env.NO_PROXY || process.env.no_proxy || '')
48
- .split(',')
49
- .map((s) => s.trim())
50
- .filter(Boolean);
51
- if (noProxy.some((n) => n === host || (n.startsWith('.') && host.endsWith(n.slice(1))))) return null;
47
+ const noProxy = process.env.NO_PROXY || process.env.no_proxy || '';
48
+ if (noProxyMatches(target.hostname, Number(target.port) || 443, noProxy)) return null;
52
49
  return proxy;
53
50
  } catch {
54
51
  return null;
55
52
  }
56
53
  }
57
54
 
55
+ /**
56
+ * Does a NO_PROXY list exempt this host? NO_PROXY has no standard (survey:
57
+ * about.gitlab.com/blog/we-need-to-talk-no-proxy). Every common client suffix-matches a
58
+ * name; beyond that they disagree, so for names and ports this accepts the UNION of the
59
+ * forms curl, Python and Go accept, and it can exempt a host one of them would still
60
+ * proxy. Case-insensitive; a '*' entry exempts every host (Go); a name entry covers itself
61
+ * and every subdomain on a '.' boundary, with or without a leading '.' (curl, Python) or
62
+ * '*.' (Go); an optional :port narrows the entry to that port (Python, Go); IPv6 with or
63
+ * without brackets. Narrower than the union: an IP entry matches only the canonical
64
+ * spelling URL.hostname uses, never as a suffix (Python suffix-matches IPs), no CIDR
65
+ * (curl, Go), no IDN-to-xn-- conversion (Go), no DNS lookups. NO_PROXY is read before
66
+ * no_proxy; curl, Python and Go (golang.org/x/net/http/httpproxy) read no_proxy first.
67
+ * @param {string} hostname URL.hostname (lowercase; IPv6 bracketed)
68
+ * @param {number} port effective target port
69
+ * @param {string} list raw NO_PROXY value
70
+ * @returns {boolean}
71
+ */
72
+ function noProxyMatches(hostname, port, list) {
73
+ const host = hostname.replace(/^\[|\]$/g, '').replace(/\.$/, '');
74
+ for (const raw of list.split(',')) {
75
+ let entry = raw.trim().toLowerCase();
76
+ if (!entry) continue;
77
+ if (entry === '*') return true;
78
+ let entryPort = null;
79
+ const bracketed = /^\[([^\]]+)\](?::(\d+))?$/.exec(entry);
80
+ if (bracketed) {
81
+ entry = bracketed[1];
82
+ entryPort = bracketed[2] ?? null;
83
+ } else if (entry.split(':').length === 2) {
84
+ [entry, entryPort] = entry.split(':');
85
+ }
86
+ if (entryPort !== null && Number(entryPort) !== port) continue;
87
+ entry = entry.replace(/^\*?\./, '').replace(/\.$/, '');
88
+ if (!entry) continue;
89
+ if (host === entry) return true;
90
+ if (!net.isIP(host) && host.endsWith(`.${entry}`)) return true;
91
+ }
92
+ return false;
93
+ }
94
+
58
95
  /**
59
96
  * Proxy-Authorization header for a proxy URL that carries credentials, or {} when it does
60
97
  * not. R10 P2-14.
@@ -240,23 +277,30 @@ export function onceViaConnectProxy(
240
277
  // the certificate identity check, brackets stripped for IPv6.
241
278
  const tlsHost = t.hostname.replace(/^\[|\]$/g, '');
242
279
  const sni = net.isIP(tlsHost) ? {} : { servername: tlsHost };
280
+ // defaultPort: with createConnection and no agent, https.request takes its default
281
+ // port as 80, so a URL without a port went out as `Host: api.github.com:80`. GitHub
282
+ // answers that with 400 (API) or a 301 to the same URL (release downloads), which
283
+ // broke the update check and the release download behind every proxy, silently.
243
284
  const req = https.request(
244
285
  url,
245
- { method, headers, createConnection: () => tls.connect({ socket, host: tlsHost, ...sni }) },
286
+ {
287
+ method,
288
+ headers,
289
+ defaultPort: 443,
290
+ createConnection: () => tls.connect({ socket, host: tlsHost, ...sni }),
291
+ },
246
292
  (resp) => {
247
293
  const chunks = [];
248
- resp.on('data', (c) => chunks.push(Buffer.from(c)));
249
- resp.on('end', () => {
250
- const buf = Buffer.concat(chunks);
251
- finish(resolve, {
252
- ok: resp.statusCode >= 200 && resp.statusCode < 300,
253
- status: resp.statusCode,
254
- headers: resp.headers,
255
- buffer: () => buf,
256
- text: () => buf.toString('utf8'),
257
- json: () => JSON.parse(buf.toString('utf8')),
258
- });
294
+ // A connection dropped mid-body destroys the response without 'end' (and
295
+ // emits 'error' only to a listener), but 'close' always fires. Without this
296
+ // the call stayed pending until the unref'd overall timer, so an otherwise
297
+ // idle worker exited with it unsettled and its caller's fallback never ran.
298
+ // Native fetch rejects here too.
299
+ resp.on('close', () => {
300
+ if (!resp.complete) finish(reject, new Error('proxy response closed before the body ended'));
259
301
  });
302
+ resp.on('data', (c) => chunks.push(Buffer.from(c)));
303
+ resp.on('end', () => finish(resolve, fetchLikeResponse(resp, Buffer.concat(chunks))));
260
304
  },
261
305
  );
262
306
  req.setTimeout(remaining(), () => req.destroy(new Error('proxy request timeout')));
@@ -267,6 +311,80 @@ export function onceViaConnectProxy(
267
311
  });
268
312
  }
269
313
 
314
+ /** The fetch-compatible subset both node:http transports below resolve with. */
315
+ function fetchLikeResponse(resp, buf) {
316
+ return {
317
+ ok: resp.statusCode >= 200 && resp.statusCode < 300,
318
+ status: resp.statusCode,
319
+ headers: resp.headers,
320
+ buffer: () => buf,
321
+ text: () => buf.toString('utf8'),
322
+ json: () => JSON.parse(buf.toString('utf8')),
323
+ };
324
+ }
325
+
326
+ /**
327
+ * ONE plain-http POST that never goes through a proxy. Same contract as
328
+ * onceViaConnectProxy: resolves the fetch-compatible subset without following a
329
+ * redirect, and REJECTS on a socket error, on `timeout` (the whole call), or on a body
330
+ * cut off mid-stream.
331
+ *
332
+ * Native fetch cannot promise "direct". With NODE_USE_ENV_PROXY=1 it hands an http:// URL
333
+ * to HTTP_PROXY unless Node's own NO_PROXY matcher exempts the host, headers in cleartext.
334
+ * Measured 2026-10-07 against a fake proxy: Node 26.8.1 sent it as a plain request, Node
335
+ * 22.23.3 wrote it into a CONNECT tunnel the proxy can read, and on both an explicit
336
+ * `agent: false` (a fresh Agent without `proxyEnv`) went straight to the target. The only
337
+ * caller is a loopback gateway (resolveAnthropicBaseUrl refuses plain http to any other
338
+ * host), and the proxy's loopback is not this machine's. (D#250)
339
+ *
340
+ * @param {string} url absolute http:// target
341
+ * @param {{headers?:object, body?:string, timeout?:number}} [opts]
342
+ */
343
+ export function postDirectHttp(url, { headers = {}, body = '', timeout = 20000 } = {}) {
344
+ return new Promise((resolve, reject) => {
345
+ let t;
346
+ try {
347
+ t = new URL(url);
348
+ } catch (e) {
349
+ return reject(e);
350
+ }
351
+ if (t.protocol !== 'http:') {
352
+ return reject(new Error(`direct http supports http targets only (got ${t.protocol})`));
353
+ }
354
+ let settled = false;
355
+ let req = null;
356
+ const finish = (fn, arg) => {
357
+ if (settled) return;
358
+ settled = true;
359
+ clearTimeout(overall);
360
+ fn(arg);
361
+ };
362
+ const overall = setTimeout(() => {
363
+ req?.destroy();
364
+ finish(reject, new Error('direct http request timeout'));
365
+ }, timeout);
366
+ if (typeof overall.unref === 'function') overall.unref();
367
+ req = http.request(
368
+ t,
369
+ {
370
+ method: 'POST',
371
+ headers: { ...headers, 'Content-Length': Buffer.byteLength(body) },
372
+ agent: false,
373
+ },
374
+ (resp) => {
375
+ const chunks = [];
376
+ resp.on('close', () => {
377
+ if (!resp.complete) finish(reject, new Error('response closed before the body ended'));
378
+ });
379
+ resp.on('data', (c) => chunks.push(Buffer.from(c)));
380
+ resp.on('end', () => finish(resolve, fetchLikeResponse(resp, Buffer.concat(chunks))));
381
+ },
382
+ );
383
+ req.on('error', (e) => finish(reject, e));
384
+ req.end(body);
385
+ });
386
+ }
387
+
270
388
  /**
271
389
  * onceViaConnectProxy + redirect following. Native fetch follows redirects by
272
390
  * default, so a call site swapped from fetch to the tunnel needs this or the
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "6.23.1",
3
+ "version": "6.23.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "claude-mem-lite",
9
- "version": "6.23.1",
9
+ "version": "6.23.3",
10
10
  "os": [
11
11
  "darwin",
12
12
  "linux",
@@ -22,14 +22,14 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "@eslint/js": "^10.0.1",
25
- "@vitest/coverage-v8": "^5.0.1",
25
+ "@vitest/coverage-v8": "^5.0.3",
26
26
  "acorn": "8.18.0",
27
27
  "eslint": "^10.11.0",
28
28
  "fast-check": "^4.10.2",
29
29
  "knip": "^6.38.0",
30
30
  "picomatch": "^4.0.4",
31
31
  "prettier": "3.9.9",
32
- "vitest": "^5.0.0"
32
+ "vitest": "^5.0.3"
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=22"
@@ -1078,9 +1078,9 @@
1078
1078
  ]
1079
1079
  },
1080
1080
  "node_modules/@rolldown/binding-android-arm-eabi": {
1081
- "version": "1.2.10",
1082
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.10.tgz",
1083
- "integrity": "sha512-bp9svZb+QurZeh+8H4BhrZkifEB0YBNvTVzNSJnJQkj4NrRwmQoDUCGP0vSN7PbvLeM7l1tK6GXL8mrTiH2myg==",
1081
+ "version": "1.2.13",
1082
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.13.tgz",
1083
+ "integrity": "sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==",
1084
1084
  "cpu": [
1085
1085
  "arm"
1086
1086
  ],
@@ -1096,9 +1096,9 @@
1096
1096
  }
1097
1097
  },
1098
1098
  "node_modules/@rolldown/binding-android-arm64": {
1099
- "version": "1.2.10",
1100
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.10.tgz",
1101
- "integrity": "sha512-wm6Dld3RXUAZ/gRWKyUy+4W1B5CB5UeFaOzsSWJWEdxZXHH8rCYiZ5dGe6oJmhsunAPWzL7FZV+VtvmN5Ye2eA==",
1099
+ "version": "1.2.13",
1100
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.13.tgz",
1101
+ "integrity": "sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==",
1102
1102
  "cpu": [
1103
1103
  "arm64"
1104
1104
  ],
@@ -1114,9 +1114,9 @@
1114
1114
  }
1115
1115
  },
1116
1116
  "node_modules/@rolldown/binding-darwin-arm64": {
1117
- "version": "1.2.10",
1118
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.10.tgz",
1119
- "integrity": "sha512-UbEfXq/AqGNgRTV3ik+X/iR6mUxu2QdYAadwRxJWquUGnW6gDqdP1FtLtFXRow7RJx0ssRwi80XAPr4r+4DtsA==",
1117
+ "version": "1.2.13",
1118
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.13.tgz",
1119
+ "integrity": "sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==",
1120
1120
  "cpu": [
1121
1121
  "arm64"
1122
1122
  ],
@@ -1132,9 +1132,9 @@
1132
1132
  }
1133
1133
  },
1134
1134
  "node_modules/@rolldown/binding-darwin-x64": {
1135
- "version": "1.2.10",
1136
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.10.tgz",
1137
- "integrity": "sha512-7f5h17q5KZVx/ji1vb8OTq31ch1O2I7K8NPIr44GkyWTApXMIsmhWqZfgpOH10xeauqghDAvGlZktasCkcF6Eg==",
1135
+ "version": "1.2.13",
1136
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.13.tgz",
1137
+ "integrity": "sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==",
1138
1138
  "cpu": [
1139
1139
  "x64"
1140
1140
  ],
@@ -1150,9 +1150,9 @@
1150
1150
  }
1151
1151
  },
1152
1152
  "node_modules/@rolldown/binding-freebsd-x64": {
1153
- "version": "1.2.10",
1154
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.10.tgz",
1155
- "integrity": "sha512-ynOk/eEYhC6ZB2xCGvKrEOwE58oBy9LnrAqtkrDF9Fz1VTaNdGZTsV0VarJdhPwb+sOJTGjCLwcuyRJZ1dnMcQ==",
1153
+ "version": "1.2.13",
1154
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.13.tgz",
1155
+ "integrity": "sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==",
1156
1156
  "cpu": [
1157
1157
  "x64"
1158
1158
  ],
@@ -1168,9 +1168,9 @@
1168
1168
  }
1169
1169
  },
1170
1170
  "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
1171
- "version": "1.2.10",
1172
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.10.tgz",
1173
- "integrity": "sha512-ERrAs185meZZhGan7a4l3RiiJK1ArSDlHdST++uvSxe+FDbR4TwUPahT/cbZJvaG6fIpDpF78surN+tX708Y4Q==",
1171
+ "version": "1.2.13",
1172
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.13.tgz",
1173
+ "integrity": "sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==",
1174
1174
  "cpu": [
1175
1175
  "arm"
1176
1176
  ],
@@ -1186,9 +1186,9 @@
1186
1186
  }
1187
1187
  },
1188
1188
  "node_modules/@rolldown/binding-linux-arm64-gnu": {
1189
- "version": "1.2.10",
1190
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.10.tgz",
1191
- "integrity": "sha512-KN7OHKD0J3jy1UzBwZWPxpwhODf9IARUIJcrH+yLYKOcmegZ8luEUM38lDP1bDVj40yP6PsSzCqOJF76vljFnQ==",
1189
+ "version": "1.2.13",
1190
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.13.tgz",
1191
+ "integrity": "sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==",
1192
1192
  "cpu": [
1193
1193
  "arm64"
1194
1194
  ],
@@ -1204,9 +1204,9 @@
1204
1204
  }
1205
1205
  },
1206
1206
  "node_modules/@rolldown/binding-linux-arm64-musl": {
1207
- "version": "1.2.10",
1208
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.10.tgz",
1209
- "integrity": "sha512-8l9wP8O+wa8zD6iw6egSfzVtu7oZVfH3hlUsMM4MwbLMhxleqeoXbZzjddyK3YyNlwLhqznq3tF7PkNJ8T/V2w==",
1207
+ "version": "1.2.13",
1208
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.13.tgz",
1209
+ "integrity": "sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==",
1210
1210
  "cpu": [
1211
1211
  "arm64"
1212
1212
  ],
@@ -1222,9 +1222,9 @@
1222
1222
  }
1223
1223
  },
1224
1224
  "node_modules/@rolldown/binding-linux-ppc64-gnu": {
1225
- "version": "1.2.10",
1226
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.10.tgz",
1227
- "integrity": "sha512-SeXNKeQzA5kLhz/J0CH6ZP0/HJ3v1xm/0YbiYpE0kK7emfRC2OIGGIaE14xzkISEGv2aYuUSpiLiU5Gbq+OI0A==",
1225
+ "version": "1.2.13",
1226
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.13.tgz",
1227
+ "integrity": "sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==",
1228
1228
  "cpu": [
1229
1229
  "ppc64"
1230
1230
  ],
@@ -1240,9 +1240,9 @@
1240
1240
  }
1241
1241
  },
1242
1242
  "node_modules/@rolldown/binding-linux-s390x-gnu": {
1243
- "version": "1.2.10",
1244
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.10.tgz",
1245
- "integrity": "sha512-mtht0nR+y8/hart4175Ll15w7lY8dg7CtQ+j2FDNTsDRspOWTK/2V3l0aj9sIj7XmvqxT8Yli/wq22e7feTTWg==",
1243
+ "version": "1.2.13",
1244
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.13.tgz",
1245
+ "integrity": "sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==",
1246
1246
  "cpu": [
1247
1247
  "s390x"
1248
1248
  ],
@@ -1258,9 +1258,9 @@
1258
1258
  }
1259
1259
  },
1260
1260
  "node_modules/@rolldown/binding-linux-x64-gnu": {
1261
- "version": "1.2.10",
1262
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.10.tgz",
1263
- "integrity": "sha512-FSM94nGd55NYo48usCyM/nHfUKRnqc9+b0vJNuKV0oCCpIp/OGims7rO1Nv/DkFkt0S/s2rxsJ2kkS8J3HcpeA==",
1261
+ "version": "1.2.13",
1262
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.13.tgz",
1263
+ "integrity": "sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==",
1264
1264
  "cpu": [
1265
1265
  "x64"
1266
1266
  ],
@@ -1276,9 +1276,9 @@
1276
1276
  }
1277
1277
  },
1278
1278
  "node_modules/@rolldown/binding-linux-x64-musl": {
1279
- "version": "1.2.10",
1280
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.10.tgz",
1281
- "integrity": "sha512-C3YxNB16myRLs7o+B+6PnQ6jBsdIS4+AE4Ah8glVGhDpEv9AOvxhZ/1duAb4B0UGczEK/lBbccksd8VI+p6zfw==",
1279
+ "version": "1.2.13",
1280
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.13.tgz",
1281
+ "integrity": "sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==",
1282
1282
  "cpu": [
1283
1283
  "x64"
1284
1284
  ],
@@ -1294,9 +1294,9 @@
1294
1294
  }
1295
1295
  },
1296
1296
  "node_modules/@rolldown/binding-openharmony-arm64": {
1297
- "version": "1.2.10",
1298
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.10.tgz",
1299
- "integrity": "sha512-571TlE/F1eeTjjdjYAMMMPs1Mfv3MtX6s3+ZKVU6HiUjZ5Njc6c/qzNy/8K3zALTZnaw3JQVYrHxvNfjm43KAg==",
1297
+ "version": "1.2.13",
1298
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.13.tgz",
1299
+ "integrity": "sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==",
1300
1300
  "cpu": [
1301
1301
  "arm64"
1302
1302
  ],
@@ -1312,9 +1312,9 @@
1312
1312
  }
1313
1313
  },
1314
1314
  "node_modules/@rolldown/binding-win32-arm64-msvc": {
1315
- "version": "1.2.10",
1316
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.10.tgz",
1317
- "integrity": "sha512-QXW+ZWaiqs2c7Fi++D/SsW07LTPcUrncxcskJGfGNBoaLik1IU6fJymz4HsqwEO0u5Iq11yTO0B/mc4cPk7jrQ==",
1315
+ "version": "1.2.13",
1316
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.13.tgz",
1317
+ "integrity": "sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==",
1318
1318
  "cpu": [
1319
1319
  "arm64"
1320
1320
  ],
@@ -1330,9 +1330,9 @@
1330
1330
  }
1331
1331
  },
1332
1332
  "node_modules/@rolldown/binding-win32-x64-msvc": {
1333
- "version": "1.2.10",
1334
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.10.tgz",
1335
- "integrity": "sha512-5FQFGgah17YeMtG1Yd5a+rMxQpTksyNXxRtKz06FVTaQw3RKYUJQbUoKk0/5jrXBpDo+7makNP7UHA2LQyH64A==",
1333
+ "version": "1.2.13",
1334
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.13.tgz",
1335
+ "integrity": "sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==",
1336
1336
  "cpu": [
1337
1337
  "x64"
1338
1338
  ],
@@ -1406,9 +1406,9 @@
1406
1406
  "license": "MIT"
1407
1407
  },
1408
1408
  "node_modules/@vitest/coverage-v8": {
1409
- "version": "5.0.1",
1410
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-5.0.1.tgz",
1411
- "integrity": "sha512-FRC8ACiudC3dI6MTplzRSYWHDRnIv2IPfbzs4FdoJNsMal/35sWV8hwIfV8ZcqzSPy+uXHeMVONt9CEqtOU17w==",
1409
+ "version": "5.0.3",
1410
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-5.0.3.tgz",
1411
+ "integrity": "sha512-+klsyz7BvT1vCU28Zkfzms1Ia78XD0V41U3FUtRaa3S+vOr/EXvK1O6BvVD7l1RzEjm6SONR2aybOvDDf9u0mQ==",
1412
1412
  "dev": true,
1413
1413
  "license": "MIT",
1414
1414
  "dependencies": {
@@ -1425,8 +1425,8 @@
1425
1425
  "url": "https://opencollective.com/vitest"
1426
1426
  },
1427
1427
  "peerDependencies": {
1428
- "@vitest/browser": "5.0.1",
1429
- "vitest": "5.0.1"
1428
+ "@vitest/browser": "5.0.3",
1429
+ "vitest": "5.0.3"
1430
1430
  },
1431
1431
  "peerDependenciesMeta": {
1432
1432
  "@vitest/browser": {
@@ -1458,14 +1458,14 @@
1458
1458
  }
1459
1459
  },
1460
1460
  "node_modules/@vitest/mocker": {
1461
- "version": "5.0.1",
1462
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.1.tgz",
1463
- "integrity": "sha512-6K1DoBNAPGvuOcSsGA4D6x+5zEEff/KmOOP3uetT2TrGpVfI+HRHRnJJfKi5ib/g1vx8IYHQD8s0pbJz8WQI7Q==",
1461
+ "version": "5.0.3",
1462
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.3.tgz",
1463
+ "integrity": "sha512-T8sWAIbkSyAjkwTcaEc3Iu0o9A27X1/kdXrizhZkGuSKScRQtRzclfAMpOTcGdXCsqxeWlpGy3XjqaW8CpLORg==",
1464
1464
  "dev": true,
1465
1465
  "license": "MIT",
1466
1466
  "dependencies": {
1467
1467
  "@jridgewell/trace-mapping": "0.3.31",
1468
- "@vitest/spy": "5.0.1",
1468
+ "@vitest/spy": "5.0.3",
1469
1469
  "estree-walker": "^3.0.3",
1470
1470
  "magic-string": "^1.2.3"
1471
1471
  },
@@ -1486,9 +1486,9 @@
1486
1486
  }
1487
1487
  },
1488
1488
  "node_modules/@vitest/spy": {
1489
- "version": "5.0.1",
1490
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.1.tgz",
1491
- "integrity": "sha512-rbto/mF/SGERxEgYOek7Xm6B9b+y+mVoo+f4b2LymYO8zM1b7uB5nHuhVMTP2hxdzgxvGiZYGxGIaMvL5y180Q==",
1489
+ "version": "5.0.3",
1490
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.3.tgz",
1491
+ "integrity": "sha512-XhFysQTB8AZ+P4gMi+Lpo99vg2AZi0qKpaB9yXQl37+CaMEAPO3iH/wGVnSyL5MPERiLezpqTVtrR6UZH5GCXg==",
1492
1492
  "dev": true,
1493
1493
  "license": "MIT",
1494
1494
  "funding": {
@@ -1646,9 +1646,9 @@
1646
1646
  }
1647
1647
  },
1648
1648
  "node_modules/brace-expansion": {
1649
- "version": "5.0.9",
1650
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
1651
- "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
1649
+ "version": "5.0.12",
1650
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
1651
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
1652
1652
  "dev": true,
1653
1653
  "license": "MIT",
1654
1654
  "dependencies": {
@@ -1711,9 +1711,9 @@
1711
1711
  }
1712
1712
  },
1713
1713
  "node_modules/chai": {
1714
- "version": "6.2.2",
1715
- "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
1716
- "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
1714
+ "version": "6.3.0",
1715
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.3.0.tgz",
1716
+ "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==",
1717
1717
  "dev": true,
1718
1718
  "license": "MIT",
1719
1719
  "engines": {
@@ -3075,9 +3075,9 @@
3075
3075
  }
3076
3076
  },
3077
3077
  "node_modules/magic-string": {
3078
- "version": "1.4.2",
3079
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
3080
- "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
3078
+ "version": "1.4.3",
3079
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz",
3080
+ "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==",
3081
3081
  "dev": true,
3082
3082
  "license": "MIT",
3083
3083
  "dependencies": {
@@ -3174,9 +3174,9 @@
3174
3174
  "license": "MIT"
3175
3175
  },
3176
3176
  "node_modules/nanoid": {
3177
- "version": "3.3.19",
3178
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
3179
- "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
3177
+ "version": "3.3.20",
3178
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
3179
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
3180
3180
  "dev": true,
3181
3181
  "funding": [
3182
3182
  {
@@ -3240,9 +3240,9 @@
3240
3240
  }
3241
3241
  },
3242
3242
  "node_modules/obug": {
3243
- "version": "2.1.4",
3244
- "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz",
3245
- "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==",
3243
+ "version": "2.2.1",
3244
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz",
3245
+ "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==",
3246
3246
  "dev": true,
3247
3247
  "funding": [
3248
3248
  "https://github.com/sponsors/sxzz",
@@ -3468,9 +3468,9 @@
3468
3468
  }
3469
3469
  },
3470
3470
  "node_modules/postcss": {
3471
- "version": "8.5.28",
3472
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
3473
- "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
3471
+ "version": "8.5.29",
3472
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz",
3473
+ "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==",
3474
3474
  "dev": true,
3475
3475
  "funding": [
3476
3476
  {
@@ -3489,9 +3489,9 @@
3489
3489
  "license": "MIT",
3490
3490
  "peer": true,
3491
3491
  "dependencies": {
3492
- "nanoid": "^3.3.18",
3492
+ "nanoid": "^3.3.19",
3493
3493
  "picocolors": "^1.1.1",
3494
- "source-map-js": "^1.2.1"
3494
+ "source-map-js": "^1.2.2"
3495
3495
  },
3496
3496
  "engines": {
3497
3497
  "node": "^10 || ^12 || >=14"
@@ -3647,14 +3647,14 @@
3647
3647
  }
3648
3648
  },
3649
3649
  "node_modules/rolldown": {
3650
- "version": "1.2.10",
3651
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.10.tgz",
3652
- "integrity": "sha512-OxkA08pSryMK7B3XiFA09B4OJ1xJMPgIYCBMY2xchzpqgBGsV1o0DetPAE+Sl3N3L4oCPiEzmHVSOj7iR04Zog==",
3650
+ "version": "1.2.13",
3651
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.13.tgz",
3652
+ "integrity": "sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==",
3653
3653
  "dev": true,
3654
3654
  "license": "MIT",
3655
3655
  "peer": true,
3656
3656
  "dependencies": {
3657
- "@oxc-project/types": "=0.151.0",
3657
+ "@oxc-project/types": "=0.153.0",
3658
3658
  "@rolldown/pluginutils": "^1.0.0"
3659
3659
  },
3660
3660
  "bin": {
@@ -3664,27 +3664,27 @@
3664
3664
  "node": "^20.19.0 || >=22.12.0"
3665
3665
  },
3666
3666
  "optionalDependencies": {
3667
- "@rolldown/binding-android-arm-eabi": "1.2.10",
3668
- "@rolldown/binding-android-arm64": "1.2.10",
3669
- "@rolldown/binding-darwin-arm64": "1.2.10",
3670
- "@rolldown/binding-darwin-x64": "1.2.10",
3671
- "@rolldown/binding-freebsd-x64": "1.2.10",
3672
- "@rolldown/binding-linux-arm-gnueabihf": "1.2.10",
3673
- "@rolldown/binding-linux-arm64-gnu": "1.2.10",
3674
- "@rolldown/binding-linux-arm64-musl": "1.2.10",
3675
- "@rolldown/binding-linux-ppc64-gnu": "1.2.10",
3676
- "@rolldown/binding-linux-s390x-gnu": "1.2.10",
3677
- "@rolldown/binding-linux-x64-gnu": "1.2.10",
3678
- "@rolldown/binding-linux-x64-musl": "1.2.10",
3679
- "@rolldown/binding-openharmony-arm64": "1.2.10",
3680
- "@rolldown/binding-win32-arm64-msvc": "1.2.10",
3681
- "@rolldown/binding-win32-x64-msvc": "1.2.10"
3667
+ "@rolldown/binding-android-arm-eabi": "1.2.13",
3668
+ "@rolldown/binding-android-arm64": "1.2.13",
3669
+ "@rolldown/binding-darwin-arm64": "1.2.13",
3670
+ "@rolldown/binding-darwin-x64": "1.2.13",
3671
+ "@rolldown/binding-freebsd-x64": "1.2.13",
3672
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.13",
3673
+ "@rolldown/binding-linux-arm64-gnu": "1.2.13",
3674
+ "@rolldown/binding-linux-arm64-musl": "1.2.13",
3675
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.13",
3676
+ "@rolldown/binding-linux-s390x-gnu": "1.2.13",
3677
+ "@rolldown/binding-linux-x64-gnu": "1.2.13",
3678
+ "@rolldown/binding-linux-x64-musl": "1.2.13",
3679
+ "@rolldown/binding-openharmony-arm64": "1.2.13",
3680
+ "@rolldown/binding-win32-arm64-msvc": "1.2.13",
3681
+ "@rolldown/binding-win32-x64-msvc": "1.2.13"
3682
3682
  }
3683
3683
  },
3684
3684
  "node_modules/rolldown/node_modules/@oxc-project/types": {
3685
- "version": "0.151.0",
3686
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.151.0.tgz",
3687
- "integrity": "sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==",
3685
+ "version": "0.153.0",
3686
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.153.0.tgz",
3687
+ "integrity": "sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==",
3688
3688
  "dev": true,
3689
3689
  "license": "MIT",
3690
3690
  "peer": true,
@@ -3858,17 +3858,10 @@
3858
3858
  "url": "https://github.com/sponsors/ljharb"
3859
3859
  }
3860
3860
  },
3861
- "node_modules/siginfo": {
3862
- "version": "2.0.0",
3863
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
3864
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
3865
- "dev": true,
3866
- "license": "ISC"
3867
- },
3868
3861
  "node_modules/smol-toml": {
3869
- "version": "1.8.0",
3870
- "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz",
3871
- "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==",
3862
+ "version": "1.9.0",
3863
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.0.tgz",
3864
+ "integrity": "sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ==",
3872
3865
  "dev": true,
3873
3866
  "license": "BSD-3-Clause",
3874
3867
  "engines": {
@@ -3879,22 +3872,15 @@
3879
3872
  }
3880
3873
  },
3881
3874
  "node_modules/source-map-js": {
3882
- "version": "1.2.1",
3883
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
3884
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
3875
+ "version": "1.2.2",
3876
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
3877
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
3885
3878
  "dev": true,
3886
3879
  "license": "BSD-3-Clause",
3887
3880
  "engines": {
3888
3881
  "node": ">=0.10.0"
3889
3882
  }
3890
3883
  },
3891
- "node_modules/stackback": {
3892
- "version": "0.0.2",
3893
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
3894
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
3895
- "dev": true,
3896
- "license": "MIT"
3897
- },
3898
3884
  "node_modules/statuses": {
3899
3885
  "version": "2.0.2",
3900
3886
  "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
@@ -3905,9 +3891,9 @@
3905
3891
  }
3906
3892
  },
3907
3893
  "node_modules/std-env": {
3908
- "version": "4.2.0",
3909
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
3910
- "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
3894
+ "version": "4.3.0",
3895
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz",
3896
+ "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==",
3911
3897
  "dev": true,
3912
3898
  "license": "MIT"
3913
3899
  },
@@ -3925,9 +3911,9 @@
3925
3911
  }
3926
3912
  },
3927
3913
  "node_modules/tinybench": {
3928
- "version": "6.1.4",
3929
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.1.4.tgz",
3930
- "integrity": "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==",
3914
+ "version": "6.2.1",
3915
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.1.tgz",
3916
+ "integrity": "sha512-IAbQaPJIIdhVxi0mqy9lez1wEwje0UQf9F1vwtbelEG5Nbgn0nPOxCvU+mNeNS9gyJTAhrHp74CbUaSynQpZcQ==",
3931
3917
  "dev": true,
3932
3918
  "license": "MIT",
3933
3919
  "engines": {
@@ -3935,9 +3921,9 @@
3935
3921
  }
3936
3922
  },
3937
3923
  "node_modules/tinyexec": {
3938
- "version": "1.3.0",
3939
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz",
3940
- "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==",
3924
+ "version": "1.3.1",
3925
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz",
3926
+ "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==",
3941
3927
  "dev": true,
3942
3928
  "license": "MIT",
3943
3929
  "engines": {
@@ -4061,9 +4047,9 @@
4061
4047
  }
4062
4048
  },
4063
4049
  "node_modules/vite": {
4064
- "version": "8.3.0",
4065
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.0.tgz",
4066
- "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==",
4050
+ "version": "8.3.3",
4051
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.3.tgz",
4052
+ "integrity": "sha512-cTAldKPImjg6c+gk48U19POPn3GCBzZwpdsN8ZMEEcbpes+6/wvfqUd0C2y3qYY4wsj8PwgFwrZ/1jBPVttMSg==",
4067
4053
  "dev": true,
4068
4054
  "license": "MIT",
4069
4055
  "peer": true,
@@ -4071,7 +4057,7 @@
4071
4057
  "lightningcss": "^1.33.0",
4072
4058
  "picomatch": "^4.0.7",
4073
4059
  "postcss": "^8.5.28",
4074
- "rolldown": "~1.2.6",
4060
+ "rolldown": "~1.2.11",
4075
4061
  "tinyglobby": "^0.2.17"
4076
4062
  },
4077
4063
  "bin": {
@@ -4140,14 +4126,14 @@
4140
4126
  }
4141
4127
  },
4142
4128
  "node_modules/vitest": {
4143
- "version": "5.0.1",
4144
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.1.tgz",
4145
- "integrity": "sha512-iA95lQbKEkvrtTkdAgnWbXfbipWiiWe/hDl2P5tMi6WFwD76G0NxXAGp/M9EOcYupeGJRr6wppMc7CoA41TQjg==",
4129
+ "version": "5.0.3",
4130
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.3.tgz",
4131
+ "integrity": "sha512-xMw97S3rjdtj5dkVat7jCsqWBpvchs3RlpQctUqwJD0KkERk40vz2fJ77lDwW/Vzh/pk18eItYAzkodhSes3jQ==",
4146
4132
  "dev": true,
4147
4133
  "license": "MIT",
4148
4134
  "dependencies": {
4149
4135
  "@types/chai": "^5.2.2",
4150
- "@vitest/mocker": "5.0.1",
4136
+ "@vitest/mocker": "5.0.3",
4151
4137
  "chai": "^6.2.2",
4152
4138
  "es-module-lexer": "^2.3.2",
4153
4139
  "expect-type": "^1.4.0",
@@ -4155,10 +4141,10 @@
4155
4141
  "obug": "^2.1.4",
4156
4142
  "picomatch": "^4.0.7",
4157
4143
  "std-env": "^4.2.0",
4158
- "tinybench": "6.1.4",
4159
- "tinyexec": "1.3.0",
4144
+ "tinybench": "^6.1.4",
4145
+ "tinyexec": "^1.3.0",
4160
4146
  "tinyglobby": "^0.2.17",
4161
- "why-is-node-running": "^2.3.0"
4147
+ "why-is-node-running": "3.2.1"
4162
4148
  },
4163
4149
  "bin": {
4164
4150
  "vitest": "vitest.mjs"
@@ -4173,12 +4159,12 @@
4173
4159
  "@edge-runtime/vm": "*",
4174
4160
  "@opentelemetry/api": "^1.9.0",
4175
4161
  "@types/node": "^22.0.0 || >=24.0.0",
4176
- "@vitest/browser-playwright": "5.0.1",
4177
- "@vitest/browser-preview": "5.0.1",
4162
+ "@vitest/browser-playwright": "5.0.3",
4163
+ "@vitest/browser-preview": "5.0.3",
4178
4164
  "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
4179
- "@vitest/coverage-istanbul": "5.0.1",
4180
- "@vitest/coverage-v8": "5.0.1",
4181
- "@vitest/ui": "5.0.1",
4165
+ "@vitest/coverage-istanbul": "5.0.3",
4166
+ "@vitest/coverage-v8": "5.0.3",
4167
+ "@vitest/ui": "5.0.3",
4182
4168
  "happy-dom": "*",
4183
4169
  "jsdom": "*",
4184
4170
  "vite": "^6.4.0 || ^7.0.0 || ^8.0.0"
@@ -4248,20 +4234,16 @@
4248
4234
  }
4249
4235
  },
4250
4236
  "node_modules/why-is-node-running": {
4251
- "version": "2.3.0",
4252
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
4253
- "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
4237
+ "version": "3.2.1",
4238
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.1.tgz",
4239
+ "integrity": "sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==",
4254
4240
  "dev": true,
4255
4241
  "license": "MIT",
4256
- "dependencies": {
4257
- "siginfo": "^2.0.0",
4258
- "stackback": "0.0.2"
4259
- },
4260
4242
  "bin": {
4261
4243
  "why-is-node-running": "cli.js"
4262
4244
  },
4263
4245
  "engines": {
4264
- "node": ">=8"
4246
+ "node": ">=20.11"
4265
4247
  }
4266
4248
  },
4267
4249
  "node_modules/word-wrap": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "6.23.1",
3
+ "version": "6.23.3",
4
4
  "description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. FTS5 BM25 keyword search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",
@@ -241,13 +241,13 @@
241
241
  },
242
242
  "devDependencies": {
243
243
  "@eslint/js": "^10.0.1",
244
- "@vitest/coverage-v8": "^5.0.1",
244
+ "@vitest/coverage-v8": "^5.0.3",
245
245
  "acorn": "8.18.0",
246
246
  "eslint": "^10.11.0",
247
247
  "fast-check": "^4.10.2",
248
248
  "knip": "^6.38.0",
249
249
  "picomatch": "^4.0.4",
250
250
  "prettier": "3.9.9",
251
- "vitest": "^5.0.0"
251
+ "vitest": "^5.0.3"
252
252
  }
253
253
  }