Commit Graph
289 Commits
Author SHA1 Message Date
rootandClaude Opus 5.5 d13c18b4b1 feat(cache): capacity LRU for image cache (CACHE-2)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 17:16:50 +08:00
rootandClaude Opus 5.5 85b352b8eb feat(cache): read cache TTLs from storage settings and renew tracked TMDB details (CACHE-2)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 17:16:50 +08:00
rootandClaude Opus 5.5 58e358e4a9 feat(settings): storage budgets, retention days and cache TTL settings (CACHE-2)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 17:16:50 +08:00
rootandClaude Fable 5.1 c3aaf901ad docs(plan): ID-2 identity matching parity, FE-6 tasks/plan split, CACHE-2 storage budget
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 16:46:45 +08:00
rootandClaude Opus 5.5 d0da4f4add docs(plan): INT-2 integration record and shared-index lesson
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 16:45:44 +08:00
rootandClaude Opus 5.5 04cffcd1f1 feat(sites): on-demand site detail page content (INT-2)
- SiteReleaseDetail.page: description, MediaInfo/BDInfo, screenshots,
  IMDb / Douban / TMDB ids, file list, tags, uploader, plus a parse probe
  (labels found) for layout-change diagnosis. Generic NexusPHP rules
  (field label -> next sibling) starting from the MovieClaw detail
  selectors; site overrides under umt.detail.page (HHClub: div labels).
  M-Team builds the same structure from descr BBCode + mediainfo.
- Fetched only on demand (drawer open without cache, "复核详情",
  release.inspect); content in kv_cache region site.detail for the
  site detail cache period (>= 24 h); within the window the site is not
  requested again. External ids persist in source_release.raw._detail,
  which list snapshots do not overwrite.
- Screenshots only as proxy paths /api/v1/img/site-detail/{rid}/{i}:
  public-address check on every hop, no site credentials, magic-byte
  image check, 8 MB cap. Poster proxy shares the same helper.
- Identity: site ids count as explicit-id evidence; when TMDB is
  queried, a TMDB id goes straight to details and an IMDb id to
  /find (no title search on a hit). Douban only for local recall.
- Release drawer "站点详情页" section; fixtures and tests for HHClub div
  layout, rowhead layout, BBCode, cache/proxy/identity end to end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 16:21:17 +08:00
rootandClaude Opus 5.5 6e9e8efec2 fix(sites): HHClub parsing, resource list layout and request restraint (re-landed)
Re-lands 901b01d, which was reverted wholesale by 28974d1 (BR-2 committed
from the shared index). The agent UI files 901b01d had rolled back are
left at their AGUI-2 versions; contracts, routes, db types and the runbook
part already reached main through later commits, so this carries the rest.

HHClub (憨憨) was checked read-only against a real account (one detail
request; list, user data and health came from the product's own fetch).

Parsing fixes:
- list titles carried the site's new-torrent marker "[新]" (58 of 100
  rows; the detail page title has none); stripped with a replace filter
- refreshing a detail overwrote seeders / leechers / snatched / category
  name / H&R with null because the HHClub div detail page lacks them;
  detail values now fall back to the list snapshot (mergeDetailOverList),
  and an unknown detail promotion keeps the list promotion
- level "贵宾" is VIP (umt.vipLevels)
- sanitized minimal fixture HHANCLUB_LIST_PAGE_2026 + tests; README marks
  HHClub as verified 2026-09-29
Size, counts, category ids/names, +08:00 time and subtitle were correct.

Request restraint:
- site definitions may carry umt.defaults; merged with settings.sites
  (longer intervals, fewer pages): new settings defaultSnapshotMaxPages 1,
  defaultHealthCheckIntervalSec 6 h, defaultDetailCacheSec 24 h; default
  burst 2. HHClub: snapshot 60 min page 1 only, health 6 h, search
  concurrency 1, detail cache 24 h, 1 token / 3 s burst 2
- periodic / manual snapshots are capped to that page count; scheduled
  health checks skip sites checked within the interval; detail refresh is
  served from cache inside the window; live searches on one site queue
