Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
1bee2bf
chore: temporarily pause Windows CI validation (#238)
hetaoBackend Sep 20, 2026
a122003
fix: recover path-based attachments without duplicate placeholders (#…
hetaoBackend Sep 20, 2026
91001a7
chore: label issues by product interface (#205)
hetaoBackend Sep 20, 2026
ec38e13
test: make smoke config and proxy assertions state-independent (#242)
hetaoBackend Sep 20, 2026
a2f0af6
fix: preserve TUI scrollback boundaries during redraws (#243)
hetaoBackend Sep 20, 2026
5aeef37
feat: advertise installed skills in ACP command menus (#244)
hetaoBackend Sep 20, 2026
a55d629
fix: preserve malformed config files during local updates (#246)
hetaoBackend Sep 20, 2026
bddea42
feat: add versioned CLI releases and npm installation archives (#248)
hetaoBackend Sep 20, 2026
3b3310f
fix: reduce repeated history processing and token estimation (#250)
hetaoBackend Sep 20, 2026
13fd900
chore: release MiniMax Code 0.5.0 (#251)
hetaoBackend Sep 20, 2026
a00c3e0
feat: run basic perf checks by default and full checks by label (#252)
SaladDay Sep 20, 2026
a3ae605
fix: retry transient mcode-tools artifact download failures (#256)
SaladDay Sep 20, 2026
6d79b10
perf: reuse long-history token counts and owned snapshots (#254)
SaladDay Sep 20, 2026
73a2581
fix: restore complete TUI viewports and clear stale history hints (#257)
hetaoBackend Sep 20, 2026
44b9bcb
Merge upstream/main (73a2581, 14 commits) into fork
hermes-agent Sep 20, 2026
00b7ecb
Merge remote-tracking branch 'origin/main' into merge/upstream-73a2581
hermes-agent Sep 20, 2026
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
18 changes: 18 additions & 0 deletions .agents/skills/testing-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ suites are outside this distribution's verification.
| Permission facade on macOS/Linux | `pnpm test:policy` |
| Sandbox on macOS | `pnpm test:sandbox` |
| Source-sync, workflow and release tools | `pnpm test:release-tools` |
| npm release archive installation | `MCODE_RELEASE_TAG=vX.Y.Z MCODE_RELEASE_ARCHIVE=/path/to/package.tar.gz pnpm verify --profile package` |
| Types and standalone build boundary | `pnpm typecheck`, `pnpm build`, `pnpm check:standalone` |
| Published files and generated paths | `pnpm check:source`, `pnpm check:tsconfig` |

Expand Down Expand Up @@ -61,6 +62,23 @@ Skills under `.agents/skills`, unknown paths and inventory changes require the
full profile. The `archive` profile is for source-archive validation, not a way to
bypass the clean-commit export requirement.

The `package` profile authenticates an npm release archive, installs it into a
temporary npm prefix, and exercises its launcher, native dependencies and offline
smoke/BYOK suites. It requires `MCODE_RELEASE_TAG` and `MCODE_RELEASE_ARCHIVE` and
does not replace source validation. The release command commits matching root/TUI source versions before tagging.
The release workflow rejects version mismatches and runs the full profile before
package installation checks.

## Performance coverage

Use [CONTRIBUTING.md](../../../CONTRIBUTING.md#performance-checks) to classify the
change. Add `perf:full` for performance optimizations, changes to history/token
processing, storage, streaming or tool execution, and large runtime refactors.
The label automatically selects the full suite and keeps it selected for later
commits. Before merge, link a passing `performance` run with `Suite: full` for the
latest head and intended base. Read [Performance CI](../../../docs/performance-ci.md)
for evidence, limits and manual dispatch.

## Manual evidence and reporting

For CLI behavior, exercise the built `dist/cli.js` and inspect stdout, stderr and
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/01-bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ body:
id: product
attributes:
label: Product or interface
description: Desktop app and interactive TUI reports automatically receive the desktop or tui label.
options:
- Desktop app
- CLI - interactive TUI
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/02-feature-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ body:
id: product
attributes:
label: Product or interface
description: Desktop app and interactive TUI reports automatically receive the desktop or tui label.
options:
- Desktop app
- CLI - interactive TUI
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/03-question.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ body:
id: product
attributes:
label: Product or interface
description: Leave blank if unsure or asking about repository policy.
description: Leave blank if unsure or asking about repository policy. Desktop app and interactive TUI reports automatically receive the desktop or tui label.
options:
- Desktop app
- CLI - interactive TUI
Expand Down
13 changes: 13 additions & 0 deletions .github/ISSUE_TEMPLATE/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ description: Report missing, incorrect, or unclear documentation.
title: "[Docs] "
labels: ["documentation", "needs-triage"]
body:
- type: dropdown
id: product
attributes:
label: Product or interface
description: Desktop app and interactive TUI reports automatically receive the desktop or tui label.
options:
- Desktop app
- CLI - interactive TUI
- CLI - headless
- CLI - ACP
- Source build or repository tooling
validations:
required: true
- type: input
id: location
attributes:
Expand Down
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Describe the user-visible problem and resulting behavior. Link a public issue wh
## Validation

- Checks run and results (include the revision/profile where relevant):
- Performance: basic / `perf:full` (see [requirements](https://github.com/MiniMax-AI/minimax-code/blob/main/CONTRIBUTING.md#performance-checks)); for full coverage, link a passing run for the latest PR head and intended base:
- NOT RUN, platform limitations and live-service boundaries:

## Publication and contribution checks
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# Windows validation is temporarily paused until its checks are reliable.
os: [ubuntu-latest, macos-latest]
node: ["24"]
include:
- os: ubuntu-latest
Expand Down
146 changes: 146 additions & 0 deletions .github/workflows/cli-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
name: CLI release
on:
push:
tags: ['v*']
pull_request:
paths:
- '.github/workflows/cli-release.yml'
- 'scripts/build.mjs'
- 'scripts/*cli-release.mjs'
- 'scripts/release-cli.mjs'
- 'scripts/lib/cli-release.mjs'
- 'scripts/verify.mjs'
- 'test/smoke.test.mjs'
- 'test/byok.test.mjs'
- 'pnpm-lock.yaml'
- 'package.json'
- 'packages/tui/package.json'
workflow_dispatch:
inputs:
tag:
description: 'Optional tag matching the source version (dry run; does not publish)'
required: false
type: string
permissions:
contents: read
concurrency:
group: cli-release-${{ inputs.tag || github.ref }}
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 25
outputs:
version: ${{ steps.release.outputs.version }}
matrix: ${{ steps.release.outputs.matrix }}
tag: ${{ steps.release.outputs.tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: pnpm
- name: Validate release version and revision
id: release
shell: bash
run: |
node --input-type=module -e 'import { appendFileSync } from "node:fs"; import { cliBuildVersion, cliReleaseTargets } from "./scripts/lib/cli-release.mjs"; const tag = process.env.REQUESTED_TAG || `v${cliBuildVersion(process.cwd())}`; const version = cliBuildVersion(process.cwd(), tag); appendFileSync(process.env.GITHUB_OUTPUT, `version=${version}\ntag=${tag}\nmatrix=${JSON.stringify({include: cliReleaseTargets})}\n`); appendFileSync(process.env.GITHUB_ENV, `MCODE_RELEASE_TAG=${tag}\n`);'
if [ "$EVENT_NAME" = push ]; then
test "$(git rev-parse "refs/tags/$REQUESTED_TAG^{commit}")" = "$(git rev-parse HEAD)"
fi
env:
EVENT_NAME: ${{ github.event_name }}
REQUESTED_TAG: ${{ inputs.tag || (github.event_name == 'push' && github.ref_name) || '' }}
- run: pnpm install --frozen-lockfile
- uses: ./.github/actions/setup-gitleaks
- name: Scan source history
run: gitleaks git --redact --config .gitleaks.toml --log-opts=--all
- run: pnpm verify
env:
MCODE_VERIFY_REPORT_DIR: ${{ runner.temp }}/build-report
- name: Scan distribution
run: gitleaks dir dist --redact --config .gitleaks.toml
- name: Package the tagged CLI
shell: bash
run: node scripts/package-cli-release.mjs "$MCODE_RELEASE_TAG" "$RUNNER_TEMP/package"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: cli-package
path: ${{ runner.temp }}/package/
retention-days: 14
if-no-files-found: error
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ always() }}
with:
name: cli-build-report
path: ${{ runner.temp }}/build-report/
retention-days: 14
install:
needs: build
env:
MCODE_RELEASE_TAG: ${{ needs.build.outputs.tag }}
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.build.outputs.matrix) }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: cli-package
path: ${{ runner.temp }}/package
- run: pnpm verify --profile package
env:
MCODE_RELEASE_ARCHIVE: ${{ runner.temp }}/package/minimax-code-${{ needs.build.outputs.version }}.tar.gz
MCODE_VERIFY_REPORT_DIR: ${{ runner.temp }}/install-report
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ always() }}
with:
name: cli-install-${{ matrix.os }}-${{ matrix.node }}
path: ${{ runner.temp }}/install-report/
retention-days: 14
publish:
needs: [build, install]
if: github.event_name == 'push'
permissions:
contents: write
runs-on: ubuntu-latest
timeout-minutes: 5
env:
MCODE_RELEASE_TAG: ${{ needs.build.outputs.tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
package-manager-cache: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: cli-package
path: ${{ runner.temp }}/package
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: cli-install-*
path: ${{ runner.temp }}/reports
- name: Publish only the authenticated, validated archive
run: node scripts/publish-cli-release.mjs
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
MCODE_RELEASE_DIRECTORY: ${{ runner.temp }}/package
MCODE_RELEASE_REPORTS: ${{ runner.temp }}/reports
3 changes: 2 additions & 1 deletion .github/workflows/compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# Windows validation is temporarily paused until its checks are reliable.
os: [ubuntu-latest, macos-latest]
node: ["22.19.0", "24.2.0", "25", "26"]
include:
- os: ubuntu-latest
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/label-issue-product.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Label issue product

on:
issues:
types: [opened, edited]

permissions:
issues: write

concurrency:
group: issue-product-${{ github.event.issue.number }}
cancel-in-progress: false

jobs:
label-product:
runs-on: ubuntu-latest
timeout-minutes: 5
if: ${{ github.repository == 'MiniMax-AI/minimax-code' && github.event.repository.private == false && !github.event.issue.pull_request }}
steps:
- name: Synchronize product labels
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
node <<'EOF'
const fs = require('node:fs');

async function main() {
const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8'));
const issuePath = `/repos/${process.env.GITHUB_REPOSITORY}/issues/${event.issue.number}`;
async function request(path, method = 'GET', body) {
const response = await fetch(`${process.env.GITHUB_API_URL}${path}`, {
method,
headers: {
Authorization: `Bearer ${process.env.GH_TOKEN}`,
Accept: 'application/vnd.github+json',
'Content-Type': 'application/json',
},
body: body === undefined ? undefined : JSON.stringify(body),
});
if (!response.ok) throw new Error(`GitHub ${method} failed: ${response.status}`);
return response.status === 204 ? undefined : response.json();
}

// Read current state so queued edits cannot restore an outdated label.
const issue = await request(issuePath);
const body = (issue.body || '').replace(/\r\n/g, '\n');
const product = body.match(/^### Product or interface\n+([^\n]+)\n*(?=### |$)/m)?.[1].trim();
const products = new Map([
['Desktop app', 'desktop'],
['CLI - interactive TUI', 'tui'],
['CLI - headless', null],
['CLI - ACP', null],
['Source build or repository tooling', null],
]);
// Leave manually triaged issues alone when no valid form answer exists.
if (!products.has(product)) return;
const desired = products.get(product);
const labels = issue.labels.map(label => label.name);
if (desired && !labels.includes(desired)) {
await request(`${issuePath}/labels`, 'POST', { labels: [desired] });
}
for (const label of ['desktop', 'tui']) {
if (label !== desired && labels.includes(label)) {
await request(`${issuePath}/labels/${label}`, 'DELETE');
}
}
}

main();
EOF
Loading
Loading