diff --git a/.github/workflows/_build-python-packages.yml b/.github/workflows/_build-python-packages.yml index 78485c8f..50feee39 100644 --- a/.github/workflows/_build-python-packages.yml +++ b/.github/workflows/_build-python-packages.yml @@ -68,7 +68,7 @@ jobs: "${RUNNER_TEMP}/reme-package-smoke/bin/python" -c "import reme" - name: Verify released core dependencies - if: inputs.expected_version != '' + if: inputs.upload_artifacts run: | REME_WHEEL="$(pwd)/$(ls dist/reme/reme_ai-[0-9]*.whl)" python -m venv "${RUNNER_TEMP}/reme-core-package-smoke" diff --git a/.github/workflows/_release-npm-plugin.yml b/.github/workflows/_release-npm-plugin.yml index dfafbf23..e534b7e1 100644 --- a/.github/workflows/_release-npm-plugin.yml +++ b/.github/workflows/_release-npm-plugin.yml @@ -15,14 +15,6 @@ on: description: Prefix for the packed package artifact required: true type: string - version: - description: Exact package.json version; an optional v prefix is accepted - required: true - type: string - npm_tag: - description: npm distribution tag - required: true - type: string use_npm_token: description: Use the npm environment NPM_TOKEN instead of Trusted Publishing required: false @@ -37,6 +29,9 @@ on: version: description: Normalized package version value: ${{ jobs.build.outputs.version }} + npm_tag: + description: npm distribution tag derived from the package version + value: ${{ jobs.build.outputs.npm_tag }} secrets: NPM_TOKEN: description: Optional bootstrap or recovery token for npm publishing @@ -51,6 +46,7 @@ jobs: timeout-minutes: 30 outputs: version: ${{ steps.validate.outputs.version }} + npm_tag: ${{ steps.validate.outputs.npm_tag }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -68,21 +64,15 @@ jobs: working-directory: ${{ inputs.directory }} env: EXPECTED_NAME: ${{ inputs.package_name }} - RELEASE_VERSION: ${{ inputs.version }} - NPM_TAG: ${{ inputs.npm_tag }} run: | node --input-type=module <<'JS' import { appendFileSync, readFileSync } from 'node:fs'; const manifest = JSON.parse(readFileSync('package.json', 'utf8')); - const expected = process.env.RELEASE_VERSION.replace(/^v/, ''); if (manifest.name !== process.env.EXPECTED_NAME) { throw new Error(`Expected ${process.env.EXPECTED_NAME}, found ${manifest.name}`); } - if (manifest.version !== expected) throw new Error(`package.json is ${manifest.version}, workflow input is ${expected}`); - if (manifest.version.includes('-') !== (process.env.NPM_TAG === 'next')) { - throw new Error('Prereleases must use next; stable releases must use latest'); - } appendFileSync(process.env.GITHUB_OUTPUT, `version=${manifest.version}\n`); + appendFileSync(process.env.GITHUB_OUTPUT, `npm_tag=${manifest.version.includes('-') ? 'next' : 'latest'}\n`); JS - run: npm ci @@ -140,13 +130,13 @@ jobs: - name: Publish to npm with Trusted Publishing if: ${{ !inputs.use_npm_token }} env: - NPM_TAG: ${{ inputs.npm_tag }} + NPM_TAG: ${{ needs.build.outputs.npm_tag }} run: npm publish dist/plugin/*.tgz --access public --tag "$NPM_TAG" --provenance - name: Publish to npm with NPM_TOKEN if: inputs.use_npm_token env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_TAG: ${{ inputs.npm_tag }} + NPM_TAG: ${{ needs.build.outputs.npm_tag }} run: | if [[ -z "${NODE_AUTH_TOKEN}" ]]; then echo "NPM_TOKEN is required when use_npm_token is enabled" >&2 diff --git a/.github/workflows/release-auto-fin.yml b/.github/workflows/release-auto-fin.yml index 91d75620..31d294d1 100644 --- a/.github/workflows/release-auto-fin.yml +++ b/.github/workflows/release-auto-fin.yml @@ -3,22 +3,17 @@ # 2. 确认插件依赖的 reme-ai 版本已经发布到 PyPI;本工作流会在构建阶段验证该依赖可下载。 # 3. 确认 PyPI Trusted Publisher 已绑定本仓库、此工作流和 pypi environment,且 PyPI 上不存在相同版本。 # 4. 在 GitHub 仓库的 Actions 页面选择“Release / Auto Fin plugin”,点击“Run workflow”。 -# 5. 输入与 project.version 完全一致的版本号(例如 0.1.0)后运行;版本也可以带 v 前缀。 +# 5. 选择目标分支并运行;发布版本直接读取该提交的 project.version。 # # 推荐发布顺序:reme-ai -> reme-auto-fin -> QwenPaw 更新依赖并通过 plugins: [auto-fin] 启用。 # 当前仅支持 workflow_dispatch 手动触发,不会因 push、tag 或 release 自动发布。 name: Release / Auto Fin plugin -run-name: Publish reme-auto-fin ${{ inputs.version }} +run-name: Publish reme-auto-fin ${{ github.ref_name }} on: workflow_dispatch: - inputs: - version: - description: Version from plugins/auto-fin/pyproject.toml (for example, 0.1.0) - required: true - type: string permissions: contents: read @@ -31,8 +26,8 @@ jobs: build: runs-on: ubuntu-latest timeout-minutes: 45 - env: - RELEASE_VERSION: ${{ inputs.version }} + outputs: + version: ${{ steps.package.outputs.version }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -54,9 +49,8 @@ jobs: - name: Validate package name and release version id: package run: | - python - "${RELEASE_VERSION}" <<'PY' + python - <<'PY' import os - import sys import tomllib from pathlib import Path @@ -64,12 +58,9 @@ jobs: from packaging.version import Version project = tomllib.loads(Path("plugins/auto-fin/pyproject.toml").read_text(encoding="utf-8"))["project"] - expected = Version(sys.argv[1].removeprefix("v")) actual = Version(project["version"]) if project["name"] != "reme-auto-fin": raise SystemExit(f"Expected project name 'reme-auto-fin', found {project['name']!r}") - if actual != expected: - raise SystemExit(f"Package version is {actual}, but workflow input is {expected}") requirements = [requirement for requirement in project["dependencies"] if requirement.startswith("reme-ai")] if len(requirements) != 1: raise SystemExit(f"Expected one reme-ai dependency, found {requirements!r}") @@ -97,6 +88,7 @@ jobs: with Path(os.environ["GITHUB_OUTPUT"]).open("a", encoding="utf-8") as output: print(f"reme_requirement={reme_requirement}", file=output) print(f"agentscope_requirement={agentscope_requirement}", file=output) + print(f"version={actual}", file=output) print(f"Publishing {project['name']} {actual}") PY @@ -152,7 +144,7 @@ jobs: - name: Upload distributions uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: - name: reme-auto-fin-${{ inputs.version }} + name: reme-auto-fin-${{ steps.package.outputs.version }} path: dist/auto-fin/ if-no-files-found: error @@ -169,7 +161,7 @@ jobs: - name: Download distributions uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: - name: reme-auto-fin-${{ inputs.version }} + name: reme-auto-fin-${{ needs.build.outputs.version }} path: dist/auto-fin - name: Publish reme-auto-fin diff --git a/.github/workflows/release-daily-paper.yml b/.github/workflows/release-daily-paper.yml index b1ebf362..7d51dc81 100644 --- a/.github/workflows/release-daily-paper.yml +++ b/.github/workflows/release-daily-paper.yml @@ -2,22 +2,17 @@ # 1. Update project.version in plugins/daily_paper/pyproject.toml and merge it into the target branch. # 2. Publish the required reme-ai version before this plugin; the build verifies that dependency on PyPI. # 3. Configure PyPI Trusted Publishing for this repository/workflow and its pypi environment. -# 4. Run "Release / Daily Paper plugin" from GitHub Actions with the exact project version (a v prefix is accepted). +# 4. Run "Release / Daily Paper plugin" from GitHub Actions from the target branch; the version is read from project.version. # # Recommended order: reme-ai -> reme-daily-paper -> downstream applications enabling plugins: [daily-paper]. # This workflow is intentionally manual and never publishes from a push, tag, or GitHub release event. name: Release / Daily Paper plugin -run-name: Publish reme-daily-paper ${{ inputs.version }} +run-name: Publish reme-daily-paper ${{ github.ref_name }} on: workflow_dispatch: - inputs: - version: - description: Version from plugins/daily_paper/pyproject.toml (for example, 0.1.0) - required: true - type: string permissions: contents: read @@ -30,8 +25,8 @@ jobs: build: runs-on: ubuntu-latest timeout-minutes: 45 - env: - RELEASE_VERSION: ${{ inputs.version }} + outputs: + version: ${{ steps.package.outputs.version }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -53,9 +48,8 @@ jobs: - name: Validate package name, dependencies, and release version id: package run: | - python - "${RELEASE_VERSION}" <<'PY' + python - <<'PY' import os - import sys import tomllib from pathlib import Path @@ -63,12 +57,9 @@ jobs: from packaging.version import Version project = tomllib.loads(Path("plugins/daily_paper/pyproject.toml").read_text(encoding="utf-8"))["project"] - expected = Version(sys.argv[1].removeprefix("v")) actual = Version(project["version"]) if project["name"] != "reme-daily-paper": raise SystemExit(f"Expected project name 'reme-daily-paper', found {project['name']!r}") - if actual != expected: - raise SystemExit(f"Package version is {actual}, but workflow input is {expected}") requirements = [Requirement(value) for value in project["dependencies"]] reme_requirements = [requirement for requirement in requirements if requirement.name == "reme-ai"] if len(reme_requirements) != 1 or reme_requirements[0].extras: @@ -96,6 +87,7 @@ jobs: with Path(os.environ["GITHUB_OUTPUT"]).open("a", encoding="utf-8") as output: print(f"reme_requirement={reme_requirements[0]}", file=output) print(f"agentscope_requirement={agentscope_requirement}", file=output) + print(f"version={actual}", file=output) print(f"Publishing {project['name']} {actual}") PY @@ -152,7 +144,7 @@ jobs: - name: Upload distributions uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: - name: reme-daily-paper-${{ inputs.version }} + name: reme-daily-paper-${{ steps.package.outputs.version }} path: dist/daily-paper/ if-no-files-found: error @@ -169,7 +161,7 @@ jobs: - name: Download distributions uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: - name: reme-daily-paper-${{ inputs.version }} + name: reme-daily-paper-${{ needs.build.outputs.version }} path: dist/daily-paper - name: Publish reme-daily-paper diff --git a/.github/workflows/release-dsh-plugin.yml b/.github/workflows/release-dsh-plugin.yml index cb2d9cfc..445fd09b 100644 --- a/.github/workflows/release-dsh-plugin.yml +++ b/.github/workflows/release-dsh-plugin.yml @@ -1,23 +1,11 @@ # Configure npm Trusted Publishing for this caller filename and the npm environment. name: Release / DSH plugin -run-name: Publish ReMe DSH plugin ${{ inputs.version }} (${{ inputs.npm_tag }}) +run-name: Publish ReMe DSH plugin from ${{ github.ref_name }} on: workflow_dispatch: inputs: - version: - description: Exact package.json version; an optional v prefix is accepted - required: true - type: string - npm_tag: - description: npm distribution tag - required: true - default: latest - type: choice - options: - - next - - latest use_npm_token: description: Use the npm environment NPM_TOKEN instead of Trusted Publishing required: true @@ -44,6 +32,4 @@ jobs: directory: integrations/dsh package_name: '@agentscope-ai/reme-dsh-plugin' artifact_name: agentscope-ai-reme-dsh-plugin - version: ${{ inputs.version }} - npm_tag: ${{ inputs.npm_tag }} use_npm_token: ${{ inputs.use_npm_token }} diff --git a/.github/workflows/release-openclaw-plugin.yml b/.github/workflows/release-openclaw-plugin.yml index ec8c31dc..b47f2e9b 100644 --- a/.github/workflows/release-openclaw-plugin.yml +++ b/.github/workflows/release-openclaw-plugin.yml @@ -1,23 +1,11 @@ # Configure npm Trusted Publishing for this caller filename and the npm environment. name: Release / OpenClaw plugin -run-name: Publish ReMe OpenClaw plugin ${{ inputs.version }} (${{ inputs.npm_tag }}) +run-name: Publish ReMe OpenClaw plugin from ${{ github.ref_name }} on: workflow_dispatch: inputs: - version: - description: Exact package.json version; an optional v prefix is accepted - required: true - type: string - npm_tag: - description: npm distribution tag - required: true - default: latest - type: choice - options: - - next - - latest use_npm_token: description: Use the npm environment NPM_TOKEN instead of Trusted Publishing required: true @@ -49,8 +37,6 @@ jobs: directory: integrations/openclaw package_name: '@agentscope-ai/reme-openclaw-plugin' artifact_name: agentscope-ai-reme-openclaw-plugin - version: ${{ inputs.version }} - npm_tag: ${{ inputs.npm_tag }} use_npm_token: ${{ inputs.use_npm_token }} validate_clawhub: true @@ -65,7 +51,7 @@ jobs: with: family: code-plugin version: ${{ needs.release.outputs.version }} - tags: ${{ inputs.npm_tag }} + tags: ${{ needs.release.outputs.npm_tag }} source_repo: ${{ github.repository }} source_commit: ${{ github.sha }} source_ref: ${{ github.sha }} diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index e62ce19c..d0769b91 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -1,17 +1,13 @@ name: Release / ReMe Python package # Publishing a GitHub Release is the primary release trigger for reme-ai; workflow_dispatch is the recovery path. +# Manual runs publish the version in reme/__init__.py from the selected ref. # Configure a PyPI Trusted Publisher for this repository, workflow, and its pypi environment first. -run-name: Publish reme-ai ${{ github.event.release.tag_name || inputs.version }} +run-name: Publish reme-ai ${{ github.event.release.tag_name || github.ref_name }} on: workflow_dispatch: - inputs: - version: - description: Exact reme-ai version; an optional v prefix is accepted - required: true - type: string release: types: [published] @@ -27,7 +23,7 @@ jobs: name: Build and verify distributions uses: ./.github/workflows/_build-python-packages.yml with: - expected_version: ${{ github.event.release.tag_name || inputs.version }} + expected_version: ${{ github.event.release.tag_name }} upload_artifacts: true publish-reme: diff --git a/.github/workflows/release-reme-studio.yml b/.github/workflows/release-reme-studio.yml index c3bb2d3f..01e8d328 100644 --- a/.github/workflows/release-reme-studio.yml +++ b/.github/workflows/release-reme-studio.yml @@ -1,27 +1,15 @@ # Release checklist: # 1. Update reme_studio/pyproject.toml, package.json, and package-lock.json to the same Studio version. # 2. Configure npm Trusted Publishing with the npm environment and PyPI Trusted Publishing with the pypi environment. -# 3. Run this workflow manually with the exact Studio version. +# 3. Run this workflow from main; versions and the npm tag are read from the package manifests. name: Release / ReMe Studio -run-name: Publish ReMe Studio ${{ inputs.version }} (${{ inputs.npm_tag }}) +run-name: Publish ReMe Studio from main (${{ inputs.publish_target }}) on: workflow_dispatch: inputs: - version: - description: Version from the Studio Python and npm manifests - required: true - type: string - npm_tag: - description: npm distribution tag - required: true - default: latest - type: choice - options: - - next - - latest use_npm_token: description: Use the npm environment NPM_TOKEN instead of Trusted Publishing required: true @@ -49,9 +37,9 @@ jobs: if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest timeout-minutes: 45 - env: - RELEASE_VERSION: ${{ inputs.version }} - NPM_TAG: ${{ inputs.npm_tag }} + outputs: + version: ${{ steps.package.outputs.version }} + npm_tag: ${{ steps.package.outputs.npm_tag }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -69,6 +57,7 @@ jobs: python-version: "3.11" - name: Validate Studio package names and version + id: package run: | python - <<'PY' import json @@ -79,19 +68,19 @@ jobs: studio = Path("reme_studio") python_manifest = tomllib.loads((studio / "pyproject.toml").read_text(encoding="utf-8"))["project"] npm_manifest = json.loads((studio / "package.json").read_text(encoding="utf-8")) - expected = os.environ["RELEASE_VERSION"].removeprefix("v") + version = npm_manifest["version"] if python_manifest["name"] != "reme_studio": raise SystemExit(f"Unexpected Python package name: {python_manifest['name']}") if npm_manifest["name"] != "@agentscope-ai/reme_studio": raise SystemExit(f"Unexpected npm package name: {npm_manifest['name']}") - if python_manifest["version"] != expected or npm_manifest["version"] != expected: + if python_manifest["version"] != version: raise SystemExit( - f"Studio manifests are {python_manifest['version']} and {npm_manifest['version']}; " - f"workflow input is {expected}", + f"Studio versions differ: Python {python_manifest['version']}, npm {version}", ) - prerelease = "-" in expected - if prerelease != (os.environ["NPM_TAG"] == "next"): - raise SystemExit("Prereleases must use next; stable releases must use latest") + npm_tag = "next" if "-" in version else "latest" + with Path(os.environ["GITHUB_OUTPUT"]).open("a", encoding="utf-8") as output: + print(f"version={version}", file=output) + print(f"npm_tag={npm_tag}", file=output) PY - name: Install dependencies and run checks @@ -126,7 +115,7 @@ jobs: - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: - name: reme-studio-${{ inputs.version }} + name: reme-studio-${{ steps.package.outputs.version }} path: | dist/studio-python/* dist/studio-npm/* @@ -144,7 +133,7 @@ jobs: steps: - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: - name: reme-studio-${{ inputs.version }} + name: reme-studio-${{ needs.build.outputs.version }} path: dist - name: Publish ReMe Studio to PyPI @@ -174,13 +163,13 @@ jobs: - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: - name: reme-studio-${{ inputs.version }} + name: reme-studio-${{ needs.build.outputs.version }} path: dist - name: Verify the matching PyPI release for npm-only recovery if: inputs.publish_target == 'npm' env: - PACKAGE_VERSION: ${{ inputs.version }} + PACKAGE_VERSION: ${{ needs.build.outputs.version }} run: | python - <<'PY' import os @@ -200,7 +189,7 @@ jobs: - name: Check for an identical existing npm package id: npm-version env: - PACKAGE_VERSION: ${{ inputs.version }} + PACKAGE_VERSION: ${{ needs.build.outputs.version }} run: | package_file=$(find dist/studio-npm -maxdepth 1 -name '*.tgz' -print -quit) if [[ -z "${package_file}" ]]; then @@ -228,13 +217,13 @@ jobs: - name: Publish ReMe Studio to npm with Trusted Publishing if: ${{ steps.npm-version.outputs.exists != 'true' && !inputs.use_npm_token }} env: - NPM_TAG: ${{ inputs.npm_tag }} + NPM_TAG: ${{ needs.build.outputs.npm_tag }} run: npm publish dist/studio-npm/*.tgz --access public --tag "${NPM_TAG}" --provenance - name: Publish ReMe Studio to npm with NPM_TOKEN if: ${{ steps.npm-version.outputs.exists != 'true' && inputs.use_npm_token }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_TAG: ${{ inputs.npm_tag }} + NPM_TAG: ${{ needs.build.outputs.npm_tag }} run: | if [[ -z "${NODE_AUTH_TOKEN}" ]]; then echo "NPM_TOKEN is required when use_npm_token is enabled" >&2 diff --git a/integrations/dsh/package-lock.json b/integrations/dsh/package-lock.json index 925ab455..94cd94bc 100644 --- a/integrations/dsh/package-lock.json +++ b/integrations/dsh/package-lock.json @@ -1,12 +1,12 @@ { "name": "@agentscope-ai/reme-dsh-plugin", - "version": "0.1.2", + "version": "0.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@agentscope-ai/reme-dsh-plugin", - "version": "0.1.2", + "version": "0.1.3", "license": "Apache-2.0", "devDependencies": { "@deepseek-ai/cordis": "4.0.5-alpha.2", diff --git a/integrations/dsh/package.json b/integrations/dsh/package.json index 7fc58abc..86388a31 100644 --- a/integrations/dsh/package.json +++ b/integrations/dsh/package.json @@ -1,6 +1,6 @@ { "name": "@agentscope-ai/reme-dsh-plugin", - "version": "0.1.2", + "version": "0.1.3", "description": "ReMe memory and context integration for DeepSeek Harness", "type": "module", "main": "./dist/index.js", diff --git a/reme/__init__.py b/reme/__init__.py index 6026f9d1..4e483086 100644 --- a/reme/__init__.py +++ b/reme/__init__.py @@ -1,6 +1,6 @@ """ReMe CLI package.""" -__version__ = "0.4.1.13" +__version__ = "0.4.2.0" from . import config from . import constants diff --git a/tests/unit/test_package_versions.py b/tests/unit/test_package_versions.py index 07855130..fb91c00c 100644 --- a/tests/unit/test_package_versions.py +++ b/tests/unit/test_package_versions.py @@ -75,7 +75,7 @@ def test_typescript_host_plugins_are_independent_packages() -> None: assert manifests["dsh"]["name"] == "@agentscope-ai/reme-dsh-plugin" assert manifests["openclaw"]["name"] == "@agentscope-ai/reme-openclaw-plugin" - assert manifests["dsh"]["version"] == "0.1.2" + assert manifests["dsh"]["version"] == "0.1.3" assert manifests["openclaw"]["version"] == "0.1.1" assert manifests["dsh"].get("dependencies", {}) == {} assert manifests["openclaw"].get("dependencies", {}) == {"typebox": "1.3.19"}