@taptap/instant-games-open-mcp 1.22.0-beta.5 → 1.22.0-beta.6

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
@@ -72,17 +72,21 @@ maker_push_current_directory
72
72
  - 保存 PAT 后会自动列出 app;`maker_status` 如果发现本地已有 PAT 且当前目录未绑定,也会自动列出 app,无需用户额外要求。
73
73
  - 保存 PAT 后会自动调用 `GET /api/v1/user/taptap-token` 获取并保存 TapTap MAC token;Tap OAuth 登录只作为 legacy fallback。
74
74
  - `maker_list_apps` 和 `maker_clone_to_current_directory` 不再要求先完成 Tap 登录。
75
+ - `maker_clone_to_current_directory` 不要求当前目录为空;clone 前会检查本地目录,忽略 `.claude`、`.mcp`、`.skill`、`.config`、`.ini` 等点开头配置项,只对普通本地文件输出提醒。clone 最终结果固定包含 `Pre-clone local directory check` 区块;已有本地文件会保留,若与 Maker 项目文件同路径冲突则失败并列出冲突文件。
76
+ - `maker_list_apps` 会解析 Maker `/apps` 返回的创建时间、最近会话时间、游戏类型、阶段、图标、置顶/归档/删除时间等字段,并保留原始 `raw` 数据。
75
77
  - Maker Tap 登录只需要 client id;`rnd` 环境或 npm `@beta` 包会使用内置 Maker client id 兜底,不要求产品配置 `TAPTAP_MCP_CLIENT_SECRET`。
76
78
  - PAT 会保存到 `~/.taptap-maker/pat.json`,并兼容旧的 `~/.maker-pat`、`PAT` / `MAKER_PAT` 环境变量。
77
79
  - JWT 仅作为 legacy fallback 保留:`maker_exchange_jwt(manual_jwt)`、`JWT` / `MAKER_JWT` 仍可用于旧后端或创建新 PAT。
78
80
  - Maker app 必须先通过 `maker_list_apps` 展示给用户选择,再调用 clone。
79
81
  - Maker 后端地址按 `TAPTAP_MCP_ENV` 从 `src/maker/config.ts` 的环境配置表读取,本地 MCP 配置只需要切 `rnd` / `production`。
80
82
  - 如果用户直接说“构建 / build / 重新构建游戏”,本地 Maker MCP 应调用 `maker_build_current_directory` 转发到远端 `build` tool。
83
+ - 构建转发会从 MCP 包自身定位 `dist/proxy.js`;`cwd` / `target_dir` 只用于识别 Maker 游戏项目,不要求游戏目录存在 MCP 的 `dist/proxy.js`。
81
84
  - 如需在当前游戏项目里直接暴露远端全量 `taptap-proxy` tools,再使用 `maker_configure_remote_proxy` 写入 `.mcp.json` 并重启 MCP 会话。
82
85
  - 用户说“帮我提交/提交代码”时使用 `maker_submit_current_directory`,会对当前 Maker 项目执行 commit + push。
83
86
  - “帮我提交代码到maker / taptap制造 / tap制造 / tap”也应触发 `maker_submit_current_directory`。
84
87
  - Maker 项目提交不走通用 Git skill 的任务号、新分支规则;冲突时先和用户确认 pull/rebase 流程。
85
88
  - 如果 commit 已完成但 push 失败,Maker MCP 会返回 commit hash、ahead 状态、exit code、stderr/stdout 和下一步建议,便于开发期排查。
89
+ - clone/fetch、push 和远端 build 属于慢操作;工具会尽量发送 MCP progress notification,Git 阶段会解析 stderr 百分比,最终返回会包含耗时和最近进度。
86
90
 
87
91
  Git 引导:
88
92
 
package/dist/maker.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // TapTap Maker MCP - Standalone Bundle
3
3
  import { createRequire } from 'node:module';
4
4
  const require = createRequire(import.meta.url);
5
+ const __MAKER_BUNDLE_URL__ = import.meta.url;
5
6
 
6
7
  var __create = Object.create;
7
8
  var __defProp = Object.defineProperty;
