Skip to content

release: v1.4.3 — live speed (#93), domain export (#54), LOG_LEVEL (#80); agent GitHub token (#77) - #99

Merged
foru17 merged 16 commits into
mainfrom
codex/v1.4.3
Oct 9, 2026
Merged

foru17 merged 16 commits into
mainfrom
codex/v1.4.3

Conversation

@foru17

@foru17 foru17 commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Release v1.4.3 (collector/web) and agent-v1.4.8.

Added

Fixed (found while verifying #93)

  • Totals dipped on every flush. After a flush, the cached persisted summary was combined with the already-cleared realtime deltas, so the live totals briefly lost one flush interval of traffic. Both caches are now invalidated when realtime is cleared. This covers the mihomo, Surge and agent paths.
  • WS pushes from an old range. Stats pushes now carry the range they were computed for. The client drops pushes for another range and clears its last message on disconnect.

Verification

  • Automated checks:
    • collector: tsc, lint, vitest (185 tests)
    • web: tsc, next build, lint (trend-chart now 0 issues; web total 110 errors vs 111 on main)
    • agent: go vet, go test, sh -n and dash -n
  • E2E against a mock mihomo controller sending 2.25 MiB/s:
    • Cards read 2.25 MB/s, including across 30m, 7d and 24h switches.
    • The speed chart is flat at 2.25 MB/s, with no dip at the right edge.
    • WS totals stayed consistent over 3 flush cycles.
    • The exported file matches the panel.
    • LOG_LEVEL=error reduced collector log lines from 24 to 0.
  • Rate tracker scenarios: range or backend switches, first load, and reconnects after 20s, 60s and 600s down all stay at the true rate.
  • UI acceptance: desktop, mobile and dark mode all pass.
  • Reviews: fable-reviewer PASS on the second re-review.

🤖 Generated with Claude Code

foru17 and others added 16 commits October 9, 2026 09:29
…chart (#93)

- Download/Upload cards show the current rate, derived from successive
  summary totals averaged over a 15s window. Shown only for live presets;
  the window restarts when the rolling range shifts and is cleared when
  the backend changes, so a moving window never yields negative or huge
  rates. Stale readings expire after 30s.
- The trend chart gains a Traffic / Speed toggle; speed is bytes per
  bucket divided by the bucket length, with B/s units on axis and tooltip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex (gpt-6-astra) <noreply@openai.com>
… retries (#77)

Co-Authored-By: Codex (gpt-6-astra) <noreply@openai.com>
Co-Authored-By: Codex (gpt-6-astra) <noreply@openai.com>
The request is about domains hit by a proxy or rule, which live in the
shared DomainStatsTable of the rule, proxy and device detail views. Add
the export button there too; it exports the full filtered, sorted list
(not just the current page) named after the rule, proxy or device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The newest trend bucket is still filling, so dividing it by the full
bucket length under-reported the current speed. Divide by the time up to
the query end instead (at least 60s, since the end is minute-rounded).
Speed axis ticks use one decimal and a wider axis so labels aren't clipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The query end is minute-rounded, so the newest bucket was still
under-reported. A 5s clock (state set from a timer, not during render)
gives the elapsed time of the bucket that is still filling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The newest bucket keeps receiving bytes for a while after it starts, so
any rate computed from it dips at the right edge. Speed mode now plots
completed buckets only; the live rate is shown on the stat cards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…token

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…93)

Queries keep the previous data while a new window or backend loads, so
the first totals after a switch belonged to the old window. Using them as
the baseline turned the jump to the new totals into GB/s readings for up
to 15s (review B1). The tracker is now a pure stepRateTracker() that holds
back those totals until they change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- get_latest_remote_tag now returns non-zero on failure, which under
  set -eu exited before the 'pin a version' hint; fall back to an empty
  tag so the hint is printed (#77).
- LOG_LEVEL= (empty) is treated as unset instead of warning (#80).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#93)

On first load the HTTP summary carries persisted totals only, while WS
pushes also include the realtime buffer, so the first delta read ~4x the
real speed in the browser. After a switch the tracker now also holds back
the first fresh totals and starts sampling on the next change. A 5s
minimum span damps push-timing jitter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…flushed

Persisted totals are cached (DB range cache 8s, WS base summary 2s) while
realtime deltas are cleared right after each flush. Until those caches
expired, 'cached persisted + realtime' missed a whole flush interval, so
the live Total Download/Upload cards dipped by ~30s of traffic every flush
and jumped back on the next push (seen while verifying #93).

RealtimeStore now notifies onCleared(); the entry point drops the DB range
cache and the WS base-summary cache for that backend. This covers the
mihomo, Surge and agent flush paths, which all clear through the store.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Track 'has ever received data' in state (adjusted during render)
  instead of reading a ref during render.
- Hoist the tooltip into a module-level component so it is not recreated
  on every render.
- Widen the traffic-mode Y axis so 3-digit MB labels are not clipped.

Brings trend-chart.tsx from 7 lint errors (1 on main) to 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review B2: after a reconnect the dashboard briefly showed the last push
from before the disconnect, while HTTP fallback had already moved the
totals forward. That stale value became the rate baseline and the whole
outage was spread over a few seconds (about 11x after 60s down).

- websocket: clear lastMessage on close; stats pushes now carry the range
  they were computed for (captured before the async query) and the client
  drops pushes for another range.
- transfer-rate: within one window totals never decrease, so a lower
  reading is ignored instead of becoming a new baseline.
- collector: reuse clearBackendCache for the flush invalidation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T03:03:22.081660Z 55f353c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 55f353c10c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/agent/nekoagent
tag="$(curl -fsSL "$api_url" 2>/dev/null | awk -F'"' '/"tag_name"/{print $4}' | grep '^agent-v' | head -1)"
set -- -fsSL --connect-timeout 10 --max-time 120 --retry 3 --retry-delay 2
if [ -n "$token" ]; then
set -- "$@" -H "Authorization: Bearer $token"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep GitHub tokens out of downloader arguments

When GITHUB_TOKEN or GITHUB_PAT is set, the literal bearer token is expanded into the curl or wget argument list. During a slow or retried API request, another local user or process monitor can read the downloader's command line and recover the token, which may be a broadly scoped PAT. Pass the header through a protected config file or another non-argv channel; the same exposure is duplicated in install.sh.

Useful? React with 👍 / 👎.

Comment on lines +211 to +215
const scale = mode === "speed" ? bucketSeconds : 1;
return {
time: point.time,
download: point.download,
upload: point.upload,
download: point.download / scale,
upload: point.upload / scale,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude partial boundary buckets from speed mode

When a query boundary is not aligned to bucketMinutes—for example, a normal 24-hour range ending at :03 with ten-minute buckets—the repository groups only the included minutes into the first boundary bucket, but this code divides that partial total by the full bucket duration. The first displayed speed is therefore systematically low, and historical ranges can similarly include a partial final bucket. Exclude both clipped boundary buckets or divide them by their actual covered duration.

Useful? React with 👍 / 👎.

Comment on lines +385 to +389
onClick={() =>
downloadTextFile(
getDomainsExportFilename(ruleName || sourceChain || sourceIP || title || "domains"),
filteredDomains.map((item) => item.domain).filter(Boolean),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fetch every matching domain before exporting

For a rule, proxy, or device with more than 5,000 associated domains, filteredDomains contains only the bounded detail-query result (QUERY_CONFIG.LIMIT.DETAIL is 5,000), so this button silently exports a truncated rule set. The IP expansion path has the same issue and is capped by its controller at 2,000 domains. Paginate or use a dedicated export endpoint so the downloaded file contains the complete matching set.

Useful? React with 👍 / 👎.

@foru17
foru17 merged commit 55f353c into main Oct 9, 2026
9 checks passed
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.

1 participant