Skip to content
Draft
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
74 changes: 74 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install the pinned formatter
shell: bash
run: |
version=$(python3 -c 'import tomllib; print(tomllib.load(open("mise.toml", "rb"))["tools"]["rust"]["version"])')
rustup toolchain install "$version" --profile minimal --component rustfmt
rustup override set "$version"
- name: Check formatting
run: |
cargo fmt --all
git diff --exit-code > "$RUNNER_TEMP/rustfmt.patch"
- name: Keep formatting corrections on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: rustfmt-patch
path: ${{ runner.temp }}/rustfmt.patch
retention-days: 7
if-no-files-found: ignore
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install the pinned Rust toolchain
shell: bash
run: |
version=$(python3 -c 'import tomllib; print(tomllib.load(open("mise.toml", "rb"))["tools"]["rust"]["version"])')
rustup toolchain install "$version" --profile minimal --component clippy
rustup override set "$version"
- name: Check translations
run: python3 scripts/check-i18n.py
- name: Run tests
run: |
set -o pipefail
cargo test --locked 2>&1 | tee "$RUNNER_TEMP/tests.log"
- name: Check lints
run: |
set -o pipefail
cargo clippy --locked --all-targets --all-features -- -D warnings 2>&1 | tee "$RUNNER_TEMP/clippy.log"
- name: Verify source package
run: cargo package --locked
- name: Keep check logs
if: always()
uses: actions/upload-artifact@v4
with:
name: check-logs
path: ${{ runner.temp }}/*.log
retention-days: 7
if-no-files-found: ignore
- name: Keep the checked source package
uses: actions/upload-artifact@v4
with:
name: lmm-cli-source-${{ github.sha }}
path: target/package/*.crate
retention-days: 7
if-no-files-found: error
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ fixtures instead of real account, system configuration or production writes.
Run fmt, clippy and the complete CLI tests locally. Report the tested commit and
skipped checks. A source change does not authorize publishing a crate, release
or production deployment.

Keep user-facing text in locales/en.json and locales/zh-CN.json, not Rust source.
Use stable message keys and named placeholders. Do not translate command names,
JSON field names, identifiers or protocol values. Run scripts/check-i18n.py and
read docs/i18n.md when adding messages. Keep both README versions in sync.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ homepage = "https://api.lmm.best"
readme = "README.md"
keywords = ["lmm", "cli", "oauth", "ai"]
categories = ["command-line-utilities"]
include = ["Cargo.toml", "Cargo.lock", "README.md", "LICENSE", "src/**", "tests/**", "docs/**", "NOTICE", "third_party/**", "scripts/*.py"]
include = ["Cargo.toml", "Cargo.lock", "README.md", "README.zh-CN.md", "locales/**", "mise.toml", "LICENSE", "src/**", "tests/**", "docs/**", "NOTICE", "third_party/**", "scripts/*.py"]

[lib]
name = "lmm"
Expand Down
122 changes: 122 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{
"arg.activate": "Request adding and selecting LMM; this does not mean it has been applied",
"arg.add_only": "Add LMM without changing the current selection",
"arg.all": "Include only installed, supported targets; updates also require management approval",
"arg.dry_run": "Create a plan without applying changes",
"arg.fix": "Request approved LMM repairs without bypassing capability checks",
"arg.instance": "Explicit local instance root; remote and Docker instances are not scanned",
"arg.issuer": "Trusted LMM HTTPS origin; set explicitly for a self-hosted server",
"arg.json": "Write JSON without CLI prompts or configuration contents",
"arg.lang": "Display language: en or zh-CN; overrides LMM_LANG and locale variables",
"arg.no_browser": "Print the login URL; the browser must still reach this machine through loopback",
"arg.non_interactive": "Do not wait for input when a target or authorization is missing",
"arg.query": "Search text; omit to list all entries",
"arg.report": "Create a shareable report without paths or configuration contents",
"arg.software": "Exact catalog ID, such as astrbot or cc-switch",
"arg.timeout": "Maximum wait for the browser callback, in seconds",
"arg.yes": "Approve the displayed scope, not account changes, provider switches, or paid tests",
"auth.already_logged_in": "The CLI is already signed in; run lmm logout before switching accounts. Application grants will not be transferred",
"auth.busy": "Another LMM authorization operation is running, or a secure per-user lock could not be created",
"auth.callback": "Could not bind the local OAuth callback port",
"auth.credential_store": "Could not access the system vault. Unlock Keychain, Credential Manager, or Secret Service; plain-text files will not be used",
"auth.denied": "Authorization was cancelled or denied",
"auth.invalid_issuer": "issuer must be a canonical HTTPS domain origin without a port, path, query, or credentials",
"auth.invalid_response": "The LMM OAuth response was invalid; authorization has stopped",
"auth.network": "The LMM network request failed; check connectivity and whether the server has enabled the lmm client",
"auth.not_logged_in": "Not signed in; run lmm login first",
"auth.output": "Could not display the login URL; login has stopped",
"auth.refresh_blocked": "The previous refresh did not complete reliably. The old refresh token will not be reused; run logout, then login",
"auth.timeout": "Login timed out; no further requests were sent",
"auth.unauthorized": "The server rejected authorization; sign in again or check that the lmm client is deployed",
"auth.unstored_grant": "The new grant could not be saved and revocation could not be confirmed; check LMM CLI on the LMM authorization page",
"callback.invalid": "Invalid or denied authorization. Return to LMM CLI.",
"callback.received": "Authorization received. Return to LMM CLI to check completion.",
"cli.about": "LMM: provider presets, software discovery, and read-only OAuth (development preview)",
"cmd.catalog": "Search the software catalog; entries are not verified integrations",
"cmd.disconnect": "Plan removal of an integration and its application grant",
"cmd.doctor": "Run read-only checks; --fix still requires adapter support and approval",
"cmd.help": "Print help for a command",
"cmd.install": "Plan software installation; LMM login is not required",
"cmd.login": "Sign in with a browser and store credentials in the system vault",
"cmd.logout": "Sign out of the CLI without revoking other application grants",
"cmd.models": "Read authorized models and prices without calling or selecting a model",
"cmd.presets": "Search the built-in provider snapshot without reading credentials or using the network",
"cmd.restore": "Plan field-level restoration while preserving later user edits",
"cmd.run": "Request a launch with the selected software configuration",
"cmd.setup": "Preview setup; writes stay blocked until a verified adapter is available",
"cmd.status": "Inspect local environment and path evidence without making changes",
"cmd.sync": "Plan an LMM refresh while preserving the current provider and model",
"cmd.uninstall": "Plan removal of managed software; keep user data by default",
"cmd.update": "Plan updates for software explicitly placed under management",
"error.auth_unattended": "The system vault may need to be unlocked; OAuth commands do not support --non-interactive yet. No credentials or network were accessed",
"error.catalog_output": "Could not write the software catalog",
"error.config_shape": "not a bounded regular configuration file",
"error.config_size": "configuration exceeds size limit",
"error.instance_unsupported": "Instance selection is not supported for this software; --instance will not be ignored",
"error.invalid_instance": "--instance must be an absolute local path for this environment; remote and container adapters are not available",
"error.json_output": "Could not write JSON",
"error.login_interactive": "Login needs browser approval; run lmm login in an interactive terminal. Unattended mode will not wait or consent for you",
"error.login_output": "Could not write the login result",
"error.logout_output": "Could not write the logout result",
"error.menu_output": "Could not display the selection menu",
"error.models_output": "Could not write models",
"error.no_selection": "No target selected; no changes were made",
"error.output": "Could not write results",
"error.presets_output": "Could not write provider presets",
"error.presets_read": "Could not read the built-in provider presets",
"error.selection_input": "Could not read the selection",
"error.target_required": "Unattended mode requires a software ID or --all; no changes were made",
"error.unknown_software": "Unknown software ID; run lmm catalog to find the exact name",
"error.unsupported_language": "Unsupported language. Use en or zh-CN.",
"help.arguments": "Arguments",
"help.commands": "Commands",
"help.help": "Print help",
"help.options": "Options",
"help.template": "{about-with-newline}\nUsage: {usage}\n\n{all-args}{after-help}",
"help.version": "Print version",
"kind.local": "local",
"kind.relay": "relay",
"kind.remote": "remote",
"kind.vendor": "vendor",
"note.all_blocked": "No automatic integration adapter has been verified; --all has no executable targets. No software was installed or changed",
"note.doctor_incomplete": "Diagnosis is incomplete: only local path evidence was checked. Check the selected instance, version, and configuration manager. No network or paid tests were run",
"note.dry_run": "Plan only; blockers remain unresolved. This is not evidence of a completed integration",
"note.execution_blocked": "No safe execution adapter is available for this target; no software was started or removed, no configuration changed, and no grants revoked",
"note.fix_blocked": "No repair adapter has been verified; configuration was not changed",
"note.install": "Installation does not require LMM login; a verified installation adapter is not available yet",
"note.yes": "--yes does not bypass missing capabilities, authorization, or cost limits",
"observation.not_found": "Not found",
"observation.present": "Present",
"observation.unknown": "Unknown",
"output.authorization_url": "Approve LMM CLI in your browser (catalog and balance reads only; no application migration):\n{url}",
"output.blocked_plan": "\n{software} plan blocked: no configuration changes, paid calls, or restarts",
"output.browser_failed": "The browser could not be opened. Open the URL above in a browser on this machine.",
"output.catalog_entry": "{id} - {name}\n {purpose}\n Source: {source}\n Installation/integration: unavailable; maintenance: local evidence only; versions/platforms/scenarios: unverified\n",
"output.evidence": " {path}: {observation} (path evidence only)",
"output.login": "LMM CLI is signed in. Credentials are stored in the system vault. Applications have not been granted model-call permission; run lmm models to read the catalog.",
"output.logout": "CLI signed out. Other application grants were not revoked and cannot be listed by this version.",
"output.model_entry": "{id} / {upstream} / {group}\n Price unit: {currency} / {unit}; input: {input}, output: {output}, per request: {request}; basis: {basis}\n null/None means unknown; no model was called or selected.",
"output.models": "Authorized models (application compatibility is not verified; final costs depend on usage):",
"output.presets": "Built-in provider presets (Magpie snapshot {revision}); configuration and connectivity were not checked. No providers were added.",
"output.scope": "Scope: current user and runtime environment; checked at {time} (Unix seconds)",
"output.target": "\n{software}: installation cannot be confirmed; installation and configuration managers are unknown",
"output.verification": " LMM added/active: unknown; authorization, connectivity, application, streaming, and tool calls: not checked",
"plan.application_grant": "CLI login allows only catalog and balance reads; separate application authorization is not connected yet",
"plan.install_adapter": "A verified software version, download-source check, and installation adapter are required",
"plan.paid_verification": "Paid verification requires explicit consent, a known quote, and a server-enforced spending limit",
"plan.restore_adapter": "No target change journal or native transaction adapter is connected; backups cannot be overwritten directly",
"plan.revoked_grant": "The application grant was revoked; explicit approval is required to authorize it again",
"plan.unknown_selection": "The current provider is unknown; first read the selected instance configuration",
"plan.unverified_target": "The software version, configuration manager, and actual request path have not been verified",
"plan.write_adapter": "This version has no verified configuration-write adapter for the target software",
"purpose.astrbot": "Agent and bot runtime for messaging platforms",
"purpose.cc_switch": "Provider configuration management and local routing",
"purpose.coding": "Coding assistant for the terminal",
"purpose.pi": "Terminal agent; its LMM provider is a separate project",
"restore.conflict": "The field changed after LMM wrote it; restoration has stopped",
"restore.duplicate_field": "The change journal contains duplicate fields",
"restore.invalid_pointer": "Could not locate the parent object for the field to restore",
"restore.unsupported_shape": "Only individual scalar fields in objects are supported; collections need a dedicated adapter",
"select.prompt": "Enter a number, or press Enter to cancel: ",
"select.title": "Select software to plan setup (no integration has been verified yet):"
}
Loading
Loading