Turn the lightpanda-backed fetch service on, bump worker concurrency to
3, and add baidu.com plus weixin.sogou.com to the allowed domains so the
knowledge URL fallback can resolve those sources without a config edit.
Postgres rejects FOR UPDATE on the nullable side of a LEFT JOIN, which
made LeaseNextQueuedDesktopTask fail under contention. Replace the join
with a NOT EXISTS subquery, scope the row lock to the dt alias, and add
a regression test plus warn-level logging on lease query failures so
similar issues are easier to diagnose.
Map dongchedi adapter failures (raw "server exception" or
dongchedi_platform_exception) to a Chinese prompt steering the user to
the dongchedi backend, so renderer/admin views and desktop-task error
payloads no longer surface the opaque platform message.
The state-consistency worker now detects articles still flagged as
generating whose latest generation_task is already failed or completed
(with a version) and aligns the article status to the terminal task,
invalidating article caches on the way out. Adds supporting partial
indexes and switches UpdateGenerationTaskStatus to COALESCE started_at
and completed_at so partial status updates don't wipe the timestamps.
Adds a new browser-fetch microservice that wraps Lightpanda for rendering
JS-heavy pages, and wires it into the knowledge URL parser as a fallback
when the upstream link reader returns 403/429/5xx for an allow-listed
domain (e.g. zhuanlan.zhihu.com). Includes config/env plumbing, hot-reload
diff support, and full deploy assets (Dockerfile target, docker-compose,
k3s manifests, image-build/package scripts).
Refactor readDeepseekAccountIdentity so the JSON payload parser is a pure
ts function (extractDeepseekIdentityFromPayload). The webContents IIFE now
just polls for userToken and returns the raw API JSON; payload picking lives
in ts and is unit-tested.
Tests lock the contract for both login types we observed in the wild:
- WeChat-bound account: id_profile.name = '阿白', picture present.
- Phone-only login: id_profile = null, mobile_number = '177******08',
email = '' (empty string, not null) — the case that originally regressed.
Plus regressions for the priority order (profile.name > mobile_number > email),
the all-empty fallback, and non-record payloads.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the broad path filters that triggered the desktop client build on
unrelated workspace changes, and add a swagger description for the
existing article regenerate endpoint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Poll the knowledge item list every 5s while any item is still pending
or processing so the UI reflects ingestion progress without manual
refresh, and exclude items that have no active chunks from group
counters so groups with no usable content do not appear populated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expose tenant-authenticated publish task list and retry endpoints so the
admin web can show desktop publish state without an Electron bridge, and
register a `shengxintui://` deep-link so the page can hand off to the
desktop client workbench.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Why: prior migration created the workspace identity unique index without
client_id, so accounts on the same workspace+platform+uid couldn't coexist
across desktop clients. Also drop the legacy uk_platform_accounts_identity_active
index so re-runs are idempotent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Scope desktop media accounts by the authenticated desktop client_id so
the same user logging in from Mac and Windows no longer sees a shared
account list. The list, identity lookup, upsert, patch, tombstone and
async health sink paths now all require matching client_id, and the
active uniqueness index moves from (workspace, platform, uid) to
(workspace, client, platform, uid).
Also strengthen the desktop client_id seed: when the OS machine id is
unavailable, fall back to a hashed fingerprint of stable hardware MAC
addresses before the random installation id, so the same hardware
keeps the same client across reinstalls.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- admin-web vite dev server now proxies websockets on /api so live
features (e.g. SSE/WS) work in development.
- Tenant desktop publish compliance recheck now logs warnings when the
query, scan or row iteration fails so the silent 50118 errors can be
diagnosed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Provide a unified ops console for inspecting, retrying and cancelling
jobs across generation, template/kol assist, knowledge parse, desktop
publish/task, compliance review and monitoring collect sources. Wires
RabbitMQ for retry republish and consolidates the desktop_publish_jobs
columns into the base migration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Restrict account tracking, probing, and health reporting to accounts owned
by the current client (client_id match). Extend identity-match verification
to bilibili, juejin, and smzdm so session validity is confirmed locally
rather than deferred to remote health state. Server-side account view now
uses stored client_id as authoritative owner instead of presence data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- shared/cache: add Options/L1/async/metrics/prefix decorators, multi-key ops, Redis pool tuning, and JSON readthrough metrics
- worker-generate: claim tasks via DB lease + heartbeat, requeue stale queued tasks, expire dead leases with refund/cache invalidation
- tenant: version article cache keys so worker recovery invalidations propagate cleanly
- shared/config: expand Redis (pool/timeouts/TLS) and Generation (lease/recovery) configs with defaults
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Admin login-lock reset now SCANs and clears all auth:login:* keys (any
scope) and surfaces redis_deleted_keys / fallback_deleted_keys back to
ops-web so the operator can tell whether the cache was actually hit.
Also tracks paired keys via a per-identifier index plus an unlock marker
so legacy/in-flight pair locks get cleared on the next acquire.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Increase default main window size from 1320x860 to 1420x960
- Use transparent titlebar overlay for all window modes
- Remove hardcoded CONFIG_PATH from dev-ops-api make target
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Translate all login error messages to Chinese (network errors, HTTP
status codes, URL validation errors)
- Add password visibility toggle (eye icon) to login form
- Add live countdown timer when login is locked, disable login button
during cooldown, auto-clear error when countdown ends
- Add X button red hover feedback in server settings dialog
- Add LoginGuard.Unlock() method to clear Redis lock/failure keys
- Expose POST /admin-users/:id/reset-login-lock endpoint in ops API
- Add "重置登录保护" button in ops-web user management table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace generic "METHOD path" summaries with curated Chinese summaries
and longer descriptions, surfaced in Swagger UI. Adds a parity test that
fails when a new tenant-api route is wired up without a docs entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Updated dompurify from 3.3.3 to 3.4.2
- Updated axios from 1.14.0 to 1.15.2
- Updated Go module github.com/golang-jwt/jwt/v5 from v5.2.1 to v5.2.2
- Updated Go module github.com/jackc/pgx/v5 from v5.5.5 to v5.9.0
- Updated Go module github.com/redis/go-redis/v9 from v9.5.1 to v9.7.3
- Updated Go module github.com/stretchr/testify from v1.9.0 to v1.11.1
- Updated various golang.org/x modules to their latest versions
- Updated google.golang.org/grpc from v1.66.0 to v1.79.3
- Updated google.golang.org/protobuf from v1.34.2 to v1.36.10
os.WriteFile truncates then writes, so inotify can deliver back-to-back
MODIFY events while the file is momentarily empty. Reading mid-sequence
made TestStoreReloadsWhenLocalOverrideIsCreated and
TestStoreReloadsConfigAndKeepsPreviousOnInvalidYAML flake on Linux CI by
firing onReload with a blank config before the write settled.
Coalesce updates over a 50ms quiet window before reloading, and skip
onReload when the diff is empty so subscribers only see real changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add POST /api/tenant/knowledge/items/retry/:id to re-queue failed parse
tasks, plus a 20-rune cap on text item names with matching frontend
validation. Wires the retry button into the knowledge table with a
colored status tag for clearer state feedback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A fresh production environment only ran migrations, so the four built-in
platform templates were never inserted unless someone manually ran
dev-seed (which also writes broad demo data). Extract the platform
template upsert into a reusable repository.EnsurePlatformTemplates and
add a standalone cmd/seed-platform-templates that calls it. Bake the
binary into the migrate image and chain it after migrate up in both
docker-compose and the k3s migration job (mounting app config so the
binary can dial the right database).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "platforms" stat tile was a constant (5) that never reflected what the
tenant actually had set up. Drop SupportedPlatformCount from the workspace
overview API/domain/shared-types and have admin-web compute a bound media
account count from the desktop accounts list, filtered through a new
isMediaPublishAccount helper that excludes deleted rows and AI-only
platforms (yuanbao/kimi/wenxin/deepseek/doubao/qwen).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace single Load() with a watching Store that re-reads config files
(and config.local.yaml) and fans out a ReloadEvent with a per-field diff
so consumers can decide whether the change is hot-applicable or requires
a process restart.
- Wrap llm, retrieval, vector store, and object storage clients in
Reloadable* shells so the bootstrap can swap their underlying impls when
config changes without re-instantiating handlers.
- Make jwt.Manager and ops TokenIssuer mutable under a lock so secrets and
TTLs can be rotated live; thread default plan code through a setter on
the ops AdminUserService.
- Wire ConfigStore through bootstrap and every cmd/main.go, scheduler /
worker / tenant-api / ops-api start the watcher; services and handlers
take a config.Provider so they always read current values for things
like generation.stream_enabled, scheduler dispatch, retrieval, etc.
- Switch shared/config decoding off viper to a Kratos-derived runtime
package so env placeholders (\${VAR:default}) resolve consistently and
the same source machinery powers both the loader and the watcher.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the domain+title fuzzy alias scoring with a canonical
candidate-key index built from published-link aliases — only exact
matches now resolve to a SaaS source, eliminating false positives
across articles sharing a host (e.g. m.163.com vs www.163.com).
Surface the summary scoping that already existed on loadCitationRanking
/ loadCitedArticles by accepting brand_id, keyword_id, ai_platform_id
and business_date on CitationSummary, plumbing them through the handler
and admin tracking view.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update server titles, web/desktop window/tray/document titles, login
copy, and electron build metadata to use the Chinese product name 省心推.
Drop the runtime locale switcher and en-US import — the app now ships
zh-CN only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The target-platform supplement only fed legacy prompt builders that read
the now-removed wizard_state platforms field. Drop the YAML entry,
loader struct field, and runtime helper.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the freeform `platforms` field on articles/tasks (parsed out of
wizard_state/input_params JSON) with `auto_publish_platforms`, resolved
by joining schedule publish accounts to platform_accounts. The migration
strips the legacy keys from existing rows so the new field is the single
source of truth.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an in-process Swagger UI and OpenAPI JSON under /swagger,
registered automatically when the Gin mode is not release. The
admin-web Vite dev server and production nginx config now proxy
/swagger to the tenant API so the docs are reachable from the
existing admin host.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build https://www.163.com/dy/article/<docId>.html when wangyihao tasks finish, and normalize publish-record responses + monitoring alias inputs to surface the same public URL when the doc id is known.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>