Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ Maker 本地开发的默认路径是 CLI-first + PAT-first:
- Maker 鉴权文件必须沿用线上已发布版本的原始本地保存路径,不要为 production 或 rnd 新建环境子目录;不要在用户文档或普通用户说明里暴露具体凭证缓存路径。
- 用户可运行 `taptap-maker login` 主动刷新当前环境鉴权;`taptap-maker init` 和无参数 `taptap-maker pat set` 缺 PAT 时也走 CLI 登录。兼容写法 `taptap-maker pat set <PAT>`、`--pat PAT` 或 `--pat-stdin` 仅用于 CI / 应急联调,其中 argv 形式会让 PAT 进入 `ps`/shell history。
- 本地研发环境配置只作为内部开发能力处理:CLI/MCP 按当前环境使用对应配置,显式 `--env` 或 `TAPTAP_MCP_ENV` 优先;项目目录级配置只读取 `.maker/taptap-maker.local.json`,不读取项目根目录散落的本地配置文件;不要把内部研发配置写入面向用户的 README/使用文档。
- `taptap-maker init` 会检查 Git、Python 环境、maker-lua-lsp 本地 Lua 诊断环境、PAT、TapTap token、当前目录绑定状态、app 列表、AI dev kit,并在用户选择 app 后先记录 `.maker-mcp/config.json`,再 checkout 到当前目录;Python 未就绪时会自动尝试准备,最多 3 次,仍失败则暂停 init 且不继续 PAT、app、clone 或 MCP 配置;Python ready 后会 best-effort 安装/升级 `maker-lua-lsp` 并执行 `maker-lua-lsp install --ide codex,cursor,claude`,LSP 失败只提示错误且不阻塞远端构建。clone/fetch 失败后重复执行 init 会复用已记录 app,显式选择不同 app 会拒绝覆盖已有绑定。app 文本预览默认展示前 40 个;账号 app 很多时在 init 交互中输入 `all` 一次性展开全部,或单独跑 `taptap-maker apps --all`;`taptap-maker apps --json` 仅给 AI / 脚本解析使用。AI 转述时宽屏可用两列紧凑布局,窄屏保持单列;每个 app 保留 app_id,并在用户确认后选择 app。
- `taptap-maker init` 会检查 Git、Python 环境、maker-lua-lsp 本地 Lua 诊断环境、PAT、TapTap token、当前目录绑定状态、app 列表、AI dev kit,并在用户选择 app 后先记录 `.maker-mcp/config.json`,再 checkout 到当前目录;Python 未就绪时会自动尝试准备,最多 3 次,仍失败则暂停 init 且不继续 PAT、app、clone 或 MCP 配置;Python ready 后会 best-effort 创建 Maker 私有 LSP venv,在其中安装/升级 `maker-lua-lsp` 并执行 `maker-lua-lsp install --ide codex,cursor,claude`,LSP 失败只提示错误且不阻塞远端构建。clone/fetch 失败后重复执行 init 会复用已记录 app,显式选择不同 app 会拒绝覆盖已有绑定。app 文本预览默认展示前 40 个;账号 app 很多时在 init 交互中输入 `all` 一次性展开全部,或单独跑 `taptap-maker apps --all`;`taptap-maker apps --json` 仅给 AI / 脚本解析使用。AI 转述时宽屏可用两列紧凑布局,窄屏保持单列;每个 app 保留 app_id,并在用户确认后选择 app。
- AI dev kit 安装/更新按当前环境查询最新版本信息,按返回的 `current.version` 生成版本化下载 URL;版本检查失败时降级使用内置默认下载地址。安装成功后记录本地已安装版本,`taptap-maker doctor`、`maker://status` 和 `maker_status_lite` 输出当前版本、最新版本和是否可更新。
- `taptap-maker init` 首次拉取默认使用 `git init` + `git fetch --depth=1 origin` + checkout;Git clone/fetch 会按错误内容判断是否自动重试:503、HTTP 5xx、超时、连接重置、RPC/HTTP2 中断等远端临时错误会重试;认证、权限、仓库不存在、远端拒绝和本地目录冲突不重试。
- 首次 clone/fetch 前必须提示用户:Maker server 可能正在准备仓库,首次拉代码 20 秒以上是正常现象,请保持当前命令运行。
Expand Down
12 changes: 7 additions & 5 deletions docs/MAKER.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ CLI 命令:
- `taptap-maker python setup`:自动准备本地 Lua 诊断环境。缺少可用系统 Python 时,CLI 会先把
`uv` 安装到 `~/.taptap-maker/bin/`,再用 uv 安装 managed Python 到
`~/.taptap-maker/python/uv/`,不修改系统 Python 或全局 PATH;Python ready 后会 best-effort
安装/升级 `maker-lua-lsp` 并执行 `maker-lua-lsp install --ide codex,cursor,claude`。
创建 Maker 私有 LSP venv,在其中安装/升级 `maker-lua-lsp` 并执行
`maker-lua-lsp install --ide codex,cursor,claude`。
- `taptap-maker python path`:输出 Maker 诊断脚本应使用的真实 Python 可执行文件路径。
- `taptap-maker lua-lsp doctor`:检查 `maker-lua-lsp` 是否已经可用于本地 Lua 诊断。
- `taptap-maker lua-lsp setup`:使用当前 Maker Python 执行
`python -m pip install --upgrade maker-lua-lsp`,然后配置 Codex、Cursor 和 Claude。
- `taptap-maker lua-lsp setup`:使用当前 Maker Python 创建
`~/.taptap-maker/lua-lsp-venv/`,在 venv 中安装/升级 `maker-lua-lsp`,
然后配置 Codex、Cursor 和 Claude。

