Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions .downstream/native-domains.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ handshake. Account mode edits invalidate only that account's subsequent connecti

## Independent Pelican tests

`/admin/pelican-tests` is a task/result workbench. The new-task composer loads
`/admin/pelican-tests` opens a paginated gallery of all observations from the last
24 hours, with task/account/model/effort/scene/execution/verdict filters. Wide
screens show four cards, medium screens two, and phones one. The new-task composer loads
accounts in pages of 50, retains selection across pages, and offers explicit
current-page/all-matching scopes. Models use locally saved mappings and catalogs;
searchable dropdowns accept catalog choices only. Backend defaults prefer
Expand Down Expand Up @@ -171,10 +173,21 @@ and failed-item retests directly create a new task with original model/effort
parameters and budget. Cross-task selected retries create one task per source,
preserving each source budget. New submissions retain UUID replay protection;
history, browsing, reconnecting and comparison are read-only.
The fixed Pelican prompt is preserved. The actual sending path, credentials,
New manual tasks select Pelican and/or candy (the UI defaults to both). Each
result saves its chosen scene and a fresh visible verification code. The fixed
legacy prompt remains exclusive to the old `/tests` contract. The actual sending path, credentials,
identity, model mapping, proxy, TLS and protocol remain owned by each account. No API Key, group policy, model score or fallback account
is manufactured for a test.

Candy (90 seconds), SVG generation (the saved generation budget), rendering
(30 seconds after renderer admission), and same-model visual review (180 seconds)
run as distinct stages. Candy failure does not prevent generation. Review uses
four 960x640 frames at 0/0.23/0.51/0.79 of the sampled animation cycle, checks
pelican/bicycle/riding/motion, and keeps true/false/null judgments. Unsupported
image input is unreviewed. Only all selected checks passing gives a passed verdict;
execution status is independent. Stage evidence retains raw bytes as Base64 in
detail JSON. A single on-demand Chromium process renders network-blocked SVGs.

All batches share ten model execution slots, with one request per account.
Ordinary selected-account sends participate in normal business
account capacity. Generation starts after preparation and admission; its default
Expand All @@ -184,7 +197,7 @@ renew every 30 seconds; lost capacity cancels the operation. Existing credential
refresh remains available, while account health, quota, scheduling, affinity,
usage and billing writes are suppressed, including background callbacks.

Task IDs are timestamped UUIDv7 values. Expired/future IDs are rejected and replay
Submission IDs are timestamped UUIDv7 values. Expired/future IDs are rejected and replay
cannot dispatch again. Migration 275 owns the task/result tables; migration 276
adds budgets, execution phases and actual invocation metadata in place, preserving
old records and raw BYTEA output. Existing records retain their 90-second budget.
Expand All @@ -201,7 +214,18 @@ idempotent. Output/errors of retained results preserve original bytes;
binary upstream envelopes use lossless Base64. Truncated or incomplete output is
recorded without another generation or automatic repair.

Result previews use short random capability URLs under
`GET /admin/pelican-tests/results` reads only gallery summaries.
`POST /admin/pelican-tests/tasks/:id/retest` accepts a new client UUID, optional
result IDs or failed-only selection, preserves source configuration/scenes and
budget, and creates fresh verification codes. Replays compare the retest source
and selection before consulting source records. Migration 280 adds task config,
small evaluation metadata and byte-backed evidence/SVG/review image in place.
Old records remain unscored and are never automatically re-executed.

