Skip to content

feat: three-state update mode and fixed nudge growth interval - #86

Open
LX666-666 wants to merge 1 commit into
ranxianglei:masterfrom
LX666-666:2026-08-10_nudge-growth-tokens
Open

feat: three-state update mode and fixed nudge growth interval#86
LX666-666 wants to merge 1 commit into
ranxianglei:masterfrom
LX666-666:2026-08-10_nudge-growth-tokens

Conversation

@LX666-666

Copy link
Copy Markdown
Contributor

Update becomes a real 3-state policy (auto/check/manual) instead of a boolean autoUpdate plus two buttons:

  • type UpdateMode = "auto" | "check" | "manual"; config update.mode
  • update.ts refactored into checkLatestVersion() / installUpdate() / runScheduledUpdate() — checking no longer installs
  • manual mode never touches the network; only explicit user actions do
  • precedence: CLI > BILI_UPDATE_MODE > update.mode > legacy autoUpdate
  • registry metadata + tarball downloads reuse the upstream-proxy ProxyAgent egress so system-proxy users don't hit direct-fetch timeouts
  • Web UI three-state selector with current/latest/last-check/status; check failure no longer toasts a false "up to date"

compress.nudgeGrowthTokens pins acp-kernel's adaptive nudge interval by setting nudge.growthFloor = nudge.growthCap = value; config PUT/reload hot-reloads kernelConfig, modelContextLimit, and compress for new requests (in-flight requests keep their snapshot).

Tests: update-mode (auto/check/manual semantics, precedence, legacy migration, concurrent lock, proxy egress, Web UI endpoints) and nudge-growth-tokens (adaptive default, floor=cap, breakdown denominator, hot reload, emergencyThresholdPct survival).

Update becomes a real 3-state policy (auto/check/manual) instead of a
boolean autoUpdate plus two buttons:
- type UpdateMode = "auto" | "check" | "manual"; config update.mode
- update.ts refactored into checkLatestVersion() / installUpdate() /
  runScheduledUpdate() — checking no longer installs
- manual mode never touches the network; only explicit user actions do
- precedence: CLI > BILI_UPDATE_MODE > update.mode > legacy autoUpdate
- registry metadata + tarball downloads reuse the upstream-proxy
  ProxyAgent egress so system-proxy users don't hit direct-fetch timeouts
- Web UI three-state selector with current/latest/last-check/status;
  check failure no longer toasts a false "up to date"

compress.nudgeGrowthTokens pins acp-kernel's adaptive nudge interval by
setting nudge.growthFloor = nudge.growthCap = value; config PUT/reload
hot-reloads kernelConfig, modelContextLimit, and compress for new
requests (in-flight requests keep their snapshot).

Tests: update-mode (auto/check/manual semantics, precedence, legacy
migration, concurrent lock, proxy egress, Web UI endpoints) and
nudge-growth-tokens (adaptive default, floor=cap, breakdown
denominator, hot reload, emergencyThresholdPct survival).
@ranxianglei

Copy link
Copy Markdown
Owner

Review feedback — two design concerns

1. nudgeGrowthTokens should be per-URL, not global

nudgeGrowthTokens is model-dependent — different upstreams serve different models with different context windows and different optimal compression thresholds:

URL Model Context Reasonable nudgeGrowthTokens
chatgpt.com/backend-api/codex gpt-5.6-codex 400K ~50K
api.anthropic.com claude-opus-4 200K ~20K
open.bigmodel.cn glm-5.2 1M ~100K

A global value is wrong for all but one model: too small for large-context models (frequent over-trigger), too large for small-context models (context blows up before compression).

Suggested fix: move it to routes.<url>.nudgeGrowthTokens, same pattern as context and protocol:

{
  "routes": {
    "https://chatgpt.com/backend-api/codex": {
      "context": 400000,
      "nudgeGrowthTokens": 50000
    }
  }
}

Implementation: resolveConfiguredNudge(routes, url) with longest-prefix match (mirrors resolveConfiguredContextLimit), then per-request override reqConfig.nudge.growthFloor/growthCap alongside the existing modelContextLimit override in server.ts.

Global compress.nudgeGrowthTokens could remain as a fallback when URL has no override.


2. "check" update mode is unnecessary — keep it clean

The three-state model (auto/check/manual) adds complexity without clear value. The clean design is binary:

  • auto — check + install automatically
  • manual — never check in background; user triggers explicitly when they want to update

"check" (check but don't install) is a middle ground that creates confusion:

  • Web UI "检查更新" button calls /check, but in auto mode runScheduledUpdate actually installs — the button name doesn't match the behavior
  • Users who want "just tell me" can simply leave it on manual and check npm themselves

Removing "check" simplifies: one less state in the config precedence chain, one less UI option, one less mode-dependent code path in runScheduledUpdate.


Also: 🔴 critical hot-reload bug

As noted separately: const config: Config = opts.kernelConfig; at server.ts startup captures the reference once. The PUT/reload handlers reassign opts.kernelConfig = fresh.kernelConfig (new object), but the closure config const still points to the OLD object — so hot-reload of kernelConfig doesn't actually take effect on real requests. The test only checks opts.kernelConfig, not what handle() uses, so it's a false positive.

Fix: read opts.kernelConfig per-request inside handle() instead of capturing at startup, OR mutate in-place (Object.assign) instead of reassigning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants