Commit Graph
103 Commits
Author SHA1 Message Date
rootandClaude Opus 5.5 7862573944 feat(cache): TMDB image proxy, posters, cache admin API and settings cards
GET /img/tmdb/{size}/{file} ported from MP ImageHelper / fetch_image
(sanitized cache path under DATA_DIR/cache/images, GLOBAL_IMAGE_CACHE
read switch, md5 ETag / 304, day-based cleanup job). Cache module adds
cache.sweep / cache.images_clean jobs and /cache/tmdb, /cache/images
list and clear endpoints. Library list/detail and the search palette
show posters with the neutral placeholder as fallback; metadata settings
get TMDB cache and image cache cards. Runbook docs/runbook/cache.md and
porting notes docs/porting/moviepilot-tmdb-cache.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 22:26:29 +08:00
rootandClaude Fable 5.1 a99c77ce4e docs(plan): TMDB response cache in PG, image proxy with disk cache (no Web Cache API)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 21:40:53 +08:00
rootandClaude Fable 5.1 5169529562 docs(plan): cache and rate-limit decisions (PG token bucket, unlogged cache tables, no Redis)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 21:39:25 +08:00
rootandClaude Opus 5.5 cd70a69508 docs(runbook): automation-first agent interaction, plan/options/approval events and E12
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 21:07:01 +08:00
rootandClaude Opus 5.5 d931e75310 docs(runbook): MCP server access and security boundary
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:28:41 +08:00
rootandClaude Opus 5.5 b0e5d539ed feat(auth): TOTP setup endpoint, recovery codes, passkeys and master key rotation
- GET /auth/totp/setup returns the pending secret and otpauth URL (created
  on first call, reused on refresh) for the console to render as a QR code.
- Enabling TOTP issues 8 one-time recovery codes (argon2id hashes in
  admin_recovery_code); login accepts recoveryCode in place of totpCode,
  disable accepts either, and recovery_codes regenerates with the password.
- Passkeys via @simplewebauthn/server: register/list/rename/delete under
  the console session, public login options/verify that reuse the login
  rate limit and session cookies. Challenges are one-time rows in
  webauthn_challenge; RP ID and origins come from WEBAUTHN_RP_ID /
  WEBAUTHN_ORIGINS, falling back to the request host. Signature counter
  regressions are rejected. SessionInfo gains passkeyEnabled.
- --role rotate-master-key re-encrypts the secret table from
  SECRET_MASTER_KEY to SECRET_MASTER_KEY_NEW one row per transaction,
  skips rows already on the new key (resumable, swap keys to roll back),
  logs progress and audits secret.master_key_rotate. Secrets now record
  the master key fingerprint in kdf_params.kid.
- Runbook: recovery codes, passkey configuration, rotation steps and
  rollback.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:22:07 +08:00
rootandClaude Opus 5.5 5c6f483420 feat(agent): agent.spawn{await:true} suspends too; children wake the parent via fact
agent.await and agent.spawn{await:true} now return immediately when
children are still running: the session closes, runAgent registers a
wake signal in agent_run.await_wake and waits with waitForFact without
holding an io/agent worker slot. A child that settles (terminal or
waiting) signals the parent's registered fact, so the parent resumes at
once instead of polling; the suspended call replays and the child
report becomes the tool result. agent.spawn is registered replay-safe;
a suspended spawn is recorded as failed in the ledger so the replay
re-runs it against the same child.

Migration 0037 also adds the admin_recovery_code, admin_passkey and
webauthn_challenge tables used by the account work.

E11 asserts the parent is suspended with no run held by any worker
while it waits, and covers spawn{await:true} end to end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:21:52 +08:00
rootandClaude Opus 5.5 f9b30b7e72 docs(runbook): browser provider setup, takeover rules and real-instance checklist
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:17:46 +08:00
rootandClaude Opus 5.5 62290d4477 docs(runbook): subscriptions C1-A private rule groups, presets, reset and calendar
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:14:40 +08:00
rootandClaude Opus 5.5 52402864d6 style(copy): punctuation rules and site-wide fix with a CI check (QA U11)
- glossary: 10 punctuation rules (full-width in Chinese, CJK/Latin spacing,
  full-width parens around Chinese, single ellipsis, 「」 quotes, period rules)
- scripts/check-copy-punctuation.mjs: checks string literals, templates and JSX
  text (not comments, types, keys, match/compare strings); --fix, --strict,
  --by-file; wired into deno task ci as check:copy in warn mode
- --fix applied to web, server and contracts; files other lanes were editing
  (subscriptions, sites, browser, agent, auth/account, inventory) left for them
- tests updated for the changed messages

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:09:29 +08:00
rootandClaude Opus 5.5 abc69886ea feat(contracts,server,web): files G6–G8 fields and identify S-7 contract
- G6: FileRoot.pendingCount/pendingPartial for download roots (same rule as the
  unidentified filter, recursive, cached 5 min, invalidated by files.changed)
- G7: FileEntry.parsedHint from parseReleasePath (file + parent dirs); the web
  subline uses it and no longer parses names itself
- G8: FileIdentifyCandidate.posterUrl (TMDB poster_path via adapter and
  catalog.lookup, local entities from metadata.posterPath); thumbnails in the
  identify panel
- S-7 contract: FilesIdentifyResult.remoteTaskId/remotePending,
  MediaServerInventory.partial, EventType identify.completed with
  IdentifyCompletedPayload; identify panel (useIdentifyLive) and organize wizard
  merge remote results by root + path, buffering events that beat the response

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:09:29 +08:00
rootandClaude Opus 5.5 fd2f7bc33d perf(server): parallel media-server inventory, queued identify remote lookups, dev DB cleanup
- GET /inventory/media-servers: per-instance Promise.allSettled, per-instance
  concurrency cap (2) and timeout (8s); failed/timed-out instances are unknown,
  response carries partial=true (field not yet in contracts)
- S-7: POST /files/identify returns local matches plus remoteTaskId/remotePending
  and enqueues identifyRemote; the worker runs the TMDB lookups and publishes SSE
  identify.completed {taskId,status,items,truncated,excludedBySize,error};
  ?wait=true keeps the synchronous path, capped at 15s overall
- catalog.lookup / release.search honour the caller's abort signal
- scripts/dev-db-clean.ts: dry-run by default, --yes to drop leftover test
  schemas and w32-/w33-/fe4-/qa- prefixed entities; refuses non localhost:55433
- runbook: dev DB cleanup

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 19:47:41 +08:00
rootandClaude Fable 5.1 5b8927d1dc docs(plan): agent automation-first (drop modes, plan todo, options), tools/MCP visualization
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 19:45:59 +08:00
rootandClaude Fable 5.1 da73015b09 docs(plan): v0.2.1 closeout scope (finish deferred items)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 19:29:36 +08:00
rootandClaude Opus 5.5 2627e4cff3 docs(plan): W10 integration record and visual QA front-end status
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 17:46:04 +08:00
rootandClaude Opus 5.5 363f85b1a1 feat(server,contracts,web): dashboard library counts and engine runs triggeredBy/multi-status filters
- GET /dashboard: automation.library {entities, movies, series, seasons,
  episodes, assets} and automation.slotSatisfiedRate; home media overview
  shows the counts instead of placeholders.
- GET /engine/runs: `status` accepts comma-separated values; new
  `triggeredBy` filter (comma-separated) evaluated server-side by scanning
  batches and paging with the last inspected row's cursor (scan cap 2000).
- Task stream: source filter and the "active" tab (running,pending) are now
  one paginated server query.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:49:11 +08:00
rootandClaude Opus 5.5 04401309fb merge: fe3-web (FE-3 rules page, naming form, global search) into main
Conflicts resolved: routes.ts keeps both /console/status (FE-1) and
/console/search (FE-3); smoke list keeps FE-1/FE-4/FE-5 routes plus the
rules tabs, search results and preferences→rules redirects. Top bar mounts
SearchTrigger and CommandPalette next to the FE-1 inbox bell.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:39:13 +08:00
rootandClaude Opus 5.5 2b8fe667a5 fix(organize,identity,sites,pi): W10-pre backend fixes from v0.2 visual QA
- slot: new manual_verify event (attention -> verifying, with reason); a
  successful organize of a download whose slot is in attention goes back
  through verifying and lands by verify_passed on the actually imported
  assets; the download's organize_blocked decision is resolved with
  resolution {key: manual_organize | organize_retry, organizationRecordId} (U1)
- acquisition: plan purpose is upgrade only when the slot already has a
  current asset; a movie slot gap is a fill (U7)
- identity: entities created from TMDB details get metadata fields projected
  in the same transaction; TMDB aliases deduped by normalized text, site-title
  aliases skipped when the text already exists (U9)
- pi: auth-mode test of a custom Base URL no longer marks the upstream ok, and
  says to use the minimal completion to probe the endpoint (U2)
- sites: PUT /sites/{id}/credentials replaces same-kind secrets in place and
  names new secrets with site id + random suffix (secret.name is unique; was a
  500 on update); M-Team user data uses config/definition apiBaseUrl instead
  of deriving api.<domain> from the site URL (Invalid URL on IP/local bases)
- copy: setup error says 初始化口令; backup job points at umt backup
- tests: schema expected tables add site_user_data; migration round-trip
  timeout 60s; fake secrets honor label as name; vertical/resolve/pi/slot/
  site-center tests for the above
- docs: 09-visual-qa W10-pre status table (U3 root cause: outbox events are
  never mirrored to SSE)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:29:29 +08:00
rootandClaude Opus 5.5 09a6b0b5d3 docs(design): IA-3 implementation notes in console-ia (FE-1)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:10:42 +08:00
rootandClaude Opus 5.5 b908b4a0c9 feat(web): rules page with layer cards, rule-string sync, preview and preferences as tags (FE-3)
- /console/rules tabs: rule groups, custom conditions, defaults, acquisition policies, suppressions
- editor: rule string parsed live via /rules/parse (position + suggestions) and synced both ways with layer cards; hard excludes; expectedRevision conflicts keep local edits
- preview against recent releases or pasted titles with pri / level / reasons / trace
- single-rule groups shown as preference tags; disable/delete writes suppression records
- /console/preferences redirects to /console/rules (origin passed through)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:06:16 +08:00
rootandClaude Opus 5.5 81bf010e3e feat(sources,organize): site agent capabilities and organize.minSizeBytes setting (W10-pre2)
- site.list / site.health_check / site.refresh_login / site.user_data capabilities
  over the W9-A site center services; outputs whitelisted (no secret refs,
  cookies, passwords, login names); execute kinds need automation grant.
  IDs use snake_case (CapabilityId regex); registry count 17 -> 21.
- settings.organize.minSizeBytes (default 50 MiB); file-manager identify /
  organize and planImport take request > setting > port default.
- tests and runbook notes (sites, files).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:02:30 +08:00
rootandClaude Opus 5.5 c08d8ce62a docs(runbook): subscriptions v2 endpoints, matrix, auto-fill and form fields
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:54:29 +08:00
rootandClaude Opus 5.5 99a3e17210 feat(file-manager): suggest-name via naming engine; plan.naming source from override chain (W9-H G9)
- POST /files/suggest-name renders the effective template (entity > root >
  global) with the same variables as organize: file name segment for files,
  work/season dir segment for directories; identity_uncertain when no entity
- planImport plan.naming.templateSource/templateVersion now come from
  effectiveNaming + the registered template version (fixes the leftover
  DEFAULT_TEMPLATES reference after the naming chain landed)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:26:34 +08:00
rootandClaude Opus 5.5 8651a35594 feat(organize): naming endpoints and override chain for target paths
- GET /naming/variables, POST /naming/preview (builtin/fileName/sourceRelease/asset samples,
  line:col errors, warnings, binding-aware), GET/PUT /naming/templates,
  PUT /library-roots/{id}/naming, PUT /media-entities/{id}/naming-override
- planImport picks templates entity > library root > global, registers the template
  version for new path bindings; naming vars include en title, external ids, season/
  episode metadata, slot and root names; optional lock of file-name template for bound works
- runbook: docs/runbook/naming.md

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:25:08 +08:00
rootandClaude Opus 5.5 238445a258 docs(plan): v0.2 visual and interaction QA report
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:24:49 +08:00
rootandClaude Opus 5.5 e8745115f4 feat(system): process heartbeat + /system/health, engine runs business fields (W9-I)
- process_heartbeat / process_heartbeat_sample (0034): api / worker / worker:agent / all
  upsert every 15s (event loop lag last/max, concurrency, running runs, SSE connections, memory)
- GET /system/health (admin): processes with 45s stale flag, SSE, DB latency/size/connections,
  disks (DATA_DIR / library roots / download dirs, cache thresholds), mount sentinel checks
  with IO timeout, engine pending/oldest/24h failure rate, schedules
- GET /system/health/history?hours=: bucketed lag / running / SSE series
- /engine/runs and /engine/runs/{id}: business {kind, refId, title, triggeredBy} joined from
  run input / task / agent_run / tasks_run_meta / outbox; businessKind / businessRefId filters
- docs/runbook/ops.md: field meanings and alert thresholds

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:23:37 +08:00
rootandClaude Opus 5.5 51c3196311 docs(runbook): sites (site center endpoints, login states, jobs, defaults)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:18:40 +08:00
rootandClaude Opus 5.5 d28686ed02 docs(rules): runbook for rule groups, keywords, endpoints, deprecated aliases and differential
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:08:44 +08:00
rootandClaude Opus 5.5 f0b3a10564 docs(runbook): file manager v2 backend gaps G1-G9
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:08:18 +08:00
rootandClaude Opus 5.5 a0946bf480 feat(search): global search aggregation backend (W9-G)
- GET /search?q=&scope=all|media|releases|actions&limit=: local works (title_alias
  exact/prefix/trgm + name prefix, slot status summary), TMDB candidates (cached,
  localEntityId), cross-site releases, page/action jump list; tookMs per group
- cross-site: enabled sites via shared per-site limiter, 15s AbortSignal timeout,
  site concurrency cap 4, same-query coalescing, 30s cache; partial + failedSites;
  results upserted to source_release; inventory overlay via GET /inventory
- GET /search/releases: site/resolution/source/size/free/H&R filters, sort, cursor,
  facets; shares the cache
- POST /search/releases/{siteId}/{siteReleaseId}/plan: forwards in-process to
  POST /acquisition-plans (same auth, validation, audit, rejections)
- contracts/search.ts, runbook, tests (partial/timeout, coalesce, cache, overlay,
  filters/sort, plan)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 15:05:58 +08:00