- every rate-limiter token is counted per site per hour
  (site_request_count, migration 0046); GET /sites/{id}/request-stats;
  site overview and resource list show requests in the last 24 hours

Resource list: two-layer rows. Main line: title + spec tags (episodes,
resolution, source, codec, HDR, group, 国语/中字, site tags) + promotion
with time left + H&R. Second line: subtitle (one line, ellipsis) and
fixed-width category / size / seed-leech-snatched / upload time
(relative, absolute on hover) columns, stale badge, inventory overlay;
folds into a card on phones.

Also aligns identity_candidate.normalized_title order in db types with
the migrations (schema drift test).

Takes effect after the stack is rebuilt (migration 0046).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 16:00:34 +08:00
rootandClaude Fable 5.1 99e335d13c docs(plan): META-1 follow-up (broaden enrichment sources)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 15:58:56 +08:00
rootandClaude Opus 5.5 f4666a4671 feat(identity): web metadata enrichment for titles missing on TMDB (META-1)
- metadata.enrich (propose, low, replay safe): normalized-title cache (kv_cache
  region enrich, 7 days) -> daily budget -> web.search (title + 短剧 / 电视剧 平台,
  second query limited to whitelist via site:) -> web.fetch of up to 3 relevant
  whitelisted pages (registered site domains never read, redirects out of the
  whitelist dropped) -> upstream model extraction with rule fallback -> server-side
  evidence check (rule_confirmed / multi_evidence / needs_review). Suggestion only.
- POST /identity-pool/{id}/enrich (suggest) and /enrich/apply (console session):
  provisional entity or same-title merge, season/episode units, field-level
  metadata with source web/agent + evidence, aliases, release assignment.
  Poster proxy GET /img/enrich/{id} (og:image from whitelisted pages only).
- Auto-enrich once per pool entry when subscription/rule lookups find nothing on
  TMDB (identity.autoEnrich, off by default); identity.enrichDailyBudget,
  identity.enrichDomains settings; web.fetch now returns og:image.
- Pool sheet "元数据补全" section; entity detail shows evidence links.
- Migration 0049_enrichment (metadata_enrichment, metadata_field.evidence, source
  web). Requires image rebuild / api + worker restart to take effect.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 15:57:48 +08:00
rootandClaude Opus 5.5 18a5cf1de7 feat(search): two-stage search, site search defaults, TMDB work page (SEARCH-2)
The code for this change landed in ac47867 by accident (a parallel
docs commit swept up the staged index); this empty commit records it.

- Search first lists works (local ledger + TMDB, merged, local first)
  with library comparison (not collected / tracked / owned, slot
  satisfaction and gaps, downloading); /search scope=all no longer
  queries sites. Emby comparison via /inventory/media-servers, which
  now also accepts tmdbType + tmdbId.
- "Search releases" on work cards and detail pages opens a site
  picker (default / all / chosen, remembered per browser) and calls
  /search/releases?entityId|tmdb&sites=; the server builds query terms
  (original title + year, translated title), caches per (site, term),
  and queues unresolved hits for identification with trigger=search.
- site.search_default (migration 0048, default true) with toggles on
  site cards and the edit sheet; settings.search.defaultSiteMode.
- GET /media/tmdb/{type}/{id} and /console/media/tmdb/:type/🆔
  TMDB info, seasons, local/Emby comparison; subscribe (form prefilled,
  entity created on save), search releases, create entity only.
  Subscribe is no longer offered in search results or the command
  palette, which now opens the work page.

Requires rebuild/restart (migration runs on start).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 15:43:55 +08:00
rootandClaude Opus 5.5 28974d1e1a feat(browser): unify site credentials with browser profiles (BR-2)
- Inject the site account Cookie (manual + auto-login session, session wins)
  into the camofox profile before the first tab opens; password accounts
  without a session run refresh-login first; API Key sites are skipped.
- Cookie expired after injection -> credential.status=expired; cookie
  accounts go to waiting/login_required ("log in once, applies site-wide").