@@ -25750,7 +25751,7 @@ function requireMakerJwt(manualJwt) {
25750
25751
  var BUILT_IN_MAKER_CLIENT_ID = "m2dnabebip3fpardnm";
25751
25752
  var MAKER_CLIENT_ID_ENV = "TAPTAP_MAKER_CLIENT_ID";
25752
25753
  var TAPTAP_CLIENT_ID_ENV = "TAPTAP_MCP_CLIENT_ID";
25753
- var MAKER_VERSION = true ? "1.22.0-beta.5" : "dev";
25754
+ var MAKER_VERSION = true ? "1.22.0-beta.6" : "dev";
25754
25755
  async function startTapDeviceLogin() {
25755
25756
  ensureMakerClientId();
25756
25757
  const environment = EnvConfig.environment;
@@ -26158,17 +26159,59 @@ function getMakerApiBase() {
26158
26159
  function getMakerGitBase() {
26159
26160
  return requireMakerEndpoint("gitBase", getConfiguredMakerGitBase()).replace(/\/$/, "");
26160
26161
  }
26162
+ function stringField(item, ...keys) {
26163
+ for (const key of keys) {
26164
+ const value = item[key];
26165
+ if (typeof value === "string") {
26166
+ return value;
26167
+ }
26168
+ }
26169
+ return void 0;
26170
+ }
26171
+ function nullableStringField(item, ...keys) {
26172
+ for (const key of keys) {
26173
+ const value = item[key];
26174
+ if (typeof value === "string" || value === null) {
26175
+ return value;
26176
+ }
26177
+ }
26178
+ return void 0;
26179
+ }
26180
+ function numberField(item, ...keys) {
26181
+ for (const key of keys) {
26182
+ const value = item[key];
26183
+ if (typeof value === "number") {
26184
+ return value;
26185
+ }
26186
+ }
26187
+ return void 0;
26188
+ }
26161
26189
  function normalizeProjectsResponse(data) {
26162
26190
  const body = data;
26163
26191
  const list = Array.isArray(data) ? data : Array.isArray(body.data) ? body.data : Array.isArray(body.apps) ? body.apps : Array.isArray(body.projects) ? body.projects : [];
26164
- return list.map((item) => item).map((item) => ({
26165
- id: String(item.id || item.app_id || item.project_id || ""),
26166
- name: typeof item.name === "string" ? item.name : typeof item.title === "string" ? item.title : void 0,
26167
- user_id: typeof item.user_id === "string" ? item.user_id : typeof item.userId === "string" ? item.userId : void 0,
26168
- sce_endpoint: typeof item.sce_endpoint === "string" ? item.sce_endpoint : typeof item.sce_mcp_url === "string" ? item.sce_mcp_url : void 0,
26169
- git_url: typeof item.git_url === "string" ? item.git_url : void 0,
26170
- raw: item
26171
- })).filter((project) => project.id.length > 0);
26192
+ return list.map((item) => item).map((item) => {
26193
+ const userId = stringField(item, "userId", "user_id");
26194
+ return {
26195
+ id: String(item.id || item.app_id || item.project_id || ""),
26196
+ name: stringField(item, "name", "title"),
26197
+ userId,
26198
+ user_id: userId,
26199
+ createdAt: stringField(item, "createdAt", "created_at"),
26200
+ archivedAt: nullableStringField(item, "archivedAt", "archived_at"),
26201
+ deletedAt: nullableStringField(item, "deletedAt", "deleted_at"),
26202
+ gameType: stringField(item, "gameType", "game_type"),
26203
+ icon: numberField(item, "icon"),
26204
+ iconColor: numberField(item, "iconColor", "icon_color"),
26205
+ lastAccessedAt: nullableStringField(item, "lastAccessedAt", "last_accessed_at"),
26206
+ lastConversationAt: stringField(item, "lastConversationAt", "last_conversation_at"),
26207
+ metadata: item.metadata,
26208
+ pinnedAt: nullableStringField(item, "pinnedAt", "pinned_at"),
26209
+ stage: stringField(item, "stage"),
26210
+ sce_endpoint: stringField(item, "sce_endpoint", "sce_mcp_url"),
26211
+ git_url: stringField(item, "git_url"),
26212
+ raw: item
26213
+ };
26214
+ }).filter((project) => project.id.length > 0);
26172
26215
  }
26173
26216
  async function runProjects(args, flags) {
26174
26217
  const subcommand = args[0] || "list";
@@ -26265,41 +26308,70 @@ async function pushProject(flags) {
26265
26308
  `);
26266
26309
  }
26267
26310
  async function cloneMakerProject(options) {
26268
- ensureGitAvailable();
26311
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
26269
26312
  const target = path6.resolve(options.targetDir);
26270
26313
  ensureTargetCanBindApp(target, options.appId);
26314
+ const warnings = createPreCloneWarnings(target);
26315
+ (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
26316
+ progress: 0,
26317
+ total: 100,
26318
+ phase: "pre_clone_check",
26319
+ message: formatPreCloneProgressMessage(options.appId, warnings)
26320
+ });
26321
+ ensureGitAvailable();
26322
+ (_b = options.onProgress) == null ? void 0 : _b.call(options, {
26323
+ progress: 1,
26324
+ total: 100,
26325
+ phase: "prepare",
26326
+ message: `Preparing Maker project ${options.appId}`
26327
+ });
26271
26328
  let pat = await requestMakerPat({
26272
26329
  jwt: options.jwt,
26273
26330
  pat: options.pat,
26274
26331
  name: options.patName || "first-pat",
26275
26332
  force: options.forcePat
26276
26333
  });
26334
+ (_c = options.onProgress) == null ? void 0 : _c.call(options, {
26335
+ progress: 5,
26336
+ total: 100,
26337
+ phase: "auth",
26338
+ message: "Maker PAT ready for git authentication"
26339
+ });
26277
26340
  const gitBase = getMakerGitBase();
26278
26341
  const gitUrl = `${gitBase}/${options.appId}.git`;
26279
26342
  let authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
26280
26343
  let retriedWithNewPat = false;
26281
26344
  let transientRetries = 0;
26282
- if (isGitRepo(target)) {
26345
+ if (isGitRepo(target) && hasGitHead(target)) {
26346
+ (_d = options.onProgress) == null ? void 0 : _d.call(options, {
26347
+ progress: 10,
26348
+ total: 100,
26349
+ phase: "fetch",
26350
+ message: "Existing git repository found; fetching origin"
26351
+ });
26283
26352
  await setOrigin(target, authUrl);
26284
26353
  try {
26285
26354
  transientRetries += await runGitWithTransientRetry(["fetch", "origin"], {
26286
- cwd: target
26355
+ cwd: target,
26356
+ onProgress: options.onProgress
26287
26357
  });
26288
26358
  } catch (error2) {
26289
- if (options.forcePat) {
26290
- throw error2;
26359
+ if (options.forcePat || !isAuthGitError(error2)) {
26360
+ throw withPreCloneWarnings(error2, warnings);
26291
26361
  }
26292
- pat = await requestMakerPat({
26362
+ pat = await refreshPatAfterAuthFailure(error2, {
26293
26363
  jwt: options.jwt,
26294
26364
  pat: options.pat,
26295
- name: options.patName || "first-pat",
26296
- force: true
26365
+ name: options.patName || "first-pat"
26297
26366
  });
26298
26367
  authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
26299
26368
  retriedWithNewPat = true;
26300
26369
  await setOrigin(target, authUrl);
26301
26370
  transientRetries += await runGitWithTransientRetry(["fetch", "origin"], {
26302
- cwd: target
26371
+ cwd: target,
26372
+ onProgress: options.onProgress
26373
+ }).catch((retryError) => {
26374
+ throw withPreCloneWarnings(retryError, warnings);
26303
26375
  });
26304
26376
  }
26305
26377
  saveProjectConfig(target, {
@@ -26307,59 +26379,99 @@ async function cloneMakerProject(options) {
26307
26379
  user_id: options.userId || await resolveMakerProjectUserId(options),
26308
26380
  sce_endpoint: options.sceEndpoint
26309
26381
  });
26382
+ (_e = options.onProgress) == null ? void 0 : _e.call(options, {
26383
+ progress: 100,
26384
+ total: 100,
26385
+ phase: "done",
26386
+ message: "Maker project fetch completed"
26387
+ });
26310
26388
  return {
26311
26389
  appId: options.appId,
26312
26390
  targetDir: target,
26313
26391
  status: "fetched",
26314
26392
  retriedWithNewPat,
26315
- transientRetries
26393
+ transientRetries,
26394
+ warnings
26316
26395
  };
26317
26396
  }
26318
- if (fs4.existsSync(target) && hasNonIgnorableFiles(target)) {
26319
- throw new Error(
26320
- [
26321
- `${target} is not empty and is not a git repository.`,
26322
- "Maker clone can be run multiple times after the directory is a git repo, but the first clone requires an empty target directory.",
26323
- "Please open an empty directory, or remove the unrelated files before cloning."
26324
- ].join("\n")
26397
+ if (isGitRepo(target)) {
26398
+ warnings.push(
26399
+ "Target directory already contained git metadata but no checked-out commit. Maker MCP will fetch and check out the remote Maker project branch before reporting success."
26325
26400
  );
26326
26401
  }
26327
26402
  try {
26328
- transientRetries += await runGitCaptureWithTransientRetry(["clone", authUrl, target], {
26329
- sanitize: pat.token
26403
+ (_f = options.onProgress) == null ? void 0 : _f.call(options, {
26404
+ progress: 10,
26405
+ total: 100,
26406
+ phase: "clone",
26407
+ message: `Cloning Maker project ${options.appId}`
26330
26408
  });
26409
+ transientRetries += await cloneOrInitializeTarget(
26410
+ target,
26411
+ authUrl,
26412
+ pat.token,
26413
+ options.onProgress
26414
+ );
26331
26415
  } catch (error2) {
26332
- if (options.forcePat) {
26333
- throw error2;
26416
+ if (options.forcePat || !isAuthGitError(error2)) {
26417
+ throw withPreCloneWarnings(error2, warnings);
26334
26418
  }
26335
- pat = await requestMakerPat({
26419
+ pat = await refreshPatAfterAuthFailure(error2, {
26336
26420
  jwt: options.jwt,
26337
26421
  pat: options.pat,
26338
- name: options.patName || "first-pat",
26339
- force: true
26422
+ name: options.patName || "first-pat"
26340
26423
  });
26341
26424
  authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
26342
26425
  retriedWithNewPat = true;
26343
- transientRetries += await runGitCaptureWithTransientRetry(["clone", authUrl, target], {
26344
- sanitize: pat.token
26426
+ (_g = options.onProgress) == null ? void 0 : _g.call(options, {
26427
+ progress: 10,
26428
+ total: 100,
26429
+ phase: "clone",
26430
+ message: `Retrying clone for Maker project ${options.appId} with refreshed PAT`
26345
26431
  });
26432
+ transientRetries += await cloneOrInitializeTarget(
26433
+ target,
26434
+ authUrl,
26435
+ pat.token,
26436
+ options.onProgress
26437
+ ).catch((retryError) => {
26438
+ throw withPreCloneWarnings(retryError, warnings);
26439
+ });
26440
+ }
26441
+ try {
26442
+ ensureGitHeadCheckedOut(target);
26443
+ } catch (error2) {
26444
+ throw withPreCloneWarnings(error2, warnings);
26346
26445
  }
26347
26446
  saveProjectConfig(target, {
26348
26447
  project_id: options.appId,
26349
26448
  user_id: options.userId || await resolveMakerProjectUserId(options),
26350
26449
  sce_endpoint: options.sceEndpoint
26351
26450
  });
26451
+ (_h = options.onProgress) == null ? void 0 : _h.call(options, {
26452
+ progress: 100,
26453
+ total: 100,
26454
+ phase: "done",
26455
+ message: "Maker project clone completed"
26456
+ });
26352
26457
  return {
26353
26458
  appId: options.appId,
26354
26459
  targetDir: target,
26355
26460
  status: "cloned",
26356
26461
  retriedWithNewPat,
26357
- transientRetries
26462
+ transientRetries,
26463
+ warnings
26358
26464
  };
26359
26465
  }
26360
26466
  async function pushMakerProject(options) {
26361
- var _a2;
26467
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
26362
26468
  ensureGitAvailable();
26469
+ (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
26470
+ progress: 0,
26471
+ total: 100,
26472
+ phase: "prepare",
26473
+ message: "Preparing Maker project push"
26474
+ });
26363
26475
  const cwd = path6.resolve(options.cwd);
26364
26476
  if (!isGitRepo(cwd)) {
26365
26477
  throw new Error(`${cwd} is not a git repository.`);
@@ -26377,11 +26489,24 @@ async function pushMakerProject(options) {
26377
26489
  appId: project.project_id,
26378
26490
  jwt: options.jwt,
26379
26491
  pat: options.pat,
26380
- forcePat: options.forcePat
26492
+ forcePat: options.forcePat,
26493
+ onProgress: options.onProgress
26494
+ });
26495
+ (_b = options.onProgress) == null ? void 0 : _b.call(options, {
26496
+ progress: 10,
26497
+ total: 100,
26498
+ phase: "auth",
26499
+ message: "Authenticated Maker git origin ready"
26381
26500
  });
26382
26501
  const statusBefore = await readGit(["status", "--porcelain"], cwd);
26383
26502
  const branch = await currentBranch(cwd, options.branch);
26384
26503
  if (!statusBefore.trim() && !options.allowEmpty) {
26504
+ (_c = options.onProgress) == null ? void 0 : _c.call(options, {
26505
+ progress: 100,
26506
+ total: 100,
26507
+ phase: "done",
26508
+ message: "Maker project has no local changes to push"
26509
+ });
26385
26510
  return {
26386
26511
  branch,
26387
26512
  committed: false,
@@ -26390,9 +26515,21 @@ async function pushMakerProject(options) {
26390
26515
  status: "clean"
26391
26516
  };
26392
26517
  }
26393
- if ((_a2 = options.files) == null ? void 0 : _a2.length) {
26518
+ if ((_d = options.files) == null ? void 0 : _d.length) {
26519
+ (_e = options.onProgress) == null ? void 0 : _e.call(options, {
26520
+ progress: 20,
26521
+ total: 100,
26522
+ phase: "stage",
26523
+ message: "Staging selected files"
26524
+ });
26394
26525
  await runGit(["add", ...options.files], { cwd });
26395
26526
  } else {
26527
+ (_f = options.onProgress) == null ? void 0 : _f.call(options, {
26528
+ progress: 20,
26529
+ total: 100,
26530
+ phase: "stage",
26531
+ message: "Staging all local changes"
26532
+ });
26396
26533
  await runGit(["add", "-A"], { cwd });
26397
26534
  }
26398
26535
  const staged = await readGit(["diff", "--cached", "--name-only"], cwd);
@@ -26400,6 +26537,12 @@ async function pushMakerProject(options) {
26400
26537
  let commitHash;
26401
26538
  const message = options.message || generateCommitMessage(statusBefore);
26402
26539
  if (staged.trim() || options.allowEmpty) {
26540
+ (_g = options.onProgress) == null ? void 0 : _g.call(options, {
26541
+ progress: 45,
26542
+ total: 100,
26543
+ phase: "commit",
26544
+ message: "Creating local Maker project commit"
26545
+ });
26403
26546
  await runGit(
26404
26547
  [
26405
26548
  "-c",
@@ -26417,7 +26560,13 @@ async function pushMakerProject(options) {
26417
26560
  commitHash = (await readGit(["rev-parse", "--short", "HEAD"], cwd)).trim();
26418
26561
  }
26419
26562
  try {
26420
- await pushGit(["push", "origin", `HEAD:${branch}`], cwd);
26563
+ (_h = options.onProgress) == null ? void 0 : _h.call(options, {
26564
+ progress: 65,
26565
+ total: 100,
26566
+ phase: "push",
26567
+ message: `Pushing Maker project to ${branch}`
26568
+ });
26569
+ await pushGit(["push", "origin", `HEAD:${branch}`], cwd, options.onProgress);
26421
26570
  } catch (error2) {
26422
26571
  const failure = toMakerGitFailure(error2, "push");
26423
26572
  return {
@@ -26431,6 +26580,12 @@ async function pushMakerProject(options) {
26431
26580
  ahead: await readAheadState(cwd)
26432
26581
  };
26433
26582
  }
26583
+ (_i = options.onProgress) == null ? void 0 : _i.call(options, {
26584
+ progress: 100,
26585
+ total: 100,
26586
+ phase: "done",
26587
+ message: "Maker project push completed"
26588
+ });
26434
26589
  return {
26435
26590
  branch,
26436
26591
  committed,
@@ -26545,7 +26700,7 @@ function nextActionForFailure(classification) {
26545
26700
  return "保留本地提交,不要重复提交;把错误详情反馈给用户,并在确认后重试 push。";
26546
26701
  }
26547
26702
  }
26548
- function pushGit(args, cwd) {
26703
+ function pushGit(args, cwd, onProgress) {
26549
26704
  return new Promise((resolve2, reject) => {
26550
26705
  const gitCommand = getGitCommand();
26551
26706
  const child = spawn(gitCommand, args, {
@@ -26556,6 +26711,7 @@ function pushGit(args, cwd) {
26556
26711
  let stderr = "";
26557
26712
  child.stderr.on("data", (chunk) => {
26558
26713
  stderr += String(chunk);
26714
+ emitGitProgress(chunk, onProgress);
26559
26715
  });
26560
26716
  child.stdout.on("data", (chunk) => {
26561
26717
  stdout += String(chunk);
@@ -26605,6 +26761,7 @@ async function resolveMakerProjectUserId(options) {
26605
26761
  }
26606
26762
  }
26607
26763
  async function ensureAuthenticatedOrigin(options) {
26764
+ var _a2;
26608
26765
  const pat = await requestMakerPat({
26609
26766
  jwt: options.jwt,
26610
26767
  pat: options.pat,
@@ -26615,15 +26772,189 @@ async function ensureAuthenticatedOrigin(options) {
26615
26772
  const gitUrl = `${gitBase}/${options.appId}.git`;
26616
26773
  const authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
26617
26774
  await setOrigin(options.cwd, authUrl);
26775
+ (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
26776
+ progress: 8,
26777
+ total: 100,
26778
+ phase: "auth",
26779
+ message: "Maker git origin updated with PAT authentication"
26780
+ });
26618
26781
  }
26619
26782
  function makeAuthenticatedGitUrl(gitUrl, pat) {
26620
26783
  return gitUrl.replace(/^https:\/\//, `https://git:${encodeURIComponent(pat)}@`);
26621
26784
  }
26622
- function hasNonIgnorableFiles(target) {
26785
+ async function cloneOrInitializeTarget(target, authUrl, pat, onProgress) {
26786
+ if (fs4.existsSync(target) && hasDirectoryEntries(target)) {
26787
+ onProgress == null ? void 0 : onProgress({
26788
+ progress: 10,
26789
+ total: 100,
26790
+ phase: "clone",
26791
+ message: "Target directory is not empty; initializing git repository in place and keeping existing untracked files unless they conflict with Maker project files."
26792
+ });
26793
+ let transientRetries = 0;
26794
+ transientRetries += await runGitCaptureWithTransientRetry(["init", target], {
26795
+ sanitize: pat,
26796
+ onProgress
26797
+ });
26798
+ await setOrigin(target, authUrl);
26799
+ transientRetries += await runGitWithTransientRetry(["fetch", "origin"], {
26800
+ cwd: target,
26801
+ onProgress
26802
+ });
26803
+ const branch = await resolveRemoteDefaultBranch(target);
26804
+ await assertNoCheckoutFileConflicts(target, branch);
26805
+ try {
26806
+ transientRetries += await runGitCaptureWithTransientRetry(
26807
+ ["checkout", "-B", branch, `origin/${branch}`],
26808
+ {
26809
+ cwd: target,
26810
+ sanitize: pat,
26811
+ onProgress
26812
+ }
26813
+ );
26814
+ } catch (error2) {
26815
+ throw enhanceCheckoutConflictError(error2, target);
26816
+ }
26817
+ return transientRetries;
26818
+ }
26819
+ return runGitCaptureWithTransientRetry(["clone", authUrl, target], {
26820
+ sanitize: pat,
26821
+ onProgress
26822
+ });
26823
+ }
26824
+ function hasDirectoryEntries(target) {
26623
26825
  if (!fs4.existsSync(target)) {
26624
26826
  return false;
26625
26827
  }
26626
- return fs4.readdirSync(target).some((entry) => entry !== ".maker-mcp" && entry !== ".DS_Store");
26828
+ return fs4.readdirSync(target).length > 0;
26829
+ }
26830
+ function listLocalFiles(root) {
26831
+ if (!fs4.existsSync(root)) {
26832
+ return [];
26833
+ }
26834
+ const files = [];
26835
+ const visit = (dir, relativeDir) => {
26836
+ for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
26837
+ const relativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
26838
+ if (entry.name === ".git" || relativePath === ".maker-mcp" || relativePath.startsWith(".maker-mcp/") || entry.name === ".DS_Store") {
26839
+ continue;
26840
+ }
26841
+ const fullPath = path6.join(dir, entry.name);
26842
+ if (entry.isDirectory()) {
26843
+ visit(fullPath, relativePath);
26844
+ continue;
26845
+ }
26846
+ if (entry.isFile()) {
26847
+ files.push(relativePath);
26848
+ }
26849
+ }
26850
+ };
26851
+ visit(root, "");
26852
+ return files;
26853
+ }
26854
+ function listPreCloneNoticeFiles(root) {
26855
+ if (!fs4.existsSync(root)) {
26856
+ return [];
26857
+ }
26858
+ return fs4.readdirSync(root, { withFileTypes: true }).filter((entry) => !isIgnorablePreCloneEntry(entry.name)).map((entry) => entry.name).sort();
26859
+ }
26860
+ function createPreCloneWarnings(target) {
26861
+ const preCloneLocalFiles = listPreCloneNoticeFiles(target);
26862
+ if (preCloneLocalFiles.length === 0) {
26863
+ return [];
26864
+ }
26865
+ const preview = preCloneLocalFiles.slice(0, 10);
26866
+ return [
26867
+ [
26868
+ "Pre-clone notice: target directory already contains local files. Maker MCP will keep them and continue unless they conflict with Maker project files.",
26869
+ `local_file_count: ${preCloneLocalFiles.length}`,
26870
+ "local_files:",
26871
+ ...preview.map((file2) => ` - ${file2}`),
26872
+ preCloneLocalFiles.length > preview.length ? ` - ... ${preCloneLocalFiles.length - preview.length} more` : ""
26873
+ ].filter(Boolean).join("\n")
26874
+ ];
26875
+ }
26876
+ function formatPreCloneProgressMessage(appId, warnings) {
26877
+ if (warnings.length === 0) {
26878
+ return `Pre-clone local directory check passed for Maker project ${appId}`;
26879
+ }
26880
+ return [
26881
+ `Pre-clone local directory check found existing local files for Maker project ${appId}.`,
26882
+ ...warnings
26883
+ ].join("\n");
26884
+ }
26885
+ function isIgnorablePreCloneEntry(entryName) {
26886
+ return entryName === ".DS_Store" || entryName.startsWith(".");
26887
+ }
26888
+ function isAuthGitError(error2) {
26889
+ return toMakerGitFailure(error2, "clone").classification === "auth";
26890
+ }
26891
+ async function refreshPatAfterAuthFailure(originalError, options) {
26892
+ try {
26893
+ return await requestMakerPat({
26894
+ jwt: options.jwt,
26895
+ pat: options.pat,
26896
+ name: options.name || "first-pat",
26897
+ force: true
26898
+ });
26899
+ } catch (refreshError) {
26900
+ const originalMessage = originalError instanceof Error ? originalError.message : String(originalError);
26901
+ const refreshMessage = refreshError instanceof Error ? refreshError.message : String(refreshError);
26902
+ throw new Error(
26903
+ [
26904
+ "Maker git authentication failed and PAT refresh also failed.",
26905
+ "",
26906
+ "original_git_error:",
26907
+ originalMessage,
26908
+ "",
26909
+ "pat_refresh_error:",
26910
+ refreshMessage
26911
+ ].join("\n")
26912
+ );
26913
+ }
26914
+ }
26915
+ function withPreCloneWarnings(error2, warnings) {
26916
+ const original = error2 instanceof Error ? error2 : new Error(String(error2));
26917
+ if (warnings.length === 0) {
26918
+ return original;
26919
+ }
26920
+ return new Error(
26921
+ [
26922
+ "Maker clone failed after pre-clone local directory check.",
26923
+ "",
26924
+ "Pre-clone notices:",
26925
+ ...warnings.map((warning) => indentText(warning)),
26926
+ "",
26927
+ "original_error:",
26928
+ original.message
26929
+ ].join("\n")
26930
+ );
26931
+ }
26932
+ function indentText(text) {
26933
+ return text.split("\n").map((line) => ` ${line}`).join("\n");
26934
+ }
26935
+ async function assertNoCheckoutFileConflicts(cwd, branch) {
26936
+ const remoteTree = await readGit(["ls-tree", "-r", "--name-only", `origin/${branch}`], cwd);
26937
+ const remoteFiles = new Set(
26938
+ remoteTree.split(/\r?\n/).map((line) => line.trim()).filter(Boolean)
26939
+ );
26940
+ if (remoteFiles.size === 0) {
26941
+ return;
26942
+ }
26943
+ const conflicts = listLocalFiles(cwd).filter((file2) => remoteFiles.has(file2)).sort();
26944
+ if (conflicts.length === 0) {
26945
+ return;
26946
+ }
26947
+ throw new Error(
26948
+ [
26949
+ "Maker clone cannot continue because existing local files have the same paths as files in the remote Maker project.",
26950
+ `target_dir: ${cwd}`,
26951
+ "",
26952
+ "Conflicting local files:",
26953
+ ...conflicts.map((file2) => `- ${file2}`),
26954
+ "",
26955
+ "Please move, rename, or delete these local files, then retry maker_clone_to_current_directory."
26956
+ ].join("\n")
26957
+ );
26627
26958
  }
26628
26959
  async function setOrigin(cwd, authUrl) {
26629
26960
  await runGit(["remote", "get-url", "origin"], { cwd, quiet: true }).then(() => runGit(["remote", "set-url", "origin", authUrl], { cwd, quiet: true })).catch(() => runGit(["remote", "add", "origin", authUrl], { cwd, quiet: true }));
@@ -26636,6 +26967,41 @@ function isGitRepo(repoDir) {
26636
26967
  return false;
26637
26968
  }
26638
26969
  }
26970
+ function hasGitHead(repoDir) {
26971
+ try {
26972
+ const head = readGitSync(["-C", repoDir, "rev-parse", "--verify", "HEAD"]);
26973
+ return head.trim().length > 0;
26974
+ } catch {
26975
+ return false;
26976
+ }
26977
+ }
26978
+ function ensureGitHeadCheckedOut(repoDir) {
26979
+ if (hasGitHead(repoDir)) {
26980
+ return;
26981
+ }
26982
+ throw new Error(
26983
+ [
26984
+ "Maker clone did not complete checkout: local git repository has no HEAD commit.",
26985
+ `target_dir: ${repoDir}`,
26986
+ "The remote fetch may have succeeded, but project files were not checked out. Please inspect git status and retry maker_clone_to_current_directory."
26987
+ ].join("\n")
26988
+ );
26989
+ }
26990
+ function enhanceCheckoutConflictError(error2, target) {
26991
+ const message = error2 instanceof Error ? error2.message : String(error2);
26992
+ if (!/untracked working tree files would be overwritten by checkout/i.test(message)) {
26993
+ return error2 instanceof Error ? error2 : new Error(message);
26994
+ }
26995
+ return new Error(
26996
+ [
26997
+ "Maker clone could not check out project files because existing local files would be overwritten.",
26998
+ `target_dir: ${target}`,
26999
+ "Please move, rename, or delete the conflicting local files, then retry maker_clone_to_current_directory.",
27000
+ "",
27001
+ message
27002
+ ].join("\n")
27003
+ );
27004
+ }
26639
27005
  async function currentBranch(cwd, explicitBranch) {
26640
27006
  if (explicitBranch) {
26641
27007
  return explicitBranch;
@@ -26643,6 +27009,20 @@ async function currentBranch(cwd, explicitBranch) {
26643
27009
  const branch = await readGit(["branch", "--show-current"], cwd);
26644
27010
  return branch.trim() || "main";
26645
27011
  }
27012
+ async function resolveRemoteDefaultBranch(cwd) {
27013
+ try {
27014
+ const branch = await readGit(["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], cwd);
27015
+ return branch.trim().replace(/^origin\//, "") || "main";
27016
+ } catch {
27017
+ }
27018
+ try {
27019
+ const remoteHead = await readGit(["ls-remote", "--symref", "origin", "HEAD"], cwd);
27020
+ const match = remoteHead.match(/^ref:\s+refs\/heads\/([^\s]+)\s+HEAD/m);
27021
+ return (match == null ? void 0 : match[1]) || "main";
27022
+ } catch {
27023
+ return "main";
27024
+ }
27025
+ }
26646
27026
  function readGitSync(args) {
26647
27027
  const gitCommand = getGitCommand();
26648
27028
  const result = spawnSync3(gitCommand, args, {
@@ -26725,6 +27105,7 @@ function runGitCapture(args, options = {}) {
26725
27105
  });
26726
27106
  child.stderr.on("data", (chunk) => {
26727
27107
  stderr += String(chunk);
27108
+ emitGitProgress(chunk, options.onProgress, options.sanitize);
26728
27109
  });
26729
27110
  child.on("exit", (code) => {
26730
27111
  if (code === 0) {
@@ -26757,6 +27138,7 @@ function runGit(args, options) {
26757
27138
  });
26758
27139
  child.stderr.on("data", (chunk) => {
26759
27140
  stderr += String(chunk);
27141
+ emitGitProgress(chunk, options.onProgress);
26760
27142
  });
26761
27143
  child.on("exit", (code) => {
26762
27144
  if (code === 0) {
@@ -26796,6 +27178,42 @@ function sanitize(value, secret) {
26796
27178
  }
26797
27179
  return value.split(secret).join("***");
26798
27180
  }
27181
+ function emitGitProgress(chunk, onProgress, secret) {
27182
+ if (!onProgress) {
27183
+ return;
27184
+ }
27185
+ for (const rawLine of String(chunk).split(/\r\n|\n|\r/)) {
27186
+ const line = sanitize(rawLine.trim(), secret);
27187
+ const progress = parseGitProgressLine(line);
27188
+ if (progress) {
27189
+ onProgress(progress);
27190
+ }
27191
+ }
27192
+ }
27193
+ function parseGitProgressLine(line) {
27194
+ const message = line.trim();
27195
+ if (!message) {
27196
+ return void 0;
27197
+ }
27198
+ const percentMatch = message.match(
27199
+ /(?:remote:\s*)?(Counting objects|Compressing objects|Receiving objects|Resolving deltas|Writing objects):\s+(\d+)%/i
27200
+ );
27201
+ if (percentMatch) {
27202
+ return {
27203
+ progress: Math.max(0, Math.min(100, Number(percentMatch[2]))),
27204
+ total: 100,
27205
+ phase: "git",
27206
+ message
27207
+ };
27208
+ }
27209
+ if (/^(remote:\s*)?(Cloning into|Enumerating objects|Total )/i.test(message)) {
27210
+ return {
27211
+ phase: "git",
27212
+ message
27213
+ };
27214
+ }
27215
+ return void 0;
27216
+ }
26799
27217
 
26800
27218
  // src/maker/cli/init.ts
26801
27219
  async function runInit(flags) {
@@ -27000,6 +27418,7 @@ async function runStatus(flags) {
27000
27418
  // src/maker/server/mcp.ts
27001
27419
  import fs6 from "node:fs";
27002
27420
  import path9 from "node:path";
27421
+ import { fileURLToPath } from "node:url";
27003
27422
 
27004
27423
  // node_modules/zod/v3/helpers/util.js
27005
27424
  var util;
@@ -41962,10 +42381,11 @@ function isElectron() {
41962
42381
  }
41963
42382
 
41964
42383
  // src/maker/server/mcp.ts
41965
- var VERSION = true ? "1.22.0-beta.5" : "dev";
42384
+ var VERSION = true ? "1.22.0-beta.6" : "dev";
41966
42385
  var DEFAULT_PROXY_MCP_NAME = "taptap-proxy";
41967
42386
  var DEFAULT_PROXY_PACKAGE = "@taptap/instant-games-open-mcp@1.22.0";
41968
42387
  var DEFAULT_BUILD_TIMEOUT_MS = 10 * 60 * 1e3;
42388
+ var LONG_OPERATION_HEARTBEAT_MS = 3 * 60 * 1e3;
41969
42389
  var MAKER_WEB_URL = getMakerWebUrl();
41970
42390
  var tools = [
41971
42391
  {
@@ -42063,7 +42483,7 @@ var tools = [
42063
42483
  },
42064
42484
  {
42065
42485
  name: "maker_clone_to_current_directory",
42066
- description: 'Clone a Maker app repository into the current Codex/agent working directory. Use after the user chooses an app from the Maker app list for requests like "拉取maker游戏到本地", "把这个maker app拉下来", "clone maker项目", or "下载maker游戏代码". Call this only after maker_list_apps has listed apps and the user has chosen one. Requires local Git. If Git is missing, this tool stops before changing files and returns install guidance; do not retry clone until the user installs Git and git --version works. Requires the selected app_id; uses cached Maker PAT by default.',
42486
+ description: 'Clone a Maker app repository into the current Codex/agent working directory. Use after the user chooses an app from the Maker app list for requests like "拉取maker游戏到本地", "把这个maker app拉下来", "clone maker项目", or "下载maker游戏代码". Call this only after maker_list_apps has listed apps and the user has chosen one. Requires local Git. If Git is missing, this tool stops before changing files and returns install guidance; do not retry clone until the user installs Git and git --version works. The target directory does not have to be empty; before clone, the tool checks local entries and warns about non-config local files while ignoring dot-prefixed config entries such as .claude, .mcp, .skill, .config, and .ini. Existing local files are kept unless they conflict with Maker project files; conflicts fail with a file list. Requires the selected app_id; uses cached Maker PAT by default.',
42067
42487
  inputSchema: {
42068
42488
  type: "object",
42069
42489
  properties: {
@@ -42184,7 +42604,7 @@ var tools = [
42184
42604
  },
42185
42605
  use_npx: {
42186
42606
  type: "boolean",
42187
- description: "If true, write the script-style npx package command. Defaults to false for local development and uses local dist/proxy.js."
42607
+ description: "If true, write the script-style npx package command. Defaults to false and uses the proxy.js bundled with the Maker MCP package when available."
42188
42608
  },
42189
42609
  pkg: {
42190
42610
  type: "string",
@@ -42253,7 +42673,8 @@ async function startMakerMcpServer() {
42253
42673
  }
42254
42674
  );
42255
42675
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
42256
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
42676
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
42677
+ var _a2, _b, _c;
42257
42678
  const name = request.params.name;
42258
42679
  try {
42259
42680
  if (name === "maker_status") {
@@ -42442,15 +42863,29 @@ async function startMakerMcpServer() {
42442
42863
  throw new McpError(ErrorCode.InvalidParams, "app_id is required");
42443
42864
  }
42444
42865
  const targetDir = args.target_dir || process.cwd();
42445
- const result = await cloneMakerProject({
42446
- appId: args.app_id,
42447
- targetDir,
42448
- pat: args.pat,
42449
- userId: args.user_id,
42450
- jwt: args.jwt,
42451
- forcePat: args.force_pat === true,
42452
- sceEndpoint: process.env.SCE_MCP_URL
42453
- });
42866
+ const progressReporter = createToolProgressReporter(
42867
+ (_a2 = request.params._meta) == null ? void 0 : _a2.progressToken,
42868
+ extra,
42869
+ "Maker clone"
42870
+ );
42871
+ let result;
42872
+ let progressSummary;
42873
+ try {
42874
+ result = await cloneMakerProject({
42875
+ appId: args.app_id,
42876
+ targetDir,
42877
+ pat: args.pat,
42878
+ userId: args.user_id,
42879
+ jwt: args.jwt,
42880
+ forcePat: args.force_pat === true,
42881
+ sceEndpoint: process.env.SCE_MCP_URL,
42882
+ onProgress: progressReporter.report
42883
+ });
42884
+ progressSummary = progressReporter.finish();
42885
+ } catch (error2) {
42886
+ progressReporter.finish();
42887
+ throw error2;
42888
+ }
42454
42889
  return {
42455
42890
  content: [
42456
42891
  {
@@ -42458,10 +42893,12 @@ async function startMakerMcpServer() {
42458
42893
  text: [
42459
42894
  "✓ Maker project cloned",
42460
42895
  "",
42896
+ ...formatCloneWarnings(result.warnings),
42461
42897
  `- app_id: ${args.app_id}`,
42462
42898
  `- target_dir: ${result.targetDir}`,
42463
42899
  `- status: ${result.status}`,
42464
42900
  `- retried_with_new_pat: ${result.retriedWithNewPat ? "yes" : "no"}`,
42901
+ ...formatProgressSummary(progressSummary),
42465
42902
  "- project config: .maker-mcp/config.json"
42466
42903
  ].join("\n")
42467
42904
  }
@@ -42471,21 +42908,35 @@ async function startMakerMcpServer() {
42471
42908
  if (name === "maker_push_current_directory" || name === "maker_submit_current_directory") {
42472
42909
  const args = request.params.arguments || {};
42473
42910
  const targetDir = args.target_dir || process.cwd();
42474
- const result = await pushMakerProject({
42475
- cwd: targetDir,
42476
- message: args.message,
42477
- branch: args.branch,
42478
- files: args.files,
42479
- allowEmpty: args.allow_empty === true,
42480
- pat: args.pat,
42481
- jwt: args.jwt,
42482
- forcePat: args.force_pat === true
42483
- });
42911
+ const progressReporter = createToolProgressReporter(
42912
+ (_b = request.params._meta) == null ? void 0 : _b.progressToken,
42913
+ extra,
42914
+ "Maker push"
42915
+ );
42916
+ let result;
42917
+ let progressSummary;
42918
+ try {
42919
+ result = await pushMakerProject({
42920
+ cwd: targetDir,
42921
+ message: args.message,
42922
+ branch: args.branch,
42923
+ files: args.files,
42924
+ allowEmpty: args.allow_empty === true,
42925
+ pat: args.pat,
42926
+ jwt: args.jwt,
42927
+ forcePat: args.force_pat === true,
42928
+ onProgress: progressReporter.report
42929
+ });
42930
+ progressSummary = progressReporter.finish();
42931
+ } catch (error2) {
42932
+ progressReporter.finish();
42933
+ throw error2;
42934
+ }
42484
42935
  return {
42485
42936
  content: [
42486
42937
  {
42487
42938
  type: "text",
42488
- text: formatPushResult(targetDir, result)
42939
+ text: formatPushResult(targetDir, result, progressSummary)
42489
42940
  }
42490
42941
  ]
42491
42942
  };
@@ -42511,22 +42962,36 @@ async function startMakerMcpServer() {
42511
42962
  }
42512
42963
  if (name === "maker_build_current_directory") {
42513
42964
  const args = request.params.arguments || {};
42514
- const result = await buildCurrentDirectory({
42515
- targetDir: args.target_dir || process.cwd(),
42516
- entry: args.entry,
42517
- scriptsPath: args.scriptsPath,
42518
- entryClient: args.entry_client,
42519
- entryServer: args.entry_server,
42520
- multiplayer: args.multiplayer,
42521
- serverUrl: args.server_url,
42522
- env: args.env,
42523
- timeoutMs: args.timeout_ms
42524
- });
42965
+ const progressReporter = createToolProgressReporter(
42966
+ (_c = request.params._meta) == null ? void 0 : _c.progressToken,
42967
+ extra,
42968
+ "Maker build"
42969
+ );
42970
+ let result;
42971
+ let progressSummary;
42972
+ try {
42973
+ result = await buildCurrentDirectory({
42974
+ targetDir: args.target_dir || process.cwd(),
42975
+ entry: args.entry,
42976
+ scriptsPath: args.scriptsPath,
42977
+ entryClient: args.entry_client,
42978
+ entryServer: args.entry_server,
42979
+ multiplayer: args.multiplayer,
42980
+ serverUrl: args.server_url,
42981
+ env: args.env,
42982
+ timeoutMs: args.timeout_ms,
42983
+ onProgress: progressReporter.report
42984
+ });
42985
+ progressSummary = progressReporter.finish();
42986
+ } catch (error2) {
42987
+ progressReporter.finish();
42988
+ throw error2;
42989
+ }
42525
42990
  return {
42526
42991
  content: [
42527
42992
  {
42528
42993
  type: "text",
42529
- text: formatBuildResult(result)
42994
+ text: formatBuildResult(result, progressSummary)
42530
42995
  }
42531
42996
  ]
42532
42997
  };
@@ -42651,12 +43116,32 @@ function formatProjectList(projects) {
42651
43116
  "Maker apps",
42652
43117
  "",
42653
43118
  ...projects.map(
42654
- (project, index) => `${index + 1}. ${project.id}${project.name ? ` ${project.name}` : ""}${project.user_id ? ` user_id=${project.user_id}` : ""}`
43119
+ (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}` : ""}`
42655
43120
  ),
42656
43121
  "",
42657
43122
  "请让用户选择一个 app,然后调用 maker_clone_to_current_directory。"
42658
43123
  ].join("\n");
42659
43124
  }
43125
+ function formatCloneWarnings(warnings) {
43126
+ if (warnings.length === 0) {
43127
+ return [
43128
+ "Pre-clone local directory check",
43129
+ "",
43130
+ "- result: checked",
43131
+ "- local_files: none found before clone, ignoring dot-prefixed local config entries",
43132
+ ""
43133
+ ];
43134
+ }
43135
+ return [
43136
+ "Pre-clone local directory check",
43137
+ "",
43138
+ "- result: found local files before clone",
43139
+ "- action: kept local files and continued unless they conflicted with Maker project files",
43140
+ "",
43141
+ ...warnings.map((warning) => `- ${warning}`),
43142
+ ""
43143
+ ];
43144
+ }
42660
43145
  function createRemoteProxyContext(options) {
42661
43146
  const identify = identifyMakerProject({ cwd: options.targetDir });
42662
43147
  if (!identify.projectRoot || !identify.projectId) {
@@ -42752,19 +43237,23 @@ function configureRemoteProxy(options) {
42752
43237
  envVars: proxy.envVars
42753
43238
  };
42754
43239
  }
42755
- function resolveLocalProxyBundle() {
42756
- const makerEntry = process.argv[1] ? path9.resolve(process.argv[1]) : "";
42757
- const alongsideMaker = makerEntry ? path9.join(path9.dirname(makerEntry), "proxy.js") : "";
42758
- if (alongsideMaker && fs6.existsSync(alongsideMaker)) {
42759
- return alongsideMaker;
42760
- }
42761
- const cwdBundle = path9.resolve(process.cwd(), "dist", "proxy.js");
42762
- if (fs6.existsSync(cwdBundle)) {
42763
- return cwdBundle;
43240
+ function resolveLocalProxyBundle(options) {
43241
+ const currentModuleUrl = (options == null ? void 0 : options.currentModuleUrl) || (typeof __MAKER_BUNDLE_URL__ !== "undefined" ? __MAKER_BUNDLE_URL__ : void 0);
43242
+ const currentModuleDir = currentModuleUrl ? path9.dirname(fileURLToPath(currentModuleUrl)) : "";
43243
+ const makerEntry = (options == null ? void 0 : options.makerEntry) ?? process.argv[1];
43244
+ const makerEntryDir = makerEntry ? path9.dirname(path9.resolve(makerEntry)) : "";
43245
+ const cwd = (options == null ? void 0 : options.cwd) ?? process.cwd();
43246
+ const candidates = [
43247
+ currentModuleDir ? path9.join(currentModuleDir, "proxy.js") : "",
43248
+ makerEntryDir ? path9.join(makerEntryDir, "..", "dist", "proxy.js") : "",
43249
+ path9.resolve(cwd, "dist", "proxy.js")
43250
+ ].filter(Boolean);
43251
+ for (const candidate of candidates) {
43252
+ if (fs6.existsSync(candidate)) {
43253
+ return candidate;
43254
+ }
42764
43255
  }
42765
- throw new Error(
42766
- "Local dist/proxy.js not found. Run npm run build before configuring remote proxy."
42767
- );
43256
+ throw new Error(`MCP proxy bundle not found. Checked: ${candidates.join(", ")}`);
42768
43257
  }
42769
43258
  function readMcpJson(filePath) {
42770
43259
  if (!fs6.existsSync(filePath)) {
@@ -42830,6 +43319,84 @@ function formatProxyEnv(envVars) {
42830
43319
  }
42831
43320
  return Object.keys(envVars).map((key) => `${key}=<redacted>`).join(" ");
42832
43321
  }
43322
+ function createToolProgressReporter(progressToken, extra, operationName) {
43323
+ var _a2;
43324
+ const startedAt = Date.now();
43325
+ let events = 0;
43326
+ let lastProgress;
43327
+ let lastSentProgress = 0;
43328
+ let finished = false;
43329
+ const sendProgress = (progress) => {
43330
+ if (finished || progressToken === void 0) {
43331
+ return;
43332
+ }
43333
+ const elapsed = formatDuration(Date.now() - startedAt);
43334
+ const numericProgress = progress.progress !== void 0 ? Math.max(lastSentProgress, progress.progress) : Math.max(lastSentProgress, Math.floor((Date.now() - startedAt) / 1e3));
43335
+ lastSentProgress = numericProgress;
43336
+ const message = `${operationName}: ${progress.message} (elapsed ${elapsed})`;
43337
+ void extra.sendNotification({
43338
+ method: "notifications/progress",
43339
+ params: {
43340
+ progressToken,
43341
+ progress: numericProgress,
43342
+ ...progress.total !== void 0 ? { total: progress.total } : {},
43343
+ message
43344
+ }
43345
+ }).catch(() => {
43346
+ });
43347
+ };
43348
+ const heartbeat = setInterval(() => {
43349
+ const elapsed = formatDuration(Date.now() - startedAt);
43350
+ sendProgress({
43351
+ progress: lastProgress == null ? void 0 : lastProgress.progress,
43352
+ total: lastProgress == null ? void 0 : lastProgress.total,
43353
+ phase: lastProgress == null ? void 0 : lastProgress.phase,
43354
+ message: `still running; elapsed ${elapsed}; last status: ${(lastProgress == null ? void 0 : lastProgress.message) || "waiting for progress"}`
43355
+ });
43356
+ }, LONG_OPERATION_HEARTBEAT_MS);
43357
+ (_a2 = heartbeat.unref) == null ? void 0 : _a2.call(heartbeat);
43358
+ return {
43359
+ report(progress) {
43360
+ events += 1;
43361
+ lastProgress = progress;
43362
+ sendProgress(progress);
43363
+ },
43364
+ finish() {
43365
+ if (!finished) {
43366
+ finished = true;
43367
+ clearInterval(heartbeat);
43368
+ }
43369
+ const elapsedMs = Date.now() - startedAt;
43370
+ return {
43371
+ elapsedMs,
43372
+ elapsed: formatDuration(elapsedMs),
43373
+ progressEvents: events,
43374
+ lastProgress
43375
+ };
43376
+ }
43377
+ };
43378
+ }
43379
+ function formatProgressSummary(summary) {
43380
+ return [
43381
+ `- elapsed_ms: ${summary.elapsedMs}`,
43382
+ `- elapsed: ${summary.elapsed}`,
43383
+ `- progress_events: ${summary.progressEvents}`,
43384
+ summary.lastProgress ? `- last_progress: ${formatProgressMessage(summary.lastProgress)}` : "- last_progress: (none)"
43385
+ ];
43386
+ }
43387
+ function formatProgressMessage(progress) {
43388
+ const percent = progress.progress !== void 0 ? `${progress.progress}${progress.total === 100 ? "%" : ""}` : void 0;
43389
+ return [progress.phase ? `[${progress.phase}]` : "", percent, progress.message].filter(Boolean).join(" ");
43390
+ }
43391
+ function formatDuration(ms) {
43392
+ const totalSeconds = Math.max(0, Math.round(ms / 1e3));
43393
+ const minutes = Math.floor(totalSeconds / 60);
43394
+ const seconds = totalSeconds % 60;
43395
+ if (minutes === 0) {
43396
+ return `${seconds}s`;
43397
+ }
43398
+ return `${minutes}m ${seconds}s`;
43399
+ }
42833
43400
  async function buildCurrentDirectory(options) {
42834
43401
  const proxy = createRemoteProxyContext({
42835
43402
  targetDir: options.targetDir,
@@ -42841,10 +43408,7 @@ async function buildCurrentDirectory(options) {
42841
43408
  const transport = new StdioClientTransport({
42842
43409
  command: proxy.command,
42843
43410
  args: proxy.args,
42844
- env: {
42845
- ...process.env,
42846
- ...proxy.envVars
42847
- },
43411
+ env: mergeStringEnv(process.env, proxy.envVars),
42848
43412
  stderr: "pipe"
42849
43413
  });
42850
43414
  const client = new Client(
@@ -42866,7 +43430,16 @@ async function buildCurrentDirectory(options) {
42866
43430
  void 0,
42867
43431
  {
42868
43432
  timeout: timeoutMs,
42869
- resetTimeoutOnProgress: true
43433
+ resetTimeoutOnProgress: true,
43434
+ onprogress: (progress) => {
43435
+ var _a2;
43436
+ (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
43437
+ progress: progress.progress,
43438
+ total: progress.total,
43439
+ phase: "remote_build",
43440
+ message: progress.message || "Remote Maker build progress"
43441
+ });
43442
+ }
42870
43443
  }
42871
43444
  );
42872
43445
  return {
@@ -42904,6 +43477,20 @@ function createBuildArgs(projectRoot, options) {
42904
43477
  }
42905
43478
  return buildArgs;
42906
43479
  }
43480
+ function mergeStringEnv(...sources) {
43481
+ const result = {};
43482
+ for (const source of sources) {
43483
+ if (!source) {
43484
+ continue;
43485
+ }
43486
+ for (const [key, value] of Object.entries(source)) {
43487
+ if (typeof value === "string") {
43488
+ result[key] = value;
43489
+ }
43490
+ }
43491
+ }
43492
+ return result;
43493
+ }
42907
43494
  function formatRemoteToolResult(result) {
42908
43495
  if (!result || typeof result !== "object") {
42909
43496
  return String(result);
@@ -42919,7 +43506,7 @@ function formatRemoteToolResult(result) {
42919
43506
  return JSON.stringify(item);
42920
43507
  }).join("\n");
42921
43508
  }
42922
- function formatBuildResult(result) {
43509
+ function formatBuildResult(result, progressSummary) {
42923
43510
  return [
42924
43511
  "✓ Remote Maker build finished",
42925
43512
  "",
@@ -42930,12 +43517,13 @@ function formatBuildResult(result) {
42930
43517
  `- env: ${result.env}`,
42931
43518
  `- timeout_ms: ${result.timeoutMs}`,
42932
43519
  `- build_args: ${JSON.stringify(result.buildArgs)}`,
43520
+ ...formatProgressSummary(progressSummary),
42933
43521
  "",
42934
43522
  "remote_result:",
42935
43523
  indent(result.resultText)
42936
43524
  ].join("\n");
42937
43525
  }
42938
- function formatPushResult(targetDir, result) {
43526
+ function formatPushResult(targetDir, result, progressSummary) {
42939
43527
  const lines = [
42940
43528
  result.pushed ? "✓ Maker project pushed" : result.status === "clean" ? "Maker project has no changes to push" : "✗ Maker project push failed",
42941
43529
  "",
@@ -42945,7 +43533,8 @@ function formatPushResult(targetDir, result) {
42945
43533
  `- committed: ${result.committed ? "yes" : "no"}`,
42946
43534
  result.commitHash ? `- commit_hash: ${result.commitHash}` : "",
42947
43535
  result.message ? `- commit_message: ${result.message}` : "",
42948
- result.ahead ? `- git_state: ${result.ahead}` : ""
43536
+ result.ahead ? `- git_state: ${result.ahead}` : "",
43537
+ ...formatProgressSummary(progressSummary)
42949
43538
  ].filter(Boolean);
42950
43539
  if (!result.failure) {
42951
43540
  return lines.join("\n");
package/dist/proxy.js CHANGED
@@ -29137,7 +29137,7 @@ var LogWriter = class {
29137
29137
  };
29138
29138
 
29139
29139
  // src/mcp-proxy/proxy.ts
29140
- var VERSION = true ? "1.22.0-beta.5" : "dev";
29140
+ var VERSION = true ? "1.22.0-beta.6" : "dev";
29141
29141
  var TapTapMCPProxy = class {
29142
29142
  constructor(config2) {
29143
29143
  this.connected = false;
package/dist/server.js CHANGED
@@ -6078,7 +6078,7 @@ class MultiplayerManager {
6078
6078
  // 导出
6079
6079
  // export default MultiplayerManager;
6080
6080
  // module.exports = MultiplayerManager;
6081
- // window.MultiplayerManager = MultiplayerManager;`}]}}};var ws;ws="1.22.0-beta.5";async function MRe(){return Go(Rm,"api_event_relations")}async function NRe(){return Go(Rm,"protocol_template")}async function SD(){return Go(Rm,"complete_example")}async function jRe(){return`# TapTap 多人联机集成指南
6081
+ // window.MultiplayerManager = MultiplayerManager;`}]}}};var ws;ws="1.22.0-beta.6";async function MRe(){return Go(Rm,"api_event_relations")}async function NRe(){return Go(Rm,"protocol_template")}async function SD(){return Go(Rm,"complete_example")}async function jRe(){return`# TapTap 多人联机集成指南
6082
6082
 
6083
6083
  ---
6084
6084
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taptap/instant-games-open-mcp",
3
- "version": "1.22.0-beta.5",
3
+ "version": "1.22.0-beta.6",
4
4
  "type": "module",
5
5
  "description": "TapTap Open API MCP Server - Documentation and Management APIs for TapTap Minigame and H5 Games (Leaderboard, and more features coming)",
6
6
  "main": "dist/server.js",