docs+ci(v0.8.12): Resume by UUID, triage workflows, CHANGELOG refresh
- README Usage block now documents `deepseek resume <SESSION_ID>` and `deepseek fork <SESSION_ID>`. Both commands have existed since v0.7 but were undiscoverable; #682 reported "no way to resume." - New GitHub Actions for issue triage (#688): * triage.yml — keyword-driven auto-labeller (bug / feat / docs / question, area:* by file-path mention, os:*, lang:zh on CJK titles). Only adds labels that already exist on the repo so it can't create noise unilaterally. * stale.yml — 14 d stale → 7 d close on `needs-info` issues only; PRs untouched; respects pinned/keep-open/ bug/security exemptions. * spam-lockdown.yml — auto-closes promotional issues from accounts <30 days old. Pure github-script (no third-party action) so the matching rules stay readable. - CHANGELOG (v0.8.12) updated: README install rewrite (#672), Scoop (#696), pricing extension (#692), Resume docs surface, and the cargo-install-on-stable fix from the previous commit. Lease "pending" caveat removed since it's now actually fixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
name: Lock down obvious spam issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
lockdown:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Auto-close spam patterns from new accounts
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const author = issue.user;
|
||||
|
||||
// Only consider brand-new accounts. If the user has been around
|
||||
// long enough to file good-faith issues elsewhere, don't touch.
|
||||
const created = new Date(author.created_at || 0);
|
||||
const ageDays = (Date.now() - created.getTime()) / 86_400_000;
|
||||
if (ageDays > 30) return;
|
||||
|
||||
const blob = `${issue.title || ''}\n${issue.body || ''}`;
|
||||
const patterns = [
|
||||
/\bcrypto\b/i,
|
||||
/\bairdrop\b/i,
|
||||
/\bnft\b/i,
|
||||
/\bpresale\b/i,
|
||||
/\busdt\b/i,
|
||||
/\btg\s*@/i,
|
||||
/\btelegram\s+@/i,
|
||||
/\bt\.me\//i,
|
||||
/\bwhatsapp\s+\+/i,
|
||||
/\bseo\s+service/i,
|
||||
/\bguest\s+post/i,
|
||||
/\bbacklink/i,
|
||||
/\bbuy\s+followers/i,
|
||||
/\bjoin\s+our\s+(community|server|group)/i,
|
||||
/\bpromot[ei]\s+your\b/i,
|
||||
];
|
||||
const hit = patterns.find(p => p.test(blob));
|
||||
if (!hit) return;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: [
|
||||
'This issue was auto-closed because the title or body matches',
|
||||
'a spam pattern (paid promotion / unrelated link) and the author',
|
||||
'account is less than 30 days old. If this is a real bug or',
|
||||
'feature request, please reopen with a clearer description',
|
||||
'(in English or 中文) of the project-relevant context.',
|
||||
].join(' '),
|
||||
});
|
||||
|
||||
await github.rest.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
state: 'closed',
|
||||
state_reason: 'not_planned',
|
||||
});
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: ['spam'],
|
||||
}).catch(() => {}); // ignore if label doesn't exist yet
|
||||
@@ -0,0 +1,36 @@
|
||||
name: Close stale issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '17 5 * * *' # daily, off-peak
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-stale: 14
|
||||
days-before-close: 7
|
||||
stale-issue-message: >
|
||||
This issue has been inactive for 14 days while waiting on
|
||||
additional information. It will close automatically in 7 days
|
||||
unless someone responds. If you still need help, drop a
|
||||
comment with the requested details and a maintainer can
|
||||
reopen.
|
||||
close-issue-message: >
|
||||
Closing for inactivity. Feel free to comment to reopen if
|
||||
you can share the requested information.
|
||||
stale-issue-label: 'stale'
|
||||
only-labels: 'needs-info'
|
||||
exempt-issue-labels: 'pinned,keep-open,bug,security'
|
||||
# Don't touch PRs — `actions/stale` defaults can be aggressive
|
||||
# there. We only want it for `needs-info` issues.
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
operations-per-run: 60
|
||||
@@ -0,0 +1,63 @@
|
||||
name: Issue triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Auto-label by title and body
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = (issue.title || '').toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = `${title}\n${body}`;
|
||||
const labels = new Set();
|
||||
|
||||
// Type
|
||||
if (/\b(bug|crash|panic|broken|stack ?trace|regression|err(?:or)?|fail(?:ed|ure)?)\b/.test(text)) labels.add('bug');
|
||||
if (/\b(feat(?:ure)?|request|enhancement|wishlist|proposal|please add|would be nice|support for)\b/.test(text)) labels.add('enhancement');
|
||||
if (/\b(docs?|readme|documentation|typo|grammar|wording|spelling)\b/.test(text)) labels.add('documentation');
|
||||
if (/\b(question|how (?:do|to)|why does|what does|is it possible)\b/.test(text)) labels.add('question');
|
||||
|
||||
// Locale — title contains CJK (Chinese, Japanese, Korean) characters
|
||||
if (/[-ヿ㐀-鿿가-]/.test(issue.title || '')) labels.add('lang:zh');
|
||||
|
||||
// Areas (path-driven hints)
|
||||
if (/crates\/tui|\btui\b|ratatui|composer|sidebar/.test(text)) labels.add('area:tui');
|
||||
if (/crates\/core|engine|turn ?loop|agent ?loop/.test(text)) labels.add('area:core');
|
||||
if (/crates\/mcp|\bmcp\b/.test(text)) labels.add('area:mcp');
|
||||
if (/crates\/state|sqlite|sessions?|persistence/.test(text)) labels.add('area:state');
|
||||
if (/crates\/execpolicy|approval|sandbox|seatbelt|landlock/.test(text)) labels.add('area:execpolicy');
|
||||
if (/crates\/tools|tool[ _]call|tool[ _]registry/.test(text)) labels.add('area:tools');
|
||||
if (/install|cargo install|npm install|scoop|homebrew|prebuilt|binary/.test(text)) labels.add('area:install');
|
||||
if (/windows/.test(text)) labels.add('os:windows');
|
||||
if (/macos|darwin|apple silicon/.test(text)) labels.add('os:macos');
|
||||
if (/\blinux\b|ubuntu|debian|fedora|arch ?linux/.test(text)) labels.add('os:linux');
|
||||
|
||||
if (labels.size === 0) return;
|
||||
|
||||
// Only add labels that already exist on the repo to avoid creating noise.
|
||||
const existing = await github.paginate(github.rest.issues.listLabelsForRepo, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100,
|
||||
});
|
||||
const existingNames = new Set(existing.map(l => l.name));
|
||||
const toAdd = [...labels].filter(name => existingNames.has(name));
|
||||
if (toAdd.length === 0) return;
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: toAdd,
|
||||
});
|
||||
@@ -127,6 +127,20 @@ resident sub-agents. No breaking changes.
|
||||
diagnostics via the engine-level LSP hooks path.
|
||||
|
||||
### Docs
|
||||
- **README install section rewritten** (#672) — the previous lede claimed
|
||||
"no Node.js or Python runtime" but the very next paragraph told readers to
|
||||
install Node before continuing. Replaced with a three-path Install block
|
||||
(npm / cargo / direct download) that makes the npm wrapper's role explicit:
|
||||
it downloads the prebuilt binary, but `deepseek` itself does not depend on
|
||||
Node at runtime. zh-CN README mirrored.
|
||||
- **Windows Scoop install instructions** (#696) — README and zh-CN README now
|
||||
document `scoop install deepseek-tui` for Windows users. *Thanks to
|
||||
[@woyxiang](https://github.com/woyxiang) for this PR.*
|
||||
- **DeepSeek Pro discount window extended** (#692) — pricing footnote updated
|
||||
from 5 May 2026 to 31 May 2026 to match the platform-side promotion. *Thanks
|
||||
to [@wangfeng](mailto:wangfengcsu@qq.com) for this PR.*
|
||||
- **`deepseek resume <SESSION_ID>` surfaced in Usage** — the command exists
|
||||
since v0.7 but was undocumented. Reported via #682.
|
||||
- **SECURITY.md** (#648) — vulnerability reporting policy and supported
|
||||
versions.
|
||||
- **CODE_OF_CONDUCT.md** (#686) — Contributor Covenant v2.1. *Thanks to
|
||||
@@ -135,6 +149,23 @@ resident sub-agents. No breaking changes.
|
||||
config.example.toml now document `locale = "zh-Hans"`.
|
||||
|
||||
### Fixed
|
||||
- **`cargo install` on stable Rust** — the language-picker match guard at
|
||||
`crates/tui/src/tui/ui.rs:1603` used `&& let Some(...) = ...` inside an
|
||||
`if`-guard, which requires the nightly-only `if_let_guard` feature on Rust
|
||||
before 1.94. Reported by an external user whose `cargo install
|
||||
deepseek-tui` failed with E0658. Rewrote as a plain match guard with a
|
||||
nested `if let` inside the arm body. The workspace also now declares
|
||||
`rust-version = "1.88"` (the actual minimum for `let_chains` in
|
||||
`if`/`while`) so users on too-old toolchains see a clear cargo error
|
||||
instead of a confusing rustc one. AGENTS.md gains a "stable Rust only"
|
||||
section so this doesn't regress.
|
||||
- **Resident-file lease never released after spawn** (#660) — the lease was
|
||||
stamped as `"pending"` at spawn time because the agent id is only assigned
|
||||
by the manager after the spawn call returns. The release-on-terminal-state
|
||||
path (added in the original #660 commit) matched leases by agent id, so
|
||||
it could never find these placeholder entries. Now the placeholder is
|
||||
replaced with the real agent id immediately after spawn so existing
|
||||
release wiring fires. Resolves the v0.8.12 caveat documented at RC time.
|
||||
- **Color::Reset across all UI widgets** (#651, #671) — replaced hardcoded
|
||||
`Color::Black` and `Color::Rgb(18, 29, 39)` backgrounds with `Color::Reset`
|
||||
so the TUI respects the terminal's actual background color on light-themed
|
||||
@@ -145,6 +176,14 @@ resident sub-agents. No breaking changes.
|
||||
shared `truncate_id` helper across session, picker, and UI call sites.
|
||||
|
||||
### Maintenance
|
||||
- Workspace `cargo fmt` sweep across community PRs that landed unformatted.
|
||||
- Issue-triage GitHub Actions added (#688): keyword-driven auto-labeller,
|
||||
stale-bot for `needs-info` issues (14 d → stale → 7 d → close), and a
|
||||
spam lockdown that auto-closes promotional issues from accounts <30 d
|
||||
old. All pure GitHub Actions — no third-party services.
|
||||
- Annotated `TuiPrefs` (#657) and `handoff::THRESHOLDS` (#667) with
|
||||
`#[allow(dead_code)]` so the deferred APIs don't trip CI's `-D warnings`
|
||||
flag while their call sites are staged for v0.8.13.
|
||||
- Removed dead `prefer_handoff` field from `CompactionConfig` — config knob
|
||||
existed but zero code paths consulted it (#667).
|
||||
- Removed dead `use_terminal_colors` field from `TuiConfig` — no rendering
|
||||
|
||||
@@ -209,7 +209,9 @@ deepseek setup --status # read-only setup status
|
||||
deepseek setup --tools --plugins # scaffold tool/plugin dirs
|
||||
deepseek models # list live API models
|
||||
deepseek sessions # list saved sessions
|
||||
deepseek resume --last # resume latest session
|
||||
deepseek resume --last # resume the most recent session
|
||||
deepseek resume <SESSION_ID> # resume a specific session by UUID
|
||||
deepseek fork <SESSION_ID> # fork a session at a chosen turn
|
||||
deepseek serve --http # HTTP/SSE API server
|
||||
deepseek pr <N> # fetch PR and pre-seed review prompt
|
||||
deepseek mcp list # list configured MCP servers
|
||||
|
||||
Reference in New Issue
Block a user