- Write back site-domain cookies from the browser on handover, session close,
  every 10 min of activity, and from refresh-login when the stored cookie is
  invalid (verified before saving). user_info.cookieOrigin records
  source=browser; source shown as manual/login/browser in the origin view.
- New camofox plugin umt-cookies (GET/POST /umt/sessions/:userId/cookies
  under the access key); profile dir 0700/files 0600 in the desktop image.
- Single entry: sources-identity/service/credentials.ts.
- Real check: HHClub cookie injected into a fresh profile -> home page
  logged in (logout link present), 5 cookies read back.

Requires rebuilding umt-browser-desktop (docker compose build camofox &&
docker compose up -d camofox) to take effect.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 15:25:07 +08:00
rootandClaude Opus 5.5 901b01d1a1 fix(sites): HHClub parsing, resource list layout and request restraint
HHClub (憨憨) was checked read-only against a real account (one detail
request; list, user data and health came from the product's own fetch).

Parsing fixes:
- list titles carried the site's new-torrent marker "[新]" (58 of 100
  rows; the detail page title has none); stripped with a replace filter
- refreshing a detail overwrote seeders / leechers / snatched / category
  name / H&R with null because the HHClub div detail page lacks them;
  detail values now fall back to the list snapshot (mergeDetailOverList),
  and an unknown detail promotion keeps the list promotion
- level "贵宾" is VIP (umt.vipLevels)
- sanitized minimal fixture HHANCLUB_LIST_PAGE_2026 + tests; README marks
  HHClub as verified 2026-09-29
Size, counts, category ids/names, +08:00 time and subtitle were correct.

Request restraint:
- site definitions may carry umt.defaults; merged with settings.sites
  (longer intervals, fewer pages): new settings defaultSnapshotMaxPages 1,
  defaultHealthCheckIntervalSec 6 h, defaultDetailCacheSec 24 h; default
  burst 2. HHClub: snapshot 60 min page 1 only, health 6 h, search
  concurrency 1, detail cache 24 h, 1 token / 3 s burst 2
- periodic / manual snapshots are capped to that page count; scheduled
  health checks skip sites checked within the interval; detail refresh is
  served from cache inside the window; live searches on one site queue
- every rate-limiter token is counted per site per hour
  (site_request_count, migration 0046); GET /sites/{id}/request-stats;
  site overview and resource list show requests in the last 24 hours

Resource list: two-layer rows. Main line: title + spec tags (episodes,
resolution, source, codec, HDR, group, 国语/中字, site tags) + promotion
with time left + H&R. Second line: subtitle (one line, ellipsis) and
fixed-width category / size / seed-leech-snatched / upload time
(relative, absolute on hover) columns, stale badge, inventory overlay;
folds into a card on phones.

Also aligns identity_candidate.normalized_title order in db types with
the migrations (schema drift test).

Takes effect after the stack is rebuilt (migration 0046).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 15:18:15 +08:00
rootandClaude Opus 5.5 20b63db254 feat(agent): in-drawer history tab and denser session layout (AGUI-2)
- Drawer tabs 当前/历史: searchable run list (status/source/time filters,
  cursor auto-load), opens runs inside the drawer, keeps scroll and filters,
  remembers the last tab; 在页面打开 is secondary
- Ended runs: append to resume, or 用同目标新建 with 先看方案再执行 toggle
- Session page: 88ch conversation column, turns grouped with one timestamp,
  tool cards collapse to one line, 3+ activities fold; steps/subagents/budget
  moved to a right rail (collapsible overview bar on narrow screens and in
  the drawer), long model reports fold behind 展开全文
- Smoke covers the drawer history flow

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 15:17:37 +08:00
rootandClaude Fable 5.1 ac478673bc docs(plan): on-demand site detail page parsing (HHClub details.php)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 15:13:35 +08:00
rootandClaude Opus 5.5 94fd48bff2 feat(identity): lazy TMDB lookup and bounded identity pool (DEC-1)
RSS/list releases that match no subscription or local work no longer hit
TMDB or open a pending item; they go to the identity pool as `unmatched`.
TMDB is queried only on a local alias hit, a published new-title rule whose
prefilter passes, manual/Agent retry, search results, or when the new
setting identity.eagerTmdbLookup (default off) is on. Mirrors MoviePilot:
torrents are recognised only when matched to a subscription or searched,
and recognition failures are logged, not alerted.

