@taptap/instant-games-open-mcp 1.23.7-beta.1 → 1.23.7-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -133,9 +133,9 @@ Maker 现在同时内置三个工作流 skill:
133
133
 
134
134
  初始化流程里,PAT 验证通过、用户选择 app 后,`taptap-maker init` 会自动准备本地 AI dev kit。
135
135
 
136
- CLI 会根据 `TAPTAP_MCP_ENV` 自动选择下载源:`production`(默认)使用 `https://urhox-demo-platform.spark.xd.com/ai-dev-kit/pd/stable/ai-dev-kit.zip`,`rnd` 使用 `https://urhox-demo-platform.spark.xd.com/ai-dev-kit/rnd/latest/ai-dev-kit.zip`,解压开发环境文档、引擎 API、demo 和本地 AI skills 到当前目录;会跳过 ZIP 里的顶层 `scripts` 目录并删除下载 ZIP,避免和 Maker 项目代码冲突。clone 前会先生成 `.gitignore.dev-kit-before-clone` 临时 block,clone 成功后自动合并到远端 `.gitignore`,防止这些本地开发环境文件和 `.maker/` 本地运行状态被提交到 Maker Git。
136
+ CLI 会根据 `TAPTAP_MCP_ENV` 自动选择下载源:`production`(默认)使用 `https://urhox-demo-platform.spark.xd.com/ai-dev-kit/pd/stable/ai-dev-kit.zip`,`rnd` 使用 `https://urhox-demo-platform.spark.xd.com/ai-dev-kit/rnd/latest/ai-dev-kit.zip`,解压开发环境文档、引擎 API、demo、Lua 工具和本地 AI skills 到当前目录;解压复制完成后会自动运行 `tools/install-skills.sh all`(Linux/macOS)或 `tools/install-skills.ps1 all`(Windows),把 dev kit skills 安装到各 Agent 的发现目录。CLI 会先输出 `AI skills install started: <script>`,完成后输出 `AI skills install result: claude=N, codex=N, cursor=N, gemini=N`;脚本缺失、跳过或失败时也会输出原因,失败会带上平台、脚本、命令、stdout 和 stderr,方便 AI 与用户直接判断安装情况。流程会跳过 ZIP 里的顶层 `scripts` 目录并删除下载 ZIP,避免和 Maker 项目代码冲突。clone 前会先生成 `.gitignore.dev-kit-before-clone` 临时 block,clone 成功后自动合并到远端 `.gitignore`,防止这些本地开发环境文件、Agent skill 目录和 `.maker/` 本地运行状态被提交到 Maker Git。
137
137
 
138
- `maker://status` 和 `maker_status_lite` 会输出已随包内置的 skill 名称和文档路径:`taptap-maker-local`、`taptap-maker-dev-kit-guide` 与 `update-taptap-mcp`。Maker 操作目标是用户当前项目目录;若 MCP 进程 cwd 是临时对话目录,Agent 应把用户当前项目目录作为 `target_dir` 传入,不扫描其他项目。已绑定项目会检查 `CLAUDE.md`、`examples/`、`templates/`、`urhox-libs/`,缺失时用 `taptap-maker dev-kit update` 恢复本地 AI dev kit 并刷新 `.gitignore` 管理块。
138
+ `maker://status` 和 `maker_status_lite` 会输出已随包内置的 skill 名称和文档路径:`taptap-maker-local`、`taptap-maker-dev-kit-guide` 与 `update-taptap-mcp`。Maker 操作目标是用户当前项目目录;若 MCP 进程 cwd 是临时对话目录,Agent 应把用户当前项目目录作为 `target_dir` 传入,不扫描其他项目。已绑定项目会检查 `CLAUDE.md`、`examples/`、`templates/`、`urhox-libs/`,并输出 `skill_install_status` 和 `skill_install_summary` 说明 `.claude/.codex/.cursor/.gemini` 下的 skill 安装状态;缺失时用 `taptap-maker dev-kit update` 恢复本地 AI dev kit 并刷新 `.gitignore` 管理块。
139
139
 
140
140
  Git 引导:
141
141
 
package/dist/maker.js CHANGED
@@ -28814,14 +28814,24 @@ var DEV_KIT_GITIGNORE_STAGING_FILE = ".gitignore.dev-kit-before-clone";
28814
28814
  var DEV_KIT_REQUIRED_ENTRIES = ["CLAUDE.md", "examples", "templates", "urhox-libs"];
28815
28815
  var ALWAYS_IGNORED_LOCAL_ENTRIES = [".DS_Store", ".maker"];
28816
28816
  var DEV_KIT_MANAGED_ENTRY_CANDIDATES = [
28817
+ ".claude",
28818
+ ".cli",
28819
+ ".codex",
28820
+ ".cursor",
28817
28821
  ".emmylua",
28822
+ ".gemini",
28823
+ "AGENTS.md",
28818
28824
  "CLAUDE.md",
28819
28825
  "engine-docs",
28820
28826
  "examples",
28827
+ "schemas",
28828
+ "skills",
28821
28829
  "templates",
28830
+ "tools",
28822
28831
  "urhox-libs"
28823
28832
  ];
28824
28833
  var SKIPPED_TOP_LEVEL_ENTRIES = /* @__PURE__ */ new Set(["scripts", ".DS_Store", "ai-dev-kit.zip"]);
28834
+ var SKILL_INSTALLER_OUTPUT_ENTRIES = [".claude", ".codex", ".cursor", ".gemini"];
28825
28835
  function inspectAiDevKit(targetDir) {
28826
28836
  const resolvedTargetDir = path4.resolve(targetDir);
28827
28837
  const presentEntries = DEV_KIT_REQUIRED_ENTRIES.filter(
@@ -28862,15 +28872,43 @@ async function installAiDevKit(options = {}) {
28862
28872
  });
28863
28873
  installedEntries.push(entry.name);
28864
28874
  }
28875
+ const skillInstaller = runDevKitSkillInstallerForInstall(targetDir, {
28876
+ onStart: options.onSkillInstallerStart
28877
+ });
28865
28878
  const stagedGitignorePath = path4.join(targetDir, DEV_KIT_GITIGNORE_STAGING_FILE);
28866
- writeDevKitStagedGitignore(stagedGitignorePath, installedEntries);
28879
+ writeDevKitStagedGitignore(stagedGitignorePath, [
28880
+ ...installedEntries,
28881
+ ...listPresentSkillInstallerOutputEntries(targetDir)
28882
+ ]);
28867
28883
  return {
28868
28884
  targetDir,
28869
28885
  sourceDir,
28870
28886
  installedEntries: installedEntries.sort(),
28871
28887
  skippedEntries: skippedEntries.sort(),
28872
28888
  gitignorePath: path4.join(targetDir, ".gitignore"),
28873
- stagedGitignorePath
28889
+ stagedGitignorePath,
28890
+ skillInstaller
28891
+ };
28892
+ }
28893
+ function inspectAiDevKitSkillInstallStatus(targetDir) {
28894
+ const resolvedTargetDir = path4.resolve(targetDir);
28895
+ const targets = SKILL_INSTALLER_OUTPUT_ENTRIES.map((entry) => {
28896
+ const skillsDir = path4.join(resolvedTargetDir, entry, "skills");
28897
+ const present = fs3.existsSync(skillsDir) && fs3.statSync(skillsDir).isDirectory();
28898
+ const skillCount = present ? fs3.readdirSync(skillsDir, { withFileTypes: true }).filter((item) => item.isDirectory() || item.isSymbolicLink()).length : 0;
28899
+ return {
28900
+ name: entry.replace(/^\./, ""),
28901
+ path: skillsDir,
28902
+ present,
28903
+ skillCount
28904
+ };
28905
+ });
28906
+ const installedCount = targets.filter((target) => target.present && target.skillCount > 0).length;
28907
+ const status = installedCount === targets.length ? "installed" : installedCount > 0 ? "partial" : "missing";
28908
+ return {
28909
+ status,
28910
+ summary: targets.map((target) => `${target.name}=${target.skillCount}`).join(", "),
28911
+ targets
28874
28912
  };
28875
28913
  }
28876
28914
  function createDevKitGitignoreBlock(entries) {
@@ -28927,6 +28965,87 @@ function copyEntry(source, target, options = {}) {
28927
28965
  fs3.copyFileSync(source, target);
28928
28966
  }
28929
28967
  }