Python 运行时策略:

Expand All @@ -163,8 +165,8 @@ Python 运行时策略:
- Maker Lua 诊断脚本的 Python 最低要求是 3.8;低于 3.8 会被标记为
`version_unsupported`,并提示运行 `taptap-maker python setup`。
- Python 3.8 到 3.11 满足最低要求,可以继续使用;状态中会提示推荐使用 3.12 或更新版本。
- `taptap-maker python setup` 使用 uv 安装 Python 3.12,满足推荐版本要求;随后继续准备
`maker-lua-lsp`。LSP 安装成功或失败都会在命令输出和状态中展示,但失败不阻塞远端构建。
- `taptap-maker python setup` 使用 uv 安装 Python 3.12,满足推荐版本要求;随后创建
Maker 私有 LSP venv 并继续准备 `maker-lua-lsp`。LSP 安装成功或失败都会在命令输出和状态中展示,但失败不阻塞远端构建。
- Windows 不信任 `%LOCALAPPDATA%\Microsoft\WindowsApps\python.exe` 这类 Microsoft Store
app execution alias;检测到 alias 时会提示运行 `taptap-maker python setup`。
- macOS 不把 `/usr/bin/python3`、Xcode 或 Command Line Tools 自带 Python 作为 Maker 工具链,
Expand Down
6 changes: 4 additions & 2 deletions docs/MAKER_CLI_MCP_SKILL_REWORK_OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,16 @@ CLI 负责所有与本机环境、账号、项目绑定相关的低频动作:
`taptap-maker python setup` 才下载 uv,并用 uv 准备 `~/.taptap-maker/` 下的私有 Python;
Python ready 后继续 best-effort 准备 `maker-lua-lsp`。
- `maker-lua-lsp` 是本地 Lua 诊断真正使用的能力。CLI 会执行
`python -m pip install --upgrade maker-lua-lsp` 和
`python -m venv ~/.taptap-maker/lua-lsp-venv`,再用 venv Python 执行
`pip install --upgrade maker-lua-lsp` 和
`maker-lua-lsp install --ide codex,cursor,claude`;失败只在状态和输出中提示,不阻塞远端构建。
- Maker Lua 诊断的 Python 最低要求是 3.8,推荐 3.12 或更新;低于 3.8 会提示自动准备
Maker 私有 Python,3.8 到 3.11 可用但会提示推荐升级。uv 自动准备的版本固定为 3.12。
- Windows 不信任 `python.exe` 的 Microsoft Store app execution alias,检测优先使用 `py -3`;
自动准备路径不调用系统 `python`,避免触发商店安装。
- macOS 不把 Apple/Xcode/Command Line Tools 自带 Python 当作 Maker 工具链运行时;这类 Python
可能无法稳定安装诊断依赖,自动准备时会走 uv managed Python。
可能无法稳定安装诊断依赖,自动准备时会走 uv managed Python。Lua LSP 依赖安装在 Maker
私有 venv 中,不直接修改 uv-managed Python。
- 本地分支测试可直接用 `node dist/maker.js`,不依赖 npm 发布。
- Windows 下生成 MCP 配置时通过 `cmd.exe` 包装 `npx.cmd`,兼容无 shell 的 MCP 启动器。
- 初始化失败时保留现场,返回可重试状态,不自动删除用户文件。
Expand Down
9 changes: 6 additions & 3 deletions docs/MAKER_PYTHON_RUNTIME_WINDOWS_TEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Python 运行时,然后触发 `maker-lua-lsp` 安装和 IDE 配置;LSP 安
- 如果没有可信 Python,就自动准备 Maker 私有 Python。
- Python 最低支持版本是 3.8,推荐 3.12 或更新。
- Python 缺失不能阻塞 Maker MCP 的主状态、提交、推送和远端构建流程。
- Python ready 后需要 best-effort 执行 `pip install --upgrade maker-lua-lsp` 和
- Python ready 后需要 best-effort 创建 Maker 私有 LSP venv,在其中执行
`pip install --upgrade maker-lua-lsp`,再执行
`maker-lua-lsp install --ide codex,cursor,claude`。
- `maker-lua-lsp` 安装失败需要暴露错误给用户和本地 AI,但不能阻塞远端构建。