New SVG previews use `scene.svg` image capabilities and a no-script CSP.
Gallery and preview SQL do not read original answers, upstream envelopes or review
images. An already generated SVG remains viewable after candy/review failure.
Legacy HTML result previews use short random capability URLs under
`/pelican-tests/preview/` only,
expire within 30 minutes and the task's remaining lifetime, and use an opaque
script-enabled sandbox and their own
Expand Down
19 changes: 18 additions & 1 deletion .github/workflows/downstream-verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,31 @@ jobs:
file: Dockerfile
platforms: linux/amd64
push: false
outputs: type=oci,dest=/tmp/sub2api-candidate.tar
tags: sub2api-pelican-candidate:check
outputs: |
type=oci,dest=/tmp/sub2api-candidate.tar
type=docker,name=sub2api-pelican-candidate:check
build-args: |
VERSION=0.0.0-candidate
COMMIT=${{ github.sha }}
GOPROXY=https://proxy.golang.org,direct
GOSUMDB=sum.golang.org
cache-from: type=gha,scope=sub2api-candidate-amd64
cache-to: type=gha,mode=max,scope=sub2api-candidate-amd64
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version-file: backend/go.mod
check-latest: false
cache: true
cache-dependency-path: backend/go.sum
- name: Verify four-frame rendering inside the candidate runtime
working-directory: backend
run: |
CGO_ENABLED=0 go test -c -tags unit -o "$RUNNER_TEMP/pelican-render.test" ./internal/service
docker run --rm --init --network none --memory 768m --user 1000:1000 \
--mount "type=bind,src=$RUNNER_TEMP/pelican-render.test,dst=/tmp/pelican-render.test,readonly" \
-e PELICAN_RENDER_TEST=1 --entrypoint /tmp/pelican-render.test \
sub2api-pelican-candidate:check -test.run '^TestPelicanChromiumRenderer$' -test.v
- name: Upload candidate
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ LABEL org.opencontainers.image.source="https://github.com/Wei-Shaw/sub2api"
RUN apk add --no-cache \
ca-certificates \
tzdata \
chromium \
su-exec \
libpq \
zstd-libs \
Expand All @@ -148,6 +149,7 @@ WORKDIR /app
COPY --from=backend-builder --chown=sub2api:sub2api /app/sub2api /app/sub2api
COPY --from=backend-builder --chown=sub2api:sub2api /app/backend/resources /app/resources
COPY --chown=sub2api:sub2api THIRD_PARTY_NOTICES.md /app/THIRD_PARTY_NOTICES.md
COPY --chown=sub2api:sub2api third_party/manxue-ai.LICENSE /app/third_party/manxue-ai.LICENSE

# Create the writable paired registry directory used by the runtime snapshot.
RUN mkdir -p /app/data && \
Expand Down
10 changes: 10 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,13 @@ SOFTWARE.
under the MIT license; its original license is retained in `LICENSE.txt`.
Local changes add opt-in client compression-window negotiation using the already
locked klauspost/compress dependency. Other service paths retain the original module.

## Pelican scenes, candy test and visual review

The SVG scene prompt, eight scene names, candy problem, visual-review criteria
and animation frame sampling are adapted from w1196396546/manxue-ai at
commit 5da79674417dd0748682f09b7b7467efd1968ea8 (Apache License 2.0).
Source: https://github.com/w1196396546/manxue-ai
The retained Apache license is in third_party/manxue-ai.LICENSE.
The Go implementation and Vue gallery integrate these ideas with Sub2API's
existing account senders, background observations and isolated previews.
7 changes: 7 additions & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ require (
github.com/aws/aws-sdk-go-v2/credentials v1.19.10
github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3
github.com/cespare/xxhash/v2 v2.3.0
github.com/chromedp/cdproto v0.0.0-20260321001828-e3e3800016bc
github.com/chromedp/chromedp v0.15.1
github.com/coder/websocket v1.8.14
github.com/dgraph-io/ristretto v0.2.0
github.com/gin-gonic/gin v1.9.1
Expand Down Expand Up @@ -97,6 +99,7 @@ require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/chromedp/sysutil v1.1.0 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
Expand All @@ -117,6 +120,7 @@ require (
github.com/fxamacker/cbor/v2 v2.9.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
Expand All @@ -125,6 +129,9 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/go-webauthn/x v0.2.6 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.4.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.7.0 // indirect
Expand Down
Loading
Loading