28968
+ function installAiDevKitSkills(targetDir, options = {}) {
28969
+ var _a2;
28970
+ const toolsDir = path4.join(targetDir, "tools");
28971
+ if (!fs3.existsSync(toolsDir) || !fs3.statSync(toolsDir).isDirectory()) {
28972
+ return {
28973
+ ok: false,
28974
+ status: "skipped",
28975
+ stdout: "",
28976
+ stderr: "",
28977
+ summary: "skipped: tools directory not found",
28978
+ reason: "tools_not_found"
28979
+ };
28980
+ }
28981
+ const isWindows = process.platform === "win32";
28982
+ const scriptName = isWindows ? "install-skills.ps1" : "install-skills.sh";
28983
+ const scriptPath = path4.join(toolsDir, scriptName);
28984
+ if (!fs3.existsSync(scriptPath)) {
28985
+ return {
28986
+ ok: false,
28987
+ status: "skipped",
28988
+ script: scriptPath,
28989
+ stdout: "",
28990
+ stderr: "",
28991
+ summary: `skipped: ${scriptName} not found`,
28992
+ reason: "script_not_found"
28993
+ };
28994
+ }
28995
+ const command = isWindows ? ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", scriptPath, "all"] : ["bash", scriptPath, "all"];
28996
+ (_a2 = options.onStart) == null ? void 0 : _a2.call(options, {
28997
+ platform: process.platform,
28998
+ script: scriptPath,
28999
+ cwd: toolsDir,
29000
+ command
29001
+ });
29002
+ const result = spawnSync2(command[0], command.slice(1), { cwd: toolsDir, encoding: "utf8" });
29003
+ if (result.status !== 0) {
29004
+ throw new AiDevKitSkillInstallerError(
29005
+ formatFailedSkillInstallerResult({
29006
+ platform: process.platform,
29007
+ scriptPath,
29008
+ toolsDir,
29009
+ command,
29010
+ result
29011
+ })
29012
+ );
29013
+ }
29014
+ const stdout = String(result.stdout || "");
29015
+ const stderr = String(result.stderr || "");
29016
+ return {
29017
+ ok: true,
29018
+ status: "installed",
29019
+ script: scriptPath,
29020
+ stdout,
29021
+ stderr,
29022
+ summary: summarizeSkillInstallerOutput(stdout)
29023
+ };
29024
+ }
29025
+ function runDevKitSkillInstallerForInstall(targetDir, options = {}) {
29026
+ try {
29027
+ return installAiDevKitSkills(targetDir, options);
29028
+ } catch (error2) {
29029
+ if (error2 instanceof AiDevKitSkillInstallerError) {
29030
+ return error2.result;
29031
+ }
29032
+ const message = error2 instanceof Error ? error2.message : String(error2);
29033
+ return {
29034
+ ok: false,
29035
+ status: "failed",
29036
+ stdout: "",
29037
+ stderr: "",
29038
+ summary: "failed",
29039
+ reason: "installer_failed",
29040
+ error: message
29041
+ };
29042
+ }
29043
+ }
29044
+ function listPresentSkillInstallerOutputEntries(targetDir) {
29045
+ return SKILL_INSTALLER_OUTPUT_ENTRIES.filter(
29046
+ (entry) => fs3.existsSync(path4.join(targetDir, entry))
29047
+ );
29048
+ }
28930
29049
  async function downloadAndExtractDevKit(url2) {
28931
29050
  const tempDir = fs3.mkdtempSync(path4.join(os3.tmpdir(), "taptap-maker-ai-dev-kit-"));
28932
29051
  const zipPath = path4.join(tempDir, "ai-dev-kit.zip");
@@ -29003,6 +29122,67 @@ function formatSpawnFailure(result) {
29003
29122
  var _a2;
29004
29123
  return ((_a2 = result.error) == null ? void 0 : _a2.message) || String(result.stderr || "").trim() || String(result.stdout || "").trim() || `exit status ${result.status ?? "unknown"}`;
29005
29124
  }
29125
+ function formatDevKitSkillInstallerFailure(options) {
29126
+ return [
29127
+ "Failed to install AI dev kit skills",
29128
+ `platform: ${options.platform}`,
29129
+ `script: ${options.scriptPath}`,
29130
+ `cwd: ${options.toolsDir}`,
29131
+ `command: ${options.command.map(shellQuote).join(" ")}`,
29132
+ `exit_status: ${options.result.status ?? "unknown"}`,
29133
+ options.result.signal ? `signal: ${options.result.signal}` : "",
29134
+ options.result.error ? `spawn_error: ${options.result.error.message}` : "",
29135
+ "stdout:",
29136
+ formatSpawnOutput(options.result.stdout),
29137
+ "stderr:",
29138
+ formatSpawnOutput(options.result.stderr)
29139
+ ].filter((line) => line.length > 0).join("\n");
29140
+ }
29141
+ function formatFailedSkillInstallerResult(options) {
29142
+ return {
29143
+ ok: false,
29144
+ status: "failed",
29145
+ script: options.scriptPath,
29146
+ stdout: String(options.result.stdout || ""),
29147
+ stderr: String(options.result.stderr || ""),
29148
+ summary: summarizeSkillInstallerFailure(options.result),
29149
+ reason: "installer_failed",
29150
+ error: formatDevKitSkillInstallerFailure(options)
29151
+ };
29152
+ }
29153
+ function summarizeSkillInstallerFailure(result) {
29154
+ if (typeof result.status === "number") {
29155
+ return `failed: exit_status=${result.status}`;
29156
+ }
29157
+ if (result.signal) {
29158
+ return `failed: signal=${result.signal}`;
29159
+ }
29160
+ if (result.error) {
29161
+ return `failed: ${result.error.message}`;
29162
+ }
29163
+ return "failed";
29164
+ }
29165
+ var AiDevKitSkillInstallerError = class extends Error {
29166
+ constructor(result) {
29167
+ super(result.error || result.summary);
29168
+ this.result = result;
29169
+ this.name = "AiDevKitSkillInstallerError";
29170
+ }
29171
+ };
29172
+ function formatSpawnOutput(value) {
29173
+ const text = String(value || "").trim();
29174
+ return text.length > 0 ? text : "(empty)";
29175
+ }
29176
+ function summarizeSkillInstallerOutput(stdout) {
29177
+ const entries = stdout.split(/\r?\n/).map((line) => line.match(/\[install-skills\]\s+([^:]+):\s+installed=(\d+)/)).filter((match) => Boolean(match)).map((match) => `${match[1]}=${match[2]}`);
29178
+ return entries.length > 0 ? entries.join(", ") : "completed";
29179
+ }
29180
+ function shellQuote(value) {
29181
+ if (/^[A-Za-z0-9_./:=@-]+$/.test(value)) {
29182
+ return value;
29183
+ }
29184
+ return `'${value.replace(/'/g, "'\\''")}'`;
29185
+ }
29006
29186
  function resolveDevKitRoot(sourceDir) {
29007
29187
  const directEntries = fs3.existsSync(sourceDir) ? fs3.readdirSync(sourceDir) : [];
29008
29188
  if (looksLikeDevKitRoot(sourceDir)) {
@@ -29524,7 +29704,7 @@ async function inspectMakerRemoteSyncStatus(cwd) {
29524
29704
  }
29525
29705
  function getMakerRemoteSyncFailureNextAction(failure) {
29526
29706
  if (failure.classification === "auth") {
29527
- return "暂时无法检查 Maker 远端是否有新提交:Git 鉴权失败。请先运行 `taptap-maker pat set` 并粘贴新的 Maker PAT 后,再重新读取 maker://status。";
29707
+ return `暂时无法检查 Maker 远端是否有新提交:Git 鉴权失败。PAT 页面:${getMakerPatTokensUrl()}。请在该页面创建新的 Maker PAT,然后运行 \`taptap-maker pat set\` 并粘贴 PAT 后,再重新读取 maker://status。`;
29528
29708
  }
29529
29709
  return "暂时无法检查 Maker 远端是否有新提交。请把 failure 信息反馈给用户;如果只是 503、5xx、超时或网络中断,可稍后重新读取 maker://status。";
29530
29710
  }
@@ -29745,7 +29925,7 @@ function nextActionForFailure(classification) {
29745
29925
  case "git_missing":
29746
29926
  return "本机未检测到可用的 Git。请用户自行安装 Git,并在 `git --version` 可用后重启 MCP 客户端再重试;安装前不要执行 clone、fetch、commit 或 push。";
29747
29927
  case "auth":
29748
- return "运行 `taptap-maker pat set` 并粘贴新的 Maker PAT 后,再重试 maker_build_current_directory;如果仍失败,请确认 PAT 是否过期或缺少 Maker git 权限。";
29928
+ return `Maker Git 鉴权失败。PAT 页面:${getMakerPatTokensUrl()}。请在该页面创建新的 Maker PAT,然后运行 \`taptap-maker pat set\` 并粘贴 PAT 后重试。`;
29749
29929
  case "remote_transient":
29750
29930
  return "远端 Maker git 服务临时不可用。本地 commit 会保留;不要手动执行通用 git push,稍后直接重试 maker_build_current_directory。";
29751
29931
  case "branch_not_allowed":
@@ -30547,11 +30727,13 @@ function formatMakerSkillStatus(_options = {}) {
30547
30727
  path: path6.join(resolveMakerSkillSourceDir(skill.name), "SKILL.md")
30548
30728
  }));
30549
30729
  return [
30550
- "TapTap bundled workflow skills",
30730
+ "TapTap Maker workflow guide documents",
30551
30731
  "",
30552
30732
  ...skillDocuments.map((skill) => `- ${skill.name}: ${skill.path}`),
30553
30733
  "",
30554
- "These skill documents are bundled in the package. Let the current AI client decide whether and how to load them."
30734
+ "Use these documents as reading references for Maker local workflows.",
30735
+ "Maker initialization next_step: execute `taptap-maker init`.",
30736
+ "Load these documents when the current AI client supports reading local guide files."
30555
30737
  ].join("\n");
30556
30738
  }
30557
30739
  function resolveMakerSkillSourceDir(skillName = MAKER_LOCAL_SKILL_NAME) {
@@ -30951,7 +31133,7 @@ function compactRuntimeLogEntry(entry) {
30951
31133
  }
30952
31134
 
30953
31135
  // src/maker/server/mcp.ts
30954
- var VERSION = true ? "1.23.7-beta.1" : "dev";
31136
+ var VERSION = true ? "1.23.7-beta.3" : "dev";
30955
31137
  var DEFAULT_PROXY_PACKAGE = "@taptap/instant-games-open-mcp@1.22.0";
30956
31138
  var DEFAULT_BUILD_TIMEOUT_MS = 10 * 60 * 1e3;
30957
31139
  var PREVIEW_REFRESH_TIMEOUT_MS = 15 * 1e3;
@@ -30970,7 +31152,7 @@ var MakerCloneFailedError = class extends Error {
30970
31152
  var tools = [
30971
31153
  {
30972
31154
  name: "maker_status_lite",
30973
- description: "Compatibility fallback for clients that cannot read the maker://status resource. Prefer reading maker://status when resources are available. Shows local Maker status for the user current working directory, including Git, PAT/TapTap auth, project binding, AI dev kit status, and bundled workflow skill document paths.",
31155
+ description: "Compatibility status surface for clients using tool output instead of the maker://status resource. Prefer reading maker://status when resources are available. Shows local Maker status for the user current working directory, including Git, PAT/TapTap auth, project binding, AI dev kit status, and bundled workflow guide document paths. Maker initialization next_step: taptap-maker init.",
30974
31156
  inputSchema: {
30975
31157
  type: "object",
30976
31158
  properties: {
@@ -31087,7 +31269,7 @@ var resources = [
31087
31269
  {
31088
31270
  uri: "maker://status",
31089
31271
  name: "Maker status",
31090
- description: "Local TapTap Maker project status, including Git, PAT/TapTap auth, project binding, AI dev kit status, and bundled workflow skill document paths.",
31272
+ description: "Local TapTap Maker project status, including Git, PAT/TapTap auth, project binding, AI dev kit status, and bundled workflow guide document paths. Maker initialization next_step: taptap-maker init.",
31091
31273
  mimeType: "text/plain"
31092
31274
  }
31093
31275
  ];
@@ -31248,8 +31430,8 @@ async function formatStatus(options = {}) {
31248
31430
  const git = checkGitEnvironment();
31249
31431
  const projectSection = identify.projectId ? [
31250
31432
  "目标目录已绑定 Maker 项目。",
31251
- "请继续在当前绑定项目上执行状态、提交、构建等操作;不要再引导用户 clone,除非用户明确要求切换或重新拉取项目。",
31252
- "本地 Maker 工作流请优先参考 taptap-maker-local skill;CLI 负责初始化/PAT/app/clone,MCP 只保留状态和同步构建。"
31433
+ "请继续在当前绑定项目上执行状态、提交、构建等操作;用户明确要求切换或重新拉取项目时,再进入项目选择流程。",
31434
+ "本地 Maker 工作流请参考 taptap-maker-local workflow guide document;CLI 负责初始化/PAT/app/clone,MCP 只保留状态和同步构建。"
31253
31435
  ].join("\n") : isLikelyAiDialogueDirectory(targetDir) ? formatAiDialogueDirectoryHint(targetDir) : pat ? await formatAutoProjectListFromPat() : formatIdentifyHint();
31254
31436
  return [
31255
31437
  "TapTap Maker MCP status",
@@ -31287,7 +31469,7 @@ function formatMakerRemoteSyncSkipped() {
31287
31469
  "Maker remote sync",
31288
31470
  "",
31289
31471
  "- status: skipped",
31290
- "- next_action: 已跳过远端同步检查;如需确认是否需要 pull,请重新读取 maker_status_lite 且不要设置 skip_remote_sync。"
31472
+ "- next_action: 已跳过远端同步检查;如需确认是否需要 pull,请重新读取 maker_status_lite 并启用远端同步检查。"
31291
31473
  ].join("\n");
31292
31474
  }
31293
31475
  async function formatMakerRemoteSyncStatus(projectRoot) {
@@ -31387,13 +31569,16 @@ async function formatAiDevKitStatus(projectRoot) {
31387
31569
  ].join("\n");
31388
31570
  }
31389
31571
  function formatAiDevKitStatusLines(status, devKitStatus) {
31572
+ const skillStatus = inspectAiDevKitSkillInstallStatus(devKitStatus.targetDir);
31390
31573
  return [
31391
31574
  "AI dev kit",
31392
31575
  "",
31393
31576
  `- status: ${status}`,
31394
31577
  `- required_entries: ${devKitStatus.requiredEntries.join(", ")}`,
31395
31578
  `- present_entries: ${devKitStatus.presentEntries.join(", ") || "(none)"}`,
31396
- `- missing_entries: ${devKitStatus.missingEntries.join(", ") || "(none)"}`
31579
+ `- missing_entries: ${devKitStatus.missingEntries.join(", ") || "(none)"}`,
31580
+ `- skill_install_status: ${skillStatus.status}`,
31581
+ `- skill_install_summary: ${skillStatus.summary}`
31397
31582
  ];
31398
31583
  }
31399
31584
  async function formatAutoProjectListFromPat() {
@@ -31401,7 +31586,8 @@ async function formatAutoProjectListFromPat() {
31401
31586
  const projects = await listMakerProjects();
31402
31587
  return [
31403
31588
  "本地已有 Maker PAT,当前目录尚未绑定 Maker 项目。",
31404
- "当前目录未绑定时,先展示下面的 Maker Apps 预览和总数,避免长列表刷屏;选择、解释和 clone 顺序请参考 taptap-maker-local skill。",
31589
+ "当前目录未绑定时,先展示下面的 Maker Apps 预览和总数;选择、解释和 clone 顺序请参考 taptap-maker-local workflow guide document。",
31590
+ "用户选择 app 后,next_step: 执行 `taptap-maker init`。",
31405
31591
  "",
31406
31592
  formatStatusProjectList(projects)
31407
31593
  ].join("\n");
@@ -31446,14 +31632,15 @@ function formatStatusProjectList(projects) {
31446
31632
  "",
31447
31633
  hiddenCount > 0 ? `为了保持友好的可读性,默认最多展示 ${visibleProjects.length} 个 app;如需完整列表,可以选择显示全部。` : "已显示全部 app;请询问用户选择。",
31448
31634
  hiddenCount > 0 ? "如需完整列表,请运行 taptap-maker apps --json 查看全部 app。" : void 0,
31449
- "AI 展示建议:如果聊天或客户端宽度足够,可把 app 预览整理成两列紧凑布局;每个 app 保留序号、app_id、名称,以及可用的最近活跃时间或 user_id。窄屏保持单列。不要省略 app_id,也不要在用户确认前自动选择 app。",
31635
+ "AI 展示建议:如果聊天或客户端宽度足够,可把 app 预览整理成两列紧凑布局;每个 app 保留序号、app_id、名称,以及可用的最近活跃时间或 user_id。窄屏保持单列。选择 app 前先获取用户确认。",
31450
31636
  "",
31451
31637
  ...visibleProjects.map(
31452
31638
  (project, index) => `${index + 1}. ${project.id}${project.name ? ` ${project.name}` : ""}${project.user_id ? ` user_id=${project.user_id}` : ""}${project.gameType ? ` gameType=${project.gameType}` : ""}${project.stage ? ` stage=${project.stage}` : ""}${project.createdAt ? ` createdAt=${project.createdAt}` : ""}${project.lastConversationAt ? ` lastConversationAt=${project.lastConversationAt}` : ""}`
31453
31639
  ),
31454
31640
  "",
31455
- "仅当当前目录未绑定且用户要初始化或 clone 时,才让用户选择 app 并继续 taptap-maker init。",
31456
- "如果当前目录已绑定 Maker 项目,这个列表仅作账号项目参考;请继续当前项目,除非用户明确要求切换或重新 clone。"
31641
+ "当前目录未绑定且用户要初始化或 clone 时,让用户选择 app 并继续 taptap-maker init。",
31642
+ "用户回复序号或 app_id 后,next_step: 执行 `taptap-maker init`,或让已经启动的 `taptap-maker init` 交互继续读取该选择。",
31643
+ "如果当前目录已绑定 Maker 项目,这个列表仅作账号项目参考;请继续当前项目。用户明确要求切换或重新 clone 时,再进入项目选择流程。"
31457
31644
  ].filter((line) => line !== void 0).join("\n");
31458
31645
  }
31459
31646
  function formatClonePartialStateLines(targetDir) {
@@ -31480,7 +31667,7 @@ function formatClonePartialStateLines(targetDir) {
31480
31667
  `- ai_dev_kit_missing_entries: ${devKitStatus.missingEntries.join(", ") || "(none)"}`,
31481
31668
  `- staged_dev_kit_gitignore: ${fs7.existsSync(stagedDevKitGitignorePath) ? "yes" : "no"}`,
31482
31669
  `- safe_to_retry: ${safeToRetry ? "yes" : "no"}`,
31483
- safeToRetry ? "- next_step: 可以直接重试 taptap-maker init;如果连续失败,建议换一个全新的独立目录重新 clone。" : "- next_step: 当前目录已经有 Maker 绑定信息;先运行 taptap-maker doctor 或读取 maker://status 确认状态,不要重复 clone。"
31670
+ safeToRetry ? "- next_step: 可以直接重试 taptap-maker init;如果连续失败,建议换一个全新的独立目录重新 clone。" : "- next_step: 当前目录已经有 Maker 绑定信息;先运行 taptap-maker doctor 或读取 maker://status 确认状态。"
31484
31671
  ].filter(Boolean);
31485
31672
  }
31486
31673
  function createRemoteProxyContext(options) {
@@ -32638,12 +32825,16 @@ async function runInit(parsed, ctx) {
32638
32825
  emit(ctx, "doctor", "Git is available", { version: git.version });
32639
32826
  const pat = await resolvePat(parsed, ctx);
32640
32827
  emit(ctx, "pat", "Maker PAT ready", { saved: getPatPath() });
32641
- const tapAuth = await requestTapAuthWithPat(pat);
32828
+ const tapAuth = await requestTapAuthWithPat(pat).catch((error2) => {
32829
+ throw appendPatRecoveryUrl(error2, parsed);
32830
+ });
32642
32831
  emit(ctx, "tap_auth", "TapTap token exchanged and saved", {
32643
32832
  kid: mask(tapAuth.kid),
32644
32833
  saved: getTapAuthPath()
32645
32834
  });
32646
- const projects = await listMakerProjects({ pat });
32835
+ const projects = await listMakerProjects({ pat }).catch((error2) => {
32836
+ throw appendPatRecoveryUrl(error2, parsed);
32837
+ });
32647
32838
  const selected = await resolveProjectSelection(parsed, projects, {
32648
32839
  skipConfirm
32649
32840
  });
@@ -32666,6 +32857,8 @@ async function runInit(parsed, ctx) {
32666
32857
  userId: selected.user_id,
32667
32858
  sceEndpoint: selected.sce_endpoint || process.env.SCE_MCP_URL,
32668
32859
  onProgress: (progress) => emitProgress(ctx, "clone", progress)
32860
+ }).catch((error2) => {
32861
+ throw appendPatRecoveryUrl(error2, parsed);
32669
32862
  });
32670
32863
  emit(ctx, "clone", "Maker project cloned or fetched", cloneResult);
32671
32864
  if (!skipMcpInstall) {
@@ -32744,7 +32937,9 @@ async function runApps(parsed, ctx) {
32744
32937
  warnPatArgExposure();
32745
32938
  }
32746
32939
  const showAll = booleanOption(parsed, "all");
32747
- const projects = await listMakerProjects({ pat });
32940
+ const projects = await listMakerProjects({ pat }).catch((error2) => {
32941
+ throw appendPatRecoveryUrl(error2, parsed);
32942
+ });
32748
32943
  if (ctx.json) {
32749
32944
  writeJson(projects);
32750
32945
  return;
@@ -32755,7 +32950,9 @@ async function runApps(parsed, ctx) {
32755
32950
  async function runPatSet(parsed, ctx) {
32756
32951
  const pat = await resolvePatSet(parsed, ctx);
32757
32952
  saveManualMakerPat(pat);
32758
- const tapAuth = await requestTapAuthWithPat(pat);
32953
+ const tapAuth = await requestTapAuthWithPat(pat).catch((error2) => {
32954
+ throw appendPatRecoveryUrl(error2, parsed);
32955
+ });
32759
32956
  emit(ctx, "pat", "Maker PAT and TapTap token saved", {
32760
32957
  pat_path: getPatPath(),
32761
32958
  tap_auth_path: getTapAuthPath(),
@@ -32897,7 +33094,8 @@ async function runDevKitUpdate(parsed, ctx) {
32897
33094
  preserveExisting: true
32898
33095
  });
32899
33096
  finalizeStagedDevKitGitignore(targetDir);
32900
- emit(ctx, "dev_kit", "AI dev kit updated", result);
33097
+ emit(ctx, "dev_kit", formatDevKitInstallMessage("AI dev kit updated", result), result);
33098
+ emitDevKitSkillInstallerFailure(ctx, result.skillInstaller, "AI skills install failed");
32901
33099
  }
32902
33100
  async function runLogsWatch(parsed, ctx) {
32903
33101
  const targetDir = path9.resolve(stringOption(parsed, "target_dir") || process.cwd());
@@ -33085,18 +33283,87 @@ async function prepareDevKit(targetDir, ctx) {
33085
33283
  path9.join(targetDir, DEV_KIT_GITIGNORE_STAGING_FILE),
33086
33284
  listPresentDevKitManagedEntries(targetDir)
33087
33285
  );
33088
- emit(ctx, "dev_kit", "AI dev kit already present", before);
33286
+ try {
33287
+ const skillInstaller = installAiDevKitSkills(targetDir, {
33288
+ onStart: (event) => emitSkillInstallerStart(ctx, event)
33289
+ });
33290
+ emit(
33291
+ ctx,
33292
+ "dev_kit",
33293
+ formatDevKitInstallMessage("AI dev kit already present", { skillInstaller }),
33294
+ {
33295
+ ...before,
33296
+ skillInstaller
33297
+ }
33298
+ );
33299
+ } catch (error2) {
33300
+ const detail = error2 instanceof Error ? error2.message : String(error2);
33301
+ emit(ctx, "dev_kit_warning", `AI skills install failed; clone will continue
33302
+ ${detail}`, {
33303
+ error: detail
33304
+ });
33305
+ }
33089
33306
  return;
33090
33307
  }
33091
33308
  try {
33092
- const result = await installAiDevKit({ targetDir });
33093
- emit(ctx, "dev_kit", "AI dev kit prepared", result);
33309
+ const result = await installAiDevKit({
33310
+ targetDir,
33311
+ onSkillInstallerStart: (event) => emitSkillInstallerStart(ctx, event)
33312
+ });
33313
+ emit(ctx, "dev_kit", formatDevKitInstallMessage("AI dev kit prepared", result), result);
33314
+ emitDevKitSkillInstallerFailure(
33315
+ ctx,
33316
+ result.skillInstaller,
33317
+ "AI skills install failed; clone will continue"
33318
+ );
33094
33319
  } catch (error2) {
33095
- emit(ctx, "dev_kit_warning", "AI dev kit preparation failed; clone will continue", {
33096
- error: error2 instanceof Error ? error2.message : String(error2)
33320
+ const detail = error2 instanceof Error ? error2.message : String(error2);
33321
+ emit(ctx, "dev_kit_warning", `AI dev kit preparation failed; clone will continue
33322
+ ${detail}`, {
33323
+ error: detail
33097
33324
  });
33098
33325
  }
33099
33326
  }
33327
+ function formatDevKitInstallMessage(message, result) {
33328
+ if (!result.skillInstaller) {
33329
+ return message;
33330
+ }
33331
+ return `${message}
33332
+ AI skills install result: ${result.skillInstaller.summary}`;
33333
+ }
33334
+ function emitSkillInstallerStart(ctx, event) {
33335
+ emit(ctx, "dev_kit_skill_install_start", `AI skills install started: ${event.script}`, event);
33336
+ }
33337
+ function emitDevKitSkillInstallerFailure(ctx, result, message) {
33338
+ if (!result || result.ok || result.status !== "failed") {
33339
+ return;
33340
+ }
33341
+ const detail = result.error || "unknown installer failure";
33342
+ emit(ctx, "dev_kit_warning", `${message}
33343
+ ${detail}`, {
33344
+ error: detail
33345
+ });
33346
+ }
33347
+ function appendPatRecoveryUrl(error2, parsed) {
33348
+ const message = error2 instanceof Error ? error2.message : String(error2);
33349
+ if (!isPatValidationFailure(message) || message.includes("/pat-tokens")) {
33350
+ return error2 instanceof Error ? error2 : new Error(message);
33351
+ }
33352
+ const patPage = getMakerPatTokensUrl(makerEnvOption(parsed));
33353
+ return new Error(
33354
+ [
33355
+ message,
33356
+ "",
33357
+ `PAT 页面:${patPage}`,
33358
+ "请在该页面创建新的 Maker PAT,然后运行 `taptap-maker pat set` 并粘贴 PAT。"
33359
+ ].join("\n")
33360
+ );
33361
+ }
33362
+ function isPatValidationFailure(message) {
33363
+ return /\b(?:PAT_INVALID|HTTP\s*40[13]|40[13]|unauthori[sz]ed|invalid\s+PAT|PAT\s+invalid|expired)\b/i.test(
33364
+ message
33365
+ ) || /(?:过期|失效)/.test(message);
33366
+ }
33100
33367
  function installMcpConfigs(options) {
33101
33368
  return options.ides.map((ide) => installMcpConfig(ide, options));
33102
33369
  }
package/dist/proxy.js CHANGED
@@ -29137,7 +29137,8 @@ var LogWriter = class {
29137
29137
  };
29138
29138
 
29139
29139
  // src/mcp-proxy/proxy.ts
29140
- var VERSION = true ? "1.23.7-beta.1" : "dev";
29140
+ var VERSION = true ? "1.23.7-beta.3" : "dev";
29141
+ var LOCAL_PROXY_TAG = "local";
29141
29142
  var TapTapMCPProxy = class {
29142
29143
  constructor(config2) {
29143
29144
  this.connected = false;
@@ -29243,9 +29244,11 @@ var TapTapMCPProxy = class {
29243
29244
  * - X-TapTap-Project-Path: 项目路径
29244
29245
  * - X-TapTap-Mac-Token: MAC 认证令牌(JSON)
29245
29246
  * - X-TapTap-Custom-Fields: 业务自定义字段(JSON)
29247
+ * - X-TapTap-Tag: 调用来源标记,固定为 "local"
29246
29248
  */
29247
29249
  buildSessionHeaders() {
29248
29250
  const headers = {};
29251
+ headers["X-TapTap-Tag"] = LOCAL_PROXY_TAG;
29249
29252
  if (this.config.tenant.user_id) {
29250
29253
  headers["X-TapTap-User-Id"] = this.config.tenant.user_id;
29251
29254
  }
@@ -29273,10 +29276,12 @@ var TapTapMCPProxy = class {
29273
29276
  * - _project_id: 项目标识(可选)
29274
29277
  * - _project_path: 项目路径(可选)
29275
29278
  * - _custom_fields: 业务自定义字段(可选)
29279
+ * - _tag: 调用来源标记,固定为 "local"
29276
29280
  */
29277
29281
  injectPrivateParams(args) {
29278
29282
  const injected = { ...args || {} };
29279
29283
  injected._mac_token = this.config.auth;
29284
+ injected._tag = LOCAL_PROXY_TAG;
29280
29285
  if (this.config.tenant.user_id) {
29281
29286
  injected._user_id = this.config.tenant.user_id;
29282
29287
  }