Commit c819e4b
authored
feat(alibaba): add token-plan routing and cloud discovery (#105)
* fix(web): allow same-origin WebSockets, standardize banner, sync UI version
- Auto-populate allowed origins in local mode too: with token auth on,
the origin check is enforced, and the previously empty allowlist
rejected every request carrying an Origin header — breaking all
session-stream WebSocket handshakes with 403/1006. REST GETs worked
only because browsers omit Origin on same-origin GET fetches.
- Standardize the web/vis startup banners on a shared PYTHINKER
wordmark in utils/server.py, replacing the legacy upstream art.
- Serve the installed CLI version at runtime via /api/config
(GlobalConfig.version); the web UI header now prefers it over the
Vite build-time constant, which goes stale when the CLI is upgraded
without a frontend rebuild. Rebuilt the bundled static assets.
- Add regression tests for local-mode origin population and the
empty-allowlist reject-all semantics.
* feat(tui): adopt report prose sections, stacked tables, todo aliases, agent glyphs
Selectively adopted from an earlier TUI iteration, re-based onto the
current design system:
- report.py: detect top-level "Label: body" lines in report-like
assistant prose and render them as structured sections, with
conservative guards so ordinary paragraphs stay plain Markdown.
- markdown.py: wide multi-column report tables render as stacked
records so long paths and prose wrap in one generous value column
instead of being sliced mid-word across narrow grid cells; compact
tables keep the bordered grid.
- todo: normalize LLM-supplied status aliases (complete/completed/
finished -> done, canceled -> cancelled) via a before-validator.
- agent renderer: status glyphs (check/cross/dot) and
type-first row layout for subagent activity.
Deliberately NOT adopted (superseded by the current standardized
design): the question-marker and markdown-palette recolors, and the
space-separated tool header format with column-grid wrapping, which
conflicts with the pinned parenthesized header style.
* fix(deps): upgrade ai to 6.x to clear @ai-sdk/provider-utils advisory
GHSA-866g-f22w-33x8 (uncontrolled resource consumption) affects
@ai-sdk/provider-utils <=3.0.97, which every ai@5.x release pins; the
patched 4.x line ships only with ai@6. The web UI imports the ai
package exclusively for types (ChatStatus, FileUIPart, ToolUIPart,
LanguageModelUsage), so the major bump is type-level only — tsc and
biome pass unchanged.
The remaining elliptic advisory (GHSA-848j-6mx2-7j84, low) has no
patched release in any version; it enters via vite-plugin-node-polyfills
-> crypto-browserify at build time only, and the bundle never includes
it because only the path and url polyfills are enabled.
* fix: harden recall framing, ESC turn-task cleanup, and web token bootstrap
Three field-found fixes:
- memory/recall: frame the recalled-memory block as background context
from past sessions, not an instruction. Without the guard the model
could treat a recalled note or stale todo as the current request
(e.g. answering a plain "ping" by resuming an old code-review task).
Open todos are now labelled reference-only.
- background tasks: track tasks spawned during the current interactive
turn and kill exactly those on ESC. Previously a background subagent
launched mid-turn survived the interrupt, finished later, and
re-delivered the abandoned task via its completion notification.
Earlier turns' tasks are deliberately left running.
- web auth: consume the URL token before React mounts instead of in a
component effect. Mount-time data fetches fired first and sent a
stale localStorage token from a previous server run, yielding 401s
on first load.
* docs(tasks): record ESC/recall/web-401 investigation and fix log
* fix: address CodeRabbit findings and add required changelog entry
- web config API: log get_version() failures instead of swallowing them,
so an operator can see when the version banner falls back to empty
- usePythinkerVersion: reset the shared promise and log on a failed/empty
fetch so a transient error no longer permanently disables the backend
version banner for the session
- test_web_origins: rename unused *args to *_args to signal intent
- CHANGELOG: add the missing ## Unreleased entry for this PR's web fixes
(unblocks the required changelog-entry-required check)
- AGENTS.md: document the changelog-entry-before-PR requirement as a gotcha
to stop this check repeatedly blocking PRs
* feat(alibaba): plan-key routing fix, live discovery, compliant usage
Plan keys (sk-sp-/sk-tok-/sk-ws-) now route to the shared international Token
Plan endpoint instead of coding-intl, fixing a 401 invalid_api_key on every chat.
Generic sk- keys remain pay-as-you-go Cloud (DashScope) with US/China auto-detect.
Model discovery accepts every chat model the live /models returns (excluding
image/audio/embed/rerank/etc), infers capabilities + context window from the id,
and defaults first login to qwen3.7-plus. Removed the dead Coding-Plan endpoint
branches and constant.
Usage: the Token Plan exposes no quota API and its policy forbids automated
balance polling, so /usage on Token Plan/Coding endpoints shows Pythinker's local
token tally plus a console pointer (My Subscriptions / Usage Analysis) instead of
probing a 404 endpoint or scraping the billing console.
CI: split the docs Pages workflow into build + deploy jobs (one artifact per run)
to fix the 'multiple artifacts named github-pages' deploy failure.
Verified live: Token Plan and Cloud endpoints both return /models 200 and a real
chat completion.
* fix(alibaba): anchor token-plan host suffix and apply ruff format
Anchor the maas.aliyuncs.com suffix check on a leading dot so spoofed
hosts (e.g. evilmaas.aliyuncs.com) no longer match the token-plan
quota-skip path, resolving the CodeQL py/incomplete-url-substring-
sanitization alert. Also wrap the long ALIBABA_TOKEN_PLAN_BASE_URL
literal to satisfy ruff format.
* test(alibaba): cover sk-ws- plan key in token-plan routing test
The docstring claims sk-sp-/sk-tok-/sk-ws- all route to the Token Plan
endpoint, but the parametrization only exercised sk-sp- and sk-tok-.
Add sk-ws-test-key so the consolidated assertion matches the docstring
(addresses CodeRabbit nitpick on #105).1 parent b41bb1d commit c819e4b
6 files changed
Lines changed: 245 additions & 222 deletions
File tree
- .github/workflows
- src/pythinker_code
- auth
- ui/shell/usage_adapters
- tests/auth
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
17 | 21 | | |
18 | | - | |
| 22 | + | |
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
76 | 77 | | |
77 | 78 | | |
78 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
79 | 90 | | |
80 | 91 | | |
81 | 92 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
0 commit comments