rootandClaude Fable 5.1 e0c0c4f51d docs(plan): IA-3 final (unified tasks, schedules as plan tab, 12 nav items)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:59:03 +08:00
rootandClaude Fable 5.1 e7ef97e31f docs(plan): system group convergence (settings / schedules / run logs)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:56:06 +08:00
rootandClaude Fable 5.1 5cf1a462e8 docs(design): file manager v2 spec vs MoviePilot (52 feature points)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:51:28 +08:00
rootandClaude Fable 5.1 22856d0447 docs(plan): global search entry (MP-style)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:44:47 +08:00
rootandClaude Fable 5.1 c2f3078062 docs(plan): IA-3 final nav per user feedback; file manager second pass
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:43:13 +08:00
rootandClaude Fable 5.1 381791cd64 docs(plan): IA-3 nav convergence (merge download/organize, drop identity page)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:39:24 +08:00
rootandClaude Fable 5.1 521063c7aa docs(design): subscription redesign, unified rules and naming template specs
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:38:43 +08:00
rootandClaude Fable 5.1 8cad83e8f5 docs(design): site center spec (sites page as single entry, credentials, user data, dashboard)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:32:42 +08:00
rootandClaude Fable 5.1 911a810da5 docs(plan): v0.2.1 adds subscription redesign, unified rules, naming templates
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:28:43 +08:00
rootandClaude Fable 5.1 60a95cf93e docs(plan): v0.2.1 direction (site center, dashboard per MP)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 14:25:04 +08:00
rootandClaude Opus 5.5 83498f9738 docs(plan): v0.2 closeout (W8-A) fixes and remaining gaps
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 13:45:47 +08:00
rootandClaude Opus 5.5 3e37ac8ae7 refactor(agent): runAgent uses Agent upstreams only; deprecate legacy settings.pi fields
pi.provider / baseUrl / model / thinkingLevel / apiKeySecretRef are now
DEPRECATED_SETTINGS_FIELDS: kept in the schema for stored JSON, dropped
from PATCH /settings and from the settings sections, never read by the
server. runAgent fails with a clear message when no upstream is set.
The agent demo gate checks the default upstream provider; e2e seeds a
fake upstream as default. OpenAPI summaries say Agent upstream.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 13:45:40 +08:00
rootandClaude Opus 5.5 a0b0a64246 refactor(schedules): register pi.token_refresh and auth.cleanup as scheduled jobs
Pi token refresh (10 min) and auth session cleanup (1 h) no longer run
their own setInterval; both register in the maintain group of the
schedules registry with the same default intervals.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 13:44:48 +08:00
rootandClaude Opus 5.5 31a54186c7 copy: second-round copy review across console, settings, agent and server messages
- Trim descriptions, empty states, confirm buttons and toasts to facts
- Unify terms per glossary: 待处理/待识别/整理记录/运行记录/凭证/子会话/Agent 上游
- Subscription-login termsNote states facts only (borrowed client identity, ToS/ban risk)
- Shorter, concrete goal templates for built-in Agent checks
- Human-readable nouns instead of table names in instance CRUD errors
- Audit labels for pi_upstream / schedule / automation_grant actions
- Glossary: add 上游、订阅登录、凭证、定时任务、巡检、运行记录、子会话、停止、持续授权

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 13:29:42 +08:00
rootandClaude Opus 5.5 c67f6a9682 feat(web): settings with 9 sidebar sections and Agent upstream management
- /console/settings#<section>[/<anchor>]; legacy ?tab= redirected in clientLoader
- SETTINGS_SECTIONS in contracts with field-ownership test
- Agent section: upstream list, create wizard (provider -> credentials/model -> login/test/default),
  edit drawer with OAuth browser/device login, test, set default, delete
- sites section with site registration, snapshot/rate-limit drawer and account credentials
- path mappings moved into downloader / media-server drawers; metadata and account sections

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 03:05:51 +08:00
rootandClaude Opus 5.5 459991421e feat(agent): Pi subagents via agent.spawn / agent.await
- agent_run gains depth / spawn_reason (0029); agent_run_event types
  subagent_spawned / subagent_event / subagent_completed
- agent.spawn (propose, medium, replay never): allowlist ⊆ parent, mode not
  above parent, budget carved from parent's remainder, idempotent per run+input;
  settings.pi.subagents {enabled, maxConcurrent, maxDepth} (subagentsEnabled kept as alias)
- child runs claim a concurrency slot under an advisory lock (waitForFact while
  queued); agent.await polls business tables without calling the model
- parent abort cascades to all descendants; parent runtime budget counts
  descendant usage; child events mirrored into the parent stream by parent seq
- authorize caps every child call by all ancestors' allowlists/kinds
- session page shows parent link, inherited info and the subagent tree
- e2e E11; runbook section on subagents

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 02:49:37 +08:00
rootandClaude Opus 5.5 11c8cd4e0e docs(design): console IA implementation table (IA-1)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 02:47:10 +08:00
rootandClaude Opus 5.5 a6402c3aed docs(runbook): scheduled jobs registry, board and agent checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 02:33:20 +08:00
rootandClaude Opus 5.5 f0386af319 docs(runbook): Pi upstreams and subscription login
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 02:23:22 +08:00
rootandClaude Fable 5.1 16ab2a6c84 docs(plan): v0.2 adds Pi subagents and scheduled-jobs board
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-28 02:09:39 +08:00