- Pending items only for related releases (ambiguous after lookup, or
  related to a local work but unresolved); same source + normalized title
  merge into one decision ("来源「X」的 N 条资源待识别"), resolve/dismiss
  applies to the whole group, members detach as they get resolved.
- Pool governance: unmatched reviews capped (daily, 3x), title_alias
  insert trigger wakes similar entries, stale unmatched entries archived
  after identity.poolArchiveDays (30); review idempotency keys include the
  due time.
- Migration 0047_identity_pool: reason/outcome `unmatched`,
  identity_candidate.normalized_title (+trgm index), wake trigger, and
  cleanup of open identity_unresolved items with no related work
  (dismissed, resolution=moved_to_pool).
- Inbox: group by type + work/source with collapse, hide info-only items
  by default (minSeverity=warning), badge counts warning+ only; pool sheet
  gets manual TMDB/local-work assign and dismiss; settings card for the
  new identity settings.
- Runbook docs/runbook/identity.md.

Requires rebuild/restart (migration runs on start).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 15:05:39 +08:00
rootandClaude Fable 5.1 524af64bec docs(plan): unified credentials injected into browser sessions (BR-2)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 14:47:03 +08:00
rootandClaude Fable 5.1 3e59cb4f41 docs(plan): agent drawer history and session layout polish (AGUI-2)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 14:43:52 +08:00
rootandClaude Opus 5.5 4a92dfd2dc feat(feeds): site-scoped RSS add infers account, parser and poll
Adding a feed from a site page now only asks for the URL, purpose
(discover / track / promotion) and an optional note. POST /feed-sources
with siteId infers the site account (passkey holder first), records the
site definition version as parserVersion, defaults the name to
"<site> RSS" and polling to 30 minutes, and returns non-blocking
warnings when the URL host does not match the site. The dialog shows the
redacted URL, fetches once right after saving and reports the item count
or the error.

The generic feed form on the sources page suggests linking a registered
site when the URL host matches (can be undone). name is now optional.