Expand Down Expand Up @@ -53,8 +54,9 @@ taptap-maker lua-lsp setup
- 使用 uv 安装 Python 3.12 managed Python 到 `~/.taptap-maker/python/uv/`。
- 写入 `~/.taptap-maker/python.json`。
6. Python ready 后,CLI 会执行:
- `<python> -m pip install --upgrade maker-lua-lsp`
- `maker-lua-lsp install --ide codex,cursor,claude`
- `<python> -m venv ~/.taptap-maker/lua-lsp-venv`
- `<lua-lsp-venv-python> -m pip install --upgrade maker-lua-lsp`
- `<lua-lsp-venv>/bin/maker-lua-lsp install --ide codex,cursor,claude`
7. `maker://status` 和 `maker_status_lite` 会输出 `Python environment` 和
`Lua LSP environment`。
8. `maker_build_current_directory` 的 tool description 会引导 AI 在本地 Lua 诊断需要环境时先运行 setup,但缺 Python 或 LSP 不阻塞远端构建。
Expand Down Expand Up @@ -127,6 +129,7 @@ npx -y -p C:\Temp\taptap-maker-0.0.0-python-runtime.0.tgz taptap-maker python se

- 下载 uv 到 `$env:TAPTAP_MAKER_HOME\bin\uv.exe`
- 下载 Python 3.12 managed Python 到 `$env:TAPTAP_MAKER_HOME\python\uv\`
- 创建 Lua LSP venv 到 `$env:TAPTAP_MAKER_HOME\lua-lsp-venv\`
- 输出 `environment.status: "ready"`
- 输出 `environment.provider: "uv-managed"`

Expand Down
3 changes: 2 additions & 1 deletion skills/taptap-maker-local/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ Workflow:
4. Python plus `maker-lua-lsp` is the local Lua diagnostics prerequisite for Maker local
development. `taptap-maker init` checks Python before PAT, app list, clone, and MCP config
installation. If Python is not ready, init tries `taptap-maker python setup` up to 3 total
attempts. After Python is ready, setup best-effort installs/upgrades `maker-lua-lsp` and runs
attempts. After Python is ready, setup best-effort creates a Maker private LSP venv,
installs/upgrades `maker-lua-lsp` there, and runs
`maker-lua-lsp install --ide codex,cursor,claude`; LSP failure should be reported but must not
block remote build. If Python setup still fails, explain that init has paused before
login/project clone/MCP config, then guide the user to retry `taptap-maker python setup` with
Expand Down
45 changes: 26 additions & 19 deletions src/__tests__/makerCliCommands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1576,17 +1576,12 @@ describe('Maker CLI commands', () => {

test('lua-lsp setup installs maker-lua-lsp for Codex Cursor and Claude', async () => {
process.env.TAPTAP_MAKER_PYTHON_BIN = '/opt/maker-python/bin/python3';
const scriptsDir = path.join(tempDir, 'python-bin');
const venvDir = path.join(tempDir, 'maker-home', 'lua-lsp-venv');
const venvPython = path.join(venvDir, 'bin', 'python');
const scriptsDir = path.join(venvDir, 'bin');
const lspCommand = path.join(scriptsDir, 'maker-lua-lsp');
fs.mkdirSync(scriptsDir, { recursive: true });
fs.writeFileSync(lspCommand, '');
spawnSyncMock.mockImplementation((command, args) => {
if (command === '/opt/maker-python/bin/python3' && args.includes('-c')) {
if (String(args.at(-1)).includes('sysconfig.get_path')) {
return { status: 0, stdout: `${scriptsDir}\n`, stderr: '' } as ReturnType<
typeof spawnSync
>;
}
return {
status: 0,
stdout: JSON.stringify({
Expand All @@ -1599,12 +1594,18 @@ describe('Maker CLI commands', () => {
if (command === '/opt/maker-python/bin/python3' && args.join(' ') === '-m pip --version') {
return { status: 0, stdout: 'pip 25.1\n', stderr: '' } as ReturnType<typeof spawnSync>;
}
if (
command === '/opt/maker-python/bin/python3' &&
args.join(' ') === '-m pip install --upgrade maker-lua-lsp'
) {
if (command === '/opt/maker-python/bin/python3' && args.join(' ') === `-m venv ${venvDir}`) {
fs.mkdirSync(scriptsDir, { recursive: true });
fs.writeFileSync(venvPython, '');
fs.writeFileSync(lspCommand, '');
return { status: 0, stdout: 'created venv\n', stderr: '' } as ReturnType<typeof spawnSync>;
}
if (command === venvPython && args.join(' ') === '-m pip install --upgrade maker-lua-lsp') {
return { status: 0, stdout: 'installed\n', stderr: '' } as ReturnType<typeof spawnSync>;
}
if (command === venvPython && args.includes('-c')) {
return { status: 0, stdout: `${scriptsDir}\n`, stderr: '' } as ReturnType<typeof spawnSync>;
}
if (command === lspCommand && args.join(' ') === 'install --ide codex,cursor,claude') {
return { status: 0, stdout: 'configured\n', stderr: '' } as ReturnType<typeof spawnSync>;
}
Expand All @@ -1628,6 +1629,11 @@ describe('Maker CLI commands', () => {
);
expect(spawnSyncMock).toHaveBeenCalledWith(
'/opt/maker-python/bin/python3',
['-m', 'venv', venvDir],
expect.any(Object)
);
expect(spawnSyncMock).toHaveBeenCalledWith(
venvPython,
['-m', 'pip', 'install', '--upgrade', 'maker-lua-lsp'],
expect.any(Object)
);
Expand All @@ -1640,11 +1646,10 @@ describe('Maker CLI commands', () => {

test('python setup includes non-blocking Lua LSP setup result', async () => {
process.env.TAPTAP_MAKER_PYTHON_BIN = '/opt/maker-python/bin/python3';
const venvDir = path.join(tempDir, 'maker-home', 'lua-lsp-venv');
const venvPython = path.join(venvDir, 'bin', 'python');
spawnSyncMock.mockImplementation((command, args) => {
if (command === '/opt/maker-python/bin/python3' && args.includes('-c')) {
if (String(args.at(-1)).includes('sysconfig.get_path')) {
return { status: 0, stdout: `${tempDir}\n`, stderr: '' } as ReturnType<typeof spawnSync>;
}
return {
status: 0,
stdout: JSON.stringify({
Expand All @@ -1657,10 +1662,12 @@ describe('Maker CLI commands', () => {
if (command === '/opt/maker-python/bin/python3' && args.join(' ') === '-m pip --version') {
return { status: 0, stdout: 'pip 25.1\n', stderr: '' } as ReturnType<typeof spawnSync>;
}
if (
command === '/opt/maker-python/bin/python3' &&
args.join(' ') === '-m pip install --upgrade maker-lua-lsp'
) {
if (command === '/opt/maker-python/bin/python3' && args.join(' ') === `-m venv ${venvDir}`) {
fs.mkdirSync(path.dirname(venvPython), { recursive: true });
fs.writeFileSync(venvPython, '');
return { status: 0, stdout: 'created venv\n', stderr: '' } as ReturnType<typeof spawnSync>;
}
if (command === venvPython && args.join(' ') === '-m pip install --upgrade maker-lua-lsp') {
return { status: 1, stdout: '', stderr: 'lsp package failed' } as ReturnType<
typeof spawnSync
>;
Expand Down
62 changes: 55 additions & 7 deletions src/__tests__/makerLuaLspRuntime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,23 @@ describe('Maker Lua LSP runtime', () => {
test('setup installs maker-lua-lsp with the selected Python and configures all IDEs', () => {
const calls: SpawnCall[] = [];
const python = path.join(tempDir, 'python', 'bin', 'python3');
const scriptsDir = path.join(tempDir, 'python', 'bin');
const venvDir = path.join(tempDir, 'maker-home', 'lua-lsp-venv');
const venvPython = path.join(venvDir, 'bin', 'python');
const scriptsDir = path.join(venvDir, 'bin');
const lspCommand = path.join(scriptsDir, 'maker-lua-lsp');
fs.mkdirSync(scriptsDir, { recursive: true });
fs.writeFileSync(lspCommand, '');

const spawn = (command: string, args: string[], options?: { timeout?: number }) => {
calls.push({ command, args, timeout: options?.timeout });
if (command === python && args.join(' ') === '-m pip install --upgrade maker-lua-lsp') {
if (command === python && args.join(' ') === `-m venv ${venvDir}`) {
fs.mkdirSync(scriptsDir, { recursive: true });
fs.writeFileSync(venvPython, '');
fs.writeFileSync(lspCommand, '');
return spawnResult(0, 'created venv\n');
}
if (command === venvPython && args.join(' ') === '-m pip install --upgrade maker-lua-lsp') {
return spawnResult(0, 'installed maker-lua-lsp\n');
}
if (command === python && args.includes('-c')) {
if (command === venvPython && args.includes('-c')) {
return spawnResult(0, `${scriptsDir}\n`);
}
if (command === lspCommand && args.join(' ') === 'install --ide codex,cursor,claude') {
Expand All @@ -112,6 +118,10 @@ describe('Maker Lua LSP runtime', () => {
expect.arrayContaining([
expect.objectContaining({
command: python,
args: ['-m', 'venv', venvDir],
}),
expect.objectContaining({
command: venvPython,
args: ['-m', 'pip', 'install', '--upgrade', 'maker-lua-lsp'],
}),
expect.objectContaining({
Expand All @@ -120,18 +130,28 @@ describe('Maker Lua LSP runtime', () => {
}),
])
);
expect(calls.find((call) => call.command === python && call.args[0] === '-m')?.timeout).toBe(
expect(calls.find((call) => call.command === python && call.args[1] === 'venv')?.timeout).toBe(
120_000
);
expect(
calls.find((call) => call.command === venvPython && call.args[1] === 'pip')?.timeout
).toBe(120_000);
expect(
calls.find((call) => call.command === lspCommand && call.args[0] === 'install')?.timeout
).toBe(120_000);
});

test('setup reports LSP install failure without throwing', () => {
const python = path.join(tempDir, 'python', 'bin', 'python3');
const venvDir = path.join(tempDir, 'maker-home', 'lua-lsp-venv');
const venvPython = path.join(venvDir, 'bin', 'python');
const spawn = (command: string, args: string[]) => {
if (command === python && args.join(' ') === '-m pip install --upgrade maker-lua-lsp') {
if (command === python && args.join(' ') === `-m venv ${venvDir}`) {
fs.mkdirSync(path.dirname(venvPython), { recursive: true });
fs.writeFileSync(venvPython, '');
return spawnResult(0, 'created venv\n');
}
if (command === venvPython && args.join(' ') === '-m pip install --upgrade maker-lua-lsp') {
return spawnResult(1, '', 'network timeout');
}
return spawnResult(1, '', `unexpected command: ${command} ${args.join(' ')}`);
Expand Down Expand Up @@ -169,4 +189,32 @@ describe('Maker Lua LSP runtime', () => {
expect(environment.ready).toBe(false);
expect(environment.nextAction).toContain('taptap-maker lua-lsp setup');
});

test('doctor accepts LSP command that supports help but not version', () => {
const python = path.join(tempDir, 'python', 'bin', 'python3');
const scriptsDir = path.join(tempDir, 'maker-home', 'lua-lsp-venv', 'bin');
const lspCommand = path.join(scriptsDir, 'maker-lua-lsp');
fs.mkdirSync(scriptsDir, { recursive: true });
fs.writeFileSync(lspCommand, '');

const spawn = (command: string, args: string[]) => {
if (command === lspCommand && args[0] === '--version') {
return spawnResult(2, '', 'maker-lua-lsp: error: unrecognized arguments: --version');
}
if (command === lspCommand && args[0] === '--help') {
return spawnResult(0, 'usage: maker-lua-lsp\n');
}
return spawnResult(1, '', `unexpected command: ${command} ${args.join(' ')}`);
};

const environment = checkMakerLuaLspEnvironment({
pythonEnvironment: readyPython(python),
spawn,
});

expect(environment.ready).toBe(true);
expect(environment.status).toBe('ready');
expect(environment.command).toBe(lspCommand);
expect(environment.version).toBe('installed');
});
});
Loading
Loading