diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index cbf47b2..a730f53 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "meshy-3d-agent", - "version": "0.8.0", + "version": "0.8.1", "description": "Generate 3D models, textures, and images, rig and animate characters, and prepare models for 3D printing with the Meshy AI API.", "author": { "name": "Meshy", diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 523f5a4..c12bac9 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "meshy-3d-agent", - "version": "0.8.0", + "version": "0.8.1", "description": "Generate 3D models, textures, and images, rig and animate characters, and prepare models for 3D printing with the Meshy AI API.", "author": { "name": "Meshy" diff --git a/.github/workflows/validate-skills.yml b/.github/workflows/validate-skills.yml index ed602b9..1f04206 100644 --- a/.github/workflows/validate-skills.yml +++ b/.github/workflows/validate-skills.yml @@ -41,7 +41,7 @@ jobs: echo "MESHY_CLI_BIN=$RUNNER_TEMP/meshy-cli/node_modules/meshy-cli/dist/index.js" >> "$GITHUB_ENV" # Covers auth, runner, generation and printing contracts. The runner test runs the - # documented `npm exec --package=meshy-cli@0.7` entry point, so it reaches the npm + # documented `npm exec --package=meshy-cli@0.7.3` entry point, so it reaches the npm # registry; every API call in the suite stays on loopback with synthetic credentials. - name: Isolated CLI contract tests (no live API) run: node --test tests/*.test.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e80940..c8a7a9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [0.8.1] - 2026-10-30 + +### Changed + +- Meshy CLI 0.7.3 or later (still the `meshy-cli@0.7` range). 0.7.3 keeps the device code out of + `auth login --no-wait`, which the two-step sign-in below relies on. +- The temporary package names `meshy-cli@0.7.3` exactly: `npm exec` with the `0.7` range kept + reusing whichever 0.7.x it had cached first (0.7.1 on a machine that ran it before). The global + install keeps the range and resolves the newest 0.7.x. +- The runner installs the CLI at most once: a version still too old afterwards means the + registry the machine uses lags npm, and the agent reports that instead of looping. + +### Added + +- Remote chat sign-in. A user on a phone, talking to the agent through a chat bot, never saw the + link while the login waited in the same turn. Setup now signs in across two turns: + `meshy auth login --device --no-wait` returns the link (code included) and a flow id, the agent + ends the turn with it, and `meshy auth login --device-flow FLOW_ID` finishes on the user's + reply. A host whose question tool reaches the user (dsh's `ask_user_question`) can wait in the + same turn instead. Contract test against the published CLI. +- A host with a file-delivery tool (dsh's `present`) also gets the delivered model through it. + ## [0.8.0] - 2026-10-30 ### Changed diff --git a/INSTALL.md b/INSTALL.md index b26d7c1..d2ff575 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -21,7 +21,7 @@ If Node.js is missing or older, stop and ask the user to install a current Node. meshy --version ``` -- It prints 0.7.1 or a later 0.7.x: keep it. The skills are written for 0.7, and another minor +- It prints 0.7.3 or a later 0.7.x: keep it. The skills are written for 0.7, and another minor version can change flags and output. - It prints an older version, or there is no `meshy`: install the newest 0.7.x. @@ -30,7 +30,7 @@ npm install -g meshy-cli@0.7 ``` - It prints 0.8 or newer: do not downgrade it, since something else may rely on it. Use the - temporary 0.7 package `npm exec --yes --package=meshy-cli@0.7 -- meshy …` as `meshy` in the + temporary package `npm exec --yes --package=meshy-cli@0.7.3 -- meshy …` as `meshy` in the steps below. If the global install is refused (permissions, a managed machine), leave it and use the same diff --git a/README.md b/README.md index fcf2e21..f19f970 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Meshy 3D Agent Meshy skills for creating digital assets and preparing 3D prints. All three skills drive -**Meshy CLI 0.7** (0.7.1 or later, `meshy`) on **Node.js 22.12+**. They are instructions and references only — -no bundled runtime scripts. Current release: **0.8.0**. +**Meshy CLI 0.7** (0.7.3 or later, `meshy`) on **Node.js 22.12+**. They are instructions and references only — +no bundled runtime scripts. Current release: **0.8.1**. ## Let your agent install it @@ -33,7 +33,7 @@ Two more things worth knowing: - **The agent installs the CLI.** With Node 22.12+ and no `meshy` (or an older one), it runs `npm install -g meshy-cli@0.7`. Where a global install is not allowed, or a newer CLI is already installed, it runs the pinned package temporarily instead - (`npm exec --yes --package=meshy-cli@0.7 -- meshy …`). + (`npm exec --yes --package=meshy-cli@0.7.3 -- meshy …`). - **Local print work needs no account.** Rescaling an OBJ or opening a 3MF in a slicer runs entirely on your machine — no login, no balance check, no credits. diff --git a/scripts/validate_skills.py b/scripts/validate_skills.py index e9bd6f1..e15fb80 100644 --- a/scripts/validate_skills.py +++ b/scripts/validate_skills.py @@ -10,13 +10,13 @@ ROOT = Path(__file__).resolve().parent.parent SKILLS = ("meshy-3d-generation", "meshy-3d-printing", "meshy-openclaw") -VERSION = "0.8.0" +VERSION = "0.8.1" # The Meshy CLI the skills are written for: any 0.7.x from MIN_CLI. Package specs use the range. CLI = "0.7" -MIN_CLI = "0.7.1" +MIN_CLI = "0.7.3" LINK = re.compile(r"\[[^\]]*\]\(([^)]+)\)") # The pinned temporary-package runner documented in setup.md; recipes stay written as `meshy ...`. -RUNNER = ["npm", "exec", "--yes", f"--package=meshy-cli@{CLI}", "--"] +RUNNER = ["npm", "exec", "--yes", f"--package=meshy-cli@{MIN_CLI}", "--"] # Written paths are placeholders resolved from the user's request, never a hardcoded directory. WORKSPACE_FLAGS = ("--workspace", "WORKSPACE") @@ -97,9 +97,10 @@ def validate_skill(folder): require(markdown <= reachable, f"{folder}: unreachable documents {markdown - reachable}") # The first-run contract each skill must be able to answer on its own. setup = (folder / "references" / "setup.md").read_text() - for needle in (f"npm exec --yes --package=meshy-cli@{CLI} -- meshy", "auth login --device", "--region cn", "./meshy_output", "WORKSPACE", "JOB_DIR"): + for needle in (f"npm exec --yes --package=meshy-cli@{MIN_CLI} -- meshy", "auth login --device", "--region cn", "./meshy_output", "WORKSPACE", "JOB_DIR"): require(needle in setup, f"{folder}: setup.md does not document {needle!r}") - require("--no-wait" not in re.sub(r"Do not use `--no-wait`[^.]*\.", "", setup), f"{folder}: setup.md must not use the device-secret login mode") + # --no-wait only in the two-step sign-in, which resumes by flow_id (CLI 0.7.3 no longer prints the device code). + require("--no-wait" not in setup or "--device-flow FLOW_ID" in setup, f"{folder}: --no-wait without the --device-flow resume") delivery = (folder / "references" / "delivery.md").read_text() for needle in ("thumbnail.primary", "docs.meshy.ai/en/api/pricing", "--dry-run", "_meta.json"): require(needle in delivery, f"{folder}: delivery.md does not document {needle!r}") diff --git a/skills/meshy-3d-generation/SKILL.md b/skills/meshy-3d-generation/SKILL.md index b17dac9..98571d1 100644 --- a/skills/meshy-3d-generation/SKILL.md +++ b/skills/meshy-3d-generation/SKILL.md @@ -2,12 +2,12 @@ name: meshy-3d-generation description: "Generates and edits digital 3D assets with the Meshy CLI: text-to-3D and image-to-3D models, texturing, remeshing and LODs, UV unwrapping, format conversion (GLB, FBX, OBJ, USDZ, STL, 3MF, Blender), rigging, animation, motion clips from text and reference images. Use when the user asks to make, texture, rig, animate or convert a 3D model or game asset. For physical 3D printing use meshy-3d-printing." license: MIT -compatibility: "Needs Node.js 22.12+ and the Meshy CLI 0.7.x, 0.7.1 or later (npm install -g meshy-cli@0.7); network access to the Meshy API." +compatibility: "Needs Node.js 22.12+ and the Meshy CLI 0.7.x, 0.7.3 or later (npm install -g meshy-cli@0.7); network access to the Meshy API." --- # Meshy 3D Generation -Use Meshy CLI **0.7** (0.7.1 or later) to turn the user's request into a delivered asset. Completion means +Use Meshy CLI **0.7** (0.7.3 or later) to turn the user's request into a delivered asset. Completion means saving the requested files in the requested location, inspecting an available preview, and finishing any project integration the user requested. Login or task submission alone is not completion. Choose the shortest suitable pipeline and reuse existing assets for follow-ups. @@ -29,13 +29,14 @@ existing GLB needs no extra format conversion. Use command help when parameters ## First use and authorization Before the first command run `meshy --version`; no need to ask. When `meshy` is missing or -older than 0.7.1, install the newest 0.7.x with `npm install -g meshy-cli@0.7` and say so in +older than 0.7.3, install the newest 0.7.x with `npm install -g meshy-cli@0.7` and say so in one line; Setup covers a refused install and a CLI of 0.8 or newer. Reuse a verified session. If login is needed, follow Setup and run `auth login --device` (adding `--region cn` for a user in mainland China) in a persistent tool session. Show its verification URL and user code in **commentary/progress, not a final answer**. Await that same session in this turn until it exits, verify `auth status`, then continue the original request. -A background process cannot resume a finished turn; do not require a "done" chat message. +A background process cannot resume a finished turn; do not require a "done" chat message, except in +Setup's two-step sign-in for a user on a remote chat (a phone through a chat bot). Browser approval stays with the user; credentials never belong in chat. ## Execution boundaries diff --git a/skills/meshy-3d-generation/references/delivery.md b/skills/meshy-3d-generation/references/delivery.md index 0d16a15..a7b0286 100644 --- a/skills/meshy-3d-generation/references/delivery.md +++ b/skills/meshy-3d-generation/references/delivery.md @@ -99,7 +99,9 @@ Deliver four things, every time: 1. **The model file**, at the path the user asked for, written as a plain path in backticks. Do not present it as a clickable link: hosts open such links in a text/preview pane that - cannot render a binary mesh, and it looks broken. Offer the next real action instead — + cannot render a binary mesh, and it looks broken. A host with a tool that delivers files to the + user (dsh's `present`) gets the model through that tool as well, so it opens from the + conversation. Offer the next real action instead — reveal it in the file manager (`open -R ` on macOS, `explorer /select,` on Windows), open it in a local 3D tool, or wire it into the project. 2. **The preview**, shown inline when one exists, or an explicit note that none does. diff --git a/skills/meshy-3d-generation/references/setup.md b/skills/meshy-3d-generation/references/setup.md index fcc6ed9..cf1a5be 100644 --- a/skills/meshy-3d-generation/references/setup.md +++ b/skills/meshy-3d-generation/references/setup.md @@ -2,7 +2,7 @@ Shared by the generation and print workflows. Three things are settled before any job starts: **how to run the CLI**, **whether a session already exists**, and **where files go**. -The supported CLI is **0.7.x, from 0.7.1,** on **Node.js 22.12 or newer**. No Python, request wrapper or +The supported CLI is **0.7.x, from 0.7.3,** on **Node.js 22.12 or newer**. No Python, request wrapper or separate token store is involved. Contents: 1 runner · 2 reuse a session · 3 first login · 4 where files go · 5 one session @@ -17,26 +17,29 @@ meshy --version | Observation | What to do | |---|---| -| `meshy --version` prints 0.7.1 or a later 0.7.x | run `meshy` | -| no `meshy` command, or a version older than 0.7.1 | install the newest 0.7.x (below), then run `meshy` | -| 0.8 or newer | keep it, since something else may rely on it, and run the temporary 0.7 package | +| `meshy --version` prints 0.7.3 or a later 0.7.x | run `meshy` | +| no `meshy` command, or a version older than 0.7.3 | install the newest 0.7.x (below), then run `meshy` | +| 0.8 or newer | keep it, since something else may rely on it, and run the temporary package | | no Node.js, or Node older than 22.12 | stop and report it: the user installs Node.js 22.12+ | ```bash npm install -g meshy-cli@0.7 ``` -Check and install without asking first; say in one line that you are installing it. Never use `sudo` or change system policy: when the -install is refused (permissions, a managed machine, a sandbox), use the temporary 0.7 package +Check and install without asking first; say in one line that you are installing it. Install at +most once: when `meshy --version` still reports a version older than 0.7.3 afterwards, the +registry this machine uses lags npm, so report that instead of installing again. Never use `sudo` +or change system policy: when the install is refused (permissions, a managed machine, a sandbox), use the temporary package instead. It runs the same CLI without installing anything: put `npm exec --yes ---package=meshy-cli@0.7 --` in front of the same arguments, and the exit code and the JSON on +--package=meshy-cli@0.7.3 --` in front of the same arguments, and the exit code and the JSON on stdout are forwarded unchanged. Recipes are written as `meshy …`; example: ```bash -npm exec --yes --package=meshy-cli@0.7 -- meshy auth status --format json --no-update-check +npm exec --yes --package=meshy-cli@0.7.3 -- meshy auth status --format json --no-update-check ``` -The first such call downloads the package into the npm cache; later calls reuse it. On Windows +The first such call downloads the package into the npm cache; later calls reuse it. It names an +exact version because `npm exec` keeps reusing whatever matching version it cached first. On Windows both commands go through `npm.cmd`. A missing `npm` with a working Node.js means the host stripped npm: report that and ask the user to install the CLI themselves. @@ -138,12 +141,35 @@ Failure branches — each is a different recovery, so read the error rather than - **`device_flow_not_supported`**: this API host has no device endpoint. Ask the user to run `meshy auth login` in their own desktop terminal (loopback + browser), or to store their own key with `meshy auth login --with-key ` privately. Never ask for the key in chat. -- **Host cannot keep a process alive at all**: fall back to the user running the login command - in their own terminal, then re-check `auth status` and resume. This is the only case where a - manual terminal step is acceptable. +- **Host cannot keep a process alive at all**: use the two-step sign-in below. -Do not use `--no-wait`: its JSON contains a `device_code`, which is a bearer secret. Do not use -`--manual` from an agent — it prompts on stdin for a pasted code. Never show a token, a device +### Remote chat: sign in across two turns + +When the user talks to you through a chat bridge from another device (a phone in QQ, WeChat, +Slack or Telegram), progress messages may arrive late or only when the turn ends, so a link shown +while the login waits never reaches them. Sign in in two steps instead (add `--region cn` to the +first for the China site): + +```bash +meshy auth login --device --no-wait --format json --no-update-check +``` + +It returns at once with `result.verification_url` (the code is already in the link), +`result.user_code` and `result.flow_id`. Keep FLOW_ID in your notes and end the turn with the link +and the code: ask the user to open it in the phone's own browser rather than the chat app's (an +in-app browser may not keep the sign-in), approve, and reply when done. When they reply: + +```bash +meshy auth login --device-flow FLOW_ID --format json --no-update-check +``` + +It waits while the approval is still pending, saves the session and prints +`result.status: "logged_in"`; verify `auth status` and continue the original request. An expired +or unknown flow means running step one again. A host whose question tool reaches the user +(dsh's `ask_user_question` is forwarded by its chat bridges) can instead ask with the link and +wait for the answer in the same turn, then run step two. + +Do not use `--manual` from an agent — it prompts on stdin for a pasted code. Never show a token, a device code or a signed URL to the user or copy one into chat or a file: task results and sidecars carry signed URLs, so report paths and task IDs instead of pasting them. diff --git a/skills/meshy-3d-generation/references/troubleshooting.md b/skills/meshy-3d-generation/references/troubleshooting.md index 89a9286..d6b2611 100644 --- a/skills/meshy-3d-generation/references/troubleshooting.md +++ b/skills/meshy-3d-generation/references/troubleshooting.md @@ -11,11 +11,11 @@ timeout · deleting a task · local files. ## Runner problems -- **`meshy: command not found`** or **a version older than 0.7.1**: install the newest 0.7.x as - Setup describes. If the install is refused, use the temporary 0.7 package - (`npm exec --yes --package=meshy-cli@0.7 -- meshy …`) and carry on with the same job. +- **`meshy: command not found`** or **a version older than 0.7.3**: install the newest 0.7.x as + Setup describes. If the install is refused, use the temporary package + (`npm exec --yes --package=meshy-cli@0.7.3 -- meshy …`) and carry on with the same job. - **A global 0.8 or newer** answers `--version`. Do not uninstall or downgrade it; use the - temporary 0.7 package for this work and mention the mismatch once. + temporary package for this work and mention the mismatch once. - **Node older than 22.12** fails the CLI's own runtime gate. Report the required version and the installed one; do not try to relax it or run an older CLI. - **`npm exec` cannot reach the registry**: report the network/proxy error. A cached package diff --git a/skills/meshy-3d-printing/SKILL.md b/skills/meshy-3d-printing/SKILL.md index 932dda7..3033782 100644 --- a/skills/meshy-3d-printing/SKILL.md +++ b/skills/meshy-3d-printing/SKILL.md @@ -2,12 +2,12 @@ name: meshy-3d-printing description: "Generates and prepares models for physical 3D printing with the Meshy CLI: white and multicolor prints (3MF, STL, OBJ), printability analysis and repair, splitting into parts, Creative Lab products such as figures, lamps and keychains, sizing, and slicer handoff (Bambu Studio, OrcaSlicer, PrusaSlicer, Cura). Use when the user wants something 3D-printed or asks for print or slicer files." license: MIT -compatibility: "Needs Node.js 22.12+ and the Meshy CLI 0.7.x, 0.7.1 or later (npm install -g meshy-cli@0.7); network access to the Meshy API." +compatibility: "Needs Node.js 22.12+ and the Meshy CLI 0.7.x, 0.7.3 or later (npm install -g meshy-cli@0.7); network access to the Meshy API." --- # Meshy 3D Printing -Use Meshy CLI **0.7** (0.7.1 or later) to deliver the requested print files at the intended size, with +Use Meshy CLI **0.7** (0.7.3 or later) to deliver the requested print files at the intended size, with analysis/repair results where applicable and a slicer handoff when requested. This skill is self-contained. Ordinary digital assets belong to meshy-3d-generation. @@ -48,13 +48,14 @@ local dimension check cannot establish full printability. ## Cloud authorization Before the first command run `meshy --version`; no need to ask. When `meshy` is missing or -older than 0.7.1, install the newest 0.7.x with `npm install -g meshy-cli@0.7` and say so in +older than 0.7.3, install the newest 0.7.x with `npm install -g meshy-cli@0.7` and say so in one line; Setup covers a refused install and a CLI of 0.8 or newer. Local-only work stops at runner setup. Cloud work reuses a verified session. If login is needed, keep `auth login --device` running (with `--region cn` for a user in mainland China), show its URL and user code in **commentary/progress, never a final answer**, and await the same tool session in this turn. After it exits, verify `auth status` and resume the print job. -Do not ask for a "done" message or credentials in chat; Setup has the host wait procedure. +Never ask for credentials in chat, nor for a "done" message except in Setup's two-step sign-in for a +user on a remote chat (a phone through a chat bot); Setup has the host wait procedure. ## Printing-specific constraints diff --git a/skills/meshy-3d-printing/references/delivery.md b/skills/meshy-3d-printing/references/delivery.md index 0d16a15..a7b0286 100644 --- a/skills/meshy-3d-printing/references/delivery.md +++ b/skills/meshy-3d-printing/references/delivery.md @@ -99,7 +99,9 @@ Deliver four things, every time: 1. **The model file**, at the path the user asked for, written as a plain path in backticks. Do not present it as a clickable link: hosts open such links in a text/preview pane that - cannot render a binary mesh, and it looks broken. Offer the next real action instead — + cannot render a binary mesh, and it looks broken. A host with a tool that delivers files to the + user (dsh's `present`) gets the model through that tool as well, so it opens from the + conversation. Offer the next real action instead — reveal it in the file manager (`open -R ` on macOS, `explorer /select,` on Windows), open it in a local 3D tool, or wire it into the project. 2. **The preview**, shown inline when one exists, or an explicit note that none does. diff --git a/skills/meshy-3d-printing/references/setup.md b/skills/meshy-3d-printing/references/setup.md index fcc6ed9..cf1a5be 100644 --- a/skills/meshy-3d-printing/references/setup.md +++ b/skills/meshy-3d-printing/references/setup.md @@ -2,7 +2,7 @@ Shared by the generation and print workflows. Three things are settled before any job starts: **how to run the CLI**, **whether a session already exists**, and **where files go**. -The supported CLI is **0.7.x, from 0.7.1,** on **Node.js 22.12 or newer**. No Python, request wrapper or +The supported CLI is **0.7.x, from 0.7.3,** on **Node.js 22.12 or newer**. No Python, request wrapper or separate token store is involved. Contents: 1 runner · 2 reuse a session · 3 first login · 4 where files go · 5 one session @@ -17,26 +17,29 @@ meshy --version | Observation | What to do | |---|---| -| `meshy --version` prints 0.7.1 or a later 0.7.x | run `meshy` | -| no `meshy` command, or a version older than 0.7.1 | install the newest 0.7.x (below), then run `meshy` | -| 0.8 or newer | keep it, since something else may rely on it, and run the temporary 0.7 package | +| `meshy --version` prints 0.7.3 or a later 0.7.x | run `meshy` | +| no `meshy` command, or a version older than 0.7.3 | install the newest 0.7.x (below), then run `meshy` | +| 0.8 or newer | keep it, since something else may rely on it, and run the temporary package | | no Node.js, or Node older than 22.12 | stop and report it: the user installs Node.js 22.12+ | ```bash npm install -g meshy-cli@0.7 ``` -Check and install without asking first; say in one line that you are installing it. Never use `sudo` or change system policy: when the -install is refused (permissions, a managed machine, a sandbox), use the temporary 0.7 package +Check and install without asking first; say in one line that you are installing it. Install at +most once: when `meshy --version` still reports a version older than 0.7.3 afterwards, the +registry this machine uses lags npm, so report that instead of installing again. Never use `sudo` +or change system policy: when the install is refused (permissions, a managed machine, a sandbox), use the temporary package instead. It runs the same CLI without installing anything: put `npm exec --yes ---package=meshy-cli@0.7 --` in front of the same arguments, and the exit code and the JSON on +--package=meshy-cli@0.7.3 --` in front of the same arguments, and the exit code and the JSON on stdout are forwarded unchanged. Recipes are written as `meshy …`; example: ```bash -npm exec --yes --package=meshy-cli@0.7 -- meshy auth status --format json --no-update-check +npm exec --yes --package=meshy-cli@0.7.3 -- meshy auth status --format json --no-update-check ``` -The first such call downloads the package into the npm cache; later calls reuse it. On Windows +The first such call downloads the package into the npm cache; later calls reuse it. It names an +exact version because `npm exec` keeps reusing whatever matching version it cached first. On Windows both commands go through `npm.cmd`. A missing `npm` with a working Node.js means the host stripped npm: report that and ask the user to install the CLI themselves. @@ -138,12 +141,35 @@ Failure branches — each is a different recovery, so read the error rather than - **`device_flow_not_supported`**: this API host has no device endpoint. Ask the user to run `meshy auth login` in their own desktop terminal (loopback + browser), or to store their own key with `meshy auth login --with-key ` privately. Never ask for the key in chat. -- **Host cannot keep a process alive at all**: fall back to the user running the login command - in their own terminal, then re-check `auth status` and resume. This is the only case where a - manual terminal step is acceptable. +- **Host cannot keep a process alive at all**: use the two-step sign-in below. -Do not use `--no-wait`: its JSON contains a `device_code`, which is a bearer secret. Do not use -`--manual` from an agent — it prompts on stdin for a pasted code. Never show a token, a device +### Remote chat: sign in across two turns + +When the user talks to you through a chat bridge from another device (a phone in QQ, WeChat, +Slack or Telegram), progress messages may arrive late or only when the turn ends, so a link shown +while the login waits never reaches them. Sign in in two steps instead (add `--region cn` to the +first for the China site): + +```bash +meshy auth login --device --no-wait --format json --no-update-check +``` + +It returns at once with `result.verification_url` (the code is already in the link), +`result.user_code` and `result.flow_id`. Keep FLOW_ID in your notes and end the turn with the link +and the code: ask the user to open it in the phone's own browser rather than the chat app's (an +in-app browser may not keep the sign-in), approve, and reply when done. When they reply: + +```bash +meshy auth login --device-flow FLOW_ID --format json --no-update-check +``` + +It waits while the approval is still pending, saves the session and prints +`result.status: "logged_in"`; verify `auth status` and continue the original request. An expired +or unknown flow means running step one again. A host whose question tool reaches the user +(dsh's `ask_user_question` is forwarded by its chat bridges) can instead ask with the link and +wait for the answer in the same turn, then run step two. + +Do not use `--manual` from an agent — it prompts on stdin for a pasted code. Never show a token, a device code or a signed URL to the user or copy one into chat or a file: task results and sidecars carry signed URLs, so report paths and task IDs instead of pasting them. diff --git a/skills/meshy-3d-printing/references/troubleshooting.md b/skills/meshy-3d-printing/references/troubleshooting.md index 89a9286..d6b2611 100644 --- a/skills/meshy-3d-printing/references/troubleshooting.md +++ b/skills/meshy-3d-printing/references/troubleshooting.md @@ -11,11 +11,11 @@ timeout · deleting a task · local files. ## Runner problems -- **`meshy: command not found`** or **a version older than 0.7.1**: install the newest 0.7.x as - Setup describes. If the install is refused, use the temporary 0.7 package - (`npm exec --yes --package=meshy-cli@0.7 -- meshy …`) and carry on with the same job. +- **`meshy: command not found`** or **a version older than 0.7.3**: install the newest 0.7.x as + Setup describes. If the install is refused, use the temporary package + (`npm exec --yes --package=meshy-cli@0.7.3 -- meshy …`) and carry on with the same job. - **A global 0.8 or newer** answers `--version`. Do not uninstall or downgrade it; use the - temporary 0.7 package for this work and mention the mismatch once. + temporary package for this work and mention the mismatch once. - **Node older than 22.12** fails the CLI's own runtime gate. Report the required version and the installed one; do not try to relax it or run an older CLI. - **`npm exec` cannot reach the registry**: report the network/proxy error. A cached package diff --git a/skills/meshy-openclaw/SKILL.md b/skills/meshy-openclaw/SKILL.md index c089ae3..e28c28a 100644 --- a/skills/meshy-openclaw/SKILL.md +++ b/skills/meshy-openclaw/SKILL.md @@ -2,7 +2,7 @@ name: meshy-openclaw description: "Generates 3D models, textures, format conversions, reference images, rigging, animation and motion clips with the Meshy CLI, and prepares them for physical 3D printing: white or multicolor prints, printability repair, Creative Lab products, sizing and slicer handoff (Bambu Studio, OrcaSlicer, PrusaSlicer, Cura). Use when the user asks to make, texture, rig, animate or convert a 3D model, or wants something 3D-printed. Signs in through the browser; no API key required." license: MIT-0 -compatibility: "Needs Node.js 22.12+ and the Meshy CLI 0.7.x, 0.7.1 or later (npm install -g meshy-cli@0.7); network access to the Meshy API." +compatibility: "Needs Node.js 22.12+ and the Meshy CLI 0.7.x, 0.7.3 or later (npm install -g meshy-cli@0.7); network access to the Meshy API." metadata: openclaw: emoji: "🧊" @@ -23,7 +23,7 @@ metadata: # Meshy 3D — Generation + Printing -Use Meshy CLI **0.7** (0.7.1 or later) to turn the user's request into a delivered asset: the requested files +Use Meshy CLI **0.7** (0.7.3 or later) to turn the user's request into a delivered asset: the requested files in the requested location, an inspected preview when one exists, and — for prints — the intended size, analysis/repair results and a slicer handoff when asked. Login or task submission alone is not completion. Choose the shortest suitable pipeline and reuse existing @@ -32,7 +32,7 @@ assets for follow-ups. ## SECURITY MANIFEST **Executables:** the Meshy CLI — `meshy`, or the pinned temporary package -`npm exec --yes --package=meshy-cli@0.7 -- meshy` — plus `npm` to install it, +`npm exec --yes --package=meshy-cli@0.7.3 -- meshy` — plus `npm` to install it, `node --version` to check the runtime, and the file manager when the user asks to see a delivered file. No Python, no `curl`, no bundled scripts. @@ -99,7 +99,7 @@ missing choice materially changes the result. ## First use and sign-in on OpenClaw Before the first command run `meshy --version`; no need to ask. When `meshy` is missing or -older than 0.7.1, install the newest 0.7.x with `npm install -g meshy-cli@0.7` and say so in +older than 0.7.3, install the newest 0.7.x with `npm install -g meshy-cli@0.7` and say so in one line; Setup covers a refused install and a CLI of 0.8 or newer. Local-only print work stops there. Everything else reuses a verified `auth status` session; only when there is none, sign in: diff --git a/skills/meshy-openclaw/references/delivery.md b/skills/meshy-openclaw/references/delivery.md index 0d16a15..a7b0286 100644 --- a/skills/meshy-openclaw/references/delivery.md +++ b/skills/meshy-openclaw/references/delivery.md @@ -99,7 +99,9 @@ Deliver four things, every time: 1. **The model file**, at the path the user asked for, written as a plain path in backticks. Do not present it as a clickable link: hosts open such links in a text/preview pane that - cannot render a binary mesh, and it looks broken. Offer the next real action instead — + cannot render a binary mesh, and it looks broken. A host with a tool that delivers files to the + user (dsh's `present`) gets the model through that tool as well, so it opens from the + conversation. Offer the next real action instead — reveal it in the file manager (`open -R ` on macOS, `explorer /select,` on Windows), open it in a local 3D tool, or wire it into the project. 2. **The preview**, shown inline when one exists, or an explicit note that none does. diff --git a/skills/meshy-openclaw/references/setup.md b/skills/meshy-openclaw/references/setup.md index fcc6ed9..cf1a5be 100644 --- a/skills/meshy-openclaw/references/setup.md +++ b/skills/meshy-openclaw/references/setup.md @@ -2,7 +2,7 @@ Shared by the generation and print workflows. Three things are settled before any job starts: **how to run the CLI**, **whether a session already exists**, and **where files go**. -The supported CLI is **0.7.x, from 0.7.1,** on **Node.js 22.12 or newer**. No Python, request wrapper or +The supported CLI is **0.7.x, from 0.7.3,** on **Node.js 22.12 or newer**. No Python, request wrapper or separate token store is involved. Contents: 1 runner · 2 reuse a session · 3 first login · 4 where files go · 5 one session @@ -17,26 +17,29 @@ meshy --version | Observation | What to do | |---|---| -| `meshy --version` prints 0.7.1 or a later 0.7.x | run `meshy` | -| no `meshy` command, or a version older than 0.7.1 | install the newest 0.7.x (below), then run `meshy` | -| 0.8 or newer | keep it, since something else may rely on it, and run the temporary 0.7 package | +| `meshy --version` prints 0.7.3 or a later 0.7.x | run `meshy` | +| no `meshy` command, or a version older than 0.7.3 | install the newest 0.7.x (below), then run `meshy` | +| 0.8 or newer | keep it, since something else may rely on it, and run the temporary package | | no Node.js, or Node older than 22.12 | stop and report it: the user installs Node.js 22.12+ | ```bash npm install -g meshy-cli@0.7 ``` -Check and install without asking first; say in one line that you are installing it. Never use `sudo` or change system policy: when the -install is refused (permissions, a managed machine, a sandbox), use the temporary 0.7 package +Check and install without asking first; say in one line that you are installing it. Install at +most once: when `meshy --version` still reports a version older than 0.7.3 afterwards, the +registry this machine uses lags npm, so report that instead of installing again. Never use `sudo` +or change system policy: when the install is refused (permissions, a managed machine, a sandbox), use the temporary package instead. It runs the same CLI without installing anything: put `npm exec --yes ---package=meshy-cli@0.7 --` in front of the same arguments, and the exit code and the JSON on +--package=meshy-cli@0.7.3 --` in front of the same arguments, and the exit code and the JSON on stdout are forwarded unchanged. Recipes are written as `meshy …`; example: ```bash -npm exec --yes --package=meshy-cli@0.7 -- meshy auth status --format json --no-update-check +npm exec --yes --package=meshy-cli@0.7.3 -- meshy auth status --format json --no-update-check ``` -The first such call downloads the package into the npm cache; later calls reuse it. On Windows +The first such call downloads the package into the npm cache; later calls reuse it. It names an +exact version because `npm exec` keeps reusing whatever matching version it cached first. On Windows both commands go through `npm.cmd`. A missing `npm` with a working Node.js means the host stripped npm: report that and ask the user to install the CLI themselves. @@ -138,12 +141,35 @@ Failure branches — each is a different recovery, so read the error rather than - **`device_flow_not_supported`**: this API host has no device endpoint. Ask the user to run `meshy auth login` in their own desktop terminal (loopback + browser), or to store their own key with `meshy auth login --with-key ` privately. Never ask for the key in chat. -- **Host cannot keep a process alive at all**: fall back to the user running the login command - in their own terminal, then re-check `auth status` and resume. This is the only case where a - manual terminal step is acceptable. +- **Host cannot keep a process alive at all**: use the two-step sign-in below. -Do not use `--no-wait`: its JSON contains a `device_code`, which is a bearer secret. Do not use -`--manual` from an agent — it prompts on stdin for a pasted code. Never show a token, a device +### Remote chat: sign in across two turns + +When the user talks to you through a chat bridge from another device (a phone in QQ, WeChat, +Slack or Telegram), progress messages may arrive late or only when the turn ends, so a link shown +while the login waits never reaches them. Sign in in two steps instead (add `--region cn` to the +first for the China site): + +```bash +meshy auth login --device --no-wait --format json --no-update-check +``` + +It returns at once with `result.verification_url` (the code is already in the link), +`result.user_code` and `result.flow_id`. Keep FLOW_ID in your notes and end the turn with the link +and the code: ask the user to open it in the phone's own browser rather than the chat app's (an +in-app browser may not keep the sign-in), approve, and reply when done. When they reply: + +```bash +meshy auth login --device-flow FLOW_ID --format json --no-update-check +``` + +It waits while the approval is still pending, saves the session and prints +`result.status: "logged_in"`; verify `auth status` and continue the original request. An expired +or unknown flow means running step one again. A host whose question tool reaches the user +(dsh's `ask_user_question` is forwarded by its chat bridges) can instead ask with the link and +wait for the answer in the same turn, then run step two. + +Do not use `--manual` from an agent — it prompts on stdin for a pasted code. Never show a token, a device code or a signed URL to the user or copy one into chat or a file: task results and sidecars carry signed URLs, so report paths and task IDs instead of pasting them. diff --git a/skills/meshy-openclaw/references/troubleshooting.md b/skills/meshy-openclaw/references/troubleshooting.md index 89a9286..d6b2611 100644 --- a/skills/meshy-openclaw/references/troubleshooting.md +++ b/skills/meshy-openclaw/references/troubleshooting.md @@ -11,11 +11,11 @@ timeout · deleting a task · local files. ## Runner problems -- **`meshy: command not found`** or **a version older than 0.7.1**: install the newest 0.7.x as - Setup describes. If the install is refused, use the temporary 0.7 package - (`npm exec --yes --package=meshy-cli@0.7 -- meshy …`) and carry on with the same job. +- **`meshy: command not found`** or **a version older than 0.7.3**: install the newest 0.7.x as + Setup describes. If the install is refused, use the temporary package + (`npm exec --yes --package=meshy-cli@0.7.3 -- meshy …`) and carry on with the same job. - **A global 0.8 or newer** answers `--version`. Do not uninstall or downgrade it; use the - temporary 0.7 package for this work and mention the mismatch once. + temporary package for this work and mention the mismatch once. - **Node older than 22.12** fails the CLI's own runtime gate. Report the required version and the installed one; do not try to relax it or run an older CLI. - **`npm exec` cannot reach the registry**: report the network/proxy error. A cached package diff --git a/tests/auth-contract.test.mjs b/tests/auth-contract.test.mjs index 141ee11..b6fcc7d 100644 --- a/tests/auth-contract.test.mjs +++ b/tests/auth-contract.test.mjs @@ -79,7 +79,7 @@ async function fixture(t, handler) { } const version = await run(['--version']); assert.equal(version.code, 0); - assert.match(version.data, /^0\.7\.([1-9]\d*)$/, 'these contracts target Meshy CLI 0.7.1 or a later 0.7.x'); + assert.match(version.data, /^0\.7\.([3-9]|[1-9]\d+)$/, 'these contracts target Meshy CLI 0.7.3 or a later 0.7.x'); async function storeOauth(expiresAt = Date.now() + 3600000) { await writeFile(env.MESHY_CREDENTIALS_PATH, JSON.stringify({ auth_version: 1, active_profile: 'shared', profiles: { @@ -216,6 +216,48 @@ test('explicit key-file uses balance verification without requiring a stored pro assert.ok(!output.stdout.includes('msy_synthetic_key_file')); }); +// setup.md "Remote chat": step one returns at once with the link and a flow id and prints no +// device code (the agent relays it to a chat); step two finishes that flow after the approval. +test('two-step sign-in returns the link without the device code, then --device-flow finishes it', { skip }, async t => { + const DEVICE_CODE = 'synthetic-two-step-device-code'; + let approved = false; + const f = await fixture(t, (req, res) => { + const reply = (status, body) => { res.writeHead(status, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(body)); }; + if (req.url === '/openapi/v1/oauth/device_authorization') { + return reply(200, { + device_code: DEVICE_CODE, user_code: 'TWOS-TEP1', + verification_uri: 'https://www.meshy.ai/device', + verification_uri_complete: 'https://www.meshy.ai/device?user_code=TWOS-TEP1', + expires_in: 300, interval: 1, + }); + } + if (req.url === '/openapi/v1/oauth/token') { + if (!approved) return reply(400, { error: 'authorization_pending' }); + return reply(200, { access_token: 'synthetic-two-step-access', refresh_token: 'synthetic-two-step-refresh', token_type: 'Bearer', expires_in: 3600, user_id: 'synthetic-user' }); + } + if (req.url === '/openapi/v1/balance') return balance(res); + reply(404, {}); + }); + + const start = await f.run(['auth', 'login', '--device', '--no-wait']); + assert.equal(start.code, 0, start.stderr); + assert.equal(start.data.result.status, 'device_flow_started'); + assert.equal(start.data.result.verification_url, 'https://www.meshy.ai/device?user_code=TWOS-TEP1', 'the link carries the code'); + assert.equal(start.data.result.user_code, 'TWOS-TEP1'); + assert.ok(!`${start.stdout}${start.stderr}`.includes(DEVICE_CODE), 'step one prints no device code'); + + approved = true; // the user approved on their phone and replied + const finish = await f.run(['auth', 'login', '--device-flow', start.data.result.flow_id]); + assert.equal(finish.code, 0, finish.stderr); + assert.equal(finish.data.result.status, 'logged_in'); + assert.equal(finish.data.result.verified, true); + for (const secret of [DEVICE_CODE, 'synthetic-two-step-access', 'synthetic-two-step-refresh']) { + assert.ok(!`${finish.stdout}${finish.stderr}`.includes(secret), 'no bearer secret is printed'); + } + const status = await f.run(['auth', 'status'], f.cwdB); + assert.equal(status.data.result.verified, true); +}); + // CLI-level contract only: delayed synthetic approval completes the original process. // This does NOT prove an agent keeps its turn alive; that needs a host behavioral check. test('device login publishes the verification URL and code before it exits, then stores a verified session', { skip }, async t => { diff --git a/tests/generation-recipes.test.mjs b/tests/generation-recipes.test.mjs index 7d3b49b..4dfcf58 100644 --- a/tests/generation-recipes.test.mjs +++ b/tests/generation-recipes.test.mjs @@ -111,7 +111,7 @@ async function fixture(t, respond) { } const version = await run(['--version']); assert.equal(version.code, 0, version.stderr); - assert.match(version.stdout.trim(), /^0\.7\.([1-9]\d*)$/, 'these recipes require Meshy CLI 0.7.1 or a later 0.7.x'); + assert.match(version.stdout.trim(), /^0\.7\.([3-9]|[1-9]\d+)$/, 'these recipes require Meshy CLI 0.7.3 or a later 0.7.x'); const image = join(cwd, 'reference photo.png'); const png = Buffer.from('89504e470d0a1a0a0000000000000000', 'hex'); await writeFile(image, png); diff --git a/tests/printing-recipes.test.mjs b/tests/printing-recipes.test.mjs index 801ab2b..9c4b127 100644 --- a/tests/printing-recipes.test.mjs +++ b/tests/printing-recipes.test.mjs @@ -106,7 +106,7 @@ async function fixture(t) { }); } async function ok(args) { const r = await run(args); assert.equal(r.code, 0, r.stdout + r.stderr); return r.json; } - const version = await run(['--version']); assert.match(version.stdout.trim(), /^0\.7\.([1-9]\d*)$/); assert.equal(version.code, 0); + const version = await run(['--version']); assert.match(version.stdout.trim(), /^0\.7\.([3-9]|[1-9]\d+)$/); assert.equal(version.code, 0); // The documented default job location, resolved the same way a user-named directory would be. const workspace = join(root, 'job output'); await mkdir(workspace); diff --git a/tests/runner-contract.test.mjs b/tests/runner-contract.test.mjs index cad8c3d..e7ff91b 100644 --- a/tests/runner-contract.test.mjs +++ b/tests/runner-contract.test.mjs @@ -17,7 +17,7 @@ const documented = [...setupDoc.matchAll(/```bash\n([\s\S]*?)```/g)] .filter(line => line.startsWith('npm exec ')); assert.equal(documented.length, 1, 'setup.md documents exactly one temporary-package invocation'); const RUNNER = documented[0].split(' ').slice(0, 5); -assert.deepEqual(RUNNER, ['npm', 'exec', '--yes', '--package=meshy-cli@0.7', '--'], RUNNER.join(' ')); +assert.deepEqual(RUNNER, ['npm', 'exec', '--yes', '--package=meshy-cli@0.7.3', '--'], RUNNER.join(' ')); const DOCUMENTED_ARGS = documented[0].split(' ').slice(5); // Shared between runs so only the first execution on a machine downloads the package. const NPM_CACHE = join(tmpdir(), 'meshy-skill-runner-npm-cache'); @@ -65,7 +65,7 @@ test('the pinned temporary package is the CLI, forwards flags and exit codes, an const version = await f.run([...RUNNER.slice(1), 'meshy', '--version'], f.generation); assert.equal(version.code, 0, version.stderr); - assert.match(version.stdout.trim(), /^0\.7\.([1-9]\d*)$/, 'the temporary package is a supported 0.7.x'); + assert.match(version.stdout.trim(), /^0\.7\.([3-9]|[1-9]\d+)$/, 'the temporary package is a supported 0.7.x'); // Documented command, verbatim, with no credential anywhere: the CLI's own exit code survives npm. const missing = await f.run([...RUNNER.slice(1), ...DOCUMENTED_ARGS], f.generation);