Takes effect after the stack is rebuilt.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 14:43:19 +08:00
rootandClaude Fable 5.1 00ebdda7ed docs(plan): self-enrichment for titles missing on TMDB (META-1)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 14:40:55 +08:00
rootandClaude Fable 5.1 b8e3cbf689 docs(plan): inbox flood root cause and lazy identification decision (DEC-1)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 14:33:03 +08:00
rootandClaude Fable 5.1 d1f5b908b3 docs(plan): simplified site-scoped RSS add flow
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 14:22:13 +08:00
rootandClaude Fable 5.1 52d0bcd935 docs(plan): site request restraint defaults and resource list format
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 14:15:38 +08:00
rootandClaude Fable 5.1 740764c538 docs(plan): status and next steps after v0.2.4
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 03:27:41 +08:00
rootandClaude Fable 5.1 a662a4d2fd chore(release): v0.2.4
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 03:27:14 +08:00
rootandClaude Opus 5.5 c115676e23 fix(browser): opening a session ignores ones another process already closed
The worker's adapter still held a session the api process had closed,
so browser.navigate {siteId} from an agent run failed with "该站点/账号
已有未关闭的浏览器会话" (REAL-2 task 4). When the database has no live
session for the profile, stale in-memory ones are marked closed before
opening. Needs image rebuild.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 03:15:46 +08:00
rootandClaude Opus 5.5 e53d05a872 fix(browser): reload session state when another process switched the tab
api and worker processes each keep adapter state in memory. After the
upstream reaped an idle tab and the api process reopened one, the agent
worker kept pointing at the lost tab and every screenshot / snapshot in
solve_challenge failed with not_found (REAL-2 task 4). loaded() now
restores from the database when its current tab differs. Needs image
rebuild.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 03:13:40 +08:00
rootandClaude Opus 5.5 be216fbe65 fix(db): place config_customized last in ScheduledJobTable to match migration order
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 03:13:39 +08:00
rootandClaude Opus 5.5 7dc7b1c5fa fix(agent): solve_challenge authorization covers its child's coordinate steps
With only a browser.solve_challenge grant, the vision child run was
denied browser.click_at, so the loop stopped after the first screenshot
(REAL-2 task 4). Steps inside a run spawned by solve_challenge are now
allowed; ancestors' allowlist and step budget still apply. Needs image
rebuild.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 03:06:05 +08:00
rootandClaude Opus 5.5 bd0e011748 fix(schedules): refresh untouched builtin config so checks get new capabilities
Built-in agent checks kept the config stored at first registration, so
check.pending never received decision.list / subscription.list added in
AG-3 and the patrol could not read pending items (REAL-2 scenario g).
Track config_customized (migration 0045); sync replaces config with the
code default unless the user PATCHed it. Needs image rebuild.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 03:06:05 +08:00
rootandClaude Fable 5.1 96fc089f92 build(browser-desktop): guard APT_MIRROR rewrite when debian.sources is absent
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 02:42:05 +08:00
rootandClaude Fable 5.1 94d8b55f36 docs(plan): lessons from deployment and real-environment onboarding
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 02:41:08 +08:00
rootandClaude Fable 5.1 bfe07c3114 chore(release): v0.2.3
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 02:40:38 +08:00
rootandClaude Opus 5.5 d0884bca37 docs(runbook): browser desktop mode, HTTPS and prototype verification
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 02:30:55 +08:00
rootandClaude Opus 5.5 67c8542498 feat(web): desktop mode in site origin view with screenshot fallback
Uses the desktop iframe when the backend reports it available and the page is
a secure context; otherwise falls back to screenshot mode and says why.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 02:30:55 +08:00
rootandClaude Opus 5.5 7e028fa23e feat(server): proxy browser desktop with lease-based control/view credentials
/api/v1/browser/desktop/{sessionId}/* proxies Selkies HTTP and WebSocket,
console sessions only. The holder of the active human lease gets the control
password, everyone else the view-only one; the WS bridge rechecks every 3s
and drops the connection on role change so the client reconnects downgraded.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 02:30:55 +08:00
rootandClaude Opus 5.5 880cec4d23 feat(docker): browser desktop image (Selkies Wayland + headed camofox) and optional TLS proxy
Selkies baseimage (debiantrixie, digest-pinned) with camofox 1.17.0 copied
from camofox-browser:1.17.0, run headed under labwc so the desktop shows the
same Firefox the agent drives. s6 service waits for wayland-0 and depends on
svc-de and svc-dbus so shutdown persists login state. Selkies control/view
passwords derive from CAMOFOX_ACCESS_KEY. Compose defaults to the new image;
CAMOFOX_IMAGE=camofox-browser:1.17.0 switches back. Optional caddy (profile tls).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 02:30:55 +08:00
rootandClaude Opus 5.5 3f0327ad97 test(e2e): AG-3 agent quality with fake model; runbook capability list
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 41e3647f0a feat(web): render agent reports as safe-subset Markdown
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 b7cbc06567 feat(agent): prompt rules for probe queries, param types, Chinese reports and interrupted summaries
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 a00a9eaf5d feat(agent): budget reminders, usage while waiting, budget-exceeded status and dedupe
- tool results carry a budget reminder near limits; text before the last tool
  call is dropped as report when cut by budget/abort
- usage persisted when a run suspends, so waiting sessions show spent tokens
- task page shows budget_exceeded via business.outcome instead of completed
- budget-exceeded decisions merge by root cause (decision / schedule / goal
  template); new summaries added to investigate allowlist

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 4cd9ec8390 fix(pi): upstream completion test sends a sessionId (OpenCode x-opencode-session)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 975a14ace7 feat(agent): subscription.list, decision.list, download.inspect; grant-scoped requiresApproval
- three read-only summary capabilities (38 registered); task.inspect points
  download task ids to download.inspect
- probe queries reject empty / single-letter / wildcard-only terms; externalId
  documented as string; every description says when to use it
- download.plan requiresApproval uses coveringGrant (shared with authorize)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 3134e3a55e test(contracts): upstream model list columns are db-only in db-sync
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:58:28 +08:00
rootandClaude Opus 5.5 c437c6bff6 feat(browser): vision automation loop with screenshots, coordinate actions and bounded challenge solving
- browser.screenshot returns the page as an image content block (≤1280px wide, JPEG quality
  configurable) for vision-capable upstreams; non-vision upstreams get a redacted text snapshot.
  Login pages / password fields are marked sensitive and withheld unless a
  browser.sensitive_screenshot grant exists and allowSensitive is passed.
- browser.click_at / type_at / scroll / wait act in screenshot pixels; the server converts via
  viewport/DPR, requires automation control and an allowlisted host, and writes a thumbnail
  evidence file (DATA_DIR/tmp/evidence) referenced from agent_run_event.
- browser.solve_challenge runs a bounded child agent_run (vision caps only, maxSteps ≤ 12,
  budget), judges success from page facts, stops immediately on 2FA / SMS / device confirmation,
  and otherwise moves the session to waiting with evidence and a takeover link.
- PiAgentRuntime passes modelImage outputs as pi-ai image content when model.input has image;
  the ledger never stores image data; coordinate actions use per-invocation idempotency keys.
- Tests: image codec, runtime image content, E14 e2e (login solved, 2FA stop, step limit,
  sensitive withheld). Real camofox 1.17.0 check on example.com recorded in the runbook.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:27:48 +08:00
rootandClaude Opus 5.5 0765264a47 feat(pi): fetch and refresh upstream model lists, searchable model picker
- POST /pi/upstreams/{id}/models/refresh calls the provider's model list
  endpoint (OpenAI-shaped /models, Anthropic /v1/models, Google
  /v1beta/models, OpenRouter /api/v1/models; Radius via pi-ai refresh),
  normalizes {id, displayName, contextWindow, supportsVision,
  supportsTools, pricing} and stores it in pi_upstream.models (0044)
- GET .../models returns {source, fetchedAt, models[]}: remote merged
  with the static catalog (remote first); failures (401/network/
  unsupported) fall back to static with a one-line error
- POST /pi/models/probe for trying credentials before creating
- wizard and edit drawer: fetch button, searchable dropdown with
  vision/tool tags, manual id, source line; default upstream needs a model
- tests: mock /models, 401, network failure; smoke step; runbook

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:26:07 +08:00
rootandClaude Fable 5.1 e5abfa6217 docs(plan): AG-3 agent quality items from real-upstream verification
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 01:24:37 +08:00
rootandClaude Opus 5.5 4b6da1343a fix(agent): auto-recover outcome is failed when a recovery action itself fails
When download.recheck / task.retry was executed but errored (e.g. the
downloader was unreachable), applyRecoveryOutcome only looked at
succeeded actions and recorded outcome=not_attempted with the summary
"没有执行恢复动作", which is false. Record outcome=failed and name the
failed action instead. Needs image rebuild to take effect.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:21:37 +08:00
rootandClaude Opus 5.5 57fe4c11d3 fix(downloads): treat missing site/adapter as permanent source failure
torrentSource threw plain Error for a missing site or a site without an
adapter definition, so submitDownload retried to max attempts, left the
plan and slot reserved, and sweepReservedPlans re-enqueued it forever
(agent runs stayed waiting on goal-settled). Throw SiteError
(not_found / unsupported) so the plan fails and the slot is released.
Needs image rebuild to take effect.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:13:19 +08:00
rootandClaude Fable 5.1 ce36a42336 docs(plan): upstream model list refresh; real-upstream testing model
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 01:01:13 +08:00
rootandClaude Fable 5.1 ff098734c6 docs(design): Webtop 4.0 same-session browser desktop plan (placement A, vision loop)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-29 01:00:26 +08:00